Merge commits '88e80722 ff8edf89 f29a3270 a7a7bfaf a01a7d86 b1579cf5 ad7433b1 233822d8 5fbff5d3 2b77240b 1bff2005 e1817a6f 5596ec5c 8ebe5c52 1cca7c17 1b21aa51 cbd25559 09b1d466 57573187 8962fc95 9d1b458d eb8749fc 6048e6c0 ' into temp-merge-1222

This commit is contained in:
Jonas Nick 2023-07-20 16:29:21 +00:00
commit 0d540ec942
No known key found for this signature in database
GPG Key ID: 4861DBF262123605
64 changed files with 1691 additions and 821 deletions

View File

@ -1,4 +1,6 @@
env: env:
### cirrus config
CIRRUS_CLONE_DEPTH: 1
### compiler options ### compiler options
HOST: HOST:
WRAPPER_CMD: WRAPPER_CMD:
@ -29,7 +31,7 @@ env:
SECP256K1_TEST_ITERS: SECP256K1_TEST_ITERS:
BENCH: yes BENCH: yes
SECP256K1_BENCH_ITERS: 2 SECP256K1_BENCH_ITERS: 2
CTIMETEST: yes CTIMETESTS: yes
# Compile and run the tests # Compile and run the tests
EXAMPLES: yes EXAMPLES: yes
@ -46,8 +48,8 @@ cat_logs_snippet: &CAT_LOGS
- cat noverify_tests.log || true - cat noverify_tests.log || true
cat_exhaustive_tests_log_script: cat_exhaustive_tests_log_script:
- cat exhaustive_tests.log || true - cat exhaustive_tests.log || true
cat_valgrind_ctime_test_log_script: cat_ctime_tests_log_script:
- cat valgrind_ctime_test.log || true - cat ctime_tests.log || true
cat_bench_log_script: cat_bench_log_script:
- cat bench.log || true - cat bench.log || true
cat_config_log_script: cat_config_log_script:
@ -60,10 +62,8 @@ cat_logs_snippet: &CAT_LOGS
merge_base_script_snippet: &MERGE_BASE merge_base_script_snippet: &MERGE_BASE
merge_base_script: merge_base_script:
- if [ "$CIRRUS_PR" = "" ]; then exit 0; fi - if [ "$CIRRUS_PR" = "" ]; then exit 0; fi
- git fetch $CIRRUS_REPO_CLONE_URL $CIRRUS_BASE_BRANCH - git fetch --depth=1 $CIRRUS_REPO_CLONE_URL "pull/${CIRRUS_PR}/merge"
- git config --global user.email "ci@ci.ci" - git checkout FETCH_HEAD # Use merged changes to detect silent merge conflicts
- git config --global user.name "ci"
- git merge FETCH_HEAD # Merge base to detect silent merge conflicts
linux_container_snippet: &LINUX_CONTAINER linux_container_snippet: &LINUX_CONTAINER
container: container:
@ -87,9 +87,10 @@ task:
- env: {WIDEMUL: int128, ECDH: yes, SCHNORRSIG: yes, EXPERIMENTAL: yes, ECDSA_S2C: yes, RANGEPROOF: yes, WHITELIST: yes, GENERATOR: yes, MUSIG: yes, ECDSAADAPTOR: yes, BPPP: yes} - env: {WIDEMUL: int128, ECDH: yes, SCHNORRSIG: yes, EXPERIMENTAL: yes, ECDSA_S2C: yes, RANGEPROOF: yes, WHITELIST: yes, GENERATOR: yes, MUSIG: yes, ECDSAADAPTOR: yes, BPPP: yes}
- env: {WIDEMUL: int128, ASM: x86_64} - env: {WIDEMUL: int128, ASM: x86_64}
- env: { RECOVERY: yes, SCHNORRSIG: yes, EXPERIMENTAL: yes, ECDSA_S2C: yes, RANGEPROOF: yes, WHITELIST: yes, GENERATOR: yes, MUSIG: yes, ECDSAADAPTOR: yes, BPPP: yes} - env: { RECOVERY: yes, SCHNORRSIG: yes, EXPERIMENTAL: yes, ECDSA_S2C: yes, RANGEPROOF: yes, WHITELIST: yes, GENERATOR: yes, MUSIG: yes, ECDSAADAPTOR: yes, BPPP: yes}
- env: {BUILD: distcheck, WITH_VALGRIND: no, CTIMETEST: no, BENCH: no} - env: {CTIMETESTS: no, RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, EXPERIMENTAL: yes, ECDSA_S2C: yes, RANGEPROOF: yes, WHITELIST: yes, GENERATOR: yes, MUSIG: yes, ECDSAADAPTOR: yes, BPPP: yes, CPPFLAGS: -DVERIFY}
- env: {BUILD: distcheck, WITH_VALGRIND: no, CTIMETESTS: no, BENCH: no}
- env: {CPPFLAGS: -DDETERMINISTIC} - env: {CPPFLAGS: -DDETERMINISTIC}
- env: {CFLAGS: -O0, CTIMETEST: no} - env: {CFLAGS: -O0, CTIMETESTS: no}
- env: { ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } - env: { ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 }
- env: { ECMULTGENPRECISION: 8, ECMULTWINDOW: 4 } - env: { ECMULTGENPRECISION: 8, ECMULTWINDOW: 4 }
matrix: matrix:
@ -144,7 +145,7 @@ task:
env: env:
ASM: no ASM: no
WITH_VALGRIND: no WITH_VALGRIND: no
CTIMETEST: no CTIMETESTS: no
matrix: matrix:
- env: - env:
CC: gcc CC: gcc
@ -177,7 +178,7 @@ task:
MUSIG: yes MUSIG: yes
ECDSAADAPTOR: yes ECDSAADAPTOR: yes
BPPP: yes BPPP: yes
CTIMETEST: no CTIMETESTS: no
<< : *MERGE_BASE << : *MERGE_BASE
test_script: test_script:
# https://sourceware.org/bugzilla/show_bug.cgi?id=27008 # https://sourceware.org/bugzilla/show_bug.cgi?id=27008
@ -196,7 +197,7 @@ task:
ECDH: yes ECDH: yes
RECOVERY: yes RECOVERY: yes
SCHNORRSIG: yes SCHNORRSIG: yes
CTIMETEST: no CTIMETESTS: no
matrix: matrix:
- env: {} - env: {}
- env: {EXPERIMENTAL: yes, ASM: arm} - env: {EXPERIMENTAL: yes, ASM: arm}
@ -216,7 +217,7 @@ task:
ECDH: yes ECDH: yes
RECOVERY: yes RECOVERY: yes
SCHNORRSIG: yes SCHNORRSIG: yes
CTIMETEST: no CTIMETESTS: no
<< : *MERGE_BASE << : *MERGE_BASE
test_script: test_script:
- ./ci/cirrus.sh - ./ci/cirrus.sh
@ -233,7 +234,7 @@ task:
ECDH: yes ECDH: yes
RECOVERY: yes RECOVERY: yes
SCHNORRSIG: yes SCHNORRSIG: yes
CTIMETEST: no CTIMETESTS: no
<< : *MERGE_BASE << : *MERGE_BASE
test_script: test_script:
- ./ci/cirrus.sh - ./ci/cirrus.sh
@ -247,7 +248,7 @@ task:
ECDH: yes ECDH: yes
RECOVERY: yes RECOVERY: yes
SCHNORRSIG: yes SCHNORRSIG: yes
CTIMETEST: no CTIMETESTS: no
matrix: matrix:
- name: "x86_64 (mingw32-w64): Windows (Debian stable, Wine)" - name: "x86_64 (mingw32-w64): Windows (Debian stable, Wine)"
env: env:
@ -277,7 +278,7 @@ task:
MUSIG: yes MUSIG: yes
ECDSAADAPTOR: yes ECDSAADAPTOR: yes
BPPP: yes BPPP: yes
CTIMETEST: no CTIMETESTS: no
# Use a MinGW-w64 host to tell ./configure we're building for Windows. # Use a MinGW-w64 host to tell ./configure we're building for Windows.
# This will detect some MinGW-w64 tools but then make will need only # This will detect some MinGW-w64 tools but then make will need only
# the MSVC tools CC, AR and NM as specified below. # the MSVC tools CC, AR and NM as specified below.
@ -288,7 +289,7 @@ task:
# Set non-essential options that affect the CLI messages here. # Set non-essential options that affect the CLI messages here.
# (They depend on the user's taste, so we don't want to set them automatically in configure.ac.) # (They depend on the user's taste, so we don't want to set them automatically in configure.ac.)
CFLAGS: -nologo -diagnostics:caret CFLAGS: -nologo -diagnostics:caret
LDFLAGS: -XCClinker -nologo -XCClinker -diagnostics:caret LDFLAGS: -Xlinker -Xlinker -Xlinker -nologo
matrix: matrix:
- name: "x86_64 (MSVC): Windows (Debian stable, Wine)" - name: "x86_64 (MSVC): Windows (Debian stable, Wine)"
- name: "x86_64 (MSVC): Windows (Debian stable, Wine, int128_struct)" - name: "x86_64 (MSVC): Windows (Debian stable, Wine, int128_struct)"
@ -325,7 +326,7 @@ task:
MUSIG: yes MUSIG: yes
ECDSAADAPTOR: yes ECDSAADAPTOR: yes
BPPP: yes BPPP: yes
CTIMETEST: no CTIMETESTS: no
matrix: matrix:
- name: "Valgrind (memcheck)" - name: "Valgrind (memcheck)"
container: container:
@ -378,10 +379,11 @@ task:
MUSIG: yes MUSIG: yes
ECDSAADAPTOR: yes ECDSAADAPTOR: yes
BPPP: yes BPPP: yes
CTIMETEST: no CTIMETESTS: yes
CC: clang CC: clang
SECP256K1_TEST_ITERS: 32 SECP256K1_TEST_ITERS: 32
ASM: no ASM: no
WITH_VALGRIND: no
container: container:
memory: 2G memory: 2G
matrix: matrix:

3
.gitignore vendored
View File

@ -5,12 +5,13 @@ bench_generator
bench_rangeproof bench_rangeproof
bench_internal bench_internal
bench_whitelist bench_whitelist
noverify_tests
tests tests
example_musig example_musig
exhaustive_tests exhaustive_tests
precompute_ecmult_gen precompute_ecmult_gen
precompute_ecmult precompute_ecmult
valgrind_ctime_test ctime_tests
ecdh_example ecdh_example
ecdsa_example ecdsa_example
schnorr_example schnorr_example

View File

@ -10,6 +10,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
#### Added
- Usage examples: Added a recommended method for securely clearing sensitive data, e.g., secret keys, from memory.
- Tests: Added a new test binary `noverify_tests`. This binary runs the tests without some additional checks present in the ordinary `tests` binary and is thereby closer to production binaries. The `noverify_tests` binary is automatically run as part of the `make check` target.
#### Fixed
- Fixed declarations of API variables for MSVC (`__declspec(dllimport)`). This fixes MSVC builds of programs which link against a libsecp256k1 DLL dynamically and use API variables (and not only API functions). Unfortunately, the MSVC linker now will emit warning `LNK4217` when trying to link against libsecp256k1 statically. Pass `/ignore:4217` to the linker to suppress this warning.
#### Changed
- Forbade cloning or destroying `secp256k1_context_static`. Create a new context instead of cloning the static context. (If this change breaks your code, your code is probably wrong.)
- Forbade randomizing (copies of) `secp256k1_context_static`. Randomizing a copy of `secp256k1_context_static` did not have any effect and did not provide defense-in-depth protection against side-channel attacks. Create a new context if you want to benefit from randomization.
#### Removed
- Removed the configuration header `src/libsecp256k1-config.h`. We recommend passing flags to `./configure` to set configuration options (see `./configure --help`). If you cannot or do not want to use `./configure`, pass configuration flags such as `-DSECP256K1_ENABLE_MODULE_SCHNORRSIG` manually to the compiler (see the file `configure.ac` for supported flags).
## [0.2.0] - 2022-12-12 ## [0.2.0] - 2022-12-12
#### Added #### Added

View File

@ -49,6 +49,7 @@ noinst_HEADERS += src/modinv64_impl.h
noinst_HEADERS += src/precomputed_ecmult.h noinst_HEADERS += src/precomputed_ecmult.h
noinst_HEADERS += src/precomputed_ecmult_gen.h noinst_HEADERS += src/precomputed_ecmult_gen.h
noinst_HEADERS += src/assumptions.h noinst_HEADERS += src/assumptions.h
noinst_HEADERS += src/checkmem.h
noinst_HEADERS += src/util.h noinst_HEADERS += src/util.h
noinst_HEADERS += src/int128.h noinst_HEADERS += src/int128.h
noinst_HEADERS += src/int128_impl.h noinst_HEADERS += src/int128_impl.h
@ -70,12 +71,14 @@ noinst_HEADERS += contrib/lax_der_parsing.h
noinst_HEADERS += contrib/lax_der_parsing.c noinst_HEADERS += contrib/lax_der_parsing.c
noinst_HEADERS += contrib/lax_der_privatekey_parsing.h noinst_HEADERS += contrib/lax_der_privatekey_parsing.h
noinst_HEADERS += contrib/lax_der_privatekey_parsing.c noinst_HEADERS += contrib/lax_der_privatekey_parsing.c
noinst_HEADERS += examples/random.h noinst_HEADERS += examples/examples_util.h
PRECOMPUTED_LIB = libsecp256k1_precomputed.la PRECOMPUTED_LIB = libsecp256k1_precomputed.la
noinst_LTLIBRARIES = $(PRECOMPUTED_LIB) noinst_LTLIBRARIES = $(PRECOMPUTED_LIB)
libsecp256k1_precomputed_la_SOURCES = src/precomputed_ecmult.c src/precomputed_ecmult_gen.c libsecp256k1_precomputed_la_SOURCES = src/precomputed_ecmult.c src/precomputed_ecmult_gen.c
libsecp256k1_precomputed_la_CPPFLAGS = $(SECP_INCLUDES) $(SECP_CONFIG_DEFINES) # We need `-I$(top_srcdir)/src` in VPATH builds if libsecp256k1_precomputed_la_SOURCES have been recreated in the build tree.
# This helps users and packagers who insist on recreating the precomputed files (e.g., Gentoo).
libsecp256k1_precomputed_la_CPPFLAGS = -I$(top_srcdir)/src $(SECP_CONFIG_DEFINES)
if USE_EXTERNAL_ASM if USE_EXTERNAL_ASM
COMMON_LIB = libsecp256k1_common.la COMMON_LIB = libsecp256k1_common.la
@ -94,26 +97,22 @@ endif
endif endif
libsecp256k1_la_SOURCES = src/secp256k1.c libsecp256k1_la_SOURCES = src/secp256k1.c
libsecp256k1_la_CPPFLAGS = $(SECP_INCLUDES) $(SECP_CONFIG_DEFINES) libsecp256k1_la_CPPFLAGS = $(SECP_CONFIG_DEFINES)
libsecp256k1_la_LIBADD = $(SECP_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB) libsecp256k1_la_LIBADD = $(COMMON_LIB) $(PRECOMPUTED_LIB)
libsecp256k1_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_CURRENT):$(LIB_VERSION_REVISION):$(LIB_VERSION_AGE) libsecp256k1_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_CURRENT):$(LIB_VERSION_REVISION):$(LIB_VERSION_AGE)
if VALGRIND_ENABLED
libsecp256k1_la_CPPFLAGS += -DVALGRIND
endif
noinst_PROGRAMS = noinst_PROGRAMS =
if USE_BENCHMARK if USE_BENCHMARK
noinst_PROGRAMS += bench bench_internal bench_ecmult noinst_PROGRAMS += bench bench_internal bench_ecmult
bench_SOURCES = src/bench.c bench_SOURCES = src/bench.c
bench_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) bench_LDADD = libsecp256k1.la
bench_CPPFLAGS = $(SECP_CONFIG_DEFINES) bench_CPPFLAGS = $(SECP_CONFIG_DEFINES)
bench_internal_SOURCES = src/bench_internal.c bench_internal_SOURCES = src/bench_internal.c
bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB) bench_internal_LDADD = $(COMMON_LIB) $(PRECOMPUTED_LIB)
bench_internal_CPPFLAGS = $(SECP_INCLUDES) $(SECP_CONFIG_DEFINES) bench_internal_CPPFLAGS = $(SECP_CONFIG_DEFINES)
bench_ecmult_SOURCES = src/bench_ecmult.c bench_ecmult_SOURCES = src/bench_ecmult.c
bench_ecmult_LDADD = $(SECP_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB) bench_ecmult_LDADD = $(COMMON_LIB) $(PRECOMPUTED_LIB)
bench_ecmult_CPPFLAGS = $(SECP_INCLUDES) $(SECP_CONFIG_DEFINES) bench_ecmult_CPPFLAGS = $(SECP_CONFIG_DEFINES)
endif endif
TESTS = TESTS =
@ -121,15 +120,9 @@ if USE_TESTS
TESTS += noverify_tests TESTS += noverify_tests
noinst_PROGRAMS += noverify_tests noinst_PROGRAMS += noverify_tests
noverify_tests_SOURCES = src/tests.c noverify_tests_SOURCES = src/tests.c
noverify_tests_CPPFLAGS = $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) $(SECP_CONFIG_DEFINES) noverify_tests_CPPFLAGS = $(SECP_CONFIG_DEFINES)
noverify_tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB) noverify_tests_LDADD = $(COMMON_LIB) $(PRECOMPUTED_LIB)
noverify_tests_LDFLAGS = -static noverify_tests_LDFLAGS = -static
if VALGRIND_ENABLED
noverify_tests_CPPFLAGS += -DVALGRIND
noinst_PROGRAMS += valgrind_ctime_test
valgrind_ctime_test_SOURCES = src/valgrind_ctime_test.c
valgrind_ctime_test_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB)
endif
if !ENABLE_COVERAGE if !ENABLE_COVERAGE
TESTS += tests TESTS += tests
noinst_PROGRAMS += tests noinst_PROGRAMS += tests
@ -140,15 +133,22 @@ tests_LDFLAGS = $(noverify_tests_LDFLAGS)
endif endif
endif endif
if USE_CTIME_TESTS
noinst_PROGRAMS += ctime_tests
ctime_tests_SOURCES = src/ctime_tests.c
ctime_tests_LDADD = libsecp256k1.la
ctime_tests_CPPFLAGS = $(SECP_CONFIG_DEFINES)
endif
if USE_EXHAUSTIVE_TESTS if USE_EXHAUSTIVE_TESTS
noinst_PROGRAMS += exhaustive_tests noinst_PROGRAMS += exhaustive_tests
exhaustive_tests_SOURCES = src/tests_exhaustive.c exhaustive_tests_SOURCES = src/tests_exhaustive.c
exhaustive_tests_CPPFLAGS = $(SECP_INCLUDES) $(SECP_CONFIG_DEFINES) exhaustive_tests_CPPFLAGS = $(SECP_CONFIG_DEFINES)
if !ENABLE_COVERAGE if !ENABLE_COVERAGE
exhaustive_tests_CPPFLAGS += -DVERIFY exhaustive_tests_CPPFLAGS += -DVERIFY
endif endif
# Note: do not include $(PRECOMPUTED_LIB) in exhaustive_tests (it uses runtime-generated tables). # Note: do not include $(PRECOMPUTED_LIB) in exhaustive_tests (it uses runtime-generated tables).
exhaustive_tests_LDADD = $(SECP_LIBS) $(COMMON_LIB) exhaustive_tests_LDADD = $(COMMON_LIB)
exhaustive_tests_LDFLAGS = -static exhaustive_tests_LDFLAGS = -static
TESTS += exhaustive_tests TESTS += exhaustive_tests
endif endif
@ -203,12 +203,12 @@ EXTRA_PROGRAMS = precompute_ecmult precompute_ecmult_gen
CLEANFILES = $(EXTRA_PROGRAMS) CLEANFILES = $(EXTRA_PROGRAMS)
precompute_ecmult_SOURCES = src/precompute_ecmult.c precompute_ecmult_SOURCES = src/precompute_ecmult.c
precompute_ecmult_CPPFLAGS = $(SECP_INCLUDES) $(SECP_CONFIG_DEFINES) precompute_ecmult_CPPFLAGS = $(SECP_CONFIG_DEFINES)
precompute_ecmult_LDADD = $(SECP_LIBS) $(COMMON_LIB) precompute_ecmult_LDADD = $(COMMON_LIB)
precompute_ecmult_gen_SOURCES = src/precompute_ecmult_gen.c precompute_ecmult_gen_SOURCES = src/precompute_ecmult_gen.c
precompute_ecmult_gen_CPPFLAGS = $(SECP_INCLUDES) $(SECP_CONFIG_DEFINES) precompute_ecmult_gen_CPPFLAGS = $(SECP_CONFIG_DEFINES)
precompute_ecmult_gen_LDADD = $(SECP_LIBS) $(COMMON_LIB) precompute_ecmult_gen_LDADD = $(COMMON_LIB)
# See Automake manual, Section "Errors with distclean". # See Automake manual, Section "Errors with distclean".
# We don't list any dependencies for the prebuilt files here because # We don't list any dependencies for the prebuilt files here because

View File

@ -14,7 +14,7 @@ print_environment() {
ECMULTWINDOW ECMULTGENPRECISION ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \ ECMULTWINDOW ECMULTGENPRECISION ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \
EXPERIMENTAL ECDH RECOVERY SCHNORRSIG \ EXPERIMENTAL ECDH RECOVERY SCHNORRSIG \
ECDSA_S2C GENERATOR RANGEPROOF WHITELIST MUSIG ECDSAADAPTOR BPPP \ ECDSA_S2C GENERATOR RANGEPROOF WHITELIST MUSIG ECDSAADAPTOR BPPP \
SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETEST\ SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETESTS\
EXAMPLES \ EXAMPLES \
HOST WRAPPER_CMD \ HOST WRAPPER_CMD \
CC CFLAGS CPPFLAGS AR NM CC CFLAGS CPPFLAGS AR NM
@ -35,6 +35,8 @@ print_environment
# This speeds up jobs with many invocations of wine (e.g., ./configure with MSVC) tremendously. # This speeds up jobs with many invocations of wine (e.g., ./configure with MSVC) tremendously.
case "$WRAPPER_CMD" in case "$WRAPPER_CMD" in
*wine*) *wine*)
# Make sure to shutdown wineserver whenever we exit.
trap "wineserver -k || true" EXIT INT HUP
# This is apparently only reliable when we run a dummy command such as "hh.exe" afterwards. # This is apparently only reliable when we run a dummy command such as "hh.exe" afterwards.
wineserver -p && wine hh.exe wineserver -p && wine hh.exe
;; ;;
@ -67,6 +69,7 @@ fi
--enable-module-schnorrsig="$SCHNORRSIG" --enable-module-musig="$MUSIG" --enable-module-ecdsa-adaptor="$ECDSAADAPTOR" \ --enable-module-schnorrsig="$SCHNORRSIG" --enable-module-musig="$MUSIG" --enable-module-ecdsa-adaptor="$ECDSAADAPTOR" \
--enable-module-schnorrsig="$SCHNORRSIG" \ --enable-module-schnorrsig="$SCHNORRSIG" \
--enable-examples="$EXAMPLES" \ --enable-examples="$EXAMPLES" \
--enable-ctime-tests="$CTIMETESTS" \
--with-valgrind="$WITH_VALGRIND" \ --with-valgrind="$WITH_VALGRIND" \
--host="$HOST" $EXTRAFLAGS --host="$HOST" $EXTRAFLAGS
@ -83,14 +86,15 @@ export LOG_COMPILER="$WRAPPER_CMD"
make "$BUILD" make "$BUILD"
# Using the local `libtool` because on macOS the system's libtool has nothing to do with GNU libtool
EXEC='./libtool --mode=execute'
if [ -n "$WRAPPER_CMD" ]
then
EXEC="$EXEC $WRAPPER_CMD"
fi
if [ "$BENCH" = "yes" ] if [ "$BENCH" = "yes" ]
then then
# Using the local `libtool` because on macOS the system's libtool has nothing to do with GNU libtool
EXEC='./libtool --mode=execute'
if [ -n "$WRAPPER_CMD" ]
then
EXEC="$EXEC $WRAPPER_CMD"
fi
{ {
$EXEC ./bench_ecmult $EXEC ./bench_ecmult
$EXEC ./bench_internal $EXEC ./bench_internal
@ -102,9 +106,13 @@ then
} >> bench.log 2>&1 } >> bench.log 2>&1
fi fi
if [ "$CTIMETEST" = "yes" ] if [ "$CTIMETESTS" = "yes" ]
then then
./libtool --mode=execute valgrind --error-exitcode=42 ./valgrind_ctime_test > valgrind_ctime_test.log 2>&1 if [ "$WITH_VALGRIND" = "yes" ]; then
./libtool --mode=execute valgrind --error-exitcode=42 ./ctime_tests > ctime_tests.log 2>&1
else
$EXEC ./ctime_tests > ctime_tests.log 2>&1
fi
fi fi
# Rebuild precomputed files (if not cross-compiling). # Rebuild precomputed files (if not cross-compiling).
@ -114,9 +122,6 @@ then
make precomp make precomp
fi fi
# Shutdown wineserver again
wineserver -k || true
# Check that no repo files have been modified by the build. # Check that no repo files have been modified by the build.
# (This fails for example if the precomp files need to be updated in the repo.) # (This fails for example if the precomp files need to be updated in the repo.)
git diff --exit-code git diff --exit-code

View File

@ -22,9 +22,6 @@ AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG
AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([build-aux/m4]) AC_CONFIG_MACRO_DIR([build-aux/m4])
AC_CANONICAL_HOST AC_CANONICAL_HOST
AH_TOP([#ifndef LIBSECP256K1_CONFIG_H])
AH_TOP([#define LIBSECP256K1_CONFIG_H])
AH_BOTTOM([#endif /*LIBSECP256K1_CONFIG_H*/])
# Require Automake 1.11.2 for AM_PROG_AR # Require Automake 1.11.2 for AM_PROG_AR
AM_INIT_AUTOMAKE([1.11.2 foreign subdir-objects]) AM_INIT_AUTOMAKE([1.11.2 foreign subdir-objects])
@ -105,6 +102,7 @@ AC_DEFUN([SECP_TRY_APPEND_DEFAULT_CFLAGS], [
SECP_TRY_APPEND_CFLAGS([-Wcast-align], $1) # GCC >= 2.95 SECP_TRY_APPEND_CFLAGS([-Wcast-align], $1) # GCC >= 2.95
SECP_TRY_APPEND_CFLAGS([-Wcast-align=strict], $1) # GCC >= 8.0 SECP_TRY_APPEND_CFLAGS([-Wcast-align=strict], $1) # GCC >= 8.0
SECP_TRY_APPEND_CFLAGS([-Wconditional-uninitialized], $1) # Clang >= 3.0 only SECP_TRY_APPEND_CFLAGS([-Wconditional-uninitialized], $1) # Clang >= 3.0 only
SECP_TRY_APPEND_CFLAGS([-Wreserved-identifier], $1) # Clang >= 13.0 only
SECP_TRY_APPEND_CFLAGS([-fvisibility=hidden], $1) # GCC >= 4.0 SECP_TRY_APPEND_CFLAGS([-fvisibility=hidden], $1) # GCC >= 4.0
CFLAGS="$SECP_TRY_APPEND_DEFAULT_CFLAGS_saved_CFLAGS" CFLAGS="$SECP_TRY_APPEND_DEFAULT_CFLAGS_saved_CFLAGS"
@ -117,6 +115,12 @@ AC_DEFUN([SECP_TRY_APPEND_DEFAULT_CFLAGS], [
if test x"$GCC" != x"yes" && test x"$build_windows" = x"yes"; then if test x"$GCC" != x"yes" && test x"$build_windows" = x"yes"; then
SECP_TRY_APPEND_CFLAGS([-W2 -wd4146], $1) # Moderate warning level, disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned" SECP_TRY_APPEND_CFLAGS([-W2 -wd4146], $1) # Moderate warning level, disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned"
SECP_TRY_APPEND_CFLAGS([-external:anglebrackets -external:W0], $1) # Suppress warnings from #include <...> files SECP_TRY_APPEND_CFLAGS([-external:anglebrackets -external:W0], $1) # Suppress warnings from #include <...> files
# We pass -ignore:4217 to the MSVC linker to suppress warning 4217 when
# importing variables from a statically linked secp256k1.
# (See the libtool manual, section "Windows DLLs" for background.)
# Unfortunately, libtool tries to be too clever and strips "-Xlinker arg"
# into "arg", so this will be " -Xlinker -ignore:4217" after stripping.
LDFLAGS="-Xlinker -Xlinker -Xlinker -ignore:4217 $LDFLAGS"
fi fi
]) ])
SECP_TRY_APPEND_DEFAULT_CFLAGS(SECP_CFLAGS) SECP_TRY_APPEND_DEFAULT_CFLAGS(SECP_CFLAGS)
@ -142,6 +146,10 @@ AC_ARG_ENABLE(tests,
AS_HELP_STRING([--enable-tests],[compile tests [default=yes]]), [], AS_HELP_STRING([--enable-tests],[compile tests [default=yes]]), [],
[SECP_SET_DEFAULT([enable_tests], [yes], [yes])]) [SECP_SET_DEFAULT([enable_tests], [yes], [yes])])
AC_ARG_ENABLE(ctime_tests,
AS_HELP_STRING([--enable-ctime-tests],[compile constant-time tests [default=yes if valgrind enabled]]), [],
[SECP_SET_DEFAULT([enable_ctime_tests], [auto], [auto])])
AC_ARG_ENABLE(experimental, AC_ARG_ENABLE(experimental,
AS_HELP_STRING([--enable-experimental],[allow experimental configure options [default=no]]), [], AS_HELP_STRING([--enable-experimental],[allow experimental configure options [default=no]]), [],
[SECP_SET_DEFAULT([enable_experimental], [no], [yes])]) [SECP_SET_DEFAULT([enable_experimental], [no], [yes])])
@ -270,7 +278,10 @@ else
enable_valgrind=yes enable_valgrind=yes
fi fi
fi fi
AM_CONDITIONAL([VALGRIND_ENABLED],[test "$enable_valgrind" = "yes"])
if test x"$enable_ctime_tests" = x"auto"; then
enable_ctime_tests=$enable_valgrind
fi
if test x"$enable_coverage" = x"yes"; then if test x"$enable_coverage" = x"yes"; then
SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DCOVERAGE=1" SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DCOVERAGE=1"
@ -401,7 +412,7 @@ case $set_ecmult_gen_precision in
esac esac
if test x"$enable_valgrind" = x"yes"; then if test x"$enable_valgrind" = x"yes"; then
SECP_INCLUDES="$SECP_INCLUDES $VALGRIND_CPPFLAGS" SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES $VALGRIND_CPPFLAGS -DVALGRIND"
fi fi
# Add -Werror and similar flags passed from the outside (for testing, e.g., in CI). # Add -Werror and similar flags passed from the outside (for testing, e.g., in CI).
@ -527,14 +538,11 @@ fi
### ###
AC_CONFIG_FILES([Makefile libsecp256k1.pc]) AC_CONFIG_FILES([Makefile libsecp256k1.pc])
AC_SUBST(SECP_INCLUDES)
AC_SUBST(SECP_LIBS)
AC_SUBST(SECP_TEST_LIBS)
AC_SUBST(SECP_TEST_INCLUDES)
AC_SUBST(SECP_CFLAGS) AC_SUBST(SECP_CFLAGS)
AC_SUBST(SECP_CONFIG_DEFINES) AC_SUBST(SECP_CONFIG_DEFINES)
AM_CONDITIONAL([ENABLE_COVERAGE], [test x"$enable_coverage" = x"yes"]) AM_CONDITIONAL([ENABLE_COVERAGE], [test x"$enable_coverage" = x"yes"])
AM_CONDITIONAL([USE_TESTS], [test x"$enable_tests" != x"no"]) AM_CONDITIONAL([USE_TESTS], [test x"$enable_tests" != x"no"])
AM_CONDITIONAL([USE_CTIME_TESTS], [test x"$enable_ctime_tests" = x"yes"])
AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$enable_exhaustive_tests" != x"no"]) AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$enable_exhaustive_tests" != x"no"])
AM_CONDITIONAL([USE_EXAMPLES], [test x"$enable_examples" != x"no"]) AM_CONDITIONAL([USE_EXAMPLES], [test x"$enable_examples" != x"no"])
AM_CONDITIONAL([USE_BENCHMARK], [test x"$enable_benchmark" = x"yes"]) AM_CONDITIONAL([USE_BENCHMARK], [test x"$enable_benchmark" = x"yes"])
@ -565,6 +573,7 @@ echo "Build Options:"
echo " with external callbacks = $enable_external_default_callbacks" echo " with external callbacks = $enable_external_default_callbacks"
echo " with benchmarks = $enable_benchmark" echo " with benchmarks = $enable_benchmark"
echo " with tests = $enable_tests" echo " with tests = $enable_tests"
echo " with ctime tests = $enable_ctime_tests"
echo " with coverage = $enable_coverage" echo " with coverage = $enable_coverage"
echo " with examples = $enable_examples" echo " with examples = $enable_examples"
echo " module ecdh = $enable_module_ecdh" echo " module ecdh = $enable_module_ecdh"

View File

@ -1,7 +1,7 @@
# The safegcd implementation in libsecp256k1 explained # The safegcd implementation in libsecp256k1 explained
This document explains the modular inverse implementation in the `src/modinv*.h` files. It is based This document explains the modular inverse and Jacobi symbol implementations in the `src/modinv*.h` files.
on the paper It is based on the paper
["Fast constant-time gcd computation and modular inversion"](https://gcd.cr.yp.to/papers.html#safegcd) ["Fast constant-time gcd computation and modular inversion"](https://gcd.cr.yp.to/papers.html#safegcd)
by Daniel J. Bernstein and Bo-Yin Yang. The references below are for the Date: 2019.04.13 version. by Daniel J. Bernstein and Bo-Yin Yang. The references below are for the Date: 2019.04.13 version.
@ -410,7 +410,7 @@ sufficient even. Given that every loop iteration performs *N* divsteps, it will
To deal with the branches in `divsteps_n_matrix` we will replace them with constant-time bitwise To deal with the branches in `divsteps_n_matrix` we will replace them with constant-time bitwise
operations (and hope the C compiler isn't smart enough to turn them back into branches; see operations (and hope the C compiler isn't smart enough to turn them back into branches; see
`valgrind_ctime_test.c` for automated tests that this isn't the case). To do so, observe that a `ctime_tests.c` for automated tests that this isn't the case). To do so, observe that a
divstep can be written instead as (compare to the inner loop of `gcd` in section 1). divstep can be written instead as (compare to the inner loop of `gcd` in section 1).
```python ```python
@ -769,3 +769,51 @@ def modinv_var(M, Mi, x):
d, e = update_de(d, e, t, M, Mi) d, e = update_de(d, e, t, M, Mi)
return normalize(f, d, Mi) return normalize(f, d, Mi)
``` ```
## 8. From GCDs to Jacobi symbol
We can also use a similar approach to calculate Jacobi symbol *(x | M)* by keeping track of an
extra variable *j*, for which at every step *(x | M) = j (g | f)*. As we update *f* and *g*, we
make corresponding updates to *j* using
[properties of the Jacobi symbol](https://en.wikipedia.org/wiki/Jacobi_symbol#Properties):
* *((g/2) | f)* is either *(g | f)* or *-(g | f)*, depending on the value of *f mod 8* (negating if it's *3* or *5*).
* *(f | g)* is either *(g | f)* or *-(g | f)*, depending on *f mod 4* and *g mod 4* (negating if both are *3*).
These updates depend only on the values of *f* and *g* modulo *4* or *8*, and can thus be applied
very quickly, as long as we keep track of a few additional bits of *f* and *g*. Overall, this
calculation is slightly simpler than the one for the modular inverse because we no longer need to
keep track of *d* and *e*.
However, one difficulty of this approach is that the Jacobi symbol *(a | n)* is only defined for
positive odd integers *n*, whereas in the original safegcd algorithm, *f, g* can take negative
values. We resolve this by using the following modified steps:
```python
# Before
if delta > 0 and g & 1:
delta, f, g = 1 - delta, g, (g - f) // 2
# After
if delta > 0 and g & 1:
delta, f, g = 1 - delta, g, (g + f) // 2
```
The algorithm is still correct, since the changed divstep, called a "posdivstep" (see section 8.4
and E.5 in the paper) preserves *gcd(f, g)*. However, there's no proof that the modified algorithm
will converge. The justification for posdivsteps is completely empirical: in practice, it appears
that the vast majority of nonzero inputs converge to *f=g=gcd(f<sub>0</sub>, g<sub>0</sub>)* in a
number of steps proportional to their logarithm.
Note that:
- We require inputs to satisfy *gcd(x, M) = 1*, as otherwise *f=1* is not reached.
- We require inputs *x &neq; 0*, because applying posdivstep with *g=0* has no effect.
- We need to update the termination condition from *g=0* to *f=1*.
We account for the possibility of nonconvergence by only performing a bounded number of
posdivsteps, and then falling back to square-root based Jacobi calculation if a solution has not
yet been found.
The optimizations in sections 3-7 above are described in the context of the original divsteps, but
in the C implementation we also adapt most of them (not including "avoiding modulus operations",
since it's not necessary to track *d, e*, and "constant-time operation", since we never calculate
Jacobi symbols for secret data) to the posdivsteps version.

View File

@ -14,8 +14,7 @@
#include <secp256k1.h> #include <secp256k1.h>
#include <secp256k1_ecdh.h> #include <secp256k1_ecdh.h>
#include "random.h" #include "examples_util.h"
int main(void) { int main(void) {
unsigned char seckey1[32]; unsigned char seckey1[32];
@ -112,12 +111,12 @@ int main(void) {
* example through "out of bounds" array access (see Heartbleed), Or the OS * example through "out of bounds" array access (see Heartbleed), Or the OS
* swapping them to disk. Hence, we overwrite the secret key buffer with zeros. * swapping them to disk. Hence, we overwrite the secret key buffer with zeros.
* *
* TODO: Prevent these writes from being optimized out, as any good compiler * Here we are preventing these writes from being optimized out, as any good compiler
* will remove any writes that aren't used. */ * will remove any writes that aren't used. */
memset(seckey1, 0, sizeof(seckey1)); secure_erase(seckey1, sizeof(seckey1));
memset(seckey2, 0, sizeof(seckey2)); secure_erase(seckey2, sizeof(seckey2));
memset(shared_secret1, 0, sizeof(shared_secret1)); secure_erase(shared_secret1, sizeof(shared_secret1));
memset(shared_secret2, 0, sizeof(shared_secret2)); secure_erase(shared_secret2, sizeof(shared_secret2));
return 0; return 0;
} }

View File

@ -13,9 +13,7 @@
#include <secp256k1.h> #include <secp256k1.h>
#include "random.h" #include "examples_util.h"
int main(void) { int main(void) {
/* Instead of signing the message directly, we must sign a 32-byte hash. /* Instead of signing the message directly, we must sign a 32-byte hash.
@ -34,7 +32,7 @@ int main(void) {
unsigned char compressed_pubkey[33]; unsigned char compressed_pubkey[33];
unsigned char serialized_signature[64]; unsigned char serialized_signature[64];
size_t len; size_t len;
int is_signature_valid; int is_signature_valid, is_signature_valid2;
int return_val; int return_val;
secp256k1_pubkey pubkey; secp256k1_pubkey pubkey;
secp256k1_ecdsa_signature sig; secp256k1_ecdsa_signature sig;
@ -116,18 +114,26 @@ int main(void) {
printf("Signature: "); printf("Signature: ");
print_hex(serialized_signature, sizeof(serialized_signature)); print_hex(serialized_signature, sizeof(serialized_signature));
/* This will clear everything from the context and free the memory */ /* This will clear everything from the context and free the memory */
secp256k1_context_destroy(ctx); secp256k1_context_destroy(ctx);
/* Bonus example: if all we need is signature verification (and no key
generation or signing), we don't need to use a context created via
secp256k1_context_create(). We can simply use the static (i.e., global)
context secp256k1_context_static. See its description in
include/secp256k1.h for details. */
is_signature_valid2 = secp256k1_ecdsa_verify(secp256k1_context_static,
&sig, msg_hash, &pubkey);
assert(is_signature_valid2 == is_signature_valid);
/* It's best practice to try to clear secrets from memory after using them. /* It's best practice to try to clear secrets from memory after using them.
* This is done because some bugs can allow an attacker to leak memory, for * This is done because some bugs can allow an attacker to leak memory, for
* example through "out of bounds" array access (see Heartbleed), Or the OS * example through "out of bounds" array access (see Heartbleed), Or the OS
* swapping them to disk. Hence, we overwrite the secret key buffer with zeros. * swapping them to disk. Hence, we overwrite the secret key buffer with zeros.
* *
* TODO: Prevent these writes from being optimized out, as any good compiler * Here we are preventing these writes from being optimized out, as any good compiler
* will remove any writes that aren't used. */ * will remove any writes that aren't used. */
memset(seckey, 0, sizeof(seckey)); secure_erase(seckey, sizeof(seckey));
return 0; return 0;
} }

View File

@ -71,3 +71,32 @@ static void print_hex(unsigned char* data, size_t size) {
} }
printf("\n"); printf("\n");
} }
#if defined(_MSC_VER)
// For SecureZeroMemory
#include <Windows.h>
#endif
/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */
static SECP256K1_INLINE void secure_erase(void *ptr, size_t len) {
#if defined(_MSC_VER)
/* SecureZeroMemory is guaranteed not to be optimized out by MSVC. */
SecureZeroMemory(ptr, len);
#elif defined(__GNUC__)
/* We use a memory barrier that scares the compiler away from optimizing out the memset.
*
* Quoting Adam Langley <agl@google.com> in commit ad1907fe73334d6c696c8539646c21b11178f20f
* in BoringSSL (ISC License):
* As best as we can tell, this is sufficient to break any optimisations that
* might try to eliminate "superfluous" memsets.
* This method used in memzero_explicit() the Linux kernel, too. Its advantage is that it is
* pretty efficient, because the compiler can still implement the memset() efficently,
* just not remove it entirely. See "Dead Store Elimination (Still) Considered Harmful" by
* Yang et al. (USENIX Security 2017) for more background.
*/
memset(ptr, 0, len);
__asm__ __volatile__("" : : "r"(ptr) : "memory");
#else
void *(*volatile const volatile_memset)(void *, int, size_t) = memset;
volatile_memset(ptr, 0, len);
#endif
}

View File

@ -14,11 +14,13 @@
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#include <string.h>
#include <secp256k1.h> #include <secp256k1.h>
#include <secp256k1_schnorrsig.h> #include <secp256k1_schnorrsig.h>
#include <secp256k1_musig.h> #include <secp256k1_musig.h>
#include "random.h" #include "examples_util.h"
struct signer_secrets { struct signer_secrets {
secp256k1_keypair keypair; secp256k1_keypair keypair;
@ -34,7 +36,7 @@ struct signer {
/* Number of public keys involved in creating the aggregate signature */ /* Number of public keys involved in creating the aggregate signature */
#define N_SIGNERS 3 #define N_SIGNERS 3
/* Create a key pair, store it in signer_secrets->keypair and signer->pubkey */ /* Create a key pair, store it in signer_secrets->keypair and signer->pubkey */
int create_keypair(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer) { static int create_keypair(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer) {
unsigned char seckey[32]; unsigned char seckey[32];
while (1) { while (1) {
if (!fill_random(seckey, sizeof(seckey))) { if (!fill_random(seckey, sizeof(seckey))) {
@ -53,7 +55,7 @@ int create_keypair(const secp256k1_context* ctx, struct signer_secrets *signer_s
/* Tweak the pubkey corresponding to the provided keyagg cache, update the cache /* Tweak the pubkey corresponding to the provided keyagg cache, update the cache
* and return the tweaked aggregate pk. */ * and return the tweaked aggregate pk. */
int tweak(const secp256k1_context* ctx, secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *cache) { static int tweak(const secp256k1_context* ctx, secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *cache) {
secp256k1_pubkey output_pk; secp256k1_pubkey output_pk;
unsigned char plain_tweak[32] = "this could be a BIP32 tweak...."; unsigned char plain_tweak[32] = "this could be a BIP32 tweak....";
unsigned char xonly_tweak[32] = "this could be a taproot tweak.."; unsigned char xonly_tweak[32] = "this could be a taproot tweak..";
@ -91,7 +93,7 @@ int tweak(const secp256k1_context* ctx, secp256k1_xonly_pubkey *agg_pk, secp256k
} }
/* Sign a message hash with the given key pairs and store the result in sig */ /* Sign a message hash with the given key pairs and store the result in sig */
int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer, const secp256k1_musig_keyagg_cache *cache, const unsigned char *msg32, unsigned char *sig64) { static int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer, const secp256k1_musig_keyagg_cache *cache, const unsigned char *msg32, unsigned char *sig64) {
int i; int i;
const secp256k1_musig_pubnonce *pubnonces[N_SIGNERS]; const secp256k1_musig_pubnonce *pubnonces[N_SIGNERS];
const secp256k1_musig_partial_sig *partial_sigs[N_SIGNERS]; const secp256k1_musig_partial_sig *partial_sigs[N_SIGNERS];

View File

@ -15,7 +15,7 @@
#include <secp256k1_extrakeys.h> #include <secp256k1_extrakeys.h>
#include <secp256k1_schnorrsig.h> #include <secp256k1_schnorrsig.h>
#include "random.h" #include "examples_util.h"
int main(void) { int main(void) {
unsigned char msg[12] = "Hello World!"; unsigned char msg[12] = "Hello World!";
@ -26,7 +26,7 @@ int main(void) {
unsigned char auxiliary_rand[32]; unsigned char auxiliary_rand[32];
unsigned char serialized_pubkey[32]; unsigned char serialized_pubkey[32];
unsigned char signature[64]; unsigned char signature[64];
int is_signature_valid; int is_signature_valid, is_signature_valid2;
int return_val; int return_val;
secp256k1_xonly_pubkey pubkey; secp256k1_xonly_pubkey pubkey;
secp256k1_keypair keypair; secp256k1_keypair keypair;
@ -135,14 +135,22 @@ int main(void) {
/* This will clear everything from the context and free the memory */ /* This will clear everything from the context and free the memory */
secp256k1_context_destroy(ctx); secp256k1_context_destroy(ctx);
/* Bonus example: if all we need is signature verification (and no key
generation or signing), we don't need to use a context created via
secp256k1_context_create(). We can simply use the static (i.e., global)
context secp256k1_context_static. See its description in
include/secp256k1.h for details. */
is_signature_valid2 = secp256k1_schnorrsig_verify(secp256k1_context_static,
signature, msg_hash, 32, &pubkey);
assert(is_signature_valid2 == is_signature_valid);
/* It's best practice to try to clear secrets from memory after using them. /* It's best practice to try to clear secrets from memory after using them.
* This is done because some bugs can allow an attacker to leak memory, for * This is done because some bugs can allow an attacker to leak memory, for
* example through "out of bounds" array access (see Heartbleed), Or the OS * example through "out of bounds" array access (see Heartbleed), Or the OS
* swapping them to disk. Hence, we overwrite the secret key buffer with zeros. * swapping them to disk. Hence, we overwrite the secret key buffer with zeros.
* *
* TODO: Prevent these writes from being optimized out, as any good compiler * Here we are preventing these writes from being optimized out, as any good compiler
* will remove any writes that aren't used. */ * will remove any writes that aren't used. */
memset(seckey, 0, sizeof(seckey)); secure_erase(seckey, sizeof(seckey));
return 0; return 0;
} }

View File

@ -145,21 +145,28 @@ typedef int (*secp256k1_nonce_function)(
# define SECP256K1_NO_BUILD # define SECP256K1_NO_BUILD
#endif #endif
/** At secp256k1 build-time DLL_EXPORT is defined when building objects destined /* Symbol visibility. See libtool manual, section "Windows DLLs". */
* for a shared library, but not for those intended for static libraries. #if defined(_WIN32) && !defined(__GNUC__)
*/ # ifdef SECP256K1_BUILD
# ifdef DLL_EXPORT
#ifndef SECP256K1_API # define SECP256K1_API __declspec (dllexport)
# if defined(_WIN32) # define SECP256K1_API_VAR extern __declspec (dllexport)
# if defined(SECP256K1_BUILD) && defined(DLL_EXPORT)
# define SECP256K1_API __declspec(dllexport)
# else
# define SECP256K1_API
# endif # endif
# elif defined(__GNUC__) && (__GNUC__ >= 4) && defined(SECP256K1_BUILD) # elif defined _MSC_VER
# define SECP256K1_API
# define SECP256K1_API_VAR extern __declspec (dllimport)
# elif defined DLL_EXPORT
# define SECP256K1_API __declspec (dllimport)
# define SECP256K1_API_VAR extern __declspec (dllimport)
# endif
#endif
#ifndef SECP256K1_API
# if defined(__GNUC__) && (__GNUC__ >= 4) && defined(SECP256K1_BUILD)
# define SECP256K1_API __attribute__ ((visibility ("default"))) # define SECP256K1_API __attribute__ ((visibility ("default")))
# define SECP256K1_API_VAR extern __attribute__ ((visibility ("default")))
# else # else
# define SECP256K1_API # define SECP256K1_API
# define SECP256K1_API_VAR extern
# endif # endif
#endif #endif
@ -231,10 +238,10 @@ typedef int (*secp256k1_nonce_function)(
* *
* It is highly recommended to call secp256k1_selftest before using this context. * It is highly recommended to call secp256k1_selftest before using this context.
*/ */
SECP256K1_API extern const secp256k1_context *secp256k1_context_static; SECP256K1_API_VAR const secp256k1_context *secp256k1_context_static;
/** Deprecated alias for secp256k1_context_static. */ /** Deprecated alias for secp256k1_context_static. */
SECP256K1_API extern const secp256k1_context *secp256k1_context_no_precomp SECP256K1_API_VAR const secp256k1_context *secp256k1_context_no_precomp
SECP256K1_DEPRECATED("Use secp256k1_context_static instead"); SECP256K1_DEPRECATED("Use secp256k1_context_static instead");
/** Perform basic self tests (to be used in conjunction with secp256k1_context_static) /** Perform basic self tests (to be used in conjunction with secp256k1_context_static)
@ -291,8 +298,11 @@ SECP256K1_API secp256k1_context* secp256k1_context_create(
* called at most once for every call of this function. If you need to avoid dynamic * called at most once for every call of this function. If you need to avoid dynamic
* memory allocation entirely, see the functions in secp256k1_preallocated.h. * memory allocation entirely, see the functions in secp256k1_preallocated.h.
* *
* Cloning secp256k1_context_static is not possible, and should not be emulated by
* the caller (e.g., using memcpy). Create a new context instead.
*
* Returns: a newly created context object. * Returns: a newly created context object.
* Args: ctx: an existing context to copy * Args: ctx: an existing context to copy (not secp256k1_context_static)
*/ */
SECP256K1_API secp256k1_context* secp256k1_context_clone( SECP256K1_API secp256k1_context* secp256k1_context_clone(
const secp256k1_context* ctx const secp256k1_context* ctx
@ -310,6 +320,7 @@ SECP256K1_API secp256k1_context* secp256k1_context_clone(
* *
* Args: ctx: an existing context to destroy, constructed using * Args: ctx: an existing context to destroy, constructed using
* secp256k1_context_create or secp256k1_context_clone * secp256k1_context_create or secp256k1_context_clone
* (i.e., not secp256k1_context_static).
*/ */
SECP256K1_API void secp256k1_context_destroy( SECP256K1_API void secp256k1_context_destroy(
secp256k1_context* ctx secp256k1_context* ctx
@ -627,10 +638,10 @@ SECP256K1_API int secp256k1_ecdsa_signature_normalize(
* If a data pointer is passed, it is assumed to be a pointer to 32 bytes of * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
* extra entropy. * extra entropy.
*/ */
SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979; SECP256K1_API_VAR const secp256k1_nonce_function secp256k1_nonce_function_rfc6979;
/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */ /** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */
SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_default; SECP256K1_API_VAR const secp256k1_nonce_function secp256k1_nonce_function_default;
/** Create an ECDSA signature. /** Create an ECDSA signature.
* *
@ -820,10 +831,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
/** Randomizes the context to provide enhanced protection against side-channel leakage. /** Randomizes the context to provide enhanced protection against side-channel leakage.
* *
* Returns: 1: randomization successful (or called on copy of secp256k1_context_static) * Returns: 1: randomization successful
* 0: error * 0: error
* Args: ctx: pointer to a context object. * Args: ctx: pointer to a context object (not secp256k1_context_static).
* In: seed32: pointer to a 32-byte random seed (NULL resets to initial state) * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state).
* *
* While secp256k1 code is written and tested to be constant-time no matter what * While secp256k1 code is written and tested to be constant-time no matter what
* secret values are, it is possible that a compiler may output code which is not, * secret values are, it is possible that a compiler may output code which is not,
@ -838,21 +849,17 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
* functions that perform computations involving secret keys, e.g., signing and * functions that perform computations involving secret keys, e.g., signing and
* public key generation. It is possible to call this function more than once on * public key generation. It is possible to call this function more than once on
* the same context, and doing so before every few computations involving secret * the same context, and doing so before every few computations involving secret
* keys is recommended as a defense-in-depth measure. * keys is recommended as a defense-in-depth measure. Randomization of the static
* context secp256k1_context_static is not supported.
* *
* Currently, the random seed is mainly used for blinding multiplications of a * Currently, the random seed is mainly used for blinding multiplications of a
* secret scalar with the elliptic curve base point. Multiplications of this * secret scalar with the elliptic curve base point. Multiplications of this
* kind are performed by exactly those API functions which are documented to * kind are performed by exactly those API functions which are documented to
* require a context that is not the secp256k1_context_static. As a rule of thumb, * require a context that is not secp256k1_context_static. As a rule of thumb,
* these are all functions which take a secret key (or a keypair) as an input. * these are all functions which take a secret key (or a keypair) as an input.
* A notable exception to that rule is the ECDH module, which relies on a different * A notable exception to that rule is the ECDH module, which relies on a different
* kind of elliptic curve point multiplication and thus does not benefit from * kind of elliptic curve point multiplication and thus does not benefit from
* enhanced protection against side-channel leakage currently. * enhanced protection against side-channel leakage currently.
*
* It is safe to call this function on a copy of secp256k1_context_static in writable
* memory (e.g., obtained via secp256k1_context_clone). In that case, this
* function is guaranteed to return 1, but the call will have no effect because
* the static context (or a copy thereof) is not meant to be randomized.
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(
secp256k1_context* ctx, secp256k1_context* ctx,

View File

@ -27,11 +27,11 @@ typedef int (*secp256k1_ecdh_hash_function)(
/** An implementation of SHA256 hash function that applies to compressed public key. /** An implementation of SHA256 hash function that applies to compressed public key.
* Populates the output parameter with 32 bytes. */ * Populates the output parameter with 32 bytes. */
SECP256K1_API extern const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256; SECP256K1_API_VAR const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256;
/** A default ECDH hash function (currently equal to secp256k1_ecdh_hash_function_sha256). /** A default ECDH hash function (currently equal to secp256k1_ecdh_hash_function_sha256).
* Populates the output parameter with 32 bytes. */ * Populates the output parameter with 32 bytes. */
SECP256K1_API extern const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default; SECP256K1_API_VAR const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default;
/** Compute an EC Diffie-Hellman secret in constant time /** Compute an EC Diffie-Hellman secret in constant time
* *

View File

@ -88,8 +88,11 @@ SECP256K1_API size_t secp256k1_context_preallocated_clone_size(
* the lifetime of this context object, see the description of * the lifetime of this context object, see the description of
* secp256k1_context_preallocated_create for details. * secp256k1_context_preallocated_create for details.
* *
* Cloning secp256k1_context_static is not possible, and should not be emulated by
* the caller (e.g., using memcpy). Create a new context instead.
*
* Returns: a newly created context object. * Returns: a newly created context object.
* Args: ctx: an existing context to copy. * Args: ctx: an existing context to copy (not secp256k1_context_static).
* In: prealloc: a pointer to a rewritable contiguous block of memory of * In: prealloc: a pointer to a rewritable contiguous block of memory of
* size at least secp256k1_context_preallocated_size(flags) * size at least secp256k1_context_preallocated_size(flags)
* bytes, as detailed above. * bytes, as detailed above.
@ -117,7 +120,8 @@ SECP256K1_API secp256k1_context* secp256k1_context_preallocated_clone(
* *
* Args: ctx: an existing context to destroy, constructed using * Args: ctx: an existing context to destroy, constructed using
* secp256k1_context_preallocated_create or * secp256k1_context_preallocated_create or
* secp256k1_context_preallocated_clone. * secp256k1_context_preallocated_clone
* (i.e., not secp256k1_context_static).
*/ */
SECP256K1_API void secp256k1_context_preallocated_destroy( SECP256K1_API void secp256k1_context_preallocated_destroy(
secp256k1_context* ctx secp256k1_context* ctx

View File

@ -61,7 +61,7 @@ typedef int (*secp256k1_nonce_function_hardened)(
* Therefore, to create BIP-340 compliant signatures, algo must be set to * Therefore, to create BIP-340 compliant signatures, algo must be set to
* "BIP0340/nonce" and algolen to 13. * "BIP0340/nonce" and algolen to 13.
*/ */
SECP256K1_API extern const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340; SECP256K1_API_VAR const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340;
/** Data structure that contains additional arguments for schnorrsig_sign_custom. /** Data structure that contains additional arguments for schnorrsig_sign_custom.
* *

View File

@ -9,5 +9,4 @@ URL: https://github.com/bitcoin-core/secp256k1
Version: @PACKAGE_VERSION@ Version: @PACKAGE_VERSION@
Cflags: -I${includedir} Cflags: -I${includedir}
Libs: -L${libdir} -lsecp256k1 Libs: -L${libdir} -lsecp256k1
Libs.private: @SECP_LIBS@

View File

@ -1,124 +1,156 @@
load("secp256k1_params.sage") load("secp256k1_params.sage")
MAX_ORDER = 1000
# Set of (curve) orders we have encountered so far.
orders_done = set() orders_done = set()
results = {}
first = True # Map from (subgroup) orders to [b, int(gen.x), int(gen.y), gen, lambda] for those subgroups.
solutions = {}
# Iterate over curves of the form y^2 = x^3 + B.
for b in range(1, P): for b in range(1, P):
# There are only 6 curves (up to isomorphism) of the form y^2=x^3+B. Stop once we have tried all. # There are only 6 curves (up to isomorphism) of the form y^2 = x^3 + B. Stop once we have tried all.
if len(orders_done) == 6: if len(orders_done) == 6:
break break
E = EllipticCurve(F, [0, b]) E = EllipticCurve(F, [0, b])
print("Analyzing curve y^2 = x^3 + %i" % b) print("Analyzing curve y^2 = x^3 + %i" % b)
n = E.order() n = E.order()
# Skip curves with an order we've already tried # Skip curves with an order we've already tried
if n in orders_done: if n in orders_done:
print("- Isomorphic to earlier curve") print("- Isomorphic to earlier curve")
print()
continue continue
orders_done.add(n) orders_done.add(n)
# Skip curves isomorphic to the real secp256k1 # Skip curves isomorphic to the real secp256k1
if n.is_pseudoprime(): if n.is_pseudoprime():
print(" - Isomorphic to secp256k1") assert E.is_isomorphic(C)
print("- Isomorphic to secp256k1")
print()
continue continue
print("- Finding subgroups") print("- Finding prime subgroups")
# Find what prime subgroups exist # Map from group_order to a set of independent generators for that order.
for f, _ in n.factor(): curve_gens = {}
print("- Analyzing subgroup of order %i" % f)
# Skip subgroups of order >1000 for g in E.gens():
if f < 4 or f > 1000: # Find what prime subgroups of group generated by g exist.
print(" - Bad size") g_order = g.order()
for f, _ in g.order().factor():
# Skip subgroups that have bad size.
if f < 4:
print(f" - Subgroup of size {f}: too small")
continue
if f > MAX_ORDER:
print(f" - Subgroup of size {f}: too large")
continue continue
# Iterate over X coordinates until we find one that is on the curve, has order f, # Construct a generator for that subgroup.
# and for which curve isomorphism exists that maps it to X coordinate 1. gen = g * (g_order // f)
for x in range(1, P): assert(gen.order() == f)
# Skip X coordinates not on the curve, and construct the full point otherwise.
if not E.is_x_coord(x):
continue
G = E.lift_x(F(x))
print(" - Analyzing (multiples of) point with X=%i" % x) # Add to set the minimal multiple of gen.
curve_gens.setdefault(f, set()).add(min([j*gen for j in range(1, f)]))
print(f" - Subgroup of size {f}: ok")
# Skip points whose order is not a multiple of f. Project the point to have for f in sorted(curve_gens.keys()):
# order f otherwise. print(f"- Constructing group of order {f}")
if (G.order() % f): cbrts = sorted([int(c) for c in Integers(f)(1).nth_root(3, all=true) if c != 1])
print(" - Bad order") gens = list(curve_gens[f])
continue sol_count = 0
G = G * (G.order() // f) no_endo_count = 0
# Consider all non-zero linear combinations of the independent generators.
for j in range(1, f**len(gens)):
gen = sum(gens[k] * ((j // f**k) % f) for k in range(len(gens)))
assert not gen.is_zero()
assert (f*gen).is_zero()
# Find lambda for endomorphism. Skip if none can be found. # Find lambda for endomorphism. Skip if none can be found.
lam = None lam = None
for l in Integers(f)(1).nth_root(3, all=True): for l in cbrts:
if int(l)*G == E(BETA*G[0], G[1]): if l*gen == E(BETA*gen[0], gen[1]):
lam = int(l) lam = l
break break
if lam is None: if lam is None:
print(" - No endomorphism for this subgroup") no_endo_count += 1
break else:
sol_count += 1
solutions.setdefault(f, []).append((b, int(gen[0]), int(gen[1]), gen, lam))
# Now look for an isomorphism of the curve that gives this point an X print(f" - Found {sol_count} generators (plus {no_endo_count} without endomorphism)")
# coordinate equal to 1.
# If (x,y) is on y^2 = x^3 + b, then (a^2*x, a^3*y) is on y^2 = x^3 + a^6*b.
# So look for m=a^2=1/x.
m = F(1)/G[0]
if not m.is_square():
print(" - No curve isomorphism maps it to a point with X=1")
continue
a = m.sqrt()
rb = a^6*b
RE = EllipticCurve(F, [0, rb])
# Use as generator twice the image of G under the above isormorphism. print()
# This means that generator*(1/2 mod f) will have X coordinate 1.
RG = RE(1, a^3*G[1]) * 2
# And even Y coordinate.
if int(RG[1]) % 2:
RG = -RG
assert(RG.order() == f)
assert(lam*RG == RE(BETA*RG[0], RG[1]))
# We have found curve RE:y^2=x^3+rb with generator RG of order f. Remember it def output_generator(g, name):
results[f] = {"b": rb, "G": RG, "lambda": lam} print(f"#define {name} SECP256K1_GE_CONST(\\")
print(" - Found solution") print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x,\\" % tuple((int(g[0]) >> (32 * (7 - i))) & 0xffffffff for i in range(4)))
break print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x,\\" % tuple((int(g[0]) >> (32 * (7 - i))) & 0xffffffff for i in range(4, 8)))
print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x,\\" % tuple((int(g[1]) >> (32 * (7 - i))) & 0xffffffff for i in range(4)))
print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x\\" % tuple((int(g[1]) >> (32 * (7 - i))) & 0xffffffff for i in range(4, 8)))
print(")")
print("") def output_b(b):
print(f"#define SECP256K1_B {int(b)}")
print("") print()
print("") print("To be put in src/group_impl.h:")
print("/* To be put in src/group_impl.h: */") print()
print("/* Begin of section generated by sage/gen_exhaustive_groups.sage. */")
for f in sorted(solutions.keys()):
# Use as generator/2 the one with lowest b, and lowest (x, y) generator (interpreted as non-negative integers).
b, _, _, HALF_G, lam = min(solutions[f])
output_generator(2 * HALF_G, f"SECP256K1_G_ORDER_{f}")
print("/** Generator for secp256k1, value 'g' defined in")
print(" * \"Standards for Efficient Cryptography\" (SEC2) 2.7.1.")
print(" */")
output_generator(G, "SECP256K1_G")
print("/* These exhaustive group test orders and generators are chosen such that:")
print(" * - The field size is equal to that of secp256k1, so field code is the same.")
print(" * - The curve equation is of the form y^2=x^3+B for some small constant B.")
print(" * - The subgroup has a generator 2*P, where P.x is as small as possible.")
print(f" * - The subgroup has size less than {MAX_ORDER} to permit exhaustive testing.")
print(" * - The subgroup admits an endomorphism of the form lambda*(x,y) == (beta*x,y).")
print(" */")
print("#if defined(EXHAUSTIVE_TEST_ORDER)")
first = True first = True
for f in sorted(results.keys()): for f in sorted(solutions.keys()):
b = results[f]["b"] b, _, _, _, lam = min(solutions[f])
G = results[f]["G"] print(f"# {'if' if first else 'elif'} EXHAUSTIVE_TEST_ORDER == {f}")
print("# %s EXHAUSTIVE_TEST_ORDER == %i" % ("if" if first else "elif", f))
first = False first = False
print("static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(") print()
print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x," % tuple((int(G[0]) >> (32 * (7 - i))) & 0xffffffff for i in range(4))) print(f"static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_{f};")
print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x," % tuple((int(G[0]) >> (32 * (7 - i))) & 0xffffffff for i in range(4, 8))) output_b(b)
print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x," % tuple((int(G[1]) >> (32 * (7 - i))) & 0xffffffff for i in range(4))) print()
print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x" % tuple((int(G[1]) >> (32 * (7 - i))) & 0xffffffff for i in range(4, 8)))
print(");")
print("static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(")
print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x," % tuple((int(b) >> (32 * (7 - i))) & 0xffffffff for i in range(4)))
print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x" % tuple((int(b) >> (32 * (7 - i))) & 0xffffffff for i in range(4, 8)))
print(");")
print("# else") print("# else")
print("# error No known generator for the specified exhaustive test group order.") print("# error No known generator for the specified exhaustive test group order.")
print("# endif") print("# endif")
print("#else")
print()
print("static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G;")
output_b(7)
print()
print("#endif")
print("/* End of section generated by sage/gen_exhaustive_groups.sage. */")
print("")
print("") print()
print("/* To be put in src/scalar_impl.h: */") print()
print("To be put in src/scalar_impl.h:")
print()
print("/* Begin of section generated by sage/gen_exhaustive_groups.sage. */")
first = True first = True
for f in sorted(results.keys()): for f in sorted(solutions.keys()):
lam = results[f]["lambda"] _, _, _, _, lam = min(solutions[f])
print("# %s EXHAUSTIVE_TEST_ORDER == %i" % ("if" if first else "elif", f)) print("# %s EXHAUSTIVE_TEST_ORDER == %i" % ("if" if first else "elif", f))
first = False first = False
print("# define EXHAUSTIVE_TEST_LAMBDA %i" % lam) print("# define EXHAUSTIVE_TEST_LAMBDA %i" % lam)
print("# else") print("# else")
print("# error No known lambda for the specified exhaustive test group order.") print("# error No known lambda for the specified exhaustive test group order.")
print("# endif") print("# endif")
print("") print("/* End of section generated by sage/gen_exhaustive_groups.sage. */")

View File

@ -148,7 +148,7 @@ def formula_secp256k1_gej_add_ge(branch, a, b):
zeroes = {} zeroes = {}
nonzeroes = {} nonzeroes = {}
a_infinity = False a_infinity = False
if (branch & 4) != 0: if (branch & 2) != 0:
nonzeroes.update({a.Infinity : 'a_infinite'}) nonzeroes.update({a.Infinity : 'a_infinite'})
a_infinity = True a_infinity = True
else: else:
@ -167,15 +167,11 @@ def formula_secp256k1_gej_add_ge(branch, a, b):
m_alt = -u2 m_alt = -u2
tt = u1 * m_alt tt = u1 * m_alt
rr = rr + tt rr = rr + tt
degenerate = (branch & 3) == 3 degenerate = (branch & 1) != 0
if (branch & 1) != 0: if degenerate:
zeroes.update({m : 'm_zero'}) zeroes.update({m : 'm_zero'})
else: else:
nonzeroes.update({m : 'm_nonzero'}) nonzeroes.update({m : 'm_nonzero'})
if (branch & 2) != 0:
zeroes.update({rr : 'rr_zero'})
else:
nonzeroes.update({rr : 'rr_nonzero'})
rr_alt = s1 rr_alt = s1
rr_alt = rr_alt * 2 rr_alt = rr_alt * 2
m_alt = m_alt + u1 m_alt = m_alt + u1
@ -190,13 +186,6 @@ def formula_secp256k1_gej_add_ge(branch, a, b):
n = m n = m
t = rr_alt^2 t = rr_alt^2
rz = a.Z * m_alt rz = a.Z * m_alt
infinity = False
if (branch & 8) != 0:
if not a_infinity:
infinity = True
zeroes.update({rz : 'r.z=0'})
else:
nonzeroes.update({rz : 'r.z!=0'})
t = t + q t = t + q
rx = t rx = t
t = t * 2 t = t * 2
@ -209,8 +198,11 @@ def formula_secp256k1_gej_add_ge(branch, a, b):
rx = b.X rx = b.X
ry = b.Y ry = b.Y
rz = 1 rz = 1
if infinity: if (branch & 4) != 0:
zeroes.update({rz : 'r.z = 0'})
return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), point_at_infinity()) return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), point_at_infinity())
else:
nonzeroes.update({rz : 'r.z != 0'})
return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), jacobianpoint(rx, ry, rz)) return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), jacobianpoint(rx, ry, rz))
def formula_secp256k1_gej_add_ge_old(branch, a, b): def formula_secp256k1_gej_add_ge_old(branch, a, b):
@ -280,14 +272,14 @@ if __name__ == "__main__":
success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var) success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var)
success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var) success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var)
success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var) success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var)
success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge) success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 8, formula_secp256k1_gej_add_ge)
success = success & (not check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old)) success = success & (not check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old))
if len(sys.argv) >= 2 and sys.argv[1] == "--exhaustive": if len(sys.argv) >= 2 and sys.argv[1] == "--exhaustive":
success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var, 43) success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var, 43)
success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var, 43) success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var, 43)
success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var, 43) success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var, 43)
success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge, 43) success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 8, formula_secp256k1_gej_add_ge, 43)
success = success & (not check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old, 43)) success = success & (not check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old, 43))
sys.exit(int(not success)) sys.exit(int(not success))

View File

@ -11,7 +11,7 @@
#include "util.h" #include "util.h"
#include "bench.h" #include "bench.h"
void help(int default_iters) { static void help(int default_iters) {
printf("Benchmarks the following algorithms:\n"); printf("Benchmarks the following algorithms:\n");
printf(" - ECDSA signing/verification\n"); printf(" - ECDSA signing/verification\n");

View File

@ -38,7 +38,7 @@ static int64_t gettime_i64(void) {
#define FP_MULT (1000000LL) #define FP_MULT (1000000LL)
/* Format fixed point number. */ /* Format fixed point number. */
void print_number(const int64_t x) { static void print_number(const int64_t x) {
int64_t x_abs, y; int64_t x_abs, y;
int c, i, rounding, g; /* g = integer part size, c = fractional part size */ int c, i, rounding, g; /* g = integer part size, c = fractional part size */
size_t ptr; size_t ptr;
@ -95,7 +95,7 @@ void print_number(const int64_t x) {
printf("%-*s", FP_EXP, &buffer[ptr + g]); /* Prints fractional part */ printf("%-*s", FP_EXP, &buffer[ptr + g]); /* Prints fractional part */
} }
void run_benchmark(char *name, void (*benchmark)(void*, int), void (*setup)(void*), void (*teardown)(void*, int), void* data, int count, int iter) { static void run_benchmark(char *name, void (*benchmark)(void*, int), void (*setup)(void*), void (*teardown)(void*, int), void* data, int count, int iter) {
int i; int i;
int64_t min = INT64_MAX; int64_t min = INT64_MAX;
int64_t sum = 0; int64_t sum = 0;
@ -129,7 +129,7 @@ void run_benchmark(char *name, void (*benchmark)(void*, int), void (*setup)(void
printf("\n"); printf("\n");
} }
int have_flag(int argc, char** argv, char *flag) { static int have_flag(int argc, char** argv, char *flag) {
char** argm = argv + argc; char** argm = argv + argc;
argv++; argv++;
while (argv != argm) { while (argv != argm) {
@ -145,7 +145,7 @@ int have_flag(int argc, char** argv, char *flag) {
returns: returns:
- 1 if the user entered an invalid argument - 1 if the user entered an invalid argument
- 0 if all the user entered arguments are valid */ - 0 if all the user entered arguments are valid */
int have_invalid_args(int argc, char** argv, char** valid_args, size_t n) { static int have_invalid_args(int argc, char** argv, char** valid_args, size_t n) {
size_t i; size_t i;
int found_valid; int found_valid;
char** argm = argv + argc; char** argm = argv + argc;
@ -167,7 +167,7 @@ int have_invalid_args(int argc, char** argv, char** valid_args, size_t n) {
return 0; return 0;
} }
int get_iters(int default_iters) { static int get_iters(int default_iters) {
char* env = getenv("SECP256K1_BENCH_ITERS"); char* env = getenv("SECP256K1_BENCH_ITERS");
if (env) { if (env) {
return strtol(env, NULL, 0); return strtol(env, NULL, 0);
@ -176,7 +176,7 @@ int get_iters(int default_iters) {
} }
} }
void print_output_table_header_row(void) { static void print_output_table_header_row(void) {
char* bench_str = "Benchmark"; /* left justified */ char* bench_str = "Benchmark"; /* left justified */
char* min_str = " Min(us) "; /* center alignment */ char* min_str = " Min(us) "; /* center alignment */
char* avg_str = " Avg(us) "; char* avg_str = " Avg(us) ";

View File

@ -18,7 +18,7 @@
#define POINTS 32768 #define POINTS 32768
void help(char **argv) { static void help(char **argv) {
printf("Benchmark EC multiplication algorithms\n"); printf("Benchmark EC multiplication algorithms\n");
printf("\n"); printf("\n");
printf("Usage: %s <help|pippenger_wnaf|strauss_wnaf|simple>\n", argv[0]); printf("Usage: %s <help|pippenger_wnaf|strauss_wnaf|simple>\n", argv[0]);

View File

@ -27,7 +27,7 @@ typedef struct {
int wnaf[256]; int wnaf[256];
} bench_inv; } bench_inv;
void bench_setup(void* arg) { static void bench_setup(void* arg) {
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
static const unsigned char init[4][32] = { static const unsigned char init[4][32] = {
@ -79,7 +79,7 @@ void bench_setup(void* arg) {
memcpy(data->data + 32, init[1], 32); memcpy(data->data + 32, init[1], 32);
} }
void bench_scalar_add(void* arg, int iters) { static void bench_scalar_add(void* arg, int iters) {
int i, j = 0; int i, j = 0;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -89,7 +89,7 @@ void bench_scalar_add(void* arg, int iters) {
CHECK(j <= iters); CHECK(j <= iters);
} }
void bench_scalar_negate(void* arg, int iters) { static void bench_scalar_negate(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -98,7 +98,7 @@ void bench_scalar_negate(void* arg, int iters) {
} }
} }
void bench_scalar_sqr(void* arg, int iters) { static void bench_scalar_sqr(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -107,7 +107,7 @@ void bench_scalar_sqr(void* arg, int iters) {
} }
} }
void bench_scalar_mul(void* arg, int iters) { static void bench_scalar_mul(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -116,18 +116,19 @@ void bench_scalar_mul(void* arg, int iters) {
} }
} }
void bench_scalar_split(void* arg, int iters) { static void bench_scalar_split(void* arg, int iters) {
int i, j = 0; int i, j = 0;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
secp256k1_scalar tmp;
for (i = 0; i < iters; i++) { for (i = 0; i < iters; i++) {
secp256k1_scalar_split_lambda(&data->scalar[0], &data->scalar[1], &data->scalar[0]); secp256k1_scalar_split_lambda(&tmp, &data->scalar[1], &data->scalar[0]);
j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); j += secp256k1_scalar_add(&data->scalar[0], &tmp, &data->scalar[1]);
} }
CHECK(j <= iters); CHECK(j <= iters);
} }
void bench_scalar_inverse(void* arg, int iters) { static void bench_scalar_inverse(void* arg, int iters) {
int i, j = 0; int i, j = 0;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -138,7 +139,7 @@ void bench_scalar_inverse(void* arg, int iters) {
CHECK(j <= iters); CHECK(j <= iters);
} }
void bench_scalar_inverse_var(void* arg, int iters) { static void bench_scalar_inverse_var(void* arg, int iters) {
int i, j = 0; int i, j = 0;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -149,7 +150,7 @@ void bench_scalar_inverse_var(void* arg, int iters) {
CHECK(j <= iters); CHECK(j <= iters);
} }
void bench_field_half(void* arg, int iters) { static void bench_field_half(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -158,7 +159,7 @@ void bench_field_half(void* arg, int iters) {
} }
} }
void bench_field_normalize(void* arg, int iters) { static void bench_field_normalize(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -167,7 +168,7 @@ void bench_field_normalize(void* arg, int iters) {
} }
} }
void bench_field_normalize_weak(void* arg, int iters) { static void bench_field_normalize_weak(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -176,7 +177,7 @@ void bench_field_normalize_weak(void* arg, int iters) {
} }
} }
void bench_field_mul(void* arg, int iters) { static void bench_field_mul(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -185,7 +186,7 @@ void bench_field_mul(void* arg, int iters) {
} }
} }
void bench_field_sqr(void* arg, int iters) { static void bench_field_sqr(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -194,7 +195,7 @@ void bench_field_sqr(void* arg, int iters) {
} }
} }
void bench_field_inverse(void* arg, int iters) { static void bench_field_inverse(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -204,7 +205,7 @@ void bench_field_inverse(void* arg, int iters) {
} }
} }
void bench_field_inverse_var(void* arg, int iters) { static void bench_field_inverse_var(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -214,7 +215,7 @@ void bench_field_inverse_var(void* arg, int iters) {
} }
} }
void bench_field_sqrt(void* arg, int iters) { static void bench_field_sqrt(void* arg, int iters) {
int i, j = 0; int i, j = 0;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
secp256k1_fe t; secp256k1_fe t;
@ -227,7 +228,20 @@ void bench_field_sqrt(void* arg, int iters) {
CHECK(j <= iters); CHECK(j <= iters);
} }
void bench_group_double_var(void* arg, int iters) { static void bench_field_is_square_var(void* arg, int iters) {
int i, j = 0;
bench_inv *data = (bench_inv*)arg;
secp256k1_fe t = data->fe[0];
for (i = 0; i < iters; i++) {
j += secp256k1_fe_is_square_var(&t);
secp256k1_fe_add(&t, &data->fe[1]);
secp256k1_fe_normalize_var(&t);
}
CHECK(j <= iters);
}
static void bench_group_double_var(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -236,7 +250,7 @@ void bench_group_double_var(void* arg, int iters) {
} }
} }
void bench_group_add_var(void* arg, int iters) { static void bench_group_add_var(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -245,7 +259,7 @@ void bench_group_add_var(void* arg, int iters) {
} }
} }
void bench_group_add_affine(void* arg, int iters) { static void bench_group_add_affine(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -254,7 +268,7 @@ void bench_group_add_affine(void* arg, int iters) {
} }
} }
void bench_group_add_affine_var(void* arg, int iters) { static void bench_group_add_affine_var(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -263,7 +277,7 @@ void bench_group_add_affine_var(void* arg, int iters) {
} }
} }
void bench_group_jacobi_var(void* arg, int iters) { static void bench_group_jacobi_var(void* arg, int iters) {
int i, j = 0; int i, j = 0;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -283,7 +297,7 @@ void bench_group_jacobi_var(void* arg, int iters) {
CHECK(j <= iters); CHECK(j <= iters);
} }
void bench_group_add_zinv_var(void* arg, int iters) { static void bench_group_add_zinv_var(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -292,7 +306,7 @@ void bench_group_add_zinv_var(void* arg, int iters) {
} }
} }
void bench_group_to_affine_var(void* arg, int iters) { static void bench_group_to_affine_var(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -310,7 +324,7 @@ void bench_group_to_affine_var(void* arg, int iters) {
} }
} }
void bench_ecmult_wnaf(void* arg, int iters) { static void bench_ecmult_wnaf(void* arg, int iters) {
int i, bits = 0, overflow = 0; int i, bits = 0, overflow = 0;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -322,7 +336,7 @@ void bench_ecmult_wnaf(void* arg, int iters) {
CHECK(bits <= 256*iters); CHECK(bits <= 256*iters);
} }
void bench_wnaf_const(void* arg, int iters) { static void bench_wnaf_const(void* arg, int iters) {
int i, bits = 0, overflow = 0; int i, bits = 0, overflow = 0;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
@ -334,8 +348,7 @@ void bench_wnaf_const(void* arg, int iters) {
CHECK(bits <= 256*iters); CHECK(bits <= 256*iters);
} }
static void bench_sha256(void* arg, int iters) {
void bench_sha256(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
secp256k1_sha256 sha; secp256k1_sha256 sha;
@ -347,7 +360,7 @@ void bench_sha256(void* arg, int iters) {
} }
} }
void bench_hmac_sha256(void* arg, int iters) { static void bench_hmac_sha256(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
secp256k1_hmac_sha256 hmac; secp256k1_hmac_sha256 hmac;
@ -359,7 +372,7 @@ void bench_hmac_sha256(void* arg, int iters) {
} }
} }
void bench_rfc6979_hmac_sha256(void* arg, int iters) { static void bench_rfc6979_hmac_sha256(void* arg, int iters) {
int i; int i;
bench_inv *data = (bench_inv*)arg; bench_inv *data = (bench_inv*)arg;
secp256k1_rfc6979_hmac_sha256 rng; secp256k1_rfc6979_hmac_sha256 rng;
@ -370,7 +383,7 @@ void bench_rfc6979_hmac_sha256(void* arg, int iters) {
} }
} }
void bench_context(void* arg, int iters) { static void bench_context(void* arg, int iters) {
int i; int i;
(void)arg; (void)arg;
for (i = 0; i < iters; i++) { for (i = 0; i < iters; i++) {
@ -399,6 +412,7 @@ int main(int argc, char **argv) {
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); 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);
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse", bench_field_inverse, bench_setup, NULL, &data, 10, iters); if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse", bench_field_inverse, bench_setup, NULL, &data, 10, iters);
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse_var", bench_field_inverse_var, bench_setup, NULL, &data, 10, iters); if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse_var", bench_field_inverse_var, bench_setup, NULL, &data, 10, iters);
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "issquare")) run_benchmark("field_is_square_var", bench_field_is_square_var, bench_setup, NULL, &data, 10, iters);
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt", bench_field_sqrt, bench_setup, NULL, &data, 10, iters); if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt", bench_field_sqrt, bench_setup, NULL, &data, 10, iters);
if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "double")) run_benchmark("group_double_var", bench_group_double_var, bench_setup, NULL, &data, 10, iters*10); if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "double")) run_benchmark("group_double_var", bench_group_double_var, bench_setup, NULL, &data, 10, iters*10);

View File

@ -49,7 +49,7 @@ static void run_test(bench_data* data, int iters) {
run_benchmark(str, bench_whitelist, bench_whitelist_setup, NULL, data, 100, iters); run_benchmark(str, bench_whitelist, bench_whitelist_setup, NULL, data, 100, iters);
} }
void random_scalar_order(secp256k1_scalar *num) { static void random_scalar_order(secp256k1_scalar *num) {
do { do {
unsigned char b32[32]; unsigned char b32[32];
int overflow = 0; int overflow = 0;

88
src/checkmem.h Normal file
View File

@ -0,0 +1,88 @@
/***********************************************************************
* Copyright (c) 2022 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
***********************************************************************/
/* The code here is inspired by Kris Kwiatkowski's approach in
* https://github.com/kriskwiatkowski/pqc/blob/main/src/common/ct_check.h
* to provide a general interface for memory-checking mechanisms, primarily
* for constant-time checking.
*/
/* These macros are defined by this header file:
*
* - SECP256K1_CHECKMEM_ENABLED:
* - 1 if memory-checking integration is available, 0 otherwise.
* This is just a compile-time macro. Use the next macro to check it is actually
* available at runtime.
* - SECP256K1_CHECKMEM_RUNNING():
* - Acts like a function call, returning 1 if memory checking is available
* at runtime.
* - SECP256K1_CHECKMEM_CHECK(p, len):
* - Assert or otherwise fail in case the len-byte memory block pointed to by p is
* not considered entirely defined.
* - SECP256K1_CHECKMEM_CHECK_VERIFY(p, len):
* - Like SECP256K1_CHECKMEM_CHECK, but only works in VERIFY mode.
* - SECP256K1_CHECKMEM_UNDEFINE(p, len):
* - marks the len-byte memory block pointed to by p as undefined data (secret data,
* in the context of constant-time checking).
* - SECP256K1_CHECKMEM_DEFINE(p, len):
* - marks the len-byte memory pointed to by p as defined data (public data, in the
* context of constant-time checking).
*
*/
#ifndef SECP256K1_CHECKMEM_H
#define SECP256K1_CHECKMEM_H
/* Define a statement-like macro that ignores the arguments. */
#define SECP256K1_CHECKMEM_NOOP(p, len) do { (void)(p); (void)(len); } while(0)
/* If compiling under msan, map the SECP256K1_CHECKMEM_* functionality to msan.
* Choose this preferentially, even when VALGRIND is defined, as msan-compiled
* binaries can't be run under valgrind anyway. */
#if defined(__has_feature)
# if __has_feature(memory_sanitizer)
# include <sanitizer/msan_interface.h>
# define SECP256K1_CHECKMEM_ENABLED 1
# define SECP256K1_CHECKMEM_UNDEFINE(p, len) __msan_allocated_memory((p), (len))
# define SECP256K1_CHECKMEM_DEFINE(p, len) __msan_unpoison((p), (len))
# define SECP256K1_CHECKMEM_CHECK(p, len) __msan_check_mem_is_initialized((p), (len))
# define SECP256K1_CHECKMEM_RUNNING() (1)
# endif
#endif
/* If valgrind integration is desired (through the VALGRIND define), implement the
* SECP256K1_CHECKMEM_* macros using valgrind. */
#if !defined SECP256K1_CHECKMEM_ENABLED
# if defined VALGRIND
# include <stddef.h>
# include <valgrind/memcheck.h>
# define SECP256K1_CHECKMEM_ENABLED 1
# define SECP256K1_CHECKMEM_UNDEFINE(p, len) VALGRIND_MAKE_MEM_UNDEFINED((p), (len))
# define SECP256K1_CHECKMEM_DEFINE(p, len) VALGRIND_MAKE_MEM_DEFINED((p), (len))
# define SECP256K1_CHECKMEM_CHECK(p, len) VALGRIND_CHECK_MEM_IS_DEFINED((p), (len))
/* VALGRIND_MAKE_MEM_DEFINED returns 0 iff not running on memcheck.
* This is more precise than the RUNNING_ON_VALGRIND macro, which
* checks for valgrind in general instead of memcheck specifically. */
# define SECP256K1_CHECKMEM_RUNNING() (VALGRIND_MAKE_MEM_DEFINED(NULL, 0) != 0)
# endif
#endif
/* As a fall-back, map these macros to dummy statements. */
#if !defined SECP256K1_CHECKMEM_ENABLED
# define SECP256K1_CHECKMEM_ENABLED 0
# define SECP256K1_CHECKMEM_UNDEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len))
# define SECP256K1_CHECKMEM_DEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len))
# define SECP256K1_CHECKMEM_CHECK(p, len) SECP256K1_CHECKMEM_NOOP((p), (len))
# define SECP256K1_CHECKMEM_RUNNING() (0)
#endif
#if defined VERIFY
#define SECP256K1_CHECKMEM_CHECK_VERIFY(p, len) SECP256K1_CHECKMEM_CHECK((p), (len))
#else
#define SECP256K1_CHECKMEM_CHECK_VERIFY(p, len) SECP256K1_CHECKMEM_NOOP((p), (len))
#endif
#endif /* SECP256K1_CHECKMEM_H */

View File

@ -4,13 +4,16 @@
* file COPYING or https://www.opensource.org/licenses/mit-license.php.* * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
***********************************************************************/ ***********************************************************************/
#include <valgrind/memcheck.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "../include/secp256k1.h" #include "../include/secp256k1.h"
#include "assumptions.h" #include "assumptions.h"
#include "util.h" #include "checkmem.h"
#if !SECP256K1_CHECKMEM_ENABLED
# error "This tool cannot be compiled without memory-checking interface (valgrind or msan)"
#endif
#ifdef ENABLE_MODULE_ECDH #ifdef ENABLE_MODULE_ECDH
# include "../include/secp256k1_ecdh.h" # include "../include/secp256k1_ecdh.h"
@ -40,16 +43,16 @@
#include "../include/secp256k1_musig.h" #include "../include/secp256k1_musig.h"
#endif #endif
void run_tests(secp256k1_context *ctx, unsigned char *key); static void run_tests(secp256k1_context *ctx, unsigned char *key);
int main(void) { int main(void) {
secp256k1_context* ctx; secp256k1_context* ctx;
unsigned char key[32]; unsigned char key[32];
int ret, i; int ret, i;
if (!RUNNING_ON_VALGRIND) { if (!SECP256K1_CHECKMEM_RUNNING()) {
fprintf(stderr, "This test can only usefully be run inside valgrind.\n"); fprintf(stderr, "This test can only usefully be run inside valgrind because it was not compiled under msan.\n");
fprintf(stderr, "Usage: libtool --mode=execute valgrind ./valgrind_ctime_test\n"); fprintf(stderr, "Usage: libtool --mode=execute valgrind ./ctime_tests\n");
return 1; return 1;
} }
ctx = secp256k1_context_create(SECP256K1_CONTEXT_DECLASSIFY); ctx = secp256k1_context_create(SECP256K1_CONTEXT_DECLASSIFY);
@ -64,16 +67,16 @@ int main(void) {
/* Test context randomisation. Do this last because it leaves the context /* Test context randomisation. Do this last because it leaves the context
* tainted. */ * tainted. */
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_context_randomize(ctx, key); ret = secp256k1_context_randomize(ctx, key);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret); CHECK(ret);
secp256k1_context_destroy(ctx); secp256k1_context_destroy(ctx);
return 0; return 0;
} }
void run_tests(secp256k1_context *ctx, unsigned char *key) { static void run_tests(secp256k1_context *ctx, unsigned char *key) {
secp256k1_ecdsa_signature signature; secp256k1_ecdsa_signature signature;
secp256k1_pubkey pubkey; secp256k1_pubkey pubkey;
size_t siglen = 74; size_t siglen = 74;
@ -96,89 +99,89 @@ void run_tests(secp256k1_context *ctx, unsigned char *key) {
} }
/* Test keygen. */ /* Test keygen. */
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_ec_pubkey_create(ctx, &pubkey, key); ret = secp256k1_ec_pubkey_create(ctx, &pubkey, key);
VALGRIND_MAKE_MEM_DEFINED(&pubkey, sizeof(secp256k1_pubkey)); SECP256K1_CHECKMEM_DEFINE(&pubkey, sizeof(secp256k1_pubkey));
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret); CHECK(ret);
CHECK(secp256k1_ec_pubkey_serialize(ctx, spubkey, &outputlen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); CHECK(secp256k1_ec_pubkey_serialize(ctx, spubkey, &outputlen, &pubkey, SECP256K1_EC_COMPRESSED) == 1);
/* Test signing. */ /* Test signing. */
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_ecdsa_sign(ctx, &signature, msg, key, NULL, NULL); ret = secp256k1_ecdsa_sign(ctx, &signature, msg, key, NULL, NULL);
VALGRIND_MAKE_MEM_DEFINED(&signature, sizeof(secp256k1_ecdsa_signature)); SECP256K1_CHECKMEM_DEFINE(&signature, sizeof(secp256k1_ecdsa_signature));
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret); CHECK(ret);
CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature)); CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature));
#ifdef ENABLE_MODULE_ECDH #ifdef ENABLE_MODULE_ECDH
/* Test ECDH. */ /* Test ECDH. */
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_ecdh(ctx, msg, &pubkey, key, NULL, NULL); ret = secp256k1_ecdh(ctx, msg, &pubkey, key, NULL, NULL);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1); CHECK(ret == 1);
#endif #endif
#ifdef ENABLE_MODULE_RECOVERY #ifdef ENABLE_MODULE_RECOVERY
/* Test signing a recoverable signature. */ /* Test signing a recoverable signature. */
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_ecdsa_sign_recoverable(ctx, &recoverable_signature, msg, key, NULL, NULL); ret = secp256k1_ecdsa_sign_recoverable(ctx, &recoverable_signature, msg, key, NULL, NULL);
VALGRIND_MAKE_MEM_DEFINED(&recoverable_signature, sizeof(recoverable_signature)); SECP256K1_CHECKMEM_DEFINE(&recoverable_signature, sizeof(recoverable_signature));
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret); CHECK(ret);
CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &recoverable_signature)); CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &recoverable_signature));
CHECK(recid >= 0 && recid <= 3); CHECK(recid >= 0 && recid <= 3);
#endif #endif
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_ec_seckey_verify(ctx, key); ret = secp256k1_ec_seckey_verify(ctx, key);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1); CHECK(ret == 1);
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_ec_seckey_negate(ctx, key); ret = secp256k1_ec_seckey_negate(ctx, key);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1); CHECK(ret == 1);
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); SECP256K1_CHECKMEM_UNDEFINE(key, 32);
VALGRIND_MAKE_MEM_UNDEFINED(msg, 32); SECP256K1_CHECKMEM_UNDEFINE(msg, 32);
ret = secp256k1_ec_seckey_tweak_add(ctx, key, msg); ret = secp256k1_ec_seckey_tweak_add(ctx, key, msg);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1); CHECK(ret == 1);
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); SECP256K1_CHECKMEM_UNDEFINE(key, 32);
VALGRIND_MAKE_MEM_UNDEFINED(msg, 32); SECP256K1_CHECKMEM_UNDEFINE(msg, 32);
ret = secp256k1_ec_seckey_tweak_mul(ctx, key, msg); ret = secp256k1_ec_seckey_tweak_mul(ctx, key, msg);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1); CHECK(ret == 1);
/* Test keypair_create and keypair_xonly_tweak_add. */ /* Test keypair_create and keypair_xonly_tweak_add. */
#ifdef ENABLE_MODULE_EXTRAKEYS #ifdef ENABLE_MODULE_EXTRAKEYS
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_keypair_create(ctx, &keypair, key); ret = secp256k1_keypair_create(ctx, &keypair, key);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1); CHECK(ret == 1);
/* The tweak is not treated as a secret in keypair_tweak_add */ /* The tweak is not treated as a secret in keypair_tweak_add */
VALGRIND_MAKE_MEM_DEFINED(msg, 32); SECP256K1_CHECKMEM_DEFINE(msg, 32);
ret = secp256k1_keypair_xonly_tweak_add(ctx, &keypair, msg); ret = secp256k1_keypair_xonly_tweak_add(ctx, &keypair, msg);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1); CHECK(ret == 1);
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); SECP256K1_CHECKMEM_UNDEFINE(key, 32);
VALGRIND_MAKE_MEM_UNDEFINED(&keypair, sizeof(keypair)); SECP256K1_CHECKMEM_UNDEFINE(&keypair, sizeof(keypair));
ret = secp256k1_keypair_sec(ctx, key, &keypair); ret = secp256k1_keypair_sec(ctx, key, &keypair);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1); CHECK(ret == 1);
#endif #endif
#ifdef ENABLE_MODULE_SCHNORRSIG #ifdef ENABLE_MODULE_SCHNORRSIG
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_keypair_create(ctx, &keypair, key); ret = secp256k1_keypair_create(ctx, &keypair, key);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1); CHECK(ret == 1);
ret = secp256k1_schnorrsig_sign32(ctx, sig, msg, &keypair, NULL); ret = secp256k1_schnorrsig_sign32(ctx, sig, msg, &keypair, NULL);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1); CHECK(ret == 1);
#endif #endif

View File

@ -85,6 +85,9 @@ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a);
* as an argument. The magnitude of the output is one higher. */ * as an argument. The magnitude of the output is one higher. */
static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m); static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m);
/** Adds a small integer (up to 0x7FFF) to r. The resulting magnitude increases by one. */
static void secp256k1_fe_add_int(secp256k1_fe *r, int a);
/** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that /** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that
* small integer. */ * small integer. */
static void secp256k1_fe_mul_int(secp256k1_fe *r, int a); static void secp256k1_fe_mul_int(secp256k1_fe *r, int a);
@ -138,4 +141,7 @@ static void secp256k1_fe_half(secp256k1_fe *r);
* magnitude set to 'm' and is normalized if (and only if) 'm' is zero. */ * magnitude set to 'm' and is normalized if (and only if) 'm' is zero. */
static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m); static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m);
/** Determine whether a is a square (modulo p). */
static int secp256k1_fe_is_square_var(const secp256k1_fe *a);
#endif /* SECP256K1_FIELD_H */ #endif /* SECP256K1_FIELD_H */

View File

@ -7,6 +7,7 @@
#ifndef SECP256K1_FIELD_REPR_IMPL_H #ifndef SECP256K1_FIELD_REPR_IMPL_H
#define SECP256K1_FIELD_REPR_IMPL_H #define SECP256K1_FIELD_REPR_IMPL_H
#include "checkmem.h"
#include "util.h" #include "util.h"
#include "field.h" #include "field.h"
#include "modinv32_impl.h" #include "modinv32_impl.h"
@ -481,6 +482,20 @@ SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_f
#endif #endif
} }
SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) {
#ifdef VERIFY
secp256k1_fe_verify(r);
VERIFY_CHECK(a >= 0);
VERIFY_CHECK(a <= 0x7FFF);
#endif
r->n[0] += a;
#ifdef VERIFY
r->magnitude += 1;
r->normalized = 0;
secp256k1_fe_verify(r);
#endif
}
#if defined(USE_EXTERNAL_ASM) #if defined(USE_EXTERNAL_ASM)
/* External assembler implementation */ /* External assembler implementation */
@ -1133,7 +1148,7 @@ static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
uint32_t mask0, mask1; uint32_t mask0, mask1;
volatile int vflag = flag; volatile int vflag = flag;
VG_CHECK_VERIFY(r->n, sizeof(r->n)); SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
mask0 = vflag + ~((uint32_t)0); mask0 = vflag + ~((uint32_t)0);
mask1 = ~mask0; mask1 = ~mask0;
r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);
@ -1233,7 +1248,7 @@ static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) {
uint32_t mask0, mask1; uint32_t mask0, mask1;
volatile int vflag = flag; volatile int vflag = flag;
VG_CHECK_VERIFY(r->n, sizeof(r->n)); SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
mask0 = vflag + ~((uint32_t)0); mask0 = vflag + ~((uint32_t)0);
mask1 = ~mask0; mask1 = ~mask0;
r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);
@ -1366,4 +1381,31 @@ static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *x) {
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == secp256k1_fe_normalizes_to_zero(&tmp)); VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == secp256k1_fe_normalizes_to_zero(&tmp));
} }
static int secp256k1_fe_is_square_var(const secp256k1_fe *x) {
secp256k1_fe tmp;
secp256k1_modinv32_signed30 s;
int jac, ret;
tmp = *x;
secp256k1_fe_normalize_var(&tmp);
/* secp256k1_jacobi32_maybe_var cannot deal with input 0. */
if (secp256k1_fe_is_zero(&tmp)) return 1;
secp256k1_fe_to_signed30(&s, &tmp);
jac = secp256k1_jacobi32_maybe_var(&s, &secp256k1_const_modinfo_fe);
if (jac == 0) {
/* secp256k1_jacobi32_maybe_var failed to compute the Jacobi symbol. Fall back
* to computing a square root. This should be extremely rare with random
* input (except in VERIFY mode, where a lower iteration count is used). */
secp256k1_fe dummy;
ret = secp256k1_fe_sqrt(&dummy, &tmp);
} else {
#ifdef VERIFY
secp256k1_fe dummy;
VERIFY_CHECK(jac == 2*secp256k1_fe_sqrt(&dummy, &tmp) - 1);
#endif
ret = jac >= 0;
}
return ret;
}
#endif /* SECP256K1_FIELD_REPR_IMPL_H */ #endif /* SECP256K1_FIELD_REPR_IMPL_H */

View File

@ -7,6 +7,7 @@
#ifndef SECP256K1_FIELD_REPR_IMPL_H #ifndef SECP256K1_FIELD_REPR_IMPL_H
#define SECP256K1_FIELD_REPR_IMPL_H #define SECP256K1_FIELD_REPR_IMPL_H
#include "checkmem.h"
#include "util.h" #include "util.h"
#include "field.h" #include "field.h"
#include "modinv64_impl.h" #include "modinv64_impl.h"
@ -424,6 +425,20 @@ SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) {
#endif #endif
} }
SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) {
#ifdef VERIFY
secp256k1_fe_verify(r);
VERIFY_CHECK(a >= 0);
VERIFY_CHECK(a <= 0x7FFF);
#endif
r->n[0] += a;
#ifdef VERIFY
r->magnitude += 1;
r->normalized = 0;
secp256k1_fe_verify(r);
#endif
}
SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) {
#ifdef VERIFY #ifdef VERIFY
secp256k1_fe_verify(a); secp256k1_fe_verify(a);
@ -473,7 +488,7 @@ static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
uint64_t mask0, mask1; uint64_t mask0, mask1;
volatile int vflag = flag; volatile int vflag = flag;
VG_CHECK_VERIFY(r->n, sizeof(r->n)); SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
mask0 = vflag + ~((uint64_t)0); mask0 = vflag + ~((uint64_t)0);
mask1 = ~mask0; mask1 = ~mask0;
r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);
@ -557,7 +572,7 @@ static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) {
uint64_t mask0, mask1; uint64_t mask0, mask1;
volatile int vflag = flag; volatile int vflag = flag;
VG_CHECK_VERIFY(r->n, sizeof(r->n)); SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
mask0 = vflag + ~((uint64_t)0); mask0 = vflag + ~((uint64_t)0);
mask1 = ~mask0; mask1 = ~mask0;
r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);
@ -665,4 +680,31 @@ static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *x) {
#endif #endif
} }
static int secp256k1_fe_is_square_var(const secp256k1_fe *x) {
secp256k1_fe tmp;
secp256k1_modinv64_signed62 s;
int jac, ret;
tmp = *x;
secp256k1_fe_normalize_var(&tmp);
/* secp256k1_jacobi64_maybe_var cannot deal with input 0. */
if (secp256k1_fe_is_zero(&tmp)) return 1;
secp256k1_fe_to_signed62(&s, &tmp);
jac = secp256k1_jacobi64_maybe_var(&s, &secp256k1_const_modinfo_fe);
if (jac == 0) {
/* secp256k1_jacobi64_maybe_var failed to compute the Jacobi symbol. Fall back
* to computing a square root. This should be extremely rare with random
* input (except in VERIFY mode, where a lower iteration count is used). */
secp256k1_fe dummy;
ret = secp256k1_fe_sqrt(&dummy, &tmp);
} else {
#ifdef VERIFY
secp256k1_fe dummy;
VERIFY_CHECK(jac == 2*secp256k1_fe_sqrt(&dummy, &tmp) - 1);
#endif
ret = jac >= 0;
}
return ret;
}
#endif /* SECP256K1_FIELD_REPR_IMPL_H */ #endif /* SECP256K1_FIELD_REPR_IMPL_H */

View File

@ -10,59 +10,69 @@
#include "field.h" #include "field.h"
#include "group.h" #include "group.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(\ #define SECP256K1_G_ORDER_13 SECP256K1_GE_CONST(\
0xc3459c3d, 0x35326167, 0xcd86cce8, 0x07a2417f,\ 0xa2482ff8, 0x4bf34edf, 0xa51262fd, 0xe57921db,\
0x5b8bd567, 0xde8538ee, 0x0d507b0c, 0xd128f5bb,\ 0xe0dd2cb7, 0xa5914790, 0xbc71631f, 0xc09704fb,\
0x8e467fec, 0xcd30000a, 0x6cc1184e, 0x25d382c2,\ 0x942536cb, 0xa3e49492, 0x3a701cc3, 0xee3e443f,\
0xa2f4494e, 0x2fbe9abc, 0x8b64abac, 0xd005fb24\ 0xdf182aa9, 0x15b8aa6a, 0x166d3b19, 0xba84b045\
) )
#define SECP256K1_G_ORDER_199 SECP256K1_GE_CONST(\ #define SECP256K1_G_ORDER_199 SECP256K1_GE_CONST(\
0x226e653f, 0xc8df7744, 0x9bacbf12, 0x7d1dcbf9,\ 0x7fb07b5c, 0xd07c3bda, 0x553902e2, 0x7a87ea2c,\
0x87f05b2a, 0xe7edbd28, 0x1f564575, 0xc48dcf18,\ 0x35108a7f, 0x051f41e5, 0xb76abad5, 0x1f2703ad,\
0xa13872c2, 0xe933bb17, 0x5d9ffd5b, 0xb5b6e10c,\ 0x0a251539, 0x5b4c4438, 0x952a634f, 0xac10dd4d,\
0x57fe3c00, 0xbaaaa15a, 0xe003ec3e, 0x9c269bae\ 0x6d6f4745, 0x98990c27, 0x3a4f3116, 0xd32ff969\
) )
/** Generator for secp256k1, value 'g' defined in /** Generator for secp256k1, value 'g' defined in
* "Standards for Efficient Cryptography" (SEC2) 2.7.1. * "Standards for Efficient Cryptography" (SEC2) 2.7.1.
*/ */
#define SECP256K1_G SECP256K1_GE_CONST(\ #define SECP256K1_G SECP256K1_GE_CONST(\
0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL,\ 0x79be667e, 0xf9dcbbac, 0x55a06295, 0xce870b07,\
0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL,\ 0x029bfcdb, 0x2dce28d9, 0x59f2815b, 0x16f81798,\
0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL,\ 0x483ada77, 0x26a3c465, 0x5da4fbfc, 0x0e1108a8,\
0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL\ 0xfd17b448, 0xa6855419, 0x9c47d08f, 0xfb10d4b8\
) )
/* These exhaustive group test orders and generators are chosen such that: /* 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 field size is equal to that of secp256k1, so field code is the same.
* - The curve equation is of the form y^2=x^3+B for some constant B. * - 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=1. * - 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 has size less than 1000 to permit exhaustive testing.
* - The subgroup admits an endomorphism of the form lambda*(x,y) == (beta*x,y). * - The subgroup admits an endomorphism of the form lambda*(x,y) == (beta*x,y).
*
* These parameters are generated using sage/gen_exhaustive_groups.sage.
*/ */
#if defined(EXHAUSTIVE_TEST_ORDER) #if defined(EXHAUSTIVE_TEST_ORDER)
# if EXHAUSTIVE_TEST_ORDER == 13 # 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; static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_13;
#define SECP256K1_B 2
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(
0x3d3486b2, 0x159a9ca5, 0xc75638be, 0xb23a69bc,
0x946a45ab, 0x24801247, 0xb4ed2b8e, 0x26b6a417
);
# elif EXHAUSTIVE_TEST_ORDER == 199 # elif EXHAUSTIVE_TEST_ORDER == 199
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_199;
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST( static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_199;
0x2cca28fa, 0xfc614b80, 0x2a3db42b, 0x00ba00b1, #define SECP256K1_B 4
0xbea8d943, 0xdace9ab2, 0x9536daea, 0x0074defb
);
# else # else
# error No known generator for the specified exhaustive test group order. # error No known generator for the specified exhaustive test group order.
# endif # endif
#else #else
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G;
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 7); static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G;
#define SECP256K1_B 7
#endif #endif
/* End of section generated by sage/gen_exhaustive_groups.sage. */
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, SECP256K1_B);
static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) { static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) {
secp256k1_fe zi2; secp256k1_fe zi2;
@ -217,7 +227,7 @@ static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) {
secp256k1_fe_sqr(&x2, x); secp256k1_fe_sqr(&x2, x);
secp256k1_fe_mul(&x3, x, &x2); secp256k1_fe_mul(&x3, x, &x2);
r->infinity = 0; r->infinity = 0;
secp256k1_fe_add(&x3, &secp256k1_fe_const_b); secp256k1_fe_add_int(&x3, SECP256K1_B);
return secp256k1_fe_sqrt(&r->y, &x3); return secp256k1_fe_sqrt(&r->y, &x3);
} }
@ -276,7 +286,7 @@ static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) {
/* y^2 = x^3 + 7 */ /* y^2 = x^3 + 7 */
secp256k1_fe_sqr(&y2, &a->y); secp256k1_fe_sqr(&y2, &a->y);
secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
secp256k1_fe_add(&x3, &secp256k1_fe_const_b); secp256k1_fe_add_int(&x3, SECP256K1_B);
secp256k1_fe_normalize_weak(&x3); secp256k1_fe_normalize_weak(&x3);
return secp256k1_fe_equal_var(&y2, &x3); return secp256k1_fe_equal_var(&y2, &x3);
} }
@ -526,11 +536,11 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const
/* Operations: 7 mul, 5 sqr, 24 add/cmov/half/mul_int/negate/normalize_weak/normalizes_to_zero */ /* Operations: 7 mul, 5 sqr, 24 add/cmov/half/mul_int/negate/normalize_weak/normalizes_to_zero */
secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr; secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr;
secp256k1_fe m_alt, rr_alt; secp256k1_fe m_alt, rr_alt;
int infinity, degenerate; int degenerate;
VERIFY_CHECK(!b->infinity); VERIFY_CHECK(!b->infinity);
VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); VERIFY_CHECK(a->infinity == 0 || a->infinity == 1);
/** In: /* In:
* Eric Brier and Marc Joye, Weierstrass Elliptic Curves and Side-Channel Attacks. * Eric Brier and Marc Joye, Weierstrass Elliptic Curves and Side-Channel Attacks.
* In D. Naccache and P. Paillier, Eds., Public Key Cryptography, vol. 2274 of Lecture Notes in Computer Science, pages 335-345. Springer-Verlag, 2002. * In D. Naccache and P. Paillier, Eds., Public Key Cryptography, vol. 2274 of Lecture Notes in Computer Science, pages 335-345. Springer-Verlag, 2002.
* we find as solution for a unified addition/doubling formula: * we find as solution for a unified addition/doubling formula:
@ -592,10 +602,9 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const
secp256k1_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 */ secp256k1_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 */
secp256k1_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (2) */ secp256k1_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (2) */
secp256k1_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (3) */ secp256k1_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (3) */
/** If lambda = R/M = 0/0 we have a problem (except in the "trivial" /* If lambda = R/M = R/0 we have a problem (except in the "trivial"
* case that Z = z1z2 = 0, and this is special-cased later on). */ * case that Z = z1z2 = 0, and this is special-cased later on). */
degenerate = secp256k1_fe_normalizes_to_zero(&m) & degenerate = secp256k1_fe_normalizes_to_zero(&m);
secp256k1_fe_normalizes_to_zero(&rr);
/* This only occurs when y1 == -y2 and x1^3 == x2^3, but x1 != x2. /* This only occurs when y1 == -y2 and x1^3 == x2^3, but x1 != x2.
* This means either x1 == beta*x2 or beta*x1 == x2, where beta is * This means either x1 == beta*x2 or beta*x1 == x2, where beta is
* a nontrivial cube root of one. In either case, an alternate * a nontrivial cube root of one. In either case, an alternate
@ -607,7 +616,7 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const
secp256k1_fe_cmov(&rr_alt, &rr, !degenerate); secp256k1_fe_cmov(&rr_alt, &rr, !degenerate);
secp256k1_fe_cmov(&m_alt, &m, !degenerate); secp256k1_fe_cmov(&m_alt, &m, !degenerate);
/* Now Ralt / Malt = lambda and is guaranteed not to be 0/0. /* Now Ralt / Malt = lambda and is guaranteed not to be Ralt / 0.
* From here on out Ralt and Malt represent the numerator * From here on out Ralt and Malt represent the numerator
* and denominator of lambda; R and M represent the explicit * and denominator of lambda; R and M represent the explicit
* expressions x1^2 + x2^2 + x1x2 and y1 + y2. */ * expressions x1^2 + x2^2 + x1x2 and y1 + y2. */
@ -622,7 +631,6 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const
secp256k1_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (2) */ secp256k1_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (2) */
secp256k1_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */ secp256k1_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */
secp256k1_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Z3 = Malt*Z (1) */ secp256k1_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Z3 = Malt*Z (1) */
infinity = secp256k1_fe_normalizes_to_zero(&r->z) & ~a->infinity;
secp256k1_fe_add(&t, &q); /* t = Ralt^2 + Q (2) */ secp256k1_fe_add(&t, &q); /* t = Ralt^2 + Q (2) */
r->x = t; /* r->x = X3 = Ralt^2 + Q (2) */ r->x = t; /* r->x = X3 = Ralt^2 + Q (2) */
secp256k1_fe_mul_int(&t, 2); /* t = 2*X3 (4) */ secp256k1_fe_mul_int(&t, 2); /* t = 2*X3 (4) */
@ -632,11 +640,28 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const
secp256k1_fe_negate(&r->y, &t, 3); /* r->y = -(Ralt*(2*X3 + Q) + M^3*Malt) (4) */ secp256k1_fe_negate(&r->y, &t, 3); /* r->y = -(Ralt*(2*X3 + Q) + M^3*Malt) (4) */
secp256k1_fe_half(&r->y); /* r->y = Y3 = -(Ralt*(2*X3 + Q) + M^3*Malt)/2 (3) */ secp256k1_fe_half(&r->y); /* r->y = Y3 = -(Ralt*(2*X3 + Q) + M^3*Malt)/2 (3) */
/** In case a->infinity == 1, replace r with (b->x, b->y, 1). */ /* In case a->infinity == 1, replace r with (b->x, b->y, 1). */
secp256k1_fe_cmov(&r->x, &b->x, a->infinity); secp256k1_fe_cmov(&r->x, &b->x, a->infinity);
secp256k1_fe_cmov(&r->y, &b->y, a->infinity); secp256k1_fe_cmov(&r->y, &b->y, a->infinity);
secp256k1_fe_cmov(&r->z, &secp256k1_fe_one, a->infinity); secp256k1_fe_cmov(&r->z, &secp256k1_fe_one, a->infinity);
r->infinity = infinity;
/* Set r->infinity if r->z is 0.
*
* If a->infinity is set, then r->infinity = (r->z == 0) = (1 == 0) = false,
* which is correct because the function assumes that b is not infinity.
*
* Now assume !a->infinity. This implies Z = Z1 != 0.
*
* Case y1 = -y2:
* In this case we could have a = -b, namely if x1 = x2.
* We have degenerate = true, r->z = (x1 - x2) * Z.
* Then r->infinity = ((x1 - x2)Z == 0) = (x1 == x2) = (a == -b).
*
* Case y1 != -y2:
* In this case, we can't have a = -b.
* We have degenerate = false, r->z = (y1 + y2) * Z.
* Then r->infinity = ((y1 + y2)Z == 0) = (y1 == -y2) = false. */
r->infinity = secp256k1_fe_normalizes_to_zero(&r->z);
} }
static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) { static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) {

View File

@ -80,10 +80,10 @@ static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_
/* Compare two 128-bit values for equality. */ /* Compare two 128-bit values for equality. */
static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b); static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b);
/* Tests if r is equal to 2^n. /* Tests if r is equal to sign*2^n (sign must be 1 or -1).
* n must be strictly less than 127. * n must be strictly less than 127.
*/ */
static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n); static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n, int sign);
#endif #endif

View File

@ -84,9 +84,10 @@ static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, con
return *a == *b; return *a == *b;
} }
static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n) { static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n, int sign) {
VERIFY_CHECK(n < 127); VERIFY_CHECK(n < 127);
return (*r == (int128_t)1 << n); VERIFY_CHECK(sign == 1 || sign == -1);
return (*r == (int128_t)((uint128_t)sign << n));
} }
#endif #endif

View File

@ -189,10 +189,11 @@ static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, con
return a->hi == b->hi && a->lo == b->lo; return a->hi == b->hi && a->lo == b->lo;
} }
static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n) { static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n, int sign) {
VERIFY_CHECK(n < 127); VERIFY_CHECK(n < 127);
return n >= 64 ? r->hi == (uint64_t)1 << (n - 64) && r->lo == 0 VERIFY_CHECK(sign == 1 || sign == -1);
: r->hi == 0 && r->lo == (uint64_t)1 << n; return n >= 64 ? r->hi == (uint64_t)sign << (n - 64) && r->lo == 0
: r->hi == (uint64_t)((sign - 1) >> 1) && r->lo == (uint64_t)sign << n;
} }
#endif #endif

View File

@ -35,4 +35,9 @@ static void secp256k1_modinv32_var(secp256k1_modinv32_signed30 *x, const secp256
/* Same as secp256k1_modinv32_var, but constant time in x (not in the modulus). */ /* Same as secp256k1_modinv32_var, but constant time in x (not in the modulus). */
static void secp256k1_modinv32(secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo); static void secp256k1_modinv32(secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo);
/* Compute the Jacobi symbol for (x | modinfo->modulus). x must be coprime with modulus (and thus
* cannot be 0, as modulus >= 3). All limbs of x must be non-negative. Returns 0 if the result
* cannot be computed. */
static int secp256k1_jacobi32_maybe_var(const secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo);
#endif /* SECP256K1_MODINV32_H */ #endif /* SECP256K1_MODINV32_H */

View File

@ -235,19 +235,8 @@ static int32_t secp256k1_modinv32_divsteps_30(int32_t zeta, uint32_t f0, uint32_
return zeta; return zeta;
} }
/* Compute the transition matrix and eta for 30 divsteps (variable time). /* inv256[i] = -(2*i+1)^-1 (mod 256) */
* static const uint8_t secp256k1_modinv32_inv256[128] = {
* Input: eta: initial eta
* f0: bottom limb of initial f
* g0: bottom limb of initial g
* Output: t: transition matrix
* Return: final eta
*
* Implements the divsteps_n_matrix_var function from the explanation.
*/
static int32_t secp256k1_modinv32_divsteps_30_var(int32_t eta, uint32_t f0, uint32_t g0, secp256k1_modinv32_trans2x2 *t) {
/* inv256[i] = -(2*i+1)^-1 (mod 256) */
static const uint8_t inv256[128] = {
0xFF, 0x55, 0x33, 0x49, 0xC7, 0x5D, 0x3B, 0x11, 0x0F, 0xE5, 0xC3, 0x59, 0xFF, 0x55, 0x33, 0x49, 0xC7, 0x5D, 0x3B, 0x11, 0x0F, 0xE5, 0xC3, 0x59,
0xD7, 0xED, 0xCB, 0x21, 0x1F, 0x75, 0x53, 0x69, 0xE7, 0x7D, 0x5B, 0x31, 0xD7, 0xED, 0xCB, 0x21, 0x1F, 0x75, 0x53, 0x69, 0xE7, 0x7D, 0x5B, 0x31,
0x2F, 0x05, 0xE3, 0x79, 0xF7, 0x0D, 0xEB, 0x41, 0x3F, 0x95, 0x73, 0x89, 0x2F, 0x05, 0xE3, 0x79, 0xF7, 0x0D, 0xEB, 0x41, 0x3F, 0x95, 0x73, 0x89,
@ -259,8 +248,19 @@ static int32_t secp256k1_modinv32_divsteps_30_var(int32_t eta, uint32_t f0, uint
0xBF, 0x15, 0xF3, 0x09, 0x87, 0x1D, 0xFB, 0xD1, 0xCF, 0xA5, 0x83, 0x19, 0xBF, 0x15, 0xF3, 0x09, 0x87, 0x1D, 0xFB, 0xD1, 0xCF, 0xA5, 0x83, 0x19,
0x97, 0xAD, 0x8B, 0xE1, 0xDF, 0x35, 0x13, 0x29, 0xA7, 0x3D, 0x1B, 0xF1, 0x97, 0xAD, 0x8B, 0xE1, 0xDF, 0x35, 0x13, 0x29, 0xA7, 0x3D, 0x1B, 0xF1,
0xEF, 0xC5, 0xA3, 0x39, 0xB7, 0xCD, 0xAB, 0x01 0xEF, 0xC5, 0xA3, 0x39, 0xB7, 0xCD, 0xAB, 0x01
}; };
/* Compute the transition matrix and eta for 30 divsteps (variable time).
*
* Input: eta: initial eta
* f0: bottom limb of initial f
* g0: bottom limb of initial g
* Output: t: transition matrix
* Return: final eta
*
* Implements the divsteps_n_matrix_var function from the explanation.
*/
static int32_t secp256k1_modinv32_divsteps_30_var(int32_t eta, uint32_t f0, uint32_t g0, secp256k1_modinv32_trans2x2 *t) {
/* Transformation matrix; see comments in secp256k1_modinv32_divsteps_30. */ /* Transformation matrix; see comments in secp256k1_modinv32_divsteps_30. */
uint32_t u = 1, v = 0, q = 0, r = 1; uint32_t u = 1, v = 0, q = 0, r = 1;
uint32_t f = f0, g = g0, m; uint32_t f = f0, g = g0, m;
@ -300,7 +300,7 @@ static int32_t secp256k1_modinv32_divsteps_30_var(int32_t eta, uint32_t f0, uint
VERIFY_CHECK(limit > 0 && limit <= 30); VERIFY_CHECK(limit > 0 && limit <= 30);
m = (UINT32_MAX >> (32 - limit)) & 255U; m = (UINT32_MAX >> (32 - limit)) & 255U;
/* Find what multiple of f must be added to g to cancel its bottom min(limit, 8) bits. */ /* Find what multiple of f must be added to g to cancel its bottom min(limit, 8) bits. */
w = (g * inv256[(f >> 1) & 127]) & m; w = (g * secp256k1_modinv32_inv256[(f >> 1) & 127]) & m;
/* Do so. */ /* Do so. */
g += f * w; g += f * w;
q += u * w; q += u * w;
@ -320,6 +320,86 @@ static int32_t secp256k1_modinv32_divsteps_30_var(int32_t eta, uint32_t f0, uint
return eta; return eta;
} }
/* Compute the transition matrix and eta for 30 posdivsteps (variable time, eta=-delta), and keeps track
* of the Jacobi symbol along the way. f0 and g0 must be f and g mod 2^32 rather than 2^30, because
* Jacobi tracking requires knowing (f mod 8) rather than just (f mod 2).
*
* Input: eta: initial eta
* f0: bottom limb of initial f
* g0: bottom limb of initial g
* Output: t: transition matrix
* Input/Output: (*jacp & 1) is bitflipped if and only if the Jacobi symbol of (f | g) changes sign
* by applying the returned transformation matrix to it. The other bits of *jacp may
* change, but are meaningless.
* Return: final eta
*/
static int32_t secp256k1_modinv32_posdivsteps_30_var(int32_t eta, uint32_t f0, uint32_t g0, secp256k1_modinv32_trans2x2 *t, int *jacp) {
/* Transformation matrix. */
uint32_t u = 1, v = 0, q = 0, r = 1;
uint32_t f = f0, g = g0, m;
uint16_t w;
int i = 30, limit, zeros;
int jac = *jacp;
for (;;) {
/* Use a sentinel bit to count zeros only up to i. */
zeros = secp256k1_ctz32_var(g | (UINT32_MAX << i));
/* Perform zeros divsteps at once; they all just divide g by two. */
g >>= zeros;
u <<= zeros;
v <<= zeros;
eta -= zeros;
i -= zeros;
/* Update the bottom bit of jac: when dividing g by an odd power of 2,
* if (f mod 8) is 3 or 5, the Jacobi symbol changes sign. */
jac ^= (zeros & ((f >> 1) ^ (f >> 2)));
/* We're done once we've done 30 posdivsteps. */
if (i == 0) break;
VERIFY_CHECK((f & 1) == 1);
VERIFY_CHECK((g & 1) == 1);
VERIFY_CHECK((u * f0 + v * g0) == f << (30 - i));
VERIFY_CHECK((q * f0 + r * g0) == g << (30 - i));
/* If eta is negative, negate it and replace f,g with g,f. */
if (eta < 0) {
uint32_t tmp;
eta = -eta;
/* Update bottom bit of jac: when swapping f and g, the Jacobi symbol changes sign
* if both f and g are 3 mod 4. */
jac ^= ((f & g) >> 1);
tmp = f; f = g; g = tmp;
tmp = u; u = q; q = tmp;
tmp = v; v = r; r = tmp;
}
/* eta is now >= 0. In what follows we're going to cancel out the bottom bits of g. No more
* than i can be cancelled out (as we'd be done before that point), and no more than eta+1
* can be done as its sign will flip once that happens. */
limit = ((int)eta + 1) > i ? i : ((int)eta + 1);
/* m is a mask for the bottom min(limit, 8) bits (our table only supports 8 bits). */
VERIFY_CHECK(limit > 0 && limit <= 30);
m = (UINT32_MAX >> (32 - limit)) & 255U;
/* Find what multiple of f must be added to g to cancel its bottom min(limit, 8) bits. */
w = (g * secp256k1_modinv32_inv256[(f >> 1) & 127]) & m;
/* Do so. */
g += f * w;
q += u * w;
r += v * w;
VERIFY_CHECK((g & m) == 0);
}
/* Return data in t and return value. */
t->u = (int32_t)u;
t->v = (int32_t)v;
t->q = (int32_t)q;
t->r = (int32_t)r;
/* The determinant of t must be a power of two. This guarantees that multiplication with t
* does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which
* will be divided out again). As each divstep's individual matrix has determinant 2 or -2,
* the aggregate of 30 of them will have determinant 2^30 or -2^30. */
VERIFY_CHECK((int64_t)t->u * t->r - (int64_t)t->v * t->q == ((int64_t)1) << 30 ||
(int64_t)t->u * t->r - (int64_t)t->v * t->q == -(((int64_t)1) << 30));
*jacp = jac;
return eta;
}
/* Compute (t/2^30) * [d, e] mod modulus, where t is a transition matrix for 30 divsteps. /* Compute (t/2^30) * [d, e] mod modulus, where t is a transition matrix for 30 divsteps.
* *
* On input and output, d and e are in range (-2*modulus,modulus). All output limbs will be in range * On input and output, d and e are in range (-2*modulus,modulus). All output limbs will be in range
@ -338,10 +418,8 @@ static void secp256k1_modinv32_update_de_30(secp256k1_modinv32_signed30 *d, secp
VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(d, 9, &modinfo->modulus, 1) < 0); /* d < modulus */ VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(d, 9, &modinfo->modulus, 1) < 0); /* d < modulus */
VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(e, 9, &modinfo->modulus, -2) > 0); /* e > -2*modulus */ VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(e, 9, &modinfo->modulus, -2) > 0); /* e > -2*modulus */
VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(e, 9, &modinfo->modulus, 1) < 0); /* e < modulus */ VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(e, 9, &modinfo->modulus, 1) < 0); /* e < modulus */
VERIFY_CHECK((labs(u) + labs(v)) >= 0); /* |u|+|v| doesn't overflow */ VERIFY_CHECK(labs(u) <= (M30 + 1 - labs(v))); /* |u|+|v| <= 2^30 */
VERIFY_CHECK((labs(q) + labs(r)) >= 0); /* |q|+|r| doesn't overflow */ VERIFY_CHECK(labs(q) <= (M30 + 1 - labs(r))); /* |q|+|r| <= 2^30 */
VERIFY_CHECK((labs(u) + labs(v)) <= M30 + 1); /* |u|+|v| <= 2^30 */
VERIFY_CHECK((labs(q) + labs(r)) <= M30 + 1); /* |q|+|r| <= 2^30 */
#endif #endif
/* [md,me] start as zero; plus [u,q] if d is negative; plus [v,r] if e is negative. */ /* [md,me] start as zero; plus [u,q] if d is negative; plus [v,r] if e is negative. */
sd = d->v[8] >> 31; sd = d->v[8] >> 31;
@ -587,4 +665,74 @@ static void secp256k1_modinv32_var(secp256k1_modinv32_signed30 *x, const secp256
*x = d; *x = d;
} }
/* Do up to 50 iterations of 30 posdivsteps (up to 1500 steps; more is extremely rare) each until f=1.
* In VERIFY mode use a lower number of iterations (750, close to the median 756), so failure actually occurs. */
#ifdef VERIFY
#define JACOBI32_ITERATIONS 25
#else
#define JACOBI32_ITERATIONS 50
#endif
/* Compute the Jacobi symbol of x modulo modinfo->modulus (variable time). gcd(x,modulus) must be 1. */
static int secp256k1_jacobi32_maybe_var(const secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo) {
/* Start with f=modulus, g=x, eta=-1. */
secp256k1_modinv32_signed30 f = modinfo->modulus;
secp256k1_modinv32_signed30 g = *x;
int j, len = 9;
int32_t eta = -1; /* eta = -delta; delta is initially 1 */
int32_t cond, fn, gn;
int jac = 0;
int count;
/* The input limbs must all be non-negative. */
VERIFY_CHECK(g.v[0] >= 0 && g.v[1] >= 0 && g.v[2] >= 0 && g.v[3] >= 0 && g.v[4] >= 0 && g.v[5] >= 0 && g.v[6] >= 0 && g.v[7] >= 0 && g.v[8] >= 0);
/* If x > 0, then if the loop below converges, it converges to f=g=gcd(x,modulus). Since we
* require that gcd(x,modulus)=1 and modulus>=3, x cannot be 0. Thus, we must reach f=1 (or
* time out). */
VERIFY_CHECK((g.v[0] | g.v[1] | g.v[2] | g.v[3] | g.v[4] | g.v[5] | g.v[6] | g.v[7] | g.v[8]) != 0);
for (count = 0; count < JACOBI32_ITERATIONS; ++count) {
/* Compute transition matrix and new eta after 30 posdivsteps. */
secp256k1_modinv32_trans2x2 t;
eta = secp256k1_modinv32_posdivsteps_30_var(eta, f.v[0] | ((uint32_t)f.v[1] << 30), g.v[0] | ((uint32_t)g.v[1] << 30), &t, &jac);
/* Update f,g using that transition matrix. */
#ifdef VERIFY
VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 0) > 0); /* f > 0 */
VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */
VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 0) > 0); /* g > 0 */
VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */
#endif
secp256k1_modinv32_update_fg_30_var(len, &f, &g, &t);
/* If the bottom limb of f is 1, there is a chance that f=1. */
if (f.v[0] == 1) {
cond = 0;
/* Check if the other limbs are also 0. */
for (j = 1; j < len; ++j) {
cond |= f.v[j];
}
/* If so, we're done. If f=1, the Jacobi symbol (g | f)=1. */
if (cond == 0) return 1 - 2*(jac & 1);
}
/* Determine if len>1 and limb (len-1) of both f and g is 0. */
fn = f.v[len - 1];
gn = g.v[len - 1];
cond = ((int32_t)len - 2) >> 31;
cond |= fn;
cond |= gn;
/* If so, reduce length. */
if (cond == 0) --len;
#ifdef VERIFY
VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 0) > 0); /* f > 0 */
VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */
VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 0) > 0); /* g > 0 */
VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */
#endif
}
/* The loop failed to converge to f=g after 1500 iterations. Return 0, indicating unknown result. */
return 0;
}
#endif /* SECP256K1_MODINV32_IMPL_H */ #endif /* SECP256K1_MODINV32_IMPL_H */

View File

@ -39,4 +39,9 @@ static void secp256k1_modinv64_var(secp256k1_modinv64_signed62 *x, const secp256
/* Same as secp256k1_modinv64_var, but constant time in x (not in the modulus). */ /* Same as secp256k1_modinv64_var, but constant time in x (not in the modulus). */
static void secp256k1_modinv64(secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo); static void secp256k1_modinv64(secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo);
/* Compute the Jacobi symbol for (x | modinfo->modulus). x must be coprime with modulus (and thus
* cannot be 0, as modulus >= 3). All limbs of x must be non-negative. Returns 0 if the result
* cannot be computed. */
static int secp256k1_jacobi64_maybe_var(const secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo);
#endif /* SECP256K1_MODINV64_H */ #endif /* SECP256K1_MODINV64_H */

View File

@ -71,11 +71,13 @@ static int secp256k1_modinv64_mul_cmp_62(const secp256k1_modinv64_signed62 *a, i
return 0; return 0;
} }
/* Check if the determinant of t is equal to 1 << n. */ /* Check if the determinant of t is equal to 1 << n. If abs, check if |det t| == 1 << n. */
static int secp256k1_modinv64_det_check_pow2(const secp256k1_modinv64_trans2x2 *t, unsigned int n) { static int secp256k1_modinv64_det_check_pow2(const secp256k1_modinv64_trans2x2 *t, unsigned int n, int abs) {
secp256k1_int128 a; secp256k1_int128 a;
secp256k1_i128_det(&a, t->u, t->v, t->q, t->r); secp256k1_i128_det(&a, t->u, t->v, t->q, t->r);
return secp256k1_i128_check_pow2(&a, n); if (secp256k1_i128_check_pow2(&a, n, 1)) return 1;
if (abs && secp256k1_i128_check_pow2(&a, n, -1)) return 1;
return 0;
} }
#endif #endif
@ -221,7 +223,7 @@ static int64_t secp256k1_modinv64_divsteps_59(int64_t zeta, uint64_t f0, uint64_
* aggregate of 59 of them will have determinant 2^59. Multiplying with the initial * aggregate of 59 of them will have determinant 2^59. Multiplying with the initial
* 8*identity (which has determinant 2^6) means the overall outputs has determinant * 8*identity (which has determinant 2^6) means the overall outputs has determinant
* 2^65. */ * 2^65. */
VERIFY_CHECK(secp256k1_modinv64_det_check_pow2(t, 65)); VERIFY_CHECK(secp256k1_modinv64_det_check_pow2(t, 65, 0));
#endif #endif
return zeta; return zeta;
} }
@ -269,7 +271,7 @@ static int64_t secp256k1_modinv64_divsteps_62_var(int64_t eta, uint64_t f0, uint
tmp = v; v = r; r = -tmp; tmp = v; v = r; r = -tmp;
/* Use a formula to cancel out up to 6 bits of g. Also, no more than i can be cancelled /* Use a formula to cancel out up to 6 bits of g. Also, no more than i can be cancelled
* out (as we'd be done before that point), and no more than eta+1 can be done as its * out (as we'd be done before that point), and no more than eta+1 can be done as its
* will flip again once that happens. */ * sign will flip again once that happens. */
limit = ((int)eta + 1) > i ? i : ((int)eta + 1); limit = ((int)eta + 1) > i ? i : ((int)eta + 1);
VERIFY_CHECK(limit > 0 && limit <= 62); VERIFY_CHECK(limit > 0 && limit <= 62);
/* m is a mask for the bottom min(limit, 6) bits. */ /* m is a mask for the bottom min(limit, 6) bits. */
@ -304,11 +306,103 @@ static int64_t secp256k1_modinv64_divsteps_62_var(int64_t eta, uint64_t f0, uint
* does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which * does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which
* will be divided out again). As each divstep's individual matrix has determinant 2, the * will be divided out again). As each divstep's individual matrix has determinant 2, the
* aggregate of 62 of them will have determinant 2^62. */ * aggregate of 62 of them will have determinant 2^62. */
VERIFY_CHECK(secp256k1_modinv64_det_check_pow2(t, 62)); VERIFY_CHECK(secp256k1_modinv64_det_check_pow2(t, 62, 0));
#endif #endif
return eta; return eta;
} }
/* Compute the transition matrix and eta for 62 posdivsteps (variable time, eta=-delta), and keeps track
* of the Jacobi symbol along the way. f0 and g0 must be f and g mod 2^64 rather than 2^62, because
* Jacobi tracking requires knowing (f mod 8) rather than just (f mod 2).
*
* Input: eta: initial eta
* f0: bottom limb of initial f
* g0: bottom limb of initial g
* Output: t: transition matrix
* Input/Output: (*jacp & 1) is bitflipped if and only if the Jacobi symbol of (f | g) changes sign
* by applying the returned transformation matrix to it. The other bits of *jacp may
* change, but are meaningless.
* Return: final eta
*/
static int64_t secp256k1_modinv64_posdivsteps_62_var(int64_t eta, uint64_t f0, uint64_t g0, secp256k1_modinv64_trans2x2 *t, int *jacp) {
/* Transformation matrix; see comments in secp256k1_modinv64_divsteps_62. */
uint64_t u = 1, v = 0, q = 0, r = 1;
uint64_t f = f0, g = g0, m;
uint32_t w;
int i = 62, limit, zeros;
int jac = *jacp;
for (;;) {
/* Use a sentinel bit to count zeros only up to i. */
zeros = secp256k1_ctz64_var(g | (UINT64_MAX << i));
/* Perform zeros divsteps at once; they all just divide g by two. */
g >>= zeros;
u <<= zeros;
v <<= zeros;
eta -= zeros;
i -= zeros;
/* Update the bottom bit of jac: when dividing g by an odd power of 2,
* if (f mod 8) is 3 or 5, the Jacobi symbol changes sign. */
jac ^= (zeros & ((f >> 1) ^ (f >> 2)));
/* We're done once we've done 62 posdivsteps. */
if (i == 0) break;
VERIFY_CHECK((f & 1) == 1);
VERIFY_CHECK((g & 1) == 1);
VERIFY_CHECK((u * f0 + v * g0) == f << (62 - i));
VERIFY_CHECK((q * f0 + r * g0) == g << (62 - i));
/* If eta is negative, negate it and replace f,g with g,f. */
if (eta < 0) {
uint64_t tmp;
eta = -eta;
tmp = f; f = g; g = tmp;
tmp = u; u = q; q = tmp;
tmp = v; v = r; r = tmp;
/* Update bottom bit of jac: when swapping f and g, the Jacobi symbol changes sign
* if both f and g are 3 mod 4. */
jac ^= ((f & g) >> 1);
/* Use a formula to cancel out up to 6 bits of g. Also, no more than i can be cancelled
* out (as we'd be done before that point), and no more than eta+1 can be done as its
* sign will flip again once that happens. */
limit = ((int)eta + 1) > i ? i : ((int)eta + 1);
VERIFY_CHECK(limit > 0 && limit <= 62);
/* m is a mask for the bottom min(limit, 6) bits. */
m = (UINT64_MAX >> (64 - limit)) & 63U;
/* Find what multiple of f must be added to g to cancel its bottom min(limit, 6)
* bits. */
w = (f * g * (f * f - 2)) & m;
} else {
/* In this branch, use a simpler formula that only lets us cancel up to 4 bits of g, as
* eta tends to be smaller here. */
limit = ((int)eta + 1) > i ? i : ((int)eta + 1);
VERIFY_CHECK(limit > 0 && limit <= 62);
/* m is a mask for the bottom min(limit, 4) bits. */
m = (UINT64_MAX >> (64 - limit)) & 15U;
/* Find what multiple of f must be added to g to cancel its bottom min(limit, 4)
* bits. */
w = f + (((f + 1) & 4) << 1);
w = (-w * g) & m;
}
g += f * w;
q += u * w;
r += v * w;
VERIFY_CHECK((g & m) == 0);
}
/* Return data in t and return value. */
t->u = (int64_t)u;
t->v = (int64_t)v;
t->q = (int64_t)q;
t->r = (int64_t)r;
#ifdef VERIFY
/* The determinant of t must be a power of two. This guarantees that multiplication with t
* does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which
* will be divided out again). As each divstep's individual matrix has determinant 2 or -2,
* the aggregate of 62 of them will have determinant 2^62 or -2^62. */
VERIFY_CHECK(secp256k1_modinv64_det_check_pow2(t, 62, 1));
#endif
*jacp = jac;
return eta;
}
/* Compute (t/2^62) * [d, e] mod modulus, where t is a transition matrix scaled by 2^62. /* Compute (t/2^62) * [d, e] mod modulus, where t is a transition matrix scaled by 2^62.
* *
* On input and output, d and e are in range (-2*modulus,modulus). All output limbs will be in range * On input and output, d and e are in range (-2*modulus,modulus). All output limbs will be in range
@ -328,10 +422,8 @@ static void secp256k1_modinv64_update_de_62(secp256k1_modinv64_signed62 *d, secp
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, 1) < 0); /* d < modulus */ VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, 1) < 0); /* d < modulus */
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(e, 5, &modinfo->modulus, -2) > 0); /* e > -2*modulus */ VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(e, 5, &modinfo->modulus, -2) > 0); /* e > -2*modulus */
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(e, 5, &modinfo->modulus, 1) < 0); /* e < modulus */ VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(e, 5, &modinfo->modulus, 1) < 0); /* e < modulus */
VERIFY_CHECK((secp256k1_modinv64_abs(u) + secp256k1_modinv64_abs(v)) >= 0); /* |u|+|v| doesn't overflow */ VERIFY_CHECK(secp256k1_modinv64_abs(u) <= (((int64_t)1 << 62) - secp256k1_modinv64_abs(v))); /* |u|+|v| <= 2^62 */
VERIFY_CHECK((secp256k1_modinv64_abs(q) + secp256k1_modinv64_abs(r)) >= 0); /* |q|+|r| doesn't overflow */ VERIFY_CHECK(secp256k1_modinv64_abs(q) <= (((int64_t)1 << 62) - secp256k1_modinv64_abs(r))); /* |q|+|r| <= 2^62 */
VERIFY_CHECK((secp256k1_modinv64_abs(u) + secp256k1_modinv64_abs(v)) <= (int64_t)1 << 62); /* |u|+|v| <= 2^62 */
VERIFY_CHECK((secp256k1_modinv64_abs(q) + secp256k1_modinv64_abs(r)) <= (int64_t)1 << 62); /* |q|+|r| <= 2^62 */
#endif #endif
/* [md,me] start as zero; plus [u,q] if d is negative; plus [v,r] if e is negative. */ /* [md,me] start as zero; plus [u,q] if d is negative; plus [v,r] if e is negative. */
sd = d4 >> 63; sd = d4 >> 63;
@ -629,4 +721,74 @@ static void secp256k1_modinv64_var(secp256k1_modinv64_signed62 *x, const secp256
*x = d; *x = d;
} }
/* Do up to 25 iterations of 62 posdivsteps (up to 1550 steps; more is extremely rare) each until f=1.
* In VERIFY mode use a lower number of iterations (744, close to the median 756), so failure actually occurs. */
#ifdef VERIFY
#define JACOBI64_ITERATIONS 12
#else
#define JACOBI64_ITERATIONS 25
#endif
/* Compute the Jacobi symbol of x modulo modinfo->modulus (variable time). gcd(x,modulus) must be 1. */
static int secp256k1_jacobi64_maybe_var(const secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo) {
/* Start with f=modulus, g=x, eta=-1. */
secp256k1_modinv64_signed62 f = modinfo->modulus;
secp256k1_modinv64_signed62 g = *x;
int j, len = 5;
int64_t eta = -1; /* eta = -delta; delta is initially 1 */
int64_t cond, fn, gn;
int jac = 0;
int count;
/* The input limbs must all be non-negative. */
VERIFY_CHECK(g.v[0] >= 0 && g.v[1] >= 0 && g.v[2] >= 0 && g.v[3] >= 0 && g.v[4] >= 0);
/* If x > 0, then if the loop below converges, it converges to f=g=gcd(x,modulus). Since we
* require that gcd(x,modulus)=1 and modulus>=3, x cannot be 0. Thus, we must reach f=1 (or
* time out). */
VERIFY_CHECK((g.v[0] | g.v[1] | g.v[2] | g.v[3] | g.v[4]) != 0);
for (count = 0; count < JACOBI64_ITERATIONS; ++count) {
/* Compute transition matrix and new eta after 62 posdivsteps. */
secp256k1_modinv64_trans2x2 t;
eta = secp256k1_modinv64_posdivsteps_62_var(eta, f.v[0] | ((uint64_t)f.v[1] << 62), g.v[0] | ((uint64_t)g.v[1] << 62), &t, &jac);
/* Update f,g using that transition matrix. */
#ifdef VERIFY
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 0) > 0); /* f > 0 */
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 0) > 0); /* g > 0 */
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */
#endif
secp256k1_modinv64_update_fg_62_var(len, &f, &g, &t);
/* If the bottom limb of f is 1, there is a chance that f=1. */
if (f.v[0] == 1) {
cond = 0;
/* Check if the other limbs are also 0. */
for (j = 1; j < len; ++j) {
cond |= f.v[j];
}
/* If so, we're done. When f=1, the Jacobi symbol (g | f)=1. */
if (cond == 0) return 1 - 2*(jac & 1);
}
/* Determine if len>1 and limb (len-1) of both f and g is 0. */
fn = f.v[len - 1];
gn = g.v[len - 1];
cond = ((int64_t)len - 2) >> 63;
cond |= fn;
cond |= gn;
/* If so, reduce length. */
if (cond == 0) --len;
#ifdef VERIFY
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 0) > 0); /* f > 0 */
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 0) > 0); /* g > 0 */
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */
#endif
}
/* The loop failed to converge to f=g after 1550 iterations. Return 0, indicating unknown result. */
return 0;
}
#endif /* SECP256K1_MODINV64_IMPL_H */ #endif /* SECP256K1_MODINV64_IMPL_H */

View File

@ -160,7 +160,7 @@ static void test_bppp_tagged_hash(void) {
} }
} }
void test_log_exp(void) { static void test_log_exp(void) {
CHECK(secp256k1_is_power_of_two(0) == 0); CHECK(secp256k1_is_power_of_two(0) == 0);
CHECK(secp256k1_is_power_of_two(1) == 1); CHECK(secp256k1_is_power_of_two(1) == 1);
CHECK(secp256k1_is_power_of_two(2) == 1); CHECK(secp256k1_is_power_of_two(2) == 1);
@ -175,7 +175,7 @@ void test_log_exp(void) {
CHECK(secp256k1_bppp_log2(257) == 8); CHECK(secp256k1_bppp_log2(257) == 8);
} }
void test_norm_util_helpers(void) { static void test_norm_util_helpers(void) {
secp256k1_scalar a_vec[4], b_vec[4], rho_pows[4], res, res2, mu, rho; secp256k1_scalar a_vec[4], b_vec[4], rho_pows[4], res, res2, mu, rho;
int i; int i;
/* a = {1, 2, 3, 4} b = {5, 6, 7, 8}, mu = 4, rho = 2 */ /* a = {1, 2, 3, 4} b = {5, 6, 7, 8}, mu = 4, rho = 2 */
@ -213,7 +213,7 @@ void test_norm_util_helpers(void) {
} }
void test_serialize_two_points_roundtrip(secp256k1_ge *X, secp256k1_ge *R) { static void test_serialize_two_points_roundtrip(secp256k1_ge *X, secp256k1_ge *R) {
secp256k1_ge X_tmp, R_tmp; secp256k1_ge X_tmp, R_tmp;
unsigned char buf[65]; unsigned char buf[65];
secp256k1_bppp_serialize_points(buf, X, R); secp256k1_bppp_serialize_points(buf, X, R);
@ -223,7 +223,7 @@ void test_serialize_two_points_roundtrip(secp256k1_ge *X, secp256k1_ge *R) {
ge_equals_ge(R, &R_tmp); ge_equals_ge(R, &R_tmp);
} }
void test_serialize_two_points(void) { static void test_serialize_two_points(void) {
secp256k1_ge X, R; secp256k1_ge X, R;
int i; int i;
@ -453,7 +453,7 @@ static int secp256k1_norm_arg_verify(
} }
/* Verify |c| = 0 */ /* Verify |c| = 0 */
void norm_arg_verify_zero_len(void) { static void norm_arg_verify_zero_len(void) {
secp256k1_scalar n_vec[64], l_vec[64], c_vec[64]; secp256k1_scalar n_vec[64], l_vec[64], c_vec[64];
secp256k1_scalar rho, mu; secp256k1_scalar rho, mu;
secp256k1_ge commit; secp256k1_ge commit;
@ -480,7 +480,7 @@ void norm_arg_verify_zero_len(void) {
secp256k1_scratch_space_destroy(CTX, scratch); secp256k1_scratch_space_destroy(CTX, scratch);
} }
void norm_arg_test(unsigned int n, unsigned int m) { static void norm_arg_test(unsigned int n, unsigned int m) {
secp256k1_scalar n_vec[64], l_vec[64], c_vec[64]; secp256k1_scalar n_vec[64], l_vec[64], c_vec[64];
secp256k1_scalar rho, mu; secp256k1_scalar rho, mu;
secp256k1_ge commit; secp256k1_ge commit;
@ -580,7 +580,7 @@ int norm_arg_verify_vectors_helper(secp256k1_scratch *scratch, const unsigned ch
#define IDX_TO_TEST(i) (norm_arg_verify_vectors_helper(scratch, verify_vector_gens, verify_vector_##i##_proof, sizeof(verify_vector_##i##_proof), verify_vector_##i##_r32, verify_vector_##i##_n_vec_len, verify_vector_##i##_c_vec32, verify_vector_##i##_c_vec, sizeof(verify_vector_##i##_c_vec)/sizeof(secp256k1_scalar), verify_vector_##i##_commit33) == verify_vector_##i##_result) #define IDX_TO_TEST(i) (norm_arg_verify_vectors_helper(scratch, verify_vector_gens, verify_vector_##i##_proof, sizeof(verify_vector_##i##_proof), verify_vector_##i##_r32, verify_vector_##i##_n_vec_len, verify_vector_##i##_c_vec32, verify_vector_##i##_c_vec, sizeof(verify_vector_##i##_c_vec)/sizeof(secp256k1_scalar), verify_vector_##i##_commit33) == verify_vector_##i##_result)
void norm_arg_verify_vectors(void) { static void norm_arg_verify_vectors(void) {
secp256k1_scratch *scratch = secp256k1_scratch_space_create(CTX, 1000*1000); /* shouldn't need much */ secp256k1_scratch *scratch = secp256k1_scratch_space_create(CTX, 1000*1000); /* shouldn't need much */
size_t alloc = scratch->alloc_size; size_t alloc = scratch->alloc_size;
@ -603,7 +603,7 @@ void norm_arg_verify_vectors(void) {
} }
#undef IDX_TO_TEST #undef IDX_TO_TEST
void norm_arg_prove_vectors_helper(secp256k1_scratch *scratch, const unsigned char *gens, const unsigned char *proof, size_t plen, const unsigned char *r32, const unsigned char n_vec32[][32], secp256k1_scalar *n_vec, size_t n_vec_len, const unsigned char l_vec32[][32], secp256k1_scalar *l_vec, const unsigned char c_vec32[][32], secp256k1_scalar *c_vec, size_t c_vec_len, int result) { static void norm_arg_prove_vectors_helper(secp256k1_scratch *scratch, const unsigned char *gens, const unsigned char *proof, size_t plen, const unsigned char *r32, const unsigned char n_vec32[][32], secp256k1_scalar *n_vec, size_t n_vec_len, const unsigned char l_vec32[][32], secp256k1_scalar *l_vec, const unsigned char c_vec32[][32], secp256k1_scalar *c_vec, size_t c_vec_len, int result) {
secp256k1_sha256 transcript; secp256k1_sha256 transcript;
secp256k1_bppp_generators *gs = bppp_generators_parse_regular(gens, 33*(n_vec_len + c_vec_len)); secp256k1_bppp_generators *gs = bppp_generators_parse_regular(gens, 33*(n_vec_len + c_vec_len));
secp256k1_scalar rho, mu; secp256k1_scalar rho, mu;
@ -651,7 +651,7 @@ void norm_arg_prove_vectors_helper(secp256k1_scratch *scratch, const unsigned ch
prove_vector_##i##_c_vec32, prove_vector_##i##_c_vec, sizeof(prove_vector_##i##_c_vec)/sizeof(secp256k1_scalar), \ prove_vector_##i##_c_vec32, prove_vector_##i##_c_vec, sizeof(prove_vector_##i##_c_vec)/sizeof(secp256k1_scalar), \
prove_vector_##i##_result)) prove_vector_##i##_result))
void norm_arg_prove_vectors(void) { static void norm_arg_prove_vectors(void) {
secp256k1_scratch *scratch = secp256k1_scratch_space_create(CTX, 1000*1000); /* shouldn't need much */ secp256k1_scratch *scratch = secp256k1_scratch_space_create(CTX, 1000*1000); /* shouldn't need much */
size_t alloc = scratch->alloc_size; size_t alloc = scratch->alloc_size;
@ -667,7 +667,7 @@ void norm_arg_prove_vectors(void) {
#undef IDX_TO_TEST #undef IDX_TO_TEST
void run_bppp_tests(void) { static void run_bppp_tests(void) {
test_log_exp(); test_log_exp();
test_norm_util_helpers(); test_norm_util_helpers();
test_serialize_two_points(); test_serialize_two_points();

View File

@ -42,7 +42,7 @@ static void bench_ecdh(void* arg, int iters) {
} }
} }
void run_ecdh_bench(int iters, int argc, char** argv) { static void run_ecdh_bench(int iters, int argc, char** argv) {
bench_ecdh_data data; bench_ecdh_data data;
int d = argc == 1; int d = argc == 1;

View File

@ -7,7 +7,7 @@
#ifndef SECP256K1_MODULE_ECDH_TESTS_H #ifndef SECP256K1_MODULE_ECDH_TESTS_H
#define SECP256K1_MODULE_ECDH_TESTS_H #define SECP256K1_MODULE_ECDH_TESTS_H
int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) { static int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
(void)output; (void)output;
(void)x; (void)x;
(void)y; (void)y;
@ -15,7 +15,7 @@ int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x,
return 0; return 0;
} }
int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) { static int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
(void)data; (void)data;
/* Save x and y as uncompressed public key */ /* Save x and y as uncompressed public key */
output[0] = 0x04; output[0] = 0x04;
@ -24,7 +24,7 @@ int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, con
return 1; return 1;
} }
void test_ecdh_api(void) { static void test_ecdh_api(void) {
/* Setup context that just counts errors */ /* Setup context that just counts errors */
secp256k1_context *tctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); secp256k1_context *tctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
secp256k1_pubkey point; secp256k1_pubkey point;
@ -53,7 +53,7 @@ void test_ecdh_api(void) {
secp256k1_context_destroy(tctx); secp256k1_context_destroy(tctx);
} }
void test_ecdh_generator_basepoint(void) { static void test_ecdh_generator_basepoint(void) {
unsigned char s_one[32] = { 0 }; unsigned char s_one[32] = { 0 };
secp256k1_pubkey point[2]; secp256k1_pubkey point[2];
int i; int i;
@ -94,7 +94,7 @@ void test_ecdh_generator_basepoint(void) {
} }
} }
void test_bad_scalar(void) { static void test_bad_scalar(void) {
unsigned char s_zero[32] = { 0 }; unsigned char s_zero[32] = { 0 };
unsigned char s_overflow[32] = { unsigned char s_overflow[32] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@ -124,7 +124,7 @@ void test_bad_scalar(void) {
} }
/** Test that ECDH(sG, 1/s) == ECDH((1/s)G, s) == ECDH(G, 1) for a few random s. */ /** Test that ECDH(sG, 1/s) == ECDH((1/s)G, s) == ECDH(G, 1) for a few random s. */
void test_result_basepoint(void) { static void test_result_basepoint(void) {
secp256k1_pubkey point; secp256k1_pubkey point;
secp256k1_scalar rand; secp256k1_scalar rand;
unsigned char s[32]; unsigned char s[32];
@ -155,7 +155,7 @@ void test_result_basepoint(void) {
} }
} }
void run_ecdh_tests(void) { static void run_ecdh_tests(void) {
test_ecdh_api(); test_ecdh_api();
test_ecdh_generator_basepoint(); test_ecdh_generator_basepoint();
test_bad_scalar(); test_bad_scalar();

View File

@ -3,13 +3,13 @@
#include "../../../include/secp256k1_ecdsa_adaptor.h" #include "../../../include/secp256k1_ecdsa_adaptor.h"
void rand_scalar(secp256k1_scalar *scalar) { static void rand_scalar(secp256k1_scalar *scalar) {
unsigned char buf32[32]; unsigned char buf32[32];
secp256k1_testrand256(buf32); secp256k1_testrand256(buf32);
secp256k1_scalar_set_b32(scalar, buf32, NULL); secp256k1_scalar_set_b32(scalar, buf32, NULL);
} }
void rand_point(secp256k1_ge *point) { static void rand_point(secp256k1_ge *point) {
secp256k1_scalar x; secp256k1_scalar x;
secp256k1_gej pointj; secp256k1_gej pointj;
rand_scalar(&x); rand_scalar(&x);
@ -18,7 +18,7 @@ void rand_point(secp256k1_ge *point) {
secp256k1_ge_set_gej(point, &pointj); secp256k1_ge_set_gej(point, &pointj);
} }
void dleq_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) { static void dleq_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) {
secp256k1_scalar k1, k2; secp256k1_scalar k1, k2;
CHECK(secp256k1_dleq_nonce(&k1, args[0], args[1], args[2], args[3], NULL, args[4]) == 1); CHECK(secp256k1_dleq_nonce(&k1, args[0], args[1], args[2], args[3], NULL, args[4]) == 1);
@ -27,7 +27,7 @@ void dleq_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) {
CHECK(secp256k1_scalar_eq(&k1, &k2) == 0); CHECK(secp256k1_scalar_eq(&k1, &k2) == 0);
} }
void dleq_tests(void) { static void dleq_tests(void) {
secp256k1_scalar s, e, sk, k; secp256k1_scalar s, e, sk, k;
secp256k1_ge gen2, p1, p2; secp256k1_ge gen2, p1, p2;
unsigned char *args[5]; unsigned char *args[5];
@ -100,13 +100,13 @@ void dleq_tests(void) {
CHECK(secp256k1_dleq_nonce(&k, sk32, gen2_33, p1_33, p2_33, NULL, NULL) == 1); CHECK(secp256k1_dleq_nonce(&k, sk32, gen2_33, p1_33, p2_33, NULL, NULL) == 1);
} }
void rand_flip_bit(unsigned char *array, size_t n) { static void rand_flip_bit(unsigned char *array, size_t n) {
array[secp256k1_testrand_int(n)] ^= 1 << secp256k1_testrand_int(8); array[secp256k1_testrand_int(n)] ^= 1 << secp256k1_testrand_int(8);
} }
/* Helper function for test_ecdsa_adaptor_spec_vectors /* Helper function for test_ecdsa_adaptor_spec_vectors
* Checks that the adaptor signature is valid for the public and encryption keys. */ * Checks that the adaptor signature is valid for the public and encryption keys. */
void test_ecdsa_adaptor_spec_vectors_check_verify(const unsigned char *adaptor_sig162, const unsigned char *msg32, const unsigned char *pubkey33, const unsigned char *encryption_key33, int expected) { static void test_ecdsa_adaptor_spec_vectors_check_verify(const unsigned char *adaptor_sig162, const unsigned char *msg32, const unsigned char *pubkey33, const unsigned char *encryption_key33, int expected) {
secp256k1_pubkey pubkey; secp256k1_pubkey pubkey;
secp256k1_ge pubkey_ge; secp256k1_ge pubkey_ge;
secp256k1_pubkey encryption_key; secp256k1_pubkey encryption_key;
@ -122,7 +122,7 @@ void test_ecdsa_adaptor_spec_vectors_check_verify(const unsigned char *adaptor_s
/* Helper function for test_ecdsa_adaptor_spec_vectors /* Helper function for test_ecdsa_adaptor_spec_vectors
* Checks that the signature can be decrypted from the adaptor signature and the decryption key. */ * Checks that the signature can be decrypted from the adaptor signature and the decryption key. */
void test_ecdsa_adaptor_spec_vectors_check_decrypt(const unsigned char *adaptor_sig162, const unsigned char *decryption_key32, const unsigned char *signature64, int expected) { static void test_ecdsa_adaptor_spec_vectors_check_decrypt(const unsigned char *adaptor_sig162, const unsigned char *decryption_key32, const unsigned char *signature64, int expected) {
unsigned char signature[64]; unsigned char signature[64];
secp256k1_ecdsa_signature s; secp256k1_ecdsa_signature s;
@ -134,7 +134,7 @@ void test_ecdsa_adaptor_spec_vectors_check_decrypt(const unsigned char *adaptor_
/* Helper function for test_ecdsa_adaptor_spec_vectors /* Helper function for test_ecdsa_adaptor_spec_vectors
* Checks that the decryption key can be recovered from the adaptor signature, encryption key, and the signature. */ * Checks that the decryption key can be recovered from the adaptor signature, encryption key, and the signature. */
void test_ecdsa_adaptor_spec_vectors_check_recover(const unsigned char *adaptor_sig162, const unsigned char *encryption_key33, const unsigned char *decryption_key32, const unsigned char *signature64, int expected) { static void test_ecdsa_adaptor_spec_vectors_check_recover(const unsigned char *adaptor_sig162, const unsigned char *encryption_key33, const unsigned char *decryption_key32, const unsigned char *signature64, int expected) {
unsigned char deckey32[32] = { 0 }; unsigned char deckey32[32] = { 0 };
secp256k1_ecdsa_signature sig; secp256k1_ecdsa_signature sig;
secp256k1_pubkey encryption_key; secp256k1_pubkey encryption_key;
@ -152,7 +152,7 @@ void test_ecdsa_adaptor_spec_vectors_check_recover(const unsigned char *adaptor_
/* Helper function for test_ecdsa_adaptor_spec_vectors /* Helper function for test_ecdsa_adaptor_spec_vectors
* Checks deserialization and serialization. */ * Checks deserialization and serialization. */
void test_ecdsa_adaptor_spec_vectors_check_serialization(const unsigned char *adaptor_sig162, int expected) { static void test_ecdsa_adaptor_spec_vectors_check_serialization(const unsigned char *adaptor_sig162, int expected) {
unsigned char buf[162]; unsigned char buf[162];
secp256k1_scalar dleq_proof_s, dleq_proof_e; secp256k1_scalar dleq_proof_s, dleq_proof_e;
secp256k1_ge r, rp; secp256k1_ge r, rp;
@ -168,7 +168,7 @@ void test_ecdsa_adaptor_spec_vectors_check_serialization(const unsigned char *ad
/* Test vectors according to ECDSA adaptor signature spec. See /* Test vectors according to ECDSA adaptor signature spec. See
* https://github.com/discreetlogcontracts/dlcspecs/blob/596a177375932a47306f07e7385f398f52519a83/test/ecdsa_adaptor.json. */ * https://github.com/discreetlogcontracts/dlcspecs/blob/596a177375932a47306f07e7385f398f52519a83/test/ecdsa_adaptor.json. */
void test_ecdsa_adaptor_spec_vectors(void) { static void test_ecdsa_adaptor_spec_vectors(void) {
{ {
/* Test vector 0 */ /* Test vector 0 */
/* kind: verification test */ /* kind: verification test */
@ -710,7 +710,7 @@ static int ecdsa_adaptor_nonce_function_overflowing(unsigned char *nonce32, cons
/* Checks that a bit flip in the n_flip-th argument (that has n_bytes many /* Checks that a bit flip in the n_flip-th argument (that has n_bytes many
* bytes) changes the hash function * bytes) changes the hash function
*/ */
void nonce_function_ecdsa_adaptor_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes, size_t algolen) { static void nonce_function_ecdsa_adaptor_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes, size_t algolen) {
unsigned char nonces[2][32]; unsigned char nonces[2][32];
CHECK(nonce_function_ecdsa_adaptor(nonces[0], args[0], args[1], args[2], args[3], algolen, args[4]) == 1); CHECK(nonce_function_ecdsa_adaptor(nonces[0], args[0], args[1], args[2], args[3], algolen, args[4]) == 1);
secp256k1_testrand_flip(args[n_flip], n_bytes); secp256k1_testrand_flip(args[n_flip], n_bytes);
@ -721,7 +721,7 @@ void nonce_function_ecdsa_adaptor_bitflip(unsigned char **args, size_t n_flip, s
/* Tests for the equality of two sha256 structs. This function only produces a /* Tests for the equality of two sha256 structs. This function only produces a
* correct result if an integer multiple of 64 many bytes have been written * correct result if an integer multiple of 64 many bytes have been written
* into the hash functions. */ * into the hash functions. */
void ecdsa_adaptor_test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_sha256 *sha2) { static void ecdsa_adaptor_test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_sha256 *sha2) {
/* Is buffer fully consumed? */ /* Is buffer fully consumed? */
CHECK((sha1->bytes & 0x3F) == 0); CHECK((sha1->bytes & 0x3F) == 0);
@ -729,7 +729,7 @@ void ecdsa_adaptor_test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_
CHECK(secp256k1_memcmp_var(sha1->s, sha2->s, sizeof(sha1->s)) == 0); CHECK(secp256k1_memcmp_var(sha1->s, sha2->s, sizeof(sha1->s)) == 0);
} }
void run_nonce_function_ecdsa_adaptor_tests(void) { static void run_nonce_function_ecdsa_adaptor_tests(void) {
unsigned char tag[16] = "ECDSAadaptor/non"; unsigned char tag[16] = "ECDSAadaptor/non";
unsigned char aux_tag[16] = "ECDSAadaptor/aux"; unsigned char aux_tag[16] = "ECDSAadaptor/aux";
unsigned char algo[16] = "ECDSAadaptor/non"; unsigned char algo[16] = "ECDSAadaptor/non";
@ -813,7 +813,7 @@ void run_nonce_function_ecdsa_adaptor_tests(void) {
CHECK(nonce_function_ecdsa_adaptor(nonce, msg, key, pk, algo, algolen, NULL) == 1); CHECK(nonce_function_ecdsa_adaptor(nonce, msg, key, pk, algo, algolen, NULL) == 1);
} }
void test_ecdsa_adaptor_api(void) { static void test_ecdsa_adaptor_api(void) {
secp256k1_pubkey pubkey; secp256k1_pubkey pubkey;
secp256k1_pubkey enckey; secp256k1_pubkey enckey;
secp256k1_pubkey zero_pk; secp256k1_pubkey zero_pk;
@ -905,7 +905,7 @@ void test_ecdsa_adaptor_api(void) {
secp256k1_context_set_illegal_callback(STATIC_CTX, NULL, NULL); secp256k1_context_set_illegal_callback(STATIC_CTX, NULL, NULL);
} }
void adaptor_tests(void) { static void adaptor_tests(void) {
unsigned char seckey[32]; unsigned char seckey[32];
secp256k1_pubkey pubkey; secp256k1_pubkey pubkey;
unsigned char msg[32]; unsigned char msg[32];
@ -1105,7 +1105,7 @@ void adaptor_tests(void) {
} }
} }
void multi_hop_lock_tests(void) { static void multi_hop_lock_tests(void) {
unsigned char seckey_a[32]; unsigned char seckey_a[32];
unsigned char seckey_b[32]; unsigned char seckey_b[32];
unsigned char pop[32]; unsigned char pop[32];
@ -1179,7 +1179,7 @@ void multi_hop_lock_tests(void) {
CHECK(secp256k1_memcmp_var(buf, pop, 32) == 0); CHECK(secp256k1_memcmp_var(buf, pop, 32) == 0);
} }
void run_ecdsa_adaptor_tests(void) { static void run_ecdsa_adaptor_tests(void) {
int i; int i;
run_nonce_function_ecdsa_adaptor_tests(); run_nonce_function_ecdsa_adaptor_tests();

View File

@ -30,7 +30,7 @@ static void test_ecdsa_s2c_tagged_hash(void) {
CHECK(secp256k1_memcmp_var(output, output_optimized, 32) == 0); CHECK(secp256k1_memcmp_var(output, output_optimized, 32) == 0);
} }
void run_s2c_opening_test(void) { static void run_s2c_opening_test(void) {
int i = 0; int i = 0;
unsigned char output[33]; unsigned char output[33];
unsigned char input[33] = { unsigned char input[33] = {

View File

@ -14,7 +14,7 @@ static void set_counting_callbacks(secp256k1_context *ctx0, int *ecount) {
secp256k1_context_set_illegal_callback(ctx0, counting_illegal_callback_fn, ecount); secp256k1_context_set_illegal_callback(ctx0, counting_illegal_callback_fn, ecount);
} }
void test_xonly_pubkey(void) { static void test_xonly_pubkey(void) {
secp256k1_pubkey pk; secp256k1_pubkey pk;
secp256k1_xonly_pubkey xonly_pk, xonly_pk_tmp; secp256k1_xonly_pubkey xonly_pk, xonly_pk_tmp;
secp256k1_ge pk1; secp256k1_ge pk1;
@ -128,7 +128,7 @@ void test_xonly_pubkey(void) {
CHECK(ecount == 2); CHECK(ecount == 2);
} }
void test_xonly_pubkey_comparison(void) { static void test_xonly_pubkey_comparison(void) {
unsigned char pk1_ser[32] = { unsigned char pk1_ser[32] = {
0x58, 0x84, 0xb3, 0xa2, 0x4b, 0x97, 0x37, 0x88, 0x92, 0x38, 0xa6, 0x26, 0x62, 0x52, 0x35, 0x11, 0x58, 0x84, 0xb3, 0xa2, 0x4b, 0x97, 0x37, 0x88, 0x92, 0x38, 0xa6, 0x26, 0x62, 0x52, 0x35, 0x11,
0xd0, 0x9a, 0xa1, 0x1b, 0x80, 0x0b, 0x5e, 0x93, 0x80, 0x26, 0x11, 0xef, 0x67, 0x4b, 0xd9, 0x23 0xd0, 0x9a, 0xa1, 0x1b, 0x80, 0x0b, 0x5e, 0x93, 0x80, 0x26, 0x11, 0xef, 0x67, 0x4b, 0xd9, 0x23
@ -164,7 +164,7 @@ void test_xonly_pubkey_comparison(void) {
CHECK(ecount == 6); CHECK(ecount == 6);
} }
void test_xonly_pubkey_tweak(void) { static void test_xonly_pubkey_tweak(void) {
unsigned char zeros64[64] = { 0 }; unsigned char zeros64[64] = { 0 };
unsigned char overflows[32]; unsigned char overflows[32];
unsigned char sk[32]; unsigned char sk[32];
@ -231,7 +231,7 @@ void test_xonly_pubkey_tweak(void) {
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
} }
void test_xonly_pubkey_tweak_check(void) { static void test_xonly_pubkey_tweak_check(void) {
unsigned char zeros64[64] = { 0 }; unsigned char zeros64[64] = { 0 };
unsigned char overflows[32]; unsigned char overflows[32];
unsigned char sk[32]; unsigned char sk[32];
@ -297,7 +297,7 @@ void test_xonly_pubkey_tweak_check(void) {
* additional pubkeys by calling tweak_add. Then verifies every tweak starting * additional pubkeys by calling tweak_add. Then verifies every tweak starting
* from the last pubkey. */ * from the last pubkey. */
#define N_PUBKEYS 32 #define N_PUBKEYS 32
void test_xonly_pubkey_tweak_recursive(void) { static void test_xonly_pubkey_tweak_recursive(void) {
unsigned char sk[32]; unsigned char sk[32];
secp256k1_pubkey pk[N_PUBKEYS]; secp256k1_pubkey pk[N_PUBKEYS];
unsigned char pk_serialized[32]; unsigned char pk_serialized[32];
@ -326,7 +326,7 @@ void test_xonly_pubkey_tweak_recursive(void) {
} }
#undef N_PUBKEYS #undef N_PUBKEYS
void test_keypair(void) { static void test_keypair(void) {
unsigned char sk[32]; unsigned char sk[32];
unsigned char sk_tmp[32]; unsigned char sk_tmp[32];
unsigned char zeros96[96] = { 0 }; unsigned char zeros96[96] = { 0 };
@ -444,7 +444,7 @@ void test_keypair(void) {
secp256k1_context_set_illegal_callback(STATIC_CTX, NULL, NULL); secp256k1_context_set_illegal_callback(STATIC_CTX, NULL, NULL);
} }
void test_keypair_add(void) { static void test_keypair_add(void) {
unsigned char sk[32]; unsigned char sk[32];
secp256k1_keypair keypair; secp256k1_keypair keypair;
unsigned char overflows[32]; unsigned char overflows[32];
@ -563,7 +563,7 @@ static int test_hsort_cmp(const void *i1, const void *i2, void *counter) {
} }
#define NUM 64 #define NUM 64
void test_hsort(void) { static void test_hsort(void) {
int ints[NUM] = { 0 }; int ints[NUM] = { 0 };
size_t counter = 0; size_t counter = 0;
int i, j; int i, j;
@ -590,7 +590,7 @@ void test_hsort(void) {
} }
#undef NUM #undef NUM
void test_pubkey_comparison(void) { static void test_pubkey_comparison(void) {
unsigned char pk1_ser[33] = { unsigned char pk1_ser[33] = {
0x02, 0x02,
0x58, 0x84, 0xb3, 0xa2, 0x4b, 0x97, 0x37, 0x88, 0x92, 0x38, 0xa6, 0x26, 0x62, 0x52, 0x35, 0x11, 0x58, 0x84, 0xb3, 0xa2, 0x4b, 0x97, 0x37, 0x88, 0x92, 0x38, 0xa6, 0x26, 0x62, 0x52, 0x35, 0x11,
@ -629,7 +629,7 @@ void test_pubkey_comparison(void) {
} }
void test_sort_helper(secp256k1_pubkey *pk, size_t *pk_order, size_t n_pk) { static void test_sort_helper(secp256k1_pubkey *pk, size_t *pk_order, size_t n_pk) {
size_t i; size_t i;
const secp256k1_pubkey *pk_test[5]; const secp256k1_pubkey *pk_test[5];
@ -642,7 +642,7 @@ void test_sort_helper(secp256k1_pubkey *pk, size_t *pk_order, size_t n_pk) {
} }
} }
void permute(size_t *arr, size_t n) { static void permute(size_t *arr, size_t n) {
size_t i; size_t i;
for (i = n - 1; i >= 1; i--) { for (i = n - 1; i >= 1; i--) {
size_t tmp, j; size_t tmp, j;
@ -653,7 +653,7 @@ void permute(size_t *arr, size_t n) {
} }
} }
void rand_pk(secp256k1_pubkey *pk) { static void rand_pk(secp256k1_pubkey *pk) {
unsigned char seckey[32]; unsigned char seckey[32];
secp256k1_keypair keypair; secp256k1_keypair keypair;
secp256k1_testrand256(seckey); secp256k1_testrand256(seckey);
@ -661,7 +661,7 @@ void rand_pk(secp256k1_pubkey *pk) {
CHECK(secp256k1_keypair_pub(CTX, pk, &keypair) == 1); CHECK(secp256k1_keypair_pub(CTX, pk, &keypair) == 1);
} }
void test_sort_api(void) { static void test_sort_api(void) {
int ecount = 0; int ecount = 0;
secp256k1_pubkey pks[2]; secp256k1_pubkey pks[2];
const secp256k1_pubkey *pks_ptr[2]; const secp256k1_pubkey *pks_ptr[2];
@ -688,7 +688,7 @@ void test_sort_api(void) {
} }
void test_sort(void) { static void test_sort(void) {
secp256k1_pubkey pk[5]; secp256k1_pubkey pk[5];
unsigned char pk_ser[5][33] = { unsigned char pk_ser[5][33] = {
{ 0x02, 0x08 }, { 0x02, 0x08 },
@ -734,7 +734,7 @@ void test_sort(void) {
} }
/* Test vectors from BIP-MuSig2 */ /* Test vectors from BIP-MuSig2 */
void test_sort_vectors(void) { static void test_sort_vectors(void) {
enum { N_PUBKEYS = 6 }; enum { N_PUBKEYS = 6 };
unsigned char pk_ser[N_PUBKEYS][33] = { unsigned char pk_ser[N_PUBKEYS][33] = {
{ 0x02, 0xDD, 0x30, 0x8A, 0xFE, 0xC5, 0x77, 0x7E, 0x13, 0x12, 0x1F, { 0x02, 0xDD, 0x30, 0x8A, 0xFE, 0xC5, 0x77, 0x7E, 0x13, 0x12, 0x1F,
@ -778,7 +778,7 @@ void test_sort_vectors(void) {
} }
} }
void run_extrakeys_tests(void) { static void run_extrakeys_tests(void) {
/* xonly key test cases */ /* xonly key test cases */
test_xonly_pubkey(); test_xonly_pubkey();
test_xonly_pubkey_tweak(); test_xonly_pubkey_tweak();

View File

@ -17,7 +17,7 @@
#include "../../../include/secp256k1_generator.h" #include "../../../include/secp256k1_generator.h"
void test_generator_api(void) { static void test_generator_api(void) {
unsigned char key[32]; unsigned char key[32];
unsigned char blind[32]; unsigned char blind[32];
unsigned char sergen[33]; unsigned char sergen[33];
@ -70,7 +70,7 @@ void test_generator_api(void) {
secp256k1_context_set_illegal_callback(STATIC_CTX, NULL, NULL); secp256k1_context_set_illegal_callback(STATIC_CTX, NULL, NULL);
} }
void test_shallue_van_de_woestijne(void) { static void test_shallue_van_de_woestijne(void) {
/* Matches with the output of the shallue_van_de_woestijne.sage SAGE program */ /* Matches with the output of the shallue_van_de_woestijne.sage SAGE program */
static const secp256k1_ge_storage results[32] = { static const secp256k1_ge_storage results[32] = {
SECP256K1_GE_STORAGE_CONST(0xedd1fd3e, 0x327ce90c, 0xc7a35426, 0x14289aee, 0x9682003e, 0x9cf7dcc9, 0xcf2ca974, 0x3be5aa0c, 0x0225f529, 0xee75acaf, 0xccfc4560, 0x26c5e46b, 0xf80237a3, 0x3924655a, 0x16f90e88, 0x085ed52a), SECP256K1_GE_STORAGE_CONST(0xedd1fd3e, 0x327ce90c, 0xc7a35426, 0x14289aee, 0x9682003e, 0x9cf7dcc9, 0xcf2ca974, 0x3be5aa0c, 0x0225f529, 0xee75acaf, 0xccfc4560, 0x26c5e46b, 0xf80237a3, 0x3924655a, 0x16f90e88, 0x085ed52a),
@ -127,7 +127,7 @@ void test_shallue_van_de_woestijne(void) {
} }
} }
void test_generator_generate(void) { static void test_generator_generate(void) {
static const secp256k1_ge_storage results[32] = { static const secp256k1_ge_storage results[32] = {
SECP256K1_GE_STORAGE_CONST(0x806cd8ed, 0xd6c153e3, 0x4aa9b9a0, 0x8755c4be, 0x4718b1ef, 0xb26cb93f, 0xfdd99e1b, 0x21f2af8e, 0xc7062208, 0xcc649a03, 0x1bdc1a33, 0x9d01f115, 0x4bcd0dca, 0xfe0b875d, 0x62f35f73, 0x28673006), SECP256K1_GE_STORAGE_CONST(0x806cd8ed, 0xd6c153e3, 0x4aa9b9a0, 0x8755c4be, 0x4718b1ef, 0xb26cb93f, 0xfdd99e1b, 0x21f2af8e, 0xc7062208, 0xcc649a03, 0x1bdc1a33, 0x9d01f115, 0x4bcd0dca, 0xfe0b875d, 0x62f35f73, 0x28673006),
SECP256K1_GE_STORAGE_CONST(0xd91b15ec, 0x47a811f4, 0xaa189561, 0xd13f5c4d, 0x4e81f10d, 0xc7dc551f, 0x4fea9b84, 0x610314c4, 0x9b0ada1e, 0xb38efd67, 0x8bff0b6c, 0x7d7315f7, 0xb49b8cc5, 0xa679fad4, 0xc94f9dc6, 0x9da66382), SECP256K1_GE_STORAGE_CONST(0xd91b15ec, 0x47a811f4, 0xaa189561, 0xd13f5c4d, 0x4e81f10d, 0xc7dc551f, 0x4fea9b84, 0x610314c4, 0x9b0ada1e, 0xb38efd67, 0x8bff0b6c, 0x7d7315f7, 0xb49b8cc5, 0xa679fad4, 0xc94f9dc6, 0x9da66382),
@ -192,7 +192,7 @@ void test_generator_generate(void) {
CHECK(!secp256k1_generator_generate_blinded(CTX, &gen, v, s)); CHECK(!secp256k1_generator_generate_blinded(CTX, &gen, v, s));
} }
void test_generator_fixed_vector(void) { static void test_generator_fixed_vector(void) {
const unsigned char two_g[33] = { const unsigned char two_g[33] = {
0x0b, 0x0b,
0xc6, 0x04, 0x7f, 0x94, 0x41, 0xed, 0x7d, 0x6d, 0x30, 0x45, 0x40, 0x6e, 0x95, 0xc0, 0x7c, 0xd8, 0xc6, 0x04, 0x7f, 0x94, 0x41, 0xed, 0x7d, 0x6d, 0x30, 0x45, 0x40, 0x6e, 0x95, 0xc0, 0x7c, 0xd8,
@ -337,7 +337,7 @@ static void test_pedersen(void) {
CHECK(secp256k1_pedersen_verify_tally(CTX, &cptr[1], 1, &cptr[1], 1)); CHECK(secp256k1_pedersen_verify_tally(CTX, &cptr[1], 1, &cptr[1], 1));
} }
void test_pedersen_commitment_fixed_vector(void) { static void test_pedersen_commitment_fixed_vector(void) {
const unsigned char two_g[33] = { const unsigned char two_g[33] = {
0x09, 0x09,
0xc6, 0x04, 0x7f, 0x94, 0x41, 0xed, 0x7d, 0x6d, 0x30, 0x45, 0x40, 0x6e, 0x95, 0xc0, 0x7c, 0xd8, 0xc6, 0x04, 0x7f, 0x94, 0x41, 0xed, 0x7d, 0x6d, 0x30, 0x45, 0x40, 0x6e, 0x95, 0xc0, 0x7c, 0xd8,
@ -357,7 +357,7 @@ void test_pedersen_commitment_fixed_vector(void) {
} }
void run_generator_tests(void) { static void run_generator_tests(void) {
int i; int i;
test_shallue_van_de_woestijne(); test_shallue_van_de_woestijne();

View File

@ -38,7 +38,7 @@ static int create_keypair_and_pk(secp256k1_keypair *keypair, secp256k1_pubkey *p
/* Just a simple (non-adaptor, non-tweaked) 2-of-2 MuSig aggregate, sign, verify /* Just a simple (non-adaptor, non-tweaked) 2-of-2 MuSig aggregate, sign, verify
* test. */ * test. */
void musig_simple_test(secp256k1_scratch_space *scratch) { static void musig_simple_test(secp256k1_scratch_space *scratch) {
unsigned char sk[2][32]; unsigned char sk[2][32];
secp256k1_keypair keypair[2]; secp256k1_keypair keypair[2];
secp256k1_musig_pubnonce pubnonce[2]; secp256k1_musig_pubnonce pubnonce[2];
@ -82,7 +82,7 @@ void musig_simple_test(secp256k1_scratch_space *scratch) {
CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &agg_pk) == 1); CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &agg_pk) == 1);
} }
void pubnonce_summing_to_inf(secp256k1_musig_pubnonce *pubnonce) { static void pubnonce_summing_to_inf(secp256k1_musig_pubnonce *pubnonce) {
secp256k1_ge ge[2]; secp256k1_ge ge[2];
int i; int i;
secp256k1_gej summed_nonces[2]; secp256k1_gej summed_nonces[2];
@ -113,7 +113,7 @@ int memcmp_and_randomize(unsigned char *value, const unsigned char *expected, si
return ret; return ret;
} }
void musig_api_tests(secp256k1_scratch_space *scratch) { static void musig_api_tests(secp256k1_scratch_space *scratch) {
secp256k1_scratch_space *scratch_small; secp256k1_scratch_space *scratch_small;
secp256k1_musig_partial_sig partial_sig[2]; secp256k1_musig_partial_sig partial_sig[2];
const secp256k1_musig_partial_sig *partial_sig_ptr[2]; const secp256k1_musig_partial_sig *partial_sig_ptr[2];
@ -598,7 +598,7 @@ void musig_api_tests(secp256k1_scratch_space *scratch) {
secp256k1_context_set_illegal_callback(STATIC_CTX, NULL, NULL); secp256k1_context_set_illegal_callback(STATIC_CTX, NULL, NULL);
} }
void musig_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) { static void musig_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) {
secp256k1_scalar k1[2], k2[2]; secp256k1_scalar k1[2], k2[2];
secp256k1_nonce_function_musig(k1, args[0], args[1], args[2], args[3], args[4], args[5]); secp256k1_nonce_function_musig(k1, args[0], args[1], args[2], args[3], args[4], args[5]);
@ -608,7 +608,7 @@ void musig_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) {
CHECK(secp256k1_scalar_eq(&k1[1], &k2[1]) == 0); CHECK(secp256k1_scalar_eq(&k1[1], &k2[1]) == 0);
} }
void musig_nonce_test(void) { static void musig_nonce_test(void) {
unsigned char *args[6]; unsigned char *args[6];
unsigned char session_id[32]; unsigned char session_id[32];
unsigned char sk[32]; unsigned char sk[32];
@ -663,7 +663,7 @@ void musig_nonce_test(void) {
} }
} }
void scriptless_atomic_swap(secp256k1_scratch_space *scratch) { static void scriptless_atomic_swap(secp256k1_scratch_space *scratch) {
/* Throughout this test "a" and "b" refer to two hypothetical blockchains, /* Throughout this test "a" and "b" refer to two hypothetical blockchains,
* while the indices 0 and 1 refer to the two signers. Here signer 0 is * while the indices 0 and 1 refer to the two signers. Here signer 0 is
* sending a-coins to signer 1, while signer 1 is sending b-coins to signer * sending a-coins to signer 1, while signer 1 is sending b-coins to signer
@ -768,7 +768,7 @@ void scriptless_atomic_swap(secp256k1_scratch_space *scratch) {
CHECK(secp256k1_schnorrsig_verify(CTX, final_sig_a, msg32_a, sizeof(msg32_a), &agg_pk_a) == 1); CHECK(secp256k1_schnorrsig_verify(CTX, final_sig_a, msg32_a, sizeof(msg32_a), &agg_pk_a) == 1);
} }
void sha256_tag_test_internal(secp256k1_sha256 *sha_tagged, unsigned char *tag, size_t taglen) { static void sha256_tag_test_internal(secp256k1_sha256 *sha_tagged, unsigned char *tag, size_t taglen) {
secp256k1_sha256 sha; secp256k1_sha256 sha;
unsigned char buf[32]; unsigned char buf[32];
unsigned char buf2[32]; unsigned char buf2[32];
@ -798,7 +798,7 @@ void sha256_tag_test_internal(secp256k1_sha256 *sha_tagged, unsigned char *tag,
/* Checks that the initialized tagged hashes initialized have the expected /* Checks that the initialized tagged hashes initialized have the expected
* state. */ * state. */
void sha256_tag_test(void) { static void sha256_tag_test(void) {
secp256k1_sha256 sha_tagged; secp256k1_sha256 sha_tagged;
{ {
char tag[11] = "KeyAgg list"; char tag[11] = "KeyAgg list";
@ -814,7 +814,7 @@ void sha256_tag_test(void) {
/* Attempts to create a signature for the aggregate public key using given secret /* Attempts to create a signature for the aggregate public key using given secret
* keys and keyagg_cache. */ * keys and keyagg_cache. */
void musig_tweak_test_helper(const secp256k1_xonly_pubkey* agg_pk, const unsigned char *sk0, const unsigned char *sk1, secp256k1_musig_keyagg_cache *keyagg_cache) { static void musig_tweak_test_helper(const secp256k1_xonly_pubkey* agg_pk, const unsigned char *sk0, const unsigned char *sk1, secp256k1_musig_keyagg_cache *keyagg_cache) {
secp256k1_pubkey pk[2]; secp256k1_pubkey pk[2];
unsigned char session_id[2][32]; unsigned char session_id[2][32];
unsigned char msg[32]; unsigned char msg[32];
@ -857,7 +857,7 @@ void musig_tweak_test_helper(const secp256k1_xonly_pubkey* agg_pk, const unsigne
/* Create aggregate public key P[0], tweak multiple times (using xonly and /* Create aggregate public key P[0], tweak multiple times (using xonly and
* plain tweaking) and test signing. */ * plain tweaking) and test signing. */
void musig_tweak_test(secp256k1_scratch_space *scratch) { static void musig_tweak_test(secp256k1_scratch_space *scratch) {
unsigned char sk[2][32]; unsigned char sk[2][32];
secp256k1_pubkey pk[2]; secp256k1_pubkey pk[2];
const secp256k1_pubkey *pk_ptr[2]; const secp256k1_pubkey *pk_ptr[2];
@ -971,7 +971,7 @@ int musig_vectors_keyagg_and_tweak(enum MUSIG_ERROR *error,
return 1; return 1;
} }
void musig_test_vectors_keyagg(void) { static void musig_test_vectors_keyagg(void) {
size_t i; size_t i;
const struct musig_key_agg_vector *vector = &musig_key_agg_vector; const struct musig_key_agg_vector *vector = &musig_key_agg_vector;
@ -995,7 +995,7 @@ void musig_test_vectors_keyagg(void) {
} }
} }
void musig_test_vectors_noncegen(void) { static void musig_test_vectors_noncegen(void) {
size_t i; size_t i;
const struct musig_nonce_gen_vector *vector = &musig_nonce_gen_vector; const struct musig_nonce_gen_vector *vector = &musig_nonce_gen_vector;
@ -1043,7 +1043,7 @@ void musig_test_vectors_noncegen(void) {
} }
void musig_test_vectors_nonceagg(void) { static void musig_test_vectors_nonceagg(void) {
size_t i; size_t i;
int j; int j;
const struct musig_nonce_agg_vector *vector = &musig_nonce_agg_vector; const struct musig_nonce_agg_vector *vector = &musig_nonce_agg_vector;
@ -1073,7 +1073,7 @@ void musig_test_vectors_nonceagg(void) {
} }
} }
void musig_test_set_secnonce(secp256k1_musig_secnonce *secnonce, const unsigned char *secnonce64, const secp256k1_pubkey *pubkey) { static void musig_test_set_secnonce(secp256k1_musig_secnonce *secnonce, const unsigned char *secnonce64, const secp256k1_pubkey *pubkey) {
secp256k1_ge pk; secp256k1_ge pk;
secp256k1_scalar k[2]; secp256k1_scalar k[2];
@ -1083,7 +1083,7 @@ void musig_test_set_secnonce(secp256k1_musig_secnonce *secnonce, const unsigned
secp256k1_musig_secnonce_save(secnonce, k, &pk); secp256k1_musig_secnonce_save(secnonce, k, &pk);
} }
void musig_test_vectors_signverify(void) { static void musig_test_vectors_signverify(void) {
size_t i; size_t i;
const struct musig_sign_verify_vector *vector = &musig_sign_verify_vector; const struct musig_sign_verify_vector *vector = &musig_sign_verify_vector;
@ -1214,7 +1214,7 @@ void musig_test_vectors_signverify(void) {
} }
} }
void musig_test_vectors_tweak(void) { static void musig_test_vectors_tweak(void) {
size_t i; size_t i;
const struct musig_tweak_vector *vector = &musig_tweak_vector; const struct musig_tweak_vector *vector = &musig_tweak_vector;
secp256k1_pubkey pubkey; secp256k1_pubkey pubkey;
@ -1257,7 +1257,7 @@ void musig_test_vectors_tweak(void) {
} }
} }
void musig_test_vectors_sigagg(void) { static void musig_test_vectors_sigagg(void) {
size_t i, j; size_t i, j;
const struct musig_sig_agg_vector *vector = &musig_sig_agg_vector; const struct musig_sig_agg_vector *vector = &musig_sig_agg_vector;
@ -1297,7 +1297,7 @@ void musig_test_vectors_sigagg(void) {
} }
} }
void run_musig_tests(void) { static void run_musig_tests(void) {
int i; int i;
secp256k1_scratch_space *scratch = secp256k1_scratch_space_create(CTX, 1024 * 1024); secp256k1_scratch_space *scratch = secp256k1_scratch_space_create(CTX, 1024 * 1024);

View File

@ -14,10 +14,10 @@
#include "../../ecmult.h" #include "../../ecmult.h"
#include "../../ecmult_gen.h" #include "../../ecmult_gen.h"
int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e0, const secp256k1_scalar *s, static int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e0, const secp256k1_scalar *s,
const secp256k1_gej *pubs, const size_t *rsizes, size_t nrings, const unsigned char *m, size_t mlen); const secp256k1_gej *pubs, const size_t *rsizes, size_t nrings, const unsigned char *m, size_t mlen);
int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, static int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec, unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec,
const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen); const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen);

View File

@ -620,7 +620,7 @@ static void test_multiple_generators(void) {
} }
} }
void test_rangeproof_fixed_vectors(void) { static void test_rangeproof_fixed_vectors(void) {
size_t i; size_t i;
unsigned char blind[32]; unsigned char blind[32];
uint64_t value; uint64_t value;
@ -885,7 +885,7 @@ static unsigned char vector_nonce[] = {
}; };
/* Maximum length of a message that can be embedded into a rangeproof */ /* Maximum length of a message that can be embedded into a rangeproof */
void test_rangeproof_fixed_vectors_reproducible_helper(unsigned char *vector, size_t vector_len, unsigned char *commit, uint64_t *value_r, uint64_t *min_value_r, uint64_t *max_value_r, unsigned char *message_r, size_t *m_len_r) { static void test_rangeproof_fixed_vectors_reproducible_helper(unsigned char *vector, size_t vector_len, unsigned char *commit, uint64_t *value_r, uint64_t *min_value_r, uint64_t *max_value_r, unsigned char *message_r, size_t *m_len_r) {
secp256k1_pedersen_commitment pc; secp256k1_pedersen_commitment pc;
unsigned char blind_r[32]; unsigned char blind_r[32];
@ -914,7 +914,7 @@ void test_rangeproof_fixed_vectors_reproducible_helper(unsigned char *vector, si
CHECK(secp256k1_memcmp_var(blind_r, vector_blind, sizeof(vector_blind)) == 0); CHECK(secp256k1_memcmp_var(blind_r, vector_blind, sizeof(vector_blind)) == 0);
} }
void test_rangeproof_fixed_vectors_reproducible(void) { static void test_rangeproof_fixed_vectors_reproducible(void) {
uint64_t value_r; uint64_t value_r;
uint64_t min_value_r; uint64_t min_value_r;
uint64_t max_value_r; uint64_t max_value_r;
@ -1382,7 +1382,7 @@ void test_rangeproof_fixed_vectors_reproducible(void) {
} }
} }
void run_rangeproof_tests(void) { static void run_rangeproof_tests(void) {
int i; int i;
test_api(); test_api();

View File

@ -15,7 +15,7 @@ typedef struct {
unsigned char sig[64]; unsigned char sig[64];
} bench_recover_data; } bench_recover_data;
void bench_recover(void* arg, int iters) { static void bench_recover(void* arg, int iters) {
int i; int i;
bench_recover_data *data = (bench_recover_data*)arg; bench_recover_data *data = (bench_recover_data*)arg;
secp256k1_pubkey pubkey; secp256k1_pubkey pubkey;
@ -36,7 +36,7 @@ void bench_recover(void* arg, int iters) {
} }
} }
void bench_recover_setup(void* arg) { static void bench_recover_setup(void* arg) {
int i; int i;
bench_recover_data *data = (bench_recover_data*)arg; bench_recover_data *data = (bench_recover_data*)arg;
@ -48,7 +48,7 @@ void bench_recover_setup(void* arg) {
} }
} }
void run_recovery_bench(int iters, int argc, char** argv) { static void run_recovery_bench(int iters, int argc, char** argv) {
bench_recover_data data; bench_recover_data data;
int d = argc == 1; int d = argc == 1;

View File

@ -10,7 +10,7 @@
#include "main_impl.h" #include "main_impl.h"
#include "../../../include/secp256k1_recovery.h" #include "../../../include/secp256k1_recovery.h"
void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const secp256k1_ge *group) { static void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const secp256k1_ge *group) {
int i, j, k; int i, j, k;
uint64_t iter = 0; uint64_t iter = 0;
@ -43,8 +43,7 @@ void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const secp256k1
(k * (EXHAUSTIVE_TEST_ORDER - s)) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_ORDER); (k * (EXHAUSTIVE_TEST_ORDER - s)) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_ORDER);
/* The recid's second bit is for conveying overflow (R.x value >= group order). /* The recid's second bit is for conveying overflow (R.x value >= group order).
* In the actual secp256k1 this is an astronomically unlikely event, but in the * In the actual secp256k1 this is an astronomically unlikely event, but in the
* small group used here, it will be the case for all points except the ones where * small group used here, it will almost certainly be the case for all points.
* R.x=1 (which the group is specifically selected to have).
* Note that this isn't actually useful; full recovery would need to convey * Note that this isn't actually useful; full recovery would need to convey
* floor(R.x / group_order), but only one bit is used as that is sufficient * floor(R.x / group_order), but only one bit is used as that is sufficient
* in the real group. */ * in the real group. */
@ -79,7 +78,7 @@ void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const secp256k1
} }
} }
void test_exhaustive_recovery_verify(const secp256k1_context *ctx, const secp256k1_ge *group) { static void test_exhaustive_recovery_verify(const secp256k1_context *ctx, const secp256k1_ge *group) {
/* This is essentially a copy of test_exhaustive_verify, with recovery added */ /* This is essentially a copy of test_exhaustive_verify, with recovery added */
int s, r, msg, key; int s, r, msg, key;
uint64_t iter = 0; uint64_t iter = 0;

View File

@ -28,7 +28,7 @@ static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned c
return secp256k1_testrand_bits(1); return secp256k1_testrand_bits(1);
} }
void test_ecdsa_recovery_api(void) { static void test_ecdsa_recovery_api(void) {
/* Setup contexts that just count errors */ /* Setup contexts that just count errors */
secp256k1_pubkey pubkey; secp256k1_pubkey pubkey;
secp256k1_pubkey recpubkey; secp256k1_pubkey recpubkey;
@ -127,7 +127,7 @@ void test_ecdsa_recovery_api(void) {
secp256k1_context_set_illegal_callback(STATIC_CTX, NULL, NULL); secp256k1_context_set_illegal_callback(STATIC_CTX, NULL, NULL);
} }
void test_ecdsa_recovery_end_to_end(void) { static void test_ecdsa_recovery_end_to_end(void) {
unsigned char extra[32] = {0x00}; unsigned char extra[32] = {0x00};
unsigned char privkey[32]; unsigned char privkey[32];
unsigned char message[32]; unsigned char message[32];
@ -186,7 +186,7 @@ void test_ecdsa_recovery_end_to_end(void) {
} }
/* Tests several edge cases. */ /* Tests several edge cases. */
void test_ecdsa_recovery_edge_cases(void) { static void test_ecdsa_recovery_edge_cases(void) {
const unsigned char msg32[32] = { const unsigned char msg32[32] = {
'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'T', 'h', 'i', 's', ' ', 'i', 's', ' ',
'a', ' ', 'v', 'e', 'r', 'y', ' ', 's', 'a', ' ', 'v', 'e', 'r', 'y', ' ', 's',
@ -359,7 +359,7 @@ void test_ecdsa_recovery_edge_cases(void) {
} }
} }
void run_recovery_tests(void) { static void run_recovery_tests(void) {
int i; int i;
for (i = 0; i < COUNT; i++) { for (i = 0; i < COUNT; i++) {
test_ecdsa_recovery_api(); test_ecdsa_recovery_api();

View File

@ -21,7 +21,7 @@ typedef struct {
const unsigned char **msgs; const unsigned char **msgs;
} bench_schnorrsig_data; } bench_schnorrsig_data;
void bench_schnorrsig_sign(void* arg, int iters) { static void bench_schnorrsig_sign(void* arg, int iters) {
bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg; bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg;
int i; int i;
unsigned char msg[MSGLEN] = {0}; unsigned char msg[MSGLEN] = {0};
@ -34,7 +34,7 @@ void bench_schnorrsig_sign(void* arg, int iters) {
} }
} }
void bench_schnorrsig_verify(void* arg, int iters) { static void bench_schnorrsig_verify(void* arg, int iters) {
bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg; bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg;
int i; int i;
@ -45,7 +45,7 @@ void bench_schnorrsig_verify(void* arg, int iters) {
} }
} }
void run_schnorrsig_bench(int iters, int argc, char** argv) { static void run_schnorrsig_bench(int iters, int argc, char** argv) {
int i; int i;
bench_schnorrsig_data data; bench_schnorrsig_data data;
int d = argc == 1; int d = argc == 1;

View File

@ -12,7 +12,7 @@
/* Checks that a bit flip in the n_flip-th argument (that has n_bytes many /* Checks that a bit flip in the n_flip-th argument (that has n_bytes many
* bytes) changes the hash function * bytes) changes the hash function
*/ */
void nonce_function_bip340_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes, size_t msglen, size_t algolen) { static void nonce_function_bip340_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes, size_t msglen, size_t algolen) {
unsigned char nonces[2][32]; unsigned char nonces[2][32];
CHECK(nonce_function_bip340(nonces[0], args[0], msglen, args[1], args[2], args[3], algolen, args[4]) == 1); CHECK(nonce_function_bip340(nonces[0], args[0], msglen, args[1], args[2], args[3], algolen, args[4]) == 1);
secp256k1_testrand_flip(args[n_flip], n_bytes); secp256k1_testrand_flip(args[n_flip], n_bytes);
@ -23,7 +23,7 @@ void nonce_function_bip340_bitflip(unsigned char **args, size_t n_flip, size_t n
/* Tests for the equality of two sha256 structs. This function only produces a /* Tests for the equality of two sha256 structs. This function only produces a
* correct result if an integer multiple of 64 many bytes have been written * correct result if an integer multiple of 64 many bytes have been written
* into the hash functions. */ * into the hash functions. */
void test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_sha256 *sha2) { static void test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_sha256 *sha2) {
/* Is buffer fully consumed? */ /* Is buffer fully consumed? */
CHECK((sha1->bytes & 0x3F) == 0); CHECK((sha1->bytes & 0x3F) == 0);
@ -31,7 +31,7 @@ void test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_sha256 *sha2)
CHECK(secp256k1_memcmp_var(sha1->s, sha2->s, sizeof(sha1->s)) == 0); CHECK(secp256k1_memcmp_var(sha1->s, sha2->s, sizeof(sha1->s)) == 0);
} }
void run_nonce_function_bip340_tests(void) { static void run_nonce_function_bip340_tests(void) {
unsigned char tag[13] = "BIP0340/nonce"; unsigned char tag[13] = "BIP0340/nonce";
unsigned char aux_tag[11] = "BIP0340/aux"; unsigned char aux_tag[11] = "BIP0340/aux";
unsigned char algo[13] = "BIP0340/nonce"; unsigned char algo[13] = "BIP0340/nonce";
@ -114,7 +114,7 @@ void run_nonce_function_bip340_tests(void) {
CHECK(secp256k1_memcmp_var(nonce_z, nonce, 32) == 0); CHECK(secp256k1_memcmp_var(nonce_z, nonce, 32) == 0);
} }
void test_schnorrsig_api(void) { static void test_schnorrsig_api(void) {
unsigned char sk1[32]; unsigned char sk1[32];
unsigned char sk2[32]; unsigned char sk2[32];
unsigned char sk3[32]; unsigned char sk3[32];
@ -203,7 +203,7 @@ void test_schnorrsig_api(void) {
/* Checks that hash initialized by secp256k1_schnorrsig_sha256_tagged has the /* Checks that hash initialized by secp256k1_schnorrsig_sha256_tagged has the
* expected state. */ * expected state. */
void test_schnorrsig_sha256_tagged(void) { static void test_schnorrsig_sha256_tagged(void) {
unsigned char tag[17] = "BIP0340/challenge"; unsigned char tag[17] = "BIP0340/challenge";
secp256k1_sha256 sha; secp256k1_sha256 sha;
secp256k1_sha256 sha_optimized; secp256k1_sha256 sha_optimized;
@ -215,7 +215,7 @@ void test_schnorrsig_sha256_tagged(void) {
/* Helper function for schnorrsig_bip_vectors /* Helper function for schnorrsig_bip_vectors
* Signs the message and checks that it's the same as expected_sig. */ * Signs the message and checks that it's the same as expected_sig. */
void test_schnorrsig_bip_vectors_check_signing(const unsigned char *sk, const unsigned char *pk_serialized, const unsigned char *aux_rand, const unsigned char *msg32, const unsigned char *expected_sig) { static void test_schnorrsig_bip_vectors_check_signing(const unsigned char *sk, const unsigned char *pk_serialized, const unsigned char *aux_rand, const unsigned char *msg32, const unsigned char *expected_sig) {
unsigned char sig[64]; unsigned char sig[64];
secp256k1_keypair keypair; secp256k1_keypair keypair;
secp256k1_xonly_pubkey pk, pk_expected; secp256k1_xonly_pubkey pk, pk_expected;
@ -232,7 +232,7 @@ void test_schnorrsig_bip_vectors_check_signing(const unsigned char *sk, const un
/* Helper function for schnorrsig_bip_vectors /* Helper function for schnorrsig_bip_vectors
* Checks that both verify and verify_batch (TODO) return the same value as expected. */ * Checks that both verify and verify_batch (TODO) return the same value as expected. */
void test_schnorrsig_bip_vectors_check_verify(const unsigned char *pk_serialized, const unsigned char *msg32, const unsigned char *sig, int expected) { static void test_schnorrsig_bip_vectors_check_verify(const unsigned char *pk_serialized, const unsigned char *msg32, const unsigned char *sig, int expected) {
secp256k1_xonly_pubkey pk; secp256k1_xonly_pubkey pk;
CHECK(secp256k1_xonly_pubkey_parse(CTX, &pk, pk_serialized)); CHECK(secp256k1_xonly_pubkey_parse(CTX, &pk, pk_serialized));
@ -241,7 +241,7 @@ void test_schnorrsig_bip_vectors_check_verify(const unsigned char *pk_serialized
/* Test vectors according to BIP-340 ("Schnorr Signatures for secp256k1"). See /* Test vectors according to BIP-340 ("Schnorr Signatures for secp256k1"). See
* https://github.com/bitcoin/bips/blob/master/bip-0340/test-vectors.csv. */ * https://github.com/bitcoin/bips/blob/master/bip-0340/test-vectors.csv. */
void test_schnorrsig_bip_vectors(void) { static void test_schnorrsig_bip_vectors(void) {
{ {
/* Test vector 0 */ /* Test vector 0 */
const unsigned char sk[32] = { const unsigned char sk[32] = {
@ -699,7 +699,7 @@ static int nonce_function_overflowing(unsigned char *nonce32, const unsigned cha
return 1; return 1;
} }
void test_schnorrsig_sign(void) { static void test_schnorrsig_sign(void) {
unsigned char sk[32]; unsigned char sk[32];
secp256k1_xonly_pubkey pk; secp256k1_xonly_pubkey pk;
secp256k1_keypair keypair; secp256k1_keypair keypair;
@ -749,7 +749,7 @@ void test_schnorrsig_sign(void) {
/* Creates N_SIGS valid signatures and verifies them with verify and /* Creates N_SIGS valid signatures and verifies them with verify and
* verify_batch (TODO). Then flips some bits and checks that verification now * verify_batch (TODO). Then flips some bits and checks that verification now
* fails. */ * fails. */
void test_schnorrsig_sign_verify(void) { static void test_schnorrsig_sign_verify(void) {
unsigned char sk[32]; unsigned char sk[32];
unsigned char msg[N_SIGS][32]; unsigned char msg[N_SIGS][32];
unsigned char sig[N_SIGS][64]; unsigned char sig[N_SIGS][64];
@ -826,7 +826,7 @@ void test_schnorrsig_sign_verify(void) {
} }
#undef N_SIGS #undef N_SIGS
void test_schnorrsig_taproot(void) { static void test_schnorrsig_taproot(void) {
unsigned char sk[32]; unsigned char sk[32];
secp256k1_keypair keypair; secp256k1_keypair keypair;
secp256k1_xonly_pubkey internal_pk; secp256k1_xonly_pubkey internal_pk;
@ -862,7 +862,7 @@ void test_schnorrsig_taproot(void) {
CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, output_pk_bytes, pk_parity, &internal_pk, tweak) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, output_pk_bytes, pk_parity, &internal_pk, tweak) == 1);
} }
void run_schnorrsig_tests(void) { static void run_schnorrsig_tests(void) {
int i; int i;
run_nonce_function_bip340_tests(); run_nonce_function_bip340_tests();

View File

@ -493,7 +493,7 @@ static void test_no_used_inputs_verify(void) {
CHECK(result == 0); CHECK(result == 0);
} }
void test_bad_serialize(void) { static void test_bad_serialize(void) {
secp256k1_surjectionproof proof; secp256k1_surjectionproof proof;
unsigned char serialized_proof[SECP256K1_SURJECTIONPROOF_SERIALIZATION_BYTES_MAX]; unsigned char serialized_proof[SECP256K1_SURJECTIONPROOF_SERIALIZATION_BYTES_MAX];
size_t serialized_len; size_t serialized_len;
@ -504,7 +504,7 @@ void test_bad_serialize(void) {
CHECK(secp256k1_surjectionproof_serialize(CTX, serialized_proof, &serialized_len, &proof) == 0); CHECK(secp256k1_surjectionproof_serialize(CTX, serialized_proof, &serialized_len, &proof) == 0);
} }
void test_bad_parse(void) { static void test_bad_parse(void) {
secp256k1_surjectionproof proof; secp256k1_surjectionproof proof;
unsigned char serialized_proof0[] = { 0x00 }; unsigned char serialized_proof0[] = { 0x00 };
unsigned char serialized_proof1[] = { 0x01, 0x00 }; unsigned char serialized_proof1[] = { 0x01, 0x00 };
@ -518,7 +518,7 @@ void test_bad_parse(void) {
CHECK(secp256k1_surjectionproof_parse(CTX, &proof, serialized_proof2, sizeof(serialized_proof2)) == 0); CHECK(secp256k1_surjectionproof_parse(CTX, &proof, serialized_proof2, sizeof(serialized_proof2)) == 0);
} }
void test_input_eq_output(void) { static void test_input_eq_output(void) {
secp256k1_surjectionproof proof; secp256k1_surjectionproof proof;
secp256k1_fixed_asset_tag fixed_tag; secp256k1_fixed_asset_tag fixed_tag;
secp256k1_generator ephemeral_tag; secp256k1_generator ephemeral_tag;
@ -543,7 +543,7 @@ void test_input_eq_output(void) {
CHECK(!secp256k1_surjectionproof_generate(CTX, &proof, &ephemeral_tag, 1, &ephemeral_tag, input_index, blinding_key, blinding_key)); CHECK(!secp256k1_surjectionproof_generate(CTX, &proof, &ephemeral_tag, 1, &ephemeral_tag, input_index, blinding_key, blinding_key));
} }
void test_fixed_vectors(void) { static void test_fixed_vectors(void) {
const unsigned char tag0_ser[] = { const unsigned char tag0_ser[] = {
0x0a, 0x0a,
0x1c, 0xa3, 0xdd, 0x12, 0x48, 0xdd, 0x4d, 0xd0, 0x04, 0x30, 0x47, 0x48, 0x75, 0xf5, 0xf5, 0xff, 0x1c, 0xa3, 0xdd, 0x12, 0x48, 0xdd, 0x4d, 0xd0, 0x04, 0x30, 0x47, 0x48, 0x75, 0xf5, 0xf5, 0xff,
@ -689,7 +689,7 @@ void test_fixed_vectors(void) {
CHECK(!secp256k1_surjectionproof_parse(CTX, &proof, bad, total5_used3_len)); CHECK(!secp256k1_surjectionproof_parse(CTX, &proof, bad, total5_used3_len));
} }
void run_surjection_tests(void) { static void run_surjection_tests(void) {
test_surjectionproof_api(); test_surjectionproof_api();
test_input_eq_output(); test_input_eq_output();
test_fixed_vectors(); test_fixed_vectors();

View File

@ -9,7 +9,7 @@
#include "../../../include/secp256k1_whitelist.h" #include "../../../include/secp256k1_whitelist.h"
void test_whitelist_end_to_end_internal(const unsigned char *summed_seckey, const unsigned char *online_seckey, const secp256k1_pubkey *online_pubkeys, const secp256k1_pubkey *offline_pubkeys, const secp256k1_pubkey *sub_pubkey, const size_t signer_i, const size_t n_keys) { static void test_whitelist_end_to_end_internal(const unsigned char *summed_seckey, const unsigned char *online_seckey, const secp256k1_pubkey *online_pubkeys, const secp256k1_pubkey *offline_pubkeys, const secp256k1_pubkey *sub_pubkey, const size_t signer_i, const size_t n_keys) {
unsigned char serialized[32 + 4 + 32 * SECP256K1_WHITELIST_MAX_N_KEYS] = {0}; unsigned char serialized[32 + 4 + 32 * SECP256K1_WHITELIST_MAX_N_KEYS] = {0};
size_t slen = sizeof(serialized); size_t slen = sizeof(serialized);
secp256k1_whitelist_signature sig; secp256k1_whitelist_signature sig;
@ -41,7 +41,7 @@ void test_whitelist_end_to_end_internal(const unsigned char *summed_seckey, cons
sig.n_keys = n_keys; sig.n_keys = n_keys;
} }
void test_whitelist_end_to_end(const size_t n_keys, int test_all_keys) { static void test_whitelist_end_to_end(const size_t n_keys, int test_all_keys) {
unsigned char **online_seckey = (unsigned char **) malloc(n_keys * sizeof(*online_seckey)); unsigned char **online_seckey = (unsigned char **) malloc(n_keys * sizeof(*online_seckey));
unsigned char **summed_seckey = (unsigned char **) malloc(n_keys * sizeof(*summed_seckey)); unsigned char **summed_seckey = (unsigned char **) malloc(n_keys * sizeof(*summed_seckey));
secp256k1_pubkey *online_pubkeys = (secp256k1_pubkey *) malloc(n_keys * sizeof(*online_pubkeys)); secp256k1_pubkey *online_pubkeys = (secp256k1_pubkey *) malloc(n_keys * sizeof(*online_pubkeys));
@ -104,7 +104,7 @@ void test_whitelist_end_to_end(const size_t n_keys, int test_all_keys) {
free(offline_pubkeys); free(offline_pubkeys);
} }
void test_whitelist_bad_parse(void) { static void test_whitelist_bad_parse(void) {
secp256k1_whitelist_signature sig; secp256k1_whitelist_signature sig;
const unsigned char serialized0[] = { 1+32*(0+1) }; const unsigned char serialized0[] = { 1+32*(0+1) };
@ -131,7 +131,7 @@ void test_whitelist_bad_parse(void) {
CHECK(secp256k1_whitelist_signature_parse(CTX, &sig, serialized2, sizeof(serialized2)) == 0); CHECK(secp256k1_whitelist_signature_parse(CTX, &sig, serialized2, sizeof(serialized2)) == 0);
} }
void test_whitelist_bad_serialize(void) { static void test_whitelist_bad_serialize(void) {
unsigned char serialized[] = { unsigned char serialized[] = {
0x00, 0x00,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
@ -148,7 +148,7 @@ void test_whitelist_bad_serialize(void) {
CHECK(secp256k1_whitelist_signature_serialize(CTX, serialized, &serialized_len, &sig) == 0); CHECK(secp256k1_whitelist_signature_serialize(CTX, serialized, &serialized_len, &sig) == 0);
} }
void run_whitelist_tests(void) { static void run_whitelist_tests(void) {
int i; int i;
test_whitelist_bad_parse(); test_whitelist_bad_parse();
test_whitelist_bad_serialize(); test_whitelist_bad_serialize();

View File

@ -13,7 +13,9 @@ extern "C" {
#include "group.h" #include "group.h"
#if defined(EXHAUSTIVE_TEST_ORDER) #if defined(EXHAUSTIVE_TEST_ORDER)
#if EXHAUSTIVE_TEST_ORDER == 13 # if EXHAUSTIVE_TEST_ORDER == 7
# define WINDOW_G 3
# elif EXHAUSTIVE_TEST_ORDER == 13
# define WINDOW_G 4 # define WINDOW_G 4
# elif EXHAUSTIVE_TEST_ORDER == 199 # elif EXHAUSTIVE_TEST_ORDER == 199
# define WINDOW_G 8 # define WINDOW_G 8

View File

@ -94,9 +94,10 @@ static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar
/** Find r1 and r2 such that r1+r2*2^128 = k. */ /** Find r1 and r2 such that r1+r2*2^128 = k. */
static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k); static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k);
/** Find r1 and r2 such that r1+r2*lambda = k, /** Find r1 and r2 such that r1+r2*lambda = k, where r1 and r2 or their
* where r1 and r2 or their negations are maximum 128 bits long (see secp256k1_ge_mul_lambda). */ * negations are maximum 128 bits long (see secp256k1_ge_mul_lambda). It is
static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k); * required that r1, r2, and k all point to different objects. */
static void secp256k1_scalar_split_lambda(secp256k1_scalar * SECP256K1_RESTRICT r1, secp256k1_scalar * SECP256K1_RESTRICT r2, const secp256k1_scalar * SECP256K1_RESTRICT k);
/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */ /** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */
static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift); static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift);

View File

@ -8,6 +8,7 @@
#define SECP256K1_SCALAR_REPR_IMPL_H #define SECP256K1_SCALAR_REPR_IMPL_H
#include <string.h> #include <string.h>
#include "checkmem.h"
#include "int128.h" #include "int128.h"
#include "modinv64_impl.h" #include "modinv64_impl.h"
@ -987,7 +988,7 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r,
static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) { static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) {
uint64_t mask0, mask1; uint64_t mask0, mask1;
volatile int vflag = flag; volatile int vflag = flag;
VG_CHECK_VERIFY(r->d, sizeof(r->d)); SECP256K1_CHECKMEM_CHECK_VERIFY(r->d, sizeof(r->d));
mask0 = vflag + ~((uint64_t)0); mask0 = vflag + ~((uint64_t)0);
mask1 = ~mask0; mask1 = ~mask0;
r->d[0] = (r->d[0] & mask0) | (a->d[0] & mask1); r->d[0] = (r->d[0] & mask0) | (a->d[0] & mask1);

View File

@ -9,6 +9,7 @@
#include <string.h> #include <string.h>
#include "checkmem.h"
#include "modinv32_impl.h" #include "modinv32_impl.h"
/* Limbs of the secp256k1 order. */ /* Limbs of the secp256k1 order. */
@ -736,7 +737,7 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r,
static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) { static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) {
uint32_t mask0, mask1; uint32_t mask0, mask1;
volatile int vflag = flag; volatile int vflag = flag;
VG_CHECK_VERIFY(r->d, sizeof(r->d)); SECP256K1_CHECKMEM_CHECK_VERIFY(r->d, sizeof(r->d));
mask0 = vflag + ~((uint32_t)0); mask0 = vflag + ~((uint32_t)0);
mask1 = ~mask0; mask1 = ~mask0;
r->d[0] = (r->d[0] & mask0) | (a->d[0] & mask1); r->d[0] = (r->d[0] & mask0) | (a->d[0] & mask1);

View File

@ -33,15 +33,18 @@ static int secp256k1_scalar_set_b32_seckey(secp256k1_scalar *r, const unsigned c
return (!overflow) & (!secp256k1_scalar_is_zero(r)); return (!overflow) & (!secp256k1_scalar_is_zero(r));
} }
/* These parameters are generated using sage/gen_exhaustive_groups.sage. */
#if defined(EXHAUSTIVE_TEST_ORDER) #if defined(EXHAUSTIVE_TEST_ORDER)
# if EXHAUSTIVE_TEST_ORDER == 13 /* 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 # define EXHAUSTIVE_TEST_LAMBDA 9
# elif EXHAUSTIVE_TEST_ORDER == 199 # elif EXHAUSTIVE_TEST_ORDER == 199
# define EXHAUSTIVE_TEST_LAMBDA 92 # define EXHAUSTIVE_TEST_LAMBDA 92
# else # else
# error No known lambda for the specified exhaustive test group order. # error No known lambda for the specified exhaustive test group order.
# endif # 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 * Find r1 and r2 given k, such that r1 + r2 * lambda == k mod n; unlike in the
@ -49,7 +52,10 @@ static int secp256k1_scalar_set_b32_seckey(secp256k1_scalar *r, const unsigned c
* nontrivial to get full test coverage for the exhaustive tests. We therefore * nontrivial to get full test coverage for the exhaustive tests. We therefore
* (arbitrarily) set r2 = k + 5 (mod n) and r1 = k - r2 * lambda (mod n). * (arbitrarily) set r2 = k + 5 (mod n) and r1 = k - r2 * lambda (mod n).
*/ */
static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) { static void secp256k1_scalar_split_lambda(secp256k1_scalar * SECP256K1_RESTRICT r1, secp256k1_scalar * SECP256K1_RESTRICT r2, const secp256k1_scalar * SECP256K1_RESTRICT k) {
VERIFY_CHECK(r1 != k);
VERIFY_CHECK(r2 != k);
VERIFY_CHECK(r1 != r2);
*r2 = (*k + 5) % EXHAUSTIVE_TEST_ORDER; *r2 = (*k + 5) % EXHAUSTIVE_TEST_ORDER;
*r1 = (*k + (EXHAUSTIVE_TEST_ORDER - *r2) * EXHAUSTIVE_TEST_LAMBDA) % EXHAUSTIVE_TEST_ORDER; *r1 = (*k + (EXHAUSTIVE_TEST_ORDER - *r2) * EXHAUSTIVE_TEST_LAMBDA) % EXHAUSTIVE_TEST_ORDER;
} }
@ -116,7 +122,7 @@ static void secp256k1_scalar_split_lambda_verify(const secp256k1_scalar *r1, con
* *
* See proof below. * See proof below.
*/ */
static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) { static void secp256k1_scalar_split_lambda(secp256k1_scalar * SECP256K1_RESTRICT r1, secp256k1_scalar * SECP256K1_RESTRICT r2, const secp256k1_scalar * SECP256K1_RESTRICT k) {
secp256k1_scalar c1, c2; secp256k1_scalar c1, c2;
static const secp256k1_scalar minus_b1 = SECP256K1_SCALAR_CONST( static const secp256k1_scalar minus_b1 = SECP256K1_SCALAR_CONST(
0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
@ -136,6 +142,7 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar
); );
VERIFY_CHECK(r1 != k); VERIFY_CHECK(r1 != k);
VERIFY_CHECK(r2 != k); VERIFY_CHECK(r2 != k);
VERIFY_CHECK(r1 != r2);
/* these _var calls are constant time since the shift amount is constant */ /* these _var calls are constant time since the shift amount is constant */
secp256k1_scalar_mul_shift_var(&c1, k, &g1, 384); secp256k1_scalar_mul_shift_var(&c1, k, &g1, 384);
secp256k1_scalar_mul_shift_var(&c2, k, &g2, 384); secp256k1_scalar_mul_shift_var(&c2, k, &g2, 384);

View File

@ -7,6 +7,7 @@
#ifndef SECP256K1_SCALAR_REPR_IMPL_H #ifndef SECP256K1_SCALAR_REPR_IMPL_H
#define SECP256K1_SCALAR_REPR_IMPL_H #define SECP256K1_SCALAR_REPR_IMPL_H
#include "checkmem.h"
#include "scalar.h" #include "scalar.h"
#include <string.h> #include <string.h>
@ -121,7 +122,7 @@ SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const
static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) { static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) {
uint32_t mask0, mask1; uint32_t mask0, mask1;
volatile int vflag = flag; volatile int vflag = flag;
VG_CHECK_VERIFY(r, sizeof(*r)); SECP256K1_CHECKMEM_CHECK_VERIFY(r, sizeof(*r));
mask0 = vflag + ~((uint32_t)0); mask0 = vflag + ~((uint32_t)0);
mask1 = ~mask0; mask1 = ~mask0;
*r = (*r & mask0) | (*a & mask1); *r = (*r & mask0) | (*a & mask1);

View File

@ -21,6 +21,7 @@
#include "../include/secp256k1_preallocated.h" #include "../include/secp256k1_preallocated.h"
#include "assumptions.h" #include "assumptions.h"
#include "checkmem.h"
#include "util.h" #include "util.h"
#include "field_impl.h" #include "field_impl.h"
@ -41,10 +42,6 @@
# error "secp256k1.h processed without SECP256K1_BUILD defined while building secp256k1.c" # error "secp256k1.h processed without SECP256K1_BUILD defined while building secp256k1.c"
#endif #endif
#if defined(VALGRIND)
# include <valgrind/memcheck.h>
#endif
#ifdef ENABLE_MODULE_GENERATOR #ifdef ENABLE_MODULE_GENERATOR
# include "../include/secp256k1_generator.h" # include "../include/secp256k1_generator.h"
#endif #endif
@ -123,13 +120,19 @@ size_t secp256k1_context_preallocated_size(unsigned int flags) {
return 0; return 0;
} }
if (EXPECT(!SECP256K1_CHECKMEM_RUNNING() && (flags & SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY), 0)) {
secp256k1_callback_call(&default_illegal_callback,
"Declassify flag requires running with memory checking");
return 0;
}
return ret; return ret;
} }
size_t secp256k1_context_preallocated_clone_size(const secp256k1_context* ctx) { size_t secp256k1_context_preallocated_clone_size(const secp256k1_context* ctx) {
size_t ret = sizeof(secp256k1_context);
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
return ret; ARG_CHECK(secp256k1_context_is_proper(ctx));
return sizeof(secp256k1_context);
} }
secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigned int flags) { secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigned int flags) {
@ -170,6 +173,7 @@ secp256k1_context* secp256k1_context_preallocated_clone(const secp256k1_context*
secp256k1_context* ret; secp256k1_context* ret;
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(prealloc != NULL); ARG_CHECK(prealloc != NULL);
ARG_CHECK(secp256k1_context_is_proper(ctx));
ret = (secp256k1_context*)prealloc; ret = (secp256k1_context*)prealloc;
*ret = *ctx; *ret = *ctx;
@ -181,6 +185,8 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
size_t prealloc_size; size_t prealloc_size;
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_context_is_proper(ctx));
prealloc_size = secp256k1_context_preallocated_clone_size(ctx); prealloc_size = secp256k1_context_preallocated_clone_size(ctx);
ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, prealloc_size); ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, prealloc_size);
ret = secp256k1_context_preallocated_clone(ctx, ret); ret = secp256k1_context_preallocated_clone(ctx, ret);
@ -188,17 +194,26 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
} }
void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) { void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) {
ARG_CHECK_VOID(ctx != secp256k1_context_static); ARG_CHECK_VOID(ctx == NULL || secp256k1_context_is_proper(ctx));
if (ctx != NULL) {
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); /* Defined as noop */
if (ctx == NULL) {
return;
} }
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
} }
void secp256k1_context_destroy(secp256k1_context* ctx) { void secp256k1_context_destroy(secp256k1_context* ctx) {
if (ctx != NULL) { ARG_CHECK_VOID(ctx == NULL || secp256k1_context_is_proper(ctx));
/* Defined as noop */
if (ctx == NULL) {
return;
}
secp256k1_context_preallocated_destroy(ctx); secp256k1_context_preallocated_destroy(ctx);
free(ctx); free(ctx);
}
} }
void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) {
@ -236,17 +251,10 @@ void secp256k1_scratch_space_destroy(const secp256k1_context *ctx, secp256k1_scr
} }
/* Mark memory as no-longer-secret for the purpose of analysing constant-time behaviour /* Mark memory as no-longer-secret for the purpose of analysing constant-time behaviour
* of the software. This is setup for use with valgrind but could be substituted with * of the software.
* the appropriate instrumentation for other analysis tools.
*/ */
static SECP256K1_INLINE void secp256k1_declassify(const secp256k1_context* ctx, const void *p, size_t len) { static SECP256K1_INLINE void secp256k1_declassify(const secp256k1_context* ctx, const void *p, size_t len) {
#if defined(VALGRIND) if (EXPECT(ctx->declassify, 0)) SECP256K1_CHECKMEM_DEFINE(p, len);
if (EXPECT(ctx->declassify,0)) VALGRIND_MAKE_MEM_DEFINED(p, len);
#else
(void)ctx;
(void)p;
(void)len;
#endif
} }
static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) { static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) {
@ -791,6 +799,8 @@ int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey
int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) { int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) {
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_context_is_proper(ctx));
if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) { if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) {
secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32);
} }

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@
static int count = 2; static int count = 2;
/** stolen from tests.c */ /** stolen from tests.c */
void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) { static void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) {
CHECK(a->infinity == b->infinity); CHECK(a->infinity == b->infinity);
if (a->infinity) { if (a->infinity) {
return; return;
@ -33,7 +33,7 @@ void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) {
CHECK(secp256k1_fe_equal_var(&a->y, &b->y)); CHECK(secp256k1_fe_equal_var(&a->y, &b->y));
} }
void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) { static void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) {
secp256k1_fe z2s; secp256k1_fe z2s;
secp256k1_fe u1, u2, s1, s2; secp256k1_fe u1, u2, s1, s2;
CHECK(a->infinity == b->infinity); CHECK(a->infinity == b->infinity);
@ -50,7 +50,7 @@ void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) {
CHECK(secp256k1_fe_equal_var(&s1, &s2)); CHECK(secp256k1_fe_equal_var(&s1, &s2));
} }
void random_fe(secp256k1_fe *x) { static void random_fe(secp256k1_fe *x) {
unsigned char bin[32]; unsigned char bin[32];
do { do {
secp256k1_testrand256(bin); secp256k1_testrand256(bin);
@ -70,7 +70,7 @@ SECP256K1_INLINE static int skip_section(uint64_t* iter) {
return ((((uint32_t)*iter ^ (*iter >> 32)) * num_cores) >> 32) != this_core; return ((((uint32_t)*iter ^ (*iter >> 32)) * num_cores) >> 32) != this_core;
} }
int secp256k1_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32, static int secp256k1_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32,
const unsigned char *key32, const unsigned char *algo16, const unsigned char *key32, const unsigned char *algo16,
void *data, unsigned int attempt) { void *data, unsigned int attempt) {
secp256k1_scalar s; secp256k1_scalar s;
@ -90,7 +90,7 @@ int secp256k1_nonce_function_smallint(unsigned char *nonce32, const unsigned cha
return 1; return 1;
} }
void test_exhaustive_endomorphism(const secp256k1_ge *group) { static void test_exhaustive_endomorphism(const secp256k1_ge *group) {
int i; int i;
for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) {
secp256k1_ge res; secp256k1_ge res;
@ -99,7 +99,7 @@ void test_exhaustive_endomorphism(const secp256k1_ge *group) {
} }
} }
void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *groupj) { static void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *groupj) {
int i, j; int i, j;
uint64_t iter = 0; uint64_t iter = 0;
@ -159,7 +159,7 @@ void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *gr
} }
} }
void test_exhaustive_ecmult(const secp256k1_ge *group, const secp256k1_gej *groupj) { static void test_exhaustive_ecmult(const secp256k1_ge *group, const secp256k1_gej *groupj) {
int i, j, r_log; int i, j, r_log;
uint64_t iter = 0; uint64_t iter = 0;
for (r_log = 1; r_log < EXHAUSTIVE_TEST_ORDER; r_log++) { for (r_log = 1; r_log < EXHAUSTIVE_TEST_ORDER; r_log++) {
@ -195,7 +195,7 @@ static int ecmult_multi_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t
return 1; return 1;
} }
void test_exhaustive_ecmult_multi(const secp256k1_context *ctx, const secp256k1_ge *group) { static void test_exhaustive_ecmult_multi(const secp256k1_context *ctx, const secp256k1_ge *group) {
int i, j, k, x, y; int i, j, k, x, y;
uint64_t iter = 0; uint64_t iter = 0;
secp256k1_scratch *scratch = secp256k1_scratch_create(&ctx->error_callback, 4096); secp256k1_scratch *scratch = secp256k1_scratch_create(&ctx->error_callback, 4096);
@ -225,7 +225,7 @@ void test_exhaustive_ecmult_multi(const secp256k1_context *ctx, const secp256k1_
secp256k1_scratch_destroy(&ctx->error_callback, scratch); secp256k1_scratch_destroy(&ctx->error_callback, scratch);
} }
void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k, int* overflow) { static void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k, int* overflow) {
secp256k1_fe x; secp256k1_fe x;
unsigned char x_bin[32]; unsigned char x_bin[32];
k %= EXHAUSTIVE_TEST_ORDER; k %= EXHAUSTIVE_TEST_ORDER;
@ -235,7 +235,7 @@ void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k, int* overfl
secp256k1_scalar_set_b32(r, x_bin, overflow); secp256k1_scalar_set_b32(r, x_bin, overflow);
} }
void test_exhaustive_verify(const secp256k1_context *ctx, const secp256k1_ge *group) { static void test_exhaustive_verify(const secp256k1_context *ctx, const secp256k1_ge *group) {
int s, r, msg, key; int s, r, msg, key;
uint64_t iter = 0; uint64_t iter = 0;
for (s = 1; s < EXHAUSTIVE_TEST_ORDER; s++) { for (s = 1; s < EXHAUSTIVE_TEST_ORDER; s++) {
@ -288,7 +288,7 @@ void test_exhaustive_verify(const secp256k1_context *ctx, const secp256k1_ge *gr
} }
} }
void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *group) { static void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *group) {
int i, j, k; int i, j, k;
uint64_t iter = 0; uint64_t iter = 0;

View File

@ -97,25 +97,6 @@ static const secp256k1_callback default_error_callback = {
#define VERIFY_SETUP(stmt) #define VERIFY_SETUP(stmt)
#endif #endif
/* Define `VG_UNDEF` and `VG_CHECK` when VALGRIND is defined */
#if !defined(VG_CHECK)
# if defined(VALGRIND)
# include <valgrind/memcheck.h>
# define VG_UNDEF(x,y) VALGRIND_MAKE_MEM_UNDEFINED((x),(y))
# define VG_CHECK(x,y) VALGRIND_CHECK_MEM_IS_DEFINED((x),(y))
# else
# define VG_UNDEF(x,y)
# define VG_CHECK(x,y)
# endif
#endif
/* Like `VG_CHECK` but on VERIFY only */
#if defined(VERIFY)
#define VG_CHECK_VERIFY(x,y) VG_CHECK((x), (y))
#else
#define VG_CHECK_VERIFY(x,y)
#endif
static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_t size) { static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_t size) {
void *ret = malloc(size); void *ret = malloc(size);
if (ret == NULL) { if (ret == NULL) {
@ -321,7 +302,7 @@ static SECP256K1_INLINE int secp256k1_ctz32_var_debruijn(uint32_t x) {
0x10, 0x07, 0x0C, 0x1A, 0x1F, 0x17, 0x12, 0x05, 0x15, 0x09, 0x0F, 0x0B, 0x10, 0x07, 0x0C, 0x1A, 0x1F, 0x17, 0x12, 0x05, 0x15, 0x09, 0x0F, 0x0B,
0x1E, 0x11, 0x08, 0x0E, 0x1D, 0x0D, 0x1C, 0x1B 0x1E, 0x11, 0x08, 0x0E, 0x1D, 0x0D, 0x1C, 0x1B
}; };
return debruijn[((x & -x) * 0x04D7651F) >> 27]; return debruijn[(uint32_t)((x & -x) * 0x04D7651FU) >> 27];
} }
/* Determine the number of trailing zero bits in a (non-zero) 64-bit x. /* Determine the number of trailing zero bits in a (non-zero) 64-bit x.
@ -334,7 +315,7 @@ static SECP256K1_INLINE int secp256k1_ctz64_var_debruijn(uint64_t x) {
63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10, 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
}; };
return debruijn[((x & -x) * 0x022FDD63CC95386D) >> 58]; return debruijn[(uint64_t)((x & -x) * 0x022FDD63CC95386DU) >> 58];
} }
/* Determine the number of trailing zero bits in a (non-zero) 32-bit x. */ /* Determine the number of trailing zero bits in a (non-zero) 32-bit x. */