forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
kernel/security/integrity/ima/ima_crypto.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,15 +6,9 @@
56 * Mimi Zohar <zohar@us.ibm.com>
67 * Kylene Hall <kjhall@us.ibm.com>
78 *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License as published by
10
- * the Free Software Foundation, version 2 of the License.
11
- *
129 * File: ima_crypto.c
1310 * Calculates md5/sha1 file hash, template hash, boot-aggreate hash
1411 */
15
-
16
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1712
1813 #include <linux/kernel.h>
1914 #include <linux/moduleparam.h>
....@@ -62,7 +57,22 @@
6257 static struct crypto_shash *ima_shash_tfm;
6358 static struct crypto_ahash *ima_ahash_tfm;
6459
65
-int __init ima_init_crypto(void)
60
+struct ima_algo_desc {
61
+ struct crypto_shash *tfm;
62
+ enum hash_algo algo;
63
+};
64
+
65
+int ima_sha1_idx __ro_after_init;
66
+int ima_hash_algo_idx __ro_after_init;
67
+/*
68
+ * Additional number of slots reserved, as needed, for SHA1
69
+ * and IMA default algo.
70
+ */
71
+int ima_extra_slots __ro_after_init;
72
+
73
+static struct ima_algo_desc *ima_algo_array;
74
+
75
+static int __init ima_init_ima_crypto(void)
6676 {
6777 long rc;
6878
....@@ -81,26 +91,138 @@
8191 static struct crypto_shash *ima_alloc_tfm(enum hash_algo algo)
8292 {
8393 struct crypto_shash *tfm = ima_shash_tfm;
84
- int rc;
94
+ int rc, i;
8595
8696 if (algo < 0 || algo >= HASH_ALGO__LAST)
8797 algo = ima_hash_algo;
8898
89
- if (algo != ima_hash_algo) {
90
- tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0);
91
- if (IS_ERR(tfm)) {
92
- rc = PTR_ERR(tfm);
93
- pr_err("Can not allocate %s (reason: %d)\n",
94
- hash_algo_name[algo], rc);
95
- }
99
+ if (algo == ima_hash_algo)
100
+ return tfm;
101
+
102
+ for (i = 0; i < NR_BANKS(ima_tpm_chip) + ima_extra_slots; i++)
103
+ if (ima_algo_array[i].tfm && ima_algo_array[i].algo == algo)
104
+ return ima_algo_array[i].tfm;
105
+
106
+ tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0);
107
+ if (IS_ERR(tfm)) {
108
+ rc = PTR_ERR(tfm);
109
+ pr_err("Can not allocate %s (reason: %d)\n",
110
+ hash_algo_name[algo], rc);
96111 }
97112 return tfm;
98113 }
99114
115
+int __init ima_init_crypto(void)
116
+{
117
+ enum hash_algo algo;
118
+ long rc;
119
+ int i;
120
+
121
+ rc = ima_init_ima_crypto();
122
+ if (rc)
123
+ return rc;
124
+
125
+ ima_sha1_idx = -1;
126
+ ima_hash_algo_idx = -1;
127
+
128
+ for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
129
+ algo = ima_tpm_chip->allocated_banks[i].crypto_id;
130
+ if (algo == HASH_ALGO_SHA1)
131
+ ima_sha1_idx = i;
132
+
133
+ if (algo == ima_hash_algo)
134
+ ima_hash_algo_idx = i;
135
+ }
136
+
137
+ if (ima_sha1_idx < 0) {
138
+ ima_sha1_idx = NR_BANKS(ima_tpm_chip) + ima_extra_slots++;
139
+ if (ima_hash_algo == HASH_ALGO_SHA1)
140
+ ima_hash_algo_idx = ima_sha1_idx;
141
+ }
142
+
143
+ if (ima_hash_algo_idx < 0)
144
+ ima_hash_algo_idx = NR_BANKS(ima_tpm_chip) + ima_extra_slots++;
145
+
146
+ ima_algo_array = kcalloc(NR_BANKS(ima_tpm_chip) + ima_extra_slots,
147
+ sizeof(*ima_algo_array), GFP_KERNEL);
148
+ if (!ima_algo_array) {
149
+ rc = -ENOMEM;
150
+ goto out;
151
+ }
152
+
153
+ for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
154
+ algo = ima_tpm_chip->allocated_banks[i].crypto_id;
155
+ ima_algo_array[i].algo = algo;
156
+
157
+ /* unknown TPM algorithm */
158
+ if (algo == HASH_ALGO__LAST)
159
+ continue;
160
+
161
+ if (algo == ima_hash_algo) {
162
+ ima_algo_array[i].tfm = ima_shash_tfm;
163
+ continue;
164
+ }
165
+
166
+ ima_algo_array[i].tfm = ima_alloc_tfm(algo);
167
+ if (IS_ERR(ima_algo_array[i].tfm)) {
168
+ if (algo == HASH_ALGO_SHA1) {
169
+ rc = PTR_ERR(ima_algo_array[i].tfm);
170
+ ima_algo_array[i].tfm = NULL;
171
+ goto out_array;
172
+ }
173
+
174
+ ima_algo_array[i].tfm = NULL;
175
+ }
176
+ }
177
+
178
+ if (ima_sha1_idx >= NR_BANKS(ima_tpm_chip)) {
179
+ if (ima_hash_algo == HASH_ALGO_SHA1) {
180
+ ima_algo_array[ima_sha1_idx].tfm = ima_shash_tfm;
181
+ } else {
182
+ ima_algo_array[ima_sha1_idx].tfm =
183
+ ima_alloc_tfm(HASH_ALGO_SHA1);
184
+ if (IS_ERR(ima_algo_array[ima_sha1_idx].tfm)) {
185
+ rc = PTR_ERR(ima_algo_array[ima_sha1_idx].tfm);
186
+ goto out_array;
187
+ }
188
+ }
189
+
190
+ ima_algo_array[ima_sha1_idx].algo = HASH_ALGO_SHA1;
191
+ }
192
+
193
+ if (ima_hash_algo_idx >= NR_BANKS(ima_tpm_chip) &&
194
+ ima_hash_algo_idx != ima_sha1_idx) {
195
+ ima_algo_array[ima_hash_algo_idx].tfm = ima_shash_tfm;
196
+ ima_algo_array[ima_hash_algo_idx].algo = ima_hash_algo;
197
+ }
198
+
199
+ return 0;
200
+out_array:
201
+ for (i = 0; i < NR_BANKS(ima_tpm_chip) + ima_extra_slots; i++) {
202
+ if (!ima_algo_array[i].tfm ||
203
+ ima_algo_array[i].tfm == ima_shash_tfm)
204
+ continue;
205
+
206
+ crypto_free_shash(ima_algo_array[i].tfm);
207
+ }
208
+ kfree(ima_algo_array);
209
+out:
210
+ crypto_free_shash(ima_shash_tfm);
211
+ return rc;
212
+}
213
+
100214 static void ima_free_tfm(struct crypto_shash *tfm)
101215 {
102
- if (tfm != ima_shash_tfm)
103
- crypto_free_shash(tfm);
216
+ int i;
217
+
218
+ if (tfm == ima_shash_tfm)
219
+ return;
220
+
221
+ for (i = 0; i < NR_BANKS(ima_tpm_chip) + ima_extra_slots; i++)
222
+ if (ima_algo_array[i].tfm == tfm)
223
+ return;
224
+
225
+ crypto_free_shash(tfm);
104226 }
105227
106228 /**
....@@ -341,7 +463,6 @@
341463 SHASH_DESC_ON_STACK(shash, tfm);
342464
343465 shash->tfm = tfm;
344
- shash->flags = 0;
345466
346467 hash->length = crypto_shash_digestsize(tfm);
347468
....@@ -366,8 +487,10 @@
366487 rc = rbuf_len;
367488 break;
368489 }
369
- if (rbuf_len == 0)
490
+ if (rbuf_len == 0) { /* unexpected EOF */
491
+ rc = -EINVAL;
370492 break;
493
+ }
371494 offset += rbuf_len;
372495
373496 rc = crypto_shash_update(shash, rbuf, rbuf_len);
....@@ -458,18 +581,15 @@
458581 * Calculate the hash of template data
459582 */
460583 static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
461
- struct ima_template_desc *td,
462
- int num_fields,
463
- struct ima_digest_data *hash,
464
- struct crypto_shash *tfm)
584
+ struct ima_template_entry *entry,
585
+ int tfm_idx)
465586 {
466
- SHASH_DESC_ON_STACK(shash, tfm);
587
+ SHASH_DESC_ON_STACK(shash, ima_algo_array[tfm_idx].tfm);
588
+ struct ima_template_desc *td = entry->template_desc;
589
+ int num_fields = entry->template_desc->num_fields;
467590 int rc, i;
468591
469
- shash->tfm = tfm;
470
- shash->flags = 0;
471
-
472
- hash->length = crypto_shash_digestsize(tfm);
592
+ shash->tfm = ima_algo_array[tfm_idx].tfm;
473593
474594 rc = crypto_shash_init(shash);
475595 if (rc != 0)
....@@ -499,27 +619,44 @@
499619 }
500620
501621 if (!rc)
502
- rc = crypto_shash_final(shash, hash->digest);
622
+ rc = crypto_shash_final(shash, entry->digests[tfm_idx].digest);
503623
504624 return rc;
505625 }
506626
507627 int ima_calc_field_array_hash(struct ima_field_data *field_data,
508
- struct ima_template_desc *desc, int num_fields,
509
- struct ima_digest_data *hash)
628
+ struct ima_template_entry *entry)
510629 {
511
- struct crypto_shash *tfm;
512
- int rc;
630
+ u16 alg_id;
631
+ int rc, i;
513632
514
- tfm = ima_alloc_tfm(hash->algo);
515
- if (IS_ERR(tfm))
516
- return PTR_ERR(tfm);
633
+ rc = ima_calc_field_array_hash_tfm(field_data, entry, ima_sha1_idx);
634
+ if (rc)
635
+ return rc;
517636
518
- rc = ima_calc_field_array_hash_tfm(field_data, desc, num_fields,
519
- hash, tfm);
637
+ entry->digests[ima_sha1_idx].alg_id = TPM_ALG_SHA1;
520638
521
- ima_free_tfm(tfm);
639
+ for (i = 0; i < NR_BANKS(ima_tpm_chip) + ima_extra_slots; i++) {
640
+ if (i == ima_sha1_idx)
641
+ continue;
522642
643
+ if (i < NR_BANKS(ima_tpm_chip)) {
644
+ alg_id = ima_tpm_chip->allocated_banks[i].alg_id;
645
+ entry->digests[i].alg_id = alg_id;
646
+ }
647
+
648
+ /* for unmapped TPM algorithms digest is still a padded SHA1 */
649
+ if (!ima_algo_array[i].tfm) {
650
+ memcpy(entry->digests[i].digest,
651
+ entry->digests[ima_sha1_idx].digest,
652
+ TPM_DIGEST_SIZE);
653
+ continue;
654
+ }
655
+
656
+ rc = ima_calc_field_array_hash_tfm(field_data, entry, i);
657
+ if (rc)
658
+ return rc;
659
+ }
523660 return rc;
524661 }
525662
....@@ -589,7 +726,6 @@
589726 int rc;
590727
591728 shash->tfm = tfm;
592
- shash->flags = 0;
593729
594730 hash->length = crypto_shash_digestsize(tfm);
595731
....@@ -641,39 +777,64 @@
641777 return calc_buffer_shash(buf, len, hash);
642778 }
643779
644
-static void ima_pcrread(int idx, u8 *pcr)
780
+static void ima_pcrread(u32 idx, struct tpm_digest *d)
645781 {
646782 if (!ima_tpm_chip)
647783 return;
648784
649
- if (tpm_pcr_read(ima_tpm_chip, idx, pcr) != 0)
785
+ if (tpm_pcr_read(ima_tpm_chip, idx, d) != 0)
650786 pr_err("Error Communicating to TPM chip\n");
651787 }
652788
653789 /*
654
- * Calculate the boot aggregate hash
790
+ * The boot_aggregate is a cumulative hash over TPM registers 0 - 7. With
791
+ * TPM 1.2 the boot_aggregate was based on reading the SHA1 PCRs, but with
792
+ * TPM 2.0 hash agility, TPM chips could support multiple TPM PCR banks,
793
+ * allowing firmware to configure and enable different banks.
794
+ *
795
+ * Knowing which TPM bank is read to calculate the boot_aggregate digest
796
+ * needs to be conveyed to a verifier. For this reason, use the same
797
+ * hash algorithm for reading the TPM PCRs as for calculating the boot
798
+ * aggregate digest as stored in the measurement list.
655799 */
656
-static int ima_calc_boot_aggregate_tfm(char *digest,
800
+static int ima_calc_boot_aggregate_tfm(char *digest, u16 alg_id,
657801 struct crypto_shash *tfm)
658802 {
659
- u8 pcr_i[TPM_DIGEST_SIZE];
660
- int rc, i;
803
+ struct tpm_digest d = { .alg_id = alg_id, .digest = {0} };
804
+ int rc;
805
+ u32 i;
661806 SHASH_DESC_ON_STACK(shash, tfm);
662807
663808 shash->tfm = tfm;
664
- shash->flags = 0;
809
+
810
+ pr_devel("calculating the boot-aggregate based on TPM bank: %04x\n",
811
+ d.alg_id);
665812
666813 rc = crypto_shash_init(shash);
667814 if (rc != 0)
668815 return rc;
669816
670
- /* cumulative sha1 over tpm registers 0-7 */
817
+ /* cumulative digest over TPM registers 0-7 */
671818 for (i = TPM_PCR0; i < TPM_PCR8; i++) {
672
- ima_pcrread(i, pcr_i);
819
+ ima_pcrread(i, &d);
673820 /* now accumulate with current aggregate */
674
- rc = crypto_shash_update(shash, pcr_i, TPM_DIGEST_SIZE);
821
+ rc = crypto_shash_update(shash, d.digest,
822
+ crypto_shash_digestsize(tfm));
675823 if (rc != 0)
676824 return rc;
825
+ }
826
+ /*
827
+ * Extend cumulative digest over TPM registers 8-9, which contain
828
+ * measurement for the kernel command line (reg. 8) and image (reg. 9)
829
+ * in a typical PCR allocation. Registers 8-9 are only included in
830
+ * non-SHA1 boot_aggregate digests to avoid ambiguity.
831
+ */
832
+ if (alg_id != TPM_ALG_SHA1) {
833
+ for (i = TPM_PCR8; i < TPM_PCR10; i++) {
834
+ ima_pcrread(i, &d);
835
+ rc = crypto_shash_update(shash, d.digest,
836
+ crypto_shash_digestsize(tfm));
837
+ }
677838 }
678839 if (!rc)
679840 crypto_shash_final(shash, digest);
....@@ -683,14 +844,37 @@
683844 int ima_calc_boot_aggregate(struct ima_digest_data *hash)
684845 {
685846 struct crypto_shash *tfm;
686
- int rc;
847
+ u16 crypto_id, alg_id;
848
+ int rc, i, bank_idx = -1;
849
+
850
+ for (i = 0; i < ima_tpm_chip->nr_allocated_banks; i++) {
851
+ crypto_id = ima_tpm_chip->allocated_banks[i].crypto_id;
852
+ if (crypto_id == hash->algo) {
853
+ bank_idx = i;
854
+ break;
855
+ }
856
+
857
+ if (crypto_id == HASH_ALGO_SHA256)
858
+ bank_idx = i;
859
+
860
+ if (bank_idx == -1 && crypto_id == HASH_ALGO_SHA1)
861
+ bank_idx = i;
862
+ }
863
+
864
+ if (bank_idx == -1) {
865
+ pr_err("No suitable TPM algorithm for boot aggregate\n");
866
+ return 0;
867
+ }
868
+
869
+ hash->algo = ima_tpm_chip->allocated_banks[bank_idx].crypto_id;
687870
688871 tfm = ima_alloc_tfm(hash->algo);
689872 if (IS_ERR(tfm))
690873 return PTR_ERR(tfm);
691874
692875 hash->length = crypto_shash_digestsize(tfm);
693
- rc = ima_calc_boot_aggregate_tfm(hash->digest, tfm);
876
+ alg_id = ima_tpm_chip->allocated_banks[bank_idx].alg_id;
877
+ rc = ima_calc_boot_aggregate_tfm(hash->digest, alg_id, tfm);
694878
695879 ima_free_tfm(tfm);
696880