diff --git a/examples/attestation/make_credential.c b/examples/attestation/make_credential.c index 7e52969ea..512c1a4c4 100644 --- a/examples/attestation/make_credential.c +++ b/examples/attestation/make_credential.c @@ -143,9 +143,18 @@ int TPM2_MakeCredential_Example(void* userCtx, int argc, char *argv[]) fp = XFOPEN("ak.name", "rb"); if (fp != XBADFILE) { size_t nameReadSz = XFREAD((BYTE*)&name, 1, sizeof(name), fp); - printf("Read AK Name digest %s\n", - nameReadSz == sizeof(name) ? "success" : "failed"); XFCLOSE(fp); + if (nameReadSz != sizeof(name)) { + printf("Read AK Name digest failed\n"); + rc = BUFFER_E; + goto exit; + } + printf("Read AK Name digest success\n"); + } + else { + printf("Failed to open ak.name\n"); + rc = BAD_FUNC_ARG; + goto exit; } #endif diff --git a/examples/bench/bench.c b/examples/bench/bench.c index e705548d1..37e96b8f8 100644 --- a/examples/bench/bench.c +++ b/examples/bench/bench.c @@ -516,19 +516,19 @@ int TPM2_Wrapper_BenchArgs(void* userCtx, int argc, char *argv[]) /* SHA1 */ rc = bench_sym_hash(&dev, "SHA1", TPM_ALG_SHA1, message.buffer, sizeof(message.buffer), cipher.buffer, TPM_SHA_DIGEST_SIZE, maxDuration); - if (rc != 0 && (rc & TPM_RC_HASH) != TPM_RC_HASH) goto exit; + if (rc != 0 && (rc & RC_MAX_FMT1) != TPM_RC_HASH) goto exit; /* SHA256 */ rc = bench_sym_hash(&dev, "SHA256", TPM_ALG_SHA256, message.buffer, sizeof(message.buffer), cipher.buffer, TPM_SHA256_DIGEST_SIZE, maxDuration); - if (rc != 0 && (rc & TPM_RC_HASH) != TPM_RC_HASH) goto exit; + if (rc != 0 && (rc & RC_MAX_FMT1) != TPM_RC_HASH) goto exit; /* SHA384 */ rc = bench_sym_hash(&dev, "SHA384", TPM_ALG_SHA384, message.buffer, sizeof(message.buffer), cipher.buffer, TPM_SHA384_DIGEST_SIZE, maxDuration); - if (rc != 0 && (rc & TPM_RC_HASH) != TPM_RC_HASH) goto exit; + if (rc != 0 && (rc & RC_MAX_FMT1) != TPM_RC_HASH) goto exit; /* SHA512 */ rc = bench_sym_hash(&dev, "SHA512", TPM_ALG_SHA512, message.buffer, sizeof(message.buffer), cipher.buffer, TPM_SHA512_DIGEST_SIZE, maxDuration); - if (rc != 0 && (rc & TPM_RC_HASH) != TPM_RC_HASH) goto exit; + if (rc != 0 && (rc & RC_MAX_FMT1) != TPM_RC_HASH) goto exit; /* Create RSA key for encrypt/decrypt */ diff --git a/examples/firmware/ifx_fw_update.c b/examples/firmware/ifx_fw_update.c index 33b5d4fb3..b696b7899 100644 --- a/examples/firmware/ifx_fw_update.c +++ b/examples/firmware/ifx_fw_update.c @@ -253,6 +253,7 @@ int TPM2_IFX_Firmware_Update(void* userCtx, int argc, char *argv[]) if (manifest_file == NULL || firmware_file == NULL) { if (argc > 1) { printf("Manifest file or firmware file arguments missing!\n"); + rc = BAD_FUNC_ARG; } goto exit; } diff --git a/examples/gpio/gpio_config.c b/examples/gpio/gpio_config.c index 1e7f8ab1c..182f4bf57 100644 --- a/examples/gpio/gpio_config.c +++ b/examples/gpio/gpio_config.c @@ -176,6 +176,7 @@ int TPM2_GPIO_Config_Example(void* userCtx, int argc, char *argv[]) #ifdef WOLFTPM_ST33 if (caps.mfg != TPM_MFG_STM) { printf("TPM vendor mismatch. GPIO support requires an ST33 TPM 2.0 module\n"); + rc = BAD_FUNC_ARG; goto exit; } @@ -263,6 +264,7 @@ int TPM2_GPIO_Config_Example(void* userCtx, int argc, char *argv[]) if (caps.mfg != TPM_MFG_NUVOTON) { printf("TPM vendor mismatch. GPIO support requires Nuvoton NPCT7xx TPM 2.0 module\n"); + rc = BAD_FUNC_ARG; goto exit; } diff --git a/examples/management/flush.c b/examples/management/flush.c index 1a55d0874..751b599da 100644 --- a/examples/management/flush.c +++ b/examples/management/flush.c @@ -101,7 +101,7 @@ int TPM2_Flush_Tool(void* userCtx, int argc, char *argv[]) else { flushCtx.flushHandle = handle; printf("Freeing %X object\n", handle); - TPM2_FlushContext(&flushCtx); + rc = TPM2_FlushContext(&flushCtx); } wolfTPM2_Cleanup(&dev); diff --git a/examples/pcr/policy.c b/examples/pcr/policy.c index b7c0730e5..eabd0f835 100644 --- a/examples/pcr/policy.c +++ b/examples/pcr/policy.c @@ -94,7 +94,7 @@ int TPM2_PCR_Policy_Test(void* userCtx, int argc, char *argv[]) else if (XSTRCMP(argv[argc-1], "-xor") == 0) { paramEncAlg = TPM_ALG_XOR; } - else if (XMEMCMP(argv[argc-1], "-digest=", XSTRLEN("-digest=")) == 0) { + else if (XSTRNCMP(argv[argc-1], "-digest=", XSTRLEN("-digest=")) == 0) { const char *digestStr, *end; digestStr = argv[argc-1] + XSTRLEN("-digest="); end = XSTRSTR(digestStr, " "); @@ -108,13 +108,13 @@ int TPM2_PCR_Policy_Test(void* userCtx, int argc, char *argv[]) digestLen > sizeof(digest)*2) { printf("Invalid digest! Must be 16 or 32 bytes of hex like 01020304050607080910111213141516\n"); usage(); - return 0; + return BAD_FUNC_ARG; } hexRet = hexToByte(digestStr, digest, digestLen); if (hexRet < 0) { printf("Invalid hex digest string\n"); usage(); - return 0; + return BAD_FUNC_ARG; } digestLen = (word32)hexRet; } @@ -124,7 +124,7 @@ int TPM2_PCR_Policy_Test(void* userCtx, int argc, char *argv[]) if (pcrIndex < (int)PCR_FIRST || pcrIndex > (int)PCR_LAST) { printf("PCR index is out of range (0-23)\n"); usage(); - return 0; + return BAD_FUNC_ARG; } } else { diff --git a/examples/pcr/policy_sign.c b/examples/pcr/policy_sign.c index 86c6c9c69..ab8a9081a 100644 --- a/examples/pcr/policy_sign.c +++ b/examples/pcr/policy_sign.c @@ -196,17 +196,17 @@ static int PolicySign(TPM_ALG_ID alg, const char* keyFile, const char* password, rc = mp_init_multi(&r, &s, NULL, NULL, NULL, NULL); if (rc == 0) { rc = wc_ecc_sign_hash_ex(hash, hashSz, &rng, &key.ecc, &r, &s); - } - if (rc == 0) { - word32 keySz = key.ecc.dp->size; - *sigSz = keySz * 2; - /* Pre-zero in case mp export fails and leaves the buffer - * partially written. Fixed-width export of r and s - * removes the data-dependent wire offset that previously - * leaked the leading-zero count. */ - XMEMSET(sig, 0, *sigSz); - mp_to_unsigned_bin_len(&r, &sig[0], keySz); - mp_to_unsigned_bin_len(&s, &sig[keySz], keySz); + if (rc == 0) { + word32 keySz = key.ecc.dp->size; + *sigSz = keySz * 2; + /* Pre-zero in case mp export fails and leaves the buffer + * partially written. Fixed-width export of r and s + * removes the data-dependent wire offset that previously + * leaked the leading-zero count. */ + XMEMSET(sig, 0, *sigSz); + mp_to_unsigned_bin_len(&r, &sig[0], keySz); + mp_to_unsigned_bin_len(&s, &sig[keySz], keySz); + } mp_clear(&r); mp_clear(&s); } diff --git a/examples/pkcs7/pkcs7.c b/examples/pkcs7/pkcs7.c index 721c8beab..f54bde479 100644 --- a/examples/pkcs7/pkcs7.c +++ b/examples/pkcs7/pkcs7.c @@ -109,6 +109,7 @@ static int PKCS7_SignVerifyEx(WOLFTPM2_DEV* dev, int tpmDevId, { int rc; wc_PKCS7 pkcs7; + int pkcs7Init = 0; wc_HashAlg hash; byte hashBuf[TPM_MAX_DIGEST_SIZE]; word32 hashSz; @@ -155,6 +156,7 @@ static int PKCS7_SignVerifyEx(WOLFTPM2_DEV* dev, int tpmDevId, /* Generate and verify PKCS#7 files containing data using TPM key */ rc = wc_PKCS7_Init(&pkcs7, NULL, tpmDevId); if (rc != 0) goto exit; + pkcs7Init = 1; rc = wc_PKCS7_InitWithCert(&pkcs7, derCert, derCertSz); if (rc != 0) goto exit; @@ -177,6 +179,7 @@ static int PKCS7_SignVerifyEx(WOLFTPM2_DEV* dev, int tpmDevId, if (rc != 0) goto exit; wc_PKCS7_Free(&pkcs7); + pkcs7Init = 0; printf("PKCS7 Header %d\n", outputHeadSz); TPM2_PrintBin(outputHead, outputHeadSz); @@ -232,6 +235,7 @@ static int PKCS7_SignVerifyEx(WOLFTPM2_DEV* dev, int tpmDevId, /* Test verify with TPM */ rc = wc_PKCS7_Init(&pkcs7, NULL, tpmDevId); if (rc != 0) goto exit; + pkcs7Init = 1; rc = wc_PKCS7_InitWithCert(&pkcs7, NULL, 0); if (rc != 0) goto exit; @@ -241,12 +245,14 @@ static int PKCS7_SignVerifyEx(WOLFTPM2_DEV* dev, int tpmDevId, if (rc != 0) goto exit; wc_PKCS7_Free(&pkcs7); + pkcs7Init = 0; printf("PKCS7 Container Verified (using TPM)\n"); /* Test verify with software */ rc = wc_PKCS7_Init(&pkcs7, NULL, INVALID_DEVID); if (rc != 0) goto exit; + pkcs7Init = 1; rc = wc_PKCS7_InitWithCert(&pkcs7, NULL, 0); if (rc != 0) goto exit; pkcs7.contentSz = dataChunkSz; @@ -254,10 +260,14 @@ static int PKCS7_SignVerifyEx(WOLFTPM2_DEV* dev, int tpmDevId, outputHead, outputHeadSz, outputFoot, outputFootSz); if (rc != 0) goto exit; wc_PKCS7_Free(&pkcs7); + pkcs7Init = 0; printf("PKCS7 Container Verified (using software)\n"); exit: + if (pkcs7Init) { + wc_PKCS7_Free(&pkcs7); + } return rc; } #endif /* ENABLE_PKCS7EX_EXAMPLE */ @@ -268,6 +278,7 @@ static int PKCS7_SignVerify(WOLFTPM2_DEV* dev, int tpmDevId, { int rc; wc_PKCS7 pkcs7; + int pkcs7Init = 0; byte data[] = "My encoded DER cert."; byte output[MAX_PKCS7_SIZE]; int outputSz; @@ -280,6 +291,7 @@ static int PKCS7_SignVerify(WOLFTPM2_DEV* dev, int tpmDevId, /* Generate and verify PKCS#7 files containing data using TPM key */ rc = wc_PKCS7_Init(&pkcs7, NULL, tpmDevId); if (rc != 0) goto exit; + pkcs7Init = 1; rc = wc_PKCS7_InitWithCert(&pkcs7, derCert, derCertSz); if (rc != 0) goto exit; @@ -296,6 +308,7 @@ static int PKCS7_SignVerify(WOLFTPM2_DEV* dev, int tpmDevId, rc = wc_PKCS7_EncodeSignedData(&pkcs7, output, sizeof(output)); if (rc <= 0) goto exit; wc_PKCS7_Free(&pkcs7); + pkcs7Init = 0; outputSz = rc; printf("PKCS7 Signed Container %d\n", outputSz); @@ -321,26 +334,33 @@ static int PKCS7_SignVerify(WOLFTPM2_DEV* dev, int tpmDevId, /* Test verify with TPM */ rc = wc_PKCS7_Init(&pkcs7, NULL, tpmDevId); if (rc != 0) goto exit; + pkcs7Init = 1; rc = wc_PKCS7_InitWithCert(&pkcs7, NULL, 0); if (rc != 0) goto exit; rc = wc_PKCS7_VerifySignedData(&pkcs7, output, outputSz); if (rc != 0) goto exit; wc_PKCS7_Free(&pkcs7); + pkcs7Init = 0; printf("PKCS7 Container Verified (using TPM)\n"); /* Test verify with software */ rc = wc_PKCS7_Init(&pkcs7, NULL, INVALID_DEVID); if (rc != 0) goto exit; + pkcs7Init = 1; rc = wc_PKCS7_InitWithCert(&pkcs7, NULL, 0); if (rc != 0) goto exit; rc = wc_PKCS7_VerifySignedData(&pkcs7, output, outputSz); if (rc != 0) goto exit; wc_PKCS7_Free(&pkcs7); + pkcs7Init = 0; printf("PKCS7 Container Verified (using software)\n"); exit: + if (pkcs7Init) { + wc_PKCS7_Free(&pkcs7); + } return rc; } diff --git a/examples/wrap/caps.c b/examples/wrap/caps.c index 450014c98..25b4c4308 100644 --- a/examples/wrap/caps.c +++ b/examples/wrap/caps.c @@ -129,6 +129,7 @@ int TPM2_Wrapper_CapsArgs(void* userCtx, int argc, char *argv[]) rc = wolfTPM2_GetHandles(PERSISTENT_FIRST, NULL); if (rc >= 0) { printf("Found %d persistent handles\n", rc); + rc = TPM_RC_SUCCESS; } /* Print the available PCR's */ diff --git a/examples/wrap/getrandom.c b/examples/wrap/getrandom.c index 135205929..b6e04610f 100644 --- a/examples/wrap/getrandom.c +++ b/examples/wrap/getrandom.c @@ -58,6 +58,7 @@ int TPM2_GetRandom_Example(void* userCtx, int argc, char* argv[]) byte buf[GETRANDOM_MAX_BYTES]; word32 len = GETRANDOM_DEFAULT_BYTES; word32 i; + int lenArg; if (argc > 1) { if (XSTRCMP(argv[1], "-?") == 0 || @@ -66,7 +67,12 @@ int TPM2_GetRandom_Example(void* userCtx, int argc, char* argv[]) usage(); return 0; } - len = (word32)XATOI(argv[1]); + lenArg = XATOI(argv[1]); + if (lenArg < 0) { + printf("Invalid length %d\n", lenArg); + return BAD_FUNC_ARG; + } + len = (word32)lenArg; if (len == 0) { len = GETRANDOM_DEFAULT_BYTES; } diff --git a/examples/wrap/hash.c b/examples/wrap/hash.c index 83116629b..82356df0f 100644 --- a/examples/wrap/hash.c +++ b/examples/wrap/hash.c @@ -146,6 +146,7 @@ int TPM2_Hash_Example(void* userCtx, int argc, char* argv[]) exit: + wolfTPM2_UnloadHandle(&dev, &hash.handle); wolfTPM2_Cleanup(&dev); return rc; diff --git a/hal/tpm_io.c b/hal/tpm_io.c index 9ed1cfe27..4ab945d62 100644 --- a/hal/tpm_io.c +++ b/hal/tpm_io.c @@ -183,27 +183,33 @@ int TPM2_IoCb(TPM2_CTX* ctx, INT32 isRead, UINT32 addr, (void)userCtx; #endif #else - /* Build TPM header */ - txBuf[1] = (addr>>16) & 0xFF; - txBuf[2] = (addr>>8) & 0xFF; - txBuf[3] = (addr) & 0xFF; - if (isRead) { - txBuf[0] = TPM_TIS_READ | ((size & 0xFF) - 1); - XMEMSET(&txBuf[TPM_TIS_HEADER_SZ], 0, - sizeof(txBuf) - TPM_TIS_HEADER_SZ); + if (buf == NULL || size == 0 || + size > (UINT16)(sizeof(txBuf) - TPM_TIS_HEADER_SZ)) { + ret = BAD_FUNC_ARG; } else { - txBuf[0] = TPM_TIS_WRITE | ((size & 0xFF) - 1); - XMEMCPY(&txBuf[TPM_TIS_HEADER_SZ], buf, size); - XMEMSET(&txBuf[TPM_TIS_HEADER_SZ + size], 0, - sizeof(txBuf) - TPM_TIS_HEADER_SZ - size); - } - XMEMSET(rxBuf, 0, sizeof(rxBuf)); - - ret = TPM2_IoCb_SPI(ctx, txBuf, rxBuf, size + TPM_TIS_HEADER_SZ, userCtx); - - if (isRead) { - XMEMCPY(buf, &rxBuf[TPM_TIS_HEADER_SZ], size); + /* Build TPM header */ + txBuf[1] = (addr>>16) & 0xFF; + txBuf[2] = (addr>>8) & 0xFF; + txBuf[3] = (addr) & 0xFF; + if (isRead) { + txBuf[0] = TPM_TIS_READ | ((size & 0xFF) - 1); + XMEMSET(&txBuf[TPM_TIS_HEADER_SZ], 0, + sizeof(txBuf) - TPM_TIS_HEADER_SZ); + } + else { + txBuf[0] = TPM_TIS_WRITE | ((size & 0xFF) - 1); + XMEMCPY(&txBuf[TPM_TIS_HEADER_SZ], buf, size); + XMEMSET(&txBuf[TPM_TIS_HEADER_SZ + size], 0, + sizeof(txBuf) - TPM_TIS_HEADER_SZ - size); + } + XMEMSET(rxBuf, 0, sizeof(rxBuf)); + + ret = TPM2_IoCb_SPI(ctx, txBuf, rxBuf, size + TPM_TIS_HEADER_SZ, userCtx); + + if (isRead) { + XMEMCPY(buf, &rxBuf[TPM_TIS_HEADER_SZ], size); + } } #endif diff --git a/hal/tpm_io_espressif.c b/hal/tpm_io_espressif.c index d54c1b438..a68374631 100644 --- a/hal/tpm_io_espressif.c +++ b/hal/tpm_io_espressif.c @@ -187,6 +187,7 @@ static esp_err_t show_binary(byte* theVar, size_t dataSz) { hex_buffer[maxSz * 2] = '\0'; ESP_LOGI("TAG", "%s", hex_buffer); ESP_LOGI(TAG, "*********************************************************"); + TPM2_ForceZero(hex_buffer, sizeof(hex_buffer)); return ESP_OK; } #endif diff --git a/src/fwtpm/fwtpm.c b/src/fwtpm/fwtpm.c index 1d6c2b0be..12d653720 100644 --- a/src/fwtpm/fwtpm.c +++ b/src/fwtpm/fwtpm.c @@ -40,6 +40,7 @@ int FWTPM_Init(FWTPM_CTX* ctx) { int rc; int rngInit = 0; + int wcInit = 0; FWTPM_NV_HAL savedNvHal; struct FWTPM_CLOCK_HAL_S savedClockHal; #ifndef FWTPM_NO_PP @@ -96,6 +97,7 @@ int FWTPM_Init(FWTPM_CTX* ctx) /* Initialize wolfCrypt RNG */ rc = wolfCrypt_Init(); if (rc == 0) { + wcInit = 1; rc = wc_InitRng(&ctx->rng); if (rc == 0) { rngInit = 1; @@ -141,7 +143,9 @@ int FWTPM_Init(FWTPM_CTX* ctx) if (rngInit) { wc_FreeRng(&ctx->rng); } - wolfCrypt_Cleanup(); + if (wcInit) { + wolfCrypt_Cleanup(); + } } return rc; diff --git a/src/fwtpm/fwtpm_command.c b/src/fwtpm/fwtpm_command.c index fa201d3e9..d70b05cf0 100644 --- a/src/fwtpm/fwtpm_command.c +++ b/src/fwtpm/fwtpm_command.c @@ -2401,6 +2401,14 @@ static TPM_RC FwCmd_PCR_Read(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize, printf("fwTPM: PCR_Read(selCount=%d)\n", pcrSelCount); #endif + /* Reject more banks than the implementation supports rather than + * echoing a count that exceeds the emitted selections */ + if (pcrSelCount > HASH_COUNT) { + rc = TPM_RC_SIZE; + } + } + + if (rc == 0) { /* pcrUpdateCounter */ TPM2_Packet_AppendU32(rsp, ctx->pcrUpdateCounter); @@ -2408,9 +2416,6 @@ static TPM_RC FwCmd_PCR_Read(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize, TPM2_Packet_AppendU32(rsp, pcrSelCount); numSel = pcrSelCount; - if (numSel > HASH_COUNT) { - numSel = HASH_COUNT; - } for (s = 0; s < numSel && rc == 0; s++) { int j; @@ -2422,7 +2427,8 @@ static TPM_RC FwCmd_PCR_Read(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize, TPM2_Packet_ParseU16(cmd, &selections[s].hashAlg); TPM2_Packet_ParseU8(cmd, &selections[s].sizeOfSelect); if (selections[s].sizeOfSelect > PCR_SELECT_MAX) { - selections[s].sizeOfSelect = PCR_SELECT_MAX; + rc = TPM_RC_SIZE; + break; } for (j = 0; j < selections[s].sizeOfSelect; j++) { if (cmd->pos >= cmdSize) { @@ -3565,8 +3571,8 @@ static TPM_RC FwCmd_CreatePrimary(FWTPM_CTX* ctx, TPM2_Packet* cmd, for (cacheIdx = 0; cacheIdx < FWTPM_MAX_PRIMARY_CACHE; cacheIdx++) { if (ctx->primaryCache[cacheIdx].used && ctx->primaryCache[cacheIdx].hierarchy == primaryHandle && - XMEMCMP(ctx->primaryCache[cacheIdx].templateHash, templateHash, - WC_SHA256_DIGEST_SIZE) == 0) { + TPM2_ConstantCompare(ctx->primaryCache[cacheIdx].templateHash, + templateHash, WC_SHA256_DIGEST_SIZE) == 0) { cached = &ctx->primaryCache[cacheIdx]; break; } @@ -6457,18 +6463,21 @@ static TPM_RC FwCmd_Create(FWTPM_CTX* ctx, TPM2_Packet* cmd, /* Compute object name from public area for creation ticket */ nameDigSz = TPM2_GetHashDigestSize(inPublic->publicArea.nameAlg); FWTPM_ALLOC_BUF(pubBuf2, FWTPM_MAX_PUB_BUF); - tmpPkt2.buf = pubBuf2; - tmpPkt2.pos = 0; - tmpPkt2.size = (int)FWTPM_MAX_PUB_BUF; - TPM2_Packet_AppendPublicArea(&tmpPkt2, &inPublic->publicArea); - FwStoreU16BE(objName, inPublic->publicArea.nameAlg); - if (nameDigSz > 0) { - int hashRc = wc_Hash(FwGetWcHashType(inPublic->publicArea.nameAlg), - pubBuf2, tmpPkt2.pos, objName + 2, nameDigSz); - if (hashRc == 0) - objNameSz = 2 + nameDigSz; - } - FWTPM_FREE_BUF(pubBuf2); + if (rc == 0) { + tmpPkt2.buf = pubBuf2; + tmpPkt2.pos = 0; + tmpPkt2.size = (int)FWTPM_MAX_PUB_BUF; + TPM2_Packet_AppendPublicArea(&tmpPkt2, &inPublic->publicArea); + FwStoreU16BE(objName, inPublic->publicArea.nameAlg); + if (nameDigSz > 0) { + int hashRc = wc_Hash( + FwGetWcHashType(inPublic->publicArea.nameAlg), + pubBuf2, tmpPkt2.pos, objName + 2, nameDigSz); + if (hashRc == 0) + objNameSz = 2 + nameDigSz; + } + FWTPM_FREE_BUF(pubBuf2); + } /* Creation ticket hierarchy = parent's hierarchy per Part 2 * Sec.10.6.5 Table 112. */ @@ -10368,17 +10377,22 @@ static TPM_RC FwCmd_StartAuthSession(FWTPM_CTX* ctx, TPM2_Packet* cmd, FWTPM_ALLOC_BUF(encSalt, FWTPM_MAX_PUB_BUF); - (void)cmdTag; - (void)cmdSize; - /* Parse: tpmKey(U32), bind(U32) */ TPM2_Packet_ParseU32(cmd, &tpmKey); TPM2_Packet_ParseU32(cmd, &bind); + /* A session-tagged command with no auth handles still carries an auth + * area between the handles and parameters; skip it before parsing */ + if (cmdTag == TPM_ST_SESSIONS) { + rc = FwSkipAuthArea(cmd, cmdSize); + } + /* Parse: nonceCaller (TPM2B) */ - TPM2_Packet_ParseU16(cmd, &nonceCallerSize); - if (nonceCallerSize > sizeof(nonceCaller)) { - rc = TPM_RC_SIZE; + if (rc == 0) { + TPM2_Packet_ParseU16(cmd, &nonceCallerSize); + if (nonceCallerSize > sizeof(nonceCaller)) { + rc = TPM_RC_SIZE; + } } if (rc == 0 && nonceCallerSize > 0) { TPM2_Packet_ParseBytes(cmd, nonceCaller, nonceCallerSize); @@ -10593,7 +10607,13 @@ static TPM_RC FwCmd_StartAuthSession(FWTPM_CTX* ctx, TPM2_Packet* cmd, FwFreeSession(sess); } TPM2_ForceZero(salt, sizeof(salt)); +#ifdef WOLFTPM_SMALL_STACK + if (encSalt != NULL) { + TPM2_ForceZero(encSalt, FWTPM_MAX_PUB_BUF); + } +#else TPM2_ForceZero(encSalt, FWTPM_MAX_PUB_BUF); +#endif FWTPM_FREE_BUF(encSalt); return rc; } @@ -12393,11 +12413,17 @@ static TPM_RC FwCmd_PolicyTemplate(FWTPM_CTX* ctx, TPM2_Packet* cmd, if (sess->cpHashA.size > 0 || sess->nameHash.size > 0) { rc = TPM_RC_CPHASH; } - else if (sess->templateHash.size > 0 && - (sess->templateHash.size != templateHashSz || - TPM2_ConstantCompare(sess->templateHash.buffer, templateHash, - templateHashSz) != 0)) { - rc = TPM_RC_VALUE; + else if (sess->templateHash.size > 0) { + /* Always run the compare so a size mismatch cannot short-circuit + * the constant-time path */ + int sizeMismatch = (sess->templateHash.size != templateHashSz); + word32 cmpSz = (sess->templateHash.size < templateHashSz) ? + sess->templateHash.size : templateHashSz; + if (sizeMismatch | + (TPM2_ConstantCompare(sess->templateHash.buffer, templateHash, + cmpSz) != 0)) { + rc = TPM_RC_VALUE; + } } } if (rc == 0) { @@ -14413,7 +14439,13 @@ static TPM_RC FwEncryptDecryptCore(FWTPM_CTX* ctx, TPM2_Packet* cmd, FWTPM_ALLOC_VAR(aes, Aes); XMEMSET(ivBuf, 0, sizeof(ivBuf)); +#ifdef WOLFTPM_SMALL_STACK + if (inData != NULL) { + XMEMSET(inData, 0, FWTPM_MAX_COMMAND_SIZE / 2); + } +#else XMEMSET(inData, 0, FWTPM_MAX_COMMAND_SIZE / 2); +#endif if (cmdSize < TPM2_HEADER_SIZE + 4) { rc = TPM_RC_COMMAND_SIZE; @@ -14659,7 +14691,13 @@ static TPM_RC FwEncryptDecryptCore(FWTPM_CTX* ctx, TPM2_Packet* cmd, FwRspParamsEnd(rsp, cmdTag, paramSzPos, paramStart); } +#ifdef WOLFTPM_SMALL_STACK + if (inData != NULL) { + TPM2_ForceZero(inData, FWTPM_MAX_COMMAND_SIZE / 2); + } +#else TPM2_ForceZero(inData, FWTPM_MAX_COMMAND_SIZE / 2); +#endif FWTPM_FREE_BUF(inData); FWTPM_FREE_VAR(aes); return rc; @@ -15586,7 +15624,11 @@ static TPM_RC FwCmd_MakeCredential(FWTPM_CTX* ctx, TPM2_Packet* cmd, } } - /* MakeCredential has no auth area */ + /* A session-tagged command with no auth handles still carries an auth + * area between the handle and parameters; skip it before parsing */ + if (rc == 0 && cmdTag == TPM_ST_SESSIONS) { + rc = FwSkipAuthArea(cmd, cmdSize); + } /* credential (TPM2B_DIGEST) */ if (rc == 0) { @@ -18959,18 +19001,29 @@ static TPM_RC FwCheckPolicyAssertions(FWTPM_CTX* ctx, TPM_RC rc = TPM_RC_SUCCESS; byte digest[TPM_MAX_DIGEST_SIZE]; int digestSz = 0; + int sizeMismatch; + word32 cmpSz; if (sess->commandCode != 0 && sess->commandCode != cmdCode) { rc = TPM_RC_POLICY_CC; } if (rc == 0 && sess->nameHash.size > 0) { if (FwComputeNameHash(ctx, sess->authHash, handles, handleCnt, - digest, &digestSz) != 0 || - (int)sess->nameHash.size != digestSz || - TPM2_ConstantCompare(sess->nameHash.buffer, digest, - (word32)digestSz) != 0) { + digest, &digestSz) != 0) { rc = TPM_RC_POLICY_FAIL; } + else { + /* Always run the compare so a size mismatch cannot short-circuit + * the constant-time path */ + sizeMismatch = ((int)sess->nameHash.size != digestSz); + cmpSz = (sess->nameHash.size < (word32)digestSz) ? + sess->nameHash.size : (word32)digestSz; + if (sizeMismatch | + (TPM2_ConstantCompare(sess->nameHash.buffer, digest, + cmpSz) != 0)) { + rc = TPM_RC_POLICY_FAIL; + } + } } /* PolicyTemplate binds only the creation template (Part 3 Sec.23.19); * it does not restrict the command, that is PolicyCommandCode's role. */ @@ -18978,12 +19031,19 @@ static TPM_RC FwCheckPolicyAssertions(FWTPM_CTX* ctx, (cmdCode == TPM_CC_Create || cmdCode == TPM_CC_CreatePrimary || cmdCode == TPM_CC_CreateLoaded)) { if (FwComputeTemplateHash(sess->authHash, cmdBuf, cmdSize, cpStart, - digest, &digestSz) != 0 || - (int)sess->templateHash.size != digestSz || - TPM2_ConstantCompare(sess->templateHash.buffer, digest, - (word32)digestSz) != 0) { + digest, &digestSz) != 0) { rc = TPM_RC_POLICY_FAIL; } + else { + sizeMismatch = ((int)sess->templateHash.size != digestSz); + cmpSz = (sess->templateHash.size < (word32)digestSz) ? + sess->templateHash.size : (word32)digestSz; + if (sizeMismatch | + (TPM2_ConstantCompare(sess->templateHash.buffer, digest, + cmpSz) != 0)) { + rc = TPM_RC_POLICY_FAIL; + } + } } if (rc == 0 && sess->checkNvWritten) { #ifndef FWTPM_NO_NV @@ -19181,6 +19241,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, if (authAreaSz > (UINT32)(cmdSize - cmdPkt.pos)) { *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_AUTHSIZE); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } cpStart = cmdPkt.pos + (int)authAreaSz; @@ -19324,6 +19385,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, if (rc != TPM_RC_SUCCESS) { *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, rc); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } @@ -19332,6 +19394,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, if (entry->authHandleCnt > 0 && cmdAuthCnt < (int)entry->authHandleCnt) { *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_AUTH_MISSING); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } @@ -19342,6 +19405,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, cmdAuths[pj].sess->sessionType == TPM_SE_TRIAL) { *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_AUTH_TYPE); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } } @@ -19369,6 +19433,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, pSess->pcrUpdateCounter != ctx->pcrUpdateCounter) { *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_PCR_CHANGED); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } @@ -19432,6 +19497,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, #endif *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_POLICY_FAIL); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } /* Enforce any PolicyLocality constraint bound to the session */ @@ -19440,6 +19506,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, !((1u << ctx->activeLocality) & pSess->requiredLocality))) { *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_LOCALITY); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } #ifndef FWTPM_NO_PP @@ -19449,6 +19516,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, !FwPhysicalPresenceAsserted(ctx)) { *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_PP); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } #endif /* !FWTPM_NO_PP */ @@ -19465,6 +19533,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, ccpHash, (word32)ccpHashSz) != 0) { *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_POLICY_FAIL); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } } @@ -19483,6 +19552,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, #endif *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_POLICY_FAIL); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } else if (authPolicy == NULL) { @@ -19495,6 +19565,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, #endif *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_POLICY_FAIL); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } @@ -19509,6 +19580,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, #endif *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, rc); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } } @@ -19535,6 +19607,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, NULL) & FW_AUTH_USES_LOCKOUT) != 0) { *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_LOCKOUT); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } } @@ -19572,6 +19645,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, hasDaAuth) { *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_LOCKOUT); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } } @@ -19620,6 +19694,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, #ifdef FWTPM_DA_USED_RETRY *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_RETRY); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; #endif } @@ -19640,6 +19715,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, #endif *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_AUTH_TYPE); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } @@ -19684,6 +19760,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, #endif *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_AUTH_TYPE); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } if (adminSess != NULL && adminSess->sessionType == TPM_SE_POLICY && @@ -19694,6 +19771,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, #endif *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_POLICY_CC); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } } @@ -19720,6 +19798,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, #endif *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_AUTH_UNAVAILABLE); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } } @@ -19756,12 +19835,14 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, if (FwDaRegisterFailure(ctx, daHandle)) { *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_LOCKOUT); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } } #endif *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, authRc); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } } @@ -19789,6 +19870,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, ctx, cpStart, cpHash, &cpHashSz) != 0) { *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_FAILURE); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } @@ -19820,12 +19902,14 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, if (FwDaRegisterFailure(ctx, daHandle)) { *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_LOCKOUT); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } } #endif *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, authRc); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } TPM2_ForceZero(cpHash, sizeof(cpHash)); @@ -19868,12 +19952,14 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, if (FwDaRegisterFailure(ctx, daHandle)) { *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_LOCKOUT); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } } #endif *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, authRc); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } @@ -19898,6 +19984,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, #endif *rspSize = FwBuildErrorResponse(rspBuf, rspCap, TPM_ST_NO_SESSIONS, TPM_RC_FAILURE); + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } } @@ -20151,10 +20238,12 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, FwFlushAllObjects(ctx); nvRc = FWTPM_NV_Save(ctx); if (nvRc != TPM_RC_SUCCESS) { + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return nvRc; } } + TPM2_ForceZero(cmdAuths, sizeof(cmdAuths)); return TPM_RC_SUCCESS; } diff --git a/src/fwtpm/fwtpm_crypto.c b/src/fwtpm/fwtpm_crypto.c index 5ffea3422..b19459d6c 100644 --- a/src/fwtpm/fwtpm_crypto.c +++ b/src/fwtpm/fwtpm_crypto.c @@ -2259,6 +2259,7 @@ int FwWrapPrivate(FWTPM_Object* parent, WC_RNG* rng, FWTPM_DECLARE_VAR(hmac, Hmac); int sensSz = 0; int aesInit = 0; + int hmacInit = 0; int pos = 0; FWTPM_ALLOC_BUF(sensBuf, FWTPM_MAX_PRIVKEY_DER + 128); @@ -2304,6 +2305,9 @@ int FwWrapPrivate(FWTPM_Object* parent, WC_RNG* rng, /* HMAC integrity over IV and encrypted data */ if (rc == 0) { rc = wc_HmacInit(hmac, NULL, INVALID_DEVID); + if (rc == 0) { + hmacInit = 1; + } } if (rc == 0) { rc = wc_HmacSetKey(hmac, WC_SHA256, macKey, sizeof(macKey)); @@ -2317,7 +2321,9 @@ int FwWrapPrivate(FWTPM_Object* parent, WC_RNG* rng, if (rc == 0) { rc = wc_HmacFinal(hmac, hmacDigest); } - wc_HmacFree(hmac); + if (hmacInit) { + wc_HmacFree(hmac); + } /* Pack into TPM2B_PRIVATE */ if (rc == 0) { @@ -2517,7 +2523,9 @@ int FwWrapContextBlob(FWTPM_CTX* ctx, UINT64 seq, byte ctxType, FWTPM_ALLOC_VAR(hmac, Hmac); /* Generate random IV */ - rc = wc_RNG_GenerateBlock(&ctx->rng, iv, AES_BLOCK_SIZE); + if (rc == 0) { + rc = wc_RNG_GenerateBlock(&ctx->rng, iv, AES_BLOCK_SIZE); + } /* AES-CFB encrypt */ if (rc == 0) { diff --git a/src/fwtpm/fwtpm_nv.c b/src/fwtpm/fwtpm_nv.c index fe1059c5e..9c4ecc612 100644 --- a/src/fwtpm/fwtpm_nv.c +++ b/src/fwtpm/fwtpm_nv.c @@ -1759,6 +1759,7 @@ static int FwNvInitAppendOnly(FWTPM_CTX* ctx, byte** valueBufP, rc = TPM_RC_MEMORY; break; } + TPM2_ForceZero(valueBuf, valueBufSz); XFREE(valueBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); valueBuf = newBuf; valueBufSz = len; @@ -1933,6 +1934,7 @@ int FWTPM_NV_Init(FWTPM_CTX* ctx) rc = TPM_RC_MEMORY; break; } + TPM2_ForceZero(valueBuf, valueBufSz); XFREE(valueBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); valueBuf = newBuf; valueBufSz = len; @@ -1970,6 +1972,7 @@ int FWTPM_NV_Init(FWTPM_CTX* ctx) rc = FwNvGenFreshState(ctx); } + TPM2_ForceZero(valueBuf, valueBufSz); XFREE(valueBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); return rc; } @@ -2097,6 +2100,7 @@ int FWTPM_NV_Save(FWTPM_CTX* ctx) rc = TPM_RC_MEMORY; } else { + TPM2_ForceZero(buf, bufSz); XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); buf = newBuf; bufSz = needed; @@ -2214,6 +2218,7 @@ int FWTPM_NV_Save(FWTPM_CTX* ctx) rc = TPM_RC_MEMORY; break; } + TPM2_ForceZero(buf, bufSz); XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); buf = newBuf; bufSz = needed; @@ -2242,6 +2247,7 @@ int FWTPM_NV_Save(FWTPM_CTX* ctx) rc = TPM_RC_MEMORY; break; } + TPM2_ForceZero(buf, bufSz); XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); buf = newBuf; bufSz = needed; @@ -2269,6 +2275,7 @@ int FWTPM_NV_Save(FWTPM_CTX* ctx) rc = TPM_RC_MEMORY; break; } + TPM2_ForceZero(buf, bufSz); XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); buf = newBuf; bufSz = needed; @@ -2371,6 +2378,7 @@ int FWTPM_NV_SaveAuth(FWTPM_CTX* ctx, UINT32 hierarchy) if (rc == 0) { rc = FwNvAppendEntry(ctx, tag, buf, (UINT16)pos); } + TPM2_ForceZero(buf, sizeof(buf)); return rc; } @@ -2426,6 +2434,7 @@ int FWTPM_NV_SavePcrAuth(FWTPM_CTX* ctx) rc = FwNvAppendEntry(ctx, FWTPM_NV_TAG_PCR_AUTH, buf, (UINT16)pos); + TPM2_ForceZero(buf, bufSz); XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); return rc; } diff --git a/src/fwtpm/fwtpm_tis.c b/src/fwtpm/fwtpm_tis.c index b78d38ea5..0169081db 100644 --- a/src/fwtpm/fwtpm_tis.c +++ b/src/fwtpm/fwtpm_tis.c @@ -51,6 +51,11 @@ * VID = "WF" (0x4657), DID = "TP" (0x5054) */ #define FWTPM_TIS_DID_VID_VAL 0x50544657UL +/* The TIS response FIFO must hold a full dispatched response; a mismatched + * FWTPM_TIS_FIFO_SIZE override must fail the build, not overflow at runtime */ +typedef char fwtpm_tis_fifo_fits_max_cmd[ + (FWTPM_TIS_FIFO_SIZE >= FWTPM_MAX_COMMAND_SIZE) ? 1 : -1]; + /* --- Static helpers --- */ /* Extract register offset from a full TIS address. diff --git a/src/spdm/spdm_context.c b/src/spdm/spdm_context.c index cc6b17f9d..5d2a569eb 100644 --- a/src/spdm/spdm_context.c +++ b/src/spdm/spdm_context.c @@ -369,7 +369,8 @@ int wolfSPDM_Disconnect(WOLFSPDM_CTX* ctx) } } - /* Reset state and zero ALL key material */ + /* Reset session state and wipe session-scoped keys; configured identity + * keys remain for a later connection */ ctx->state = WOLFSPDM_STATE_INIT; ctx->sessionId = 0; ctx->reqSeqNum = 0; diff --git a/src/spdm/spdm_msg.c b/src/spdm/spdm_msg.c index e627a5661..388ec4032 100644 --- a/src/spdm/spdm_msg.c +++ b/src/spdm/spdm_msg.c @@ -55,6 +55,18 @@ static int wolfSPDM_BuildSimpleMsg(WOLFSPDM_CTX* ctx, byte msgCode, return WOLFSPDM_SUCCESS; } +/* KEY_EXCHANGE request size: 8-byte header, 32-byte RandomData, and two ECC + * coordinates, plus a config-specific OpaqueData block. Keep + * WOLFSPDM_KEYEX_OPAQUE_SZ in sync with the OpaqueData written below. */ +#define WOLFSPDM_KEYEX_FIXED_SZ (40 + 2 * WOLFSPDM_ECC_KEY_SIZE) +#ifdef WOLFSPDM_NUVOTON + #define WOLFSPDM_KEYEX_OPAQUE_SZ 14 +#elif defined(WOLFSPDM_NATIONS) + #define WOLFSPDM_KEYEX_OPAQUE_SZ 2 +#else + #define WOLFSPDM_KEYEX_OPAQUE_SZ 22 +#endif + int wolfSPDM_BuildKeyExchange(WOLFSPDM_CTX* ctx, byte* buf, word32* bufSz) { word32 offset = 0; @@ -64,7 +76,9 @@ int wolfSPDM_BuildKeyExchange(WOLFSPDM_CTX* ctx, byte* buf, word32* bufSz) word32 pubKeyYSz = sizeof(pubKeyY); int rc; - SPDM_CHECK_BUILD_ARGS(ctx, buf, bufSz, 180); + /* Require exactly the encoded request size */ + SPDM_CHECK_BUILD_ARGS(ctx, buf, bufSz, + WOLFSPDM_KEYEX_FIXED_SZ + WOLFSPDM_KEYEX_OPAQUE_SZ); rc = wolfSPDM_GenerateEphemeralKey(ctx); if (rc == WOLFSPDM_SUCCESS) diff --git a/src/spdm/spdm_nations.c b/src/spdm/spdm_nations.c index 33108fbc9..37d722442 100644 --- a/src/spdm/spdm_nations.c +++ b/src/spdm/spdm_nations.c @@ -75,6 +75,9 @@ int wolfSPDM_Nations_GetStatus(WOLFSPDM_CTX* ctx, status->pskProvisioned ? "YES" : "NO", rsp.payload[3]); } + else { + return WOLFSPDM_E_FRAMING; + } return WOLFSPDM_SUCCESS; } diff --git a/src/spdm/spdm_nuvoton.c b/src/spdm/spdm_nuvoton.c index 6ef017702..400046db6 100644 --- a/src/spdm/spdm_nuvoton.c +++ b/src/spdm/spdm_nuvoton.c @@ -82,6 +82,9 @@ int wolfSPDM_Nuvoton_GetStatus( wolfSPDM_DebugPrint(ctx, "GET_STS_: SPDMOnly=%s (minimal response)\n", status->spdmOnlyLocked ? "LOCKED" : "unlocked"); } + else { + return WOLFSPDM_E_FRAMING; + } return WOLFSPDM_SUCCESS; } diff --git a/src/spdm/spdm_responder.c b/src/spdm/spdm_responder.c index 371122885..05aff93c6 100644 --- a/src/spdm/spdm_responder.c +++ b/src/spdm/spdm_responder.c @@ -152,12 +152,19 @@ int wolfSPDM_RespSetPSK(WOLFSPDM_RESP_CTX* ctx, (void)hintSz; return WOLFSPDM_E_NOT_AVAILABLE; #else + int rc; if (ctx == NULL || !ctx->flags.initialized) { return WOLFSPDM_E_INVALID_ARG; } if (psk == NULL || pskSz == 0 || pskSz > sizeof(ctx->pskStore)) { return WOLFSPDM_E_INVALID_ARG; } + /* Commit the inner context first so a rejected PSK leaves no partially + * provisioned responder state */ + rc = wolfSPDM_SetPSK(&ctx->ctx, psk, pskSz, hint, hintSz); + if (rc != WOLFSPDM_SUCCESS) { + return rc; + } XMEMCPY(ctx->pskStore, psk, pskSz); ctx->pskStoreSz = pskSz; if (hint != NULL && hintSz > 0 && hintSz <= sizeof(ctx->pskHintStore)) { @@ -168,7 +175,7 @@ int wolfSPDM_RespSetPSK(WOLFSPDM_RESP_CTX* ctx, ctx->pskHintStoreSz = 0; } ctx->flags.pskProvisioned = 1; - return wolfSPDM_SetPSK(&ctx->ctx, psk, pskSz, hint, hintSz); + return WOLFSPDM_SUCCESS; #endif } @@ -484,9 +491,10 @@ static int RespBuildPskExchangeRsp(WOLFSPDM_RESP_CTX* rctx, reqHintLen = SPDM_Get16LE(&in[6]); reqContextLen = SPDM_Get16LE(&in[8]); reqOpaqueLen = SPDM_Get16LE(&in[10]); - (void)reqHintLen; - (void)reqContextLen; - (void)reqOpaqueLen; + /* Every declared variable-length field must fit within the request */ + if ((word32)12 + reqHintLen + reqContextLen + reqOpaqueLen > inSz) { + return WOLFSPDM_E_FRAMING; + } ctx->rspSessionId = 0xFFFE; ctx->sessionId = (word32)ctx->reqSessionId | @@ -1152,7 +1160,7 @@ static int RespDispatchSecured(WOLFSPDM_RESP_CTX* rctx, rc = wolfSPDM_DeriveAppDataKeys(ctx); } - if (sessionEnded) { + if (sessionEnded && rc == WOLFSPDM_SUCCESS) { wolfSPDM_RespReset(rctx); } return rc; diff --git a/src/spdm/spdm_secured.c b/src/spdm/spdm_secured.c index 6544c13b8..705a757d4 100644 --- a/src/spdm/spdm_secured.c +++ b/src/spdm/spdm_secured.c @@ -120,6 +120,12 @@ int wolfSPDM_EncryptInternal(WOLFSPDM_CTX* ctx, word16 appDataLen = (word16)(1 + plainSz); word16 encDataLen = (word16)(2 + appDataLen); + /* MCTP carries a 16-bit sequence number; fail rather than let the wire + * value and the 64-bit IV counter diverge past 0xFFFF */ + if (ctx->reqSeqNum > 0xFFFF) { + return WOLFSPDM_E_BAD_STATE; + } + plainBufSz = encDataLen; recordLen = (word16)(encDataLen + WOLFSPDM_AEAD_TAG_SIZE); hdrSz = 8; /* 4 + 2 + 2 */ @@ -272,10 +278,6 @@ int wolfSPDM_DecryptInternal(WOLFSPDM_CTX* ctx, wolfSPDM_BuildIV(iv, ctx->rspDataIv, (word64)rspSeqNum); } - /* response consumed and seq validated; advance to stay in lockstep with - * the peer even if AEAD/parse below fails */ - ctx->rspSeqNum++; - /* ----- AES-GCM decrypt (shared for both transports) ----- */ ret = WOLFSPDM_E_CRYPTO_FAIL; @@ -292,6 +294,13 @@ int wolfSPDM_DecryptInternal(WOLFSPDM_CTX* ctx, wolfSPDM_DebugPrint(ctx, "AES-GCM decrypt failed: %d\n", rc); ret = WOLFSPDM_E_DECRYPT_FAIL; } + else { + /* Record is authenticated (tag verified) so the peer has advanced; + * advance now. A forged record fails the tag and never reaches + * here, and a later payload parse error stays fatal without + * desyncing the sequence. */ + ctx->rspSeqNum++; + } } if (aesInit) { wc_AesFree(&aes); diff --git a/src/spdm/spdm_tcg.c b/src/spdm/spdm_tcg.c index e80184bb1..936df65a9 100644 --- a/src/spdm/spdm_tcg.c +++ b/src/spdm/spdm_tcg.c @@ -204,6 +204,14 @@ int wolfSPDM_BuildVendorDefined( if (vdCode == NULL || outBuf == NULL) { return WOLFSPDM_E_INVALID_ARG; } + if (payload == NULL && payloadSz != 0) { + return WOLFSPDM_E_INVALID_ARG; + } + + /* Reject a payload that would overflow the 16-bit request-length field */ + if (payloadSz > (word32)(0xFFFF - WOLFSPDM_VDCODE_LEN)) { + return WOLFSPDM_E_INVALID_ARG; + } /* SPDM VENDOR_DEFINED_REQUEST format: * SPDMVersion(1) + reqRspCode(1) + param1(1) + param2(1) + diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 53f8e2976..2a9476400 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -2904,6 +2904,8 @@ int wolfTPM2_StartSession_ex(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session, #ifdef DEBUG_WOLFTPM printf("TPM2_GetNonce failed %d: %s\n", rc, wolfTPM2_GetRCString(rc)); #endif + TPM2_ForceZero(&authSesIn, sizeof(authSesIn)); + TPM2_ForceZero(&authSesOut, sizeof(authSesOut)); return rc; } @@ -2913,6 +2915,8 @@ int wolfTPM2_StartSession_ex(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session, rc = TPM2_GetNonceNoLock(session->salt.buffer, session->salt.size); if (rc != 0) { TPM2_ForceZero(&session->salt, sizeof(session->salt)); + TPM2_ForceZero(&authSesIn, sizeof(authSesIn)); + TPM2_ForceZero(&authSesOut, sizeof(authSesOut)); return rc; } @@ -2925,6 +2929,8 @@ int wolfTPM2_StartSession_ex(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session, wolfTPM2_GetRCString(rc)); #endif TPM2_ForceZero(&session->salt, sizeof(session->salt)); + TPM2_ForceZero(&authSesIn, sizeof(authSesIn)); + TPM2_ForceZero(&authSesOut, sizeof(authSesOut)); return rc; } }