From 4713ad5675e8256fdb857b6dd1386547105cca28 Mon Sep 17 00:00:00 2001 From: night1rider Date: Wed, 25 Feb 2026 10:26:38 -0700 Subject: [PATCH] Add Free(dst) + XMEMSET before XMEMCPY in all wc_ hash Copy functions (MD5, SHA, SHA2, SHA3, SHAKE) and add copy cleanup tests to prevent resource leaks when copying into previously-used contexts. --- wolfcrypt/src/md5.c | 5 + wolfcrypt/src/sha.c | 1 + wolfcrypt/src/sha256.c | 2 + wolfcrypt/src/sha3.c | 5 + wolfcrypt/src/sha512.c | 2 + wolfcrypt/test/test.c | 299 ++++++++++++++++++++++++++++++++++++++++- 6 files changed, 308 insertions(+), 6 deletions(-) diff --git a/wolfcrypt/src/md5.c b/wolfcrypt/src/md5.c index 2f89de07d4..06b8828c26 100644 --- a/wolfcrypt/src/md5.c +++ b/wolfcrypt/src/md5.c @@ -537,6 +537,11 @@ 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); + XMEMSET(dst, 0, sizeof(wc_Md5)); + XMEMCPY(dst, src, sizeof(wc_Md5)); #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index 67ca19aba7..c21c134c00 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -1175,6 +1175,7 @@ int wc_ShaCopy(wc_Sha* src, wc_Sha* dst) /* Free dst resources before copy to prevent memory leaks (e.g., msg * buffer, W cache, hardware contexts). XMEMCPY overwrites dst. */ wc_ShaFree(dst); + XMEMSET(dst, 0, sizeof(wc_Sha)); XMEMCPY(dst, src, sizeof(wc_Sha)); diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index a9ce10cd7c..0de305276d 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -2585,6 +2585,7 @@ int wc_Sha224_Grow(wc_Sha224* sha224, const byte* in, int inSz) /* Free dst resources before copy to prevent memory leaks (e.g., msg * buffer, W cache, hardware contexts). XMEMCPY overwrites dst. */ wc_Sha224Free(dst); + XMEMSET(dst, 0, sizeof(wc_Sha224)); XMEMCPY(dst, src, sizeof(wc_Sha224)); @@ -2735,6 +2736,7 @@ int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) /* Free dst resources before copy to prevent memory leaks (e.g., msg * buffer, W cache, hardware contexts). XMEMCPY overwrites dst. */ wc_Sha256Free(dst); + XMEMSET(dst, 0, sizeof(wc_Sha256)); XMEMCPY(dst, src, sizeof(wc_Sha256)); diff --git a/wolfcrypt/src/sha3.c b/wolfcrypt/src/sha3.c index 8b02cffb49..9fa681fd2f 100644 --- a/wolfcrypt/src/sha3.c +++ b/wolfcrypt/src/sha3.c @@ -1306,6 +1306,11 @@ 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); + XMEMSET(dst, 0, sizeof(wc_Sha3)); + XMEMCPY(dst, src, sizeof(wc_Sha3)); #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index 5d3d68a214..c120907f7d 100644 --- a/wolfcrypt/src/sha512.c +++ b/wolfcrypt/src/sha512.c @@ -2252,6 +2252,7 @@ int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst) /* Free dst resources before copy to prevent memory leaks (e.g., msg * buffer, W cache, hardware contexts). XMEMCPY overwrites dst. */ wc_Sha512Free(dst); + XMEMSET(dst, 0, sizeof(wc_Sha512)); XMEMCPY(dst, src, sizeof(wc_Sha512)); #ifdef WOLFSSL_SMALL_STACK_CACHE @@ -2694,6 +2695,7 @@ int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst) /* Free dst resources before copy to prevent memory leaks (e.g., msg * buffer, W cache, hardware contexts). XMEMCPY overwrites dst. */ wc_Sha384Free(dst); + XMEMSET(dst, 0, sizeof(wc_Sha384)); XMEMCPY(dst, src, sizeof(wc_Sha384)); diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 6a8ca6798f..80743ff8cc 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -4329,6 +4329,29 @@ 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. */ + 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 +4563,29 @@ 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. */ + 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 +5025,29 @@ 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. */ + 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 +5272,29 @@ 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. */ + 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) @@ -5418,6 +5510,29 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t sha512_test(void) #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. */ + 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 +5954,29 @@ 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. */ + 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); @@ -5852,7 +5990,7 @@ exit: #ifndef WOLFSSL_NOSHA3_224 static wc_test_ret_t sha3_224_test(void) { - wc_Sha3 sha; + wc_Sha3 sha, shaCopy; byte hash[WC_SHA3_224_DIGEST_SIZE]; byte hashcopy[WC_SHA3_224_DIGEST_SIZE]; @@ -5930,8 +6068,32 @@ 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. */ + 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); return ret; } @@ -5940,7 +6102,7 @@ exit: #ifndef WOLFSSL_NOSHA3_256 static wc_test_ret_t sha3_256_test(void) { - wc_Sha3 sha; + wc_Sha3 sha, shaCopy; byte hash[WC_SHA3_256_DIGEST_SIZE]; byte hashcopy[WC_SHA3_256_DIGEST_SIZE]; @@ -6051,8 +6213,32 @@ 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. */ + 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); return ret; } @@ -6061,7 +6247,7 @@ exit: #ifndef WOLFSSL_NOSHA3_384 static wc_test_ret_t sha3_384_test(void) { - wc_Sha3 sha; + wc_Sha3 sha, shaCopy; byte hash[WC_SHA3_384_DIGEST_SIZE]; byte buf[64]; #ifndef NO_INTM_HASH_TEST @@ -6172,8 +6358,32 @@ 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. */ + 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); return ret; } @@ -6182,7 +6392,7 @@ exit: #ifndef WOLFSSL_NOSHA3_512 static wc_test_ret_t sha3_512_test(void) { - wc_Sha3 sha; + wc_Sha3 sha, shaCopy; byte hash[WC_SHA3_512_DIGEST_SIZE]; byte hashcopy[WC_SHA3_512_DIGEST_SIZE]; @@ -6274,8 +6484,32 @@ 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. */ + 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); return ret; } @@ -6497,7 +6731,7 @@ exit: WOLFSSL_TEST_SUBROUTINE wc_test_ret_t shake128_test(void) { - wc_Shake sha; + wc_Shake sha, shaCopy; byte hash[250]; testVector a, b, c, d, e; @@ -6653,9 +6887,35 @@ 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. */ + 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); #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) XFREE(large_input, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -6837,7 +7097,7 @@ exit: WOLFSSL_TEST_SUBROUTINE wc_test_ret_t shake256_test(void) { - wc_Shake sha; + wc_Shake sha, shaCopy; byte hash[250]; testVector a, b, c, d, e; @@ -6992,8 +7252,35 @@ 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. */ + 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); #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) XFREE(large_input, NULL, DYNAMIC_TYPE_TMP_BUFFER);