Files
wolfssl/wolfcrypt
Tobias Frauenschläger 929dd9913b ecc: fix invalid-curve attack via missing on-curve validation
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. wc_ecc_shared_secret performed no on-curve validation at all.

An attacker who can supply an EC public key (e.g. via an ECIES
ciphertext, PKCS#7 enveloped-data, or EVP_PKEY_derive) 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.

Three changes close the attack:

1. Define USE_ECC_B_PARAM unconditionally in ecc.h so that
   wc_ecc_point_is_on_curve() is compiled in all builds, not only
   those with HAVE_COMP_KEY or OPENSSL_EXTRA.

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_shared_secret: add defense-in-depth on-curve check before
   scalar multiplication, catching any import path that bypassed the
   import-time validation (e.g. direct wc_ecc_import_x963_ex2 with
   untrusted=0).

Both new validation sites dispatch to sp_ecc_check_key_NNN for
SP-supported curves (P-256/384/521, SM2) when WOLFSSL_HAVE_SP_ECC is
defined, keeping the mp_int stack cost off embedded targets. Non-SP
curves fall back to wc_ecc_point_is_on_curve.

Reported by: Nicholas Carlini (Anthropic) & Thai Duong (Calif.io)
2026-03-31 15:14:15 +02:00
..