hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/security/integrity/ima/ima_queue.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2005,2006,2007,2008 IBM Corporation
34 *
....@@ -5,11 +6,6 @@
56 * Serge Hallyn <serue@us.ibm.com>
67 * Reiner Sailer <sailer@watson.ibm.com>
78 * Mimi Zohar <zohar@us.ibm.com>
8
- *
9
- * This program is free software; you can redistribute it and/or
10
- * modify it under the terms of the GNU General Public License as
11
- * published by the Free Software Foundation, version 2 of the
12
- * License.
139 *
1410 * File: ima_queue.c
1511 * Implements queues that store template measurements and
....@@ -19,14 +15,14 @@
1915 * ever removed or changed during the boot-cycle.
2016 */
2117
22
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
-
24
-#include <linux/module.h>
2518 #include <linux/rculist.h>
2619 #include <linux/slab.h>
2720 #include "ima.h"
2821
2922 #define AUDIT_CAUSE_LEN_MAX 32
23
+
24
+/* pre-allocated array of tpm_digest structures to extend a PCR */
25
+static struct tpm_digest *digests;
3026
3127 LIST_HEAD(ima_measurements); /* list of all measurements */
3228 #ifdef CONFIG_IMA_KEXEC
....@@ -59,7 +55,8 @@
5955 key = ima_hash_key(digest_value);
6056 rcu_read_lock();
6157 hlist_for_each_entry_rcu(qe, &ima_htable.queue[key], hnext) {
62
- rc = memcmp(qe->entry->digest, digest_value, TPM_DIGEST_SIZE);
58
+ rc = memcmp(qe->entry->digests[ima_hash_algo_idx].digest,
59
+ digest_value, hash_digest_size[ima_hash_algo]);
6360 if ((rc == 0) && (qe->entry->pcr == pcr)) {
6461 ret = qe;
6562 break;
....@@ -79,7 +76,7 @@
7976 int size = 0;
8077
8178 size += sizeof(u32); /* pcr */
82
- size += sizeof(entry->digest);
79
+ size += TPM_DIGEST_SIZE;
8380 size += sizeof(int); /* template name size field */
8481 size += strlen(entry->template_desc->name);
8582 size += sizeof(entry->template_data_len);
....@@ -111,7 +108,7 @@
111108
112109 atomic_long_inc(&ima_htable.len);
113110 if (update_htable) {
114
- key = ima_hash_key(entry->digest);
111
+ key = ima_hash_key(entry->digests[ima_hash_algo_idx].digest);
115112 hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
116113 }
117114
....@@ -136,16 +133,16 @@
136133 return ULONG_MAX;
137134 else
138135 return binary_runtime_size + sizeof(struct ima_kexec_hdr);
139
-};
136
+}
140137
141
-static int ima_pcr_extend(const u8 *hash, int pcr)
138
+static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr)
142139 {
143140 int result = 0;
144141
145142 if (!ima_tpm_chip)
146143 return result;
147144
148
- result = tpm_pcr_extend(ima_tpm_chip, pcr, hash);
145
+ result = tpm_pcr_extend(ima_tpm_chip, pcr, digests_arg);
149146 if (result != 0)
150147 pr_err("Error Communicating to TPM chip, result: %d\n", result);
151148 return result;
....@@ -163,7 +160,8 @@
163160 const char *op, struct inode *inode,
164161 const unsigned char *filename)
165162 {
166
- u8 digest[TPM_DIGEST_SIZE];
163
+ u8 *digest = entry->digests[ima_hash_algo_idx].digest;
164
+ struct tpm_digest *digests_arg = entry->digests;
167165 const char *audit_cause = "hash_added";
168166 char tpm_audit_cause[AUDIT_CAUSE_LEN_MAX];
169167 int audit_info = 1;
....@@ -171,7 +169,6 @@
171169
172170 mutex_lock(&ima_extend_list_mutex);
173171 if (!violation) {
174
- memcpy(digest, entry->digest, sizeof(digest));
175172 if (ima_lookup_digest_entry(digest, entry->pcr)) {
176173 audit_cause = "hash_exists";
177174 result = -EEXIST;
....@@ -187,9 +184,9 @@
187184 }
188185
189186 if (violation) /* invalidate pcr */
190
- memset(digest, 0xff, sizeof(digest));
187
+ digests_arg = digests;
191188
192
- tpmresult = ima_pcr_extend(digest, entry->pcr);
189
+ tpmresult = ima_pcr_extend(digests_arg, entry->pcr);
193190 if (tpmresult != 0) {
194191 snprintf(tpm_audit_cause, AUDIT_CAUSE_LEN_MAX, "TPM_error(%d)",
195192 tpmresult);
....@@ -212,3 +209,32 @@
212209 mutex_unlock(&ima_extend_list_mutex);
213210 return result;
214211 }
212
+
213
+int __init ima_init_digests(void)
214
+{
215
+ u16 digest_size;
216
+ u16 crypto_id;
217
+ int i;
218
+
219
+ if (!ima_tpm_chip)
220
+ return 0;
221
+
222
+ digests = kcalloc(ima_tpm_chip->nr_allocated_banks, sizeof(*digests),
223
+ GFP_NOFS);
224
+ if (!digests)
225
+ return -ENOMEM;
226
+
227
+ for (i = 0; i < ima_tpm_chip->nr_allocated_banks; i++) {
228
+ digests[i].alg_id = ima_tpm_chip->allocated_banks[i].alg_id;
229
+ digest_size = ima_tpm_chip->allocated_banks[i].digest_size;
230
+ crypto_id = ima_tpm_chip->allocated_banks[i].crypto_id;
231
+
232
+ /* for unmapped TPM algorithms digest is still a padded SHA1 */
233
+ if (crypto_id == HASH_ALGO__LAST)
234
+ digest_size = SHA1_DIGEST_SIZE;
235
+
236
+ memset(digests[i].digest, 0xff, digest_size);
237
+ }
238
+
239
+ return 0;
240
+}