From patchwork Wed Oct 11 19:10:14 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Garrett X-Patchwork-Id: 10000373 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 24588602BF for ; Wed, 11 Oct 2017 19:10:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0C1D1289E8 for ; Wed, 11 Oct 2017 19:10:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0A18328B52; Wed, 11 Oct 2017 19:10:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A76FC28B54 for ; Wed, 11 Oct 2017 19:10:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752490AbdJKTK3 (ORCPT ); Wed, 11 Oct 2017 15:10:29 -0400 Received: from mail-io0-f202.google.com ([209.85.223.202]:44808 "EHLO mail-io0-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757389AbdJKTK2 (ORCPT ); Wed, 11 Oct 2017 15:10:28 -0400 Received: by mail-io0-f202.google.com with SMTP id m81so2161306ioi.3 for ; Wed, 11 Oct 2017 12:10:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=mime-version:date:message-id:subject:from:to:cc; bh=bso6UAOzdZdoYQL/Ab3PaDho9szsBr6bWshO/y/ePgI=; b=NocXw4C4xlJ3E+cSFKGGJE2HMv304fujgtTg0UhcrNij8tMOmRFvymbWTWn0vL9RJZ MpawJFkEJurVDetlelaRekRu0caSFUe5xnMU1T8CDk4zpCzg75Pp37PiNFH/jjYr2FV9 qtdM7m9qdCRtYuZNNTtkSnysnmBQiTEvwAPo6jY63DOWg/3HdBYHmX/m3OyiSAu+fRCR /kD0mNveI/T7OMfuESpF2/uc2ZVXgiSm3treCxWqcfE4w8yndPMsqPPgp76N+xSJplrR DIo2Kad/cPmIQ1r0cGBgUiiXSMTb04zGxFPf8pdI9obc2O2YKhE55T+LGZq5qcb+W+mU 2tmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:date:message-id:subject:from:to:cc; bh=bso6UAOzdZdoYQL/Ab3PaDho9szsBr6bWshO/y/ePgI=; b=iBpmYt5pt20G/T3Zw66zTFQ5fmy2592eQur1SzOLI73MHUbWslbPLnE8eBLww4z8ub WGwPN21HVugkiUnhTIjk9UmDyHF/LaBI0DwH5C/Gqw4DmaUTVH709d7tN2PWzrWAEagf ZKcIBkqVQ3AMLQLxzz86ZP6hV+dEaltn9r/C0TGbd8tjHTMWzyVuKaqdoyu9n1N4W71O /igIyqncQsDhwn0g1MMu0EF4OJi0qiFgjXePzUWlRw7FjeYvBTRQFX22UkzuZCQTrcyG HLr5dtzC8uKo0YXDbIp3uZK1dOD1pjtkG6sv5ZzrjgP9jyzWtxdJSvo9kTJUi6I7GMwM AkUw== X-Gm-Message-State: AMCzsaWzPgFOiwMU6QDY6nYSaKnsCcrtPJyj/gHxZnmydXLDFC422jPT x70HBaw4WdVxxS5c4w2WZIRgSYanGnfR3C4QTfj7AD6D/dA+H4T8pGTouLdkFSqaJK7SEhvaS7I TT+hQylDlN2KtYtreJAkcx4IsOJZR5ARFx8I= X-Google-Smtp-Source: AOwi7QDFdzzzGLLKm/JB1BqTURBFth/l9Ezj3f2pG7VeO6k3Vgb0rv3c0e4NSefw0j8Ge0BkMVo3wEeMBIniBK0XC8UwNQ== MIME-Version: 1.0 X-Received: by 10.36.36.213 with SMTP id f204mr2729ita.49.1507749027730; Wed, 11 Oct 2017 12:10:27 -0700 (PDT) Date: Wed, 11 Oct 2017 12:10:14 -0700 Message-Id: <20171011191014.4426-1-mjg59@google.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog Subject: [PATCH V2] EVM: Allow userspace to signal an RSA key has been loaded From: Matthew Garrett To: linux-integrity@vger.kernel.org Cc: zohar@linux.vnet.ibm.com, Matthew Garrett Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP EVM will only perform validation once a key has been loaded. This key may either be a symmetric trusted key (for HMAC validation and creation) or the public half of an asymmetric key (for digital signature validation). The /sys/kernel/security/evm interface allows userland to signal that a symmetric key has been loaded, but does not allow userland to signal that an asymmetric public key has been loaded. This patch extends the interface to permit userspace to pass a bitmask of loaded key types. It also allows userspace to block loading of an asymmetric key in order to avoid a compromised system from being able to load an additional key type later. Signed-off-by: Matthew Garrett --- Documentation/ABI/testing/evm | 48 +++++++++++++++++++++++++++----------- security/integrity/evm/evm.h | 3 +++ security/integrity/evm/evm_secfs.c | 29 +++++++++++++---------- 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/Documentation/ABI/testing/evm b/Documentation/ABI/testing/evm index 8374d4557e5d..d2782afb0d96 100644 --- a/Documentation/ABI/testing/evm +++ b/Documentation/ABI/testing/evm @@ -7,17 +7,37 @@ Description: HMAC-sha1 value across the extended attributes, storing the value as the extended attribute 'security.evm'. - EVM depends on the Kernel Key Retention System to provide it - with a trusted/encrypted key for the HMAC-sha1 operation. - The key is loaded onto the root's keyring using keyctl. Until - EVM receives notification that the key has been successfully - loaded onto the keyring (echo 1 > /evm), EVM - can not create or validate the 'security.evm' xattr, but - returns INTEGRITY_UNKNOWN. Loading the key and signaling EVM - should be done as early as possible. Normally this is done - in the initramfs, which has already been measured as part - of the trusted boot. For more information on creating and - loading existing trusted/encrypted keys, refer to: - Documentation/keys-trusted-encrypted.txt. (A sample dracut - patch, which loads the trusted/encrypted key and enables - EVM, is available from http://linux-ima.sourceforge.net/#EVM.) + EVM supports two classes of security.evm. The first is + an HMAC-sha1 generated locally with a + trusted/encrypted key stored in the Kernel Key + Retention System. The second is a digital signature + generated either locally or remotely using an + asymmetric key. These keys are loaded onto root's + keyring using keyctl, and EVM is then enabled by + echoing a value to /evm: + + 1: enable HMAC validation and creation + 2: enable digital signature validation + 3: enable HMAC and digital signature validation and HMAC + creation + + Further writes will be blocked if HMAC support is enabled or + if bit 32 is set: + + echo 0x80000002 >/evm + + will enable digital signature validation and block + further writes to /evm. + + Until this is done, EVM can not create or validate the + 'security.evm' xattr, but returns INTEGRITY_UNKNOWN. + Loading keys and signaling EVM should be done as early + as possible. Normally this is done in the initramfs, + which has already been measured as part of the trusted + boot. For more information on creating and loading + existing trusted/encrypted keys, refer to: + Documentation/keys-trusted-encrypted.txt. Both dracut + (via 97masterkey and 98integrity) and systemd (via + core/ima-setup) have support for loading keys at boot + time. + diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h index 2ff02459fcfd..946efffcc389 100644 --- a/security/integrity/evm/evm.h +++ b/security/integrity/evm/evm.h @@ -23,6 +23,9 @@ #define EVM_INIT_HMAC 0x0001 #define EVM_INIT_X509 0x0002 +#define EVM_SETUP 0x80000000 /* userland has signaled key load */ + +#define EVM_INIT_MASK (EVM_INIT_HMAC | EVM_INIT_X509 | EVM_SETUP) extern int evm_initialized; extern char *evm_hmac; diff --git a/security/integrity/evm/evm_secfs.c b/security/integrity/evm/evm_secfs.c index c8dccd54d501..319cf16d6603 100644 --- a/security/integrity/evm/evm_secfs.c +++ b/security/integrity/evm/evm_secfs.c @@ -40,7 +40,7 @@ static ssize_t evm_read_key(struct file *filp, char __user *buf, if (*ppos != 0) return 0; - sprintf(temp, "%d", evm_initialized); + sprintf(temp, "%d", (evm_initialized & ~EVM_SETUP)); rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); return rc; @@ -61,24 +61,29 @@ static ssize_t evm_read_key(struct file *filp, char __user *buf, static ssize_t evm_write_key(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - char temp[80]; - int i; + int i, ret; - if (!capable(CAP_SYS_ADMIN) || (evm_initialized & EVM_INIT_HMAC)) + if (!capable(CAP_SYS_ADMIN) || (evm_initialized & EVM_SETUP)) return -EPERM; - if (count >= sizeof(temp) || count == 0) - return -EINVAL; - - if (copy_from_user(temp, buf, count) != 0) - return -EFAULT; + ret = kstrtoint_from_user(buf, count, 0, &i); - temp[count] = '\0'; + if (ret) + return ret; - if ((sscanf(temp, "%d", &i) != 1) || (i != 1)) + /* Reject invalid values */ + if (!i || (i & ~EVM_INIT_MASK) != 0) return -EINVAL; - evm_init_key(); + if (i & EVM_INIT_HMAC) { + ret = evm_init_key(); + if (ret != 0) + return ret; + /* Forbid further writes after the symmetric key is loaded */ + i |= EVM_SETUP; + } + + evm_initialized |= i; return count; }