From 0a719093ff29d389ce703a4ce2237aad7df1fc77 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 28 Oct 2026 14:36:09 +0000 Subject: [PATCH 1/2] Fail EVP_DigestSignFinal() for ECDSA when the buffer is too small The EC branch returned success without writing the signature when the DER encoding did not fit in *siglen, and set *siglen past the end of the caller's buffer. Fail instead and leave sig and *siglen unchanged. Get the sig == NULL size from wc_ecc_sig_size(), as EVP_PKEY_size() and EVP_PKEY_sign() do. size * 2 + 8 was too small for brainpoolP512r1 (136 vs 137) and read ecc_sets[-1] for keys with explicit curve parameters. The size is now the DER maximum: P-521 139 (was 140) and prime239v1-3 66 (was 68). Fixes #11904 --- tests/api/test_evp_pkey.c | 43 +++++++++++++++++++++++++++++++++++++++ tests/api/test_evp_pkey.h | 2 ++ wolfcrypt/src/evp.c | 18 ++++++++++++---- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/tests/api/test_evp_pkey.c b/tests/api/test_evp_pkey.c index 632af9eae4d..8f3fdfb58a9 100644 --- a/tests/api/test_evp_pkey.c +++ b/tests/api/test_evp_pkey.c @@ -2440,6 +2440,12 @@ int test_wolfSSL_EVP_MD_ecc_signing(void) (unsigned int)XSTRLEN(testData)), 1); checkSz = sizeof(check); ExpectIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, NULL, &checkSz), 1); + ExpectIntEQ((int)checkSz, wolfSSL_EVP_PKEY_size(privKey)); + /* A buffer too small for the signature is an error. */ + checkSz = 8; + ExpectIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 0); + ExpectIntEQ((int)checkSz, 8); + ExpectIntEQ(check[0], 0); checkSz = sizeof(check); ExpectIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); ret = wolfSSL_EVP_MD_CTX_cleanup(&mdCtx); @@ -2487,6 +2493,43 @@ int test_wolfSSL_EVP_MD_ecc_signing(void) return EXPECT_RESULT(); } +int test_wolfSSL_EVP_DigestSignFinal_ecc_size(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && !defined(NO_SHA256) && \ + defined(HAVE_ECC_BRAINPOOL) && \ + (defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)) && \ + ECC_MIN_KEY_SZ <= 512 + WOLFSSL_EC_KEY* ecKey = NULL; + WOLFSSL_EVP_PKEY* pkey = NULL; + WOLFSSL_EVP_MD_CTX mdCtx; + size_t sigSz = 0; + int ret; + + ExpectNotNull(ecKey = wolfSSL_EC_KEY_new_by_curve_name( + NID_brainpoolP512r1)); + ExpectIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); + ExpectNotNull(pkey = wolfSSL_EVP_PKEY_new()); + ExpectIntEQ(wolfSSL_EVP_PKEY_assign_EC_KEY(pkey, ecKey), WOLFSSL_SUCCESS); + if (EXPECT_FAIL()) { + wolfSSL_EC_KEY_free(ecKey); + } + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + ExpectIntEQ(wolfSSL_EVP_DigestSignInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, pkey), 1); + ExpectIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, NULL, &sigSz), 1); + /* r and s may need a leading zero and the SEQ length is two bytes. */ + ExpectIntEQ((int)sigSz, 137); + ExpectIntEQ((int)sigSz, wolfSSL_EVP_PKEY_size(pkey)); + ret = wolfSSL_EVP_MD_CTX_cleanup(&mdCtx); + ExpectIntEQ(ret, 1); + + wolfSSL_EVP_PKEY_free(pkey); +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_EVP_DigestSign(void) { diff --git a/tests/api/test_evp_pkey.h b/tests/api/test_evp_pkey.h index 874391edb21..1db3107f3b6 100644 --- a/tests/api/test_evp_pkey.h +++ b/tests/api/test_evp_pkey.h @@ -65,6 +65,7 @@ int test_wolfSSL_EVP_PKEY_verify_dsa_len(void); int test_wolfSSL_EVP_MD_rsa_signing(void); int test_wc_RsaPSS_DigitalSignVerify(void); int test_wolfSSL_EVP_MD_ecc_signing(void); +int test_wolfSSL_EVP_DigestSignFinal_ecc_size(void); int test_wolfSSL_EVP_DigestSign(void); int test_wolfSSL_EVP_DigestSign_ecc(void); int test_wolfSSL_EVP_PKEY_encrypt(void); @@ -126,6 +127,7 @@ int test_wolfSSL_CTX_use_PrivateKey_pkcs8_repopulate(void); TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_MD_rsa_signing), \ TEST_DECL_GROUP("evp_pkey", test_wc_RsaPSS_DigitalSignVerify), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_MD_ecc_signing), \ + TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_DigestSignFinal_ecc_size), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_DigestSign), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_DigestSign_ecc), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_encrypt), \ diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 3b212155b64..6164dff91f2 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -5225,9 +5225,17 @@ int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sig, #ifdef HAVE_ECC else if (ctx->pctx->pkey->type == WC_EVP_PKEY_EC) { if (sig == NULL) { - /* SEQ + INT + INT */ - *siglen = (size_t)ecc_sets[ctx->pctx->pkey->ecc->group->curve_idx]. - size * 2 + 8; + WOLFSSL_EC_KEY* key = ctx->pctx->pkey->ecc; + int sigSz; + + if (key == NULL || (key->inSet == 0 && + SetECKeyInternal(key) != WOLFSSL_SUCCESS)) { + return WOLFSSL_FAILURE; + } + sigSz = wc_ecc_sig_size((ecc_key*)key->internal); + if (sigSz <= 0) + return WOLFSSL_FAILURE; + *siglen = (size_t)sigSz; return WOLFSSL_SUCCESS; } } @@ -5277,8 +5285,10 @@ int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sig, len = wolfSSL_i2d_ECDSA_SIG(ecdsaSig, NULL); if (len > 0 && (size_t)len <= *siglen) len = wolfSSL_i2d_ECDSA_SIG(ecdsaSig, &sig); + else + len = 0; wolfSSL_ECDSA_SIG_free(ecdsaSig); - if (len == 0) + if (len <= 0) break; *siglen = (size_t)len; ret = WOLFSSL_SUCCESS; From ea17e70baa708fefd28e2b8d3c85860e29f2010d Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Fri, 30 Oct 2026 06:30:47 +0000 Subject: [PATCH 2/2] Address review: skip Brainpool sig size test on FIPS v6+ FIPS v6+ wolfSSL_EC_KEY_generate_key() rejects non-approved curves. --- tests/api/test_evp_pkey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/api/test_evp_pkey.c b/tests/api/test_evp_pkey.c index 8f3fdfb58a9..51c8b5cef02 100644 --- a/tests/api/test_evp_pkey.c +++ b/tests/api/test_evp_pkey.c @@ -2499,7 +2499,7 @@ int test_wolfSSL_EVP_DigestSignFinal_ecc_size(void) #if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && !defined(NO_SHA256) && \ defined(HAVE_ECC_BRAINPOOL) && \ (defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)) && \ - ECC_MIN_KEY_SZ <= 512 + ECC_MIN_KEY_SZ <= 512 && FIPS_VERSION3_LT(6,0,0) WOLFSSL_EC_KEY* ecKey = NULL; WOLFSSL_EVP_PKEY* pkey = NULL; WOLFSSL_EVP_MD_CTX mdCtx;