All of lore.kernel.org
 help / color / mirror / Atom feed
From: Roberto Sassu <roberto.sassu@huawei.com>
To: <zohar@linux.ibm.com>
Cc: <linux-integrity@vger.kernel.org>,
	<linux-security-module@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>,
	Roberto Sassu <roberto.sassu@huawei.com>
Subject: [PATCH 6/7] evm: Allow choice of hash algorithm for HMAC
Date: Fri, 9 Apr 2021 13:43:12 +0200	[thread overview]
Message-ID: <20210409114313.4073-7-roberto.sassu@huawei.com> (raw)
In-Reply-To: <20210409114313.4073-1-roberto.sassu@huawei.com>

Commit 5feeb61183dd ("evm: Allow non-SHA1 digital signatures") introduced
the possibility to use a 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 performs HMAC-related operations. This
variable can be modified at kernel build time with the new configuration
option called CONFIG_EVM_DEFAULT_HASH, or at run-time with the new option
evm_hash=.

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
 .../admin-guide/kernel-parameters.txt         |  8 +++
 security/integrity/evm/Kconfig                | 34 ++++++++++++
 security/integrity/evm/evm.h                  |  2 +
 security/integrity/evm/evm_crypto.c           | 55 +++++++++++++++++--
 security/integrity/evm/evm_main.c             | 13 +++--
 security/integrity/integrity.h                |  3 +-
 6 files changed, 105 insertions(+), 10 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 265f7657f59d..f61ce44c5d8e 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1343,6 +1343,14 @@
 			Permit 'security.evm' to be updated regardless of
 			current integrity status.
 
+	evm_hash=	[EVM] Hash algorithm used to calculate the HMAC.
+			Format: { md5 | sha1 | rmd160 | sha256 | sha384
+				   | sha512 | ... }
+			default: "sha256"
+
+			The list of supported hash algorithms is defined
+			in crypto/hash_info.h.
+
 	failslab=
 	fail_usercopy=
 	fail_page_alloc=
diff --git a/security/integrity/evm/Kconfig b/security/integrity/evm/Kconfig
index a6e19d23e700..234077b24283 100644
--- a/security/integrity/evm/Kconfig
+++ b/security/integrity/evm/Kconfig
@@ -13,6 +13,40 @@ 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. The compiled
+	   default hash algorithm can be overwritten using the kernel command
+	   line 'evm_hash=' option.
+
+	config EVM_DEFAULT_HASH_SHA1
+		bool "SHA1"
+		depends on CRYPTO_SHA1=y
+
+	config EVM_DEFAULT_HASH_SHA256
+		bool "SHA256 (default)"
+		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 f2fef2b5ed51..ae590f71ce7d 100644
--- a/security/integrity/evm/evm.h
+++ b/security/integrity/evm/evm.h
@@ -32,6 +32,7 @@ struct xattr_list {
 };
 
 extern int evm_initialized;
+extern enum hash_algo evm_hash_algo;
 
 #define EVM_ATTR_FSUUID		0x0001
 
@@ -49,6 +50,7 @@ struct evm_digest {
 } __packed;
 
 int evm_init_key(void);
+int __init evm_init_crypto(void);
 int evm_update_evmxattr(struct dentry *dentry,
 			const char *req_xattr_name,
 			const char *req_xattr_value,
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
index d76b006cbcc4..b66264b53d5d 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -33,7 +33,24 @@ static DEFINE_MUTEX(mutex);
 
 static unsigned long evm_set_key_flags;
 
-static const char evm_hmac[] = "hmac(sha1)";
+enum hash_algo evm_hash_algo __ro_after_init = HASH_ALGO_SHA1;
+
+static int hash_setup_done;
+static int __init hash_setup(char *str)
+{
+	int i;
+
+	i = match_string(hash_algo_name, HASH_ALGO__LAST, str);
+	if (i < 0) {
+		pr_err("invalid hash algorithm \"%s\"", str);
+		return 1;
+	}
+
+	evm_hash_algo = i;
+	hash_setup_done = 1;
+	return 1;
+}
+__setup("evm_hash=", hash_setup);
 
 /**
  * evm_set_key() - set EVM HMAC key from the kernel
@@ -74,8 +91,12 @@ static struct shash_desc *init_desc(char type, uint8_t hash_algo)
 	long rc;
 	const char *algo;
 	struct crypto_shash **tfm, *tmp_tfm = NULL;
+	char evm_hmac[CRYPTO_MAX_ALG_NAME];
 	struct shash_desc *desc;
 
+	snprintf(evm_hmac, sizeof(evm_hmac), "hmac(%s)",
+		 hash_algo_name[evm_hash_algo]);
+
 	if (type == EVM_XATTR_HMAC) {
 		if (!(evm_initialized & EVM_INIT_HMAC)) {
 			pr_err_once("HMAC key is not set\n");
@@ -317,7 +338,7 @@ 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) {
@@ -325,7 +346,8 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
 		rc = __vfs_setxattr_noperm(&init_user_ns, 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(&init_user_ns, dentry, XATTR_NAME_EVM);
 	}
@@ -337,7 +359,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);
@@ -350,7 +372,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)
 {
@@ -373,3 +395,26 @@ int evm_init_key(void)
 	key_put(evm_key);
 	return rc;
 }
+
+/*
+ * Configure the hash algorithm for the HMAC
+ */
+int __init evm_init_crypto(void)
+{
+	int i;
+
+	if (hash_setup_done)
+		return 0;
+
+	i = match_string(hash_algo_name, HASH_ALGO__LAST,
+			 CONFIG_EVM_DEFAULT_HASH);
+	if (i < 0) {
+		pr_err("invalid hash algorithm \"%s\"",
+		       CONFIG_EVM_DEFAULT_HASH);
+		return -EINVAL;
+	}
+
+	evm_hash_algo = i;
+
+	return 0;
+}
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 8e80af97021e..cb3754e0cc60 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -187,18 +187,18 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
 	/* check value type */
 	switch (xattr_data->type) {
 	case EVM_XATTR_HMAC:
-		if (xattr_len != sizeof(struct evm_xattr)) {
+		if (xattr_len != hash_digest_size[evm_hash_algo] + 1) {
 			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->data, digest.digest,
-				   SHA1_DIGEST_SIZE);
+				   hash_digest_size[evm_hash_algo]);
 		if (rc)
 			rc = -EINVAL;
 		break;
@@ -722,7 +722,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:
@@ -759,6 +759,11 @@ static int __init init_evm(void)
 		goto error;
 	}
 
+	error = evm_init_crypto();
+	if (error < 0) {
+		pr_info("Error initializing crypto\n");
+		goto error;
+	}
 error:
 	if (error != 0) {
 		if (!list_empty(&evm_config_xattrnames)) {
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index be501a63ae30..74919b638f52 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -17,6 +17,7 @@
 #include <crypto/sha1.h>
 #include <linux/key.h>
 #include <linux/audit.h>
+#include <crypto/hash_info.h>
 
 /* iint action cache flags */
 #define IMA_MEASURE		0x00000001
@@ -89,7 +90,7 @@ struct evm_ima_xattr_data {
 /* Only used in the EVM HMAC code. */
 struct evm_xattr {
 	struct evm_ima_xattr_data data;
-	u8 digest[SHA1_DIGEST_SIZE];
+	u8 digest[SHA512_DIGEST_SIZE];
 } __packed;
 
 #define IMA_MAX_DIGEST_SIZE	64
-- 
2.26.2


  parent reply	other threads:[~2021-04-09 11:45 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-09 11:43 [PATCH 0/7] ima/evm: Small enhancements Roberto Sassu
2021-04-09 11:43 ` [PATCH 1/7] ima: Avoid measurement and audit if access to the file will be denied Roberto Sassu
2021-04-09 11:43 ` [PATCH 2/7] ima: Add meta_immutable appraisal type Roberto Sassu
2021-04-09 11:43 ` [PATCH 3/7] ima: Introduce exec_tcb and tmpfs policies Roberto Sassu
2021-04-09 11:43 ` [PATCH 4/7] ima: Introduce appraise_exec_tcb and appraise_tmpfs policies Roberto Sassu
2021-04-09 11:43 ` [PATCH 5/7] ima: Introduce appraise_exec_immutable policy Roberto Sassu
2021-04-09 11:43 ` Roberto Sassu [this message]
2021-04-09 11:43 ` [PATCH 7/7] evm: Extend evm= with allow_metadata_writes and complete values Roberto Sassu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210409114313.4073-7-roberto.sassu@huawei.com \
    --to=roberto.sassu@huawei.com \
    --cc=linux-integrity@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=zohar@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.