mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-06 01:00:49 +02:00
0fb2d2ec11
wc_ecc_import_x963_ex2 only checked whether an imported public point lies on the intended curve when both USE_ECC_B_PARAM was compiled in and the caller passed untrusted=1. In a default ./configure build, USE_ECC_B_PARAM is not defined, so the check was compiled out entirely. Additionally, the legacy wrapper wc_ecc_import_x963_ex unconditionally passed untrusted=0, meaning ECIES (wc_ecc_decrypt), PKCS#7 KARI, and the EVP ECDH layer never triggered the check even when the macro was present. In the OpenSSL compatibility layer, wolfSSL_ECPoint_d2i guarded its on-curve check behind !wolfSSL_BN_is_one(point->Z), but wc_ecc_import_point_der_ex always sets Z=1 for uncompressed points, making the check dead code. An attacker who can supply an EC public key (e.g. via an ECIES ciphertext, PKCS#7 enveloped-data, EVP_PKEY_derive, or EC_POINT_oct2point + ECDH_compute_key) can choose a point on a twist of the target curve with a smooth-order subgroup. Each ECDH query leaks the victim's static private scalar modulo a small prime; CRT reconstruction across enough queries recovers the full key (Biehl-Meyer-Müller invalid-curve attack). Static-key ECIES and PKCS#7 KARI are directly affected; TLS is affected in default builds because the USE_ECC_B_PARAM gate defeated the untrusted=1 flag that the handshake does pass. Four changes close the attack: 1. Remove the USE_ECC_B_PARAM gate completely in the code base so that wc_ecc_point_is_on_curve() is compiled in all builds, not only those with HAVE_COMP_KEY or OPENSSL_EXTRA (only set for legacy FIPS builds in settings.h). 2. wc_ecc_import_x963_ex: pass untrusted=1 to wc_ecc_import_x963_ex2 so that ECIES, PKCS#7 KARI, and EVP callers that go through the four-argument wrapper always validate the imported point. 3. wc_ecc_import_x963_ex2: use the lightweight sp_ecc_is_point_NNN helpers (curve-equation check only) instead of sp_ecc_check_key_NNN (which additionally performs a full point*order scalar multiply). For prime-order curves (P-256, P-384, P-521, SM2) the on-curve equation check y^2 = x^3 + ax + b is sufficient to defeat invalid-curve attacks — every non-identity point on a prime-order curve has the full group order, so the expensive order-multiply check is unnecessary. This avoids the ~50% ECDH performance regression caused by the redundant scalar multiplication. 4. wolfSSL_ECPoint_d2i (pk_ec.c): add unconditional on-curve validation via wolfSSL_EC_POINT_is_on_curve after import. The existing check was gated on !wolfSSL_BN_is_one(point->Z) and therefore dead code for all uncompressed-point imports. This closes the OpenSSL compat layer attack path (EC_POINT_oct2point followed by ECDH_compute_key). Non-SP curves fall back to wc_ecc_point_is_on_curve which performs the same equation check using mp_int arithmetic. Reported by: Nicholas Carlini (Anthropic) & Thai Duong (Calif.io)
Before creating any new configure files (.conf) read the CONF_FILES_README.md