Merge bitcoin-core/secp256k1#956: Replace ecmult_context with a generated static array.

20abd52c2e Add tests for pre_g tables. (Russell O'Connor)
6815761cf5 Remove ecmult_context. (Russell O'Connor)
f20dcbbad1 Correct typo. (Russell O'Connor)
16a3cc07e8 Generate ecmult_static_pre_g.h (Russell O'Connor)
8de2d86a06 Bump memory limits in advance of making the ecmult context static. (Russell O'Connor)

Pull request description:

  Replace ecmult_context with a static array.

ACKs for top commit:
  real-or-random:
    ACK 20abd52c2e code inspection and tested some parameters
  sipa:
    utACK 20abd52c2e (reviewed diff with earlier reviewed commit 8e9f75a5888a8ec549fe9026053051c3db7a1282)

Tree-SHA512: 9980edf36e81430ea1774e6d5eef81946c26684f6e13eab2b61a8a6c9f23ed074ea8f33e80023bdf4275749275221879eacc8f222d2027e4286725127139f069
This commit is contained in:
Tim Ruffing 2021-08-25 20:43:11 +02:00
commit 9a5a87e0f1
No known key found for this signature in database
GPG Key ID: 8C461CCD293F6011
24 changed files with 17060 additions and 460 deletions

View File

@ -278,7 +278,7 @@ task:
container:
dockerfile: ci/linux-debian.Dockerfile
cpu: 1
memory: 1G
memory: 2G
env:
ECDH: yes
RECOVERY: yes

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
src/ecmult_static_pre_g.h linguist-generated

1
.gitignore vendored
View File

@ -9,6 +9,7 @@ bench_internal
tests
exhaustive_tests
gen_context
gen_ecmult_static_pre_g
valgrind_ctime_test
*.exe
*.so

View File

@ -127,12 +127,19 @@ exhaustive_tests_LDFLAGS = -static
TESTS += exhaustive_tests
endif
EXTRA_PROGRAMS = gen_ecmult_static_pre_g
gen_ecmult_static_pre_g_SOURCES = src/gen_ecmult_static_pre_g.c
# See Automake manual, Section "Errors with distclean"
src/ecmult_static_pre_g.h:
$(MAKE) $(AM_MAKEFLAGS) gen_ecmult_static_pre_g$(EXEEXT)
./gen_ecmult_static_pre_g$(EXEEXT)
if USE_ECMULT_STATIC_PRECOMPUTATION
CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) -I$(builddir)/src
gen_context_OBJECTS = gen_context.o
gen_context_BIN = gen_context$(BUILD_EXEEXT)
gen_%.o: src/gen_%.c src/libsecp256k1-config.h
$(gen_context_OBJECTS): src/gen_context.c src/libsecp256k1-config.h
$(CC_FOR_BUILD) $(DEFS) $(CPPFLAGS_FOR_BUILD) $(SECP_CFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@
$(gen_context_BIN): $(gen_context_OBJECTS)
@ -149,7 +156,7 @@ src/ecmult_static_context.h: $(gen_context_BIN)
CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h
endif
EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h
EXTRA_DIST = autogen.sh src/gen_context.c src/ecmult_static_pre_g.h src/basic-config.h
if ENABLE_MODULE_ECDH
include src/modules/ecdh/Makefile.am.include

View File

@ -177,6 +177,8 @@ AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE|auto],
[window size for ecmult precomputation for verification, specified as integer in range [2..24].]
[Larger values result in possibly better performance at the cost of an exponentially larger precomputed table.]
[The table will store 2^(SIZE-1) * 64 bytes of data but can be larger in memory due to platform-specific padding and alignment.]
[A window size larger than 15 will require you delete the prebuilt ecmult_static_pre_g.h file so that it can be rebuilt.]
[For very large window sizes, use "make -j 1" to reduce memory use during compilation.]
["auto" is a reasonable setting for desktop machines (currently 15). [default=auto]]
)],
[req_ecmult_window=$withval], [req_ecmult_window=auto])

View File

@ -129,7 +129,7 @@ static void bench_ecmult_1(void* arg, int iters) {
int i;
for (i = 0; i < iters; ++i) {
secp256k1_ecmult(&data->ctx->ecmult_ctx, &data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], NULL);
secp256k1_ecmult(&data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], NULL);
}
}
@ -145,7 +145,7 @@ static void bench_ecmult_1g(void* arg, int iters) {
secp256k1_scalar_set_int(&zero, 0);
for (i = 0; i < iters; ++i) {
secp256k1_ecmult(&data->ctx->ecmult_ctx, &data->output[i], NULL, &zero, &data->scalars[(data->offset1+i) % POINTS]);
secp256k1_ecmult(&data->output[i], NULL, &zero, &data->scalars[(data->offset1+i) % POINTS]);
}
}
@ -159,7 +159,7 @@ static void bench_ecmult_2g(void* arg, int iters) {
int i;
for (i = 0; i < iters/2; ++i) {
secp256k1_ecmult(&data->ctx->ecmult_ctx, &data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], &data->scalars[(data->offset1+i) % POINTS]);
secp256k1_ecmult(&data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], &data->scalars[(data->offset1+i) % POINTS]);
}
}
@ -207,7 +207,7 @@ static void bench_ecmult_multi(void* arg, int iters) {
iters = iters / data->count;
for (iter = 0; iter < iters; ++iter) {
data->ecmult_multi(&data->ctx->error_callback, &data->ctx->ecmult_ctx, data->scratch, &data->output[iter], data->includes_g ? &data->scalars[data->offset1] : NULL, bench_ecmult_multi_callback, arg, count - includes_g);
data->ecmult_multi(&data->ctx->error_callback, data->scratch, &data->output[iter], data->includes_g ? &data->scalars[data->offset1] : NULL, bench_ecmult_multi_callback, arg, count - includes_g);
data->offset1 = (data->offset1 + count) % POINTS;
data->offset2 = (data->offset2 + count - 1) % POINTS;
}
@ -266,7 +266,7 @@ static void run_ecmult_multi_bench(bench_data* data, size_t count, int includes_
secp256k1_scalar_add(&total, &total, &tmp);
}
secp256k1_scalar_negate(&total, &total);
secp256k1_ecmult(&data->ctx->ecmult_ctx, &data->expected_output[iter], NULL, &zero, &total);
secp256k1_ecmult(&data->expected_output[iter], NULL, &zero, &total);
}
/* Run the benchmark. */

View File

@ -15,7 +15,7 @@
static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, const unsigned char *sig, size_t size);
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s);
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message);
static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message);
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid);
#endif /* SECP256K1_ECDSA_H */

View File

@ -204,7 +204,7 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const
return 1;
}
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) {
static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) {
unsigned char c[32];
secp256k1_scalar sn, u1, u2;
#if !defined(EXHAUSTIVE_TEST_ORDER)
@ -221,7 +221,7 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const
secp256k1_scalar_mul(&u1, &sn, message);
secp256k1_scalar_mul(&u2, &sn, sigr);
secp256k1_gej_set_ge(&pubkeyj, pubkey);
secp256k1_ecmult(ctx, &pr, &pubkeyj, &u2, &u1);
secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1);
if (secp256k1_gej_is_infinity(&pr)) {
return 0;
}

View File

@ -18,8 +18,8 @@ static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char
static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed);
static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak);
static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak);
static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge *key, const secp256k1_scalar *tweak);
static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak);
static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak);
static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge *key, const secp256k1_scalar *tweak);
#endif /* SECP256K1_ECKEY_H */

View File

@ -57,12 +57,12 @@ static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp25
return !secp256k1_scalar_is_zero(key);
}
static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) {
static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge *key, const secp256k1_scalar *tweak) {
secp256k1_gej pt;
secp256k1_scalar one;
secp256k1_gej_set_ge(&pt, key);
secp256k1_scalar_set_int(&one, 1);
secp256k1_ecmult(ctx, &pt, &pt, &one, tweak);
secp256k1_ecmult(&pt, &pt, &one, tweak);
if (secp256k1_gej_is_infinity(&pt)) {
return 0;
@ -79,7 +79,7 @@ static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp25
return ret;
}
static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) {
static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge *key, const secp256k1_scalar *tweak) {
secp256k1_scalar zero;
secp256k1_gej pt;
if (secp256k1_scalar_is_zero(tweak)) {
@ -88,7 +88,7 @@ static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx,
secp256k1_scalar_set_int(&zero, 0);
secp256k1_gej_set_ge(&pt, key);
secp256k1_ecmult(ctx, &pt, &pt, tweak, &zero);
secp256k1_ecmult(&pt, &pt, tweak, &zero);
secp256k1_ge_set_gej(key, &pt);
return 1;
}

View File

@ -11,20 +11,26 @@
#include "scalar.h"
#include "scratch.h"
typedef struct {
/* For accelerating the computation of a*P + b*G: */
secp256k1_ge_storage (*pre_g)[]; /* odd multiples of the generator */
secp256k1_ge_storage (*pre_g_128)[]; /* odd multiples of 2^128*generator */
} secp256k1_ecmult_context;
/* Noone will ever need more than a window size of 24. The code might
* be correct for larger values of ECMULT_WINDOW_SIZE but this is not
* tested.
*
* The following limitations are known, and there are probably more:
* If WINDOW_G > 27 and size_t has 32 bits, then the code is incorrect
* because the size of the memory object that we allocate (in bytes)
* will not fit in a size_t.
* If WINDOW_G > 31 and int has 32 bits, then the code is incorrect
* because certain expressions will overflow.
*/
#if ECMULT_WINDOW_SIZE < 2 || ECMULT_WINDOW_SIZE > 24
# error Set ECMULT_WINDOW_SIZE to an integer in range [2..24].
#endif
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx);
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void **prealloc);
static void secp256k1_ecmult_context_finalize_memcpy(secp256k1_ecmult_context *dst, const secp256k1_ecmult_context *src);
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx);
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx);
/** The number of entries a table with precomputed multiples needs to have. */
#define ECMULT_TABLE_SIZE(w) (1L << ((w)-2))
/** Double multiply: R = na*A + ng*G */
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng);
static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng);
typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data);
@ -39,6 +45,6 @@ typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge
* 0 if there is not enough scratch space for a single point or
* callback returns 0
*/
static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n);
static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n);
#endif /* SECP256K1_ECMULT_H */

View File

@ -14,6 +14,7 @@
#include "group.h"
#include "scalar.h"
#include "ecmult.h"
#include "ecmult_static_pre_g.h"
#if defined(EXHAUSTIVE_TEST_ORDER)
/* We need to lower these values for exhaustive tests because
@ -21,13 +22,10 @@
* affine-isomorphism stuff which tracks z-ratios) */
# if EXHAUSTIVE_TEST_ORDER > 128
# define WINDOW_A 5
# define WINDOW_G 8
# elif EXHAUSTIVE_TEST_ORDER > 8
# define WINDOW_A 4
# define WINDOW_G 4
# else
# define WINDOW_A 2
# define WINDOW_G 2
# endif
#else
/* optimal for 128-bit and 256-bit exponents. */
@ -41,31 +39,12 @@
* Two tables of this size are used (due to the endomorphism
* optimization).
*/
# define WINDOW_G ECMULT_WINDOW_SIZE
#endif
/* Noone will ever need more than a window size of 24. The code might
* be correct for larger values of ECMULT_WINDOW_SIZE but this is not
* not tested.
*
* The following limitations are known, and there are probably more:
* If WINDOW_G > 27 and size_t has 32 bits, then the code is incorrect
* because the size of the memory object that we allocate (in bytes)
* will not fit in a size_t.
* If WINDOW_G > 31 and int has 32 bits, then the code is incorrect
* because certain expressions will overflow.
*/
#if ECMULT_WINDOW_SIZE < 2 || ECMULT_WINDOW_SIZE > 24
# error Set ECMULT_WINDOW_SIZE to an integer in range [2..24].
#endif
#define WNAF_BITS 128
#define WNAF_SIZE_BITS(bits, w) (((bits) + (w) - 1) / (w))
#define WNAF_SIZE(w) WNAF_SIZE_BITS(WNAF_BITS, w)
/** The number of entries a table with precomputed multiples needs to have. */
#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2))
/* The number of objects allocated on the scratch space for ecmult_multi algorithms */
#define PIPPENGER_SCRATCH_OBJECTS 6
#define STRAUSS_SCRATCH_OBJECTS 6
@ -119,18 +98,12 @@ static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, sec
/** Fill a table 'pre' with precomputed odd multiples of a.
*
* There are two versions of this function:
* - secp256k1_ecmult_odd_multiples_table_globalz_windowa which brings its
* resulting point set to a single constant Z denominator, stores the X and Y
* coordinates as ge_storage points in pre, and stores the global Z in rz.
* It only operates on tables sized for WINDOW_A wnaf multiples.
* - secp256k1_ecmult_odd_multiples_table_storage_var, which converts its
* resulting point set to actually affine points, and stores those in pre.
* It operates on tables of any size.
* The resulting point set is brought to a single constant Z denominator, stores the X and Y
* coordinates as ge_storage points in pre, and stores the global Z in rz.
* It only operates on tables sized for WINDOW_A wnaf multiples.
*
* To compute a*P + b*G, we compute a table for P using the first function,
* and for G using the second (which requires an inverse, but it only needs to
* happen once).
* To compute a*P + b*G, we compute a table for P using this function,
* and use the precomputed table in <ecmult_static_pre_g.h> for G.
*/
static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *pre, secp256k1_fe *globalz, const secp256k1_gej *a) {
secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)];
@ -142,137 +115,6 @@ static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *p
secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr);
}
static void secp256k1_ecmult_odd_multiples_table_storage_var(const int n, secp256k1_ge_storage *pre, const secp256k1_gej *a) {
secp256k1_gej d;
secp256k1_ge d_ge, p_ge;
secp256k1_gej pj;
secp256k1_fe zi;
secp256k1_fe zr;
secp256k1_fe dx_over_dz_squared;
int i;
VERIFY_CHECK(!a->infinity);
secp256k1_gej_double_var(&d, a, NULL);
/* First, we perform all the additions in an isomorphic curve obtained by multiplying
* all `z` coordinates by 1/`d.z`. In these coordinates `d` is affine so we can use
* `secp256k1_gej_add_ge_var` to perform the additions. For each addition, we store
* the resulting y-coordinate and the z-ratio, since we only have enough memory to
* store two field elements. These are sufficient to efficiently undo the isomorphism
* and recompute all the `x`s.
*/
d_ge.x = d.x;
d_ge.y = d.y;
d_ge.infinity = 0;
secp256k1_ge_set_gej_zinv(&p_ge, a, &d.z);
pj.x = p_ge.x;
pj.y = p_ge.y;
pj.z = a->z;
pj.infinity = 0;
for (i = 0; i < (n - 1); i++) {
secp256k1_fe_normalize_var(&pj.y);
secp256k1_fe_to_storage(&pre[i].y, &pj.y);
secp256k1_gej_add_ge_var(&pj, &pj, &d_ge, &zr);
secp256k1_fe_normalize_var(&zr);
secp256k1_fe_to_storage(&pre[i].x, &zr);
}
/* Invert d.z in the same batch, preserving pj.z so we can extract 1/d.z */
secp256k1_fe_mul(&zi, &pj.z, &d.z);
secp256k1_fe_inv_var(&zi, &zi);
/* Directly set `pre[n - 1]` to `pj`, saving the inverted z-coordinate so
* that we can combine it with the saved z-ratios to compute the other zs
* without any more inversions. */
secp256k1_ge_set_gej_zinv(&p_ge, &pj, &zi);
secp256k1_ge_to_storage(&pre[n - 1], &p_ge);
/* Compute the actual x-coordinate of D, which will be needed below. */
secp256k1_fe_mul(&d.z, &zi, &pj.z); /* d.z = 1/d.z */
secp256k1_fe_sqr(&dx_over_dz_squared, &d.z);
secp256k1_fe_mul(&dx_over_dz_squared, &dx_over_dz_squared, &d.x);
/* Going into the second loop, we have set `pre[n-1]` to its final affine
* form, but still need to set `pre[i]` for `i` in 0 through `n-2`. We
* have `zi = (p.z * d.z)^-1`, where
*
* `p.z` is the z-coordinate of the point on the isomorphic curve
* which was ultimately assigned to `pre[n-1]`.
* `d.z` is the multiplier that must be applied to all z-coordinates
* to move from our isomorphic curve back to secp256k1; so the
* product `p.z * d.z` is the z-coordinate of the secp256k1
* point assigned to `pre[n-1]`.
*
* All subsequent inverse-z-coordinates can be obtained by multiplying this
* factor by successive z-ratios, which is much more efficient than directly
* computing each one.
*
* Importantly, these inverse-zs will be coordinates of points on secp256k1,
* while our other stored values come from computations on the isomorphic
* curve. So in the below loop, we will take care not to actually use `zi`
* or any derived values until we're back on secp256k1.
*/
i = n - 1;
while (i > 0) {
secp256k1_fe zi2, zi3;
const secp256k1_fe *rzr;
i--;
secp256k1_ge_from_storage(&p_ge, &pre[i]);
/* For each remaining point, we extract the z-ratio from the stored
* x-coordinate, compute its z^-1 from that, and compute the full
* point from that. */
rzr = &p_ge.x;
secp256k1_fe_mul(&zi, &zi, rzr);
secp256k1_fe_sqr(&zi2, &zi);
secp256k1_fe_mul(&zi3, &zi2, &zi);
/* To compute the actual x-coordinate, we use the stored z ratio and
* y-coordinate, which we obtained from `secp256k1_gej_add_ge_var`
* in the loop above, as well as the inverse of the square of its
* z-coordinate. We store the latter in the `zi2` variable, which is
* computed iteratively starting from the overall Z inverse then
* multiplying by each z-ratio in turn.
*
* Denoting the z-ratio as `rzr`, we observe that it is equal to `h`
* from the inside of the above `gej_add_ge_var` call. This satisfies
*
* rzr = d_x * z^2 - x * d_z^2
*
* where (`d_x`, `d_z`) are Jacobian coordinates of `D` and `(x, z)`
* are Jacobian coordinates of our desired point -- except both are on
* the isomorphic curve that we were using when we called `gej_add_ge_var`.
* To get back to secp256k1, we must multiply both `z`s by `d_z`, or
* equivalently divide both `x`s by `d_z^2`. Our equation then becomes
*
* rzr = d_x * z^2 / d_z^2 - x
*
* (The left-hand-side, being a ratio of z-coordinates, is unaffected
* by the isomorphism.)
*
* Rearranging to solve for `x`, we have
*
* x = d_x * z^2 / d_z^2 - rzr
*
* But what we actually want is the affine coordinate `X = x/z^2`,
* which will satisfy
*
* X = d_x / d_z^2 - rzr / z^2
* = dx_over_dz_squared - rzr * zi2
*/
secp256k1_fe_mul(&p_ge.x, rzr, &zi2);
secp256k1_fe_negate(&p_ge.x, &p_ge.x, 1);
secp256k1_fe_add(&p_ge.x, &dx_over_dz_squared);
/* y is stored_y/z^3, as we expect */
secp256k1_fe_mul(&p_ge.y, &p_ge.y, &zi3);
/* Store */
secp256k1_ge_to_storage(&pre[i], &p_ge);
}
}
/** The following two macro retrieves a particular odd multiple from a table
* of precomputed multiples. */
#define ECMULT_TABLE_GET_GE(r,pre,n,w) do { \
@ -299,74 +141,6 @@ static void secp256k1_ecmult_odd_multiples_table_storage_var(const int n, secp25
} \
} while(0)
static const size_t SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE =
ROUND_TO_ALIGN(sizeof((*((secp256k1_ecmult_context*) NULL)->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G))
+ ROUND_TO_ALIGN(sizeof((*((secp256k1_ecmult_context*) NULL)->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G))
;
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) {
ctx->pre_g = NULL;
ctx->pre_g_128 = NULL;
}
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void **prealloc) {
secp256k1_gej gj;
void* const base = *prealloc;
size_t const prealloc_size = SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;
if (ctx->pre_g != NULL) {
return;
}
/* get the generator */
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
{
size_t size = sizeof((*ctx->pre_g)[0]) * ((size_t)ECMULT_TABLE_SIZE(WINDOW_G));
/* check for overflow */
VERIFY_CHECK(size / sizeof((*ctx->pre_g)[0]) == ((size_t)ECMULT_TABLE_SIZE(WINDOW_G)));
ctx->pre_g = (secp256k1_ge_storage (*)[])manual_alloc(prealloc, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G), base, prealloc_size);
}
/* precompute the tables with odd multiples */
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj);
{
secp256k1_gej g_128j;
int i;
size_t size = sizeof((*ctx->pre_g_128)[0]) * ((size_t) ECMULT_TABLE_SIZE(WINDOW_G));
/* check for overflow */
VERIFY_CHECK(size / sizeof((*ctx->pre_g_128)[0]) == ((size_t)ECMULT_TABLE_SIZE(WINDOW_G)));
ctx->pre_g_128 = (secp256k1_ge_storage (*)[])manual_alloc(prealloc, sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G), base, prealloc_size);
/* calculate 2^128*generator */
g_128j = gj;
for (i = 0; i < 128; i++) {
secp256k1_gej_double_var(&g_128j, &g_128j, NULL);
}
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j);
}
}
static void secp256k1_ecmult_context_finalize_memcpy(secp256k1_ecmult_context *dst, const secp256k1_ecmult_context *src) {
if (src->pre_g != NULL) {
/* We cast to void* first to suppress a -Wcast-align warning. */
dst->pre_g = (secp256k1_ge_storage (*)[])(void*)((unsigned char*)dst + ((unsigned char*)(src->pre_g) - (unsigned char*)src));
}
if (src->pre_g_128 != NULL) {
dst->pre_g_128 = (secp256k1_ge_storage (*)[])(void*)((unsigned char*)dst + ((unsigned char*)(src->pre_g_128) - (unsigned char*)src));
}
}
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx) {
return ctx->pre_g != NULL;
}
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx) {
secp256k1_ecmult_context_init(ctx);
}
/** 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)
@ -443,7 +217,7 @@ struct secp256k1_strauss_state {
struct secp256k1_strauss_point_state* ps;
};
static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, const struct secp256k1_strauss_state *state, secp256k1_gej *r, size_t num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *state, secp256k1_gej *r, size_t num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
secp256k1_ge tmpa;
secp256k1_fe Z;
/* Splitted G factors. */
@ -544,11 +318,11 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c
}
}
if (i < bits_ng_1 && (n = wnaf_ng_1[i])) {
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G);
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, secp256k1_pre_g, n, WINDOW_G);
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
}
if (i < bits_ng_128 && (n = wnaf_ng_128[i])) {
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g_128, n, WINDOW_G);
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, secp256k1_pre_g_128, n, WINDOW_G);
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
}
}
@ -558,7 +332,7 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c
}
}
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
@ -571,7 +345,7 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej
state.pre_a = pre_a;
state.pre_a_lam = pre_a_lam;
state.ps = ps;
secp256k1_ecmult_strauss_wnaf(ctx, &state, r, 1, a, na, ng);
secp256k1_ecmult_strauss_wnaf(&state, r, 1, a, na, ng);
}
static size_t secp256k1_strauss_scratch_size(size_t n_points) {
@ -579,7 +353,7 @@ static size_t secp256k1_strauss_scratch_size(size_t n_points) {
return n_points*point_size;
}
static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
secp256k1_gej* points;
secp256k1_scalar* scalars;
struct secp256k1_strauss_state state;
@ -612,14 +386,14 @@ static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callba
}
secp256k1_gej_set_ge(&points[i], &point);
}
secp256k1_ecmult_strauss_wnaf(ctx, &state, r, n_points, points, scalars, inp_g_sc);
secp256k1_ecmult_strauss_wnaf(&state, r, n_points, points, scalars, inp_g_sc);
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
return 1;
}
/* Wrapper for secp256k1_ecmult_multi_func interface */
static int secp256k1_ecmult_strauss_batch_single(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *actx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
return secp256k1_ecmult_strauss_batch(error_callback, actx, scratch, r, inp_g_sc, cb, cbdata, n, 0);
static int secp256k1_ecmult_strauss_batch_single(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
return secp256k1_ecmult_strauss_batch(error_callback, scratch, r, inp_g_sc, cb, cbdata, n, 0);
}
static size_t secp256k1_strauss_max_points(const secp256k1_callback* error_callback, secp256k1_scratch *scratch) {
@ -866,7 +640,7 @@ static size_t secp256k1_pippenger_scratch_size(size_t n_points, int bucket_windo
return (sizeof(secp256k1_gej) << bucket_window) + sizeof(struct secp256k1_pippenger_state) + entries * entry_size;
}
static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
const size_t scratch_checkpoint = secp256k1_scratch_checkpoint(error_callback, scratch);
/* Use 2(n+1) with the endomorphism, when calculating batch
* sizes. The reason for +1 is that we add the G scalar to the list of
@ -881,7 +655,6 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call
int i, j;
int bucket_window;
(void)ctx;
secp256k1_gej_set_infinity(r);
if (inp_g_sc == NULL && n_points == 0) {
return 1;
@ -941,8 +714,8 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call
}
/* Wrapper for secp256k1_ecmult_multi_func interface */
static int secp256k1_ecmult_pippenger_batch_single(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *actx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
return secp256k1_ecmult_pippenger_batch(error_callback, actx, scratch, r, inp_g_sc, cb, cbdata, n, 0);
static int secp256k1_ecmult_pippenger_batch_single(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
return secp256k1_ecmult_pippenger_batch(error_callback, scratch, r, inp_g_sc, cb, cbdata, n, 0);
}
/**
@ -986,7 +759,7 @@ static size_t secp256k1_pippenger_max_points(const secp256k1_callback* error_cal
/* Computes ecmult_multi by simply multiplying and adding each point. Does not
* require a scratch space */
static int secp256k1_ecmult_multi_simple_var(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points) {
static int secp256k1_ecmult_multi_simple_var(secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points) {
size_t point_idx;
secp256k1_scalar szero;
secp256k1_gej tmpj;
@ -995,7 +768,7 @@ static int secp256k1_ecmult_multi_simple_var(const secp256k1_ecmult_context *ctx
secp256k1_gej_set_infinity(r);
secp256k1_gej_set_infinity(&tmpj);
/* r = inp_g_sc*G */
secp256k1_ecmult(ctx, r, &tmpj, &szero, inp_g_sc);
secp256k1_ecmult(r, &tmpj, &szero, inp_g_sc);
for (point_idx = 0; point_idx < n_points; point_idx++) {
secp256k1_ge point;
secp256k1_gej pointj;
@ -1005,7 +778,7 @@ static int secp256k1_ecmult_multi_simple_var(const secp256k1_ecmult_context *ctx
}
/* r += scalar*point */
secp256k1_gej_set_ge(&pointj, &point);
secp256k1_ecmult(ctx, &tmpj, &pointj, &scalar, NULL);
secp256k1_ecmult(&tmpj, &pointj, &scalar, NULL);
secp256k1_gej_add_var(r, r, &tmpj, NULL);
}
return 1;
@ -1031,11 +804,11 @@ static int secp256k1_ecmult_multi_batch_size_helper(size_t *n_batches, size_t *n
return 1;
}
typedef int (*secp256k1_ecmult_multi_func)(const secp256k1_callback* error_callback, const secp256k1_ecmult_context*, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t);
static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
typedef int (*secp256k1_ecmult_multi_func)(const secp256k1_callback* error_callback, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t);
static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
size_t i;
int (*f)(const secp256k1_callback* error_callback, const secp256k1_ecmult_context*, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t, size_t);
int (*f)(const secp256k1_callback* error_callback, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t, size_t);
size_t n_batches;
size_t n_batch_points;
@ -1045,11 +818,11 @@ static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback,
} else if (n == 0) {
secp256k1_scalar szero;
secp256k1_scalar_set_int(&szero, 0);
secp256k1_ecmult(ctx, r, r, &szero, inp_g_sc);
secp256k1_ecmult(r, r, &szero, inp_g_sc);
return 1;
}
if (scratch == NULL) {
return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n);
return secp256k1_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n);
}
/* Compute the batch sizes for Pippenger's algorithm given a scratch space. If it's greater than
@ -1057,13 +830,13 @@ static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback,
* As a first step check if there's enough space for Pippenger's algo (which requires less space
* than Strauss' algo) and if not, use the simple algorithm. */
if (!secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, secp256k1_pippenger_max_points(error_callback, scratch), n)) {
return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n);
return secp256k1_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n);
}
if (n_batch_points >= ECMULT_PIPPENGER_THRESHOLD) {
f = secp256k1_ecmult_pippenger_batch;
} else {
if (!secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, secp256k1_strauss_max_points(error_callback, scratch), n)) {
return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n);
return secp256k1_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n);
}
f = secp256k1_ecmult_strauss_batch;
}
@ -1071,7 +844,7 @@ static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback,
size_t nbp = n < n_batch_points ? n : n_batch_points;
size_t offset = n_batch_points*i;
secp256k1_gej tmp;
if (!f(error_callback, ctx, scratch, &tmp, i == 0 ? inp_g_sc : NULL, cb, cbdata, nbp, offset)) {
if (!f(error_callback, scratch, &tmp, i == 0 ? inp_g_sc : NULL, cb, cbdata, nbp, offset)) {
return 0;
}
secp256k1_gej_add_var(r, r, &tmp, NULL);

16611
src/ecmult_static_pre_g.h generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,137 @@
/*****************************************************************************************************
* Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor *
* 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>
/* Autotools creates libsecp256k1-config.h, of which ECMULT_WINDOW_SIZE is needed.
ifndef guard so downstream users can define their own if they do not use autotools. */
#if !defined(ECMULT_WINDOW_SIZE)
#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"
#include "field_impl.h"
#include "group_impl.h"
#include "ecmult.h"
void print_table(FILE *fp, const char *name, int window_g, const secp256k1_gej *gen, int with_conditionals) {
static secp256k1_gej gj;
static secp256k1_ge ge, dgen;
static secp256k1_ge_storage ges;
int j;
int i;
gj = *gen;
secp256k1_ge_set_gej_var(&ge, &gj);
secp256k1_ge_to_storage(&ges, &ge);
fprintf(fp, "static const secp256k1_ge_storage %s[ECMULT_TABLE_SIZE(WINDOW_G)] = {\n", name);
fprintf(fp, " S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32
",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n",
SECP256K1_GE_STORAGE_CONST_GET(ges));
secp256k1_gej_double_var(&gj, gen, NULL);
secp256k1_ge_set_gej_var(&dgen, &gj);
j = 1;
for(i = 3; i <= window_g; ++i) {
if (with_conditionals) {
fprintf(fp, "#if ECMULT_TABLE_SIZE(WINDOW_G) > %ld\n", ECMULT_TABLE_SIZE(i-1));
}
for(;j < ECMULT_TABLE_SIZE(i); ++j) {
secp256k1_gej_set_ge(&gj, &ge);
secp256k1_gej_add_ge_var(&gj, &gj, &dgen, NULL);
secp256k1_ge_set_gej_var(&ge, &gj);
secp256k1_ge_to_storage(&ges, &ge);
fprintf(fp, ",S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32
",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n",
SECP256K1_GE_STORAGE_CONST_GET(ges));
}
if (with_conditionals) {
fprintf(fp, "#endif\n");
}
}
fprintf(fp, "};\n");
}
void print_two_tables(FILE *fp, int window_g, const secp256k1_ge *g, int with_conditionals) {
secp256k1_gej gj;
int i;
secp256k1_gej_set_ge(&gj, g);
print_table(fp, "secp256k1_pre_g", window_g, &gj, with_conditionals);
for (i = 0; i < 128; ++i) {
secp256k1_gej_double_var(&gj, &gj, NULL);
}
print_table(fp, "secp256k1_pre_g_128", window_g, &gj, with_conditionals);
}
int main(void) {
const secp256k1_ge g = SECP256K1_G;
const secp256k1_ge g_13 = SECP256K1_G_ORDER_13;
const secp256k1_ge g_199 = SECP256K1_G_ORDER_199;
const int window_g_13 = 4;
const int window_g_199 = 8;
FILE* fp;
fp = fopen("src/ecmult_static_pre_g.h","w");
if (fp == NULL) {
fprintf(stderr, "Could not open src/ecmult_static_pre_g.h for writing!\n");
return -1;
}
fprintf(fp, "/* This file was automatically generated by gen_ecmult_static_pre_g. */\n");
fprintf(fp, "/* This file contains an array secp256k1_pre_g with odd multiples of the base point G and\n");
fprintf(fp, " * an array secp256k1_pre_g_128 with odd multiples of 2^128*G for accelerating the computation of a*P + b*G.\n");
fprintf(fp, " */\n");
fprintf(fp, "#ifndef SECP256K1_ECMULT_STATIC_PRE_G_H\n");
fprintf(fp, "#define SECP256K1_ECMULT_STATIC_PRE_G_H\n");
fprintf(fp, "#include \"group.h\"\n");
fprintf(fp, "#ifdef S\n");
fprintf(fp, " #error macro identifier S already in use.\n");
fprintf(fp, "#endif\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, "#if ECMULT_TABLE_SIZE(ECMULT_WINDOW_SIZE) > %ld\n", ECMULT_TABLE_SIZE(ECMULT_WINDOW_SIZE));
fprintf(fp, " #error configuration mismatch, invalid ECMULT_WINDOW_SIZE. Try deleting ecmult_static_pre_g.h before the build.\n");
fprintf(fp, "#endif\n");
fprintf(fp, "#if defined(EXHAUSTIVE_TEST_ORDER)\n");
fprintf(fp, "#if EXHAUSTIVE_TEST_ORDER == 13\n");
fprintf(fp, "#define WINDOW_G %d\n", window_g_13);
print_two_tables(fp, window_g_13, &g_13, 0);
fprintf(fp, "#elif EXHAUSTIVE_TEST_ORDER == 199\n");
fprintf(fp, "#define WINDOW_G %d\n", window_g_199);
print_two_tables(fp, window_g_199, &g_199, 0);
fprintf(fp, "#else\n");
fprintf(fp, " #error No known generator for the specified exhaustive test group order.\n");
fprintf(fp, "#endif\n");
fprintf(fp, "#else /* !defined(EXHAUSTIVE_TEST_ORDER) */\n");
fprintf(fp, "#define WINDOW_G ECMULT_WINDOW_SIZE\n");
print_two_tables(fp, ECMULT_WINDOW_SIZE, &g, 1);
fprintf(fp, "#endif\n");
fprintf(fp, "#undef S\n");
fprintf(fp, "#endif\n");
fclose(fp);
return 0;
}

View File

@ -10,6 +10,27 @@
#include "field.h"
#include "group.h"
#define SECP256K1_G_ORDER_13 SECP256K1_GE_CONST(\
0xc3459c3d, 0x35326167, 0xcd86cce8, 0x07a2417f,\
0x5b8bd567, 0xde8538ee, 0x0d507b0c, 0xd128f5bb,\
0x8e467fec, 0xcd30000a, 0x6cc1184e, 0x25d382c2,\
0xa2f4494e, 0x2fbe9abc, 0x8b64abac, 0xd005fb24\
)
#define SECP256K1_G_ORDER_199 SECP256K1_GE_CONST(\
0x226e653f, 0xc8df7744, 0x9bacbf12, 0x7d1dcbf9,\
0x87f05b2a, 0xe7edbd28, 0x1f564575, 0xc48dcf18,\
0xa13872c2, 0xe933bb17, 0x5d9ffd5b, 0xb5b6e10c,\
0x57fe3c00, 0xbaaaa15a, 0xe003ec3e, 0x9c269bae\
)
/** Generator for secp256k1, value 'g' defined in
* "Standards for Efficient Cryptography" (SEC2) 2.7.1.
*/
#define SECP256K1_G SECP256K1_GE_CONST(\
0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL,\
0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL,\
0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL,\
0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL\
)
/* These exhaustive group test orders and generators are chosen such that:
* - The field size is equal to that of secp256k1, so field code is the same.
* - The curve equation is of the form y^2=x^3+B for some constant B.
@ -21,23 +42,15 @@
*/
#if defined(EXHAUSTIVE_TEST_ORDER)
# if EXHAUSTIVE_TEST_ORDER == 13
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(
0xc3459c3d, 0x35326167, 0xcd86cce8, 0x07a2417f,
0x5b8bd567, 0xde8538ee, 0x0d507b0c, 0xd128f5bb,
0x8e467fec, 0xcd30000a, 0x6cc1184e, 0x25d382c2,
0xa2f4494e, 0x2fbe9abc, 0x8b64abac, 0xd005fb24
);
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_13;
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(
0x3d3486b2, 0x159a9ca5, 0xc75638be, 0xb23a69bc,
0x946a45ab, 0x24801247, 0xb4ed2b8e, 0x26b6a417
);
# elif EXHAUSTIVE_TEST_ORDER == 199
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(
0x226e653f, 0xc8df7744, 0x9bacbf12, 0x7d1dcbf9,
0x87f05b2a, 0xe7edbd28, 0x1f564575, 0xc48dcf18,
0xa13872c2, 0xe933bb17, 0x5d9ffd5b, 0xb5b6e10c,
0x57fe3c00, 0xbaaaa15a, 0xe003ec3e, 0x9c269bae
);
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_199;
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(
0x2cca28fa, 0xfc614b80, 0x2a3db42b, 0x00ba00b1,
0xbea8d943, 0xdace9ab2, 0x9536daea, 0x0074defb
@ -46,15 +59,7 @@ static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(
# error No known generator for the specified exhaustive test group order.
# endif
#else
/** Generator for secp256k1, value 'g' defined in
* "Standards for Efficient Cryptography" (SEC2) 2.7.1.
*/
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(
0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL,
0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL,
0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL,
0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL
);
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G;
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 7);
#endif

View File

@ -120,12 +120,11 @@ int secp256k1_xonly_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pub
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(output_pubkey != NULL);
memset(output_pubkey, 0, sizeof(*output_pubkey));
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(internal_pubkey != NULL);
ARG_CHECK(tweak32 != NULL);
if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey)
|| !secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32)) {
|| !secp256k1_ec_pubkey_tweak_add_helper(&pk, tweak32)) {
return 0;
}
secp256k1_pubkey_save(output_pubkey, &pk);
@ -137,13 +136,12 @@ int secp256k1_xonly_pubkey_tweak_add_check(const secp256k1_context* ctx, const u
unsigned char pk_expected32[32];
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(internal_pubkey != NULL);
ARG_CHECK(tweaked_pubkey32 != NULL);
ARG_CHECK(tweak32 != NULL);
if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey)
|| !secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32)) {
|| !secp256k1_ec_pubkey_tweak_add_helper(&pk, tweak32)) {
return 0;
}
secp256k1_fe_normalize_var(&pk.x);
@ -260,7 +258,6 @@ int secp256k1_keypair_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_ke
int ret;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(keypair != NULL);
ARG_CHECK(tweak32 != NULL);
@ -273,7 +270,7 @@ int secp256k1_keypair_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_ke
}
ret &= secp256k1_ec_seckey_tweak_add_helper(&sk, tweak32);
ret &= secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32);
ret &= secp256k1_ec_pubkey_tweak_add_helper(&pk, tweak32);
secp256k1_declassify(ctx, &ret, sizeof(ret));
if (ret) {

View File

@ -197,19 +197,19 @@ void test_xonly_pubkey_tweak(void) {
CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
ecount = 0;
CHECK(secp256k1_xonly_pubkey_tweak_add(none, &output_pk, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 1);
CHECK(secp256k1_xonly_pubkey_tweak_add(sign, &output_pk, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_xonly_pubkey_tweak_add(none, &output_pk, &internal_xonly_pk, tweak) == 1);
CHECK(ecount == 0);
CHECK(secp256k1_xonly_pubkey_tweak_add(sign, &output_pk, &internal_xonly_pk, tweak) == 1);
CHECK(ecount == 0);
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1);
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, NULL, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 3);
CHECK(ecount == 1);
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, NULL, tweak) == 0);
CHECK(ecount == 4);
CHECK(ecount == 2);
/* NULL internal_xonly_pk zeroes the output_pk */
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, NULL) == 0);
CHECK(ecount == 5);
CHECK(ecount == 3);
/* NULL tweak zeroes the output_pk */
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
@ -274,20 +274,20 @@ void test_xonly_pubkey_tweak_check(void) {
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1);
CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &output_xonly_pk, &pk_parity, &output_pk) == 1);
CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &output_xonly_pk) == 1);
CHECK(secp256k1_xonly_pubkey_tweak_add_check(none, buf32, pk_parity, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 1);
CHECK(secp256k1_xonly_pubkey_tweak_add_check(sign, buf32, pk_parity, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_xonly_pubkey_tweak_add_check(none, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
CHECK(ecount == 0);
CHECK(secp256k1_xonly_pubkey_tweak_add_check(sign, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
CHECK(ecount == 0);
CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, NULL, pk_parity, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 3);
CHECK(ecount == 1);
/* invalid pk_parity value */
CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, 2, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 3);
CHECK(ecount == 1);
CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, NULL, tweak) == 0);
CHECK(ecount == 4);
CHECK(ecount == 2);
CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, NULL) == 0);
CHECK(ecount == 5);
CHECK(ecount == 3);
memset(tweak, 1, sizeof(tweak));
CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &internal_xonly_pk, NULL, &internal_pk) == 1);
@ -306,7 +306,7 @@ void test_xonly_pubkey_tweak_check(void) {
CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, pk_parity, &internal_xonly_pk, overflows) == 0);
CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, overflows) == 0);
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
CHECK(ecount == 5);
CHECK(ecount == 3);
secp256k1_context_destroy(none);
secp256k1_context_destroy(sign);
@ -479,15 +479,15 @@ void test_keypair_add(void) {
memset(overflows, 0xFF, 32);
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
CHECK(secp256k1_keypair_xonly_tweak_add(none, &keypair, tweak) == 0);
CHECK(ecount == 1);
CHECK(secp256k1_keypair_xonly_tweak_add(sign, &keypair, tweak) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_keypair_xonly_tweak_add(none, &keypair, tweak) == 1);
CHECK(ecount == 0);
CHECK(secp256k1_keypair_xonly_tweak_add(sign, &keypair, tweak) == 1);
CHECK(ecount == 0);
CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 1);
CHECK(secp256k1_keypair_xonly_tweak_add(verify, NULL, tweak) == 0);
CHECK(ecount == 3);
CHECK(ecount == 1);
CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, NULL) == 0);
CHECK(ecount == 4);
CHECK(ecount == 2);
/* This does not set the keypair to zeroes */
CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) != 0);

View File

@ -84,7 +84,7 @@ int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context* ctx,
return 1;
}
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) {
static int secp256k1_ecdsa_sig_recover(const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) {
unsigned char brx[32];
secp256k1_fe fx;
secp256k1_ge x;
@ -115,7 +115,7 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, cons
secp256k1_scalar_mul(&u1, &rn, message);
secp256k1_scalar_negate(&u1, &u1);
secp256k1_scalar_mul(&u2, &rn, sigs);
secp256k1_ecmult(ctx, &qj, &xj, &u2, &u1);
secp256k1_ecmult(&qj, &xj, &u2, &u1);
secp256k1_ge_set_gej_var(pubkey, &qj);
return !secp256k1_gej_is_infinity(&qj);
}
@ -140,7 +140,6 @@ int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubk
secp256k1_scalar m;
int recid;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(msghash32 != NULL);
ARG_CHECK(signature != NULL);
ARG_CHECK(pubkey != NULL);
@ -148,7 +147,7 @@ int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubk
secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature);
VERIFY_CHECK(recid >= 0 && recid < 4); /* should have been caught in parse_compact */
secp256k1_scalar_set_b32(&m, msghash32, NULL);
if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) {
if (secp256k1_ecdsa_sig_recover(&r, &s, &q, &m, recid)) {
secp256k1_pubkey_save(pubkey, &q);
return 1;
} else {

View File

@ -92,20 +92,20 @@ void test_ecdsa_recovery_api(void) {
/* Check bad contexts and NULLs for recovery */
ecount = 0;
CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 0);
CHECK(ecount == 1);
CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 1);
CHECK(ecount == 0);
CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 1);
CHECK(ecount == 0);
CHECK(secp256k1_ecdsa_recover(vrfy, &recpubkey, &recsig, message) == 1);
CHECK(ecount == 2);
CHECK(ecount == 0);
CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, message) == 1);
CHECK(ecount == 2);
CHECK(ecount == 0);
CHECK(secp256k1_ecdsa_recover(both, NULL, &recsig, message) == 0);
CHECK(ecount == 3);
CHECK(ecount == 1);
CHECK(secp256k1_ecdsa_recover(both, &recpubkey, NULL, message) == 0);
CHECK(ecount == 4);
CHECK(ecount == 2);
CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0);
CHECK(ecount == 5);
CHECK(ecount == 3);
/* Check NULLs for conversion */
CHECK(secp256k1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1);

View File

@ -216,7 +216,6 @@ int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned cha
int overflow;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(sig64 != NULL);
ARG_CHECK(msg != NULL || msglen == 0);
ARG_CHECK(pubkey != NULL);
@ -241,7 +240,7 @@ int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned cha
/* Compute rj = s*G + (-e)*pkj */
secp256k1_scalar_negate(&e, &e);
secp256k1_gej_set_ge(&pkj, &pk);
secp256k1_ecmult(&ctx->ecmult_ctx, &rj, &pkj, &e, &s);
secp256k1_ecmult(&rj, &pkj, &e, &s);
secp256k1_ge_set_gej_var(&r, &rj);
if (secp256k1_ge_is_infinity(&r)) {

View File

@ -193,22 +193,22 @@ void test_schnorrsig_api(void) {
ecount = 0;
CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &keypairs[0], NULL) == 1);
CHECK(secp256k1_schnorrsig_verify(none, sig, msg, sizeof(msg), &pk[0]) == 0);
CHECK(ecount == 1);
CHECK(secp256k1_schnorrsig_verify(sign, sig, msg, sizeof(msg), &pk[0]) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_schnorrsig_verify(none, sig, msg, sizeof(msg), &pk[0]) == 1);
CHECK(ecount == 0);
CHECK(secp256k1_schnorrsig_verify(sign, sig, msg, sizeof(msg), &pk[0]) == 1);
CHECK(ecount == 0);
CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), &pk[0]) == 1);
CHECK(ecount == 2);
CHECK(ecount == 0);
CHECK(secp256k1_schnorrsig_verify(vrfy, NULL, msg, sizeof(msg), &pk[0]) == 0);
CHECK(ecount == 3);
CHECK(ecount == 1);
CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, sizeof(msg), &pk[0]) == 0);
CHECK(ecount == 4);
CHECK(ecount == 2);
CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, 0, &pk[0]) == 0);
CHECK(ecount == 4);
CHECK(ecount == 2);
CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), NULL) == 0);
CHECK(ecount == 5);
CHECK(ecount == 3);
CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), &zero_pk) == 0);
CHECK(ecount == 6);
CHECK(ecount == 4);
secp256k1_context_destroy(none);
secp256k1_context_destroy(sign);

View File

@ -73,7 +73,6 @@ static const secp256k1_callback default_error_callback = {
};
struct secp256k1_context_struct {
secp256k1_ecmult_context ecmult_ctx;
secp256k1_ecmult_gen_context ecmult_gen_ctx;
secp256k1_callback illegal_callback;
secp256k1_callback error_callback;
@ -81,7 +80,6 @@ struct secp256k1_context_struct {
};
static const secp256k1_context secp256k1_context_no_precomp_ = {
{ 0 },
{ 0 },
{ secp256k1_default_illegal_callback_fn, 0 },
{ secp256k1_default_error_callback_fn, 0 },
@ -103,9 +101,6 @@ size_t secp256k1_context_preallocated_size(unsigned int flags) {
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {
ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE;
}
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) {
ret += SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;
}
return ret;
}
@ -115,9 +110,6 @@ size_t secp256k1_context_preallocated_clone_size(const secp256k1_context* ctx) {
if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) {
ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE;
}
if (secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)) {
ret += SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;
}
return ret;
}
@ -139,7 +131,6 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne
ret->illegal_callback = default_illegal_callback;
ret->error_callback = default_error_callback;
secp256k1_ecmult_context_init(&ret->ecmult_ctx);
secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx);
/* Flags have been checked by secp256k1_context_preallocated_size. */
@ -147,9 +138,6 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {
secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &prealloc);
}
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) {
secp256k1_ecmult_context_build(&ret->ecmult_ctx, &prealloc);
}
ret->declassify = !!(flags & SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY);
return (secp256k1_context*) ret;
@ -176,7 +164,6 @@ secp256k1_context* secp256k1_context_preallocated_clone(const secp256k1_context*
ret = (secp256k1_context*)prealloc;
memcpy(ret, ctx, prealloc_size);
secp256k1_ecmult_gen_context_finalize_memcpy(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx);
secp256k1_ecmult_context_finalize_memcpy(&ret->ecmult_ctx, &ctx->ecmult_ctx);
return ret;
}
@ -194,7 +181,6 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) {
ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
if (ctx != NULL) {
secp256k1_ecmult_context_clear(&ctx->ecmult_ctx);
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
}
}
@ -458,7 +444,6 @@ int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_s
secp256k1_scalar r, s;
secp256k1_scalar m;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(msghash32 != NULL);
ARG_CHECK(sig != NULL);
ARG_CHECK(pubkey != NULL);
@ -467,7 +452,7 @@ int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_s
secp256k1_ecdsa_signature_load(ctx, &r, &s, sig);
return (!secp256k1_scalar_is_high(&s) &&
secp256k1_pubkey_load(ctx, &q, pubkey) &&
secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m));
secp256k1_ecdsa_sig_verify(&r, &s, &q, &m));
}
static SECP256K1_INLINE void buffer_append(unsigned char *buf, unsigned int *offset, const void *data, unsigned int len) {
@ -685,24 +670,23 @@ int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *
return secp256k1_ec_seckey_tweak_add(ctx, seckey, tweak32);
}
static int secp256k1_ec_pubkey_tweak_add_helper(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_ge *p, const unsigned char *tweak32) {
static int secp256k1_ec_pubkey_tweak_add_helper(secp256k1_ge *p, const unsigned char *tweak32) {
secp256k1_scalar term;
int overflow = 0;
secp256k1_scalar_set_b32(&term, tweak32, &overflow);
return !overflow && secp256k1_eckey_pubkey_tweak_add(ecmult_ctx, p, &term);
return !overflow && secp256k1_eckey_pubkey_tweak_add(p, &term);
}
int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak32) {
secp256k1_ge p;
int ret = 0;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(pubkey != NULL);
ARG_CHECK(tweak32 != NULL);
ret = secp256k1_pubkey_load(ctx, &p, pubkey);
memset(pubkey, 0, sizeof(*pubkey));
ret = ret && secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &p, tweak32);
ret = ret && secp256k1_ec_pubkey_tweak_add_helper(&p, tweak32);
if (ret) {
secp256k1_pubkey_save(pubkey, &p);
}
@ -740,7 +724,6 @@ int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey
int ret = 0;
int overflow = 0;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(pubkey != NULL);
ARG_CHECK(tweak32 != NULL);
@ -748,7 +731,7 @@ int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey
ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey);
memset(pubkey, 0, sizeof(*pubkey));
if (ret) {
if (secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor)) {
if (secp256k1_eckey_pubkey_tweak_mul(&p, &factor)) {
secp256k1_pubkey_save(pubkey, &p);
} else {
ret = 0;

View File

@ -273,22 +273,22 @@ void run_context_tests(int use_prealloc) {
CHECK(secp256k1_ecdsa_sign(sign, &sig, ctmp, ctmp, NULL, NULL) == 1);
VG_CHECK(&sig, sizeof(sig));
CHECK(ecount2 == 10);
CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 0);
CHECK(ecount2 == 11);
CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 1);
CHECK(ecount2 == 10);
CHECK(secp256k1_ecdsa_verify(vrfy, &sig, ctmp, &pubkey) == 1);
CHECK(ecount == 2);
CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 0);
CHECK(ecount2 == 12);
CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 1);
CHECK(ecount2 == 10);
CHECK(secp256k1_ec_pubkey_tweak_add(vrfy, &pubkey, ctmp) == 1);
CHECK(ecount == 2);
CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0);
CHECK(ecount2 == 13);
CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 1);
CHECK(ecount2 == 10);
CHECK(secp256k1_ec_pubkey_negate(vrfy, &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 == 14);
CHECK(ecount2 == 11);
CHECK(secp256k1_ec_pubkey_negate(vrfy, &zero_pubkey) == 0);
CHECK(ecount == 3);
CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1);
@ -298,9 +298,9 @@ void run_context_tests(int use_prealloc) {
CHECK(secp256k1_context_randomize(vrfy, NULL) == 1);
CHECK(ecount == 3);
CHECK(secp256k1_context_randomize(sign, ctmp) == 1);
CHECK(ecount2 == 14);
CHECK(ecount2 == 11);
CHECK(secp256k1_context_randomize(sign, NULL) == 1);
CHECK(ecount2 == 14);
CHECK(ecount2 == 11);
secp256k1_context_set_illegal_callback(vrfy, NULL, NULL);
secp256k1_context_set_illegal_callback(sign, NULL, NULL);
@ -314,8 +314,8 @@ void run_context_tests(int use_prealloc) {
CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
/* try verifying */
CHECK(secp256k1_ecdsa_sig_verify(&vrfy->ecmult_ctx, &sigr, &sigs, &pub, &msg));
CHECK(secp256k1_ecdsa_sig_verify(&both->ecmult_ctx, &sigr, &sigs, &pub, &msg));
CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg));
CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg));
/* cleanup */
if (use_prealloc) {
@ -3416,6 +3416,84 @@ void run_group_decompress(void) {
/***** ECMULT TESTS *****/
void test_pre_g_table(const secp256k1_ge_storage * pre_g, size_t n) {
/* Tests the pre_g / pre_g_128 tables for consistency.
* For independent verification we take a "geometric" approach to verification.
* We check that every entry is on-curve.
* We check that for consecutive entries p and q, that p + gg - q = 0 by checking
* (1) p, gg, and -q are colinear.
* (2) p, gg, and -q are all distinct.
* where gg is twice the generator, where the generator is the first table entry.
*
* Checking the table's generators are correct is done in run_ecmult_pre_g.
*/
secp256k1_gej g2;
secp256k1_ge p, q, gg;
secp256k1_fe dpx, dpy, dqx, dqy;
size_t i;
CHECK(0 < n);
secp256k1_ge_from_storage(&p, &pre_g[0]);
secp256k1_fe_verify(&p.x);
secp256k1_fe_verify(&p.y);
CHECK(secp256k1_ge_is_valid_var(&p));
secp256k1_gej_set_ge(&g2, &p);
secp256k1_gej_double_var(&g2, &g2, NULL);
secp256k1_ge_set_gej_var(&gg, &g2);
for (i = 1; i < n; ++i) {
secp256k1_fe_negate(&dpx, &p.x, 1); secp256k1_fe_add(&dpx, &gg.x); secp256k1_fe_normalize_weak(&dpx);
secp256k1_fe_negate(&dpy, &p.y, 1); secp256k1_fe_add(&dpy, &gg.y); secp256k1_fe_normalize_weak(&dpy);
/* Check that p is not equal to gg */
CHECK(!secp256k1_fe_normalizes_to_zero_var(&dpx) || !secp256k1_fe_normalizes_to_zero_var(&dpy));
secp256k1_ge_from_storage(&q, &pre_g[i]);
secp256k1_fe_verify(&q.x);
secp256k1_fe_verify(&q.y);
CHECK(secp256k1_ge_is_valid_var(&q));
secp256k1_fe_negate(&dqx, &q.x, 1); secp256k1_fe_add(&dqx, &gg.x); secp256k1_fe_normalize_weak(&dqx);
dqy = q.y; secp256k1_fe_add(&dqy, &gg.y); secp256k1_fe_normalize_weak(&dqy);
/* Check that -q is not equal to gg */
CHECK(!secp256k1_fe_normalizes_to_zero_var(&dqx) || !secp256k1_fe_normalizes_to_zero_var(&dqy));
/* Check that -q is not equal to p */
CHECK(!secp256k1_fe_equal_var(&dpx, &dqx) || !secp256k1_fe_equal_var(&dpy, &dqy));
/* Check that p, -q and gg are colinear */
secp256k1_fe_mul(&dpx, &dpx, &dqy);
secp256k1_fe_mul(&dpy, &dpy, &dqx);
CHECK(secp256k1_fe_equal_var(&dpx, &dpy));
p = q;
}
}
void run_ecmult_pre_g(void) {
secp256k1_ge_storage gs;
secp256k1_gej gj;
secp256k1_ge g;
size_t i;
/* Check that the pre_g and pre_g_128 tables are consistent. */
test_pre_g_table(secp256k1_pre_g, ECMULT_TABLE_SIZE(WINDOW_G));
test_pre_g_table(secp256k1_pre_g_128, ECMULT_TABLE_SIZE(WINDOW_G));
/* Check the first entry from the pre_g table. */
secp256k1_ge_to_storage(&gs, &secp256k1_ge_const_g);
CHECK(secp256k1_memcmp_var(&gs, &secp256k1_pre_g[0], sizeof(gs)) == 0);
/* Check the first entry from the pre_g_128 table. */
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
for (i = 0; i < 128; ++i) {
secp256k1_gej_double_var(&gj, &gj, NULL);
}
secp256k1_ge_set_gej(&g, &gj);
secp256k1_ge_to_storage(&gs, &g);
CHECK(secp256k1_memcmp_var(&gs, &secp256k1_pre_g_128[0], sizeof(gs)) == 0);
}
void run_ecmult_chain(void) {
/* random starting point A (on the curve) */
secp256k1_gej a = SECP256K1_GEJ_CONST(
@ -3448,7 +3526,7 @@ void run_ecmult_chain(void) {
x = a;
for (i = 0; i < 200*count; i++) {
/* in each iteration, compute X = xn*X + gn*G; */
secp256k1_ecmult(&ctx->ecmult_ctx, &x, &x, &xn, &gn);
secp256k1_ecmult(&x, &x, &xn, &gn);
/* also compute ae and ge: the actual accumulated factors for A and G */
/* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */
secp256k1_scalar_mul(&ae, &ae, &xn);
@ -3474,7 +3552,7 @@ void run_ecmult_chain(void) {
}
}
/* redo the computation, but directly with the resulting ae and ge coefficients: */
secp256k1_ecmult(&ctx->ecmult_ctx, &x2, &a, &ae, &ge);
secp256k1_ecmult(&x2, &a, &ae, &ge);
secp256k1_gej_neg(&x2, &x2);
secp256k1_gej_add_var(&x2, &x2, &x, NULL);
CHECK(secp256k1_gej_is_infinity(&x2));
@ -3492,8 +3570,8 @@ void test_point_times_order(const secp256k1_gej *point) {
size_t psize = 65;
random_scalar_order_test(&x);
secp256k1_scalar_negate(&nx, &x);
secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &x, &x); /* calc res1 = x * point + x * G; */
secp256k1_ecmult(&ctx->ecmult_ctx, &res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */
secp256k1_ecmult(&res1, point, &x, &x); /* calc res1 = x * point + x * G; */
secp256k1_ecmult(&res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */
secp256k1_gej_add_var(&res1, &res1, &res2, NULL);
CHECK(secp256k1_gej_is_infinity(&res1));
secp256k1_ge_set_gej(&res3, &res1);
@ -3503,13 +3581,13 @@ void test_point_times_order(const secp256k1_gej *point) {
psize = 65;
CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0);
/* check zero/one edge cases */
secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &zero);
secp256k1_ecmult(&res1, point, &zero, &zero);
secp256k1_ge_set_gej(&res3, &res1);
CHECK(secp256k1_ge_is_infinity(&res3));
secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &one, &zero);
secp256k1_ecmult(&res1, point, &one, &zero);
secp256k1_ge_set_gej(&res3, &res1);
ge_equals_gej(&res3, point);
secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &one);
secp256k1_ecmult(&res1, point, &zero, &one);
secp256k1_ge_set_gej(&res3, &res1);
ge_equals_ge(&res3, &secp256k1_ge_const_g);
}
@ -3568,9 +3646,9 @@ void test_ecmult_target(const secp256k1_scalar* target, int mode) {
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &p2j, &n2);
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &ptj, target);
} else if (mode == 1) {
secp256k1_ecmult(&ctx->ecmult_ctx, &p1j, &pj, &n1, &zero);
secp256k1_ecmult(&ctx->ecmult_ctx, &p2j, &pj, &n2, &zero);
secp256k1_ecmult(&ctx->ecmult_ctx, &ptj, &pj, target, &zero);
secp256k1_ecmult(&p1j, &pj, &n1, &zero);
secp256k1_ecmult(&p2j, &pj, &n2, &zero);
secp256k1_ecmult(&ptj, &pj, target, &zero);
} else {
secp256k1_ecmult_const(&p1j, &p, &n1, 256);
secp256k1_ecmult_const(&p2j, &p, &n2, 256);
@ -3753,7 +3831,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_scalar_set_int(&szero, 0);
/* No points to multiply */
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, NULL, ecmult_multi_callback, &data, 0));
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, NULL, ecmult_multi_callback, &data, 0));
/* Check 1- and 2-point multiplies against ecmult */
for (ncount = 0; ncount < count; ncount++) {
@ -3768,32 +3846,32 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
pt[1] = secp256k1_ge_const_g;
/* only G scalar */
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &szero, &sc[0]);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &sc[0], ecmult_multi_callback, &data, 0));
secp256k1_ecmult(&r2, &ptgj, &szero, &sc[0]);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &sc[0], ecmult_multi_callback, &data, 0));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
/* 1-point */
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &szero);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 1));
secp256k1_ecmult(&r2, &ptgj, &sc[0], &szero);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 1));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
/* Try to multiply 1 point, but callback returns false */
CHECK(!ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_false_callback, &data, 1));
CHECK(!ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_false_callback, &data, 1));
/* 2-point */
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &sc[1]);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 2));
secp256k1_ecmult(&r2, &ptgj, &sc[0], &sc[1]);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 2));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
/* 2-point with G scalar */
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &sc[1]);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &sc[1], ecmult_multi_callback, &data, 1));
secp256k1_ecmult(&r2, &ptgj, &sc[0], &sc[1]);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &sc[1], ecmult_multi_callback, &data, 1));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
@ -3810,7 +3888,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
random_scalar_order(&sc[i]);
secp256k1_ge_set_infinity(&pt[i]);
}
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(secp256k1_gej_is_infinity(&r));
}
@ -3820,7 +3898,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
pt[i] = ptg;
secp256k1_scalar_set_int(&sc[i], 0);
}
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(secp256k1_gej_is_infinity(&r));
}
@ -3833,7 +3911,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
pt[2 * i + 1] = ptg;
}
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(secp256k1_gej_is_infinity(&r));
random_scalar_order(&sc[0]);
@ -3846,7 +3924,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_ge_neg(&pt[2*i+1], &pt[2*i]);
}
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(secp256k1_gej_is_infinity(&r));
}
@ -3861,7 +3939,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_scalar_negate(&sc[i], &sc[i]);
}
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 32));
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 32));
CHECK(secp256k1_gej_is_infinity(&r));
}
@ -3879,8 +3957,8 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_gej_add_ge_var(&r, &r, &pt[i], NULL);
}
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &r, &sc[0], &szero);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
secp256k1_ecmult(&r2, &r, &sc[0], &szero);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
@ -3902,8 +3980,8 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
}
secp256k1_gej_set_ge(&p0j, &pt[0]);
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &p0j, &rs, &szero);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
secp256k1_ecmult(&r2, &p0j, &rs, &szero);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
@ -3916,13 +3994,13 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
}
secp256k1_scalar_clear(&sc[0]);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
secp256k1_scalar_clear(&sc[1]);
secp256k1_scalar_clear(&sc[2]);
secp256k1_scalar_clear(&sc[3]);
secp256k1_scalar_clear(&sc[4]);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 6));
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 5));
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 6));
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 5));
CHECK(secp256k1_gej_is_infinity(&r));
/* Run through s0*(t0*P) + s1*(t1*P) exhaustively for many small values of s0, s1, t0, t1 */
@ -3946,8 +4024,8 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_scalar_set_int(&t1, (t1i + 1) / 2);
secp256k1_scalar_cond_negate(&t1, t1i & 1);
secp256k1_ecmult(&ctx->ecmult_ctx, &t0p, &ptgj, &t0, &szero);
secp256k1_ecmult(&ctx->ecmult_ctx, &t1p, &ptgj, &t1, &szero);
secp256k1_ecmult(&t0p, &ptgj, &t0, &szero);
secp256k1_ecmult(&t1p, &ptgj, &t1, &szero);
for(s0i = 0; s0i < TOP; s0i++) {
for(s1i = 0; s1i < TOP; s1i++) {
@ -3966,8 +4044,8 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_scalar_mul(&tmp2, &t1, &sc[1]);
secp256k1_scalar_add(&tmp1, &tmp1, &tmp2);
secp256k1_ecmult(&ctx->ecmult_ctx, &expected, &ptgj, &tmp1, &szero);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &actual, &szero, ecmult_multi_callback, &data, 2));
secp256k1_ecmult(&expected, &ptgj, &tmp1, &szero);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &actual, &szero, ecmult_multi_callback, &data, 2));
secp256k1_gej_neg(&expected, &expected);
secp256k1_gej_add_var(&actual, &actual, &expected, NULL);
CHECK(secp256k1_gej_is_infinity(&actual));
@ -3994,7 +4072,7 @@ void test_ecmult_multi_batch_single(secp256k1_ecmult_multi_func ecmult_multi) {
/* Try to multiply 1 point, but scratch space is empty.*/
scratch_empty = secp256k1_scratch_create(&ctx->error_callback, 0);
CHECK(!ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch_empty, &r, &szero, ecmult_multi_callback, &data, 1));
CHECK(!ecmult_multi(&ctx->error_callback, scratch_empty, &r, &szero, ecmult_multi_callback, &data, 1));
secp256k1_scratch_destroy(&ctx->error_callback, scratch_empty);
}
@ -4116,7 +4194,7 @@ void test_ecmult_multi_batching(void) {
/* Get random scalars and group elements and compute result */
random_scalar_order(&scG);
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &r2, &szero, &scG);
secp256k1_ecmult(&r2, &r2, &szero, &scG);
for(i = 0; i < n_points; i++) {
secp256k1_ge ptg;
secp256k1_gej ptgj;
@ -4124,7 +4202,7 @@ void test_ecmult_multi_batching(void) {
secp256k1_gej_set_ge(&ptgj, &ptg);
pt[i] = ptg;
random_scalar_order(&sc[i]);
secp256k1_ecmult(&ctx->ecmult_ctx, &ptgj, &ptgj, &sc[i], NULL);
secp256k1_ecmult(&ptgj, &ptgj, &sc[i], NULL);
secp256k1_gej_add_var(&r2, &r2, &ptgj, NULL);
}
data.sc = sc;
@ -4134,7 +4212,7 @@ void test_ecmult_multi_batching(void) {
/* Test with empty scratch space. It should compute the correct result using
* ecmult_mult_simple algorithm which doesn't require a scratch space. */
scratch = secp256k1_scratch_create(&ctx->error_callback, 0);
CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
secp256k1_scratch_destroy(&ctx->error_callback, scratch);
@ -4143,7 +4221,7 @@ void test_ecmult_multi_batching(void) {
* ecmult_multi selects strauss which requires more memory. It should
* therefore select the simple algorithm. */
scratch = secp256k1_scratch_create(&ctx->error_callback, secp256k1_pippenger_scratch_size(1, 1) + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT);
CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
secp256k1_scratch_destroy(&ctx->error_callback, scratch);
@ -4157,7 +4235,7 @@ void test_ecmult_multi_batching(void) {
size_t scratch_size = secp256k1_strauss_scratch_size(i);
scratch = secp256k1_scratch_create(&ctx->error_callback, scratch_size + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT);
}
CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
secp256k1_scratch_destroy(&ctx->error_callback, scratch);
@ -5276,10 +5354,10 @@ void test_ecdsa_sign_verify(void) {
} else {
random_sign(&sigr, &sigs, &key, &msg, NULL);
}
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg));
CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg));
secp256k1_scalar_set_int(&one, 1);
secp256k1_scalar_add(&msg, &msg, &one);
CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg));
CHECK(!secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg));
}
void run_ecdsa_sign_verify(void) {
@ -5957,7 +6035,7 @@ void test_ecdsa_edge_cases(void) {
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &keyj, &sr);
secp256k1_ge_set_gej(&key, &keyj);
msg = ss;
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
}
/* Verify signature with r of zero fails. */
@ -5976,7 +6054,7 @@ void test_ecdsa_edge_cases(void) {
secp256k1_scalar_set_int(&msg, 0);
secp256k1_scalar_set_int(&sr, 0);
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey_mods_zero, 33));
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
CHECK(secp256k1_ecdsa_sig_verify( &sr, &ss, &key, &msg) == 0);
}
/* Verify signature with s of zero fails. */
@ -5995,7 +6073,7 @@ void test_ecdsa_edge_cases(void) {
secp256k1_scalar_set_int(&msg, 0);
secp256k1_scalar_set_int(&sr, 1);
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
}
/* Verify signature with message 0 passes. */
@ -6023,14 +6101,14 @@ void test_ecdsa_edge_cases(void) {
secp256k1_scalar_set_int(&sr, 2);
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33));
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1);
secp256k1_scalar_negate(&ss, &ss);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1);
secp256k1_scalar_set_int(&ss, 1);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 0);
}
/* Verify signature with message 1 passes. */
@ -6064,15 +6142,15 @@ void test_ecdsa_edge_cases(void) {
secp256k1_scalar_set_b32(&sr, csr, NULL);
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33));
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1);
secp256k1_scalar_negate(&ss, &ss);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1);
secp256k1_scalar_set_int(&ss, 2);
secp256k1_scalar_inverse_var(&ss, &ss);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 0);
}
/* Verify signature with message -1 passes. */
@ -6098,12 +6176,12 @@ void test_ecdsa_edge_cases(void) {
secp256k1_scalar_negate(&msg, &msg);
secp256k1_scalar_set_b32(&sr, csr, NULL);
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
secp256k1_scalar_negate(&ss, &ss);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
secp256k1_scalar_set_int(&ss, 3);
secp256k1_scalar_inverse_var(&ss, &ss);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
}
/* Signature where s would be zero. */
@ -6349,10 +6427,10 @@ void test_ecdsa_openssl(void) {
CHECK(ec_key != NULL);
CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key));
CHECK(secp256k1_ecdsa_sig_parse(&sigr, &sigs, signature, sigsize));
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg));
CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &q, &msg));
secp256k1_scalar_set_int(&one, 1);
secp256k1_scalar_add(&msg2, &msg, &one);
CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg2));
CHECK(!secp256k1_ecdsa_sig_verify(&sigr, &sigs, &q, &msg2));
random_sign(&sigr, &sigs, &key, &msg, NULL);
CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sigr, &sigs));
@ -6620,6 +6698,7 @@ int main(int argc, char **argv) {
run_group_decompress();
/* ecmult tests */
run_ecmult_pre_g();
run_wnaf();
run_point_times_order();
run_ecmult_near_split_bound();

View File

@ -163,7 +163,7 @@ void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *gr
}
}
void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *group, const secp256k1_gej *groupj) {
void test_exhaustive_ecmult(const secp256k1_ge *group, const secp256k1_gej *groupj) {
int i, j, r_log;
uint64_t iter = 0;
for (r_log = 1; r_log < EXHAUSTIVE_TEST_ORDER; r_log++) {
@ -175,7 +175,7 @@ void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *gr
secp256k1_scalar_set_int(&na, i);
secp256k1_scalar_set_int(&ng, j);
secp256k1_ecmult(&ctx->ecmult_ctx, &tmp, &groupj[r_log], &na, &ng);
secp256k1_ecmult(&tmp, &groupj[r_log], &na, &ng);
ge_equals_gej(&group[(i * r_log + j) % EXHAUSTIVE_TEST_ORDER], &tmp);
if (i > 0) {
@ -219,7 +219,7 @@ void test_exhaustive_ecmult_multi(const secp256k1_context *ctx, const secp256k1_
data.pt[0] = group[x];
data.pt[1] = group[y];
secp256k1_ecmult_multi_var(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2);
secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2);
ge_equals_gej(&group[(i * x + j * y + k) % EXHAUSTIVE_TEST_ORDER], &tmp);
}
}
@ -430,7 +430,7 @@ int main(int argc, char** argv) {
/* Run the tests */
test_exhaustive_endomorphism(group);
test_exhaustive_addition(group, groupj);
test_exhaustive_ecmult(ctx, group, groupj);
test_exhaustive_ecmult(group, groupj);
test_exhaustive_ecmult_multi(ctx, group);
test_exhaustive_sign(ctx, group);
test_exhaustive_verify(ctx, group);