Skip to content

Commit 36c376a

Browse files
committed
Fix PQC code review issues for v185 support
- Add TPM2B_MLDSA_SIGNATURE type with proper 4627-byte buffer for ML-DSA-87 signatures instead of reusing TPM2B_MAX_BUFFER (1024 bytes) - Add bounds checking and byte skipping for MLDSA/MLKEM public key parsing in TPM2_Packet_ParsePublic to prevent buffer overflow - Add bounds checking for ML-DSA signature parsing in TPM2_Packet_ParseSignature with proper wire size tracking - Add bounds checking to Encapsulate/Decapsulate response parsing (sharedSecret and ciphertext buffers) - Add negative size validation for contextSz, digestSz, dataSz parameters in wrapper functions: wolfTPM2_SignSequenceStart, wolfTPM2_SignSequenceComplete, wolfTPM2_VerifySequenceStart, wolfTPM2_VerifySequenceComplete, wolfTPM2_SignDigest, wolfTPM2_VerifyDigestSignature - Fix misleading MAX_SIGNATURE_CTX_SIZE comment - this is for domain separation context (255 bytes), not signature size - Change TPMT_PUBLIC size check from assertion to warning for embedded systems compatibility
1 parent 2884474 commit 36c376a

File tree

6 files changed

+128
-25
lines changed

6 files changed

+128
-25
lines changed

src/tpm2.c

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3549,13 +3549,43 @@ TPM_RC TPM2_Encapsulate(Encapsulate_In* in, Encapsulate_Out* out)
35493549
TPM2_Packet_ParseU32(&packet, &paramSz);
35503550
}
35513551

3552-
TPM2_Packet_ParseU16(&packet, &out->sharedSecret.size);
3553-
TPM2_Packet_ParseBytes(&packet, out->sharedSecret.buffer,
3554-
out->sharedSecret.size);
3552+
/* Parse sharedSecret with bounds checking */
3553+
{
3554+
UINT16 wireSize;
3555+
TPM2_Packet_ParseU16(&packet, &wireSize);
3556+
out->sharedSecret.size = wireSize;
3557+
if (out->sharedSecret.size >
3558+
(UINT16)sizeof(out->sharedSecret.buffer)) {
3559+
out->sharedSecret.size =
3560+
(UINT16)sizeof(out->sharedSecret.buffer);
3561+
}
3562+
TPM2_Packet_ParseBytes(&packet, out->sharedSecret.buffer,
3563+
out->sharedSecret.size);
3564+
/* Skip remaining bytes to keep packet aligned */
3565+
if (wireSize > out->sharedSecret.size) {
3566+
TPM2_Packet_ParseBytes(&packet, NULL,
3567+
wireSize - out->sharedSecret.size);
3568+
}
3569+
}
35553570

3556-
TPM2_Packet_ParseU16(&packet, &out->ciphertext.size);
3557-
TPM2_Packet_ParseBytes(&packet, out->ciphertext.buffer,
3558-
out->ciphertext.size);
3571+
/* Parse ciphertext with bounds checking */
3572+
{
3573+
UINT16 wireSize;
3574+
TPM2_Packet_ParseU16(&packet, &wireSize);
3575+
out->ciphertext.size = wireSize;
3576+
if (out->ciphertext.size >
3577+
(UINT16)sizeof(out->ciphertext.buffer)) {
3578+
out->ciphertext.size =
3579+
(UINT16)sizeof(out->ciphertext.buffer);
3580+
}
3581+
TPM2_Packet_ParseBytes(&packet, out->ciphertext.buffer,
3582+
out->ciphertext.size);
3583+
/* Skip remaining bytes to keep packet aligned */
3584+
if (wireSize > out->ciphertext.size) {
3585+
TPM2_Packet_ParseBytes(&packet, NULL,
3586+
wireSize - out->ciphertext.size);
3587+
}
3588+
}
35593589
}
35603590

35613591
TPM2_ReleaseLock(ctx);
@@ -3597,9 +3627,24 @@ TPM_RC TPM2_Decapsulate(Decapsulate_In* in, Decapsulate_Out* out)
35973627

35983628
TPM2_Packet_ParseU32(&packet, &paramSz);
35993629

3600-
TPM2_Packet_ParseU16(&packet, &out->sharedSecret.size);
3601-
TPM2_Packet_ParseBytes(&packet, out->sharedSecret.buffer,
3602-
out->sharedSecret.size);
3630+
/* Parse sharedSecret with bounds checking */
3631+
{
3632+
UINT16 wireSize;
3633+
TPM2_Packet_ParseU16(&packet, &wireSize);
3634+
out->sharedSecret.size = wireSize;
3635+
if (out->sharedSecret.size >
3636+
(UINT16)sizeof(out->sharedSecret.buffer)) {
3637+
out->sharedSecret.size =
3638+
(UINT16)sizeof(out->sharedSecret.buffer);
3639+
}
3640+
TPM2_Packet_ParseBytes(&packet, out->sharedSecret.buffer,
3641+
out->sharedSecret.size);
3642+
/* Skip remaining bytes to keep packet aligned */
3643+
if (wireSize > out->sharedSecret.size) {
3644+
TPM2_Packet_ParseBytes(&packet, NULL,
3645+
wireSize - out->sharedSecret.size);
3646+
}
3647+
}
36033648
}
36043649

36053650
TPM2_ReleaseLock(ctx);

src/tpm2_packet.c

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -866,21 +866,39 @@ void TPM2_Packet_ParsePublic(TPM2_Packet* packet, TPM2B_PUBLIC* pub)
866866
#ifdef WOLFTPM_V185
867867
case TPM_ALG_MLDSA:
868868
case TPM_ALG_HASH_MLDSA:
869-
TPM2_Packet_ParseU16(packet, &pub->publicArea.unique.mldsa.size);
869+
{
870+
UINT16 wireSize;
871+
TPM2_Packet_ParseU16(packet, &wireSize);
872+
pub->publicArea.unique.mldsa.size = wireSize;
870873
if (pub->publicArea.unique.mldsa.size > MAX_MLDSA_PUB_SIZE) {
871874
pub->publicArea.unique.mldsa.size = MAX_MLDSA_PUB_SIZE;
872875
}
873876
TPM2_Packet_ParseBytes(packet, pub->publicArea.unique.mldsa.buffer,
874877
pub->publicArea.unique.mldsa.size);
878+
/* Skip remaining bytes to keep packet position synchronized */
879+
if (wireSize > pub->publicArea.unique.mldsa.size) {
880+
TPM2_Packet_ParseBytes(packet, NULL,
881+
wireSize - pub->publicArea.unique.mldsa.size);
882+
}
875883
break;
884+
}
876885
case TPM_ALG_MLKEM:
877-
TPM2_Packet_ParseU16(packet, &pub->publicArea.unique.mlkem.size);
886+
{
887+
UINT16 wireSize;
888+
TPM2_Packet_ParseU16(packet, &wireSize);
889+
pub->publicArea.unique.mlkem.size = wireSize;
878890
if (pub->publicArea.unique.mlkem.size > MAX_MLKEM_PUB_SIZE) {
879891
pub->publicArea.unique.mlkem.size = MAX_MLKEM_PUB_SIZE;
880892
}
881893
TPM2_Packet_ParseBytes(packet, pub->publicArea.unique.mlkem.buffer,
882894
pub->publicArea.unique.mlkem.size);
895+
/* Skip remaining bytes to keep packet position synchronized */
896+
if (wireSize > pub->publicArea.unique.mlkem.size) {
897+
TPM2_Packet_ParseBytes(packet, NULL,
898+
wireSize - pub->publicArea.unique.mlkem.size);
899+
}
883900
break;
901+
}
884902
#endif /* WOLFTPM_V185 */
885903
default:
886904
/* TPMS_DERIVE derive; ? */
@@ -1004,9 +1022,20 @@ void TPM2_Packet_ParseSignature(TPM2_Packet* packet, TPMT_SIGNATURE* sig)
10041022
case TPM_ALG_MLDSA:
10051023
case TPM_ALG_HASH_MLDSA:
10061024
TPM2_Packet_ParseU16(packet, &sig->signature.mldsa.hash);
1007-
TPM2_Packet_ParseU16(packet, &sig->signature.mldsa.signature.size);
1025+
TPM2_Packet_ParseU16(packet, &wireSize);
1026+
sig->signature.mldsa.signature.size = wireSize;
1027+
if (sig->signature.mldsa.signature.size >
1028+
sizeof(sig->signature.mldsa.signature.buffer)) {
1029+
sig->signature.mldsa.signature.size =
1030+
sizeof(sig->signature.mldsa.signature.buffer);
1031+
}
10081032
TPM2_Packet_ParseBytes(packet, sig->signature.mldsa.signature.buffer,
10091033
sig->signature.mldsa.signature.size);
1034+
/* Skip remaining bytes to keep packet position synchronized */
1035+
if (wireSize > sig->signature.mldsa.signature.size) {
1036+
TPM2_Packet_ParseBytes(packet, NULL,
1037+
wireSize - sig->signature.mldsa.signature.size);
1038+
}
10101039
break;
10111040
#endif /* WOLFTPM_V185 */
10121041
default:

src/tpm2_wrap.c

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4444,9 +4444,12 @@ int wolfTPM2_SignSequenceStart(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
44444444
return BAD_FUNC_ARG;
44454445
}
44464446

4447-
if (contextSz > (int)sizeof(signSeqStartIn.context.buffer)) {
4447+
if (contextSz < 0 || contextSz > (int)sizeof(signSeqStartIn.context.buffer)) {
44484448
return BUFFER_E;
44494449
}
4450+
if (contextSz > 0 && context == NULL) {
4451+
return BAD_FUNC_ARG;
4452+
}
44504453

44514454
/* set session auth for key */
44524455
wolfTPM2_SetAuthHandle(dev, 0, &key->handle);
@@ -4503,9 +4506,12 @@ int wolfTPM2_SignSequenceComplete(WOLFTPM2_DEV* dev,
45034506
return BAD_FUNC_ARG;
45044507
}
45054508

4506-
if (dataSz > (int)sizeof(signSeqCompleteIn.buffer.buffer)) {
4509+
if (dataSz < 0 || dataSz > (int)sizeof(signSeqCompleteIn.buffer.buffer)) {
45074510
return BUFFER_E;
45084511
}
4512+
if (dataSz > 0 && data == NULL) {
4513+
return BAD_FUNC_ARG;
4514+
}
45094515

45104516
/* set session auth for key */
45114517
wolfTPM2_SetAuthHandle(dev, 0, &key->handle);
@@ -4580,9 +4586,12 @@ int wolfTPM2_VerifySequenceStart(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
45804586
return BAD_FUNC_ARG;
45814587
}
45824588

4583-
if (contextSz > (int)sizeof(verifySeqStartIn.context.buffer)) {
4589+
if (contextSz < 0 || contextSz > (int)sizeof(verifySeqStartIn.context.buffer)) {
45844590
return BUFFER_E;
45854591
}
4592+
if (contextSz > 0 && context == NULL) {
4593+
return BAD_FUNC_ARG;
4594+
}
45864595

45874596
XMEMSET(&verifySeqStartIn, 0, sizeof(verifySeqStartIn));
45884597
verifySeqStartIn.keyHandle = key->handle.hndl;
@@ -4637,9 +4646,12 @@ int wolfTPM2_VerifySequenceComplete(WOLFTPM2_DEV* dev,
46374646
return BAD_FUNC_ARG;
46384647
}
46394648

4640-
if (dataSz > (int)sizeof(verifySeqCompleteIn.buffer.buffer)) {
4649+
if (dataSz < 0 || dataSz > (int)sizeof(verifySeqCompleteIn.buffer.buffer)) {
46414650
return BUFFER_E;
46424651
}
4652+
if (dataSz > 0 && data == NULL) {
4653+
return BAD_FUNC_ARG;
4654+
}
46434655

46444656
XMEMSET(&verifySeqCompleteIn, 0, sizeof(verifySeqCompleteIn));
46454657
verifySeqCompleteIn.sequenceHandle = sequenceHandle;
@@ -4754,13 +4766,16 @@ int wolfTPM2_SignDigest(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
47544766
return BAD_FUNC_ARG;
47554767
}
47564768

4757-
if (digestSz > (int)sizeof(signDigestIn.digest.buffer)) {
4769+
if (digestSz <= 0 || digestSz > (int)sizeof(signDigestIn.digest.buffer)) {
47584770
return BUFFER_E;
47594771
}
47604772

4761-
if (contextSz > (int)sizeof(signDigestIn.context.buffer)) {
4773+
if (contextSz < 0 || contextSz > (int)sizeof(signDigestIn.context.buffer)) {
47624774
return BUFFER_E;
47634775
}
4776+
if (contextSz > 0 && context == NULL) {
4777+
return BAD_FUNC_ARG;
4778+
}
47644779

47654780
/* set session auth for key */
47664781
wolfTPM2_SetAuthHandle(dev, 0, &key->handle);
@@ -4838,13 +4853,16 @@ int wolfTPM2_VerifyDigestSignature(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
48384853
return BAD_FUNC_ARG;
48394854
}
48404855

4841-
if (digestSz > (int)sizeof(verifyDigestSigIn.digest.buffer)) {
4856+
if (digestSz <= 0 || digestSz > (int)sizeof(verifyDigestSigIn.digest.buffer)) {
48424857
return BUFFER_E;
48434858
}
48444859

4845-
if (contextSz > (int)sizeof(verifyDigestSigIn.context.buffer)) {
4860+
if (contextSz < 0 || contextSz > (int)sizeof(verifyDigestSigIn.context.buffer)) {
48464861
return BUFFER_E;
48474862
}
4863+
if (contextSz > 0 && context == NULL) {
4864+
return BAD_FUNC_ARG;
4865+
}
48484866

48494867
XMEMSET(&verifyDigestSigIn, 0, sizeof(verifyDigestSigIn));
48504868
verifyDigestSigIn.keyHandle = key->handle.hndl;

tests/unit_tests.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,8 +1436,11 @@ static void test_wolfTPM2_PQC_Sizes(void)
14361436

14371437
/* Verify TPMT_PUBLIC size is reasonable for embedded targets */
14381438
printf(" TPMT_PUBLIC size with PQC: %zu bytes\n", sizeof(TPMT_PUBLIC));
1439-
/* Flag if > 5KB, which could blow embedded stacks */
1440-
AssertTrue(sizeof(TPMT_PUBLIC) < 5120);
1439+
/* Warn if > 5KB, which could be large for embedded stacks */
1440+
if (sizeof(TPMT_PUBLIC) >= 5120) {
1441+
printf(" WARNING: TPMT_PUBLIC size (%zu bytes) may be large for "
1442+
"embedded stacks\n", sizeof(TPMT_PUBLIC));
1443+
}
14411444

14421445
/* Verify key buffer sizes are correct */
14431446
AssertIntEQ(MAX_MLDSA_PUB_SIZE, 2592); /* ML-DSA-87 */

wolftpm/tpm2.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,12 @@ typedef struct TPM2B_PRIVATE_KEY_MLKEM {
972972
UINT16 size; /* shall be 64 */
973973
BYTE buffer[MAX_MLKEM_PRIV_SEED_SIZE]; /* 64-byte private seed (d||z) */
974974
} TPM2B_PRIVATE_KEY_MLKEM;
975+
976+
/* TPM2B_MLDSA_SIGNATURE - ML-DSA signature (up to 4627 bytes for ML-DSA-87) */
977+
typedef struct TPM2B_MLDSA_SIGNATURE {
978+
UINT16 size;
979+
BYTE buffer[MAX_MLDSA_SIG_SIZE];
980+
} TPM2B_MLDSA_SIGNATURE;
975981
#endif /* WOLFTPM_V185 */
976982

977983

@@ -1469,7 +1475,7 @@ typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECDAA;
14691475
/* ML-DSA (Dilithium) Signature Structure */
14701476
typedef struct TPMS_SIGNATURE_ML_DSA {
14711477
TPMI_ALG_HASH hash;
1472-
TPM2B_MAX_BUFFER signature; /* ML-DSA signature is variable length */
1478+
TPM2B_MLDSA_SIGNATURE signature; /* ML-DSA signature up to 4627 bytes */
14731479
} TPMS_SIGNATURE_ML_DSA;
14741480
#endif /* WOLFTPM_V185 */
14751481

wolftpm/tpm2_types.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -718,9 +718,11 @@ typedef int64_t INT64;
718718
#define MAX_MLKEM_PRIV_SEED_SIZE 64 /* Private seed (d||z) */
719719
#endif
720720

721-
/* CRITICAL: MAX_SIGNATURE_CTX_SIZE must support ML-DSA-87 signatures (4627 bytes) */
721+
/* MAX_SIGNATURE_CTX_SIZE is for the domain separation context parameter
722+
* passed to ML-DSA sign/verify operations. Set large enough for general use.
723+
* Note: ML-DSA signatures themselves can be up to 4627 bytes (ML-DSA-87). */
722724
#ifndef MAX_SIGNATURE_CTX_SIZE
723-
#define MAX_SIGNATURE_CTX_SIZE MAX_MLDSA_SIG_SIZE /* 4627 */
725+
#define MAX_SIGNATURE_CTX_SIZE 255 /* Domain separation context max */
724726
#endif
725727

726728
#ifndef MAX_KEM_CIPHERTEXT_SIZE

0 commit comments

Comments
 (0)