diff options
author | Matthew Garrett <mjg59@google.com> | 2017-10-11 15:10:14 -0400 |
---|---|---|
committer | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2017-11-08 15:16:36 -0500 |
commit | f00d79750712511d0a83c108eea0d44b680a915f (patch) | |
tree | f0bdb9499c9e6b7bb7c37ace6b70d25bc5035ac5 | |
parent | 096b85464832d2a7bd7bd6d4db2fafed2ab77244 (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/evm | 47 | ||||
-rw-r--r-- | security/integrity/evm/evm.h | 3 | ||||
-rw-r--r-- | security/integrity/evm/evm_secfs.c | 29 |
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 | ||
27 | extern int evm_initialized; | 30 | extern int evm_initialized; |
28 | extern char *evm_hmac; | 31 | 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, | |||
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, | |||
61 | static ssize_t evm_write_key(struct file *file, const char __user *buf, | 61 | static 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 | } |