tpm: Don't replay an EventLog if tcg2_log_parse() fails

We used to stop replaying an EventLog if parsing failed, but that got
lost in commit 97707f12fd ("tpm: Support boot measurements").

When an EventLog is passed yo us from a previous bootloader, we want to
validate it as much as we can and make sure the defined PCR banks of
the log exist in our TPM and firmware so we can replay it if needed or
use it as-in, in case the PCRs are already extended.

So let's add the checks back and while at it simplify the logic of
rejecting an EventLog.

Signed-off-by: Raymond Mao <raymond.mao@linaro.org>
Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
This commit is contained in:
Ilias Apalodimas
2024-12-24 08:01:12 -08:00
parent 05834d4b83
commit 3dbd84cb10

View File

@@ -359,7 +359,6 @@ static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
u16 len; u16 len;
int rc; int rc;
u32 i; u32 i;
u16 j;
if (elog->log_size <= offsetof(struct tcg_pcr_event, event)) if (elog->log_size <= offsetof(struct tcg_pcr_event, event))
return 0; return 0;
@@ -398,40 +397,51 @@ static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
if (evsz != calc_size) if (evsz != calc_size)
return 0; return 0;
rc = tcg2_get_active_pcr_banks(dev, &active); /*
if (rc) * Go through the algorithms the EventLog contains. If the EventLog
return rc; * algorithms don't match the active TPM ones exit and report the
* erroneous banks.
* We've already checked that U-Boot supports all the enabled TPM
* algorithms, so just check the EvenLog against the TPM active ones.
*/
digest_list.count = 0; digest_list.count = 0;
log_active = 0; log_active = 0;
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
algo = get_unaligned_le16(&event->digest_sizes[i].algorithm_id); algo = get_unaligned_le16(&event->digest_sizes[i].algorithm_id);
mask = tcg2_algorithm_to_mask(algo); mask = tcg2_algorithm_to_mask(algo);
if (!(active & mask))
return 0;
switch (algo) { switch (algo) {
case TPM2_ALG_SHA1: case TPM2_ALG_SHA1:
case TPM2_ALG_SHA256: case TPM2_ALG_SHA256:
case TPM2_ALG_SHA384: case TPM2_ALG_SHA384:
case TPM2_ALG_SHA512: case TPM2_ALG_SHA512:
len = get_unaligned_le16(&event->digest_sizes[i].digest_size); len = get_unaligned_le16(&event->digest_sizes[i].digest_size);
if (tpm2_algorithm_to_len(algo) != len) if (tpm2_algorithm_to_len(algo) != len) {
return 0; log_err("EventLog invalid algorithm length\n");
return -1;
}
digest_list.digests[digest_list.count++].hash_alg = algo; digest_list.digests[digest_list.count++].hash_alg = algo;
break; break;
default: default:
return 0; /*
* We can ignore this if the TPM PCRs is not extended
* by the previous bootloader. But for now just exit
*/
log_err("EventLog has unsupported algorithm 0x%x\n",
algo);
return -1;
} }
log_active |= mask; log_active |= mask;
} }
/* Ensure the previous firmware extended all the PCRs. */ rc = tcg2_get_active_pcr_banks(dev, &active);
if (log_active != active) if (rc)
return 0; return rc;
/* If the EventLog and active algorithms don't match exit */
if (log_active != active) {
log_err("EventLog doesn't contain all active PCR banks\n");
return -1;
}
/* Read PCR0 to check if previous firmware extended the PCRs or not. */ /* Read PCR0 to check if previous firmware extended the PCRs or not. */
rc = tcg2_pcr_read(dev, 0, &digest_list); rc = tcg2_pcr_read(dev, 0, &digest_list);
@@ -439,17 +449,13 @@ static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
return rc; return rc;
for (i = 0; i < digest_list.count; ++i) { for (i = 0; i < digest_list.count; ++i) {
len = tpm2_algorithm_to_len(digest_list.digests[i].hash_alg); u8 hash_buf[TPM2_SHA512_DIGEST_SIZE] = { 0 };
for (j = 0; j < len; ++j) { u16 hash_alg = digest_list.digests[i].hash_alg;
if (digest_list.digests[i].digest.sha512[j])
break;
}
/* PCR is non-zero; it has been extended, so skip extending. */ if (memcmp((u8 *)&digest_list.digests[i].digest, hash_buf,
if (j != len) { tpm2_algorithm_to_len(hash_alg)))
digest_list.count = 0; digest_list.count = 0;
break;
}
} }
return tcg2_replay_eventlog(elog, dev, &digest_list, return tcg2_replay_eventlog(elog, dev, &digest_list,