Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933651Ab1FBM2x (ORCPT ); Thu, 2 Jun 2011 08:28:53 -0400 Received: from e4.ny.us.ibm.com ([32.97.182.144]:43510 "EHLO e4.ny.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933551Ab1FBMZ0 (ORCPT ); Thu, 2 Jun 2011 08:25:26 -0400 From: Mimi Zohar To: linux-security-module@vger.kernel.org Cc: Dmitry Kasatkin , linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, James Morris , David Safford , Andrew Morton , Greg KH , Dmitry Kasatkin , Mimi Zohar Subject: [PATCH v6 10/20] evm: crypto hash replaced by shash Date: Thu, 2 Jun 2011 08:23:33 -0400 Message-Id: <1307017423-15093-11-git-send-email-zohar@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: <1307017423-15093-1-git-send-email-zohar@linux.vnet.ibm.com> References: <1307017423-15093-1-git-send-email-zohar@linux.vnet.ibm.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 7333 Lines: 254 From: Dmitry Kasatkin 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 Signed-off-by: Mimi Zohar --- security/integrity/evm/evm.h | 2 + security/integrity/evm/evm_crypto.c | 96 +++++++++++++++++++---------------- security/integrity/evm/evm_main.c | 6 +- 3 files changed, 58 insertions(+), 46 deletions(-) diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h index a45d0d6..d320f51 100644 --- a/security/integrity/evm/evm.h +++ b/security/integrity/evm/evm.h @@ -19,6 +19,8 @@ extern int evm_initialized; extern char *evm_hmac; +extern struct crypto_shash *hmac_tfm; + /* List of EVM protected security xattrs */ extern char *evm_config_xattrnames[]; diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index c9902bd..a57e0f0 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -16,8 +16,8 @@ #include #include #include -#include #include +#include #include "evm.h" #define EVMKEY "evm-key" @@ -25,26 +25,42 @@ static unsigned char evmkey[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; - - desc->tfm = crypto_alloc_hash(evm_hmac, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(desc->tfm)) { - pr_info("Can not allocate %s (reason: %ld)\n", - evm_hmac, PTR_ERR(desc->tfm)); - rc = PTR_ERR(desc->tfm); - return rc; + struct shash_desc *desc; + + if (hmac_tfm == NULL) { + hmac_tfm = crypto_alloc_shash(evm_hmac, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(hmac_tfm)) { + pr_err("Can not allocate %s (reason: %ld)\n", + 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) - goto out; - rc = crypto_hash_init(desc); + goto out; + rc = crypto_shash_init(desc); out: - if (rc) - crypto_free_hash(desc->tfm); - return rc; + if (rc) { + kfree(desc); + return ERR_PTR(rc); + } + return desc; } /* Protect against 'cutting & pasting' security.evm xattr, include inode @@ -53,7 +69,7 @@ out: * (Additional directory/file metadata needs to be added for more complete * 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) { struct h_misc { @@ -63,7 +79,6 @@ static void hmac_add_misc(struct hash_desc *desc, struct inode *inode, gid_t gid; umode_t mode; } hmac_misc; - struct scatterlist sg[1]; memset(&hmac_misc, 0, sizeof hmac_misc); hmac_misc.ino = inode->i_ino; @@ -71,9 +86,8 @@ static void hmac_add_misc(struct hash_desc *desc, struct inode *inode, hmac_misc.uid = inode->i_uid; hmac_misc.gid = inode->i_gid; hmac_misc.mode = inode->i_mode; - sg_init_one(sg, &hmac_misc, sizeof hmac_misc); - crypto_hash_update(desc, sg, sizeof hmac_misc); - crypto_hash_final(desc, digest); + crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof hmac_misc); + crypto_shash_final(desc, digest); } /* @@ -88,8 +102,7 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, char *digest) { struct inode *inode = dentry->d_inode; - struct hash_desc desc; - struct scatterlist sg[1]; + struct shash_desc *desc; char **xattrname; size_t xattr_size = 0; char *xattr_value = NULL; @@ -98,17 +111,17 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, if (!inode->i_op || !inode->i_op->getxattr) return -EOPNOTSUPP; - error = init_desc(&desc); - if (error) - return error; + desc = init_desc(); + if (IS_ERR(desc)) + return PTR_ERR(desc); error = -ENODATA; for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) { if ((req_xattr_name && req_xattr_value) && !strcmp(*xattrname, req_xattr_name)) { error = 0; - sg_init_one(sg, req_xattr_value, req_xattr_value_len); - crypto_hash_update(&desc, sg, req_xattr_value_len); + crypto_shash_update(desc, (const u8 *)req_xattr_value, + req_xattr_value_len); continue; } size = vfs_getxattr_alloc(dentry, *xattrname, @@ -122,13 +135,13 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, error = 0; xattr_size = size; - sg_init_one(sg, xattr_value, xattr_size); - crypto_hash_update(&desc, sg, xattr_size); + crypto_shash_update(desc, (const u8 *)xattr_value, xattr_size); } - hmac_add_misc(&desc, inode, digest); - kfree(xattr_value); + hmac_add_misc(desc, inode, digest); + out: - crypto_free_hash(desc.tfm); + kfree(xattr_value); + kfree(desc); return error; } @@ -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, char *hmac_val) { - struct hash_desc desc; - struct scatterlist sg[1]; - int error; + struct shash_desc *desc; - error = init_desc(&desc); - if (error != 0) { + desc = init_desc(); + if (IS_ERR(desc)) { 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_hash_update(&desc, sg, lsm_xattr->value_len); - hmac_add_misc(&desc, inode, hmac_val); - crypto_free_hash(desc.tfm); + crypto_shash_update(desc, lsm_xattr->value, lsm_xattr->value_len); + hmac_add_misc(desc, inode, hmac_val); + kfree(desc); return 0; } diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index d48e815..0f3e8a6 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "evm.h" int evm_initialized; @@ -283,12 +284,10 @@ out: } EXPORT_SYMBOL_GPL(evm_inode_post_init_security); -static struct crypto_hash *tfm_hmac; /* preload crypto alg */ static int __init init_evm(void) { int error; - tfm_hmac = crypto_alloc_hash(evm_hmac, 0, CRYPTO_ALG_ASYNC); error = evm_init_secfs(); if (error < 0) { printk(KERN_INFO "EVM: Error registering secfs\n"); @@ -301,7 +300,8 @@ err: static void __exit cleanup_evm(void) { evm_cleanup_secfs(); - crypto_free_hash(tfm_hmac); + if (hmac_tfm) + crypto_free_shash(hmac_tfm); } /* -- 1.7.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/