Skip to content

Commit 49ee0db

Browse files
peterdettmansipa
authored andcommitted
Add _normalizes_to_zero_var variant
1 parent eed599d commit 49ee0db

File tree

5 files changed

+78
-6
lines changed

5 files changed

+78
-6
lines changed

src/field.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ static void secp256k1_fe_normalize_var(secp256k1_fe_t *r);
5858
* implementation may optionally normalize the input, but this should not be relied upon. */
5959
static int secp256k1_fe_normalizes_to_zero(secp256k1_fe_t *r);
6060

61+
/** Verify whether a field element represents zero i.e. would normalize to a zero value. The field
62+
* implementation may optionally normalize the input, but this should not be relied upon. */
63+
static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe_t *r);
64+
6165
/** Set a field element equal to a small integer. Resulting field element is normalized. */
6266
static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a);
6367

src/field_10x26_impl.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,44 @@ static int secp256k1_fe_normalizes_to_zero(secp256k1_fe_t *r) {
219219
return (z0 == 0) | (z1 == 0x3FFFFFFUL);
220220
}
221221

222+
static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe_t *r) {
223+
uint32_t t0 = r->n[0], t9 = r->n[9];
224+
225+
/* Reduce t9 at the start so there will be at most a single carry from the first pass */
226+
uint32_t x = t9 >> 22;
227+
228+
/* The first pass ensures the magnitude is 1, ... */
229+
t0 += x * 0x3D1UL;
230+
231+
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
232+
uint32_t z0 = t0 & 0x3FFFFFFUL, z1 = z0 ^ 0x3D0UL;
233+
234+
/* Fast return path should catch the majority of cases */
235+
if ((z0 != 0UL) & (z1 != 0x3FFFFFFUL))
236+
return 0;
237+
238+
uint32_t t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
239+
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8];
240+
t9 &= 0x03FFFFFUL;
241+
t1 += (x << 6);
242+
243+
t1 += (t0 >> 26); t0 = z0;
244+
t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; z0 |= t1; z1 &= t1 ^ 0x40UL;
245+
t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; z0 |= t2; z1 &= t2;
246+
t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; z0 |= t3; z1 &= t3;
247+
t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; z0 |= t4; z1 &= t4;
248+
t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; z0 |= t5; z1 &= t5;
249+
t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; z0 |= t6; z1 &= t6;
250+
t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; z0 |= t7; z1 &= t7;
251+
t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; z0 |= t8; z1 &= t8;
252+
z0 |= t9; z1 &= t9 ^ 0x3C00000UL;
253+
254+
/* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */
255+
VERIFY_CHECK(t9 >> 23 == 0);
256+
257+
return (z0 == 0) | (z1 == 0x3FFFFFFUL);
258+
}
259+
222260
SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
223261
r->n[0] = a;
224262
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: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,37 @@ static int secp256k1_fe_normalizes_to_zero(secp256k1_fe_t *r) {
191191
return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL);
192192
}
193193

194+
static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe_t *r) {
195+
uint64_t t0 = r->n[0], t4 = r->n[4];
196+
197+
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
198+
uint64_t x = t4 >> 48;
199+
200+
/* The first pass ensures the magnitude is 1, ... */
201+
t0 += x * 0x1000003D1ULL;
202+
203+
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
204+
uint64_t z0 = t0 & 0xFFFFFFFFFFFFFULL, z1 = z0 ^ 0x1000003D0ULL;
205+
206+
/* Fast return path should catch the majority of cases */
207+
if ((z0 != 0ULL) & (z1 != 0xFFFFFFFFFFFFFULL))
208+
return 0;
209+
210+
uint64_t t1 = r->n[1], t2 = r->n[2], t3 = r->n[3];
211+
t4 &= 0x0FFFFFFFFFFFFULL;
212+
213+
t1 += (t0 >> 52); t0 = z0;
214+
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1;
215+
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2;
216+
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3;
217+
z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL;
218+
219+
/* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */
220+
VERIFY_CHECK(t4 >> 49 == 0);
221+
222+
return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL);
223+
}
224+
194225
SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
195226
r->n[0] = a;
196227
r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;

src/field_impl.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,11 @@ 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 */
6867
SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
6968
secp256k1_fe_t na;
7069
secp256k1_fe_negate(&na, a, 1);
7170
secp256k1_fe_add(&na, b);
72-
return secp256k1_fe_normalizes_to_zero(&na);
71+
return secp256k1_fe_normalizes_to_zero_var(&na);
7372
}
7473

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

src/group_impl.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,8 @@ static void secp256k1_gej_add_var(secp256k1_gej_t *r, const secp256k1_gej_t *a,
257257
secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z);
258258
secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
259259
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)) {
260+
if (secp256k1_fe_normalizes_to_zero_var(&h)) {
261+
if (secp256k1_fe_normalizes_to_zero_var(&i)) {
262262
secp256k1_gej_double_var(r, a);
263263
} else {
264264
r->infinity = 1;
@@ -296,8 +296,8 @@ static void secp256k1_gej_add_ge_var(secp256k1_gej_t *r, const secp256k1_gej_t *
296296
secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z);
297297
secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
298298
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)) {
299+
if (secp256k1_fe_normalizes_to_zero_var(&h)) {
300+
if (secp256k1_fe_normalizes_to_zero_var(&i)) {
301301
secp256k1_gej_double_var(r, a);
302302
} else {
303303
r->infinity = 1;

0 commit comments

Comments
 (0)