Skip to content

Commit 341cc19

Browse files
Merge #1299: Infinity handling: ecmult_const(infinity) works, and group verification
bbc8344 Avoid secp256k1_ge_set_gej_zinv with uninitialized z (Pieter Wuille) 0a2e0b2 Make secp256k1_{fe,ge,gej}_verify work as no-op if non-VERIFY (Pieter Wuille) f202667 Add invariant checking to group elements (Pieter Wuille) a18821d Always initialize output coordinates in secp256k1_ge_set_gej (Pieter Wuille) 3086cb9 Expose secp256k1_fe_verify to other modules (Pieter Wuille) a0e696f Make secp256k1_ecmult_const handle infinity (Gregory Maxwell) Pull request description: Rebase of #791. * Clean up infinity handling, make x/y/z always initialized for infinity. * 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: needs a constant time addition function that tracks RZR). It isn't typical for ECDH to be constant time in terms of the pubkey. 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. * Add group verification (`secp256k1_ge_verify` and `secp256k1_gej_verify`, mimicking `secp256k1_fe_verify`). * Make the `secp256k1_{fe,ge,gej}_verify` functions also defined (as no-ops) in non-VERIFY mode. ACKs for top commit: jonasnick: ACK bbc8344 real-or-random: ACK bbc8344 Tree-SHA512: 82cb51faa2c207603aa10359a311ea618fcb5a81ba175bf15515bf84043223db6428434875854cdfce9ae95f9cfd68c74e4e415f26bd574f1791b5dec1615d19
2 parents 24c768a + bbc8344 commit 341cc19

8 files changed

+129
-27
lines changed

src/ecmult_const.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111
#include "group.h"
1212

1313
/**
14-
* Multiply: R = q*A (in constant-time)
15-
* A must not be infinity.
14+
* Multiply: R = q*A (in constant-time for q)
1615
*/
1716
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q);
1817

src/ecmult_const_impl.h

+5
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
144144

145145
int i;
146146

147+
if (secp256k1_ge_is_infinity(a)) {
148+
secp256k1_gej_set_infinity(r);
149+
return;
150+
}
151+
147152
/* build wnaf representation for q. */
148153
/* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */
149154
secp256k1_scalar_split_lambda(&q_1, &q_lam, scalar);

src/field.h

+3
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,7 @@ static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m);
143143
/** Determine whether a is a square (modulo p). */
144144
static int secp256k1_fe_is_square_var(const secp256k1_fe *a);
145145

146+
/** Check invariants on a field element (no-op unless VERIFY is enabled). */
147+
static void secp256k1_fe_verify(const secp256k1_fe *a);
148+
146149
#endif /* SECP256K1_FIELD_H */

src/field_10x26_impl.h

+3-6
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
* - 2*M*(2^26-1) is the max (inclusive) of the remaining limbs
2222
*/
2323

24-
#ifdef VERIFY
2524
static void secp256k1_fe_verify(const secp256k1_fe *a) {
25+
#ifdef VERIFY
2626
const uint32_t *d = a->n;
2727
int m = a->normalized ? 1 : 2 * a->magnitude, r = 1;
2828
r &= (d[0] <= 0x3FFFFFFUL * m);
@@ -47,8 +47,9 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) {
4747
}
4848
}
4949
VERIFY_CHECK(r == 1);
50-
}
5150
#endif
51+
(void)a;
52+
}
5253

5354
static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m) {
5455
VERIFY_CHECK(m >= 0);
@@ -458,9 +459,7 @@ SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) {
458459
}
459460

460461
SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) {
461-
#ifdef VERIFY
462462
secp256k1_fe_verify(a);
463-
#endif
464463
r->n[0] += a->n[0];
465464
r->n[1] += a->n[1];
466465
r->n[2] += a->n[2];
@@ -479,11 +478,9 @@ SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_f
479478
}
480479

481480
SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) {
482-
#ifdef VERIFY
483481
secp256k1_fe_verify(r);
484482
VERIFY_CHECK(a >= 0);
485483
VERIFY_CHECK(a <= 0x7FFF);
486-
#endif
487484
r->n[0] += a;
488485
#ifdef VERIFY
489486
r->magnitude += 1;

src/field_5x52_impl.h

+3-6
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
* 0 or 1, and its value is already reduced modulo the order of the field.
3434
*/
3535

36-
#ifdef VERIFY
3736
static void secp256k1_fe_verify(const secp256k1_fe *a) {
37+
#ifdef VERIFY
3838
const uint64_t *d = a->n;
3939
int m = a->normalized ? 1 : 2 * a->magnitude, r = 1;
4040
/* 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) {
5252
}
5353
}
5454
VERIFY_CHECK(r == 1);
55-
}
5655
#endif
56+
(void)a;
57+
}
5758

5859
static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m) {
5960
VERIFY_CHECK(m >= 0);
@@ -422,11 +423,9 @@ SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) {
422423
}
423424

424425
SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) {
425-
#ifdef VERIFY
426426
secp256k1_fe_verify(r);
427427
VERIFY_CHECK(a >= 0);
428428
VERIFY_CHECK(a <= 0x7FFF);
429-
#endif
430429
r->n[0] += a;
431430
#ifdef VERIFY
432431
r->magnitude += 1;
@@ -436,9 +435,7 @@ SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) {
436435
}
437436

438437
SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) {
439-
#ifdef VERIFY
440438
secp256k1_fe_verify(a);
441-
#endif
442439
r->n[0] += a->n[0];
443440
r->n[1] += a->n[1];
444441
r->n[2] += a->n[2];

src/group.h

+6
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,10 @@ static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b);
164164
*/
165165
static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge);
166166

167+
/** Check invariants on an affine group element (no-op unless VERIFY is enabled). */
168+
static void secp256k1_ge_verify(const secp256k1_ge *a);
169+
170+
/** Check invariants on a Jacobian group element (no-op unless VERIFY is enabled). */
171+
static void secp256k1_gej_verify(const secp256k1_gej *a);
172+
167173
#endif /* SECP256K1_GROUP_H */

0 commit comments

Comments
 (0)