Merge bitcoin-core/secp256k1#988: Make signing table fully static
7dfceceea6build: Remove #undef hack for ASM in the precomputation programs (Tim Ruffing)bb36fe9be0ci: Test `make precomp` (Tim Ruffing)d94a37a20cbuild: Remove CC_FOR_BUILD stuff (Tim Ruffing)ad63bb4c29build: Prebuild and distribute ecmult_gen table (Tim Ruffing)ac49361ed0prealloc: Get rid of manual memory management for prealloc contexts (Tim Ruffing)6573c08f65ecmult_gen: Tidy precomputed file and save space (Tim Ruffing)5eba83f17cecmult_gen: Precompute tables for all values of ECMULT_GEN_PREC_BITS (Tim Ruffing)fdb33dd122refactor: Make PREC_BITS a parameter of ecmult_gen_build_prec_table (Tim Ruffing)a4875e30a6refactor: Move default callbacks to util.h (Tim Ruffing)4c94c55bcedoc: Remove obsolete hint for valgrind stack size (Tim Ruffing)5106226991exhaustive_tests: Fix with ecmult_gen table with custom generator (Tim Ruffing)e1a76530dbrefactor: Make generator a parameter of ecmult_gen_create_prec_table (Tim Ruffing)9ad09f6911refactor: Rename program that generates static ecmult_gen table (Tim Ruffing)8ae18f1ab3refactor: Rename file that contains static ecmult_gen table (Tim Ruffing)00d2fa116eecmult_gen: Make code consistent with comment (Tim Ruffing)3b0c2185eaecmult_gen: Simplify ecmult_gen context after making table static (Tim Ruffing)e43ba02cfcrefactor: Decouple table generation and ecmult_gen context (Tim Ruffing)22dc2c0a0decmult_gen: Move table creation to new file and force static prec (Tim Ruffing) Pull request description: This resolves #893, resolves #692 (and also resolves bitcoin/bitcoin#22854). - [x] Extract table generation to separate function in separate file (to be used by generation script and exhaustive tests) - [x] Tidy up - [x] Remove code that deals with non-static tables - [x] Make functions that need ecmult_gen not depend on signing context - [x] Rename stuff to make it fit the new structure and consistent with how we hande verification tables (#956) - [x] Fix exhaustive tests - [x] Make table generation function take generator as input - [x] Overwrite the static tables with a table with custom generator in exhaustive tests - [x] Overhaul script that generates table files - [x] Make table generation function take PREC_BITS as input (I have some code already, just not yet in this branch) - [x] Change generation script to generate three tables (for all three values of ECMULT_GEN_PREC_BITS) - [x] Ship pre-built tables - [x] Add pregenerated table file to repo - [x] Remove generation of table file from build process (like in #956) - [x] Remove left-over stuff (e.g., detecting a compiler running on the build machine) from build system - [x] Final cleanups (copyright headers, commit, messages, etc.) - [ ] (separate PR:) Make sure link-time optimization remove corresponding static tables (and code) when no signing/verifcation function is called - [ ] (separate PR:) Compile precomputation as a separate object file and link it (https://github.com/bitcoin-core/secp256k1/pull/988#issuecomment-977813538) - [ ] (separate PR:) Document the backwards-compatible API changes made in this PR and in #956. - [ ] Maybe deprecate the static context ACKs for top commit: sipa: ACK7dfceceea6robot-dreams: ACK7dfceceea6(based on range-diff between 56284c7d44c0ed46e636588bfbf6c403b7dfa6c1 and7dfceceea6) Tree-SHA512: 6efb3f36f05efe3b79bbd877881fe1409f71fd6488d24c811b2e77d9f053bed78670dd1dcbb42ad780458a51c4ffa36de9cd6567271b22041dc7a122ceb677c5
This commit is contained in:
@@ -13,33 +13,20 @@
|
||||
#if ECMULT_GEN_PREC_BITS != 2 && ECMULT_GEN_PREC_BITS != 4 && ECMULT_GEN_PREC_BITS != 8
|
||||
# error "Set ECMULT_GEN_PREC_BITS to 2, 4 or 8."
|
||||
#endif
|
||||
#define ECMULT_GEN_PREC_B ECMULT_GEN_PREC_BITS
|
||||
#define ECMULT_GEN_PREC_G (1 << ECMULT_GEN_PREC_B)
|
||||
#define ECMULT_GEN_PREC_N (256 / ECMULT_GEN_PREC_B)
|
||||
#define ECMULT_GEN_PREC_G(bits) (1 << bits)
|
||||
#define ECMULT_GEN_PREC_N(bits) (256 / bits)
|
||||
|
||||
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 PREC_B bits, called n_0, n_1, n_2, ..., n_(PREC_N-1).
|
||||
* * Compute sum(n_i * (PREC_G)^i * G + U_i, i=0 ... PREC_N-1), where:
|
||||
* * U_i = U * 2^i, for i=0 ... PREC_N-2
|
||||
* * U_i = U * (1-2^(PREC_N-1)), for i=PREC_N-1
|
||||
* where U is a point with no known corresponding scalar. Note that sum(U_i, i=0 ... PREC_N-1) = 0.
|
||||
* For each i, and each of the PREC_G possible values of n_i, (n_i * (PREC_G)^i * G + U_i) is
|
||||
* precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0 ... PREC_N-1).
|
||||
* None of the resulting prec group elements have a known scalar, and neither do any of
|
||||
* the intermediate sums while computing a*G.
|
||||
*/
|
||||
secp256k1_ge_storage (*prec)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G]; /* prec[j][i] = (PREC_G)^j * i * G + U_i */
|
||||
secp256k1_scalar blind;
|
||||
secp256k1_gej initial;
|
||||
/* Whether the context has been built. */
|
||||
int built;
|
||||
|
||||
/* Blinding values used when computing (n-b)G + bG. */
|
||||
secp256k1_scalar blind; /* -b */
|
||||
secp256k1_gej initial; /* bG */
|
||||
} secp256k1_ecmult_gen_context;
|
||||
|
||||
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context* ctx);
|
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx, void **prealloc);
|
||||
static void secp256k1_ecmult_gen_context_finalize_memcpy(secp256k1_ecmult_gen_context *dst, const secp256k1_ecmult_gen_context* src);
|
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx);
|
||||
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx);
|
||||
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx);
|
||||
|
||||
/** Multiply with the generator: R = a*G */
|
||||
static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a);
|
||||
|
||||
@@ -12,130 +12,54 @@
|
||||
#include "group.h"
|
||||
#include "ecmult_gen.h"
|
||||
#include "hash_impl.h"
|
||||
#ifdef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
#include "ecmult_static_context.h"
|
||||
#endif
|
||||
#include "ecmult_gen_static_prec_table.h"
|
||||
|
||||
#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 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
|
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx) {
|
||||
secp256k1_ecmult_gen_blind(ctx, NULL);
|
||||
ctx->built = 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx) {
|
||||
return ctx->prec != NULL;
|
||||
}
|
||||
|
||||
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
|
||||
return ctx->built;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) {
|
||||
ctx->built = 0;
|
||||
secp256k1_scalar_clear(&ctx->blind);
|
||||
secp256k1_gej_clear(&ctx->initial);
|
||||
ctx->prec = NULL;
|
||||
}
|
||||
|
||||
/* For accelerating the computation of a*G:
|
||||
* To harden against timing attacks, use the following mechanism:
|
||||
* * Break up the multiplicand into groups of PREC_BITS bits, called n_0, n_1, n_2, ..., n_(PREC_N-1).
|
||||
* * Compute sum(n_i * (PREC_G)^i * G + U_i, i=0 ... PREC_N-1), where:
|
||||
* * U_i = U * 2^i, for i=0 ... PREC_N-2
|
||||
* * U_i = U * (1-2^(PREC_N-1)), for i=PREC_N-1
|
||||
* where U is a point with no known corresponding scalar. Note that sum(U_i, i=0 ... PREC_N-1) = 0.
|
||||
* For each i, and each of the PREC_G possible values of n_i, (n_i * (PREC_G)^i * G + U_i) is
|
||||
* precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0 ... PREC_N-1).
|
||||
* None of the resulting prec group elements have a known scalar, and neither do any of
|
||||
* the intermediate sums while computing a*G.
|
||||
* The prec values are stored in secp256k1_ecmult_gen_prec_table[i][n_i] = n_i * (PREC_G)^i * G + U_i.
|
||||
*/
|
||||
static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) {
|
||||
int bits = ECMULT_GEN_PREC_BITS;
|
||||
int g = ECMULT_GEN_PREC_G(bits);
|
||||
int n = ECMULT_GEN_PREC_N(bits);
|
||||
|
||||
secp256k1_ge add;
|
||||
secp256k1_ge_storage adds;
|
||||
secp256k1_scalar gnb;
|
||||
int bits;
|
||||
int i, j;
|
||||
int i, j, n_i;
|
||||
|
||||
memset(&adds, 0, sizeof(adds));
|
||||
*r = ctx->initial;
|
||||
/* Blind scalar/point multiplication by computing (n-b)G + bG instead of nG. */
|
||||
secp256k1_scalar_add(&gnb, gn, &ctx->blind);
|
||||
add.infinity = 0;
|
||||
for (j = 0; j < ECMULT_GEN_PREC_N; j++) {
|
||||
bits = secp256k1_scalar_get_bits(&gnb, j * ECMULT_GEN_PREC_B, ECMULT_GEN_PREC_B);
|
||||
for (i = 0; i < ECMULT_GEN_PREC_G; i++) {
|
||||
for (i = 0; i < n; i++) {
|
||||
n_i = secp256k1_scalar_get_bits(&gnb, i * bits, bits);
|
||||
for (j = 0; j < g; j++) {
|
||||
/** This uses a conditional move to avoid any secret data in array indexes.
|
||||
* _Any_ use of secret indexes has been demonstrated to result in timing
|
||||
* sidechannels, even when the cache-line access patterns are uniform.
|
||||
@@ -146,12 +70,12 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25
|
||||
* by Dag Arne Osvik, Adi Shamir, and Eran Tromer
|
||||
* (https://www.tau.ac.il/~tromer/papers/cache.pdf)
|
||||
*/
|
||||
secp256k1_ge_storage_cmov(&adds, &(*ctx->prec)[j][i], i == bits);
|
||||
secp256k1_ge_storage_cmov(&adds, &secp256k1_ecmult_gen_prec_table[i][j], j == n_i);
|
||||
}
|
||||
secp256k1_ge_from_storage(&add, &adds);
|
||||
secp256k1_gej_add_ge(r, r, &add);
|
||||
}
|
||||
bits = 0;
|
||||
n_i = 0;
|
||||
secp256k1_ge_clear(&add);
|
||||
secp256k1_scalar_clear(&gnb);
|
||||
}
|
||||
|
||||
14
src/ecmult_gen_prec.h
Normal file
14
src/ecmult_gen_prec.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/***********************************************************************
|
||||
* 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 void secp256k1_ecmult_gen_create_prec_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int bits);
|
||||
|
||||
#endif /* SECP256K1_ECMULT_GEN_PREC_H */
|
||||
81
src/ecmult_gen_prec_impl.h
Normal file
81
src/ecmult_gen_prec_impl.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/***********************************************************************
|
||||
* 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"
|
||||
#include "util.h"
|
||||
|
||||
static void secp256k1_ecmult_gen_create_prec_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int bits) {
|
||||
int g = ECMULT_GEN_PREC_G(bits);
|
||||
int n = ECMULT_GEN_PREC_N(bits);
|
||||
|
||||
secp256k1_ge* prec = checked_malloc(&default_error_callback, n * g * sizeof(*prec));
|
||||
secp256k1_gej gj;
|
||||
secp256k1_gej nums_gej;
|
||||
int i, j;
|
||||
|
||||
/* get the generator */
|
||||
secp256k1_gej_set_ge(&gj, gen);
|
||||
|
||||
/* 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, gen, NULL);
|
||||
}
|
||||
|
||||
/* compute prec. */
|
||||
{
|
||||
secp256k1_gej gbase;
|
||||
secp256k1_gej numsbase;
|
||||
secp256k1_gej* precj = checked_malloc(&default_error_callback, n * g * sizeof(*precj)); /* Jacobian versions of prec. */
|
||||
gbase = gj; /* PREC_G^j * G */
|
||||
numsbase = nums_gej; /* 2^j * nums. */
|
||||
for (j = 0; j < n; j++) {
|
||||
/* Set precj[j*PREC_G .. j*PREC_G+(PREC_G-1)] to (numsbase, numsbase + gbase, ..., numsbase + (PREC_G-1)*gbase). */
|
||||
precj[j*g] = numsbase;
|
||||
for (i = 1; i < g; i++) {
|
||||
secp256k1_gej_add_var(&precj[j*g + i], &precj[j*g + i - 1], &gbase, NULL);
|
||||
}
|
||||
/* Multiply gbase by PREC_G. */
|
||||
for (i = 0; i < bits; i++) {
|
||||
secp256k1_gej_double_var(&gbase, &gbase, NULL);
|
||||
}
|
||||
/* Multiply numbase by 2. */
|
||||
secp256k1_gej_double_var(&numsbase, &numsbase, NULL);
|
||||
if (j == 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, n * g);
|
||||
free(precj);
|
||||
}
|
||||
for (j = 0; j < n; j++) {
|
||||
for (i = 0; i < g; i++) {
|
||||
secp256k1_ge_to_storage(&table[j*g + i], &prec[j*g + i]);
|
||||
}
|
||||
}
|
||||
free(prec);
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_ECMULT_GEN_PREC_IMPL_H */
|
||||
9748
src/ecmult_gen_static_prec_table.h
generated
Normal file
9748
src/ecmult_gen_static_prec_table.h
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,95 +0,0 @@
|
||||
/***********************************************************************
|
||||
* Copyright (c) 2013, 2014, 2015 Thomas Daede, Cory Fields *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
||||
***********************************************************************/
|
||||
|
||||
/* Autotools creates libsecp256k1-config.h, of which ECMULT_GEN_PREC_BITS is needed.
|
||||
ifndef guard so downstream users can define their own if they do not use autotools. */
|
||||
#if !defined(ECMULT_GEN_PREC_BITS)
|
||||
#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. */
|
||||
#undef USE_EXTERNAL_ASM
|
||||
#undef USE_ASM_X86_64
|
||||
|
||||
#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"
|
||||
|
||||
static void default_error_callback_fn(const char* str, void* data) {
|
||||
(void)data;
|
||||
fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str);
|
||||
abort();
|
||||
}
|
||||
|
||||
static const secp256k1_callback default_error_callback = {
|
||||
default_error_callback_fn,
|
||||
NULL
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
secp256k1_ecmult_gen_context ctx;
|
||||
void *prealloc, *base;
|
||||
int inner;
|
||||
int outer;
|
||||
FILE* fp;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
fp = fopen("src/ecmult_static_context.h","w");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "Could not open src/ecmult_static_context.h for writing!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(fp, "#ifndef SECP256K1_ECMULT_STATIC_CONTEXT_H\n");
|
||||
fprintf(fp, "#define SECP256K1_ECMULT_STATIC_CONTEXT_H\n");
|
||||
fprintf(fp, "#include \"src/group.h\"\n");
|
||||
fprintf(fp, "#define SC SECP256K1_GE_STORAGE_CONST\n");
|
||||
fprintf(fp, "#if ECMULT_GEN_PREC_N != %d || ECMULT_GEN_PREC_G != %d\n", ECMULT_GEN_PREC_N, ECMULT_GEN_PREC_G);
|
||||
fprintf(fp, " #error configuration mismatch, invalid ECMULT_GEN_PREC_N, ECMULT_GEN_PREC_G. Try deleting ecmult_static_context.h before the build.\n");
|
||||
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);
|
||||
prealloc = base;
|
||||
secp256k1_ecmult_gen_context_init(&ctx);
|
||||
secp256k1_ecmult_gen_context_build(&ctx, &prealloc);
|
||||
for(outer = 0; outer != ECMULT_GEN_PREC_N; outer++) {
|
||||
fprintf(fp,"{\n");
|
||||
for(inner = 0; inner != ECMULT_GEN_PREC_G; inner++) {
|
||||
fprintf(fp," SC(%uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu)", SECP256K1_GE_STORAGE_CONST_GET((*ctx.prec)[outer][inner]));
|
||||
if (inner != ECMULT_GEN_PREC_G - 1) {
|
||||
fprintf(fp,",\n");
|
||||
} else {
|
||||
fprintf(fp,"\n");
|
||||
}
|
||||
}
|
||||
if (outer != ECMULT_GEN_PREC_N - 1) {
|
||||
fprintf(fp,"},\n");
|
||||
} else {
|
||||
fprintf(fp,"}\n");
|
||||
}
|
||||
}
|
||||
fprintf(fp,"};\n");
|
||||
secp256k1_ecmult_gen_context_clear(&ctx);
|
||||
free(base);
|
||||
|
||||
fprintf(fp, "#undef SC\n");
|
||||
fprintf(fp, "#endif\n");
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
83
src/gen_ecmult_gen_static_prec_table.c
Normal file
83
src/gen_ecmult_gen_static_prec_table.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/***********************************************************************
|
||||
* Copyright (c) 2013, 2014, 2015 Thomas Daede, Cory Fields *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
||||
***********************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../include/secp256k1.h"
|
||||
#include "assumptions.h"
|
||||
#include "util.h"
|
||||
#include "group.h"
|
||||
#include "ecmult_gen.h"
|
||||
#include "ecmult_gen_prec_impl.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const char outfile[] = "src/ecmult_gen_static_prec_table.h";
|
||||
FILE* fp;
|
||||
int bits;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
fp = fopen(outfile, "w");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "Could not open %s for writing!\n", outfile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(fp, "/* This file was automatically generated by gen_ecmult_gen_static_prec_table. */\n");
|
||||
fprintf(fp, "/* See ecmult_gen_impl.h for details about the contents of this file. */\n");
|
||||
fprintf(fp, "#ifndef SECP256K1_ECMULT_GEN_STATIC_PREC_TABLE_H\n");
|
||||
fprintf(fp, "#define SECP256K1_ECMULT_GEN_STATIC_PREC_TABLE_H\n");
|
||||
|
||||
fprintf(fp, "#include \"group.h\"\n");
|
||||
|
||||
fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) "
|
||||
"SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,"
|
||||
"0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n");
|
||||
|
||||
fprintf(fp, "#ifdef EXHAUSTIVE_TEST_ORDER\n");
|
||||
fprintf(fp, "static secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)];\n");
|
||||
fprintf(fp, "#else\n");
|
||||
fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)] = {\n");
|
||||
|
||||
for (bits = 2; bits <= 8; bits *= 2) {
|
||||
int g = ECMULT_GEN_PREC_G(bits);
|
||||
int n = ECMULT_GEN_PREC_N(bits);
|
||||
int inner, outer;
|
||||
|
||||
secp256k1_ge_storage* table = checked_malloc(&default_error_callback, n * g * sizeof(secp256k1_ge_storage));
|
||||
secp256k1_ecmult_gen_create_prec_table(table, &secp256k1_ge_const_g, bits);
|
||||
|
||||
fprintf(fp, "#if ECMULT_GEN_PREC_BITS == %d\n", bits);
|
||||
for(outer = 0; outer != n; outer++) {
|
||||
fprintf(fp,"{");
|
||||
for(inner = 0; inner != g; inner++) {
|
||||
fprintf(fp, "S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32
|
||||
",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")",
|
||||
SECP256K1_GE_STORAGE_CONST_GET(table[outer * g + inner]));
|
||||
if (inner != g - 1) {
|
||||
fprintf(fp,",\n");
|
||||
}
|
||||
}
|
||||
if (outer != n - 1) {
|
||||
fprintf(fp,"},\n");
|
||||
} else {
|
||||
fprintf(fp,"}\n");
|
||||
}
|
||||
}
|
||||
fprintf(fp, "#endif\n");
|
||||
free(table);
|
||||
}
|
||||
|
||||
fprintf(fp, "};\n");
|
||||
fprintf(fp, "#endif /* EXHAUSTIVE_TEST_ORDER */\n");
|
||||
fprintf(fp, "#undef SC\n");
|
||||
fprintf(fp, "#endif /* SECP256K1_ECMULT_GEN_STATIC_PREC_TABLE_H */\n");
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -13,12 +13,6 @@
|
||||
#include "libsecp256k1-config.h"
|
||||
#endif
|
||||
|
||||
/* 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. */
|
||||
#undef USE_EXTERNAL_ASM
|
||||
#undef USE_ASM_X86_64
|
||||
|
||||
#include "../include/secp256k1.h"
|
||||
#include "assumptions.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -359,6 +359,9 @@ void test_keypair(void) {
|
||||
secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
|
||||
secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
|
||||
secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
|
||||
secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
|
||||
secp256k1_context_set_error_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
|
||||
CHECK(sizeof(zeros96) == sizeof(keypair));
|
||||
memset(overflows, 0xFF, sizeof(overflows));
|
||||
@@ -366,18 +369,22 @@ void test_keypair(void) {
|
||||
/* Test keypair_create */
|
||||
ecount = 0;
|
||||
secp256k1_testrand256(sk);
|
||||
CHECK(secp256k1_keypair_create(none, &keypair, sk) == 0);
|
||||
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
|
||||
CHECK(secp256k1_keypair_create(none, &keypair, sk) == 1);
|
||||
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_keypair_create(verify, &keypair, sk) == 1);
|
||||
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_keypair_create(sign, NULL, sk) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_keypair_create(verify, &keypair, sk) == 0);
|
||||
CHECK(secp256k1_keypair_create(sign, &keypair, NULL) == 0);
|
||||
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
|
||||
CHECK(secp256k1_keypair_create(sign, NULL, sk) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_keypair_create(sign, &keypair, NULL) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_keypair_create(sttc, &keypair, sk) == 0);
|
||||
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(ecount == 3);
|
||||
|
||||
/* Invalid secret key */
|
||||
CHECK(secp256k1_keypair_create(sign, &keypair, zeros96) == 0);
|
||||
@@ -459,6 +466,7 @@ void test_keypair(void) {
|
||||
secp256k1_context_destroy(none);
|
||||
secp256k1_context_destroy(sign);
|
||||
secp256k1_context_destroy(verify);
|
||||
secp256k1_context_destroy(sttc);
|
||||
}
|
||||
|
||||
void test_keypair_add(void) {
|
||||
|
||||
@@ -34,6 +34,7 @@ void test_ecdsa_recovery_api(void) {
|
||||
secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
|
||||
secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
||||
secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
|
||||
secp256k1_pubkey pubkey;
|
||||
secp256k1_pubkey recpubkey;
|
||||
secp256k1_ecdsa_signature normal_sig;
|
||||
@@ -53,10 +54,12 @@ void test_ecdsa_recovery_api(void) {
|
||||
secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
|
||||
/* Construct and verify corresponding public key. */
|
||||
CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1);
|
||||
@@ -64,29 +67,31 @@ void test_ecdsa_recovery_api(void) {
|
||||
|
||||
/* Check bad contexts and NULLs for signing */
|
||||
ecount = 0;
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(sign, &recsig, message, privkey, NULL, NULL) == 1);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(vrfy, &recsig, message, privkey, NULL, NULL) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(vrfy, &recsig, message, privkey, NULL, NULL) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(both, NULL, message, privkey, NULL, NULL) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, NULL, privkey, NULL, NULL) == 0);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, NULL, NULL, NULL) == 0);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(sttc, &recsig, message, privkey, NULL, NULL) == 0);
|
||||
CHECK(ecount == 4);
|
||||
/* This will fail or succeed randomly, and in either case will not ARG_CHECK failure */
|
||||
secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, recovery_test_nonce_function, NULL);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(ecount == 4);
|
||||
/* These will all fail, but not in ARG_CHECK way */
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, zero_privkey, NULL, NULL) == 0);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, over_privkey, NULL, NULL) == 0);
|
||||
/* This one will succeed. */
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(ecount == 4);
|
||||
|
||||
/* Check signing with a goofy nonce function */
|
||||
|
||||
@@ -145,6 +150,7 @@ void test_ecdsa_recovery_api(void) {
|
||||
secp256k1_context_destroy(sign);
|
||||
secp256k1_context_destroy(vrfy);
|
||||
secp256k1_context_destroy(both);
|
||||
secp256k1_context_destroy(sttc);
|
||||
}
|
||||
|
||||
void test_ecdsa_recovery_end_to_end(void) {
|
||||
|
||||
@@ -132,16 +132,19 @@ void test_schnorrsig_api(void) {
|
||||
secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
|
||||
secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
||||
secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
|
||||
int ecount;
|
||||
|
||||
secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
|
||||
secp256k1_testrand256(sk1);
|
||||
secp256k1_testrand256(sk2);
|
||||
@@ -157,42 +160,46 @@ void test_schnorrsig_api(void) {
|
||||
|
||||
/** main test body **/
|
||||
ecount = 0;
|
||||
CHECK(secp256k1_schnorrsig_sign(none, sig, msg, &keypairs[0], NULL) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_schnorrsig_sign(vrfy, sig, msg, &keypairs[0], NULL) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_schnorrsig_sign(none, sig, msg, &keypairs[0], NULL) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_schnorrsig_sign(vrfy, sig, msg, &keypairs[0], NULL) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &keypairs[0], NULL) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_schnorrsig_sign(sign, NULL, msg, &keypairs[0], NULL) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_schnorrsig_sign(sign, sig, NULL, &keypairs[0], NULL) == 0);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, NULL, NULL) == 0);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &invalid_keypair, NULL) == 0);
|
||||
CHECK(ecount == 6);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(secp256k1_schnorrsig_sign(sttc, sig, msg, &keypairs[0], NULL) == 0);
|
||||
CHECK(ecount == 5);
|
||||
|
||||
ecount = 0;
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(none, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(vrfy, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(none, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(vrfy, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sign, NULL, msg, sizeof(msg), &keypairs[0], &extraparams) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, NULL, sizeof(msg), &keypairs[0], &extraparams) == 0);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, NULL, 0, &keypairs[0], &extraparams) == 1);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), NULL, &extraparams) == 0);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &invalid_keypair, &extraparams) == 0);
|
||||
CHECK(ecount == 6);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &keypairs[0], NULL) == 1);
|
||||
CHECK(ecount == 6);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &keypairs[0], &invalid_extraparams) == 0);
|
||||
CHECK(ecount == 7);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sttc, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 0);
|
||||
CHECK(ecount == 6);
|
||||
|
||||
ecount = 0;
|
||||
CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &keypairs[0], NULL) == 1);
|
||||
@@ -217,6 +224,7 @@ void test_schnorrsig_api(void) {
|
||||
secp256k1_context_destroy(sign);
|
||||
secp256k1_context_destroy(vrfy);
|
||||
secp256k1_context_destroy(both);
|
||||
secp256k1_context_destroy(sttc);
|
||||
}
|
||||
|
||||
/* Checks that hash initialized by secp256k1_schnorrsig_sha256_tagged has the
|
||||
|
||||
@@ -44,34 +44,6 @@
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#ifndef USE_EXTERNAL_DEFAULT_CALLBACKS
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
static void secp256k1_default_illegal_callback_fn(const char* str, void* data) {
|
||||
(void)data;
|
||||
fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str);
|
||||
abort();
|
||||
}
|
||||
static void secp256k1_default_error_callback_fn(const char* str, void* data) {
|
||||
(void)data;
|
||||
fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str);
|
||||
abort();
|
||||
}
|
||||
#else
|
||||
void secp256k1_default_illegal_callback_fn(const char* str, void* data);
|
||||
void secp256k1_default_error_callback_fn(const char* str, void* data);
|
||||
#endif
|
||||
|
||||
static const secp256k1_callback default_illegal_callback = {
|
||||
secp256k1_default_illegal_callback_fn,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const secp256k1_callback default_error_callback = {
|
||||
secp256k1_default_error_callback_fn,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct secp256k1_context_struct {
|
||||
secp256k1_ecmult_gen_context ecmult_gen_ctx;
|
||||
secp256k1_callback illegal_callback;
|
||||
@@ -88,7 +60,7 @@ static const secp256k1_context secp256k1_context_no_precomp_ = {
|
||||
const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_no_precomp_;
|
||||
|
||||
size_t secp256k1_context_preallocated_size(unsigned int flags) {
|
||||
size_t ret = ROUND_TO_ALIGN(sizeof(secp256k1_context));
|
||||
size_t ret = sizeof(secp256k1_context);
|
||||
/* A return value of 0 is reserved as an indicator for errors when we call this function internally. */
|
||||
VERIFY_CHECK(ret != 0);
|
||||
|
||||
@@ -98,23 +70,16 @@ size_t secp256k1_context_preallocated_size(unsigned int flags) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {
|
||||
ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t secp256k1_context_preallocated_clone_size(const secp256k1_context* ctx) {
|
||||
size_t ret = ROUND_TO_ALIGN(sizeof(secp256k1_context));
|
||||
size_t ret = sizeof(secp256k1_context);
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) {
|
||||
ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigned int flags) {
|
||||
void* const base = prealloc;
|
||||
size_t prealloc_size;
|
||||
secp256k1_context* ret;
|
||||
|
||||
@@ -127,20 +92,16 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne
|
||||
return NULL;
|
||||
}
|
||||
VERIFY_CHECK(prealloc != NULL);
|
||||
ret = (secp256k1_context*)manual_alloc(&prealloc, sizeof(secp256k1_context), base, prealloc_size);
|
||||
ret = (secp256k1_context*)prealloc;
|
||||
ret->illegal_callback = default_illegal_callback;
|
||||
ret->error_callback = default_error_callback;
|
||||
|
||||
secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx);
|
||||
|
||||
/* Flags have been checked by secp256k1_context_preallocated_size. */
|
||||
VERIFY_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_CONTEXT);
|
||||
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {
|
||||
secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &prealloc);
|
||||
}
|
||||
secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx);
|
||||
ret->declassify = !!(flags & SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY);
|
||||
|
||||
return (secp256k1_context*) ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
secp256k1_context* secp256k1_context_create(unsigned int flags) {
|
||||
@@ -155,15 +116,12 @@ secp256k1_context* secp256k1_context_create(unsigned int flags) {
|
||||
}
|
||||
|
||||
secp256k1_context* secp256k1_context_preallocated_clone(const secp256k1_context* ctx, void* prealloc) {
|
||||
size_t prealloc_size;
|
||||
secp256k1_context* ret;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(prealloc != NULL);
|
||||
|
||||
prealloc_size = secp256k1_context_preallocated_clone_size(ctx);
|
||||
ret = (secp256k1_context*)prealloc;
|
||||
memcpy(ret, ctx, prealloc_size);
|
||||
secp256k1_ecmult_gen_context_finalize_memcpy(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx);
|
||||
*ret = *ctx;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
32
src/tests.c
32
src/tests.c
@@ -143,10 +143,12 @@ void run_context_tests(int use_prealloc) {
|
||||
secp256k1_context *sign;
|
||||
secp256k1_context *vrfy;
|
||||
secp256k1_context *both;
|
||||
secp256k1_context *sttc;
|
||||
void *none_prealloc = NULL;
|
||||
void *sign_prealloc = NULL;
|
||||
void *vrfy_prealloc = NULL;
|
||||
void *both_prealloc = NULL;
|
||||
void *sttc_prealloc = NULL;
|
||||
|
||||
secp256k1_gej pubj;
|
||||
secp256k1_ge pub;
|
||||
@@ -158,26 +160,30 @@ void run_context_tests(int use_prealloc) {
|
||||
sign_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN));
|
||||
vrfy_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY));
|
||||
both_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY));
|
||||
sttc_prealloc = malloc(secp256k1_context_preallocated_clone_size(secp256k1_context_no_precomp));
|
||||
CHECK(none_prealloc != NULL);
|
||||
CHECK(sign_prealloc != NULL);
|
||||
CHECK(vrfy_prealloc != NULL);
|
||||
CHECK(both_prealloc != NULL);
|
||||
CHECK(sttc_prealloc != NULL);
|
||||
none = secp256k1_context_preallocated_create(none_prealloc, SECP256K1_CONTEXT_NONE);
|
||||
sign = secp256k1_context_preallocated_create(sign_prealloc, SECP256K1_CONTEXT_SIGN);
|
||||
vrfy = secp256k1_context_preallocated_create(vrfy_prealloc, SECP256K1_CONTEXT_VERIFY);
|
||||
both = secp256k1_context_preallocated_create(both_prealloc, SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
sttc = secp256k1_context_preallocated_clone(secp256k1_context_no_precomp, sttc_prealloc);
|
||||
} else {
|
||||
none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
|
||||
sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
|
||||
vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
||||
both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
|
||||
}
|
||||
|
||||
memset(&zero_pubkey, 0, sizeof(zero_pubkey));
|
||||
|
||||
ecount = 0;
|
||||
ecount2 = 10;
|
||||
secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount2);
|
||||
/* set error callback (to a function that still aborts in case malloc() fails in secp256k1_context_clone() below) */
|
||||
secp256k1_context_set_error_callback(sign, secp256k1_default_illegal_callback_fn, NULL);
|
||||
@@ -189,6 +195,7 @@ void run_context_tests(int use_prealloc) {
|
||||
CHECK(secp256k1_context_preallocated_clone_size(sign) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN));
|
||||
CHECK(secp256k1_context_preallocated_clone_size(vrfy) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY));
|
||||
CHECK(secp256k1_context_preallocated_clone_size(both) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY));
|
||||
CHECK(secp256k1_context_preallocated_clone_size(sttc) >= sizeof(secp256k1_context));
|
||||
|
||||
/*** clone and destroy all of them to make sure cloning was complete ***/
|
||||
{
|
||||
@@ -252,12 +259,12 @@ void run_context_tests(int use_prealloc) {
|
||||
|
||||
/* Verify context-type checking illegal-argument errors. */
|
||||
memset(ctmp, 1, 32);
|
||||
CHECK(secp256k1_ec_pubkey_create(vrfy, &pubkey, ctmp) == 0);
|
||||
CHECK(secp256k1_ec_pubkey_create(sttc, &pubkey, ctmp) == 0);
|
||||
CHECK(ecount == 1);
|
||||
VG_UNDEF(&pubkey, sizeof(pubkey));
|
||||
CHECK(secp256k1_ec_pubkey_create(sign, &pubkey, ctmp) == 1);
|
||||
VG_CHECK(&pubkey, sizeof(pubkey));
|
||||
CHECK(secp256k1_ecdsa_sign(vrfy, &sig, ctmp, ctmp, NULL, NULL) == 0);
|
||||
CHECK(secp256k1_ecdsa_sign(sttc, &sig, ctmp, ctmp, NULL, NULL) == 0);
|
||||
CHECK(ecount == 2);
|
||||
VG_UNDEF(&sig, sizeof(sig));
|
||||
CHECK(secp256k1_ecdsa_sign(sign, &sig, ctmp, ctmp, NULL, NULL) == 1);
|
||||
@@ -265,33 +272,33 @@ void run_context_tests(int use_prealloc) {
|
||||
CHECK(ecount2 == 10);
|
||||
CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 1);
|
||||
CHECK(ecount2 == 10);
|
||||
CHECK(secp256k1_ecdsa_verify(vrfy, &sig, ctmp, &pubkey) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(sttc, &sig, ctmp, &pubkey) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 1);
|
||||
CHECK(ecount2 == 10);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(vrfy, &pubkey, ctmp) == 1);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(sttc, &pubkey, ctmp) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 1);
|
||||
CHECK(ecount2 == 10);
|
||||
CHECK(secp256k1_ec_pubkey_negate(vrfy, &pubkey) == 1);
|
||||
CHECK(secp256k1_ec_pubkey_negate(sttc, &pubkey) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ec_pubkey_negate(sign, &pubkey) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ec_pubkey_negate(sign, NULL) == 0);
|
||||
CHECK(ecount2 == 11);
|
||||
CHECK(secp256k1_ec_pubkey_negate(vrfy, &zero_pubkey) == 0);
|
||||
CHECK(secp256k1_ec_pubkey_negate(sttc, &zero_pubkey) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_mul(sttc, &pubkey, ctmp) == 1);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_context_randomize(vrfy, ctmp) == 1);
|
||||
CHECK(secp256k1_context_randomize(sttc, ctmp) == 1);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_context_randomize(vrfy, NULL) == 1);
|
||||
CHECK(secp256k1_context_randomize(sttc, NULL) == 1);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_context_randomize(sign, ctmp) == 1);
|
||||
CHECK(ecount2 == 11);
|
||||
CHECK(secp256k1_context_randomize(sign, NULL) == 1);
|
||||
CHECK(ecount2 == 11);
|
||||
secp256k1_context_set_illegal_callback(vrfy, NULL, NULL);
|
||||
secp256k1_context_set_illegal_callback(sttc, NULL, NULL);
|
||||
secp256k1_context_set_illegal_callback(sign, NULL, NULL);
|
||||
|
||||
/* obtain a working nonce */
|
||||
@@ -313,15 +320,18 @@ void run_context_tests(int use_prealloc) {
|
||||
secp256k1_context_preallocated_destroy(sign);
|
||||
secp256k1_context_preallocated_destroy(vrfy);
|
||||
secp256k1_context_preallocated_destroy(both);
|
||||
secp256k1_context_preallocated_destroy(sttc);
|
||||
free(none_prealloc);
|
||||
free(sign_prealloc);
|
||||
free(vrfy_prealloc);
|
||||
free(both_prealloc);
|
||||
free(sttc_prealloc);
|
||||
} else {
|
||||
secp256k1_context_destroy(none);
|
||||
secp256k1_context_destroy(sign);
|
||||
secp256k1_context_destroy(vrfy);
|
||||
secp256k1_context_destroy(both);
|
||||
secp256k1_context_destroy(sttc);
|
||||
}
|
||||
/* Defined as no-op. */
|
||||
secp256k1_context_destroy(NULL);
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#undef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
|
||||
#ifndef EXHAUSTIVE_TEST_ORDER
|
||||
/* see group_impl.h for allowable values */
|
||||
#define EXHAUSTIVE_TEST_ORDER 13
|
||||
@@ -24,6 +22,7 @@
|
||||
#include "assumptions.h"
|
||||
#include "group.h"
|
||||
#include "testrand_impl.h"
|
||||
#include "ecmult_gen_prec_impl.h"
|
||||
|
||||
static int count = 2;
|
||||
|
||||
@@ -390,6 +389,9 @@ int main(int argc, char** argv) {
|
||||
printf("running tests for core %lu (out of [0..%lu])\n", (unsigned long)this_core, (unsigned long)num_cores - 1);
|
||||
}
|
||||
|
||||
/* Recreate the ecmult_gen table using the right generator (as selected via EXHAUSTIVE_TEST_ORDER) */
|
||||
secp256k1_ecmult_gen_create_prec_table(&secp256k1_ecmult_gen_prec_table[0][0], &secp256k1_ge_const_g, ECMULT_GEN_PREC_BITS);
|
||||
|
||||
while (count--) {
|
||||
/* Build context */
|
||||
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
|
||||
59
src/util.h
59
src/util.h
@@ -25,6 +25,33 @@ static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback *
|
||||
cb->fn(text, (void*)cb->data);
|
||||
}
|
||||
|
||||
#ifndef USE_EXTERNAL_DEFAULT_CALLBACKS
|
||||
static void secp256k1_default_illegal_callback_fn(const char* str, void* data) {
|
||||
(void)data;
|
||||
fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str);
|
||||
abort();
|
||||
}
|
||||
static void secp256k1_default_error_callback_fn(const char* str, void* data) {
|
||||
(void)data;
|
||||
fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str);
|
||||
abort();
|
||||
}
|
||||
#else
|
||||
void secp256k1_default_illegal_callback_fn(const char* str, void* data);
|
||||
void secp256k1_default_error_callback_fn(const char* str, void* data);
|
||||
#endif
|
||||
|
||||
static const secp256k1_callback default_illegal_callback = {
|
||||
secp256k1_default_illegal_callback_fn,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const secp256k1_callback default_error_callback = {
|
||||
secp256k1_default_error_callback_fn,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
#ifdef DETERMINISTIC
|
||||
#define TEST_FAILURE(msg) do { \
|
||||
fprintf(stderr, "%s\n", msg); \
|
||||
@@ -115,38 +142,6 @@ static SECP256K1_INLINE void *checked_realloc(const secp256k1_callback* cb, void
|
||||
|
||||
#define ROUND_TO_ALIGN(size) ((((size) + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT)
|
||||
|
||||
/* Assume there is a contiguous memory object with bounds [base, base + max_size)
|
||||
* of which the memory range [base, *prealloc_ptr) is already allocated for usage,
|
||||
* where *prealloc_ptr is an aligned pointer. In that setting, this functions
|
||||
* reserves the subobject [*prealloc_ptr, *prealloc_ptr + alloc_size) of
|
||||
* alloc_size bytes by increasing *prealloc_ptr accordingly, taking into account
|
||||
* alignment requirements.
|
||||
*
|
||||
* The function returns an aligned pointer to the newly allocated subobject.
|
||||
*
|
||||
* This is useful for manual memory management: if we're simply given a block
|
||||
* [base, base + max_size), the caller can use this function to allocate memory
|
||||
* in this block and keep track of the current allocation state with *prealloc_ptr.
|
||||
*
|
||||
* It is VERIFY_CHECKed that there is enough space left in the memory object and
|
||||
* *prealloc_ptr is aligned relative to base.
|
||||
*/
|
||||
static SECP256K1_INLINE void *manual_alloc(void** prealloc_ptr, size_t alloc_size, void* base, size_t max_size) {
|
||||
size_t aligned_alloc_size = ROUND_TO_ALIGN(alloc_size);
|
||||
void* ret;
|
||||
VERIFY_CHECK(prealloc_ptr != NULL);
|
||||
VERIFY_CHECK(*prealloc_ptr != NULL);
|
||||
VERIFY_CHECK(base != NULL);
|
||||
VERIFY_CHECK((unsigned char*)*prealloc_ptr >= (unsigned char*)base);
|
||||
VERIFY_CHECK(((unsigned char*)*prealloc_ptr - (unsigned char*)base) % ALIGNMENT == 0);
|
||||
VERIFY_CHECK((unsigned char*)*prealloc_ptr - (unsigned char*)base + aligned_alloc_size <= max_size);
|
||||
/* Avoid unused parameter warnings when building without VERIFY */
|
||||
(void) base; (void) max_size;
|
||||
ret = *prealloc_ptr;
|
||||
*prealloc_ptr = (unsigned char*)*prealloc_ptr + aligned_alloc_size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Macro for restrict, when available and not in a VERIFY build. */
|
||||
#if defined(SECP256K1_BUILD) && defined(VERIFY)
|
||||
# define SECP256K1_RESTRICT
|
||||
|
||||
Reference in New Issue
Block a user