From a1db58c4dbb996869544e6d3b209abb9f267f46b Mon Sep 17 00:00:00 2001 From: Yosuke Shimizu Date: Thu, 29 Oct 2026 16:23:24 +0900 Subject: [PATCH 1/2] pk_ec: bound the DER re-encode in wolfSSL_ECDSA_do_verify - In the WOLF_CRYPTO_CB_ONLY_ECC path, wolfSSL_ECDSA_do_verify() queries the encoded length with wolfSSL_i2d_ECDSA_SIG(sig, NULL) and returns WOLFSSL_FATAL_ERROR when it is not positive or exceeds the signature buffer, before encoding. - tests: add test_ECDSA_do_verify_oversized_sig, which verifies an ECDSA_SIG whose r encodes larger than ECC_MAX_SIG_SIZE. Issue: F-11725 --- src/pk_ec.c | 16 ++++++++++------ tests/api/test_ossl_ec.c | 38 ++++++++++++++++++++++++++++++++++++++ tests/api/test_ossl_ec.h | 2 ++ 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/pk_ec.c b/src/pk_ec.c index 05459162bd1..11325459ecc 100644 --- a/src/pk_ec.c +++ b/src/pk_ec.c @@ -5484,8 +5484,16 @@ int wolfSSL_ECDSA_do_verify(const unsigned char *dgst, int dLen, ret = 0; } #else - signatureLen = i2d_ECDSA_SIG(sig, &p); - if (signatureLen > 0) { + signatureLen = wolfSSL_i2d_ECDSA_SIG(sig, NULL); + if ((signatureLen <= 0) || (signatureLen > (int)sizeof(signature))) { + WOLFSSL_MSG("wolfSSL_ECDSA_do_verify signature length error"); + ret = WOLFSSL_FATAL_ERROR; + } + else if (wolfSSL_i2d_ECDSA_SIG(sig, &p) != signatureLen) { + WOLFSSL_MSG("wolfSSL_i2d_ECDSA_SIG failed"); + ret = WOLFSSL_FATAL_ERROR; + } + else { /* verify hash. expects to call wc_CryptoCb_EccVerify internally */ ret = wc_ecc_verify_hash(signature, signatureLen, dgst, (word32)dLen, &verified, (ecc_key*)key->internal); @@ -5498,10 +5506,6 @@ int wolfSSL_ECDSA_do_verify(const unsigned char *dgst, int dLen, ret = 0; } } - else { - WOLFSSL_MSG("i2d_ECDSA_SIG failed"); - ret = WOLFSSL_FATAL_ERROR; - } #endif /* WOLF_CRYPTO_CB_ONLY_ECC */ } diff --git a/tests/api/test_ossl_ec.c b/tests/api/test_ossl_ec.c index 90b892dce7c..42b23ceb83c 100644 --- a/tests/api/test_ossl_ec.c +++ b/tests/api/test_ossl_ec.c @@ -1659,6 +1659,44 @@ int test_ECDSA_size_sign(void) return EXPECT_RESULT(); } +int test_ECDSA_do_verify_oversized_sig(void) +{ + EXPECT_DECLS; + /* NO_RSA builds may size big integers too small to hold an r of + * ECC_MAX_SIG_SIZE bytes. */ +#if defined(OPENSSL_EXTRA) && !defined(NO_ECC256) && !defined(NO_ECC_SECP) && \ + !defined(NO_RSA) + EC_KEY* key = NULL; + ECDSA_SIG* sig = NULL; + BIGNUM* r = NULL; + BIGNUM* s = NULL; + byte hash[WC_MAX_DIGEST_SIZE]; + byte big[ECC_MAX_SIG_SIZE]; + + XMEMSET(hash, 123, sizeof(hash)); + XMEMSET(big, 0xff, sizeof(big)); + + ExpectNotNull(key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + ExpectNotNull(sig = ECDSA_SIG_new()); + /* r alone DER encodes to more than ECC_MAX_SIG_SIZE bytes. */ + ExpectNotNull(r = BN_bin2bn(big, (int)sizeof(big), NULL)); + ExpectNotNull(s = BN_new()); + ExpectIntEQ(BN_set_word(s, 1), 1); + ExpectIntEQ(ECDSA_SIG_set0(sig, r, s), 1); + if (EXPECT_FAIL()) { + BN_free(r); + BN_free(s); + } + + ExpectIntEQ(ECDSA_do_verify(hash, sizeof(hash), sig, key), + WOLFSSL_FATAL_ERROR); + + ECDSA_SIG_free(sig); + EC_KEY_free(key); +#endif + return EXPECT_RESULT(); +} + int test_ECDH_compute_key(void) { EXPECT_DECLS; diff --git a/tests/api/test_ossl_ec.h b/tests/api/test_ossl_ec.h index 3bfbdc9d1c7..52fc422caa1 100644 --- a/tests/api/test_ossl_ec.h +++ b/tests/api/test_ossl_ec.h @@ -43,6 +43,7 @@ int test_wolfSSL_EC_KEY_print_fp(void); int test_wolfSSL_EC_get_builtin_curves(void); int test_wolfSSL_ECDSA_SIG(void); int test_ECDSA_size_sign(void); +int test_ECDSA_do_verify_oversized_sig(void); int test_ECDH_compute_key(void); int test_d2i_ECPrivateKey_no_pubkey(void); int test_wolfSSL_EC_POINT_point2hex_oversized(void); @@ -66,6 +67,7 @@ int test_wolfSSL_EC_POINT_point2hex_oversized(void); TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_get_builtin_curves), \ TEST_DECL_GROUP("ossl_ec", test_wolfSSL_ECDSA_SIG), \ TEST_DECL_GROUP("ossl_ec", test_ECDSA_size_sign), \ + TEST_DECL_GROUP("ossl_ec", test_ECDSA_do_verify_oversized_sig), \ TEST_DECL_GROUP("ossl_ec", test_ECDH_compute_key), \ TEST_DECL_GROUP("ossl_ec", test_d2i_ECPrivateKey_no_pubkey), \ TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_POINT_point2hex_oversized) From 7c2f514be149db4dbb9dfb2abe000136444d8bea Mon Sep 17 00:00:00 2001 From: Yosuke Shimizu Date: Thu, 29 Oct 2026 19:26:58 +0900 Subject: [PATCH 2/2] pk_ec: keep wolfSSL_ECDSA_do_verify success result under crypto cb only - The WOLF_CRYPTO_CB_ONLY_ECC branch of wolfSSL_ECDSA_do_verify() compares the wc_ecc_verify_hash() return value and returns 1 on success. - tests: test_wolfSSL_EC_POINT is compiled out under WOLF_CRYPTO_CB_ONLY_ECC, matching the library's guard on wolfSSL_EC_POINT_get_affine_coordinates_GFp(). - tests: the ECDH derive part of test_wolfSSL_EVP_PKEY_encoded_public_key is compiled out under WOLF_CRYPTO_CB_ONLY_ECC, matching the EC case of wolfSSL_EVP_PKEY_derive(). --- src/pk_ec.c | 6 +++--- tests/api/test_evp_pkey.c | 2 ++ tests/api/test_ossl_ec.c | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/pk_ec.c b/src/pk_ec.c index 11325459ecc..91da8ed6fb5 100644 --- a/src/pk_ec.c +++ b/src/pk_ec.c @@ -5495,9 +5495,9 @@ int wolfSSL_ECDSA_do_verify(const unsigned char *dgst, int dLen, } else { /* verify hash. expects to call wc_CryptoCb_EccVerify internally */ - ret = wc_ecc_verify_hash(signature, signatureLen, dgst, - (word32)dLen, &verified, (ecc_key*)key->internal); - if (ret != MP_OKAY) { + if (wc_ecc_verify_hash(signature, (word32)signatureLen, dgst, + (word32)dLen, &verified, (ecc_key*)key->internal) != + MP_OKAY) { WOLFSSL_MSG("wc_ecc_verify_hash failed"); ret = WOLFSSL_FATAL_ERROR; } diff --git a/tests/api/test_evp_pkey.c b/tests/api/test_evp_pkey.c index 632af9eae4d..c9f9bf0599b 100644 --- a/tests/api/test_evp_pkey.c +++ b/tests/api/test_evp_pkey.c @@ -3802,6 +3802,7 @@ int test_wolfSSL_EVP_PKEY_encoded_public_key(void) EVP_PKEY_free(pkey2); } +#ifndef WOLF_CRYPTO_CB_ONLY_ECC /* set1 must produce a peer key usable for ECDH, i.e. the internal wolfCrypt * key (consumed by EVP_PKEY_derive) is synced, not just the wire bytes. */ { @@ -3866,6 +3867,7 @@ int test_wolfSSL_EVP_PKEY_encoded_public_key(void) EVP_PKEY_free(bob); EVP_PKEY_free(peer); } +#endif /* !WOLF_CRYPTO_CB_ONLY_ECC */ #endif /* HAVE_ECC */ #ifdef HAVE_CURVE25519 diff --git a/tests/api/test_ossl_ec.c b/tests/api/test_ossl_ec.c index 42b23ceb83c..266053298ca 100644 --- a/tests/api/test_ossl_ec.c +++ b/tests/api/test_ossl_ec.c @@ -300,7 +300,7 @@ int test_wolfSSL_i2d_ECPKParameters(void) int test_wolfSSL_EC_POINT(void) { EXPECT_DECLS; -#if !defined(WOLFSSL_SP_MATH) && \ +#if !defined(WOLFSSL_SP_MATH) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) && \ (!defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2))) #ifdef OPENSSL_EXTRA