Merge pull request #10155 from aidangarske/fenrir-fixes-2

Add Negative Testing and Zeroization
This commit is contained in:
David Garske
2026-05-11 21:07:53 -07:00
committed by GitHub
4 changed files with 185 additions and 0 deletions
+33
View File
@@ -180,6 +180,39 @@ int test_ascon_aead128(void)
}
}
/* Negative test: corrupted tag must be rejected with ASCON_AUTH_E. */
{
byte key[ASCON_AEAD128_KEY_SZ];
byte nonce[ASCON_AEAD128_NONCE_SZ];
byte pt[4] = { 0x00, 0x01, 0x02, 0x03 };
byte ct[4];
byte tag[ASCON_AEAD128_TAG_SZ];
byte buf[4];
XMEMSET(key, 0xAA, sizeof(key));
XMEMSET(nonce, 0xBB, sizeof(nonce));
ExpectIntEQ(wc_AsconAEAD128_Init(asconAEAD), 0);
ExpectIntEQ(wc_AsconAEAD128_SetKey(asconAEAD, key), 0);
ExpectIntEQ(wc_AsconAEAD128_SetNonce(asconAEAD, nonce), 0);
ExpectIntEQ(wc_AsconAEAD128_SetAD(asconAEAD, NULL, 0), 0);
ExpectIntEQ(wc_AsconAEAD128_EncryptUpdate(asconAEAD, ct, pt,
sizeof(pt)), 0);
ExpectIntEQ(wc_AsconAEAD128_EncryptFinal(asconAEAD, tag), 0);
/* Corrupt one byte of the tag. */
tag[0] ^= 0x01;
ExpectIntEQ(wc_AsconAEAD128_Init(asconAEAD), 0);
ExpectIntEQ(wc_AsconAEAD128_SetKey(asconAEAD, key), 0);
ExpectIntEQ(wc_AsconAEAD128_SetNonce(asconAEAD, nonce), 0);
ExpectIntEQ(wc_AsconAEAD128_SetAD(asconAEAD, NULL, 0), 0);
ExpectIntEQ(wc_AsconAEAD128_DecryptUpdate(asconAEAD, buf, ct,
sizeof(ct)), 0);
ExpectIntEQ(wc_AsconAEAD128_DecryptFinal(asconAEAD, tag),
WC_NO_ERR_TRACE(ASCON_AUTH_E));
}
wc_AsconAEAD128_Free(asconAEAD);
#endif
return EXPECT_RESULT();
+2
View File
@@ -2510,6 +2510,8 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out,
#endif
}
if (d != NULL)
ForceZero(d, dSz);
XFREE(d, key->heap, DYNAMIC_TYPE_PRIVATE_KEY);
}
#endif
+2
View File
@@ -1562,6 +1562,8 @@ static int Pkcs11CreateEccPrivateKey(CK_OBJECT_HANDLE* privateKey,
ret = WC_HW_E;
}
}
if (priv != NULL)
ForceZero(priv, privLen);
XFREE(priv, private_key->heap, DYNAMIC_TYPE_TMP_BUFFER);
}
+148
View File
@@ -11385,6 +11385,51 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ascon_aead128_test(void)
}
}
/* Negative test: corrupted tag must be rejected with ASCON_AUTH_E. */
{
byte tkey[ASCON_AEAD128_KEY_SZ];
byte tnonce[ASCON_AEAD128_NONCE_SZ];
byte tpt[4] = { 0x00, 0x01, 0x02, 0x03 };
byte tct[4];
byte ttag[ASCON_AEAD128_TAG_SZ];
byte tbuf[4];
XMEMSET(tkey, 0xAA, sizeof(tkey));
XMEMSET(tnonce, 0xBB, sizeof(tnonce));
err = wc_AsconAEAD128_Init(&asconAEAD);
if (err != 0) return WC_TEST_RET_ENC_EC(err);
err = wc_AsconAEAD128_SetKey(&asconAEAD, tkey);
if (err != 0) return WC_TEST_RET_ENC_EC(err);
err = wc_AsconAEAD128_SetNonce(&asconAEAD, tnonce);
if (err != 0) return WC_TEST_RET_ENC_EC(err);
err = wc_AsconAEAD128_SetAD(&asconAEAD, NULL, 0);
if (err != 0) return WC_TEST_RET_ENC_EC(err);
err = wc_AsconAEAD128_EncryptUpdate(&asconAEAD, tct, tpt, sizeof(tpt));
if (err != 0) return WC_TEST_RET_ENC_EC(err);
err = wc_AsconAEAD128_EncryptFinal(&asconAEAD, ttag);
if (err != 0) return WC_TEST_RET_ENC_EC(err);
/* Corrupt one byte of the tag. */
ttag[0] ^= 0x01;
err = wc_AsconAEAD128_Init(&asconAEAD);
if (err != 0) return WC_TEST_RET_ENC_EC(err);
err = wc_AsconAEAD128_SetKey(&asconAEAD, tkey);
if (err != 0) return WC_TEST_RET_ENC_EC(err);
err = wc_AsconAEAD128_SetNonce(&asconAEAD, tnonce);
if (err != 0) return WC_TEST_RET_ENC_EC(err);
err = wc_AsconAEAD128_SetAD(&asconAEAD, NULL, 0);
if (err != 0) return WC_TEST_RET_ENC_EC(err);
err = wc_AsconAEAD128_DecryptUpdate(&asconAEAD, tbuf, tct, sizeof(tct));
if (err != 0) return WC_TEST_RET_ENC_EC(err);
err = wc_AsconAEAD128_DecryptFinal(&asconAEAD, ttag);
if (err != WC_NO_ERR_TRACE(ASCON_AUTH_E)) {
return WC_TEST_RET_ENC_EC(err);
}
wc_AsconAEAD128_Clear(&asconAEAD);
}
return 0;
}
#endif /* HAVE_ASCON */
@@ -20003,6 +20048,25 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aeskeywrap_test(void)
return WC_TEST_RET_ENC_I(i);
}
/* Negative test: corrupted wrapped data must be rejected with
* BAD_KEYWRAP_IV_E. */
{
wrapSz = wc_AesKeyWrap(test_wrap[0].kek, test_wrap[0].kekLen,
test_wrap[0].data, test_wrap[0].dataLen,
output, sizeof(output), NULL);
if (wrapSz < 0)
return WC_TEST_RET_ENC_EC(wrapSz);
/* Corrupt one byte of the wrapped data. */
output[0] ^= 0x01;
plainSz = wc_AesKeyUnWrap(test_wrap[0].kek, test_wrap[0].kekLen,
output, (word32)wrapSz,
plain, sizeof(plain), NULL);
if (plainSz != WC_NO_ERR_TRACE(BAD_KEYWRAP_IV_E))
return WC_TEST_RET_ENC_EC(plainSz);
}
return 0;
}
#endif /* HAVE_AES_KEYWRAP */
@@ -28904,6 +28968,58 @@ static wc_test_ret_t srp_test_digest(SrpType dgstType)
if (!r) r = wc_SrpVerifyPeersProof(cli, serverProof, serverProofSz);
/* Negative test: corrupted proof must be rejected with SRP_VERIFY_E. */
if (!r) {
int rNeg;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
Srp* cli2 = (Srp*)XMALLOC(sizeof *cli2, HEAP_HINT,
DYNAMIC_TYPE_TMP_BUFFER);
if (cli2 == NULL) {
r = WC_TEST_RET_ENC_NC;
}
#else
Srp cli2_buf[1];
Srp* cli2 = cli2_buf;
#endif
if (!r) {
XMEMSET(cli2, 0, sizeof *cli2);
/* Reset sizes consumed by the first exchange. */
clientPubKeySz = SRP_TEST_BUFFER_SIZE;
clientProofSz = SRP_MAX_DIGEST_SIZE;
rNeg = wc_SrpInit_ex(cli2, dgstType, SRP_CLIENT_SIDE, HEAP_HINT,
devId);
if (!rNeg) rNeg = wc_SrpSetUsername(cli2, username, usernameSz);
if (!rNeg) rNeg = wc_SrpSetParams(cli2, N, sizeof(N),
g, sizeof(g), salt,
sizeof(salt));
if (!rNeg) rNeg = wc_SrpSetPassword(cli2, password, passwordSz);
if (!rNeg) rNeg = wc_SrpGetPublic(cli2, clientPubKey,
&clientPubKeySz);
if (!rNeg) rNeg = wc_SrpComputeKey(cli2, clientPubKey,
clientPubKeySz, serverPubKey,
serverPubKeySz);
if (!rNeg) rNeg = wc_SrpGetProof(cli2, clientProof,
&clientProofSz);
/* Corrupt the server proof before verifying. */
serverProof[0] ^= 0x01;
if (!rNeg) {
rNeg = wc_SrpVerifyPeersProof(cli2, serverProof,
serverProofSz);
if (rNeg != WC_NO_ERR_TRACE(SRP_VERIFY_E)) {
r = WC_TEST_RET_ENC_EC(rNeg);
}
}
else {
r = WC_TEST_RET_ENC_EC(rNeg);
}
wc_SrpTerm(cli2);
}
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
XFREE(cli2, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
#endif
}
wc_SrpTerm(cli);
wc_SrpTerm(srv);
@@ -40909,6 +41025,15 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ecc_test_buffers(void)
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done);
if (XMEMCMP(plain, in, inLen))
ERROR_OUT(WC_TEST_RET_ENC_NC, done);
/* Negative test: corrupt HMAC tag in encrypted msg, expect
* HASH_TYPE_E from wc_ecc_decrypt. */
out[x - 1] ^= 0x01;
y = sizeof(plain);
ret = wc_ecc_decrypt(servKey, tmpKey, out, x, plain, &y, NULL);
if (ret != WC_NO_ERR_TRACE(HASH_TYPE_E))
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done);
ret = 0; /* reset ret for following tests */
}
#endif
@@ -70934,6 +71059,29 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes_siv_test(void)
}
}
/* Negative test: corrupted SIV must be rejected with AES_SIV_AUTH_E. */
{
ret = wc_AesSivEncrypt(testVectors[0].key, testVectors[0].keySz,
testVectors[0].assoc1, testVectors[0].assoc1Sz,
testVectors[0].nonce, testVectors[0].nonceSz,
testVectors[0].plaintext,
testVectors[0].plaintextSz, siv,
computedCiphertext);
if (ret != 0) {
return WC_TEST_RET_ENC_EC(ret);
}
/* Corrupt one byte of the SIV tag. */
siv[0] ^= 0x01;
ret = wc_AesSivDecrypt(testVectors[0].key, testVectors[0].keySz,
testVectors[0].assoc1, testVectors[0].assoc1Sz,
testVectors[0].nonce, testVectors[0].nonceSz,
computedCiphertext, testVectors[0].plaintextSz,
siv, computedPlaintext);
if (ret != WC_NO_ERR_TRACE(AES_SIV_AUTH_E)) {
return WC_TEST_RET_ENC_EC(ret);
}
}
return 0;
}
#endif