From 515b2f7b1514c9c4ff550fd2723538ed0cc15681 Mon Sep 17 00:00:00 2001 From: kaage Date: Tue, 6 Oct 2026 10:04:56 +0900 Subject: [PATCH 1/4] Reject overlapping src and dst in wc_Sha224/256Copy --- wolfcrypt/src/sha256.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 12e95b6aef8..3f3aded4fee 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -3425,11 +3425,22 @@ int wc_Sha224Reset(wc_Sha224* sha224) { int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst) { int ret = 0; /* assume success unless proven otherwise */ + wc_ptr_t srcAddr; + wc_ptr_t dstAddr; if (src == NULL || dst == NULL) { return BAD_FUNC_ARG; } + /* Reject if src and dst had overlapping */ + srcAddr = (wc_ptr_t)src; + dstAddr = (wc_ptr_t)dst; + + if ((srcAddr <= dstAddr && dstAddr - srcAddr < sizeof(*src)) || + (dstAddr < srcAddr && srcAddr - dstAddr < sizeof(*dst))) { + return BAD_FUNC_ARG; + } + #if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_COPY) #ifndef WOLF_CRYPTO_CB_FIND if (src->devId != INVALID_DEVID) @@ -3574,11 +3585,22 @@ int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash) int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) { int ret = 0; + wc_ptr_t srcAddr; + wc_ptr_t dstAddr; if (src == NULL || dst == NULL) { return BAD_FUNC_ARG; } + /* Reject if src and dst had overlapping */ + srcAddr = (wc_ptr_t)src; + dstAddr = (wc_ptr_t)dst; + + if ((srcAddr <= dstAddr && dstAddr - srcAddr < sizeof(*src)) || + (dstAddr < srcAddr && srcAddr - dstAddr < sizeof(*dst))) { + return BAD_FUNC_ARG; + } + #if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_COPY) #ifndef WOLF_CRYPTO_CB_FIND if (src->devId != INVALID_DEVID) From f4bc2f4b4b006a48b1d260e77ce3a603c58f3f64 Mon Sep 17 00:00:00 2001 From: kaage Date: Tue, 6 Oct 2026 10:06:21 +0900 Subject: [PATCH 2/4] Modified docs to clarify the exceptional behavior --- doc/dox_comments/header_files/sha256.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/doc/dox_comments/header_files/sha256.h b/doc/dox_comments/header_files/sha256.h index 8a896ff795f..b88b0269a21 100644 --- a/doc/dox_comments/header_files/sha256.h +++ b/doc/dox_comments/header_files/sha256.h @@ -402,12 +402,16 @@ int wc_Sha256_Grow(wc_Sha256* sha256, const byte* in, int inSz); \ingroup SHA \brief Copies SHA256 context. + The memory regions occupied by the source and destination structures + must not overlap. If they overlap, including when src == dst, the + behavior is undefined. + \return 0 on success \return negative on error \param src Source SHA256 structure \param dst Destination SHA256 structure; - (must be zeroed or previously initialized) + (must be zeroed or previously initialized and must not overlap src) _Example_ \code @@ -613,12 +617,16 @@ int wc_Sha224GetHash(wc_Sha224* sha224, byte* hash); \ingroup SHA \brief Copies SHA224 context. + The memory regions occupied by the source and destination structures + must not overlap. If they overlap, including when src == dst, the + behavior is undefined. + \return 0 on success \return negative on error \param src Source SHA224 structure \param dst Destination SHA224 structure - (must be zeroed or previously initialized) + (must be zeroed or previously initialized and must not overlap src) _Example_ \code From 6b79737c32a7149b6e3bc8aeae8e4b91cc4eb6d4 Mon Sep 17 00:00:00 2001 From: kaage Date: Tue, 27 Oct 2026 02:19:09 +0900 Subject: [PATCH 3/4] Simplify SHA context copy validation and test self-copy --- wolfcrypt/src/sha256.c | 26 ++------------------------ wolfcrypt/test/test.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 3f3aded4fee..0b19caea404 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -3425,19 +3425,8 @@ int wc_Sha224Reset(wc_Sha224* sha224) { int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst) { int ret = 0; /* assume success unless proven otherwise */ - wc_ptr_t srcAddr; - wc_ptr_t dstAddr; - if (src == NULL || dst == NULL) { - return BAD_FUNC_ARG; - } - - /* Reject if src and dst had overlapping */ - srcAddr = (wc_ptr_t)src; - dstAddr = (wc_ptr_t)dst; - - if ((srcAddr <= dstAddr && dstAddr - srcAddr < sizeof(*src)) || - (dstAddr < srcAddr && srcAddr - dstAddr < sizeof(*dst))) { + if (src == NULL || dst == NULL || src == dst) { return BAD_FUNC_ARG; } @@ -3585,19 +3574,8 @@ int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash) int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) { int ret = 0; - wc_ptr_t srcAddr; - wc_ptr_t dstAddr; - - if (src == NULL || dst == NULL) { - return BAD_FUNC_ARG; - } - - /* Reject if src and dst had overlapping */ - srcAddr = (wc_ptr_t)src; - dstAddr = (wc_ptr_t)dst; - if ((srcAddr <= dstAddr && dstAddr - srcAddr < sizeof(*src)) || - (dstAddr < srcAddr && srcAddr - dstAddr < sizeof(*dst))) { + if (src == NULL || dst == NULL || src == dst) { return BAD_FUNC_ARG; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 3ca57e524ca..f1113f1150d 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -6573,6 +6573,20 @@ static wc_test_ret_t sha224_copy_test(wc_Sha224* sha, wc_Sha224* shaCopy) ret = wc_Sha224Update(shaCopy, (byte*)b_input, (word32)XSTRLEN(b_input)); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); + /* The common implementation rejects self-copy with BAD_FUNC_ARG. + * Platform-specific implementations differ: some accept self-copy as a + * no-op, while others do not check for it. Keep this assertion limited + * to configurations that use the common implementation. */ +#if !defined(WOLFSSL_TI_HASH) && !defined(WOLFSSL_RENESAS_RX64_HASH) && \ + (!defined(WOLFSSL_RENESAS_RSIP) || \ + defined(NO_WOLFSSL_RENESAS_FSPSM_HASH)) && \ + (!defined(WOLFSSL_KCAPI_HASH) || defined(WOLFSSL_NO_KCAPI_SHA224)) && \ + (!defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH)) && \ + !defined(MAX3266X_SHA) + ret = wc_Sha224Copy(sha, sha); + if (ret != BAD_FUNC_ARG) + ERROR_OUT(WC_TEST_RET_ENC_NC, exit); +#endif ret = wc_Sha224Update(sha, (byte*)a_input, (word32)XSTRLEN(a_input)); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); @@ -6876,6 +6890,25 @@ static wc_test_ret_t sha256_copy_test(wc_Sha256* sha, wc_Sha256* shaCopy) ret = wc_Sha256Update(shaCopy, (byte*)b_input, (word32)XSTRLEN(b_input)); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); +#endif + /* The common implementation rejects self-copy with BAD_FUNC_ARG. + * Platform-specific implementations differ: some accept self-copy as a + * no-op, while others do not check for it. Keep this assertion limited + * to configurations that use the common implementation. */ +#if !defined(WOLFSSL_TI_HASH) && !defined(WOLFSSL_AFALG_HASH) && \ + !defined(WOLFSSL_DEVCRYPTO_HASH) && \ + ((!defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY)) || \ + defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH)) && \ + ((!defined(WOLFSSL_RENESAS_SCEPROTECT) && \ + !defined(WOLFSSL_RENESAS_RSIP)) || \ + defined(NO_WOLFSSL_RENESAS_FSPSM_HASH)) && \ + !defined(WOLFSSL_IMXRT_DCP) && !defined(WOLFSSL_KCAPI_HASH) && \ + (!defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH)) && \ + !defined(WOLFSSL_RENESAS_RX64_HASH) && !defined(MAX3266X_SHA) + ret = wc_Sha256Copy(sha, sha); + if (ret != BAD_FUNC_ARG) + ERROR_OUT(WC_TEST_RET_ENC_NC, exit); #endif ret = wc_Sha256Update(sha, (byte*)a_input, (word32)XSTRLEN(a_input)); if (ret != 0) From c47c5f24c5761351b7e53096253d734fa5cc3027 Mon Sep 17 00:00:00 2001 From: kaage Date: Tue, 27 Oct 2026 12:44:26 +0900 Subject: [PATCH 4/4] Wrap SHA self-copy test error codes with WC_NO_ERR_TRACE --- wolfcrypt/test/test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index f1113f1150d..aceb49786a8 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -6584,7 +6584,7 @@ static wc_test_ret_t sha224_copy_test(wc_Sha224* sha, wc_Sha224* shaCopy) (!defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH)) && \ !defined(MAX3266X_SHA) ret = wc_Sha224Copy(sha, sha); - if (ret != BAD_FUNC_ARG) + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) ERROR_OUT(WC_TEST_RET_ENC_NC, exit); #endif ret = wc_Sha224Update(sha, (byte*)a_input, (word32)XSTRLEN(a_input)); @@ -6907,7 +6907,7 @@ static wc_test_ret_t sha256_copy_test(wc_Sha256* sha, wc_Sha256* shaCopy) (!defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH)) && \ !defined(WOLFSSL_RENESAS_RX64_HASH) && !defined(MAX3266X_SHA) ret = wc_Sha256Copy(sha, sha); - if (ret != BAD_FUNC_ARG) + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) ERROR_OUT(WC_TEST_RET_ENC_NC, exit); #endif ret = wc_Sha256Update(sha, (byte*)a_input, (word32)XSTRLEN(a_input));