Skip to content

Commit c918a32

Browse files
committed
Remove old ecmult_gen code and always use multi-comb
1 parent 3e10eb4 commit c918a32

File tree

3 files changed

+10
-157
lines changed

3 files changed

+10
-157
lines changed

src/ecmult_gen.h

-31
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@
1010
#include "scalar.h"
1111
#include "group.h"
1212

13-
#define USE_COMB 1
14-
15-
#if USE_COMB
16-
1713
#if defined(EXHAUSTIVE_TEST_ORDER)
1814

1915
/* We need to control these values for exhaustive tests because
@@ -78,19 +74,7 @@
7874
# error "COMB_BITS must be in the range [256, 288]"
7975
#endif
8076

81-
#else
82-
83-
#if ECMULT_GEN_PREC_BITS != 2 && ECMULT_GEN_PREC_BITS != 4 && ECMULT_GEN_PREC_BITS != 8
84-
# error "Set ECMULT_GEN_PREC_BITS to 2, 4 or 8."
85-
#endif
86-
#define ECMULT_GEN_PREC_B ECMULT_GEN_PREC_BITS
87-
#define ECMULT_GEN_PREC_G (1 << ECMULT_GEN_PREC_B)
88-
#define ECMULT_GEN_PREC_N (256 / ECMULT_GEN_PREC_B)
89-
90-
#endif
91-
9277
typedef struct {
93-
#if USE_COMB
9478
/* Precomputation data for the signed-digit multi-comb algorithm as described in section 3.3 of:
9579
* "Fast and compact elliptic-curve cryptography", Mike Hamburg
9680
* (https://eprint.iacr.org/2012/309)
@@ -103,21 +87,6 @@ typedef struct {
10387
* for the (COMB_SPACING - 1) doublings in the _ecmult_gen ladder.
10488
*/
10589
secp256k1_ge offset;
106-
#endif
107-
#else
108-
/* For accelerating the computation of a*G:
109-
* To harden against timing attacks, use the following mechanism:
110-
* * Break up the multiplicand into groups of PREC_B bits, called n_0, n_1, n_2, ..., n_(PREC_N-1).
111-
* * Compute sum(n_i * (PREC_G)^i * G + U_i, i=0 ... PREC_N-1), where:
112-
* * U_i = U * 2^i, for i=0 ... PREC_N-2
113-
* * U_i = U * (1-2^(PREC_N-1)), for i=PREC_N-1
114-
* where U is a point with no known corresponding scalar. Note that sum(U_i, i=0 ... PREC_N-1) = 0.
115-
* For each i, and each of the PREC_G possible values of n_i, (n_i * (PREC_G)^i * G + U_i) is
116-
* precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0 ... PREC_N-1).
117-
* None of the resulting prec group elements have a known scalar, and neither do any of
118-
* the intermediate sums while computing a*G.
119-
*/
120-
secp256k1_ge_storage (*prec)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G]; /* prec[j][i] = (PREC_G)^j * i * G + U_i */
12190
#endif
12291
secp256k1_scalar blind;
12392
secp256k1_gej initial;

src/ecmult_gen_impl.h

+10-110
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,9 @@ static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context *ctx)
2828

2929
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx, void **prealloc) {
3030
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
31-
#if USE_COMB
3231
secp256k1_ge prec[COMB_POINTS_TOTAL + COMB_OFFSET];
3332
secp256k1_gej u, sum;
3433
int block, index, spacing, stride, tooth;
35-
#else
36-
secp256k1_ge prec[ECMULT_GEN_PREC_N * ECMULT_GEN_PREC_G];
37-
secp256k1_gej gj;
38-
secp256k1_gej nums_gej;
39-
int i, j;
40-
#endif
4134
size_t const prealloc_size = SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE;
4235
void* const base = *prealloc;
4336
#endif
@@ -46,7 +39,6 @@ static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx
4639
return;
4740
}
4841
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
49-
#if USE_COMB
5042
ctx->prec = (secp256k1_ge_storage (*)[COMB_BLOCKS][COMB_POINTS])manual_alloc(prealloc, prealloc_size, base, prealloc_size);
5143

5244
/* get the generator */
@@ -95,72 +87,12 @@ static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx
9587
ctx->offset = prec[COMB_POINTS_TOTAL];
9688
#endif
9789

98-
#else
99-
ctx->prec = (secp256k1_ge_storage (*)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G])manual_alloc(prealloc, prealloc_size, base, prealloc_size);
100-
101-
/* get the generator */
102-
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
103-
104-
/* Construct a group element with no known corresponding scalar (nothing up my sleeve). */
105-
{
106-
static const unsigned char nums_b32[33] = "The scalar for this x is unknown";
107-
secp256k1_fe nums_x;
108-
secp256k1_ge nums_ge;
109-
int r;
110-
r = secp256k1_fe_set_b32(&nums_x, nums_b32);
111-
(void)r;
112-
VERIFY_CHECK(r);
113-
r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0);
114-
(void)r;
115-
VERIFY_CHECK(r);
116-
secp256k1_gej_set_ge(&nums_gej, &nums_ge);
117-
/* Add G to make the bits in x uniformly distributed. */
118-
secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g, NULL);
119-
}
120-
121-
/* compute prec. */
122-
{
123-
secp256k1_gej precj[ECMULT_GEN_PREC_N * ECMULT_GEN_PREC_G]; /* Jacobian versions of prec. */
124-
secp256k1_gej gbase;
125-
secp256k1_gej numsbase;
126-
gbase = gj; /* PREC_G^j * G */
127-
numsbase = nums_gej; /* 2^j * nums. */
128-
for (j = 0; j < ECMULT_GEN_PREC_N; j++) {
129-
/* Set precj[j*PREC_G .. j*PREC_G+(PREC_G-1)] to (numsbase, numsbase + gbase, ..., numsbase + (PREC_G-1)*gbase). */
130-
precj[j*ECMULT_GEN_PREC_G] = numsbase;
131-
for (i = 1; i < ECMULT_GEN_PREC_G; i++) {
132-
secp256k1_gej_add_var(&precj[j*ECMULT_GEN_PREC_G + i], &precj[j*ECMULT_GEN_PREC_G + i - 1], &gbase, NULL);
133-
}
134-
/* Multiply gbase by PREC_G. */
135-
for (i = 0; i < ECMULT_GEN_PREC_B; i++) {
136-
secp256k1_gej_double_var(&gbase, &gbase, NULL);
137-
}
138-
/* Multiply numbase by 2. */
139-
secp256k1_gej_double_var(&numsbase, &numsbase, NULL);
140-
if (j == ECMULT_GEN_PREC_N - 2) {
141-
/* In the last iteration, numsbase is (1 - 2^j) * nums instead. */
142-
secp256k1_gej_neg(&numsbase, &numsbase);
143-
secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL);
144-
}
145-
}
146-
secp256k1_ge_set_all_gej_var(prec, precj, ECMULT_GEN_PREC_N * ECMULT_GEN_PREC_G);
147-
}
148-
for (j = 0; j < ECMULT_GEN_PREC_N; j++) {
149-
for (i = 0; i < ECMULT_GEN_PREC_G; i++) {
150-
secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*ECMULT_GEN_PREC_G + i]);
151-
}
152-
}
153-
#endif
15490
#else
15591
(void)prealloc;
156-
#if USE_COMB
15792
ctx->prec = (secp256k1_ge_storage (*)[COMB_BLOCKS][COMB_POINTS])secp256k1_ecmult_gen_ctx_prec;
15893
#if COMB_OFFSET
15994
secp256k1_ge_from_storage(&ctx->offset, &secp256k1_ecmult_gen_ctx_offset);
16095
#endif
161-
#else
162-
ctx->prec = (secp256k1_ge_storage (*)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G])secp256k1_ecmult_static_context;
163-
#endif
16496
#endif
16597
secp256k1_ecmult_gen_blind(ctx, NULL);
16698
}
@@ -171,28 +103,20 @@ static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_cont
171103

172104
static void secp256k1_ecmult_gen_context_finalize_memcpy(secp256k1_ecmult_gen_context *dst, const secp256k1_ecmult_gen_context *src) {
173105
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
174-
#if USE_COMB
175106
if (src->prec != NULL) {
176107
/* We cast to void* first to suppress a -Wcast-align warning. */
177108
dst->prec = (secp256k1_ge_storage (*)[COMB_BLOCKS][COMB_POINTS])(void*)((unsigned char*)dst + ((unsigned char*)src->prec - (unsigned char*)src));
178109
}
179110
#if COMB_OFFSET
180111
dst->offset = src->offset;
181112
#endif
182-
#else
183-
if (src->prec != NULL) {
184-
dst->prec = (secp256k1_ge_storage (*)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G])(void*)((unsigned char*)dst + ((unsigned char*)src->prec - (unsigned char*)src));
185-
}
186-
#endif
187113
#endif
188114
(void)dst, (void)src;
189115
}
190116

191117
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) {
192-
#if USE_COMB
193118
#if COMB_OFFSET
194119
secp256k1_ge_clear(&ctx->offset);
195-
#endif
196120
#endif
197121
secp256k1_scalar_clear(&ctx->blind);
198122
secp256k1_gej_clear(&ctx->initial);
@@ -205,8 +129,6 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25
205129
secp256k1_scalar gnb;
206130
int bits;
207131

208-
#if USE_COMB
209-
210132
#if COMB_NEGATION
211133
secp256k1_fe neg;
212134
int sign;
@@ -252,6 +174,16 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25
252174
VERIFY_CHECK(0 <= abs && abs < COMB_POINTS);
253175

254176
for (index = 0; index < COMB_POINTS; ++index) {
177+
/** This uses a conditional move to avoid any secret data in array indexes.
178+
* _Any_ use of secret indexes has been demonstrated to result in timing
179+
* sidechannels, even when the cache-line access patterns are uniform.
180+
* See also:
181+
* "A word of warning", CHES 2013 Rump Session, by Daniel J. Bernstein and Peter Schwabe
182+
* (https://cryptojedi.org/peter/data/chesrump-20130822.pdf) and
183+
* "Cache Attacks and Countermeasures: the Case of AES", RSA 2006,
184+
* by Dag Arne Osvik, Adi Shamir, and Eran Tromer
185+
* (http://www.tau.ac.il/~tromer/papers/cache.pdf)
186+
*/
255187
secp256k1_ge_storage_cmov(&adds, &(*ctx->prec)[block][index], index == abs);
256188
}
257189

@@ -278,32 +210,6 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25
278210
memset(recoded, 0, sizeof(recoded));
279211
abs = 0;
280212

281-
#else
282-
int i, j;
283-
memset(&adds, 0, sizeof(adds));
284-
*r = ctx->initial;
285-
/* Blind scalar/point multiplication by computing (n-b)G + bG instead of nG. */
286-
secp256k1_scalar_add(&gnb, gn, &ctx->blind);
287-
add.infinity = 0;
288-
for (j = 0; j < ECMULT_GEN_PREC_N; j++) {
289-
bits = secp256k1_scalar_get_bits(&gnb, j * ECMULT_GEN_PREC_B, ECMULT_GEN_PREC_B);
290-
for (i = 0; i < ECMULT_GEN_PREC_G; i++) {
291-
/** This uses a conditional move to avoid any secret data in array indexes.
292-
* _Any_ use of secret indexes has been demonstrated to result in timing
293-
* sidechannels, even when the cache-line access patterns are uniform.
294-
* See also:
295-
* "A word of warning", CHES 2013 Rump Session, by Daniel J. Bernstein and Peter Schwabe
296-
* (https://cryptojedi.org/peter/data/chesrump-20130822.pdf) and
297-
* "Cache Attacks and Countermeasures: the Case of AES", RSA 2006,
298-
* by Dag Arne Osvik, Adi Shamir, and Eran Tromer
299-
* (http://www.tau.ac.il/~tromer/papers/cache.pdf)
300-
*/
301-
secp256k1_ge_storage_cmov(&adds, &(*ctx->prec)[j][i], i == bits);
302-
}
303-
secp256k1_ge_from_storage(&add, &adds);
304-
secp256k1_gej_add_ge(r, r, &add);
305-
}
306-
#endif
307213
bits = 0;
308214
secp256k1_ge_clear(&add);
309215
memset(&adds, 0, sizeof(adds));
@@ -312,9 +218,7 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25
312218

313219
/* Setup blinding values for secp256k1_ecmult_gen. */
314220
static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32) {
315-
#if USE_COMB
316221
int spacing;
317-
#endif
318222
secp256k1_scalar b;
319223
secp256k1_gej gb;
320224
secp256k1_fe s;
@@ -327,13 +231,11 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
327231
secp256k1_gej_set_ge(&ctx->initial, &secp256k1_ge_const_g);
328232
secp256k1_gej_neg(&ctx->initial, &ctx->initial);
329233
secp256k1_scalar_set_int(&ctx->blind, 1);
330-
#if USE_COMB
331234
for (spacing = 1; spacing < COMB_SPACING; ++spacing) {
332235
secp256k1_scalar_add(&ctx->blind, &ctx->blind, &ctx->blind);
333236
}
334237
#if COMB_OFFSET
335238
secp256k1_gej_add_ge(&ctx->initial, &ctx->initial, &ctx->offset);
336-
#endif
337239
#endif
338240
}
339241
/* The prior blinding value (if not reset) is chained forward by including it in the hash. */
@@ -369,13 +271,11 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
369271
secp256k1_scalar_negate(&b, &b);
370272
ctx->blind = b;
371273
ctx->initial = gb;
372-
#if USE_COMB
373274
for (spacing = 1; spacing < COMB_SPACING; ++spacing) {
374275
secp256k1_scalar_add(&ctx->blind, &ctx->blind, &ctx->blind);
375276
}
376277
#if COMB_OFFSET
377278
secp256k1_gej_add_ge(&ctx->initial, &ctx->initial, &ctx->offset);
378-
#endif
379279
#endif
380280
secp256k1_scalar_clear(&b);
381281
secp256k1_gej_clear(&gb);

src/gen_context.c

-16
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,11 @@ int main(int argc, char **argv) {
3838
FILE* fp;
3939
const char *SC_FORMAT = " SC(%uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu)";
4040

41-
#if USE_COMB
4241
const int blocks = COMB_BLOCKS;
4342
const int points = COMB_POINTS;
4443
#if COMB_OFFSET
4544
secp256k1_ge_storage offset;
4645
#endif
47-
#else
48-
const int blocks = ECMULT_GEN_PREC_N;
49-
const int points = ECMULT_GEN_PREC_G;
50-
#endif
5146

5247
(void)argc;
5348
(void)argv;
@@ -62,31 +57,20 @@ int main(int argc, char **argv) {
6257
fprintf(fp, "#define _SECP256K1_ECMULT_STATIC_CONTEXT_\n");
6358
fprintf(fp, "#include \"src/group.h\"\n");
6459
fprintf(fp, "#define SC SECP256K1_GE_STORAGE_CONST\n");
65-
fprintf(fp, "#if USE_COMB != %i\n", USE_COMB);
66-
fprintf(fp, " #error configuration mismatch, invalid USE_COMB. Try deleting ecmult_static_context.h before the build.\n");
67-
fprintf(fp, "#endif\n");
68-
#if USE_COMB
6960
fprintf(fp, "#if COMB_BLOCKS != %i || COMB_TEETH != %i || COMB_SPACING != %i || COMB_NEGATION != %i\n", COMB_BLOCKS, COMB_TEETH, COMB_SPACING, COMB_NEGATION);
7061
fprintf(fp, " #error configuration mismatch, invalid COMB_BLOCKS, COMB_TEETH, COMB_SPACING, or COMB_NEGATION. Try deleting ecmult_static_context.h before the build.\n");
7162
fprintf(fp, "#endif\n");
72-
#else
73-
fprintf(fp, "#if ECMULT_GEN_PREC_N != %d || ECMULT_GEN_PREC_G != %d\n", ECMULT_GEN_PREC_N, ECMULT_GEN_PREC_G);
74-
fprintf(fp, " #error configuration mismatch, invalid ECMULT_GEN_PREC_N, ECMULT_GEN_PREC_G. Try deleting ecmult_static_context.h before the build.\n");
75-
fprintf(fp, "#endif\n");
76-
#endif
7763

7864
base = checked_malloc(&default_error_callback, SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE);
7965
prealloc = base;
8066
secp256k1_ecmult_gen_context_init(&ctx);
8167
secp256k1_ecmult_gen_context_build(&ctx, &prealloc);
8268

83-
#if USE_COMB
8469
#if COMB_OFFSET
8570
secp256k1_ge_to_storage(&offset, &ctx.offset);
8671
fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_gen_ctx_offset =\n");
8772
fprintf(fp, SC_FORMAT, SECP256K1_GE_STORAGE_CONST_GET(offset));
8873
fprintf(fp, ";\n");
89-
#endif
9074
#endif
9175

9276
fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_gen_ctx_prec[%i][%i] = {\n", blocks, points);

0 commit comments

Comments
 (0)