Linux-Integrity Archive mirror
 help / color / mirror / Atom feed
From: Enrico Bravi <enrico.bravi@polito.it>
To: linux-integrity@vger.kernel.org, zohar@linux.ibm.com,
	roberto.sassu@huawei.com
Cc: Enrico Bravi <enrico.bravi@polito.it>,
	Silvia Sisinni <silvia.sisinni@polito.it>
Subject: [RFC][PATCH] ima: add crypto agility support for template-hash algorithm
Date: Thu, 14 Dec 2023 15:51:53 +0100	[thread overview]
Message-ID: <20231214145152.36985-1-enrico.bravi@polito.it> (raw)

The purpose of this patch is to add the possibility to configure the hash
algorithm to use when calculating the template-hash.
The ima_template_hash command line parameter has been introduced to enable
this configuration.
The entry will contain the hash_algo_name before the actual template-hash,
separated by a colon (:).
An example of the resulting ima log is the following:

10 sha256:64326[...]25313 ima-ng sha1:5fc9b[...]974e6 boot_aggregate
10 sha256:afd64[...]e3123 ima-ng sha1:5a493[...]f9566 /init
10 sha256:99329[...]a6353 ima-ng sha1:8c87d[...]3d8c7 /usr/bin/sh
10 sha256:a16ad[...]2ac0e ima-ng sha1:59d4b[...]330b0 /etc/ld.so.cache

This patch has been created starting from the master branch of the main tree:
<git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git>

Signed-off-by: Silvia Sisinni <silvia.sisinni@polito.it>
Signed-off-by: Enrico Bravi <enrico.bravi@polito.it>
---
 security/integrity/ima/Kconfig      | 30 +++++++++++++++++++++++++++
 security/integrity/ima/ima.h        |  2 ++
 security/integrity/ima/ima_crypto.c | 26 ++++++++++++++++++++++-
 security/integrity/ima/ima_fs.c     | 25 ++++++++++++++--------
 security/integrity/ima/ima_main.c   | 32 +++++++++++++++++++++++++++++
 5 files changed, 105 insertions(+), 10 deletions(-)

diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index a6bd817efc1a..9cdeedb2be53 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -121,6 +121,36 @@ config IMA_DEFAULT_HASH
 	default "wp512" if IMA_DEFAULT_HASH_WP512
 	default "sm3" if IMA_DEFAULT_HASH_SM3
 
+choice
+	prompt "Default template-hash algorithm"
+	default IMA_DEFAULT_TEMPLATE_HASH_SHA1
+	depends on IMA
+	help
+	   Select the default template-hash algorithm written in Measurement
+	   Log entries. The compiled default template-hash algorithm can
+	   be overwritten using the kernel command line 'ima_template_hash='
+	   option.
+
+	config IMA_DEFAULT_TEMPLATE_HASH_SHA1
+		bool "SHA1 (default)"
+		depends on CRYPTO_SHA1=y
+
+	config IMA_DEFAULT_TEMPLATE_HASH_SHA256
+		bool "SHA256"
+		depends on CRYPTO_SHA256=y
+
+	config IMA_DEFAULT_TEMPLATE_HASH_SHA512
+		bool "SHA512"
+		depends on CRYPTO_SHA512=y
+endchoice
+
+config IMA_DEFAULT_TEMPLATE_HASH
+	string
+	depends on IMA
+	default "sha1" if IMA_DEFAULT_TEMPLATE_HASH_SHA1
+	default "sha256" if IMA_DEFAULT_TEMPLATE_HASH_SHA256
+	default "sha512" if IMA_DEFAULT_TEMPLATE_HASH_SHA512
+
 config IMA_WRITE_POLICY
 	bool "Enable multiple writes to the IMA policy"
 	default n
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index c29db699c996..a19375b9a6e4 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -55,6 +55,8 @@ extern int ima_sha1_idx __ro_after_init;
 extern int ima_hash_algo_idx __ro_after_init;
 extern int ima_extra_slots __ro_after_init;
 extern int ima_appraise;
+extern int ima_template_hash_algo __ro_after_init;
+extern int ima_template_hash_algo_idx __ro_after_init;
 extern struct tpm_chip *ima_tpm_chip;
 extern const char boot_aggregate_name[];
 
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 51ad29940f05..448b55ed5033 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -64,6 +64,7 @@ struct ima_algo_desc {
 
 int ima_sha1_idx __ro_after_init;
 int ima_hash_algo_idx __ro_after_init;
+int ima_template_hash_algo_idx __ro_after_init;
 /*
  * Additional number of slots reserved, as needed, for SHA1
  * and IMA default algo.
@@ -124,6 +125,7 @@ int __init ima_init_crypto(void)
 
 	ima_sha1_idx = -1;
 	ima_hash_algo_idx = -1;
+	ima_template_hash_algo_idx = -1;
 
 	for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
 		algo = ima_tpm_chip->allocated_banks[i].crypto_id;
@@ -132,16 +134,28 @@ int __init ima_init_crypto(void)
 
 		if (algo == ima_hash_algo)
 			ima_hash_algo_idx = i;
+
+		if (algo == ima_template_hash_algo)
+			ima_template_hash_algo_idx = i;
 	}
 
 	if (ima_sha1_idx < 0) {
 		ima_sha1_idx = NR_BANKS(ima_tpm_chip) + ima_extra_slots++;
 		if (ima_hash_algo == HASH_ALGO_SHA1)
 			ima_hash_algo_idx = ima_sha1_idx;
+
+		if (ima_template_hash_algo == HASH_ALGO_SHA1)
+			ima_template_hash_algo_idx = ima_sha1_idx;
 	}
 
-	if (ima_hash_algo_idx < 0)
+	if (ima_hash_algo_idx < 0) {
 		ima_hash_algo_idx = NR_BANKS(ima_tpm_chip) + ima_extra_slots++;
+		if (ima_template_hash_algo == ima_hash_algo)
+			ima_template_hash_algo_idx = ima_hash_algo_idx;
+	}
+
+	if (ima_template_hash_algo_idx < 0)
+		ima_template_hash_algo_idx = NR_BANKS(ima_tpm_chip) + ima_extra_slots++;
 
 	ima_algo_array = kcalloc(NR_BANKS(ima_tpm_chip) + ima_extra_slots,
 				 sizeof(*ima_algo_array), GFP_KERNEL);
@@ -196,6 +210,16 @@ int __init ima_init_crypto(void)
 		ima_algo_array[ima_hash_algo_idx].algo = ima_hash_algo;
 	}
 
+	if (ima_template_hash_algo_idx >= NR_BANKS(ima_tpm_chip) &&
+		ima_template_hash_algo_idx != ima_sha1_idx &&
+		ima_template_hash_algo_idx != ima_hash_algo_idx) {
+		ima_algo_array[ima_template_hash_algo_idx].tfm = ima_alloc_tfm(ima_template_hash_algo);
+		if (IS_ERR(ima_algo_array[ima_template_hash_algo_idx].tfm)) {
+			rc = PTR_ERR(ima_algo_array[ima_template_hash_algo_idx].tfm);
+			goto out_array;
+		}
+	}
+
 	return 0;
 out_array:
 	for (i = 0; i < NR_BANKS(ima_tpm_chip) + ima_extra_slots; i++) {
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index cd1683dad3bf..5545602a6144 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -21,6 +21,7 @@
 #include <linux/rcupdate.h>
 #include <linux/parser.h>
 #include <linux/vmalloc.h>
+#include <crypto/hash_info.h>
 
 #include "ima.h"
 
@@ -130,7 +131,7 @@ int ima_measurements_show(struct seq_file *m, void *v)
 	struct ima_queue_entry *qe = v;
 	struct ima_template_entry *e;
 	char *template_name;
-	u32 pcr, namelen, template_data_len; /* temporary fields */
+	u32 pcr, namelen, template_hash_len, template_data_len; /* temporary fields */
 	bool is_ima_template = false;
 	int i;
 
@@ -150,18 +151,23 @@ int ima_measurements_show(struct seq_file *m, void *v)
 	pcr = !ima_canonical_fmt ? e->pcr : (__force u32)cpu_to_le32(e->pcr);
 	ima_putc(m, &pcr, sizeof(e->pcr));
 
-	/* 2nd: template digest */
-	ima_putc(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE);
+	/* 2nd: template digest size */
+	template_hash_len = !ima_canonical_fmt ? hash_digest_size[ima_template_hash_algo] :
+		(__force u32)cpu_to_le32(hash_digest_size[ima_template_hash_algo]);
+	ima_putc(m, &template_hash_len, sizeof(template_hash_len));
 
-	/* 3rd: template name size */
+	/* 3rd: template digest */
+	ima_putc(m, e->digests[ima_template_hash_algo_idx].digest, hash_digest_size[ima_template_hash_algo]);
+
+	/* 4th: template name size */
 	namelen = !ima_canonical_fmt ? strlen(template_name) :
 		(__force u32)cpu_to_le32(strlen(template_name));
 	ima_putc(m, &namelen, sizeof(namelen));
 
-	/* 4th:  template name */
+	/* 5th:  template name */
 	ima_putc(m, template_name, strlen(template_name));
 
-	/* 5th:  template length (except for 'ima' template) */
+	/* 6th:  template length (except for 'ima' template) */
 	if (strcmp(template_name, IMA_TEMPLATE_IMA_NAME) == 0)
 		is_ima_template = true;
 
@@ -171,7 +177,7 @@ int ima_measurements_show(struct seq_file *m, void *v)
 		ima_putc(m, &template_data_len, sizeof(e->template_data_len));
 	}
 
-	/* 6th:  template specific data */
+	/* 7th:  template specific data */
 	for (i = 0; i < e->template_desc->num_fields; i++) {
 		enum ima_show_type show = IMA_SHOW_BINARY;
 		const struct ima_template_field *field =
@@ -233,8 +239,9 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v)
 	/* 1st: PCR used (config option) */
 	seq_printf(m, "%2d ", e->pcr);
 
-	/* 2nd: SHA1 template hash */
-	ima_print_digest(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE);
+	/* 2nd: template hash (hash_algo_name:digest)*/
+	seq_printf(m, "%s:", hash_algo_name[ima_template_hash_algo]);
+	ima_print_digest(m, e->digests[ima_template_hash_algo_idx].digest, hash_digest_size[ima_template_hash_algo]);
 
 	/* 3th:  template name */
 	seq_printf(m, " %s", template_name);
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index cc1217ac2c6f..fa31ecb66606 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -36,7 +36,9 @@ int ima_appraise;
 #endif
 
 int __ro_after_init ima_hash_algo = HASH_ALGO_SHA1;
+int __ro_after_init ima_template_hash_algo = HASH_ALGO_SHA1;
 static int hash_setup_done;
+static int template_hash_setup_done;
 
 static struct notifier_block ima_lsm_policy_notifier = {
 	.notifier_call = ima_lsm_policy_change,
@@ -76,6 +78,26 @@ static int __init hash_setup(char *str)
 }
 __setup("ima_hash=", hash_setup);
 
+static int __init template_hash_setup(char *str)
+{
+	int i;
+
+	if (template_hash_setup_done)
+		return 1;
+
+	i = match_string(hash_algo_name, HASH_ALGO__LAST, str);
+	if (i < 0) {
+		pr_err("invalid template-hash algorithm \"%s\"", str);
+		return 1;
+	}
+
+	ima_template_hash_algo = i;
+
+	template_hash_setup_done = 1;
+	return 1;
+}
+__setup("ima_template_hash=", template_hash_setup);
+
 enum hash_algo ima_get_current_hash_algo(void)
 {
 	return ima_hash_algo;
@@ -1096,6 +1118,7 @@ static int __init init_ima(void)
 	ima_appraise_parse_cmdline();
 	ima_init_template_list();
 	hash_setup(CONFIG_IMA_DEFAULT_HASH);
+	template_hash_setup(CONFIG_IMA_DEFAULT_TEMPLATE_HASH);
 	error = ima_init();
 
 	if (error && strcmp(hash_algo_name[ima_hash_algo],
@@ -1107,6 +1130,15 @@ static int __init init_ima(void)
 		error = ima_init();
 	}
 
+	if (error && strcmp(hash_algo_name[ima_template_hash_algo],
+			    CONFIG_IMA_DEFAULT_TEMPLATE_HASH) != 0) {
+		pr_info("Allocating %s failed, going to use default template-hash algorithm %s\n",
+			hash_algo_name[ima_template_hash_algo], CONFIG_IMA_DEFAULT_TEMPLATE_HASH);
+		template_hash_setup_done = 0;
+		template_hash_setup(CONFIG_IMA_DEFAULT_TEMPLATE_HASH);
+		error = ima_init();
+	}
+
 	if (error)
 		return error;

base-commit: 88035e5694a86a7167d490bb95e9df97a9bb162b 
-- 
2.34.1


             reply	other threads:[~2023-12-14 14:54 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-14 14:51 Enrico Bravi [this message]
2023-12-19 20:54 ` [RFC][PATCH] ima: add crypto agility support for template-hash algorithm Mimi Zohar
2023-12-21 14:38   ` Enrico Bravi
2023-12-21 22:05     ` Mimi Zohar
2023-12-25 13:00       ` Guozihua (Scott)
2023-12-26 15:36         ` Ken Goldman
2023-12-27 14:03           ` Mimi Zohar
2024-01-09 17:05       ` Silvia Sisinni

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=20231214145152.36985-1-enrico.bravi@polito.it \
    --to=enrico.bravi@polito.it \
    --cc=linux-integrity@vger.kernel.org \
    --cc=roberto.sassu@huawei.com \
    --cc=silvia.sisinni@polito.it \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).