[PATCH 7/8] ima: use ima_hash_algo for collision detection in the measurement list

Roberto Sassu roberto.sassu at huawei.com
Mon Jan 27 17:04:42 UTC 2020


Before calculating a digest for each PCR bank, collisions were detected
with a SHA1 digest. This patch includes ima_hash_algo among the algorithms
used to calculate the template digest and checks collisions on that digest.

Signed-off-by: Roberto Sassu <roberto.sassu at huawei.com>
---
 security/integrity/ima/ima.h          |  1 +
 security/integrity/ima/ima_api.c      |  2 +-
 security/integrity/ima/ima_crypto.c   | 25 ++++++++++++++++++-------
 security/integrity/ima/ima_main.c     |  1 +
 security/integrity/ima/ima_queue.c    |  8 ++++----
 security/integrity/ima/ima_template.c |  2 +-
 6 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index d959dab5bcce..3e1afa5150bc 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -51,6 +51,7 @@ extern int ima_policy_flag;
 /* set during initialization */
 extern int ima_hash_algo;
 extern int ima_sha1_idx;
+extern int ima_hash_algo_idx;
 extern int ima_appraise;
 extern struct tpm_chip *ima_tpm_chip;
 
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index ebaf0056735c..a9bb45de6db9 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -51,7 +51,7 @@ int ima_alloc_init_template(struct ima_event_data *event_data,
 	if (!*entry)
 		return -ENOMEM;
 
-	(*entry)->digests = kcalloc(ima_tpm_chip->nr_allocated_banks + 1,
+	(*entry)->digests = kcalloc(ima_tpm_chip->nr_allocated_banks + 2,
 				    sizeof(*(*entry)->digests), GFP_NOFS);
 	if (!(*entry)->digests) {
 		result = -ENOMEM;
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 786340feebbb..f84dfd8fc5ca 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -93,7 +93,7 @@ static struct crypto_shash *ima_alloc_tfm(enum hash_algo algo)
 	if (algo == ima_hash_algo)
 		return tfm;
 
-	for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 1; i++)
+	for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 2; i++)
 		if (ima_algo_array[i].algo == algo && ima_algo_array[i].tfm)
 			return ima_algo_array[i].tfm;
 
@@ -116,19 +116,20 @@ int __init ima_init_crypto(void)
 	if (rc)
 		return rc;
 
-	ima_algo_array = kmalloc_array(ima_tpm_chip->nr_allocated_banks + 1,
+	ima_algo_array = kmalloc_array(ima_tpm_chip->nr_allocated_banks + 2,
 				       sizeof(*ima_algo_array), GFP_KERNEL);
 	if (!ima_algo_array) {
 		rc = -ENOMEM;
 		goto out;
 	}
 
-	for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 1; i++) {
+	for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 2; i++) {
 		ima_algo_array[i].tfm = NULL;
 		ima_algo_array[i].algo = HASH_ALGO__LAST;
 	}
 
 	ima_sha1_idx = -1;
+	ima_hash_algo_idx = -1;
 
 	for (i = 0; i < ima_tpm_chip->nr_allocated_banks; i++) {
 		algo = ima_tpm_chip->allocated_banks[i].crypto_id;
@@ -143,6 +144,7 @@ int __init ima_init_crypto(void)
 
 		if (algo == ima_hash_algo) {
 			ima_algo_array[i].tfm = ima_shash_tfm;
+			ima_hash_algo_idx = i;
 			continue;
 		}
 
@@ -166,12 +168,21 @@ int __init ima_init_crypto(void)
 		}
 
 		ima_sha1_idx = i;
-		ima_algo_array[i].algo = HASH_ALGO_SHA1;
+		if (ima_hash_algo == HASH_ALGO_SHA1)
+			ima_hash_algo_idx = i;
+
+		ima_algo_array[i++].algo = HASH_ALGO_SHA1;
+	}
+
+	if (ima_hash_algo_idx < 0) {
+		ima_algo_array[i].tfm = ima_shash_tfm;
+		ima_algo_array[i].algo = ima_hash_algo;
+		ima_hash_algo_idx = i;
 	}
 
 	return 0;
 out_array:
-	for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 1; i++) {
+	for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 2; i++) {
 		if (!ima_algo_array[i].tfm ||
 		    ima_algo_array[i].tfm == ima_shash_tfm)
 			continue;
@@ -190,7 +201,7 @@ static void ima_free_tfm(struct crypto_shash *tfm)
 	if (tfm == ima_shash_tfm)
 		return;
 
-	for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 1; i++)
+	for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 2; i++)
 		if (ima_algo_array[i].tfm == tfm)
 			return;
 
@@ -619,7 +630,7 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data,
 
 	entry->digests[ima_sha1_idx].alg_id = TPM_ALG_SHA1;
 
-	for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 1; i++) {
+	for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 2; i++) {
 		if (i == ima_sha1_idx)
 			continue;
 
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index c068067a0c47..6963d6c31bf1 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -31,6 +31,7 @@
 #include "ima.h"
 
 int ima_sha1_idx;
+int ima_hash_algo_idx;
 
 #ifdef CONFIG_IMA_APPRAISE
 int ima_appraise = IMA_APPRAISE_ENFORCE;
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index 7f7509774b85..58983d0f0214 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -57,8 +57,8 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
 	key = ima_hash_key(digest_value);
 	rcu_read_lock();
 	hlist_for_each_entry_rcu(qe, &ima_htable.queue[key], hnext) {
-		rc = memcmp(qe->entry->digests[ima_sha1_idx].digest,
-			    digest_value, TPM_DIGEST_SIZE);
+		rc = memcmp(qe->entry->digests[ima_hash_algo_idx].digest,
+			    digest_value, hash_digest_size[ima_hash_algo]);
 		if ((rc == 0) && (qe->entry->pcr == pcr)) {
 			ret = qe;
 			break;
@@ -110,7 +110,7 @@ static int ima_add_digest_entry(struct ima_template_entry *entry,
 
 	atomic_long_inc(&ima_htable.len);
 	if (update_htable) {
-		key = ima_hash_key(entry->digests[ima_sha1_idx].digest);
+		key = ima_hash_key(entry->digests[ima_hash_algo_idx].digest);
 		hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
 	}
 
@@ -162,7 +162,7 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
 			   const char *op, struct inode *inode,
 			   const unsigned char *filename)
 {
-	u8 *digest = entry->digests[ima_sha1_idx].digest;
+	u8 *digest = entry->digests[ima_hash_algo_idx].digest;
 	struct tpm_digest *digests_arg = entry->digests;
 	const char *audit_cause = "hash_added";
 	char tpm_audit_cause[AUDIT_CAUSE_LEN_MAX];
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
index a9e1390c8e12..f71b5ee44179 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -311,7 +311,7 @@ static int ima_restore_template_data(struct ima_template_desc *template_desc,
 	if (!*entry)
 		return -ENOMEM;
 
-	(*entry)->digests = kcalloc(ima_tpm_chip->nr_allocated_banks + 1,
+	(*entry)->digests = kcalloc(ima_tpm_chip->nr_allocated_banks + 2,
 				    sizeof(*(*entry)->digests), GFP_NOFS);
 	if (!(*entry)->digests) {
 		kfree(*entry);
-- 
2.17.1



More information about the Linux-security-module-archive mailing list