fix ECC failing wycheproof tests

This commit is contained in:
Karel Miko 2026-04-29 20:46:49 +02:00 committed by Steffen Jaeckel
parent 7c0e52114e
commit e312fffaf2
4 changed files with 33 additions and 15 deletions

View file

@ -605,7 +605,7 @@ static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q,
{
fp_int t1, t2, x, y, z;
fp_digit mp;
int err, inf, x_or_y_is_zero;
int err, inf;
LTC_ARGCHK(P != NULL);
LTC_ARGCHK(Q != NULL);
@ -704,6 +704,15 @@ dbl_point:
fp_mul(Q->y, &t1, &t1);
fp_montgomery_reduce(&t1, TFM_UNCONST(void *)modulus, mp);
/* Same-affine dispatch (mirror of ltc_ecc_projective_add_point): A==B means P,Q share affine x; dispatch to dbl or O before the formulas */
if (fp_cmp(&x, &t2) == FP_EQ) {
if (fp_cmp(&y, &t1) == FP_EQ) goto dbl_point;
ltc_mp.set_int(R->x, 1);
ltc_mp.set_int(R->y, 1);
ltc_mp.set_int(R->z, 0);
return CRYPT_OK;
}
/* Y = Y - T1 */
fp_sub(&y, &t1, &y);
if (fp_cmp_d(&y, 0) == FP_LT) {
@ -767,7 +776,6 @@ dbl_point:
if (fp_cmp_d(&x, 0) == FP_LT) {
fp_add(&x, TFM_UNCONST(void *)modulus, &x);
}
x_or_y_is_zero = fp_cmp_d(&x, 0) == FP_EQ;
/* T2 = T2 - X */
fp_sub(&t2, &x, &t2);
@ -792,11 +800,6 @@ dbl_point:
fp_add(&y, TFM_UNCONST(void *)modulus, &y);
}
fp_div_2(&y, &y);
x_or_y_is_zero |= fp_cmp_d(&y, 0) == LTC_MP_EQ;
if (x_or_y_is_zero) {
goto dbl_point;
}
fp_copy(&x, R->x);
fp_copy(&y, R->y);

View file

@ -36,6 +36,20 @@ int ecc_shared_secret(const ecc_key *private_key, const ecc_key *public_key,
return CRYPT_PK_NOT_PRIVATE;
}
/* Domain-parameter check: both keys must be on the same curve. Otherwise the scalar mul
below would silently use the private key's prime/A against a public point that lives
in a different group (scenarion from Wycheproof ecdh_*WrongCurve).
*/
if (ltc_mp_cmp(private_key->dp.prime, public_key->dp.prime) != LTC_MP_EQ ||
ltc_mp_cmp(private_key->dp.order, public_key->dp.order) != LTC_MP_EQ ||
ltc_mp_cmp(private_key->dp.A, public_key->dp.A) != LTC_MP_EQ ||
ltc_mp_cmp(private_key->dp.B, public_key->dp.B) != LTC_MP_EQ ||
ltc_mp_cmp(private_key->dp.base.x, public_key->dp.base.x) != LTC_MP_EQ ||
ltc_mp_cmp(private_key->dp.base.y, public_key->dp.base.y) != LTC_MP_EQ ||
private_key->dp.cofactor != public_key->dp.cofactor) {
return CRYPT_PK_TYPE_MISMATCH;
}
/* make new point */
result = ltc_ecc_new_point();
if (result == NULL) {

View file

@ -24,7 +24,7 @@ int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_poi
const void *ma, const void *modulus, void *mp)
{
void *t1, *t2, *x, *y, *z;
int err, inf, x_or_y_is_zero;
int err, inf;
LTC_ARGCHK(P != NULL);
LTC_ARGCHK(Q != NULL);
@ -116,6 +116,13 @@ dbl_point:
if ((err = ltc_mp_mul(Q->y, t1, t1)) != CRYPT_OK) { goto done; }
if ((err = ltc_mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
/* Same-affine dispatch: A==B means P,Q share affine x; dispatch to dbl or O before the formulas */
if (ltc_mp_cmp(x, t2) == LTC_MP_EQ) {
if (ltc_mp_cmp(y, t1) == LTC_MP_EQ) goto dbl_point;
err = ltc_ecc_set_point_xyz(1, 1, 0, R);
goto done;
}
/* Y = Y - T1 */
if ((err = ltc_mp_sub(y, t1, y)) != CRYPT_OK) { goto done; }
if (ltc_mp_cmp_d(y, 0) == LTC_MP_LT) {
@ -179,7 +186,6 @@ dbl_point:
if (ltc_mp_cmp_d(x, 0) == LTC_MP_LT) {
if ((err = ltc_mp_add(x, modulus, x)) != CRYPT_OK) { goto done; }
}
x_or_y_is_zero = ltc_mp_cmp_d(x, 0) == LTC_MP_EQ;
/* T2 = T2 - X */
if ((err = ltc_mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; }
@ -204,11 +210,6 @@ dbl_point:
if ((err = ltc_mp_add(y, modulus, y)) != CRYPT_OK) { goto done; }
}
if ((err = ltc_mp_div_2(y, y)) != CRYPT_OK) { goto done; }
x_or_y_is_zero |= ltc_mp_cmp_d(y, 0) == LTC_MP_EQ;
if (x_or_y_is_zero) {
goto dbl_point;
}
if ((err = ltc_mp_copy(x, R->x)) != CRYPT_OK) { goto done; }
if ((err = ltc_mp_copy(y, R->y)) != CRYPT_OK) { goto done; }

View file

@ -353,7 +353,7 @@ static int s_ecc_wycheproof_p256_pem_invalid_explicit(void)
"MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCBPNBTRWJtJ9xctQ5y7\n"
"545bU1Dchd6kDNLWJ0dAxuAjnA==\n"
"-----END PRIVATE KEY-----\n";
/* tcId=352 WrongOrder (order = -secp256r1.order) */
/* tcId=352 WrongOrder (order = -secp256r1.order) */
static const char pub_pem[] =
"-----BEGIN PUBLIC KEY-----\n"
"MIIBMzCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAA\n"