diff --git a/src/ecmult_gen.h b/src/ecmult_gen.h index 05cf4d52c..9930b6ac3 100644 --- a/src/ecmult_gen.h +++ b/src/ecmult_gen.h @@ -18,28 +18,16 @@ #define ECMULT_GEN_PREC_N (256 / ECMULT_GEN_PREC_B) 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); diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index 0a9b5c4b7..b75af0265 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -14,35 +14,34 @@ #include "hash_impl.h" #include "ecmult_static_context.h" -static const size_t SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE = 0; - -static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context *ctx) { - ctx->prec = NULL; -} - -static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx, void **prealloc) { - if (ctx->prec != NULL) { - return; - } - (void)prealloc; - ctx->prec = (secp256k1_ge_storage (*)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G])secp256k1_ecmult_static_context; +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) { - (void)dst, (void)src; + 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_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. + * The prec values are stored in secp256k1_ecmult_gen_prec_table[j][i] = (PREC_G)^j * i * G + U_i. + */ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) { secp256k1_ge add; secp256k1_ge_storage adds; @@ -67,7 +66,7 @@ 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[j][i], i == bits); } secp256k1_ge_from_storage(&add, &adds); secp256k1_gej_add_ge(r, r, &add); diff --git a/src/gen_context.c b/src/gen_context.c index 85652aec9..9b770bb83 100644 --- a/src/gen_context.c +++ b/src/gen_context.c @@ -56,7 +56,7 @@ int main(int argc, char **argv) { 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"); + fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G] = {\n"); table = checked_malloc(&default_error_callback, ECMULT_GEN_PREC_TABLE_SIZE); secp256k1_ecmult_gen_create_prec_table(table); diff --git a/src/modules/extrakeys/tests_impl.h b/src/modules/extrakeys/tests_impl.h index dd53f9e12..c8a99f446 100644 --- a/src/modules/extrakeys/tests_impl.h +++ b/src/modules/extrakeys/tests_impl.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) { diff --git a/src/modules/recovery/tests_impl.h b/src/modules/recovery/tests_impl.h index 2fcd46d20..abf62f7f3 100644 --- a/src/modules/recovery/tests_impl.h +++ b/src/modules/recovery/tests_impl.h @@ -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) { diff --git a/src/modules/schnorrsig/tests_impl.h b/src/modules/schnorrsig/tests_impl.h index d301abee5..2efec8a2b 100644 --- a/src/modules/schnorrsig/tests_impl.h +++ b/src/modules/schnorrsig/tests_impl.h @@ -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 diff --git a/src/secp256k1.c b/src/secp256k1.c index 9b1141376..53f35f715 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -98,18 +98,12 @@ 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)); VERIFY_CHECK(ctx != NULL); - if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) { - ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE; - } return ret; } @@ -131,13 +125,9 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne 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; @@ -163,7 +153,6 @@ secp256k1_context* secp256k1_context_preallocated_clone(const secp256k1_context* 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); return ret; } diff --git a/src/tests.c b/src/tests.c index 6027ebc07..e53eb02d4 100644 --- a/src/tests.c +++ b/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);