From 76ce607df4535f0e6d59cc8e2e82f7ca713fbc83 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 13 Aug 2025 10:09:11 +0200 Subject: [PATCH 01/14] tests: Make ecmult tests use internal scratch API This has the advantage of keeping the ecmult tests focused on the ecmult code, and so this change might be desirable anyway. That's why it is done in a separate commit, so it can be kept if we ever bring back the public scratch space API. --- src/tests.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tests.c b/src/tests.c index 0f7b0d4c4c..5f5790ec94 100644 --- a/src/tests.c +++ b/src/tests.c @@ -5455,7 +5455,7 @@ static void test_ecmult_constants_2bit(void) { secp256k1_sha256 acc; unsigned char b32[32]; int i, j; - secp256k1_scratch_space *scratch = secp256k1_scratch_space_create(CTX, 65536); + secp256k1_scratch_space *scratch = secp256k1_scratch_create(&CTX->error_callback, 65536); /* Expected hash of all the computed points; created with an independent * implementation. */ @@ -5483,7 +5483,7 @@ static void test_ecmult_constants_2bit(void) { secp256k1_sha256_finalize(&acc, b32); CHECK(secp256k1_memcmp_var(b32, expected32, 32) == 0); - secp256k1_scratch_space_destroy(CTX, scratch); + secp256k1_scratch_destroy(&CTX->error_callback, scratch); } static void test_ecmult_constants_sha(uint32_t prefix, size_t iter, const unsigned char* expected32) { @@ -5499,7 +5499,7 @@ static void test_ecmult_constants_sha(uint32_t prefix, size_t iter, const unsign unsigned char b32[32]; unsigned char inp[6]; size_t i; - secp256k1_scratch_space *scratch = secp256k1_scratch_space_create(CTX, 65536); + secp256k1_scratch_space *scratch = secp256k1_scratch_create(&CTX->error_callback, 65536); inp[0] = prefix & 0xFF; inp[1] = (prefix >> 8) & 0xFF; @@ -5526,7 +5526,7 @@ static void test_ecmult_constants_sha(uint32_t prefix, size_t iter, const unsign secp256k1_sha256_finalize(&acc, b32); CHECK(secp256k1_memcmp_var(b32, expected32, 32) == 0); - secp256k1_scratch_space_destroy(CTX, scratch); + secp256k1_scratch_destroy(&CTX->error_callback, scratch); } static void run_ecmult_constants(void) { From bb37ad8fa05e7ee0c5d965ef9d87d6e50bf59bca Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 13 Aug 2025 09:08:27 +0200 Subject: [PATCH 02/14] Remove ununsed scratch space functions These were in the public API at some point but they have been made static in 712e7f8722eba5dec2bc6b37d75aadeb6f6e633b. --- src/bench_ecmult.c | 4 ++-- src/secp256k1.c | 10 ---------- src/tests.c | 16 +++++++--------- 3 files changed, 9 insertions(+), 21 deletions(-) diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index b2bab65d26..ef2c3ca900 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -336,7 +336,7 @@ int main(int argc, char **argv) { data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); scratch_size = secp256k1_strauss_scratch_size(POINTS) + STRAUSS_SCRATCH_OBJECTS*16; if (!have_flag(argc, argv, "simple")) { - data.scratch = secp256k1_scratch_space_create(data.ctx, scratch_size); + data.scratch = secp256k1_scratch_create(&data.ctx->error_callback, scratch_size); } else { data.scratch = NULL; } @@ -384,7 +384,7 @@ int main(int argc, char **argv) { } if (data.scratch != NULL) { - secp256k1_scratch_space_destroy(data.ctx, data.scratch); + secp256k1_scratch_destroy(&data.ctx->error_callback, data.scratch); } secp256k1_context_destroy(data.ctx); free(data.scalars); diff --git a/src/secp256k1.c b/src/secp256k1.c index 0915af7797..1fb80390ec 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -220,16 +220,6 @@ void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(co ctx->error_callback.data = data; } -static secp256k1_scratch_space* secp256k1_scratch_space_create(const secp256k1_context* ctx, size_t max_size) { - VERIFY_CHECK(ctx != NULL); - return secp256k1_scratch_create(&ctx->error_callback, max_size); -} - -static void secp256k1_scratch_space_destroy(const secp256k1_context *ctx, secp256k1_scratch_space* scratch) { - VERIFY_CHECK(ctx != NULL); - secp256k1_scratch_destroy(&ctx->error_callback, scratch); -} - /* Mark memory as no-longer-secret for the purpose of analysing constant-time behaviour * of the software. */ diff --git a/src/tests.c b/src/tests.c index 5f5790ec94..54656fb202 100644 --- a/src/tests.c +++ b/src/tests.c @@ -357,11 +357,9 @@ static void run_scratch_tests(void) { secp256k1_scratch_space *scratch; secp256k1_scratch_space local_scratch; - /* Test public API */ - scratch = secp256k1_scratch_space_create(CTX, 1000); - CHECK(scratch != NULL); - /* Test internal API */ + scratch = secp256k1_scratch_create(&CTX->error_callback, 1000); + CHECK(scratch != NULL); CHECK(secp256k1_scratch_max_allocation(&CTX->error_callback, scratch, 0) == 1000); CHECK(secp256k1_scratch_max_allocation(&CTX->error_callback, scratch, 1) == 1000 - (ALIGNMENT - 1)); CHECK(scratch->alloc_size == 0); @@ -396,15 +394,15 @@ static void run_scratch_tests(void) { CHECK_ERROR_VOID(CTX, secp256k1_scratch_apply_checkpoint(&CTX->error_callback, scratch, (size_t) -1)); /* this is just wildly invalid */ /* try to use badly initialized scratch space */ - secp256k1_scratch_space_destroy(CTX, scratch); + secp256k1_scratch_destroy(&CTX->error_callback, scratch); memset(&local_scratch, 0, sizeof(local_scratch)); scratch = &local_scratch; CHECK_ERROR(CTX, secp256k1_scratch_max_allocation(&CTX->error_callback, scratch, 0)); CHECK_ERROR(CTX, secp256k1_scratch_alloc(&CTX->error_callback, scratch, 500)); - CHECK_ERROR_VOID(CTX, secp256k1_scratch_space_destroy(CTX, scratch)); + CHECK_ERROR_VOID(CTX, secp256k1_scratch_destroy(&CTX->error_callback, scratch)); /* Test that large integers do not wrap around in a bad way */ - scratch = secp256k1_scratch_space_create(CTX, 1000); + scratch = secp256k1_scratch_create(&CTX->error_callback, 1000); /* Try max allocation with a large number of objects. Only makes sense if * ALIGNMENT is greater than 1 because otherwise the objects take no extra * space. */ @@ -413,10 +411,10 @@ static void run_scratch_tests(void) { * ALIGNMENT > 1, otherwise it returns NULL anyway because the scratch * space is too small. */ CHECK(secp256k1_scratch_alloc(&CTX->error_callback, scratch, SIZE_MAX) == NULL); - secp256k1_scratch_space_destroy(CTX, scratch); + secp256k1_scratch_destroy(&CTX->error_callback, scratch); /* cleanup */ - secp256k1_scratch_space_destroy(CTX, NULL); /* no-op */ + secp256k1_scratch_destroy(&CTX->error_callback, NULL); /* no-op */ } static void run_ctz_tests(void) { From d72f3613cc5879c1d9b75a0160c6e211c136eb6a Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 13 Aug 2025 10:17:29 +0200 Subject: [PATCH 03/14] scalar: Move definitions of constants to header --- src/scalar.h | 3 +++ src/scalar_impl.h | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scalar.h b/src/scalar.h index 70f49b1cf2..7054efd291 100644 --- a/src/scalar.h +++ b/src/scalar.h @@ -19,6 +19,9 @@ #error "Please select wide multiplication implementation" #endif +static const secp256k1_scalar secp256k1_scalar_one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); +static const secp256k1_scalar secp256k1_scalar_zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + /** Clear a scalar to prevent the leak of sensitive data. */ static void secp256k1_scalar_clear(secp256k1_scalar *r); diff --git a/src/scalar_impl.h b/src/scalar_impl.h index 0232a8c223..abcc459251 100644 --- a/src/scalar_impl.h +++ b/src/scalar_impl.h @@ -24,9 +24,6 @@ #error "Please select wide multiplication implementation" #endif -static const secp256k1_scalar secp256k1_scalar_one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); -static const secp256k1_scalar secp256k1_scalar_zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); - SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { secp256k1_memclear(r, sizeof(secp256k1_scalar)); } From 29e82e7649e807e0c18d27021150b2cfed045e7f Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 13 Aug 2025 13:45:18 +0200 Subject: [PATCH 04/14] scalar: Move EXHAUSTIVE_TEST_LAMBDA to header --- sage/gen_exhaustive_groups.sage | 2 +- src/scalar.h | 11 +++++++++++ src/scalar_impl.h | 12 ------------ 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/sage/gen_exhaustive_groups.sage b/sage/gen_exhaustive_groups.sage index 070bc1285f..218868d655 100644 --- a/sage/gen_exhaustive_groups.sage +++ b/sage/gen_exhaustive_groups.sage @@ -141,7 +141,7 @@ print("/* End of section generated by sage/gen_exhaustive_groups.sage. */") print() print() -print("To be put in src/scalar_impl.h:") +print("To be put in src/scalar.h:") print() print("/* Begin of section generated by sage/gen_exhaustive_groups.sage. */") first = True diff --git a/src/scalar.h b/src/scalar.h index 7054efd291..773034ed27 100644 --- a/src/scalar.h +++ b/src/scalar.h @@ -10,6 +10,17 @@ #include "util.h" #if defined(EXHAUSTIVE_TEST_ORDER) +/* Begin of section generated by sage/gen_exhaustive_groups.sage. */ +# if EXHAUSTIVE_TEST_ORDER == 7 +# define EXHAUSTIVE_TEST_LAMBDA 2 +# elif EXHAUSTIVE_TEST_ORDER == 13 +# define EXHAUSTIVE_TEST_LAMBDA 9 +# elif EXHAUSTIVE_TEST_ORDER == 199 +# define EXHAUSTIVE_TEST_LAMBDA 92 +# else +# error No known lambda for the specified exhaustive test group order. +# endif +/* End of section generated by sage/gen_exhaustive_groups.sage. */ #include "scalar_low.h" #elif defined(SECP256K1_WIDEMUL_INT128) #include "scalar_4x64.h" diff --git a/src/scalar_impl.h b/src/scalar_impl.h index abcc459251..e65850f2f8 100644 --- a/src/scalar_impl.h +++ b/src/scalar_impl.h @@ -43,18 +43,6 @@ static void secp256k1_scalar_verify(const secp256k1_scalar *r) { } #if defined(EXHAUSTIVE_TEST_ORDER) -/* Begin of section generated by sage/gen_exhaustive_groups.sage. */ -# if EXHAUSTIVE_TEST_ORDER == 7 -# define EXHAUSTIVE_TEST_LAMBDA 2 -# elif EXHAUSTIVE_TEST_ORDER == 13 -# define EXHAUSTIVE_TEST_LAMBDA 9 -# elif EXHAUSTIVE_TEST_ORDER == 199 -# define EXHAUSTIVE_TEST_LAMBDA 92 -# else -# error No known lambda for the specified exhaustive test group order. -# endif -/* End of section generated by sage/gen_exhaustive_groups.sage. */ - /** * Find r1 and r2 given k, such that r1 + r2 * lambda == k mod n; unlike in the * full case we don't bother making r1 and r2 be small, we just want them to be From 3304ce0c993211a1d25e9f3f72cf2750b9311016 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 13 Aug 2025 10:49:45 +0200 Subject: [PATCH 05/14] Create header for internal API in secp256k1.c --- Makefile.am | 1 + src/secp256k1.c | 10 ++-------- src/secp256k1_internal.h | 43 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 src/secp256k1_internal.h diff --git a/Makefile.am b/Makefile.am index d511853b05..f556d3bfa0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,6 +8,7 @@ lib_LTLIBRARIES = libsecp256k1.la include_HEADERS = include/secp256k1.h include_HEADERS += include/secp256k1_preallocated.h noinst_HEADERS = +noinst_HEADERS += src/secp256k1_internal.h noinst_HEADERS += src/scalar.h noinst_HEADERS += src/scalar_4x64.h noinst_HEADERS += src/scalar_8x32.h diff --git a/src/secp256k1.c b/src/secp256k1.c index 1fb80390ec..20f1cdd67d 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -20,6 +20,8 @@ #include "../include/secp256k1.h" #include "../include/secp256k1_preallocated.h" +#include "secp256k1_internal.h" + #include "assumptions.h" #include "checkmem.h" #include "util.h" @@ -74,11 +76,6 @@ static const secp256k1_context secp256k1_context_static_ = { const secp256k1_context * const secp256k1_context_static = &secp256k1_context_static_; const secp256k1_context * const secp256k1_context_no_precomp = &secp256k1_context_static_; -/* Helper function that determines if a context is proper, i.e., is not the static context or a copy thereof. - * - * This is intended for "context" functions such as secp256k1_context_clone. Functions that need specific - * features of a context should still check for these features directly. For example, a function that needs - * ecmult_gen should directly check for the existence of the ecmult_gen context. */ static int secp256k1_context_is_proper(const secp256k1_context* ctx) { return secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx); } @@ -220,9 +217,6 @@ void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(co ctx->error_callback.data = data; } -/* Mark memory as no-longer-secret for the purpose of analysing constant-time behaviour - * of the software. - */ static SECP256K1_INLINE void secp256k1_declassify(const secp256k1_context* ctx, const void *p, size_t len) { if (EXPECT(ctx->declassify, 0)) SECP256K1_CHECKMEM_DEFINE(p, len); } diff --git a/src/secp256k1_internal.h b/src/secp256k1_internal.h new file mode 100644 index 0000000000..8fbc266aa6 --- /dev/null +++ b/src/secp256k1_internal.h @@ -0,0 +1,43 @@ +/*********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_SECP256K1_INTERNAL_H +#define SECP256K1_SECP256K1_INTERNAL_H + +#include "../include/secp256k1.h" + +#include "ecmult_gen.h" +#include "group.h" +#include "scalar.h" +#include "util.h" + +/* Helper function that determines if a context is proper, i.e., is not the static context or a copy thereof. + * + * This is intended for "context" functions such as secp256k1_context_clone. Functions that need specific + * features of a context should still check for these features directly. For example, a function that needs + * ecmult_gen should directly check for the existence of the ecmult_gen context. */ +static int secp256k1_context_is_proper(const secp256k1_context* ctx); + +/* Mark memory as no-longer-secret for the purpose of analysing constant-time behaviour + * of the software. + */ +static SECP256K1_INLINE void secp256k1_declassify(const secp256k1_context* ctx, const void *p, size_t len); + +static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey); +static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge); + +static int secp256k1_ec_pubkey_sort_cmp(const void* pk1, const void* pk2, void *ctx); + +static void secp256k1_ecdsa_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_ecdsa_signature* sig); +static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s); + +static int secp256k1_ecdsa_sign_inner(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, int* recid, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata); + +static int secp256k1_ec_pubkey_create_helper(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_scalar *seckey_scalar, secp256k1_ge *p, const unsigned char *seckey); +static int secp256k1_ec_seckey_tweak_add_helper(secp256k1_scalar *sec, const unsigned char *tweak32); +static int secp256k1_ec_pubkey_tweak_add_helper(secp256k1_ge *p, const unsigned char *tweak32); + +#endif /* SECP256K1_SECP256K1_INTERNAL_H */ From f181af00d7773ac150243dc1a1e7e062525229ee Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 13 Aug 2025 10:53:24 +0200 Subject: [PATCH 06/14] gitignore: Add precompiled headers (.gch and .pch) We don't use precompiled headers in our builds but those files are what you get if you invoke gcc or clang, respectively, on a .h file, e.g., to check if it's self-contained. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ce33a84adf..55c2ca6a2e 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ libtool *.lo *.o *~ +*.[gp]ch coverage/ coverage.html From 151a2da0ae93b0b14589212017b30a3d1f575902 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 13 Aug 2025 11:05:26 +0200 Subject: [PATCH 07/14] group: Add missing declarations to internal header --- src/group.h | 7 +++++++ src/group_impl.h | 2 -- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/group.h b/src/group.h index 05ae0d203c..e771abdeb2 100644 --- a/src/group.h +++ b/src/group.h @@ -21,6 +21,7 @@ typedef struct { #define SECP256K1_GE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), 0} #define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} +static const secp256k1_ge secp256k1_ge_const_g; /** A group element of the secp256k1 curve, in jacobian coordinates. * Note: For exhastive test mode, secp256k1 is replaced by a small subgroup of a different curve. @@ -87,6 +88,12 @@ static void secp256k1_ge_set_all_gej(secp256k1_ge *r, const secp256k1_gej *a, si /** Set group elements r[0:len] (affine) equal to group elements a[0:len] (jacobian). */ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len); +/** Set a group element (affine) equal to the group element with jacobian coordinates (a.x, a.y, 1/zi). */ +static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi); + +/** Set a group element (affine) equal to the group element with jacobian coordinates (a.x, a.y, 1/zi). */ +static void secp256k1_ge_set_ge_zinv(secp256k1_ge *r, const secp256k1_ge *a, const secp256k1_fe *zi); + /** Bring a batch of inputs to the same global z "denominator", based on ratios between * (omitted) z coordinates of adjacent elements. * diff --git a/src/group_impl.h b/src/group_impl.h index b8f2395d93..f57db051f6 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -95,7 +95,6 @@ static void secp256k1_gej_verify(const secp256k1_gej *a) { (void)a; } -/* Set r to the affine coordinates of Jacobian point (a.x, a.y, 1/zi). */ static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) { secp256k1_fe zi2; secp256k1_fe zi3; @@ -112,7 +111,6 @@ static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, c SECP256K1_GE_VERIFY(r); } -/* Set r to the affine coordinates of Jacobian point (a.x, a.y, 1/zi). */ static void secp256k1_ge_set_ge_zinv(secp256k1_ge *r, const secp256k1_ge *a, const secp256k1_fe *zi) { secp256k1_fe zi2; secp256k1_fe zi3; From 250c61450f36e79866557eb78bd763accebd1998 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 13 Aug 2025 11:48:48 +0200 Subject: [PATCH 08/14] Tidy includes to make many headers self-contained --- src/ecdsa.h | 1 + src/ecmult_compute_table.h | 2 ++ src/hsort_impl.h | 1 + src/modinv64.h | 2 ++ src/scalar_4x64_impl.h | 4 +++- src/scalar_8x32_impl.h | 4 +++- src/scratch.h | 4 ++++ src/selftest.h | 1 + src/testrand_impl.h | 1 + src/tests.c | 2 -- src/testutil.h | 2 ++ 11 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/ecdsa.h b/src/ecdsa.h index 4441b08398..157ff631b5 100644 --- a/src/ecdsa.h +++ b/src/ecdsa.h @@ -12,6 +12,7 @@ #include "scalar.h" #include "group.h" #include "ecmult.h" +#include "ecmult_gen.h" 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); diff --git a/src/ecmult_compute_table.h b/src/ecmult_compute_table.h index 665f87ff3d..9b0c385477 100644 --- a/src/ecmult_compute_table.h +++ b/src/ecmult_compute_table.h @@ -7,6 +7,8 @@ #ifndef SECP256K1_ECMULT_COMPUTE_TABLE_H #define SECP256K1_ECMULT_COMPUTE_TABLE_H +#include "group.h" + /* Construct table of all odd multiples of gen in range 1..(2**(window_g-1)-1). */ static void secp256k1_ecmult_compute_table(secp256k1_ge_storage* table, int window_g, const secp256k1_gej* gen); diff --git a/src/hsort_impl.h b/src/hsort_impl.h index 1c674ff1c4..651ccc3e7a 100644 --- a/src/hsort_impl.h +++ b/src/hsort_impl.h @@ -8,6 +8,7 @@ #define SECP256K1_HSORT_IMPL_H #include "hsort.h" +#include "util.h" /* An array is a heap when, for all non-zero indexes i, the element at index i * compares as less than or equal to the element at index parent(i) = (i-1)/2. diff --git a/src/modinv64.h b/src/modinv64.h index f4208e6c23..86a414dc61 100644 --- a/src/modinv64.h +++ b/src/modinv64.h @@ -9,6 +9,8 @@ #include "util.h" +#include + #ifndef SECP256K1_WIDEMUL_INT128 #error "modinv64 requires 128-bit wide multiplication support" #endif diff --git a/src/scalar_4x64_impl.h b/src/scalar_4x64_impl.h index 807b9b70ab..1e11fc8abf 100644 --- a/src/scalar_4x64_impl.h +++ b/src/scalar_4x64_impl.h @@ -9,7 +9,9 @@ #include "checkmem.h" #include "int128.h" -#include "modinv64_impl.h" +#include "modinv64.h" +#include "scalar.h" +#include "scalar_4x64.h" #include "util.h" /* Limbs of the secp256k1 order. */ diff --git a/src/scalar_8x32_impl.h b/src/scalar_8x32_impl.h index 2610496052..0dbf612fa0 100644 --- a/src/scalar_8x32_impl.h +++ b/src/scalar_8x32_impl.h @@ -8,7 +8,9 @@ #define SECP256K1_SCALAR_REPR_IMPL_H #include "checkmem.h" -#include "modinv32_impl.h" +#include "modinv32.h" +#include "scalar.h" +#include "scalar_8x32.h" #include "util.h" /* Limbs of the secp256k1 order. */ diff --git a/src/scratch.h b/src/scratch.h index 6164330b39..8d325a6f51 100644 --- a/src/scratch.h +++ b/src/scratch.h @@ -7,6 +7,10 @@ #ifndef SECP256K1_SCRATCH_H #define SECP256K1_SCRATCH_H +#include "secp256k1_internal.h" + +#include + /* The typedef is used internally; the struct name is used in the public API * (where it is exposed as a different typedef) */ typedef struct secp256k1_scratch_space_struct { diff --git a/src/selftest.h b/src/selftest.h index d083ac9524..c0720c0294 100644 --- a/src/selftest.h +++ b/src/selftest.h @@ -8,6 +8,7 @@ #define SECP256K1_SELFTEST_H #include "hash.h" +#include "util.h" #include diff --git a/src/testrand_impl.h b/src/testrand_impl.h index b84f5730a9..2ccbcd892d 100644 --- a/src/testrand_impl.h +++ b/src/testrand_impl.h @@ -10,6 +10,7 @@ #include #include #include +#include #include "testrand.h" #include "hash.h" diff --git a/src/tests.c b/src/tests.c index 54656fb202..3e2c83f2e3 100644 --- a/src/tests.c +++ b/src/tests.c @@ -8,8 +8,6 @@ #include #include -#include - #ifdef USE_EXTERNAL_DEFAULT_CALLBACKS #pragma message("Ignoring USE_EXTERNAL_CALLBACKS in tests.") #undef USE_EXTERNAL_DEFAULT_CALLBACKS diff --git a/src/testutil.h b/src/testutil.h index 64b3bb41c0..0ecbbafc00 100644 --- a/src/testutil.h +++ b/src/testutil.h @@ -8,6 +8,8 @@ #include "field.h" #include "group.h" +#include "scalar.h" +#include "secp256k1_internal.h" #include "testrand.h" #include "util.h" From 8969deb9428c3e254faf1c8f38c0a00de0b099ad Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 13 Aug 2025 12:12:39 +0200 Subject: [PATCH 09/14] field: Inline fe_verify fields in repr headers Otherwise, the repr headers field_AxB.h would need to include field.h to be self-contained but this recursive inclusion leaves clangd confused, see https://github.com/clangd/clangd/issues/337 . --- src/field.h | 7 ------- src/field_10x26.h | 5 ++++- src/field_5x52.h | 5 ++++- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/field.h b/src/field.h index 1f6ba7460f..f4b13f4b20 100644 --- a/src/field.h +++ b/src/field.h @@ -29,13 +29,6 @@ * implementation also provides a secp256k1_fe_verify routine to verify that * these fields match the run-time value and perform internal consistency * checks. */ -#ifdef VERIFY -# define SECP256K1_FE_VERIFY_FIELDS \ - int magnitude; \ - int normalized; -#else -# define SECP256K1_FE_VERIFY_FIELDS -#endif #if defined(SECP256K1_WIDEMUL_INT128) #include "field_5x52.h" diff --git a/src/field_10x26.h b/src/field_10x26.h index 203c10167c..c01d92c10b 100644 --- a/src/field_10x26.h +++ b/src/field_10x26.h @@ -30,7 +30,10 @@ typedef struct { * sum(i=0..9, n[i] << (i*26)) < p * (together these imply n[9] <= 2^22 - 1) */ - SECP256K1_FE_VERIFY_FIELDS +#ifdef VERIFY + int magnitude; + int normalized; +#endif } secp256k1_fe; /* Unpacks a constant into a overlapping multi-limbed FE element. */ diff --git a/src/field_5x52.h b/src/field_5x52.h index f20c246fdd..30cdf3bb10 100644 --- a/src/field_5x52.h +++ b/src/field_5x52.h @@ -30,7 +30,10 @@ typedef struct { * sum(i=0..4, n[i] << (i*52)) < p * (together these imply n[4] <= 2^48 - 1) */ - SECP256K1_FE_VERIFY_FIELDS +#ifdef VERIFY + int magnitude; + int normalized; +#endif } secp256k1_fe; /* Unpacks a constant into a overlapping multi-limbed FE element. */ From 0e17403bb6533be39c892bc87c2c043ee935c69b Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 13 Aug 2025 13:46:27 +0200 Subject: [PATCH 10/14] bench_internal: Remove unnecessary includes secp256k1.c is included anyway, so there's no need to include the individual _impl.h files. --- src/bench_internal.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/bench_internal.c b/src/bench_internal.c index 8688a4dc77..378c21f544 100644 --- a/src/bench_internal.c +++ b/src/bench_internal.c @@ -10,13 +10,8 @@ #include "../include/secp256k1.h" #include "assumptions.h" -#include "util.h" -#include "hash_impl.h" -#include "field_impl.h" -#include "group_impl.h" -#include "scalar_impl.h" -#include "ecmult_impl.h" #include "bench.h" +#include "util.h" static void help(int default_iters) { printf("Benchmarks various internal routines.\n"); From b7840be6dcbd865fe659e8598b76db7f123861f6 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 13 Aug 2025 18:05:56 +0200 Subject: [PATCH 11/14] group: Move definitions of constants to header SECP256K1_B and secp256k1_ge_const_g are used outside of group_impl.h, e.g., in ecmult_const_impl.h and ecmult_gen_impl.h, respectively. --- sage/gen_exhaustive_groups.sage | 2 +- src/group.h | 63 ++++++++++++++++++++++++++++++++- src/group_impl.h | 62 -------------------------------- 3 files changed, 63 insertions(+), 64 deletions(-) diff --git a/sage/gen_exhaustive_groups.sage b/sage/gen_exhaustive_groups.sage index 218868d655..87be4fe4c2 100644 --- a/sage/gen_exhaustive_groups.sage +++ b/sage/gen_exhaustive_groups.sage @@ -99,7 +99,7 @@ def output_b(b): print(f"#define SECP256K1_B {int(b)}") print() -print("To be put in src/group_impl.h:") +print("To be put in src/group.h:") print() print("/* Begin of section generated by sage/gen_exhaustive_groups.sage. */") for f in sorted(solutions.keys()): diff --git a/src/group.h b/src/group.h index e771abdeb2..5ad098980c 100644 --- a/src/group.h +++ b/src/group.h @@ -21,7 +21,6 @@ typedef struct { #define SECP256K1_GE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), 0} #define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} -static const secp256k1_ge secp256k1_ge_const_g; /** A group element of the secp256k1 curve, in jacobian coordinates. * Note: For exhastive test mode, secp256k1 is replaced by a small subgroup of a different curve. @@ -53,6 +52,68 @@ typedef struct { #define SECP256K1_GEJ_Y_MAGNITUDE_MAX 4 #define SECP256K1_GEJ_Z_MAGNITUDE_MAX 1 +/* Begin of section generated by sage/gen_exhaustive_groups.sage. */ +#define SECP256K1_G_ORDER_7 SECP256K1_GE_CONST(\ + 0x66625d13, 0x317ffe44, 0x63d32cff, 0x1ca02b9b,\ + 0xe5c6d070, 0x50b4b05e, 0x81cc30db, 0xf5166f0a,\ + 0x1e60e897, 0xa7c00c7c, 0x2df53eb6, 0x98274ff4,\ + 0x64252f42, 0x8ca44e17, 0x3b25418c, 0xff4ab0cf\ +) +#define SECP256K1_G_ORDER_13 SECP256K1_GE_CONST(\ + 0xa2482ff8, 0x4bf34edf, 0xa51262fd, 0xe57921db,\ + 0xe0dd2cb7, 0xa5914790, 0xbc71631f, 0xc09704fb,\ + 0x942536cb, 0xa3e49492, 0x3a701cc3, 0xee3e443f,\ + 0xdf182aa9, 0x15b8aa6a, 0x166d3b19, 0xba84b045\ +) +#define SECP256K1_G_ORDER_199 SECP256K1_GE_CONST(\ + 0x7fb07b5c, 0xd07c3bda, 0x553902e2, 0x7a87ea2c,\ + 0x35108a7f, 0x051f41e5, 0xb76abad5, 0x1f2703ad,\ + 0x0a251539, 0x5b4c4438, 0x952a634f, 0xac10dd4d,\ + 0x6d6f4745, 0x98990c27, 0x3a4f3116, 0xd32ff969\ +) +/** Generator for secp256k1, value 'g' defined in + * "Standards for Efficient Cryptography" (SEC2) 2.7.1. + */ +#define SECP256K1_G SECP256K1_GE_CONST(\ + 0x79be667e, 0xf9dcbbac, 0x55a06295, 0xce870b07,\ + 0x029bfcdb, 0x2dce28d9, 0x59f2815b, 0x16f81798,\ + 0x483ada77, 0x26a3c465, 0x5da4fbfc, 0x0e1108a8,\ + 0xfd17b448, 0xa6855419, 0x9c47d08f, 0xfb10d4b8\ +) +/* 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 small constant B. + * - The subgroup has a generator 2*P, where P.x is as small as possible. + * - The subgroup has size less than 1000 to permit exhaustive testing. + * - The subgroup admits an endomorphism of the form lambda*(x,y) == (beta*x,y). + */ +#if defined(EXHAUSTIVE_TEST_ORDER) +# if EXHAUSTIVE_TEST_ORDER == 7 + +static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_7; +#define SECP256K1_B 6 + +# elif EXHAUSTIVE_TEST_ORDER == 13 + +static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_13; +#define SECP256K1_B 2 + +# elif EXHAUSTIVE_TEST_ORDER == 199 + +static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_199; +#define SECP256K1_B 4 + +# else +# error No known generator for the specified exhaustive test group order. +# endif +#else + +static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G; +#define SECP256K1_B 7 + +#endif +/* End of section generated by sage/gen_exhaustive_groups.sage. */ + /** Set a group element equal to the point with given X and Y coordinates */ static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y); diff --git a/src/group_impl.h b/src/group_impl.h index f57db051f6..a137d2a5c6 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -13,68 +13,6 @@ #include "group.h" #include "util.h" -/* Begin of section generated by sage/gen_exhaustive_groups.sage. */ -#define SECP256K1_G_ORDER_7 SECP256K1_GE_CONST(\ - 0x66625d13, 0x317ffe44, 0x63d32cff, 0x1ca02b9b,\ - 0xe5c6d070, 0x50b4b05e, 0x81cc30db, 0xf5166f0a,\ - 0x1e60e897, 0xa7c00c7c, 0x2df53eb6, 0x98274ff4,\ - 0x64252f42, 0x8ca44e17, 0x3b25418c, 0xff4ab0cf\ -) -#define SECP256K1_G_ORDER_13 SECP256K1_GE_CONST(\ - 0xa2482ff8, 0x4bf34edf, 0xa51262fd, 0xe57921db,\ - 0xe0dd2cb7, 0xa5914790, 0xbc71631f, 0xc09704fb,\ - 0x942536cb, 0xa3e49492, 0x3a701cc3, 0xee3e443f,\ - 0xdf182aa9, 0x15b8aa6a, 0x166d3b19, 0xba84b045\ -) -#define SECP256K1_G_ORDER_199 SECP256K1_GE_CONST(\ - 0x7fb07b5c, 0xd07c3bda, 0x553902e2, 0x7a87ea2c,\ - 0x35108a7f, 0x051f41e5, 0xb76abad5, 0x1f2703ad,\ - 0x0a251539, 0x5b4c4438, 0x952a634f, 0xac10dd4d,\ - 0x6d6f4745, 0x98990c27, 0x3a4f3116, 0xd32ff969\ -) -/** Generator for secp256k1, value 'g' defined in - * "Standards for Efficient Cryptography" (SEC2) 2.7.1. - */ -#define SECP256K1_G SECP256K1_GE_CONST(\ - 0x79be667e, 0xf9dcbbac, 0x55a06295, 0xce870b07,\ - 0x029bfcdb, 0x2dce28d9, 0x59f2815b, 0x16f81798,\ - 0x483ada77, 0x26a3c465, 0x5da4fbfc, 0x0e1108a8,\ - 0xfd17b448, 0xa6855419, 0x9c47d08f, 0xfb10d4b8\ -) -/* 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 small constant B. - * - The subgroup has a generator 2*P, where P.x is as small as possible. - * - The subgroup has size less than 1000 to permit exhaustive testing. - * - The subgroup admits an endomorphism of the form lambda*(x,y) == (beta*x,y). - */ -#if defined(EXHAUSTIVE_TEST_ORDER) -# if EXHAUSTIVE_TEST_ORDER == 7 - -static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_7; -#define SECP256K1_B 6 - -# elif EXHAUSTIVE_TEST_ORDER == 13 - -static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_13; -#define SECP256K1_B 2 - -# elif EXHAUSTIVE_TEST_ORDER == 199 - -static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_199; -#define SECP256K1_B 4 - -# else -# error No known generator for the specified exhaustive test group order. -# endif -#else - -static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G; -#define SECP256K1_B 7 - -#endif -/* End of section generated by sage/gen_exhaustive_groups.sage. */ - static void secp256k1_ge_verify(const secp256k1_ge *a) { SECP256K1_FE_VERIFY(&a->x); SECP256K1_FE_VERIFY(&a->y); From 5ac6929f5481864dd2d9b4e2917051da72c4328c Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 13 Aug 2025 21:45:42 +0200 Subject: [PATCH 12/14] Include modinv32/64 like other internal modules And also sort the _impl.h includes. --- src/field_10x26_impl.h | 2 +- src/field_5x52_impl.h | 2 +- src/precompute_ecmult.c | 6 ++++++ src/precompute_ecmult_gen.c | 6 ++++++ src/secp256k1.c | 19 ++++++++++++------- src/tests.c | 6 ------ 6 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/field_10x26_impl.h b/src/field_10x26_impl.h index ea14c27318..009fb288d3 100644 --- a/src/field_10x26_impl.h +++ b/src/field_10x26_impl.h @@ -10,7 +10,7 @@ #include "checkmem.h" #include "util.h" #include "field.h" -#include "modinv32_impl.h" +#include "modinv32.h" #ifdef VERIFY static void secp256k1_fe_impl_verify(const secp256k1_fe *a) { diff --git a/src/field_5x52_impl.h b/src/field_5x52_impl.h index 46dca6b981..4f36743f66 100644 --- a/src/field_5x52_impl.h +++ b/src/field_5x52_impl.h @@ -10,7 +10,7 @@ #include "checkmem.h" #include "util.h" #include "field.h" -#include "modinv64_impl.h" +#include "modinv64.h" #include "field_5x52_int128_impl.h" diff --git a/src/precompute_ecmult.c b/src/precompute_ecmult.c index 021fe3940c..cdf57b9f60 100644 --- a/src/precompute_ecmult.c +++ b/src/precompute_ecmult.c @@ -16,6 +16,12 @@ #include "field_impl.h" #include "group_impl.h" #include "int128_impl.h" +#include "modinv32_impl.h" +#ifdef SECP256K1_WIDEMUL_INT128 +/* modinv64 is only available if we have an int128 implementation. */ +#include "modinv64_impl.h" +#endif + #include "ecmult.h" #include "ecmult_compute_table_impl.h" diff --git a/src/precompute_ecmult_gen.c b/src/precompute_ecmult_gen.c index cd0fe70fc2..cd3570b223 100644 --- a/src/precompute_ecmult_gen.c +++ b/src/precompute_ecmult_gen.c @@ -15,6 +15,12 @@ #include "group.h" #include "int128_impl.h" +#include "modinv32_impl.h" +#ifdef SECP256K1_WIDEMUL_INT128 +/* modinv64 is only available if we have an int128 implementation. */ +#include "modinv64_impl.h" +#endif + #include "ecmult_gen.h" #include "ecmult_gen_compute_table_impl.h" diff --git a/src/secp256k1.c b/src/secp256k1.c index 20f1cdd67d..dbd729c9fa 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -26,19 +26,24 @@ #include "checkmem.h" #include "util.h" -#include "field_impl.h" -#include "scalar_impl.h" -#include "group_impl.h" -#include "ecmult_impl.h" -#include "ecmult_const_impl.h" -#include "ecmult_gen_impl.h" #include "ecdsa_impl.h" #include "eckey_impl.h" +#include "ecmult_const_impl.h" +#include "ecmult_gen_impl.h" +#include "ecmult_impl.h" +#include "field_impl.h" +#include "group_impl.h" #include "hash_impl.h" +#include "hsort_impl.h" #include "int128_impl.h" +#include "modinv32_impl.h" +#ifdef SECP256K1_WIDEMUL_INT128 +/* modinv64 is only available if we have an int128 implementation. */ +#include "modinv64_impl.h" +#endif +#include "scalar_impl.h" #include "scratch_impl.h" #include "selftest.h" -#include "hsort_impl.h" #ifdef SECP256K1_NO_BUILD # error "secp256k1.h processed without SECP256K1_BUILD defined while building secp256k1.c" diff --git a/src/tests.c b/src/tests.c index 3e2c83f2e3..596bd3861a 100644 --- a/src/tests.c +++ b/src/tests.c @@ -27,12 +27,6 @@ #include "../contrib/lax_der_parsing.c" #include "../contrib/lax_der_privatekey_parsing.c" -#include "modinv32_impl.h" -#ifdef SECP256K1_WIDEMUL_INT128 -#include "modinv64_impl.h" -#include "int128_impl.h" -#endif - #define CONDITIONAL_TEST(cnt, nam) if (COUNT < (cnt)) { printf("Skipping %s (iteration count too low)\n", nam); } else static int COUNT = 16; From a2f118e6a979cbb757ae8c8f67fd8f48f6e9e0bb Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 14 Aug 2025 10:22:23 +0200 Subject: [PATCH 13/14] selftest: Split into .h and _impl.h --- Makefile.am | 1 + src/secp256k1.c | 2 +- src/selftest.h | 24 ++---------------------- src/selftest_impl.h | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 23 deletions(-) create mode 100644 src/selftest_impl.h diff --git a/Makefile.am b/Makefile.am index f556d3bfa0..4fc9ed9cf2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -58,6 +58,7 @@ noinst_HEADERS += src/int128_struct_impl.h noinst_HEADERS += src/scratch.h noinst_HEADERS += src/scratch_impl.h noinst_HEADERS += src/selftest.h +noinst_HEADERS += src/selftest_impl.h noinst_HEADERS += src/testrand.h noinst_HEADERS += src/testrand_impl.h noinst_HEADERS += src/hash.h diff --git a/src/secp256k1.c b/src/secp256k1.c index dbd729c9fa..5ae16a4a15 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -43,7 +43,7 @@ #endif #include "scalar_impl.h" #include "scratch_impl.h" -#include "selftest.h" +#include "selftest_impl.h" #ifdef SECP256K1_NO_BUILD # error "secp256k1.h processed without SECP256K1_BUILD defined while building secp256k1.c" diff --git a/src/selftest.h b/src/selftest.h index c0720c0294..96dc6cd86f 100644 --- a/src/selftest.h +++ b/src/selftest.h @@ -7,27 +7,7 @@ #ifndef SECP256K1_SELFTEST_H #define SECP256K1_SELFTEST_H -#include "hash.h" -#include "util.h" - -#include - -static int secp256k1_selftest_sha256(void) { - static const char *input63 = "For this sample, this 63-byte string will be used as input data"; - static const unsigned char output32[32] = { - 0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, - 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42, - }; - unsigned char out[32]; - secp256k1_sha256 hasher; - secp256k1_sha256_initialize(&hasher); - secp256k1_sha256_write(&hasher, (const unsigned char*)input63, 63); - secp256k1_sha256_finalize(&hasher, out); - return secp256k1_memcmp_var(out, output32, 32) == 0; -} - -static int secp256k1_selftest_passes(void) { - return secp256k1_selftest_sha256(); -} +static int secp256k1_selftest_sha256(void); +static int secp256k1_selftest_passes(void); #endif /* SECP256K1_SELFTEST_H */ diff --git a/src/selftest_impl.h b/src/selftest_impl.h new file mode 100644 index 0000000000..db89803ecb --- /dev/null +++ b/src/selftest_impl.h @@ -0,0 +1,34 @@ +/*********************************************************************** + * Copyright (c) 2020 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_SELFTEST_IMPL_H +#define SECP256K1_SELFTEST_IMPL_H + +#include "hash.h" +#include "selftest.h" +#include "util.h" + +#include + +static int secp256k1_selftest_sha256(void) { + static const char *input63 = "For this sample, this 63-byte string will be used as input data"; + static const unsigned char output32[32] = { + 0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, + 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42, + }; + unsigned char out[32]; + secp256k1_sha256 hasher; + secp256k1_sha256_initialize(&hasher); + secp256k1_sha256_write(&hasher, (const unsigned char*)input63, 63); + secp256k1_sha256_finalize(&hasher, out); + return secp256k1_memcmp_var(out, output32, 32) == 0; +} + +static int secp256k1_selftest_passes(void) { + return secp256k1_selftest_sha256(); +} + +#endif /* SECP256K1_SELFTEST_IMPL_H */ From 8cce3922b4d330356a621dbcbe354527391f0cad Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 18 Aug 2025 17:43:01 +0200 Subject: [PATCH 14/14] ecmult_gen: Export _ecmult_gen_context_is_built() --- src/ecmult_gen.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ecmult_gen.h b/src/ecmult_gen.h index 43dd10c38d..5fe959b9ff 100644 --- a/src/ecmult_gen.h +++ b/src/ecmult_gen.h @@ -134,6 +134,7 @@ typedef struct { 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);