aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--security/integrity/evm/evm.h2
-rw-r--r--security/integrity/evm/evm_crypto.c94
-rw-r--r--security/integrity/evm/evm_main.c6
3 files changed, 57 insertions, 45 deletions
diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h
index a45d0d630a30..d320f5197437 100644
--- a/security/integrity/evm/evm.h
+++ b/security/integrity/evm/evm.h
@@ -19,6 +19,8 @@
19extern int evm_initialized; 19extern int evm_initialized;
20extern char *evm_hmac; 20extern char *evm_hmac;
21 21
22extern struct crypto_shash *hmac_tfm;
23
22/* List of EVM protected security xattrs */ 24/* List of EVM protected security xattrs */
23extern char *evm_config_xattrnames[]; 25extern char *evm_config_xattrnames[];
24 26
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
index c9902bddcb9a..5dd5b140242c 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -16,8 +16,8 @@
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/crypto.h> 17#include <linux/crypto.h>
18#include <linux/xattr.h> 18#include <linux/xattr.h>
19#include <linux/scatterlist.h>
20#include <keys/encrypted-type.h> 19#include <keys/encrypted-type.h>
20#include <crypto/hash.h>
21#include "evm.h" 21#include "evm.h"
22 22
23#define EVMKEY "evm-key" 23#define EVMKEY "evm-key"
@@ -25,26 +25,42 @@
25static unsigned char evmkey[MAX_KEY_SIZE]; 25static unsigned char evmkey[MAX_KEY_SIZE];
26static int evmkey_len = MAX_KEY_SIZE; 26static int evmkey_len = MAX_KEY_SIZE;
27 27
28static int init_desc(struct hash_desc *desc) 28struct crypto_shash *hmac_tfm;
29
30static struct shash_desc *init_desc(void)
29{ 31{
30 int rc; 32 int rc;
31 33 struct shash_desc *desc;
32 desc->tfm = crypto_alloc_hash(evm_hmac, 0, CRYPTO_ALG_ASYNC); 34
33 if (IS_ERR(desc->tfm)) { 35 if (hmac_tfm == NULL) {
34 pr_info("Can not allocate %s (reason: %ld)\n", 36 hmac_tfm = crypto_alloc_shash(evm_hmac, 0, CRYPTO_ALG_ASYNC);
35 evm_hmac, PTR_ERR(desc->tfm)); 37 if (IS_ERR(hmac_tfm)) {
36 rc = PTR_ERR(desc->tfm); 38 pr_err("Can not allocate %s (reason: %ld)\n",
37 return rc; 39 evm_hmac, PTR_ERR(hmac_tfm));
40 rc = PTR_ERR(hmac_tfm);
41 hmac_tfm = NULL;
42 return ERR_PTR(rc);
43 }
38 } 44 }
39 desc->flags = 0; 45
40 rc = crypto_hash_setkey(desc->tfm, evmkey, evmkey_len); 46 desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac_tfm),
47 GFP_KERNEL);
48 if (!desc)
49 return ERR_PTR(-ENOMEM);
50
51 desc->tfm = hmac_tfm;
52 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
53
54 rc = crypto_shash_setkey(hmac_tfm, evmkey, evmkey_len);
41 if (rc) 55 if (rc)
42 goto out; 56 goto out;
43 rc = crypto_hash_init(desc); 57 rc = crypto_shash_init(desc);
44out: 58out:
45 if (rc) 59 if (rc) {
46 crypto_free_hash(desc->tfm); 60 kfree(desc);
47 return rc; 61 return ERR_PTR(rc);
62 }
63 return desc;
48} 64}
49 65
50/* Protect against 'cutting & pasting' security.evm xattr, include inode 66/* Protect against 'cutting & pasting' security.evm xattr, include inode
@@ -53,7 +69,7 @@ out:
53 * (Additional directory/file metadata needs to be added for more complete 69 * (Additional directory/file metadata needs to be added for more complete
54 * protection.) 70 * protection.)
55 */ 71 */
56static void hmac_add_misc(struct hash_desc *desc, struct inode *inode, 72static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
57 char *digest) 73 char *digest)
58{ 74{
59 struct h_misc { 75 struct h_misc {
@@ -63,7 +79,6 @@ static void hmac_add_misc(struct hash_desc *desc, struct inode *inode,
63 gid_t gid; 79 gid_t gid;
64 umode_t mode; 80 umode_t mode;
65 } hmac_misc; 81 } hmac_misc;
66 struct scatterlist sg[1];
67 82
68 memset(&hmac_misc, 0, sizeof hmac_misc); 83 memset(&hmac_misc, 0, sizeof hmac_misc);
69 hmac_misc.ino = inode->i_ino; 84 hmac_misc.ino = inode->i_ino;
@@ -71,9 +86,8 @@ static void hmac_add_misc(struct hash_desc *desc, struct inode *inode,
71 hmac_misc.uid = inode->i_uid; 86 hmac_misc.uid = inode->i_uid;
72 hmac_misc.gid = inode->i_gid; 87 hmac_misc.gid = inode->i_gid;
73 hmac_misc.mode = inode->i_mode; 88 hmac_misc.mode = inode->i_mode;
74 sg_init_one(sg, &hmac_misc, sizeof hmac_misc); 89 crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof hmac_misc);
75 crypto_hash_update(desc, sg, sizeof hmac_misc); 90 crypto_shash_final(desc, digest);
76 crypto_hash_final(desc, digest);
77} 91}
78 92
79/* 93/*
@@ -88,8 +102,7 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
88 char *digest) 102 char *digest)
89{ 103{
90 struct inode *inode = dentry->d_inode; 104 struct inode *inode = dentry->d_inode;
91 struct hash_desc desc; 105 struct shash_desc *desc;
92 struct scatterlist sg[1];
93 char **xattrname; 106 char **xattrname;
94 size_t xattr_size = 0; 107 size_t xattr_size = 0;
95 char *xattr_value = NULL; 108 char *xattr_value = NULL;
@@ -98,17 +111,17 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
98 111
99 if (!inode->i_op || !inode->i_op->getxattr) 112 if (!inode->i_op || !inode->i_op->getxattr)
100 return -EOPNOTSUPP; 113 return -EOPNOTSUPP;
101 error = init_desc(&desc); 114 desc = init_desc();
102 if (error) 115 if (IS_ERR(desc))
103 return error; 116 return PTR_ERR(desc);
104 117
105 error = -ENODATA; 118 error = -ENODATA;
106 for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) { 119 for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
107 if ((req_xattr_name && req_xattr_value) 120 if ((req_xattr_name && req_xattr_value)
108 && !strcmp(*xattrname, req_xattr_name)) { 121 && !strcmp(*xattrname, req_xattr_name)) {
109 error = 0; 122 error = 0;
110 sg_init_one(sg, req_xattr_value, req_xattr_value_len); 123 crypto_shash_update(desc, (const u8 *)req_xattr_value,
111 crypto_hash_update(&desc, sg, req_xattr_value_len); 124 req_xattr_value_len);
112 continue; 125 continue;
113 } 126 }
114 size = vfs_getxattr_alloc(dentry, *xattrname, 127 size = vfs_getxattr_alloc(dentry, *xattrname,
@@ -122,13 +135,13 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
122 135
123 error = 0; 136 error = 0;
124 xattr_size = size; 137 xattr_size = size;
125 sg_init_one(sg, xattr_value, xattr_size); 138 crypto_shash_update(desc, (const u8 *)xattr_value, xattr_size);
126 crypto_hash_update(&desc, sg, xattr_size);
127 } 139 }
128 hmac_add_misc(&desc, inode, digest); 140 hmac_add_misc(desc, inode, digest);
129 kfree(xattr_value); 141
130out: 142out:
131 crypto_free_hash(desc.tfm); 143 kfree(xattr_value);
144 kfree(desc);
132 return error; 145 return error;
133} 146}
134 147
@@ -160,20 +173,17 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
160int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr, 173int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
161 char *hmac_val) 174 char *hmac_val)
162{ 175{
163 struct hash_desc desc; 176 struct shash_desc *desc;
164 struct scatterlist sg[1];
165 int error;
166 177
167 error = init_desc(&desc); 178 desc = init_desc();
168 if (error != 0) { 179 if (IS_ERR(desc)) {
169 printk(KERN_INFO "init_desc failed\n"); 180 printk(KERN_INFO "init_desc failed\n");
170 return error; 181 return PTR_ERR(desc);
171 } 182 }
172 183
173 sg_init_one(sg, lsm_xattr->value, lsm_xattr->value_len); 184 crypto_shash_update(desc, lsm_xattr->value, lsm_xattr->value_len);
174 crypto_hash_update(&desc, sg, lsm_xattr->value_len); 185 hmac_add_misc(desc, inode, hmac_val);
175 hmac_add_misc(&desc, inode, hmac_val); 186 kfree(desc);
176 crypto_free_hash(desc.tfm);
177 return 0; 187 return 0;
178} 188}
179 189
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 23486355f443..b65adb5b06c8 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -19,6 +19,7 @@
19#include <linux/xattr.h> 19#include <linux/xattr.h>
20#include <linux/integrity.h> 20#include <linux/integrity.h>
21#include <linux/evm.h> 21#include <linux/evm.h>
22#include <crypto/hash.h>
22#include "evm.h" 23#include "evm.h"
23 24
24int evm_initialized; 25int evm_initialized;
@@ -283,12 +284,10 @@ out:
283} 284}
284EXPORT_SYMBOL_GPL(evm_inode_init_security); 285EXPORT_SYMBOL_GPL(evm_inode_init_security);
285 286
286static struct crypto_hash *tfm_hmac; /* preload crypto alg */
287static int __init init_evm(void) 287static int __init init_evm(void)
288{ 288{
289 int error; 289 int error;
290 290
291 tfm_hmac = crypto_alloc_hash(evm_hmac, 0, CRYPTO_ALG_ASYNC);
292 error = evm_init_secfs(); 291 error = evm_init_secfs();
293 if (error < 0) { 292 if (error < 0) {
294 printk(KERN_INFO "EVM: Error registering secfs\n"); 293 printk(KERN_INFO "EVM: Error registering secfs\n");
@@ -301,7 +300,8 @@ err:
301static void __exit cleanup_evm(void) 300static void __exit cleanup_evm(void)
302{ 301{
303 evm_cleanup_secfs(); 302 evm_cleanup_secfs();
304 crypto_free_hash(tfm_hmac); 303 if (hmac_tfm)
304 crypto_free_shash(hmac_tfm);
305} 305}
306 306
307/* 307/*