From bf85ff7d7a5b13ff95162545a0eb48871612f9ff Mon Sep 17 00:00:00 2001 From: Davide Cavalca Date: Thu, 13 Mar 2025 10:17:18 -0700 Subject: [PATCH] Backport upstream bugfix for tpm2_eventlog tpm2_eventlog reads the UEFI TPM eventlog, and uses it to calculate the PCR values we expect the TPM to contain. If they match then we know we can use the information in the eventlog to validate we see the expected events. This commit fixes an error where the PCR calculation fails to take into account the startup details of the TPM, resulting in incorrectly calculating the expected value for PCR0. Resolves: RHEL-83453 Signed-off-by: Davide Cavalca --- ...31bcc910da517067b29667f45fbe78e812e0.patch | 194 ++++++++++++++++++ tpm2-tools.spec | 8 +- 2 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 576a31bcc910da517067b29667f45fbe78e812e0.patch diff --git a/576a31bcc910da517067b29667f45fbe78e812e0.patch b/576a31bcc910da517067b29667f45fbe78e812e0.patch new file mode 100644 index 0000000..0ba4e6a --- /dev/null +++ b/576a31bcc910da517067b29667f45fbe78e812e0.patch @@ -0,0 +1,194 @@ +From 576a31bcc910da517067b29667f45fbe78e812e0 Mon Sep 17 00:00:00 2001 +From: Thore Sommer +Date: Tue, 25 Apr 2023 17:24:55 +0300 +Subject: [PATCH] tpm2_eventlog: add support for replay with different + StartupLocality + +According to the "TCG PC Client Platform Firmware Profile Specification +Level 00 Version 1.05 Revision 23" section 10.4.5.3 the startup locality +is the starting value of PCR0. This can be currently either 0 or 3. + +Signed-off-by: Thore Sommer +--- + lib/efi_event.h | 1 + + lib/tpm2_eventlog.c | 31 ++++++++++++++++++++++++++++--- + lib/tpm2_eventlog.h | 2 +- + test/unit/test_tpm2_eventlog.c | 14 +++++++------- + 4 files changed, 37 insertions(+), 11 deletions(-) + +diff --git a/lib/efi_event.h b/lib/efi_event.h +index cc2ffc983..e1b295501 100644 +--- a/lib/efi_event.h ++++ b/lib/efi_event.h +@@ -45,6 +45,7 @@ + #define EV_EFI_HANDOFF_TABLES2 EV_EFI_EVENT_BASE + 0xb + #define EV_EFI_VARIABLE_BOOT2 EV_EFI_EVENT_BASE + 0xc + ++#define EV_EFI_HCRTM_EVENT EV_EFI_EVENT_BASE + 0x10 + #define EV_EFI_VARIABLE_AUTHORITY EV_EFI_EVENT_BASE + 0xe0 + + #ifndef PACKED +diff --git a/lib/tpm2_eventlog.c b/lib/tpm2_eventlog.c +index e2e27f02b..2514b524e 100644 +--- a/lib/tpm2_eventlog.c ++++ b/lib/tpm2_eventlog.c +@@ -31,7 +31,7 @@ bool digest2_accumulator_callback(TCG_DIGEST2 const *digest, size_t size, + * 'size' parameter. + */ + bool foreach_digest2(tpm2_eventlog_context *ctx, UINT32 eventType, unsigned pcr_index, +- TCG_DIGEST2 const *digest, size_t count, size_t size) { ++ TCG_DIGEST2 const *digest, size_t count, size_t size, uint8_t locality) { + + if (digest == NULL) { + LOG_ERR("digest cannot be NULL"); +@@ -81,6 +81,10 @@ bool foreach_digest2(tpm2_eventlog_context *ctx, UINT32 eventType, unsigned pcr_ + LOG_WARN("PCR%d algorithm %d unsupported", pcr_index, alg); + } + ++ if (eventType == EV_NO_ACTION && pcr && pcr_index == 0 && locality > 0 ){ ++ pcr[alg_size -1] = locality; ++ } ++ + if (eventType != EV_NO_ACTION && pcr && + !tpm2_openssl_pcr_extend(alg, pcr, digest->Digest, alg_size)) { + LOG_ERR("PCR%d extend failed", pcr_index); +@@ -184,7 +188,7 @@ bool parse_event2(TCG_EVENT_HEADER2 const *eventhdr, size_t buf_size, + ret = foreach_digest2(&ctx, eventhdr->EventType, + eventhdr->PCRIndex, + eventhdr->Digests, eventhdr->DigestCount, +- buf_size - sizeof(*eventhdr)); ++ buf_size - sizeof(*eventhdr), 0); + if (ret != true) { + return false; + } +@@ -430,6 +434,7 @@ bool foreach_event2(tpm2_eventlog_context *ctx, TCG_EVENT_HEADER2 const *eventhd + TCG_EVENT_HEADER2 const *eventhdr; + size_t event_size; + bool ret; ++ bool found_hcrtm = false; + + for (eventhdr = eventhdr_start, event_size = 0; + size > 0; +@@ -437,6 +442,7 @@ bool foreach_event2(tpm2_eventlog_context *ctx, TCG_EVENT_HEADER2 const *eventhd + size -= event_size) { + + size_t digests_size = 0; ++ uint8_t locality = 0; + + ret = parse_event2(eventhdr, size, &event_size, &digests_size); + if (!ret) { +@@ -445,6 +451,25 @@ bool foreach_event2(tpm2_eventlog_context *ctx, TCG_EVENT_HEADER2 const *eventhd + + TCG_EVENT2 *event = (TCG_EVENT2*)((uintptr_t)eventhdr->Digests + digests_size); + ++ if (eventhdr->EventType == EV_EFI_HCRTM_EVENT && eventhdr->PCRIndex == 0) { ++ found_hcrtm = true; ++ } ++ ++ /* Handle StartupLocality in replay for PCR0 */ ++ if (!found_hcrtm && eventhdr->EventType == EV_NO_ACTION && eventhdr->PCRIndex == 0) { ++ if (event_size < sizeof(EV_NO_ACTION_STRUCT)){ ++ LOG_ERR("EventSize is too small\n"); ++ return false; ++ } ++ ++ EV_NO_ACTION_STRUCT *locality_event = (EV_NO_ACTION_STRUCT*)event->Event; ++ ++ if (memcmp(locality_event->Signature, STARTUP_LOCALITY_SIGNATURE, sizeof(STARTUP_LOCALITY_SIGNATURE)) == 0){ ++ locality = locality_event->Cases.StartupLocality; ++ } ++ } ++ ++ + /* event header callback */ + if (ctx->event2hdr_cb != NULL) { + ret = ctx->event2hdr_cb(eventhdr, event_size, ctx->data); +@@ -455,7 +480,7 @@ bool foreach_event2(tpm2_eventlog_context *ctx, TCG_EVENT_HEADER2 const *eventhd + + /* digest callback foreach digest */ + ret = foreach_digest2(ctx, eventhdr->EventType, eventhdr->PCRIndex, +- eventhdr->Digests, eventhdr->DigestCount, digests_size); ++ eventhdr->Digests, eventhdr->DigestCount, digests_size, locality); + if (ret != true) { + return false; + } +diff --git a/lib/tpm2_eventlog.h b/lib/tpm2_eventlog.h +index f141e8068..0af897070 100644 +--- a/lib/tpm2_eventlog.h ++++ b/lib/tpm2_eventlog.h +@@ -45,7 +45,7 @@ bool digest2_accumulator_callback(TCG_DIGEST2 const *digest, size_t size, + + bool parse_event2body(TCG_EVENT2 const *event, UINT32 type); + bool foreach_digest2(tpm2_eventlog_context *ctx, UINT32 eventType, unsigned pcr_index, +- TCG_DIGEST2 const *event_hdr, size_t count, size_t size); ++ TCG_DIGEST2 const *event_hdr, size_t count, size_t size, uint8_t locality); + bool parse_event2(TCG_EVENT_HEADER2 const *eventhdr, size_t buf_size, + size_t *event_size, size_t *digests_size); + bool foreach_event2(tpm2_eventlog_context *ctx, TCG_EVENT_HEADER2 const *eventhdr_start, size_t size); +diff --git a/test/unit/test_tpm2_eventlog.c b/test/unit/test_tpm2_eventlog.c +index e48404d8d..1c36f907e 100644 +--- a/test/unit/test_tpm2_eventlog.c ++++ b/test/unit/test_tpm2_eventlog.c +@@ -27,7 +27,7 @@ static void test_foreach_digest2_null(void **state){ + (void)state; + tpm2_eventlog_context ctx = {0}; + +- assert_false(foreach_digest2(&ctx, 0, 0, NULL, 0, sizeof(TCG_DIGEST2))); ++ assert_false(foreach_digest2(&ctx, 0, 0, NULL, 0, sizeof(TCG_DIGEST2), 0)); + } + static void test_foreach_digest2_size(void **state) { + +@@ -36,7 +36,7 @@ static void test_foreach_digest2_size(void **state) { + TCG_DIGEST2 *digest = (TCG_DIGEST2*)buf; + tpm2_eventlog_context ctx = { .digest2_cb = foreach_digest2_test_callback }; + +- assert_false(foreach_digest2(&ctx, 0, 0, digest, 1, sizeof(TCG_DIGEST2) - 1)); ++ assert_false(foreach_digest2(&ctx, 0, 0, digest, 1, sizeof(TCG_DIGEST2) - 1, 0)); + } + static void test_foreach_digest2(void **state) { + +@@ -47,7 +47,7 @@ static void test_foreach_digest2(void **state) { + will_return(foreach_digest2_test_callback, true); + + tpm2_eventlog_context ctx = { .digest2_cb = foreach_digest2_test_callback }; +- assert_true(foreach_digest2(&ctx, 0, 0, digest, 1, TCG_DIGEST2_SHA1_SIZE)); ++ assert_true(foreach_digest2(&ctx, 0, 0, digest, 1, TCG_DIGEST2_SHA1_SIZE, 0)); + } + static void test_foreach_digest2_cbnull(void **state){ + +@@ -56,7 +56,7 @@ static void test_foreach_digest2_cbnull(void **state){ + TCG_DIGEST2* digest = (TCG_DIGEST2*)buf; + + tpm2_eventlog_context ctx = {0}; +- assert_true(foreach_digest2(&ctx, 0, 0, digest, 1, TCG_DIGEST2_SHA1_SIZE)); ++ assert_true(foreach_digest2(&ctx, 0, 0, digest, 1, TCG_DIGEST2_SHA1_SIZE, 0)); + } + static void test_sha1(void **state){ + +@@ -73,7 +73,7 @@ static void test_sha1(void **state){ + memcpy(digest->Digest, "the magic words are:", TPM2_SHA1_DIGEST_SIZE); + + tpm2_eventlog_context ctx = {0}; +- assert_true(foreach_digest2(&ctx, 0, pcr_index, digest, 1, TCG_DIGEST2_SHA1_SIZE)); ++ assert_true(foreach_digest2(&ctx, 0, pcr_index, digest, 1, TCG_DIGEST2_SHA1_SIZE, 0)); + assert_memory_equal(ctx.sha1_pcrs[pcr_index], sha1sum, sizeof(sha1sum)); + } + static void test_sha256(void **state){ +@@ -93,7 +93,7 @@ static void test_sha256(void **state){ + memcpy(digest->Digest, "The Magic Words are Squeamish Ossifrage, for RSA-129 (from 1977)", TPM2_SHA256_DIGEST_SIZE); + + tpm2_eventlog_context ctx = {0}; +- assert_true(foreach_digest2(&ctx, 0, pcr_index, digest, 1, TCG_DIGEST2_SHA256_SIZE)); ++ assert_true(foreach_digest2(&ctx, 0, pcr_index, digest, 1, TCG_DIGEST2_SHA256_SIZE, 0)); + assert_memory_equal(ctx.sha256_pcrs[pcr_index], sha256sum, sizeof(sha256sum)); + } + static void test_foreach_digest2_cbfail(void **state){ +@@ -105,7 +105,7 @@ static void test_foreach_digest2_cbfail(void **state){ + will_return(foreach_digest2_test_callback, false); + + tpm2_eventlog_context ctx = { .digest2_cb = foreach_digest2_test_callback }; +- assert_false(foreach_digest2(&ctx, 0, 0, digest, 1, TCG_DIGEST2_SHA1_SIZE)); ++ assert_false(foreach_digest2(&ctx, 0, 0, digest, 1, TCG_DIGEST2_SHA1_SIZE, 0)); + } + static void test_digest2_accumulator_callback(void **state) { + diff --git a/tpm2-tools.spec b/tpm2-tools.spec index 70c694f..414add3 100644 --- a/tpm2-tools.spec +++ b/tpm2-tools.spec @@ -2,7 +2,7 @@ Name: tpm2-tools Version: 5.2 -Release: 4%{?candidate:.%{candidate}}%{?dist} +Release: 5%{?candidate:.%{candidate}}%{?dist} Summary: A bunch of TPM testing toolS build upon tpm2-tss License: BSD @@ -44,6 +44,8 @@ Patch203: 0003-tpm2_nvread-fix-input-handling-no-nv-index.patch Patch204: 0004-tpm2_checkquote-Add-comparison-of-pcr-selection.patch Patch205: 0005-tpm2_checkquote-Fix-check-of-magic-number.patch Patch206: 0006-tpm2_setprimarypolicy-Fix-resource-leak.patch +# tpm2_eventlog: add support for replay with different StartupLocality +Patch207: %{url}/commit/576a31bcc910da517067b29667f45fbe78e812e0.patch BuildRequires: git BuildRequires: make @@ -95,6 +97,10 @@ autoreconf -i %{_mandir}/man1/tss2_*.1.gz %changelog +* Fri Mar 21 2025 Davide Cavalca - 5.2-5 +- Backport upstream bugfix for tpm2_eventlog + Resolves: RHEL-83453 + * Wed Jun 19 2024 Štěpán Horáček - 5.2-4 - Backport upstream fixes. - tpm2_checkquote: Fix check of magic number. (CVE-2024-29038)