From da55986fdfa585e23a061591d2ec340733a4ec0e Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 4 Nov 2014 02:34:11 -0800 Subject: [PATCH] Label variable-time functions correctly and don't use those in sign --- src/ecdsa_impl.h | 4 ++-- src/ecmult_gen_impl.h | 17 ++++++++++------- src/ecmult_impl.h | 36 ++++++++++++++++++------------------ src/group.h | 12 ++++++------ src/group_impl.h | 28 ++++++++++++++++++++-------- 5 files changed, 56 insertions(+), 41 deletions(-) diff --git a/src/ecdsa_impl.h b/src/ecdsa_impl.h index 264a00176f..5a8fc4333a 100644 --- a/src/ecdsa_impl.h +++ b/src/ecdsa_impl.h @@ -70,7 +70,7 @@ int static secp256k1_ecdsa_sig_recompute(secp256k1_num_t *r2, const secp256k1_ec secp256k1_gej_t pubkeyj; secp256k1_gej_set_ge(&pubkeyj, pubkey); secp256k1_gej_t pr; secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1); if (!secp256k1_gej_is_infinity(&pr)) { - secp256k1_fe_t xr; secp256k1_gej_get_x(&xr, &pr); + secp256k1_fe_t xr; secp256k1_gej_get_x_var(&xr, &pr); secp256k1_fe_normalize(&xr); unsigned char xrb[32]; secp256k1_fe_get_b32(xrb, &xr); secp256k1_num_set_bin(r2, xrb, 32); @@ -121,7 +121,7 @@ int static secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256 secp256k1_num_mod_mul(&u2, &rn, &sig->s, &c->order); secp256k1_gej_t qj; secp256k1_ecmult(&qj, &xj, &u2, &u1); - secp256k1_ge_set_gej(pubkey, &qj); + secp256k1_ge_set_gej_var(pubkey, &qj); secp256k1_num_free(&rn); secp256k1_num_free(&u1); secp256k1_num_free(&u2); diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index a81c494e2d..976569ca43 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -49,7 +49,7 @@ static void secp256k1_ecmult_gen_start(void) { VERIFY_CHECK(secp256k1_ge_set_xo(&nums_ge, &nums_x, 0)); secp256k1_gej_set_ge(&nums_gej, &nums_ge); // Add G to make the bits in x uniformly distributed. - secp256k1_gej_add_ge(&nums_gej, &nums_gej, g); + secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, g); } // compute prec. @@ -63,21 +63,21 @@ static void secp256k1_ecmult_gen_start(void) { // Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). precj[j*16] = numsbase; for (int i=1; i<16; i++) { - secp256k1_gej_add(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase); + secp256k1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase); } // Multiply gbase by 16. for (int i=0; i<4; i++) { - secp256k1_gej_double(&gbase, &gbase); + secp256k1_gej_double_var(&gbase, &gbase); } // Multiply numbase by 2. - secp256k1_gej_double(&numsbase, &numsbase); + secp256k1_gej_double_var(&numsbase, &numsbase); if (j == 62) { // In the last iteration, numsbase is (1 - 2^j) * nums instead. secp256k1_gej_neg(&numsbase, &numsbase); - secp256k1_gej_add(&numsbase, &numsbase, &nums_gej); + secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej); } } - secp256k1_ge_set_all_gej(1024, prec, precj); + secp256k1_ge_set_all_gej_var(1024, prec, precj); } for (int j=0; j<64; j++) { for (int i=0; i<16; i++) { @@ -109,7 +109,10 @@ void static secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_scalar_t *g bits = secp256k1_scalar_get_bits(gn, j * 4, 4); for (int k=0; kprec[j][k][bits]; - secp256k1_gej_add_ge(r, r, &add); + // Note that the next line uses a variable-time addition function, which + // is fine, as the inputs are blinded (they have no known corresponding + // private key). + secp256k1_gej_add_ge_var(r, r, &add); } bits = 0; secp256k1_ge_clear(&add); diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h index 4c4806e2ac..c0e4b116b0 100644 --- a/src/ecmult_impl.h +++ b/src/ecmult_impl.h @@ -29,22 +29,22 @@ * To compute a*P + b*G, we use the jacobian version for P, and the affine version for G, as * G is constant, so it only needs to be done once in advance. */ -void static secp256k1_ecmult_table_precomp_gej(secp256k1_gej_t *pre, const secp256k1_gej_t *a, int w) { +void static secp256k1_ecmult_table_precomp_gej_var(secp256k1_gej_t *pre, const secp256k1_gej_t *a, int w) { pre[0] = *a; - secp256k1_gej_t d; secp256k1_gej_double(&d, &pre[0]); + secp256k1_gej_t d; secp256k1_gej_double_var(&d, &pre[0]); for (int i=1; i<(1 << (w-2)); i++) - secp256k1_gej_add(&pre[i], &d, &pre[i-1]); + secp256k1_gej_add_var(&pre[i], &d, &pre[i-1]); } -void static secp256k1_ecmult_table_precomp_ge(secp256k1_ge_t *pre, const secp256k1_gej_t *a, int w) { +void static secp256k1_ecmult_table_precomp_ge_var(secp256k1_ge_t *pre, const secp256k1_gej_t *a, int w) { const int table_size = 1 << (w-2); secp256k1_gej_t prej[table_size]; prej[0] = *a; - secp256k1_gej_t d; secp256k1_gej_double(&d, a); + secp256k1_gej_t d; secp256k1_gej_double_var(&d, a); for (int i=1; ipre_g, &gj, WINDOW_G); - secp256k1_ecmult_table_precomp_ge(ret->pre_g_128, &g_128j, WINDOW_G); + secp256k1_ecmult_table_precomp_ge_var(ret->pre_g, &gj, WINDOW_G); + secp256k1_ecmult_table_precomp_ge_var(ret->pre_g_128, &g_128j, WINDOW_G); // Set the global pointer to the precomputation table. secp256k1_ecmult_consts = ret; @@ -150,7 +150,7 @@ void static secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const #ifdef USE_ENDOMORPHISM secp256k1_num_t na_1, na_lam; // split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) - secp256k1_gej_split_exp(&na_1, &na_lam, na); + secp256k1_gej_split_exp_var(&na_1, &na_lam, na); // build wnaf representation for na_1 and na_lam. int wnaf_na_1[129]; int bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A); @@ -165,7 +165,7 @@ void static secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const // calculate odd multiples of a secp256k1_gej_t pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_ecmult_table_precomp_gej(pre_a, a, WINDOW_A); + secp256k1_ecmult_table_precomp_gej_var(pre_a, a, WINDOW_A); #ifdef USE_ENDOMORPHISM secp256k1_gej_t pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; @@ -190,30 +190,30 @@ void static secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t tmpa; for (int i=bits-1; i>=0; i--) { - secp256k1_gej_double(r, r); + secp256k1_gej_double_var(r, r); int n; #ifdef USE_ENDOMORPHISM if (i < bits_na_1 && (n = wnaf_na_1[i])) { ECMULT_TABLE_GET_GEJ(&tmpj, pre_a, n, WINDOW_A); - secp256k1_gej_add(r, r, &tmpj); + secp256k1_gej_add_var(r, r, &tmpj); } if (i < bits_na_lam && (n = wnaf_na_lam[i])) { ECMULT_TABLE_GET_GEJ(&tmpj, pre_a_lam, n, WINDOW_A); - secp256k1_gej_add(r, r, &tmpj); + secp256k1_gej_add_var(r, r, &tmpj); } #else if (i < bits_na && (n = wnaf_na[i])) { ECMULT_TABLE_GET_GEJ(&tmpj, pre_a, n, WINDOW_A); - secp256k1_gej_add(r, r, &tmpj); + secp256k1_gej_add_var(r, r, &tmpj); } #endif if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { ECMULT_TABLE_GET_GE(&tmpa, c->pre_g, n, WINDOW_G); - secp256k1_gej_add_ge(r, r, &tmpa); + secp256k1_gej_add_ge_var(r, r, &tmpa); } if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { ECMULT_TABLE_GET_GE(&tmpa, c->pre_g_128, n, WINDOW_G); - secp256k1_gej_add_ge(r, r, &tmpa); + secp256k1_gej_add_ge_var(r, r, &tmpa); } } } diff --git a/src/group.h b/src/group.h index aea5658c12..fde1e1365f 100644 --- a/src/group.h +++ b/src/group.h @@ -69,7 +69,7 @@ void static secp256k1_ge_get_hex(char *r, int *rlen, const secp256k1_ge_t *a); void static secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a); /** Set a batch of group elements equal to the inputs given in jacobian coordinates */ -void static secp256k1_ge_set_all_gej(size_t len, secp256k1_ge_t r[len], const secp256k1_gej_t a[len]); +void static secp256k1_ge_set_all_gej_var(size_t len, secp256k1_ge_t r[len], const secp256k1_gej_t a[len]); /** Set a group element (jacobian) equal to the point at infinity. */ @@ -82,7 +82,7 @@ void static secp256k1_gej_set_xy(secp256k1_gej_t *r, const secp256k1_fe_t *x, co void static secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a); /** Get the X coordinate of a group element (jacobian). */ -void static secp256k1_gej_get_x(secp256k1_fe_t *r, const secp256k1_gej_t *a); +void static secp256k1_gej_get_x_var(secp256k1_fe_t *r, const secp256k1_gej_t *a); /** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ void static secp256k1_gej_neg(secp256k1_gej_t *r, const secp256k1_gej_t *a); @@ -91,14 +91,14 @@ void static secp256k1_gej_neg(secp256k1_gej_t *r, const secp256k1_gej_t *a); int static secp256k1_gej_is_infinity(const secp256k1_gej_t *a); /** Set r equal to the double of a. */ -void static secp256k1_gej_double(secp256k1_gej_t *r, const secp256k1_gej_t *a); +void static secp256k1_gej_double_var(secp256k1_gej_t *r, const secp256k1_gej_t *a); /** Set r equal to the sum of a and b. */ -void static secp256k1_gej_add(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_t *b); +void static secp256k1_gej_add_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_t *b); /** Set r equal to the sum of a and b (with b given in affine coordinates). This is more efficient than secp256k1_gej_add. */ -void static secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b); +void static secp256k1_gej_add_ge_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b); /** Get a hex representation of a point. *rlen will be overwritten with the real length. */ void static secp256k1_gej_get_hex(char *r, int *rlen, const secp256k1_gej_t *a); @@ -109,7 +109,7 @@ void static secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t * /** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (given that a is not more than 256 bits). */ -void static secp256k1_gej_split_exp(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a); +void static secp256k1_gej_split_exp_var(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a); #endif /** Clear a secp256k1_gej_t to prevent leaking sensitive information. */ diff --git a/src/group_impl.h b/src/group_impl.h index 4c39382102..446ddf9daf 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -55,6 +55,18 @@ void static secp256k1_ge_get_hex(char *r, int *rlen, const secp256k1_ge_t *a) { } void static secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a) { + r->infinity = a->infinity; + secp256k1_fe_inv(&a->z, &a->z); + secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &a->z); + secp256k1_fe_t z3; secp256k1_fe_mul(&z3, &a->z, &z2); + secp256k1_fe_mul(&a->x, &a->x, &z2); + secp256k1_fe_mul(&a->y, &a->y, &z3); + secp256k1_fe_set_int(&a->z, 1); + r->x = a->x; + r->y = a->y; +} + +void static secp256k1_ge_set_gej_var(secp256k1_ge_t *r, secp256k1_gej_t *a) { r->infinity = a->infinity; if (a->infinity) { return; @@ -69,7 +81,7 @@ void static secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a) { r->y = a->y; } -void static secp256k1_ge_set_all_gej(size_t len, secp256k1_ge_t r[len], const secp256k1_gej_t a[len]) { +void static secp256k1_ge_set_all_gej_var(size_t len, secp256k1_ge_t r[len], const secp256k1_gej_t a[len]) { int count = 0; secp256k1_fe_t az[len]; for (int i=0; iz, 1); } -void static secp256k1_gej_get_x(secp256k1_fe_t *r, const secp256k1_gej_t *a) { +void static secp256k1_gej_get_x_var(secp256k1_fe_t *r, const secp256k1_gej_t *a) { secp256k1_fe_t zi2; secp256k1_fe_inv_var(&zi2, &a->z); secp256k1_fe_sqr(&zi2, &zi2); secp256k1_fe_mul(r, &a->x, &zi2); } @@ -189,7 +201,7 @@ int static secp256k1_ge_is_valid(const secp256k1_ge_t *a) { return secp256k1_fe_equal(&y2, &x3); } -void static secp256k1_gej_double(secp256k1_gej_t *r, const secp256k1_gej_t *a) { +void static secp256k1_gej_double_var(secp256k1_gej_t *r, const secp256k1_gej_t *a) { if (a->infinity) { r->infinity = 1; return; @@ -226,7 +238,7 @@ void static secp256k1_gej_double(secp256k1_gej_t *r, const secp256k1_gej_t *a) { r->infinity = 0; } -void static secp256k1_gej_add(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_t *b) { +void static secp256k1_gej_add_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_t *b) { if (a->infinity) { *r = *b; return; @@ -248,7 +260,7 @@ void static secp256k1_gej_add(secp256k1_gej_t *r, const secp256k1_gej_t *a, cons secp256k1_fe_normalize(&s1); secp256k1_fe_normalize(&s2); if (secp256k1_fe_equal(&s1, &s2)) { - secp256k1_gej_double(r, a); + secp256k1_gej_double_var(r, a); } else { r->infinity = 1; } @@ -267,7 +279,7 @@ void static secp256k1_gej_add(secp256k1_gej_t *r, const secp256k1_gej_t *a, cons secp256k1_fe_add(&r->y, &h3); } -void static secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b) { +void static secp256k1_gej_add_ge_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b) { if (a->infinity) { r->infinity = b->infinity; r->x = b->x; @@ -291,7 +303,7 @@ void static secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, c secp256k1_fe_normalize(&s1); secp256k1_fe_normalize(&s2); if (secp256k1_fe_equal(&s1, &s2)) { - secp256k1_gej_double(r, a); + secp256k1_gej_double_var(r, a); } else { r->infinity = 1; } @@ -323,7 +335,7 @@ void static secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t * secp256k1_fe_mul(&r->x, &r->x, beta); } -void static secp256k1_gej_split_exp(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a) { +void static secp256k1_gej_split_exp_var(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a) { const secp256k1_ge_consts_t *c = secp256k1_ge_consts; secp256k1_num_t bnc1, bnc2, bnt1, bnt2, bnn2;