Skip to content

Commit d518bff

Browse files
committed
fwTPM v185: final skoll reivew pass
1 parent 960ba43 commit d518bff

11 files changed

Lines changed: 519 additions & 41 deletions

File tree

.github/workflows/pqc-examples.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,10 @@ jobs:
139139
env:
140140
WOLFSSL_PATH: ${{ github.workspace }}/wolfssl
141141
run: |
142+
set +e
142143
bash -x ./examples/run_examples.sh
143144
rc=$?
145+
set -e
144146
if [ $rc -ne 0 ]; then
145147
echo "=== run.out (last 200 lines) ==="
146148
tail -200 run.out

examples/pqc/mldsa_sign.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,10 @@ static int mldsa_sign_run(int argc, char *argv[])
7272
TPMT_TK_VERIFIED validation;
7373
byte message[] = "wolfTPM PQC example: Pure ML-DSA sign/verify";
7474
int messageSz = (int)sizeof(message) - 1;
75-
byte sig[5000]; /* ML-DSA-87 sig = 4627 bytes; slack included */
76-
int sigSz = (int)sizeof(sig);
75+
/* ML-DSA-87 sig = 4627 bytes; heap-alloc to keep stack small. */
76+
byte* sig = NULL;
77+
int sigBufSz = 5000;
78+
int sigSz = sigBufSz;
7779

7880
if (argc >= 2) {
7981
if (XSTRCMP(argv[1], "-?") == 0 ||
@@ -110,10 +112,17 @@ static int mldsa_sign_run(int argc, char *argv[])
110112
paramSet == TPM_MLDSA_44 ? "44" :
111113
paramSet == TPM_MLDSA_87 ? "87" : "65");
112114

115+
sig = (byte*)XMALLOC(sigBufSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
116+
if (sig == NULL) {
117+
printf("XMALLOC sig failed\n");
118+
return MEMORY_E;
119+
}
120+
113121
rc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL);
114122
if (rc != TPM_RC_SUCCESS) {
115123
printf("wolfTPM2_Init failed 0x%x: %s\n",
116124
rc, wolfTPM2_GetRCString(rc));
125+
XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
117126
return rc;
118127
}
119128

@@ -186,6 +195,7 @@ static int mldsa_sign_run(int argc, char *argv[])
186195
exit:
187196
wolfTPM2_UnloadHandle(&dev, &mldsaKey.handle);
188197
wolfTPM2_Cleanup(&dev);
198+
XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
189199
return rc;
190200
}
191201

examples/pqc/mlkem_encap.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,10 @@ static int mlkem_encap_run(int argc, char *argv[])
6161
WOLFTPM2_KEY mlkemKey;
6262
TPMT_PUBLIC pubTemplate;
6363
TPMI_MLKEM_PARAMETER_SET paramSet = TPM_MLKEM_768;
64-
byte ciphertext[1600];
65-
int ciphertextSz = (int)sizeof(ciphertext);
64+
/* MLKEM-1024 ct = 1568 bytes; heap-alloc to keep stack small. */
65+
byte* ciphertext = NULL;
66+
int ciphertextBufSz = 1600;
67+
int ciphertextSz = ciphertextBufSz;
6668
byte sharedSecret1[64];
6769
int sharedSecret1Sz = (int)sizeof(sharedSecret1);
6870
byte sharedSecret2[64];
@@ -96,7 +98,6 @@ static int mlkem_encap_run(int argc, char *argv[])
9698
XMEMSET(&dev, 0, sizeof(dev));
9799
XMEMSET(&mlkemKey, 0, sizeof(mlkemKey));
98100
XMEMSET(&pubTemplate, 0, sizeof(pubTemplate));
99-
XMEMSET(ciphertext, 0, sizeof(ciphertext));
100101
XMEMSET(sharedSecret1, 0, sizeof(sharedSecret1));
101102
XMEMSET(sharedSecret2, 0, sizeof(sharedSecret2));
102103

@@ -105,10 +106,18 @@ static int mlkem_encap_run(int argc, char *argv[])
105106
paramSet == TPM_MLKEM_512 ? "512" :
106107
paramSet == TPM_MLKEM_1024 ? "1024" : "768");
107108

109+
ciphertext = (byte*)XMALLOC(ciphertextBufSz, NULL,
110+
DYNAMIC_TYPE_TMP_BUFFER);
111+
if (ciphertext == NULL) {
112+
printf("XMALLOC ciphertext failed\n");
113+
return MEMORY_E;
114+
}
115+
108116
rc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL);
109117
if (rc != TPM_RC_SUCCESS) {
110118
printf("wolfTPM2_Init failed 0x%x: %s\n",
111119
rc, wolfTPM2_GetRCString(rc));
120+
XFREE(ciphertext, NULL, DYNAMIC_TYPE_TMP_BUFFER);
112121
return rc;
113122
}
114123

@@ -161,6 +170,7 @@ static int mlkem_encap_run(int argc, char *argv[])
161170
wc_ForceZero(sharedSecret2, sizeof(sharedSecret2));
162171
wolfTPM2_UnloadHandle(&dev, &mlkemKey.handle);
163172
wolfTPM2_Cleanup(&dev);
173+
XFREE(ciphertext, NULL, DYNAMIC_TYPE_TMP_BUFFER);
164174
return rc;
165175
}
166176

examples/pqc/pqc_mssim_e2e.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,24 +62,31 @@ static int test_mlkem_roundtrip(WOLFTPM2_DEV* dev)
6262
int rc;
6363
byte ss1[32], ss2[32];
6464
int ss1Sz = sizeof(ss1), ss2Sz = sizeof(ss2);
65-
byte ct[MAX_MLKEM_CT_SIZE];
66-
int ctSz = sizeof(ct);
65+
/* MLKEM ciphertext can be up to 1568 bytes — heap-alloc. */
66+
byte* ct = NULL;
67+
int ctBufSz = MAX_MLKEM_CT_SIZE;
68+
int ctSz = ctBufSz;
6769

6870
XMEMSET(&mlkem, 0, sizeof(mlkem));
6971
XMEMSET(&tpl, 0, sizeof(tpl));
7072

73+
ct = (byte*)XMALLOC(ctBufSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
74+
if (ct == NULL) return MEMORY_E;
75+
7176
rc = wolfTPM2_GetKeyTemplate_MLKEM(&tpl,
7277
TPMA_OBJECT_decrypt | TPMA_OBJECT_fixedTPM | TPMA_OBJECT_fixedParent |
7378
TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth,
7479
TPM_MLKEM_768);
7580
if (rc != 0) {
7681
printf("GetKeyTemplate_MLKEM rc=%d\n", rc);
82+
XFREE(ct, NULL, DYNAMIC_TYPE_TMP_BUFFER);
7783
return rc;
7884
}
7985

8086
rc = wolfTPM2_CreatePrimaryKey(dev, &mlkem, TPM_RH_OWNER, &tpl, NULL, 0);
8187
if (rc != 0) {
8288
printf("CreatePrimary(MLKEM-768) rc=%d\n", rc);
89+
XFREE(ct, NULL, DYNAMIC_TYPE_TMP_BUFFER);
8390
return rc;
8491
}
8592

@@ -121,6 +128,7 @@ static int test_mlkem_roundtrip(WOLFTPM2_DEV* dev)
121128
wc_ForceZero(ss1, sizeof(ss1));
122129
wc_ForceZero(ss2, sizeof(ss2));
123130
wolfTPM2_UnloadHandle(dev, &mlkem.handle);
131+
XFREE(ct, NULL, DYNAMIC_TYPE_TMP_BUFFER);
124132
return rc;
125133
}
126134

@@ -130,27 +138,34 @@ static int test_hash_mldsa_digest_roundtrip(WOLFTPM2_DEV* dev)
130138
TPMT_PUBLIC tpl;
131139
int rc;
132140
byte digest[32];
133-
byte sig[MAX_MLDSA_SIG_SIZE];
134-
int sigSz = sizeof(sig);
141+
/* MLDSA-87 sig = 4627 bytes — heap-alloc to keep stack small. */
142+
byte* sig = NULL;
143+
int sigBufSz = MAX_MLDSA_SIG_SIZE;
144+
int sigSz = sigBufSz;
135145
TPMT_TK_VERIFIED validation;
136146

137147
XMEMSET(&mldsa, 0, sizeof(mldsa));
138148
XMEMSET(&tpl, 0, sizeof(tpl));
139149
XMEMSET(&validation, 0, sizeof(validation));
140150
XMEMSET(digest, 0xAA, sizeof(digest));
141151

152+
sig = (byte*)XMALLOC(sigBufSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
153+
if (sig == NULL) return MEMORY_E;
154+
142155
rc = wolfTPM2_GetKeyTemplate_HASH_MLDSA(&tpl,
143156
TPMA_OBJECT_sign | TPMA_OBJECT_fixedTPM | TPMA_OBJECT_fixedParent |
144157
TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth,
145158
TPM_MLDSA_65, TPM_ALG_SHA256);
146159
if (rc != 0) {
147160
printf("GetKeyTemplate_HASH_MLDSA rc=%d\n", rc);
161+
XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
148162
return rc;
149163
}
150164

151165
rc = wolfTPM2_CreatePrimaryKey(dev, &mldsa, TPM_RH_OWNER, &tpl, NULL, 0);
152166
if (rc != 0) {
153167
printf("CreatePrimary(HashMLDSA-65) rc=%d\n", rc);
168+
XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
154169
return rc;
155170
}
156171

@@ -196,6 +211,7 @@ static int test_hash_mldsa_digest_roundtrip(WOLFTPM2_DEV* dev)
196211

197212
cleanup:
198213
wolfTPM2_UnloadHandle(dev, &mldsa.handle);
214+
XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
199215
return rc;
200216
}
201217

examples/run_examples.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ if [ -z "$ENABLE_V185" ]; then
3333
ENABLE_V185=0
3434
for cfg in src/config.h config.h ../src/config.h ../config.h \
3535
wolftpm/options.h wolftpm/version.h; do
36-
if [ -f "$cfg" ] && grep -q "WOLFTPM_V185[[:space:]]*1" "$cfg"; then
36+
if [ -f "$cfg" ] && grep -qE \
37+
'^[[:space:]]*#[[:space:]]*define[[:space:]]+WOLFTPM_V185([[:space:]]|$)' \
38+
"$cfg"; then
3739
ENABLE_V185=1
3840
break
3941
fi

src/fwtpm/fwtpm_command.c

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7172,6 +7172,9 @@ static TPM_RC FwCmd_SequenceComplete(FWTPM_CTX* ctx, TPM2_Packet* cmd,
71727172
TPMI_ALG_HASH hashAlg = TPM_ALG_NULL;
71737173
int paramSzPos, paramStart;
71747174
int trc;
7175+
#ifdef WOLFTPM_V185
7176+
FWTPM_SignSeq* misRoutedSign = NULL;
7177+
#endif
71757178

71767179
FWTPM_ALLOC_BUF(dataBuf, FWTPM_MAX_DATA_BUF);
71777180

@@ -7185,6 +7188,11 @@ static TPM_RC FwCmd_SequenceComplete(FWTPM_CTX* ctx, TPM2_Packet* cmd,
71857188
seq = FwFindHashSeq(ctx, seqHandle);
71867189
if (seq == NULL) {
71877190
rc = TPM_RC_HANDLE;
7191+
#ifdef WOLFTPM_V185
7192+
/* Free a sign/verify slot mis-routed here so it doesn't leak. */
7193+
misRoutedSign = FwFindSignSeq(ctx, seqHandle);
7194+
if (misRoutedSign != NULL) FwFreeSignSeq(misRoutedSign);
7195+
#endif
71887196
}
71897197
else {
71907198
hashAlg = seq->hashAlg;
@@ -13144,9 +13152,10 @@ static TPM_RC FwCmd_Encapsulate(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize,
1314413152
if (rc == 0 && cmdTag == TPM_ST_SESSIONS) {
1314513153
rc = FwSkipAuthArea(cmd, cmdSize);
1314613154
}
13147-
/* Two KEM types per Part 2 Sec.10.3.13 Table 100: ML-KEM (FIPS 203) and
13148-
* ECC DHKEM (RFC 9180 Sec.4.1). For ECC the kdf scheme MUST be HKDF
13149-
* (Part 2 Sec.12.2.3.5) — TPM_RC_KEY for any other key type or unset kdf. */
13155+
/* KEM types per Part 2 Sec.10.3.13 Table 100: ML-KEM (FIPS 203) and ECC
13156+
* DHKEM (RFC 9180 Sec.4.1, ECC kdf MUST be HKDF). Part 3 Sec.14.10.1
13157+
* explicitly says the TPM does NOT verify objectAttributes here (only
13158+
* the public portion may be loaded), so no decrypt/restricted check. */
1315013159
if (rc == 0) {
1315113160
if (obj->pub.type == TPM_ALG_MLKEM) {
1315213161
ps = obj->pub.parameters.mlkemDetail.parameterSet;
@@ -13401,13 +13410,15 @@ static TPM_RC FwCmd_SignSequenceStart(FWTPM_CTX* ctx, TPM2_Packet* cmd,
1340113410
rc = TPM_RC_KEY;
1340213411
}
1340313412
/* Accept ML-DSA, Hash-ML-DSA, classical RSA/ECC, and KEYEDHASH
13404-
* (HMAC) signing keys. Other types (SM2, ECSCHNORR) unsupported. */
13413+
* (HMAC) signing keys. Other types (SYMCIPHER, SM2, ECSCHNORR)
13414+
* map to TPM_RC_KEY ("not a signing key" — Part 3 Sec.17.5.1
13415+
* reserves TPM_RC_SCHEME for the NULL-scheme case below). */
1340513416
else if (obj->pub.type != TPM_ALG_MLDSA &&
1340613417
obj->pub.type != TPM_ALG_HASH_MLDSA &&
1340713418
obj->pub.type != TPM_ALG_RSA &&
1340813419
obj->pub.type != TPM_ALG_ECC &&
1340913420
obj->pub.type != TPM_ALG_KEYEDHASH) {
13410-
rc = TPM_RC_SCHEME;
13421+
rc = TPM_RC_KEY;
1341113422
}
1341213423
}
1341313424

@@ -13426,6 +13437,9 @@ static TPM_RC FwCmd_SignSequenceStart(FWTPM_CTX* ctx, TPM2_Packet* cmd,
1342613437
if (authSz > sizeof(((TPM2B_AUTH*)0)->buffer)) {
1342713438
rc = TPM_RC_SIZE;
1342813439
}
13440+
else if (cmd->pos + authSz > cmdSize) {
13441+
rc = TPM_RC_COMMAND_SIZE;
13442+
}
1342913443
}
1343013444
/* Parse context (TPM2B_SIGNATURE_CTX) */
1343113445
if (rc == 0) {
@@ -13565,13 +13579,15 @@ static TPM_RC FwCmd_VerifySequenceStart(FWTPM_CTX* ctx, TPM2_Packet* cmd,
1356513579
rc = TPM_RC_KEY;
1356613580
}
1356713581
/* Accept ML-DSA, Hash-ML-DSA, classical RSA/ECC, and KEYEDHASH
13568-
* (HMAC) signing keys. */
13582+
* (HMAC) signing keys. Other types map to TPM_RC_KEY per
13583+
* Part 3 Sec.17.6.1 (TPM_RC_SCHEME is reserved for the
13584+
* NULL-scheme case below). */
1356913585
else if (obj->pub.type != TPM_ALG_MLDSA &&
1357013586
obj->pub.type != TPM_ALG_HASH_MLDSA &&
1357113587
obj->pub.type != TPM_ALG_RSA &&
1357213588
obj->pub.type != TPM_ALG_ECC &&
1357313589
obj->pub.type != TPM_ALG_KEYEDHASH) {
13574-
rc = TPM_RC_SCHEME;
13590+
rc = TPM_RC_KEY;
1357513591
}
1357613592
}
1357713593

@@ -13587,6 +13603,9 @@ static TPM_RC FwCmd_VerifySequenceStart(FWTPM_CTX* ctx, TPM2_Packet* cmd,
1358713603
if (authSz > sizeof(((TPM2B_AUTH*)0)->buffer)) {
1358813604
rc = TPM_RC_SIZE;
1358913605
}
13606+
else if (cmd->pos + authSz > cmdSize) {
13607+
rc = TPM_RC_COMMAND_SIZE;
13608+
}
1359013609
}
1359113610
if (rc == 0) {
1359213611
seq = FwAllocSignSeq(ctx, &seqHandle);
@@ -13599,8 +13618,11 @@ static TPM_RC FwCmd_VerifySequenceStart(FWTPM_CTX* ctx, TPM2_Packet* cmd,
1359913618
TPM2_Packet_ParseBytes(cmd, seq->authValue.buffer, authSz);
1360013619

1360113620
TPM2_Packet_ParseU16(cmd, &hintSz);
13602-
/* Part 2 Sec.11.3.9: hint MUST be zero-length for non-EdDSA schemes.
13603-
* Reject any non-zero hint up front; nothing to consume on the wire. */
13621+
/* Part 3 Sec.17.6.1: hint carries the EdDSA R for EDDSA verify;
13622+
* MUST be zero-length for all other schemes. wolfTPM does not yet
13623+
* implement EDDSA verify-sequences (no TPM_ALG_EDDSA dispatch in
13624+
* VerifySequenceComplete), so reject any non-zero hint with
13625+
* TPM_RC_VALUE. Re-gate this on obj->pub.type when EDDSA is added. */
1360413626
if (hintSz > 0) {
1360513627
rc = TPM_RC_VALUE;
1360613628
}
@@ -13723,7 +13745,13 @@ static TPM_RC FwCmd_SignSequenceComplete(FWTPM_CTX* ctx, TPM2_Packet* cmd,
1372313745
TPM2_Packet_ParseU32(cmd, &sequenceHandle);
1372413746
TPM2_Packet_ParseU32(cmd, &keyHandle);
1372513747
seq = FwFindSignSeq(ctx, sequenceHandle);
13726-
if (seq == NULL || seq->isVerifySeq) {
13748+
/* NULL out seq for a peer's verify-sequence so cleanup
13749+
* doesn't free their slot. */
13750+
if (seq != NULL && seq->isVerifySeq) {
13751+
seq = NULL;
13752+
rc = TPM_RC_HANDLE;
13753+
}
13754+
else if (seq == NULL) {
1372713755
rc = TPM_RC_HANDLE;
1372813756
}
1372913757
}
@@ -13969,12 +13997,15 @@ static TPM_RC FwCmd_SignSequenceComplete(FWTPM_CTX* ctx, TPM2_Packet* cmd,
1396913997
rc = TPM_RC_SCHEME;
1397013998
}
1397113999
else {
13972-
paramStart = FwRspParamsBegin(rsp, cmdTag, &paramSzPos);
14000+
paramStart = FwRspParamsBegin(rsp, cmdTag,
14001+
&paramSzPos);
1397314002
rc = FwSignDigestAndAppend(ctx, keyObj,
1397414003
schemeAlg, hashAlg,
1397514004
digestOut, digestSz, rsp);
14005+
/* Always pair Begin with End so the param-size
14006+
* back-patch fires even on failure. */
14007+
FwRspParamsEnd(rsp, cmdTag, paramSzPos, paramStart);
1397614008
if (rc == 0) {
13977-
FwRspParamsEnd(rsp, cmdTag, paramSzPos, paramStart);
1397814009
FwFreeSignSeq(seq);
1397914010
FWTPM_FREE_BUF(msgBuf);
1398014011
FWTPM_FREE_VAR(sigOut);
@@ -14073,7 +14104,13 @@ static TPM_RC FwCmd_VerifySequenceComplete(FWTPM_CTX* ctx, TPM2_Packet* cmd,
1407314104
TPM2_Packet_ParseU32(cmd, &sequenceHandle);
1407414105
TPM2_Packet_ParseU32(cmd, &keyHandle);
1407514106
seq = FwFindSignSeq(ctx, sequenceHandle);
14076-
if (seq == NULL || !seq->isVerifySeq) {
14107+
/* NULL out seq for a peer's sign-sequence so cleanup
14108+
* doesn't free their slot. */
14109+
if (seq != NULL && !seq->isVerifySeq) {
14110+
seq = NULL;
14111+
rc = TPM_RC_HANDLE;
14112+
}
14113+
else if (seq == NULL) {
1407714114
rc = TPM_RC_HANDLE;
1407814115
}
1407914116
}
@@ -14563,6 +14600,12 @@ static TPM_RC FwCmd_SignDigest(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize,
1456314600
if (sigScheme == TPM_ALG_NULL || sigHashAlg == TPM_ALG_NULL) {
1456414601
rc = TPM_RC_SCHEME;
1456514602
}
14603+
else if (digest->size !=
14604+
(UINT16)TPM2_GetHashDigestSize(sigHashAlg)) {
14605+
/* Part 3 Sec.20.7.1: digest size MUST match the hashAlg
14606+
* digest size for ALL signing schemes. */
14607+
rc = TPM_RC_SIZE;
14608+
}
1456614609
else {
1456714610
rc = FwSignDigestAndAppend(ctx, obj, sigScheme, sigHashAlg,
1456814611
digest->buffer, digest->size, rsp);
@@ -14744,6 +14787,12 @@ static TPM_RC FwCmd_VerifyDigestSignature(FWTPM_CTX* ctx, TPM2_Packet* cmd,
1474414787
keyHashAlg != classicalSig.signature.any.hashAlg) {
1474514788
rc = TPM_RC_SCHEME;
1474614789
}
14790+
else if (digest->size !=
14791+
(UINT16)TPM2_GetHashDigestSize(keyHashAlg)) {
14792+
/* Part 3 Sec.20.4.1: digest size MUST match the hashAlg
14793+
* digest size for ALL signing schemes. */
14794+
rc = TPM_RC_SIZE;
14795+
}
1474714796
else {
1474814797
rc = FwVerifySignatureCore(obj, digest->buffer, digest->size,
1474914798
&classicalSig);

0 commit comments

Comments
 (0)