Backport upstream fixes

Resolves: RHEL-164796

Signed-off-by: Štěpán Horáček <shoracek@redhat.com>
This commit is contained in:
Štěpán Horáček 2026-05-25 20:52:48 +02:00
parent 64018ac5ab
commit 8b31466bc1
31 changed files with 4309 additions and 4 deletions

View File

@ -0,0 +1,849 @@
From b294a9eebae6be1563526c017cca1b3de71944dc 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 01/30] 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 | 73 ++++++-------
lib/tpm2_eventlog_yaml.c | 219 ++++++++++++++++++++-------------------
2 files changed, 147 insertions(+), 145 deletions(-)
diff --git a/lib/tpm2_eventlog.c b/lib/tpm2_eventlog.c
index 70ae35fe..40148f8b 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");
@@ -122,13 +123,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;
@@ -146,7 +147,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;
}
@@ -158,7 +159,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;
}
@@ -171,7 +172,7 @@ bool parse_event2body(TCG_EVENT2 const *event, UINT32 type) {
const char hcrtm_data[] = "HCRTM";
size_t len = strlen(hcrtm_data);
BYTE *data = (BYTE *)event->Event;
- if (event->EventSize != len ||
+ if (le32toh(event->EventSize) != len ||
strncmp((const char *)data, hcrtm_data, len)) {
LOG_ERR("HCRTM Event Data MUST be the string: \"%s\"", hcrtm_data);
return false;
@@ -201,9 +202,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;
@@ -217,11 +218,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;
}
@@ -238,19 +239,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;
}
@@ -289,14 +290,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;
@@ -467,12 +468,12 @@ 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;
}
/* Handle StartupLocality in replay for PCR0 */
- if (!found_hcrtm && eventhdr->EventType == EV_NO_ACTION && eventhdr->PCRIndex == 0) {
+ if (!found_hcrtm && le32toh(eventhdr->EventType) == EV_NO_ACTION && le32toh(eventhdr->PCRIndex) == 0) {
if (event_size < sizeof(EV_NO_ACTION_STRUCT)) {
LOG_ERR("EventSize is too small\n");
return false;
@@ -496,13 +497,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;
}
@@ -514,7 +515,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;
}
@@ -533,12 +534,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;
}
@@ -552,29 +553,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;
}
@@ -582,18 +583,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;
@@ -614,7 +615,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 c9c87efb..0f86aca0 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>
@@ -46,7 +47,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]);
}
@@ -140,9 +141,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;
}
@@ -152,8 +153,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;
}
@@ -167,7 +168,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;
@@ -187,7 +188,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);
@@ -196,21 +197,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);
@@ -238,7 +239,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) {
@@ -260,7 +261,7 @@ static bool yaml_uefi_post_code(const TCG_EVENT2* const event) {
static bool yaml_uefi_hcrtm(const TCG_EVENT2* const event) {
- const size_t len = event->EventSize;
+ const size_t len = le32toh(event->EventSize);
const char* const data = (const char *) event->Event;
tpm2_tool_output(" Event: |-\n"
@@ -494,28 +495,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");
}
@@ -533,7 +534,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;
@@ -542,7 +543,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;
}
@@ -553,67 +554,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 {
@@ -628,15 +629,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 {
@@ -650,19 +651,19 @@ 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];
- if (data->VariableDataLength < sizeof(EFI_SIGNATURE_DATA)) {
+ le64toh(data->UnicodeNameLength)];
+ if (le64toh(data->VariableDataLength) < sizeof(EFI_SIGNATURE_DATA)) {
LOG_ERR("VariableDataLength is too short for EFI_SIGNATURE_DATA");
return false;
}
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",
@@ -674,25 +675,25 @@ static bool yaml_uefi_var(UEFI_VARIABLE_DATA *data, size_t size, UINT32 type,
tpm2_tool_output(" VariableData:\n");
UINT8 *description = (UINT8 *)&data->UnicodeName[
- data->UnicodeNameLength];
+ le64toh(data->UnicodeNameLength)];
return yaml_split_print_string(" ", "String",
- description, data->VariableDataLength);
+ description, le64toh(data->VariableDataLength));
}
} else if (type == EV_EFI_VARIABLE_BOOT || type == EV_EFI_VARIABLE_BOOT2) {
if ((strlen(ret) == NAME_BOOTORDER_LEN && strncmp(ret, NAME_BOOTORDER, NAME_BOOTORDER_LEN) == 0)) {
free(ret);
tpm2_tool_output(" VariableData:\n");
- if (data->VariableDataLength % 2 != 0) {
+ if (le64toh(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;
}
@@ -706,27 +707,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);
@@ -742,12 +743,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
@@ -767,8 +768,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;
}
@@ -793,8 +794,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;
@@ -832,17 +833,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);
@@ -892,24 +893,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);
@@ -927,9 +928,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);
@@ -968,9 +969,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;
}
@@ -979,8 +980,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:
@@ -989,23 +990,23 @@ 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);
case EV_EFI_HCRTM_EVENT:
return yaml_uefi_hcrtm(event);
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;
}
@@ -1071,9 +1072,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) {
@@ -1092,10 +1093,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) {
@@ -1105,9 +1106,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) {
@@ -1134,11 +1135,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.54.0

View File

@ -0,0 +1,32 @@
From 17100afa995900d11c54446acc850a67c2eaaec2 Mon Sep 17 00:00:00 2001
From: Juergen Repp <juergen_repp@web.de>
Date: Wed, 10 Sep 2025 11:44:02 +0200
Subject: [PATCH 02/30] man tpm2_policysigned: add parameter --raw-data
The parameter --raw-data which can be used to compute the hash
which must be signed was not documented.
Signed-off-by: Juergen Repp <juergen_repp@web.de>
---
man/tpm2_policysigned.1.md | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/man/tpm2_policysigned.1.md b/man/tpm2_policysigned.1.md
index 2f32d87d..498eb244 100644
--- a/man/tpm2_policysigned.1.md
+++ b/man/tpm2_policysigned.1.md
@@ -58,6 +58,11 @@ The optional TPM2 parameters being cpHashA, nonceTPM, policyRef and expiration.
The command parameter hash (cpHash), enforcing the TPM command to be
authorized as well as its handle and parameter values.
+* **\--raw-data**=_FILE_:
+
+ The raw data, generated based on the selected parameters, serves as the input
+ for computing the hash that must be signed.
+
* **\--ticket**=_FILE_:
The ticket file to record the authorization ticket structure.
--
2.54.0

View File

@ -0,0 +1,87 @@
From e9e1260a4cb5e97650de77d3bf16445a55884504 Mon Sep 17 00:00:00 2001
From: Juergen Repp <juergen_repp@web.de>
Date: Tue, 26 Aug 2025 10:01:49 +0200
Subject: [PATCH 03/30] tpm2_loadexternal: Add option rsa_exponent_zero
If TPM RSA keys are exported to PEM the exponent is set to 0x10001.
The option --rsa_exponent_zero is added to enable compatibility in the
computation of the key name if the TPM key is generated with
exponent zero.
Fixes: #3508
Signed-off-by: Juergen Repp <juergen_repp@web.de>
---
man/tpm2_loadexternal.1.md | 5 +++++
tools/tpm2_loadexternal.c | 17 ++++++++++++++---
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/man/tpm2_loadexternal.1.md b/man/tpm2_loadexternal.1.md
index 01d9bad3..7bf63957 100644
--- a/man/tpm2_loadexternal.1.md
+++ b/man/tpm2_loadexternal.1.md
@@ -112,6 +112,11 @@ It also saves a context file for future interactions with the object.
It mirrors the -passin option of OSSL and is known to support the pass,
file, env, fd and plain password formats of openssl.
(see *man(1) openssl*) for more.
+
+ * **-e**, **\--rsa_exponent_zero**:
+ Set the exponent of a public RSA key to zero, to enable compatibility
+ in the computation of the key name if the TPM key is generated with
+ exponent zero.
## References
diff --git a/tools/tpm2_loadexternal.c b/tools/tpm2_loadexternal.c
index 7a7809f7..bddc1b73 100644
--- a/tools/tpm2_loadexternal.c
+++ b/tools/tpm2_loadexternal.c
@@ -38,6 +38,8 @@ struct tpm_loadexternal_ctx {
TPM2B_SENSITIVE priv; /* Set the AUTH value for sensitive portion */
TPM2B_PUBLIC pub; /* Load the users specified public object if specified via -u*/
bool autoflush; /* Flush the object after creation of the ctx file */
+ bool rsa_exponent_zero; /* Set rsa exponent to zero to support name computation for
+ tpm2 keys with exponent zero. */
/*
* TSS Privkey related
*/
@@ -258,6 +260,11 @@ static tool_rc process_inputs(ESYS_CONTEXT *ectx) {
if (!result) {
return tool_rc_general_error;
}
+ if (ctx.pub.publicArea.type == TPM2_ALG_RSA && ctx.rsa_exponent_zero) {
+ ctx.pub.publicArea.parameters.rsaDetail.exponent = 0;
+ } else if (ctx.rsa_exponent_zero) {
+ LOG_WARN("Option --rsa_exponent_zero used for key which is no RSA key.");
+ }
}
} else {
LOG_ERR("Unkown internal state");
@@ -410,7 +417,10 @@ static bool on_option(char key, char *value) {
break;
case 'R':
ctx.autoflush = true;
- break;
+ break;
+ case 'e':
+ ctx.rsa_exponent_zero = true;
+ break;
}
return true;
@@ -431,10 +441,11 @@ static bool tpm2_tool_onstart(tpm2_options **opts) {
{ "name", required_argument, 0, 'n'},
{ "passin", required_argument, 0, 0 },
{ "cphash", required_argument, 0, 1 },
- { "autoflush", no_argument, 0, 'R' },
+ { "autoflush", no_argument, 0, 'R'},
+ { "rsa_exponent_zero", no_argument, 0, 'e'},
};
- *opts = tpm2_options_new("C:u:r:c:a:p:L:g:G:n:R", ARRAY_LEN(topts), topts,
+ *opts = tpm2_options_new("C:u:r:c:a:p:L:g:G:n:Re", ARRAY_LEN(topts), topts,
on_option, 0, 0);
return *opts != 0;
--
2.54.0

View File

@ -0,0 +1,539 @@
From 2f31c8e4f1ded994823468ab66d1e019b8b89cae 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 04/30] 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 | 6 ++
10 files changed, 192 insertions(+), 97 deletions(-)
diff --git a/lib/pcr.c b/lib/pcr.c
index 9aa5fbf0..134dc1a3 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)
@@ -232,58 +234,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) {
@@ -329,6 +279,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 c584c7d4..73463e18 100644
--- a/lib/pcr.h
+++ b/lib/pcr.h
@@ -44,18 +44,6 @@ typedef struct tpm2_forwards {
*/
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
@@ -100,6 +88,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,
tpm2_forwards *forwards);
diff --git a/lib/tpm2_convert.c b/lib/tpm2_convert.c
index d3a30eb2..6c922993 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 be14602c..2964d3c3 100644
--- a/lib/tpm2_openssl.h
+++ b/lib/tpm2_openssl.h
@@ -97,24 +97,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/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
diff --git a/tools/misc/tpm2_checkquote.c b/tools/misc/tpm2_checkquote.c
index 498dffbc..0f20ad96 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,
};
/**
@@ -340,37 +345,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) {
@@ -394,9 +459,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,
@@ -519,20 +591,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;
}
@@ -668,7 +740,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 4248cbef..108586a6 100644
--- a/tools/tpm2_pcrread.c
+++ b/tools/tpm2_pcrread.c
@@ -89,6 +89,10 @@ static tool_rc process_outputs(ESYS_CONTEXT *ectx) {
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 c0758ff7..a7a20e1c 100644
--- a/tools/tpm2_quote.c
+++ b/tools/tpm2_quote.c
@@ -105,6 +105,12 @@ static tool_rc write_output_files(void) {
if (!result) {
is_file_op_success = result;
}
+ } else if (ctx.pcrs_format == pcrs_output_format_marshaled) {
+ result = pcr_fwrite_marshaled(&ctx.pcr_selections, &ctx.pcrs,
+ ctx.pcr_output);
+ if (!result) {
+ is_file_op_success = result;
+ }
}
}
--
2.54.0

View File

@ -0,0 +1,93 @@
From 3e6cba1e5c2b8cdb03fd86e419081e4b9a5c17fa Mon Sep 17 00:00:00 2001
From: Juergen Repp <juergen_repp@web.de>
Date: Wed, 22 Oct 2025 12:57:18 +0200
Subject: [PATCH 05/30] tpm2_makecredential: Fix usage of name parameter.
The man page for tpm2_makecredential states that the -name parameter
can be a file. However, a hex string of the name is expected. Similar
to the procedure used with tpm2_certifycreation, a file with the name
or a hex string can now be passed.
Fixes: #3274
Signed-off-by: Juergen Repp <juergen_repp@web.de>
---
man/tpm2_makecredential.1.md | 5 +++--
test/integration/tests/makecredential.sh | 5 +++++
tools/tpm2_makecredential.c | 12 ++++++++----
3 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/man/tpm2_makecredential.1.md b/man/tpm2_makecredential.1.md
index e10d4a92..18896690 100644
--- a/man/tpm2_makecredential.1.md
+++ b/man/tpm2_makecredential.1.md
@@ -55,9 +55,10 @@ TCTI option.
The secret which will be protected by the key derived from the random seed. It can be specified as a file or passed from stdin.
- * **-n**, **\--name**=_FILE_:
+ * **-n**, **\--name**=_FILE\_OR\_HEX_:
- The name of the key for which certificate is to be created.
+ The name of the key for which certificate is to be created. Can either be
+ a path or hex string.
* **-o**, **\--credential-blob**=_FILE_:
diff --git a/test/integration/tests/makecredential.sh b/test/integration/tests/makecredential.sh
index 783422bf..1a26962a 100644
--- a/test/integration/tests/makecredential.sh
+++ b/test/integration/tests/makecredential.sh
@@ -14,6 +14,7 @@ output_ek_pub=ek_pub.out
output_ak_pub=ak_pub.out
output_ak_pub_name=ak_name_pub.out
output_mkcredential=mkcredential.out
+output_mkcredential2=mkcredentiali2.out
cleanup() {
rm -f $output_ek_pub $output_ak_pub $output_ak_pub_name \
@@ -45,6 +46,10 @@ Loadkeyname=`cat $output_ak_pub_name | xxd -p -c $file_size`
tpm2 makecredential -Q -u $output_ek_pub -s $file_input_data -n $Loadkeyname \
-o $output_mkcredential
+# Check usage of name file instead of hex string
+tpm2 makecredential -Q -u $output_ek_pub -s $file_input_data -n $output_ak_pub_name \
+-o $output_mkcredential2
+
# use no tpm backend
tpm2 makecredential -T none -Q -u $output_ek_pub -s $file_input_data \
-n $Loadkeyname -o $output_mkcredential
diff --git a/tools/tpm2_makecredential.c b/tools/tpm2_makecredential.c
index ae2af991..f7ce24fa 100644
--- a/tools/tpm2_makecredential.c
+++ b/tools/tpm2_makecredential.c
@@ -203,6 +203,7 @@ static tool_rc make_credential_and_save(ESYS_CONTEXT *ectx) {
static bool on_option(char key, char *value) {
+ tool_rc rc;
switch (key) {
case 'u':
if (ctx.flags.e) {
@@ -226,12 +227,15 @@ static bool on_option(char key, char *value) {
break;
case 'n':
ctx.object_name.size = BUFFER_SIZE(TPM2B_NAME, name);
- int q;
- if ((q = tpm2_util_hex_to_byte_structure(value, &ctx.object_name.size,
- ctx.object_name.name)) != 0) {
- LOG_ERR("FAILED: %d", q);
+ rc = tpm2_util_bin_from_hex_or_file(value,
+ &ctx.object_name.size, ctx.object_name.name) ?
+ tool_rc_success : tool_rc_general_error;
+
+ if (rc != tool_rc_success) {
+ LOG_ERR("Could not load name data");
return false;
}
+
ctx.flags.n = 1;
break;
case 'o':
--
2.54.0

View File

@ -0,0 +1,51 @@
From ceadf429e5f774cd40f96894fea28d32ba18e384 Mon Sep 17 00:00:00 2001
From: Dimitrios Siganos <dimitris@siganos.org>
Date: Sun, 9 Nov 2025 11:41:34 +0000
Subject: [PATCH 06/30] tpm2_checkquote: Fix indentation in
parse_marshaled_selection_data
Signed-off-by: Dimitrios Siganos <dimitris@siganos.org>
---
tools/misc/tpm2_checkquote.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/tools/misc/tpm2_checkquote.c b/tools/misc/tpm2_checkquote.c
index 0f20ad96..bdc54240 100644
--- a/tools/misc/tpm2_checkquote.c
+++ b/tools/misc/tpm2_checkquote.c
@@ -421,19 +421,19 @@ static bool parse_marshaled_selection_data(FILE *pcr_input,
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;
+ 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,
--
2.54.0

View File

@ -0,0 +1,30 @@
From 3d303cc0eac7d0e57557924964ea795da2fb4c3e Mon Sep 17 00:00:00 2001
From: Dimitrios Siganos <dimitris@siganos.org>
Date: Sun, 9 Nov 2025 11:50:52 +0000
Subject: [PATCH 07/30] tpm2_checkquote: Fix missing error checking
The return of malloc was not checked
Signed-off-by: Dimitrios Siganos <dimitris@siganos.org>
---
tools/misc/tpm2_checkquote.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tools/misc/tpm2_checkquote.c b/tools/misc/tpm2_checkquote.c
index bdc54240..648a383f 100644
--- a/tools/misc/tpm2_checkquote.c
+++ b/tools/misc/tpm2_checkquote.c
@@ -398,6 +398,10 @@ static bool parse_marshaled_selection_data(FILE *pcr_input,
UINT32 count;
buffer = malloc(fsize);
+ if (!buffer) {
+ LOG_ERR("OOM");
+ return false;
+ }
if (!file_read_bytes_from_file(pcr_input, buffer, &size, ctx.pcr_file_path)) {
LOG_ERR("Failed to read PCR selection from file");
--
2.54.0

View File

@ -0,0 +1,47 @@
From 9ae92d6db68bdf7f7691e84a6f95c3e064a2d96f Mon Sep 17 00:00:00 2001
From: Dimitrios Siganos <dimitris@siganos.org>
Date: Sun, 9 Nov 2025 11:53:21 +0000
Subject: [PATCH 08/30] tpm2_checkquote: Fix memory leaks, malloced buffer not
always freed
A buffer allocated with malloc was not freed in all possible paths,
not even in the success path.
Signed-off-by: Dimitrios Siganos <dimitris@siganos.org>
---
tools/misc/tpm2_checkquote.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/tools/misc/tpm2_checkquote.c b/tools/misc/tpm2_checkquote.c
index 648a383f..259d9c62 100644
--- a/tools/misc/tpm2_checkquote.c
+++ b/tools/misc/tpm2_checkquote.c
@@ -405,7 +405,7 @@ static bool parse_marshaled_selection_data(FILE *pcr_input,
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;
+ goto error;
}
rc = Tss2_MU_TPML_PCR_SELECTION_Unmarshal(buffer, size, &offset, pcr_select);
@@ -422,7 +422,7 @@ static bool parse_marshaled_selection_data(FILE *pcr_input,
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;
+ goto error;
}
for (i = 0; i < pcrs->count; i++) {
@@ -433,6 +433,7 @@ static bool parse_marshaled_selection_data(FILE *pcr_input,
goto error;
}
}
+ free(buffer);
return true;
error:
--
2.54.0

View File

@ -0,0 +1,178 @@
From ed18f6c4daee86f980e02564e6dd5ebc6e9daf25 Mon Sep 17 00:00:00 2001
From: Silas Meier <silas.meier@gapfruit.com>
Date: Fri, 14 Nov 2025 15:40:07 +0100
Subject: [PATCH 09/30] tpm2_makecredential: fix wrong tcg ek templates
The current implementation assumes low-range RSA and ECC keys. Therefore
if another key type is used, the default values are used and either the
tpm2_makecredential call or the tpm2_activatecredential call fails.
This commit reduces the required template values to a minimum and
supports additional key types.
Fixes: #3526
Signed-off-by: Silas Meier <silas.meier@gapfruit.com>
---
.../tests/activecredential_ecc_384.sh | 67 +++++++++++++++++++
tools/tpm2_makecredential.c | 50 +++++++-------
2 files changed, 93 insertions(+), 24 deletions(-)
create mode 100644 test/integration/tests/activecredential_ecc_384.sh
diff --git a/test/integration/tests/activecredential_ecc_384.sh b/test/integration/tests/activecredential_ecc_384.sh
new file mode 100644
index 00000000..dfeddad6
--- /dev/null
+++ b/test/integration/tests/activecredential_ecc_384.sh
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: BSD-3-Clause
+
+source helpers.sh
+
+cleanup() {
+ rm -f secret.data ek.pub ak.pub ak.name mkcred.out actcred.out ak.out \
+ ak.ctx session.ctx policyA.sha384 policyC.sha384
+
+ # Evict persistent handles, we want them to always succeed and never trip
+ # the onerror trap.
+ tpm2 evictcontrol -Q -C o -c 0x81010009 2>/dev/null || true
+
+ if [ "$1" != "no-shut-down" ]; then
+ shut_down
+ fi
+}
+trap cleanup EXIT
+
+start_up
+
+cleanup "no-shut-down"
+
+echo 12345678 > secret.data
+
+# Policies for high range EKs
+policy_a_hex="8bbf2266537c171cb56e403c4dc1d4b64f432611dc386e6f532050c3278c930e143e8bb1133824ccb431053871c6db53"
+echo -n "$policy_a_hex" | xxd -r -p > policyA.sha384
+policy_c_hex="d6032ce61f2fb3c240eb3cf6a33237ef2b6a16f4293c22b455e261cffd217ad5b4947c2d73e63005eed2dc2b3593d165"
+echo -n "$policy_c_hex" | xxd -r -p > policyC.sha384
+
+tpm2 createek -Q -c 0x81010009 -G ecc384 -u ek.pub
+
+tpm2 createak -C 0x81010009 -c ak.ctx -G rsa -g sha384 -s rsassa -u ak.pub \
+-n ak.name -p akpass> ak.out
+
+file_size=`ls -l ak.name | awk {'print $5'}`
+loaded_key_name=`cat ak.name | xxd -p -c $file_size` # Use -c in xxd so there is no line wrapping
+
+tpm2 readpublic -c 0x81010009 -o ek.pem -f pem -Q
+
+tpm2 makecredential -Q -u ek.pem -s secret.data -n $loaded_key_name \
+-o mkcred.out -G ecc --tcti=none
+
+# Test the secret data matches after credential activation process
+tpm2 startauthsession --policy-session -S session.ctx -g sha384
+tpm2 policysecret -S session.ctx -c e
+tpm2 policyor -S session.ctx sha384:policyA.sha384,policyC.sha384
+tpm2 activatecredential -Q -c ak.ctx -C 0x81010009 -i mkcred.out \
+-o actcred.out -p akpass -P"session:session.ctx"
+tpm2 flushcontext session.ctx
+
+diff actcred.out secret.data
+
+# Capture the yaml output and verify that its the same as the name output
+loaded_key_name_yaml=`python << pyscript
+from __future__ import print_function
+
+import yaml
+
+with open('ak.out', 'r') as f:
+ doc = yaml.safe_load(f)
+ print(doc['loaded-key']['name'])
+pyscript`
+
+test "$loaded_key_name_yaml" == "$loaded_key_name"
+
+exit 0
diff --git a/tools/tpm2_makecredential.c b/tools/tpm2_makecredential.c
index f7ce24fa..f91533e8 100644
--- a/tools/tpm2_makecredential.c
+++ b/tools/tpm2_makecredential.c
@@ -268,50 +268,52 @@ static bool tpm2_tool_onstart(tpm2_options **opts) {
}
static void set_default_TCG_EK_template(TPMI_ALG_PUBLIC alg) {
+ /* Values for RSA-2048 and ECC-256 keys. */
+ TPMI_AES_KEY_BITS bits = 128;
+ TPMI_ALG_HASH name_alg = TPM2_ALG_SHA256;
+
+ ctx.public.publicArea.objectAttributes = 0;
switch (alg) {
case TPM2_ALG_RSA:
+ if (ctx.public.publicArea.parameters.rsaDetail.keyBits > 2048) {
+ /* Values for RSA-3072 and RSA-4096 keys. */
+ bits = 256;
+ name_alg = TPM2_ALG_SHA384;
+ ctx.public.publicArea.objectAttributes = TPMA_OBJECT_USERWITHAUTH;
+ }
ctx.public.publicArea.parameters.rsaDetail.symmetric.algorithm =
TPM2_ALG_AES;
- ctx.public.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128;
+ ctx.public.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = bits;
ctx.public.publicArea.parameters.rsaDetail.symmetric.mode.aes =
TPM2_ALG_CFB;
- ctx.public.publicArea.parameters.rsaDetail.scheme.scheme = TPM2_ALG_NULL;
- ctx.public.publicArea.parameters.rsaDetail.keyBits = 2048;
- ctx.public.publicArea.parameters.rsaDetail.exponent = 0;
- ctx.public.publicArea.unique.rsa.size = 256;
break;
case TPM2_ALG_ECC:
+ if (ctx.public.publicArea.unique.ecc.x.size > 32) {
+ /* Values for ECC-384 keys. */
+ bits = 256;
+ name_alg = TPM2_ALG_SHA384;
+ ctx.public.publicArea.objectAttributes = TPMA_OBJECT_USERWITHAUTH;
+ }
+ if (ctx.public.publicArea.unique.ecc.x.size > 48) {
+ /* Values for ECC-512 keys. */
+ name_alg = TPM2_ALG_SHA512;
+ }
+
ctx.public.publicArea.parameters.eccDetail.symmetric.algorithm =
TPM2_ALG_AES;
- ctx.public.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128;
+ ctx.public.publicArea.parameters.eccDetail.symmetric.keyBits.aes = bits;
ctx.public.publicArea.parameters.eccDetail.symmetric.mode.sym =
TPM2_ALG_CFB;
- ctx.public.publicArea.parameters.eccDetail.scheme.scheme = TPM2_ALG_NULL;
- ctx.public.publicArea.parameters.eccDetail.curveID = TPM2_ECC_NIST_P256;
- ctx.public.publicArea.parameters.eccDetail.kdf.scheme = TPM2_ALG_NULL;
- ctx.public.publicArea.unique.ecc.x.size = 32;
- ctx.public.publicArea.unique.ecc.y.size = 32;
break;
}
- ctx.public.publicArea.objectAttributes =
+ ctx.public.publicArea.objectAttributes |=
TPMA_OBJECT_RESTRICTED | TPMA_OBJECT_ADMINWITHPOLICY
| TPMA_OBJECT_DECRYPT | TPMA_OBJECT_FIXEDTPM
| TPMA_OBJECT_FIXEDPARENT | TPMA_OBJECT_SENSITIVEDATAORIGIN;
- static const TPM2B_DIGEST auth_policy = {
- .size = 32,
- .buffer = {
- 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xB3, 0xF8, 0x1A, 0x90, 0xCC,
- 0x8D, 0x46, 0xA5, 0xD7, 0x24, 0xFD, 0x52, 0xD7, 0x6E, 0x06, 0x52,
- 0x0B, 0x64, 0xF2, 0xA1, 0xDA, 0x1B, 0x33, 0x14, 0x69, 0xAA
- }
- };
- TPM2B_DIGEST *authp = &ctx.public.publicArea.authPolicy;
- *authp = auth_policy;
-
- ctx.public.publicArea.nameAlg = TPM2_ALG_SHA256;
+ ctx.public.publicArea.nameAlg = name_alg;
}
static tool_rc process_input(tpm2_option_flags flags) {
--
2.54.0

View File

@ -0,0 +1,383 @@
From eed1dccb18cc92f08567988a9aaab4c3a279fceb Mon Sep 17 00:00:00 2001
From: Juergen Repp <juergen_repp@web.de>
Date: Tue, 25 Nov 2025 11:18:43 +0100
Subject: [PATCH 10/30] tools: Fix several clang-tidy errors
Several clang-tidy error related to conversion from uint to int,
rewind, and realloc were fixed.
Signed-off-by: Juergen Repp <juergen_repp@web.de>
---
lib/files.c | 7 +++++--
lib/pcr.c | 13 ++++++++-----
lib/tpm2_convert.c | 9 +++++----
lib/tpm2_eventlog_yaml.c | 16 ++++++++--------
lib/tpm2_identity_util.c | 8 +++++++-
lib/tpm2_openssl.c | 29 +++++++++++++++++++++++++----
lib/tpm2_util.c | 2 +-
tools/fapi/tss2_gettpm2object.c | 2 +-
tools/fapi/tss2_quote.c | 2 +-
tools/fapi/tss2_template.c | 10 +++++-----
tools/misc/tpm2_print.c | 6 +++++-
11 files changed, 71 insertions(+), 33 deletions(-)
diff --git a/lib/files.c b/lib/files.c
index dd93d7d3..1d6e579c 100644
--- a/lib/files.c
+++ b/lib/files.c
@@ -327,7 +327,10 @@ static bool load_tpm_context_file(FILE *fstream, TPMS_CONTEXT *context) {
LOG_WARN("The loaded tpm context does not appear to be in the proper "
"format, assuming old format, this will be converted on the "
"next save.");
- rewind(fstream);
+ if (fseek(fstream, 0, SEEK_SET) != 0) {
+ LOG_ERR("Could not rewind stream: %s", strerror(errno));
+ return false;
+ }
result = files_read_bytes(fstream, (UINT8 *) context, sizeof(*context));
if (!result) {
LOG_ERR("Could not load tpm context file");
@@ -400,7 +403,7 @@ static bool check_magic(FILE *fstream, bool seek_reset) {
bool match = magic == MAGIC;
if (seek_reset) {
- int rc = fseek(fstream, -sizeof(magic), SEEK_CUR);
+ int rc = fseek(fstream, -(long)sizeof(magic), SEEK_CUR);
if (rc != 0) {
LOG_ERR("fseek failed: %s", strerror(errno));
return false;
diff --git a/lib/pcr.c b/lib/pcr.c
index 134dc1a3..bcbd306c 100644
--- a/lib/pcr.c
+++ b/lib/pcr.c
@@ -74,22 +74,25 @@ static bool pcr_parse_list(const char *str, size_t len,
current_string = str;
str = memchr(current_string, ',', len);
if (str) {
- current_length = str - current_string;
+ ptrdiff_t diff = str - current_string;
+ if (diff > INT_MAX)
+ return false;
+ current_length = (int)diff;
str++;
len -= current_length + 1;
} else {
- current_length = len;
+ current_length = (int)len;
len = 0;
}
dgst = memchr(current_string, '=', current_length);
if (dgst && ((str == NULL) || (str && dgst < str))) {
- pcr_len = dgst - current_string;
+ pcr_len = (int)(dgst - current_string);
dgst++;
if (str) {
- dgst_len = str - dgst - 1;
+ dgst_len = (int)(str - dgst - 1);
} else {
- dgst_len = current_length - pcr_len - 1;
+ dgst_len = (int)(current_length - pcr_len - 1);
}
} else {
dgst = NULL;
diff --git a/lib/tpm2_convert.c b/lib/tpm2_convert.c
index 6c922993..6c975dd7 100644
--- a/lib/tpm2_convert.c
+++ b/lib/tpm2_convert.c
@@ -806,7 +806,7 @@ bool tpm2_base64_encode(BYTE *buffer, size_t buffer_length, char *base64) {
EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
EVP_EncodeInit(ctx);
- int rc = EVP_EncodeUpdate(ctx, out, &outl, buffer, buffer_length);
+ int rc = EVP_EncodeUpdate(ctx, out, &outl, buffer, (int)buffer_length);
if(rc < 0) {
LOG_ERR("EVP_DecodeUpdate failed with %d\n", rc);
EVP_ENCODE_CTX_free(ctx);
@@ -824,19 +824,20 @@ bool tpm2_base64_encode(BYTE *buffer, size_t buffer_length, char *base64) {
bool tpm2_base64_decode(char *base64, BYTE *buffer, size_t *buffer_length) {
- bool is_base64_bufferlen_valid = strlen(base64) > 1024 ? false : true;
+ size_t len = strlen(base64);
+ bool is_base64_bufferlen_valid = len > 1024 ? false : true;
if (!is_base64_bufferlen_valid) {
return false;
}
unsigned char base64u[1024];
- memcpy(base64u, base64, strlen(base64));
+ memcpy(base64u, base64, len);
EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
EVP_DecodeInit(ctx);
unsigned char out[1024];
int outl;
- int rc = EVP_DecodeUpdate(ctx, out, &outl, base64u, strlen(base64));
+ int rc = EVP_DecodeUpdate(ctx, out, &outl, base64u, (int)len);
if(rc < 0) {
LOG_ERR("EVP_DecodeUpdate failed with %d\n", rc);
EVP_ENCODE_CTX_free(ctx);
diff --git a/lib/tpm2_eventlog_yaml.c b/lib/tpm2_eventlog_yaml.c
index 0f86aca0..c6efdcd7 100644
--- a/lib/tpm2_eventlog_yaml.c
+++ b/lib/tpm2_eventlog_yaml.c
@@ -188,7 +188,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, le16toh(data[i].c), &st);
+ ret = c16rtomb(tmp, (int)le16toh(data[i].c), &st);
if (ret < 0) {
LOG_ERR("c16rtomb failed: %s", strerror(errno));
free(mbstr);
@@ -277,7 +277,7 @@ static bool yaml_uefi_hcrtm(const TCG_EVENT2* const event) {
#ifdef HAVE_EFIVAR_EFIVAR_H
char *yaml_devicepath(BYTE* dp, UINT64 dp_len) {
int ret;
- ret = efidp_format_device_path(NULL, 0, (const_efidp)dp, dp_len);
+ ret = (int)efidp_format_device_path(NULL, 0, (const_efidp)dp, (ssize_t)dp_len);
if (ret < 0) {
LOG_ERR("failed to allocate memory: %s\n", strerror(errno));
return NULL;
@@ -293,8 +293,8 @@ char *yaml_devicepath(BYTE* dp, UINT64 dp_len) {
}
/* The void* cast is a hack to support efivar versions < 38 */
- ret = efidp_format_device_path((void *)text_path,
- text_path_len, (const_efidp)dp, dp_len);
+ ret = (int)efidp_format_device_path((void *)text_path,
+ text_path_len, (const_efidp)dp, (ssize_t)dp_len);
if (ret < 0) {
free(text_path);
LOG_ERR("cannot parse device path\n");
@@ -349,7 +349,7 @@ char **yaml_split_escape_string(UINT8 const *description, size_t size)
len = size - i;
}
- tmp = realloc(lines, sizeof(char *) * (nlines + 2));
+ tmp = (char **)realloc(lines, sizeof(char *) * (nlines + 2));
if (!tmp) {
LOG_ERR("failed to allocate memory for description lines: %s\n",
strerror(errno));
@@ -420,7 +420,7 @@ char **yaml_split_escape_string(UINT8 const *description, size_t size)
}
if (escape == NULL) {
- lines[nlines][k++] = description[j];
+ lines[nlines][k++] = (char)description[j];
} else {
while (*escape) {
lines[nlines][k++] = *escape;
@@ -438,7 +438,7 @@ char **yaml_split_escape_string(UINT8 const *description, size_t size)
for (i = 0; lines != NULL && lines[i] != NULL; i++) {
free(lines[i]);
}
- free(lines);
+ free((char **)lines);
return NULL;
}
@@ -573,7 +573,7 @@ static bool yaml_uefi_var(UEFI_VARIABLE_DATA *data, size_t size, UINT32 type,
uint8_t *signature = (uint8_t *)slist +
sizeof(*slist) + le32toh(slist->SignatureHeaderSize);
- int signatures = signature_size / le32toh(slist->SignatureSize);
+ int signatures = (int)(signature_size / le32toh(slist->SignatureSize));
/* iterate through each EFI_SIGNATURE on the list */
int i;
for (i = 0; i < signatures; i++) {
diff --git a/lib/tpm2_identity_util.c b/lib/tpm2_identity_util.c
index fbf1e938..03cfd269 100644
--- a/lib/tpm2_identity_util.c
+++ b/lib/tpm2_identity_util.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause */
#include <stdbool.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -249,8 +250,13 @@ static bool aes_encrypt_buffers(TPMT_SYM_DEF_OBJECT *sym,
if (!b) {
continue;
}
+ size_t diff = total_len - offset;
+ if (diff > INT_MAX || l > INT_MAX) {
+ LOG_ERR("Size can't be converted to int");
+ return false;
+ }
- int output_len = total_len - offset;
+ int output_len = (int)diff;
rc = EVP_EncryptUpdate(ctx, &cipher_text->buffer[offset], &output_len,
b, l);
diff --git a/lib/tpm2_openssl.c b/lib/tpm2_openssl.c
index d2f07a7c..669475c2 100644
--- a/lib/tpm2_openssl.c
+++ b/lib/tpm2_openssl.c
@@ -466,7 +466,15 @@ static bool do_file(const char *path, char **pass) {
static bool do_fd(const char *passin, char **pass) {
char *end_ptr = NULL;
- int fd = strtoul(passin, &end_ptr, 0);
+ unsigned long tmp = strtoul(passin, &end_ptr, 0);
+
+ if (tmp > INT_MAX) {
+ LOG_ERR("Invalid fd (out of range), got: \"%s\"", passin);
+ return false;
+ }
+
+ int fd = (int)tmp;
+
if (passin[0] != '\0' && end_ptr[0] != '\0') {
LOG_ERR("Invalid fd, got: \"%s\"", passin);
return false;
@@ -793,6 +801,7 @@ static bool load_public_ECC_from_key(EVP_PKEY *key, TPM2B_PUBLIC *pub) {
goto out;
}
pp->curveID = curve_id;
+ unsigned int tmp;
/*
* Copy the X and Y coordinate data into the ECC unique field,
@@ -813,13 +822,25 @@ static bool load_public_ECC_from_key(EVP_PKEY *key, TPM2B_PUBLIC *pub) {
goto out;
}
- X->size = BN_bn2binpad(x, X->buffer, keysize);
+ tmp = BN_bn2binpad(x, X->buffer, (int)keysize);
+
+ if (tmp > INT_MAX) {
+ LOG_ERR("Invalid result of BN_bn2binpad");
+ return false;
+ }
+ X->size = tmp;
if (X->size != keysize) {
LOG_ERR("Error converting X point BN to binary");
goto out;
}
- Y->size = BN_bn2binpad(y, Y->buffer, keysize);
+ tmp = BN_bn2binpad(y, Y->buffer, (int)keysize);
+ if (tmp > INT_MAX) {
+ LOG_ERR("Invalid result of BN_bn2binpad");
+ return false;
+ }
+
+ Y->size = (int)tmp;
if (Y->size != keysize) {
LOG_ERR("Error converting Y point BN to binary");
goto out;
@@ -1073,7 +1094,7 @@ static bool load_private_ECC_from_key(EVP_PKEY *key, TPM2B_SENSITIVE *priv) {
goto out;
}
- p->size = BN_bn2binpad(b, p->buffer, priv_bytes);
+ p->size = BN_bn2binpad(b, p->buffer, (int)priv_bytes);
if (p->size != priv_bytes) {
goto out;
}
diff --git a/lib/tpm2_util.c b/lib/tpm2_util.c
index c489430d..17a9ca9f 100644
--- a/lib/tpm2_util.c
+++ b/lib/tpm2_util.c
@@ -188,7 +188,7 @@ int tpm2_util_hex_to_byte_structure(const char *input_string, UINT16 *byte_lengt
int i = 0;
if (input_string == NULL || byte_length == NULL || byte_buffer == NULL)
return -1;
- str_length = strlen(input_string);
+ str_length = (int)strlen(input_string);
if (str_length % 2)
return -2;
for (i = 0; i < str_length; i++) {
diff --git a/tools/fapi/tss2_gettpm2object.c b/tools/fapi/tss2_gettpm2object.c
index 07e816b7..48e80b7f 100644
--- a/tools/fapi/tss2_gettpm2object.c
+++ b/tools/fapi/tss2_gettpm2object.c
@@ -81,7 +81,7 @@ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) {
return 1;
}
- if (strcmp(ctx.data, "-")) {
+ if (strcmp(ctx.data, "-") != 0) {
if (!ctx.overwrite) {
FILE *fp = fopen(ctx.data, "rb");
if (fp) {
diff --git a/tools/fapi/tss2_quote.c b/tools/fapi/tss2_quote.c
index 250d4b2d..7ed8b591 100644
--- a/tools/fapi/tss2_quote.c
+++ b/tools/fapi/tss2_quote.c
@@ -141,7 +141,7 @@ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) {
/* Read qualifyingData file */
TSS2_RC r;
- uint8_t *qualifyingData = NULL;
+ void *qualifyingData = NULL;
size_t qualifyingDataSize = 0;
if (ctx.qualifyingData) {
r = open_read_and_close (ctx.qualifyingData,
diff --git a/tools/fapi/tss2_template.c b/tools/fapi/tss2_template.c
index ecec0f04..a01a1f5b 100644
--- a/tools/fapi/tss2_template.c
+++ b/tools/fapi/tss2_template.c
@@ -142,7 +142,7 @@ static tpm2_option_code tss2_handle_options (
case '?':
goto out;
default:
- if (!(*tool_opts)->callbacks.on_opt(c, optarg))
+ if (!(*tool_opts)->callbacks.on_opt((char)c, optarg))
goto out;
}
}
@@ -293,8 +293,8 @@ TSS2_RC sign_callback(
int cpy_size = 0;
if (strlen(publicKeyHint) > 0) {
const char* tmp = "the key corresponding to the key hint \"%s\" and";
- cpy_size = strlen(tmp) - 2 /* remove replaced %s */ +
- strlen(publicKeyHint);
+ cpy_size = (int)(strlen(tmp) - 2 /* remove replaced %s */ +
+ strlen(publicKeyHint));
rc = snprintf(publicKeyHintStr, cpy_size+1 /* add \0 */, tmp,
publicKeyHint);
if (rc != cpy_size){
@@ -311,8 +311,8 @@ TSS2_RC sign_callback(
"PEM-encoded public key\n");
return TSS2_FAPI_RC_GENERAL_FAILURE;
}
- cpy_size = strlen(tmp) - 2 /* remove replaced %s */ +
- strlen(publicKeyHintTmp);
+ cpy_size = (int)(strlen(tmp) - 2 /* remove replaced %s */ +
+ strlen(publicKeyHintTmp));
rc = snprintf(publicKeyHintStr, cpy_size+1 /* add \0 */, tmp,
publicKeyHintTmp);
if (rc != cpy_size){
diff --git a/tools/misc/tpm2_print.c b/tools/misc/tpm2_print.c
index faa5ac3a..3e5f5b68 100644
--- a/tools/misc/tpm2_print.c
+++ b/tools/misc/tpm2_print.c
@@ -4,6 +4,7 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
+#include <errno.h>
#include <tss2/tss2_esys.h>
#include <tss2/tss2_rc.h>
@@ -304,7 +305,10 @@ static bool print_TPMS_CONTEXT(FILE *fstream) {
if (!result) {
LOG_WARN("The loaded tpm context does not appear to be in the proper "
"format, assuming old format.");
- rewind(fstream);
+ if (fseek(fstream, 0, SEEK_SET) != 0) {
+ LOG_ERR("Could not rewind stream: %s", strerror(errno));
+ return false;
+ }
result = files_read_bytes(fstream, (UINT8 *) &context, sizeof(context));
if (!result) {
LOG_ERR("Could not load tpm context file");
--
2.54.0

View File

@ -0,0 +1,166 @@
From 1b9fb8b89fd4cc39aed530d9504b39cf8270f866 Mon Sep 17 00:00:00 2001
From: Juergen Repp <juergen_repp@web.de>
Date: Thu, 27 Nov 2025 19:48:08 +0100
Subject: [PATCH 11/30] tools: Fix wrong type usage of enums.
enums used as bitmask are now declared as <enum_type>_enum
the bitmaks is now declared with typedef unsigned int <enum_type>
Signed-off-by: Juergen Repp <juergen_repp@web.de>
---
lib/tpm2_alg_util.h | 34 ++++++++++++++-------------
lib/tpm2_openssl.h | 12 ++++++----
lib/tpm2_util.h | 6 +++--
tools/misc/tpm2_certifyX509certutil.c | 2 +-
tools/tpm2_getekcertificate.c | 24 ++++++++++---------
5 files changed, 43 insertions(+), 35 deletions(-)
diff --git a/lib/tpm2_alg_util.h b/lib/tpm2_alg_util.h
index ae5e3fbb..68ee1fdd 100644
--- a/lib/tpm2_alg_util.h
+++ b/lib/tpm2_alg_util.h
@@ -9,24 +9,26 @@
#include "tool_rc.h"
-typedef enum tpm2_alg_util_flags tpm2_alg_util_flags;
-enum tpm2_alg_util_flags {
- tpm2_alg_util_flags_none = 0,
- tpm2_alg_util_flags_hash = 1 << 0,
- tpm2_alg_util_flags_keyedhash = 1 << 1,
- tpm2_alg_util_flags_symmetric = 1 << 2,
- tpm2_alg_util_flags_asymmetric = 1 << 3,
- tpm2_alg_util_flags_kdf = 1 << 4,
- tpm2_alg_util_flags_mgf = 1 << 5,
- tpm2_alg_util_flags_sig = 1 << 6,
- tpm2_alg_util_flags_mode = 1 << 7,
- tpm2_alg_util_flags_base = 1 << 8,
- tpm2_alg_util_flags_misc = 1 << 9,
- tpm2_alg_util_flags_enc_scheme = 1 << 10,
- tpm2_alg_util_flags_rsa_scheme = 1 << 11,
- tpm2_alg_util_flags_any = ~0
+typedef enum tpm2_alg_util_flags_enum tpm2_alg_util_flags_enum;
+enum tpm2_alg_util_flags_enum {
+ tpm2_alg_util_flags_none = 0,
+ tpm2_alg_util_flags_hash = 1 << 0,
+ tpm2_alg_util_flags_keyedhash = 1 << 1,
+ tpm2_alg_util_flags_symmetric = 1 << 2,
+ tpm2_alg_util_flags_asymmetric = 1 << 3,
+ tpm2_alg_util_flags_kdf = 1 << 4,
+ tpm2_alg_util_flags_mgf = 1 << 5,
+ tpm2_alg_util_flags_sig = 1 << 6,
+ tpm2_alg_util_flags_mode = 1 << 7,
+ tpm2_alg_util_flags_base = 1 << 8,
+ tpm2_alg_util_flags_misc = 1 << 9,
+ tpm2_alg_util_flags_enc_scheme = 1 << 10,
+ tpm2_alg_util_flags_rsa_scheme = 1 << 11,
+ tpm2_alg_util_flags_any = ~0
};
+typedef unsigned int tpm2_alg_util_flags;
+
/**
* Convert a "nice-name" string to an algorithm id.
* @param name
diff --git a/lib/tpm2_openssl.h b/lib/tpm2_openssl.h
index 2964d3c3..3b44f089 100644
--- a/lib/tpm2_openssl.h
+++ b/lib/tpm2_openssl.h
@@ -113,13 +113,15 @@ bool tpm2_openssl_hash_pcr_banks(TPMI_ALG_HASH hashAlg,
bool tpm2_openssl_pcr_extend(TPMI_ALG_HASH halg, BYTE *pcr,
const BYTE *data, UINT16 length);
-typedef enum tpm2_openssl_load_rc tpm2_openssl_load_rc;
-enum tpm2_openssl_load_rc {
- lprc_error = 0, /* an error has occurred */
- lprc_private = 1 << 0, /* successfully loaded a private portion of object */
- lprc_public = 1 << 1, /* successfully loaded a public portion of object */
+typedef enum tpm2_openssl_load_rc_enum tpm2_openssl_load_rc_enum;
+enum tpm2_openssl_load_rc_eum {
+ lprc_error = 0, /* an error has occurred */
+ lprc_private = 1 << 0, /* successfully loaded a private portion of object */
+ lprc_public = 1 << 1, /* successfully loaded a public portion of object */
};
+typedef unsigned int tpm2_openssl_load_rc;
+
/**
* Helper routine for gathering if the loading status included a public
* portion of an object.
diff --git a/lib/tpm2_util.h b/lib/tpm2_util.h
index 04f96ad1..4d730364 100644
--- a/lib/tpm2_util.h
+++ b/lib/tpm2_util.h
@@ -435,8 +435,8 @@ char *tpm2_util_getenv(const char *name);
bool tpm2_util_env_yes(const char *name);
-typedef enum tpm2_handle_flags tpm2_handle_flags;
-enum tpm2_handle_flags {
+typedef enum tpm2_handle_flags_enum tpm2_handle_flags_enum;
+enum tpm2_handle_flags_enum {
TPM2_HANDLE_FLAGS_NONE = 0,
TPM2_HANDLE_FLAGS_O = 1 << 0,
TPM2_HANDLE_FLAGS_P = 1 << 1,
@@ -453,6 +453,8 @@ enum tpm2_handle_flags {
TPM2_HANDLE_ALL_W_PCR = 0x17F,
};
+typedef unsigned int tpm2_handle_flags;
+
/**
* Converts an option from the command line into a valid TPM handle, checking
* for errors and if the tool supports it based on flags settings.
diff --git a/tools/misc/tpm2_certifyX509certutil.c b/tools/misc/tpm2_certifyX509certutil.c
index 5eea08e8..85925572 100644
--- a/tools/misc/tpm2_certifyX509certutil.c
+++ b/tools/misc/tpm2_certifyX509certutil.c
@@ -192,7 +192,7 @@ static tool_rc generate_partial_X509() {
BIO *cert_out = BIO_new_file(ctx.out_path, "wb");
if (!cert_out) {
LOG_ERR("Can not create file %s", ctx.out_path);
- return -1;
+ return tool_rc_general_error;
}
X509_EXTENSION *extv3 = NULL;
diff --git a/tools/tpm2_getekcertificate.c b/tools/tpm2_getekcertificate.c
index cd2d86a3..961021cf 100644
--- a/tools/tpm2_getekcertificate.c
+++ b/tools/tpm2_getekcertificate.c
@@ -69,19 +69,21 @@ enum pubkey_enc_mode {
*
*/
-typedef enum ek_nv_index ek_nv_index;
-enum ek_nv_index {
- RSA_EK_CERT_NV_INDEX = 0x01C00002,
- ECC_EK_CERT_NV_INDEX = 0x01C0000A,
- RSA_2048_EK_CERT_NV_INDEX = 0x01C00012,
- RSA_3072_EK_CERT_NV_INDEX = 0x01C0001C,
- RSA_4096_EK_CERT_NV_INDEX = 0x01C0001E,
- ECC_NIST_P256_EK_CERT_NV_INDEX = 0x01C00014,
- ECC_NIST_P384_EK_CERT_NV_INDEX = 0x01C00016,
- ECC_NIST_P521_EK_CERT_NV_INDEX = 0x01C00018,
- ECC_SM2_P256_EK_CERT_NV_INDEX = 0x01C0001A,
+typedef enum ek_nv_index_enum ek_nv_index_enum;
+enum ek_nv_index_enum {
+ RSA_EK_CERT_NV_INDEX = 0x01C00002,
+ ECC_EK_CERT_NV_INDEX = 0x01C0000A,
+ RSA_2048_EK_CERT_NV_INDEX = 0x01C00012,
+ RSA_3072_EK_CERT_NV_INDEX = 0x01C0001C,
+ RSA_4096_EK_CERT_NV_INDEX = 0x01C0001E,
+ ECC_NIST_P256_EK_CERT_NV_INDEX = 0x01C00014,
+ ECC_NIST_P384_EK_CERT_NV_INDEX = 0x01C00016,
+ ECC_NIST_P521_EK_CERT_NV_INDEX = 0x01C00018,
+ ECC_SM2_P256_EK_CERT_NV_INDEX = 0x01C0001A,
};
+typedef unsigned int ek_nv_index;
+
#define EK_SERVER_INTEL "https://ekop.intel.com/ekcertservice/"
#define EK_SERVER_AMD "https://ftpm.amd.com/pki/aia/"
--
2.54.0

View File

@ -0,0 +1,33 @@
From 9bf3121b9567ef031608f72b042411e0cfb39ac4 Mon Sep 17 00:00:00 2001
From: Juergen Repp <juergen_repp@web.de>
Date: Wed, 17 Dec 2025 11:44:23 +0100
Subject: [PATCH 12/30] tpm2_eventlog: Extend pcrs using event EV_IPL.
For TPM2 PCR measurements made by systemd for each PE section of the UKI that is
defined by the UAPI.5 UKI Specification PCR 11 is used.
Addresses: #3511
Signed-off-by: Juergen Repp <juergen_repp@web.de>
---
lib/tpm2_eventlog.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lib/tpm2_eventlog.c b/lib/tpm2_eventlog.c
index 40148f8b..e6c94347 100644
--- a/lib/tpm2_eventlog.c
+++ b/lib/tpm2_eventlog.c
@@ -427,6 +427,11 @@ size_t i;
}
break;
+ /* For TPM2 PCR measurements made by systemd for each PE section of the UKI that is
+ defined by the UAPI.5 UKI Specification PCR 11 is used. */
+ case 11:
+ return true;
+
default:
LOG_WARN("Event %zu is unexectedly not extending either PCR 8, 9, 12 or 14", eventnum - 1);
return false;
--
2.54.0

View File

@ -0,0 +1,49 @@
From e37509f142eac4049f6f29473df3032e90ab9cc7 Mon Sep 17 00:00:00 2001
From: Juergen Repp <juergen_repp@web.de>
Date: Sat, 27 Dec 2025 21:03:04 +0100
Subject: [PATCH 13/30] tpm2_nvcertify: Set size if the --size parameter is not
specified.
The man page states: If not specified, the size of the data
as reported by the public portion of the index will be used.
But 0 was used if --size was not specified.
Also an error in the man page is fixed.
Fixes: #3538
Signed-off-by: Juergen Repp <juergen_repp@web.de>
---
man/tpm2_nvcertify.1.md | 2 +-
tools/tpm2_nvcertify.c | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/man/tpm2_nvcertify.1.md b/man/tpm2_nvcertify.1.md
index 08662d0e..d1a7aa6c 100644
--- a/man/tpm2_nvcertify.1.md
+++ b/man/tpm2_nvcertify.1.md
@@ -68,7 +68,7 @@ These options control the certification:
* **--attestation**=_FILE_:
- The attestation data of the type TPM2_CREATION_INFO signed with signing key.
+ The attestation data of the type TPMS_ATTEST signed with signing key.
* **\--cphash**=_FILE_
diff --git a/tools/tpm2_nvcertify.c b/tools/tpm2_nvcertify.c
index 72e60470..53729bb8 100644
--- a/tools/tpm2_nvcertify.c
+++ b/tools/tpm2_nvcertify.c
@@ -387,6 +387,10 @@ static tool_rc check_options(ESYS_CONTEXT *ectx, tpm2_option_flags flags) {
goto is_input_options_args_valid_out;
}
+ if (ctx.size == 0) {
+ ctx.size = nv_public->nvPublic.dataSize;
+ }
+
if (ctx.offset + ctx.size > nv_public->nvPublic.dataSize) {
LOG_ERR("Size to read at offset is bigger than nv index size");
rc = tool_rc_option_error;
--
2.54.0

View File

@ -0,0 +1,265 @@
From 79544d38a3c1500bbe7aa6b94f1cf25627720f0e Mon Sep 17 00:00:00 2001
From: Juergen Repp <juergen_repp@web.de>
Date: Wed, 14 Jan 2026 08:34:13 +0100
Subject: [PATCH 14/30] tpm2_create: Fix creation of ctx file if
TPM2_CreateLoaded is not available.
If the TPM2 command CreateLoaded is not available the creation of a ctx
file with tpm2_create was not possible. Now a TPM2_Create and TPM2_Load is
used to create a ctx file if CreateLoaded is not available.
Signed-off-by: Juergen Repp <juergen_repp@web.de>
---
lib/tpm2.c | 67 ++++++++++++++++++++++++++++++---------
lib/tpm2.h | 9 ++++--
lib/tpm2_capability.c | 73 +++++++++++++++++++++++++++++++++----------
tools/tpm2_create.c | 14 ++-------
4 files changed, 117 insertions(+), 46 deletions(-)
diff --git a/lib/tpm2.c b/lib/tpm2.c
index 6098f7a9..ca1227a5 100644
--- a/lib/tpm2.c
+++ b/lib/tpm2.c
@@ -2060,15 +2060,32 @@ tpm2_create_skip_esapi_call:
tool_rc tpm2_create_loaded(ESYS_CONTEXT *esys_context,
tpm2_loaded_object *parent_obj,
const TPM2B_SENSITIVE_CREATE *in_sensitive,
- const TPM2B_TEMPLATE *in_public, ESYS_TR *object_handle,
+ const TPM2B_PUBLIC *in_public, ESYS_TR *object_handle,
TPM2B_PRIVATE **out_private, TPM2B_PUBLIC **out_public,
TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash,
TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2,
ESYS_TR shandle3) {
-
+ TPM2B_TEMPLATE template = { .size = 0 };
+
TSS2_SYS_CONTEXT *sys_context = NULL;
+ bool create_loaded_exists;
tool_rc rc = tool_rc_success;
- if (cp_hash->size || rp_hash->size) {
+ size_t offset = 0;
+
+ tool_rc tmp_rc = tpm2_mu_tpmt_public_marshal(
+ &in_public->publicArea, &template.buffer[0],
+ sizeof(TPMT_PUBLIC), &offset);
+ if (tmp_rc != tool_rc_success) {
+ return tmp_rc;
+ }
+
+ template.size = offset;
+
+ rc = tpm2_check_cc(esys_context, TPM2_CC_CreateLoaded, &create_loaded_exists);
+ if (rc != tool_rc_success) {
+ return rc;
+ }
+ if ((cp_hash->size || rp_hash->size) && create_loaded_exists) {
rc = tpm2_getsapicontext(esys_context, &sys_context);
if(rc != tool_rc_success) {
@@ -2077,9 +2094,9 @@ tool_rc tpm2_create_loaded(ESYS_CONTEXT *esys_context,
}
}
- if (cp_hash->size) {
+ if (cp_hash->size && create_loaded_exists) {
TSS2_RC rval = Tss2_Sys_CreateLoaded_Prepare(sys_context,
- parent_obj->handle, in_sensitive, in_public);
+ parent_obj->handle, in_sensitive, &template);
if (rval != TPM2_RC_SUCCESS) {
LOG_PERR(Tss2_Sys_CreateLoaded_Prepare, rval);
return tool_rc_general_error;
@@ -2115,19 +2132,39 @@ tpm2_createloaded_free_name1:
return rc;
}
- TSS2_RC rval = Esys_CreateLoaded(esys_context, parent_obj->tr_handle,
- shandle1, shandle2, shandle3, in_sensitive, in_public,
+ if (create_loaded_exists) {
+ TSS2_RC rval = Esys_CreateLoaded(esys_context, parent_obj->tr_handle,
+ shandle1, shandle2, shandle3, in_sensitive, &template,
object_handle, out_private, out_public);
- if (rval != TSS2_RC_SUCCESS) {
- LOG_PERR(Esys_CreateLoaded, rval);
- return tool_rc_from_tpm(rval);
- }
+ if (rval != TSS2_RC_SUCCESS) {
+ LOG_PERR(Esys_CreateLoaded, rval);
+ return tool_rc_from_tpm(rval);
+ }
- if (rp_hash->size) {
- rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash,
- parameter_hash_algorithm);
+ if (rp_hash->size) {
+ rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash,
+ parameter_hash_algorithm);
+ }
+ } else {
+ TPML_PCR_SELECTION creationPCR = {
+ .count = 0,
+ };
+
+ TSS2_RC rval = Esys_Create(esys_context, parent_obj->tr_handle,
+ shandle1, shandle2, shandle3, in_sensitive, in_public,
+ NULL, &creationPCR, out_private, out_public, NULL, NULL, NULL);
+ if (rval != TSS2_RC_SUCCESS) {
+ LOG_PERR(Esys_CreateLoaded, rval);
+ return tool_rc_from_tpm(rval);
+ }
+ rval = Esys_Load(esys_context, parent_obj->tr_handle,
+ shandle1, shandle2, shandle3, *out_private,
+ *out_public, object_handle);
+ if (rval != TPM2_RC_SUCCESS) {
+ LOG_PERR(Esys_Load, rval);
+ return tool_rc_from_tpm(rval);
+ }
}
-
tpm2_createloaded_skip_esapi_call:
return rc;
}
diff --git a/lib/tpm2.h b/lib/tpm2.h
index 67940c0e..0dc826a4 100644
--- a/lib/tpm2.h
+++ b/lib/tpm2.h
@@ -64,8 +64,11 @@ tool_rc tpm2_sess_get_noncetpm(ESYS_CONTEXT *esys_context,
ESYS_TR session_handle, TPM2B_NONCE **nonce_tpm);
tool_rc tpm2_policy_restart(ESYS_CONTEXT *esys_context, ESYS_TR session_handle,
- ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3,
- TPM2B_DIGEST *cp_hash, TPMI_ALG_HASH parameter_hash_algorithm);
+ ESYS_TR shandle1, ESYS_TR shandle2,
+ ESYS_TR shandle3, TPM2B_DIGEST *cp_hash,
+ TPMI_ALG_HASH parameter_hash_algorithm);
+
+tool_rc tpm2_check_cc(ESYS_CONTEXT *ectx, uint32_t cc, bool *exists);
tool_rc tpm2_get_capability(ESYS_CONTEXT *esys_context, ESYS_TR shandle1,
ESYS_TR shandle2, ESYS_TR shandle3, TPM2_CAP capability,
@@ -212,7 +215,7 @@ tool_rc tpm2_create(ESYS_CONTEXT *esys_context, tpm2_loaded_object *parent_obj,
tool_rc tpm2_create_loaded(ESYS_CONTEXT *esys_context,
tpm2_loaded_object *parent_obj,
const TPM2B_SENSITIVE_CREATE *in_sensitive,
- const TPM2B_TEMPLATE *in_public, ESYS_TR *object_handle,
+ const TPM2B_PUBLIC *in_public, ESYS_TR *object_handle,
TPM2B_PRIVATE **out_private, TPM2B_PUBLIC **out_public,
TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash,
TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2,
diff --git a/lib/tpm2_capability.c b/lib/tpm2_capability.c
index dca35e5a..9ca73c01 100644
--- a/lib/tpm2_capability.c
+++ b/lib/tpm2_capability.c
@@ -5,27 +5,68 @@
#include <string.h>
#include "log.h"
+#include "tool_rc.h"
#include "tpm2.h"
#include "tpm2_capability.h"
-#define APPEND_CAPABILITY_INFORMATION(capability, field, subfield, max_count) \
- if (fetched_data->data.capability.count > max_count - property_count) { \
- fetched_data->data.capability.count = max_count - property_count; \
- } \
-\
- memmove(&(*capability_data)->data.capability.field[property_count], \
- fetched_data->data.capability.field, \
- fetched_data->data.capability.count * sizeof(fetched_data->data.capability.field[0])); \
- property_count += fetched_data->data.capability.count; \
-\
- (*capability_data)->data.capability.count = property_count; \
-\
- if (more_data && property_count < count && fetched_data->data.capability.count) { \
- property = (*capability_data)->data.capability.field[property_count - 1]subfield + 1; \
- } else { \
- more_data = false; \
+#define APPEND_CAPABILITY_INFORMATION(capability, field, subfield, max_count) \
+ if (fetched_data->data.capability.count > max_count - property_count) { \
+ fetched_data->data.capability.count = max_count - property_count; \
+ } \
+ \
+ memmove(&(*capability_data)->data.capability.field[property_count], \
+ fetched_data->data.capability.field, \
+ fetched_data->data.capability.count * \
+ sizeof(fetched_data->data.capability.field[0])); \
+ property_count += fetched_data->data.capability.count; \
+ \
+ (*capability_data)->data.capability.count = property_count; \
+ \
+ if (more_data && property_count < count && \
+ fetched_data->data.capability.count) { \
+ property = (*capability_data) \
+ ->data.capability.field[property_count - 1] subfield + \
+ 1; \
+ } else { \
+ more_data = false; \
+ }
+
+tool_rc tpm2_check_cc(ESYS_CONTEXT *ectx, uint32_t cc, bool *exists) {
+ TPMI_YES_NO more_data = TPM2_NO;
+ TPMS_CAPABILITY_DATA *cap = NULL;
+ uint32_t count = 1;
+
+
+ TSS2_RC rc = Esys_GetCapability(
+ ectx,
+ ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+ TPM2_CAP_COMMANDS,
+ cc,
+ count,
+ &more_data,
+ &cap
+ );
+
+ if (rc != TSS2_RC_SUCCESS) {
+ LOG_ERR("Esys_GetCapability(TPM2_CAP_COMMANDS, property=0x%08" PRIX32 " failed: 0x%x",
+ cc, rc);
+ return tool_rc_general_error;
}
+ const TPML_CCA *cmds = &cap->data.command;
+
+ if (cmds->count == 1 && (cmds->commandAttributes[0] & 0xffff) == cc) {
+ Esys_Free(cap);
+ *exists = true;
+ return tool_rc_success;
+ }
+
+ Esys_Free(cap);
+ *exists = false;
+ return tool_rc_success;
+}
+
+
tool_rc tpm2_capability_get_ex(ESYS_CONTEXT *ectx, TPM2_CAP capability,
UINT32 property, UINT32 count, bool ignore_more_data,
TPMS_CAPABILITY_DATA **capability_data) {
diff --git a/tools/tpm2_create.c b/tools/tpm2_create.c
index cf25137a..39bbc935 100644
--- a/tools/tpm2_create.c
+++ b/tools/tpm2_create.c
@@ -134,19 +134,9 @@ static tool_rc create(ESYS_CONTEXT *ectx) {
/* TPM2_CC_CreateLoaded */
if (ctx.is_createloaded) {
- size_t offset = 0;
- TPM2B_TEMPLATE template = { .size = 0 };
- tool_rc tmp_rc = tpm2_mu_tpmt_public_marshal(
- &ctx.object.in_public.publicArea, &template.buffer[0],
- sizeof(TPMT_PUBLIC), &offset);
- if (tmp_rc != tool_rc_success) {
- return tmp_rc;
- }
-
- template.size = offset;
-
+ tool_rc tmp_rc;
tmp_rc = tpm2_create_loaded(ectx, &ctx.parent.object,
- &ctx.object.sensitive, &template, &ctx.object.object_handle,
+ &ctx.object.sensitive, &ctx.object.in_public, &ctx.object.object_handle,
&ctx.object.out_private, &ctx.object.out_public, &ctx.cp_hash,
&ctx.rp_hash, ctx.parameter_hash_algorithm,
ctx.aux_session_handle[0], ctx.aux_session_handle[1]);
--
2.54.0

View File

@ -0,0 +1,66 @@
From a07362ae933a83845410a8ac7cfc46f41ad6a237 Mon Sep 17 00:00:00 2001
From: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
Date: Tue, 3 Feb 2026 18:43:01 +0900
Subject: [PATCH 15/30] fix(checkquote): fix off-by-one in PCR digest list
handling
parse_selection_data_from_selection_string() now updates
TPML_DIGEST.count correctly and rolls over to a new list only after
8 digests, resolving failures with 8+ PCRs in the -f/-l path.
Fixes: #3542
Signed-off-by: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
---
tools/misc/tpm2_checkquote.c | 30 ++++++++++++------------------
1 file changed, 12 insertions(+), 18 deletions(-)
diff --git a/tools/misc/tpm2_checkquote.c b/tools/misc/tpm2_checkquote.c
index 259d9c62..1264a9a3 100644
--- a/tools/misc/tpm2_checkquote.c
+++ b/tools/misc/tpm2_checkquote.c
@@ -308,29 +308,23 @@ static bool parse_selection_data_from_selection_string(FILE *pcr_input,
/*
* Read the digest at a selected PCR index.
*/
- pcrs->pcr_values[digest_list_count].digests[pcrs->pcr_values[
- digest_list_count].count].size = read_size;
- read_count = fread(pcrs->pcr_values[digest_list_count].digests[
- pcrs->pcr_values[digest_list_count].count].buffer,
+ if (pcrs->pcr_values[digest_list_count].count == 8) {
+ ++digest_list_count;
+ if (digest_list_count >= TPM2_MAX_PCRS) {
+ LOG_ERR("Maximum count for allowed digest lists reached.");
+ return false;
+ }
+ }
+ UINT32 digest_index = pcrs->pcr_values[digest_list_count].count;
+ pcrs->pcr_values[digest_list_count].digests[digest_index].size = read_size;
+ read_count = fread(
+ pcrs->pcr_values[digest_list_count].digests[digest_index].buffer,
read_size, 1, pcr_input);
if (read_count != 1) {
LOG_ERR("Failed to read PCR digests from file");
return false;
}
- /*
- * Ensure we don't overrun the allowed digest count in a
- * TPML_DIGEST.
- */
- if (pcrs->pcr_values[digest_list_count].count == 7) {
- digest_list_count++;
- } else {
- /*
- * Ensure we populate the digest in a new list if we
- * exhausted the digest count in the current TPML_DIGEST
- * instance.
- */
- pcrs->pcr_values[digest_list_count].count++;
- }
+ pcrs->pcr_values[digest_list_count].count++;
}
}
}
--
2.54.0

View File

@ -0,0 +1,54 @@
From 921be44cfc4fe76af49748aa039dd8ff421571e7 Mon Sep 17 00:00:00 2001
From: Juergen Repp <juergen_repp@web.de>
Date: Tue, 3 Feb 2026 16:18:46 +0100
Subject: [PATCH 16/30] tpm2_checkquote: Add size checks for PCR
desearialization
When a binary blob in the PCR file written in the form 'serialized'
is used the size fields are not checked after reading the file.
These field are no checked and an error is produced if the max values
are exceeded.
Signed-off-by: Juergen Repp <juergen_repp@web.de>
---
tools/misc/tpm2_checkquote.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/tools/misc/tpm2_checkquote.c b/tools/misc/tpm2_checkquote.c
index 1264a9a3..e91f84f1 100644
--- a/tools/misc/tpm2_checkquote.c
+++ b/tools/misc/tpm2_checkquote.c
@@ -347,6 +347,10 @@ static bool parse_selection_data_from_file(FILE *pcr_input,
return false;
}
pcr_select->count = le32toh(pcr_select->count);
+ if (pcr_select->count > TPM2_NUM_PCR_BANKS) {
+ LOG_ERR("Failed to read PCR selection from file");
+ return false;
+ }
for (i = 0; i < pcr_select->count; i++) {
pcr_select->pcrSelections[i].hash = le16toh(pcr_select->pcrSelections[i].hash);
}
@@ -373,9 +377,19 @@ static bool parse_selection_data_from_file(FILE *pcr_input,
}
// Convert TPML_DIGEST from little endian to host endian.
pcrs->pcr_values[j].count = le32toh( pcrs->pcr_values[j].count);
+ if (pcrs->pcr_values[j].count > ARRAY_LEN(pcrs->pcr_values[j].digests)) {
+ LOG_ERR("Malformed PCR file, TPML_DIGEST count cannot be greater than %" PRIu64,
+ ARRAY_LEN(pcrs->pcr_values[j].digests));
+ return false;
+ }
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);
+ if (pcrs->pcr_values[j].digests[i].size > sizeof(TPMU_HA)) {
+ LOG_ERR("Malformed PCR file, TPML_DIGEST count cannot be greater than %" PRIu64,
+ sizeof(TPMU_HA));
+ return false;
+ }
}
}
--
2.54.0

View File

@ -0,0 +1,44 @@
From 66bcb37ac78d8e0f7324f6a7f02dcff3190ec6a3 Mon Sep 17 00:00:00 2001
From: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
Date: Sun, 15 Feb 2026 04:39:57 +0900
Subject: [PATCH 17/30] fix(tpm2_send): validate command_size before computing
data_size
Signed-off-by: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
---
tools/tpm2_send.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/tools/tpm2_send.c b/tools/tpm2_send.c
index a4da5692..10751f9b 100644
--- a/tools/tpm2_send.c
+++ b/tools/tpm2_send.c
@@ -47,15 +47,19 @@ static int read_command_from_file(FILE *f, tpm2_command_header **c,
const tpm2_command_header *header = tpm2_command_header_from_bytes(buffer);
UINT32 command_size = tpm2_command_header_get_size(header, true);
- UINT32 data_size = tpm2_command_header_get_size(header, false);
-
- if (command_size > TPM2_MAX_SIZE || command_size < data_size) {
- LOG_ERR("Command buffer %"PRIu32" bytes cannot be smaller then the "
- "encapsulated data %"PRIu32" bytes, and can not be bigger than"
- " the maximum buffer size", command_size, data_size);
+ if (command_size < TPM2_COMMAND_HEADER_SIZE) {
+ LOG_ERR("Command buffer size %"PRIu32" is smaller than command header "
+ "size %zu", command_size, TPM2_COMMAND_HEADER_SIZE);
+ return -1;
+ }
+ if (command_size > TPM2_MAX_SIZE) {
+ LOG_ERR("Command buffer size %"PRIu32" exceeds maximum buffer size %u",
+ command_size, TPM2_MAX_SIZE);
return -1;
}
+ UINT32 data_size = tpm2_command_header_get_size(header, false);
+
tpm2_command_header *command = (tpm2_command_header *) malloc(command_size);
if (!command) {
LOG_ERR("oom");
--
2.54.0

View File

@ -0,0 +1,27 @@
From 856abc96e60ec0c7e9a78e7ab6e7111c866e3a88 Mon Sep 17 00:00:00 2001
From: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
Date: Sun, 15 Feb 2026 05:59:27 +0900
Subject: [PATCH 18/30] fix(tpm2_send): avoid unintended stdio closing in
close_file()
Signed-off-by: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
---
tools/tpm2_send.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/tpm2_send.c b/tools/tpm2_send.c
index 10751f9b..13264ac2 100644
--- a/tools/tpm2_send.c
+++ b/tools/tpm2_send.c
@@ -111,7 +111,7 @@ static FILE *open_file(const char *path, const char *mode) {
static void close_file(FILE *f) {
- if (f && (f != stdin || f != stdout)) {
+ if (f && f != stdin && f != stdout) {
fclose(f);
}
}
--
2.54.0

View File

@ -0,0 +1,27 @@
From 78785206da66bfcb2a48a95c9a9e3800320b465a Mon Sep 17 00:00:00 2001
From: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
Date: Sun, 15 Feb 2026 13:04:10 +0900
Subject: [PATCH 19/30] fix(tpm2_util): fix error message in
tpm2_pem_encoded_key_to_fingerprint
Signed-off-by: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
---
lib/tpm2_util.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/tpm2_util.c b/lib/tpm2_util.c
index 17a9ca9f..9a1170dc 100644
--- a/lib/tpm2_util.c
+++ b/lib/tpm2_util.c
@@ -1079,7 +1079,7 @@ bool tpm2_pem_encoded_key_to_fingerprint(const char *pem_encoded_key,
rc = tpm2_base64_encode(buffer, buffer_length, base64);
if(!rc){
- LOG_ERR("%s", "tpm2_base64_decode");
+ LOG_ERR("%s", "tpm2_base64_encode");
return false;
}
strcpy(fingerprint, "SHA256:");
--
2.54.0

View File

@ -0,0 +1,70 @@
From 0bc0a85a077c1299daba5a6fe70be8bea9fd96ae Mon Sep 17 00:00:00 2001
From: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
Date: Sun, 15 Feb 2026 08:05:58 +0900
Subject: [PATCH 20/30] fix(tpm2_util)!: modify tpm2_safe_read_from_stdin to
read entire line
Fixes #3551.
The tpm2_safe_read_from_stdin function is used exclusively in
tools/fapi/tss2_template.c to read file paths from stdin. The current
implementation however uses the "%s" template in sscanf, which cannot
properly handle file paths containing whitespaces.
This commit modifies the function's behavior to read the entire line.
Signed-off-by: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
---
lib/tpm2_util.c | 25 +++++++------------------
1 file changed, 7 insertions(+), 18 deletions(-)
diff --git a/lib/tpm2_util.c b/lib/tpm2_util.c
index 9a1170dc..962f297a 100644
--- a/lib/tpm2_util.c
+++ b/lib/tpm2_util.c
@@ -3,6 +3,7 @@
#include <ctype.h>
#include <dlfcn.h>
#include <inttypes.h>
+#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -1010,28 +1011,16 @@ out:
}
bool tpm2_safe_read_from_stdin(int length, char *data) {
- int rc;
- char *buf = malloc(length);
- char *read_data = malloc(length);
-
- if (buf == fgets(buf, length, stdin)) {
- rc = sscanf(buf, "%s", read_data);
- if (rc != 1) {
- free(buf);
- free(read_data);
- return false;
- }
- }
- else {
- free(buf);
- free(read_data);
+ /* Read line from stdin; at most length-1 bytes + null-termination */
+ if (!fgets(data, length, stdin)) {
return false;
}
- strcpy(data, read_data);
- free(buf);
- free(read_data);
+ /* Delete newline character */
+ size_t end = strcspn(data, "\r\n");
+ data[end] = '\0';
+
return true;
}
--
2.54.0

View File

@ -0,0 +1,447 @@
From df8c01be5f7672a04615b4427b0d92d23c956bd1 Mon Sep 17 00:00:00 2001
From: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
Date: Tue, 17 Feb 2026 23:36:49 +0900
Subject: [PATCH 21/30] fix(tools): out-of-bounds write with too many auxiliary
sessions
Signed-off-by: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
---
tools/tpm2_activatecredential.c | 9 ++++-----
tools/tpm2_certify.c | 9 ++++-----
tools/tpm2_certifycreation.c | 9 ++++-----
tools/tpm2_changeauth.c | 7 +++----
tools/tpm2_changeeps.c | 9 ++++-----
tools/tpm2_changepps.c | 9 ++++-----
tools/tpm2_create.c | 9 ++++-----
tools/tpm2_getrandom.c | 9 ++++-----
tools/tpm2_nvcertify.c | 9 ++++-----
tools/tpm2_nvdefine.c | 8 ++++----
tools/tpm2_nvextend.c | 8 ++++----
tools/tpm2_nvincrement.c | 9 ++++-----
tools/tpm2_nvread.c | 9 ++++-----
tools/tpm2_nvreadlock.c | 9 ++++-----
tools/tpm2_nvreadpublic.c | 9 ++++-----
tools/tpm2_nvsetbits.c | 9 ++++-----
tools/tpm2_nvundefine.c | 9 ++++-----
tools/tpm2_nvwrite.c | 9 ++++-----
tools/tpm2_nvwritelock.c | 9 ++++-----
19 files changed, 75 insertions(+), 92 deletions(-)
diff --git a/tools/tpm2_activatecredential.c b/tools/tpm2_activatecredential.c
index eee8a210..a1cf65fa 100644
--- a/tools/tpm2_activatecredential.c
+++ b/tools/tpm2_activatecredential.c
@@ -292,13 +292,12 @@ static bool on_option(char key, char *value) {
ctx.rp_hash_path = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
- LOG_ERR("Specify a max of 3 sessions");
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
}
diff --git a/tools/tpm2_certify.c b/tools/tpm2_certify.c
index ca1e468a..e504da09 100644
--- a/tools/tpm2_certify.c
+++ b/tools/tpm2_certify.c
@@ -282,13 +282,12 @@ static bool on_option(char key, char *value) {
}
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
- LOG_ERR("Specify a max of 3 sessions");
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
}
diff --git a/tools/tpm2_certifycreation.c b/tools/tpm2_certifycreation.c
index b6dbc6fa..7e1d6e24 100644
--- a/tools/tpm2_certifycreation.c
+++ b/tools/tpm2_certifycreation.c
@@ -358,13 +358,12 @@ static bool on_option(char key, char *value) {
ctx.policy_qualifier_data = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
- LOG_ERR("Specify a max of 3 sessions");
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
/* no default */
}
diff --git a/tools/tpm2_changeauth.c b/tools/tpm2_changeauth.c
index f2ad99fe..373fbd5c 100644
--- a/tools/tpm2_changeauth.c
+++ b/tools/tpm2_changeauth.c
@@ -326,13 +326,12 @@ static bool on_option(char key, char *value) {
ctx.rp_hash_path = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
LOG_ERR("Specify a max of 3 sessions");
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
case 'R':
ctx.autoflush = true;
diff --git a/tools/tpm2_changeeps.c b/tools/tpm2_changeeps.c
index c3d6f6df..8c95915f 100644
--- a/tools/tpm2_changeeps.c
+++ b/tools/tpm2_changeeps.c
@@ -164,13 +164,12 @@ static bool on_option(char key, char *value) {
ctx.rp_hash_path = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
- LOG_ERR("Specify a max of 3 sessions");
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
}
diff --git a/tools/tpm2_changepps.c b/tools/tpm2_changepps.c
index 343dfc9b..fa331cd8 100644
--- a/tools/tpm2_changepps.c
+++ b/tools/tpm2_changepps.c
@@ -164,13 +164,12 @@ static bool on_option(char key, char *value) {
ctx.rp_hash_path = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
- LOG_ERR("Specify a max of 3 sessions");
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
}
diff --git a/tools/tpm2_create.c b/tools/tpm2_create.c
index 39bbc935..a4dbf569 100644
--- a/tools/tpm2_create.c
+++ b/tools/tpm2_create.c
@@ -540,13 +540,12 @@ static bool on_option(char key, char *value) {
ctx.rp_hash_path = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
- LOG_ERR("Specify a max of 3 sessions");
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
case 'f':
ctx.format = tpm2_convert_pubkey_fmt_from_optarg(value);
diff --git a/tools/tpm2_getrandom.c b/tools/tpm2_getrandom.c
index f4b064d9..a6775a60 100644
--- a/tools/tpm2_getrandom.c
+++ b/tools/tpm2_getrandom.c
@@ -289,13 +289,12 @@ static bool on_option(char key, char *value) {
ctx.rp_hash_path = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
- LOG_ERR("Specify a max of 3 sessions");
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
/* no default */
}
diff --git a/tools/tpm2_nvcertify.c b/tools/tpm2_nvcertify.c
index 53729bb8..996bbc6c 100644
--- a/tools/tpm2_nvcertify.c
+++ b/tools/tpm2_nvcertify.c
@@ -484,13 +484,12 @@ static bool on_option(char key, char *value) {
ctx.rp_hash_path = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
- LOG_ERR("Specify a max of 3 sessions");
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
case 'n':
ctx.precalc_nvname.size = BUFFER_SIZE(TPM2B_NAME, name);
diff --git a/tools/tpm2_nvdefine.c b/tools/tpm2_nvdefine.c
index 7b14b90f..800190a2 100644
--- a/tools/tpm2_nvdefine.c
+++ b/tools/tpm2_nvdefine.c
@@ -453,12 +453,12 @@ static bool on_option(char key, char *value) {
ctx.rp_hash_path = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
case 'g':
ctx.halg = tpm2_alg_util_from_optarg(value,
diff --git a/tools/tpm2_nvextend.c b/tools/tpm2_nvextend.c
index 3cf14550..0bf005c5 100644
--- a/tools/tpm2_nvextend.c
+++ b/tools/tpm2_nvextend.c
@@ -237,12 +237,12 @@ static bool on_option(char key, char *value) {
ctx.rp_hash_path = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
case 'n':
ctx.precalc_nvname.size = BUFFER_SIZE(TPM2B_NAME, name);
diff --git a/tools/tpm2_nvincrement.c b/tools/tpm2_nvincrement.c
index c411fa67..fd8ce195 100644
--- a/tools/tpm2_nvincrement.c
+++ b/tools/tpm2_nvincrement.c
@@ -258,13 +258,12 @@ static bool on_option(char key, char *value) {
ctx.rp_hash_path = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
- LOG_ERR("Specify a max of 3 sessions");
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
case 'n':
ctx.precalc_nvname.size = BUFFER_SIZE(TPM2B_NAME, name);
diff --git a/tools/tpm2_nvread.c b/tools/tpm2_nvread.c
index d1d855d2..4720d48b 100644
--- a/tools/tpm2_nvread.c
+++ b/tools/tpm2_nvread.c
@@ -336,13 +336,12 @@ static bool on_option(char key, char *value) {
ctx.rp_hash_path = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
- LOG_ERR("Specify a max of 3 sessions");
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
case 3:
ctx.is_yaml = true;
diff --git a/tools/tpm2_nvreadlock.c b/tools/tpm2_nvreadlock.c
index 387e6f38..16bd2a3e 100644
--- a/tools/tpm2_nvreadlock.c
+++ b/tools/tpm2_nvreadlock.c
@@ -244,13 +244,12 @@ static bool on_option(char key, char *value) {
ctx.rp_hash_path = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
- LOG_ERR("Specify a max of 3 sessions");
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
case 'n':
ctx.precalc_nvname.size = BUFFER_SIZE(TPM2B_NAME, name);
diff --git a/tools/tpm2_nvreadpublic.c b/tools/tpm2_nvreadpublic.c
index 190749c2..b39d1ac7 100644
--- a/tools/tpm2_nvreadpublic.c
+++ b/tools/tpm2_nvreadpublic.c
@@ -349,13 +349,12 @@ static bool on_option(char key, char *value) {
ctx.rp_hash_path = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
- LOG_ERR("Specify a max of 3 sessions");
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
case 'n':
ctx.precalc_nvname.size = BUFFER_SIZE(TPM2B_NAME, name);
diff --git a/tools/tpm2_nvsetbits.c b/tools/tpm2_nvsetbits.c
index 841753a5..a9a12876 100644
--- a/tools/tpm2_nvsetbits.c
+++ b/tools/tpm2_nvsetbits.c
@@ -248,13 +248,12 @@ static bool on_option(char key, char *value) {
ctx.rp_hash_path = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
- LOG_ERR("Specify a max of 3 sessions");
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
case 'n':
ctx.precalc_nvname.size = BUFFER_SIZE(TPM2B_NAME, name);
diff --git a/tools/tpm2_nvundefine.c b/tools/tpm2_nvundefine.c
index 3e8e77ea..be488574 100644
--- a/tools/tpm2_nvundefine.c
+++ b/tools/tpm2_nvundefine.c
@@ -355,13 +355,12 @@ static bool on_option(char key, char *value) {
if (!ctx.aux_session_cnt) {
ctx.policy_session.path = value;
}
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
- LOG_ERR("Specify a max of 3 sessions");
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
case 0:
ctx.cp_hash_path = value;
diff --git a/tools/tpm2_nvwrite.c b/tools/tpm2_nvwrite.c
index e29ca8a3..220ea5ec 100644
--- a/tools/tpm2_nvwrite.c
+++ b/tools/tpm2_nvwrite.c
@@ -396,13 +396,12 @@ static bool on_option(char key, char *value) {
ctx.rp_hash_path = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
- LOG_ERR("Specify a max of 3 sessions");
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
case 'n':
ctx.precalc_nvname.size = BUFFER_SIZE(TPM2B_NAME, name);
diff --git a/tools/tpm2_nvwritelock.c b/tools/tpm2_nvwritelock.c
index 52be0be1..ac76fcef 100644
--- a/tools/tpm2_nvwritelock.c
+++ b/tools/tpm2_nvwritelock.c
@@ -278,13 +278,12 @@ static bool on_option(char key, char *value) {
ctx.rp_hash_path = value;
break;
case 'S':
- ctx.aux_session_path[ctx.aux_session_cnt] = value;
- if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
- ctx.aux_session_cnt++;
- } else {
- LOG_ERR("Specify a max of 3 sessions");
+ if (ctx.aux_session_cnt >= MAX_AUX_SESSIONS) {
+ LOG_ERR("Specify a max of %u auxiliary sessions", MAX_AUX_SESSIONS);
return false;
}
+ ctx.aux_session_path[ctx.aux_session_cnt] = value;
+ ++ctx.aux_session_cnt;
break;
case 'n':
ctx.precalc_nvname.size = BUFFER_SIZE(TPM2B_NAME, name);
--
2.54.0

View File

@ -0,0 +1,127 @@
From 70671552f843f1a94c04c3a57631ae3f0c20c8eb Mon Sep 17 00:00:00 2001
From: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
Date: Wed, 18 Feb 2026 23:38:43 +0900
Subject: [PATCH 22/30] fix(tpm2_alg_util): avoid mutating input scheme in
handle_scheme_sign
Signed-off-by: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
---
lib/tpm2_alg_util.c | 56 ++++++++++++++++++++++++---------------------
1 file changed, 30 insertions(+), 26 deletions(-)
diff --git a/lib/tpm2_alg_util.c b/lib/tpm2_alg_util.c
index 65739fc7..42946752 100644
--- a/lib/tpm2_alg_util.c
+++ b/lib/tpm2_alg_util.c
@@ -152,9 +152,9 @@ static alg_parser_rc handle_sym_common(const char *ext, TPMT_SYM_DEF_OBJECT *s,
* You cannot change all the variables in this, as they are dependent
* on names in that routine; this is for simplicity.
*/
-#define do_scheme_halg(scheme, advance, alg) \
+#define DO_SCHEME_HALG(scheme_, advance, alg) \
do { \
- scheme += advance; \
+ scheme_ += advance; \
s->scheme.scheme = alg; \
do_scheme_hash_alg = true; \
found = true; \
@@ -174,16 +174,18 @@ static alg_parser_rc handle_scheme_sign(const char *scheme,
return alg_parser_rc_error;
}
+ char *buf_ptr = buf;
+
// Get the scheme and symetric details
TPMS_ASYM_PARMS *s = &public->publicArea.parameters.asymDetail;
- if (!strcmp(scheme, "null")) {
+ if (!strcmp(buf_ptr, "null")) {
public->publicArea.parameters.asymDetail.scheme.scheme = TPM2_ALG_NULL;
return alg_parser_rc_continue;
}
char *halg = NULL;
- char *split = strchr(scheme, '-');
+ char *split = strchr(buf_ptr, '-');
if (split) {
*split = '\0';
halg = split + 1;
@@ -193,51 +195,53 @@ static alg_parser_rc handle_scheme_sign(const char *scheme,
bool do_scheme_hash_alg = false;
if (public->publicArea.type == TPM2_ALG_ECC) {
- if (!strncmp(scheme, "ecdsa", 5)) {
- do_scheme_halg(scheme, 5, TPM2_ALG_ECDSA);
- } else if (!strncmp(scheme, "ecdh", 4)) {
- do_scheme_halg(scheme, 4, TPM2_ALG_ECDH);
- } else if (!strncmp(scheme, "ecschnorr", 9)) {
- do_scheme_halg(scheme, 9, TPM2_ALG_ECSCHNORR);
- } else if (!strncmp(scheme, "sm2", 3)) {
- do_scheme_halg(scheme, 3, TPM2_ALG_SM2);
- } else if (!strncmp(scheme, "ecdaa", 5)) {
- do_scheme_halg(scheme, 5, TPM2_ALG_ECDAA);
+ if (!strncmp(buf_ptr, "ecdsa", 5)) {
+ DO_SCHEME_HALG(buf_ptr, 5, TPM2_ALG_ECDSA);
+ } else if (!strncmp(buf_ptr, "ecdh", 4)) {
+ DO_SCHEME_HALG(buf_ptr, 4, TPM2_ALG_ECDH);
+ } else if (!strncmp(buf_ptr, "ecschnorr", 9)) {
+ DO_SCHEME_HALG(buf_ptr, 9, TPM2_ALG_ECSCHNORR);
+ } else if (!strncmp(buf_ptr, "sm2", 3)) {
+ DO_SCHEME_HALG(buf_ptr, 3, TPM2_ALG_SM2);
+ } else if (!strncmp(buf_ptr, "ecdaa", 5)) {
+ DO_SCHEME_HALG(buf_ptr, 5, TPM2_ALG_ECDAA);
/*
* ECDAA has both a commit-counter value and hashing algorithm.
* The default commit-counter value is set to zero to use the first
* commit-id.
*/
- if (scheme[0] == '\0') {
- scheme = "0";
+ const char *count_str = buf_ptr;
+ if (buf_ptr[0] == '\0') {
+ count_str = "0";
}
TPMS_SIG_SCHEME_ECDAA *e = &s->scheme.details.ecdaa;
- bool res = tpm2_util_string_to_uint16(scheme, &e->count);
+ bool res = tpm2_util_string_to_uint16(count_str, &e->count);
if (!res) {
return alg_parser_rc_error;
}
- } else if (!strcmp("null", scheme)) {
+ } else if (!strcmp(buf_ptr, "null")) {
s->scheme.scheme = TPM2_ALG_NULL;
+ found = true;
}
} else {
- if (!strcmp(scheme, "rsaes")) {
+ if (!strcmp(buf_ptr, "rsaes")) {
/*
* rsaes has no hash alg or details, so it MUST
* match exactly, notice strcmp and NOT strNcmp!
*/
s->scheme.scheme = TPM2_ALG_RSAES;
found = true;
- } else if (!strcmp("null", scheme)) {
+ } else if (!strcmp(buf_ptr, "null")) {
s->scheme.scheme = TPM2_ALG_NULL;
found = true;
- } else if (!strncmp("rsapss", scheme, 6)) {
- do_scheme_halg(scheme, 6, TPM2_ALG_RSAPSS);
- } else if (!strncmp("rsassa", scheme, 6)) {
- do_scheme_halg(scheme, 6, TPM2_ALG_RSASSA);
- } else if (!strncmp(scheme, "oaep", 4)) {
- do_scheme_halg(scheme, 4, TPM2_ALG_OAEP);
+ } else if (!strncmp(buf_ptr, "rsapss", 6)) {
+ DO_SCHEME_HALG(buf_ptr, 6, TPM2_ALG_RSAPSS);
+ } else if (!strncmp(buf_ptr, "rsassa", 6)) {
+ DO_SCHEME_HALG(buf_ptr, 6, TPM2_ALG_RSASSA);
+ } else if (!strncmp(buf_ptr, "oaep", 4)) {
+ DO_SCHEME_HALG(buf_ptr, 4, TPM2_ALG_OAEP);
}
}
--
2.54.0

View File

@ -0,0 +1,115 @@
From 6169f5cf75ea205125b7127b25875f0b2eeb770c Mon Sep 17 00:00:00 2001
From: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
Date: Sun, 1 Mar 2026 03:41:03 +0900
Subject: [PATCH 23/30] fix(tools): add missing null checks after malloc
Signed-off-by: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
---
tools/tpm2_duplicate.c | 9 +++++++++
tools/tpm2_encryptdecrypt.c | 4 ++++
tools/tpm2_getekcertificate.c | 8 ++++++++
tools/tpm2_nvreadpublic.c | 4 ++++
tools/tpm2_verifysignature.c | 4 ++++
5 files changed, 29 insertions(+)
diff --git a/tools/tpm2_duplicate.c b/tools/tpm2_duplicate.c
index 2c7c340c..26f4ca1d 100644
--- a/tools/tpm2_duplicate.c
+++ b/tools/tpm2_duplicate.c
@@ -179,6 +179,11 @@ static tool_rc openssl_create_duplicate(void) {
encrypted_duplicate_sensitive.size);
ctx.out_private_data = malloc(private.size + sizeof(private.size));
+ if (!ctx.out_private_data) {
+ LOG_ERR("oom");
+ rc = tool_rc_general_error;
+ goto out;
+ }
memcpy(ctx.out_private_data, &private, private.size + sizeof(private.size));
out:
@@ -231,6 +236,10 @@ static tool_rc process_openssl_duplicate(void) {
ctx.out_sym_seed = malloc(encrypted_seed.size +
sizeof(encrypted_seed.size));
+ if (!ctx.out_sym_seed) {
+ LOG_ERR("oom");
+ return tool_rc_general_error;
+ }
memcpy(ctx.out_sym_seed, &encrypted_seed,
encrypted_seed.size + sizeof(encrypted_seed.size));
diff --git a/tools/tpm2_encryptdecrypt.c b/tools/tpm2_encryptdecrypt.c
index e9087dc8..3a6b243a 100644
--- a/tools/tpm2_encryptdecrypt.c
+++ b/tools/tpm2_encryptdecrypt.c
@@ -375,6 +375,10 @@ static tool_rc process_inputs(ESYS_CONTEXT *ectx) {
ctx.iv_in = 0;
} else {
ctx.iv_in = malloc(iv_start.size + sizeof(iv_start));
+ if (!ctx.iv_in) {
+ LOG_ERR("oom");
+ return tool_rc_general_error;
+ }
ctx.iv_in->size = iv_start.size;
memcpy(ctx.iv_in->buffer, &iv_start.buffer, iv_start.size);
}
diff --git a/tools/tpm2_getekcertificate.c b/tools/tpm2_getekcertificate.c
index 961021cf..d962c13c 100644
--- a/tools/tpm2_getekcertificate.c
+++ b/tools/tpm2_getekcertificate.c
@@ -424,6 +424,10 @@ static char *encode_ek_public_amd(void) {
return NULL;
}
char *hash_str = malloc(AMD_EK_URI_LEN * 2 + NULL_TERM_LEN);
+ if (!hash_str) {
+ LOG_ERR("oom");
+ return NULL;
+ }
for (size_t i = 0; i < AMD_EK_URI_LEN; i++)
{
sprintf((char*)(hash_str + (i*2)), "%02x", hash[i]);
@@ -845,6 +849,10 @@ static tool_rc process_input(ESYS_CONTEXT *ectx) {
if (ctx.ek_path) {
ctx.out_public = malloc(sizeof(*ctx.out_public));
+ if (!ctx.out_public) {
+ LOG_ERR("oom");
+ return tool_rc_general_error;
+ }
ctx.out_public->size = 0;
bool res = files_load_public(ctx.ek_path, ctx.out_public);
if (!res) {
diff --git a/tools/tpm2_nvreadpublic.c b/tools/tpm2_nvreadpublic.c
index b39d1ac7..597ff6d1 100644
--- a/tools/tpm2_nvreadpublic.c
+++ b/tools/tpm2_nvreadpublic.c
@@ -243,6 +243,10 @@ static tool_rc process_inputs(ESYS_CONTEXT *ectx) {
*/
if (!ctx.is_command_dispatch) {
ctx.nv_public_list[0] = malloc(sizeof(TPM2B_NV_PUBLIC));
+ if (!ctx.nv_public_list[0]) {
+ LOG_ERR("oom");
+ return tool_rc_general_error;
+ }
}
/*
diff --git a/tools/tpm2_verifysignature.c b/tools/tpm2_verifysignature.c
index 240165d6..5f7c3e96 100644
--- a/tools/tpm2_verifysignature.c
+++ b/tools/tpm2_verifysignature.c
@@ -196,6 +196,10 @@ static bool on_option(char key, char *value) {
break;
case 'd': {
ctx.msg_hash = malloc(sizeof(TPM2B_DIGEST));
+ if (!ctx.msg_hash) {
+ LOG_ERR("oom");
+ return false;
+ }
ctx.msg_hash->size = sizeof(ctx.msg_hash->buffer);
if (!files_load_bytes_from_path(value, ctx.msg_hash->buffer,
&ctx.msg_hash->size)) {
--
2.54.0

View File

@ -0,0 +1,38 @@
From 73befeab5b79429864a2d1f95e8a94b501913b32 Mon Sep 17 00:00:00 2001
From: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
Date: Sun, 1 Mar 2026 03:41:45 +0900
Subject: [PATCH 24/30] fix(test): add missing null checks after malloc
Signed-off-by: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
---
test/unit/test_tpm2_auth_util.c | 1 +
test/unit/test_tpm2_session.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/test/unit/test_tpm2_auth_util.c b/test/unit/test_tpm2_auth_util.c
index d88e42ba..c2e07481 100644
--- a/test/unit/test_tpm2_auth_util.c
+++ b/test/unit/test_tpm2_auth_util.c
@@ -308,6 +308,7 @@ static int setup(void **state) {
ESYS_CONTEXT *ectx;
size_t size = sizeof(TSS2_TCTI_CONTEXT_FAKE);
TSS2_TCTI_CONTEXT *tcti = malloc(size);
+ assert_non_null(tcti);
rc = tcti_fake_initialize(tcti, &size);
if (rc) {
diff --git a/test/unit/test_tpm2_session.c b/test/unit/test_tpm2_session.c
index dccb87f0..12851569 100644
--- a/test/unit/test_tpm2_session.c
+++ b/test/unit/test_tpm2_session.c
@@ -77,6 +77,7 @@ TSS2_RC __wrap_Esys_TR_GetName(ESYS_CONTEXT *esysContext, ESYS_TR handle,
UNUSED(handle);
*name = malloc(sizeof(TPM2B_NAME));
+ assert_non_null(*name);
size_t offset = 0;
TSS2_RC rc = Tss2_MU_TPM2_HANDLE_Marshal(SESSION_HANDLE, &(*name)->name[0],
sizeof(TPM2_HANDLE), &offset);
--
2.54.0

View File

@ -0,0 +1,45 @@
From 7f25b8648b50b025788e1d1d78f6c023eb559b79 Mon Sep 17 00:00:00 2001
From: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
Date: Sun, 1 Mar 2026 02:47:49 +0900
Subject: [PATCH 25/30] fix(tpm2_util): fix buffer overflow in string
validation checks
Signed-off-by: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
---
lib/tpm2_util.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/lib/tpm2_util.c b/lib/tpm2_util.c
index 962f297a..4a79cfa3 100644
--- a/lib/tpm2_util.c
+++ b/lib/tpm2_util.c
@@ -1027,22 +1027,20 @@ bool tpm2_safe_read_from_stdin(int length, char *data) {
bool tpm2_pem_encoded_key_to_fingerprint(const char *pem_encoded_key,
char *fingerprint) {
- bool is_pemkey_len_valid = strlen(pem_encoded_key) > 1024 ? false : true;
- if (!is_pemkey_len_valid) {
+ if (strlen(pem_encoded_key) >= 1024) {
return false;
}
char str[1024] = "";
- strcpy(str, pem_encoded_key);
+ strncpy(str, pem_encoded_key, 1023);
+ str[1023] = '\0';
/* walk through other tokens */
char base64[1024] = "";
char *token = strtok(str, "\n");
while ( token != NULL ) {
if (!strstr(token, "-----")) {
- bool is_base64_overrun = (strlen(base64) + strlen(token)) > 1024 ?
- true : false;
- if (is_base64_overrun) {
+ if ((strlen(base64) + strlen(token)) >= 1024) {
return false;
}
strcat(base64, token);
--
2.54.0

View File

@ -0,0 +1,30 @@
From 494ae8b5a8a705c7457df078f476b843b89ae6f1 Mon Sep 17 00:00:00 2001
From: Andreas Fuchs <andreas.fuchs@infineon.com>
Date: Tue, 10 Feb 2026 09:20:05 +0100
Subject: [PATCH 26/30] Allocate the right amount of memory for auth_policy
For some reason we did a malloc(UINT16_MAX+...) which is way to much for a policy.
Signed-off-by: Andreas Fuchs <andreas.fuchs@infineon.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
---
tools/tpm2_setprimarypolicy.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/tpm2_setprimarypolicy.c b/tools/tpm2_setprimarypolicy.c
index cdabcd9e..35064ce6 100644
--- a/tools/tpm2_setprimarypolicy.c
+++ b/tools/tpm2_setprimarypolicy.c
@@ -106,7 +106,7 @@ static tool_rc process_inputs(ESYS_CONTEXT *ectx) {
*/
if (ctx.policy_path) {
- ctx.auth_policy = malloc(UINT16_MAX + sizeof(uint16_t));
+ ctx.auth_policy = malloc(sizeof(*ctx.auth_policy));
if (!ctx.auth_policy) {
LOG_ERR("oom");
return tool_rc_general_error;
--
2.54.0

View File

@ -0,0 +1,37 @@
From 09cc3b776849fba9d37487bfbc7ae4d725805b0c Mon Sep 17 00:00:00 2001
From: Juergen Repp <juergen_repp@web.de>
Date: Sun, 8 Mar 2026 15:59:20 +0100
Subject: [PATCH 27/30] tpm2_util: add some checks to
tpm2_safe_read_from_stdin.
* Prevent garbage in stdin buffer.
* Add check whether input is empty.
Signed-off-by: Juergen Repp <juergen_repp@web.de>
---
lib/tpm2_util.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/lib/tpm2_util.c b/lib/tpm2_util.c
index 4a79cfa3..d4b46c95 100644
--- a/lib/tpm2_util.c
+++ b/lib/tpm2_util.c
@@ -1021,6 +1021,15 @@ bool tpm2_safe_read_from_stdin(int length, char *data) {
size_t end = strcspn(data, "\r\n");
data[end] = '\0';
+ /* clear fget buffer */
+ if (strlen(data) == (size_t)length - 1) {
+ int c;
+ while ((c = getchar()) != '\n' && c != EOF);
+ }
+ /* Return false if input is empty */
+ if (data[0] == '\0') {
+ return false;
+ }
return true;
}
--
2.54.0

View File

@ -0,0 +1,150 @@
From 8776c467e8d5a95fcbcd252ce737dea7b1bd1a8a Mon Sep 17 00:00:00 2001
From: Juergen Repp <juergen_repp@web.de>
Date: Thu, 5 Mar 2026 21:47:17 +0100
Subject: [PATCH 28/30] tpm2_createak: add attribute option.
The default attributes for the ak are:
"restricted|userwithauth|sign|fixedtpm|fixedparent|sensitivedataorigin"
This default setting differs from the settings in the specification
TPM 2.0 Keys for Device Identity and Attestation. "adminwithpolicy"
is not set. Thus the option -a, --attributes is added.
Addresses: #3225
Signed-off-by: Juergen Repp <juergen_repp@web.de>
---
man/tpm2_createak.1.md | 9 +++++++++
test/integration/tests/createak.sh | 13 +++++++++++--
tools/tpm2_createak.c | 19 +++++++++++++++++--
3 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/man/tpm2_createak.1.md b/man/tpm2_createak.1.md
index adcda09a..883d7fa5 100644
--- a/man/tpm2_createak.1.md
+++ b/man/tpm2_createak.1.md
@@ -48,6 +48,15 @@ loaded-key:
* **rsa** - An RSA2048 key.
* **keyedhash** - hmac key.
+ * **-a**, **\--attributes**=_ATTRIBUTES_:
+
+ The object attributes, optional. The default for created objects is:
+ "restricted|userwithauth|sign|fixedtpm|fixedparent|sensitivedataorigin"
+ This default setting differs from the settings in the specification
+ TPM 2.0 Keys for Device Identity and Attestation. "adminwithpolicy" is
+ not set and can be added to the default:
+ "restricted|userwithauth|...|adminwithpolicy"
+
* **-g**, **\--hash-algorithm**=_ALGORITHM_:
Specifies the digest algorithm used for signing.
diff --git a/test/integration/tests/createak.sh b/test/integration/tests/createak.sh
index 7067f9d2..b8fb1d44 100644
--- a/test/integration/tests/createak.sh
+++ b/test/integration/tests/createak.sh
@@ -3,7 +3,7 @@
source helpers.sh
cleanup() {
- rm -f ek.pub ak.pub ak.name ak.name ak.log
+ rm -f ek.pub ak.pub ak.name ak.name ak.log ek.ctx
# Evict persistent handles, we want them to always succeed and never trip
# the onerror trap.
@@ -26,7 +26,7 @@ cleanup "no-shut-down"
tpm2 createek -Q -c 0x8101000b -G rsa -u ek.pub
tpm2 createak -Q -C 0x8101000b -c ak.ctx -G rsa -g sha256 -s rsassa -u ak.pub \
--n ak.name -q ak.qname
+ -n ak.name -q ak.qname
# Validate the qname
tpm2 readpublic -c ak.ctx -q ak.qname2
@@ -45,4 +45,13 @@ tpm2 changeauth -c e endauth
tpm2 createek -Q -P endauth -c 0x8101000b -G rsa -u ek.pub
tpm2 createak -Q -P endauth -C 0x8101000b -c ak.ctx -G rsa -u ak.pub -n ak.name
+# Check attributes different from default
+tpm2 createak -Q -Q -P endauth -C 0x8101000b -c ak.ctx -u ak.pub -n ak.name \
+ -a "restricted|userwithauth|sign|fixedtpm|fixedparent|sensitivedataorigin|adminwithpolicy"
+
+# Check whether non default attribute was set
+tpm2 readpublic -c ak.ctx | grep adminwithpolicy
+
+
+
exit 0
diff --git a/tools/tpm2_createak.c b/tools/tpm2_createak.c
index 8239e5f4..d9d5a869 100644
--- a/tools/tpm2_createak.c
+++ b/tools/tpm2_createak.c
@@ -12,6 +12,7 @@
#include "tpm2_auth_util.h"
#include "tpm2_convert.h"
#include "tpm2_tool.h"
+#include "tpm2_attr_util.h"
#define ATTRS \
TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_USERWITHAUTH| \
@@ -108,6 +109,7 @@ struct createak_context {
const char *qname_file;
} out;
char *auth_str;
+ char *attrs;
} ak;
struct {
UINT8 f :1;
@@ -136,6 +138,7 @@ static tool_rc init_ak_public(TPMI_ALG_HASH name_alg, TPM2B_PUBLIC *public) {
const char *name_halg;
char alg[256];
+ TPMA_OBJECT attrs;
name_halg = tpm2_alg_util_algtostr(name_alg, tpm2_alg_util_flags_hash);
@@ -159,7 +162,15 @@ static tool_rc init_ak_public(TPMI_ALG_HASH name_alg, TPM2B_PUBLIC *public) {
snprintf(alg, sizeof(alg), "%s:%s-%s:null", ctx.ak.in.alg.type,
ctx.ak.in.alg.sign, ctx.ak.in.alg.digest);
}
- return tpm2_alg_util_public_init(alg, name_halg, NULL, NULL, ATTRS, public);
+ if (ctx.ak.attrs) {
+ if (!tpm2_attr_util_obj_from_optarg(ctx.ak.attrs, &attrs)) {
+ LOG_ERR("Invalid attributes.");
+ return tool_rc_general_error;
+ }
+ } else {
+ attrs = ATTRS;
+ }
+ return tpm2_alg_util_public_init(alg, name_halg, NULL, NULL, attrs, public);
}
static tool_rc create_ak(ESYS_CONTEXT *ectx) {
@@ -464,6 +475,9 @@ static bool on_option(char key, char *value) {
case 'R':
ctx.autoflush = true;
break;
+ case 'a':
+ ctx.ak.attrs = value;
+ break;
}
return true;
@@ -479,6 +493,7 @@ static bool tpm2_tool_onstart(tpm2_options **opts) {
{ "ak-name", required_argument, NULL, 'n' },
{ "key-algorithm", required_argument, NULL, 'G' },
{ "hash-algorithm", required_argument, NULL, 'g' },
+ { "attributes", required_argument, NULL, 'a' },
{ "signing-algorithm", required_argument, NULL, 's' },
{ "format", required_argument, NULL, 'f' },
{ "public", required_argument, NULL, 'u' },
@@ -487,7 +502,7 @@ static bool tpm2_tool_onstart(tpm2_options **opts) {
{ "autoflush", no_argument, NULL, 'R' },
};
- *opts = tpm2_options_new("P:p:C:c:n:G:g:s:f:u:r:q:R", ARRAY_LEN(topts), topts,
+ *opts = tpm2_options_new("P:p:C:c:n:G:a:g:s:f:u:r:q:R", ARRAY_LEN(topts), topts,
on_option, NULL, 0);
return *opts != NULL;
--
2.54.0

View File

@ -0,0 +1,41 @@
From cd3d4df82a4cd629ca36345eb4afb8f5d622f837 Mon Sep 17 00:00:00 2001
From: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
Date: Fri, 6 Mar 2026 23:45:56 +0900
Subject: [PATCH 29/30] fix(tpm2_loadexternal): check return value of
RAND_bytes
RAND_bytes() can fail with return code 0 or -1 when the OpenSSL CSPRNG has
not been sufficiently seeded.
If RAND_bytes() fails, seed->buffer is left uninitialised. This seed value
is stored in ctx.priv.sensitiveArea.seedValue and used in the consistency
checks by TPM.
Check the return value and return tool_rc_general_error on failure so that
the operation is aborted rather than proceeding with a bad seed.
Signed-off-by: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
---
tools/tpm2_loadexternal.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/tools/tpm2_loadexternal.c b/tools/tpm2_loadexternal.c
index bddc1b73..9c8bab63 100644
--- a/tools/tpm2_loadexternal.c
+++ b/tools/tpm2_loadexternal.c
@@ -284,7 +284,11 @@ priv_path:
TPM2B_DIGEST *seed = &ctx.priv.sensitiveArea.seedValue;
seed->size = tpm2_alg_util_get_hash_size(ctx.pub.publicArea.nameAlg);
if (seed->size != 0) {
- RAND_bytes(seed->buffer, seed->size);
+ int tmp_rc = RAND_bytes(seed->buffer, seed->size);
+ if (tmp_rc != 1) {
+ LOG_ERR("Failed to generate random seed value");
+ return tool_rc_general_error;
+ }
}
tpm2_openssl_load_rc load_status = tpm2_openssl_load_private(
--
2.54.0

View File

@ -0,0 +1,154 @@
From 6dfbb0fd748f51bec179ac28bf8239199155df72 Mon Sep 17 00:00:00 2001
From: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
Date: Fri, 27 Mar 2026 19:15:29 +0900
Subject: [PATCH 30/30] fix(tpm2_identity_util)!: add buffer size check
hmac_outer_integrity() concatenates two caller-supplied buffers into a
fixed-size stack buffer of TPM2_MAX_DIGEST_BUFFER (1024) bytes using
memcpy without checking their combined size.
This commit adds a buffer size check before memcpy to prevent potential
oob.
To propagate errors to the caller, the return type of hmac_outer_integrity()
and tpm2_identity_util_calculate_outer_integrity() from void to bool.
The latter change breaks compatibility with the public API.
Signed-off-by: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
---
lib/tpm2_identity_util.c | 15 ++++++++++++---
lib/tpm2_identity_util.h | 2 +-
tools/tpm2_duplicate.c | 5 ++++-
tools/tpm2_import.c | 7 ++++++-
tools/tpm2_makecredential.c | 7 +++++--
5 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/lib/tpm2_identity_util.c b/lib/tpm2_identity_util.c
index 03cfd269..b78413f3 100644
--- a/lib/tpm2_identity_util.c
+++ b/lib/tpm2_identity_util.c
@@ -285,11 +285,18 @@ out:
return result;
}
-static void hmac_outer_integrity(TPMI_ALG_HASH parent_name_alg,
+static bool hmac_outer_integrity(TPMI_ALG_HASH parent_name_alg,
uint8_t *buffer1, uint16_t buffer1_size, uint8_t *buffer2,
uint16_t buffer2_size, uint8_t *hmac_key,
TPM2B_DIGEST *outer_integrity_hmac) {
+ if ((size_t)buffer1_size + buffer2_size > TPM2_MAX_DIGEST_BUFFER) {
+ LOG_ERR("Necessary buffer size (%u) exceeds TPM2_MAX_DIGEST_BUFFER (%zu)",
+ (unsigned)(buffer1_size + buffer2_size),
+ (size_t)TPM2_MAX_DIGEST_BUFFER);
+ return false;
+ }
+
uint8_t to_hmac_buffer[TPM2_MAX_DIGEST_BUFFER];
memcpy(to_hmac_buffer, buffer1, buffer1_size);
memcpy(to_hmac_buffer + buffer1_size, buffer2, buffer2_size);
@@ -301,6 +308,7 @@ static void hmac_outer_integrity(TPMI_ALG_HASH parent_name_alg,
to_hmac_buffer, buffer1_size + buffer2_size,
outer_integrity_hmac->buffer, &size);
outer_integrity_hmac->size = size;
+ return true;
}
bool tpm2_identity_util_calculate_inner_integrity(TPMI_ALG_HASH name_alg,
@@ -376,7 +384,7 @@ bool tpm2_identity_util_calculate_inner_integrity(TPMI_ALG_HASH name_alg,
encrypted_inner_integrity);
}
-void tpm2_identity_util_calculate_outer_integrity(TPMI_ALG_HASH parent_name_alg,
+bool tpm2_identity_util_calculate_outer_integrity(TPMI_ALG_HASH parent_name_alg,
TPM2B_NAME *pubname, TPM2B_MAX_BUFFER *marshalled_sensitive,
TPM2B_MAX_BUFFER *protection_hmac_key,
TPM2B_MAX_BUFFER *protection_enc_key, TPMT_SYM_DEF_OBJECT *sym_alg,
@@ -390,7 +398,8 @@ void tpm2_identity_util_calculate_outer_integrity(TPMI_ALG_HASH parent_name_alg,
marshalled_sensitive->buffer, marshalled_sensitive->size,
NULL, 0, encrypted_duplicate_sensitive);
//Calculate outerHMAC
- hmac_outer_integrity(parent_name_alg, encrypted_duplicate_sensitive->buffer,
+ return hmac_outer_integrity(parent_name_alg,
+ encrypted_duplicate_sensitive->buffer,
encrypted_duplicate_sensitive->size, pubname->name, pubname->size,
protection_hmac_key->buffer, outer_hmac);
}
diff --git a/lib/tpm2_identity_util.h b/lib/tpm2_identity_util.h
index c298a62f..31ba6e6e 100644
--- a/lib/tpm2_identity_util.h
+++ b/lib/tpm2_identity_util.h
@@ -95,7 +95,7 @@ bool tpm2_identity_util_calculate_inner_integrity(TPMI_ALG_HASH name_alg,
* @param outer_hmac
* The outer HMAC structure to populate.
*/
-void tpm2_identity_util_calculate_outer_integrity(TPMI_ALG_HASH parent_name_alg,
+bool tpm2_identity_util_calculate_outer_integrity(TPMI_ALG_HASH parent_name_alg,
TPM2B_NAME *pubname, TPM2B_MAX_BUFFER *marshalled_sensitive,
TPM2B_MAX_BUFFER *protection_hmac_key,
TPM2B_MAX_BUFFER *protection_enc_key, TPMT_SYM_DEF_OBJECT *sym_alg,
diff --git a/tools/tpm2_duplicate.c b/tools/tpm2_duplicate.c
index 26f4ca1d..75f7d3c4 100644
--- a/tools/tpm2_duplicate.c
+++ b/tools/tpm2_duplicate.c
@@ -147,11 +147,14 @@ static tool_rc openssl_create_duplicate(void) {
*/
TPM2B_DIGEST outer_hmac = TPM2B_EMPTY_INIT;
TPM2B_MAX_BUFFER encrypted_duplicate_sensitive = TPM2B_EMPTY_INIT;
- tpm2_identity_util_calculate_outer_integrity(
+ bool outer_res = tpm2_identity_util_calculate_outer_integrity(
ctx.in_parent_public_key_data.publicArea.nameAlg,
&pubname, &marshalled_sensitive, &hmac_key, &enc_key,
&ctx.in_parent_public_key_data.publicArea.parameters.rsaDetail.symmetric,
&encrypted_duplicate_sensitive, &outer_hmac);
+ if (!outer_res) {
+ return tool_rc_general_error;
+ }
/*
* Build the private data structure for writing out
diff --git a/tools/tpm2_import.c b/tools/tpm2_import.c
index 480ed89a..ac33a05d 100644
--- a/tools/tpm2_import.c
+++ b/tools/tpm2_import.c
@@ -375,10 +375,15 @@ static tool_rc process_input_ossl_import(ESYS_CONTEXT *ectx) {
TPM2B_DIGEST outer_hmac = TPM2B_EMPTY_INIT;
TPM2B_MAX_BUFFER encrypted_duplicate_sensitive = TPM2B_EMPTY_INIT;
- tpm2_identity_util_calculate_outer_integrity(parent_pub->publicArea.nameAlg,
+ bool outer_res = tpm2_identity_util_calculate_outer_integrity(
+ parent_pub->publicArea.nameAlg,
&pubname, &encrypted_inner_integrity, &hmac_key, &enc_key,
&parent_pub->publicArea.parameters.rsaDetail.symmetric,
&encrypted_duplicate_sensitive, &outer_hmac);
+ if (!outer_res) {
+ rc = tool_rc_general_error;
+ goto out;
+ }
result = create_import_key_private_data(parent_pub->publicArea.nameAlg,
&encrypted_duplicate_sensitive, &outer_hmac);
diff --git a/tools/tpm2_makecredential.c b/tools/tpm2_makecredential.c
index f91533e8..b9098ee7 100644
--- a/tools/tpm2_makecredential.c
+++ b/tools/tpm2_makecredential.c
@@ -137,10 +137,13 @@ static tool_rc make_external_credential_and_save(void) {
*/
TPM2B_DIGEST outer_hmac = TPM2B_EMPTY_INIT;
TPM2B_MAX_BUFFER encrypted_sensitive = TPM2B_EMPTY_INIT;
- tpm2_identity_util_calculate_outer_integrity(name_alg, &ctx.object_name,
- &marshalled_inner_integrity, &hmac_key, &enc_key,
+ bool outer_res = tpm2_identity_util_calculate_outer_integrity(name_alg,
+ &ctx.object_name, &marshalled_inner_integrity, &hmac_key, &enc_key,
&ctx.public.publicArea.parameters.rsaDetail.symmetric,
&encrypted_sensitive, &outer_hmac);
+ if (!outer_res) {
+ return tool_rc_general_error;
+ }
/*
* Package up the info to save
--
2.54.0

View File

@ -2,7 +2,7 @@
Name: tpm2-tools
Version: 5.7
Release: 5%{?candidate:.%{candidate}}%{?dist}
Release: 6%{?candidate:.%{candidate}}%{?dist}
Summary: A bunch of TPM testing toolS build upon tpm2-tss
License: BSD-3-Clause
@ -43,9 +43,36 @@ Patch0018: 0018-tpm2_policy-Do-not-overflow-list-of-policy-digests.patch
patch0101: 0001-tpm2_clockrateadjust-Fix-segfault.patch
Patch0102: 0002-eventlog-TCG-PC-Client-FPF-renumbered-its-sections.patch
Patch0106: 0006-build-remove-trailing-comma.patch
Patch0201: 0001-tpm2_eventlog-Fix-parsing-on-big-endian-systems.patch
Patch0202: 0002-man-tpm2_policysigned-add-parameter-raw-data.patch
Patch0203: 0003-tpm2_loadexternal-Add-option-rsa_exponent_zero.patch
Patch0204: 0004-tpm2_quote-checkquote-Fix-usage-of-little-endian-ser.patch
Patch0205: 0005-tpm2_makecredential-Fix-usage-of-name-parameter.patch
Patch0206: 0006-tpm2_checkquote-Fix-indentation-in-parse_marshaled_s.patch
Patch0207: 0007-tpm2_checkquote-Fix-missing-error-checking.patch
Patch0208: 0008-tpm2_checkquote-Fix-memory-leaks-malloced-buffer-not.patch
Patch0209: 0009-tpm2_makecredential-fix-wrong-tcg-ek-templates.patch
Patch0210: 0010-tools-Fix-several-clang-tidy-errors.patch
Patch0211: 0011-tools-Fix-wrong-type-usage-of-enums.patch
Patch0212: 0012-tpm2_eventlog-Extend-pcrs-using-event-EV_IPL.patch
Patch0213: 0013-tpm2_nvcertify-Set-size-if-the-size-parameter-is-not.patch
Patch0214: 0014-tpm2_create-Fix-creation-of-ctx-file-if-TPM2_CreateL.patch
Patch0215: 0015-fix-checkquote-fix-off-by-one-in-PCR-digest-list-han.patch
Patch0216: 0016-tpm2_checkquote-Add-size-checks-for-PCR-desearializa.patch
Patch0217: 0017-fix-tpm2_send-validate-command_size-before-computing.patch
Patch0218: 0018-fix-tpm2_send-avoid-unintended-stdio-closing-in-clos.patch
Patch0219: 0019-fix-tpm2_util-fix-error-message-in-tpm2_pem_encoded_.patch
Patch0220: 0020-fix-tpm2_util-modify-tpm2_safe_read_from_stdin-to-re.patch
Patch0221: 0021-fix-tools-out-of-bounds-write-with-too-many-auxiliar.patch
Patch0222: 0022-fix-tpm2_alg_util-avoid-mutating-input-scheme-in-han.patch
Patch0223: 0023-fix-tools-add-missing-null-checks-after-malloc.patch
Patch0224: 0024-fix-test-add-missing-null-checks-after-malloc.patch
Patch0225: 0025-fix-tpm2_util-fix-buffer-overflow-in-string-validati.patch
Patch0226: 0026-Allocate-the-right-amount-of-memory-for-auth_policy.patch
Patch0227: 0027-tpm2_util-add-some-checks-to-tpm2_safe_read_from_std.patch
Patch0228: 0028-tpm2_createak-add-attribute-option.patch
Patch0229: 0029-fix-tpm2_loadexternal-check-return-value-of-RAND_byt.patch
Patch0230: 0030-fix-tpm2_identity_util-add-buffer-size-check.patch
# tpm2-tools is heavily depending on TPM2.0-TSS project, matched tss is required
Requires: tpm2-tss%{?_isa} >= 3.1.0
@ -80,6 +107,10 @@ autoreconf -i
%{_mandir}/man1/tss2_*.1.gz
%changelog
* Wed Apr 15 2026 Štěpán Horáček <shoracek@redhat.com> - 5.7-6
- Backport upstream fixes
Resolves: RHEL-164796
* Thu Aug 21 2025 Štěpán Horáček <shoracek@redhat.com> - 5.7-5
- Backport upstream fixes
Resolves: RHEL-94930