提交 d46eb369 编写于 作者: D Dmitry Kasatkin 提交者: Mimi Zohar

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: NDmitry Kasatkin <dmitry.kasatkin@nokia.com>
Signed-off-by: NMimi Zohar <zohar@linux.vnet.ibm.com>
上级 823eb1cc
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
extern int evm_initialized; extern int evm_initialized;
extern char *evm_hmac; extern char *evm_hmac;
extern struct crypto_shash *hmac_tfm;
/* List of EVM protected security xattrs */ /* List of EVM protected security xattrs */
extern char *evm_config_xattrnames[]; extern char *evm_config_xattrnames[];
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/crypto.h> #include <linux/crypto.h>
#include <linux/xattr.h> #include <linux/xattr.h>
#include <linux/scatterlist.h>
#include <keys/encrypted-type.h> #include <keys/encrypted-type.h>
#include <crypto/hash.h>
#include "evm.h" #include "evm.h"
#define EVMKEY "evm-key" #define EVMKEY "evm-key"
...@@ -25,26 +25,42 @@ ...@@ -25,26 +25,42 @@
static unsigned char evmkey[MAX_KEY_SIZE]; static unsigned char evmkey[MAX_KEY_SIZE];
static int evmkey_len = MAX_KEY_SIZE; static int evmkey_len = MAX_KEY_SIZE;
static int init_desc(struct hash_desc *desc) struct crypto_shash *hmac_tfm;
static struct shash_desc *init_desc(void)
{ {
int rc; int rc;
struct shash_desc *desc;
desc->tfm = crypto_alloc_hash(evm_hmac, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(desc->tfm)) { if (hmac_tfm == NULL) {
pr_info("Can not allocate %s (reason: %ld)\n", hmac_tfm = crypto_alloc_shash(evm_hmac, 0, CRYPTO_ALG_ASYNC);
evm_hmac, PTR_ERR(desc->tfm)); if (IS_ERR(hmac_tfm)) {
rc = PTR_ERR(desc->tfm); pr_err("Can not allocate %s (reason: %ld)\n",
return rc; evm_hmac, PTR_ERR(hmac_tfm));
rc = PTR_ERR(hmac_tfm);
hmac_tfm = NULL;
return ERR_PTR(rc);
}
} }
desc->flags = 0;
rc = crypto_hash_setkey(desc->tfm, evmkey, evmkey_len); desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac_tfm),
GFP_KERNEL);
if (!desc)
return ERR_PTR(-ENOMEM);
desc->tfm = hmac_tfm;
desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
rc = crypto_shash_setkey(hmac_tfm, evmkey, evmkey_len);
if (rc) if (rc)
goto out; goto out;
rc = crypto_hash_init(desc); rc = crypto_shash_init(desc);
out: out:
if (rc) if (rc) {
crypto_free_hash(desc->tfm); kfree(desc);
return rc; return ERR_PTR(rc);
}
return desc;
} }
/* Protect against 'cutting & pasting' security.evm xattr, include inode /* Protect against 'cutting & pasting' security.evm xattr, include inode
...@@ -53,7 +69,7 @@ static int init_desc(struct hash_desc *desc) ...@@ -53,7 +69,7 @@ static int init_desc(struct hash_desc *desc)
* (Additional directory/file metadata needs to be added for more complete * (Additional directory/file metadata needs to be added for more complete
* protection.) * protection.)
*/ */
static void hmac_add_misc(struct hash_desc *desc, struct inode *inode, static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
char *digest) char *digest)
{ {
struct h_misc { struct h_misc {
...@@ -63,7 +79,6 @@ static void hmac_add_misc(struct hash_desc *desc, struct inode *inode, ...@@ -63,7 +79,6 @@ static void hmac_add_misc(struct hash_desc *desc, struct inode *inode,
gid_t gid; gid_t gid;
umode_t mode; umode_t mode;
} hmac_misc; } hmac_misc;
struct scatterlist sg[1];
memset(&hmac_misc, 0, sizeof hmac_misc); memset(&hmac_misc, 0, sizeof hmac_misc);
hmac_misc.ino = inode->i_ino; hmac_misc.ino = inode->i_ino;
...@@ -71,9 +86,8 @@ static void hmac_add_misc(struct hash_desc *desc, struct inode *inode, ...@@ -71,9 +86,8 @@ static void hmac_add_misc(struct hash_desc *desc, struct inode *inode,
hmac_misc.uid = inode->i_uid; hmac_misc.uid = inode->i_uid;
hmac_misc.gid = inode->i_gid; hmac_misc.gid = inode->i_gid;
hmac_misc.mode = inode->i_mode; hmac_misc.mode = inode->i_mode;
sg_init_one(sg, &hmac_misc, sizeof hmac_misc); crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof hmac_misc);
crypto_hash_update(desc, sg, sizeof hmac_misc); crypto_shash_final(desc, digest);
crypto_hash_final(desc, digest);
} }
/* /*
...@@ -88,8 +102,7 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, ...@@ -88,8 +102,7 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
char *digest) char *digest)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct hash_desc desc; struct shash_desc *desc;
struct scatterlist sg[1];
char **xattrname; char **xattrname;
size_t xattr_size = 0; size_t xattr_size = 0;
char *xattr_value = NULL; char *xattr_value = NULL;
...@@ -98,17 +111,17 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, ...@@ -98,17 +111,17 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
if (!inode->i_op || !inode->i_op->getxattr) if (!inode->i_op || !inode->i_op->getxattr)
return -EOPNOTSUPP; return -EOPNOTSUPP;
error = init_desc(&desc); desc = init_desc();
if (error) if (IS_ERR(desc))
return error; return PTR_ERR(desc);
error = -ENODATA; error = -ENODATA;
for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) { for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
if ((req_xattr_name && req_xattr_value) if ((req_xattr_name && req_xattr_value)
&& !strcmp(*xattrname, req_xattr_name)) { && !strcmp(*xattrname, req_xattr_name)) {
error = 0; error = 0;
sg_init_one(sg, req_xattr_value, req_xattr_value_len); crypto_shash_update(desc, (const u8 *)req_xattr_value,
crypto_hash_update(&desc, sg, req_xattr_value_len); req_xattr_value_len);
continue; continue;
} }
size = vfs_getxattr_alloc(dentry, *xattrname, size = vfs_getxattr_alloc(dentry, *xattrname,
...@@ -122,13 +135,13 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, ...@@ -122,13 +135,13 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
error = 0; error = 0;
xattr_size = size; xattr_size = size;
sg_init_one(sg, xattr_value, xattr_size); crypto_shash_update(desc, (const u8 *)xattr_value, xattr_size);
crypto_hash_update(&desc, sg, xattr_size);
} }
hmac_add_misc(&desc, inode, digest); hmac_add_misc(desc, inode, digest);
kfree(xattr_value);
out: out:
crypto_free_hash(desc.tfm); kfree(xattr_value);
kfree(desc);
return error; return error;
} }
...@@ -160,20 +173,17 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name, ...@@ -160,20 +173,17 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr, int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
char *hmac_val) char *hmac_val)
{ {
struct hash_desc desc; struct shash_desc *desc;
struct scatterlist sg[1];
int error;
error = init_desc(&desc); desc = init_desc();
if (error != 0) { if (IS_ERR(desc)) {
printk(KERN_INFO "init_desc failed\n"); printk(KERN_INFO "init_desc failed\n");
return error; return PTR_ERR(desc);
} }
sg_init_one(sg, lsm_xattr->value, lsm_xattr->value_len); crypto_shash_update(desc, lsm_xattr->value, lsm_xattr->value_len);
crypto_hash_update(&desc, sg, lsm_xattr->value_len); hmac_add_misc(desc, inode, hmac_val);
hmac_add_misc(&desc, inode, hmac_val); kfree(desc);
crypto_free_hash(desc.tfm);
return 0; return 0;
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/xattr.h> #include <linux/xattr.h>
#include <linux/integrity.h> #include <linux/integrity.h>
#include <linux/evm.h> #include <linux/evm.h>
#include <crypto/hash.h>
#include "evm.h" #include "evm.h"
int evm_initialized; int evm_initialized;
...@@ -283,12 +284,10 @@ int evm_inode_init_security(struct inode *inode, ...@@ -283,12 +284,10 @@ int evm_inode_init_security(struct inode *inode,
} }
EXPORT_SYMBOL_GPL(evm_inode_init_security); EXPORT_SYMBOL_GPL(evm_inode_init_security);
static struct crypto_hash *tfm_hmac; /* preload crypto alg */
static int __init init_evm(void) static int __init init_evm(void)
{ {
int error; int error;
tfm_hmac = crypto_alloc_hash(evm_hmac, 0, CRYPTO_ALG_ASYNC);
error = evm_init_secfs(); error = evm_init_secfs();
if (error < 0) { if (error < 0) {
printk(KERN_INFO "EVM: Error registering secfs\n"); printk(KERN_INFO "EVM: Error registering secfs\n");
...@@ -301,7 +300,8 @@ static int __init init_evm(void) ...@@ -301,7 +300,8 @@ static int __init init_evm(void)
static void __exit cleanup_evm(void) static void __exit cleanup_evm(void)
{ {
evm_cleanup_secfs(); evm_cleanup_secfs();
crypto_free_hash(tfm_hmac); if (hmac_tfm)
crypto_free_shash(hmac_tfm);
} }
/* /*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册