diff --git a/src/internal.c b/src/internal.c index 2034f107d8..c37891bbe5 100644 --- a/src/internal.c +++ b/src/internal.c @@ -12368,6 +12368,7 @@ static int BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender) #else wc_Md5 md5[1]; #endif + XMEMSET(md5, 0, sizeof(wc_Md5)); /* make md5 inner */ ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5); @@ -12413,6 +12414,7 @@ static int BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender) #else wc_Sha sha[1]; #endif + XMEMSET(sha, 0, sizeof(wc_Sha)); /* make sha inner */ ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */ if (ret == 0) @@ -23919,6 +23921,7 @@ static int BuildMD5_CertVerify(const WOLFSSL* ssl, byte* digest) #else wc_Md5 md5[1]; #endif + XMEMSET(md5, 0, sizeof(wc_Md5)); /* make md5 inner */ ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5); /* Save current position */ @@ -23962,6 +23965,7 @@ static int BuildSHA_CertVerify(const WOLFSSL* ssl, byte* digest) #else wc_Sha sha[1]; #endif + XMEMSET(sha, 0, sizeof(wc_Sha)); /* make sha inner */ ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */ diff --git a/src/tls13.c b/src/tls13.c index d057bd5158..a464ce9006 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -11983,6 +11983,8 @@ static int ExpectedResumptionSecret(WOLFSSL* ssl) Digest digest; static byte header[] = { 0x14, 0x00, 0x00, 0x00 }; + XMEMSET(&digest, 0, sizeof(Digest)); + /* Copy the running hash so we can restore it after. */ switch (ssl->specs.mac_algorithm) { #ifndef NO_SHA256 diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index cc2bb3a73b..cf197ef15b 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -5846,6 +5846,9 @@ void wolfSSL_EVP_init(void) if (out->pctx == NULL) return WOLFSSL_FAILURE; } + /* Zero hash context after shallow copy to prevent shared sub-pointers + * with src. The hash Copy function will perform the proper deep copy. */ + XMEMSET(&out->hash, 0, sizeof(out->hash)); return wolfSSL_EVP_MD_Copy_Hasher(out, (WOLFSSL_EVP_MD_CTX*)in); } #ifndef NO_AES diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index 9d1576d1b8..f42292f8ee 100644 --- a/wolfcrypt/src/hmac.c +++ b/wolfcrypt/src/hmac.c @@ -331,6 +331,11 @@ int wc_HmacCopy(Hmac* src, Hmac* dst) { XMEMCPY(dst, src, sizeof(*dst)); + /* Zero hash context after shallow copy to prevent shared sub-pointers + * (e.g., msg, W buffers) with src. The hash Copy function will perform + * the proper deep copy. */ + XMEMSET(&dst->hash, 0, sizeof(wc_HmacHash)); + ret = HmacKeyCopyHash(src->macType, &src->hash, &dst->hash); if (ret != 0) diff --git a/wolfcrypt/src/md5.c b/wolfcrypt/src/md5.c index 2f89de07d4..5ee180bb60 100644 --- a/wolfcrypt/src/md5.c +++ b/wolfcrypt/src/md5.c @@ -522,6 +522,7 @@ int wc_Md5GetHash(wc_Md5* md5, byte* hash) if (md5 == NULL || hash == NULL) return BAD_FUNC_ARG; + XMEMSET(&tmpMd5, 0, sizeof(tmpMd5)); ret = wc_Md5Copy(md5, &tmpMd5); if (ret == 0) { ret = wc_Md5Final(&tmpMd5, hash); @@ -537,6 +538,9 @@ int wc_Md5Copy(wc_Md5* src, wc_Md5* dst) if (src == NULL || dst == NULL) return BAD_FUNC_ARG; + /* Free dst resources before copy to prevent memory leaks (e.g., + * hardware contexts). XMEMCPY overwrites dst. */ + wc_Md5Free(dst); XMEMCPY(dst, src, sizeof(wc_Md5)); #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) diff --git a/wolfcrypt/src/port/riscv/riscv-64-sha256.c b/wolfcrypt/src/port/riscv/riscv-64-sha256.c index abf9581da4..44af0b80c3 100644 --- a/wolfcrypt/src/port/riscv/riscv-64-sha256.c +++ b/wolfcrypt/src/port/riscv/riscv-64-sha256.c @@ -1031,6 +1031,7 @@ int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash) } else { wc_Sha256 tmpSha256; + XMEMSET(&tmpSha256, 0, sizeof(tmpSha256)); /* Create a copy of the hash to finalize. */ ret = wc_Sha256Copy(sha256, &tmpSha256); if (ret == 0) { @@ -1350,6 +1351,7 @@ int wc_Sha224GetHash(wc_Sha224* sha224, byte* hash) } else { wc_Sha224 tmpSha224; + XMEMSET(&tmpSha224, 0, sizeof(tmpSha224)); /* Create a copy of the hash to finalize. */ ret = wc_Sha224Copy(sha224, &tmpSha224); if (ret == 0) { diff --git a/wolfcrypt/src/port/riscv/riscv-64-sha512.c b/wolfcrypt/src/port/riscv/riscv-64-sha512.c index c7ab141cd2..5c00f28d16 100644 --- a/wolfcrypt/src/port/riscv/riscv-64-sha512.c +++ b/wolfcrypt/src/port/riscv/riscv-64-sha512.c @@ -1140,6 +1140,7 @@ int wc_Sha512GetHash(wc_Sha512* sha512, byte* hash) } else { wc_Sha512 tmpSha512; + XMEMSET(&tmpSha512, 0, sizeof(tmpSha512)); /* Create a copy of the hash to finalize. */ ret = wc_Sha512Copy(sha512, &tmpSha512); if (ret == 0) { @@ -1357,6 +1358,7 @@ int wc_Sha512_224GetHash(wc_Sha512* sha512, byte* hash) } else { wc_Sha512 tmpSha512; + XMEMSET(&tmpSha512, 0, sizeof(tmpSha512)); /* Create a copy of the hash to finalize. */ ret = wc_Sha512Copy(sha512, &tmpSha512); if (ret == 0) { @@ -1456,6 +1458,7 @@ int wc_Sha512_256GetHash(wc_Sha512* sha512, byte* hash) } else { wc_Sha512 tmpSha512; + XMEMSET(&tmpSha512, 0, sizeof(tmpSha512)); /* Create a copy of the hash to finalize. */ ret = wc_Sha512Copy(sha512, &tmpSha512); if (ret == 0) { @@ -1671,6 +1674,7 @@ int wc_Sha384GetHash(wc_Sha384* sha384, byte* hash) } else { wc_Sha384 tmpSha384; + XMEMSET(&tmpSha384, 0, sizeof(tmpSha384)); /* Create a copy of the hash to finalize. */ ret = wc_Sha384Copy(sha384, &tmpSha384); if (ret == 0) { diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index 590a06104d..1af94e8155 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -1137,7 +1137,7 @@ int wc_ShaGetHash(wc_Sha* sha, byte* hash) return BAD_FUNC_ARG; } - WC_ALLOC_VAR_EX(tmpSha, wc_Sha, 1, NULL, DYNAMIC_TYPE_TMP_BUFFER, + WC_CALLOC_VAR_EX(tmpSha, wc_Sha, 1, NULL, DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E); ret = wc_ShaCopy(sha, tmpSha); @@ -1172,6 +1172,9 @@ int wc_ShaCopy(wc_Sha* src, wc_Sha* dst) ret = 0; /* Reset ret to 0 to avoid returning the callback error code */ #endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_COPY */ + /* Free dst resources before copy to prevent memory leaks (e.g., msg + * buffer, W cache, hardware contexts). XMEMCPY overwrites dst. */ + wc_ShaFree(dst); XMEMCPY(dst, src, sizeof(wc_Sha)); #if defined(WOLFSSL_SILABS_SE_ACCEL) && defined(WOLFSSL_SILABS_SE_ACCEL_3) diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 745eb13673..fbe8157d81 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -2546,7 +2546,7 @@ int wc_Sha224_Grow(wc_Sha224* sha224, const byte* in, int inSz) return BAD_FUNC_ARG; } - WC_ALLOC_VAR_EX(tmpSha224, wc_Sha224, 1, NULL, + WC_CALLOC_VAR_EX(tmpSha224, wc_Sha224, 1, NULL, DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E); ret = wc_Sha224Copy(sha224, tmpSha224); @@ -2582,6 +2582,9 @@ int wc_Sha224_Grow(wc_Sha224* sha224, const byte* in, int inSz) ret = 0; /* Reset ret to 0 to avoid returning the callback error code */ #endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_COPY */ + /* Free dst resources before copy to prevent memory leaks (e.g., msg + * buffer, W cache, hardware contexts). XMEMCPY overwrites dst. */ + wc_Sha224Free(dst); XMEMCPY(dst, src, sizeof(wc_Sha224)); #ifdef WOLFSSL_SMALL_STACK_CACHE @@ -2691,7 +2694,7 @@ int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash) return BAD_FUNC_ARG; } - WC_ALLOC_VAR_EX(tmpSha256, wc_Sha256, 1, NULL, DYNAMIC_TYPE_TMP_BUFFER, + WC_CALLOC_VAR_EX(tmpSha256, wc_Sha256, 1, NULL, DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E); ret = wc_Sha256Copy(sha256, tmpSha256); @@ -2728,6 +2731,9 @@ int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) ret = 0; /* Reset ret to 0 to avoid returning the callback error code */ #endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_COPY */ + /* Free dst resources before copy to prevent memory leaks (e.g., msg + * buffer, W cache, hardware contexts). XMEMCPY overwrites dst. */ + wc_Sha256Free(dst); XMEMCPY(dst, src, sizeof(wc_Sha256)); #ifdef WOLFSSL_MAXQ10XX_CRYPTO diff --git a/wolfcrypt/src/sha3.c b/wolfcrypt/src/sha3.c index 8b02cffb49..5fd3b0e305 100644 --- a/wolfcrypt/src/sha3.c +++ b/wolfcrypt/src/sha3.c @@ -1306,6 +1306,9 @@ static int wc_Sha3Copy(wc_Sha3* src, wc_Sha3* dst) ret = 0; /* Reset ret to 0 to avoid returning the callback error code */ #endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_COPY */ + /* Free dst resources before copy to prevent memory leaks (e.g., + * hardware contexts). XMEMCPY overwrites dst. */ + wc_Sha3Free(dst); XMEMCPY(dst, src, sizeof(wc_Sha3)); #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) @@ -1342,6 +1345,7 @@ static int wc_Sha3GetHash(wc_Sha3* sha3, byte* hash, byte p, byte len) if (sha3 == NULL || hash == NULL) return BAD_FUNC_ARG; + XMEMSET(&tmpSha3, 0, sizeof(tmpSha3)); ret = wc_Sha3Copy(sha3, &tmpSha3); if (ret == 0) { ret = wc_Sha3Final(&tmpSha3, hash, p, len); diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index a50e2ebd6a..70df3c68fe 100644 --- a/wolfcrypt/src/sha512.c +++ b/wolfcrypt/src/sha512.c @@ -2206,7 +2206,7 @@ static int Sha512_Family_GetHash(wc_Sha512* sha512, byte* hash, return BAD_FUNC_ARG; } - WC_ALLOC_VAR_EX(tmpSha512, wc_Sha512, 1, NULL, DYNAMIC_TYPE_TMP_BUFFER, + WC_CALLOC_VAR_EX(tmpSha512, wc_Sha512, 1, NULL, DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E); /* copy this sha512 into tmpSha */ @@ -2249,6 +2249,9 @@ int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst) ret = 0; /* Reset ret to 0 to avoid returning the callback error code */ #endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_COPY */ + /* Free dst resources before copy to prevent memory leaks (e.g., msg + * buffer, W cache, hardware contexts). XMEMCPY overwrites dst. */ + wc_Sha512Free(dst); XMEMCPY(dst, src, sizeof(wc_Sha512)); #ifdef WOLFSSL_SMALL_STACK_CACHE /* This allocation combines the customary W buffer used by @@ -2649,7 +2652,7 @@ int wc_Sha384GetHash(wc_Sha384* sha384, byte* hash) return BAD_FUNC_ARG; } - WC_ALLOC_VAR_EX(tmpSha384, wc_Sha384, 1, NULL, DYNAMIC_TYPE_TMP_BUFFER, + WC_CALLOC_VAR_EX(tmpSha384, wc_Sha384, 1, NULL, DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E); /* copy this sha384 into tmpSha */ @@ -2687,6 +2690,9 @@ int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst) ret = 0; /* Reset ret to 0 to avoid returning the callback error code */ #endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_COPY */ + /* Free dst resources before copy to prevent memory leaks (e.g., msg + * buffer, W cache, hardware contexts). XMEMCPY overwrites dst. */ + wc_Sha384Free(dst); XMEMCPY(dst, src, sizeof(wc_Sha384)); #ifdef WOLFSSL_SMALL_STACK_CACHE diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 6a8ca6798f..7da4766f5f 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -4329,6 +4329,30 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t md5_test(void) } /* END LARGE HASH TEST */ #endif /* NO_LARGE_HASH_TEST */ + /* Copy cleanup test: verify Copy into a previously-used dst does not leak + * resources (e.g., hardware contexts). Detectable by valgrind/ASAN. */ + wc_Md5Free(&md5); + ret = wc_InitMd5_ex(&md5, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_InitMd5_ex(&md5Copy, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Md5Update(&md5Copy, (byte*)b.input, (word32)b.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Md5Update(&md5, (byte*)a.input, (word32)a.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Md5Copy(&md5, &md5Copy); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Md5Final(&md5Copy, hash); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + if (XMEMCMP(hash, a.output, WC_MD5_DIGEST_SIZE) != 0) + ERROR_OUT(WC_TEST_RET_ENC_NC, exit); + exit: wc_Md5Free(&md5); @@ -4540,6 +4564,30 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t sha_test(void) } /* END LARGE HASH TEST */ #endif /* NO_LARGE_HASH_TEST */ + /* Copy cleanup test: verify Copy into a previously-used dst does not leak + * resources (e.g., msg buffer, W cache). Detectable by valgrind/ASAN. */ + wc_ShaFree(&sha); + ret = wc_InitSha_ex(&sha, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_InitSha_ex(&shaCopy, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_ShaUpdate(&shaCopy, (byte*)b.input, (word32)b.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_ShaUpdate(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_ShaCopy(&sha, &shaCopy); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_ShaFinal(&shaCopy, hash); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + if (XMEMCMP(hash, a.output, WC_SHA_DIGEST_SIZE) != 0) + ERROR_OUT(WC_TEST_RET_ENC_NC, exit); + exit: wc_ShaFree(&sha); @@ -4979,6 +5027,30 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t sha224_test(void) ERROR_OUT(WC_TEST_RET_ENC_I(i), exit); } + /* Copy cleanup test: verify Copy into a previously-used dst does not leak + * resources (e.g., msg buffer, W cache). Detectable by valgrind/ASAN. */ + wc_Sha224Free(&sha); + ret = wc_InitSha224_ex(&sha, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_InitSha224_ex(&shaCopy, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha224Update(&shaCopy, (byte*)b.input, (word32)b.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha224Update(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha224Copy(&sha, &shaCopy); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha224Final(&shaCopy, hash); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + if (XMEMCMP(hash, a.output, WC_SHA224_DIGEST_SIZE) != 0) + ERROR_OUT(WC_TEST_RET_ENC_NC, exit); + exit: wc_Sha224Free(&sha); wc_Sha224Free(&shaCopy); @@ -5203,6 +5275,30 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t sha256_test(void) } #endif + /* Copy cleanup test: verify Copy into a previously-used dst does not leak + * resources (e.g., msg buffer, W cache). Detectable by valgrind/ASAN. */ + wc_Sha256Free(&sha); + ret = wc_InitSha256_ex(&sha, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_InitSha256_ex(&shaCopy, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha256Update(&shaCopy, (byte*)b.input, (word32)b.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha256Update(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha256Copy(&sha, &shaCopy); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha256Final(&shaCopy, hash); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + if (XMEMCMP(hash, a.output, WC_SHA256_DIGEST_SIZE) != 0) + ERROR_OUT(WC_TEST_RET_ENC_NC, exit); + exit: #if !defined(NO_LARGE_HASH_TEST) && defined(WOLFSSL_SMALL_STACK) @@ -5412,12 +5508,38 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t sha512_test(void) if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); ret = wc_Sha512Final(&sha, hash); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); } #endif } /* END LARGE HASH TEST */ #undef LARGE_HASH_TEST_INPUT_SZ #endif /* NO_LARGE_HASH_TEST */ + /* Copy cleanup test: verify Copy into a previously-used dst does not leak + * resources (e.g., msg buffer, W cache). Detectable by valgrind/ASAN. */ + wc_Sha512Free(&sha); + ret = wc_InitSha512_ex(&sha, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_InitSha512_ex(&shaCopy, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha512Update(&shaCopy, (byte*)b.input, (word32)b.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha512Update(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha512Copy(&sha, &shaCopy); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha512Final(&shaCopy, hash); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + if (XMEMCMP(hash, a.output, WC_SHA512_DIGEST_SIZE) != 0) + ERROR_OUT(WC_TEST_RET_ENC_NC, exit); + exit: #if !defined(NO_LARGE_HASH_TEST) && defined(WOLFSSL_SMALL_STACK) @@ -5839,6 +5961,30 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t sha384_test(void) } /* END LARGE HASH TEST */ #endif /* NO_LARGE_HASH_TEST */ + /* Copy cleanup test: verify Copy into a previously-used dst does not leak + * resources (e.g., msg buffer, W cache). Detectable by valgrind/ASAN. */ + wc_Sha384Free(&sha); + ret = wc_InitSha384_ex(&sha, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_InitSha384_ex(&shaCopy, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha384Update(&shaCopy, (byte*)b.input, (word32)b.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha384Update(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha384Copy(&sha, &shaCopy); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha384Final(&shaCopy, hash); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + if (XMEMCMP(hash, a.output, WC_SHA384_DIGEST_SIZE) != 0) + ERROR_OUT(WC_TEST_RET_ENC_NC, exit); + exit: wc_Sha384Free(&sha); @@ -5853,6 +5999,9 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t sha384_test(void) static wc_test_ret_t sha3_224_test(void) { wc_Sha3 sha; + /* Heap-allocated when WOLFSSL_SMALL_STACK to avoid exceeding stack frame + * limit with two wc_Sha3 structs on the stack. */ + WC_DECLARE_VAR(shaCopy, wc_Sha3, 1, HEAP_HINT); byte hash[WC_SHA3_224_DIGEST_SIZE]; byte hashcopy[WC_SHA3_224_DIGEST_SIZE]; @@ -5861,6 +6010,10 @@ static wc_test_ret_t sha3_224_test(void) wc_test_ret_t ret = 0; int times = sizeof(test_sha) / sizeof(struct testVector), i; + WC_ALLOC_VAR(shaCopy, wc_Sha3, 1, HEAP_HINT); + if (!WC_VAR_OK(shaCopy)) + return WC_TEST_RET_ENC_EC(MEMORY_E); + a.input = ""; a.output = "\x6b\x4e\x03\x42\x36\x67\xdb\xb7\x3b\x6e\x15\x45\x4f\x0e\xb1" "\xab\xd4\x59\x7f\x9a\x1b\x07\x8e\x3f\x5b\x5a\x6b\xc7"; @@ -5930,8 +6083,34 @@ static wc_test_ret_t sha3_224_test(void) } /* END LARGE HASH TEST */ #endif /* NO_LARGE_HASH_TEST */ + /* Copy cleanup test: verify Copy into a previously-used dst does not leak + * resources (e.g., hardware contexts). Detectable by valgrind/ASAN. */ + wc_Sha3_224_Free(&sha); + ret = wc_InitSha3_224(&sha, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_InitSha3_224(shaCopy, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha3_224_Update(shaCopy, (byte*)b.input, (word32)b.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha3_224_Update(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha3_224_Copy(&sha, shaCopy); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha3_224_Final(shaCopy, hash); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + if (XMEMCMP(hash, a.output, WC_SHA3_224_DIGEST_SIZE) != 0) + ERROR_OUT(WC_TEST_RET_ENC_NC, exit); + exit: wc_Sha3_224_Free(&sha); + wc_Sha3_224_Free(shaCopy); + WC_FREE_VAR(shaCopy, HEAP_HINT); return ret; } @@ -5941,6 +6120,9 @@ static wc_test_ret_t sha3_224_test(void) static wc_test_ret_t sha3_256_test(void) { wc_Sha3 sha; + /* Heap-allocated when WOLFSSL_SMALL_STACK to avoid exceeding stack frame + * limit with two wc_Sha3 structs on the stack. */ + WC_DECLARE_VAR(shaCopy, wc_Sha3, 1, HEAP_HINT); byte hash[WC_SHA3_256_DIGEST_SIZE]; byte hashcopy[WC_SHA3_256_DIGEST_SIZE]; @@ -5961,6 +6143,10 @@ static wc_test_ret_t sha3_256_test(void) "\xe5\x00\xb6\x53\xca\x82\x27\x3b\x7b\xfa\xd8\x04\x5d\x85\xa4\x70"; #endif + WC_ALLOC_VAR(shaCopy, wc_Sha3, 1, HEAP_HINT); + if (!WC_VAR_OK(shaCopy)) + return WC_TEST_RET_ENC_EC(MEMORY_E); + /* ** https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-256_Msg0.pdf */ @@ -6051,8 +6237,34 @@ static wc_test_ret_t sha3_256_test(void) } #endif /* WOLFSSL_HASH_FLAGS && !WOLFSSL_ASYNC_CRYPT */ + /* Copy cleanup test: verify Copy into a previously-used dst does not leak + * resources (e.g., hardware contexts). Detectable by valgrind/ASAN. */ + wc_Sha3_256_Free(&sha); + ret = wc_InitSha3_256(&sha, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_InitSha3_256(shaCopy, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha3_256_Update(shaCopy, (byte*)b.input, (word32)b.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha3_256_Update(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha3_256_Copy(&sha, shaCopy); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha3_256_Final(shaCopy, hash); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + if (XMEMCMP(hash, a.output, WC_SHA3_256_DIGEST_SIZE) != 0) + ERROR_OUT(WC_TEST_RET_ENC_NC, exit); + exit: wc_Sha3_256_Free(&sha); + wc_Sha3_256_Free(shaCopy); + WC_FREE_VAR(shaCopy, HEAP_HINT); return ret; } @@ -6062,6 +6274,9 @@ static wc_test_ret_t sha3_256_test(void) static wc_test_ret_t sha3_384_test(void) { wc_Sha3 sha; + /* Heap-allocated when WOLFSSL_SMALL_STACK to avoid exceeding stack frame + * limit with two wc_Sha3 structs on the stack. */ + WC_DECLARE_VAR(shaCopy, wc_Sha3, 1, HEAP_HINT); byte hash[WC_SHA3_384_DIGEST_SIZE]; byte buf[64]; #ifndef NO_INTM_HASH_TEST @@ -6073,6 +6288,10 @@ static wc_test_ret_t sha3_384_test(void) wc_test_ret_t ret; int times = sizeof(test_sha) / sizeof(struct testVector), i; + WC_ALLOC_VAR(shaCopy, wc_Sha3, 1, HEAP_HINT); + if (!WC_VAR_OK(shaCopy)) + return WC_TEST_RET_ENC_EC(MEMORY_E); + /* ** https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-384_Msg0.pdf */ @@ -6172,8 +6391,34 @@ static wc_test_ret_t sha3_384_test(void) } /* END LARGE HASH TEST */ #endif /* NO_LARGE_HASH_TEST */ + /* Copy cleanup test: verify Copy into a previously-used dst does not leak + * resources (e.g., hardware contexts). Detectable by valgrind/ASAN. */ + wc_Sha3_384_Free(&sha); + ret = wc_InitSha3_384(&sha, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_InitSha3_384(shaCopy, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha3_384_Update(shaCopy, (byte*)b.input, (word32)b.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha3_384_Update(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha3_384_Copy(&sha, shaCopy); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha3_384_Final(shaCopy, hash); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + if (XMEMCMP(hash, a.output, WC_SHA3_384_DIGEST_SIZE) != 0) + ERROR_OUT(WC_TEST_RET_ENC_NC, exit); + exit: wc_Sha3_384_Free(&sha); + wc_Sha3_384_Free(shaCopy); + WC_FREE_VAR(shaCopy, HEAP_HINT); return ret; } @@ -6183,6 +6428,9 @@ static wc_test_ret_t sha3_384_test(void) static wc_test_ret_t sha3_512_test(void) { wc_Sha3 sha; + /* Heap-allocated when WOLFSSL_SMALL_STACK to avoid exceeding stack frame + * limit with two wc_Sha3 structs on the stack. */ + WC_DECLARE_VAR(shaCopy, wc_Sha3, 1, HEAP_HINT); byte hash[WC_SHA3_512_DIGEST_SIZE]; byte hashcopy[WC_SHA3_512_DIGEST_SIZE]; @@ -6191,6 +6439,10 @@ static wc_test_ret_t sha3_512_test(void) wc_test_ret_t ret; int times = sizeof(test_sha) / sizeof(struct testVector), i; + WC_ALLOC_VAR(shaCopy, wc_Sha3, 1, HEAP_HINT); + if (!WC_VAR_OK(shaCopy)) + return WC_TEST_RET_ENC_EC(MEMORY_E); + /* ** https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-512_Msg0.pdf */ @@ -6274,8 +6526,34 @@ static wc_test_ret_t sha3_512_test(void) } /* END LARGE HASH TEST */ #endif /* NO_LARGE_HASH_TEST */ + /* Copy cleanup test: verify Copy into a previously-used dst does not leak + * resources (e.g., hardware contexts). Detectable by valgrind/ASAN. */ + wc_Sha3_512_Free(&sha); + ret = wc_InitSha3_512(&sha, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_InitSha3_512(shaCopy, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha3_512_Update(shaCopy, (byte*)b.input, (word32)b.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha3_512_Update(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha3_512_Copy(&sha, shaCopy); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Sha3_512_Final(shaCopy, hash); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + if (XMEMCMP(hash, a.output, WC_SHA3_512_DIGEST_SIZE) != 0) + ERROR_OUT(WC_TEST_RET_ENC_NC, exit); + exit: wc_Sha3_512_Free(&sha); + wc_Sha3_512_Free(shaCopy); + WC_FREE_VAR(shaCopy, HEAP_HINT); return ret; } @@ -6498,6 +6776,9 @@ static wc_test_ret_t shake128_absorb_test(wc_Shake* sha, byte *large_input_buf, WOLFSSL_TEST_SUBROUTINE wc_test_ret_t shake128_test(void) { wc_Shake sha; + /* Heap-allocated when WOLFSSL_SMALL_STACK to avoid exceeding stack frame + * limit with two wc_Shake structs on the stack. */ + WC_DECLARE_VAR(shaCopy, wc_Shake, 1, HEAP_HINT); byte hash[250]; testVector a, b, c, d, e; @@ -6522,6 +6803,9 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t shake128_test(void) "\xfa\x1b"; WOLFSSL_ENTER("shake128_test"); + WC_ALLOC_VAR(shaCopy, wc_Shake, 1, HEAP_HINT); + if (!WC_VAR_OK(shaCopy)) + return WC_TEST_RET_ENC_EC(MEMORY_E); /* ** https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHAKE128_Msg0.pdf @@ -6653,9 +6937,37 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t shake128_test(void) #endif /* NO_LARGE_HASH_TEST */ ret = shake128_absorb_test(&sha, large_input, SHAKE128_LARGE_INPUT_BUFSIZ); + if (ret != 0) + ERROR_OUT(ret, exit); + + /* Copy cleanup test: verify Copy into a previously-used dst does not leak + * resources (e.g., hardware contexts). Detectable by valgrind/ASAN. */ + wc_Shake128_Free(&sha); + ret = wc_InitShake128(&sha, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_InitShake128(shaCopy, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Shake128_Update(shaCopy, (byte*)b.input, (word32)b.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Shake128_Update(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Shake128_Copy(&sha, shaCopy); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Shake128_Final(shaCopy, hash, (word32)a.outLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + if (XMEMCMP(hash, a.output, a.outLen) != 0) + ERROR_OUT(WC_TEST_RET_ENC_NC, exit); exit: wc_Shake128_Free(&sha); + wc_Shake128_Free(shaCopy); + WC_FREE_VAR(shaCopy, HEAP_HINT); #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) XFREE(large_input, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -6838,6 +7150,9 @@ static wc_test_ret_t shake256_absorb_test(wc_Shake* sha, byte *large_input_buf, WOLFSSL_TEST_SUBROUTINE wc_test_ret_t shake256_test(void) { wc_Shake sha; + /* Heap-allocated when WOLFSSL_SMALL_STACK to avoid exceeding stack frame + * limit with two wc_Shake structs on the stack. */ + WC_DECLARE_VAR(shaCopy, wc_Shake, 1, HEAP_HINT); byte hash[250]; testVector a, b, c, d, e; @@ -6862,6 +7177,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t shake256_test(void) "\xea\x26"; WOLFSSL_ENTER("shake256_test"); + + WC_ALLOC_VAR(shaCopy, wc_Shake, 1, HEAP_HINT); + if (!WC_VAR_OK(shaCopy)) + return WC_TEST_RET_ENC_EC(MEMORY_E); + /* ** https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHAKE256_Msg0.pdf */ @@ -6992,8 +7312,37 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t shake256_test(void) #endif /* NO_LARGE_HASH_TEST */ ret = shake256_absorb_test(&sha, large_input, SHAKE256_LARGE_INPUT_BUFSIZ); + if (ret != 0) + ERROR_OUT(ret, exit); + + /* Copy cleanup test: verify Copy into a previously-used dst does not leak + * resources (e.g., hardware contexts). Detectable by valgrind/ASAN. */ + wc_Shake256_Free(&sha); + ret = wc_InitShake256(&sha, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_InitShake256(shaCopy, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Shake256_Update(shaCopy, (byte*)b.input, (word32)b.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Shake256_Update(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Shake256_Copy(&sha, shaCopy); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + ret = wc_Shake256_Final(shaCopy, hash, (word32)a.outLen); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + if (XMEMCMP(hash, a.output, a.outLen) != 0) + ERROR_OUT(WC_TEST_RET_ENC_NC, exit); + exit: wc_Shake256_Free(&sha); + wc_Shake256_Free(shaCopy); + WC_FREE_VAR(shaCopy, HEAP_HINT); #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) XFREE(large_input, NULL, DYNAMIC_TYPE_TMP_BUFFER);