From a0e696fd4da3788758bb3fdae66c7ae262dbf224 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Sat, 8 Aug 2020 03:52:34 +0000 Subject: [PATCH 1/6] Make secp256k1_ecmult_const handle infinity Infinity isn't currently needed here, but correctly handling it is a little more safe against future changes. Update docs for it to make it clear that it is not constant time in A (the input point). It never was constant time in Q (and would be a little complicated to make constant time in A). If it was later made constant time in A, infinity support would be easy to preserve, e.g. by running it on a dummy value and cmoving infinity into the output. --- src/ecmult_const.h | 3 +-- src/ecmult_const_impl.h | 5 +++++ src/tests_exhaustive.c | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/ecmult_const.h b/src/ecmult_const.h index 9e065d555d7b9..080e04bc882f2 100644 --- a/src/ecmult_const.h +++ b/src/ecmult_const.h @@ -11,8 +11,7 @@ #include "group.h" /** - * Multiply: R = q*A (in constant-time) - * A must not be infinity. + * Multiply: R = q*A (in constant-time for q) */ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q); diff --git a/src/ecmult_const_impl.h b/src/ecmult_const_impl.h index f2b6f48285fc5..81e16e343de99 100644 --- a/src/ecmult_const_impl.h +++ b/src/ecmult_const_impl.h @@ -144,6 +144,11 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons int i; + if (secp256k1_ge_is_infinity(a)) { + secp256k1_gej_set_infinity(r); + return; + } + /* build wnaf representation for q. */ /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */ secp256k1_scalar_split_lambda(&q_1, &q_lam, scalar); diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index 5a990f7d64dda..ee60fe9f45458 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -193,7 +193,7 @@ static void test_exhaustive_ecmult(const secp256k1_ge *group, const secp256k1_ge } for (j = 0; j < EXHAUSTIVE_TEST_ORDER; j++) { - for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { + for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { int ret; secp256k1_gej tmp; secp256k1_fe xn, xd, tmpf; @@ -207,7 +207,7 @@ static void test_exhaustive_ecmult(const secp256k1_ge *group, const secp256k1_ge secp256k1_ecmult_const(&tmp, &group[i], &ng); ge_equals_gej(&group[(i * j) % EXHAUSTIVE_TEST_ORDER], &tmp); - if (j != 0) { + if (i != 0 && j != 0) { /* Test secp256k1_ecmult_const_xonly with all curve X coordinates, and xd=NULL. */ ret = secp256k1_ecmult_const_xonly(&tmpf, &group[i].x, NULL, &ng, 0); CHECK(ret); From 3086cb90acd9d61c5b38e862877fdeacaff74a50 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 1 Sep 2020 16:33:22 -0700 Subject: [PATCH 2/6] Expose secp256k1_fe_verify to other modules --- src/field.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/field.h b/src/field.h index c7a88c4e13b4b..62dc0f3ae04da 100644 --- a/src/field.h +++ b/src/field.h @@ -143,4 +143,9 @@ static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m); /** Determine whether a is a square (modulo p). */ static int secp256k1_fe_is_square_var(const secp256k1_fe *a); +#ifdef VERIFY +/** Check invariants on a field element. */ +static void secp256k1_fe_verify(const secp256k1_fe *a); +#endif + #endif /* SECP256K1_FIELD_H */ From a18821d5b1d44db0e7c8335f338cc9876bec98cb Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 1 Sep 2020 18:15:21 -0700 Subject: [PATCH 3/6] Always initialize output coordinates in secp256k1_ge_set_gej --- src/group_impl.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/group_impl.h b/src/group_impl.h index 29017dc965242..d6031e58cfc64 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -115,10 +115,11 @@ static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) { static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { secp256k1_fe z2, z3; - if (a->infinity) { + if (secp256k1_gej_is_infinity(a)) { secp256k1_ge_set_infinity(r); return; } + r->infinity = 0; secp256k1_fe_inv_var(&a->z, &a->z); secp256k1_fe_sqr(&z2, &a->z); secp256k1_fe_mul(&z3, &a->z, &z2); From f20266722ac93ca66d1beb0d2f2d2469b95aafea Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 1 Sep 2020 17:59:51 -0700 Subject: [PATCH 4/6] Add invariant checking to group elements --- src/group.h | 8 ++ src/group_impl.h | 188 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 191 insertions(+), 5 deletions(-) diff --git a/src/group.h b/src/group.h index b79ba597dbbbc..14cdb4062d22e 100644 --- a/src/group.h +++ b/src/group.h @@ -164,4 +164,12 @@ static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b); */ static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge); +#ifdef VERIFY +/** Check invariants on an affine group element. */ +static void secp256k1_ge_verify(const secp256k1_ge *a); + +/** Check invariants on a Jacobian group element. */ +static void secp256k1_gej_verify(const secp256k1_gej *a); +#endif + #endif /* SECP256K1_GROUP_H */ diff --git a/src/group_impl.h b/src/group_impl.h index d6031e58cfc64..86be92d59deda 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -73,35 +73,78 @@ static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G; #endif /* End of section generated by sage/gen_exhaustive_groups.sage. */ +#ifdef VERIFY +static void secp256k1_ge_verify(const secp256k1_ge *a) { + secp256k1_fe_verify(&a->x); + secp256k1_fe_verify(&a->y); + VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); +} + +static void secp256k1_gej_verify(const secp256k1_gej *a) { + secp256k1_fe_verify(&a->x); + secp256k1_fe_verify(&a->y); + secp256k1_fe_verify(&a->z); + VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); +} +#endif + static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) { secp256k1_fe zi2; secp256k1_fe zi3; +#ifdef VERIFY + /* Do not call secp256k1_ge_verify, as we do not require a->z to be initialized. */ + secp256k1_fe_verify(&a->x); + secp256k1_fe_verify(&a->y); + secp256k1_fe_verify(zi); +#endif VERIFY_CHECK(!a->infinity); secp256k1_fe_sqr(&zi2, zi); secp256k1_fe_mul(&zi3, &zi2, zi); secp256k1_fe_mul(&r->x, &a->x, &zi2); secp256k1_fe_mul(&r->y, &a->y, &zi3); r->infinity = a->infinity; +#ifdef VERIFY + secp256k1_ge_verify(r); +#endif } static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) { +#ifdef VERIFY + secp256k1_fe_verify(x); + secp256k1_fe_verify(y); +#endif r->infinity = 0; r->x = *x; r->y = *y; +#ifdef VERIFY + secp256k1_ge_verify(r); +#endif } static int secp256k1_ge_is_infinity(const secp256k1_ge *a) { +#ifdef VERIFY + secp256k1_ge_verify(a); +#endif return a->infinity; } static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) { +#ifdef VERIFY + secp256k1_ge_verify(a); +#endif *r = *a; secp256k1_fe_normalize_weak(&r->y); secp256k1_fe_negate(&r->y, &r->y, 1); +#ifdef VERIFY + secp256k1_ge_verify(r); +#endif } static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) { secp256k1_fe z2, z3; +#ifdef VERIFY + secp256k1_gej_verify(a); +#endif r->infinity = a->infinity; secp256k1_fe_inv(&a->z, &a->z); secp256k1_fe_sqr(&z2, &a->z); @@ -111,10 +154,16 @@ static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) { secp256k1_fe_set_int(&a->z, 1); r->x = a->x; r->y = a->y; +#ifdef VERIFY + secp256k1_ge_verify(r); +#endif } static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { secp256k1_fe z2, z3; +#ifdef VERIFY + secp256k1_gej_verify(a); +#endif if (secp256k1_gej_is_infinity(a)) { secp256k1_ge_set_infinity(r); return; @@ -127,6 +176,9 @@ static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { secp256k1_fe_mul(&a->y, &a->y, &z3); secp256k1_fe_set_int(&a->z, 1); secp256k1_ge_set_xy(r, &a->x, &a->y); +#ifdef VERIFY + secp256k1_ge_verify(r); +#endif } static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len) { @@ -135,6 +187,9 @@ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a size_t last_i = SIZE_MAX; for (i = 0; i < len; i++) { +#ifdef VERIFY + secp256k1_gej_verify(&a[i]); +#endif if (a[i].infinity) { secp256k1_ge_set_infinity(&r[i]); } else { @@ -168,6 +223,9 @@ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a if (!a[i].infinity) { secp256k1_ge_set_gej_zinv(&r[i], &a[i], &r[i].x); } +#ifdef VERIFY + secp256k1_ge_verify(&r[i]); +#endif } } @@ -176,6 +234,11 @@ static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const se secp256k1_fe zs; if (len > 0) { +#ifdef VERIFY + /* Verify inputs a[len-1] and zr[len-1]. */ + secp256k1_ge_verify(&a[i]); + secp256k1_fe_verify(&zr[i]); +#endif /* Ensure all y values are in weak normal form for fast negation of points */ secp256k1_fe_normalize_weak(&a[i].y); zs = zr[i]; @@ -183,6 +246,11 @@ static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const se /* Work our way backwards, using the z-ratios to scale the x/y values. */ while (i > 0) { secp256k1_gej tmpa; +#ifdef VERIFY + /* Verify all inputs a[i] and zr[i]. */ + secp256k1_fe_verify(&zr[i]); + secp256k1_ge_verify(&a[i]); +#endif if (i != len - 1) { secp256k1_fe_mul(&zs, &zs, &zr[i]); } @@ -191,6 +259,10 @@ static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const se tmpa.y = a[i].y; tmpa.infinity = 0; secp256k1_ge_set_gej_zinv(&a[i], &tmpa, &zs); +#ifdef VERIFY + /* Verify the output a[i]. */ + secp256k1_ge_verify(&a[i]); +#endif } } } @@ -200,12 +272,18 @@ static void secp256k1_gej_set_infinity(secp256k1_gej *r) { secp256k1_fe_clear(&r->x); secp256k1_fe_clear(&r->y); secp256k1_fe_clear(&r->z); +#ifdef VERIFY + secp256k1_gej_verify(r); +#endif } static void secp256k1_ge_set_infinity(secp256k1_ge *r) { r->infinity = 1; secp256k1_fe_clear(&r->x); secp256k1_fe_clear(&r->y); +#ifdef VERIFY + secp256k1_ge_verify(r); +#endif } static void secp256k1_gej_clear(secp256k1_gej *r) { @@ -223,31 +301,45 @@ static void secp256k1_ge_clear(secp256k1_ge *r) { static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) { secp256k1_fe x2, x3; + int ret; +#ifdef VERIFY + secp256k1_fe_verify(x); +#endif r->x = *x; secp256k1_fe_sqr(&x2, x); secp256k1_fe_mul(&x3, x, &x2); r->infinity = 0; secp256k1_fe_add_int(&x3, SECP256K1_B); - if (!secp256k1_fe_sqrt(&r->y, &x3)) { - return 0; - } + ret = secp256k1_fe_sqrt(&r->y, &x3); secp256k1_fe_normalize_var(&r->y); if (secp256k1_fe_is_odd(&r->y) != odd) { secp256k1_fe_negate(&r->y, &r->y, 1); } - return 1; - +#ifdef VERIFY + secp256k1_ge_verify(r); +#endif + return ret; } static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) { +#ifdef VERIFY + secp256k1_ge_verify(a); +#endif r->infinity = a->infinity; r->x = a->x; r->y = a->y; secp256k1_fe_set_int(&r->z, 1); +#ifdef VERIFY + secp256k1_gej_verify(r); +#endif } static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b) { secp256k1_gej tmp; +#ifdef VERIFY + secp256k1_gej_verify(b); + secp256k1_gej_verify(a); +#endif secp256k1_gej_neg(&tmp, a); secp256k1_gej_add_var(&tmp, &tmp, b, NULL); return secp256k1_gej_is_infinity(&tmp); @@ -255,6 +347,10 @@ static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b) static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) { secp256k1_fe r, r2; +#ifdef VERIFY + secp256k1_fe_verify(x); + secp256k1_gej_verify(a); +#endif VERIFY_CHECK(!a->infinity); secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x); r2 = a->x; secp256k1_fe_normalize_weak(&r2); @@ -262,20 +358,32 @@ static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) } static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) { +#ifdef VERIFY + secp256k1_gej_verify(a); +#endif r->infinity = a->infinity; r->x = a->x; r->y = a->y; r->z = a->z; secp256k1_fe_normalize_weak(&r->y); secp256k1_fe_negate(&r->y, &r->y, 1); +#ifdef VERIFY + secp256k1_gej_verify(r); +#endif } static int secp256k1_gej_is_infinity(const secp256k1_gej *a) { +#ifdef VERIFY + secp256k1_gej_verify(a); +#endif return a->infinity; } static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) { secp256k1_fe y2, x3; +#ifdef VERIFY + secp256k1_ge_verify(a); +#endif if (a->infinity) { return 0; } @@ -291,6 +399,9 @@ static SECP256K1_INLINE void secp256k1_gej_double(secp256k1_gej *r, const secp25 /* Operations: 3 mul, 4 sqr, 8 add/half/mul_int/negate */ secp256k1_fe l, s, t; +#ifdef VERIFY + secp256k1_gej_verify(a); +#endif r->infinity = a->infinity; /* Formula used: @@ -317,6 +428,9 @@ static SECP256K1_INLINE void secp256k1_gej_double(secp256k1_gej *r, const secp25 secp256k1_fe_mul(&r->y, &t, &l); /* Y3 = L*(X3 + T) (1) */ secp256k1_fe_add(&r->y, &s); /* Y3 = L*(X3 + T) + S^2 (2) */ secp256k1_fe_negate(&r->y, &r->y, 2); /* Y3 = -(L*(X3 + T) + S^2) (3) */ +#ifdef VERIFY + secp256k1_gej_verify(r); +#endif } static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { @@ -330,6 +444,9 @@ static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, s * the infinity flag even though the point doubles to infinity, and the result * point will be gibberish (z = 0 but infinity = 0). */ +#ifdef VERIFY + secp256k1_gej_verify(a); +#endif if (a->infinity) { secp256k1_gej_set_infinity(r); if (rzr != NULL) { @@ -344,12 +461,19 @@ static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, s } secp256k1_gej_double(r, a); +#ifdef VERIFY + secp256k1_gej_verify(r); +#endif } static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) { /* 12 mul, 4 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */ secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, h2, h3, t; +#ifdef VERIFY + secp256k1_gej_verify(a); + secp256k1_gej_verify(b); +#endif if (a->infinity) { VERIFY_CHECK(rzr == NULL); *r = *b; @@ -404,11 +528,18 @@ static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, cons secp256k1_fe_mul(&r->y, &t, &i); secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_add(&r->y, &h3); +#ifdef VERIFY + secp256k1_gej_verify(r); +#endif } static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) { /* 8 mul, 3 sqr, 13 add/negate/normalize_weak/normalizes_to_zero (ignoring special cases) */ secp256k1_fe z12, u1, u2, s1, s2, h, i, h2, h3, t; +#ifdef VERIFY + secp256k1_gej_verify(a); + secp256k1_ge_verify(b); +#endif if (a->infinity) { VERIFY_CHECK(rzr == NULL); secp256k1_gej_set_ge(r, b); @@ -461,12 +592,20 @@ static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, c secp256k1_fe_mul(&r->y, &t, &i); secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_add(&r->y, &h3); +#ifdef VERIFY + secp256k1_gej_verify(r); + if (rzr != NULL) secp256k1_fe_verify(rzr); +#endif } static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) { /* 9 mul, 3 sqr, 13 add/negate/normalize_weak/normalizes_to_zero (ignoring special cases) */ secp256k1_fe az, z12, u1, u2, s1, s2, h, i, h2, h3, t; +#ifdef VERIFY + secp256k1_ge_verify(b); + secp256k1_fe_verify(bzinv); +#endif if (a->infinity) { secp256k1_fe bzinv2, bzinv3; r->infinity = b->infinity; @@ -525,6 +664,9 @@ static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe_mul(&r->y, &t, &i); secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_add(&r->y, &h3); +#ifdef VERIFY + secp256k1_gej_verify(r); +#endif } @@ -533,6 +675,10 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr; secp256k1_fe m_alt, rr_alt; int degenerate; +#ifdef VERIFY + secp256k1_gej_verify(a); + secp256k1_ge_verify(b); +#endif VERIFY_CHECK(!b->infinity); VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); @@ -658,21 +804,34 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const * We have degenerate = false, r->z = (y1 + y2) * Z. * Then r->infinity = ((y1 + y2)Z == 0) = (y1 == -y2) = false. */ r->infinity = secp256k1_fe_normalizes_to_zero(&r->z); +#ifdef VERIFY + secp256k1_gej_verify(r); +#endif } static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) { /* Operations: 4 mul, 1 sqr */ secp256k1_fe zz; +#ifdef VERIFY + secp256k1_gej_verify(r); + secp256k1_fe_verify(s); +#endif VERIFY_CHECK(!secp256k1_fe_is_zero(s)); secp256k1_fe_sqr(&zz, s); secp256k1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */ secp256k1_fe_mul(&r->y, &r->y, &zz); secp256k1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */ secp256k1_fe_mul(&r->z, &r->z, s); /* r->z *= s */ +#ifdef VERIFY + secp256k1_gej_verify(r); +#endif } static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) { secp256k1_fe x, y; +#ifdef VERIFY + secp256k1_ge_verify(a); +#endif VERIFY_CHECK(!a->infinity); x = a->x; secp256k1_fe_normalize(&x); @@ -686,14 +845,24 @@ static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storag secp256k1_fe_from_storage(&r->x, &a->x); secp256k1_fe_from_storage(&r->y, &a->y); r->infinity = 0; +#ifdef VERIFY + secp256k1_ge_verify(r); +#endif } static SECP256K1_INLINE void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag) { +#ifdef VERIFY + secp256k1_gej_verify(r); + secp256k1_gej_verify(a); +#endif secp256k1_fe_cmov(&r->x, &a->x, flag); secp256k1_fe_cmov(&r->y, &a->y, flag); secp256k1_fe_cmov(&r->z, &a->z, flag); r->infinity ^= (r->infinity ^ a->infinity) & flag; +#ifdef VERIFY + secp256k1_gej_verify(r); +#endif } static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) { @@ -703,7 +872,13 @@ static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) { *r = *a; +#ifdef VERIFY + secp256k1_ge_verify(a); +#endif secp256k1_fe_mul(&r->x, &r->x, &secp256k1_const_beta); +#ifdef VERIFY + secp256k1_ge_verify(r); +#endif } static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) { @@ -711,6 +886,9 @@ static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) { secp256k1_gej out; int i; +#ifdef VERIFY + secp256k1_ge_verify(ge); +#endif /* A very simple EC multiplication ladder that avoids a dependency on ecmult. */ secp256k1_gej_set_infinity(&out); for (i = 0; i < 32; ++i) { From 0a2e0b2ae456c7ae60e92ddc354071f21fb6aa62 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 9 May 2023 12:46:00 -0400 Subject: [PATCH 5/6] Make secp256k1_{fe,ge,gej}_verify work as no-op if non-VERIFY --- src/field.h | 4 +- src/field_10x26_impl.h | 9 ++-- src/field_5x52_impl.h | 9 ++-- src/group.h | 6 +-- src/group_impl.h | 106 +++-------------------------------------- 5 files changed, 15 insertions(+), 119 deletions(-) diff --git a/src/field.h b/src/field.h index 62dc0f3ae04da..dca75aac10912 100644 --- a/src/field.h +++ b/src/field.h @@ -143,9 +143,7 @@ static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m); /** Determine whether a is a square (modulo p). */ static int secp256k1_fe_is_square_var(const secp256k1_fe *a); -#ifdef VERIFY -/** Check invariants on a field element. */ +/** Check invariants on a field element (no-op unless VERIFY is enabled). */ static void secp256k1_fe_verify(const secp256k1_fe *a); -#endif #endif /* SECP256K1_FIELD_H */ diff --git a/src/field_10x26_impl.h b/src/field_10x26_impl.h index 6b58380f98d9e..c164711757fb8 100644 --- a/src/field_10x26_impl.h +++ b/src/field_10x26_impl.h @@ -21,8 +21,8 @@ * - 2*M*(2^26-1) is the max (inclusive) of the remaining limbs */ -#ifdef VERIFY static void secp256k1_fe_verify(const secp256k1_fe *a) { +#ifdef VERIFY const uint32_t *d = a->n; int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; r &= (d[0] <= 0x3FFFFFFUL * m); @@ -47,8 +47,9 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) { } } VERIFY_CHECK(r == 1); -} #endif + (void)a; +} static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m) { VERIFY_CHECK(m >= 0); @@ -458,9 +459,7 @@ SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { } SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { -#ifdef VERIFY secp256k1_fe_verify(a); -#endif r->n[0] += a->n[0]; r->n[1] += a->n[1]; r->n[2] += a->n[2]; @@ -479,11 +478,9 @@ SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_f } SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) { -#ifdef VERIFY secp256k1_fe_verify(r); VERIFY_CHECK(a >= 0); VERIFY_CHECK(a <= 0x7FFF); -#endif r->n[0] += a; #ifdef VERIFY r->magnitude += 1; diff --git a/src/field_5x52_impl.h b/src/field_5x52_impl.h index 0e403f32a627f..9b9794c099760 100644 --- a/src/field_5x52_impl.h +++ b/src/field_5x52_impl.h @@ -33,8 +33,8 @@ * 0 or 1, and its value is already reduced modulo the order of the field. */ -#ifdef VERIFY static void secp256k1_fe_verify(const secp256k1_fe *a) { +#ifdef VERIFY const uint64_t *d = a->n; int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; /* secp256k1 'p' value defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ @@ -52,8 +52,9 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) { } } VERIFY_CHECK(r == 1); -} #endif + (void)a; +} static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m) { VERIFY_CHECK(m >= 0); @@ -422,11 +423,9 @@ SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { } SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) { -#ifdef VERIFY secp256k1_fe_verify(r); VERIFY_CHECK(a >= 0); VERIFY_CHECK(a <= 0x7FFF); -#endif r->n[0] += a; #ifdef VERIFY r->magnitude += 1; @@ -436,9 +435,7 @@ SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) { } SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { -#ifdef VERIFY secp256k1_fe_verify(a); -#endif r->n[0] += a->n[0]; r->n[1] += a->n[1]; r->n[2] += a->n[2]; diff --git a/src/group.h b/src/group.h index 14cdb4062d22e..77ad7435f84cd 100644 --- a/src/group.h +++ b/src/group.h @@ -164,12 +164,10 @@ static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b); */ static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge); -#ifdef VERIFY -/** Check invariants on an affine group element. */ +/** Check invariants on an affine group element (no-op unless VERIFY is enabled). */ static void secp256k1_ge_verify(const secp256k1_ge *a); -/** Check invariants on a Jacobian group element. */ +/** Check invariants on a Jacobian group element (no-op unless VERIFY is enabled). */ static void secp256k1_gej_verify(const secp256k1_gej *a); -#endif #endif /* SECP256K1_GROUP_H */ diff --git a/src/group_impl.h b/src/group_impl.h index 86be92d59deda..48357a1c5db8a 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -73,78 +73,66 @@ static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G; #endif /* End of section generated by sage/gen_exhaustive_groups.sage. */ -#ifdef VERIFY static void secp256k1_ge_verify(const secp256k1_ge *a) { +#ifdef VERIFY secp256k1_fe_verify(&a->x); secp256k1_fe_verify(&a->y); VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); +#endif + (void)a; } static void secp256k1_gej_verify(const secp256k1_gej *a) { +#ifdef VERIFY secp256k1_fe_verify(&a->x); secp256k1_fe_verify(&a->y); secp256k1_fe_verify(&a->z); VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); -} #endif + (void)a; +} static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) { secp256k1_fe zi2; secp256k1_fe zi3; -#ifdef VERIFY /* Do not call secp256k1_ge_verify, as we do not require a->z to be initialized. */ secp256k1_fe_verify(&a->x); secp256k1_fe_verify(&a->y); secp256k1_fe_verify(zi); -#endif VERIFY_CHECK(!a->infinity); secp256k1_fe_sqr(&zi2, zi); secp256k1_fe_mul(&zi3, &zi2, zi); secp256k1_fe_mul(&r->x, &a->x, &zi2); secp256k1_fe_mul(&r->y, &a->y, &zi3); r->infinity = a->infinity; -#ifdef VERIFY secp256k1_ge_verify(r); -#endif } static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) { -#ifdef VERIFY secp256k1_fe_verify(x); secp256k1_fe_verify(y); -#endif r->infinity = 0; r->x = *x; r->y = *y; -#ifdef VERIFY secp256k1_ge_verify(r); -#endif } static int secp256k1_ge_is_infinity(const secp256k1_ge *a) { -#ifdef VERIFY secp256k1_ge_verify(a); -#endif return a->infinity; } static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) { -#ifdef VERIFY secp256k1_ge_verify(a); -#endif *r = *a; secp256k1_fe_normalize_weak(&r->y); secp256k1_fe_negate(&r->y, &r->y, 1); -#ifdef VERIFY secp256k1_ge_verify(r); -#endif } static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) { secp256k1_fe z2, z3; -#ifdef VERIFY secp256k1_gej_verify(a); -#endif r->infinity = a->infinity; secp256k1_fe_inv(&a->z, &a->z); secp256k1_fe_sqr(&z2, &a->z); @@ -154,16 +142,12 @@ static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) { secp256k1_fe_set_int(&a->z, 1); r->x = a->x; r->y = a->y; -#ifdef VERIFY secp256k1_ge_verify(r); -#endif } static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { secp256k1_fe z2, z3; -#ifdef VERIFY secp256k1_gej_verify(a); -#endif if (secp256k1_gej_is_infinity(a)) { secp256k1_ge_set_infinity(r); return; @@ -176,9 +160,7 @@ static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { secp256k1_fe_mul(&a->y, &a->y, &z3); secp256k1_fe_set_int(&a->z, 1); secp256k1_ge_set_xy(r, &a->x, &a->y); -#ifdef VERIFY secp256k1_ge_verify(r); -#endif } static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len) { @@ -187,9 +169,7 @@ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a size_t last_i = SIZE_MAX; for (i = 0; i < len; i++) { -#ifdef VERIFY secp256k1_gej_verify(&a[i]); -#endif if (a[i].infinity) { secp256k1_ge_set_infinity(&r[i]); } else { @@ -223,9 +203,7 @@ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a if (!a[i].infinity) { secp256k1_ge_set_gej_zinv(&r[i], &a[i], &r[i].x); } -#ifdef VERIFY secp256k1_ge_verify(&r[i]); -#endif } } @@ -234,11 +212,9 @@ static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const se secp256k1_fe zs; if (len > 0) { -#ifdef VERIFY /* Verify inputs a[len-1] and zr[len-1]. */ secp256k1_ge_verify(&a[i]); secp256k1_fe_verify(&zr[i]); -#endif /* Ensure all y values are in weak normal form for fast negation of points */ secp256k1_fe_normalize_weak(&a[i].y); zs = zr[i]; @@ -246,11 +222,9 @@ static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const se /* Work our way backwards, using the z-ratios to scale the x/y values. */ while (i > 0) { secp256k1_gej tmpa; -#ifdef VERIFY /* Verify all inputs a[i] and zr[i]. */ secp256k1_fe_verify(&zr[i]); secp256k1_ge_verify(&a[i]); -#endif if (i != len - 1) { secp256k1_fe_mul(&zs, &zs, &zr[i]); } @@ -259,10 +233,8 @@ static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const se tmpa.y = a[i].y; tmpa.infinity = 0; secp256k1_ge_set_gej_zinv(&a[i], &tmpa, &zs); -#ifdef VERIFY /* Verify the output a[i]. */ secp256k1_ge_verify(&a[i]); -#endif } } } @@ -272,18 +244,14 @@ static void secp256k1_gej_set_infinity(secp256k1_gej *r) { secp256k1_fe_clear(&r->x); secp256k1_fe_clear(&r->y); secp256k1_fe_clear(&r->z); -#ifdef VERIFY secp256k1_gej_verify(r); -#endif } static void secp256k1_ge_set_infinity(secp256k1_ge *r) { r->infinity = 1; secp256k1_fe_clear(&r->x); secp256k1_fe_clear(&r->y); -#ifdef VERIFY secp256k1_ge_verify(r); -#endif } static void secp256k1_gej_clear(secp256k1_gej *r) { @@ -302,9 +270,7 @@ static void secp256k1_ge_clear(secp256k1_ge *r) { static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) { secp256k1_fe x2, x3; int ret; -#ifdef VERIFY secp256k1_fe_verify(x); -#endif r->x = *x; secp256k1_fe_sqr(&x2, x); secp256k1_fe_mul(&x3, x, &x2); @@ -315,31 +281,23 @@ static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int o if (secp256k1_fe_is_odd(&r->y) != odd) { secp256k1_fe_negate(&r->y, &r->y, 1); } -#ifdef VERIFY secp256k1_ge_verify(r); -#endif return ret; } static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) { -#ifdef VERIFY secp256k1_ge_verify(a); -#endif r->infinity = a->infinity; r->x = a->x; r->y = a->y; secp256k1_fe_set_int(&r->z, 1); -#ifdef VERIFY secp256k1_gej_verify(r); -#endif } static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b) { secp256k1_gej tmp; -#ifdef VERIFY secp256k1_gej_verify(b); secp256k1_gej_verify(a); -#endif secp256k1_gej_neg(&tmp, a); secp256k1_gej_add_var(&tmp, &tmp, b, NULL); return secp256k1_gej_is_infinity(&tmp); @@ -347,10 +305,8 @@ static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b) static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) { secp256k1_fe r, r2; -#ifdef VERIFY secp256k1_fe_verify(x); secp256k1_gej_verify(a); -#endif VERIFY_CHECK(!a->infinity); secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x); r2 = a->x; secp256k1_fe_normalize_weak(&r2); @@ -358,32 +314,24 @@ static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) } static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) { -#ifdef VERIFY secp256k1_gej_verify(a); -#endif r->infinity = a->infinity; r->x = a->x; r->y = a->y; r->z = a->z; secp256k1_fe_normalize_weak(&r->y); secp256k1_fe_negate(&r->y, &r->y, 1); -#ifdef VERIFY secp256k1_gej_verify(r); -#endif } static int secp256k1_gej_is_infinity(const secp256k1_gej *a) { -#ifdef VERIFY secp256k1_gej_verify(a); -#endif return a->infinity; } static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) { secp256k1_fe y2, x3; -#ifdef VERIFY secp256k1_ge_verify(a); -#endif if (a->infinity) { return 0; } @@ -399,9 +347,7 @@ static SECP256K1_INLINE void secp256k1_gej_double(secp256k1_gej *r, const secp25 /* Operations: 3 mul, 4 sqr, 8 add/half/mul_int/negate */ secp256k1_fe l, s, t; -#ifdef VERIFY secp256k1_gej_verify(a); -#endif r->infinity = a->infinity; /* Formula used: @@ -428,9 +374,7 @@ static SECP256K1_INLINE void secp256k1_gej_double(secp256k1_gej *r, const secp25 secp256k1_fe_mul(&r->y, &t, &l); /* Y3 = L*(X3 + T) (1) */ secp256k1_fe_add(&r->y, &s); /* Y3 = L*(X3 + T) + S^2 (2) */ secp256k1_fe_negate(&r->y, &r->y, 2); /* Y3 = -(L*(X3 + T) + S^2) (3) */ -#ifdef VERIFY secp256k1_gej_verify(r); -#endif } static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { @@ -444,9 +388,7 @@ static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, s * the infinity flag even though the point doubles to infinity, and the result * point will be gibberish (z = 0 but infinity = 0). */ -#ifdef VERIFY secp256k1_gej_verify(a); -#endif if (a->infinity) { secp256k1_gej_set_infinity(r); if (rzr != NULL) { @@ -461,19 +403,15 @@ static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, s } secp256k1_gej_double(r, a); -#ifdef VERIFY secp256k1_gej_verify(r); -#endif } static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) { /* 12 mul, 4 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */ secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, h2, h3, t; -#ifdef VERIFY secp256k1_gej_verify(a); secp256k1_gej_verify(b); -#endif if (a->infinity) { VERIFY_CHECK(rzr == NULL); *r = *b; @@ -528,18 +466,14 @@ static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, cons secp256k1_fe_mul(&r->y, &t, &i); secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_add(&r->y, &h3); -#ifdef VERIFY secp256k1_gej_verify(r); -#endif } static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) { /* 8 mul, 3 sqr, 13 add/negate/normalize_weak/normalizes_to_zero (ignoring special cases) */ secp256k1_fe z12, u1, u2, s1, s2, h, i, h2, h3, t; -#ifdef VERIFY secp256k1_gej_verify(a); secp256k1_ge_verify(b); -#endif if (a->infinity) { VERIFY_CHECK(rzr == NULL); secp256k1_gej_set_ge(r, b); @@ -592,20 +526,16 @@ static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, c secp256k1_fe_mul(&r->y, &t, &i); secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_add(&r->y, &h3); -#ifdef VERIFY secp256k1_gej_verify(r); if (rzr != NULL) secp256k1_fe_verify(rzr); -#endif } static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) { /* 9 mul, 3 sqr, 13 add/negate/normalize_weak/normalizes_to_zero (ignoring special cases) */ secp256k1_fe az, z12, u1, u2, s1, s2, h, i, h2, h3, t; -#ifdef VERIFY secp256k1_ge_verify(b); secp256k1_fe_verify(bzinv); -#endif if (a->infinity) { secp256k1_fe bzinv2, bzinv3; r->infinity = b->infinity; @@ -664,9 +594,7 @@ static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe_mul(&r->y, &t, &i); secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_add(&r->y, &h3); -#ifdef VERIFY secp256k1_gej_verify(r); -#endif } @@ -675,10 +603,8 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr; secp256k1_fe m_alt, rr_alt; int degenerate; -#ifdef VERIFY secp256k1_gej_verify(a); secp256k1_ge_verify(b); -#endif VERIFY_CHECK(!b->infinity); VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); @@ -804,34 +730,26 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const * We have degenerate = false, r->z = (y1 + y2) * Z. * Then r->infinity = ((y1 + y2)Z == 0) = (y1 == -y2) = false. */ r->infinity = secp256k1_fe_normalizes_to_zero(&r->z); -#ifdef VERIFY secp256k1_gej_verify(r); -#endif } static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) { /* Operations: 4 mul, 1 sqr */ secp256k1_fe zz; -#ifdef VERIFY secp256k1_gej_verify(r); secp256k1_fe_verify(s); -#endif VERIFY_CHECK(!secp256k1_fe_is_zero(s)); secp256k1_fe_sqr(&zz, s); secp256k1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */ secp256k1_fe_mul(&r->y, &r->y, &zz); secp256k1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */ secp256k1_fe_mul(&r->z, &r->z, s); /* r->z *= s */ -#ifdef VERIFY secp256k1_gej_verify(r); -#endif } static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) { secp256k1_fe x, y; -#ifdef VERIFY secp256k1_ge_verify(a); -#endif VERIFY_CHECK(!a->infinity); x = a->x; secp256k1_fe_normalize(&x); @@ -845,24 +763,18 @@ static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storag secp256k1_fe_from_storage(&r->x, &a->x); secp256k1_fe_from_storage(&r->y, &a->y); r->infinity = 0; -#ifdef VERIFY secp256k1_ge_verify(r); -#endif } static SECP256K1_INLINE void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag) { -#ifdef VERIFY secp256k1_gej_verify(r); secp256k1_gej_verify(a); -#endif secp256k1_fe_cmov(&r->x, &a->x, flag); secp256k1_fe_cmov(&r->y, &a->y, flag); secp256k1_fe_cmov(&r->z, &a->z, flag); r->infinity ^= (r->infinity ^ a->infinity) & flag; -#ifdef VERIFY secp256k1_gej_verify(r); -#endif } static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) { @@ -872,13 +784,9 @@ static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) { *r = *a; -#ifdef VERIFY secp256k1_ge_verify(a); -#endif secp256k1_fe_mul(&r->x, &r->x, &secp256k1_const_beta); -#ifdef VERIFY secp256k1_ge_verify(r); -#endif } static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) { @@ -886,9 +794,7 @@ static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) { secp256k1_gej out; int i; -#ifdef VERIFY secp256k1_ge_verify(ge); -#endif /* A very simple EC multiplication ladder that avoids a dependency on ecmult. */ secp256k1_gej_set_infinity(&out); for (i = 0; i < 32; ++i) { From bbc834467c5d14e3e53744211e7c4fa9d8fabe41 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 9 May 2023 13:10:56 -0400 Subject: [PATCH 6/6] Avoid secp256k1_ge_set_gej_zinv with uninitialized z --- src/group_impl.h | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/group_impl.h b/src/group_impl.h index 48357a1c5db8a..f1b62e3689127 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -92,12 +92,26 @@ static void secp256k1_gej_verify(const secp256k1_gej *a) { (void)a; } +/* Set r to the affine coordinates of Jacobian point (a.x, a.y, 1/zi). */ static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) { secp256k1_fe zi2; secp256k1_fe zi3; - /* Do not call secp256k1_ge_verify, as we do not require a->z to be initialized. */ - secp256k1_fe_verify(&a->x); - secp256k1_fe_verify(&a->y); + secp256k1_gej_verify(a); + secp256k1_fe_verify(zi); + VERIFY_CHECK(!a->infinity); + secp256k1_fe_sqr(&zi2, zi); + secp256k1_fe_mul(&zi3, &zi2, zi); + secp256k1_fe_mul(&r->x, &a->x, &zi2); + secp256k1_fe_mul(&r->y, &a->y, &zi3); + r->infinity = a->infinity; + secp256k1_ge_verify(r); +} + +/* Set r to the affine coordinates of Jacobian point (a.x, a.y, 1/zi). */ +static void secp256k1_ge_set_ge_zinv(secp256k1_ge *r, const secp256k1_ge *a, const secp256k1_fe *zi) { + secp256k1_fe zi2; + secp256k1_fe zi3; + secp256k1_ge_verify(a); secp256k1_fe_verify(zi); VERIFY_CHECK(!a->infinity); secp256k1_fe_sqr(&zi2, zi); @@ -221,7 +235,6 @@ static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const se /* Work our way backwards, using the z-ratios to scale the x/y values. */ while (i > 0) { - secp256k1_gej tmpa; /* Verify all inputs a[i] and zr[i]. */ secp256k1_fe_verify(&zr[i]); secp256k1_ge_verify(&a[i]); @@ -229,10 +242,7 @@ static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const se secp256k1_fe_mul(&zs, &zs, &zr[i]); } i--; - tmpa.x = a[i].x; - tmpa.y = a[i].y; - tmpa.infinity = 0; - secp256k1_ge_set_gej_zinv(&a[i], &tmpa, &zs); + secp256k1_ge_set_ge_zinv(&a[i], &a[i], &zs); /* Verify the output a[i]. */ secp256k1_ge_verify(&a[i]); }