@@ -64,9 +64,20 @@ void static secp256k1_ecmult_table_precomp_ge(secp256k1_ge_t *pre, const secp256
6464#define ECMULT_TABLE_GET_GE (r ,pre ,n ,w ) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_ge_neg)
6565
6666typedef struct {
67+ // For accelerating the computation of a*P + b*G:
6768 secp256k1_ge_t pre_g [ECMULT_TABLE_SIZE (WINDOW_G )]; // odd multiples of the generator
6869 secp256k1_ge_t pre_g_128 [ECMULT_TABLE_SIZE (WINDOW_G )]; // odd multiples of 2^128*generator
69- secp256k1_ge_t prec [64 ][16 ]; // prec[j][i] = 16^j * (i+1) * G
70+
71+ // For accelerating the computation of a*G:
72+ // To harden against timing attacks, use the following mechanism:
73+ // * Break up the multiplicand into groups of 4 bits, called n_0, n_1, n_2, ..., n_63.
74+ // * Compute sum((n_i + 1) * 16^i * G, i=0..63).
75+ // * Subtract sum(1 * 16^i * G, i=0..63).
76+ // For each i, and each of the 16 possible values of n_i, ((n_i + 1) * 16^i * G) is
77+ // precomputed (call it prec(i,n_i), as well as -sum(1 * 16^i * G) (called fin).
78+ // The formula now becomes sum(prec(i, n_i), i=0..63) + fin.
79+ // To make memory access uniform, the bytes of prec(i,n_i) are sliced per value of n_i.
80+ unsigned char prec [64 ][sizeof (secp256k1_ge_t )][16 ]; // prec[j][k][i] = k'th byte of (16^j * (i+1) * G)
7081 secp256k1_ge_t fin ; // -(sum(prec[j][0], j=0..63))
7182} secp256k1_ecmult_consts_t ;
7283
@@ -94,16 +105,21 @@ static void secp256k1_ecmult_start(void) {
94105
95106 // compute prec and fin
96107 secp256k1_gej_t gg ; secp256k1_gej_set_ge (& gg , g );
108+ secp256k1_ge_t ggn ; ggn = * g ;
97109 secp256k1_ge_t ad = * g ;
98110 secp256k1_gej_t fn ; secp256k1_gej_set_infinity (& fn );
99111 for (int j = 0 ; j < 64 ; j ++ ) {
100- secp256k1_ge_set_gej (& ret -> prec [j ][0 ], & gg );
112+ for (int k = 0 ; k < sizeof (secp256k1_ge_t ); k ++ )
113+ ret -> prec [j ][k ][0 ] = ((unsigned char * )(& ggn ))[k ];
101114 secp256k1_gej_add (& fn , & fn , & gg );
102115 for (int i = 1 ; i < 16 ; i ++ ) {
103116 secp256k1_gej_add_ge (& gg , & gg , & ad );
104- secp256k1_ge_set_gej (& ret -> prec [j ][i ], & gg );
117+ secp256k1_ge_set_gej (& ggn , & gg );
118+ if (i == 15 )
119+ ad = ggn ;
120+ for (int k = 0 ; k < sizeof (secp256k1_ge_t ); k ++ )
121+ ret -> prec [j ][k ][i ] = ((unsigned char * )(& ggn ))[k ];
105122 }
106- ad = ret -> prec [j ][15 ];
107123 }
108124 secp256k1_ge_set_gej (& ret -> fin , & fn );
109125 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)
163179 secp256k1_num_init (& n );
164180 secp256k1_num_copy (& n , gn );
165181 const secp256k1_ecmult_consts_t * c = secp256k1_ecmult_consts ;
166- secp256k1_gej_set_ge (r , & c -> prec [0 ][secp256k1_num_shift (& n , 4 )]);
167- for (int j = 1 ; j < 64 ; j ++ )
168- secp256k1_gej_add_ge (r , r , & c -> prec [j ][secp256k1_num_shift (& n , 4 )]);
182+ secp256k1_gej_set_infinity (r );
183+ for (int j = 0 ; j < 64 ; j ++ ) {
184+ secp256k1_ge_t add ;
185+ int bits = secp256k1_num_shift (& n , 4 );
186+ for (int k = 0 ; k < sizeof (secp256k1_ge_t ); k ++ )
187+ ((unsigned char * )(& add ))[k ] = c -> prec [j ][k ][bits ];
188+ secp256k1_gej_add_ge (r , r , & add );
189+ }
169190 secp256k1_num_free (& n );
170191 secp256k1_gej_add_ge (r , r , & c -> fin );
171192}
0 commit comments