import CS tpm2-tools-5.2-7.el9

This commit is contained in:
AlmaLinux RelEng Bot 2026-03-30 11:09:41 -04:00
parent 3d2f581a84
commit fab956c775
5 changed files with 1495 additions and 1 deletions

View File

@ -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?=
<shoracek@redhat.com>
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 <shoracek@redhat.com>
---
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

View File

@ -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?=
<shoracek@redhat.com>
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 <shoracek@redhat.com>
---
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 <inttypes.h>
#include <stdlib.h>
#include <string.h>
+#include <endian.h>
#include <tss2/tss2_tpm2_types.h>
@@ -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 <stdlib.h>
#include <string.h>
#include <uchar.h>
+#include <endian.h>
#include <tss2/tss2_tpm2_types.h>
@@ -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

View File

@ -0,0 +1,519 @@
From 9764e1cff9fd113154272dd2aa40700bd9b9956b Mon Sep 17 00:00:00 2001
From: Juergen Repp <juergen_repp@web.de>
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 <juergen_repp@web.de>
---
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 <endian.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
@@ -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

View File

@ -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

View File

@ -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 <shoracek@redhat.com> - 5.2-7
- Fix endianity issues.
Resolves: RHEL-79885
Resolves: RHEL-94933
Resolves: RHEL-113400
* Wed Apr 24 2025 Štěpán Horáček <shoracek@redhat.com> - 5.2-6
- Backport upstream fixes.
Resolves: RHEL-72772