Skip to content

Commit eed599d

Browse files
peterdettmansipa
authored andcommitted
Add _fe_normalizes_to_zero method
1 parent d7174ed commit eed599d

File tree

5 files changed

+71
-15
lines changed

5 files changed

+71
-15
lines changed

src/field.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ static void secp256k1_fe_normalize_weak(secp256k1_fe_t *r);
5454
/** Normalize a field element, without constant-time guarantee. */
5555
static void secp256k1_fe_normalize_var(secp256k1_fe_t *r);
5656

57+
/** Verify whether a field element represents zero i.e. would normalize to a zero value. The field
58+
* implementation may optionally normalize the input, but this should not be relied upon. */
59+
static int secp256k1_fe_normalizes_to_zero(secp256k1_fe_t *r);
60+
5761
/** Set a field element equal to a small integer. Resulting field element is normalized. */
5862
static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a);
5963

src/field_10x26_impl.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ static void secp256k1_fe_normalize_weak(secp256k1_fe_t *r) {
122122
t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL;
123123
t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL;
124124

125+
/* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */
126+
VERIFY_CHECK(t9 >> 23 == 0);
127+
125128
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
126129
r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9;
127130

@@ -187,6 +190,35 @@ static void secp256k1_fe_normalize_var(secp256k1_fe_t *r) {
187190
#endif
188191
}
189192

193+
static int secp256k1_fe_normalizes_to_zero(secp256k1_fe_t *r) {
194+
uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
195+
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
196+
197+
/* Reduce t9 at the start so there will be at most a single carry from the first pass */
198+
uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL;
199+
200+
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
201+
uint32_t z0, z1;
202+
203+
/* The first pass ensures the magnitude is 1, ... */
204+
t0 += x * 0x3D1UL; t1 += (x << 6);
205+
t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; z0 = t0; z1 = t0 ^ 0x3D0UL;
206+
t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; z0 |= t1; z1 &= t1 ^ 0x40UL;
207+
t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; z0 |= t2; z1 &= t2;
208+
t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; z0 |= t3; z1 &= t3;
209+
t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; z0 |= t4; z1 &= t4;
210+
t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; z0 |= t5; z1 &= t5;
211+
t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; z0 |= t6; z1 &= t6;
212+
t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; z0 |= t7; z1 &= t7;
213+
t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; z0 |= t8; z1 &= t8;
214+
z0 |= t9; z1 &= t9 ^ 0x3C00000UL;
215+
216+
/* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */
217+
VERIFY_CHECK(t9 >> 23 == 0);
218+
219+
return (z0 == 0) | (z1 == 0x3FFFFFFUL);
220+
}
221+
190222
SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
191223
r->n[0] = a;
192224
r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0;

src/field_5x52_impl.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,29 @@ static void secp256k1_fe_normalize_var(secp256k1_fe_t *r) {
168168
#endif
169169
}
170170

171+
static int secp256k1_fe_normalizes_to_zero(secp256k1_fe_t *r) {
172+
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
173+
174+
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
175+
uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
176+
177+
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
178+
uint64_t z0, z1;
179+
180+
/* The first pass ensures the magnitude is 1, ... */
181+
t0 += x * 0x1000003D1ULL;
182+
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; z0 = t0; z1 = t0 ^ 0x1000003D0ULL;
183+
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1;
184+
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2;
185+
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3;
186+
z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL;
187+
188+
/* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */
189+
VERIFY_CHECK(t4 >> 49 == 0);
190+
191+
return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL);
192+
}
193+
171194
SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
172195
r->n[0] = a;
173196
r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;

src/field_impl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,12 @@ static int secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen) {
6464
return secp256k1_fe_set_b32(r, tmp);
6565
}
6666

67+
/* TODO Not actually var currently */
6768
SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
6869
secp256k1_fe_t na;
6970
secp256k1_fe_negate(&na, a, 1);
7071
secp256k1_fe_add(&na, b);
71-
secp256k1_fe_normalize_var(&na);
72-
return secp256k1_fe_is_zero(&na);
72+
return secp256k1_fe_normalizes_to_zero(&na);
7373
}
7474

7575
static int secp256k1_fe_sqrt_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {

src/group_impl.h

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,7 @@ static void secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a) {
160160
static int secp256k1_gej_eq_x_var(const secp256k1_fe_t *x, const secp256k1_gej_t *a) {
161161
VERIFY_CHECK(!a->infinity);
162162
secp256k1_fe_t r; secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x);
163-
secp256k1_fe_t r2 = a->x;
164-
secp256k1_fe_normalize_weak(&r);
165-
secp256k1_fe_normalize_weak(&r2);
163+
secp256k1_fe_t r2 = a->x; secp256k1_fe_normalize_weak(&r2);
166164
return secp256k1_fe_equal_var(&r, &r2);
167165
}
168166

@@ -257,16 +255,16 @@ static void secp256k1_gej_add_var(secp256k1_gej_t *r, const secp256k1_gej_t *a,
257255
secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &z12);
258256
secp256k1_fe_t s1; secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z);
259257
secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z);
260-
if (secp256k1_fe_equal_var(&u1, &u2)) {
261-
if (secp256k1_fe_equal_var(&s1, &s2)) {
258+
secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
259+
secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
260+
if (secp256k1_fe_normalizes_to_zero(&h)) {
261+
if (secp256k1_fe_normalizes_to_zero(&i)) {
262262
secp256k1_gej_double_var(r, a);
263263
} else {
264264
r->infinity = 1;
265265
}
266266
return;
267267
}
268-
secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
269-
secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
270268
secp256k1_fe_t i2; secp256k1_fe_sqr(&i2, &i);
271269
secp256k1_fe_t h2; secp256k1_fe_sqr(&h2, &h);
272270
secp256k1_fe_t h3; secp256k1_fe_mul(&h3, &h, &h2);
@@ -296,16 +294,16 @@ static void secp256k1_gej_add_ge_var(secp256k1_gej_t *r, const secp256k1_gej_t *
296294
secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &z12);
297295
secp256k1_fe_t s1 = a->y; secp256k1_fe_normalize_weak(&s1);
298296
secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z);
299-
if (secp256k1_fe_equal_var(&u1, &u2)) {
300-
if (secp256k1_fe_equal_var(&s1, &s2)) {
297+
secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
298+
secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
299+
if (secp256k1_fe_normalizes_to_zero(&h)) {
300+
if (secp256k1_fe_normalizes_to_zero(&i)) {
301301
secp256k1_gej_double_var(r, a);
302302
} else {
303303
r->infinity = 1;
304304
}
305305
return;
306306
}
307-
secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
308-
secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
309307
secp256k1_fe_t i2; secp256k1_fe_sqr(&i2, &i);
310308
secp256k1_fe_t h2; secp256k1_fe_sqr(&h2, &h);
311309
secp256k1_fe_t h3; secp256k1_fe_mul(&h3, &h, &h2);
@@ -360,8 +358,7 @@ static void secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, c
360358
secp256k1_fe_add(&rr, &t); /* rr = R = T^2-U1*U2 (3) */
361359
secp256k1_fe_sqr(&t, &rr); /* t = R^2 (1) */
362360
secp256k1_fe_mul(&r->z, &m, &z); /* r->z = M*Z (1) */
363-
secp256k1_fe_normalize(&r->z);
364-
int infinity = secp256k1_fe_is_zero(&r->z) * (1 - a->infinity);
361+
int infinity = secp256k1_fe_normalizes_to_zero(&r->z) * (1 - a->infinity);
365362
secp256k1_fe_mul_int(&r->z, 2 * (1 - a->infinity)); /* r->z = Z3 = 2*M*Z (2) */
366363
r->x = t; /* r->x = R^2 (1) */
367364
secp256k1_fe_negate(&q, &q, 1); /* q = -Q (2) */

0 commit comments

Comments
 (0)