aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Kasatkin <dmitry.kasatkin@nokia.com>2011-03-09 15:07:36 -0500
committerMimi Zohar <zohar@linux.vnet.ibm.com>2011-07-18 12:29:46 -0400
commitd46eb3699502ba221e81e88e6c6594e2a7818532 (patch)
tree4761b63f12ded9ad53e3019c33d62d173b4b07da
parent823eb1ccd0b310449e99c822412ea8208334d14c (diff)
evm: crypto hash replaced by shash
Using shash is more efficient, because the algorithm is allocated only once. Only the descriptor to store the hash state needs to be allocated for every operation. Changelog v6: - check for crypto_shash_setkey failure Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@nokia.com> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
-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/*