diff --git a/src/group.h b/src/group.h index 0f5161fbf2be6..d81deb42649b4 100644 --- a/src/group.h +++ b/src/group.h @@ -102,6 +102,9 @@ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a */ static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const secp256k1_fe *zr); +/** Check two group elements (affine) for equality in variable time. */ +static int secp256k1_ge_eq_var(const secp256k1_ge *a, const secp256k1_ge *b); + /** Set a group element (affine) equal to the point at infinity. */ static void secp256k1_ge_set_infinity(secp256k1_ge *r); @@ -114,6 +117,9 @@ static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a); /** Check two group elements (jacobian) for equality in variable time. */ static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b); +/** Check two group elements (jacobian and affine) for equality in variable time. */ +static int secp256k1_gej_eq_ge_var(const secp256k1_gej *a, const secp256k1_ge *b); + /** Compare the X coordinate of a group element (jacobian). * The magnitude of the group element's X coordinate must not exceed 31. */ static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a); diff --git a/src/group_impl.h b/src/group_impl.h index cd5f0b01f9312..537be32ff6480 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -354,6 +354,35 @@ static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b) return secp256k1_gej_is_infinity(&tmp); } +static int secp256k1_gej_eq_ge_var(const secp256k1_gej *a, const secp256k1_ge *b) { + secp256k1_gej tmp; + SECP256K1_GEJ_VERIFY(a); + SECP256K1_GE_VERIFY(b); + + secp256k1_gej_neg(&tmp, a); + secp256k1_gej_add_ge_var(&tmp, &tmp, b, NULL); + return secp256k1_gej_is_infinity(&tmp); +} + +static int secp256k1_ge_eq_var(const secp256k1_ge *a, const secp256k1_ge *b) { + secp256k1_fe tmp; + SECP256K1_GE_VERIFY(a); + SECP256K1_GE_VERIFY(b); + + if (a->infinity != b->infinity) return 0; + if (a->infinity) return 1; + + tmp = a->x; + secp256k1_fe_normalize_weak(&tmp); + if (!secp256k1_fe_equal(&tmp, &b->x)) return 0; + + tmp = a->y; + secp256k1_fe_normalize_weak(&tmp); + if (!secp256k1_fe_equal(&tmp, &b->y)) return 0; + + return 1; +} + static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) { secp256k1_fe r; SECP256K1_FE_VERIFY(x); diff --git a/src/testutil.h b/src/testutil.h index 7333541dc59cb..fd701f254052f 100644 --- a/src/testutil.h +++ b/src/testutil.h @@ -7,6 +7,7 @@ #define SECP256K1_TESTUTIL_H #include "field.h" +#include "group.h" #include "testrand.h" #include "util.h" @@ -27,29 +28,11 @@ static void random_fe_non_zero(secp256k1_fe *nz) { } static void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) { - CHECK(a->infinity == b->infinity); - if (a->infinity) { - return; - } - CHECK(secp256k1_fe_equal(&a->x, &b->x)); - CHECK(secp256k1_fe_equal(&a->y, &b->y)); + CHECK(secp256k1_ge_eq_var(a, b)); } static void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) { - secp256k1_fe z2s; - secp256k1_fe u1, u2, s1, s2; - CHECK(a->infinity == b->infinity); - if (a->infinity) { - return; - } - /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */ - secp256k1_fe_sqr(&z2s, &b->z); - secp256k1_fe_mul(&u1, &a->x, &z2s); - u2 = b->x; - secp256k1_fe_mul(&s1, &a->y, &z2s); secp256k1_fe_mul(&s1, &s1, &b->z); - s2 = b->y; - CHECK(secp256k1_fe_equal(&u1, &u2)); - CHECK(secp256k1_fe_equal(&s1, &s2)); + CHECK(secp256k1_gej_eq_ge_var(b, a)); } #endif /* SECP256K1_TESTUTIL_H */