hulk inclusion category: bugfix bugzilla: 3007 CVE: NA
---------------------------
Commit 5feeb61183dd ("evm: Allow non-SHA1 digital signatures") introduced the possibility to use different hash algorithm for signatures, but kept the algorithm for the HMAC hard-coded (SHA1). Switching to a different algorithm for HMAC would require to change the code in different places.
This patch introduces a new global variable called evm_hash_algo, and consistently uses it whenever EVM perform HMAC-related operations. It also introduces a new kernel configuration option called CONFIG_EVM_DEFAULT_HASH so that evm_hash_algo can be defined at kernel compilation time.
Signed-off-by: Roberto Sassu roberto.sassu@huawei.com --- security/integrity/evm/Kconfig | 32 +++++++++++++++++++++++++++++ security/integrity/evm/evm.h | 1 + security/integrity/evm/evm_crypto.c | 15 +++++++++----- security/integrity/evm/evm_main.c | 21 +++++++++++-------- security/integrity/integrity.h | 2 +- 5 files changed, 56 insertions(+), 15 deletions(-)
diff --git a/security/integrity/evm/Kconfig b/security/integrity/evm/Kconfig index 60221852b26a..9ccfa4df58ed 100644 --- a/security/integrity/evm/Kconfig +++ b/security/integrity/evm/Kconfig @@ -12,6 +12,38 @@ config EVM
If you are unsure how to answer this question, answer N.
+choice + prompt "Default EVM hash algorithm" + default EVM_DEFAULT_HASH_SHA256 + depends on EVM + help + Select the default hash algorithm used for the HMAC. + + config EVM_DEFAULT_HASH_SHA1 + bool "SHA1 (default)" + depends on CRYPTO_SHA1=y + + config EVM_DEFAULT_HASH_SHA256 + bool "SHA256" + depends on CRYPTO_SHA256=y + + config EVM_DEFAULT_HASH_SHA512 + bool "SHA512" + depends on CRYPTO_SHA512=y + + config EVM_DEFAULT_HASH_WP512 + bool "WP512" + depends on CRYPTO_WP512=y +endchoice + +config EVM_DEFAULT_HASH + string + depends on EVM + default "sha1" if EVM_DEFAULT_HASH_SHA1 + default "sha256" if EVM_DEFAULT_HASH_SHA256 + default "sha512" if EVM_DEFAULT_HASH_SHA512 + default "wp512" if EVM_DEFAULT_HASH_WP512 + config EVM_ATTR_FSUUID bool "FSUUID (version 2)" default y diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h index c3f437f5db10..9afbe0f3254a 100644 --- a/security/integrity/evm/evm.h +++ b/security/integrity/evm/evm.h @@ -36,6 +36,7 @@ struct xattr_list { };
extern int evm_initialized; +extern enum hash_algo evm_hash_algo;
#define EVM_ATTR_FSUUID 0x0001
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index 61082bff1645..917a08e06b62 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -38,7 +38,7 @@ static DEFINE_MUTEX(mutex);
static unsigned long evm_set_key_flags;
-static char * const evm_hmac = "hmac(sha256)"; +enum hash_algo evm_hash_algo __ro_after_init = HASH_ALGO_SHA256;
/** * evm_set_key() - set EVM HMAC key from the kernel @@ -79,8 +79,12 @@ static struct shash_desc *init_desc(char type, uint8_t hash_algo) long rc; const char *algo; struct crypto_shash **tfm, *tmp_tfm; + char evm_hmac[CRYPTO_MAX_ALG_NAME]; struct shash_desc *desc;
+ snprintf(evm_hmac, sizeof(evm_hmac), "hmac(%s)", + CONFIG_EVM_DEFAULT_HASH); + if (type == EVM_XATTR_HMAC) { if (!(evm_initialized & EVM_INIT_HMAC)) { pr_err_once("HMAC key is not set\n"); @@ -324,14 +328,15 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name, if (rc) return -EPERM;
- data.hdr.algo = HASH_ALGO_SHA1; + data.hdr.algo = evm_hash_algo; rc = evm_calc_hmac(dentry, xattr_name, xattr_value, xattr_value_len, &data); if (rc == 0) { data.hdr.xattr.sha1.type = EVM_XATTR_HMAC; rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM, &data.hdr.xattr.data[1], - SHA1_DIGEST_SIZE + 1, 0); + hash_digest_size[evm_hash_algo] + 1, + 0); } else if (rc == -ENODATA && (inode->i_opflags & IOP_XATTR)) { rc = __vfs_removexattr(dentry, XATTR_NAME_EVM); } @@ -343,7 +348,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr, { struct shash_desc *desc;
- desc = init_desc(EVM_XATTR_HMAC, HASH_ALGO_SHA1); + desc = init_desc(EVM_XATTR_HMAC, evm_hash_algo); if (IS_ERR(desc)) { pr_info("init_desc failed\n"); return PTR_ERR(desc); @@ -356,7 +361,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr, }
/* - * Get the key from the TPM for the SHA1-HMAC + * Get the key from the TPM for the HMAC */ int evm_init_key(void) { diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 181f4758e3bd..61172bd96780 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -196,21 +196,19 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry, /* check value type */ switch (xattr_data->type) { case EVM_XATTR_HMAC: - if (xattr_len < SHA256_DIGEST_SIZE) { + if (xattr_len != hash_digest_size[evm_hash_algo] + 1) { + evm_status = INTEGRITY_FAIL; rc = -EINVAL; break; } - if (xattr_len != sizeof(struct evm_ima_xattr_data)) { - evm_status = INTEGRITY_FAIL; - goto out; - } - digest.hdr.algo = HASH_ALGO_SHA1; + + digest.hdr.algo = evm_hash_algo; rc = evm_calc_hmac(dentry, xattr_name, xattr_value, xattr_value_len, &digest); if (rc) break; rc = crypto_memneq(xattr_data->digest, digest.digest, - SHA1_DIGEST_SIZE); + hash_digest_size[evm_hash_algo]); if (rc) rc = -EINVAL; break; @@ -750,7 +748,7 @@ int evm_inode_init_security(struct inode *inode, goto out;
evm_xattr->value = xattr_data; - evm_xattr->value_len = sizeof(*xattr_data); + evm_xattr->value_len = hash_digest_size[evm_hash_algo] + 1; evm_xattr->name = XATTR_EVM_SUFFIX; return 0; out: @@ -772,10 +770,15 @@ void __init evm_load_x509(void)
static int __init init_evm(void) { - int error; + int error, i; struct list_head *pos, *q; struct xattr_list *xattr;
+ i = match_string(hash_algo_name, HASH_ALGO__LAST, + CONFIG_EVM_DEFAULT_HASH); + if (i >= 0) + evm_hash_algo = i; + evm_init_config();
error = integrity_init_keyring(INTEGRITY_KEYRING_EVM); diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 2828661c6097..82008b9dda57 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -83,7 +83,7 @@ enum evm_ima_xattr_type {
struct evm_ima_xattr_data { u8 type; - u8 digest[SHA256_DIGEST_SIZE]; + u8 digest[SHA512_DIGEST_SIZE]; } __packed;
#define IMA_MAX_DIGEST_SIZE 64