diff --git a/Makefile.am b/Makefile.am index a9df7d50469..adf778d802c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,6 +14,8 @@ noinst_HEADERS += src/ecdsa.h noinst_HEADERS += src/ecdsa_impl.h noinst_HEADERS += src/ecmult.h noinst_HEADERS += src/ecmult_impl.h +noinst_HEADERS += src/ecmult_gen.h +noinst_HEADERS += src/ecmult_gen_impl.h noinst_HEADERS += src/num.h noinst_HEADERS += src/num_impl.h noinst_HEADERS += src/field_10x26.h diff --git a/src/ecdsa_impl.h b/src/ecdsa_impl.h index 71762abebe4..236108c92ae 100644 --- a/src/ecdsa_impl.h +++ b/src/ecdsa_impl.h @@ -9,6 +9,7 @@ #include "field.h" #include "group.h" #include "ecmult.h" +#include "ecmult_gen.h" #include "ecdsa.h" void static secp256k1_ecdsa_sig_init(secp256k1_ecdsa_sig_t *r) { diff --git a/src/ecmult.h b/src/ecmult.h index 856bd284fe9..7d74b5e4620 100644 --- a/src/ecmult.h +++ b/src/ecmult.h @@ -1,5 +1,5 @@ -// Copyright (c) 2013 Pieter Wuille -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2013-2014 Pieter Wuille +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef _SECP256K1_ECMULT_ @@ -11,8 +11,6 @@ static void secp256k1_ecmult_start(void); static void secp256k1_ecmult_stop(void); -/** Multiply with the generator: R = a*G */ -static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *a); /** Double multiply: R = na*A + ng*G */ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng); diff --git a/src/ecmult_gen.h b/src/ecmult_gen.h new file mode 100644 index 00000000000..b71b6a96a4c --- /dev/null +++ b/src/ecmult_gen.h @@ -0,0 +1,17 @@ +// Copyright (c) 2013-2014 Pieter Wuille +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef _SECP256K1_ECMULT_GEN_ +#define _SECP256K1_ECMULT_GEN_ + +#include "num.h" +#include "group.h" + +static void secp256k1_ecmult_gen_start(void); +static void secp256k1_ecmult_gen_stop(void); + +/** Multiply with the generator: R = a*G */ +static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *a); + +#endif diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h new file mode 100644 index 00000000000..9fa3dc4ce7f --- /dev/null +++ b/src/ecmult_gen_impl.h @@ -0,0 +1,123 @@ +// Copyright (c) 2013-2014 Pieter Wuille +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef _SECP256K1_ECMULT_GEN_IMPL_H_ +#define _SECP256K1_ECMULT_GEN_IMPL_H_ + +#include +#include "num.h" +#include "group.h" +#include "ecmult_gen.h" + +typedef struct { + // 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 * 16^i * G + U_i, i=0..63), where: + // * U_i = U * 2^i (for i=0..62) + // * U_i = U * (1-2^63) (for i=63) + // where U is a point with no known corresponding scalar. Note that sum(U_i, i=0..63) = 0. + // For each i, and each of the 16 possible values of n_i, (n_i * 16^i * G + U_i) is + // precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63). + // None of the resulting prec group elements have a known scalar, and neither do any of + // the intermediate sums while computing a*G. + // 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 * G + U_i) +} secp256k1_ecmult_gen_consts_t; + +static const secp256k1_ecmult_gen_consts_t *secp256k1_ecmult_gen_consts = NULL; + +static void secp256k1_ecmult_gen_start(void) { + if (secp256k1_ecmult_gen_consts != NULL) + return; + + // Allocate the precomputation table. + secp256k1_ecmult_gen_consts_t *ret = (secp256k1_ecmult_gen_consts_t*)malloc(sizeof(secp256k1_ecmult_gen_consts_t)); + + // get the generator + const secp256k1_ge_t *g = &secp256k1_ge_consts->g; + secp256k1_gej_t gj; secp256k1_gej_set_ge(&gj, g); + + // Construct a group element with no known corresponding scalar (nothing up my sleeve). + secp256k1_gej_t nums_gej; + { + static const unsigned char nums_b32[32] = "The scalar for this x is unknown"; + secp256k1_fe_t nums_x; + secp256k1_fe_set_b32(&nums_x, nums_b32); + secp256k1_ge_t nums_ge; + 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); + } + + // compute prec. + secp256k1_ge_t prec[1024]; + { + secp256k1_gej_t precj[1024]; // Jacobian versions of prec. + int j = 0; + secp256k1_gej_t gbase; gbase = gj; // 16^j * G + secp256k1_gej_t numsbase; numsbase = nums_gej; // 2^j * nums. + for (int j=0; j<64; j++) { + // 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); + } + // Multiply gbase by 16. + for (int i=0; i<4; i++) { + secp256k1_gej_double(&gbase, &gbase); + } + // Multiply numbase by 2. + secp256k1_gej_double(&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_ge_set_all_gej(1024, prec, precj); + } + for (int j=0; j<64; j++) { + for (int i=0; i<16; i++) { + const unsigned char* raw = (const unsigned char*)(&prec[j*16 + i]); + for (int k=0; kprec[j][k][i] = raw[k]; + } + } + + // Set the global pointer to the precomputation table. + secp256k1_ecmult_gen_consts = ret; +} + +static void secp256k1_ecmult_gen_stop(void) { + if (secp256k1_ecmult_gen_consts == NULL) + return; + + secp256k1_ecmult_gen_consts_t *c = (secp256k1_ecmult_gen_consts_t*)secp256k1_ecmult_gen_consts; + secp256k1_ecmult_gen_consts = NULL; + free(c); +} + +void static secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *gn) { + secp256k1_num_t n; + secp256k1_num_init(&n); + secp256k1_num_copy(&n, gn); + const secp256k1_ecmult_gen_consts_t *c = secp256k1_ecmult_gen_consts; + secp256k1_gej_set_infinity(r); + secp256k1_ge_t add; + int bits; + for (int j=0; j<64; j++) { + bits = secp256k1_num_shift(&n, 4); + for (int k=0; kprec[j][k][bits]; + secp256k1_gej_add_ge(r, r, &add); + } + bits = 0; + secp256k1_ge_clear(&add); + secp256k1_num_clear(&n); + secp256k1_num_free(&n); +} + +#endif diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h index 1b575aa5ecd..06eb8ddc787 100644 --- a/src/ecmult_impl.h +++ b/src/ecmult_impl.h @@ -1,5 +1,5 @@ -// Copyright (c) 2013 Pieter Wuille -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2013-2014 Pieter Wuille +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef _SECP256K1_ECMULT_IMPL_H_ @@ -71,24 +71,7 @@ typedef struct { secp256k1_ge_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of 2^128*generator } secp256k1_ecmult_consts_t; -typedef struct { - // 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 * 16^i * G + U_i, i=0..63), where: - // * U_i = U * 2^i (for i=0..62) - // * U_i = U * (1-2^63) (for i=63) - // where U is a point with no known corresponding scalar. Note that sum(U_i, i=0..63) = 0. - // For each i, and each of the 16 possible values of n_i, (n_i * 16^i * G + U_i) is - // precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63). - // None of the resulting prec group elements have a known scalar, and neither do any of - // the intermediate sums while computing a*G. - // 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 * G + U_i) -} secp256k1_ecmult_gen_consts_t; - static const secp256k1_ecmult_consts_t *secp256k1_ecmult_consts = NULL; -static const secp256k1_ecmult_gen_consts_t *secp256k1_ecmult_gen_consts = NULL; static void secp256k1_ecmult_start(void) { if (secp256k1_ecmult_consts != NULL) @@ -114,69 +97,6 @@ static void secp256k1_ecmult_start(void) { secp256k1_ecmult_consts = ret; } -static void secp256k1_ecmult_gen_start(void) { - if (secp256k1_ecmult_gen_consts != NULL) - return; - - // Allocate the precomputation table. - secp256k1_ecmult_gen_consts_t *ret = (secp256k1_ecmult_gen_consts_t*)malloc(sizeof(secp256k1_ecmult_gen_consts_t)); - - // get the generator - const secp256k1_ge_t *g = &secp256k1_ge_consts->g; - secp256k1_gej_t gj; secp256k1_gej_set_ge(&gj, g); - - // Construct a group element with no known corresponding scalar (nothing up my sleeve). - secp256k1_gej_t nums_gej; - { - static const unsigned char nums_b32[32] = "The scalar for this x is unknown"; - secp256k1_fe_t nums_x; - secp256k1_fe_set_b32(&nums_x, nums_b32); - secp256k1_ge_t nums_ge; - 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); - } - - // compute prec. - secp256k1_ge_t prec[1024]; - { - secp256k1_gej_t precj[1024]; // Jacobian versions of prec. - int j = 0; - secp256k1_gej_t gbase; gbase = gj; // 16^j * G - secp256k1_gej_t numsbase; numsbase = nums_gej; // 2^j * nums. - for (int j=0; j<64; j++) { - // 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); - } - // Multiply gbase by 16. - for (int i=0; i<4; i++) { - secp256k1_gej_double(&gbase, &gbase); - } - // Multiply numbase by 2. - secp256k1_gej_double(&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_ge_set_all_gej(1024, prec, precj); - } - for (int j=0; j<64; j++) { - for (int i=0; i<16; i++) { - const unsigned char* raw = (const unsigned char*)(&prec[j*16 + i]); - for (int k=0; kprec[j][k][i] = raw[k]; - } - } - - // Set the global pointer to the precomputation table. - secp256k1_ecmult_gen_consts = ret; -} - static void secp256k1_ecmult_stop(void) { if (secp256k1_ecmult_consts == NULL) return; @@ -186,15 +106,6 @@ static void secp256k1_ecmult_stop(void) { free(c); } -static void secp256k1_ecmult_gen_stop(void) { - if (secp256k1_ecmult_gen_consts == NULL) - return; - - secp256k1_ecmult_gen_consts_t *c = (secp256k1_ecmult_gen_consts_t*)secp256k1_ecmult_gen_consts; - secp256k1_ecmult_gen_consts = NULL; - free(c); -} - /** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits), * with the following guarantees: * - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) @@ -235,26 +146,6 @@ static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_num_t *a, int w) { return ret; } -void static secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *gn) { - secp256k1_num_t n; - secp256k1_num_init(&n); - secp256k1_num_copy(&n, gn); - const secp256k1_ecmult_gen_consts_t *c = secp256k1_ecmult_gen_consts; - secp256k1_gej_set_infinity(r); - secp256k1_ge_t add; - int bits; - for (int j=0; j<64; j++) { - bits = secp256k1_num_shift(&n, 4); - for (int k=0; kprec[j][k][bits]; - secp256k1_gej_add_ge(r, r, &add); - } - bits = 0; - secp256k1_ge_clear(&add); - secp256k1_num_clear(&n); - secp256k1_num_free(&n); -} - void static secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng) { const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts; diff --git a/src/secp256k1.c b/src/secp256k1.c index 1a6854e5734..b1ef48d4f69 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -10,6 +10,7 @@ #include "field_impl.h" #include "group_impl.h" #include "ecmult_impl.h" +#include "ecmult_gen_impl.h" #include "ecdsa_impl.h" void secp256k1_start(unsigned int flags) {