F-3001 - https://fenrir.wolfssl.com/finding/3001 - Reject NULL IV for non-ECB modes and oversized IV in wolfTPM2_EncryptDecryptBlock

pull/488/head
Aidan 2026-04-17 13:44:06 -07:00
parent f1afb9ff4a
commit bf3a39fb4a
4 changed files with 90 additions and 8 deletions

View File

@ -160,6 +160,7 @@ static int bench_sym_aes(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* storageKey,
double start;
TPMT_PUBLIC publicTemplate;
WOLFTPM2_KEY aesKey;
byte iv[MAX_AES_BLOCK_SIZE_BYTES];
XMEMSET(&aesKey, 0, sizeof(aesKey));
rc = wolfTPM2_GetKeyTemplate_Symmetric(&publicTemplate, keyBits, algo,
@ -175,8 +176,9 @@ static int bench_sym_aes(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* storageKey,
bench_stats_start(&count, &start);
do {
rc = wolfTPM2_EncryptDecrypt(dev, &aesKey, in, out, inOutSz, NULL, 0,
isDecrypt);
XMEMSET(iv, 0, sizeof(iv));
rc = wolfTPM2_EncryptDecrypt(dev, &aesKey, in, out, inOutSz, iv,
sizeof(iv), isDecrypt);
if (WOLFTPM_IS_COMMAND_UNAVAILABLE(rc)) {
printf("Encrypt/Decrypt unavailable\n");
break;

View File

@ -960,14 +960,16 @@ int TPM2_Wrapper_TestArgs(void* userCtx, int argc, char *argv[])
XMEMSET(cipher.buffer, 0, sizeof(cipher.buffer));
cipher.size = message.size;
XMEMSET(aesIv, 0, sizeof(aesIv));
rc = wolfTPM2_EncryptDecrypt(&dev, &aesKey, message.buffer, cipher.buffer,
message.size, NULL, 0, WOLFTPM2_ENCRYPT);
message.size, aesIv, (word32)sizeof(aesIv), WOLFTPM2_ENCRYPT);
if (rc != 0 && !WOLFTPM_IS_COMMAND_UNAVAILABLE(rc)) goto exit;
XMEMSET(plain.buffer, 0, sizeof(plain.buffer));
plain.size = message.size;
XMEMSET(aesIv, 0, sizeof(aesIv));
rc = wolfTPM2_EncryptDecrypt(&dev, &aesKey, cipher.buffer, plain.buffer,
cipher.size, NULL, 0, WOLFTPM2_DECRYPT);
cipher.size, aesIv, (word32)sizeof(aesIv), WOLFTPM2_DECRYPT);
wolfTPM2_UnloadHandle(&dev, &aesKey.handle);

View File

@ -6635,18 +6635,23 @@ int wolfTPM2_EncryptDecryptBlock(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
XMEMSET(&encDecIn, 0, sizeof(encDecIn));
encDecIn.keyHandle = key->handle.hndl;
/* use symmetric algorithm from key */
encDecIn.mode = key->pub.publicArea.parameters.symDetail.sym.mode.aes;
if (iv == NULL || ivSz == 0) {
/* Modes other than ECB and NULL require an explicit IV */
if (encDecIn.mode != TPM_ALG_ECB && encDecIn.mode != TPM_ALG_NULL) {
return BAD_FUNC_ARG;
}
encDecIn.ivIn.size = MAX_AES_BLOCK_SIZE_BYTES; /* zeros */
}
else {
if (ivSz > sizeof(encDecIn.ivIn.buffer)) {
return BUFFER_E;
}
encDecIn.ivIn.size = ivSz;
if (encDecIn.ivIn.size > sizeof(encDecIn.ivIn.buffer))
encDecIn.ivIn.size = sizeof(encDecIn.ivIn.buffer); /* truncate */
XMEMCPY(encDecIn.ivIn.buffer, iv, encDecIn.ivIn.size);
}
encDecIn.decrypt = isDecrypt;
/* use symmetric algorithm from key */
encDecIn.mode = key->pub.publicArea.parameters.symDetail.sym.mode.aes;
encDecIn.inData.size = inOutSz;
XMEMCPY(encDecIn.inData.buffer, in, inOutSz);

View File

@ -2626,6 +2626,78 @@ static void test_wolfTPM2_LoadPrivateKey_NullParent(void)
printf("Test TPM Wrapper:\tLoadPrivateKey NullParent:\tPassed\n");
}
static void test_wolfTPM2_EncryptDecryptBlock(void)
{
int rc;
WOLFTPM2_DEV dev;
WOLFTPM2_KEY key;
byte in[MAX_AES_BLOCK_SIZE_BYTES];
byte out[MAX_AES_BLOCK_SIZE_BYTES];
byte iv[MAX_AES_BLOCK_SIZE_BYTES];
byte bigIv[MAX_SYM_BLOCK_SIZE + 1];
XMEMSET(in, 0, sizeof(in));
XMEMSET(out, 0, sizeof(out));
XMEMSET(iv, 0, sizeof(iv));
XMEMSET(bigIv, 0, sizeof(bigIv));
rc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL);
AssertIntEQ(rc, 0);
XMEMSET(&key, 0, sizeof(key));
/* CBC mode: NULL IV should return BAD_FUNC_ARG */
key.pub.publicArea.parameters.symDetail.sym.mode.aes = TPM_ALG_CBC;
rc = wolfTPM2_EncryptDecryptBlock(&dev, &key, in, out,
sizeof(in), NULL, 0, WOLFTPM2_ENCRYPT);
AssertIntEQ(rc, BAD_FUNC_ARG);
/* CBC mode: ivSz == 0 with non-NULL iv should return BAD_FUNC_ARG */
rc = wolfTPM2_EncryptDecryptBlock(&dev, &key, in, out,
sizeof(in), iv, 0, WOLFTPM2_ENCRYPT);
AssertIntEQ(rc, BAD_FUNC_ARG);
/* CFB mode: NULL IV should return BAD_FUNC_ARG */
key.pub.publicArea.parameters.symDetail.sym.mode.aes = TPM_ALG_CFB;
rc = wolfTPM2_EncryptDecryptBlock(&dev, &key, in, out,
sizeof(in), NULL, 0, WOLFTPM2_ENCRYPT);
AssertIntEQ(rc, BAD_FUNC_ARG);
/* CTR mode: NULL IV should return BAD_FUNC_ARG */
key.pub.publicArea.parameters.symDetail.sym.mode.aes = TPM_ALG_CTR;
rc = wolfTPM2_EncryptDecryptBlock(&dev, &key, in, out,
sizeof(in), NULL, 0, WOLFTPM2_ENCRYPT);
AssertIntEQ(rc, BAD_FUNC_ARG);
/* OFB mode: NULL IV should return BAD_FUNC_ARG */
key.pub.publicArea.parameters.symDetail.sym.mode.aes = TPM_ALG_OFB;
rc = wolfTPM2_EncryptDecryptBlock(&dev, &key, in, out,
sizeof(in), NULL, 0, WOLFTPM2_ENCRYPT);
AssertIntEQ(rc, BAD_FUNC_ARG);
/* Oversized IV should return BUFFER_E */
key.pub.publicArea.parameters.symDetail.sym.mode.aes = TPM_ALG_CBC;
rc = wolfTPM2_EncryptDecryptBlock(&dev, &key, in, out,
sizeof(in), bigIv, sizeof(bigIv), WOLFTPM2_ENCRYPT);
AssertIntEQ(rc, BUFFER_E);
/* ECB mode: NULL IV should NOT return BAD_FUNC_ARG */
key.pub.publicArea.parameters.symDetail.sym.mode.aes = TPM_ALG_ECB;
rc = wolfTPM2_EncryptDecryptBlock(&dev, &key, in, out,
sizeof(in), NULL, 0, WOLFTPM2_ENCRYPT);
AssertIntNE(rc, BAD_FUNC_ARG);
/* NULL mode: NULL IV should NOT return BAD_FUNC_ARG */
key.pub.publicArea.parameters.symDetail.sym.mode.aes = TPM_ALG_NULL;
rc = wolfTPM2_EncryptDecryptBlock(&dev, &key, in, out,
sizeof(in), NULL, 0, WOLFTPM2_ENCRYPT);
AssertIntNE(rc, BAD_FUNC_ARG);
wolfTPM2_Cleanup(&dev);
printf("Test TPM Wrapper:\tEncryptDecryptBlock IV validate:\tPassed\n");
}
#endif /* !WOLFTPM2_NO_WRAPPER */
#ifndef NO_MAIN_DRIVER
@ -2688,6 +2760,7 @@ int unit_tests(int argc, char *argv[])
test_wolfTPM2_DecodeDer_DefaultAttribs();
#endif
test_wolfTPM2_LoadPrivateKey_NullParent();
test_wolfTPM2_EncryptDecryptBlock();
test_wolfTPM2_KeyBlob(TPM_ALG_RSA);
test_wolfTPM2_KeyBlob(TPM_ALG_ECC);
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC) && \