aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity
diff options
context:
space:
mode:
authorDmitry Kasatkin <dmitry.kasatkin@intel.com>2011-09-01 07:41:40 -0400
committerDmitry Kasatkin <dmitry.kasatkin@intel.com>2011-11-09 09:51:14 -0500
commit15647eb3985ef30dfd657038924dc85c03026733 (patch)
tree5d4629ef3b687ff56a446f42a8ee5aa35ec9322b /security/integrity
parent8607c501478432b23654739c7321bc7456053cb6 (diff)
evm: digital signature verification support
This patch adds support for digital signature verification to EVM. With this feature file metadata can be protected using digital signature instead of an HMAC. When building an image, which has to be flashed to different devices, an HMAC cannot be used to sign file metadata, because the HMAC key should be different on every device. Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com> Acked-by: Mimi Zohar <zohar@us.ibm.com>
Diffstat (limited to 'security/integrity')
-rw-r--r--security/integrity/evm/evm.h12
-rw-r--r--security/integrity/evm/evm_crypto.c66
-rw-r--r--security/integrity/evm/evm_main.c94
3 files changed, 142 insertions, 30 deletions
diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h
index d320f5197437..c885247ebcf7 100644
--- a/security/integrity/evm/evm.h
+++ b/security/integrity/evm/evm.h
@@ -12,14 +12,21 @@
12 * File: evm.h 12 * File: evm.h
13 * 13 *
14 */ 14 */
15
16#ifndef __INTEGRITY_EVM_H
17#define __INTEGRITY_EVM_H
18
15#include <linux/xattr.h> 19#include <linux/xattr.h>
16#include <linux/security.h> 20#include <linux/security.h>
21
17#include "../integrity.h" 22#include "../integrity.h"
18 23
19extern int evm_initialized; 24extern int evm_initialized;
20extern char *evm_hmac; 25extern char *evm_hmac;
26extern char *evm_hash;
21 27
22extern struct crypto_shash *hmac_tfm; 28extern struct crypto_shash *hmac_tfm;
29extern struct crypto_shash *hash_tfm;
23 30
24/* List of EVM protected security xattrs */ 31/* List of EVM protected security xattrs */
25extern char *evm_config_xattrnames[]; 32extern char *evm_config_xattrnames[];
@@ -32,7 +39,12 @@ extern int evm_update_evmxattr(struct dentry *dentry,
32extern int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, 39extern int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
33 const char *req_xattr_value, 40 const char *req_xattr_value,
34 size_t req_xattr_value_len, char *digest); 41 size_t req_xattr_value_len, char *digest);
42extern int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
43 const char *req_xattr_value,
44 size_t req_xattr_value_len, char *digest);
35extern int evm_init_hmac(struct inode *inode, const struct xattr *xattr, 45extern int evm_init_hmac(struct inode *inode, const struct xattr *xattr,
36 char *hmac_val); 46 char *hmac_val);
37extern int evm_init_secfs(void); 47extern int evm_init_secfs(void);
38extern void evm_cleanup_secfs(void); 48extern void evm_cleanup_secfs(void);
49
50#endif
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
index 5dd5b140242c..847a2d7dff17 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -26,34 +26,48 @@ static unsigned char evmkey[MAX_KEY_SIZE];
26static int evmkey_len = MAX_KEY_SIZE; 26static int evmkey_len = MAX_KEY_SIZE;
27 27
28struct crypto_shash *hmac_tfm; 28struct crypto_shash *hmac_tfm;
29struct crypto_shash *hash_tfm;
29 30
30static struct shash_desc *init_desc(void) 31static struct shash_desc *init_desc(const char type)
31{ 32{
32 int rc; 33 int rc;
34 char *algo;
35 struct crypto_shash **tfm;
33 struct shash_desc *desc; 36 struct shash_desc *desc;
34 37
35 if (hmac_tfm == NULL) { 38 if (type == EVM_XATTR_HMAC) {
36 hmac_tfm = crypto_alloc_shash(evm_hmac, 0, CRYPTO_ALG_ASYNC); 39 tfm = &hmac_tfm;
37 if (IS_ERR(hmac_tfm)) { 40 algo = evm_hmac;
41 } else {
42 tfm = &hash_tfm;
43 algo = evm_hash;
44 }
45
46 if (*tfm == NULL) {
47 *tfm = crypto_alloc_shash(algo, 0, CRYPTO_ALG_ASYNC);
48 if (IS_ERR(*tfm)) {
38 pr_err("Can not allocate %s (reason: %ld)\n", 49 pr_err("Can not allocate %s (reason: %ld)\n",
39 evm_hmac, PTR_ERR(hmac_tfm)); 50 algo, PTR_ERR(*tfm));
40 rc = PTR_ERR(hmac_tfm); 51 rc = PTR_ERR(*tfm);
41 hmac_tfm = NULL; 52 *tfm = NULL;
42 return ERR_PTR(rc); 53 return ERR_PTR(rc);
43 } 54 }
44 } 55 }
45 56
46 desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac_tfm), 57 desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(*tfm),
47 GFP_KERNEL); 58 GFP_KERNEL);
48 if (!desc) 59 if (!desc)
49 return ERR_PTR(-ENOMEM); 60 return ERR_PTR(-ENOMEM);
50 61
51 desc->tfm = hmac_tfm; 62 desc->tfm = *tfm;
52 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 63 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
53 64
54 rc = crypto_shash_setkey(hmac_tfm, evmkey, evmkey_len); 65 if (type == EVM_XATTR_HMAC) {
55 if (rc) 66 rc = crypto_shash_setkey(*tfm, evmkey, evmkey_len);
56 goto out; 67 if (rc)
68 goto out;
69 }
70
57 rc = crypto_shash_init(desc); 71 rc = crypto_shash_init(desc);
58out: 72out:
59 if (rc) { 73 if (rc) {
@@ -97,9 +111,11 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
97 * the hmac using the requested xattr value. Don't alloc/free memory for 111 * the hmac using the requested xattr value. Don't alloc/free memory for
98 * each xattr, but attempt to re-use the previously allocated memory. 112 * each xattr, but attempt to re-use the previously allocated memory.
99 */ 113 */
100int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, 114static int evm_calc_hmac_or_hash(struct dentry *dentry,
101 const char *req_xattr_value, size_t req_xattr_value_len, 115 const char *req_xattr_name,
102 char *digest) 116 const char *req_xattr_value,
117 size_t req_xattr_value_len,
118 char type, char *digest)
103{ 119{
104 struct inode *inode = dentry->d_inode; 120 struct inode *inode = dentry->d_inode;
105 struct shash_desc *desc; 121 struct shash_desc *desc;
@@ -111,7 +127,7 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
111 127
112 if (!inode->i_op || !inode->i_op->getxattr) 128 if (!inode->i_op || !inode->i_op->getxattr)
113 return -EOPNOTSUPP; 129 return -EOPNOTSUPP;
114 desc = init_desc(); 130 desc = init_desc(type);
115 if (IS_ERR(desc)) 131 if (IS_ERR(desc))
116 return PTR_ERR(desc); 132 return PTR_ERR(desc);
117 133
@@ -145,6 +161,22 @@ out:
145 return error; 161 return error;
146} 162}
147 163
164int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
165 const char *req_xattr_value, size_t req_xattr_value_len,
166 char *digest)
167{
168 return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
169 req_xattr_value_len, EVM_XATTR_HMAC, digest);
170}
171
172int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
173 const char *req_xattr_value, size_t req_xattr_value_len,
174 char *digest)
175{
176 return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
177 req_xattr_value_len, IMA_XATTR_DIGEST, digest);
178}
179
148/* 180/*
149 * Calculate the hmac and update security.evm xattr 181 * Calculate the hmac and update security.evm xattr
150 * 182 *
@@ -175,7 +207,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
175{ 207{
176 struct shash_desc *desc; 208 struct shash_desc *desc;
177 209
178 desc = init_desc(); 210 desc = init_desc(EVM_XATTR_HMAC);
179 if (IS_ERR(desc)) { 211 if (IS_ERR(desc)) {
180 printk(KERN_INFO "init_desc failed\n"); 212 printk(KERN_INFO "init_desc failed\n");
181 return PTR_ERR(desc); 213 return PTR_ERR(desc);
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 92d3d99a9f7b..8901501425f4 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -25,6 +25,7 @@
25int evm_initialized; 25int evm_initialized;
26 26
27char *evm_hmac = "hmac(sha1)"; 27char *evm_hmac = "hmac(sha1)";
28char *evm_hash = "sha1";
28 29
29char *evm_config_xattrnames[] = { 30char *evm_config_xattrnames[] = {
30#ifdef CONFIG_SECURITY_SELINUX 31#ifdef CONFIG_SECURITY_SELINUX
@@ -46,6 +47,29 @@ static int __init evm_set_fixmode(char *str)
46} 47}
47__setup("evm=", evm_set_fixmode); 48__setup("evm=", evm_set_fixmode);
48 49
50static int evm_find_protected_xattrs(struct dentry *dentry)
51{
52 struct inode *inode = dentry->d_inode;
53 char **xattr;
54 int error;
55 int count = 0;
56
57 if (!inode->i_op || !inode->i_op->getxattr)
58 return -EOPNOTSUPP;
59
60 for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) {
61 error = inode->i_op->getxattr(dentry, *xattr, NULL, 0);
62 if (error < 0) {
63 if (error == -ENODATA)
64 continue;
65 return error;
66 }
67 count++;
68 }
69
70 return count;
71}
72
49/* 73/*
50 * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr 74 * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr
51 * 75 *
@@ -65,32 +89,72 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
65 size_t xattr_value_len, 89 size_t xattr_value_len,
66 struct integrity_iint_cache *iint) 90 struct integrity_iint_cache *iint)
67{ 91{
68 struct evm_ima_xattr_data xattr_data; 92 struct evm_ima_xattr_data *xattr_data = NULL;
93 struct evm_ima_xattr_data calc;
69 enum integrity_status evm_status = INTEGRITY_PASS; 94 enum integrity_status evm_status = INTEGRITY_PASS;
70 int rc; 95 int rc, xattr_len;
71 96
72 if (iint && iint->evm_status == INTEGRITY_PASS) 97 if (iint && iint->evm_status == INTEGRITY_PASS)
73 return iint->evm_status; 98 return iint->evm_status;
74 99
75 /* if status is not PASS, try to check again - against -ENOMEM */ 100 /* if status is not PASS, try to check again - against -ENOMEM */
76 101
77 rc = evm_calc_hmac(dentry, xattr_name, xattr_value, 102 /* first need to know the sig type */
78 xattr_value_len, xattr_data.digest); 103 rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0,
79 if (rc < 0) { 104 GFP_NOFS);
80 evm_status = (rc == -ENODATA) 105 if (rc <= 0) {
81 ? INTEGRITY_NOXATTRS : INTEGRITY_FAIL; 106 if (rc == 0)
107 evm_status = INTEGRITY_FAIL; /* empty */
108 else if (rc == -ENODATA) {
109 rc = evm_find_protected_xattrs(dentry);
110 if (rc > 0)
111 evm_status = INTEGRITY_NOLABEL;
112 else if (rc == 0)
113 evm_status = INTEGRITY_NOXATTRS; /* new file */
114 }
82 goto out; 115 goto out;
83 } 116 }
84 117
85 xattr_data.type = EVM_XATTR_HMAC; 118 xattr_len = rc - 1;
86 rc = vfs_xattr_cmp(dentry, XATTR_NAME_EVM, (u8 *)&xattr_data, 119
87 sizeof xattr_data, GFP_NOFS); 120 /* check value type */
88 if (rc < 0) 121 switch (xattr_data->type) {
89 evm_status = (rc == -ENODATA) 122 case EVM_XATTR_HMAC:
90 ? INTEGRITY_NOLABEL : INTEGRITY_FAIL; 123 rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
124 xattr_value_len, calc.digest);
125 if (rc)
126 break;
127 rc = memcmp(xattr_data->digest, calc.digest,
128 sizeof(calc.digest));
129 if (rc)
130 rc = -EINVAL;
131 break;
132 case EVM_IMA_XATTR_DIGSIG:
133 rc = evm_calc_hash(dentry, xattr_name, xattr_value,
134 xattr_value_len, calc.digest);
135 if (rc)
136 break;
137 rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM,
138 xattr_data->digest, xattr_len,
139 calc.digest, sizeof(calc.digest));
140 if (!rc) {
141 /* we probably want to replace rsa with hmac here */
142 evm_update_evmxattr(dentry, xattr_name, xattr_value,
143 xattr_value_len);
144 }
145 break;
146 default:
147 rc = -EINVAL;
148 break;
149 }
150
151 if (rc)
152 evm_status = (rc == -ENODATA) ?
153 INTEGRITY_NOXATTRS : INTEGRITY_FAIL;
91out: 154out:
92 if (iint) 155 if (iint)
93 iint->evm_status = evm_status; 156 iint->evm_status = evm_status;
157 kfree(xattr_data);
94 return evm_status; 158 return evm_status;
95} 159}
96 160
@@ -354,6 +418,8 @@ static int __init init_evm(void)
354 printk(KERN_INFO "EVM: Error registering secfs\n"); 418 printk(KERN_INFO "EVM: Error registering secfs\n");
355 goto err; 419 goto err;
356 } 420 }
421
422 return 0;
357err: 423err:
358 return error; 424 return error;
359} 425}
@@ -363,6 +429,8 @@ static void __exit cleanup_evm(void)
363 evm_cleanup_secfs(); 429 evm_cleanup_secfs();
364 if (hmac_tfm) 430 if (hmac_tfm)
365 crypto_free_shash(hmac_tfm); 431 crypto_free_shash(hmac_tfm);
432 if (hash_tfm)
433 crypto_free_shash(hash_tfm);
366} 434}
367 435
368/* 436/*