Skip to content

Commit dc9cc22

Browse files
authored
Merge pull request #6 from peterdettman/202010_pr767
Rework _update_de and format conversions
2 parents d5ee559 + 683ca3b commit dc9cc22

File tree

8 files changed

+197
-164
lines changed

8 files changed

+197
-164
lines changed

src/field_10x26_impl.h

Lines changed: 16 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,58 +1169,31 @@ static void secp256k1_fe_from_signed30(secp256k1_fe *r, const secp256k1_modinv32
11691169
const uint32_t M26 = UINT32_MAX >> 6;
11701170
const uint32_t a0 = a->v[0], a1 = a->v[1], a2 = a->v[2], a3 = a->v[3], a4 = a->v[4],
11711171
a5 = a->v[5], a6 = a->v[6], a7 = a->v[7], a8 = a->v[8];
1172-
uint32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, t;
1173-
1174-
t = (int32_t)a8 >> 16;
11751172

11761173
secp256k1_modinv32_signed30_verify(a);
11771174

1178-
/* Add 2P if a8 is "negative". */
1179-
r0 = 0x3FFF85EUL & t;
1180-
r1 = 0x3FFFF7FUL & t;
1181-
r2 = 0x3FFFFFFUL & t;
1182-
r3 = 0x3FFFFFFUL & t;
1183-
r4 = 0x3FFFFFFUL & t;
1184-
r5 = 0x3FFFFFFUL & t;
1185-
r6 = 0x3FFFFFFUL & t;
1186-
r7 = 0x3FFFFFFUL & t;
1187-
r8 = 0x3FFFFFFUL & t;
1188-
r9 = 0x07FFFFFUL & t;
1189-
1190-
r0 += a0 & M26;
1191-
r1 += (a0 >> 26 | a1 << 4) & M26;
1192-
r2 += (a1 >> 22 | a2 << 8) & M26;
1193-
r3 += (a2 >> 18 | a3 << 12) & M26;
1194-
r4 += (a3 >> 14 | a4 << 16) & M26;
1195-
r5 += (a4 >> 10 | a5 << 20) & M26;
1196-
r6 += (a5 >> 6 | a6 << 24) & M26;
1197-
r7 += (a6 >> 2 ) & M26;
1198-
r8 += (a6 >> 28 | a7 << 2) & M26;
1199-
r9 += (a7 >> 24 | a8 << 6);
1200-
1201-
r->n[0] = r0;
1202-
r->n[1] = r1;
1203-
r->n[2] = r2;
1204-
r->n[3] = r3;
1205-
r->n[4] = r4;
1206-
r->n[5] = r5;
1207-
r->n[6] = r6;
1208-
r->n[7] = r7;
1209-
r->n[8] = r8;
1210-
r->n[9] = r9;
1175+
r->n[0] = a0 & M26;
1176+
r->n[1] = (a0 >> 26 | a1 << 4) & M26;
1177+
r->n[2] = (a1 >> 22 | a2 << 8) & M26;
1178+
r->n[3] = (a2 >> 18 | a3 << 12) & M26;
1179+
r->n[4] = (a3 >> 14 | a4 << 16) & M26;
1180+
r->n[5] = (a4 >> 10 | a5 << 20) & M26;
1181+
r->n[6] = (a5 >> 6 | a6 << 24) & M26;
1182+
r->n[7] = (a6 >> 2 ) & M26;
1183+
r->n[8] = (a6 >> 28 | a7 << 2) & M26;
1184+
r->n[9] = (a7 >> 24 | a8 << 6);
12111185

12121186
#ifdef VERIFY
12131187
r->magnitude = 1;
1214-
r->normalized = 0;
1188+
r->normalized = 1;
12151189
secp256k1_fe_verify(r);
12161190
#endif
12171191
}
12181192

12191193
static void secp256k1_fe_to_signed30(secp256k1_modinv32_signed30 *r, const secp256k1_fe *a) {
12201194
const uint32_t M30 = UINT32_MAX >> 2;
1221-
const uint32_t *n = &a->n[0];
1222-
const uint64_t a0 = n[0], a1 = n[1], a2 = n[2], a3 = n[3], a4 = n[4],
1223-
a5 = n[5], a6 = n[6], a7 = n[7], a8 = n[8], a9 = n[9];
1195+
const uint64_t a0 = a->n[0], a1 = a->n[1], a2 = a->n[2], a3 = a->n[3], a4 = a->n[4],
1196+
a5 = a->n[5], a6 = a->n[6], a7 = a->n[7], a8 = a->n[8], a9 = a->n[9];
12241197

12251198
#ifdef VERIFY
12261199
VERIFY_CHECK(a->normalized);
@@ -1240,11 +1213,10 @@ static void secp256k1_fe_to_signed30(secp256k1_modinv32_signed30 *r, const secp2
12401213

12411214
static const secp256k1_modinv32_modinfo secp256k1_const_modinfo_fe = {
12421215
{{-0x3D1, -4, 0, 0, 0, 0, 0, 0, 65536}},
1243-
0x12253531L * 4
1216+
0x2DDACACFL
12441217
};
12451218

12461219
static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *x) {
1247-
int sign;
12481220
secp256k1_fe tmp;
12491221
secp256k1_modinv32_signed30 s;
12501222
#ifdef VERIFY
@@ -1257,19 +1229,15 @@ static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *x) {
12571229
zero_in = secp256k1_fe_normalizes_to_zero(&tmp);
12581230
#endif
12591231
secp256k1_fe_to_signed30(&s, &tmp);
1260-
secp256k1_modinv32(&sign, &s, &secp256k1_const_modinfo_fe);
1232+
secp256k1_modinv32(&s, &secp256k1_const_modinfo_fe);
12611233
secp256k1_fe_from_signed30(r, &s);
1262-
secp256k1_fe_negate(&tmp, r, 1);
1263-
secp256k1_fe_cmov(r, &tmp, sign);
1264-
secp256k1_fe_normalize_weak(r);
12651234

12661235
#ifdef VERIFY
12671236
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == zero_in);
12681237
#endif
12691238
}
12701239

12711240
static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *x) {
1272-
int sign;
12731241
secp256k1_fe tmp;
12741242
secp256k1_modinv32_signed30 s;
12751243
#ifdef VERIFY
@@ -1282,12 +1250,8 @@ static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *x) {
12821250
zero_in = secp256k1_fe_normalizes_to_zero(&tmp);
12831251
#endif
12841252
secp256k1_fe_to_signed30(&s, &tmp);
1285-
secp256k1_modinv32_var(&sign, &s, &secp256k1_const_modinfo_fe);
1253+
secp256k1_modinv32_var(&s, &secp256k1_const_modinfo_fe);
12861254
secp256k1_fe_from_signed30(r, &s);
1287-
if (sign) {
1288-
secp256k1_fe_negate(r, r, 1);
1289-
secp256k1_fe_normalize_weak(r);
1290-
}
12911255

12921256
#ifdef VERIFY
12931257
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == zero_in);

src/field_5x52_impl.h

Lines changed: 10 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -502,42 +502,25 @@ static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const se
502502
static void secp256k1_fe_from_signed62(secp256k1_fe *r, const secp256k1_modinv64_signed62 *a) {
503503
const uint64_t M52 = UINT64_MAX >> 12;
504504
const uint64_t a0 = a->v[0], a1 = a->v[1], a2 = a->v[2], a3 = a->v[3], a4 = a->v[4];
505-
uint64_t r0, r1, r2, r3, r4, t;
506505

507506
secp256k1_modinv64_signed62_verify(a);
508507

509-
t = (int64_t)a4 >> 8;
510-
511-
/* Add 2P if a4 is "negative". */
512-
r0 = 0xFFFFDFFFFF85EULL & t;
513-
r1 = 0xFFFFFFFFFFFFFULL & t;
514-
r2 = 0xFFFFFFFFFFFFFULL & t;
515-
r3 = 0xFFFFFFFFFFFFFULL & t;
516-
r4 = 0x1FFFFFFFFFFFFULL & t;
517-
518-
r0 += a0 & M52;
519-
r1 += (a0 >> 52 | a1 << 10) & M52;
520-
r2 += (a1 >> 42 | a2 << 20) & M52;
521-
r3 += (a2 >> 32 | a3 << 30) & M52;
522-
r4 += (a3 >> 22 | a4 << 40);
523-
524-
r->n[0] = r0;
525-
r->n[1] = r1;
526-
r->n[2] = r2;
527-
r->n[3] = r3;
528-
r->n[4] = r4;
508+
r->n[0] = a0 & M52;
509+
r->n[1] = (a0 >> 52 | a1 << 10) & M52;
510+
r->n[2] = (a1 >> 42 | a2 << 20) & M52;
511+
r->n[3] = (a2 >> 32 | a3 << 30) & M52;
512+
r->n[4] = (a3 >> 22 | a4 << 40);
529513

530514
#ifdef VERIFY
531515
r->magnitude = 1;
532-
r->normalized = 0;
516+
r->normalized = 1;
533517
secp256k1_fe_verify(r);
534518
#endif
535519
}
536520

537521
static void secp256k1_fe_to_signed62(secp256k1_modinv64_signed62 *r, const secp256k1_fe *a) {
538522
const uint64_t M62 = UINT64_MAX >> 2;
539-
const uint64_t *n = &a->n[0];
540-
const uint64_t a0 = n[0], a1 = n[1], a2 = n[2], a3 = n[3], a4 = n[4];
523+
const uint64_t a0 = a->n[0], a1 = a->n[1], a2 = a->n[2], a3 = a->n[3], a4 = a->n[4];
541524

542525
#ifdef VERIFY
543526
VERIFY_CHECK(a->normalized);
@@ -552,11 +535,10 @@ static void secp256k1_fe_to_signed62(secp256k1_modinv64_signed62 *r, const secp2
552535

553536
static const secp256k1_modinv64_modinfo secp256k1_const_modinfo_fe = {
554537
{{-0x1000003D1LL, 0, 0, 0, 256}},
555-
0x1838091DD2253531LL * 4
538+
0x27C7F6E22DDACACFLL
556539
};
557540

558541
static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *x) {
559-
int sign;
560542
secp256k1_fe tmp;
561543
secp256k1_modinv64_signed62 s;
562544
#ifdef VERIFY
@@ -569,19 +551,15 @@ static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *x) {
569551
zero_in = secp256k1_fe_normalizes_to_zero(&tmp);
570552
#endif
571553
secp256k1_fe_to_signed62(&s, &tmp);
572-
secp256k1_modinv64(&sign, &s, &secp256k1_const_modinfo_fe);
554+
secp256k1_modinv64(&s, &secp256k1_const_modinfo_fe);
573555
secp256k1_fe_from_signed62(r, &s);
574-
secp256k1_fe_negate(&tmp, r, 1);
575-
secp256k1_fe_cmov(r, &tmp, sign);
576-
secp256k1_fe_normalize_weak(r);
577556

578557
#ifdef VERIFY
579558
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == zero_in);
580559
#endif
581560
}
582561

583562
static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *x) {
584-
int sign;
585563
secp256k1_fe tmp;
586564
secp256k1_modinv64_signed62 s;
587565
#ifdef VERIFY
@@ -594,12 +572,8 @@ static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *x) {
594572
zero_in = secp256k1_fe_normalizes_to_zero(&tmp);
595573
#endif
596574
secp256k1_fe_to_signed62(&s, &tmp);
597-
secp256k1_modinv64_var(&sign, &s, &secp256k1_const_modinfo_fe);
575+
secp256k1_modinv64_var(&s, &secp256k1_const_modinfo_fe);
598576
secp256k1_fe_from_signed62(r, &s);
599-
if (sign) {
600-
secp256k1_fe_negate(r, r, 1);
601-
secp256k1_fe_normalize_weak(r);
602-
}
603577

604578
#ifdef VERIFY
605579
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == zero_in);

src/modinv32.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ typedef struct {
2121
/* The modulus in signed30 notation. */
2222
secp256k1_modinv32_signed30 modulus;
2323

24-
/* (-modulus^{-1} mod 2^30) * 4 */
25-
uint32_t montmul4;
24+
/* modulus^{-1} mod 2^30 */
25+
int32_t modulus_inv30;
2626
} secp256k1_modinv32_modinfo;
2727

28-
static void secp256k1_modinv32_signed30_verify(const secp256k1_modinv32_signed30* a);
29-
static void secp256k1_modinv32(int* sign, secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo* modinfo);
30-
static void secp256k1_modinv32_var(int* sign, secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo* modinfo);
28+
static void secp256k1_modinv32_signed30_verify(const secp256k1_modinv32_signed30 *a);
29+
static void secp256k1_modinv32(secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo);
30+
static void secp256k1_modinv32_var(secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo);
3131

3232
#endif /* SECP256K1_MODINV32_H */

src/modinv32_impl.h

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111

1212
#include "util.h"
1313

14-
static void secp256k1_modinv32_signed30_verify(const secp256k1_modinv32_signed30* a) {
15-
/* a must be in the range [-2^256, 2^256). */
14+
static void secp256k1_modinv32_signed30_verify(const secp256k1_modinv32_signed30 *a) {
1615
VERIFY_CHECK(a->v[0] >> 30 == 0);
1716
VERIFY_CHECK(a->v[1] >> 30 == 0);
1817
VERIFY_CHECK(a->v[2] >> 30 == 0);
@@ -21,7 +20,58 @@ static void secp256k1_modinv32_signed30_verify(const secp256k1_modinv32_signed30
2120
VERIFY_CHECK(a->v[5] >> 30 == 0);
2221
VERIFY_CHECK(a->v[6] >> 30 == 0);
2322
VERIFY_CHECK(a->v[7] >> 30 == 0);
24-
VERIFY_CHECK(a->v[8] >> 16 == 0 || a->v[8] >> 16 == -(int32_t)1);
23+
VERIFY_CHECK(a->v[8] >> 16 == 0);
24+
}
25+
26+
static void secp256k1_modinv32_normalize_30(secp256k1_modinv32_signed30 *r, int32_t cond_negate, const secp256k1_modinv32_modinfo *modinfo) {
27+
const int32_t M30 = (int32_t)(UINT32_MAX >> 2);
28+
int32_t r0 = r->v[0], r1 = r->v[1], r2 = r->v[2], r3 = r->v[3], r4 = r->v[4],
29+
r5 = r->v[5], r6 = r->v[6], r7 = r->v[7], r8 = r->v[8];
30+
int32_t c, cond_add;
31+
32+
cond_add = r8 >> 31;
33+
34+
c = r0 + (modinfo->modulus.v[0] & cond_add);
35+
r0 = c & M30; c >>= 30;
36+
c += r1 + (modinfo->modulus.v[1] & cond_add);
37+
r1 = c & M30; c >>= 30;
38+
c += r2 + (modinfo->modulus.v[2] & cond_add);
39+
r2 = c & M30; c >>= 30;
40+
c += r3 + (modinfo->modulus.v[3] & cond_add);
41+
r3 = c & M30; c >>= 30;
42+
c += r4 + (modinfo->modulus.v[4] & cond_add);
43+
r4 = c & M30; c >>= 30;
44+
c += r5 + (modinfo->modulus.v[5] & cond_add);
45+
r5 = c & M30; c >>= 30;
46+
c += r6 + (modinfo->modulus.v[6] & cond_add);
47+
r6 = c & M30; c >>= 30;
48+
c += r7 + (modinfo->modulus.v[7] & cond_add);
49+
r7 = c & M30; c >>= 30;
50+
c += r8 + (modinfo->modulus.v[8] & cond_add);
51+
r8 = c;
52+
53+
cond_add = (c >> 31) ^ cond_negate;
54+
55+
c = (r0 ^ cond_negate) - cond_negate + (modinfo->modulus.v[0] & cond_add);
56+
r->v[0] = c & M30; c >>= 30;
57+
c += (r1 ^ cond_negate) - cond_negate + (modinfo->modulus.v[1] & cond_add);
58+
r->v[1] = c & M30; c >>= 30;
59+
c += (r2 ^ cond_negate) - cond_negate + (modinfo->modulus.v[2] & cond_add);
60+
r->v[2] = c & M30; c >>= 30;
61+
c += (r3 ^ cond_negate) - cond_negate + (modinfo->modulus.v[3] & cond_add);
62+
r->v[3] = c & M30; c >>= 30;
63+
c += (r4 ^ cond_negate) - cond_negate + (modinfo->modulus.v[4] & cond_add);
64+
r->v[4] = c & M30; c >>= 30;
65+
c += (r5 ^ cond_negate) - cond_negate + (modinfo->modulus.v[5] & cond_add);
66+
r->v[5] = c & M30; c >>= 30;
67+
c += (r6 ^ cond_negate) - cond_negate + (modinfo->modulus.v[6] & cond_add);
68+
r->v[6] = c & M30; c >>= 30;
69+
c += (r7 ^ cond_negate) - cond_negate + (modinfo->modulus.v[7] & cond_add);
70+
r->v[7] = c & M30; c >>= 30;
71+
c += (r8 ^ cond_negate) - cond_negate + (modinfo->modulus.v[8] & cond_add);
72+
r->v[8] = c;
73+
74+
VERIFY_CHECK(c >> 16 == 0);
2575
}
2676

2777
static uint32_t secp256k1_modinv32_divsteps_30(uint32_t eta, uint32_t f0, uint32_t g0, int32_t *t) {
@@ -134,20 +184,37 @@ static uint32_t secp256k1_modinv32_divsteps_30_var(uint32_t eta, uint32_t f0, ui
134184

135185
static void secp256k1_modinv32_update_de_30(secp256k1_modinv32_signed30 *d, secp256k1_modinv32_signed30 *e, const int32_t *t, const secp256k1_modinv32_modinfo* modinfo) {
136186
const int32_t M30 = (int32_t)(UINT32_MAX >> 2);
137-
int32_t u = t[0], v = t[1], q = t[2], r = t[3], di, ei, md, me;
187+
const int32_t u = t[0], v = t[1], q = t[2], r = t[3];
188+
int32_t di, ei, md, me, sd, se;
138189
int64_t cd, ce;
139190
int i;
140191

192+
/*
193+
* On input, d/e must be in the range (-2.P, P). For initially negative d (resp. e), we add
194+
* u and/or v (resp. q and/or r) multiples of the modulus to the corresponding output (prior
195+
* to division by 2^30). This has the same effect as if we added the modulus to the input(s).
196+
*/
197+
198+
sd = d->v[8] >> 31;
199+
se = e->v[8] >> 31;
200+
201+
md = (u & sd) + (v & se);
202+
me = (q & sd) + (r & se);
203+
141204
di = d->v[0];
142205
ei = e->v[0];
143206

144207
cd = (int64_t)u * di + (int64_t)v * ei;
145208
ce = (int64_t)q * di + (int64_t)r * ei;
146209

147-
/* Calculate the multiples of P to add, to zero the 30 bottom bits. We choose md, me
148-
* from the centred range [-2^29, 2^29) to keep d, e within [-2^256, 2^256). */
149-
md = ((int32_t)(modinfo->montmul4 * (uint32_t)cd)) >> 2;
150-
me = ((int32_t)(modinfo->montmul4 * (uint32_t)ce)) >> 2;
210+
/*
211+
* Subtract from md/me an extra term in the range [0, 2^30) such that the low 30 bits of each
212+
* sum of products will be 0. This allows clean division by 2^30. On output, d/e are thus in
213+
* the range (-2.P, P), consistent with the input constraint.
214+
*/
215+
216+
md -= (modinfo->modulus_inv30 * (int32_t)cd + md) & M30;
217+
me -= (modinfo->modulus_inv30 * (int32_t)ce + me) & M30;
151218

152219
if (modinfo->modulus.v[0]) {
153220
cd += (int64_t)modinfo->modulus.v[0] * md;
@@ -243,7 +310,7 @@ static void secp256k1_modinv32_update_fg_30_var(int len, secp256k1_modinv32_sign
243310
g->v[len - 1] = (int32_t)cg;
244311
}
245312

246-
static void secp256k1_modinv32(int* sign, secp256k1_modinv32_signed30* x, const secp256k1_modinv32_modinfo* modinfo) {
313+
static void secp256k1_modinv32(secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo) {
247314
/* Modular inversion based on the paper "Fast constant-time gcd computation and
248315
* modular inversion" by Daniel J. Bernstein and Bo-Yin Yang. */
249316
int32_t t[4];
@@ -272,11 +339,12 @@ static void secp256k1_modinv32(int* sign, secp256k1_modinv32_signed30* x, const
272339
* values i.e. +/- 1, and d now contains +/- the modular inverse. */
273340
VERIFY_CHECK((g.v[0] | g.v[1] | g.v[2] | g.v[3] | g.v[4] | g.v[5] | g.v[6] | g.v[7] | g.v[8]) == 0);
274341

275-
*sign = (f.v[0] >> 1) & 1;
342+
secp256k1_modinv32_normalize_30(&d, f.v[8] >> 31, modinfo);
343+
276344
*x = d;
277345
}
278346

279-
static void secp256k1_modinv32_var(int* sign, secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo* modinfo) {
347+
static void secp256k1_modinv32_var(secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo) {
280348
/* Modular inversion based on the paper "Fast constant-time gcd computation and
281349
* modular inversion" by Daniel J. Bernstein and Bo-Yin Yang. */
282350
int32_t t[4];
@@ -328,7 +396,8 @@ static void secp256k1_modinv32_var(int* sign, secp256k1_modinv32_signed30 *x, co
328396

329397
VERIFY_CHECK(i < 25);
330398

331-
*sign = (f.v[0] >> 1) & 1;
399+
secp256k1_modinv32_normalize_30(&d, f.v[len - 1] >> 31, modinfo);
400+
332401
*x = d;
333402
}
334403

0 commit comments

Comments
 (0)