Slice bytes of G multiples to avoid cache timings
This commit is contained in:
parent
55372af684
commit
65a79b300c
|
@ -64,9 +64,20 @@ void static secp256k1_ecmult_table_precomp_ge(secp256k1_ge_t *pre, const secp256
|
||||||
#define ECMULT_TABLE_GET_GE(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_ge_neg)
|
#define ECMULT_TABLE_GET_GE(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_ge_neg)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
// For accelerating the computation of a*P + b*G:
|
||||||
secp256k1_ge_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of the generator
|
secp256k1_ge_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of the generator
|
||||||
secp256k1_ge_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of 2^128*generator
|
secp256k1_ge_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of 2^128*generator
|
||||||
secp256k1_ge_t prec[64][16]; // prec[j][i] = 16^j * (i+1) * G
|
|
||||||
|
// For accelerating the computation of a*G:
|
||||||
|
// To harden against timing attacks, use the following mechanism:
|
||||||
|
// * Break up the multiplicand into groups of 4 bits, called n_0, n_1, n_2, ..., n_63.
|
||||||
|
// * Compute sum((n_i + 1) * 16^i * G, i=0..63).
|
||||||
|
// * Subtract sum(1 * 16^i * G, i=0..63).
|
||||||
|
// For each i, and each of the 16 possible values of n_i, ((n_i + 1) * 16^i * G) is
|
||||||
|
// precomputed (call it prec(i,n_i), as well as -sum(1 * 16^i * G) (called fin).
|
||||||
|
// The formula now becomes sum(prec(i, n_i), i=0..63) + fin.
|
||||||
|
// To make memory access uniform, the bytes of prec(i,n_i) are sliced per value of n_i.
|
||||||
|
unsigned char prec[64][sizeof(secp256k1_ge_t)][16]; // prec[j][k][i] = k'th byte of (16^j * (i+1) * G)
|
||||||
secp256k1_ge_t fin; // -(sum(prec[j][0], j=0..63))
|
secp256k1_ge_t fin; // -(sum(prec[j][0], j=0..63))
|
||||||
} secp256k1_ecmult_consts_t;
|
} secp256k1_ecmult_consts_t;
|
||||||
|
|
||||||
|
@ -94,16 +105,21 @@ static void secp256k1_ecmult_start(void) {
|
||||||
|
|
||||||
// compute prec and fin
|
// compute prec and fin
|
||||||
secp256k1_gej_t gg; secp256k1_gej_set_ge(&gg, g);
|
secp256k1_gej_t gg; secp256k1_gej_set_ge(&gg, g);
|
||||||
|
secp256k1_ge_t ggn; ggn = *g;
|
||||||
secp256k1_ge_t ad = *g;
|
secp256k1_ge_t ad = *g;
|
||||||
secp256k1_gej_t fn; secp256k1_gej_set_infinity(&fn);
|
secp256k1_gej_t fn; secp256k1_gej_set_infinity(&fn);
|
||||||
for (int j=0; j<64; j++) {
|
for (int j=0; j<64; j++) {
|
||||||
secp256k1_ge_set_gej(&ret->prec[j][0], &gg);
|
for (int k=0; k<sizeof(secp256k1_ge_t); k++)
|
||||||
|
ret->prec[j][k][0] = ((unsigned char*)(&ggn))[k];
|
||||||
secp256k1_gej_add(&fn, &fn, &gg);
|
secp256k1_gej_add(&fn, &fn, &gg);
|
||||||
for (int i=1; i<16; i++) {
|
for (int i=1; i<16; i++) {
|
||||||
secp256k1_gej_add_ge(&gg, &gg, &ad);
|
secp256k1_gej_add_ge(&gg, &gg, &ad);
|
||||||
secp256k1_ge_set_gej(&ret->prec[j][i], &gg);
|
secp256k1_ge_set_gej(&ggn, &gg);
|
||||||
|
if (i == 15)
|
||||||
|
ad = ggn;
|
||||||
|
for (int k=0; k<sizeof(secp256k1_ge_t); k++)
|
||||||
|
ret->prec[j][k][i] = ((unsigned char*)(&ggn))[k];
|
||||||
}
|
}
|
||||||
ad = ret->prec[j][15];
|
|
||||||
}
|
}
|
||||||
secp256k1_ge_set_gej(&ret->fin, &fn);
|
secp256k1_ge_set_gej(&ret->fin, &fn);
|
||||||
secp256k1_ge_neg(&ret->fin, &ret->fin);
|
secp256k1_ge_neg(&ret->fin, &ret->fin);
|
||||||
|
@ -163,9 +179,14 @@ void static secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *gn)
|
||||||
secp256k1_num_init(&n);
|
secp256k1_num_init(&n);
|
||||||
secp256k1_num_copy(&n, gn);
|
secp256k1_num_copy(&n, gn);
|
||||||
const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts;
|
const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts;
|
||||||
secp256k1_gej_set_ge(r, &c->prec[0][secp256k1_num_shift(&n, 4)]);
|
secp256k1_gej_set_infinity(r);
|
||||||
for (int j=1; j<64; j++)
|
for (int j=0; j<64; j++) {
|
||||||
secp256k1_gej_add_ge(r, r, &c->prec[j][secp256k1_num_shift(&n, 4)]);
|
secp256k1_ge_t add;
|
||||||
|
int bits = secp256k1_num_shift(&n, 4);
|
||||||
|
for (int k=0; k<sizeof(secp256k1_ge_t); k++)
|
||||||
|
((unsigned char*)(&add))[k] = c->prec[j][k][bits];
|
||||||
|
secp256k1_gej_add_ge(r, r, &add);
|
||||||
|
}
|
||||||
secp256k1_num_free(&n);
|
secp256k1_num_free(&n);
|
||||||
secp256k1_gej_add_ge(r, r, &c->fin);
|
secp256k1_gej_add_ge(r, r, &c->fin);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue