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:
commit
0d540ec942
40
.cirrus.yml
40
.cirrus.yml
@ -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
3
.gitignore
vendored
@ -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
|
||||||
|
14
CHANGELOG.md
14
CHANGELOG.md
@ -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
|
||||||
|
54
Makefile.am
54
Makefile.am
@ -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
|
||||||
|
29
ci/cirrus.sh
29
ci/cirrus.sh
@ -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
|
||||||
|
27
configure.ac
27
configure.ac
@ -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"
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
@ -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];
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
*
|
*
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
*
|
*
|
||||||
|
@ -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@
|
|
||||||
|
|
||||||
|
@ -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. */")
|
||||||
|
@ -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))
|
||||||
|
@ -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");
|
||||||
|
|
||||||
|
12
src/bench.h
12
src/bench.h
@ -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) ";
|
||||||
|
@ -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]);
|
||||||
|
@ -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);
|
||||||
|
@ -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
88
src/checkmem.h
Normal 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 */
|
@ -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
|
||||||
|
|
@ -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 */
|
||||||
|
@ -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 */
|
||||||
|
@ -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 */
|
||||||
|
103
src/group_impl.h
103
src/group_impl.h
@ -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) {
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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 */
|
||||||
|
@ -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 */
|
||||||
|
@ -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 */
|
||||||
|
@ -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 */
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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] = {
|
||||||
|
@ -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();
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
666
src/tests.c
666
src/tests.c
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||||
|
|
||||||
|
23
src/util.h
23
src/util.h
@ -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. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user