From ecf50d1faa72a7654a1c1039d4fef39324a1241f Mon Sep 17 00:00:00 2001 From: Aidan Date: Tue, 21 Apr 2026 10:16:48 -0700 Subject: [PATCH 01/16] F-3245 - https://fenrir.wolfssl.com/finding/3245 - Add positive+negative HMAC check test for wolfSPDM_ParseKeyExchangeRsp --- src/spdm/unit_test.c | 173 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) diff --git a/src/spdm/unit_test.c b/src/spdm/unit_test.c index 209b0d29..acfcf24a 100644 --- a/src/spdm/unit_test.c +++ b/src/spdm/unit_test.c @@ -540,6 +540,178 @@ static int test_mitm_signature_rejected(void) TEST_PASS(); } +/* Drive wolfSPDM_ParseKeyExchangeRsp past the signature check and exercise + * the ResponderVerifyData HMAC compare. The fixture reuses a single P-384 + * key pair as both requester and responder identity so the test can + * produce a signature that the parse path will accept; everything after + * (ECDH, KDF, HMAC) then runs on real inputs. */ +static int test_key_exchange_rsp_hmac_check(void) +{ + byte keRsp[300]; + const word32 keRspLen = 282; + const word32 keRspPartialLen = 138; + ecc_key ltKey; + ecc_key respEphem; + ecc_key ourPubKey; + byte ltPriv[48], ltPubX[48], ltPubY[48], ltPub[96]; + word32 ltPrivSz = 48, ltPubXSz = 48, ltPubYSz = 48; + byte respPubX[48], respPubY[48]; + word32 respPubXSz = 48, respPubYSz = 48; + byte ourPubX[48], ourPubY[48]; + word32 ourXSz = 48, ourYSz = 48; + byte sharedSecret[64]; + word32 sharedSz = sizeof(sharedSecret); + byte signMsg[160]; + word32 signMsgLen = 0; + byte th1SigHash[WOLFSPDM_HASH_SIZE]; + byte signMsgHash[WOLFSPDM_HASH_SIZE]; + byte th1[WOLFSPDM_HASH_SIZE]; + byte sigRaw[WOLFSPDM_ECC_SIG_SIZE]; + word32 sigRawSz = WOLFSPDM_ECC_SIG_SIZE; + byte expectedHmac[WOLFSPDM_HASH_SIZE]; + const char* ctxStr = "responder-key_exchange_rsp signing"; + const word32 ctxStrLen = 34; + word32 zeroPadLen; + int i, rc; + WOLFSPDM_CTX helperBuf; + WOLFSPDM_CTX* helper = &helperBuf; + TEST_CTX_SETUP_V12(); + + printf("test_key_exchange_rsp_hmac_check...\n"); + + /* Long-term P-384 key, shared between requester (for test signing) + * and responder (for parse verification) */ + ASSERT_SUCCESS(wc_ecc_init(<Key)); + ASSERT_SUCCESS(wc_ecc_make_key(&ctx->rng, 48, <Key)); + ASSERT_SUCCESS(wc_ecc_export_private_only(<Key, ltPriv, <PrivSz)); + ASSERT_SUCCESS(wc_ecc_export_public_raw(<Key, + ltPubX, <PubXSz, ltPubY, <PubYSz)); + if (ltPrivSz < 48) { + XMEMMOVE(ltPriv + (48 - ltPrivSz), ltPriv, ltPrivSz); + XMEMSET(ltPriv, 0, 48 - ltPrivSz); + } + if (ltPubXSz < 48) { + XMEMMOVE(ltPubX + (48 - ltPubXSz), ltPubX, ltPubXSz); + XMEMSET(ltPubX, 0, 48 - ltPubXSz); + } + if (ltPubYSz < 48) { + XMEMMOVE(ltPubY + (48 - ltPubYSz), ltPubY, ltPubYSz); + XMEMSET(ltPubY, 0, 48 - ltPubYSz); + } + XMEMCPY(ltPub, ltPubX, 48); + XMEMCPY(ltPub + 48, ltPubY, 48); + ASSERT_SUCCESS(wolfSPDM_SetRequesterKeyPair(ctx, ltPriv, 48, ltPub, 96)); + ASSERT_SUCCESS(wolfSPDM_SetResponderPubKey(ctx, ltPub, 96)); + + /* Our ephemeral ECDH key (requester side). Some wolfSSL builds + * (e.g. ECC_TIMING_RESISTANT) require an RNG on the ECDH private + * key for blinding; ensure one is attached for wc_ecc_shared_secret. */ + ASSERT_SUCCESS(wolfSPDM_GenerateEphemeralKey(ctx)); + ASSERT_SUCCESS(wc_ecc_set_rng(&ctx->ephemeralKey, &ctx->rng)); + ASSERT_SUCCESS(wolfSPDM_ExportEphemeralPubKey(ctx, + ourPubX, &ourXSz, ourPubY, &ourYSz)); + + /* Responder ephemeral ECDH key (simulated responder side) */ + ASSERT_SUCCESS(wc_ecc_init(&respEphem)); + ASSERT_SUCCESS(wc_ecc_make_key(&ctx->rng, 48, &respEphem)); + ASSERT_SUCCESS(wc_ecc_set_rng(&respEphem, &ctx->rng)); + ASSERT_SUCCESS(wc_ecc_export_public_raw(&respEphem, + respPubX, &respPubXSz, respPubY, &respPubYSz)); + if (respPubXSz < 48) { + XMEMMOVE(respPubX + (48 - respPubXSz), respPubX, respPubXSz); + XMEMSET(respPubX, 0, 48 - respPubXSz); + } + if (respPubYSz < 48) { + XMEMMOVE(respPubY + (48 - respPubYSz), respPubY, respPubYSz); + XMEMSET(respPubY, 0, 48 - respPubYSz); + } + + /* Build partial KE_RSP (bytes 0..137) */ + XMEMSET(keRsp, 0, sizeof(keRsp)); + keRsp[0] = SPDM_VERSION_12; + keRsp[1] = SPDM_KEY_EXCHANGE_RSP; + SPDM_Set16LE(&keRsp[4], 0x1234); + XMEMSET(&keRsp[8], 0x5A, 32); + XMEMCPY(&keRsp[40], respPubX, 48); + XMEMCPY(&keRsp[88], respPubY, 48); + SPDM_Set16LE(&keRsp[136], 0); + + /* th1SigHash = Hash(transcript + partial KE_RSP); transcript starts empty */ + ASSERT_SUCCESS(wolfSPDM_Sha384Hash(th1SigHash, + keRsp, keRspPartialLen, NULL, 0, NULL, 0)); + + /* Replicate wolfSPDM_BuildSignedHash for SPDM 1.2 over th1SigHash */ + signMsgLen = 0; + for (i = 0; i < 4; i++) { + XMEMCPY(&signMsg[signMsgLen], "dmtf-spdm-v1.2.*", 16); + signMsgLen += 16; + } + zeroPadLen = 36 - ctxStrLen; + XMEMSET(&signMsg[signMsgLen], 0, zeroPadLen); + signMsgLen += zeroPadLen; + XMEMCPY(&signMsg[signMsgLen], ctxStr, ctxStrLen); + signMsgLen += ctxStrLen; + XMEMCPY(&signMsg[signMsgLen], th1SigHash, WOLFSPDM_HASH_SIZE); + signMsgLen += WOLFSPDM_HASH_SIZE; + ASSERT_SUCCESS(wolfSPDM_Sha384Hash(signMsgHash, + signMsg, signMsgLen, NULL, 0, NULL, 0)); + + /* Sign with long-term key; wolfSPDM_SignHash pads R||S to 96 bytes */ + sigRawSz = WOLFSPDM_ECC_SIG_SIZE; + ASSERT_SUCCESS(wolfSPDM_SignHash(ctx, signMsgHash, WOLFSPDM_HASH_SIZE, + sigRaw, &sigRawSz)); + XMEMCPY(&keRsp[138], sigRaw, WOLFSPDM_ECC_SIG_SIZE); + + /* TH1 = Hash(partial || signature) */ + ASSERT_SUCCESS(wolfSPDM_Sha384Hash(th1, + keRsp, keRspPartialLen + WOLFSPDM_ECC_SIG_SIZE, NULL, 0, NULL, 0)); + + /* Shared secret from responder ephemeral and our public key (mirrors + * ECDH(our_priv, resp_pub) that parse will compute on ctx) */ + ASSERT_SUCCESS(wc_ecc_init(&ourPubKey)); + ASSERT_SUCCESS(wc_ecc_import_unsigned(&ourPubKey, + ourPubX, ourPubY, NULL, ECC_SECP384R1)); + ASSERT_SUCCESS(wc_ecc_shared_secret(&respEphem, &ourPubKey, + sharedSecret, &sharedSz)); + wc_ecc_free(&ourPubKey); + if (sharedSz < 48) { + XMEMMOVE(sharedSecret + (48 - sharedSz), sharedSecret, sharedSz); + XMEMSET(sharedSecret, 0, 48 - sharedSz); + } + sharedSz = 48; + + /* Derive rspFinishedKey via a throwaway helper ctx */ + ASSERT_SUCCESS(wolfSPDM_Init(helper)); + helper->spdmVersion = SPDM_VERSION_12; + XMEMCPY(helper->sharedSecret, sharedSecret, 48); + helper->sharedSecretSz = 48; + ASSERT_SUCCESS(wolfSPDM_DeriveHandshakeKeys(helper, th1)); + ASSERT_SUCCESS(wolfSPDM_ComputeVerifyData( + helper->rspFinishedKey, th1, expectedHmac)); + wolfSPDM_Free(helper); + + /* Positive: valid HMAC must succeed and advance state to KEY_EX */ + XMEMCPY(&keRsp[234], expectedHmac, WOLFSPDM_HASH_SIZE); + rc = wolfSPDM_ParseKeyExchangeRsp(ctx, keRsp, keRspLen); + ASSERT_EQ(rc, WOLFSPDM_SUCCESS, "valid HMAC should succeed"); + ASSERT_EQ(ctx->state, WOLFSPDM_STATE_KEY_EX, + "state should advance to KEY_EX on valid parse"); + + /* Negative: a single bit flip in rspVerifyData must be rejected. + * Reset transcript/state only; keep ephemeral key so ECDH reproduces. */ + wolfSPDM_TranscriptReset(ctx); + ctx->state = WOLFSPDM_STATE_INIT; + keRsp[234] ^= 0x01; + rc = wolfSPDM_ParseKeyExchangeRsp(ctx, keRsp, keRspLen); + ASSERT_EQ(rc, WOLFSPDM_E_BAD_HMAC, + "flipped rspVerifyData byte must return BAD_HMAC"); + + wc_ecc_free(<Key); + wc_ecc_free(&respEphem); + TEST_CTX_FREE(); + TEST_PASS(); +} + /* Test Fix 4: Invalid curve point must be rejected by ComputeSharedSecret */ static int test_invalid_curve_point(void) { @@ -1937,6 +2109,7 @@ int main(void) /* Security tests */ test_mitm_signature_rejected(); + test_key_exchange_rsp_hmac_check(); test_invalid_curve_point(); #ifdef WOLFTPM_SPDM_TCG test_tcg_underflow(); From 15420588a2c704dc28d16617e6e5a45349b47594 Mon Sep 17 00:00:00 2001 From: Aidan Date: Tue, 21 Apr 2026 10:25:03 -0700 Subject: [PATCH 02/16] F-3246 - https://fenrir.wolfssl.com/finding/3246 - Add positive+negative HMAC check test for wolfSPDM_ParsePskExchangeRsp --- src/spdm/unit_test.c | 66 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/spdm/unit_test.c b/src/spdm/unit_test.c index acfcf24a..7f15c2e3 100644 --- a/src/spdm/unit_test.c +++ b/src/spdm/unit_test.c @@ -1572,6 +1572,71 @@ static int test_parse_psk_exchange_rsp_null_args(void) TEST_PASS(); } +/* Drive wolfSPDM_ParsePskExchangeRsp through key derivation to exercise + * the PSK ResponderVerifyData HMAC compare. Previously only NULL/short- + * buffer paths were covered, so mutations of the `if (diff != 0)` block + * or of `diff |= ...` → `diff &= ...` survived every test. */ +static int test_parse_psk_exchange_rsp_hmac_check(void) +{ + byte pskRsp[64]; + const word32 pskRspLen = 60; /* 12-byte partial + 48 HMAC */ + const word32 pskRspPartialLen = 12; + byte psk[48]; + byte th1[WOLFSPDM_HASH_SIZE]; + byte expectedHmac[WOLFSPDM_HASH_SIZE]; + int rc; + WOLFSPDM_CTX helperBuf; + WOLFSPDM_CTX* helper = &helperBuf; + TEST_CTX_SETUP_V12(); + + printf("test_parse_psk_exchange_rsp_hmac_check...\n"); + + XMEMSET(psk, 0xA5, sizeof(psk)); + + /* Build PSK_EXCHANGE_RSP partial (12 bytes): rspContextLen=0, opaqueLen=0 */ + XMEMSET(pskRsp, 0, sizeof(pskRsp)); + pskRsp[0] = SPDM_VERSION_12; + pskRsp[1] = SPDM_PSK_EXCHANGE_RSP; + SPDM_Set16LE(&pskRsp[4], 0x1234); /* RspSessionID */ + SPDM_Set16LE(&pskRsp[8], 0); /* RspContextLength */ + SPDM_Set16LE(&pskRsp[10], 0); /* OpaqueDataLength */ + + /* TH1 = Hash(transcript + partial); transcript starts empty */ + ASSERT_SUCCESS(wolfSPDM_Sha384Hash(th1, + pskRsp, pskRspPartialLen, NULL, 0, NULL, 0)); + + /* Derive rspFinishedKey on a throwaway helper ctx */ + ASSERT_SUCCESS(wolfSPDM_Init(helper)); + helper->spdmVersion = SPDM_VERSION_12; + ASSERT_SUCCESS(wolfSPDM_SetPSK(helper, psk, sizeof(psk), NULL, 0)); + ASSERT_SUCCESS(wolfSPDM_DeriveHandshakeKeysPsk(helper, th1)); + ASSERT_SUCCESS(wolfSPDM_ComputeVerifyData( + helper->rspFinishedKey, th1, expectedHmac)); + wolfSPDM_Free(helper); + + /* Positive: correct HMAC must succeed and advance state to KEY_EX */ + XMEMCPY(&pskRsp[12], expectedHmac, WOLFSPDM_HASH_SIZE); + ASSERT_SUCCESS(wolfSPDM_SetPSK(ctx, psk, sizeof(psk), NULL, 0)); + rc = wolfSPDM_ParsePskExchangeRsp(ctx, pskRsp, pskRspLen); + ASSERT_EQ(rc, WOLFSPDM_SUCCESS, "valid PSK HMAC should succeed"); + ASSERT_EQ(ctx->state, WOLFSPDM_STATE_KEY_EX, + "state should advance to KEY_EX on valid PSK parse"); + + /* Negative: flip one byte — must return BAD_HMAC. + * Parse scrubs ctx->psk after derivation, so re-set it; also reset + * transcript because the successful parse appended 60 bytes. */ + wolfSPDM_TranscriptReset(ctx); + ctx->state = WOLFSPDM_STATE_INIT; + ASSERT_SUCCESS(wolfSPDM_SetPSK(ctx, psk, sizeof(psk), NULL, 0)); + pskRsp[12] ^= 0x01; + rc = wolfSPDM_ParsePskExchangeRsp(ctx, pskRsp, pskRspLen); + ASSERT_EQ(rc, WOLFSPDM_E_BAD_HMAC, + "flipped PSK rspVerifyData byte must return BAD_HMAC"); + + TEST_CTX_FREE(); + TEST_PASS(); +} + static int test_build_psk_finish_null_args(void) { byte buf[128]; @@ -2162,6 +2227,7 @@ int main(void) #endif #ifdef WOLFTPM_SPDM_PSK test_parse_psk_exchange_rsp_null_args(); + test_parse_psk_exchange_rsp_hmac_check(); test_build_psk_finish_null_args(); test_build_psk_finish_format(); test_parse_psk_finish_rsp(); From a987bc14b6d37e742be902af1ba1c7959df5dc59 Mon Sep 17 00:00:00 2001 From: Aidan Date: Tue, 21 Apr 2026 10:29:24 -0700 Subject: [PATCH 03/16] F-3247 - https://fenrir.wolfssl.com/finding/3247 - Add missing semicolon to TriCore SPI extern declaration --- hal/tpm_io_infineon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hal/tpm_io_infineon.c b/hal/tpm_io_infineon.c index 81c8e8af..4d4726b0 100644 --- a/hal/tpm_io_infineon.c +++ b/hal/tpm_io_infineon.c @@ -186,7 +186,7 @@ #include /* externally declared SPI master channel */ - extern IfxQspi_SpiMaster_Channel spiMasterChannel + extern IfxQspi_SpiMaster_Channel spiMasterChannel; static int TPM2_IoCb_Infineon_TriCore_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, word16 xferSz, void* userCtx) From bfed6a6c69039404dd827a167d55d501b631c209 Mon Sep 17 00:00:00 2001 From: Aidan Date: Tue, 21 Apr 2026 10:31:52 -0700 Subject: [PATCH 04/16] F-3248 - https://fenrir.wolfssl.com/finding/3248 - Reset busy_retry inside i2c_write outer loop to match i2c_read --- hal/tpm_io_microchip.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hal/tpm_io_microchip.c b/hal/tpm_io_microchip.c index 461e4f6a..114ca0bc 100644 --- a/hal/tpm_io_microchip.c +++ b/hal/tpm_io_microchip.c @@ -223,6 +223,8 @@ return -1; } + busy_retry = TPM_I2C_TRIES; + while (I2C_BB_IsBusy() && --busy_retry > 0) { microchip_wait(250); } From 55faf11f2714cec9eba0497a4564bb4335b558c0 Mon Sep 17 00:00:00 2001 From: Aidan Date: Tue, 21 Apr 2026 10:32:50 -0700 Subject: [PATCH 05/16] F-3249 - https://fenrir.wolfssl.com/finding/3249 - Check wc_HashGetDigestSize return with signed int before assigning to word32 --- examples/pkcs7/pkcs7.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/pkcs7/pkcs7.c b/examples/pkcs7/pkcs7.c index 65f3de46..3101e78c 100644 --- a/examples/pkcs7/pkcs7.c +++ b/examples/pkcs7/pkcs7.c @@ -115,10 +115,11 @@ static int PKCS7_SignVerifyEx(WOLFTPM2_DEV* dev, int tpmDevId, XMEMSET(&pkcs7, 0, sizeof(pkcs7)); - hashSz = wc_HashGetDigestSize(hashType); - if (hashSz <= 0) { - return hashSz; + rc = wc_HashGetDigestSize(hashType); + if (rc <= 0) { + return BAD_FUNC_ARG; } + hashSz = (word32)rc; /* calculate hash for content */ rc = wc_HashInit(&hash, hashType); From 6d28982a3d06c4d7b13e12817d3681159b9a0f3e Mon Sep 17 00:00:00 2001 From: Aidan Date: Tue, 21 Apr 2026 10:41:35 -0700 Subject: [PATCH 06/16] F-3250 - https://fenrir.wolfssl.com/finding/3250 - Route IFX firmware abandon path through exit label to run cleanup --- examples/firmware/ifx_fw_update.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/firmware/ifx_fw_update.c b/examples/firmware/ifx_fw_update.c index 5320d26e..967b6481 100644 --- a/examples/firmware/ifx_fw_update.c +++ b/examples/firmware/ifx_fw_update.c @@ -170,7 +170,7 @@ int TPM2_IFX_Firmware_Update(void* userCtx, int argc, char *argv[]) else { printf("Success: Please reset or power cycle TPM\n"); } - return rc; + goto exit; } if (manifest_file == NULL || firmware_file == NULL) { From f684ab4a8c5eba4f9503a83021bbbd46721c34ad Mon Sep 17 00:00:00 2001 From: Aidan Date: Tue, 21 Apr 2026 10:59:23 -0700 Subject: [PATCH 07/16] F-3251 - https://fenrir.wolfssl.com/finding/3251 - Use TPM2_Packet_ParseEccScheme in TPM2_ECC_Parameters to consume ECDAA count --- src/tpm2.c | 5 +---- tests/unit_tests.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/tpm2.c b/src/tpm2.c index 8c54f843..33b313aa 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -2310,10 +2310,7 @@ TPM_RC TPM2_ECC_Parameters(ECC_Parameters_In* in, TPM2_Packet_ParseU16(&packet, &out->parameters.kdf.details.any.hashAlg); - TPM2_Packet_ParseU16(&packet, &out->parameters.sign.scheme); - if (out->parameters.sign.scheme != TPM_ALG_NULL) - TPM2_Packet_ParseU16(&packet, - &out->parameters.sign.details.any.hashAlg); + TPM2_Packet_ParseEccScheme(&packet, &out->parameters.sign); TPM2_Packet_ParseU16Buf(&packet, &out->parameters.p.size, out->parameters.p.buffer, diff --git a/tests/unit_tests.c b/tests/unit_tests.c index 3d6b9f11..aba37751 100644 --- a/tests/unit_tests.c +++ b/tests/unit_tests.c @@ -1824,6 +1824,53 @@ static void test_TPM2_SchemeSerialize(void) printf("Test TPM Wrapper:\tSchemeSerialize:\t\tPassed\n"); } +/* Exercise the parse sequence used by TPM2_ECC_Parameters response: sign + * scheme = ECDAA (scheme + hashAlg + count) followed by a trailing U16 + * size field. Ensures the ECDAA count byte is consumed so the next read + * lands at the correct offset. The wire bytes are built by hand to avoid + * relying on non-exported packet helpers. */ +static void test_TPM2_ECC_Parameters_EcdaaResponseParse(void) +{ + TPM2_Packet packet; + byte buf[32]; + TPMT_SIG_SCHEME signOut; + UINT16 pSizeOut = 0; + + /* Hand-built wire: TPM2B wire is big-endian. + * [0-1] sign.scheme = TPM_ALG_ECDAA (0x001A) + * [2-3] sign.hashAlg = TPM_ALG_SHA256 (0x000B) + * [4-5] sign.count = 0x0007 + * [6-7] p.size sentinel= 0x0030 + */ + XMEMSET(buf, 0, sizeof(buf)); + buf[0] = 0x00; buf[1] = (byte)TPM_ALG_ECDAA; + buf[2] = 0x00; buf[3] = (byte)TPM_ALG_SHA256; + buf[4] = 0x00; buf[5] = 0x07; + buf[6] = 0x00; buf[7] = 0x30; + + XMEMSET(&packet, 0, sizeof(packet)); + packet.buf = buf; + packet.size = sizeof(buf); + packet.pos = 0; + + XMEMSET(&signOut, 0, sizeof(signOut)); + TPM2_Packet_ParseEccScheme(&packet, &signOut); + AssertIntEQ(signOut.scheme, TPM_ALG_ECDAA); + AssertIntEQ(signOut.details.ecdaa.hashAlg, TPM_ALG_SHA256); + AssertIntEQ(signOut.details.ecdaa.count, 7); + + /* After parsing the ECDAA scheme, packet.pos must be at byte 6 so the + * next U16 read returns the sentinel 0x0030 (the simulated p.size). + * The buggy inline parser in TPM2_ECC_Parameters consumed only + * scheme+hashAlg (4 bytes) and left the count on the wire, which + * would make p.size read 0x0007 instead. */ + AssertIntEQ(packet.pos, 6); + pSizeOut = (UINT16)((buf[packet.pos] << 8) | buf[packet.pos + 1]); + AssertIntEQ(pSizeOut, 0x0030); + + printf("Test TPM Wrapper:\tEcdaaResponseParse:\t\tPassed\n"); +} + static void test_TPM2_KeyedHashScheme_XorSerialize(void) { TPM2_Packet packet; @@ -3163,6 +3210,7 @@ int unit_tests(int argc, char *argv[]) test_wolfTPM2_ComputeName(); #endif test_TPM2_SchemeSerialize(); + test_TPM2_ECC_Parameters_EcdaaResponseParse(); test_TPM2_KeyedHashScheme_XorSerialize(); test_TPM2_Signature_EcSchnorrSm2Serialize(); test_TPM2_Sensitive_Roundtrip(); From 70ec60779f56e3983c98de0cf68753529d9fff1e Mon Sep 17 00:00:00 2001 From: Aidan Date: Tue, 21 Apr 2026 11:37:50 -0700 Subject: [PATCH 08/16] F-3264 - https://fenrir.wolfssl.com/finding/3264 - Validate pcrIndex range after XATOI in quote example --- examples/pcr/quote.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/pcr/quote.c b/examples/pcr/quote.c index b0c9dee3..4c756750 100644 --- a/examples/pcr/quote.c +++ b/examples/pcr/quote.c @@ -98,12 +98,17 @@ int TPM2_PCR_Quote_Test(void* userCtx, int argc, char *argv[]) /* Advanced usage */ if (argv[1][0] != '-') { - if (pcrIndex < 0 || pcrIndex > 23 || *argv[1] < '0' || *argv[1] > '9') { + if (*argv[1] < '0' || *argv[1] > '9') { printf("PCR index is out of range (0-23)\n"); usage(); return 0; } pcrIndex = XATOI(argv[1]); + if (pcrIndex < 0 || pcrIndex > 23) { + printf("PCR index is out of range (0-23)\n"); + usage(); + return 0; + } } if (argc >= 3 && argv[2][0] != '-') outputFile = argv[2]; From 428bf7bff56c5071fdb141c7708b8b6c5a57c95f Mon Sep 17 00:00:00 2001 From: Aidan Date: Tue, 21 Apr 2026 11:37:59 -0700 Subject: [PATCH 09/16] F-3265 - https://fenrir.wolfssl.com/finding/3265 - Route ST33 firmware abandon path through exit label to run cleanup --- examples/firmware/st33_fw_update.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/firmware/st33_fw_update.c b/examples/firmware/st33_fw_update.c index 100301be..998caa6d 100644 --- a/examples/firmware/st33_fw_update.c +++ b/examples/firmware/st33_fw_update.c @@ -264,7 +264,7 @@ int TPM2_ST33_Firmware_Update(void* userCtx, int argc, char *argv[]) else { printf("Success: Please reset or power cycle TPM\n"); } - return rc; + goto exit; } if (fi_file == NULL) { From a3b77ff2dd0614adabbb0592be9ed3ae49733f90 Mon Sep 17 00:00:00 2001 From: Aidan Date: Tue, 21 Apr 2026 11:58:36 -0700 Subject: [PATCH 10/16] F-3266 - https://fenrir.wolfssl.com/finding/3266 - Fix off-by-one >= to > in READ_BE16/READ_BE32 and data chunk length checks --- examples/firmware/ifx_fw_extract.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/firmware/ifx_fw_extract.c b/examples/firmware/ifx_fw_extract.c index 28dbe889..264b6cfe 100644 --- a/examples/firmware/ifx_fw_extract.c +++ b/examples/firmware/ifx_fw_extract.c @@ -63,7 +63,7 @@ #define LOG(t) { printf(__FILE__":%i: %s\n", __LINE__, t); } #define READ_BE16(dest, buf, size, off) { \ - if (off + sizeof(dest) >= size) { \ + if (off + sizeof(dest) > size) { \ LOG("FW file too short"); \ return -1; \ } \ @@ -73,7 +73,7 @@ } #define READ_BE32(dest, buf, size, off) { \ - if (off + sizeof(dest) >= size) { \ + if (off + sizeof(dest) > size) { \ LOG("FW file too short"); \ return -1; \ } \ @@ -172,7 +172,7 @@ static int extractFW( } READ_BE32(size32, fw, fw_size, offset); - if (offset + size32 >= fw_size) { + if (offset + size32 > fw_size) { LOG("FW file too short"); return -1; } From eb34ac0a07081af53def8823d4bdf5d53eb92f7a Mon Sep 17 00:00:00 2001 From: Aidan Date: Tue, 21 Apr 2026 12:28:11 -0700 Subject: [PATCH 11/16] F-3263 - https://fenrir.wolfssl.com/finding/3263 - Make fwTPM password auth compare constant-time over fixed bound --- src/fwtpm/fwtpm_command.c | 62 +++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/src/fwtpm/fwtpm_command.c b/src/fwtpm/fwtpm_command.c index 99ddb603..006e73db 100644 --- a/src/fwtpm/fwtpm_command.c +++ b/src/fwtpm/fwtpm_command.c @@ -429,6 +429,39 @@ static void FwLookupEntityAuth(FWTPM_CTX* ctx, TPM_HANDLE handle, } } +/* Constant-time password vs authValue comparison. + * Iterates a fixed upper bound (TPM_MAX_DIGEST_SIZE) with bitwise masks so + * neither the trip count nor per-iteration work depends on the secret + * authValSz. Trailing zeros on either side are treated as insignificant + * (matches TCG reference for authValues padded to nameAlg digest size). + * Returns 1 on mismatch, 0 on match. */ +static int FwCtAuthCompare(const byte* password, int pwSz, + const byte* authVal, int avSz) +{ + byte zeroAuth[TPM_MAX_DIGEST_SIZE]; + const byte* avPtr; + volatile byte diff = 0; + int ci; + + XMEMSET(zeroAuth, 0, sizeof(zeroAuth)); + avPtr = (authVal != NULL) ? authVal : zeroAuth; + + for (ci = 0; ci < TPM_MAX_DIGEST_SIZE; ci++) { + /* 0xFF if ci < bound, else 0x00 (bounds are at most 64) */ + byte pwMask = (byte)-(((unsigned)(ci - pwSz)) >> 31); + byte avMask = (byte)-(((unsigned)(ci - avSz)) >> 31); + byte overlap = (byte)(pwMask & avMask); + /* Overlap region: bytes must match */ + diff |= (byte)((password[ci] ^ avPtr[ci]) & overlap); + /* Trailing bytes of pw past avSz must be zero */ + diff |= (byte)(password[ci] & (pwMask & (byte)~avMask)); + /* Trailing bytes of av past pwSz must be zero */ + diff |= (byte)(avPtr[ci] & (avMask & (byte)~pwMask)); + } + + return ((int)diff != 0) ? 1 : 0; +} + /* Compute cpHash = H(commandCode || name1 || ... || cpBuffer) * Per TPM 2.0 Part 1 Section 18.7 */ static int FwComputeCpHash(TPMI_ALG_HASH hashAlg, TPM_CC cmdCode, @@ -12719,9 +12752,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, int doEncRsp = 0; /* Encrypt outgoing response param */ #endif int pj, hj; /* Loop indices for auth validation */ - int pwSz, avSz, maxSz, minSz, authFail; /* Password comparison */ - volatile byte diff; - int ci; + int authFail; /* Password comparison result */ if (ctx == NULL || cmdBuf == NULL || rspBuf == NULL || rspSize == NULL) { return BAD_FUNC_ARG; @@ -13085,29 +13116,8 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, FwLookupEntityAuth(ctx, entityH, &authVal, &authValSz); - /* Compare password with authValue in constant time. - * Per TCG reference implementation, trailing zeros are - * insignificant (handles authValues padded to nameAlg - * digest size). We compare up to the max of both sizes - * and verify trailing bytes are zero, all in constant - * time to avoid leaking the effective auth length. */ - diff = 0; - pwSz = (int)cmdAuths[pj].passwordSize; - avSz = authValSz; - maxSz = (pwSz > avSz) ? pwSz : avSz; - minSz = (pwSz < avSz) ? pwSz : avSz; - /* Compare overlapping portion */ - for (ci = 0; ci < minSz; ci++) { - diff |= cmdAuths[pj].password[ci] ^ authVal[ci]; - } - /* Verify trailing bytes of the longer buffer are zero */ - for (ci = minSz; ci < maxSz; ci++) { - if (ci < pwSz) - diff |= cmdAuths[pj].password[ci]; - if (ci < avSz) - diff |= authVal[ci]; - } - authFail = ((int)diff != 0); + authFail = FwCtAuthCompare(cmdAuths[pj].password, + (int)cmdAuths[pj].passwordSize, authVal, authValSz); if (authFail) { #ifdef DEBUG_WOLFTPM printf("fwTPM: Password auth failed for handle " From 3310a8c78ba870097f44ffb614feab698399d14b Mon Sep 17 00:00:00 2001 From: Aidan Date: Tue, 21 Apr 2026 12:56:17 -0700 Subject: [PATCH 12/16] F-3267 - https://fenrir.wolfssl.com/finding/3267 - Return BUFFER_E instead of silently truncating oversize auth in NVCreateAuthPolicy, LoadKeyedHashKey, HmacStart, HashStart --- src/tpm2_wrap.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 7ff6a79d..b660b9b9 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -5706,7 +5706,7 @@ int wolfTPM2_NVCreateAuthPolicy(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent, in.authHandle = parent->hndl; if (auth != NULL && authSz > 0) { if (authSz > (int)sizeof(in.auth.buffer)) - authSz = (int)sizeof(in.auth.buffer); + return BUFFER_E; in.auth.size = authSz; XMEMCPY(in.auth.buffer, auth, in.auth.size); } @@ -6375,10 +6375,10 @@ int wolfTPM2_HashStart(WOLFTPM2_DEV* dev, WOLFTPM2_HASH* hash, (usageAuthSz > 0 && usageAuth == NULL)) { return BAD_FUNC_ARG; } + if (usageAuthSz > sizeof(hash->handle.auth.buffer)) + return BUFFER_E; /* Capture usage auth */ - if (usageAuthSz > sizeof(hash->handle.auth.buffer)) - usageAuthSz = sizeof(hash->handle.auth.buffer); XMEMSET(hash, 0, sizeof(WOLFTPM2_HASH)); hash->handle.auth.size = usageAuthSz; if (usageAuth != NULL) @@ -6833,6 +6833,10 @@ int wolfTPM2_LoadKeyedHashKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, if (keySz == 0 || keySz > MAX_SYM_DATA) { return BUFFER_E; } + if (usageAuth != NULL && usageAuthSz > + sizeof(createIn.inSensitive.sensitive.userAuth.buffer)) { + return BUFFER_E; + } hashAlgDigSz = TPM2_GetHashDigestSize(hashAlg); if (hashAlgDigSz <= 0) { @@ -6848,11 +6852,6 @@ int wolfTPM2_LoadKeyedHashKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, XMEMSET(&createIn, 0, sizeof(createIn)); createIn.parentHandle = parent->hndl; if (usageAuth) { - if (usageAuthSz > - sizeof(createIn.inSensitive.sensitive.userAuth.buffer)) { - usageAuthSz = - sizeof(createIn.inSensitive.sensitive.userAuth.buffer); /* truncate */ - } createIn.inSensitive.sensitive.userAuth.size = usageAuthSz; XMEMCPY(createIn.inSensitive.sensitive.userAuth.buffer, usageAuth, usageAuthSz); @@ -6925,11 +6924,13 @@ int wolfTPM2_HmacStart(WOLFTPM2_DEV* dev, WOLFTPM2_HMAC* hmac, if (dev == NULL || hmac == NULL || hashAlg == TPM_ALG_NULL) { return BAD_FUNC_ARG; } + if (usageAuth != NULL && + usageAuthSz > sizeof(hmac->hash.handle.auth.buffer)) { + return BUFFER_E; + } if (usageAuth != NULL) { /* Capture usage auth */ - if (usageAuthSz > sizeof(hmac->hash.handle.auth.buffer)) - usageAuthSz = sizeof(hmac->hash.handle.auth.buffer); /* truncate */ hmac->hash.handle.auth.size = usageAuthSz; XMEMCPY(hmac->hash.handle.auth.buffer, usageAuth, usageAuthSz); } From a1341f0460cb1fd2ad0235dfa1f1175412b0ea7a Mon Sep 17 00:00:00 2001 From: Aidan Date: Tue, 21 Apr 2026 13:13:03 -0700 Subject: [PATCH 13/16] F-3268 - https://fenrir.wolfssl.com/finding/3268 - Return BUFFER_E on oversize authPolicy digest in wolfTPM2_NVCreateAuthPolicy --- src/tpm2_wrap.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index b660b9b9..91b84900 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -5695,6 +5695,15 @@ int wolfTPM2_NVCreateAuthPolicy(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent, if (dev == NULL || nv == NULL || parent == NULL) { return BAD_FUNC_ARG; } + if (auth != NULL && authSz > 0 && + authSz > (int)sizeof(in.auth.buffer)) { + return BUFFER_E; + } + if (authPolicy != NULL && authPolicySz > 0 && + authPolicySz > + (int)sizeof(in.publicInfo.nvPublic.authPolicy.buffer)) { + return BUFFER_E; + } /* set session auth for key */ if (dev->ctx.session && !parent->policyAuth) { @@ -5705,8 +5714,6 @@ int wolfTPM2_NVCreateAuthPolicy(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent, XMEMSET(&in, 0, sizeof(in)); in.authHandle = parent->hndl; if (auth != NULL && authSz > 0) { - if (authSz > (int)sizeof(in.auth.buffer)) - return BUFFER_E; in.auth.size = authSz; XMEMCPY(in.auth.buffer, auth, in.auth.size); } @@ -5715,11 +5722,6 @@ int wolfTPM2_NVCreateAuthPolicy(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent, in.publicInfo.nvPublic.attributes = nvAttributes; in.publicInfo.nvPublic.dataSize = (UINT16)maxSize; if (authPolicy != NULL && authPolicySz > 0) { - if (authPolicySz > - (int)sizeof(in.publicInfo.nvPublic.authPolicy.buffer)) { - authPolicySz = - (int)sizeof(in.publicInfo.nvPublic.authPolicy.buffer); - } in.publicInfo.nvPublic.authPolicy.size = authPolicySz; XMEMCPY(in.publicInfo.nvPublic.authPolicy.buffer, authPolicy, in.publicInfo.nvPublic.authPolicy.size); From 712669e074fcb43b51b77561585ba2477c5cb7b5 Mon Sep 17 00:00:00 2001 From: Aidan Date: Tue, 21 Apr 2026 13:18:17 -0700 Subject: [PATCH 14/16] F-3269 - https://fenrir.wolfssl.com/finding/3269 - Zeroize stack-local auth buffer in FwCmd_NV_DefineSpace before return --- src/fwtpm/fwtpm_command.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fwtpm/fwtpm_command.c b/src/fwtpm/fwtpm_command.c index 006e73db..1c91f455 100644 --- a/src/fwtpm/fwtpm_command.c +++ b/src/fwtpm/fwtpm_command.c @@ -10008,6 +10008,7 @@ static TPM_RC FwCmd_NV_DefineSpace(FWTPM_CTX* ctx, TPM2_Packet* cmd, FwRspNoParams(rsp, cmdTag); } + TPM2_ForceZero(&auth, sizeof(auth)); return rc; } From 76a2c6a40f92abe8a81ffe28bf8a63c35d6d3d3c Mon Sep 17 00:00:00 2001 From: Aidan Date: Tue, 21 Apr 2026 13:28:27 -0700 Subject: [PATCH 15/16] F-3270 - https://fenrir.wolfssl.com/finding/3270 - Clamp caller-supplied list counts in TPM2_PCR_Extend, TPM2_SetCommandCodeAuditStatus, TPM2_PolicyOR --- src/tpm2.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/tpm2.c b/src/tpm2.c index 33b313aa..95b11ced 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -1307,11 +1307,15 @@ TPM_RC TPM2_PCR_Extend(PCR_Extend_In* in) info.inHandleCnt = 1; info.flags = (CMD_FLAG_AUTH_USER1); + UINT32 count = in->digests.count; + if (count > HASH_COUNT) + count = HASH_COUNT; + TPM2_Packet_Init(ctx, &packet); TPM2_Packet_AppendU32(&packet, in->pcrHandle); TPM2_Packet_AppendAuth(&packet, ctx, &info); - TPM2_Packet_AppendU32(&packet, in->digests.count); - for (i=0; i<(int)in->digests.count; i++) { + TPM2_Packet_AppendU32(&packet, count); + for (i=0; i<(int)count; i++) { UINT16 hashAlg = in->digests.digests[i].hashAlg; int digestSz = TPM2_GetHashDigestSize(hashAlg); TPM2_Packet_AppendU16(&packet, hashAlg); @@ -3331,15 +3335,22 @@ TPM_RC TPM2_SetCommandCodeAuditStatus(SetCommandCodeAuditStatus_In* in) TPM2_Packet_AppendAuth(&packet, ctx, &info); + UINT32 setCount = in->setList.count; + UINT32 clearCount = in->clearList.count; + if (setCount > MAX_CAP_CC) + setCount = MAX_CAP_CC; + if (clearCount > MAX_CAP_CC) + clearCount = MAX_CAP_CC; + TPM2_Packet_AppendU16(&packet, in->auditAlg); - TPM2_Packet_AppendU32(&packet, in->setList.count); - for (i=0; i<(int)in->setList.count; i++) { + TPM2_Packet_AppendU32(&packet, setCount); + for (i=0; i<(int)setCount; i++) { TPM2_Packet_AppendU32(&packet, in->setList.commandCodes[i]); } - TPM2_Packet_AppendU32(&packet, in->clearList.count); - for (i=0; i<(int)in->clearList.count; i++) { + TPM2_Packet_AppendU32(&packet, clearCount); + for (i=0; i<(int)clearCount; i++) { TPM2_Packet_AppendU32(&packet, in->clearList.commandCodes[i]); } @@ -3739,12 +3750,19 @@ TPM_RC TPM2_PolicyOR(PolicyOR_In* in) if (rc == TPM_RC_SUCCESS) { int i; TPM2_Packet packet; + const UINT32 digestsMax = + (UINT32)(sizeof(in->pHashList.digests) / + sizeof(in->pHashList.digests[0])); + UINT32 count = in->pHashList.count; + if (count > digestsMax) + count = digestsMax; + TPM2_Packet_Init(ctx, &packet); TPM2_Packet_AppendU32(&packet, in->policySession); - TPM2_Packet_AppendU32(&packet, in->pHashList.count); - for (i=0; i<(int)in->pHashList.count; i++) { + TPM2_Packet_AppendU32(&packet, count); + for (i=0; i<(int)count; i++) { TPM2_Packet_AppendU16(&packet, in->pHashList.digests[i].size); TPM2_Packet_AppendBytes(&packet, in->pHashList.digests[i].buffer, From c5145d88da87880a42eb3b5e7c24420ea5bd7136 Mon Sep 17 00:00:00 2001 From: Aidan Date: Tue, 21 Apr 2026 13:32:55 -0700 Subject: [PATCH 16/16] F-3271 - https://fenrir.wolfssl.com/finding/3271 - Use TPM2_Packet_AppendSensitive in TPM2_LoadExternal and extend roundtrip test coverage --- examples/pkcs7/pkcs7.c | 5 +++- src/fwtpm/fwtpm_command.c | 15 ++++++++---- src/tpm2.c | 49 +++++++++++++-------------------------- tests/unit_tests.c | 48 +++++++++++++++++++++++++++++++++++++- 4 files changed, 78 insertions(+), 39 deletions(-) diff --git a/examples/pkcs7/pkcs7.c b/examples/pkcs7/pkcs7.c index 3101e78c..f58699b2 100644 --- a/examples/pkcs7/pkcs7.c +++ b/examples/pkcs7/pkcs7.c @@ -117,7 +117,10 @@ static int PKCS7_SignVerifyEx(WOLFTPM2_DEV* dev, int tpmDevId, rc = wc_HashGetDigestSize(hashType); if (rc <= 0) { - return BAD_FUNC_ARG; + /* Preserve the wolfCrypt error on negatives; for a 0 return + * (not currently produced by wolfCrypt), report BAD_FUNC_ARG + * rather than masquerading as success. */ + return (rc < 0) ? rc : BAD_FUNC_ARG; } hashSz = (word32)rc; diff --git a/src/fwtpm/fwtpm_command.c b/src/fwtpm/fwtpm_command.c index 1c91f455..67ea1239 100644 --- a/src/fwtpm/fwtpm_command.c +++ b/src/fwtpm/fwtpm_command.c @@ -434,7 +434,8 @@ static void FwLookupEntityAuth(FWTPM_CTX* ctx, TPM_HANDLE handle, * neither the trip count nor per-iteration work depends on the secret * authValSz. Trailing zeros on either side are treated as insignificant * (matches TCG reference for authValues padded to nameAlg digest size). - * Returns 1 on mismatch, 0 on match. */ + * Returns 1 on mismatch, 0 on match. Precondition: pwSz and avSz must + * each be <= TPM_MAX_DIGEST_SIZE; out-of-range inputs fail closed. */ static int FwCtAuthCompare(const byte* password, int pwSz, const byte* authVal, int avSz) { @@ -443,13 +444,19 @@ static int FwCtAuthCompare(const byte* password, int pwSz, volatile byte diff = 0; int ci; + if (pwSz < 0 || avSz < 0 || + pwSz > TPM_MAX_DIGEST_SIZE || avSz > TPM_MAX_DIGEST_SIZE) { + return 1; + } + XMEMSET(zeroAuth, 0, sizeof(zeroAuth)); avPtr = (authVal != NULL) ? authVal : zeroAuth; for (ci = 0; ci < TPM_MAX_DIGEST_SIZE; ci++) { - /* 0xFF if ci < bound, else 0x00 (bounds are at most 64) */ - byte pwMask = (byte)-(((unsigned)(ci - pwSz)) >> 31); - byte avMask = (byte)-(((unsigned)(ci - avSz)) >> 31); + /* 0xFF if ci < bound, else 0x00. Use UINT32 (guaranteed 32-bit + * wolfTPM typedef) so the >> 31 shift is always well-defined. */ + byte pwMask = (byte)-((UINT32)(ci - pwSz) >> 31); + byte avMask = (byte)-((UINT32)(ci - avSz) >> 31); byte overlap = (byte)(pwMask & avMask); /* Overlap region: bytes must match */ diff |= (byte)((password[ci] ^ avPtr[ci]) & overlap); diff --git a/src/tpm2.c b/src/tpm2.c index 95b11ced..e5092789 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -1304,10 +1304,11 @@ TPM_RC TPM2_PCR_Extend(PCR_Extend_In* in) int i; TPM2_Packet packet; CmdInfo_t info = {0,0,0,0}; + UINT32 count; info.inHandleCnt = 1; info.flags = (CMD_FLAG_AUTH_USER1); - UINT32 count = in->digests.count; + count = in->digests.count; if (count > HASH_COUNT) count = HASH_COUNT; @@ -1723,34 +1724,14 @@ TPM_RC TPM2_LoadExternal(LoadExternal_In* in, LoadExternal_Out* out) TPM2_Packet_Init(ctx, &packet); st = TPM2_Packet_AppendAuth(&packet, ctx, &info); + /* Reading sensitive.any.size is valid regardless of sensitiveType: + * every TPM2B variant in TPMU_SENSITIVE_COMPOSITE has UINT16 size + * at offset 0, so the .any view reliably reflects the populated + * typed member (common-initial-sequence aliasing). */ if (in->inPrivate.sensitiveArea.authValue.size > 0 || in->inPrivate.sensitiveArea.seedValue.size > 0 || in->inPrivate.sensitiveArea.sensitive.any.size > 0) { - - in->inPrivate.size = 2 + /* sensitiveType */ - 2 + in->inPrivate.sensitiveArea.authValue.size + - 2 + in->inPrivate.sensitiveArea.seedValue.size + - 2 + in->inPrivate.sensitiveArea.sensitive.any.size; - TPM2_Packet_AppendU16(&packet, in->inPrivate.size); - - TPM2_Packet_AppendU16(&packet, - in->inPrivate.sensitiveArea.sensitiveType); - TPM2_Packet_AppendU16(&packet, - in->inPrivate.sensitiveArea.authValue.size); - TPM2_Packet_AppendBytes(&packet, - in->inPrivate.sensitiveArea.authValue.buffer, - in->inPrivate.sensitiveArea.authValue.size); - TPM2_Packet_AppendU16(&packet, - in->inPrivate.sensitiveArea.seedValue.size); - TPM2_Packet_AppendBytes(&packet, - in->inPrivate.sensitiveArea.seedValue.buffer, - in->inPrivate.sensitiveArea.seedValue.size); - - TPM2_Packet_AppendU16(&packet, - in->inPrivate.sensitiveArea.sensitive.any.size); - TPM2_Packet_AppendBytes(&packet, - in->inPrivate.sensitiveArea.sensitive.any.buffer, - in->inPrivate.sensitiveArea.sensitive.any.size); + TPM2_Packet_AppendSensitive(&packet, &in->inPrivate); } else { TPM2_Packet_AppendU16(&packet, 0); @@ -3326,22 +3307,24 @@ TPM_RC TPM2_SetCommandCodeAuditStatus(SetCommandCodeAuditStatus_In* in) int i; TPM2_Packet packet; CmdInfo_t info = {0,0,0,0}; + UINT32 setCount; + UINT32 clearCount; info.inHandleCnt = 1; info.flags = (CMD_FLAG_AUTH_USER1); + setCount = in->setList.count; + clearCount = in->clearList.count; + if (setCount > MAX_CAP_CC) + setCount = MAX_CAP_CC; + if (clearCount > MAX_CAP_CC) + clearCount = MAX_CAP_CC; + TPM2_Packet_Init(ctx, &packet); TPM2_Packet_AppendU32(&packet, in->auth); TPM2_Packet_AppendAuth(&packet, ctx, &info); - UINT32 setCount = in->setList.count; - UINT32 clearCount = in->clearList.count; - if (setCount > MAX_CAP_CC) - setCount = MAX_CAP_CC; - if (clearCount > MAX_CAP_CC) - clearCount = MAX_CAP_CC; - TPM2_Packet_AppendU16(&packet, in->auditAlg); TPM2_Packet_AppendU32(&packet, setCount); diff --git a/tests/unit_tests.c b/tests/unit_tests.c index aba37751..744de33b 100644 --- a/tests/unit_tests.c +++ b/tests/unit_tests.c @@ -1826,7 +1826,7 @@ static void test_TPM2_SchemeSerialize(void) /* Exercise the parse sequence used by TPM2_ECC_Parameters response: sign * scheme = ECDAA (scheme + hashAlg + count) followed by a trailing U16 - * size field. Ensures the ECDAA count byte is consumed so the next read + * size field. Ensures the ECDAA count field is consumed so the next read * lands at the correct offset. The wire bytes are built by hand to avoid * relying on non-exported packet helpers. */ static void test_TPM2_ECC_Parameters_EcdaaResponseParse(void) @@ -2059,6 +2059,52 @@ static void test_TPM2_Sensitive_Roundtrip(void) AssertIntEQ(XMEMCMP(sensOut.sensitiveArea.sensitive.ecc.buffer, rsaPriv, sizeof(rsaPriv)), 0); + /* KEYEDHASH sensitive roundtrip */ + XMEMSET(&sensIn, 0, sizeof(sensIn)); + sensIn.sensitiveArea.sensitiveType = TPM_ALG_KEYEDHASH; + sensIn.sensitiveArea.sensitive.bits.size = sizeof(rsaPriv); + XMEMCPY(sensIn.sensitiveArea.sensitive.bits.buffer, rsaPriv, + sizeof(rsaPriv)); + + XMEMSET(buf, 0, sizeof(buf)); + XMEMSET(&packet, 0, sizeof(packet)); + packet.buf = buf; + packet.size = sizeof(buf); + + TPM2_Packet_AppendSensitive(&packet, &sensIn); + + packet.pos = 0; + XMEMSET(&sensOut, 0, sizeof(sensOut)); + TPM2_Packet_ParseSensitive(&packet, &sensOut); + + AssertIntEQ(sensOut.sensitiveArea.sensitiveType, TPM_ALG_KEYEDHASH); + AssertIntEQ(sensOut.sensitiveArea.sensitive.bits.size, sizeof(rsaPriv)); + AssertIntEQ(XMEMCMP(sensOut.sensitiveArea.sensitive.bits.buffer, + rsaPriv, sizeof(rsaPriv)), 0); + + /* SYMCIPHER sensitive roundtrip */ + XMEMSET(&sensIn, 0, sizeof(sensIn)); + sensIn.sensitiveArea.sensitiveType = TPM_ALG_SYMCIPHER; + sensIn.sensitiveArea.sensitive.sym.size = sizeof(rsaPriv); + XMEMCPY(sensIn.sensitiveArea.sensitive.sym.buffer, rsaPriv, + sizeof(rsaPriv)); + + XMEMSET(buf, 0, sizeof(buf)); + XMEMSET(&packet, 0, sizeof(packet)); + packet.buf = buf; + packet.size = sizeof(buf); + + TPM2_Packet_AppendSensitive(&packet, &sensIn); + + packet.pos = 0; + XMEMSET(&sensOut, 0, sizeof(sensOut)); + TPM2_Packet_ParseSensitive(&packet, &sensOut); + + AssertIntEQ(sensOut.sensitiveArea.sensitiveType, TPM_ALG_SYMCIPHER); + AssertIntEQ(sensOut.sensitiveArea.sensitive.sym.size, sizeof(rsaPriv)); + AssertIntEQ(XMEMCMP(sensOut.sensitiveArea.sensitive.sym.buffer, + rsaPriv, sizeof(rsaPriv)), 0); + printf("Test TPM Wrapper:\tSensitive roundtrip:\t\tPassed\n"); }