diff --git a/Makefile.am b/Makefile.am index aa8014f..d07e7bc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -28,6 +28,8 @@ noinst_HEADERS += src/ecmult_const.h noinst_HEADERS += src/ecmult_const_impl.h noinst_HEADERS += src/ecmult_gen.h noinst_HEADERS += src/ecmult_gen_impl.h +noinst_HEADERS += src/ecmult_gen_prec.h +noinst_HEADERS += src/ecmult_gen_prec_impl.h noinst_HEADERS += src/field_10x26.h noinst_HEADERS += src/field_10x26_impl.h noinst_HEADERS += src/field_5x52.h @@ -143,6 +145,7 @@ $(gen_context_BIN): $(gen_context_OBJECTS) $(libsecp256k1_la_OBJECTS): src/ecmult_static_context.h $(tests_OBJECTS): src/ecmult_static_context.h +$(exhaustive_tests_OBJECTS): src/ecmult_static_context.h $(bench_internal_OBJECTS): src/ecmult_static_context.h $(bench_ecmult_OBJECTS): src/ecmult_static_context.h diff --git a/configure.ac b/configure.ac index 48705c9..82d1965 100644 --- a/configure.ac +++ b/configure.ac @@ -125,10 +125,8 @@ AC_ARG_ENABLE(exhaustive_tests, [use_exhaustive_tests=$enableval], [use_exhaustive_tests=yes]) -AC_ARG_ENABLE(ecmult_static_precomputation, - AS_HELP_STRING([--enable-ecmult-static-precomputation],[enable precomputed ecmult table for signing [default=auto]]), - [use_ecmult_static_precomputation=$enableval], - [use_ecmult_static_precomputation=auto]) +# Force static precomputation. The code handling this will be removed in a later commit. +use_ecmult_static_precomputation=yes AC_ARG_ENABLE(module_ecdh, AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation]), diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index 384a67f..0a9b5c4 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -12,92 +12,20 @@ #include "group.h" #include "ecmult_gen.h" #include "hash_impl.h" -#ifdef USE_ECMULT_STATIC_PRECOMPUTATION #include "ecmult_static_context.h" -#endif -#ifndef USE_ECMULT_STATIC_PRECOMPUTATION - static const size_t SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE = ROUND_TO_ALIGN(sizeof(*((secp256k1_ecmult_gen_context*) NULL)->prec)); -#else - static const size_t SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE = 0; -#endif +static const size_t SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE = 0; static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context *ctx) { ctx->prec = NULL; } static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx, void **prealloc) { -#ifndef USE_ECMULT_STATIC_PRECOMPUTATION - secp256k1_ge prec[ECMULT_GEN_PREC_N * ECMULT_GEN_PREC_G]; - secp256k1_gej gj; - secp256k1_gej nums_gej; - int i, j; - size_t const prealloc_size = SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE; - void* const base = *prealloc; -#endif - if (ctx->prec != NULL) { return; } -#ifndef USE_ECMULT_STATIC_PRECOMPUTATION - ctx->prec = (secp256k1_ge_storage (*)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G])manual_alloc(prealloc, prealloc_size, base, prealloc_size); - - /* get the generator */ - secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); - - /* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ - { - static const unsigned char nums_b32[33] = "The scalar for this x is unknown"; - secp256k1_fe nums_x; - secp256k1_ge nums_ge; - int r; - r = secp256k1_fe_set_b32(&nums_x, nums_b32); - (void)r; - VERIFY_CHECK(r); - r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0); - (void)r; - VERIFY_CHECK(r); - secp256k1_gej_set_ge(&nums_gej, &nums_ge); - /* Add G to make the bits in x uniformly distributed. */ - secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g, NULL); - } - - /* compute prec. */ - { - secp256k1_gej precj[ECMULT_GEN_PREC_N * ECMULT_GEN_PREC_G]; /* Jacobian versions of prec. */ - secp256k1_gej gbase; - secp256k1_gej numsbase; - gbase = gj; /* PREC_G^j * G */ - numsbase = nums_gej; /* 2^j * nums. */ - for (j = 0; j < ECMULT_GEN_PREC_N; j++) { - /* Set precj[j*PREC_G .. j*PREC_G+(PREC_G-1)] to (numsbase, numsbase + gbase, ..., numsbase + (PREC_G-1)*gbase). */ - precj[j*ECMULT_GEN_PREC_G] = numsbase; - for (i = 1; i < ECMULT_GEN_PREC_G; i++) { - secp256k1_gej_add_var(&precj[j*ECMULT_GEN_PREC_G + i], &precj[j*ECMULT_GEN_PREC_G + i - 1], &gbase, NULL); - } - /* Multiply gbase by PREC_G. */ - for (i = 0; i < ECMULT_GEN_PREC_B; i++) { - secp256k1_gej_double_var(&gbase, &gbase, NULL); - } - /* Multiply numbase by 2. */ - secp256k1_gej_double_var(&numsbase, &numsbase, NULL); - if (j == ECMULT_GEN_PREC_N - 2) { - /* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ - secp256k1_gej_neg(&numsbase, &numsbase); - secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL); - } - } - secp256k1_ge_set_all_gej_var(prec, precj, ECMULT_GEN_PREC_N * ECMULT_GEN_PREC_G); - } - for (j = 0; j < ECMULT_GEN_PREC_N; j++) { - for (i = 0; i < ECMULT_GEN_PREC_G; i++) { - secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*ECMULT_GEN_PREC_G + i]); - } - } -#else (void)prealloc; ctx->prec = (secp256k1_ge_storage (*)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G])secp256k1_ecmult_static_context; -#endif secp256k1_ecmult_gen_blind(ctx, NULL); } @@ -106,14 +34,7 @@ static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_cont } static void secp256k1_ecmult_gen_context_finalize_memcpy(secp256k1_ecmult_gen_context *dst, const secp256k1_ecmult_gen_context *src) { -#ifndef USE_ECMULT_STATIC_PRECOMPUTATION - if (src->prec != NULL) { - /* We cast to void* first to suppress a -Wcast-align warning. */ - dst->prec = (secp256k1_ge_storage (*)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G])(void*)((unsigned char*)dst + ((unsigned char*)src->prec - (unsigned char*)src)); - } -#else (void)dst, (void)src; -#endif } static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) { diff --git a/src/ecmult_gen_prec.h b/src/ecmult_gen_prec.h new file mode 100644 index 0000000..3c0958e --- /dev/null +++ b/src/ecmult_gen_prec.h @@ -0,0 +1,16 @@ +/*********************************************************************** + * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_ECMULT_GEN_PREC_H +#define SECP256K1_ECMULT_GEN_PREC_H + +#include "ecmult_gen.h" + +static const size_t ECMULT_GEN_PREC_TABLE_SIZE = ROUND_TO_ALIGN(sizeof(*((secp256k1_ecmult_gen_context*) NULL)->prec)); + +static void secp256k1_ecmult_gen_create_prec_table(secp256k1_ecmult_gen_context *ctx, void **prealloc); + +#endif /* SECP256K1_ECMULT_GEN_PREC_H */ diff --git a/src/ecmult_gen_prec_impl.h b/src/ecmult_gen_prec_impl.h new file mode 100644 index 0000000..dc028ba --- /dev/null +++ b/src/ecmult_gen_prec_impl.h @@ -0,0 +1,78 @@ +/*********************************************************************** + * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_ECMULT_GEN_PREC_IMPL_H +#define SECP256K1_ECMULT_GEN_PREC_IMPL_H + +#include "ecmult_gen_prec.h" +#include "group_impl.h" +#include "field_impl.h" +#include "ecmult_gen.h" + +static void secp256k1_ecmult_gen_create_prec_table(secp256k1_ecmult_gen_context *ctx, void **prealloc) { + secp256k1_ge prec[ECMULT_GEN_PREC_N * ECMULT_GEN_PREC_G]; + secp256k1_gej gj; + secp256k1_gej nums_gej; + int i, j; + size_t const prealloc_size = ECMULT_GEN_PREC_TABLE_SIZE; + void* const base = *prealloc; + ctx->prec = (secp256k1_ge_storage (*)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G])manual_alloc(prealloc, prealloc_size, base, prealloc_size); + + /* get the generator */ + secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); + + /* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ + { + static const unsigned char nums_b32[33] = "The scalar for this x is unknown"; + secp256k1_fe nums_x; + secp256k1_ge nums_ge; + int r; + r = secp256k1_fe_set_b32(&nums_x, nums_b32); + (void)r; + VERIFY_CHECK(r); + r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0); + (void)r; + VERIFY_CHECK(r); + secp256k1_gej_set_ge(&nums_gej, &nums_ge); + /* Add G to make the bits in x uniformly distributed. */ + secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g, NULL); + } + + /* compute prec. */ + { + secp256k1_gej precj[ECMULT_GEN_PREC_N * ECMULT_GEN_PREC_G]; /* Jacobian versions of prec. */ + secp256k1_gej gbase; + secp256k1_gej numsbase; + gbase = gj; /* PREC_G^j * G */ + numsbase = nums_gej; /* 2^j * nums. */ + for (j = 0; j < ECMULT_GEN_PREC_N; j++) { + /* Set precj[j*PREC_G .. j*PREC_G+(PREC_G-1)] to (numsbase, numsbase + gbase, ..., numsbase + (PREC_G-1)*gbase). */ + precj[j*ECMULT_GEN_PREC_G] = numsbase; + for (i = 1; i < ECMULT_GEN_PREC_G; i++) { + secp256k1_gej_add_var(&precj[j*ECMULT_GEN_PREC_G + i], &precj[j*ECMULT_GEN_PREC_G + i - 1], &gbase, NULL); + } + /* Multiply gbase by PREC_G. */ + for (i = 0; i < ECMULT_GEN_PREC_B; i++) { + secp256k1_gej_double_var(&gbase, &gbase, NULL); + } + /* Multiply numbase by 2. */ + secp256k1_gej_double_var(&numsbase, &numsbase, NULL); + if (j == ECMULT_GEN_PREC_N - 2) { + /* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ + secp256k1_gej_neg(&numsbase, &numsbase); + secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL); + } + } + secp256k1_ge_set_all_gej_var(prec, precj, ECMULT_GEN_PREC_N * ECMULT_GEN_PREC_G); + } + for (j = 0; j < ECMULT_GEN_PREC_N; j++) { + for (i = 0; i < ECMULT_GEN_PREC_G; i++) { + secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*ECMULT_GEN_PREC_G + i]); + } + } +} + +#endif /* SECP256K1_ECMULT_GEN_PREC_IMPL_H */ diff --git a/src/gen_context.c b/src/gen_context.c index f9176eb..0e9df36 100644 --- a/src/gen_context.c +++ b/src/gen_context.c @@ -10,9 +10,6 @@ #include "libsecp256k1-config.h" #endif -/* We can't require the precomputed tables when creating them. */ -#undef USE_ECMULT_STATIC_PRECOMPUTATION - /* In principle we could use ASM, but this yields only a minor speedup in build time and it's very complicated. In particular when cross-compiling, we'd need to build the ASM for the build and the host machine. */ @@ -22,10 +19,9 @@ #include "../include/secp256k1.h" #include "assumptions.h" #include "util.h" -#include "field_impl.h" -#include "scalar_impl.h" -#include "group_impl.h" -#include "ecmult_gen_impl.h" +#include "group.h" +#include "ecmult_gen.h" +#include "ecmult_gen_prec_impl.h" static void default_error_callback_fn(const char* str, void* data) { (void)data; @@ -63,10 +59,9 @@ int main(int argc, char **argv) { fprintf(fp, "#endif\n"); fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_static_context[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G] = {\n"); - base = checked_malloc(&default_error_callback, SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE); + base = checked_malloc(&default_error_callback, ECMULT_GEN_PREC_TABLE_SIZE); prealloc = base; - secp256k1_ecmult_gen_context_init(&ctx); - secp256k1_ecmult_gen_context_build(&ctx, &prealloc); + secp256k1_ecmult_gen_create_prec_table(&ctx, &prealloc); for(outer = 0; outer != ECMULT_GEN_PREC_N; outer++) { fprintf(fp,"{\n"); for(inner = 0; inner != ECMULT_GEN_PREC_G; inner++) { @@ -84,7 +79,6 @@ int main(int argc, char **argv) { } } fprintf(fp,"};\n"); - secp256k1_ecmult_gen_context_clear(&ctx); free(base); fprintf(fp, "#undef SC\n"); diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index 4d96dd9..f112758 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -12,8 +12,6 @@ #include #include -#undef USE_ECMULT_STATIC_PRECOMPUTATION - #ifndef EXHAUSTIVE_TEST_ORDER /* see group_impl.h for allowable values */ #define EXHAUSTIVE_TEST_ORDER 13