Commit 69089399 authored by Roberto Sassu's avatar Roberto Sassu Committed by zgzxx
Browse files

evm: Propagate choice of HMAC algorithm in evm_crypto.c

euleros inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I91FSN


CVE: NA

-------------------------------------------------

Commit 5feeb611 ("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.

v5:
 - context adapt  security/integrity/evm/evm_crypto.c for 6.6 kernel

Signed-off-by: default avatarRoberto Sassu <roberto.sassu@huawei.com>
Acked-by: default avatarHanjun Guo <guohanjun@huawei.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: default avatarTianxing Zhang <zhangtianxing3@huawei.com>
Reviewed-by: default avatarJason Yan <yanaijie@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: default avatarzhoushuiqing <zhoushuiqing2@huawei.com>
Signed-off-by: default avatarzhangguangzhi <zhangguangzhi3@huawei.com>
parent 5fbe16a6
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -13,6 +13,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
+3 −0
Original line number Diff line number Diff line
@@ -33,6 +33,9 @@ struct xattr_list {
};

extern int evm_initialized;
#ifdef CONFIG_IMA_DIGEST_LIST
extern enum hash_algo evm_hash_algo;
#endif

#define EVM_ATTR_FSUUID		0x0001

+30 −1
Original line number Diff line number Diff line
@@ -35,7 +35,11 @@ static DEFINE_MUTEX(mutex);

static unsigned long evm_set_key_flags;

#ifdef CONFIG_IMA_DIGEST_LIST
enum hash_algo evm_hash_algo __ro_after_init = HASH_ALGO_SHA1;
#else
static const char evm_hmac[] = "hmac(sha1)";
#endif

/**
 * evm_set_key() - set EVM HMAC key from the kernel
@@ -76,7 +80,14 @@ static struct shash_desc *init_desc(char type, uint8_t hash_algo)
	long rc;
	const char *algo;
	struct crypto_shash **tfm, *tmp_tfm;
#ifdef CONFIG_IMA_DIGEST_LIST
	char evm_hmac[CRYPTO_MAX_ALG_NAME];
#endif
	struct shash_desc *desc;
#ifdef CONFIG_IMA_DIGEST_LIST
	snprintf(evm_hmac, sizeof(evm_hmac), "hmac(%s)",
		 CONFIG_EVM_DEFAULT_HASH);
#endif

	if (type == EVM_XATTR_HMAC) {
		if (!(evm_initialized & EVM_INIT_HMAC)) {
@@ -384,8 +395,11 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
		return rc;
	if (rc)
		return -EPERM;

#ifdef CONFIG_IMA_DIGEST_LIST
	data.hdr.algo = evm_hash_algo;
#else
	data.hdr.algo = HASH_ALGO_SHA1;
#endif
	rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
			   xattr_value_len, &data);
	if (rc == 0) {
@@ -393,7 +407,12 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
		rc = __vfs_setxattr_noperm(&nop_mnt_idmap, dentry,
					   XATTR_NAME_EVM,
					   &data.hdr.xattr.data[1],
#ifdef CONFIG_IMA_DIGEST_LIST
					   hash_digest_size[evm_hash_algo] + 1,
					   0);
#else
					   SHA1_DIGEST_SIZE + 1, 0);
#endif
	} else if (rc == -ENODATA && (inode->i_opflags & IOP_XATTR)) {
		rc = __vfs_removexattr(&nop_mnt_idmap, dentry, XATTR_NAME_EVM);
	}
@@ -406,7 +425,11 @@ int evm_init_hmac(struct inode *inode, const struct xattr *xattrs,
	struct shash_desc *desc;
	const struct xattr *xattr;

#ifdef CONFIG_IMA_DIGEST_LIST
	desc = init_desc(EVM_XATTR_HMAC, evm_hash_algo);
#else
	desc = init_desc(EVM_XATTR_HMAC, HASH_ALGO_SHA1);
#endif
	if (IS_ERR(desc)) {
		pr_info("init_desc failed\n");
		return PTR_ERR(desc);
@@ -424,9 +447,15 @@ int evm_init_hmac(struct inode *inode, const struct xattr *xattrs,
	return 0;
}

#ifdef CONFIG_IMA_DIGEST_LIST
/*
 * Get the key from the TPM for the HMAC
 */
#else
/*
 * Get the key from the TPM for the SHA1-HMAC
 */
#endif
int evm_init_key(void)
{
	struct key *evm_key;
+26 −0
Original line number Diff line number Diff line
@@ -261,18 +261,30 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
	/* check value type */
	switch (xattr_data->type) {
	case EVM_XATTR_HMAC:
#ifdef CONFIG_IMA_DIGEST_LIST
		if (xattr_len != hash_digest_size[evm_hash_algo] + 1) {
#else
		if (xattr_len != sizeof(struct evm_xattr)) {
#endif
			evm_status = INTEGRITY_FAIL;
			goto out;
		}

#ifdef CONFIG_IMA_DIGEST_LIST
		digest.hdr.algo = evm_hash_algo;
#else
		digest.hdr.algo = HASH_ALGO_SHA1;
#endif
		rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
				   xattr_value_len, &digest);
		if (rc)
			break;
		rc = crypto_memneq(xattr_data->data, digest.digest,
#ifdef CONFIG_IMA_DIGEST_LIST
				   hash_digest_size[evm_hash_algo]);
#else
				   SHA1_DIGEST_SIZE);
#endif
		if (rc)
			rc = -EINVAL;
		break;
@@ -1023,7 +1035,11 @@ int evm_inode_init_security(struct inode *inode, struct inode *dir,
		goto out;

	evm_xattr->value = xattr_data;
#ifdef CONFIG_IMA_DIGEST_LIST
	evm_xattr->value_len = hash_digest_size[evm_hash_algo] + 1;
#else
	evm_xattr->value_len = sizeof(*xattr_data);
#endif
	evm_xattr->name = XATTR_EVM_SUFFIX;
	return 0;
out:
@@ -1045,9 +1061,19 @@ void __init evm_load_x509(void)

static int __init init_evm(void)
{
#ifdef CONFIG_IMA_DIGEST_LIST
	int error, i;
#else
	int error;
#endif
	struct list_head *pos, *q;

#ifdef CONFIG_IMA_DIGEST_LIST
	i = match_string(hash_algo_name, HASH_ALGO__LAST,
			 CONFIG_EVM_DEFAULT_HASH);
	if (i >= 0)
		evm_hash_algo = i;
#endif
	evm_init_config();

	error = integrity_init_keyring(INTEGRITY_KEYRING_EVM);
+4 −0
Original line number Diff line number Diff line
@@ -104,7 +104,11 @@ struct evm_ima_xattr_data {
/* Only used in the EVM HMAC code. */
struct evm_xattr {
	struct evm_ima_xattr_data data;
#ifdef CONFIG_IMA_DIGEST_LIST
	u8 digest[SHA512_DIGEST_SIZE];
#else
	u8 digest[SHA1_DIGEST_SIZE];
#endif
} __packed;

#define IMA_MAX_DIGEST_SIZE	HASH_MAX_DIGESTSIZE