Skip to content

Commit efb7d4b

Browse files
committed
Use constant-time conditional moves instead of byte slicing
1 parent d220062 commit efb7d4b

File tree

7 files changed

+55
-10
lines changed

7 files changed

+55
-10
lines changed

src/ecmult_gen_impl.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ typedef struct {
2323
* precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63).
2424
* None of the resulting prec group elements have a known scalar, and neither do any of
2525
* the intermediate sums while computing a*G.
26-
* To make memory access uniform, the bytes of prec(i, n_i) are sliced per value of n_i. */
27-
unsigned char prec[64][sizeof(secp256k1_ge_t)][16]; /* prec[j][k][i] = k'th byte of (16^j * i * G + U_i) */
26+
*/
27+
secp256k1_fe_t prec[64][16][2]; /* prec[j][i] = (16^j * i * G + U_i).{x,y} */
2828
} secp256k1_ecmult_gen_consts_t;
2929

3030
static const secp256k1_ecmult_gen_consts_t *secp256k1_ecmult_gen_consts = NULL;
@@ -81,9 +81,9 @@ static void secp256k1_ecmult_gen_start(void) {
8181
}
8282
for (int j=0; j<64; j++) {
8383
for (int i=0; i<16; i++) {
84-
const unsigned char* raw = (const unsigned char*)(&prec[j*16 + i]);
85-
for (size_t k=0; k<sizeof(secp256k1_ge_t); k++)
86-
ret->prec[j][k][i] = raw[k];
84+
VERIFY_CHECK(!secp256k1_ge_is_infinity(&prec[j*16 + i]));
85+
ret->prec[j][i][0] = prec[j*16 + i].x;
86+
ret->prec[j][i][1] = prec[j*16 + i].y;
8787
}
8888
}
8989

@@ -104,11 +104,14 @@ static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_scalar_t *g
104104
const secp256k1_ecmult_gen_consts_t *c = secp256k1_ecmult_gen_consts;
105105
secp256k1_gej_set_infinity(r);
106106
secp256k1_ge_t add;
107+
add.infinity = 0;
107108
int bits;
108109
for (int j=0; j<64; j++) {
109110
bits = secp256k1_scalar_get_bits(gn, j * 4, 4);
110-
for (size_t k=0; k<sizeof(secp256k1_ge_t); k++)
111-
((unsigned char*)(&add))[k] = c->prec[j][k][bits];
111+
for (int i=0; i<16; i++) {
112+
secp256k1_fe_cmov(&add.x, &c->prec[j][i][0], i == bits);
113+
secp256k1_fe_cmov(&add.y, &c->prec[j][i][1], i == bits);
114+
}
112115
secp256k1_gej_add_ge(r, r, &add);
113116
}
114117
bits = 0;

src/field.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,13 @@ static void secp256k1_fe_inv_all(size_t len, secp256k1_fe_t r[len], const secp25
110110
/** Potentially faster version of secp256k1_fe_inv_all, without constant-time guarantee. */
111111
static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe_t r[len], const secp256k1_fe_t a[len]);
112112

113-
114113
/** Convert a field element to a hexadecimal string. */
115114
static void secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a);
116115

117116
/** Convert a hexadecimal string to a field element. */
118117
static int secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen);
119118

119+
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */
120+
static void secp256k1_fe_cmov(secp256k1_fe_t *r, const secp256k1_fe_t *a, int flag);
121+
120122
#endif

src/field_10x26_impl.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,4 +900,24 @@ static void secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
900900
#endif
901901
}
902902

903+
static void secp256k1_fe_cmov(secp256k1_fe_t *r, const secp256k1_fe_t *a, int flag) {
904+
uint32_t mask0 = flag + ~((uint32_t)0), mask1 = ~mask0;
905+
r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);
906+
r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1);
907+
r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1);
908+
r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1);
909+
r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1);
910+
r->n[5] = (r->n[5] & mask0) | (a->n[5] & mask1);
911+
r->n[6] = (r->n[6] & mask0) | (a->n[6] & mask1);
912+
r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1);
913+
r->n[8] = (r->n[8] & mask0) | (a->n[8] & mask1);
914+
r->n[9] = (r->n[9] & mask0) | (a->n[9] & mask1);
915+
#ifdef VERIFY
916+
if (flag) {
917+
r->magnitude = a->magnitude;
918+
r->normalized = a->normalized;
919+
}
920+
#endif
921+
}
922+
903923
#endif

src/field_5x52_impl.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,4 +276,19 @@ static void secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
276276
#endif
277277
}
278278

279+
static void secp256k1_fe_cmov(secp256k1_fe_t *r, const secp256k1_fe_t *a, int flag) {
280+
uint64_t mask0 = flag + ~((uint64_t)0), mask1 = ~mask0;
281+
r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);
282+
r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1);
283+
r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1);
284+
r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1);
285+
r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1);
286+
#ifdef VERIFY
287+
if (flag) {
288+
r->magnitude = a->magnitude;
289+
r->normalized = a->normalized;
290+
}
291+
#endif
292+
}
293+
279294
#endif

src/field_gmp_impl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,4 +170,11 @@ static void secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
170170
secp256k1_fe_reduce(r, tmp);
171171
}
172172

173+
static void secp256k1_fe_cmov(secp256k1_fe_t *r, const secp256k1_fe_t *a, int flag) {
174+
mp_limb_t mask0 = flag + ~((mp_limb_t)0), mask1 = ~mask0;
175+
for (int i = 0; i <= FIELD_LIMBS; i++) {
176+
r->n[i] = (r->n[i] & mask0) | (a->n[i] & mask1);
177+
}
178+
}
179+
173180
#endif

src/group.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,5 +117,4 @@ static void secp256k1_gej_clear(secp256k1_gej_t *r);
117117
/** Clear a secp256k1_ge_t to prevent leaking sensitive information. */
118118
static void secp256k1_ge_clear(secp256k1_ge_t *r);
119119

120-
121120
#endif

src/group_impl.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,6 @@ static void secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *
411411
}
412412
#endif
413413

414-
415414
static void secp256k1_ge_start(void) {
416415
static const unsigned char secp256k1_ge_consts_g_x[] = {
417416
0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,

0 commit comments

Comments
 (0)