Squashed 'src/secp256k1/' changes from 7262adb4b4..bd0287d650

bd0287d650 Merge bitcoin-core/secp256k1#1859: field: force-inline 5x52 mul and sqr
fdcf2d41e2 Merge bitcoin-core/secp256k1#1865: test: enable -Wunused-function in test suite (Fix #1831)
b2d2bd362d Merge bitcoin-core/secp256k1#1860: cmake: Emulate Libtool's behavior on NetBSD and OpenBSD
87bec430bf Merge bitcoin-core/secp256k1#1867: test: musig: fix dead "aggnonce encodes two points at infinity" check
71fcd8410e field: force-inline 5x52 mul and sqr
a77dacad9a test: enable -Wunused-function in test suite (Fix #1831)
aea86bc350 Merge bitcoin-core/secp256k1#1864: test: refactor: simplify tests by using `_ecmult_gen_ge` helper, add test
2ee79e77e6 test: add unit test for `_ecmult_gen_ge`
d7125e517d test: musig: fix dead "aggnonce encodes two points at infinity" check
1eab757207 cmake: Fix shared library versioning on OpenBSD
a401c5145a cmake: Fix shared library versioning on NetBSD
8a0f4002c7 cmake, refactor: Improve documenting in `SetLibtoolAbiVersion` module
acf2084aa7 cmake, refactor: Introduce `SetLibtoolAbiVersion` module
0f4a7e6bf9 Merge bitcoin-core/secp256k1#1855: bench: add internal benchmark for `secp256k1_fe_normalize_var`
ca68daf8e1 test: refactor: simplify tests by using `_ecmult_gen_ge` helper
13db747f2b Merge bitcoin-core/secp256k1#1861: refactor: introduce `_ecmult_gen_ge` helper (preventing accidental gej leaks)
9e017e5062 refactor: rename `_ecmult_gen` -> `_ecmult_gen_gej` for consistency
a3296d5e23 refactor: introduce `_ecmult_gen_ge` helper (preventing accidental gej leaks)
c63062380f Merge bitcoin-core/secp256k1#1852: Add exhaustive test for ECDH module
240578eef5 bench: add internal benchmark for `secp256k1_fe_normalize_var`
5698e66c64 Add exhaustive test for ECDH module
a39093de15 Merge bitcoin-core/secp256k1#1851: doc: correct API docs for ECDSA signing out-params (s/array/signature object/)
8363a2d8d1 Merge bitcoin-core/secp256k1#1854: tests: compare full MuSig aggregate nonce
af1fdd1215 tests: compare full MuSig aggregate nonce
40a0d874a6 doc: correct API docs for ECDSA signing out-params (s/array/signature object/)
b11340b3ce Merge bitcoin-core/secp256k1#1849: musig: always clear out secret key in `secp256k1_musig_nonce_gen_counter`
8479eafa57 musig: always clear out secret key in `secp256k1_musig_nonce_gen_counter`
c1a9e4fe64 Merge bitcoin-core/secp256k1#1848: ci: Bump GCC snapshot major version to 17
3cca6451a2 ci: Bump GCC snapshot major version to 17
ea174fe045 Merge bitcoin-core/secp256k1#1846: ci: Replace `ilammy/msvc-dev-cmd` with manual MSVC setup
285cb788e9 ci: Replace `ilammy/msvc-dev-cmd` with manual MSVC setup

git-subtree-dir: src/secp256k1
git-subtree-split: bd0287d650c24dc41e0362675a9f6a49ee952def
This commit is contained in:
fanquake
2026-06-18 09:38:02 +02:00
parent dfd54c959e
commit 1f3f0a4e22
25 changed files with 257 additions and 90 deletions

View File

@@ -604,11 +604,10 @@ jobs:
steps:
- *CHECKOUT
- name: Add cl.exe to PATH
uses: ilammy/msvc-dev-cmd@v1
- name: C++ (public headers)
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
cl.exe -c -WX -TP include/*.h
cxx_fpermissive_debian:

View File

@@ -147,6 +147,8 @@ if(MSVC)
string(REGEX REPLACE "/DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
string(REGEX REPLACE "/DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
string(REGEX REPLACE "/DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}")
# Match GCC/Clang's size-optimization macro for the inline guard
add_compile_definitions($<$<CONFIG:MinSizeRel>:__OPTIMIZE_SIZE__=1>)
else()
string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")

View File

@@ -40,7 +40,7 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-instal
apt-get clean && rm -rf /var/lib/apt/lists/*
# Build and install gcc snapshot
ARG GCC_SNAPSHOT_MAJOR=16
ARG GCC_SNAPSHOT_MAJOR=17
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
wget libgmp-dev libmpfr-dev libmpc-dev flex && \
mkdir gcc && cd gcc && \

View File

@@ -0,0 +1,61 @@
#[=[
This emulates Libtool to make sure Libtool and CMake agree on
the ABI version and file naming for shared libraries.
The `version_type` variable is set in `libtool.m4` (installed
by autoreconf into autotools-aux/m4/).
For the `major` and `versuffix` variables, see below "Calculate
the version variables" in `ltmain.sh` (installed by autoreconf
into autotools-aux/).
]=]
function(set_libtool_abi_version target current revision age)
if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|FreeBSD)$")
# version_type = linux | freebsd-elf
# major = $current - $age
# versuffix = $major.$age.$revision
math(EXPR _major "${current} - ${age}")
set_target_properties(${target} PROPERTIES
SOVERSION ${_major}
VERSION ${_major}.${age}.${revision}
)
elseif(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
# version_type = sunos
# major = $current
# versuffix = $current.$revision
set_target_properties(${target} PROPERTIES
SOVERSION ${current}
VERSION ${current}.${revision}
)
elseif(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
# version_type = sunos
# major = $current
# versuffix = $current.$revision
set_target_properties(${target} PROPERTIES
# OpenBSD has no `soname_spec` defined in `libtool.m4`.
VERSION ${current}.${revision}
)
elseif(APPLE)
# version_type = darwin
# major = $current - $age
math(EXPR _major "${current} - ${age}")
math(EXPR _compatibility "${current} + 1")
set_target_properties(${target} PROPERTIES
SOVERSION ${_major}
MACHO_COMPATIBILITY_VERSION ${_compatibility}
MACHO_CURRENT_VERSION ${_compatibility}.${revision}
)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
# version_type = windows
# major = $current - $age
# versuffix = $major
math(EXPR _major "${current} - ${age}")
set(_windows_name "secp256k1")
if(MSVC)
set(_windows_name "${PROJECT_NAME}")
endif()
set_target_properties(${target} PROPERTIES
ARCHIVE_OUTPUT_NAME "${_windows_name}"
RUNTIME_OUTPUT_NAME "${_windows_name}-${_major}"
)
endif()
endfunction()

View File

@@ -687,7 +687,7 @@ SECP256K1_API const secp256k1_nonce_function secp256k1_nonce_function_default;
* Returns: 1: signature created
* 0: the nonce generation function failed, or the secret key was invalid.
* Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: sig: pointer to an array where the signature will be placed.
* Out: sig: pointer to a signature object.
* In: msghash32: the 32-byte message hash being signed.
* seckey: pointer to a 32-byte secret key.
* noncefp: pointer to a nonce generation function. If NULL,

View File

@@ -73,7 +73,7 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact(
* Returns: 1: signature created
* 0: the nonce generation function failed, or the secret key was invalid.
* Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: sig: pointer to an array where the signature will be placed.
* Out: sig: pointer to a signature object.
* In: msghash32: the 32-byte message hash being signed.
* seckey: pointer to a 32-byte secret key.
* noncefp: pointer to a nonce generation function. If NULL,

View File

@@ -94,35 +94,12 @@ set_target_properties(secp256k1_objs PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:secp256k1,INTERFACE_INCLUDE_DIRECTORIES>"
)
# This emulates Libtool to make sure Libtool and CMake agree on the ABI version,
# see below "Calculate the version variables" in autotools-aux/ltmain.sh.
math(EXPR ${PROJECT_NAME}_soversion "${${PROJECT_NAME}_LIB_VERSION_CURRENT} - ${${PROJECT_NAME}_LIB_VERSION_AGE}")
set_target_properties(secp256k1 PROPERTIES
SOVERSION ${${PROJECT_NAME}_soversion}
include(SetLibtoolAbiVersion)
set_libtool_abi_version(secp256k1
${${PROJECT_NAME}_LIB_VERSION_CURRENT}
${${PROJECT_NAME}_LIB_VERSION_REVISION}
${${PROJECT_NAME}_LIB_VERSION_AGE}
)
if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|FreeBSD)$")
set_target_properties(secp256k1 PROPERTIES
VERSION ${${PROJECT_NAME}_soversion}.${${PROJECT_NAME}_LIB_VERSION_AGE}.${${PROJECT_NAME}_LIB_VERSION_REVISION}
)
elseif(APPLE)
math(EXPR ${PROJECT_NAME}_compatibility_version "${${PROJECT_NAME}_LIB_VERSION_CURRENT} + 1")
set_target_properties(secp256k1 PROPERTIES
MACHO_COMPATIBILITY_VERSION ${${PROJECT_NAME}_compatibility_version}
MACHO_CURRENT_VERSION ${${PROJECT_NAME}_compatibility_version}.${${PROJECT_NAME}_LIB_VERSION_REVISION}
)
unset(${PROJECT_NAME}_compatibility_version)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
set(${PROJECT_NAME}_windows "secp256k1")
if(MSVC)
set(${PROJECT_NAME}_windows "${PROJECT_NAME}")
endif()
set_target_properties(secp256k1 PROPERTIES
ARCHIVE_OUTPUT_NAME "${${PROJECT_NAME}_windows}"
RUNTIME_OUTPUT_NAME "${${PROJECT_NAME}_windows}-${${PROJECT_NAME}_soversion}"
)
unset(${PROJECT_NAME}_windows)
endif()
unset(${PROJECT_NAME}_soversion)
if(SECP256K1_BUILD_BENCHMARK)
add_executable(bench bench.c)

View File

@@ -88,7 +88,7 @@ static void bench_ecmult_teardown_helper(bench_data* data, size_t* seckey_offset
secp256k1_scalar_add(&sum_scalars, &sum_scalars, &s);
}
}
secp256k1_ecmult_gen(&data->ctx->ecmult_gen_ctx, &tmp, &sum_scalars);
secp256k1_ecmult_gen_gej(&data->ctx->ecmult_gen_ctx, &tmp, &sum_scalars);
CHECK(secp256k1_gej_eq_var(&tmp, &sum_output));
}
@@ -104,7 +104,7 @@ static void bench_ecmult_gen(void* arg, int iters) {
int i;
for (i = 0; i < iters; ++i) {
secp256k1_ecmult_gen(&data->ctx->ecmult_gen_ctx, &data->output[i], &data->scalars[(data->offset1+i) % POINTS]);
secp256k1_ecmult_gen_gej(&data->ctx->ecmult_gen_ctx, &data->output[i], &data->scalars[(data->offset1+i) % POINTS]);
}
}

View File

@@ -194,6 +194,17 @@ static void bench_field_normalize(void* arg, int iters) {
}
}
static void bench_field_normalize_var(void* arg, int iters) {
int i;
bench_inv *data = (bench_inv*)arg;
/* Note that this benchmark measures the optimistic path. The worst-case path with the final
reduction is very unlikely to be needed, so this is representative of the common case. */
for (i = 0; i < iters; i++) {
secp256k1_fe_normalize_var(&data->fe[0]);
}
}
static void bench_field_normalize_weak(void* arg, int iters) {
int i;
bench_inv *data = (bench_inv*)arg;
@@ -421,6 +432,7 @@ int main(int argc, char **argv) {
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "half")) run_benchmark("field_half", bench_field_half, bench_setup, NULL, &data, 10, iters*100);
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize", bench_field_normalize, bench_setup, NULL, &data, 10, iters*100);
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize_var", bench_field_normalize_var, bench_setup, NULL, &data, 10, iters*100);
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize_weak", bench_field_normalize_weak, bench_setup, NULL, &data, 10, iters*100);
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "sqr")) run_benchmark("field_sqr", bench_field_sqr, bench_setup, NULL, &data, 10, iters*10);
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "mul")) run_benchmark("field_mul", bench_field_mul, bench_setup, NULL, &data, 10, iters*10);

View File

@@ -40,6 +40,11 @@
#include "../include/secp256k1_ellswift.h"
#endif
#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic warning "-Wunused-function"
#endif
static void run_tests(secp256k1_context *ctx, unsigned char *key);
int main(void) {
@@ -265,3 +270,7 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) {
#endif
}
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#endif

View File

@@ -273,14 +273,12 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar *sigr, const secp25
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) {
unsigned char b[32];
secp256k1_gej rp;
secp256k1_ge r;
secp256k1_scalar n;
int overflow = 0;
int high;
secp256k1_ecmult_gen(ctx, &rp, nonce);
secp256k1_ge_set_gej(&r, &rp);
secp256k1_ecmult_gen_ge(ctx, &r, nonce);
secp256k1_fe_normalize(&r.x);
secp256k1_fe_normalize(&r.y);
secp256k1_fe_get_b32(b, &r.x);
@@ -296,7 +294,6 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec
secp256k1_scalar_inverse(sigs, nonce);
secp256k1_scalar_mul(sigs, sigs, &n);
secp256k1_scalar_clear(&n);
secp256k1_gej_clear(&rp);
secp256k1_ge_clear(&r);
high = secp256k1_scalar_is_high(sigs);
secp256k1_scalar_cond_negate(sigs, high);

View File

@@ -137,7 +137,8 @@ static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx
static void secp256k1_ecmult_gen_context_clear(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);
static void secp256k1_ecmult_gen_gej(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a);
static void secp256k1_ecmult_gen_ge(const secp256k1_ecmult_gen_context* ctx, secp256k1_ge *r, const secp256k1_scalar *a);
static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_hash_ctx *hash_ctx, const unsigned char *seed32);

View File

@@ -51,7 +51,7 @@ static void secp256k1_ecmult_gen_scalar_diff(secp256k1_scalar* diff) {
secp256k1_scalar_add(diff, diff, &neghalf);
}
static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) {
static void secp256k1_ecmult_gen_gej(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) {
uint32_t comb_off;
secp256k1_ge add;
secp256k1_fe neg;
@@ -281,11 +281,19 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25
secp256k1_memclear_explicit(&recoded, sizeof(recoded));
}
SECP256K1_INLINE static void secp256k1_ecmult_gen_ge(const secp256k1_ecmult_gen_context *ctx, secp256k1_ge *r, const secp256k1_scalar *a) {
secp256k1_gej rj;
secp256k1_ecmult_gen_gej(ctx, &rj, a);
secp256k1_ge_set_gej(r, &rj);
/* Jacobian coordinates resulting from our multiplication algorithm could potentially leak
* information about the secret input scalar, so clear the memory out to be on the safe side. */
secp256k1_gej_clear(&rj);
}
/* Setup blinding values for secp256k1_ecmult_gen. */
static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_hash_ctx *hash_ctx, const unsigned char *seed32) {
secp256k1_scalar b;
secp256k1_scalar diff;
secp256k1_gej gb;
secp256k1_fe f;
unsigned char nonce32[32];
secp256k1_rfc6979_hmac_sha256 rng;
@@ -325,15 +333,13 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
* which secp256k1_gej_add_ge cannot handle. */
secp256k1_scalar_cmov(&b, &secp256k1_scalar_one, secp256k1_scalar_is_zero(&b));
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
secp256k1_ecmult_gen(ctx, &gb, &b);
secp256k1_ecmult_gen_ge(ctx, &ctx->ge_offset, &b);
secp256k1_scalar_negate(&b, &b);
secp256k1_scalar_add(&ctx->scalar_offset, &b, &diff);
secp256k1_ge_set_gej(&ctx->ge_offset, &gb);
/* Clean up. */
secp256k1_memclear_explicit(nonce32, sizeof(nonce32));
secp256k1_scalar_clear(&b);
secp256k1_gej_clear(&gb);
secp256k1_fe_clear(&f);
secp256k1_rfc6979_hmac_sha256_clear(&rng);
}

View File

@@ -338,11 +338,11 @@ SECP256K1_INLINE static void secp256k1_fe_impl_add(secp256k1_fe *r, const secp25
r->n[4] += a->n[4];
}
SECP256K1_INLINE static void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) {
SECP256K1_FORCE_INLINE static void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) {
secp256k1_fe_mul_inner(r->n, a->n, b->n);
}
SECP256K1_INLINE static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
SECP256K1_FORCE_INLINE static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
secp256k1_fe_sqr_inner(r->n, a->n);
}

View File

@@ -15,7 +15,7 @@
#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0)
#define VERIFY_BITS_128(x, n) VERIFY_CHECK(secp256k1_u128_check_bits((x), (n)))
SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
SECP256K1_FORCE_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
secp256k1_uint128 c, d;
uint64_t t3, t4, tx, u0;
uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
@@ -151,7 +151,7 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t
/* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
}
SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) {
SECP256K1_FORCE_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) {
secp256k1_uint128 c, d;
uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
uint64_t t3, t4, tx, u0;

View File

@@ -1,5 +1,6 @@
include_HEADERS += include/secp256k1_ecdh.h
noinst_HEADERS += src/modules/ecdh/main_impl.h
noinst_HEADERS += src/modules/ecdh/tests_impl.h
noinst_HEADERS += src/modules/ecdh/tests_exhaustive_impl.h
noinst_HEADERS += src/modules/ecdh/bench_impl.h
noinst_HEADERS += src/wycheproof/ecdh_secp256k1_test.h

View File

@@ -0,0 +1,56 @@
/***********************************************************************
* Distributed under the MIT software license, see the accompanying *
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
***********************************************************************/
#ifndef SECP256K1_MODULE_ECDH_TESTS_EXHAUSTIVE_H
#define SECP256K1_MODULE_ECDH_TESTS_EXHAUSTIVE_H
#include "../../../include/secp256k1_ecdh.h"
#include "main_impl.h"
static void test_exhaustive_ecdh(const secp256k1_context *ctx, const secp256k1_ge *group) {
int i, j;
unsigned char seckeys[EXHAUSTIVE_TEST_ORDER - 1][32];
secp256k1_pubkey pubkeys[EXHAUSTIVE_TEST_ORDER - 1];
/* Construct key pairs (32-byte secret key, public key object) for the entire group. */
for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) {
secp256k1_scalar scalar;
secp256k1_scalar_set_int(&scalar, i);
secp256k1_scalar_get_b32(seckeys[i - 1], &scalar);
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkeys[i - 1], seckeys[i - 1]));
}
/* Loop over key combinations. */
for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) {
for (j = 1; j < EXHAUSTIVE_TEST_ORDER; j++) {
unsigned char ecdh_result_ij[32];
unsigned char ecdh_result_ji[32];
/* Calculate ECDH(i*G, j) and ECDH(j*G, i) using API function and verify that the results match. */
CHECK(secp256k1_ecdh(ctx, ecdh_result_ij, &pubkeys[i - 1], seckeys[j - 1], NULL, NULL));
CHECK(secp256k1_ecdh(ctx, ecdh_result_ji, &pubkeys[j - 1], seckeys[i - 1], NULL, NULL));
CHECK(secp256k1_memcmp_var(ecdh_result_ij, ecdh_result_ji, 32) == 0);
/* Recalculate the expected ECDH result manually by invoking the default ECDH hash
* function on the precomputed group element (group[i * j]) coordinates, and verify
* that it matches the previously calculated public API results. */
{
secp256k1_ge ecdh_ge_expected = group[(i * j) % EXHAUSTIVE_TEST_ORDER];
unsigned char ecdh_result_expected[32];
unsigned char x[32];
unsigned char y[32];
secp256k1_fe_normalize_var(&ecdh_ge_expected.x);
secp256k1_fe_normalize_var(&ecdh_ge_expected.y);
secp256k1_fe_get_b32(x, &ecdh_ge_expected.x);
secp256k1_fe_get_b32(y, &ecdh_ge_expected.y);
CHECK(secp256k1_ecdh_hash_function_default(ecdh_result_expected, x, y, NULL));
CHECK(secp256k1_memcmp_var(ecdh_result_ij, ecdh_result_expected, 32) == 0);
}
}
}
}
#endif

View File

@@ -415,7 +415,7 @@ static int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp
/* Compute pubnonce as two gejs */
for (i = 0; i < 2; i++) {
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &nonce_ptj[i], &k[i]);
secp256k1_ecmult_gen_gej(&ctx->ecmult_gen_ctx, &nonce_ptj[i], &k[i]);
secp256k1_scalar_clear(&k[i]);
}
@@ -483,11 +483,9 @@ int secp256k1_musig_nonce_gen_counter(const secp256k1_context* ctx, secp256k1_mu
(void) ret;
#endif
if (!secp256k1_musig_nonce_gen_internal(ctx, secnonce, pubnonce, buf, seckey, &pubkey, msg32, keyagg_cache, extra_input32)) {
return 0;
}
ret = secp256k1_musig_nonce_gen_internal(ctx, secnonce, pubnonce, buf, seckey, &pubkey, msg32, keyagg_cache, extra_input32);
secp256k1_memclear_explicit(seckey, sizeof(seckey));
return 1;
return ret;
}
static int secp256k1_musig_sum_pubnonces(const secp256k1_context* ctx, secp256k1_gej *summed_pubnonces, const secp256k1_musig_pubnonce * const* pubnonces, size_t n_pubnonces) {

View File

@@ -374,7 +374,7 @@ static void musig_api_tests(void) {
secp256k1_ge aggnonce_pt[2];
secp256k1_musig_aggnonce_load(CTX, aggnonce_pt, &aggnonce);
for (i = 0; i < 2; i++) {
secp256k1_ge_is_infinity(&aggnonce_pt[i]);
CHECK(secp256k1_ge_is_infinity(&aggnonce_pt[i]) == 1);
}
}
CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1);
@@ -862,7 +862,7 @@ static void musig_test_vectors_nonceagg(void) {
}
CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2));
CHECK(secp256k1_musig_aggnonce_serialize(CTX, aggnonce66, &aggnonce));
CHECK(secp256k1_memcmp_var(aggnonce66, c->expected, 33) == 0);
CHECK(secp256k1_memcmp_var(aggnonce66, c->expected, sizeof(aggnonce66)) == 0);
}
for (i = 0; i < ARRAY_SIZE(vector->error_case); i++) {
const struct musig_nonce_agg_test_case *c = &vector->error_case[i];

View File

@@ -123,7 +123,6 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi
secp256k1_scalar sk;
secp256k1_scalar e;
secp256k1_scalar k;
secp256k1_gej rj;
secp256k1_ge pk;
secp256k1_ge r;
unsigned char nonce32[32] = { 0 };
@@ -160,8 +159,7 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi
ret &= !secp256k1_scalar_is_zero(&k);
secp256k1_scalar_cmov(&k, &secp256k1_scalar_one, !ret);
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &k);
secp256k1_ge_set_gej(&r, &rj);
secp256k1_ecmult_gen_ge(&ctx->ecmult_gen_ctx, &r, &k);
/* We declassify r to allow using it as a branch point. This is fine
* because r is not a secret. */
@@ -183,7 +181,6 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi
secp256k1_scalar_clear(&sk);
secp256k1_memclear_explicit(seckey, sizeof(seckey));
secp256k1_memclear_explicit(nonce32, sizeof(nonce32));
secp256k1_gej_clear(&rj);
return ret;
}

View File

@@ -624,15 +624,12 @@ int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char
}
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) {
secp256k1_gej pj;
int ret;
ret = secp256k1_scalar_set_b32_seckey(seckey_scalar, seckey);
secp256k1_scalar_cmov(seckey_scalar, &secp256k1_scalar_one, !ret);
secp256k1_ecmult_gen(ecmult_gen_ctx, &pj, seckey_scalar);
secp256k1_ge_set_gej(p, &pj);
secp256k1_gej_clear(&pj);
secp256k1_ecmult_gen_ge(ecmult_gen_ctx, p, seckey_scalar);
return ret;
}

View File

@@ -37,6 +37,11 @@
#include "int128_impl.h"
#endif
#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic warning "-Wunused-function"
#endif
#define CONDITIONAL_TEST(cnt, nam) if (COUNT < (cnt)) { printf("Skipping %s (iteration count too low)\n", nam); } else
static secp256k1_context *CTX = NULL;
@@ -241,7 +246,6 @@ static void run_proper_context_tests(int use_prealloc) {
void *my_ctx_prealloc = NULL;
unsigned char seed[32] = {0x17};
secp256k1_gej pubj;
secp256k1_ge pub;
secp256k1_scalar msg, key, nonce;
secp256k1_scalar sigr, sigs;
@@ -329,8 +333,7 @@ static void run_proper_context_tests(int use_prealloc) {
/*** attempt to use them ***/
testutil_random_scalar_order_test(&msg);
testutil_random_scalar_order_test(&key);
secp256k1_ecmult_gen(&my_ctx->ecmult_gen_ctx, &pubj, &key);
secp256k1_ge_set_gej(&pub, &pubj);
secp256k1_ecmult_gen_ge(&my_ctx->ecmult_gen_ctx, &pub, &key);
/* obtain a working nonce */
do {
@@ -4304,19 +4307,16 @@ static void test_ec_combine(void) {
const secp256k1_pubkey* d[6];
secp256k1_pubkey sd;
secp256k1_pubkey sd2;
secp256k1_gej Qj;
secp256k1_ge Q;
int i;
for (i = 1; i <= 6; i++) {
secp256k1_scalar s;
testutil_random_scalar_order_test(&s);
secp256k1_scalar_add(&sum, &sum, &s);
secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &Qj, &s);
secp256k1_ge_set_gej(&Q, &Qj);
secp256k1_ecmult_gen_ge(&CTX->ecmult_gen_ctx, &Q, &s);
secp256k1_pubkey_save(&data[i - 1], &Q);
d[i - 1] = &data[i - 1];
secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &Qj, &sum);
secp256k1_ge_set_gej(&Q, &Qj);
secp256k1_ecmult_gen_ge(&CTX->ecmult_gen_ctx, &Q, &sum);
secp256k1_pubkey_save(&sd, &Q);
CHECK(secp256k1_ec_pubkey_combine(CTX, &sd2, d, i) == 1);
CHECK(secp256k1_memcmp_var(&sd, &sd2, sizeof(sd)) == 0);
@@ -4593,9 +4593,9 @@ static void test_ecmult_target(const secp256k1_scalar* target, int mode) {
/* EC multiplications */
if (mode == 0) {
secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &p1j, &n1);
secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &p2j, &n2);
secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &ptj, target);
secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &p1j, &n1);
secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &p2j, &n2);
secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &ptj, target);
} else if (mode == 1) {
secp256k1_ecmult(&p1j, &pj, &n1, &secp256k1_scalar_zero);
secp256k1_ecmult(&p2j, &pj, &n2, &secp256k1_scalar_zero);
@@ -5162,7 +5162,7 @@ static int test_ecmult_multi_random(secp256k1_scratch *scratch) {
secp256k1_scalar_mul(&scalars[filled], &sc_tmp, &g_scalar);
secp256k1_scalar_inverse_var(&sc_tmp, &sc_tmp);
secp256k1_scalar_negate(&sc_tmp, &sc_tmp);
secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &gejs[filled], &sc_tmp);
secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &gejs[filled], &sc_tmp);
++filled;
++mults;
}
@@ -5642,7 +5642,7 @@ static void test_ecmult_accumulate(secp256k1_sha256* acc, const secp256k1_scalar
size_t i;
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
secp256k1_gej_set_infinity(&infj);
secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &rj[0], x);
secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &rj[0], x);
secp256k1_ecmult(&rj[1], &gj, x, NULL);
secp256k1_ecmult(&rj[2], &gj, x, &secp256k1_scalar_zero);
secp256k1_ecmult(&rj[3], &infj, &secp256k1_scalar_zero, x);
@@ -5786,6 +5786,25 @@ static void run_ecmult_constants(void) {
}
}
static void run_ecmult_gen_ge(void) {
/* Test that secp256k1_ecmult_gen_ge result matches secp256k1_ecmult_gen_gej with
* manual Jacobian-to-affine conversion (secp256k1_ge_set_gej) over random scalars */
int i;
for (i = 0; i < COUNT; i++) {
secp256k1_scalar scalar;
secp256k1_gej result_gej;
secp256k1_ge result_ge, expected_ge;
testutil_random_scalar_order_test(&scalar);
secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &result_gej, &scalar);
secp256k1_ge_set_gej(&expected_ge, &result_gej);
secp256k1_ecmult_gen_ge(&CTX->ecmult_gen_ctx, &result_ge, &scalar);
CHECK(secp256k1_ge_eq_var(&result_ge, &expected_ge));
}
}
static void test_ecmult_gen_blind(void) {
/* Test ecmult_gen() blinding and confirm that the blinding changes, the affine points match, and the z's don't match. */
secp256k1_scalar key;
@@ -5796,13 +5815,13 @@ static void test_ecmult_gen_blind(void) {
secp256k1_ge p;
secp256k1_ge pge;
testutil_random_scalar_order_test(&key);
secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pgej, &key);
secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &pgej, &key);
testrand256(seed32);
b = CTX->ecmult_gen_ctx.scalar_offset;
p = CTX->ecmult_gen_ctx.ge_offset;
secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, secp256k1_get_hash_context(CTX), seed32);
CHECK(!secp256k1_scalar_eq(&b, &CTX->ecmult_gen_ctx.scalar_offset));
secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pgej2, &key);
secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &pgej2, &key);
CHECK(!gej_xyz_equals_gej(&pgej, &pgej2));
CHECK(!secp256k1_ge_eq_var(&p, &CTX->ecmult_gen_ctx.ge_offset));
secp256k1_ge_set_gej(&pge, &pgej);
@@ -5832,7 +5851,7 @@ static void test_ecmult_gen_edge_cases(void) {
for (i = -1; i < 2; ++i) {
/* Run test with gn = i - scalar_offset (so that the ecmult_gen recoded value represents i). */
secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &res1, &gn);
secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &res1, &gn);
secp256k1_ecmult(&res2, NULL, &secp256k1_scalar_zero, &gn);
secp256k1_ecmult_const(&res3, &secp256k1_ge_const_g, &gn);
CHECK(secp256k1_gej_eq_var(&res1, &res2));
@@ -6515,7 +6534,6 @@ static void random_sign(secp256k1_scalar *sigr, secp256k1_scalar *sigs, const se
}
static void test_ecdsa_sign_verify(void) {
secp256k1_gej pubj;
secp256k1_ge pub;
secp256k1_scalar one;
secp256k1_scalar msg, key;
@@ -6524,8 +6542,7 @@ static void test_ecdsa_sign_verify(void) {
int recid;
testutil_random_scalar_order_test(&msg);
testutil_random_scalar_order_test(&key);
secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pubj, &key);
secp256k1_ge_set_gej(&pub, &pubj);
secp256k1_ecmult_gen_ge(&CTX->ecmult_gen_ctx, &pub, &key);
getrec = testrand_bits(1);
/* The specific way in which this conditional is written sidesteps a potential bug in clang.
See the commit messages of the commit that introduced this comment for details. */
@@ -7284,7 +7301,6 @@ static void run_ecdsa_edge_cases(void) {
/* Test the case where ECDSA recomputes a point that is infinity. */
{
secp256k1_gej keyj;
secp256k1_ge key;
secp256k1_scalar msg;
secp256k1_scalar sr, ss;
@@ -7292,8 +7308,7 @@ static void run_ecdsa_edge_cases(void) {
secp256k1_scalar_negate(&ss, &ss);
secp256k1_scalar_inverse(&ss, &ss);
secp256k1_scalar_set_int(&sr, 1);
secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &keyj, &sr);
secp256k1_ge_set_gej(&key, &keyj);
secp256k1_ecmult_gen_ge(&CTX->ecmult_gen_ctx, &key, &sr);
msg = ss;
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
}
@@ -7969,6 +7984,7 @@ static const struct tf_test_entry tests_ecmult[] = {
CASE(ecmult_near_split_bound),
CASE(ecmult_chain),
CASE(ecmult_constants),
CASE(ecmult_gen_ge),
CASE(ecmult_gen_blind),
CASE(ecmult_const_tests),
CASE(ecmult_multi_tests),
@@ -8080,3 +8096,7 @@ int main(int argc, char **argv) {
if (tf_init(&tf, argc, argv) != 0) return EXIT_FAILURE;
return tf_run(&tf);
}
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#endif

View File

@@ -31,6 +31,11 @@
#include "testutil.h"
#include "util.h"
#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic warning "-Wunused-function"
#endif
static int count = 2;
static uint32_t num_cores = 1;
@@ -337,6 +342,10 @@ static void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_g
*/
}
#ifdef ENABLE_MODULE_ECDH
#include "modules/ecdh/tests_exhaustive_impl.h"
#endif
#ifdef ENABLE_MODULE_RECOVERY
#include "modules/recovery/tests_exhaustive_impl.h"
#endif
@@ -417,12 +426,10 @@ int main(int argc, char** argv) {
/* Verify against ecmult_gen */
{
secp256k1_scalar scalar_i;
secp256k1_gej generatedj;
secp256k1_ge generated;
secp256k1_scalar_set_int(&scalar_i, i);
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i);
secp256k1_ge_set_gej(&generated, &generatedj);
secp256k1_ecmult_gen_ge(&ctx->ecmult_gen_ctx, &generated, &scalar_i);
CHECK(!secp256k1_ge_is_infinity(&group[i]));
CHECK(secp256k1_ge_eq_var(&group[i], &generated));
@@ -437,6 +444,9 @@ int main(int argc, char** argv) {
test_exhaustive_sign(ctx, group);
test_exhaustive_verify(ctx, group);
#ifdef ENABLE_MODULE_ECDH
test_exhaustive_ecdh(ctx, group);
#endif
#ifdef ENABLE_MODULE_RECOVERY
test_exhaustive_recovery(ctx, group);
#endif
@@ -462,3 +472,7 @@ int main(int argc, char** argv) {
printf("no problems found\n");
return EXIT_SUCCESS;
}
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#endif

View File

@@ -17,6 +17,11 @@
#include "testrand.h"
#include "tests_common.h"
#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic warning "-Wunused-function"
#endif
#define UNUSED(x) (void)(x)
/* Number of times certain tests will run */
@@ -477,3 +482,7 @@ static int tf_run(struct tf_framework* tf) {
return status;
}
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#endif

View File

@@ -57,6 +57,17 @@ static void print_buf_plain(const unsigned char *buf, size_t len) {
# define SECP256K1_INLINE inline
# endif
# if !defined(_DEBUG) && !defined(__NO_INLINE__) && !defined(__OPTIMIZE_SIZE__)
# if defined(__OPTIMIZE__) && (SECP256K1_GNUC_PREREQ(3, 0) || defined(__clang__))
# define SECP256K1_FORCE_INLINE SECP256K1_INLINE __attribute__((always_inline))
# elif defined(_MSC_VER)
# define SECP256K1_FORCE_INLINE __forceinline
# endif
# endif
# ifndef SECP256K1_FORCE_INLINE
# define SECP256K1_FORCE_INLINE SECP256K1_INLINE
# endif
/** Assert statically that expr is true.
*
* This is a statement-like macro and can only be used inside functions.