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 <[email protected]>
Signed-off-by: Enrico Bravi <[email protected]>
---
 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 via email to