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@xxxxxxxxx> Signed-off-by: Enrico Bravi <enrico.bravi@xxxxxxxxx> --- 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