From fab956c77521a355185d12d97e3db4966fd61d76 Mon Sep 17 00:00:00 2001 From: AlmaLinux RelEng Bot Date: Mon, 30 Mar 2026 11:09:41 -0400 Subject: [PATCH] import CS tpm2-tools-5.2-7.el9 --- ...01-Fix-issue-with-reading-NV-indexes.patch | 64 ++ ...og-Fix-parsing-on-big-endian-systems.patch | 804 ++++++++++++++++++ ...quote-Fix-usage-of-little-endian-ser.patch | 519 +++++++++++ SOURCES/add_pregenerated_doc_2.patch | 96 +++ SPECS/tpm2-tools.spec | 13 +- 5 files changed, 1495 insertions(+), 1 deletion(-) create mode 100644 SOURCES/0001-Fix-issue-with-reading-NV-indexes.patch create mode 100644 SOURCES/0001-tpm2_eventlog-Fix-parsing-on-big-endian-systems.patch create mode 100644 SOURCES/0001-tpm2_quote-checkquote-Fix-usage-of-little-endian-ser.patch create mode 100644 SOURCES/add_pregenerated_doc_2.patch diff --git a/SOURCES/0001-Fix-issue-with-reading-NV-indexes.patch b/SOURCES/0001-Fix-issue-with-reading-NV-indexes.patch new file mode 100644 index 0000000..c924365 --- /dev/null +++ b/SOURCES/0001-Fix-issue-with-reading-NV-indexes.patch @@ -0,0 +1,64 @@ +From 8aed90958bb4d0d8d84a5334cce08a38314bffca Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20Hor=C3=A1=C4=8Dek?= + +Date: Tue, 26 Mar 2024 13:37:11 +0100 +Subject: [PATCH] Fix issue with reading NV indexes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Wrong arguments are used in tpm2_getekcertificate and tpm2_nvdefine when +accessing the list of NV indexes in use. This works fine on +little-endian systems, but on big-endian systems this will not find any +NV indexes, causing issues when using these functions without an +argument. Also, use the same argument in tpm2_nvreadpublic. + +Signed-off-by: Štěpán Horáček +--- + tools/tpm2_getekcertificate.c | 2 +- + tools/tpm2_nvdefine.c | 2 +- + tools/tpm2_nvreadpublic.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tools/tpm2_getekcertificate.c b/tools/tpm2_getekcertificate.c +index 3c9bddeb..b8fa5647 100644 +--- a/tools/tpm2_getekcertificate.c ++++ b/tools/tpm2_getekcertificate.c +@@ -478,7 +478,7 @@ tool_rc get_tpm_properties(ESYS_CONTEXT *ectx) { + + free(capability_data); + rc = tpm2_getcap(ectx, TPM2_CAP_HANDLES, +- tpm2_util_hton_32(TPM2_HT_NV_INDEX), TPM2_PT_NV_INDEX_MAX, NULL, ++ TPM2_NV_INDEX_FIRST, TPM2_PT_NV_INDEX_MAX, NULL, + &capability_data); + if (rc != tool_rc_success) { + LOG_ERR("Failed to read capability data for NV indices."); +diff --git a/tools/tpm2_nvdefine.c b/tools/tpm2_nvdefine.c +index 4462503a..7f193e83 100644 +--- a/tools/tpm2_nvdefine.c ++++ b/tools/tpm2_nvdefine.c +@@ -184,7 +184,7 @@ static tool_rc handle_no_index_specified(ESYS_CONTEXT *ectx, TPM2_NV_INDEX *chos + capabilities = NULL; + + /* now find what NV indexes are in use */ +- rc = tpm2_getcap(ectx, TPM2_CAP_HANDLES, tpm2_util_hton_32(TPM2_HT_NV_INDEX), ++ rc = tpm2_getcap(ectx, TPM2_CAP_HANDLES, TPM2_NV_INDEX_FIRST, + TPM2_PT_NV_INDEX_MAX, NULL, &capabilities); + if (rc != tool_rc_success) { + goto out; +diff --git a/tools/tpm2_nvreadpublic.c b/tools/tpm2_nvreadpublic.c +index 1f26b24e..060f521e 100644 +--- a/tools/tpm2_nvreadpublic.c ++++ b/tools/tpm2_nvreadpublic.c +@@ -85,7 +85,7 @@ static tool_rc nv_readpublic(ESYS_CONTEXT *context) { + + TPMS_CAPABILITY_DATA *capability_data = NULL; + if (ctx.nv_index == 0) { +- tool_rc rc = tpm2_getcap(context, TPM2_CAP_HANDLES, TPM2_HT_NV_INDEX << 24, ++ tool_rc rc = tpm2_getcap(context, TPM2_CAP_HANDLES, TPM2_NV_INDEX_FIRST, + TPM2_PT_NV_INDEX_MAX, NULL, &capability_data); + if (rc != tool_rc_success) { + return rc; +-- +2.51.0 + diff --git a/SOURCES/0001-tpm2_eventlog-Fix-parsing-on-big-endian-systems.patch b/SOURCES/0001-tpm2_eventlog-Fix-parsing-on-big-endian-systems.patch new file mode 100644 index 0000000..956a99a --- /dev/null +++ b/SOURCES/0001-tpm2_eventlog-Fix-parsing-on-big-endian-systems.patch @@ -0,0 +1,804 @@ +From deabe3a1fccfec9080097d7e90e98b92f3925f0a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20Hor=C3=A1=C4=8Dek?= + +Date: Fri, 8 Aug 2025 22:24:30 +0200 +Subject: [PATCH] tpm2_eventlog: Fix parsing on big-endian systems +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Štěpán Horáček +--- + lib/tpm2_eventlog.c | 69 ++++++------- + lib/tpm2_eventlog_yaml.c | 209 ++++++++++++++++++++------------------- + 2 files changed, 140 insertions(+), 138 deletions(-) + +diff --git a/lib/tpm2_eventlog.c b/lib/tpm2_eventlog.c +index 28fdba0e..b9c8b827 100644 +--- a/lib/tpm2_eventlog.c ++++ b/lib/tpm2_eventlog.c +@@ -1,6 +1,7 @@ + #include + #include + #include ++#include + + #include + +@@ -54,7 +55,7 @@ bool foreach_digest2(tpm2_eventlog_context *ctx, UINT32 eventType, unsigned pcr_ + return false; + } + +- const TPMI_ALG_HASH alg = digest->AlgorithmId; ++ const TPMI_ALG_HASH alg = le16toh(digest->AlgorithmId); + const size_t alg_size = tpm2_alg_util_get_hash_size(alg); + if (size < sizeof(*digest) + alg_size) { + LOG_ERR("insufficient size for digest buffer"); +@@ -119,13 +120,13 @@ bool parse_event2body(TCG_EVENT2 const *event, UINT32 type) { + case EV_EFI_VARIABLE_AUTHORITY: + { + UEFI_VARIABLE_DATA *data = (UEFI_VARIABLE_DATA*)event->Event; +- if (event->EventSize < sizeof(*data)) { ++ if (le32toh(event->EventSize) < sizeof(*data)) { + LOG_ERR("size is insufficient for UEFI variable data"); + return false; + } + +- if (event->EventSize < sizeof(*data) + data->UnicodeNameLength * +- sizeof(UTF16_CHAR) + data->VariableDataLength) ++ if (le32toh(event->EventSize) < sizeof(*data) + le64toh(data->UnicodeNameLength) * ++ sizeof(UTF16_CHAR) + le64toh(data->VariableDataLength)) + { + LOG_ERR("size is insufficient for UEFI variable data"); + return false; +@@ -143,7 +144,7 @@ bool parse_event2body(TCG_EVENT2 const *event, UINT32 type) { + UEFI_PLATFORM_FIRMWARE_BLOB *data = + (UEFI_PLATFORM_FIRMWARE_BLOB*)event->Event; + UNUSED(data); +- if (event->EventSize < sizeof(*data)) { ++ if (le32toh(event->EventSize) < sizeof(*data)) { + LOG_ERR("size is insufficient for UEFI FW blob data"); + return false; + } +@@ -155,7 +156,7 @@ bool parse_event2body(TCG_EVENT2 const *event, UINT32 type) { + { + UEFI_IMAGE_LOAD_EVENT *data = (UEFI_IMAGE_LOAD_EVENT*)event->Event; + UNUSED(data); +- if (event->EventSize < sizeof(*data)) { ++ if (le32toh(event->EventSize) < sizeof(*data)) { + LOG_ERR("size is insufficient for UEFI image load event"); + return false; + } +@@ -185,9 +186,9 @@ bool parse_event2(TCG_EVENT_HEADER2 const *eventhdr, size_t buf_size, + .data = digests_size, + .digest2_cb = digest2_accumulator_callback, + }; +- ret = foreach_digest2(&ctx, eventhdr->EventType, +- eventhdr->PCRIndex, +- eventhdr->Digests, eventhdr->DigestCount, ++ ret = foreach_digest2(&ctx, le32toh(eventhdr->EventType), ++ le32toh(eventhdr->PCRIndex), ++ eventhdr->Digests, le32toh(eventhdr->DigestCount), + buf_size - sizeof(*eventhdr), 0); + if (ret != true) { + return false; +@@ -201,11 +202,11 @@ bool parse_event2(TCG_EVENT_HEADER2 const *eventhdr, size_t buf_size, + } + *event_size += sizeof(*event); + +- if (buf_size < *event_size + event->EventSize) { ++ if (buf_size < *event_size + le32toh(event->EventSize)) { + LOG_ERR("size insufficient for event data"); + return false; + } +- *event_size += event->EventSize; ++ *event_size += le32toh(event->EventSize); + + return true; + } +@@ -222,19 +223,19 @@ bool parse_sha1_log_event(tpm2_eventlog_context *ctx, TCG_EVENT const *event, si + } + *event_size = sizeof(*event); + +- pcr = ctx->sha1_pcrs[ event->pcrIndex]; +- if (event->eventType != EV_NO_ACTION && pcr) { ++ pcr = ctx->sha1_pcrs[le32toh(event->pcrIndex)]; ++ if (le32toh(event->eventType) != EV_NO_ACTION && pcr) { + tpm2_openssl_pcr_extend(TPM2_ALG_SHA1, pcr, &event->digest[0], 20); +- ctx->sha1_used |= (1 << event->pcrIndex); ++ ctx->sha1_used |= (1 << le32toh(event->pcrIndex)); + } + + /* buffer size must be sufficient to hold event and event data */ + if (size < sizeof(*event) + (sizeof(event->event[0]) * +- event->eventDataSize)) { ++ le32toh(event->eventDataSize))) { + LOG_ERR("insufficient size for SpecID event data"); + return false; + } +- *event_size += event->eventDataSize; ++ *event_size += le32toh(event->eventDataSize); + return true; + } + +@@ -273,14 +274,14 @@ bool foreach_sha1_log_event(tpm2_eventlog_context *ctx, TCG_EVENT const *eventhd + } + } + +- ret = parse_event2body(event, eventhdr->eventType); ++ ret = parse_event2body(event, le32toh(eventhdr->eventType)); + if (ret != true) { + return ret; + } + + /* event data callback */ + if (ctx->event2_cb != NULL) { +- ret = ctx->event2_cb(event, eventhdr->eventType, ctx->data, ++ ret = ctx->event2_cb(event, le32toh(eventhdr->eventType), ctx->data, + ctx->eventlog_version); + if (ret != true) { + return false; +@@ -427,7 +428,7 @@ 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) { ++ if (le32toh(eventhdr->EventType) == EV_EFI_HCRTM_EVENT && le32toh(eventhdr->PCRIndex) == 0) { + found_hcrtm = true; + } + +@@ -455,13 +456,13 @@ 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, locality); ++ ret = foreach_digest2(ctx, le32toh(eventhdr->EventType), le32toh(eventhdr->PCRIndex), ++ eventhdr->Digests, le32toh(eventhdr->DigestCount), digests_size, locality); + if (ret != true) { + return false; + } + +- ret = parse_event2body(event, eventhdr->EventType); ++ ret = parse_event2body(event, le32toh(eventhdr->EventType)); + if (ret != true) { + return ret; + } +@@ -473,7 +474,7 @@ bool foreach_event2(tpm2_eventlog_context *ctx, TCG_EVENT_HEADER2 const *eventhd + + /* event data callback */ + if (ctx->event2_cb != NULL) { +- ret = ctx->event2_cb(event, eventhdr->EventType, ctx->data, ctx->eventlog_version); ++ ret = ctx->event2_cb(event, le32toh(eventhdr->EventType), ctx->data, ctx->eventlog_version); + if (ret != true) { + return false; + } +@@ -492,12 +493,12 @@ bool specid_event(TCG_EVENT const *event, size_t size, + return false; + } + +- if (event->eventType != EV_NO_ACTION) { ++ if (le32toh(event->eventType) != EV_NO_ACTION) { + LOG_ERR("SpecID eventType must be EV_NO_ACTION"); + return false; + } + +- if (event->pcrIndex != 0) { ++ if (le32toh(event->pcrIndex) != 0) { + LOG_ERR("bad pcrIndex for EV_NO_ACTION event"); + return false; + } +@@ -511,29 +512,29 @@ bool specid_event(TCG_EVENT const *event, size_t size, + } + + /* eventDataSize must be sufficient to hold the specid event */ +- if (event->eventDataSize < sizeof(TCG_SPECID_EVENT)) { ++ if (le32toh(event->eventDataSize) < sizeof(TCG_SPECID_EVENT)) { + LOG_ERR("invalid eventDataSize in specid event"); + return false; + } + + /* buffer size must be sufficient to hold event and event data */ + if (size < sizeof(*event) + (sizeof(event->event[0]) * +- event->eventDataSize)) { ++ le32toh(event->eventDataSize))) { + LOG_ERR("insufficient size for SpecID event data"); + return false; + } + + /* specid event must have 1 or more algorithms */ + TCG_SPECID_EVENT *event_specid = (TCG_SPECID_EVENT*)event->event; +- if (event_specid->numberOfAlgorithms == 0) { ++ if (le32toh(event_specid->numberOfAlgorithms) == 0) { + LOG_ERR("numberOfAlgorithms is invalid, may not be 0"); + return false; + } + + /* buffer size must be sufficient to hold event, specid event & algs */ + if (size < sizeof(*event) + sizeof(*event_specid) + +- sizeof(event_specid->digestSizes[0]) * +- event_specid->numberOfAlgorithms) { ++ sizeof(event_specid->digestSizes[0]) * ++ le32toh(event_specid->numberOfAlgorithms)) { + LOG_ERR("insufficient size for SpecID algorithms"); + return false; + } +@@ -541,18 +542,18 @@ bool specid_event(TCG_EVENT const *event, size_t size, + /* size must be sufficient for event, specid, algs & vendor stuff */ + if (size < sizeof(*event) + sizeof(*event_specid) + + sizeof(event_specid->digestSizes[0]) * +- event_specid->numberOfAlgorithms + sizeof(TCG_VENDOR_INFO)) { ++ le32toh(event_specid->numberOfAlgorithms) + sizeof(TCG_VENDOR_INFO)) { + LOG_ERR("insufficient size for VendorStuff"); + return false; + } + + TCG_VENDOR_INFO *vendor = (TCG_VENDOR_INFO*)((uintptr_t)event_specid->digestSizes + + sizeof(*event_specid->digestSizes) * +- event_specid->numberOfAlgorithms); ++ le32toh(event_specid->numberOfAlgorithms)); + /* size must be sufficient for vendorInfo */ + if (size < sizeof(*event) + sizeof(*event_specid) + + sizeof(event_specid->digestSizes[0]) * +- event_specid->numberOfAlgorithms + sizeof(*vendor) + ++ le32toh(event_specid->numberOfAlgorithms) + sizeof(*vendor) + + vendor->vendorInfoSize) { + LOG_ERR("insufficient size for VendorStuff data"); + return false; +@@ -573,7 +574,7 @@ bool parse_eventlog(tpm2_eventlog_context *ctx, BYTE const *eventlog, size_t siz + } + + TCG_EVENT *event = (TCG_EVENT*)eventlog; +- if (event->eventType == EV_NO_ACTION) { ++ if (le32toh(event->eventType) == EV_NO_ACTION) { + TCG_EVENT_HEADER2 *next; + bool ret = specid_event(event, size, &next); + if (!ret) { +diff --git a/lib/tpm2_eventlog_yaml.c b/lib/tpm2_eventlog_yaml.c +index 343fb658..cf1ca6fe 100644 +--- a/lib/tpm2_eventlog_yaml.c ++++ b/lib/tpm2_eventlog_yaml.c +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + + #include + +@@ -42,7 +43,7 @@ + static void guid_unparse_lower(EFI_GUID guid, char guid_buf[37]) { + + snprintf(guid_buf, 37, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", +- guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], ++ le32toh(guid.Data1), le16toh(guid.Data2), le16toh(guid.Data3), guid.Data4[0], guid.Data4[1], + guid.Data4[2], guid.Data4[3], guid.Data4[4], + guid.Data4[5], guid.Data4[6], guid.Data4[7]); + } +@@ -134,9 +135,9 @@ void yaml_event2hdr(TCG_EVENT_HEADER2 const *eventhdr, size_t size) { + tpm2_tool_output(" PCRIndex: %d\n" + " EventType: %s\n" + " DigestCount: %d\n", +- eventhdr->PCRIndex, +- eventtype_to_string(eventhdr->EventType), +- eventhdr->DigestCount); ++ le32toh(eventhdr->PCRIndex), ++ eventtype_to_string(le32toh(eventhdr->EventType)), ++ le32toh(eventhdr->DigestCount)); + + return; + } +@@ -146,8 +147,8 @@ void yaml_sha1_log_eventhdr(TCG_EVENT const *eventhdr, size_t size) { + + tpm2_tool_output(" PCRIndex: %d\n" + " EventType: %s\n", +- eventhdr->pcrIndex, +- eventtype_to_string(eventhdr->eventType)); ++ le32toh(eventhdr->pcrIndex), ++ eventtype_to_string(le32toh(eventhdr->eventType))); + + return; + } +@@ -161,7 +162,7 @@ bool yaml_digest2(TCG_DIGEST2 const *digest, size_t size) { + + tpm2_tool_output(" - AlgorithmId: %s\n" + " Digest: \"%s\"\n", +- tpm2_alg_util_algtostr(digest->AlgorithmId, tpm2_alg_util_flags_hash), ++ tpm2_alg_util_algtostr(le16toh(digest->AlgorithmId), tpm2_alg_util_flags_hash), + hexstr); + + return true; +@@ -181,7 +182,7 @@ static char *yaml_utf16_to_str(UTF16_CHAR *data, size_t len) { + } + + for(size_t i = 0; i < len; ++i, tmp += ret) { +- ret = c16rtomb(tmp, data[i].c, &st); ++ ret = c16rtomb(tmp, le16toh(data[i].c), &st); + if (ret < 0) { + LOG_ERR("c16rtomb failed: %s", strerror(errno)); + free(mbstr); +@@ -190,21 +191,21 @@ static char *yaml_utf16_to_str(UTF16_CHAR *data, size_t len) { + } + return mbstr; + } +-#define VAR_DATA_HEX_SIZE(data) BYTES_TO_HEX_STRING_SIZE(data->VariableDataLength) ++#define VAR_DATA_HEX_SIZE(data) BYTES_TO_HEX_STRING_SIZE(le64toh(data->VariableDataLength)) + static bool yaml_uefi_var_data(UEFI_VARIABLE_DATA *data) { + +- if (data->VariableDataLength == 0) { ++ if (le64toh(data->VariableDataLength) == 0) { + return true; + } + + char *var_data = calloc (1, VAR_DATA_HEX_SIZE(data)); + uint8_t *variable_data = (uint8_t*)&data->UnicodeName[ +- data->UnicodeNameLength]; ++ le64toh(data->UnicodeNameLength)]; + if (var_data == NULL) { + LOG_ERR("failled to allocate data: %s\n", strerror(errno)); + return false; + } +- bytes_to_str(variable_data, data->VariableDataLength, var_data, ++ bytes_to_str(variable_data, le64toh(data->VariableDataLength), var_data, + VAR_DATA_HEX_SIZE(data)); + + tpm2_tool_output(" VariableData: \"%s\"\n", var_data); +@@ -232,7 +233,7 @@ static bool yaml_uefi_var_data(UEFI_VARIABLE_DATA *data) { + */ + + static bool yaml_uefi_post_code(const TCG_EVENT2* const event) { +- const size_t len = event->EventSize; ++ const size_t len = le32toh(event->EventSize); + + /* if length is 16, we treat it as EV_EFI_PLATFORM_FIRMWARE_BLOB */ + if (len == 16) { +@@ -306,28 +307,28 @@ static bool yaml_uefi_var(UEFI_VARIABLE_DATA *data, size_t size, UINT32 type, + " VariableName: %s\n" + " UnicodeNameLength: %"PRIu64"\n" + " VariableDataLength: %" PRIu64 "\n", +- uuidstr, data->UnicodeNameLength, +- data->VariableDataLength); ++ uuidstr, le64toh(data->UnicodeNameLength), ++ le64toh(data->VariableDataLength)); + + start += sizeof(*data); +- if (start + data->UnicodeNameLength*2 > size) { ++ if (start + le64toh(data->UnicodeNameLength)*2 > size) { + LOG_ERR("EventSize is too small\n"); + return false; + } + +- char *ret = yaml_utf16_to_str(data->UnicodeName, data->UnicodeNameLength); ++ char *ret = yaml_utf16_to_str(data->UnicodeName, le64toh(data->UnicodeNameLength)); + if (!ret) { + return false; + } + tpm2_tool_output(" UnicodeName: %s\n", ret); + +- start += data->UnicodeNameLength*2; ++ start += le64toh(data->UnicodeNameLength)*2; + /* Try to parse as much as we can without fail-stop. Bugs in firmware, shim, + * grub could produce inconsistent metadata. As long as it is not preventing + * us from parsing the data, we try to continue while giving a warning + * message. + */ +- if (start + data->VariableDataLength > size) { ++ if (start + le64toh(data->VariableDataLength) > size) { + LOG_ERR("EventSize is inconsistent with actual data\n"); + } + +@@ -345,7 +346,7 @@ static bool yaml_uefi_var(UEFI_VARIABLE_DATA *data, size_t size, UINT32 type, + free(ret); + tpm2_tool_output(" VariableData:\n"); + uint8_t *variable_data = (uint8_t *)&data->UnicodeName[ +- data->UnicodeNameLength]; ++ le64toh(data->UnicodeNameLength)]; + /* iterate through each EFI_SIGNATURE_LIST */ + while (start < size) { + EFI_SIGNATURE_LIST *slist = (EFI_SIGNATURE_LIST *)variable_data; +@@ -354,7 +355,7 @@ static bool yaml_uefi_var(UEFI_VARIABLE_DATA *data, size_t size, UINT32 type, + break; + } + +- if (slist->SignatureSize < 16) { ++ if (le32toh(slist->SignatureSize) < 16) { + LOG_ERR("SignatureSize is too small\n"); + break; + } +@@ -365,67 +366,67 @@ static bool yaml_uefi_var(UEFI_VARIABLE_DATA *data, size_t size, UINT32 type, + " SignatureHeaderSize: %" PRIu32 "\n" + " SignatureSize: %" PRIu32 "\n" + " Keys:\n", +- uuidstr, slist->SignatureListSize, +- slist->SignatureHeaderSize, +- slist->SignatureSize); ++ uuidstr, le32toh(slist->SignatureListSize), ++ le32toh(slist->SignatureHeaderSize), ++ le32toh(slist->SignatureSize)); + +- start += (sizeof(*slist) + slist->SignatureHeaderSize); +- if (start + slist->SignatureSize > size) { ++ start += (sizeof(*slist) + le32toh(slist->SignatureHeaderSize)); ++ if (start + le32toh(slist->SignatureSize) > size) { + LOG_ERR("EventSize is inconsistent with actual data\n"); + break; + } + +- int signature_size = slist->SignatureListSize - +- sizeof(*slist) - slist->SignatureHeaderSize; +- if (signature_size < 0 || signature_size % slist->SignatureSize != 0) { ++ int signature_size = le32toh(slist->SignatureListSize) - ++ sizeof(*slist) - le32toh(slist->SignatureHeaderSize); ++ if (signature_size < 0 || signature_size % le32toh(slist->SignatureSize) != 0) { + LOG_ERR("Malformed EFI_SIGNATURE_LIST\n"); + break; + } + + uint8_t *signature = (uint8_t *)slist + +- sizeof(*slist) + slist->SignatureHeaderSize; +- int signatures = signature_size / slist->SignatureSize; ++ sizeof(*slist) + le32toh(slist->SignatureHeaderSize); ++ int signatures = signature_size / le32toh(slist->SignatureSize); + /* iterate through each EFI_SIGNATURE on the list */ + int i; + for (i = 0; i < signatures; i++) { + EFI_SIGNATURE_DATA *s = (EFI_SIGNATURE_DATA *)signature; + char *sdata = calloc (1, +- BYTES_TO_HEX_STRING_SIZE(slist->SignatureSize - sizeof(EFI_GUID))); ++ BYTES_TO_HEX_STRING_SIZE(le32toh(slist->SignatureSize) - sizeof(EFI_GUID))); + if (sdata == NULL) { + LOG_ERR("Failled to allocate data: %s\n", strerror(errno)); + return false; + } +- bytes_to_str(s->SignatureData, slist->SignatureSize - sizeof(EFI_GUID), +- sdata, BYTES_TO_HEX_STRING_SIZE(slist->SignatureSize - sizeof(EFI_GUID))); ++ bytes_to_str(s->SignatureData, le32toh(slist->SignatureSize) - sizeof(EFI_GUID), ++ sdata, BYTES_TO_HEX_STRING_SIZE(le32toh(slist->SignatureSize) - sizeof(EFI_GUID))); + guid_unparse_lower(s->SignatureOwner, uuidstr); + tpm2_tool_output(" - SignatureOwner: %s\n" + " SignatureData: %s\n", + uuidstr, sdata); + free(sdata); + +- signature += slist->SignatureSize; +- start += slist->SignatureSize; ++ signature += le32toh(slist->SignatureSize); ++ start += le32toh(slist->SignatureSize); + if (start > size) { + LOG_ERR("Malformed EFI_SIGNATURE_DATA\n"); + break; + } + } +- variable_data += slist->SignatureListSize; ++ variable_data += le32toh(slist->SignatureListSize); + } + return true; + } else if ((strlen(ret) == NAME_SECUREBOOT_LEN && strncmp(ret, NAME_SECUREBOOT, NAME_SECUREBOOT_LEN) == 0)) { + free(ret); + tpm2_tool_output(" VariableData:\n" + " Enabled: "); +- if (data->VariableDataLength == 0) { ++ if (le64toh(data->VariableDataLength) == 0) { + tpm2_tool_output("'No'\n"); +- } else if (data->VariableDataLength > 1) { ++ } else if (le64toh(data->VariableDataLength) > 1) { + LOG_ERR("SecureBoot value length %" PRIu64 " is unexpectedly > 1\n", +- data->VariableDataLength); ++ le64toh(data->VariableDataLength)); + return false; + } else { + uint8_t *variable_data = (uint8_t *)&data->UnicodeName[ +- data->UnicodeNameLength]; ++ le64toh(data->UnicodeNameLength)]; + if (*variable_data == 0) { + tpm2_tool_output("'No'\n"); + } else { +@@ -440,15 +441,15 @@ static bool yaml_uefi_var(UEFI_VARIABLE_DATA *data, size_t size, UINT32 type, + free(ret); + tpm2_tool_output(" VariableData:\n" + " Enabled: "); +- if (data->VariableDataLength == 0) { ++ if (le64toh(data->VariableDataLength) == 0) { + tpm2_tool_output("'No'\n"); +- } else if (data->VariableDataLength > 1) { ++ } else if (le64toh(data->VariableDataLength) > 1) { + LOG_ERR("MokListTrusted value length %" PRIu64 " is unexpectedly > 1\n", +- data->VariableDataLength); ++ le64toh(data->VariableDataLength)); + return false; + } else { + uint8_t *variable_data = (uint8_t *)&data->UnicodeName[ +- data->UnicodeNameLength]; ++ le64toh(data->UnicodeNameLength)]; + if (*variable_data == 0) { + tpm2_tool_output("'No'\n"); + } else { +@@ -461,15 +462,15 @@ static bool yaml_uefi_var(UEFI_VARIABLE_DATA *data, size_t size, UINT32 type, + free(ret); + tpm2_tool_output(" VariableData:\n"); + EFI_SIGNATURE_DATA *s= (EFI_SIGNATURE_DATA *)&data->UnicodeName[ +- data->UnicodeNameLength]; ++ le64toh(data->UnicodeNameLength)]; + char *sdata = calloc (1, +- BYTES_TO_HEX_STRING_SIZE(data->VariableDataLength - sizeof(EFI_GUID))); ++ BYTES_TO_HEX_STRING_SIZE(le64toh(data->VariableDataLength) - sizeof(EFI_GUID))); + if (sdata == NULL) { + LOG_ERR("Failled to allocate data: %s\n", strerror(errno)); + return false; + } +- bytes_to_str(s->SignatureData, data->VariableDataLength - sizeof(EFI_GUID), +- sdata, BYTES_TO_HEX_STRING_SIZE(data->VariableDataLength - sizeof(EFI_GUID))); ++ bytes_to_str(s->SignatureData, le64toh(data->VariableDataLength) - sizeof(EFI_GUID), ++ sdata, BYTES_TO_HEX_STRING_SIZE(le64toh(data->VariableDataLength) - sizeof(EFI_GUID))); + guid_unparse_lower(s->SignatureOwner, uuidstr); + tpm2_tool_output(" - SignatureOwner: %s\n" + " SignatureData: %s\n", +@@ -484,14 +485,14 @@ static bool yaml_uefi_var(UEFI_VARIABLE_DATA *data, size_t size, UINT32 type, + + if (data->VariableDataLength % 2 != 0) { + LOG_ERR("BootOrder value length %" PRIu64 " is not divisible by 2\n", +- data->VariableDataLength); ++ le64toh(data->VariableDataLength)); + return false; + } + + uint8_t *variable_data = (uint8_t *)&data->UnicodeName[ +- data->UnicodeNameLength]; +- for (uint64_t i = 0; i < data->VariableDataLength / 2; i++) { +- tpm2_tool_output(" - Boot%04x\n", *((uint16_t*)variable_data + i)); ++ le64toh(data->UnicodeNameLength)]; ++ for (uint64_t i = 0; i < le64toh(data->VariableDataLength) / 2; i++) { ++ tpm2_tool_output(" - Boot%04x\n", le16toh(*((uint16_t*)variable_data + i))); + } + return true; + } +@@ -505,27 +506,27 @@ static bool yaml_uefi_var(UEFI_VARIABLE_DATA *data, size_t size, UINT32 type, + tpm2_tool_output(" VariableData:\n" + " Enabled: "); + EFI_LOAD_OPTION *loadopt = (EFI_LOAD_OPTION*)&data->UnicodeName[ +- data->UnicodeNameLength]; ++ le64toh(data->UnicodeNameLength)]; + +- if (loadopt->Attributes & 1) { ++ if (le32toh(loadopt->Attributes) & 1) { + tpm2_tool_output("'Yes'\n"); + } else { + tpm2_tool_output("'No'\n"); + } + + tpm2_tool_output(" FilePathListLength: %" PRIu16 "\n", +- loadopt->FilePathListLength); ++ le16toh(loadopt->FilePathListLength)); + + tpm2_tool_output(" Description: \""); + int i; +- for (i = 0; (wchar_t)loadopt->Description[i] != 0; i++) { +- char16_t c = (char16_t)loadopt->Description[i]; ++ for (i = 0; (wchar_t)le16toh(loadopt->Description[i]) != 0; i++) { ++ char16_t c = (char16_t)le16toh(loadopt->Description[i]); + tpm2_tool_output("%lc", c); + } + tpm2_tool_output("\"\n"); + + uint8_t *devpath = (uint8_t*)&loadopt->Description[++i]; +- size_t devpath_len = (data->VariableDataLength - ++ size_t devpath_len = (le64toh(data->VariableDataLength) - + sizeof(EFI_LOAD_OPTION) - sizeof(UINT16) * i) * 2 + 1; + + char *buf = calloc(1, devpath_len); +@@ -541,12 +542,12 @@ static bool yaml_uefi_var(UEFI_VARIABLE_DATA *data, size_t size, UINT32 type, + free(dp); + } else { + /* fallback to printing the raw bytes if devicepath cannot be parsed */ +- bytes_to_str(devpath, data->VariableDataLength - ++ bytes_to_str(devpath, le64toh(data->VariableDataLength) - + sizeof(EFI_LOAD_OPTION) - sizeof(UINT16) * i, buf, devpath_len); + tpm2_tool_output(" DevicePath: '%s'\n", buf); + } + #else +- bytes_to_str(devpath, data->VariableDataLength - ++ bytes_to_str(devpath, le64toh(data->VariableDataLength) - + sizeof(EFI_LOAD_OPTION) - sizeof(UINT16) * i, buf, devpath_len); + tpm2_tool_output(" DevicePath: '%s'\n", buf); + #endif +@@ -566,8 +567,8 @@ bool yaml_uefi_platfwblob(UEFI_PLATFORM_FIRMWARE_BLOB *data) { + tpm2_tool_output(" Event:\n" + " BlobBase: 0x%" PRIx64 "\n" + " BlobLength: 0x%" PRIx64 "\n", +- data->BlobBase, +- data->BlobLength); ++ le64toh(data->BlobBase), ++ le64toh(data->BlobLength)); + return true; + } + +@@ -592,8 +593,8 @@ bool yaml_uefi_platfwblob2(UEFI_PLATFORM_FIRMWARE_BLOB2 *data) { + blobdescsize, + 2*blobdescsize, + eventdesc, +- data2->BlobBase, +- data2->BlobLength); ++ le64toh(data2->BlobBase), ++ le64toh(data2->BlobLength)); + + free(eventdesc); + return true; +@@ -762,17 +763,17 @@ bool yaml_uefi_image_load(UEFI_IMAGE_LOAD_EVENT *data, size_t size) { + LOG_ERR("failed to allocate memory: %s\n", strerror(errno)); + return false; + } +- ++ + tpm2_tool_output(" Event:\n" + " ImageLocationInMemory: 0x%" PRIx64 "\n" + " ImageLengthInMemory: %" PRIu64 "\n" + " ImageLinkTimeAddress: 0x%" PRIx64 "\n" + " LengthOfDevicePath: %" PRIu64 "\n", +- data->ImageLocationInMemory, data->ImageLengthInMemory, +- data->ImageLinkTimeAddress, data->LengthOfDevicePath); ++ le64toh(data->ImageLocationInMemory), le64toh(data->ImageLengthInMemory), ++ le64toh(data->ImageLinkTimeAddress), le64toh(data->LengthOfDevicePath)); + + #ifdef HAVE_EFIVAR_EFIVAR_H +- char *dp = yaml_devicepath(data->DevicePath, data->LengthOfDevicePath); ++ char *dp = yaml_devicepath(data->DevicePath, le64toh(data->LengthOfDevicePath)); + if (dp) { + tpm2_tool_output(" DevicePath: '%s'\n", dp); + free(dp); +@@ -822,24 +823,24 @@ bool yaml_gpt(UEFI_GPT_DATA *data, size_t size, uint32_t eventlog_version) { + " NumberOfPartitions: %" PRIu64 "\n" + " Partitions:\n", + 8, (char*)&header->Signature, /* 8-char ASCII string */ +- header->Revision, +- header->HeaderSize, +- header->HeaderCRC32, +- header->MyLBA, +- header->AlternateLBA, +- header->FirstUsableLBA, +- header->LastUsableLBA, ++ le32toh(header->Revision), ++ le32toh(header->HeaderSize), ++ le32toh(header->HeaderCRC32), ++ le64toh(header->MyLBA), ++ le64toh(header->AlternateLBA), ++ le64toh(header->FirstUsableLBA), ++ le64toh(header->LastUsableLBA), + guid, +- header->PartitionEntryLBA, +- header->NumberOfPartitionEntries, +- header->SizeOfPartitionEntry, +- header->PartitionEntryArrayCRC32, +- data->NumberOfPartitions); ++ le64toh(header->PartitionEntryLBA), ++ le32toh(header->NumberOfPartitionEntries), ++ le32toh(header->SizeOfPartitionEntry), ++ le32toh(header->PartitionEntryArrayCRC32), ++ le64toh(data->NumberOfPartitions)); + + size -= (sizeof(data->UEFIPartitionHeader) + sizeof(data->NumberOfPartitions)); + + UINT64 i; +- for (i = 0; i < data->NumberOfPartitions; i++) { ++ for (i = 0; i < le64toh(data->NumberOfPartitions); i++) { + UEFI_PARTITION_ENTRY *partition = &data->Partitions[i]; + if (size < sizeof(*partition)) { + LOG_ERR("Cannot parse GPT partition entry: insufficient data (%zu)\n", size); +@@ -857,9 +858,9 @@ bool yaml_gpt(UEFI_GPT_DATA *data, size_t size, uint32_t eventlog_version) { + " Attributes: 0x%" PRIx64 "\n" + " PartitionName: \"%s\"\n", + guid, +- partition->StartingLBA, +- partition->EndingLBA, +- partition->Attributes, ++ le64toh(partition->StartingLBA), ++ le64toh(partition->EndingLBA), ++ le64toh(partition->Attributes), + part_name); + free(part_name); + size -= sizeof(*partition); +@@ -898,9 +899,9 @@ bool yaml_event2data(TCG_EVENT2 const *event, UINT32 type, uint32_t eventlog_ver + + char hexstr[EVENT_BUF_MAX] = { 0, }; + +- tpm2_tool_output(" EventSize: %" PRIu32 "\n", event->EventSize); ++ tpm2_tool_output(" EventSize: %" PRIu32 "\n", le32toh(event->EventSize)); + +- if (event->EventSize == 0) { ++ if (le32toh(event->EventSize) == 0) { + return true; + } + +@@ -909,8 +910,8 @@ bool yaml_event2data(TCG_EVENT2 const *event, UINT32 type, uint32_t eventlog_ver + case EV_EFI_VARIABLE_BOOT: + case EV_EFI_VARIABLE_BOOT2: + case EV_EFI_VARIABLE_AUTHORITY: +- return yaml_uefi_var((UEFI_VARIABLE_DATA*)event->Event, +- event->EventSize, type, eventlog_version); ++ return yaml_uefi_var((UEFI_VARIABLE_DATA*)event->Event, ++ le32toh(event->EventSize), type, eventlog_version); + case EV_POST_CODE: + return yaml_uefi_post_code(event); + case EV_S_CRTM_CONTENTS: +@@ -919,21 +920,21 @@ bool yaml_event2data(TCG_EVENT2 const *event, UINT32 type, uint32_t eventlog_ver + case EV_EFI_PLATFORM_FIRMWARE_BLOB2: + return yaml_uefi_platfwblob2((UEFI_PLATFORM_FIRMWARE_BLOB2*)event->Event); + case EV_EFI_ACTION: +- return yaml_uefi_action(event->Event, event->EventSize); ++ return yaml_uefi_action(event->Event, le32toh(event->EventSize)); + case EV_IPL: +- return yaml_ipl(event->Event, event->EventSize); ++ return yaml_ipl(event->Event, le32toh(event->EventSize)); + case EV_EFI_BOOT_SERVICES_APPLICATION: + case EV_EFI_BOOT_SERVICES_DRIVER: + case EV_EFI_RUNTIME_SERVICES_DRIVER: +- return yaml_uefi_image_load((UEFI_IMAGE_LOAD_EVENT*)event->Event, +- event->EventSize); ++ return yaml_uefi_image_load((UEFI_IMAGE_LOAD_EVENT*)event->Event, ++ le32toh(event->EventSize)); + case EV_EFI_GPT_EVENT: + return yaml_gpt((UEFI_GPT_DATA*)event->Event, +- event->EventSize, eventlog_version); ++ le32toh(event->EventSize), eventlog_version); + case EV_NO_ACTION: + return yaml_no_action((EV_NO_ACTION_STRUCT*)event->Event, event->EventSize, eventlog_version); + default: +- bytes_to_str(event->Event, event->EventSize, hexstr, sizeof(hexstr)); ++ bytes_to_str(event->Event, le32toh(event->EventSize), hexstr, sizeof(hexstr)); + tpm2_tool_output(" Event: \"%s\"\n", hexstr); + return true; + } +@@ -999,9 +1000,9 @@ void yaml_eventhdr(TCG_EVENT const *event, size_t *count) { + " EventType: %s\n" + " Digest: \"%s\"\n" + " EventSize: %" PRIu32 "\n", +- (*count)++, event->pcrIndex, +- eventtype_to_string(event->eventType), digest_hex, +- event->eventDataSize); ++ (*count)++, le32toh(event->pcrIndex), ++ eventtype_to_string(le32toh(event->eventType)), digest_hex, ++ le32toh(event->eventDataSize)); + } + + void yaml_specid(TCG_SPECID_EVENT* specid) { +@@ -1020,10 +1021,10 @@ void yaml_specid(TCG_SPECID_EVENT* specid) { + " numberOfAlgorithms: %" PRIu32 "\n" + " Algorithms:\n", + sig_str, +- specid->platformClass, specid->specVersionMinor, ++ le32toh(specid->platformClass), specid->specVersionMinor, + specid->specVersionMajor, specid->specErrata, + specid->uintnSize, +- specid->numberOfAlgorithms); ++ le32toh(specid->numberOfAlgorithms)); + + } + void yaml_specid_algs(TCG_SPECID_ALG const *alg, size_t count) { +@@ -1033,9 +1034,9 @@ void yaml_specid_algs(TCG_SPECID_ALG const *alg, size_t count) { + " algorithmId: %s\n" + " digestSize: %" PRIu16 "\n", + i, +- tpm2_alg_util_algtostr(alg->algorithmId, ++ tpm2_alg_util_algtostr(le16toh(alg->algorithmId), + tpm2_alg_util_flags_hash), +- alg->digestSize); ++ le16toh(alg->digestSize)); + } + } + bool yaml_specid_vendor(TCG_VENDOR_INFO *vendor) { +@@ -1062,11 +1063,11 @@ bool yaml_specid_event(TCG_EVENT const *event, size_t *count) { + + TCG_SPECID_EVENT *specid = (TCG_SPECID_EVENT*)event->event; + TCG_SPECID_ALG *alg = (TCG_SPECID_ALG*)specid->digestSizes; +- TCG_VENDOR_INFO *vendor = (TCG_VENDOR_INFO*)(alg + specid->numberOfAlgorithms); ++ TCG_VENDOR_INFO *vendor = (TCG_VENDOR_INFO*)(alg + le32toh(specid->numberOfAlgorithms)); + + yaml_eventhdr(event, count); + yaml_specid(specid); +- yaml_specid_algs(alg, specid->numberOfAlgorithms); ++ yaml_specid_algs(alg, le32toh(specid->numberOfAlgorithms)); + return yaml_specid_vendor(vendor); + } + bool yaml_specid_callback(TCG_EVENT const *event, void *data) { +-- +2.51.0 + diff --git a/SOURCES/0001-tpm2_quote-checkquote-Fix-usage-of-little-endian-ser.patch b/SOURCES/0001-tpm2_quote-checkquote-Fix-usage-of-little-endian-ser.patch new file mode 100644 index 0000000..253de8a --- /dev/null +++ b/SOURCES/0001-tpm2_quote-checkquote-Fix-usage-of-little-endian-ser.patch @@ -0,0 +1,519 @@ +From 9764e1cff9fd113154272dd2aa40700bd9b9956b Mon Sep 17 00:00:00 2001 +From: Juergen Repp +Date: Wed, 30 Jul 2025 11:34:48 +0200 +Subject: [PATCH] tpm2_quote/checkquote: Fix usage of little endian + serialization. + +little endian is used for the pcr serialization (-F serialized) by +tpm2_pcrread, tpm2_quote, and tpm2_checkpublic. +After reading a pcr file the format was not adapted. Also on +big endian platforms still the little endian values are used. +To fix this problem new functions were added: +pcr_print_pcr_struct_le, tpm2_openssl_hash_pcr_banks_le. +But this functions are also used if the format value (-F value") +is used. But on big endian platforms the usage of these +_le functions will not work. +Now these _le functions are removed and the little endian format of +the input file is converted to host endian after the reading. +Also a new serialization format is added (-F marshaled) where +the tss2 marshaling unmarshaling functions are used. +Addresses: #3447 + +Signed-off-by: Juergen Repp +--- + lib/pcr.c | 134 +++++++++++++++++++++-------------- + lib/pcr.h | 15 +--- + lib/tpm2_convert.c | 2 + + lib/tpm2_convert.h | 1 + + lib/tpm2_openssl.h | 18 ----- + man/common/pcrs_format.md | 5 +- + man/tpm2_checkquote.1.md | 5 +- + tools/misc/tpm2_checkquote.c | 99 ++++++++++++++++++++++---- + tools/tpm2_pcrread.c | 4 ++ + tools/tpm2_quote.c | 3 + + 13 files changed, 216 insertions(+), 107 deletions(-) + +diff --git a/lib/pcr.c b/lib/pcr.c +index b39750f0..e148b625 100644 +--- a/lib/pcr.c ++++ b/lib/pcr.c +@@ -13,6 +13,8 @@ + #include "tpm2_tool.h" + #include "tpm2_alg_util.h" + #include "tpm2_util.h" ++#include "tss2_common.h" ++#include "tss2_mu.h" + + #define MAX(a,b) ((a>b)?a:b) + +@@ -185,58 +187,6 @@ static bool pcr_unset_pcr_sections(TPML_PCR_SELECTION *s) { + return true; + } + +-bool pcr_print_pcr_struct_le(TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs) { +- +- UINT32 vi = 0, di = 0, i; +- bool result = true; +- +- tpm2_tool_output("pcrs:\n"); +- +- /* Loop through all PCR/hash banks */ +- for (i = 0; i < le32toh(pcr_select->count); i++) { +- const char *alg_name = tpm2_alg_util_algtostr( +- le16toh(pcr_select->pcrSelections[i].hash), tpm2_alg_util_flags_hash); +- +- tpm2_tool_output(" %s:\n", alg_name); +- +- /* Loop through all PCRs in this bank */ +- unsigned int pcr_id; +- for (pcr_id = 0; pcr_id < pcr_select->pcrSelections[i].sizeofSelect * 8u; +- pcr_id++) { +- if (!tpm2_util_is_pcr_select_bit_set(&pcr_select->pcrSelections[i], +- pcr_id)) { +- continue; // skip non-selected banks +- } +- if (vi >= le64toh(pcrs->count) || di >= le32toh(pcrs->pcr_values[vi].count)) { +- LOG_ERR("Something wrong, trying to print but nothing more"); +- return false; +- } +- +- /* Print out PCR ID */ +- tpm2_tool_output(" %-2d: 0x", pcr_id); +- +- /* Print out current PCR digest value */ +- TPM2B_DIGEST *b = &pcrs->pcr_values[vi].digests[di]; +- int k; +- for (k = 0; k < le16toh(b->size); k++) { +- tpm2_tool_output("%02X", b->buffer[k]); +- } +- tpm2_tool_output("\n"); +- +- if (++di < le32toh(pcrs->pcr_values[vi].count)) { +- continue; +- } +- +- di = 0; +- if (++vi < le64toh(pcrs->count)) { +- continue; +- } +- } +- } +- +- return result; +-} +- + bool pcr_fwrite_serialized(const TPML_PCR_SELECTION *pcr_select, + const tpm2_pcrs *ppcrs, FILE *output_file) { + +@@ -282,6 +232,86 @@ bool pcr_fwrite_serialized(const TPML_PCR_SELECTION *pcr_select, + return true; + } + ++bool pcr_fwrite_marshaled(const TPML_PCR_SELECTION *pcr_select, ++ const tpm2_pcrs *ppcrs, FILE *output_file) { ++ TSS2_RC rc; ++ size_t size; ++ uint8_t *buffer; ++ uint8_t num_buffer[sizeof(UINT32)]; ++ ++ size = 0; ++ rc = Tss2_MU_TPML_PCR_SELECTION_Marshal(pcr_select, NULL, ++ TPM2_MAX_COMMAND_SIZE, &size); ++ if (rc) { ++ return false; ++ } ++ buffer = malloc(size); ++ if (!buffer) { ++ return false; ++ } ++ size = 0; ++ rc = Tss2_MU_TPML_PCR_SELECTION_Marshal(pcr_select, buffer, ++ TPM2_MAX_COMMAND_SIZE, &size); ++ if (rc) { ++ free(buffer); ++ return false; ++ } ++ ++ size_t fwrite_len = fwrite(buffer, size, 1, ++ output_file); ++ if (fwrite_len != 1) { ++ LOG_ERR("write to output file failed: %s", strerror(errno)); ++ free(buffer); ++ return false; ++ } ++ free(buffer); ++ ++ // Marshal PCR digests to pcr outfile ++ ++ UINT32 count = ppcrs->count; ++ size = 0; ++ rc = Tss2_MU_UINT32_Marshal(count, &num_buffer[0], ++ sizeof(num_buffer), &size); ++ if (rc) { ++ return false; ++ } ++ fwrite_len = fwrite(&num_buffer[0], size, 1, ++ output_file); ++ if (fwrite_len != 1) { ++ LOG_ERR("write to output file failed: %s", strerror(errno)); ++ return false; ++ } ++ ++ for (size_t j = 0; j < ppcrs->count; j++) { ++ size = 0; ++ rc = Tss2_MU_TPML_DIGEST_Marshal(&ppcrs->pcr_values[j], NULL, ++ TPM2_MAX_COMMAND_SIZE, &size); ++ if (rc) { ++ return false; ++ } ++ buffer = malloc(size); ++ if (!buffer) { ++ return false; ++ } ++ size = 0; ++ rc = Tss2_MU_TPML_DIGEST_Marshal(&ppcrs->pcr_values[j], buffer, ++ TPM2_MAX_COMMAND_SIZE, &size); ++ if (rc) { ++ free(buffer); ++ return false; ++ } ++ fwrite_len = fwrite(buffer, size, 1, ++ output_file); ++ if (fwrite_len != 1) { ++ free(buffer); ++ LOG_ERR("write to output file failed: %s", strerror(errno)); ++ return false; ++ } ++ free(buffer); ++ } ++ return true; ++} ++ + bool pcr_fwrite_values(const TPML_PCR_SELECTION *pcr_select, + const tpm2_pcrs *pcrs, FILE *output_file) { + +diff --git a/lib/pcr.h b/lib/pcr.h +index a782da3e..d69fc9c5 100644 +--- a/lib/pcr.h ++++ b/lib/pcr.h +@@ -34,18 +34,6 @@ struct tpm2_pcrs { + */ + bool pcr_print_pcr_struct(TPML_PCR_SELECTION *pcrSelect, tpm2_pcrs *pcrs); + +-/** +- * Echo out all PCR banks according to g_pcrSelection & g_pcrs->. +- * Assume that data structures are all little endian. +- * @param pcrSelect +- * Description of which PCR registers are selected. +- * @param pcrs +- * Struct containing PCR digests. +- * @return +- * True on success, false otherwise. +- */ +-bool pcr_print_pcr_struct_le(TPML_PCR_SELECTION *pcrSelect, tpm2_pcrs *pcrs); +- + /** + * Set the PCR value into pcrId if string in arg is a valid PCR index. + * @param arg +@@ -90,6 +78,9 @@ bool pcr_fwrite_values(const TPML_PCR_SELECTION *pcr_select, + bool pcr_fwrite_serialized(const TPML_PCR_SELECTION *pcr_select, + const tpm2_pcrs *pcrs, FILE *output_file); + ++bool pcr_fwrite_marshaled(const TPML_PCR_SELECTION *pcr_select, ++ const tpm2_pcrs *ppcrs, FILE *output_file); ++ + bool pcr_parse_selections(const char *arg, TPML_PCR_SELECTION *pcr_selections); + + tool_rc pcr_get_banks(ESYS_CONTEXT *esys_context, +diff --git a/lib/tpm2_convert.c b/lib/tpm2_convert.c +index edb9bed0..22aa7b93 100644 +--- a/lib/tpm2_convert.c ++++ b/lib/tpm2_convert.c +@@ -34,6 +34,8 @@ tpm2_convert_pcrs_output_fmt tpm2_convert_pcrs_output_fmt_from_optarg( + return pcrs_output_format_values; + } else if (strcasecmp(label, "serialized") == 0) { + return pcrs_output_format_serialized; ++ } else if (strcasecmp(label, "marshaled") == 0) { ++ return pcrs_output_format_marshaled; + } + + LOG_ERR("Invalid pcrs output format '%s' specified", label); +diff --git a/lib/tpm2_convert.h b/lib/tpm2_convert.h +index 87848ee3..fab9d396 100644 +--- a/lib/tpm2_convert.h ++++ b/lib/tpm2_convert.h +@@ -29,6 +29,7 @@ typedef enum tpm2_convert_pcrs_output_fmt tpm2_convert_pcrs_output_fmt; + enum tpm2_convert_pcrs_output_fmt { + pcrs_output_format_values, + pcrs_output_format_serialized, ++ pcrs_output_format_marshaled, + pcrs_output_format_err + }; + +diff --git a/lib/tpm2_openssl.h b/lib/tpm2_openssl.h +index 68dd54e3..62760e4e 100644 +--- a/lib/tpm2_openssl.h ++++ b/lib/tpm2_openssl.h +@@ -96,24 +96,6 @@ bool tpm2_openssl_hash_pcr_values(TPMI_ALG_HASH halg, TPML_DIGEST *digests, + bool tpm2_openssl_hash_pcr_banks(TPMI_ALG_HASH hashAlg, + TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs, TPM2B_DIGEST *digest); + +-/* +- * Hash a list of PCR digests, supporting multiple banks. +- * The data in TPML_PCR_SELECTION and tpm2_pcrs is in little endian format. +- * +- * @param halg +- * The hashing algorithm to use. +- * @param pcr_select +- * The list that specifies which PCRs are selected. +- * @param pcrs +- * The list of PCR banks, each containing a list of PCR digests to hash. +- ^ * @param digest +- ^ * The result of hashing digests with halg. +- * @return +- * true on success, false on error. +- */ +-bool tpm2_openssl_hash_pcr_banks_le(TPMI_ALG_HASH hashAlg, +- TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs, TPM2B_DIGEST *digest); +- + /** + * Extend a PCR with a new digest. + * @param halg +diff --git a/man/common/pcrs_format.md b/man/common/pcrs_format.md +index 58f40705..d1caac4b 100644 +--- a/man/common/pcrs_format.md ++++ b/man/common/pcrs_format.md +@@ -1,3 +1,6 @@ + * **-F**, **\--pcrs_format**=_FORMAT_: + +- Format selection for the binary blob in the PCR output file. 'values' will output a binary blob of the PCR values. 'serialized' will output a binary blob of the PCR values in the form of serialized data structure in little endian format. Optional. ++ Format selection for the binary blob in the PCR output file. 'values' will output a binary blob of the PCR values. 'serialized' will write or read a binary blob of the PCR values in the form of serialized data structure in little endian format. ++ 'marshaled' will will read or write a binary blob in the binary format used by the TSS2 marshaling and unmarshaling functions. If marshaled is used the data is serialized in the following order: TPML_PCR_SELECTION, ++ UINT32 (the number of following TPML_DIGEST elements) TPML_DIGEST [number of TPML_DIGEST elements]. ++ Optional. +diff --git a/tools/misc/tpm2_checkquote.c b/tools/misc/tpm2_checkquote.c +index 5083d855..fb4d5868 100644 +--- a/tools/misc/tpm2_checkquote.c ++++ b/tools/misc/tpm2_checkquote.c +@@ -1,5 +1,6 @@ + /* SPDX-License-Identifier: BSD-3-Clause */ + ++#include + #include + #include + #include +@@ -19,6 +20,8 @@ + #include "tpm2_systemdeps.h" + #include "tpm2_tool.h" + #include "tpm2_eventlog.h" ++#include "tss2_common.h" ++#include "tss2_mu.h" + + typedef struct tpm2_verifysig_ctx tpm2_verifysig_ctx; + struct tpm2_verifysig_ctx { +@@ -46,12 +49,14 @@ struct tpm2_verifysig_ctx { + char *eventlog_path; + tpm2_loaded_object key_context_object; + const char *pcr_selection_string; ++ tpm2_convert_pcrs_output_fmt pcrs_format; + }; + + static tpm2_verifysig_ctx ctx = { + .halg = TPM2_ALG_SHA256, + .msg_hash = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer), + .pcr_hash = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer), ++ .pcrs_format = pcrs_output_format_serialized, + }; + + static bool compare_pcr_selection(TPML_PCR_SELECTION *attest_sel, TPML_PCR_SELECTION *pcr_sel) { +@@ -292,37 +297,97 @@ static bool parse_selection_data_from_selection_string(FILE *pcr_input, + + static bool parse_selection_data_from_file(FILE *pcr_input, + TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs) { ++ size_t j, i; + + // Import TPML_PCR_SELECTION structure to pcr outfile + if (fread(pcr_select, sizeof(TPML_PCR_SELECTION), 1, pcr_input) != 1) { + LOG_ERR("Failed to read PCR selection from file"); + return false; + } +- ++ pcr_select->count = le32toh(pcr_select->count); ++ for (i = 0; i < pcr_select->count; i++) { ++ pcr_select->pcrSelections[i].hash = le16toh(pcr_select->pcrSelections[i].hash); ++ } ++ + // Import PCR digests to pcr outfile + if (fread(&pcrs->count, sizeof(UINT32), 1, pcr_input) != 1) { + LOG_ERR("Failed to read PCR digests header from file"); + return false; + } + +- if (le64toh(pcrs->count) > ARRAY_LEN(pcrs->pcr_values)) { ++ pcrs->count = le64toh(pcrs->count); ++ ++ if (pcrs->count > ARRAY_LEN(pcrs->pcr_values)) { + LOG_ERR("Malformed PCR file, pcr count cannot be greater than %zu, got: %" PRIu64 " ", + ARRAY_LEN(pcrs->pcr_values), le64toh((UINT64)pcrs->count)); + return false; + } + +- size_t j; +- for (j = 0; j < le64toh(pcrs->count); j++) { ++ for (j = 0; j < pcrs->count; j++) { + if (fread(&pcrs->pcr_values[j], sizeof(TPML_DIGEST), 1, pcr_input) + != 1) { + LOG_ERR("Failed to read PCR digest from file"); + return false; + } ++ // Convert TPML_DIGEST from little endian to host endian. ++ pcrs->pcr_values[j].count = le32toh( pcrs->pcr_values[j].count); ++ for (i = 0; i < pcrs->pcr_values[j].count; i++) { ++ pcrs->pcr_values[j].digests[i].size = ++ le16toh(pcrs->pcr_values[j].digests[i].size); ++ } + } + + return true; + } + ++static bool parse_marshaled_selection_data(FILE *pcr_input, ++ TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs, unsigned long fsize) { ++ size_t i; ++ uint8_t *buffer = NULL; ++ UINT16 size = fsize; ++ size_t offset = 0; ++ TSS2_RC rc; ++ UINT32 count; ++ ++ buffer = malloc(fsize); ++ ++ if (!file_read_bytes_from_file(pcr_input, buffer, &size, ctx.pcr_file_path)) { ++ LOG_ERR("Failed to read PCR selection from file"); ++ return false; ++ } ++ ++ rc = Tss2_MU_TPML_PCR_SELECTION_Unmarshal(buffer, size, &offset, pcr_select); ++ if (rc) { ++ LOG_ERR("Failed unmarshal PCR selection."); ++ goto error; ++ } ++ rc = Tss2_MU_UINT32_Unmarshal(buffer, size, &offset, &count); ++ if (rc) { ++ LOG_ERR("Failed unmarshal number of PCR digest lists."); ++ goto error; ++ } ++ pcrs->count = count; ++ if (pcrs->count > ARRAY_LEN(pcrs->pcr_values)) { ++ LOG_ERR("Malformed PCR file, pcr count cannot be greater than %zu, got: %" PRIu64 " ", ++ ARRAY_LEN(pcrs->pcr_values), le64toh((UINT64)pcrs->count)); ++ return false; ++ } ++ ++ for (i = 0; i < pcrs->count; i++) { ++ rc = Tss2_MU_TPML_DIGEST_Unmarshal(buffer, size, &offset, ++ &pcrs->pcr_values[i]); ++ if (rc) { ++ LOG_ERR("Failed unmarshal PCR digest list."); ++ goto error; ++ } ++ } ++ return true; ++ ++ error: ++ free(buffer); ++ return false; ++} ++ + static bool pcrs_from_file(const char *pcr_file_path, + TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs) { + +@@ -346,9 +411,16 @@ static bool pcrs_from_file(const char *pcr_file_path, + } + + if (!ctx.pcr_selection_string) { +- result = parse_selection_data_from_file(pcr_input, pcr_select, pcrs); +- if (!result) { ++ if (ctx.pcrs_format == pcrs_output_format_marshaled) { ++ result = parse_marshaled_selection_data(pcr_input, pcr_select, pcrs, size); ++ if (!result) { + goto out; ++ } ++ } else { ++ result = parse_selection_data_from_file(pcr_input, pcr_select, pcrs); ++ if (!result) { ++ goto out; ++ } + } + } else { + result = parse_selection_data_from_selection_string(pcr_input, +@@ -471,20 +543,20 @@ static tool_rc init(void) { + goto err; + } + +- if (le32toh(pcr_select.count) > TPM2_NUM_PCR_BANKS) ++ if (pcr_select.count > TPM2_NUM_PCR_BANKS) + goto err; + + UINT32 i; +- for (i = 0; i < le32toh(pcr_select.count); i++) +- if (le16toh(pcr_select.pcrSelections[i].hash) == TPM2_ALG_ERROR) ++ for (i = 0; i < pcr_select.count; i++) ++ if (pcr_select.pcrSelections[i].hash == TPM2_ALG_ERROR) + goto err; + +- if (!tpm2_openssl_hash_pcr_banks_le(ctx.halg, &pcr_select, pcrs, ++ if (!tpm2_openssl_hash_pcr_banks(ctx.halg, &pcr_select, pcrs, + &ctx.pcr_hash)) { + LOG_ERR("Failed to hash PCR values related to quote!"); + goto err; + } +- if (!pcr_print_pcr_struct_le(&pcr_select, pcrs)) { ++ if (!pcr_print_pcr_struct(&pcr_select, pcrs)) { + LOG_ERR("Failed to print PCR values related to quote!"); + goto err; + } +@@ -620,7 +692,10 @@ static bool on_option(char key, char *value) { + } + break; + case 'F': +- LOG_WARN("DEPRECATED: Format ignored"); ++ ctx.pcrs_format = tpm2_convert_pcrs_output_fmt_from_optarg(value); ++ if (ctx.pcrs_format == pcrs_output_format_err) { ++ return false; ++ } + break; + case 'q': + ctx.extra_data.size = sizeof(ctx.extra_data.buffer); +diff --git a/tools/tpm2_pcrread.c b/tools/tpm2_pcrread.c +index d070b2f3..675ce69e 100644 +--- a/tools/tpm2_pcrread.c ++++ b/tools/tpm2_pcrread.c +@@ -48,6 +48,10 @@ static tool_rc show_pcr_list_selected_values(ESYS_CONTEXT *esys_context, + success = pcr_fwrite_serialized(&ctx.pcr_selections, &ctx.pcrs, + ctx.output_file); + } ++ if (ctx.format == pcrs_output_format_marshaled) { ++ success = pcr_fwrite_marshaled(&ctx.pcr_selections, &ctx.pcrs, ++ ctx.output_file); ++ } + } + + return success ? tool_rc_success : tool_rc_general_error; +diff --git a/tools/tpm2_quote.c b/tools/tpm2_quote.c +index ceb63e54..3712bd3c 100644 +--- a/tools/tpm2_quote.c ++++ b/tools/tpm2_quote.c +@@ -64,6 +64,9 @@ static bool write_output_files(TPM2B_ATTEST *quoted, TPMT_SIGNATURE *signature) + } else if (ctx.pcrs_format == pcrs_output_format_values) { + res &= pcr_fwrite_values(&ctx.pcr_selections, &ctx.pcrs, + ctx.pcr_output); ++ } else if (ctx.pcrs_format == pcrs_output_format_marshaled) { ++ res &= pcr_fwrite_marshaled(&ctx.pcr_selections, &ctx.pcrs, ++ ctx.pcr_output); + } + } + +-- +2.51.0 + diff --git a/SOURCES/add_pregenerated_doc_2.patch b/SOURCES/add_pregenerated_doc_2.patch new file mode 100644 index 0000000..358cee1 --- /dev/null +++ b/SOURCES/add_pregenerated_doc_2.patch @@ -0,0 +1,96 @@ + man/man1/tpm2_checkquote.1 | 15 +++- + man/man1/tpm2_pcrread.1 | 11 +-- + man/man1/tpm2_quote.1 | 11 +-- + +diff --git a/man/man1/tpm2_checkquote.1 b/man/man1/tpm2_checkquote.1 +index 5909f4dc..11f335ac 100644 +--- a/man/man1/tpm2_checkquote.1 ++++ b/man/man1/tpm2_checkquote.1 +@@ -70,10 +70,21 @@ Can either be a hex string or path. + This is typically used to add a nonce against replay attacks. + .RE + .IP \[bu] 2 +-\f[B]\-F\f[R], \f[B]\-\-format\f[R]=\f[I]FORMAT\f[R]: ++\f[B]\-F\f[R], \f[B]\-\-pcrs_format\f[R]=\f[I]FORMAT\f[R]: + .RS 2 + .PP +-\f[B]DEPRECATED\f[R] and \f[B]IGNORED \f[R] as it\[cq]s superfluous. ++Format selection for the binary blob in the PCR output file. ++`values' will output a binary blob of the PCR values. ++`serialized' will write or read a binary blob of the PCR values in the ++form of serialized data structure in little endian format. ++`marshaled' will will read or write a binary blob in the binary format ++used by the TSS2 marshaling and unmarshaling functions. ++If marshaled is used the data is serialized in the following order: ++TPML_PCR_SELECTION, UINT32 (the number of following TPML_DIGEST ++elements) TPML_DIGEST [number of TPML_DIGEST elements]. ++Optional. ++If \-l is provided `normalized' will be used. ++Otherwise `serialized' is the default. + .RE + .SS References + .SH Algorithm Specifiers +diff --git a/man/man1/tpm2_pcrread.1 b/man/man1/tpm2_pcrread.1 +index a20b4efd..1c358a29 100644 +--- a/man/man1/tpm2_pcrread.1 ++++ b/man/man1/tpm2_pcrread.1 +@@ -56,10 +56,13 @@ The output file to write the PCR values in binary format, optional. + .PP + Format selection for the binary blob in the PCR output file. + `values' will output a binary blob of the PCR values. +-`serialized' will output a binary blob of the PCR values in the form of +-serialized data structure in little endian format. +-Optional. +-Default is `values'. ++`serialized' will write or read a binary blob of the PCR values in the ++form of serialized data structure in little endian format. ++`marshaled' will will read or write a binary blob in the binary format ++used by the TSS2 marshaling and unmarshaling functions. ++If marshaled is used the data is serialized in the following order: ++TPML_PCR_SELECTION, UINT32 (the number of following TPML_DIGEST ++elements) TPML_DIGEST [number of TPML_DIGEST elements]. + .RE + .SH COMMON OPTIONS + .PP +diff --git a/man/man1/tpm2_quote.1 b/man/man1/tpm2_quote.1 +index 087fa8a0..406bb09b 100644 +--- a/man/man1/tpm2_quote.1 ++++ b/man/man1/tpm2_quote.1 +@@ -66,10 +66,13 @@ PCR output file, optional, records the list of PCR values as defined by + .PP + Format selection for the binary blob in the PCR output file. + `values' will output a binary blob of the PCR values. +-`serialized' will output a binary blob of the PCR values in the form of +-serialized data structure in little endian format. +-Optional. +-Default is `serialized'. ++`serialized' will write or read a binary blob of the PCR values in the ++form of serialized data structure in little endian format. ++`marshaled' will will read or write a binary blob in the binary format ++used by the TSS2 marshaling and unmarshaling functions. ++If marshaled is used the data is serialized in the following order: ++TPML_PCR_SELECTION, UINT32 (the number of following TPML_DIGEST ++elements) TPML_DIGEST [number of TPML_DIGEST elements]. + .RE + .IP \[bu] 2 + \f[B]\-q\f[R], \f[B]\-\-qualification\f[R]=\f[I]HEX_STRING_OR_PATH\f[R]: +diff --git a/man/tpm2_checkquote.1.md b/man/tpm2_checkquote.1.md +index 34ab8925..635f9555 100644 +--- a/man/tpm2_checkquote.1.md ++++ b/man/tpm2_checkquote.1.md +@@ -53,9 +53,10 @@ must be specified using the **-l** option to interpret the PCR data. + Qualification data for the quote. Can either be a hex string or path. + This is typically used to add a nonce against replay attacks. + +- * **-F**, **\--format**=_FORMAT_: ++[PCR output file format specifiers](common/pcrs_format.md) ++ If -l is provided 'normalized' will be used. Otherwise 'serialized' is ++ the default. + +- **DEPRECATED** and **IGNORED ** as it's superfluous. + + ## References + +-- +2.51.0 + diff --git a/SPECS/tpm2-tools.spec b/SPECS/tpm2-tools.spec index a01804c..1dc9aae 100644 --- a/SPECS/tpm2-tools.spec +++ b/SPECS/tpm2-tools.spec @@ -2,7 +2,7 @@ Name: tpm2-tools Version: 5.2 -Release: 6%{?candidate:.%{candidate}}%{?dist} +Release: 7%{?candidate:.%{candidate}}%{?dist} Summary: A bunch of TPM testing toolS build upon tpm2-tss License: BSD @@ -54,6 +54,10 @@ Patch305: 0005-Support-high-range-NV-indexes-in-getekcert.patch Patch306: 0006-tpm2_getrandom-Fix-force-parameter.patch Patch307: 0007-tpm2_eventlog_yaml.c-Fix-output-of-BlobDescription.patch Patch308: 0008-tpm2_encode-Fix-setting-emptyAuth-in-generated-pem-f.patch +Patch401: 0001-Fix-issue-with-reading-NV-indexes.patch +Patch402: 0001-tpm2_eventlog-Fix-parsing-on-big-endian-systems.patch +Patch403: 0001-tpm2_quote-checkquote-Fix-usage-of-little-endian-ser.patch +Patch404: add_pregenerated_doc_2.patch BuildRequires: git BuildRequires: make @@ -86,6 +90,7 @@ autoreconf -i # initialization to zero is appropriate/safe. So LTO is disabled for now. %define _lto_cflags %{nil} %configure --prefix=/usr --disable-static --disable-silent-rules CFLAGS="%{optflags} -Wno-error=deprecated-declarations" +touch man/man1/* %make_build %install @@ -105,6 +110,12 @@ autoreconf -i %{_mandir}/man1/tss2_*.1.gz %changelog +* Thu Sep 18 2025 Štěpán Horáček - 5.2-7 +- Fix endianity issues. + Resolves: RHEL-79885 + Resolves: RHEL-94933 + Resolves: RHEL-113400 + * Wed Apr 24 2025 Štěpán Horáček - 5.2-6 - Backport upstream fixes. Resolves: RHEL-72772