From 9983900131561e30d89a56501c5764e49c30b13a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20Hor=C3=A1=C4=8Dek?= Date: Thu, 16 Apr 2026 00:06:41 +0200 Subject: [PATCH] Backport upstream fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves: RHEL-164795 Signed-off-by: Štěpán Horáček --- 0001-Add-missing-include.patch | 24 ++ ...edential-Fix-usage-of-name-parameter.patch | 93 ++++++ ...Fix-indentation-in-parse_marshaled_s.patch | 51 ++++ ...heckquote-Fix-missing-error-checking.patch | 30 ++ ...Fix-memory-leaks-malloced-buffer-not.patch | 47 +++ ...creation-of-ctx-file-if-TPM2_CreateL.patch | 226 ++++++++++++++ ...ix-off-by-one-in-PCR-digest-list-han.patch | 66 ++++ ...Add-size-checks-for-PCR-desearializa.patch | 54 ++++ ...lidate-command_size-before-computing.patch | 44 +++ ...oid-unintended-stdio-closing-in-clos.patch | 27 ++ ...x-error-message-in-tpm2_pem_encoded_.patch | 27 ++ ...dify-tpm2_safe_read_from_stdin-to-re.patch | 70 +++++ ...-bounds-write-with-too-many-auxiliar.patch | 286 ++++++++++++++++++ ...l-avoid-mutating-input-scheme-in-han.patch | 123 ++++++++ ...add-missing-null-checks-after-malloc.patch | 56 ++++ ...x-buffer-overflow-in-string-validati.patch | 45 +++ ...ght-amount-of-memory-for-auth_policy.patch | 30 ++ ...me-checks-to-tpm2_safe_read_from_std.patch | 37 +++ ...ernal-check-return-value-of-RAND_byt.patch | 41 +++ ..._identity_util-add-buffer-size-check.patch | 151 +++++++++ tpm2-tools.spec | 27 +- 21 files changed, 1554 insertions(+), 1 deletion(-) create mode 100644 0001-Add-missing-include.patch create mode 100644 0001-tpm2_makecredential-Fix-usage-of-name-parameter.patch create mode 100644 0002-tpm2_checkquote-Fix-indentation-in-parse_marshaled_s.patch create mode 100644 0003-tpm2_checkquote-Fix-missing-error-checking.patch create mode 100644 0004-tpm2_checkquote-Fix-memory-leaks-malloced-buffer-not.patch create mode 100644 0006-tpm2_create-Fix-creation-of-ctx-file-if-TPM2_CreateL.patch create mode 100644 0007-fix-checkquote-fix-off-by-one-in-PCR-digest-list-han.patch create mode 100644 0008-tpm2_checkquote-Add-size-checks-for-PCR-desearializa.patch create mode 100644 0009-fix-tpm2_send-validate-command_size-before-computing.patch create mode 100644 0010-fix-tpm2_send-avoid-unintended-stdio-closing-in-clos.patch create mode 100644 0011-fix-tpm2_util-fix-error-message-in-tpm2_pem_encoded_.patch create mode 100644 0012-fix-tpm2_util-modify-tpm2_safe_read_from_stdin-to-re.patch create mode 100644 0013-fix-tools-out-of-bounds-write-with-too-many-auxiliar.patch create mode 100644 0014-fix-tpm2_alg_util-avoid-mutating-input-scheme-in-han.patch create mode 100644 0015-fix-tools-add-missing-null-checks-after-malloc.patch create mode 100644 0016-fix-tpm2_util-fix-buffer-overflow-in-string-validati.patch create mode 100644 0017-Allocate-the-right-amount-of-memory-for-auth_policy.patch create mode 100644 0018-tpm2_util-add-some-checks-to-tpm2_safe_read_from_std.patch create mode 100644 0019-fix-tpm2_loadexternal-check-return-value-of-RAND_byt.patch create mode 100644 0020-fix-tpm2_identity_util-add-buffer-size-check.patch diff --git a/0001-Add-missing-include.patch b/0001-Add-missing-include.patch new file mode 100644 index 0000000..9ae8b9c --- /dev/null +++ b/0001-Add-missing-include.patch @@ -0,0 +1,24 @@ +From baf581709a6a84983df5c212ad727c18dfee0992 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Fri, 29 May 2026 22:52:33 +0200 +Subject: [PATCH] Add missing include + +--- + lib/tpm2_capability.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/tpm2_capability.c b/lib/tpm2_capability.c +index 3bccaeca..3871aaa6 100644 +--- a/lib/tpm2_capability.c ++++ b/lib/tpm2_capability.c +@@ -3,6 +3,7 @@ + #include + #include + #include ++#include + + #include "log.h" + #include "tool_rc.h" +-- +2.54.0 + diff --git a/0001-tpm2_makecredential-Fix-usage-of-name-parameter.patch b/0001-tpm2_makecredential-Fix-usage-of-name-parameter.patch new file mode 100644 index 0000000..f8b8729 --- /dev/null +++ b/0001-tpm2_makecredential-Fix-usage-of-name-parameter.patch @@ -0,0 +1,93 @@ +From 31349de663413c28c3c4fa1f8966ead8a47d6133 Mon Sep 17 00:00:00 2001 +From: Juergen Repp +Date: Wed, 22 Oct 2025 12:57:18 +0200 +Subject: [PATCH 01/20] 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 +--- + 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 5bd5b484..1f7b558c 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 + diff --git a/0002-tpm2_checkquote-Fix-indentation-in-parse_marshaled_s.patch b/0002-tpm2_checkquote-Fix-indentation-in-parse_marshaled_s.patch new file mode 100644 index 0000000..bbc684b --- /dev/null +++ b/0002-tpm2_checkquote-Fix-indentation-in-parse_marshaled_s.patch @@ -0,0 +1,51 @@ +From 2509caebf3500bf747bb11bbfe097fda275ed416 Mon Sep 17 00:00:00 2001 +From: Dimitrios Siganos +Date: Sun, 9 Nov 2025 11:41:34 +0000 +Subject: [PATCH 02/20] tpm2_checkquote: Fix indentation in + parse_marshaled_selection_data + +Signed-off-by: Dimitrios Siganos +--- + 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 fb4d5868..8abf75e6 100644 +--- a/tools/misc/tpm2_checkquote.c ++++ b/tools/misc/tpm2_checkquote.c +@@ -373,19 +373,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 + diff --git a/0003-tpm2_checkquote-Fix-missing-error-checking.patch b/0003-tpm2_checkquote-Fix-missing-error-checking.patch new file mode 100644 index 0000000..950760f --- /dev/null +++ b/0003-tpm2_checkquote-Fix-missing-error-checking.patch @@ -0,0 +1,30 @@ +From 5c20a472e856b10301a4c5c0c02dc49b594f6c3f Mon Sep 17 00:00:00 2001 +From: Dimitrios Siganos +Date: Sun, 9 Nov 2025 11:50:52 +0000 +Subject: [PATCH 03/20] tpm2_checkquote: Fix missing error checking + +The return of malloc was not checked + +Signed-off-by: Dimitrios Siganos +--- + 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 8abf75e6..abd09619 100644 +--- a/tools/misc/tpm2_checkquote.c ++++ b/tools/misc/tpm2_checkquote.c +@@ -350,6 +350,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 + diff --git a/0004-tpm2_checkquote-Fix-memory-leaks-malloced-buffer-not.patch b/0004-tpm2_checkquote-Fix-memory-leaks-malloced-buffer-not.patch new file mode 100644 index 0000000..17b05f1 --- /dev/null +++ b/0004-tpm2_checkquote-Fix-memory-leaks-malloced-buffer-not.patch @@ -0,0 +1,47 @@ +From 62846ee6a0c79d0098bcd5bece2af5955c4e3646 Mon Sep 17 00:00:00 2001 +From: Dimitrios Siganos +Date: Sun, 9 Nov 2025 11:53:21 +0000 +Subject: [PATCH 04/20] 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 +--- + 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 abd09619..0c0427da 100644 +--- a/tools/misc/tpm2_checkquote.c ++++ b/tools/misc/tpm2_checkquote.c +@@ -357,7 +357,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); +@@ -374,7 +374,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++) { +@@ -385,6 +385,7 @@ static bool parse_marshaled_selection_data(FILE *pcr_input, + goto error; + } + } ++ free(buffer); + return true; + + error: +-- +2.54.0 + diff --git a/0006-tpm2_create-Fix-creation-of-ctx-file-if-TPM2_CreateL.patch b/0006-tpm2_create-Fix-creation-of-ctx-file-if-TPM2_CreateL.patch new file mode 100644 index 0000000..9088517 --- /dev/null +++ b/0006-tpm2_create-Fix-creation-of-ctx-file-if-TPM2_CreateL.patch @@ -0,0 +1,226 @@ +From 0c563fee6c9b4cecd347420581019b62feeb51c2 Mon Sep 17 00:00:00 2001 +From: Juergen Repp +Date: Wed, 14 Jan 2026 08:34:13 +0100 +Subject: [PATCH 06/20] 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 +--- + lib/tpm2.c | 67 +++++++++++++++++++++++++++++++++---------- + lib/tpm2.h | 4 ++- + lib/tpm2_capability.c | 37 ++++++++++++++++++++++++ + tools/tpm2_create.c | 14 ++------- + 4 files changed, 94 insertions(+), 28 deletions(-) + +diff --git a/lib/tpm2.c b/lib/tpm2.c +index 27f101e9..2f8991f2 100644 +--- a/lib/tpm2.c ++++ b/lib/tpm2.c +@@ -1425,15 +1425,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) { +@@ -1442,9 +1459,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; +@@ -1480,19 +1497,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 ed5f246d..8809ca3e 100644 +--- a/lib/tpm2.h ++++ b/lib/tpm2.h +@@ -62,6 +62,8 @@ tool_rc tpm2_sess_get_noncetpm(ESYS_CONTEXT *esys_context, + tool_rc tpm2_policy_restart(ESYS_CONTEXT *esys_context, ESYS_TR session_handle, + ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3); + ++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, + UINT32 property, UINT32 property_count, TPMI_YES_NO *more_data, +@@ -199,7 +201,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 95c332d0..3bccaeca 100644 +--- a/lib/tpm2_capability.c ++++ b/lib/tpm2_capability.c +@@ -5,6 +5,7 @@ + #include + + #include "log.h" ++#include "tool_rc.h" + #include "tpm2.h" + #include "tpm2_capability.h" + +@@ -26,6 +27,42 @@ + 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(ESYS_CONTEXT *ectx, TPM2_CAP capability, + UINT32 property, UINT32 count, TPMS_CAPABILITY_DATA **capability_data) { + +diff --git a/tools/tpm2_create.c b/tools/tpm2_create.c +index 1c75c384..9e1757d7 100644 +--- a/tools/tpm2_create.c ++++ b/tools/tpm2_create.c +@@ -118,19 +118,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 + diff --git a/0007-fix-checkquote-fix-off-by-one-in-PCR-digest-list-han.patch b/0007-fix-checkquote-fix-off-by-one-in-PCR-digest-list-han.patch new file mode 100644 index 0000000..9926d18 --- /dev/null +++ b/0007-fix-checkquote-fix-off-by-one-in-PCR-digest-list-han.patch @@ -0,0 +1,66 @@ +From b543b618d8937d8d8ef351935ad6d132171699a1 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 07/20] 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 0c0427da..4c820208 100644 +--- a/tools/misc/tpm2_checkquote.c ++++ b/tools/misc/tpm2_checkquote.c +@@ -260,29 +260,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 + diff --git a/0008-tpm2_checkquote-Add-size-checks-for-PCR-desearializa.patch b/0008-tpm2_checkquote-Add-size-checks-for-PCR-desearializa.patch new file mode 100644 index 0000000..7f56c92 --- /dev/null +++ b/0008-tpm2_checkquote-Add-size-checks-for-PCR-desearializa.patch @@ -0,0 +1,54 @@ +From ca2d039f073bf3544a0ba3915c586769d724a0a3 Mon Sep 17 00:00:00 2001 +From: Juergen Repp +Date: Tue, 3 Feb 2026 16:18:46 +0100 +Subject: [PATCH 08/20] 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 +--- + 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 4c820208..4f8ae74b 100644 +--- a/tools/misc/tpm2_checkquote.c ++++ b/tools/misc/tpm2_checkquote.c +@@ -299,6 +299,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); + } +@@ -325,9 +329,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 + diff --git a/0009-fix-tpm2_send-validate-command_size-before-computing.patch b/0009-fix-tpm2_send-validate-command_size-before-computing.patch new file mode 100644 index 0000000..9e6042d --- /dev/null +++ b/0009-fix-tpm2_send-validate-command_size-before-computing.patch @@ -0,0 +1,44 @@ +From 5abee441971dcc8e98077748058704d71edcf0e1 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 09/20] 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 94936a0a..27f6dca1 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, + 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 + diff --git a/0010-fix-tpm2_send-avoid-unintended-stdio-closing-in-clos.patch b/0010-fix-tpm2_send-avoid-unintended-stdio-closing-in-clos.patch new file mode 100644 index 0000000..a487bbb --- /dev/null +++ b/0010-fix-tpm2_send-avoid-unintended-stdio-closing-in-clos.patch @@ -0,0 +1,27 @@ +From 07eaf78eb14c818a10ee5a835b76e81ccfd2ad2f 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 10/20] 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 27f6dca1..18b3a733 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 + diff --git a/0011-fix-tpm2_util-fix-error-message-in-tpm2_pem_encoded_.patch b/0011-fix-tpm2_util-fix-error-message-in-tpm2_pem_encoded_.patch new file mode 100644 index 0000000..0a3adc4 --- /dev/null +++ b/0011-fix-tpm2_util-fix-error-message-in-tpm2_pem_encoded_.patch @@ -0,0 +1,27 @@ +From 0c0035e606862ba0a37daab890162ae3de07b975 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 11/20] 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 31204b56..d9ca57e7 100644 +--- a/lib/tpm2_util.c ++++ b/lib/tpm2_util.c +@@ -1069,7 +1069,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 + diff --git a/0012-fix-tpm2_util-modify-tpm2_safe_read_from_stdin-to-re.patch b/0012-fix-tpm2_util-modify-tpm2_safe_read_from_stdin-to-re.patch new file mode 100644 index 0000000..87c65fc --- /dev/null +++ b/0012-fix-tpm2_util-modify-tpm2_safe_read_from_stdin-to-re.patch @@ -0,0 +1,70 @@ +From 8e4b970a8c1523c6af7c35e662a3ad41a5d31e3c 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 12/20] 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 d9ca57e7..a5facec7 100644 +--- a/lib/tpm2_util.c ++++ b/lib/tpm2_util.c +@@ -3,6 +3,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1000,28 +1001,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 + diff --git a/0013-fix-tools-out-of-bounds-write-with-too-many-auxiliar.patch b/0013-fix-tools-out-of-bounds-write-with-too-many-auxiliar.patch new file mode 100644 index 0000000..49ade98 --- /dev/null +++ b/0013-fix-tools-out-of-bounds-write-with-too-many-auxiliar.patch @@ -0,0 +1,286 @@ +From 35274ee8e236b379081e02b13c8c610170250463 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 13/20] 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_nvdefine.c | 8 ++++---- + tools/tpm2_nvextend.c | 8 ++++---- + tools/tpm2_nvread.c | 9 ++++----- + tools/tpm2_nvsetbits.c | 9 ++++----- + 12 files changed, 47 insertions(+), 57 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 38dd626b..7d5146b0 100644 +--- a/tools/tpm2_certify.c ++++ b/tools/tpm2_certify.c +@@ -315,13 +315,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 c301aad5..c5070d10 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 4b65ea9e..014b71b5 100644 +--- a/tools/tpm2_changeauth.c ++++ b/tools/tpm2_changeauth.c +@@ -309,13 +309,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; + /*no default */ + } +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 9e1757d7..2aea7ffc 100644 +--- a/tools/tpm2_create.c ++++ b/tools/tpm2_create.c +@@ -515,13 +515,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_nvdefine.c b/tools/tpm2_nvdefine.c +index 7f193e83..650eb205 100644 +--- a/tools/tpm2_nvdefine.c ++++ b/tools/tpm2_nvdefine.c +@@ -428,12 +428,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 44fb1e81..84d94fe6 100644 +--- a/tools/tpm2_nvextend.c ++++ b/tools/tpm2_nvextend.c +@@ -224,12 +224,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_nvread.c b/tools/tpm2_nvread.c +index 8f9c61cc..ea7d389f 100644 +--- a/tools/tpm2_nvread.c ++++ b/tools/tpm2_nvread.c +@@ -321,13 +321,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_nvsetbits.c b/tools/tpm2_nvsetbits.c +index feb4d938..89ff1ccd 100644 +--- a/tools/tpm2_nvsetbits.c ++++ b/tools/tpm2_nvsetbits.c +@@ -237,13 +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 { +- 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 + diff --git a/0014-fix-tpm2_alg_util-avoid-mutating-input-scheme-in-han.patch b/0014-fix-tpm2_alg_util-avoid-mutating-input-scheme-in-han.patch new file mode 100644 index 0000000..8a04f06 --- /dev/null +++ b/0014-fix-tpm2_alg_util-avoid-mutating-input-scheme-in-han.patch @@ -0,0 +1,123 @@ +From d154f8bf3688269fbe9bcfcf2f02a9f1fd513bdf 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 14/20] 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 | 52 ++++++++++++++++++++++++--------------------- + 1 file changed, 28 insertions(+), 24 deletions(-) + +diff --git a/lib/tpm2_alg_util.c b/lib/tpm2_alg_util.c +index 580f41cb..f66ec7bb 100644 +--- a/lib/tpm2_alg_util.c ++++ b/lib/tpm2_alg_util.c +@@ -153,9 +153,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; \ +@@ -175,16 +175,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; +@@ -194,49 +196,51 @@ 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, "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, "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 + diff --git a/0015-fix-tools-add-missing-null-checks-after-malloc.patch b/0015-fix-tools-add-missing-null-checks-after-malloc.patch new file mode 100644 index 0000000..149b8f2 --- /dev/null +++ b/0015-fix-tools-add-missing-null-checks-after-malloc.patch @@ -0,0 +1,56 @@ +From 3f0538eecd0f53fc4f9a09bad73418f0f058519a 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 15/20] fix(tools): add missing null checks after malloc + +Signed-off-by: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com> +--- + tools/tpm2_getekcertificate.c | 9 +++++++++ + tools/tpm2_verifysignature.c | 4 ++++ + 2 files changed, 13 insertions(+) + +diff --git a/tools/tpm2_getekcertificate.c b/tools/tpm2_getekcertificate.c +index b8fa5647..b824d59c 100644 +--- a/tools/tpm2_getekcertificate.c ++++ b/tools/tpm2_getekcertificate.c +@@ -381,6 +381,11 @@ static bool retrieve_web_endorsement_certificate(char *b64h) { + * rsa_cert_buffer for either RSA EK cert or ECC EK cert. + */ + ctx.rsa_cert_buffer = malloc(CURL_MAX_WRITE_SIZE); ++ if (!ctx.rsa_cert_buffer) { ++ LOG_ERR("oom"); ++ ret = false; ++ goto out_easy_cleanup; ++ } + rc = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)ctx.rsa_cert_buffer); + if (rc != CURLE_OK) { + LOG_ERR("curl_easy_setopt for CURLOPT_WRITEDATA failed: %s", +@@ -666,6 +671,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_verifysignature.c b/tools/tpm2_verifysignature.c +index e09dd48c..55e78263 100644 +--- a/tools/tpm2_verifysignature.c ++++ b/tools/tpm2_verifysignature.c +@@ -193,6 +193,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 + diff --git a/0016-fix-tpm2_util-fix-buffer-overflow-in-string-validati.patch b/0016-fix-tpm2_util-fix-buffer-overflow-in-string-validati.patch new file mode 100644 index 0000000..987a2cb --- /dev/null +++ b/0016-fix-tpm2_util-fix-buffer-overflow-in-string-validati.patch @@ -0,0 +1,45 @@ +From 11874a7231fb8a6dae77f63aaec62fd733a3ef53 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 16/20] 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 a5facec7..e1f4ff91 100644 +--- a/lib/tpm2_util.c ++++ b/lib/tpm2_util.c +@@ -1017,22 +1017,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 + diff --git a/0017-Allocate-the-right-amount-of-memory-for-auth_policy.patch b/0017-Allocate-the-right-amount-of-memory-for-auth_policy.patch new file mode 100644 index 0000000..be92f3a --- /dev/null +++ b/0017-Allocate-the-right-amount-of-memory-for-auth_policy.patch @@ -0,0 +1,30 @@ +From 5d9dc0a5abb716f6c30c8fa6c47f31fabf8ae5f7 Mon Sep 17 00:00:00 2001 +From: Andreas Fuchs +Date: Tue, 10 Feb 2026 09:20:05 +0100 +Subject: [PATCH 17/20] 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 + +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 459d3d03..c30323f4 100644 +--- a/tools/tpm2_setprimarypolicy.c ++++ b/tools/tpm2_setprimarypolicy.c +@@ -123,7 +123,7 @@ static tool_rc process_setprimarypolicy_input(ESYS_CONTEXT *ectx, + */ + if (ctx.policy_path) { + +- *auth_policy = malloc(UINT16_MAX + sizeof(uint16_t)); ++ *auth_policy = malloc(sizeof(**auth_policy)); + if (!*auth_policy) { + LOG_ERR("oom"); + return tool_rc_general_error; +-- +2.54.0 + diff --git a/0018-tpm2_util-add-some-checks-to-tpm2_safe_read_from_std.patch b/0018-tpm2_util-add-some-checks-to-tpm2_safe_read_from_std.patch new file mode 100644 index 0000000..b964ba4 --- /dev/null +++ b/0018-tpm2_util-add-some-checks-to-tpm2_safe_read_from_std.patch @@ -0,0 +1,37 @@ +From f1083844194a8ce1467d6fcf2481ab3092a1c936 Mon Sep 17 00:00:00 2001 +From: Juergen Repp +Date: Sun, 8 Mar 2026 15:59:20 +0100 +Subject: [PATCH 18/20] 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 +--- + lib/tpm2_util.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/lib/tpm2_util.c b/lib/tpm2_util.c +index e1f4ff91..a09166d9 100644 +--- a/lib/tpm2_util.c ++++ b/lib/tpm2_util.c +@@ -1011,6 +1011,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 + diff --git a/0019-fix-tpm2_loadexternal-check-return-value-of-RAND_byt.patch b/0019-fix-tpm2_loadexternal-check-return-value-of-RAND_byt.patch new file mode 100644 index 0000000..8994a7a --- /dev/null +++ b/0019-fix-tpm2_loadexternal-check-return-value-of-RAND_byt.patch @@ -0,0 +1,41 @@ +From 887387a7fb12c570f813aa8ed1de22367fe60a5a 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 19/20] 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 2cd4411f..1aa37ff0 100644 +--- a/tools/tpm2_loadexternal.c ++++ b/tools/tpm2_loadexternal.c +@@ -267,7 +267,11 @@ static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { + TPM2B_DIGEST *seed = &priv.sensitiveArea.seedValue; + seed->size = tpm2_alg_util_get_hash_size(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 + diff --git a/0020-fix-tpm2_identity_util-add-buffer-size-check.patch b/0020-fix-tpm2_identity_util-add-buffer-size-check.patch new file mode 100644 index 0000000..ae76a77 --- /dev/null +++ b/0020-fix-tpm2_identity_util-add-buffer-size-check.patch @@ -0,0 +1,151 @@ +From 92139de454e5aecfb11bf9ccba5a5bd2e8052cc6 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 20/20] 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 | 5 ++++- + tools/tpm2_makecredential.c | 7 +++++-- + 5 files changed, 26 insertions(+), 8 deletions(-) + +diff --git a/lib/tpm2_identity_util.c b/lib/tpm2_identity_util.c +index 781b34c9..759d0cd6 100644 +--- a/lib/tpm2_identity_util.c ++++ b/lib/tpm2_identity_util.c +@@ -268,11 +268,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); +@@ -284,6 +291,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, +@@ -359,7 +367,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, +@@ -373,7 +381,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 b64e8fcb..88a70f95 100644 +--- a/tools/tpm2_duplicate.c ++++ b/tools/tpm2_duplicate.c +@@ -315,10 +315,13 @@ static tool_rc tpm2_create_duplicate( + */ + 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, &marshalled_sensitive, &hmac_key, &enc_key, + &parent_pub->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 3a8c5c34..b7b1687e 100644 +--- a/tools/tpm2_import.c ++++ b/tools/tpm2_import.c +@@ -155,10 +155,13 @@ static tool_rc key_import(ESYS_CONTEXT *ectx, TPM2B_PUBLIC *parent_pub, + + 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) { ++ return tool_rc_general_error; ++ } + + TPM2B_PRIVATE private = TPM2B_EMPTY_INIT; + res = create_import_key_private_data(&private, parent_pub->publicArea.nameAlg, +diff --git a/tools/tpm2_makecredential.c b/tools/tpm2_makecredential.c +index 2a3d137a..dc1cb5e8 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 + diff --git a/tpm2-tools.spec b/tpm2-tools.spec index 1dc9aae..f71b5be 100644 --- a/tpm2-tools.spec +++ b/tpm2-tools.spec @@ -2,7 +2,7 @@ Name: tpm2-tools Version: 5.2 -Release: 7%{?candidate:.%{candidate}}%{?dist} +Release: 8%{?candidate:.%{candidate}}%{?dist} Summary: A bunch of TPM testing toolS build upon tpm2-tss License: BSD @@ -59,6 +59,27 @@ Patch402: 0001-tpm2_eventlog-Fix-parsing-on-big-endian-systems.patch Patch403: 0001-tpm2_quote-checkquote-Fix-usage-of-little-endian-ser.patch Patch404: add_pregenerated_doc_2.patch +Patch501: 0001-tpm2_makecredential-Fix-usage-of-name-parameter.patch +Patch502: 0002-tpm2_checkquote-Fix-indentation-in-parse_marshaled_s.patch +Patch503: 0003-tpm2_checkquote-Fix-missing-error-checking.patch +Patch504: 0004-tpm2_checkquote-Fix-memory-leaks-malloced-buffer-not.patch +Patch506: 0006-tpm2_create-Fix-creation-of-ctx-file-if-TPM2_CreateL.patch +Patch507: 0007-fix-checkquote-fix-off-by-one-in-PCR-digest-list-han.patch +Patch508: 0008-tpm2_checkquote-Add-size-checks-for-PCR-desearializa.patch +Patch509: 0009-fix-tpm2_send-validate-command_size-before-computing.patch +Patch510: 0010-fix-tpm2_send-avoid-unintended-stdio-closing-in-clos.patch +Patch511: 0011-fix-tpm2_util-fix-error-message-in-tpm2_pem_encoded_.patch +Patch512: 0012-fix-tpm2_util-modify-tpm2_safe_read_from_stdin-to-re.patch +Patch513: 0013-fix-tools-out-of-bounds-write-with-too-many-auxiliar.patch +Patch514: 0014-fix-tpm2_alg_util-avoid-mutating-input-scheme-in-han.patch +Patch515: 0015-fix-tools-add-missing-null-checks-after-malloc.patch +Patch516: 0016-fix-tpm2_util-fix-buffer-overflow-in-string-validati.patch +Patch517: 0017-Allocate-the-right-amount-of-memory-for-auth_policy.patch +Patch518: 0018-tpm2_util-add-some-checks-to-tpm2_safe_read_from_std.patch +Patch519: 0019-fix-tpm2_loadexternal-check-return-value-of-RAND_byt.patch +Patch520: 0020-fix-tpm2_identity_util-add-buffer-size-check.patch +Patch521: 0001-Add-missing-include.patch + BuildRequires: git BuildRequires: make BuildRequires: gcc-c++ @@ -110,6 +131,10 @@ touch man/man1/* %{_mandir}/man1/tss2_*.1.gz %changelog +* Wed Apr 15 2026 Štěpán Horáček - 5.2-8 +- Backport upstream fixes. + Resolves: RHEL-164795 + * Thu Sep 18 2025 Štěpán Horáček - 5.2-7 - Fix endianity issues. Resolves: RHEL-79885