aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Garrett <mjg59@google.com>2017-10-11 15:10:14 -0400
committerMimi Zohar <zohar@linux.vnet.ibm.com>2017-11-08 15:16:36 -0500
commitf00d79750712511d0a83c108eea0d44b680a915f (patch)
treef0bdb9499c9e6b7bb7c37ace6b70d25bc5035ac5
parent096b85464832d2a7bd7bd6d4db2fafed2ab77244 (diff)
EVM: Allow userspace to signal an RSA key has been loaded
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 a symmetric key in order to avoid a compromised system from being able to load an additional key type later. Signed-off-by: Matthew Garrett <mjg59@google.com> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
-rw-r--r--Documentation/ABI/testing/evm47
-rw-r--r--security/integrity/evm/evm.h3
-rw-r--r--security/integrity/evm/evm_secfs.c29
3 files changed, 53 insertions, 26 deletions
diff --git a/Documentation/ABI/testing/evm b/Documentation/ABI/testing/evm
index 8374d4557e5d..a0bbccb00736 100644
--- a/Documentation/ABI/testing/evm
+++ b/Documentation/ABI/testing/evm
@@ -7,17 +7,36 @@ Description:
7 HMAC-sha1 value across the extended attributes, storing the 7 HMAC-sha1 value across the extended attributes, storing the
8 value as the extended attribute 'security.evm'. 8 value as the extended attribute 'security.evm'.
9 9
10 EVM depends on the Kernel Key Retention System to provide it 10 EVM supports two classes of security.evm. The first is
11 with a trusted/encrypted key for the HMAC-sha1 operation. 11 an HMAC-sha1 generated locally with a
12 The key is loaded onto the root's keyring using keyctl. Until 12 trusted/encrypted key stored in the Kernel Key
13 EVM receives notification that the key has been successfully 13 Retention System. The second is a digital signature
14 loaded onto the keyring (echo 1 > <securityfs>/evm), EVM 14 generated either locally or remotely using an
15 can not create or validate the 'security.evm' xattr, but 15 asymmetric key. These keys are loaded onto root's
16 returns INTEGRITY_UNKNOWN. Loading the key and signaling EVM 16 keyring using keyctl, and EVM is then enabled by
17 should be done as early as possible. Normally this is done 17 echoing a value to <securityfs>/evm:
18 in the initramfs, which has already been measured as part 18
19 of the trusted boot. For more information on creating and 19 1: enable HMAC validation and creation
20 loading existing trusted/encrypted keys, refer to: 20 2: enable digital signature validation
21 Documentation/keys-trusted-encrypted.txt. (A sample dracut 21 3: enable HMAC and digital signature validation and HMAC
22 patch, which loads the trusted/encrypted key and enables 22 creation
23 EVM, is available from http://linux-ima.sourceforge.net/#EVM.) 23
24 Further writes will be blocked if HMAC support is enabled or
25 if bit 32 is set:
26
27 echo 0x80000002 ><securityfs>/evm
28
29 will enable digital signature validation and block
30 further writes to <securityfs>/evm.
31
32 Until this is done, EVM can not create or validate the
33 'security.evm' xattr, but returns INTEGRITY_UNKNOWN.
34 Loading keys and signaling EVM should be done as early
35 as possible. Normally this is done in the initramfs,
36 which has already been measured as part of the trusted
37 boot. For more information on creating and loading
38 existing trusted/encrypted keys, refer to:
39 Documentation/keys-trusted-encrypted.txt. Both dracut
40 (via 97masterkey and 98integrity) and systemd (via
41 core/ima-setup) have support for loading keys at boot
42 time.
diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h
index f5f12727771a..241aca315b0c 100644
--- a/security/integrity/evm/evm.h
+++ b/security/integrity/evm/evm.h
@@ -23,6 +23,9 @@
23 23
24#define EVM_INIT_HMAC 0x0001 24#define EVM_INIT_HMAC 0x0001
25#define EVM_INIT_X509 0x0002 25#define EVM_INIT_X509 0x0002
26#define EVM_SETUP 0x80000000 /* userland has signaled key load */
27
28#define EVM_INIT_MASK (EVM_INIT_HMAC | EVM_INIT_X509 | EVM_SETUP)
26 29
27extern int evm_initialized; 30extern int evm_initialized;
28extern char *evm_hmac; 31extern 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,
40 if (*ppos != 0) 40 if (*ppos != 0)
41 return 0; 41 return 0;
42 42
43 sprintf(temp, "%d", evm_initialized); 43 sprintf(temp, "%d", (evm_initialized & ~EVM_SETUP));
44 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); 44 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
45 45
46 return rc; 46 return rc;
@@ -61,24 +61,29 @@ static ssize_t evm_read_key(struct file *filp, char __user *buf,
61static ssize_t evm_write_key(struct file *file, const char __user *buf, 61static ssize_t evm_write_key(struct file *file, const char __user *buf,
62 size_t count, loff_t *ppos) 62 size_t count, loff_t *ppos)
63{ 63{
64 char temp[80]; 64 int i, ret;
65 int i;
66 65
67 if (!capable(CAP_SYS_ADMIN) || (evm_initialized & EVM_INIT_HMAC)) 66 if (!capable(CAP_SYS_ADMIN) || (evm_initialized & EVM_SETUP))
68 return -EPERM; 67 return -EPERM;
69 68
70 if (count >= sizeof(temp) || count == 0) 69 ret = kstrtoint_from_user(buf, count, 0, &i);
71 return -EINVAL;
72
73 if (copy_from_user(temp, buf, count) != 0)
74 return -EFAULT;
75 70
76 temp[count] = '\0'; 71 if (ret)
72 return ret;
77 73
78 if ((sscanf(temp, "%d", &i) != 1) || (i != 1)) 74 /* Reject invalid values */
75 if (!i || (i & ~EVM_INIT_MASK) != 0)
79 return -EINVAL; 76 return -EINVAL;
80 77
81 evm_init_key(); 78 if (i & EVM_INIT_HMAC) {
79 ret = evm_init_key();
80 if (ret != 0)
81 return ret;
82 /* Forbid further writes after the symmetric key is loaded */
83 i |= EVM_SETUP;
84 }
85
86 evm_initialized |= i;
82 87
83 return count; 88 return count;
84} 89}