aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity
diff options
context:
space:
mode:
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/*