Skip to content

Commit 6f1a1d1

Browse files
robertosassumimizohar
authored andcommitted
ima: Switch to ima_hash_algo for boot aggregate
boot_aggregate is the first entry of IMA measurement list. Its purpose is to link pre-boot measurements to IMA measurements. As IMA was designed to work with a TPM 1.2, the SHA1 PCR bank was always selected even if a TPM 2.0 with support for stronger hash algorithms is available. This patch first tries to find a PCR bank with the IMA default hash algorithm. If it does not find it, it selects the SHA256 PCR bank for TPM 2.0 and SHA1 for TPM 1.2. Ultimately, it selects SHA1 also for TPM 2.0 if the SHA256 PCR bank is not found. If none of the PCR banks above can be found, boot_aggregate file digest is filled with zeros, as for TPM bypass, making it impossible to perform a remote attestation of the system. Cc: [email protected] # 5.1.x Fixes: 879b589 ("tpm: retrieve digest size of unknown algorithms with PCR read") Reported-by: Jerry Snitselaar <[email protected]> Suggested-by: James Bottomley <[email protected]> Signed-off-by: Roberto Sassu <[email protected]> Signed-off-by: Mimi Zohar <[email protected]>
1 parent ae83d0b commit 6f1a1d1

File tree

2 files changed

+58
-11
lines changed

2 files changed

+58
-11
lines changed

security/integrity/ima/ima_crypto.c

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -655,18 +655,29 @@ static void __init ima_pcrread(u32 idx, struct tpm_digest *d)
655655
}
656656

657657
/*
658-
* Calculate the boot aggregate hash
658+
* The boot_aggregate is a cumulative hash over TPM registers 0 - 7. With
659+
* TPM 1.2 the boot_aggregate was based on reading the SHA1 PCRs, but with
660+
* TPM 2.0 hash agility, TPM chips could support multiple TPM PCR banks,
661+
* allowing firmware to configure and enable different banks.
662+
*
663+
* Knowing which TPM bank is read to calculate the boot_aggregate digest
664+
* needs to be conveyed to a verifier. For this reason, use the same
665+
* hash algorithm for reading the TPM PCRs as for calculating the boot
666+
* aggregate digest as stored in the measurement list.
659667
*/
660-
static int __init ima_calc_boot_aggregate_tfm(char *digest,
668+
static int __init ima_calc_boot_aggregate_tfm(char *digest, u16 alg_id,
661669
struct crypto_shash *tfm)
662670
{
663-
struct tpm_digest d = { .alg_id = TPM_ALG_SHA1, .digest = {0} };
671+
struct tpm_digest d = { .alg_id = alg_id, .digest = {0} };
664672
int rc;
665673
u32 i;
666674
SHASH_DESC_ON_STACK(shash, tfm);
667675

668676
shash->tfm = tfm;
669677

678+
pr_devel("calculating the boot-aggregate based on TPM bank: %04x\n",
679+
d.alg_id);
680+
670681
rc = crypto_shash_init(shash);
671682
if (rc != 0)
672683
return rc;
@@ -675,7 +686,8 @@ static int __init ima_calc_boot_aggregate_tfm(char *digest,
675686
for (i = TPM_PCR0; i < TPM_PCR8; i++) {
676687
ima_pcrread(i, &d);
677688
/* now accumulate with current aggregate */
678-
rc = crypto_shash_update(shash, d.digest, TPM_DIGEST_SIZE);
689+
rc = crypto_shash_update(shash, d.digest,
690+
crypto_shash_digestsize(tfm));
679691
}
680692
if (!rc)
681693
crypto_shash_final(shash, digest);
@@ -685,14 +697,37 @@ static int __init ima_calc_boot_aggregate_tfm(char *digest,
685697
int __init ima_calc_boot_aggregate(struct ima_digest_data *hash)
686698
{
687699
struct crypto_shash *tfm;
688-
int rc;
700+
u16 crypto_id, alg_id;
701+
int rc, i, bank_idx = -1;
702+
703+
for (i = 0; i < ima_tpm_chip->nr_allocated_banks; i++) {
704+
crypto_id = ima_tpm_chip->allocated_banks[i].crypto_id;
705+
if (crypto_id == hash->algo) {
706+
bank_idx = i;
707+
break;
708+
}
709+
710+
if (crypto_id == HASH_ALGO_SHA256)
711+
bank_idx = i;
712+
713+
if (bank_idx == -1 && crypto_id == HASH_ALGO_SHA1)
714+
bank_idx = i;
715+
}
716+
717+
if (bank_idx == -1) {
718+
pr_err("No suitable TPM algorithm for boot aggregate\n");
719+
return 0;
720+
}
721+
722+
hash->algo = ima_tpm_chip->allocated_banks[bank_idx].crypto_id;
689723

690724
tfm = ima_alloc_tfm(hash->algo);
691725
if (IS_ERR(tfm))
692726
return PTR_ERR(tfm);
693727

694728
hash->length = crypto_shash_digestsize(tfm);
695-
rc = ima_calc_boot_aggregate_tfm(hash->digest, tfm);
729+
alg_id = ima_tpm_chip->allocated_banks[bank_idx].alg_id;
730+
rc = ima_calc_boot_aggregate_tfm(hash->digest, alg_id, tfm);
696731

697732
ima_free_tfm(tfm);
698733

security/integrity/ima/ima_init.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct tpm_chip *ima_tpm_chip;
2525
/* Add the boot aggregate to the IMA measurement list and extend
2626
* the PCR register.
2727
*
28-
* Calculate the boot aggregate, a SHA1 over tpm registers 0-7,
28+
* Calculate the boot aggregate, a hash over tpm registers 0-7,
2929
* assuming a TPM chip exists, and zeroes if the TPM chip does not
3030
* exist. Add the boot aggregate measurement to the measurement
3131
* list and extend the PCR register.
@@ -49,15 +49,27 @@ static int __init ima_add_boot_aggregate(void)
4949
int violation = 0;
5050
struct {
5151
struct ima_digest_data hdr;
52-
char digest[TPM_DIGEST_SIZE];
52+
char digest[TPM_MAX_DIGEST_SIZE];
5353
} hash;
5454

5555
memset(iint, 0, sizeof(*iint));
5656
memset(&hash, 0, sizeof(hash));
5757
iint->ima_hash = &hash.hdr;
58-
iint->ima_hash->algo = HASH_ALGO_SHA1;
59-
iint->ima_hash->length = SHA1_DIGEST_SIZE;
60-
58+
iint->ima_hash->algo = ima_hash_algo;
59+
iint->ima_hash->length = hash_digest_size[ima_hash_algo];
60+
61+
/*
62+
* With TPM 2.0 hash agility, TPM chips could support multiple TPM
63+
* PCR banks, allowing firmware to configure and enable different
64+
* banks. The SHA1 bank is not necessarily enabled.
65+
*
66+
* Use the same hash algorithm for reading the TPM PCRs as for
67+
* calculating the boot aggregate digest. Preference is given to
68+
* the configured IMA default hash algorithm. Otherwise, use the
69+
* TCG required banks - SHA256 for TPM 2.0, SHA1 for TPM 1.2.
70+
* Ultimately select SHA1 also for TPM 2.0 if the SHA256 PCR bank
71+
* is not found.
72+
*/
6173
if (ima_tpm_chip) {
6274
result = ima_calc_boot_aggregate(&hash.hdr);
6375
if (result < 0) {

0 commit comments

Comments
 (0)