From 18644909c93953f226ef8e0ae5bebfa7dcaa666b Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Sat, 8 Aug 2020 03:42:30 +0000 Subject: [PATCH 1/5] Clean up infinity handling, make x/y/z always initialized for infinity. --- src/ecmult_impl.h | 9 +++++---- src/group_impl.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h index 057a69cf73..d782b15933 100644 --- a/src/ecmult_impl.h +++ b/src/ecmult_impl.h @@ -81,6 +81,7 @@ * the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will * contain prej[0].z / a.z. The other zr[i] values = prej[i].z / prej[i-1].z. * Prej's Z values are undefined, except for the last value. + * 'a' cannot be infinity. */ static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, secp256k1_fe *zr, const secp256k1_gej *a) { secp256k1_gej d; @@ -97,13 +98,13 @@ static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, sec */ d_ge.x = d.x; d_ge.y = d.y; - d_ge.infinity = 0; + d_ge.infinity = d.infinity; secp256k1_ge_set_gej_zinv(&a_ge, a, &d.z); prej[0].x = a_ge.x; prej[0].y = a_ge.y; prej[0].z = a->z; - prej[0].infinity = 0; + prej[0].infinity = a->infinity; zr[0] = d.z; for (i = 1; i < n; i++) { @@ -164,13 +165,13 @@ static void secp256k1_ecmult_odd_multiples_table_storage_var(const int n, secp25 */ d_ge.x = d.x; d_ge.y = d.y; - d_ge.infinity = 0; + d_ge.infinity = d.infinity; secp256k1_ge_set_gej_zinv(&p_ge, a, &d.z); pj.x = p_ge.x; pj.y = p_ge.y; pj.z = a->z; - pj.infinity = 0; + pj.infinity = p_ge.infinity; for (i = 0; i < (n - 1); i++) { secp256k1_fe_normalize_var(&pj.y); diff --git a/src/group_impl.h b/src/group_impl.h index a5fbc91a0f..c260ae6657 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -316,7 +316,7 @@ static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, s * point will be gibberish (z = 0 but infinity = 0). */ if (a->infinity) { - r->infinity = 1; + secp256k1_gej_set_infinity(r); if (rzr != NULL) { secp256k1_fe_set_int(rzr, 1); } From 020094ec1ecfe452916f8665b89747a6aba4ef06 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Sat, 8 Aug 2020 03:52:34 +0000 Subject: [PATCH 2/5] 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 Q. It never was constant time in Q (and would be a little complicated to make constant time in Q). If it was later made constant time in Q 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 | 2 +- src/ecmult_const_impl.h | 4 ++++ src/tests_exhaustive.c | 6 ++---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ecmult_const.h b/src/ecmult_const.h index 03bb33257d..484f6d1e91 100644 --- a/src/ecmult_const.h +++ b/src/ecmult_const.h @@ -11,7 +11,7 @@ #include "group.h" /** - * Multiply: R = q*A (in constant-time) + * Multiply: R = q*A (in constant-time for q) * Here `bits` should be set to the maximum bitlength of the _absolute value_ of `q`, plus * one because we internally sometimes add 2 to the number during the WNAF conversion. */ diff --git a/src/ecmult_const_impl.h b/src/ecmult_const_impl.h index bb9511108b..097e47f21c 100644 --- a/src/ecmult_const_impl.h +++ b/src/ecmult_const_impl.h @@ -150,6 +150,10 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons /* build wnaf representation for q. */ int rsize = size; + if (secp256k1_ge_is_infinity(a)) { + secp256k1_gej_set_infinity(r); + return; + } if (size > 128) { rsize = 128; /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */ diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index f4d5b8e176..aadb08b548 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -179,10 +179,8 @@ void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *gr secp256k1_ecmult(&ctx->ecmult_ctx, &tmp, &groupj[r_log], &na, &ng); ge_equals_gej(&group[(i * r_log + j) % EXHAUSTIVE_TEST_ORDER], &tmp); - if (i > 0) { - secp256k1_ecmult_const(&tmp, &group[i], &ng, 256); - ge_equals_gej(&group[(i * j) % EXHAUSTIVE_TEST_ORDER], &tmp); - } + secp256k1_ecmult_const(&tmp, &group[i], &ng, 256); + ge_equals_gej(&group[(i * j) % EXHAUSTIVE_TEST_ORDER], &tmp); } } } From c8739ee12a2d6611c0269e4e090339bb11b0f28a Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 1 Sep 2020 16:33:22 -0700 Subject: [PATCH 3/5] Expose secp256k1_fe_verify to other modules Also define it even when VERIFY is not set (as a no-op), to avoid conditions when calling it. --- src/field.h | 3 +++ src/field_10x26_impl.h | 5 +++-- src/field_5x52_impl.h | 5 +++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/field.h b/src/field.h index aca1fb72c5..03a0e3ac5c 100644 --- a/src/field.h +++ b/src/field.h @@ -131,4 +131,7 @@ static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_f /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/ static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag); +/** Check invariants on a field element (no-op unless VERIFY is enabled). */ +static void secp256k1_fe_verify(const secp256k1_fe *a); + #endif /* SECP256K1_FIELD_H */ diff --git a/src/field_10x26_impl.h b/src/field_10x26_impl.h index 651500ee8e..01a65f9bed 100644 --- a/src/field_10x26_impl.h +++ b/src/field_10x26_impl.h @@ -10,8 +10,8 @@ #include "util.h" #include "field.h" -#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); @@ -36,8 +36,9 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) { } } VERIFY_CHECK(r == 1); -} #endif + (void)a; +} static void secp256k1_fe_normalize(secp256k1_fe *r) { uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], diff --git a/src/field_5x52_impl.h b/src/field_5x52_impl.h index 71a38f915b..d7054ecc8c 100644 --- a/src/field_5x52_impl.h +++ b/src/field_5x52_impl.h @@ -28,8 +28,8 @@ * output. */ -#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. */ @@ -47,8 +47,9 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) { } } VERIFY_CHECK(r == 1); -} #endif + (void)a; +} static void secp256k1_fe_normalize(secp256k1_fe *r) { uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; From e5f1b88a4e8bc8ddd61f87514ddaeb119611c431 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 1 Sep 2020 18:15:21 -0700 Subject: [PATCH 4/5] Always initialize output coordinates in ge_set_[all_]gej_var --- src/group_impl.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/group_impl.h b/src/group_impl.h index c260ae6657..cc6c2ab516 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -101,10 +101,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; - r->infinity = a->infinity; - 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); @@ -149,9 +150,10 @@ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a r[last_i].x = u; for (i = 0; i < len; i++) { - r[i].infinity = a[i].infinity; if (!a[i].infinity) { secp256k1_ge_set_gej_zinv(&r[i], &a[i], &r[i].x); + } else { + secp256k1_ge_set_infinity(&r[i]); } } } From 666d210542b84b19a45438483ffb4a4610b58f47 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 1 Sep 2020 17:59:51 -0700 Subject: [PATCH 5/5] Add invariant checking to group elements --- src/group.h | 6 ++++ src/group_impl.h | 81 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/src/group.h b/src/group.h index 36e39ecf0f..a59031b36e 100644 --- a/src/group.h +++ b/src/group.h @@ -148,4 +148,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); +/** 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 (no-op unless VERIFY is enabled). */ +static void secp256k1_gej_verify(const secp256k1_gej *a); + #endif /* SECP256K1_GROUP_H */ diff --git a/src/group_impl.h b/src/group_impl.h index cc6c2ab516..691f88ec92 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -60,34 +60,63 @@ static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 7); #endif +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; + secp256k1_gej_verify(a); + secp256k1_fe_verify(zi); 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); } static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) { + secp256k1_fe_verify(x); + secp256k1_fe_verify(y); r->infinity = 0; r->x = *x; r->y = *y; + secp256k1_ge_verify(r); } static int secp256k1_ge_is_infinity(const secp256k1_ge *a) { + secp256k1_ge_verify(a); return a->infinity; } static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) { + secp256k1_ge_verify(a); *r = *a; secp256k1_fe_normalize_weak(&r->y); secp256k1_fe_negate(&r->y, &r->y, 1); + secp256k1_ge_verify(r); } static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) { secp256k1_fe z2, z3; + secp256k1_gej_verify(a); r->infinity = a->infinity; secp256k1_fe_inv(&a->z, &a->z); secp256k1_fe_sqr(&z2, &a->z); @@ -97,10 +126,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; + secp256k1_ge_verify(r); } static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { secp256k1_fe z2, z3; + secp256k1_gej_verify(a); if (secp256k1_gej_is_infinity(a)) { secp256k1_ge_set_infinity(r); return; @@ -114,6 +145,7 @@ static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { secp256k1_fe_set_int(&a->z, 1); r->x = a->x; r->y = a->y; + secp256k1_ge_verify(r); } static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len) { @@ -122,6 +154,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++) { + secp256k1_gej_verify(&a[i]); if (!a[i].infinity) { /* Use destination's x coordinates as scratch space */ if (last_i == SIZE_MAX) { @@ -155,6 +188,7 @@ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a } else { secp256k1_ge_set_infinity(&r[i]); } + secp256k1_ge_verify(&r[i]); } } @@ -163,6 +197,8 @@ static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp secp256k1_fe zs; if (len > 0) { + secp256k1_gej_verify(&a[i]); + secp256k1_fe_verify(&zr[i]); /* The z of the final point gives us the "global Z" for the table. */ r[i].x = a[i].x; r[i].y = a[i].y; @@ -170,6 +206,7 @@ static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp secp256k1_fe_normalize_weak(&r[i].y); *globalz = a[i].z; r[i].infinity = 0; + secp256k1_ge_verify(&r[i]); zs = zr[i]; /* Work our way backwards, using the z-ratios to scale the x/y values. */ @@ -188,12 +225,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); + secp256k1_gej_verify(r); } static void secp256k1_ge_set_infinity(secp256k1_ge *r) { r->infinity = 1; secp256k1_fe_clear(&r->x); secp256k1_fe_clear(&r->y); + secp256k1_ge_verify(r); } static void secp256k1_gej_clear(secp256k1_gej *r) { @@ -201,25 +240,32 @@ static void secp256k1_gej_clear(secp256k1_gej *r) { secp256k1_fe_clear(&r->x); secp256k1_fe_clear(&r->y); secp256k1_fe_clear(&r->z); + secp256k1_gej_verify(r); } static void secp256k1_ge_clear(secp256k1_ge *r) { r->infinity = 0; secp256k1_fe_clear(&r->x); secp256k1_fe_clear(&r->y); + secp256k1_ge_verify(r); } static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) { secp256k1_fe x2, x3; + int ret; + secp256k1_fe_verify(x); r->x = *x; secp256k1_fe_sqr(&x2, x); secp256k1_fe_mul(&x3, x, &x2); r->infinity = 0; secp256k1_fe_add(&x3, &secp256k1_fe_const_b); - return secp256k1_fe_sqrt(&r->y, &x3); + ret = secp256k1_fe_sqrt(&r->y, &x3); + secp256k1_ge_verify(r); + return ret; } static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) { + secp256k1_fe_verify(x); if (!secp256k1_ge_set_xquad(r, x)) { return 0; } @@ -227,19 +273,24 @@ 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); } + secp256k1_ge_verify(r); return 1; } static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) { + secp256k1_ge_verify(a); r->infinity = a->infinity; r->x = a->x; r->y = a->y; secp256k1_fe_set_int(&r->z, 1); + secp256k1_gej_verify(r); } static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) { secp256k1_fe r, r2; + secp256k1_fe_verify(x); + secp256k1_gej_verify(a); VERIFY_CHECK(!a->infinity); secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x); r2 = a->x; secp256k1_fe_normalize_weak(&r2); @@ -247,20 +298,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) { + secp256k1_gej_verify(a); 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); + secp256k1_gej_verify(r); } static int secp256k1_gej_is_infinity(const secp256k1_gej *a) { + secp256k1_gej_verify(a); return a->infinity; } static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) { secp256k1_fe y2, x3; + secp256k1_ge_verify(a); if (a->infinity) { return 0; } @@ -281,6 +336,7 @@ static SECP256K1_INLINE void secp256k1_gej_double(secp256k1_gej *r, const secp25 * mainly because it requires more normalizations. */ secp256k1_fe t1,t2,t3,t4; + secp256k1_gej_verify(a); r->infinity = a->infinity; @@ -304,6 +360,7 @@ static SECP256K1_INLINE void secp256k1_gej_double(secp256k1_gej *r, const secp25 secp256k1_fe_mul(&r->y, &t1, &t3); /* Y' = 36*X^3*Y^2 - 27*X^6 (1) */ secp256k1_fe_negate(&t2, &t4, 2); /* T2 = -8*Y^4 (3) */ secp256k1_fe_add(&r->y, &t2); /* Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4) */ + secp256k1_gej_verify(r); } static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { @@ -317,6 +374,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). */ + secp256k1_gej_verify(a); if (a->infinity) { secp256k1_gej_set_infinity(r); if (rzr != NULL) { @@ -338,6 +396,8 @@ static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, cons /* Operations: 12 mul, 4 sqr, 2 normalize, 12 mul_int/add/negate */ secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; + secp256k1_gej_verify(a); + secp256k1_gej_verify(b); if (a->infinity) { VERIFY_CHECK(rzr == NULL); *r = *b; @@ -385,11 +445,14 @@ static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, cons secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); secp256k1_fe_add(&r->y, &h3); + secp256k1_gej_verify(r); } 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, 4 normalize, 12 mul_int/add/negate */ secp256k1_fe z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; + secp256k1_gej_verify(a); + secp256k1_ge_verify(b); if (a->infinity) { VERIFY_CHECK(rzr == NULL); secp256k1_gej_set_ge(r, b); @@ -434,16 +497,20 @@ static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, c secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); secp256k1_fe_add(&r->y, &h3); + secp256k1_gej_verify(r); } 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, 4 normalize, 12 mul_int/add/negate */ secp256k1_fe az, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; + secp256k1_gej_verify(a); + secp256k1_ge_verify(b); if (b->infinity) { *r = *a; return; } + secp256k1_fe_verify(bzinv); if (a->infinity) { secp256k1_fe bzinv2, bzinv3; r->infinity = b->infinity; @@ -490,6 +557,7 @@ static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); secp256k1_fe_add(&r->y, &h3); + secp256k1_gej_verify(r); } @@ -501,6 +569,8 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const int infinity, degenerate; VERIFY_CHECK(!b->infinity); VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); + secp256k1_gej_verify(a); + secp256k1_ge_verify(b); /** In: * Eric Brier and Marc Joye, Weierstrass Elliptic Curves and Side-Channel Attacks. @@ -613,21 +683,26 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_fe_cmov(&r->y, &b->y, a->infinity); secp256k1_fe_cmov(&r->z, &fe_1, a->infinity); r->infinity = infinity; + secp256k1_gej_verify(r); } static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) { /* Operations: 4 mul, 1 sqr */ secp256k1_fe zz; + secp256k1_gej_verify(r); + secp256k1_fe_verify(s); 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 */ + secp256k1_gej_verify(r); } static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) { secp256k1_fe x, y; + secp256k1_ge_verify(a); VERIFY_CHECK(!a->infinity); x = a->x; secp256k1_fe_normalize(&x); @@ -641,6 +716,7 @@ 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; + secp256k1_ge_verify(r); } static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) { @@ -653,13 +729,16 @@ static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) { 0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul, 0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul ); + secp256k1_ge_verify(a); *r = *a; secp256k1_fe_mul(&r->x, &r->x, &beta); + secp256k1_ge_verify(r); } static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) { secp256k1_fe yz; + secp256k1_gej_verify(a); if (a->infinity) { return 0; }