From 65a79b300ca23f552e95e5dcd4cefd9e95eafc78 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 6 Mar 2014 11:40:24 +0100 Subject: [PATCH] Slice bytes of G multiples to avoid cache timings --- src/impl/ecmult.h | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/impl/ecmult.h b/src/impl/ecmult.h index c6711ac..9b1b2ac 100644 --- a/src/impl/ecmult.h +++ b/src/impl/ecmult.h @@ -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) 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_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_ecmult_consts_t; @@ -94,16 +105,21 @@ static void secp256k1_ecmult_start(void) { // compute prec and fin secp256k1_gej_t gg; secp256k1_gej_set_ge(&gg, g); + secp256k1_ge_t ggn; ggn = *g; secp256k1_ge_t ad = *g; secp256k1_gej_t fn; secp256k1_gej_set_infinity(&fn); for (int j=0; j<64; j++) { - secp256k1_ge_set_gej(&ret->prec[j][0], &gg); + for (int k=0; kprec[j][k][0] = ((unsigned char*)(&ggn))[k]; secp256k1_gej_add(&fn, &fn, &gg); for (int i=1; i<16; i++) { 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; kprec[j][k][i] = ((unsigned char*)(&ggn))[k]; } - ad = ret->prec[j][15]; } secp256k1_ge_set_gej(&ret->fin, &fn); 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_copy(&n, gn); const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts; - secp256k1_gej_set_ge(r, &c->prec[0][secp256k1_num_shift(&n, 4)]); - for (int j=1; j<64; j++) - secp256k1_gej_add_ge(r, r, &c->prec[j][secp256k1_num_shift(&n, 4)]); + secp256k1_gej_set_infinity(r); + for (int j=0; j<64; j++) { + secp256k1_ge_t add; + int bits = secp256k1_num_shift(&n, 4); + for (int k=0; kprec[j][k][bits]; + secp256k1_gej_add_ge(r, r, &add); + } secp256k1_num_free(&n); secp256k1_gej_add_ge(r, r, &c->fin); }