Skip to content

Commit 6c5de29

Browse files
committed
Fix ECC validation regression
1 parent b573823 commit 6c5de29

3 files changed

Lines changed: 56 additions & 1 deletion

File tree

tests/api/test_ecc.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,58 @@ int test_wc_ecc_import_x963(void)
772772
return EXPECT_RESULT();
773773
} /* END wc_ecc_import_x963 */
774774

775+
/*
776+
* testing wc_ecc_import_x963() rejects an off-curve public point.
777+
*
778+
* Regression coverage for the invalid-curve attack: the legacy wrapper
779+
* wc_ecc_import_x963_ex (called by wc_ecc_import_x963()) must pass untrusted=1
780+
* to wc_ecc_import_x963_ex2 so that ECIES, PKCS#7 KARI, and EVP ECDH callers
781+
* validate that the imported point actually lies on the curve. Without that,
782+
* an attacker can feed a point from a weak twist and leak the victim's private
783+
* scalar modulo small primes (Biehl-Meyer-Mueller).
784+
*/
785+
int test_wc_ecc_import_x963_off_curve(void)
786+
{
787+
EXPECT_DECLS;
788+
#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_IMPORT) && \
789+
!defined(NO_ECC256) && !defined(NO_ECC_SECP) && \
790+
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0)) && !defined(HAVE_SELFTEST)
791+
ecc_key pubKey;
792+
/* Uncompressed X9.63 P-256 point: 0x04 || Gx || Gy with the last byte
793+
* of Gy flipped by 1. Gx/Gy are the NIST P-256 generator coordinates;
794+
* modifying a single bit of Gy produces a point that is not on the
795+
* curve, so wc_ecc_import_x963 must reject it. */
796+
static const byte offCurveX963[] = {
797+
0x04,
798+
0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47,
799+
0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2,
800+
0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
801+
0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96,
802+
0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B,
803+
0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16,
804+
0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
805+
0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF4
806+
};
807+
808+
XMEMSET(&pubKey, 0, sizeof(ecc_key));
809+
810+
ExpectIntEQ(wc_ecc_init(&pubKey), 0);
811+
812+
/* Importing an off-curve point must fail. wc_ecc_import_x963() calls
813+
* wc_ecc_import_x963_ex() which ultimately calls wc_ecc_import_x963_ex2()
814+
* with the required untrusted=1 flag. */
815+
ExpectIntNE(wc_ecc_import_x963(offCurveX963, (word32)sizeof(offCurveX963),
816+
&pubKey), 0);
817+
818+
wc_ecc_free(&pubKey);
819+
820+
#ifdef FP_ECC
821+
wc_ecc_fp_free();
822+
#endif
823+
#endif
824+
return EXPECT_RESULT();
825+
} /* END test_wc_ecc_import_x963_off_curve */
826+
775827
/*
776828
* testing wc_ecc_import_private_key()
777829
*/

tests/api/test_ecc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ int test_wc_ecc_shared_secret(void);
3939
int test_wc_ecc_export_x963(void);
4040
int test_wc_ecc_export_x963_ex(void);
4141
int test_wc_ecc_import_x963(void);
42+
int test_wc_ecc_import_x963_off_curve(void);
4243
int test_wc_ecc_import_private_key(void);
4344
int test_wc_ecc_export_private_only(void);
4445
int test_wc_ecc_rs_to_sig(void);
@@ -76,6 +77,7 @@ int test_wc_EccPrivateKeyToDer(void);
7677
TEST_DECL_GROUP("ecc", test_wc_ecc_export_x963), \
7778
TEST_DECL_GROUP("ecc", test_wc_ecc_export_x963_ex), \
7879
TEST_DECL_GROUP("ecc", test_wc_ecc_import_x963), \
80+
TEST_DECL_GROUP("ecc", test_wc_ecc_import_x963_off_curve), \
7981
TEST_DECL_GROUP("ecc", test_wc_ecc_import_private_key), \
8082
TEST_DECL_GROUP("ecc", test_wc_ecc_export_private_only), \
8183
TEST_DECL_GROUP("ecc", test_wc_ecc_rs_to_sig), \

wolfcrypt/src/ecc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11226,7 +11226,8 @@ int wc_ecc_import_x963_ex2(const byte* in, word32 inLen, ecc_key* key,
1122611226
int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key,
1122711227
int curve_id)
1122811228
{
11229-
return wc_ecc_import_x963_ex2(in, inLen, key, curve_id, 0);
11229+
/* treat as untrusted: validate the point is on the curve */
11230+
return wc_ecc_import_x963_ex2(in, inLen, key, curve_id, 1);
1123011231
}
1123111232

1123211233
WOLFSSL_ABI

0 commit comments

Comments
 (0)