Skip to content

Commit b95f553

Browse files
authored
Merge pull request #535 from aidangarske/fenrir-fixes-batch5
Various hardening fixes and tests
2 parents 503601c + ac87e6b commit b95f553

17 files changed

Lines changed: 457 additions & 38 deletions

examples/boot/secure_rot.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,9 @@ int TPM2_Boot_SecureROT_Example(void* userCtx, int argc, char *argv[])
252252
rc = wolfTPM2_NVReadPublic(&dev, nvIndex, &nvPublic);
253253
if (rc == 0) {
254254
digestSz = nvPublic.dataSize;
255+
if (digestSz > (int)sizeof(digest)) {
256+
digestSz = (int)sizeof(digest);
257+
}
255258
}
256259

257260
/* Read access */

examples/gpio/gpio_config.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ int TPM2_GPIO_Config_Example(void* userCtx, int argc, char *argv[])
377377

378378
/* Extra step for open-drain with pull-up mode */
379379
if (gpioMode == TPM_GPIO_MODE_PULLUP) {
380-
newConfig.GpioPullUp &= ~(1 << gpioNum);
380+
newConfig.GpioPullUp |= (1 << gpioNum);
381381
}
382382

383383
#ifdef WOLFTPM_DEBUG_VERBOSE

examples/pqc/mldsa_sign.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424
* (SignSequenceComplete), Sec.17.6 (VerifySequenceStart), Sec.20.3
2525
* (VerifySequenceComplete).
2626
*
27-
* Pure ML-DSA is one-shot on the sign path: SequenceUpdate is rejected
28-
* with TPM_RC_ONE_SHOT_SIGNATURE, the full message must arrive via the
29-
* SignSequenceComplete buffer. Verify sequences do accept Update per
30-
* Sec.20.3 and this example uses that path to exercise both idioms. */
27+
* Pure ML-DSA is streamable on both sign and verify: SequenceUpdate is
28+
* accepted (only multi-pass schemes such as EdDSA are one-shot). This
29+
* example passes the whole message via SignSequenceComplete on sign and
30+
* streams it through SequenceUpdate on verify to exercise both idioms. */
3131

3232
#ifdef HAVE_CONFIG_H
3333
#include <config.h>
@@ -144,9 +144,8 @@ static int mldsa_sign_run(int argc, char *argv[])
144144
(unsigned)mldsaKey.handle.hndl,
145145
(unsigned)mldsaKey.pub.publicArea.unique.mldsa.size);
146146

147-
/* Sign: Pure ML-DSA is one-shot per Sec.17.5. Message goes via
148-
* SignSequenceComplete's buffer parameter, not via SequenceUpdate
149-
* (which returns TPM_RC_ONE_SHOT_SIGNATURE for Pure MLDSA keys). */
147+
/* Sign: pass the whole message via SignSequenceComplete's buffer.
148+
* Pure ML-DSA also accepts SequenceUpdate since it is streamable. */
150149
rc = wolfTPM2_SignSequenceStart(&dev, &mldsaKey, NULL, 0, &seqHandle);
151150
if (rc != TPM_RC_SUCCESS) {
152151
printf("SignSequenceStart failed 0x%x: %s\n",

examples/pqc/mldsa_verify_neg.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ static int mldsa_verify_neg_run(int argc, char *argv[])
163163
goto exit;
164164
}
165165

166-
/* Sign the message (Pure ML-DSA is one-shot via Complete's buffer). */
166+
/* Sign the message via Complete's buffer (Pure ML-DSA is streamable). */
167167
rc = wolfTPM2_SignSequenceStart(&dev, &mldsaKey, NULL, 0, &seqHandle);
168168
if (rc == TPM_RC_SUCCESS) {
169169
rc = wolfTPM2_SignSequenceComplete(&dev, seqHandle, &mldsaKey,

examples/tpm_test_keys.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ int readKeyBlob(const char* filename, WOLFTPM2_KEYBLOB* key)
224224
goto exit;
225225
}
226226
fileSz -= bytes_read;
227-
if (key->pub.size > sizeof(UINT16) + sizeof(pubAreaBuffer)) {
227+
if (sizeof(UINT16) + key->pub.size > sizeof(pubAreaBuffer)) {
228228
printf("Public key size is too large\n");
229229
rc = BUFFER_E; goto exit;
230230
}
@@ -249,11 +249,23 @@ int readKeyBlob(const char* filename, WOLFTPM2_KEYBLOB* key)
249249

250250
if (fileSz > 0) {
251251
printf("Reading the private part of the key\n");
252-
bytes_read = XFREAD(&key->priv, 1, fileSz, fp);
253-
if (bytes_read != fileSz) {
252+
/* Read and validate the size marker before the buffer so a
253+
* crafted file cannot overflow priv */
254+
bytes_read = XFREAD(&key->priv.size, 1, sizeof(key->priv.size), fp);
255+
if (bytes_read != sizeof(key->priv.size)) {
256+
printf("Read %zu, expected private size marker of %zu bytes\n",
257+
bytes_read, sizeof(key->priv.size));
258+
rc = BUFFER_E; goto exit;
259+
}
260+
if (key->priv.size > sizeof(key->priv.buffer)) {
261+
printf("Private key size is too large\n");
262+
rc = BUFFER_E; goto exit;
263+
}
264+
bytes_read = XFREAD(key->priv.buffer, 1, key->priv.size, fp);
265+
if (bytes_read != key->priv.size) {
254266
printf("Read %zu, expected private blob %zu bytes\n",
255-
bytes_read, fileSz);
256-
goto exit;
267+
bytes_read, (size_t)key->priv.size);
268+
rc = BUFFER_E; goto exit;
257269
}
258270
rc = 0; /* success */
259271
}

src/spdm/spdm_kdf.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,19 @@ int wolfSPDM_DeriveFromHandshakeSecret(WOLFSPDM_CTX* ctx,
170170
ctx->rspDataKey, ctx->rspDataIv);
171171
}
172172

173+
if (rc != WOLFSPDM_SUCCESS) {
174+
/* wipe any partially derived material so it cannot carry into a
175+
* reused ctx */
176+
wc_ForceZero(ctx->reqHsSecret, sizeof(ctx->reqHsSecret));
177+
wc_ForceZero(ctx->rspHsSecret, sizeof(ctx->rspHsSecret));
178+
wc_ForceZero(ctx->reqFinishedKey, sizeof(ctx->reqFinishedKey));
179+
wc_ForceZero(ctx->rspFinishedKey, sizeof(ctx->rspFinishedKey));
180+
wc_ForceZero(ctx->reqDataKey, sizeof(ctx->reqDataKey));
181+
wc_ForceZero(ctx->rspDataKey, sizeof(ctx->rspDataKey));
182+
wc_ForceZero(ctx->reqDataIv, sizeof(ctx->reqDataIv));
183+
wc_ForceZero(ctx->rspDataIv, sizeof(ctx->rspDataIv));
184+
}
185+
173186
return rc;
174187
}
175188

src/tpm2.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -450,14 +450,19 @@ static TPM_RC TPM2_SPDM_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet)
450450

451451
rc = wolfTPM2_SPDM_SecuredExchange(spdmCtx,
452452
packet->buf, packet->pos, tpmResp, &tpmRespSz);
453-
if (rc != 0)
453+
if (rc != 0) {
454+
TPM2_ForceZero(tpmResp, sizeof(tpmResp));
454455
return rc;
456+
}
455457

456-
if (tpmRespSz > MAX_RESPONSE_SIZE)
458+
if (tpmRespSz > MAX_RESPONSE_SIZE) {
459+
TPM2_ForceZero(tpmResp, sizeof(tpmResp));
457460
return TPM_RC_SIZE;
461+
}
458462
XMEMCPY(packet->buf, tpmResp, tpmRespSz);
459463
packet->pos = 0;
460464
packet->size = tpmRespSz;
465+
TPM2_ForceZero(tpmResp, sizeof(tpmResp));
461466
return TPM_RC_SUCCESS;
462467
}
463468
#endif /* WOLFTPM_SPDM */
@@ -6529,6 +6534,8 @@ int TPM2_GetNonceNoLock(byte* nonceBuf, int nonceSz)
65296534
TPM2_Packet_ParseBytes(&packet, &nonceBuf[randSz], outSz);
65306535
randSz += outSz;
65316536
}
6537+
/* response buffer held freshly generated random; wipe before return */
6538+
TPM2_ForceZero(buffer, sizeof(buffer));
65326539
#endif
65336540

65346541
return rc;

src/tpm2_linux.c

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,19 @@ int TPM2_LINUX_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet)
9292
#include <string.h>
9393

9494
/* TPM Device Path Configuration:
95-
* - /dev/tpm0: TPM raw device (default)
96-
* - /dev/tpmrm0: TPM resource manager (requires kernel 5.12+)
97-
* Enabled with WOLFTPM_USE_TPMRM
95+
* - /dev/tpmrm0: TPM resource manager (requires kernel 5.12+), preferred as it
96+
* isolates and flushes per-connection transient objects/sessions
97+
* - /dev/tpm0: TPM raw device, no in-kernel resource management
98+
* The default prefers the resource manager and falls back to the raw device
99+
* when it is unavailable. Define WOLFTPM_USE_TPMRM for resource manager only,
100+
* or set TPM2_LINUX_DEV to pin a specific device.
98101
*/
99102
#ifndef TPM2_LINUX_DEV
100103
#ifdef WOLFTPM_USE_TPMRM
101104
#define TPM2_LINUX_DEV "/dev/tpmrm0"
102105
#else
103-
#define TPM2_LINUX_DEV "/dev/tpm0"
106+
#define TPM2_LINUX_DEV "/dev/tpmrm0"
107+
#define TPM2_LINUX_DEV_FALLBACK "/dev/tpm0"
104108
#endif
105109
#endif
106110

@@ -121,14 +125,23 @@ int TPM2_LINUX_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet)
121125
int rc_poll, nfds = 1; /* Polling single TPM dev file */
122126
struct pollfd fds;
123127
int rspSz = 0;
128+
const char* devName = TPM2_LINUX_DEV;
124129

125130
#ifdef WOLFTPM_DEBUG_VERBOSE
126131
printf("Command size: %d\n", packet->pos);
127132
TPM2_PrintBin(packet->buf, packet->pos);
128133
#endif
129134

130-
if (ctx->fd < 0)
135+
if (ctx->fd < 0) {
131136
ctx->fd = open(TPM2_LINUX_DEV, O_RDWR | O_NONBLOCK);
137+
#ifdef TPM2_LINUX_DEV_FALLBACK
138+
if (ctx->fd < 0) {
139+
ctx->fd = open(TPM2_LINUX_DEV_FALLBACK, O_RDWR | O_NONBLOCK);
140+
if (ctx->fd >= 0)
141+
devName = TPM2_LINUX_DEV_FALLBACK;
142+
}
143+
#endif
144+
}
132145
if (ctx->fd >= 0) {
133146
/* Send the TPM command */
134147
if (write(ctx->fd, packet->buf, packet->pos) == packet->pos) {
@@ -147,11 +160,11 @@ int TPM2_LINUX_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet)
147160
else {
148161
#ifdef DEBUG_WOLFTPM
149162
if (ret == 0) {
150-
printf("Received EOF from %s\n", TPM2_LINUX_DEV);
163+
printf("Received EOF from %s\n", devName);
151164
}
152165
else {
153166
printf("Failed to read from %s (ret %zd):"
154-
" errno %d = %s\n", TPM2_LINUX_DEV, ret,
167+
" errno %d = %s\n", devName, ret,
155168
errno, strerror(errno));
156169
}
157170
#endif
@@ -161,27 +174,27 @@ int TPM2_LINUX_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet)
161174
else {
162175
#ifdef DEBUG_WOLFTPM
163176
printf("Failed poll on %s: errno %d = %s\n",
164-
TPM2_LINUX_DEV, errno, strerror(errno));
177+
devName, errno, strerror(errno));
165178
#endif
166179
rc = TPM_RC_FAILURE;
167180
}
168181
}
169182
else {
170183
#ifdef DEBUG_WOLFTPM
171184
printf("Failed write to %s: errno %d = %s\n",
172-
TPM2_LINUX_DEV, errno, strerror(errno));
185+
devName, errno, strerror(errno));
173186
#endif
174187
rc = TPM_RC_FAILURE;
175188
}
176189
}
177190
else if (ctx->fd == -1 && errno == EACCES) {
178191
printf("Permission denied on %s\n"
179-
"Use sudo or add tss group to user.\n", TPM2_LINUX_DEV);
192+
"Use sudo or add tss group to user.\n", devName);
180193
}
181194
else {
182195
#ifdef DEBUG_WOLFTPM
183196
printf("Failed to open %s: errno %d = %s\n",
184-
TPM2_LINUX_DEV, errno, strerror(errno));
197+
devName, errno, strerror(errno));
185198
#endif
186199
}
187200

src/tpm2_packet.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,18 +830,26 @@ void TPM2_Packet_AppendSensitive(TPM2_Packet* packet, TPM2B_SENSITIVE* sensitive
830830

831831
switch (sensitive->sensitiveArea.sensitiveType) {
832832
case TPM_ALG_RSA:
833+
if (sens->rsa.size > sizeof(sens->rsa.buffer))
834+
sens->rsa.size = sizeof(sens->rsa.buffer);
833835
TPM2_Packet_AppendU16(packet, sens->rsa.size);
834836
TPM2_Packet_AppendBytes(packet, sens->rsa.buffer, sens->rsa.size);
835837
break;
836838
case TPM_ALG_ECC:
839+
if (sens->ecc.size > sizeof(sens->ecc.buffer))
840+
sens->ecc.size = sizeof(sens->ecc.buffer);
837841
TPM2_Packet_AppendU16(packet, sens->ecc.size);
838842
TPM2_Packet_AppendBytes(packet, sens->ecc.buffer, sens->ecc.size);
839843
break;
840844
case TPM_ALG_KEYEDHASH:
845+
if (sens->bits.size > sizeof(sens->bits.buffer))
846+
sens->bits.size = sizeof(sens->bits.buffer);
841847
TPM2_Packet_AppendU16(packet, sens->bits.size);
842848
TPM2_Packet_AppendBytes(packet, sens->bits.buffer, sens->bits.size);
843849
break;
844850
case TPM_ALG_SYMCIPHER:
851+
if (sens->sym.size > sizeof(sens->sym.buffer))
852+
sens->sym.size = sizeof(sens->sym.buffer);
845853
TPM2_Packet_AppendU16(packet, sens->sym.size);
846854
TPM2_Packet_AppendBytes(packet, sens->sym.buffer, sens->sym.size);
847855
break;
@@ -1206,6 +1214,9 @@ void TPM2_Packet_ParsePublic(TPM2_Packet* packet, TPM2B_PUBLIC* pub)
12061214

12071215
TPM2_Packet_ParseU16(packet, &pub->size);
12081216
pubStartPos = (packet != NULL) ? packet->pos : 0;
1217+
if (pub->size == 0) {
1218+
XMEMSET(&pub->publicArea, 0, sizeof(pub->publicArea));
1219+
}
12091220
if (pub->size > 0) {
12101221
TPM2_Packet_ParseU16(packet, &pub->publicArea.type);
12111222
TPM2_Packet_ParseU16(packet, &pub->publicArea.nameAlg);

src/tpm2_spdm.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@
6666
/* TIS I/O Callback (SPI/I2C TPM transport for SPDM) */
6767
/* -------------------------------------------------------------------------- */
6868

69+
/* Bound a framed response size against both the caller buffer and the local
70+
* I/O buffer before copying into the caller's rxBuf. */
71+
int wolfTPM2_SPDM_ValidateRspSz(word32 rspSz, word32 rxSz, word32 ioBufSz)
72+
{
73+
if (rspSz > rxSz || rspSz > ioBufSz) {
74+
return -1;
75+
}
76+
return 0;
77+
}
78+
6979
#ifdef WOLFTPM_SPDM_TIS_IO
7080
/* TIS I/O callback for routing wolfSPDM through TPM SPI/I2C FIFO.
7181
* This matches the WOLFSPDM_IO_CB signature. TCG framing (headers) is
@@ -117,7 +127,7 @@ static int wolfTPM2_SPDM_TisIoCb(
117127
XMEMCPY(&rspSz, &ioBuf[2], sizeof(UINT32));
118128
rspSz = TPM2_Packet_SwapU32(rspSz);
119129

120-
if (rspSz > *rxSz || rspSz > sizeof(ioBuf)) {
130+
if (wolfTPM2_SPDM_ValidateRspSz(rspSz, *rxSz, sizeof(ioBuf)) != 0) {
121131
return -1;
122132
}
123133

@@ -171,7 +181,10 @@ static int wolfTPM2_SPDM_SwtpmIoCb(
171181
XMEMCPY(&rspSz, &ioBuf[2], sizeof(word32));
172182
rspSz = TPM2_Packet_SwapU32(rspSz);
173183

174-
if (rspSz < TPM2_HEADER_SIZE || rspSz > *rxSz || rspSz > sizeof(ioBuf)) {
184+
if (rspSz < TPM2_HEADER_SIZE) {
185+
return -1;
186+
}
187+
if (wolfTPM2_SPDM_ValidateRspSz(rspSz, *rxSz, sizeof(ioBuf)) != 0) {
175188
return -1;
176189
}
177190

0 commit comments

Comments
 (0)