.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2005,2006,2007,2008 IBM Corporation |
---|
3 | 4 | * |
---|
.. | .. |
---|
5 | 6 | * Mimi Zohar <zohar@us.ibm.com> |
---|
6 | 7 | * Kylene Hall <kjhall@us.ibm.com> |
---|
7 | 8 | * |
---|
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 | | - * |
---|
12 | 9 | * File: ima_crypto.c |
---|
13 | 10 | * Calculates md5/sha1 file hash, template hash, boot-aggreate hash |
---|
14 | 11 | */ |
---|
15 | | - |
---|
16 | | -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
17 | 12 | |
---|
18 | 13 | #include <linux/kernel.h> |
---|
19 | 14 | #include <linux/moduleparam.h> |
---|
.. | .. |
---|
62 | 57 | static struct crypto_shash *ima_shash_tfm; |
---|
63 | 58 | static struct crypto_ahash *ima_ahash_tfm; |
---|
64 | 59 | |
---|
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) |
---|
66 | 76 | { |
---|
67 | 77 | long rc; |
---|
68 | 78 | |
---|
.. | .. |
---|
81 | 91 | static struct crypto_shash *ima_alloc_tfm(enum hash_algo algo) |
---|
82 | 92 | { |
---|
83 | 93 | struct crypto_shash *tfm = ima_shash_tfm; |
---|
84 | | - int rc; |
---|
| 94 | + int rc, i; |
---|
85 | 95 | |
---|
86 | 96 | if (algo < 0 || algo >= HASH_ALGO__LAST) |
---|
87 | 97 | algo = ima_hash_algo; |
---|
88 | 98 | |
---|
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); |
---|
96 | 111 | } |
---|
97 | 112 | return tfm; |
---|
98 | 113 | } |
---|
99 | 114 | |
---|
| 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 | + |
---|
100 | 214 | static void ima_free_tfm(struct crypto_shash *tfm) |
---|
101 | 215 | { |
---|
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); |
---|
104 | 226 | } |
---|
105 | 227 | |
---|
106 | 228 | /** |
---|
.. | .. |
---|
341 | 463 | SHASH_DESC_ON_STACK(shash, tfm); |
---|
342 | 464 | |
---|
343 | 465 | shash->tfm = tfm; |
---|
344 | | - shash->flags = 0; |
---|
345 | 466 | |
---|
346 | 467 | hash->length = crypto_shash_digestsize(tfm); |
---|
347 | 468 | |
---|
.. | .. |
---|
366 | 487 | rc = rbuf_len; |
---|
367 | 488 | break; |
---|
368 | 489 | } |
---|
369 | | - if (rbuf_len == 0) |
---|
| 490 | + if (rbuf_len == 0) { /* unexpected EOF */ |
---|
| 491 | + rc = -EINVAL; |
---|
370 | 492 | break; |
---|
| 493 | + } |
---|
371 | 494 | offset += rbuf_len; |
---|
372 | 495 | |
---|
373 | 496 | rc = crypto_shash_update(shash, rbuf, rbuf_len); |
---|
.. | .. |
---|
458 | 581 | * Calculate the hash of template data |
---|
459 | 582 | */ |
---|
460 | 583 | 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) |
---|
465 | 586 | { |
---|
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; |
---|
467 | 590 | int rc, i; |
---|
468 | 591 | |
---|
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; |
---|
473 | 593 | |
---|
474 | 594 | rc = crypto_shash_init(shash); |
---|
475 | 595 | if (rc != 0) |
---|
.. | .. |
---|
499 | 619 | } |
---|
500 | 620 | |
---|
501 | 621 | if (!rc) |
---|
502 | | - rc = crypto_shash_final(shash, hash->digest); |
---|
| 622 | + rc = crypto_shash_final(shash, entry->digests[tfm_idx].digest); |
---|
503 | 623 | |
---|
504 | 624 | return rc; |
---|
505 | 625 | } |
---|
506 | 626 | |
---|
507 | 627 | 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) |
---|
510 | 629 | { |
---|
511 | | - struct crypto_shash *tfm; |
---|
512 | | - int rc; |
---|
| 630 | + u16 alg_id; |
---|
| 631 | + int rc, i; |
---|
513 | 632 | |
---|
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; |
---|
517 | 636 | |
---|
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; |
---|
520 | 638 | |
---|
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; |
---|
522 | 642 | |
---|
| 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 | + } |
---|
523 | 660 | return rc; |
---|
524 | 661 | } |
---|
525 | 662 | |
---|
.. | .. |
---|
589 | 726 | int rc; |
---|
590 | 727 | |
---|
591 | 728 | shash->tfm = tfm; |
---|
592 | | - shash->flags = 0; |
---|
593 | 729 | |
---|
594 | 730 | hash->length = crypto_shash_digestsize(tfm); |
---|
595 | 731 | |
---|
.. | .. |
---|
641 | 777 | return calc_buffer_shash(buf, len, hash); |
---|
642 | 778 | } |
---|
643 | 779 | |
---|
644 | | -static void ima_pcrread(int idx, u8 *pcr) |
---|
| 780 | +static void ima_pcrread(u32 idx, struct tpm_digest *d) |
---|
645 | 781 | { |
---|
646 | 782 | if (!ima_tpm_chip) |
---|
647 | 783 | return; |
---|
648 | 784 | |
---|
649 | | - if (tpm_pcr_read(ima_tpm_chip, idx, pcr) != 0) |
---|
| 785 | + if (tpm_pcr_read(ima_tpm_chip, idx, d) != 0) |
---|
650 | 786 | pr_err("Error Communicating to TPM chip\n"); |
---|
651 | 787 | } |
---|
652 | 788 | |
---|
653 | 789 | /* |
---|
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. |
---|
655 | 799 | */ |
---|
656 | | -static int ima_calc_boot_aggregate_tfm(char *digest, |
---|
| 800 | +static int ima_calc_boot_aggregate_tfm(char *digest, u16 alg_id, |
---|
657 | 801 | struct crypto_shash *tfm) |
---|
658 | 802 | { |
---|
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; |
---|
661 | 806 | SHASH_DESC_ON_STACK(shash, tfm); |
---|
662 | 807 | |
---|
663 | 808 | 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); |
---|
665 | 812 | |
---|
666 | 813 | rc = crypto_shash_init(shash); |
---|
667 | 814 | if (rc != 0) |
---|
668 | 815 | return rc; |
---|
669 | 816 | |
---|
670 | | - /* cumulative sha1 over tpm registers 0-7 */ |
---|
| 817 | + /* cumulative digest over TPM registers 0-7 */ |
---|
671 | 818 | for (i = TPM_PCR0; i < TPM_PCR8; i++) { |
---|
672 | | - ima_pcrread(i, pcr_i); |
---|
| 819 | + ima_pcrread(i, &d); |
---|
673 | 820 | /* 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)); |
---|
675 | 823 | if (rc != 0) |
---|
676 | 824 | 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 | + } |
---|
677 | 838 | } |
---|
678 | 839 | if (!rc) |
---|
679 | 840 | crypto_shash_final(shash, digest); |
---|
.. | .. |
---|
683 | 844 | int ima_calc_boot_aggregate(struct ima_digest_data *hash) |
---|
684 | 845 | { |
---|
685 | 846 | 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; |
---|
687 | 870 | |
---|
688 | 871 | tfm = ima_alloc_tfm(hash->algo); |
---|
689 | 872 | if (IS_ERR(tfm)) |
---|
690 | 873 | return PTR_ERR(tfm); |
---|
691 | 874 | |
---|
692 | 875 | 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); |
---|
694 | 878 | |
---|
695 | 879 | ima_free_tfm(tfm); |
---|
696 | 880 | |
---|