Skip to content

Commit d46eb36

Browse files
Dmitry KasatkinMimi Zohar
authored andcommitted
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>
1 parent 823eb1c commit d46eb36

File tree

3 files changed

+57
-45
lines changed

3 files changed

+57
-45
lines changed

security/integrity/evm/evm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
extern int evm_initialized;
2020
extern char *evm_hmac;
2121

22+
extern struct crypto_shash *hmac_tfm;
23+
2224
/* List of EVM protected security xattrs */
2325
extern char *evm_config_xattrnames[];
2426

security/integrity/evm/evm_crypto.c

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,35 +16,51 @@
1616
#include <linux/module.h>
1717
#include <linux/crypto.h>
1818
#include <linux/xattr.h>
19-
#include <linux/scatterlist.h>
2019
#include <keys/encrypted-type.h>
20+
#include <crypto/hash.h>
2121
#include "evm.h"
2222

2323
#define EVMKEY "evm-key"
2424
#define MAX_KEY_SIZE 128
2525
static unsigned char evmkey[MAX_KEY_SIZE];
2626
static int evmkey_len = MAX_KEY_SIZE;
2727

28-
static int init_desc(struct hash_desc *desc)
28+
struct crypto_shash *hmac_tfm;
29+
30+
static struct shash_desc *init_desc(void)
2931
{
3032
int rc;
31-
32-
desc->tfm = crypto_alloc_hash(evm_hmac, 0, CRYPTO_ALG_ASYNC);
33-
if (IS_ERR(desc->tfm)) {
34-
pr_info("Can not allocate %s (reason: %ld)\n",
35-
evm_hmac, PTR_ERR(desc->tfm));
36-
rc = PTR_ERR(desc->tfm);
37-
return rc;
33+
struct shash_desc *desc;
34+
35+
if (hmac_tfm == NULL) {
36+
hmac_tfm = crypto_alloc_shash(evm_hmac, 0, CRYPTO_ALG_ASYNC);
37+
if (IS_ERR(hmac_tfm)) {
38+
pr_err("Can not allocate %s (reason: %ld)\n",
39+
evm_hmac, PTR_ERR(hmac_tfm));
40+
rc = PTR_ERR(hmac_tfm);
41+
hmac_tfm = NULL;
42+
return ERR_PTR(rc);
43+
}
3844
}
39-
desc->flags = 0;
40-
rc = crypto_hash_setkey(desc->tfm, evmkey, evmkey_len);
45+
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);
4155
if (rc)
4256
goto out;
43-
rc = crypto_hash_init(desc);
57+
rc = crypto_shash_init(desc);
4458
out:
45-
if (rc)
46-
crypto_free_hash(desc->tfm);
47-
return rc;
59+
if (rc) {
60+
kfree(desc);
61+
return ERR_PTR(rc);
62+
}
63+
return desc;
4864
}
4965

5066
/* Protect against 'cutting & pasting' security.evm xattr, include inode
@@ -53,7 +69,7 @@ static int init_desc(struct hash_desc *desc)
5369
* (Additional directory/file metadata needs to be added for more complete
5470
* protection.)
5571
*/
56-
static void hmac_add_misc(struct hash_desc *desc, struct inode *inode,
72+
static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
5773
char *digest)
5874
{
5975
struct h_misc {
@@ -63,17 +79,15 @@ static void hmac_add_misc(struct hash_desc *desc, struct inode *inode,
6379
gid_t gid;
6480
umode_t mode;
6581
} hmac_misc;
66-
struct scatterlist sg[1];
6782

6883
memset(&hmac_misc, 0, sizeof hmac_misc);
6984
hmac_misc.ino = inode->i_ino;
7085
hmac_misc.generation = inode->i_generation;
7186
hmac_misc.uid = inode->i_uid;
7287
hmac_misc.gid = inode->i_gid;
7388
hmac_misc.mode = inode->i_mode;
74-
sg_init_one(sg, &hmac_misc, sizeof hmac_misc);
75-
crypto_hash_update(desc, sg, sizeof hmac_misc);
76-
crypto_hash_final(desc, digest);
89+
crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof hmac_misc);
90+
crypto_shash_final(desc, digest);
7791
}
7892

7993
/*
@@ -88,8 +102,7 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
88102
char *digest)
89103
{
90104
struct inode *inode = dentry->d_inode;
91-
struct hash_desc desc;
92-
struct scatterlist sg[1];
105+
struct shash_desc *desc;
93106
char **xattrname;
94107
size_t xattr_size = 0;
95108
char *xattr_value = NULL;
@@ -98,17 +111,17 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
98111

99112
if (!inode->i_op || !inode->i_op->getxattr)
100113
return -EOPNOTSUPP;
101-
error = init_desc(&desc);
102-
if (error)
103-
return error;
114+
desc = init_desc();
115+
if (IS_ERR(desc))
116+
return PTR_ERR(desc);
104117

105118
error = -ENODATA;
106119
for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
107120
if ((req_xattr_name && req_xattr_value)
108121
&& !strcmp(*xattrname, req_xattr_name)) {
109122
error = 0;
110-
sg_init_one(sg, req_xattr_value, req_xattr_value_len);
111-
crypto_hash_update(&desc, sg, req_xattr_value_len);
123+
crypto_shash_update(desc, (const u8 *)req_xattr_value,
124+
req_xattr_value_len);
112125
continue;
113126
}
114127
size = vfs_getxattr_alloc(dentry, *xattrname,
@@ -122,13 +135,13 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
122135

123136
error = 0;
124137
xattr_size = size;
125-
sg_init_one(sg, xattr_value, xattr_size);
126-
crypto_hash_update(&desc, sg, xattr_size);
138+
crypto_shash_update(desc, (const u8 *)xattr_value, xattr_size);
127139
}
128-
hmac_add_misc(&desc, inode, digest);
129-
kfree(xattr_value);
140+
hmac_add_misc(desc, inode, digest);
141+
130142
out:
131-
crypto_free_hash(desc.tfm);
143+
kfree(xattr_value);
144+
kfree(desc);
132145
return error;
133146
}
134147

@@ -160,20 +173,17 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
160173
int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
161174
char *hmac_val)
162175
{
163-
struct hash_desc desc;
164-
struct scatterlist sg[1];
165-
int error;
176+
struct shash_desc *desc;
166177

167-
error = init_desc(&desc);
168-
if (error != 0) {
178+
desc = init_desc();
179+
if (IS_ERR(desc)) {
169180
printk(KERN_INFO "init_desc failed\n");
170-
return error;
181+
return PTR_ERR(desc);
171182
}
172183

173-
sg_init_one(sg, lsm_xattr->value, lsm_xattr->value_len);
174-
crypto_hash_update(&desc, sg, lsm_xattr->value_len);
175-
hmac_add_misc(&desc, inode, hmac_val);
176-
crypto_free_hash(desc.tfm);
184+
crypto_shash_update(desc, lsm_xattr->value, lsm_xattr->value_len);
185+
hmac_add_misc(desc, inode, hmac_val);
186+
kfree(desc);
177187
return 0;
178188
}
179189

security/integrity/evm/evm_main.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/xattr.h>
2020
#include <linux/integrity.h>
2121
#include <linux/evm.h>
22+
#include <crypto/hash.h>
2223
#include "evm.h"
2324

2425
int evm_initialized;
@@ -283,12 +284,10 @@ int evm_inode_init_security(struct inode *inode,
283284
}
284285
EXPORT_SYMBOL_GPL(evm_inode_init_security);
285286

286-
static struct crypto_hash *tfm_hmac; /* preload crypto alg */
287287
static int __init init_evm(void)
288288
{
289289
int error;
290290

291-
tfm_hmac = crypto_alloc_hash(evm_hmac, 0, CRYPTO_ALG_ASYNC);
292291
error = evm_init_secfs();
293292
if (error < 0) {
294293
printk(KERN_INFO "EVM: Error registering secfs\n");
@@ -301,7 +300,8 @@ static int __init init_evm(void)
301300
static void __exit cleanup_evm(void)
302301
{
303302
evm_cleanup_secfs();
304-
crypto_free_hash(tfm_hmac);
303+
if (hmac_tfm)
304+
crypto_free_shash(hmac_tfm);
305305
}
306306

307307
/*

0 commit comments

Comments
 (0)