mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-26 17:52:13 +01:00
Squashed 'src/secp256k1/' changes from be8d9c262f..0559fc6e41
0559fc6e41 Merge bitcoin-core/secp256k1#988: Make signing table fully static 7dfceceea6 build: Remove #undef hack for ASM in the precomputation programs bb36fe9be0 ci: Test `make precomp` d94a37a20c build: Remove CC_FOR_BUILD stuff ad63bb4c29 build: Prebuild and distribute ecmult_gen table ac49361ed0 prealloc: Get rid of manual memory management for prealloc contexts 6573c08f65 ecmult_gen: Tidy precomputed file and save space 5eba83f17c ecmult_gen: Precompute tables for all values of ECMULT_GEN_PREC_BITS 5d0dbef018 Merge bitcoin-core/secp256k1#942: Verify that secp256k1_ge_set_gej_zinv does not operate on infinity. 486205aa68 Merge bitcoin-core/secp256k1#920: Test all ecmult functions with many j*2^i combinations fdb33dd122 refactor: Make PREC_BITS a parameter of ecmult_gen_build_prec_table 5eb519e1f6 ci: reduce TEST_ITERS in memcheck run e2cf77328a Test ecmult functions for all i*2^j for j=0..255 and odd i=1..255. 61ae37c612 Merge bitcoin-core/secp256k1#1022: build: Windows DLL additions 4f01840b82 Merge bitcoin-core/secp256k1#1027: build: Add a check that Valgrind actually supports a host platform 6ad908aa00 Merge bitcoin-core/secp256k1#1008: bench.c: add `--help` option and ci: move env variables 592661c22f ci: move test environment variable declaration to .cirrus.yml dcbe84b841 bench: add --help option to bench. 099bad945e Comment and check a parameter for inf in secp256k1_ecmult_const. 6c0be857f8 Verify that secp256k1_ge_set_gej_zinv does not operate on infinity. a->x and a->y should not be used if the infinity flag is set. 4900227451 Merge bitcoin-core/secp256k1#1025: build: replace backtick command substitution with $() 7c7ce872a5 build: Add a check that Valgrind actually supports a host platform a4875e30a6 refactor: Move default callbacks to util.h 4c94c55bce doc: Remove obsolete hint for valgrind stack size 5106226991 exhaustive_tests: Fix with ecmult_gen table with custom generator e1a76530db refactor: Make generator a parameter of ecmult_gen_create_prec_table 9ad09f6911 refactor: Rename program that generates static ecmult_gen table 8ae18f1ab3 refactor: Rename file that contains static ecmult_gen table 00d2fa116e ecmult_gen: Make code consistent with comment 3b0c2185ea ecmult_gen: Simplify ecmult_gen context after making table static 2b7c7497ef build: replace backtick command substitution with $() 49f608de47 Merge bitcoin-core/secp256k1#1004: ecmult: fix definition of STRAUSS_SCRATCH_OBJECTS c0cd7de6d4 build: add -no-undefined to libtool LDFLAGS fe32a79d35 build: pass win32-dll to LT_INIT 60bf8890df ecmult: fix definition of STRAUSS_SCRATCH_OBJECTS fecf436d53 Merge bitcoin-core/secp256k1#1019: build: don't append valgrind CPPFLAGS if not installed (macOS) 2e5e4b67df Merge bitcoin-core/secp256k1#1020: doc: remove use of <0xa0> "no break space" 812ff5c747 doc: remove use of 0xa0 "no break space" 214042a170 build: don't append valgrind CPPFLAGS if not installed e43ba02cfc refactor: Decouple table generation and ecmult_gen context 22dc2c0a0d ecmult_gen: Move table creation to new file and force static prec 793ad9016a Merge bitcoin-core/secp256k1#1010: doc: Minor fixes in safegcd_implementation.md dc9b6853b7 doc: Minor fixes in safegcd_implementation.md ea5e8a9c47 Merge bitcoin-core/secp256k1#1012: Fix typos 233297579d Fix typos 7006f1b97f Merge bitcoin-core/secp256k1#1011: ci: Enable -g if we set CFLAGS manually 72de1359e9 ci: Enable -g if we set CFLAGS manually 74c34e727b Merge bitcoin-core/secp256k1#1009: refactor: Use (int)&(int) in boolean context to avoid compiler warning 16d132215c refactor: Use (int)&(int) in boolean context to avoid compiler warning c74a7b7e51 Merge bitcoin-core/secp256k1#1007: doc: Replace apoelstra's GPG key by jonasnick's GPG key 3b157c48ed doc: Suggest keys.openpgp.org as keyserver in SECURITY.md 73a7472cd0 doc: Replace apoelstra's GPG key by jonasnick's GPG key 515a5dbd02 Merge bitcoin-core/secp256k1#991: Merge all "external" benchmarks into a single bench binary af6abcb3d0 Make bench support selecting which benchmarks to run 9f56bdf5b9 Merge bench_schnorrsig into bench 3208557ae1 Merge bench_recover into bench 855e18d8a8 Merge bench_ecdh into bench 2a7be678a6 Combine bench_sign and bench_verify into single bench 8fa41201bd Merge bitcoin-core/secp256k1#1002: Make aux_rnd32==NULL behave identical to 0x0000..00. 5324f8942d Make aux_rnd32==NULL behave identical to 0x0000..00. 21c188b3c5 Merge bitcoin-core/secp256k1#943: VERIFY_CHECK precondition for secp256k1_fe_set_int. 3e7b2ea194 Merge bitcoin-core/secp256k1#999: bench_ecmult: improve clarity of output 23e2f66726 bench: don't return 1 in have_flag() if argc = 1 96b1ad2ea9 bench_ecmult: improve clarity of output 20d791edfb Merge bitcoin-core/secp256k1#989: Shared benchmark format for command line and CSV outputs aa1b889b61 Merge bitcoin-core/secp256k1#996: Fix G.y parity in sage code 044d956305 Fix G.y parity in sage code b4b130678d create csv file from the benchmark output 26a255beb6 Shared benchmark format for command line and CSV outputs 9526874d14 Merge bitcoin-core/secp256k1#810: Avoid overly-wide multiplications in 5x52 field mul/sqr 920a0e5fa6 Merge bitcoin-core/secp256k1#952: Avoid computing out-of-bounds pointer. f34b5cae03 Merge bitcoin-core/secp256k1#983: [RFC] Remove OpenSSL testing support 297ce82091 Merge bitcoin-core/secp256k1#966: Make aux_rand32 arg to secp256k1_schnorrsig_sign const 2888640132 VERIFY_CHECK precondition for secp256k1_fe_set_int. d49011f54c Make _set_fe_int( . , 0 ) set magnitude to 0 bc08599e77 Remove OpenSSL testing support 10f9bd84f4 Merge bitcoin-core/secp256k1#987: Fix unused parameter warnings when building without VERIFY 189f6bcfef Fix unused parameter warnings when building without VERIFY da0092bccc Merge bitcoin-core/secp256k1#986: tests: remove `secp256k1_fe_verify` from tests.c and modify `_fe_from_storage` to call `_fe_verify` d43993724d tests: remove `secp256k1_fe_verify` from tests.c and modify `secp256k1_fe_from_storage` to call `secp256k1_fe_verify` 2a3a97c665 Merge bitcoin-core/secp256k1#976: `secp256k1_schnorrsig_sign_internal` should be static aa5d34a8fe Merge bitcoin-core/secp256k1#783: Make the public API docs more consistent and explicit 72713872a8 Add missing static to secp256k1_schnorrsig_sign_internal db4667d5e0 Make aux_rand32 arg to secp256k1_schnorrsig_sign const 9a5a87e0f1 Merge bitcoin-core/secp256k1#956: Replace ecmult_context with a generated static array. 20abd52c2e Add tests for pre_g tables. 6815761cf5 Remove ecmult_context. f20dcbbad1 Correct typo. 16a3cc07e8 Generate ecmult_static_pre_g.h 8de2d86a06 Bump memory limits in advance of making the ecmult context static. d7ec49a689 Merge bitcoin-core/secp256k1#969: ci: Fixes after Debian release 5d5c74a057 tests: Rewrite code to circument potential bug in clang 3d2f492ceb ci: Install libasan6 (instead of 5) after Debian upgrade adec5a1638 Add missing null check for ctx and input keys in the public API f4edfc7581 Improve consistency for NULL arguments in the public interface 9be7b0f083 Avoid computing out-of-bounds pointer. b53e0cd61f Avoid overly-wide multiplications git-subtree-dir: src/secp256k1 git-subtree-split: 0559fc6e41b65af6e52c32eb9b1286494412a162
This commit is contained in:
parent
c020cbaa5c
commit
86dbc4d075
26
.cirrus.yml
26
.cirrus.yml
@ -19,9 +19,9 @@ env:
|
||||
RECOVERY: no
|
||||
SCHNORRSIG: no
|
||||
### test options
|
||||
TEST_ITERS:
|
||||
SECP256K1_TEST_ITERS:
|
||||
BENCH: yes
|
||||
BENCH_ITERS: 2
|
||||
SECP256K1_BENCH_ITERS: 2
|
||||
CTIMETEST: yes
|
||||
|
||||
cat_logs_snippet: &CAT_LOGS
|
||||
@ -171,7 +171,7 @@ task:
|
||||
memory: 1G
|
||||
env:
|
||||
WRAPPER_CMD: qemu-s390x
|
||||
TEST_ITERS: 16
|
||||
SECP256K1_TEST_ITERS: 16
|
||||
HOST: s390x-linux-gnu
|
||||
WITH_VALGRIND: no
|
||||
ECDH: yes
|
||||
@ -194,7 +194,7 @@ task:
|
||||
memory: 1G
|
||||
env:
|
||||
WRAPPER_CMD: qemu-arm
|
||||
TEST_ITERS: 16
|
||||
SECP256K1_TEST_ITERS: 16
|
||||
HOST: arm-linux-gnueabihf
|
||||
WITH_VALGRIND: no
|
||||
ECDH: yes
|
||||
@ -218,7 +218,7 @@ task:
|
||||
memory: 1G
|
||||
env:
|
||||
WRAPPER_CMD: qemu-aarch64
|
||||
TEST_ITERS: 16
|
||||
SECP256K1_TEST_ITERS: 16
|
||||
HOST: aarch64-linux-gnu
|
||||
WITH_VALGRIND: no
|
||||
ECDH: yes
|
||||
@ -239,7 +239,7 @@ task:
|
||||
memory: 1G
|
||||
env:
|
||||
WRAPPER_CMD: qemu-ppc64le
|
||||
TEST_ITERS: 16
|
||||
SECP256K1_TEST_ITERS: 16
|
||||
HOST: powerpc64le-linux-gnu
|
||||
WITH_VALGRIND: no
|
||||
ECDH: yes
|
||||
@ -260,7 +260,7 @@ task:
|
||||
memory: 1G
|
||||
env:
|
||||
WRAPPER_CMD: wine64-stable
|
||||
TEST_ITERS: 16
|
||||
SECP256K1_TEST_ITERS: 16
|
||||
HOST: x86_64-w64-mingw32
|
||||
WITH_VALGRIND: no
|
||||
ECDH: yes
|
||||
@ -278,28 +278,26 @@ task:
|
||||
container:
|
||||
dockerfile: ci/linux-debian.Dockerfile
|
||||
cpu: 1
|
||||
memory: 1G
|
||||
memory: 2G
|
||||
env:
|
||||
ECDH: yes
|
||||
RECOVERY: yes
|
||||
EXPERIMENTAL: yes
|
||||
SCHNORRSIG: yes
|
||||
CTIMETEST: no
|
||||
EXTRAFLAGS: "--disable-openssl-tests"
|
||||
matrix:
|
||||
- name: "Valgrind (memcheck)"
|
||||
env:
|
||||
# The `--error-exitcode` is required to make the test fail if valgrind found errors, otherwise it'll return 0 (https://www.valgrind.org/docs/manual/manual-core.html)
|
||||
WRAPPER_CMD: "valgrind --error-exitcode=42"
|
||||
TEST_ITERS: 16
|
||||
SECP256K1_TEST_ITERS: 2
|
||||
- name: "UBSan, ASan, LSan"
|
||||
env:
|
||||
CFLAGS: "-fsanitize=undefined,address"
|
||||
CFLAGS_FOR_BUILD: "-fsanitize=undefined,address"
|
||||
CFLAGS: "-fsanitize=undefined,address -g"
|
||||
UBSAN_OPTIONS: "print_stacktrace=1:halt_on_error=1"
|
||||
ASAN_OPTIONS: "strict_string_checks=1:detect_stack_use_after_return=1:detect_leaks=1"
|
||||
LSAN_OPTIONS: "use_unaligned=1"
|
||||
TEST_ITERS: 32
|
||||
SECP256K1_TEST_ITERS: 32
|
||||
# Try to cover many configurations with just a tiny matrix.
|
||||
matrix:
|
||||
- env:
|
||||
@ -330,7 +328,7 @@ task:
|
||||
# ./configure correctly errors out when given CC=g++.
|
||||
# We hack around this by passing CC=g++ only to make.
|
||||
CC: gcc
|
||||
MAKEFLAGS: -j2 CC=g++ CFLAGS=-fpermissive
|
||||
MAKEFLAGS: -j2 CC=g++ CFLAGS=-fpermissive\ -g
|
||||
WERROR_CFLAGS:
|
||||
EXPERIMENTAL: yes
|
||||
ECDH: yes
|
||||
|
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
src/ecmult_static_pre_g.h linguist-generated
|
||||
src/ecmult_gen_static_prec_table.h linguist-generated
|
12
.gitignore
vendored
12
.gitignore
vendored
@ -1,18 +1,15 @@
|
||||
bench_inv
|
||||
bench_ecdh
|
||||
bench
|
||||
bench_ecmult
|
||||
bench_schnorrsig
|
||||
bench_sign
|
||||
bench_verify
|
||||
bench_recover
|
||||
bench_internal
|
||||
tests
|
||||
exhaustive_tests
|
||||
gen_context
|
||||
gen_ecmult_gen_static_prec_table
|
||||
gen_ecmult_static_pre_g
|
||||
valgrind_ctime_test
|
||||
*.exe
|
||||
*.so
|
||||
*.a
|
||||
*.csv
|
||||
!.gitignore
|
||||
|
||||
Makefile
|
||||
@ -44,7 +41,6 @@ coverage.*.html
|
||||
|
||||
src/libsecp256k1-config.h
|
||||
src/libsecp256k1-config.h.in
|
||||
src/ecmult_static_context.h
|
||||
build-aux/config.guess
|
||||
build-aux/config.sub
|
||||
build-aux/depcomp
|
||||
|
68
Makefile.am
68
Makefile.am
@ -1,3 +1,5 @@
|
||||
.PHONY: clean-precomp precomp
|
||||
|
||||
ACLOCAL_AMFLAGS = -I build-aux/m4
|
||||
|
||||
# AM_CFLAGS will be automatically prepended to CFLAGS by Automake when compiling some foo
|
||||
@ -28,6 +30,8 @@ noinst_HEADERS += src/ecmult_const.h
|
||||
noinst_HEADERS += src/ecmult_const_impl.h
|
||||
noinst_HEADERS += src/ecmult_gen.h
|
||||
noinst_HEADERS += src/ecmult_gen_impl.h
|
||||
noinst_HEADERS += src/ecmult_gen_prec.h
|
||||
noinst_HEADERS += src/ecmult_gen_prec_impl.h
|
||||
noinst_HEADERS += src/field_10x26.h
|
||||
noinst_HEADERS += src/field_10x26_impl.h
|
||||
noinst_HEADERS += src/field_5x52.h
|
||||
@ -50,6 +54,7 @@ noinst_HEADERS += src/hash_impl.h
|
||||
noinst_HEADERS += src/field.h
|
||||
noinst_HEADERS += src/field_impl.h
|
||||
noinst_HEADERS += src/bench.h
|
||||
noinst_HEADERS += src/basic-config.h
|
||||
noinst_HEADERS += contrib/lax_der_parsing.h
|
||||
noinst_HEADERS += contrib/lax_der_parsing.c
|
||||
noinst_HEADERS += contrib/lax_der_privatekey_parsing.h
|
||||
@ -74,6 +79,7 @@ endif
|
||||
libsecp256k1_la_SOURCES = src/secp256k1.c
|
||||
libsecp256k1_la_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES)
|
||||
libsecp256k1_la_LIBADD = $(SECP_LIBS) $(COMMON_LIB)
|
||||
libsecp256k1_la_LDFLAGS = -no-undefined
|
||||
|
||||
if VALGRIND_ENABLED
|
||||
libsecp256k1_la_CPPFLAGS += -DVALGRIND
|
||||
@ -81,13 +87,9 @@ endif
|
||||
|
||||
noinst_PROGRAMS =
|
||||
if USE_BENCHMARK
|
||||
noinst_PROGRAMS += bench_verify bench_sign bench_internal bench_ecmult
|
||||
bench_verify_SOURCES = src/bench_verify.c
|
||||
bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB)
|
||||
# SECP_TEST_INCLUDES are only used here for CRYPTO_CPPFLAGS
|
||||
bench_verify_CPPFLAGS = $(SECP_TEST_INCLUDES)
|
||||
bench_sign_SOURCES = src/bench_sign.c
|
||||
bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB)
|
||||
noinst_PROGRAMS += bench bench_internal bench_ecmult
|
||||
bench_SOURCES = src/bench.c
|
||||
bench_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB)
|
||||
bench_internal_SOURCES = src/bench_internal.c
|
||||
bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB)
|
||||
bench_internal_CPPFLAGS = $(SECP_INCLUDES)
|
||||
@ -118,7 +120,7 @@ endif
|
||||
if USE_EXHAUSTIVE_TESTS
|
||||
noinst_PROGRAMS += exhaustive_tests
|
||||
exhaustive_tests_SOURCES = src/tests_exhaustive.c
|
||||
exhaustive_tests_CPPFLAGS = -I$(top_srcdir)/src $(SECP_INCLUDES)
|
||||
exhaustive_tests_CPPFLAGS = $(SECP_INCLUDES)
|
||||
if !ENABLE_COVERAGE
|
||||
exhaustive_tests_CPPFLAGS += -DVERIFY
|
||||
endif
|
||||
@ -127,29 +129,45 @@ exhaustive_tests_LDFLAGS = -static
|
||||
TESTS += exhaustive_tests
|
||||
endif
|
||||
|
||||
if USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) -I$(builddir)/src
|
||||
### Precomputed tables
|
||||
EXTRA_PROGRAMS = gen_ecmult_static_pre_g gen_ecmult_gen_static_prec_table
|
||||
CLEANFILES = $(EXTRA_PROGRAMS)
|
||||
|
||||
gen_context_OBJECTS = gen_context.o
|
||||
gen_context_BIN = gen_context$(BUILD_EXEEXT)
|
||||
gen_%.o: src/gen_%.c src/libsecp256k1-config.h
|
||||
$(CC_FOR_BUILD) $(DEFS) $(CPPFLAGS_FOR_BUILD) $(SECP_CFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@
|
||||
gen_ecmult_static_pre_g_SOURCES = src/gen_ecmult_static_pre_g.c
|
||||
gen_ecmult_static_pre_g_CPPFLAGS = $(SECP_INCLUDES)
|
||||
gen_ecmult_static_pre_g_LDADD = $(SECP_LIBS) $(COMMON_LIB)
|
||||
|
||||
$(gen_context_BIN): $(gen_context_OBJECTS)
|
||||
$(CC_FOR_BUILD) $(SECP_CFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) $^ -o $@
|
||||
gen_ecmult_gen_static_prec_table_SOURCES = src/gen_ecmult_gen_static_prec_table.c
|
||||
gen_ecmult_gen_static_prec_table_CPPFLAGS = $(SECP_INCLUDES)
|
||||
gen_ecmult_gen_static_prec_table_LDADD = $(SECP_LIBS) $(COMMON_LIB)
|
||||
|
||||
$(libsecp256k1_la_OBJECTS): src/ecmult_static_context.h
|
||||
$(tests_OBJECTS): src/ecmult_static_context.h
|
||||
$(bench_internal_OBJECTS): src/ecmult_static_context.h
|
||||
$(bench_ecmult_OBJECTS): src/ecmult_static_context.h
|
||||
# See Automake manual, Section "Errors with distclean".
|
||||
# We don't list any dependencies for the prebuilt files here because
|
||||
# otherwise make's decision whether to rebuild them (even in the first
|
||||
# build by a normal user) depends on mtimes, and thus is very fragile.
|
||||
# This means that rebuilds of the prebuilt files always need to be
|
||||
# forced by deleting them, e.g., by invoking `make clean-precomp`.
|
||||
src/ecmult_static_pre_g.h:
|
||||
$(MAKE) $(AM_MAKEFLAGS) gen_ecmult_static_pre_g$(EXEEXT)
|
||||
./gen_ecmult_static_pre_g$(EXEEXT)
|
||||
src/ecmult_gen_static_prec_table.h:
|
||||
$(MAKE) $(AM_MAKEFLAGS) gen_ecmult_gen_static_prec_table$(EXEEXT)
|
||||
./gen_ecmult_gen_static_prec_table$(EXEEXT)
|
||||
|
||||
src/ecmult_static_context.h: $(gen_context_BIN)
|
||||
./$(gen_context_BIN)
|
||||
PRECOMP = src/ecmult_gen_static_prec_table.h src/ecmult_static_pre_g.h
|
||||
noinst_HEADERS += $(PRECOMP)
|
||||
precomp: $(PRECOMP)
|
||||
|
||||
CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h
|
||||
endif
|
||||
# Ensure the prebuilt files will be build first (only if they don't exist,
|
||||
# e.g., after `make maintainer-clean`).
|
||||
BUILT_SOURCES = $(PRECOMP)
|
||||
|
||||
EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h
|
||||
maintainer-clean-local: clean-precomp
|
||||
|
||||
clean-precomp:
|
||||
rm -f $(PRECOMP)
|
||||
|
||||
EXTRA_DIST = autogen.sh SECURITY.md
|
||||
|
||||
if ENABLE_MODULE_ECDH
|
||||
include src/modules/ecdh/Makefile.am.include
|
||||
|
23
README.md
23
README.md
@ -66,18 +66,9 @@ libsecp256k1 is built using autotools:
|
||||
$ ./autogen.sh
|
||||
$ ./configure
|
||||
$ make
|
||||
$ make check
|
||||
$ make check # run the test suite
|
||||
$ sudo make install # optional
|
||||
|
||||
Exhaustive tests
|
||||
-----------
|
||||
|
||||
$ ./exhaustive_tests
|
||||
|
||||
With valgrind, you might need to increase the max stack size:
|
||||
|
||||
$ valgrind --max-stackframe=2500000 ./exhaustive_tests
|
||||
|
||||
Test coverage
|
||||
-----------
|
||||
|
||||
@ -100,6 +91,18 @@ To create a HTML report with coloured and annotated source code:
|
||||
$ mkdir -p coverage
|
||||
$ gcovr --exclude 'src/bench*' --html --html-details -o coverage/coverage.html
|
||||
|
||||
Benchmark
|
||||
------------
|
||||
If configured with `--enable-benchmark` (which is the default), binaries for benchmarking the libsecp256k1 functions will be present in the root directory after the build.
|
||||
|
||||
To print the benchmark result to the command line:
|
||||
|
||||
$ ./bench_name
|
||||
|
||||
To create a CSV file for the benchmark result :
|
||||
|
||||
$ ./bench_name | sed '2d;s/ \{1,\}//g' > bench_name.csv
|
||||
|
||||
Reporting a vulnerability
|
||||
------------
|
||||
|
||||
|
@ -9,7 +9,7 @@ The following keys may be used to communicate sensitive information to developer
|
||||
| Name | Fingerprint |
|
||||
|------|-------------|
|
||||
| Pieter Wuille | 133E AC17 9436 F14A 5CF1 B794 860F EB80 4E66 9320 |
|
||||
| Andrew Poelstra | 699A 63EF C17A D3A9 A34C FFC0 7AD0 A91C 40BD 0091 |
|
||||
| Jonas Nick | 36C7 1A37 C9D9 88BD E825 08D9 B1A7 0E4F 8DCD 0366 |
|
||||
| Tim Ruffing | 09E0 3F87 1092 E40E 106E 902B 33BC 86AB 80FF 5516 |
|
||||
|
||||
You can import a key by running the following command with that individual’s fingerprint: `gpg --recv-keys "<fingerprint>"` Ensure that you put quotes around fingerprints containing spaces.
|
||||
You can import a key by running the following command with that individual’s fingerprint: `gpg --keyserver hkps://keys.openpgp.org --recv-keys "<fingerprint>"` Ensure that you put quotes around fingerprints containing spaces.
|
||||
|
@ -1,125 +0,0 @@
|
||||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_PROG_CC_FOR_BUILD
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This macro searches for a C compiler that generates native executables,
|
||||
# that is a C compiler that surely is not a cross-compiler. This can be
|
||||
# useful if you have to generate source code at compile-time like for
|
||||
# example GCC does.
|
||||
#
|
||||
# The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything
|
||||
# needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD).
|
||||
# The value of these variables can be overridden by the user by specifying
|
||||
# a compiler with an environment variable (like you do for standard CC).
|
||||
#
|
||||
# It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object
|
||||
# file extensions for the build platform, and GCC_FOR_BUILD to `yes' if
|
||||
# the compiler we found is GCC. All these variables but GCC_FOR_BUILD are
|
||||
# substituted in the Makefile.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Paolo Bonzini <bonzini@gnu.org>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 8
|
||||
|
||||
AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD])
|
||||
AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl
|
||||
AC_REQUIRE([AC_PROG_CC])dnl
|
||||
AC_REQUIRE([AC_PROG_CPP])dnl
|
||||
AC_REQUIRE([AC_EXEEXT])dnl
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])dnl
|
||||
|
||||
dnl Use the standard macros, but make them use other variable names
|
||||
dnl
|
||||
pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl
|
||||
pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl
|
||||
pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl
|
||||
pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl
|
||||
pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl
|
||||
pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl
|
||||
pushdef([ac_cv_objext], ac_cv_build_objext)dnl
|
||||
pushdef([ac_exeext], ac_build_exeext)dnl
|
||||
pushdef([ac_objext], ac_build_objext)dnl
|
||||
pushdef([CC], CC_FOR_BUILD)dnl
|
||||
pushdef([CPP], CPP_FOR_BUILD)dnl
|
||||
pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl
|
||||
pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl
|
||||
pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl
|
||||
pushdef([host], build)dnl
|
||||
pushdef([host_alias], build_alias)dnl
|
||||
pushdef([host_cpu], build_cpu)dnl
|
||||
pushdef([host_vendor], build_vendor)dnl
|
||||
pushdef([host_os], build_os)dnl
|
||||
pushdef([ac_cv_host], ac_cv_build)dnl
|
||||
pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl
|
||||
pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl
|
||||
pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl
|
||||
pushdef([ac_cv_host_os], ac_cv_build_os)dnl
|
||||
pushdef([ac_cpp], ac_build_cpp)dnl
|
||||
pushdef([ac_compile], ac_build_compile)dnl
|
||||
pushdef([ac_link], ac_build_link)dnl
|
||||
|
||||
save_cross_compiling=$cross_compiling
|
||||
save_ac_tool_prefix=$ac_tool_prefix
|
||||
cross_compiling=no
|
||||
ac_tool_prefix=
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_EXEEXT
|
||||
|
||||
ac_tool_prefix=$save_ac_tool_prefix
|
||||
cross_compiling=$save_cross_compiling
|
||||
|
||||
dnl Restore the old definitions
|
||||
dnl
|
||||
popdef([ac_link])dnl
|
||||
popdef([ac_compile])dnl
|
||||
popdef([ac_cpp])dnl
|
||||
popdef([ac_cv_host_os])dnl
|
||||
popdef([ac_cv_host_vendor])dnl
|
||||
popdef([ac_cv_host_cpu])dnl
|
||||
popdef([ac_cv_host_alias])dnl
|
||||
popdef([ac_cv_host])dnl
|
||||
popdef([host_os])dnl
|
||||
popdef([host_vendor])dnl
|
||||
popdef([host_cpu])dnl
|
||||
popdef([host_alias])dnl
|
||||
popdef([host])dnl
|
||||
popdef([LDFLAGS])dnl
|
||||
popdef([CPPFLAGS])dnl
|
||||
popdef([CFLAGS])dnl
|
||||
popdef([CPP])dnl
|
||||
popdef([CC])dnl
|
||||
popdef([ac_objext])dnl
|
||||
popdef([ac_exeext])dnl
|
||||
popdef([ac_cv_objext])dnl
|
||||
popdef([ac_cv_exeext])dnl
|
||||
popdef([ac_cv_prog_cc_g])dnl
|
||||
popdef([ac_cv_prog_cc_cross])dnl
|
||||
popdef([ac_cv_prog_cc_works])dnl
|
||||
popdef([ac_cv_prog_gcc])dnl
|
||||
popdef([ac_cv_prog_CPP])dnl
|
||||
|
||||
dnl Finally, set Makefile variables
|
||||
dnl
|
||||
BUILD_EXEEXT=$ac_build_exeext
|
||||
BUILD_OBJEXT=$ac_build_objext
|
||||
AC_SUBST(BUILD_EXEEXT)dnl
|
||||
AC_SUBST(BUILD_OBJEXT)dnl
|
||||
AC_SUBST([CFLAGS_FOR_BUILD])dnl
|
||||
AC_SUBST([CPPFLAGS_FOR_BUILD])dnl
|
||||
AC_SUBST([LDFLAGS_FOR_BUILD])dnl
|
||||
])
|
@ -9,77 +9,17 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
AC_MSG_RESULT([$has_64bit_asm])
|
||||
])
|
||||
|
||||
dnl
|
||||
AC_DEFUN([SECP_OPENSSL_CHECK],[
|
||||
has_libcrypto=no
|
||||
m4_ifdef([PKG_CHECK_MODULES],[
|
||||
PKG_CHECK_MODULES([CRYPTO], [libcrypto], [has_libcrypto=yes],[has_libcrypto=no])
|
||||
if test x"$has_libcrypto" = x"yes"; then
|
||||
TEMP_LIBS="$LIBS"
|
||||
LIBS="$LIBS $CRYPTO_LIBS"
|
||||
AC_CHECK_LIB(crypto, main,[AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed])],[has_libcrypto=no])
|
||||
LIBS="$TEMP_LIBS"
|
||||
fi
|
||||
])
|
||||
if test x$has_libcrypto = xno; then
|
||||
AC_CHECK_HEADER(openssl/crypto.h,[
|
||||
AC_CHECK_LIB(crypto, main,[
|
||||
has_libcrypto=yes
|
||||
CRYPTO_LIBS=-lcrypto
|
||||
AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed])
|
||||
])
|
||||
])
|
||||
LIBS=
|
||||
fi
|
||||
if test x"$has_libcrypto" = x"yes" && test x"$has_openssl_ec" = x; then
|
||||
AC_MSG_CHECKING(for EC functions in libcrypto)
|
||||
CPPFLAGS_TEMP="$CPPFLAGS"
|
||||
CPPFLAGS="$CRYPTO_CPPFLAGS $CPPFLAGS"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/obj_mac.h>]],[[
|
||||
# if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) {(void)sig->r; (void)sig->s;}
|
||||
# endif
|
||||
|
||||
unsigned int zero = 0;
|
||||
const unsigned char *zero_ptr = (unsigned char*)&zero;
|
||||
EC_KEY_free(EC_KEY_new_by_curve_name(NID_secp256k1));
|
||||
EC_KEY *eckey = EC_KEY_new();
|
||||
EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp256k1);
|
||||
EC_KEY_set_group(eckey, group);
|
||||
ECDSA_sign(0, NULL, 0, NULL, &zero, eckey);
|
||||
ECDSA_verify(0, NULL, 0, NULL, 0, eckey);
|
||||
o2i_ECPublicKey(&eckey, &zero_ptr, 0);
|
||||
d2i_ECPrivateKey(&eckey, &zero_ptr, 0);
|
||||
EC_KEY_check_key(eckey);
|
||||
EC_KEY_free(eckey);
|
||||
EC_GROUP_free(group);
|
||||
ECDSA_SIG *sig_openssl;
|
||||
sig_openssl = ECDSA_SIG_new();
|
||||
d2i_ECDSA_SIG(&sig_openssl, &zero_ptr, 0);
|
||||
i2d_ECDSA_SIG(sig_openssl, NULL);
|
||||
ECDSA_SIG_get0(sig_openssl, NULL, NULL);
|
||||
ECDSA_SIG_free(sig_openssl);
|
||||
const BIGNUM *bignum = BN_value_one();
|
||||
BN_is_negative(bignum);
|
||||
BN_num_bits(bignum);
|
||||
if (sizeof(zero) >= BN_num_bytes(bignum)) {
|
||||
BN_bn2bin(bignum, (unsigned char*)&zero);
|
||||
}
|
||||
]])],[has_openssl_ec=yes],[has_openssl_ec=no])
|
||||
AC_MSG_RESULT([$has_openssl_ec])
|
||||
CPPFLAGS="$CPPFLAGS_TEMP"
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN([SECP_VALGRIND_CHECK],[
|
||||
if test x"$has_valgrind" != x"yes"; then
|
||||
CPPFLAGS_TEMP="$CPPFLAGS"
|
||||
CPPFLAGS="$VALGRIND_CPPFLAGS $CPPFLAGS"
|
||||
AC_CHECK_HEADER([valgrind/memcheck.h], [has_valgrind=yes; AC_DEFINE(HAVE_VALGRIND,1,[Define this symbol if valgrind is installed])])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <valgrind/memcheck.h>
|
||||
]], [[
|
||||
#if defined(NVALGRIND)
|
||||
# error "Valgrind does not support this platform."
|
||||
#endif
|
||||
]])], [has_valgrind=yes; AC_DEFINE(HAVE_VALGRIND,1,[Define this symbol if valgrind is installed, and it supports the host platform])])
|
||||
fi
|
||||
])
|
||||
|
||||
|
33
ci/cirrus.sh
33
ci/cirrus.sh
@ -26,16 +26,12 @@ make
|
||||
|
||||
# Print information about binaries so that we can see that the architecture is correct
|
||||
file *tests* || true
|
||||
file bench_* || true
|
||||
file bench* || true
|
||||
file .libs/* || true
|
||||
|
||||
# This tells `make check` to wrap test invocations.
|
||||
export LOG_COMPILER="$WRAPPER_CMD"
|
||||
|
||||
# This limits the iterations in the tests and benchmarks.
|
||||
export SECP256K1_TEST_ITERS="$TEST_ITERS"
|
||||
export SECP256K1_BENCH_ITERS="$BENCH_ITERS"
|
||||
|
||||
make "$BUILD"
|
||||
|
||||
if [ "$BENCH" = "yes" ]
|
||||
@ -49,23 +45,22 @@ then
|
||||
{
|
||||
$EXEC ./bench_ecmult
|
||||
$EXEC ./bench_internal
|
||||
$EXEC ./bench_sign
|
||||
$EXEC ./bench_verify
|
||||
$EXEC ./bench
|
||||
} >> bench.log 2>&1
|
||||
if [ "$RECOVERY" = "yes" ]
|
||||
then
|
||||
$EXEC ./bench_recover >> bench.log 2>&1
|
||||
fi
|
||||
if [ "$ECDH" = "yes" ]
|
||||
then
|
||||
$EXEC ./bench_ecdh >> bench.log 2>&1
|
||||
fi
|
||||
if [ "$SCHNORRSIG" = "yes" ]
|
||||
then
|
||||
$EXEC ./bench_schnorrsig >> bench.log 2>&1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$CTIMETEST" = "yes" ]
|
||||
then
|
||||
./libtool --mode=execute valgrind --error-exitcode=42 ./valgrind_ctime_test > valgrind_ctime_test.log 2>&1
|
||||
fi
|
||||
|
||||
# Rebuild precomputed files (if not cross-compiling).
|
||||
if [ -z "$HOST" ]
|
||||
then
|
||||
make clean-precomp
|
||||
make precomp
|
||||
fi
|
||||
|
||||
# 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.)
|
||||
git diff --exit-code
|
||||
|
@ -14,7 +14,7 @@ RUN apt-get install --no-install-recommends --no-upgrade -y \
|
||||
make automake libtool pkg-config dpkg-dev valgrind qemu-user \
|
||||
gcc clang llvm libc6-dbg \
|
||||
g++ \
|
||||
gcc-i686-linux-gnu libc6-dev-i386-cross libc6-dbg:i386 libubsan1:i386 libasan5:i386 \
|
||||
gcc-i686-linux-gnu libc6-dev-i386-cross libc6-dbg:i386 libubsan1:i386 libasan6:i386 \
|
||||
gcc-s390x-linux-gnu libc6-dev-s390x-cross libc6-dbg:s390x \
|
||||
gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libc6-dbg:armhf \
|
||||
gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6-dbg:arm64 \
|
||||
|
144
configure.ac
144
configure.ac
@ -8,7 +8,7 @@ AH_TOP([#define LIBSECP256K1_CONFIG_H])
|
||||
AH_BOTTOM([#endif /*LIBSECP256K1_CONFIG_H*/])
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
||||
|
||||
LT_INIT
|
||||
LT_INIT([win32-dll])
|
||||
|
||||
# Make the compilation flags quiet unless V=1 is used.
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
@ -19,16 +19,7 @@ AC_PATH_TOOL(AR, ar)
|
||||
AC_PATH_TOOL(RANLIB, ranlib)
|
||||
AC_PATH_TOOL(STRIP, strip)
|
||||
|
||||
# Save definition of AC_PROG_CC because AM_PROG_CC_C_O in automake<=1.13 will
|
||||
# redefine AC_PROG_CC to exit with an error, which avoids the user calling it
|
||||
# accidently and screwing up the effect of AM_PROG_CC_C_O. However, we'll need
|
||||
# AC_PROG_CC later on in AX_PROG_CC_FOR_BUILD, where its usage is fine, and
|
||||
# we'll carefully make sure not to call AC_PROG_CC anywhere else.
|
||||
m4_copy([AC_PROG_CC], [saved_AC_PROG_CC])
|
||||
AM_PROG_CC_C_O
|
||||
# Restore AC_PROG_CC
|
||||
m4_rename_force([saved_AC_PROG_CC], [AC_PROG_CC])
|
||||
|
||||
AC_PROG_CC_C89
|
||||
if test x"$ac_cv_prog_cc_c89" = x"no"; then
|
||||
AC_MSG_ERROR([c89 compiler support required])
|
||||
@ -43,14 +34,8 @@ case $host_os in
|
||||
# These Homebrew packages may be keg-only, meaning that they won't be found
|
||||
# in expected paths because they may conflict with system files. Ask
|
||||
# Homebrew where each one is located, then adjust paths accordingly.
|
||||
openssl_prefix=`$BREW --prefix openssl 2>/dev/null`
|
||||
valgrind_prefix=`$BREW --prefix valgrind 2>/dev/null`
|
||||
if test x$openssl_prefix != x; then
|
||||
PKG_CONFIG_PATH="$openssl_prefix/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
export PKG_CONFIG_PATH
|
||||
CRYPTO_CPPFLAGS="-I$openssl_prefix/include"
|
||||
fi
|
||||
if test x$valgrind_prefix != x; then
|
||||
if $BREW list --versions valgrind >/dev/null; then
|
||||
valgrind_prefix=$($BREW --prefix valgrind 2>/dev/null)
|
||||
VALGRIND_CPPFLAGS="-I$valgrind_prefix/include"
|
||||
fi
|
||||
else
|
||||
@ -121,11 +106,6 @@ AC_ARG_ENABLE(tests,
|
||||
[use_tests=$enableval],
|
||||
[use_tests=yes])
|
||||
|
||||
AC_ARG_ENABLE(openssl_tests,
|
||||
AS_HELP_STRING([--enable-openssl-tests],[enable OpenSSL tests [default=auto]]),
|
||||
[enable_openssl_tests=$enableval],
|
||||
[enable_openssl_tests=auto])
|
||||
|
||||
AC_ARG_ENABLE(experimental,
|
||||
AS_HELP_STRING([--enable-experimental],[allow experimental configure options [default=no]]),
|
||||
[use_experimental=$enableval],
|
||||
@ -136,11 +116,6 @@ AC_ARG_ENABLE(exhaustive_tests,
|
||||
[use_exhaustive_tests=$enableval],
|
||||
[use_exhaustive_tests=yes])
|
||||
|
||||
AC_ARG_ENABLE(ecmult_static_precomputation,
|
||||
AS_HELP_STRING([--enable-ecmult-static-precomputation],[enable precomputed ecmult table for signing [default=auto]]),
|
||||
[use_ecmult_static_precomputation=$enableval],
|
||||
[use_ecmult_static_precomputation=auto])
|
||||
|
||||
AC_ARG_ENABLE(module_ecdh,
|
||||
AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation]),
|
||||
[enable_module_ecdh=$enableval],
|
||||
@ -171,12 +146,14 @@ AC_ARG_ENABLE(external_default_callbacks,
|
||||
AC_ARG_WITH([test-override-wide-multiply], [] ,[set_widemul=$withval], [set_widemul=auto])
|
||||
|
||||
AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto],
|
||||
[assembly optimizations to use (experimental: arm) [default=auto]])],[req_asm=$withval], [req_asm=auto])
|
||||
[assembly optimizations to use (experimental: arm) [default=auto]])],[req_asm=$withval], [req_asm=auto])
|
||||
|
||||
AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE|auto],
|
||||
[window size for ecmult precomputation for verification, specified as integer in range [2..24].]
|
||||
[Larger values result in possibly better performance at the cost of an exponentially larger precomputed table.]
|
||||
[The table will store 2^(SIZE-1) * 64 bytes of data but can be larger in memory due to platform-specific padding and alignment.]
|
||||
[A window size larger than 15 will require you delete the prebuilt ecmult_static_pre_g.h file so that it can be rebuilt.]
|
||||
[For very large window sizes, use "make -j 1" to reduce memory use during compilation.]
|
||||
["auto" is a reasonable setting for desktop machines (currently 15). [default=auto]]
|
||||
)],
|
||||
[req_ecmult_window=$withval], [req_ecmult_window=auto])
|
||||
@ -222,7 +199,6 @@ else
|
||||
# We still add it here because passing it twice is not an issue, and handling
|
||||
# this case would just add unnecessary complexity (see #896).
|
||||
SECP_CFLAGS="-O2 $SECP_CFLAGS"
|
||||
SECP_CFLAGS_FOR_BUILD="-O2 $SECP_CFLAGS_FOR_BUILD"
|
||||
fi
|
||||
|
||||
if test x"$req_asm" = x"auto"; then
|
||||
@ -327,32 +303,6 @@ case $set_ecmult_gen_precision in
|
||||
;;
|
||||
esac
|
||||
|
||||
if test x"$use_tests" = x"yes"; then
|
||||
SECP_OPENSSL_CHECK
|
||||
if test x"$enable_openssl_tests" != x"no" && test x"$has_openssl_ec" = x"yes"; then
|
||||
enable_openssl_tests=yes
|
||||
AC_DEFINE(ENABLE_OPENSSL_TESTS, 1, [Define this symbol if OpenSSL EC functions are available])
|
||||
SECP_TEST_INCLUDES="$SSL_CFLAGS $CRYPTO_CFLAGS $CRYPTO_CPPFLAGS"
|
||||
SECP_TEST_LIBS="$CRYPTO_LIBS"
|
||||
|
||||
case $host in
|
||||
*mingw*)
|
||||
SECP_TEST_LIBS="$SECP_TEST_LIBS -lgdi32"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
if test x"$enable_openssl_tests" = x"yes"; then
|
||||
AC_MSG_ERROR([OpenSSL tests requested but OpenSSL with EC support is not available])
|
||||
fi
|
||||
enable_openssl_tests=no
|
||||
fi
|
||||
else
|
||||
if test x"$enable_openssl_tests" = x"yes"; then
|
||||
AC_MSG_ERROR([OpenSSL tests requested but tests are not enabled])
|
||||
fi
|
||||
enable_openssl_tests=no
|
||||
fi
|
||||
|
||||
if test x"$enable_valgrind" = x"yes"; then
|
||||
SECP_INCLUDES="$SECP_INCLUDES $VALGRIND_CPPFLAGS"
|
||||
fi
|
||||
@ -360,77 +310,6 @@ fi
|
||||
# Add -Werror and similar flags passed from the outside (for testing, e.g., in CI)
|
||||
SECP_CFLAGS="$SECP_CFLAGS $WERROR_CFLAGS"
|
||||
|
||||
# Handle static precomputation (after everything which modifies CFLAGS and friends)
|
||||
if test x"$use_ecmult_static_precomputation" != x"no"; then
|
||||
if test x"$cross_compiling" = x"no"; then
|
||||
set_precomp=yes
|
||||
if test x"${CC_FOR_BUILD+x}${CFLAGS_FOR_BUILD+x}${CPPFLAGS_FOR_BUILD+x}${LDFLAGS_FOR_BUILD+x}" != x; then
|
||||
AC_MSG_WARN([CC_FOR_BUILD, CFLAGS_FOR_BUILD, CPPFLAGS_FOR_BUILD, and/or LDFLAGS_FOR_BUILD is set but ignored because we are not cross-compiling.])
|
||||
fi
|
||||
# If we're not cross-compiling, simply use the same compiler for building the static precompation code.
|
||||
CC_FOR_BUILD="$CC"
|
||||
CPPFLAGS_FOR_BUILD="$CPPFLAGS"
|
||||
SECP_CFLAGS_FOR_BUILD="$SECP_CFLAGS"
|
||||
CFLAGS_FOR_BUILD="$CFLAGS"
|
||||
LDFLAGS_FOR_BUILD="$LDFLAGS"
|
||||
else
|
||||
AX_PROG_CC_FOR_BUILD
|
||||
|
||||
# Temporarily switch to an environment for the native compiler
|
||||
save_cross_compiling=$cross_compiling
|
||||
cross_compiling=no
|
||||
SAVE_CC="$CC"
|
||||
CC="$CC_FOR_BUILD"
|
||||
SAVE_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS_FOR_BUILD"
|
||||
SAVE_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS_FOR_BUILD"
|
||||
SAVE_LDFLAGS="$LDFLAGS"
|
||||
LDFLAGS="$LDFLAGS_FOR_BUILD"
|
||||
|
||||
SECP_TRY_APPEND_DEFAULT_CFLAGS(SECP_CFLAGS_FOR_BUILD)
|
||||
|
||||
AC_MSG_CHECKING([for working native compiler: ${CC_FOR_BUILD}])
|
||||
AC_RUN_IFELSE(
|
||||
[AC_LANG_PROGRAM([], [])],
|
||||
[working_native_cc=yes],
|
||||
[working_native_cc=no],[:])
|
||||
|
||||
# Restore the environment
|
||||
cross_compiling=$save_cross_compiling
|
||||
CC="$SAVE_CC"
|
||||
CPPFLAGS="$SAVE_CPPFLAGS"
|
||||
CFLAGS="$SAVE_CFLAGS"
|
||||
LDFLAGS="$SAVE_LDFLAGS"
|
||||
|
||||
if test x"$working_native_cc" = x"no"; then
|
||||
AC_MSG_RESULT([no])
|
||||
set_precomp=no
|
||||
m4_define([please_set_for_build], [Please set CC_FOR_BUILD, CPPFLAGS_FOR_BUILD, CFLAGS_FOR_BUILD, and/or LDFLAGS_FOR_BUILD.])
|
||||
if test x"$use_ecmult_static_precomputation" = x"yes"; then
|
||||
AC_MSG_ERROR([native compiler ${CC_FOR_BUILD} does not produce working binaries. please_set_for_build])
|
||||
else
|
||||
AC_MSG_WARN([Disabling statically generated ecmult table because the native compiler ${CC_FOR_BUILD} does not produce working binaries. please_set_for_build])
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
set_precomp=yes
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(CC_FOR_BUILD)
|
||||
AC_SUBST(CPPFLAGS_FOR_BUILD)
|
||||
AC_SUBST(SECP_CFLAGS_FOR_BUILD)
|
||||
AC_SUBST(CFLAGS_FOR_BUILD)
|
||||
AC_SUBST(LDFLAGS_FOR_BUILD)
|
||||
else
|
||||
set_precomp=no
|
||||
fi
|
||||
|
||||
if test x"$set_precomp" = x"yes"; then
|
||||
AC_DEFINE(USE_ECMULT_STATIC_PRECOMPUTATION, 1, [Define this symbol to use a statically generated ecmult table])
|
||||
fi
|
||||
|
||||
###
|
||||
### Handle module options
|
||||
###
|
||||
@ -496,7 +375,6 @@ AM_CONDITIONAL([ENABLE_COVERAGE], [test x"$enable_coverage" = x"yes"])
|
||||
AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"])
|
||||
AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$use_exhaustive_tests" != x"no"])
|
||||
AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"])
|
||||
AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$set_precomp" = x"yes"])
|
||||
AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"])
|
||||
AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"])
|
||||
AM_CONDITIONAL([ENABLE_MODULE_EXTRAKEYS], [test x"$enable_module_extrakeys" = x"yes"])
|
||||
@ -513,11 +391,9 @@ AC_OUTPUT
|
||||
|
||||
echo
|
||||
echo "Build Options:"
|
||||
echo " with ecmult precomp = $set_precomp"
|
||||
echo " with external callbacks = $use_external_default_callbacks"
|
||||
echo " with benchmarks = $use_benchmark"
|
||||
echo " with tests = $use_tests"
|
||||
echo " with openssl tests = $enable_openssl_tests"
|
||||
echo " with coverage = $enable_coverage"
|
||||
echo " module ecdh = $enable_module_ecdh"
|
||||
echo " module recovery = $enable_module_recovery"
|
||||
@ -538,11 +414,3 @@ echo " CPPFLAGS = $CPPFLAGS"
|
||||
echo " SECP_CFLAGS = $SECP_CFLAGS"
|
||||
echo " CFLAGS = $CFLAGS"
|
||||
echo " LDFLAGS = $LDFLAGS"
|
||||
echo
|
||||
if test x"$set_precomp" = x"yes"; then
|
||||
echo " CC_FOR_BUILD = $CC_FOR_BUILD"
|
||||
echo " CPPFLAGS_FOR_BUILD = $CPPFLAGS_FOR_BUILD"
|
||||
echo " SECP_CFLAGS_FOR_BUILD = $SECP_CFLAGS_FOR_BUILD"
|
||||
echo " CFLAGS_FOR_BUILD = $CFLAGS_FOR_BUILD"
|
||||
echo " LDFLAGS_FOR_BUILD = $LDFLAGS_FOR_BUILD"
|
||||
fi
|
||||
|
@ -569,8 +569,14 @@ bits efficiently, which is possible on most platforms; it is abstracted here as
|
||||
|
||||
```python
|
||||
def count_trailing_zeros(v):
|
||||
"""For a non-zero value v, find z such that v=(d<<z) for some odd d."""
|
||||
return (v & -v).bit_length() - 1
|
||||
"""
|
||||
When v is zero, consider all N zero bits as "trailing".
|
||||
For a non-zero value v, find z such that v=(d<<z) for some odd d.
|
||||
"""
|
||||
if v == 0:
|
||||
return N
|
||||
else:
|
||||
return (v & -v).bit_length() - 1
|
||||
|
||||
i = N # divsteps left to do
|
||||
while True:
|
||||
@ -601,7 +607,7 @@ becomes negative, or when *i* reaches *0*. Combined, this is equivalent to addin
|
||||
It is easy to find what that multiple is: we want a number *w* such that *g+w f* has a few bottom
|
||||
zero bits. If that number of bits is *L*, we want *g+w f mod 2<sup>L</sup> = 0*, or *w = -g/f mod 2<sup>L</sup>*. Since *f*
|
||||
is odd, such a *w* exists for any *L*. *L* cannot be more than *i* steps (as we'd finish the loop before
|
||||
doing more) or more than *η+1* steps (as we'd run `eta, f, g = -eta, g, f` at that point), but
|
||||
doing more) or more than *η+1* steps (as we'd run `eta, f, g = -eta, g, -f` at that point), but
|
||||
apart from that, we're only limited by the complexity of computing *w*.
|
||||
|
||||
This code demonstrates how to cancel up to 4 bits per step:
|
||||
@ -618,7 +624,7 @@ while True:
|
||||
break
|
||||
# We know g is odd now
|
||||
if eta < 0:
|
||||
eta, f, g = -eta, g, f
|
||||
eta, f, g = -eta, g, -f
|
||||
# Compute limit on number of bits to cancel
|
||||
limit = min(min(eta + 1, i), 4)
|
||||
# Compute w = -g/f mod 2**limit, using the table value for -1/f mod 2**4. Note that f is
|
||||
|
@ -226,7 +226,7 @@ SECP256K1_API secp256k1_context* secp256k1_context_create(
|
||||
* memory allocation entirely, see the functions in secp256k1_preallocated.h.
|
||||
*
|
||||
* Returns: a newly created context object.
|
||||
* Args: ctx: an existing context to copy (cannot be NULL)
|
||||
* Args: ctx: an existing context to copy
|
||||
*/
|
||||
SECP256K1_API secp256k1_context* secp256k1_context_clone(
|
||||
const secp256k1_context* ctx
|
||||
@ -247,7 +247,7 @@ SECP256K1_API secp256k1_context* secp256k1_context_clone(
|
||||
*/
|
||||
SECP256K1_API void secp256k1_context_destroy(
|
||||
secp256k1_context* ctx
|
||||
);
|
||||
) SECP256K1_ARG_NONNULL(1);
|
||||
|
||||
/** Set a callback function to be called when an illegal argument is passed to
|
||||
* an API call. It will only trigger for violations that are mentioned
|
||||
@ -264,7 +264,7 @@ SECP256K1_API void secp256k1_context_destroy(
|
||||
* undefined.
|
||||
*
|
||||
* When this function has not been called (or called with fn==NULL), then the
|
||||
* default handler will be used. The library provides a default handler which
|
||||
* default handler will be used. The library provides a default handler which
|
||||
* writes the message to stderr and calls abort. This default handler can be
|
||||
* replaced at link time if the preprocessor macro
|
||||
* USE_EXTERNAL_DEFAULT_CALLBACKS is defined, which is the case if the build
|
||||
@ -278,11 +278,11 @@ SECP256K1_API void secp256k1_context_destroy(
|
||||
* fails. In this case, the corresponding default handler will be called with
|
||||
* the data pointer argument set to NULL.
|
||||
*
|
||||
* Args: ctx: an existing context object (cannot be NULL)
|
||||
* Args: ctx: an existing context object.
|
||||
* In: fun: a pointer to a function to call when an illegal argument is
|
||||
* passed to the API, taking a message and an opaque pointer.
|
||||
* (NULL restores the default handler.)
|
||||
* data: the opaque pointer to pass to fun above.
|
||||
* data: the opaque pointer to pass to fun above, must be NULL for the default handler.
|
||||
*
|
||||
* See also secp256k1_context_set_error_callback.
|
||||
*/
|
||||
@ -302,12 +302,12 @@ SECP256K1_API void secp256k1_context_set_illegal_callback(
|
||||
* for that). After this callback returns, anything may happen, including
|
||||
* crashing.
|
||||
*
|
||||
* Args: ctx: an existing context object (cannot be NULL)
|
||||
* Args: ctx: an existing context object.
|
||||
* In: fun: a pointer to a function to call when an internal error occurs,
|
||||
* taking a message and an opaque pointer (NULL restores the
|
||||
* default handler, see secp256k1_context_set_illegal_callback
|
||||
* for details).
|
||||
* data: the opaque pointer to pass to fun above.
|
||||
* data: the opaque pointer to pass to fun above, must be NULL for the default handler.
|
||||
*
|
||||
* See also secp256k1_context_set_illegal_callback.
|
||||
*/
|
||||
@ -320,7 +320,7 @@ SECP256K1_API void secp256k1_context_set_error_callback(
|
||||
/** Create a secp256k1 scratch space object.
|
||||
*
|
||||
* Returns: a newly created scratch space.
|
||||
* Args: ctx: an existing context object (cannot be NULL)
|
||||
* Args: ctx: an existing context object.
|
||||
* In: size: amount of memory to be available as scratch space. Some extra
|
||||
* (<100 bytes) will be allocated for extra accounting.
|
||||
*/
|
||||
@ -480,8 +480,8 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
|
||||
* Returns: 1: correct signature
|
||||
* 0: incorrect or unparseable signature
|
||||
* Args: ctx: a secp256k1 context object, initialized for verification.
|
||||
* In: sig: the signature being verified (cannot be NULL)
|
||||
* msghash32: the 32-byte message hash being verified (cannot be NULL).
|
||||
* In: sig: the signature being verified.
|
||||
* msghash32: the 32-byte message hash being verified.
|
||||
* The verifier must make sure to apply a cryptographic
|
||||
* hash function to the message by itself and not accept an
|
||||
* msghash32 value directly. Otherwise, it would be easy to
|
||||
@ -489,7 +489,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
|
||||
* secret key. See also
|
||||
* https://bitcoin.stackexchange.com/a/81116/35586 for more
|
||||
* background on this topic.
|
||||
* pubkey: pointer to an initialized public key to verify with (cannot be NULL)
|
||||
* pubkey: pointer to an initialized public key to verify with.
|
||||
*
|
||||
* To avoid accepting malleable signatures, only ECDSA signatures in lower-S
|
||||
* form are accepted.
|
||||
@ -515,8 +515,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
|
||||
* or copy if the input was already normalized. (can be NULL if
|
||||
* you're only interested in whether the input was already
|
||||
* normalized).
|
||||
* In: sigin: a pointer to a signature to check/normalize (cannot be NULL,
|
||||
* can be identical to sigout)
|
||||
* In: sigin: a pointer to a signature to check/normalize (can be identical to sigout)
|
||||
*
|
||||
* With ECDSA a third-party can forge a second distinct signature of the same
|
||||
* message, given a single initial signature, but without knowing the key. This
|
||||
@ -568,12 +567,16 @@ SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_def
|
||||
*
|
||||
* Returns: 1: signature created
|
||||
* 0: the nonce generation function failed, or the secret key was invalid.
|
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
|
||||
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
|
||||
* In: msghash32: the 32-byte message hash being signed (cannot be NULL)
|
||||
* seckey: pointer to a 32-byte secret key (cannot be NULL)
|
||||
* noncefp: pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
|
||||
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
|
||||
* Args: ctx: pointer to a context object, initialized for signing.
|
||||
* Out: sig: pointer to an array where the signature will be placed.
|
||||
* In: msghash32: the 32-byte message hash being signed.
|
||||
* seckey: pointer to a 32-byte secret key.
|
||||
* noncefp: pointer to a nonce generation function. If NULL,
|
||||
* secp256k1_nonce_function_default is used.
|
||||
* ndata: pointer to arbitrary data used by the nonce generation function
|
||||
* (can be NULL). If it is non-NULL and
|
||||
* secp256k1_nonce_function_default is used, then ndata must be a
|
||||
* pointer to 32-bytes of additional data.
|
||||
*
|
||||
* The created signature is always in lower-S form. See
|
||||
* secp256k1_ecdsa_signature_normalize for more details.
|
||||
@ -596,8 +599,8 @@ SECP256K1_API int secp256k1_ecdsa_sign(
|
||||
*
|
||||
* Returns: 1: secret key is valid
|
||||
* 0: secret key is invalid
|
||||
* Args: ctx: pointer to a context object (cannot be NULL)
|
||||
* In: seckey: pointer to a 32-byte secret key (cannot be NULL)
|
||||
* Args: ctx: pointer to a context object.
|
||||
* In: seckey: pointer to a 32-byte secret key.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(
|
||||
const secp256k1_context* ctx,
|
||||
@ -606,11 +609,11 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(
|
||||
|
||||
/** Compute the public key for a secret key.
|
||||
*
|
||||
* Returns: 1: secret was valid, public key stores
|
||||
* 0: secret was invalid, try again
|
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
|
||||
* Out: pubkey: pointer to the created public key (cannot be NULL)
|
||||
* In: seckey: pointer to a 32-byte secret key (cannot be NULL)
|
||||
* Returns: 1: secret was valid, public key stores.
|
||||
* 0: secret was invalid, try again.
|
||||
* Args: ctx: pointer to a context object, initialized for signing.
|
||||
* Out: pubkey: pointer to the created public key.
|
||||
* In: seckey: pointer to a 32-byte secret key.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
|
||||
const secp256k1_context* ctx,
|
||||
@ -626,8 +629,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
|
||||
* In/Out: seckey: pointer to the 32-byte secret key to be negated. If the
|
||||
* secret key is invalid according to
|
||||
* secp256k1_ec_seckey_verify, this function returns 0 and
|
||||
* seckey will be set to some unspecified value. (cannot be
|
||||
* NULL)
|
||||
* seckey will be set to some unspecified value.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_negate(
|
||||
const secp256k1_context* ctx,
|
||||
@ -645,7 +647,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate(
|
||||
*
|
||||
* Returns: 1 always
|
||||
* Args: ctx: pointer to a context object
|
||||
* In/Out: pubkey: pointer to the public key to be negated (cannot be NULL)
|
||||
* In/Out: pubkey: pointer to the public key to be negated.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate(
|
||||
const secp256k1_context* ctx,
|
||||
@ -657,15 +659,15 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate(
|
||||
* Returns: 0 if the arguments are invalid or the resulting secret key would be
|
||||
* invalid (only when the tweak is the negation of the secret key). 1
|
||||
* otherwise.
|
||||
* Args: ctx: pointer to a context object (cannot be NULL).
|
||||
* Args: ctx: pointer to a context object.
|
||||
* In/Out: seckey: pointer to a 32-byte secret key. If the secret key is
|
||||
* invalid according to secp256k1_ec_seckey_verify, this
|
||||
* function returns 0. seckey will be set to some unspecified
|
||||
* value if this function returns 0. (cannot be NULL)
|
||||
* value if this function returns 0.
|
||||
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
|
||||
* secp256k1_ec_seckey_verify, this function returns 0. For
|
||||
* uniformly random 32-byte arrays the chance of being invalid
|
||||
* is negligible (around 1 in 2^128) (cannot be NULL).
|
||||
* is negligible (around 1 in 2^128).
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_add(
|
||||
const secp256k1_context* ctx,
|
||||
@ -686,14 +688,13 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
|
||||
* Returns: 0 if the arguments are invalid or the resulting public key would be
|
||||
* invalid (only when the tweak is the negation of the corresponding
|
||||
* secret key). 1 otherwise.
|
||||
* Args: ctx: pointer to a context object initialized for validation
|
||||
* (cannot be NULL).
|
||||
* Args: ctx: pointer to a context object initialized for validation.
|
||||
* In/Out: pubkey: pointer to a public key object. pubkey will be set to an
|
||||
* invalid value if this function returns 0 (cannot be NULL).
|
||||
* invalid value if this function returns 0.
|
||||
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
|
||||
* secp256k1_ec_seckey_verify, this function returns 0. For
|
||||
* uniformly random 32-byte arrays the chance of being invalid
|
||||
* is negligible (around 1 in 2^128) (cannot be NULL).
|
||||
* is negligible (around 1 in 2^128).
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
|
||||
const secp256k1_context* ctx,
|
||||
@ -704,15 +705,15 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
|
||||
/** Tweak a secret key by multiplying it by a tweak.
|
||||
*
|
||||
* Returns: 0 if the arguments are invalid. 1 otherwise.
|
||||
* Args: ctx: pointer to a context object (cannot be NULL).
|
||||
* Args: ctx: pointer to a context object.
|
||||
* In/Out: seckey: pointer to a 32-byte secret key. If the secret key is
|
||||
* invalid according to secp256k1_ec_seckey_verify, this
|
||||
* function returns 0. seckey will be set to some unspecified
|
||||
* value if this function returns 0. (cannot be NULL)
|
||||
* value if this function returns 0.
|
||||
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
|
||||
* secp256k1_ec_seckey_verify, this function returns 0. For
|
||||
* uniformly random 32-byte arrays the chance of being invalid
|
||||
* is negligible (around 1 in 2^128) (cannot be NULL).
|
||||
* is negligible (around 1 in 2^128).
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_mul(
|
||||
const secp256k1_context* ctx,
|
||||
@ -731,14 +732,13 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(
|
||||
/** Tweak a public key by multiplying it by a tweak value.
|
||||
*
|
||||
* Returns: 0 if the arguments are invalid. 1 otherwise.
|
||||
* Args: ctx: pointer to a context object initialized for validation
|
||||
* (cannot be NULL).
|
||||
* Args: ctx: pointer to a context object initialized for validation.
|
||||
* In/Out: pubkey: pointer to a public key object. pubkey will be set to an
|
||||
* invalid value if this function returns 0 (cannot be NULL).
|
||||
* invalid value if this function returns 0.
|
||||
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
|
||||
* secp256k1_ec_seckey_verify, this function returns 0. For
|
||||
* uniformly random 32-byte arrays the chance of being invalid
|
||||
* is negligible (around 1 in 2^128) (cannot be NULL).
|
||||
* is negligible (around 1 in 2^128).
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
|
||||
const secp256k1_context* ctx,
|
||||
@ -749,7 +749,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
|
||||
/** Updates the context randomization to protect against side-channel leakage.
|
||||
* Returns: 1: randomization successfully updated or nothing to randomize
|
||||
* 0: error
|
||||
* Args: ctx: pointer to a context object (cannot be NULL)
|
||||
* Args: ctx: pointer to a context object.
|
||||
* In: seed32: pointer to a 32-byte random seed (NULL resets to initial state)
|
||||
*
|
||||
* While secp256k1 code is written to be constant-time no matter what secret
|
||||
@ -780,18 +780,17 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(
|
||||
*
|
||||
* Returns: 1: the sum of the public keys is valid.
|
||||
* 0: the sum of the public keys is not valid.
|
||||
* Args: ctx: pointer to a context object
|
||||
* Out: out: pointer to a public key object for placing the resulting public key
|
||||
* (cannot be NULL)
|
||||
* In: ins: pointer to array of pointers to public keys (cannot be NULL)
|
||||
* n: the number of public keys to add together (must be at least 1)
|
||||
* Args: ctx: pointer to a context object.
|
||||
* Out: out: pointer to a public key object for placing the resulting public key.
|
||||
* In: ins: pointer to array of pointers to public keys.
|
||||
* n: the number of public keys to add together (must be at least 1).
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pubkey *out,
|
||||
const secp256k1_pubkey * const * ins,
|
||||
size_t n
|
||||
) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Compute a tagged hash as defined in BIP-340.
|
||||
*
|
||||
|
@ -37,14 +37,15 @@ SECP256K1_API extern const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_func
|
||||
*
|
||||
* Returns: 1: exponentiation was successful
|
||||
* 0: scalar was invalid (zero or overflow) or hashfp returned 0
|
||||
* Args: ctx: pointer to a context object (cannot be NULL)
|
||||
* Out: output: pointer to an array to be filled by hashfp
|
||||
* In: pubkey: a pointer to a secp256k1_pubkey containing an
|
||||
* initialized public key
|
||||
* seckey: a 32-byte scalar with which to multiply the point
|
||||
* hashfp: pointer to a hash function. If NULL, secp256k1_ecdh_hash_function_sha256 is used
|
||||
* (in which case, 32 bytes will be written to output)
|
||||
* Args: ctx: pointer to a context object.
|
||||
* Out: output: pointer to an array to be filled by hashfp.
|
||||
* In: pubkey: a pointer to a secp256k1_pubkey containing an initialized public key.
|
||||
* seckey: a 32-byte scalar with which to multiply the point.
|
||||
* hashfp: pointer to a hash function. If NULL,
|
||||
* secp256k1_ecdh_hash_function_sha256 is used
|
||||
* (in which case, 32 bytes will be written to output).
|
||||
* data: arbitrary data pointer that is passed through to hashfp
|
||||
* (can be NULL for secp256k1_ecdh_hash_function_sha256).
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh(
|
||||
const secp256k1_context* ctx,
|
||||
|
@ -39,11 +39,10 @@ typedef struct {
|
||||
* Returns: 1 if the public key was fully valid.
|
||||
* 0 if the public key could not be parsed or is invalid.
|
||||
*
|
||||
* Args: ctx: a secp256k1 context object (cannot be NULL).
|
||||
* Args: ctx: a secp256k1 context object.
|
||||
* Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a
|
||||
* parsed version of input. If not, it's set to an invalid value.
|
||||
* (cannot be NULL).
|
||||
* In: input32: pointer to a serialized xonly_pubkey (cannot be NULL)
|
||||
* In: input32: pointer to a serialized xonly_pubkey.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_parse(
|
||||
const secp256k1_context* ctx,
|
||||
@ -55,11 +54,9 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_parse(
|
||||
*
|
||||
* Returns: 1 always.
|
||||
*
|
||||
* Args: ctx: a secp256k1 context object (cannot be NULL).
|
||||
* Out: output32: a pointer to a 32-byte array to place the serialized key in
|
||||
* (cannot be NULL).
|
||||
* In: pubkey: a pointer to a secp256k1_xonly_pubkey containing an
|
||||
* initialized public key (cannot be NULL).
|
||||
* Args: ctx: a secp256k1 context object.
|
||||
* Out: output32: a pointer to a 32-byte array to place the serialized key in.
|
||||
* In: pubkey: a pointer to a secp256k1_xonly_pubkey containing an initialized public key.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_xonly_pubkey_serialize(
|
||||
const secp256k1_context* ctx,
|
||||
@ -87,13 +84,12 @@ SECP256K1_API int secp256k1_xonly_pubkey_cmp(
|
||||
* Returns: 1 if the public key was successfully converted
|
||||
* 0 otherwise
|
||||
*
|
||||
* Args: ctx: pointer to a context object (cannot be NULL)
|
||||
* Out: xonly_pubkey: pointer to an x-only public key object for placing the
|
||||
* converted public key (cannot be NULL)
|
||||
* pk_parity: pointer to an integer that will be set to 1 if the point
|
||||
* encoded by xonly_pubkey is the negation of the pubkey and
|
||||
* set to 0 otherwise. (can be NULL)
|
||||
* In: pubkey: pointer to a public key that is converted (cannot be NULL)
|
||||
* Args: ctx: pointer to a context object.
|
||||
* Out: xonly_pubkey: pointer to an x-only public key object for placing the converted public key.
|
||||
* pk_parity: Ignored if NULL. Otherwise, pointer to an integer that
|
||||
* will be set to 1 if the point encoded by xonly_pubkey is
|
||||
* the negation of the pubkey and set to 0 otherwise.
|
||||
* In: pubkey: pointer to a public key that is converted.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubkey(
|
||||
const secp256k1_context* ctx,
|
||||
@ -113,18 +109,14 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubke
|
||||
* invalid (only when the tweak is the negation of the corresponding
|
||||
* secret key). 1 otherwise.
|
||||
*
|
||||
* Args: ctx: pointer to a context object initialized for verification
|
||||
* (cannot be NULL)
|
||||
* Args: ctx: pointer to a context object initialized for verification.
|
||||
* Out: output_pubkey: pointer to a public key to store the result. Will be set
|
||||
* to an invalid value if this function returns 0 (cannot
|
||||
* be NULL)
|
||||
* to an invalid value if this function returns 0.
|
||||
* In: internal_pubkey: pointer to an x-only pubkey to apply the tweak to.
|
||||
* (cannot be NULL).
|
||||
* tweak32: pointer to a 32-byte tweak. If the tweak is invalid
|
||||
* according to secp256k1_ec_seckey_verify, this function
|
||||
* returns 0. For uniformly random 32-byte arrays the
|
||||
* chance of being invalid is negligible (around 1 in
|
||||
* 2^128) (cannot be NULL).
|
||||
* chance of being invalid is negligible (around 1 in 2^128).
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add(
|
||||
const secp256k1_context* ctx,
|
||||
@ -146,17 +138,15 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add(
|
||||
*
|
||||
* Returns: 0 if the arguments are invalid or the tweaked pubkey is not the
|
||||
* result of tweaking the internal_pubkey with tweak32. 1 otherwise.
|
||||
* Args: ctx: pointer to a context object initialized for verification
|
||||
* (cannot be NULL)
|
||||
* In: tweaked_pubkey32: pointer to a serialized xonly_pubkey (cannot be NULL)
|
||||
* Args: ctx: pointer to a context object initialized for verification.
|
||||
* In: tweaked_pubkey32: pointer to a serialized xonly_pubkey.
|
||||
* tweaked_pk_parity: the parity of the tweaked pubkey (whose serialization
|
||||
* is passed in as tweaked_pubkey32). This must match the
|
||||
* pk_parity value that is returned when calling
|
||||
* secp256k1_xonly_pubkey with the tweaked pubkey, or
|
||||
* this function will fail.
|
||||
* internal_pubkey: pointer to an x-only public key object to apply the
|
||||
* tweak to (cannot be NULL)
|
||||
* tweak32: pointer to a 32-byte tweak (cannot be NULL)
|
||||
* internal_pubkey: pointer to an x-only public key object to apply the tweak to.
|
||||
* tweak32: pointer to a 32-byte tweak.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add_check(
|
||||
const secp256k1_context* ctx,
|
||||
@ -170,9 +160,9 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add_
|
||||
*
|
||||
* Returns: 1: secret was valid, keypair is ready to use
|
||||
* 0: secret was invalid, try again with a different secret
|
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
|
||||
* Out: keypair: pointer to the created keypair (cannot be NULL)
|
||||
* In: seckey: pointer to a 32-byte secret key (cannot be NULL)
|
||||
* Args: ctx: pointer to a context object, initialized for signing.
|
||||
* Out: keypair: pointer to the created keypair.
|
||||
* In: seckey: pointer to a 32-byte secret key.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_create(
|
||||
const secp256k1_context* ctx,
|
||||
@ -183,9 +173,9 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_create(
|
||||
/** Get the secret key from a keypair.
|
||||
*
|
||||
* Returns: 0 if the arguments are invalid. 1 otherwise.
|
||||
* Args: ctx: pointer to a context object (cannot be NULL)
|
||||
* Out: seckey: pointer to a 32-byte buffer for the secret key (cannot be NULL)
|
||||
* In: keypair: pointer to a keypair (cannot be NULL)
|
||||
* Args: ctx: pointer to a context object.
|
||||
* Out: seckey: pointer to a 32-byte buffer for the secret key.
|
||||
* In: keypair: pointer to a keypair.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_sec(
|
||||
const secp256k1_context* ctx,
|
||||
@ -196,11 +186,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_sec(
|
||||
/** Get the public key from a keypair.
|
||||
*
|
||||
* Returns: 0 if the arguments are invalid. 1 otherwise.
|
||||
* Args: ctx: pointer to a context object (cannot be NULL)
|
||||
* Args: ctx: pointer to a context object.
|
||||
* Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to
|
||||
* the keypair public key. If not, it's set to an invalid value.
|
||||
* (cannot be NULL)
|
||||
* In: keypair: pointer to a keypair (cannot be NULL)
|
||||
* In: keypair: pointer to a keypair.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_pub(
|
||||
const secp256k1_context* ctx,
|
||||
@ -214,14 +203,13 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_pub(
|
||||
* secp256k1_xonly_pubkey_from_pubkey.
|
||||
*
|
||||
* Returns: 0 if the arguments are invalid. 1 otherwise.
|
||||
* Args: ctx: pointer to a context object (cannot be NULL)
|
||||
* Args: ctx: pointer to a context object.
|
||||
* Out: pubkey: pointer to an xonly_pubkey object. If 1 is returned, it is set
|
||||
* to the keypair public key after converting it to an
|
||||
* xonly_pubkey. If not, it's set to an invalid value (cannot be
|
||||
* NULL).
|
||||
* pk_parity: pointer to an integer that will be set to the pk_parity
|
||||
* argument of secp256k1_xonly_pubkey_from_pubkey (can be NULL).
|
||||
* In: keypair: pointer to a keypair (cannot be NULL)
|
||||
* xonly_pubkey. If not, it's set to an invalid value.
|
||||
* pk_parity: Ignored if NULL. Otherwise, pointer to an integer that will be set to the
|
||||
* pk_parity argument of secp256k1_xonly_pubkey_from_pubkey.
|
||||
* In: keypair: pointer to a keypair.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub(
|
||||
const secp256k1_context* ctx,
|
||||
@ -241,15 +229,13 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub(
|
||||
* invalid (only when the tweak is the negation of the keypair's
|
||||
* secret key). 1 otherwise.
|
||||
*
|
||||
* Args: ctx: pointer to a context object initialized for verification
|
||||
* (cannot be NULL)
|
||||
* Args: ctx: pointer to a context object initialized for verification.
|
||||
* In/Out: keypair: pointer to a keypair to apply the tweak to. Will be set to
|
||||
* an invalid value if this function returns 0 (cannot be
|
||||
* NULL).
|
||||
* an invalid value if this function returns 0.
|
||||
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according
|
||||
* to secp256k1_ec_seckey_verify, this function returns 0. For
|
||||
* uniformly random 32-byte arrays the chance of being invalid
|
||||
* is negligible (around 1 in 2^128) (cannot be NULL).
|
||||
* is negligible (around 1 in 2^128).
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_tweak_add(
|
||||
const secp256k1_context* ctx,
|
||||
|
@ -55,7 +55,7 @@ SECP256K1_API size_t secp256k1_context_preallocated_size(
|
||||
* Returns: a newly created context object.
|
||||
* In: prealloc: a pointer to a rewritable contiguous block of memory of
|
||||
* size at least secp256k1_context_preallocated_size(flags)
|
||||
* bytes, as detailed above (cannot be NULL)
|
||||
* bytes, as detailed above.
|
||||
* flags: which parts of the context to initialize.
|
||||
*
|
||||
* See also secp256k1_context_randomize (in secp256k1.h)
|
||||
@ -70,7 +70,7 @@ SECP256K1_API secp256k1_context* secp256k1_context_preallocated_create(
|
||||
* caller-provided memory.
|
||||
*
|
||||
* Returns: the required size of the caller-provided memory block.
|
||||
* In: ctx: an existing context to copy (cannot be NULL)
|
||||
* In: ctx: an existing context to copy.
|
||||
*/
|
||||
SECP256K1_API size_t secp256k1_context_preallocated_clone_size(
|
||||
const secp256k1_context* ctx
|
||||
@ -87,10 +87,10 @@ SECP256K1_API size_t secp256k1_context_preallocated_clone_size(
|
||||
* secp256k1_context_preallocated_create for details.
|
||||
*
|
||||
* Returns: a newly created context object.
|
||||
* Args: ctx: an existing context to copy (cannot be NULL)
|
||||
* Args: ctx: an existing context to copy.
|
||||
* In: prealloc: a pointer to a rewritable contiguous block of memory of
|
||||
* size at least secp256k1_context_preallocated_size(flags)
|
||||
* bytes, as detailed above (cannot be NULL)
|
||||
* bytes, as detailed above.
|
||||
*/
|
||||
SECP256K1_API secp256k1_context* secp256k1_context_preallocated_clone(
|
||||
const secp256k1_context* ctx,
|
||||
@ -115,11 +115,11 @@ SECP256K1_API secp256k1_context* secp256k1_context_preallocated_clone(
|
||||
*
|
||||
* Args: ctx: an existing context to destroy, constructed using
|
||||
* secp256k1_context_preallocated_create or
|
||||
* secp256k1_context_preallocated_clone (cannot be NULL)
|
||||
* secp256k1_context_preallocated_clone.
|
||||
*/
|
||||
SECP256K1_API void secp256k1_context_preallocated_destroy(
|
||||
secp256k1_context* ctx
|
||||
);
|
||||
) SECP256K1_ARG_NONNULL(1);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -43,8 +43,9 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact(
|
||||
/** Convert a recoverable signature into a normal signature.
|
||||
*
|
||||
* Returns: 1
|
||||
* Out: sig: a pointer to a normal signature (cannot be NULL).
|
||||
* In: sigin: a pointer to a recoverable signature (cannot be NULL).
|
||||
* Args: ctx: a secp256k1 context object.
|
||||
* Out: sig: a pointer to a normal signature.
|
||||
* In: sigin: a pointer to a recoverable signature.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert(
|
||||
const secp256k1_context* ctx,
|
||||
@ -55,10 +56,10 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert(
|
||||
/** Serialize an ECDSA signature in compact format (64 bytes + recovery id).
|
||||
*
|
||||
* Returns: 1
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: output64: a pointer to a 64-byte array of the compact signature (cannot be NULL)
|
||||
* recid: a pointer to an integer to hold the recovery id (can be NULL).
|
||||
* In: sig: a pointer to an initialized signature object (cannot be NULL)
|
||||
* Args: ctx: a secp256k1 context object.
|
||||
* Out: output64: a pointer to a 64-byte array of the compact signature.
|
||||
* recid: a pointer to an integer to hold the recovery id.
|
||||
* In: sig: a pointer to an initialized signature object.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact(
|
||||
const secp256k1_context* ctx,
|
||||
@ -71,12 +72,14 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact(
|
||||
*
|
||||
* Returns: 1: signature created
|
||||
* 0: the nonce generation function failed, or the secret key was invalid.
|
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
|
||||
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
|
||||
* In: msghash32: the 32-byte message hash being signed (cannot be NULL)
|
||||
* seckey: pointer to a 32-byte secret key (cannot be NULL)
|
||||
* noncefp: pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
|
||||
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
|
||||
* Args: ctx: pointer to a context object, initialized for signing.
|
||||
* Out: sig: pointer to an array where the signature will be placed.
|
||||
* In: msghash32: the 32-byte message hash being signed.
|
||||
* seckey: pointer to a 32-byte secret key.
|
||||
* noncefp: pointer to a nonce generation function. If NULL,
|
||||
* secp256k1_nonce_function_default is used.
|
||||
* ndata: pointer to arbitrary data used by the nonce generation function
|
||||
* (can be NULL for secp256k1_nonce_function_default).
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_sign_recoverable(
|
||||
const secp256k1_context* ctx,
|
||||
@ -91,10 +94,10 @@ SECP256K1_API int secp256k1_ecdsa_sign_recoverable(
|
||||
*
|
||||
* Returns: 1: public key successfully recovered (which guarantees a correct signature).
|
||||
* 0: otherwise.
|
||||
* Args: ctx: pointer to a context object, initialized for verification (cannot be NULL)
|
||||
* Out: pubkey: pointer to the recovered public key (cannot be NULL)
|
||||
* In: sig: pointer to initialized signature that supports pubkey recovery (cannot be NULL)
|
||||
* msghash32: the 32-byte message hash assumed to be signed (cannot be NULL)
|
||||
* Args: ctx: pointer to a context object, initialized for verification.
|
||||
* Out: pubkey: pointer to the recovered public key.
|
||||
* In: sig: pointer to initialized signature that supports pubkey recovery.
|
||||
* msghash32: the 32-byte message hash assumed to be signed.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover(
|
||||
const secp256k1_context* ctx,
|
||||
|
@ -106,12 +106,13 @@ typedef struct {
|
||||
* signatures from being valid in multiple contexts by accident.
|
||||
*
|
||||
* Returns 1 on success, 0 on failure.
|
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
|
||||
* Out: sig64: pointer to a 64-byte array to store the serialized signature (cannot be NULL)
|
||||
* In: msg32: the 32-byte message being signed (cannot be NULL)
|
||||
* keypair: pointer to an initialized keypair (cannot be NULL)
|
||||
* Args: ctx: pointer to a context object, initialized for signing.
|
||||
* Out: sig64: pointer to a 64-byte array to store the serialized signature.
|
||||
* In: msg32: the 32-byte message being signed.
|
||||
* keypair: pointer to an initialized keypair.
|
||||
* aux_rand32: 32 bytes of fresh randomness. While recommended to provide
|
||||
* this, it is only supplemental to security and can be NULL. See
|
||||
* this, it is only supplemental to security and can be NULL. A
|
||||
* NULL argument is treated the same as an all-zero one. See
|
||||
* BIP-340 "Default Signing" for a full explanation of this
|
||||
* argument and for guidance if randomness is expensive.
|
||||
*/
|
||||
@ -120,7 +121,7 @@ SECP256K1_API int secp256k1_schnorrsig_sign(
|
||||
unsigned char *sig64,
|
||||
const unsigned char *msg32,
|
||||
const secp256k1_keypair *keypair,
|
||||
unsigned char *aux_rand32
|
||||
const unsigned char *aux_rand32
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Create a Schnorr signature with a more flexible API.
|
||||
@ -150,7 +151,7 @@ SECP256K1_API int secp256k1_schnorrsig_sign_custom(
|
||||
* Returns: 1: correct signature
|
||||
* 0: incorrect signature
|
||||
* Args: ctx: a secp256k1 context object, initialized for verification.
|
||||
* In: sig64: pointer to the 64-byte signature to verify (cannot be NULL)
|
||||
* In: sig64: pointer to the 64-byte signature to verify.
|
||||
* msg: the message being verified. Can only be NULL if msglen is 0.
|
||||
* msglen: length of the message
|
||||
* pubkey: pointer to an x-only public key to verify with (cannot be NULL)
|
||||
|
@ -9,6 +9,9 @@ C = EllipticCurve([F(0), F(7)])
|
||||
|
||||
"""Base point of secp256k1"""
|
||||
G = C.lift_x(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798)
|
||||
if int(G[1]) & 1:
|
||||
# G.y is even
|
||||
G = -G
|
||||
|
||||
"""Prime order of secp256k1"""
|
||||
N = C.order()
|
||||
|
234
src/bench.c
Normal file
234
src/bench.c
Normal file
@ -0,0 +1,234 @@
|
||||
/***********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
||||
***********************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../include/secp256k1.h"
|
||||
#include "util.h"
|
||||
#include "bench.h"
|
||||
|
||||
void help(int default_iters) {
|
||||
printf("Benchmarks the following algorithms:\n");
|
||||
printf(" - ECDSA signing/verification\n");
|
||||
|
||||
#ifdef ENABLE_MODULE_ECDH
|
||||
printf(" - ECDH key exchange (optional module)\n");
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MODULE_RECOVERY
|
||||
printf(" - Public key recovery (optional module)\n");
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MODULE_SCHNORRSIG
|
||||
printf(" - Schnorr signatures (optional module)\n");
|
||||
#endif
|
||||
|
||||
printf("\n");
|
||||
printf("The default number of iterations for each benchmark is %d. This can be\n", default_iters);
|
||||
printf("customized using the SECP256K1_BENCH_ITERS environment variable.\n");
|
||||
printf("\n");
|
||||
printf("Usage: ./bench [args]\n");
|
||||
printf("By default, all benchmarks will be run.\n");
|
||||
printf("args:\n");
|
||||
printf(" help : display this help and exit\n");
|
||||
printf(" ecdsa : all ECDSA algorithms--sign, verify, recovery (if enabled)\n");
|
||||
printf(" ecdsa_sign : ECDSA siging algorithm\n");
|
||||
printf(" ecdsa_verify : ECDSA verification algorithm\n");
|
||||
|
||||
#ifdef ENABLE_MODULE_RECOVERY
|
||||
printf(" ecdsa_recover : ECDSA public key recovery algorithm\n");
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MODULE_ECDH
|
||||
printf(" ecdh : ECDH key exchange algorithm\n");
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MODULE_SCHNORRSIG
|
||||
printf(" schnorrsig : all Schnorr signature algorithms (sign, verify)\n");
|
||||
printf(" schnorrsig_sign : Schnorr sigining algorithm\n");
|
||||
printf(" schnorrsig_verify : Schnorr verification algorithm\n");
|
||||
#endif
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
secp256k1_context *ctx;
|
||||
unsigned char msg[32];
|
||||
unsigned char key[32];
|
||||
unsigned char sig[72];
|
||||
size_t siglen;
|
||||
unsigned char pubkey[33];
|
||||
size_t pubkeylen;
|
||||
} bench_verify_data;
|
||||
|
||||
static void bench_verify(void* arg, int iters) {
|
||||
int i;
|
||||
bench_verify_data* data = (bench_verify_data*)arg;
|
||||
|
||||
for (i = 0; i < iters; i++) {
|
||||
secp256k1_pubkey pubkey;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
data->sig[data->siglen - 1] ^= (i & 0xFF);
|
||||
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
|
||||
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
|
||||
CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(data->ctx, &sig, data->msg, &pubkey) == (i == 0));
|
||||
data->sig[data->siglen - 1] ^= (i & 0xFF);
|
||||
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
|
||||
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
secp256k1_context* ctx;
|
||||
unsigned char msg[32];
|
||||
unsigned char key[32];
|
||||
} bench_sign_data;
|
||||
|
||||
static void bench_sign_setup(void* arg) {
|
||||
int i;
|
||||
bench_sign_data *data = (bench_sign_data*)arg;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
data->msg[i] = i + 1;
|
||||
}
|
||||
for (i = 0; i < 32; i++) {
|
||||
data->key[i] = i + 65;
|
||||
}
|
||||
}
|
||||
|
||||
static void bench_sign_run(void* arg, int iters) {
|
||||
int i;
|
||||
bench_sign_data *data = (bench_sign_data*)arg;
|
||||
|
||||
unsigned char sig[74];
|
||||
for (i = 0; i < iters; i++) {
|
||||
size_t siglen = 74;
|
||||
int j;
|
||||
secp256k1_ecdsa_signature signature;
|
||||
CHECK(secp256k1_ecdsa_sign(data->ctx, &signature, data->msg, data->key, NULL, NULL));
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(data->ctx, sig, &siglen, &signature));
|
||||
for (j = 0; j < 32; j++) {
|
||||
data->msg[j] = sig[j];
|
||||
data->key[j] = sig[j + 32];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MODULE_ECDH
|
||||
# include "modules/ecdh/bench_impl.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MODULE_RECOVERY
|
||||
# include "modules/recovery/bench_impl.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MODULE_SCHNORRSIG
|
||||
# include "modules/schnorrsig/bench_impl.h"
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int i;
|
||||
secp256k1_pubkey pubkey;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
bench_verify_data data;
|
||||
|
||||
int d = argc == 1;
|
||||
int default_iters = 20000;
|
||||
int iters = get_iters(default_iters);
|
||||
|
||||
/* Check for invalid user arguments */
|
||||
char* valid_args[] = {"ecdsa", "verify", "ecdsa_verify", "sign", "ecdsa_sign", "ecdh", "recover",
|
||||
"ecdsa_recover", "schnorrsig", "schnorrsig_verify", "schnorrsig_sign"};
|
||||
size_t valid_args_size = sizeof(valid_args)/sizeof(valid_args[0]);
|
||||
int invalid_args = have_invalid_args(argc, argv, valid_args, valid_args_size);
|
||||
|
||||
if (argc > 1) {
|
||||
if (have_flag(argc, argv, "-h")
|
||||
|| have_flag(argc, argv, "--help")
|
||||
|| have_flag(argc, argv, "help")) {
|
||||
help(default_iters);
|
||||
return 0;
|
||||
} else if (invalid_args) {
|
||||
fprintf(stderr, "./bench: unrecognized argument.\n\n");
|
||||
help(default_iters);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the user tries to benchmark optional module without building it */
|
||||
#ifndef ENABLE_MODULE_ECDH
|
||||
if (have_flag(argc, argv, "ecdh")) {
|
||||
fprintf(stderr, "./bench: ECDH module not enabled.\n");
|
||||
fprintf(stderr, "Use ./configure --enable-module-ecdh.\n\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_MODULE_RECOVERY
|
||||
if (have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) {
|
||||
fprintf(stderr, "./bench: Public key recovery module not enabled.\n");
|
||||
fprintf(stderr, "Use ./configure --enable-module-recovery.\n\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_MODULE_SCHNORRSIG
|
||||
if (have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "schnorrsig_sign") || have_flag(argc, argv, "schnorrsig_verify")) {
|
||||
fprintf(stderr, "./bench: Schnorr signatures module not enabled.\n");
|
||||
fprintf(stderr, "Use ./configure --enable-module-schnorrsig.\n\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ECDSA verification benchmark */
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
data.msg[i] = 1 + i;
|
||||
}
|
||||
for (i = 0; i < 32; i++) {
|
||||
data.key[i] = 33 + i;
|
||||
}
|
||||
data.siglen = 72;
|
||||
CHECK(secp256k1_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL));
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig));
|
||||
CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key));
|
||||
data.pubkeylen = 33;
|
||||
CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1);
|
||||
|
||||
print_output_table_header_row();
|
||||
if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "verify") || have_flag(argc, argv, "ecdsa_verify")) run_benchmark("ecdsa_verify", bench_verify, NULL, NULL, &data, 10, iters);
|
||||
|
||||
secp256k1_context_destroy(data.ctx);
|
||||
|
||||
/* ECDSA signing benchmark */
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
|
||||
|
||||
if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "sign") || have_flag(argc, argv, "ecdsa_sign")) run_benchmark("ecdsa_sign", bench_sign_run, bench_sign_setup, NULL, &data, 10, iters);
|
||||
|
||||
secp256k1_context_destroy(data.ctx);
|
||||
|
||||
#ifdef ENABLE_MODULE_ECDH
|
||||
/* ECDH benchmarks */
|
||||
run_ecdh_bench(iters, argc, argv);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MODULE_RECOVERY
|
||||
/* ECDSA recovery benchmarks */
|
||||
run_recovery_bench(iters, argc, argv);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MODULE_SCHNORRSIG
|
||||
/* Schnorr signature benchmarks */
|
||||
run_schnorrsig_bench(iters, argc, argv);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
63
src/bench.h
63
src/bench.h
@ -24,7 +24,7 @@ static int64_t gettime_i64(void) {
|
||||
/* Format fixed point number. */
|
||||
void print_number(const int64_t x) {
|
||||
int64_t x_abs, y;
|
||||
int c, i, rounding;
|
||||
int c, i, rounding, g; /* g = integer part size, c = fractional part size */
|
||||
size_t ptr;
|
||||
char buffer[30];
|
||||
|
||||
@ -56,21 +56,27 @@ void print_number(const int64_t x) {
|
||||
/* Format and print the number. */
|
||||
ptr = sizeof(buffer) - 1;
|
||||
buffer[ptr] = 0;
|
||||
if (c != 0) {
|
||||
g = 0;
|
||||
if (c != 0) { /* non zero fractional part */
|
||||
for (i = 0; i < c; ++i) {
|
||||
buffer[--ptr] = '0' + (y % 10);
|
||||
y /= 10;
|
||||
}
|
||||
buffer[--ptr] = '.';
|
||||
} else if (c == 0) { /* fractional part is 0 */
|
||||
buffer[--ptr] = '0';
|
||||
}
|
||||
buffer[--ptr] = '.';
|
||||
do {
|
||||
buffer[--ptr] = '0' + (y % 10);
|
||||
y /= 10;
|
||||
g++;
|
||||
} while (y != 0);
|
||||
if (x < 0) {
|
||||
buffer[--ptr] = '-';
|
||||
g++;
|
||||
}
|
||||
printf("%s", &buffer[ptr]);
|
||||
printf("%5.*s", g, &buffer[ptr]); /* Prints integer 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) {
|
||||
@ -97,22 +103,20 @@ void run_benchmark(char *name, void (*benchmark)(void*, int), void (*setup)(void
|
||||
}
|
||||
sum += total;
|
||||
}
|
||||
printf("%s: min ", name);
|
||||
/* ',' is used as a column delimiter */
|
||||
printf("%-30s, ", name);
|
||||
print_number(min * FP_MULT / iter);
|
||||
printf("us / avg ");
|
||||
printf(" , ");
|
||||
print_number(((sum * FP_MULT) / count) / iter);
|
||||
printf("us / max ");
|
||||
printf(" , ");
|
||||
print_number(max * FP_MULT / iter);
|
||||
printf("us\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int have_flag(int argc, char** argv, char *flag) {
|
||||
char** argm = argv + argc;
|
||||
argv++;
|
||||
if (argv == argm) {
|
||||
return 1;
|
||||
}
|
||||
while (argv != NULL && argv != argm) {
|
||||
while (argv != argm) {
|
||||
if (strcmp(*argv, flag) == 0) {
|
||||
return 1;
|
||||
}
|
||||
@ -121,6 +125,32 @@ int have_flag(int argc, char** argv, char *flag) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* takes an array containing the arguments that the user is allowed to enter on the command-line
|
||||
returns:
|
||||
- 1 if the user entered an invalid argument
|
||||
- 0 if all the user entered arguments are valid */
|
||||
int have_invalid_args(int argc, char** argv, char** valid_args, size_t n) {
|
||||
size_t i;
|
||||
int found_valid;
|
||||
char** argm = argv + argc;
|
||||
argv++;
|
||||
|
||||
while (argv != argm) {
|
||||
found_valid = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
if (strcmp(*argv, valid_args[i]) == 0) {
|
||||
found_valid = 1; /* user entered a valid arg from the list */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found_valid == 0) {
|
||||
return 1; /* invalid arg found */
|
||||
}
|
||||
argv++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_iters(int default_iters) {
|
||||
char* env = getenv("SECP256K1_BENCH_ITERS");
|
||||
if (env) {
|
||||
@ -130,4 +160,13 @@ int get_iters(int default_iters) {
|
||||
}
|
||||
}
|
||||
|
||||
void print_output_table_header_row(void) {
|
||||
char* bench_str = "Benchmark"; /* left justified */
|
||||
char* min_str = " Min(us) "; /* center alignment */
|
||||
char* avg_str = " Avg(us) ";
|
||||
char* max_str = " Max(us) ";
|
||||
printf("%-30s,%-15s,%-15s,%-15s\n", bench_str, min_str, avg_str, max_str);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_BENCH_H */
|
||||
|
@ -124,46 +124,46 @@ static void bench_ecmult_const_teardown(void* arg, int iters) {
|
||||
bench_ecmult_teardown_helper(data, &data->offset1, &data->offset2, NULL, iters);
|
||||
}
|
||||
|
||||
static void bench_ecmult_1(void* arg, int iters) {
|
||||
static void bench_ecmult_1p(void* arg, int iters) {
|
||||
bench_data* data = (bench_data*)arg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < iters; ++i) {
|
||||
secp256k1_ecmult(&data->ctx->ecmult_ctx, &data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], NULL);
|
||||
secp256k1_ecmult(&data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void bench_ecmult_1_teardown(void* arg, int iters) {
|
||||
static void bench_ecmult_1p_teardown(void* arg, int iters) {
|
||||
bench_data* data = (bench_data*)arg;
|
||||
bench_ecmult_teardown_helper(data, &data->offset1, &data->offset2, NULL, iters);
|
||||
}
|
||||
|
||||
static void bench_ecmult_1g(void* arg, int iters) {
|
||||
static void bench_ecmult_0p_g(void* arg, int iters) {
|
||||
bench_data* data = (bench_data*)arg;
|
||||
secp256k1_scalar zero;
|
||||
int i;
|
||||
|
||||
secp256k1_scalar_set_int(&zero, 0);
|
||||
for (i = 0; i < iters; ++i) {
|
||||
secp256k1_ecmult(&data->ctx->ecmult_ctx, &data->output[i], NULL, &zero, &data->scalars[(data->offset1+i) % POINTS]);
|
||||
secp256k1_ecmult(&data->output[i], NULL, &zero, &data->scalars[(data->offset1+i) % POINTS]);
|
||||
}
|
||||
}
|
||||
|
||||
static void bench_ecmult_1g_teardown(void* arg, int iters) {
|
||||
static void bench_ecmult_0p_g_teardown(void* arg, int iters) {
|
||||
bench_data* data = (bench_data*)arg;
|
||||
bench_ecmult_teardown_helper(data, NULL, NULL, &data->offset1, iters);
|
||||
}
|
||||
|
||||
static void bench_ecmult_2g(void* arg, int iters) {
|
||||
static void bench_ecmult_1p_g(void* arg, int iters) {
|
||||
bench_data* data = (bench_data*)arg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < iters/2; ++i) {
|
||||
secp256k1_ecmult(&data->ctx->ecmult_ctx, &data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], &data->scalars[(data->offset1+i) % POINTS]);
|
||||
secp256k1_ecmult(&data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], &data->scalars[(data->offset1+i) % POINTS]);
|
||||
}
|
||||
}
|
||||
|
||||
static void bench_ecmult_2g_teardown(void* arg, int iters) {
|
||||
static void bench_ecmult_1p_g_teardown(void* arg, int iters) {
|
||||
bench_data* data = (bench_data*)arg;
|
||||
bench_ecmult_teardown_helper(data, &data->offset1, &data->offset2, &data->offset1, iters/2);
|
||||
}
|
||||
@ -175,14 +175,14 @@ static void run_ecmult_bench(bench_data* data, int iters) {
|
||||
sprintf(str, "ecmult_const");
|
||||
run_benchmark(str, bench_ecmult_const, bench_ecmult_setup, bench_ecmult_const_teardown, data, 10, iters);
|
||||
/* ecmult with non generator point */
|
||||
sprintf(str, "ecmult 1");
|
||||
run_benchmark(str, bench_ecmult_1, bench_ecmult_setup, bench_ecmult_1_teardown, data, 10, iters);
|
||||
sprintf(str, "ecmult_1p");
|
||||
run_benchmark(str, bench_ecmult_1p, bench_ecmult_setup, bench_ecmult_1p_teardown, data, 10, iters);
|
||||
/* ecmult with generator point */
|
||||
sprintf(str, "ecmult 1g");
|
||||
run_benchmark(str, bench_ecmult_1g, bench_ecmult_setup, bench_ecmult_1g_teardown, data, 10, iters);
|
||||
sprintf(str, "ecmult_0p_g");
|
||||
run_benchmark(str, bench_ecmult_0p_g, bench_ecmult_setup, bench_ecmult_0p_g_teardown, data, 10, iters);
|
||||
/* ecmult with generator and non-generator point. The reported time is per point. */
|
||||
sprintf(str, "ecmult 2g");
|
||||
run_benchmark(str, bench_ecmult_2g, bench_ecmult_setup, bench_ecmult_2g_teardown, data, 10, 2*iters);
|
||||
sprintf(str, "ecmult_1p_g");
|
||||
run_benchmark(str, bench_ecmult_1p_g, bench_ecmult_setup, bench_ecmult_1p_g_teardown, data, 10, 2*iters);
|
||||
}
|
||||
|
||||
static int bench_ecmult_multi_callback(secp256k1_scalar* sc, secp256k1_ge* ge, size_t idx, void* arg) {
|
||||
@ -207,7 +207,7 @@ static void bench_ecmult_multi(void* arg, int iters) {
|
||||
iters = iters / data->count;
|
||||
|
||||
for (iter = 0; iter < iters; ++iter) {
|
||||
data->ecmult_multi(&data->ctx->error_callback, &data->ctx->ecmult_ctx, data->scratch, &data->output[iter], data->includes_g ? &data->scalars[data->offset1] : NULL, bench_ecmult_multi_callback, arg, count - includes_g);
|
||||
data->ecmult_multi(&data->ctx->error_callback, data->scratch, &data->output[iter], data->includes_g ? &data->scalars[data->offset1] : NULL, bench_ecmult_multi_callback, arg, count - includes_g);
|
||||
data->offset1 = (data->offset1 + count) % POINTS;
|
||||
data->offset2 = (data->offset2 + count - 1) % POINTS;
|
||||
}
|
||||
@ -266,11 +266,15 @@ static void run_ecmult_multi_bench(bench_data* data, size_t count, int includes_
|
||||
secp256k1_scalar_add(&total, &total, &tmp);
|
||||
}
|
||||
secp256k1_scalar_negate(&total, &total);
|
||||
secp256k1_ecmult(&data->ctx->ecmult_ctx, &data->expected_output[iter], NULL, &zero, &total);
|
||||
secp256k1_ecmult(&data->expected_output[iter], NULL, &zero, &total);
|
||||
}
|
||||
|
||||
/* Run the benchmark. */
|
||||
sprintf(str, includes_g ? "ecmult_multi %ig" : "ecmult_multi %i", (int)count);
|
||||
if (includes_g) {
|
||||
sprintf(str, "ecmult_multi_%ip_g", (int)count - 1);
|
||||
} else {
|
||||
sprintf(str, "ecmult_multi_%ip", (int)count);
|
||||
}
|
||||
run_benchmark(str, bench_ecmult_multi, bench_ecmult_multi_setup, bench_ecmult_multi_teardown, data, 10, count * iters);
|
||||
}
|
||||
|
||||
@ -288,7 +292,7 @@ int main(int argc, char **argv) {
|
||||
|| have_flag(argc, argv, "--help")
|
||||
|| have_flag(argc, argv, "help")) {
|
||||
help(argv);
|
||||
return 1;
|
||||
return 0;
|
||||
} else if(have_flag(argc, argv, "pippenger_wnaf")) {
|
||||
printf("Using pippenger_wnaf:\n");
|
||||
data.ecmult_multi = secp256k1_ecmult_pippenger_batch_single;
|
||||
@ -333,6 +337,7 @@ int main(int argc, char **argv) {
|
||||
secp256k1_ge_set_all_gej_var(data.pubkeys, data.pubkeys_gej, POINTS);
|
||||
|
||||
|
||||
print_output_table_header_row();
|
||||
/* Initialize offset1 and offset2 */
|
||||
hash_into_offset(&data, 0);
|
||||
run_ecmult_bench(&data, iters);
|
||||
|
@ -344,37 +344,39 @@ void bench_context_sign(void* arg, int iters) {
|
||||
int main(int argc, char **argv) {
|
||||
bench_inv data;
|
||||
int iters = get_iters(20000);
|
||||
int d = argc == 1; /* default */
|
||||
print_output_table_header_row();
|
||||
|
||||
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, iters*100);
|
||||
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, iters*100);
|
||||
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "mul")) run_benchmark("scalar_mul", bench_scalar_mul, bench_setup, NULL, &data, 10, iters*10);
|
||||
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "split")) run_benchmark("scalar_split", bench_scalar_split, bench_setup, NULL, &data, 10, iters);
|
||||
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse", bench_scalar_inverse, bench_setup, NULL, &data, 10, iters);
|
||||
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse_var", bench_scalar_inverse_var, bench_setup, NULL, &data, 10, iters);
|
||||
if (d || have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, iters*100);
|
||||
if (d || have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, iters*100);
|
||||
if (d || have_flag(argc, argv, "scalar") || have_flag(argc, argv, "mul")) run_benchmark("scalar_mul", bench_scalar_mul, bench_setup, NULL, &data, 10, iters*10);
|
||||
if (d || have_flag(argc, argv, "scalar") || have_flag(argc, argv, "split")) run_benchmark("scalar_split", bench_scalar_split, bench_setup, NULL, &data, 10, iters);
|
||||
if (d || have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse", bench_scalar_inverse, bench_setup, NULL, &data, 10, iters);
|
||||
if (d || have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse_var", bench_scalar_inverse_var, bench_setup, NULL, &data, 10, iters);
|
||||
|
||||
if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize", bench_field_normalize, bench_setup, NULL, &data, 10, iters*100);
|
||||
if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize_weak", bench_field_normalize_weak, bench_setup, NULL, &data, 10, iters*100);
|
||||
if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqr")) run_benchmark("field_sqr", bench_field_sqr, bench_setup, NULL, &data, 10, iters*10);
|
||||
if (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 (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse", bench_field_inverse, bench_setup, NULL, &data, 10, iters);
|
||||
if (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 (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, "normalize")) run_benchmark("field_normalize", bench_field_normalize, bench_setup, NULL, &data, 10, iters*100);
|
||||
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize_weak", bench_field_normalize_weak, bench_setup, NULL, &data, 10, iters*100);
|
||||
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "sqr")) run_benchmark("field_sqr", bench_field_sqr, bench_setup, NULL, &data, 10, iters*10);
|
||||
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "mul")) run_benchmark("field_mul", bench_field_mul, bench_setup, NULL, &data, 10, iters*10);
|
||||
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, "sqrt")) run_benchmark("field_sqrt", bench_field_sqrt, bench_setup, NULL, &data, 10, iters);
|
||||
|
||||
if (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 (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_var", bench_group_add_var, bench_setup, NULL, &data, 10, iters*10);
|
||||
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, iters*10);
|
||||
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, iters*10);
|
||||
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "to_affine")) run_benchmark("group_to_affine_var", bench_group_to_affine_var, 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, "add")) run_benchmark("group_add_var", bench_group_add_var, bench_setup, NULL, &data, 10, iters*10);
|
||||
if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, iters*10);
|
||||
if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, iters*10);
|
||||
if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "to_affine")) run_benchmark("group_to_affine_var", bench_group_to_affine_var, bench_setup, NULL, &data, 10, iters);
|
||||
|
||||
if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("wnaf_const", bench_wnaf_const, bench_setup, NULL, &data, 10, iters);
|
||||
if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, iters);
|
||||
if (d || have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("wnaf_const", bench_wnaf_const, bench_setup, NULL, &data, 10, iters);
|
||||
if (d || have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, iters);
|
||||
|
||||
if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "sha256")) run_benchmark("hash_sha256", bench_sha256, bench_setup, NULL, &data, 10, iters);
|
||||
if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "hmac")) run_benchmark("hash_hmac_sha256", bench_hmac_sha256, bench_setup, NULL, &data, 10, iters);
|
||||
if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "rng6979")) run_benchmark("hash_rfc6979_hmac_sha256", bench_rfc6979_hmac_sha256, bench_setup, NULL, &data, 10, iters);
|
||||
if (d || have_flag(argc, argv, "hash") || have_flag(argc, argv, "sha256")) run_benchmark("hash_sha256", bench_sha256, bench_setup, NULL, &data, 10, iters);
|
||||
if (d || have_flag(argc, argv, "hash") || have_flag(argc, argv, "hmac")) run_benchmark("hash_hmac_sha256", bench_hmac_sha256, bench_setup, NULL, &data, 10, iters);
|
||||
if (d || have_flag(argc, argv, "hash") || have_flag(argc, argv, "rng6979")) run_benchmark("hash_rfc6979_hmac_sha256", bench_rfc6979_hmac_sha256, bench_setup, NULL, &data, 10, iters);
|
||||
|
||||
if (have_flag(argc, argv, "context") || have_flag(argc, argv, "verify")) run_benchmark("context_verify", bench_context_verify, bench_setup, NULL, &data, 10, 1 + iters/1000);
|
||||
if (have_flag(argc, argv, "context") || have_flag(argc, argv, "sign")) run_benchmark("context_sign", bench_context_sign, bench_setup, NULL, &data, 10, 1 + iters/100);
|
||||
if (d || have_flag(argc, argv, "context") || have_flag(argc, argv, "verify")) run_benchmark("context_verify", bench_context_verify, bench_setup, NULL, &data, 10, 1 + iters/1000);
|
||||
if (d || have_flag(argc, argv, "context") || have_flag(argc, argv, "sign")) run_benchmark("context_sign", bench_context_sign, bench_setup, NULL, &data, 10, 1 + iters/100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,58 +0,0 @@
|
||||
/***********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
||||
***********************************************************************/
|
||||
|
||||
#include "../include/secp256k1.h"
|
||||
#include "util.h"
|
||||
#include "bench.h"
|
||||
|
||||
typedef struct {
|
||||
secp256k1_context* ctx;
|
||||
unsigned char msg[32];
|
||||
unsigned char key[32];
|
||||
} bench_sign_data;
|
||||
|
||||
static void bench_sign_setup(void* arg) {
|
||||
int i;
|
||||
bench_sign_data *data = (bench_sign_data*)arg;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
data->msg[i] = i + 1;
|
||||
}
|
||||
for (i = 0; i < 32; i++) {
|
||||
data->key[i] = i + 65;
|
||||
}
|
||||
}
|
||||
|
||||
static void bench_sign_run(void* arg, int iters) {
|
||||
int i;
|
||||
bench_sign_data *data = (bench_sign_data*)arg;
|
||||
|
||||
unsigned char sig[74];
|
||||
for (i = 0; i < iters; i++) {
|
||||
size_t siglen = 74;
|
||||
int j;
|
||||
secp256k1_ecdsa_signature signature;
|
||||
CHECK(secp256k1_ecdsa_sign(data->ctx, &signature, data->msg, data->key, NULL, NULL));
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(data->ctx, sig, &siglen, &signature));
|
||||
for (j = 0; j < 32; j++) {
|
||||
data->msg[j] = sig[j];
|
||||
data->key[j] = sig[j + 32];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
bench_sign_data data;
|
||||
|
||||
int iters = get_iters(20000);
|
||||
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
|
||||
|
||||
run_benchmark("ecdsa_sign", bench_sign_run, bench_sign_setup, NULL, &data, 10, iters);
|
||||
|
||||
secp256k1_context_destroy(data.ctx);
|
||||
return 0;
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
/***********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
||||
***********************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../include/secp256k1.h"
|
||||
#include "util.h"
|
||||
#include "bench.h"
|
||||
|
||||
#ifdef ENABLE_OPENSSL_TESTS
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
secp256k1_context *ctx;
|
||||
unsigned char msg[32];
|
||||
unsigned char key[32];
|
||||
unsigned char sig[72];
|
||||
size_t siglen;
|
||||
unsigned char pubkey[33];
|
||||
size_t pubkeylen;
|
||||
#ifdef ENABLE_OPENSSL_TESTS
|
||||
EC_GROUP* ec_group;
|
||||
#endif
|
||||
} bench_verify_data;
|
||||
|
||||
static void bench_verify(void* arg, int iters) {
|
||||
int i;
|
||||
bench_verify_data* data = (bench_verify_data*)arg;
|
||||
|
||||
for (i = 0; i < iters; i++) {
|
||||
secp256k1_pubkey pubkey;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
data->sig[data->siglen - 1] ^= (i & 0xFF);
|
||||
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
|
||||
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
|
||||
CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(data->ctx, &sig, data->msg, &pubkey) == (i == 0));
|
||||
data->sig[data->siglen - 1] ^= (i & 0xFF);
|
||||
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
|
||||
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_OPENSSL_TESTS
|
||||
static void bench_verify_openssl(void* arg, int iters) {
|
||||
int i;
|
||||
bench_verify_data* data = (bench_verify_data*)arg;
|
||||
|
||||
for (i = 0; i < iters; i++) {
|
||||
data->sig[data->siglen - 1] ^= (i & 0xFF);
|
||||
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
|
||||
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
|
||||
{
|
||||
EC_KEY *pkey = EC_KEY_new();
|
||||
const unsigned char *pubkey = &data->pubkey[0];
|
||||
int result;
|
||||
|
||||
CHECK(pkey != NULL);
|
||||
result = EC_KEY_set_group(pkey, data->ec_group);
|
||||
CHECK(result);
|
||||
result = (o2i_ECPublicKey(&pkey, &pubkey, data->pubkeylen)) != NULL;
|
||||
CHECK(result);
|
||||
result = ECDSA_verify(0, &data->msg[0], sizeof(data->msg), &data->sig[0], data->siglen, pkey) == (i == 0);
|
||||
CHECK(result);
|
||||
EC_KEY_free(pkey);
|
||||
}
|
||||
data->sig[data->siglen - 1] ^= (i & 0xFF);
|
||||
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
|
||||
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(void) {
|
||||
int i;
|
||||
secp256k1_pubkey pubkey;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
bench_verify_data data;
|
||||
|
||||
int iters = get_iters(20000);
|
||||
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
data.msg[i] = 1 + i;
|
||||
}
|
||||
for (i = 0; i < 32; i++) {
|
||||
data.key[i] = 33 + i;
|
||||
}
|
||||
data.siglen = 72;
|
||||
CHECK(secp256k1_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL));
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig));
|
||||
CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key));
|
||||
data.pubkeylen = 33;
|
||||
CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1);
|
||||
|
||||
run_benchmark("ecdsa_verify", bench_verify, NULL, NULL, &data, 10, iters);
|
||||
#ifdef ENABLE_OPENSSL_TESTS
|
||||
data.ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1);
|
||||
run_benchmark("ecdsa_verify_openssl", bench_verify_openssl, NULL, NULL, &data, 10, iters);
|
||||
EC_GROUP_free(data.ec_group);
|
||||
#endif
|
||||
|
||||
secp256k1_context_destroy(data.ctx);
|
||||
return 0;
|
||||
}
|
@ -15,7 +15,7 @@
|
||||
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, const unsigned char *sig, size_t size);
|
||||
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s);
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message);
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message);
|
||||
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid);
|
||||
|
||||
#endif /* SECP256K1_ECDSA_H */
|
||||
|
@ -112,7 +112,7 @@ static int secp256k1_der_parse_integer(secp256k1_scalar *r, const unsigned char
|
||||
if (secp256k1_der_read_len(&rlen, sig, sigend) == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (rlen == 0 || *sig + rlen > sigend) {
|
||||
if (rlen == 0 || rlen > (size_t)(sigend - *sig)) {
|
||||
/* Exceeds bounds or not at least length 1 (X.690-0207 8.3.1). */
|
||||
return 0;
|
||||
}
|
||||
@ -204,7 +204,7 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) {
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) {
|
||||
unsigned char c[32];
|
||||
secp256k1_scalar sn, u1, u2;
|
||||
#if !defined(EXHAUSTIVE_TEST_ORDER)
|
||||
@ -221,7 +221,7 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const
|
||||
secp256k1_scalar_mul(&u1, &sn, message);
|
||||
secp256k1_scalar_mul(&u2, &sn, sigr);
|
||||
secp256k1_gej_set_ge(&pubkeyj, pubkey);
|
||||
secp256k1_ecmult(ctx, &pr, &pubkeyj, &u2, &u1);
|
||||
secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1);
|
||||
if (secp256k1_gej_is_infinity(&pr)) {
|
||||
return 0;
|
||||
}
|
||||
@ -304,12 +304,12 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec
|
||||
high = secp256k1_scalar_is_high(sigs);
|
||||
secp256k1_scalar_cond_negate(sigs, high);
|
||||
if (recid) {
|
||||
*recid ^= high;
|
||||
*recid ^= high;
|
||||
}
|
||||
/* P.x = order is on the curve, so technically sig->r could end up being zero, which would be an invalid signature.
|
||||
* This is cryptographically unreachable as hitting it requires finding the discrete log of P.x = N.
|
||||
*/
|
||||
return !secp256k1_scalar_is_zero(sigr) & !secp256k1_scalar_is_zero(sigs);
|
||||
return (int)(!secp256k1_scalar_is_zero(sigr)) & (int)(!secp256k1_scalar_is_zero(sigs));
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_ECDSA_IMPL_H */
|
||||
|
@ -18,8 +18,8 @@ static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char
|
||||
static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed);
|
||||
|
||||
static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak);
|
||||
static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak);
|
||||
static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge *key, const secp256k1_scalar *tweak);
|
||||
static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak);
|
||||
static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak);
|
||||
static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge *key, const secp256k1_scalar *tweak);
|
||||
|
||||
#endif /* SECP256K1_ECKEY_H */
|
||||
|
@ -57,12 +57,12 @@ static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp25
|
||||
return !secp256k1_scalar_is_zero(key);
|
||||
}
|
||||
|
||||
static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) {
|
||||
static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge *key, const secp256k1_scalar *tweak) {
|
||||
secp256k1_gej pt;
|
||||
secp256k1_scalar one;
|
||||
secp256k1_gej_set_ge(&pt, key);
|
||||
secp256k1_scalar_set_int(&one, 1);
|
||||
secp256k1_ecmult(ctx, &pt, &pt, &one, tweak);
|
||||
secp256k1_ecmult(&pt, &pt, &one, tweak);
|
||||
|
||||
if (secp256k1_gej_is_infinity(&pt)) {
|
||||
return 0;
|
||||
@ -79,7 +79,7 @@ static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp25
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) {
|
||||
static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge *key, const secp256k1_scalar *tweak) {
|
||||
secp256k1_scalar zero;
|
||||
secp256k1_gej pt;
|
||||
if (secp256k1_scalar_is_zero(tweak)) {
|
||||
@ -88,7 +88,7 @@ static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx,
|
||||
|
||||
secp256k1_scalar_set_int(&zero, 0);
|
||||
secp256k1_gej_set_ge(&pt, key);
|
||||
secp256k1_ecmult(ctx, &pt, &pt, tweak, &zero);
|
||||
secp256k1_ecmult(&pt, &pt, tweak, &zero);
|
||||
secp256k1_ge_set_gej(key, &pt);
|
||||
return 1;
|
||||
}
|
||||
|
30
src/ecmult.h
30
src/ecmult.h
@ -11,20 +11,26 @@
|
||||
#include "scalar.h"
|
||||
#include "scratch.h"
|
||||
|
||||
typedef struct {
|
||||
/* For accelerating the computation of a*P + b*G: */
|
||||
secp256k1_ge_storage (*pre_g)[]; /* odd multiples of the generator */
|
||||
secp256k1_ge_storage (*pre_g_128)[]; /* odd multiples of 2^128*generator */
|
||||
} secp256k1_ecmult_context;
|
||||
/* Noone will ever need more than a window size of 24. The code might
|
||||
* be correct for larger values of ECMULT_WINDOW_SIZE but this is not
|
||||
* tested.
|
||||
*
|
||||
* The following limitations are known, and there are probably more:
|
||||
* If WINDOW_G > 27 and size_t has 32 bits, then the code is incorrect
|
||||
* because the size of the memory object that we allocate (in bytes)
|
||||
* will not fit in a size_t.
|
||||
* If WINDOW_G > 31 and int has 32 bits, then the code is incorrect
|
||||
* because certain expressions will overflow.
|
||||
*/
|
||||
#if ECMULT_WINDOW_SIZE < 2 || ECMULT_WINDOW_SIZE > 24
|
||||
# error Set ECMULT_WINDOW_SIZE to an integer in range [2..24].
|
||||
#endif
|
||||
|
||||
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx);
|
||||
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void **prealloc);
|
||||
static void secp256k1_ecmult_context_finalize_memcpy(secp256k1_ecmult_context *dst, const secp256k1_ecmult_context *src);
|
||||
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx);
|
||||
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx);
|
||||
/** The number of entries a table with precomputed multiples needs to have. */
|
||||
#define ECMULT_TABLE_SIZE(w) (1L << ((w)-2))
|
||||
|
||||
/** Double multiply: R = na*A + ng*G */
|
||||
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng);
|
||||
static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng);
|
||||
|
||||
typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data);
|
||||
|
||||
@ -39,6 +45,6 @@ typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge
|
||||
* 0 if there is not enough scratch space for a single point or
|
||||
* callback returns 0
|
||||
*/
|
||||
static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n);
|
||||
static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n);
|
||||
|
||||
#endif /* SECP256K1_ECMULT_H */
|
||||
|
@ -14,6 +14,7 @@
|
||||
* Multiply: R = q*A (in constant-time)
|
||||
* Here `bits` should be set to the maximum bitlength of the _absolute value_ of `q`, plus
|
||||
* one because we internally sometimes add 2 to the number during the WNAF conversion.
|
||||
* A must not be infinity.
|
||||
*/
|
||||
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q, int bits);
|
||||
|
||||
|
@ -168,6 +168,7 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
|
||||
* that the Z coordinate was 1, use affine addition formulae, and correct
|
||||
* the Z coordinate of the result once at the end.
|
||||
*/
|
||||
VERIFY_CHECK(!a->infinity);
|
||||
secp256k1_gej_set_ge(r, a);
|
||||
secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, r);
|
||||
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
|
||||
|
@ -13,33 +13,20 @@
|
||||
#if ECMULT_GEN_PREC_BITS != 2 && ECMULT_GEN_PREC_BITS != 4 && ECMULT_GEN_PREC_BITS != 8
|
||||
# error "Set ECMULT_GEN_PREC_BITS to 2, 4 or 8."
|
||||
#endif
|
||||
#define ECMULT_GEN_PREC_B ECMULT_GEN_PREC_BITS
|
||||
#define ECMULT_GEN_PREC_G (1 << ECMULT_GEN_PREC_B)
|
||||
#define ECMULT_GEN_PREC_N (256 / ECMULT_GEN_PREC_B)
|
||||
#define ECMULT_GEN_PREC_G(bits) (1 << bits)
|
||||
#define ECMULT_GEN_PREC_N(bits) (256 / bits)
|
||||
|
||||
typedef struct {
|
||||
/* For accelerating the computation of a*G:
|
||||
* To harden against timing attacks, use the following mechanism:
|
||||
* * Break up the multiplicand into groups of PREC_B bits, called n_0, n_1, n_2, ..., n_(PREC_N-1).
|
||||
* * Compute sum(n_i * (PREC_G)^i * G + U_i, i=0 ... PREC_N-1), where:
|
||||
* * U_i = U * 2^i, for i=0 ... PREC_N-2
|
||||
* * U_i = U * (1-2^(PREC_N-1)), for i=PREC_N-1
|
||||
* where U is a point with no known corresponding scalar. Note that sum(U_i, i=0 ... PREC_N-1) = 0.
|
||||
* For each i, and each of the PREC_G possible values of n_i, (n_i * (PREC_G)^i * G + U_i) is
|
||||
* precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0 ... PREC_N-1).
|
||||
* None of the resulting prec group elements have a known scalar, and neither do any of
|
||||
* the intermediate sums while computing a*G.
|
||||
*/
|
||||
secp256k1_ge_storage (*prec)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G]; /* prec[j][i] = (PREC_G)^j * i * G + U_i */
|
||||
secp256k1_scalar blind;
|
||||
secp256k1_gej initial;
|
||||
/* Whether the context has been built. */
|
||||
int built;
|
||||
|
||||
/* Blinding values used when computing (n-b)G + bG. */
|
||||
secp256k1_scalar blind; /* -b */
|
||||
secp256k1_gej initial; /* bG */
|
||||
} secp256k1_ecmult_gen_context;
|
||||
|
||||
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context* ctx);
|
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx, void **prealloc);
|
||||
static void secp256k1_ecmult_gen_context_finalize_memcpy(secp256k1_ecmult_gen_context *dst, const secp256k1_ecmult_gen_context* src);
|
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx);
|
||||
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx);
|
||||
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx);
|
||||
|
||||
/** Multiply with the generator: R = a*G */
|
||||
static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a);
|
||||
|
@ -12,130 +12,54 @@
|
||||
#include "group.h"
|
||||
#include "ecmult_gen.h"
|
||||
#include "hash_impl.h"
|
||||
#ifdef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
#include "ecmult_static_context.h"
|
||||
#endif
|
||||
#include "ecmult_gen_static_prec_table.h"
|
||||
|
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
static const size_t SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE = ROUND_TO_ALIGN(sizeof(*((secp256k1_ecmult_gen_context*) NULL)->prec));
|
||||
#else
|
||||
static const size_t SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE = 0;
|
||||
#endif
|
||||
|
||||
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context *ctx) {
|
||||
ctx->prec = NULL;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx, void **prealloc) {
|
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
secp256k1_ge prec[ECMULT_GEN_PREC_N * ECMULT_GEN_PREC_G];
|
||||
secp256k1_gej gj;
|
||||
secp256k1_gej nums_gej;
|
||||
int i, j;
|
||||
size_t const prealloc_size = SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE;
|
||||
void* const base = *prealloc;
|
||||
#endif
|
||||
|
||||
if (ctx->prec != NULL) {
|
||||
return;
|
||||
}
|
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
ctx->prec = (secp256k1_ge_storage (*)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G])manual_alloc(prealloc, prealloc_size, base, prealloc_size);
|
||||
|
||||
/* get the generator */
|
||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
|
||||
|
||||
/* Construct a group element with no known corresponding scalar (nothing up my sleeve). */
|
||||
{
|
||||
static const unsigned char nums_b32[33] = "The scalar for this x is unknown";
|
||||
secp256k1_fe nums_x;
|
||||
secp256k1_ge nums_ge;
|
||||
int r;
|
||||
r = secp256k1_fe_set_b32(&nums_x, nums_b32);
|
||||
(void)r;
|
||||
VERIFY_CHECK(r);
|
||||
r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0);
|
||||
(void)r;
|
||||
VERIFY_CHECK(r);
|
||||
secp256k1_gej_set_ge(&nums_gej, &nums_ge);
|
||||
/* Add G to make the bits in x uniformly distributed. */
|
||||
secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g, NULL);
|
||||
}
|
||||
|
||||
/* compute prec. */
|
||||
{
|
||||
secp256k1_gej precj[ECMULT_GEN_PREC_N * ECMULT_GEN_PREC_G]; /* Jacobian versions of prec. */
|
||||
secp256k1_gej gbase;
|
||||
secp256k1_gej numsbase;
|
||||
gbase = gj; /* PREC_G^j * G */
|
||||
numsbase = nums_gej; /* 2^j * nums. */
|
||||
for (j = 0; j < ECMULT_GEN_PREC_N; j++) {
|
||||
/* Set precj[j*PREC_G .. j*PREC_G+(PREC_G-1)] to (numsbase, numsbase + gbase, ..., numsbase + (PREC_G-1)*gbase). */
|
||||
precj[j*ECMULT_GEN_PREC_G] = numsbase;
|
||||
for (i = 1; i < ECMULT_GEN_PREC_G; i++) {
|
||||
secp256k1_gej_add_var(&precj[j*ECMULT_GEN_PREC_G + i], &precj[j*ECMULT_GEN_PREC_G + i - 1], &gbase, NULL);
|
||||
}
|
||||
/* Multiply gbase by PREC_G. */
|
||||
for (i = 0; i < ECMULT_GEN_PREC_B; i++) {
|
||||
secp256k1_gej_double_var(&gbase, &gbase, NULL);
|
||||
}
|
||||
/* Multiply numbase by 2. */
|
||||
secp256k1_gej_double_var(&numsbase, &numsbase, NULL);
|
||||
if (j == ECMULT_GEN_PREC_N - 2) {
|
||||
/* In the last iteration, numsbase is (1 - 2^j) * nums instead. */
|
||||
secp256k1_gej_neg(&numsbase, &numsbase);
|
||||
secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL);
|
||||
}
|
||||
}
|
||||
secp256k1_ge_set_all_gej_var(prec, precj, ECMULT_GEN_PREC_N * ECMULT_GEN_PREC_G);
|
||||
}
|
||||
for (j = 0; j < ECMULT_GEN_PREC_N; j++) {
|
||||
for (i = 0; i < ECMULT_GEN_PREC_G; i++) {
|
||||
secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*ECMULT_GEN_PREC_G + i]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)prealloc;
|
||||
ctx->prec = (secp256k1_ge_storage (*)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G])secp256k1_ecmult_static_context;
|
||||
#endif
|
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx) {
|
||||
secp256k1_ecmult_gen_blind(ctx, NULL);
|
||||
ctx->built = 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx) {
|
||||
return ctx->prec != NULL;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen_context_finalize_memcpy(secp256k1_ecmult_gen_context *dst, const secp256k1_ecmult_gen_context *src) {
|
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
if (src->prec != NULL) {
|
||||
/* We cast to void* first to suppress a -Wcast-align warning. */
|
||||
dst->prec = (secp256k1_ge_storage (*)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G])(void*)((unsigned char*)dst + ((unsigned char*)src->prec - (unsigned char*)src));
|
||||
}
|
||||
#else
|
||||
(void)dst, (void)src;
|
||||
#endif
|
||||
return ctx->built;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) {
|
||||
ctx->built = 0;
|
||||
secp256k1_scalar_clear(&ctx->blind);
|
||||
secp256k1_gej_clear(&ctx->initial);
|
||||
ctx->prec = NULL;
|
||||
}
|
||||
|
||||
/* For accelerating the computation of a*G:
|
||||
* To harden against timing attacks, use the following mechanism:
|
||||
* * Break up the multiplicand into groups of PREC_BITS bits, called n_0, n_1, n_2, ..., n_(PREC_N-1).
|
||||
* * Compute sum(n_i * (PREC_G)^i * G + U_i, i=0 ... PREC_N-1), where:
|
||||
* * U_i = U * 2^i, for i=0 ... PREC_N-2
|
||||
* * U_i = U * (1-2^(PREC_N-1)), for i=PREC_N-1
|
||||
* where U is a point with no known corresponding scalar. Note that sum(U_i, i=0 ... PREC_N-1) = 0.
|
||||
* For each i, and each of the PREC_G possible values of n_i, (n_i * (PREC_G)^i * G + U_i) is
|
||||
* precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0 ... PREC_N-1).
|
||||
* None of the resulting prec group elements have a known scalar, and neither do any of
|
||||
* the intermediate sums while computing a*G.
|
||||
* The prec values are stored in secp256k1_ecmult_gen_prec_table[i][n_i] = n_i * (PREC_G)^i * G + U_i.
|
||||
*/
|
||||
static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) {
|
||||
int bits = ECMULT_GEN_PREC_BITS;
|
||||
int g = ECMULT_GEN_PREC_G(bits);
|
||||
int n = ECMULT_GEN_PREC_N(bits);
|
||||
|
||||
secp256k1_ge add;
|
||||
secp256k1_ge_storage adds;
|
||||
secp256k1_scalar gnb;
|
||||
int bits;
|
||||
int i, j;
|
||||
int i, j, n_i;
|
||||
|
||||
memset(&adds, 0, sizeof(adds));
|
||||
*r = ctx->initial;
|
||||
/* Blind scalar/point multiplication by computing (n-b)G + bG instead of nG. */
|
||||
secp256k1_scalar_add(&gnb, gn, &ctx->blind);
|
||||
add.infinity = 0;
|
||||
for (j = 0; j < ECMULT_GEN_PREC_N; j++) {
|
||||
bits = secp256k1_scalar_get_bits(&gnb, j * ECMULT_GEN_PREC_B, ECMULT_GEN_PREC_B);
|
||||
for (i = 0; i < ECMULT_GEN_PREC_G; i++) {
|
||||
for (i = 0; i < n; i++) {
|
||||
n_i = secp256k1_scalar_get_bits(&gnb, i * bits, bits);
|
||||
for (j = 0; j < g; j++) {
|
||||
/** This uses a conditional move to avoid any secret data in array indexes.
|
||||
* _Any_ use of secret indexes has been demonstrated to result in timing
|
||||
* sidechannels, even when the cache-line access patterns are uniform.
|
||||
@ -146,12 +70,12 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25
|
||||
* by Dag Arne Osvik, Adi Shamir, and Eran Tromer
|
||||
* (https://www.tau.ac.il/~tromer/papers/cache.pdf)
|
||||
*/
|
||||
secp256k1_ge_storage_cmov(&adds, &(*ctx->prec)[j][i], i == bits);
|
||||
secp256k1_ge_storage_cmov(&adds, &secp256k1_ecmult_gen_prec_table[i][j], j == n_i);
|
||||
}
|
||||
secp256k1_ge_from_storage(&add, &adds);
|
||||
secp256k1_gej_add_ge(r, r, &add);
|
||||
}
|
||||
bits = 0;
|
||||
n_i = 0;
|
||||
secp256k1_ge_clear(&add);
|
||||
secp256k1_scalar_clear(&gnb);
|
||||
}
|
||||
|
14
src/ecmult_gen_prec.h
Normal file
14
src/ecmult_gen_prec.h
Normal file
@ -0,0 +1,14 @@
|
||||
/***********************************************************************
|
||||
* Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_ECMULT_GEN_PREC_H
|
||||
#define SECP256K1_ECMULT_GEN_PREC_H
|
||||
|
||||
#include "ecmult_gen.h"
|
||||
|
||||
static void secp256k1_ecmult_gen_create_prec_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int bits);
|
||||
|
||||
#endif /* SECP256K1_ECMULT_GEN_PREC_H */
|
81
src/ecmult_gen_prec_impl.h
Normal file
81
src/ecmult_gen_prec_impl.h
Normal file
@ -0,0 +1,81 @@
|
||||
/***********************************************************************
|
||||
* Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_ECMULT_GEN_PREC_IMPL_H
|
||||
#define SECP256K1_ECMULT_GEN_PREC_IMPL_H
|
||||
|
||||
#include "ecmult_gen_prec.h"
|
||||
#include "group_impl.h"
|
||||
#include "field_impl.h"
|
||||
#include "ecmult_gen.h"
|
||||
#include "util.h"
|
||||
|
||||
static void secp256k1_ecmult_gen_create_prec_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int bits) {
|
||||
int g = ECMULT_GEN_PREC_G(bits);
|
||||
int n = ECMULT_GEN_PREC_N(bits);
|
||||
|
||||
secp256k1_ge* prec = checked_malloc(&default_error_callback, n * g * sizeof(*prec));
|
||||
secp256k1_gej gj;
|
||||
secp256k1_gej nums_gej;
|
||||
int i, j;
|
||||
|
||||
/* get the generator */
|
||||
secp256k1_gej_set_ge(&gj, gen);
|
||||
|
||||
/* Construct a group element with no known corresponding scalar (nothing up my sleeve). */
|
||||
{
|
||||
static const unsigned char nums_b32[33] = "The scalar for this x is unknown";
|
||||
secp256k1_fe nums_x;
|
||||
secp256k1_ge nums_ge;
|
||||
int r;
|
||||
r = secp256k1_fe_set_b32(&nums_x, nums_b32);
|
||||
(void)r;
|
||||
VERIFY_CHECK(r);
|
||||
r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0);
|
||||
(void)r;
|
||||
VERIFY_CHECK(r);
|
||||
secp256k1_gej_set_ge(&nums_gej, &nums_ge);
|
||||
/* Add G to make the bits in x uniformly distributed. */
|
||||
secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, gen, NULL);
|
||||
}
|
||||
|
||||
/* compute prec. */
|
||||
{
|
||||
secp256k1_gej gbase;
|
||||
secp256k1_gej numsbase;
|
||||
secp256k1_gej* precj = checked_malloc(&default_error_callback, n * g * sizeof(*precj)); /* Jacobian versions of prec. */
|
||||
gbase = gj; /* PREC_G^j * G */
|
||||
numsbase = nums_gej; /* 2^j * nums. */
|
||||
for (j = 0; j < n; j++) {
|
||||
/* Set precj[j*PREC_G .. j*PREC_G+(PREC_G-1)] to (numsbase, numsbase + gbase, ..., numsbase + (PREC_G-1)*gbase). */
|
||||
precj[j*g] = numsbase;
|
||||
for (i = 1; i < g; i++) {
|
||||
secp256k1_gej_add_var(&precj[j*g + i], &precj[j*g + i - 1], &gbase, NULL);
|
||||
}
|
||||
/* Multiply gbase by PREC_G. */
|
||||
for (i = 0; i < bits; i++) {
|
||||
secp256k1_gej_double_var(&gbase, &gbase, NULL);
|
||||
}
|
||||
/* Multiply numbase by 2. */
|
||||
secp256k1_gej_double_var(&numsbase, &numsbase, NULL);
|
||||
if (j == n - 2) {
|
||||
/* In the last iteration, numsbase is (1 - 2^j) * nums instead. */
|
||||
secp256k1_gej_neg(&numsbase, &numsbase);
|
||||
secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL);
|
||||
}
|
||||
}
|
||||
secp256k1_ge_set_all_gej_var(prec, precj, n * g);
|
||||
free(precj);
|
||||
}
|
||||
for (j = 0; j < n; j++) {
|
||||
for (i = 0; i < g; i++) {
|
||||
secp256k1_ge_to_storage(&table[j*g + i], &prec[j*g + i]);
|
||||
}
|
||||
}
|
||||
free(prec);
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_ECMULT_GEN_PREC_IMPL_H */
|
9748
src/ecmult_gen_static_prec_table.h
generated
Normal file
9748
src/ecmult_gen_static_prec_table.h
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,7 @@
|
||||
#include "group.h"
|
||||
#include "scalar.h"
|
||||
#include "ecmult.h"
|
||||
#include "ecmult_static_pre_g.h"
|
||||
|
||||
#if defined(EXHAUSTIVE_TEST_ORDER)
|
||||
/* We need to lower these values for exhaustive tests because
|
||||
@ -21,13 +22,10 @@
|
||||
* affine-isomorphism stuff which tracks z-ratios) */
|
||||
# if EXHAUSTIVE_TEST_ORDER > 128
|
||||
# define WINDOW_A 5
|
||||
# define WINDOW_G 8
|
||||
# elif EXHAUSTIVE_TEST_ORDER > 8
|
||||
# define WINDOW_A 4
|
||||
# define WINDOW_G 4
|
||||
# else
|
||||
# define WINDOW_A 2
|
||||
# define WINDOW_G 2
|
||||
# endif
|
||||
#else
|
||||
/* optimal for 128-bit and 256-bit exponents. */
|
||||
@ -41,34 +39,15 @@
|
||||
* Two tables of this size are used (due to the endomorphism
|
||||
* optimization).
|
||||
*/
|
||||
# define WINDOW_G ECMULT_WINDOW_SIZE
|
||||
#endif
|
||||
|
||||
/* Noone will ever need more than a window size of 24. The code might
|
||||
* be correct for larger values of ECMULT_WINDOW_SIZE but this is not
|
||||
* not tested.
|
||||
*
|
||||
* The following limitations are known, and there are probably more:
|
||||
* If WINDOW_G > 27 and size_t has 32 bits, then the code is incorrect
|
||||
* because the size of the memory object that we allocate (in bytes)
|
||||
* will not fit in a size_t.
|
||||
* If WINDOW_G > 31 and int has 32 bits, then the code is incorrect
|
||||
* because certain expressions will overflow.
|
||||
*/
|
||||
#if ECMULT_WINDOW_SIZE < 2 || ECMULT_WINDOW_SIZE > 24
|
||||
# error Set ECMULT_WINDOW_SIZE to an integer in range [2..24].
|
||||
#endif
|
||||
|
||||
#define WNAF_BITS 128
|
||||
#define WNAF_SIZE_BITS(bits, w) (((bits) + (w) - 1) / (w))
|
||||
#define WNAF_SIZE(w) WNAF_SIZE_BITS(WNAF_BITS, w)
|
||||
|
||||
/** The number of entries a table with precomputed multiples needs to have. */
|
||||
#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2))
|
||||
|
||||
/* The number of objects allocated on the scratch space for ecmult_multi algorithms */
|
||||
#define PIPPENGER_SCRATCH_OBJECTS 6
|
||||
#define STRAUSS_SCRATCH_OBJECTS 6
|
||||
#define STRAUSS_SCRATCH_OBJECTS 7
|
||||
|
||||
#define PIPPENGER_MAX_BUCKET_WINDOW 12
|
||||
|
||||
@ -119,18 +98,12 @@ static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, sec
|
||||
|
||||
/** Fill a table 'pre' with precomputed odd multiples of a.
|
||||
*
|
||||
* There are two versions of this function:
|
||||
* - secp256k1_ecmult_odd_multiples_table_globalz_windowa which brings its
|
||||
* resulting point set to a single constant Z denominator, stores the X and Y
|
||||
* coordinates as ge_storage points in pre, and stores the global Z in rz.
|
||||
* It only operates on tables sized for WINDOW_A wnaf multiples.
|
||||
* - secp256k1_ecmult_odd_multiples_table_storage_var, which converts its
|
||||
* resulting point set to actually affine points, and stores those in pre.
|
||||
* It operates on tables of any size.
|
||||
* The resulting point set is brought to a single constant Z denominator, stores the X and Y
|
||||
* coordinates as ge_storage points in pre, and stores the global Z in rz.
|
||||
* It only operates on tables sized for WINDOW_A wnaf multiples.
|
||||
*
|
||||
* To compute a*P + b*G, we compute a table for P using the first function,
|
||||
* and for G using the second (which requires an inverse, but it only needs to
|
||||
* happen once).
|
||||
* To compute a*P + b*G, we compute a table for P using this function,
|
||||
* and use the precomputed table in <ecmult_static_pre_g.h> for G.
|
||||
*/
|
||||
static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *pre, secp256k1_fe *globalz, const secp256k1_gej *a) {
|
||||
secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)];
|
||||
@ -142,137 +115,6 @@ static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *p
|
||||
secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr);
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_odd_multiples_table_storage_var(const int n, secp256k1_ge_storage *pre, const secp256k1_gej *a) {
|
||||
secp256k1_gej d;
|
||||
secp256k1_ge d_ge, p_ge;
|
||||
secp256k1_gej pj;
|
||||
secp256k1_fe zi;
|
||||
secp256k1_fe zr;
|
||||
secp256k1_fe dx_over_dz_squared;
|
||||
int i;
|
||||
|
||||
VERIFY_CHECK(!a->infinity);
|
||||
|
||||
secp256k1_gej_double_var(&d, a, NULL);
|
||||
|
||||
/* First, we perform all the additions in an isomorphic curve obtained by multiplying
|
||||
* all `z` coordinates by 1/`d.z`. In these coordinates `d` is affine so we can use
|
||||
* `secp256k1_gej_add_ge_var` to perform the additions. For each addition, we store
|
||||
* the resulting y-coordinate and the z-ratio, since we only have enough memory to
|
||||
* store two field elements. These are sufficient to efficiently undo the isomorphism
|
||||
* and recompute all the `x`s.
|
||||
*/
|
||||
d_ge.x = d.x;
|
||||
d_ge.y = d.y;
|
||||
d_ge.infinity = 0;
|
||||
|
||||
secp256k1_ge_set_gej_zinv(&p_ge, a, &d.z);
|
||||
pj.x = p_ge.x;
|
||||
pj.y = p_ge.y;
|
||||
pj.z = a->z;
|
||||
pj.infinity = 0;
|
||||
|
||||
for (i = 0; i < (n - 1); i++) {
|
||||
secp256k1_fe_normalize_var(&pj.y);
|
||||
secp256k1_fe_to_storage(&pre[i].y, &pj.y);
|
||||
secp256k1_gej_add_ge_var(&pj, &pj, &d_ge, &zr);
|
||||
secp256k1_fe_normalize_var(&zr);
|
||||
secp256k1_fe_to_storage(&pre[i].x, &zr);
|
||||
}
|
||||
|
||||
/* Invert d.z in the same batch, preserving pj.z so we can extract 1/d.z */
|
||||
secp256k1_fe_mul(&zi, &pj.z, &d.z);
|
||||
secp256k1_fe_inv_var(&zi, &zi);
|
||||
|
||||
/* Directly set `pre[n - 1]` to `pj`, saving the inverted z-coordinate so
|
||||
* that we can combine it with the saved z-ratios to compute the other zs
|
||||
* without any more inversions. */
|
||||
secp256k1_ge_set_gej_zinv(&p_ge, &pj, &zi);
|
||||
secp256k1_ge_to_storage(&pre[n - 1], &p_ge);
|
||||
|
||||
/* Compute the actual x-coordinate of D, which will be needed below. */
|
||||
secp256k1_fe_mul(&d.z, &zi, &pj.z); /* d.z = 1/d.z */
|
||||
secp256k1_fe_sqr(&dx_over_dz_squared, &d.z);
|
||||
secp256k1_fe_mul(&dx_over_dz_squared, &dx_over_dz_squared, &d.x);
|
||||
|
||||
/* Going into the second loop, we have set `pre[n-1]` to its final affine
|
||||
* form, but still need to set `pre[i]` for `i` in 0 through `n-2`. We
|
||||
* have `zi = (p.z * d.z)^-1`, where
|
||||
*
|
||||
* `p.z` is the z-coordinate of the point on the isomorphic curve
|
||||
* which was ultimately assigned to `pre[n-1]`.
|
||||
* `d.z` is the multiplier that must be applied to all z-coordinates
|
||||
* to move from our isomorphic curve back to secp256k1; so the
|
||||
* product `p.z * d.z` is the z-coordinate of the secp256k1
|
||||
* point assigned to `pre[n-1]`.
|
||||
*
|
||||
* All subsequent inverse-z-coordinates can be obtained by multiplying this
|
||||
* factor by successive z-ratios, which is much more efficient than directly
|
||||
* computing each one.
|
||||
*
|
||||
* Importantly, these inverse-zs will be coordinates of points on secp256k1,
|
||||
* while our other stored values come from computations on the isomorphic
|
||||
* curve. So in the below loop, we will take care not to actually use `zi`
|
||||
* or any derived values until we're back on secp256k1.
|
||||
*/
|
||||
i = n - 1;
|
||||
while (i > 0) {
|
||||
secp256k1_fe zi2, zi3;
|
||||
const secp256k1_fe *rzr;
|
||||
i--;
|
||||
|
||||
secp256k1_ge_from_storage(&p_ge, &pre[i]);
|
||||
|
||||
/* For each remaining point, we extract the z-ratio from the stored
|
||||
* x-coordinate, compute its z^-1 from that, and compute the full
|
||||
* point from that. */
|
||||
rzr = &p_ge.x;
|
||||
secp256k1_fe_mul(&zi, &zi, rzr);
|
||||
secp256k1_fe_sqr(&zi2, &zi);
|
||||
secp256k1_fe_mul(&zi3, &zi2, &zi);
|
||||
/* To compute the actual x-coordinate, we use the stored z ratio and
|
||||
* y-coordinate, which we obtained from `secp256k1_gej_add_ge_var`
|
||||
* in the loop above, as well as the inverse of the square of its
|
||||
* z-coordinate. We store the latter in the `zi2` variable, which is
|
||||
* computed iteratively starting from the overall Z inverse then
|
||||
* multiplying by each z-ratio in turn.
|
||||
*
|
||||
* Denoting the z-ratio as `rzr`, we observe that it is equal to `h`
|
||||
* from the inside of the above `gej_add_ge_var` call. This satisfies
|
||||
*
|
||||
* rzr = d_x * z^2 - x * d_z^2
|
||||
*
|
||||
* where (`d_x`, `d_z`) are Jacobian coordinates of `D` and `(x, z)`
|
||||
* are Jacobian coordinates of our desired point -- except both are on
|
||||
* the isomorphic curve that we were using when we called `gej_add_ge_var`.
|
||||
* To get back to secp256k1, we must multiply both `z`s by `d_z`, or
|
||||
* equivalently divide both `x`s by `d_z^2`. Our equation then becomes
|
||||
*
|
||||
* rzr = d_x * z^2 / d_z^2 - x
|
||||
*
|
||||
* (The left-hand-side, being a ratio of z-coordinates, is unaffected
|
||||
* by the isomorphism.)
|
||||
*
|
||||
* Rearranging to solve for `x`, we have
|
||||
*
|
||||
* x = d_x * z^2 / d_z^2 - rzr
|
||||
*
|
||||
* But what we actually want is the affine coordinate `X = x/z^2`,
|
||||
* which will satisfy
|
||||
*
|
||||
* X = d_x / d_z^2 - rzr / z^2
|
||||
* = dx_over_dz_squared - rzr * zi2
|
||||
*/
|
||||
secp256k1_fe_mul(&p_ge.x, rzr, &zi2);
|
||||
secp256k1_fe_negate(&p_ge.x, &p_ge.x, 1);
|
||||
secp256k1_fe_add(&p_ge.x, &dx_over_dz_squared);
|
||||
/* y is stored_y/z^3, as we expect */
|
||||
secp256k1_fe_mul(&p_ge.y, &p_ge.y, &zi3);
|
||||
/* Store */
|
||||
secp256k1_ge_to_storage(&pre[i], &p_ge);
|
||||
}
|
||||
}
|
||||
|
||||
/** The following two macro retrieves a particular odd multiple from a table
|
||||
* of precomputed multiples. */
|
||||
#define ECMULT_TABLE_GET_GE(r,pre,n,w) do { \
|
||||
@ -299,74 +141,6 @@ static void secp256k1_ecmult_odd_multiples_table_storage_var(const int n, secp25
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static const size_t SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE =
|
||||
ROUND_TO_ALIGN(sizeof((*((secp256k1_ecmult_context*) NULL)->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G))
|
||||
+ ROUND_TO_ALIGN(sizeof((*((secp256k1_ecmult_context*) NULL)->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G))
|
||||
;
|
||||
|
||||
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) {
|
||||
ctx->pre_g = NULL;
|
||||
ctx->pre_g_128 = NULL;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void **prealloc) {
|
||||
secp256k1_gej gj;
|
||||
void* const base = *prealloc;
|
||||
size_t const prealloc_size = SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;
|
||||
|
||||
if (ctx->pre_g != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* get the generator */
|
||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
|
||||
|
||||
{
|
||||
size_t size = sizeof((*ctx->pre_g)[0]) * ((size_t)ECMULT_TABLE_SIZE(WINDOW_G));
|
||||
/* check for overflow */
|
||||
VERIFY_CHECK(size / sizeof((*ctx->pre_g)[0]) == ((size_t)ECMULT_TABLE_SIZE(WINDOW_G)));
|
||||
ctx->pre_g = (secp256k1_ge_storage (*)[])manual_alloc(prealloc, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G), base, prealloc_size);
|
||||
}
|
||||
|
||||
/* precompute the tables with odd multiples */
|
||||
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj);
|
||||
|
||||
{
|
||||
secp256k1_gej g_128j;
|
||||
int i;
|
||||
|
||||
size_t size = sizeof((*ctx->pre_g_128)[0]) * ((size_t) ECMULT_TABLE_SIZE(WINDOW_G));
|
||||
/* check for overflow */
|
||||
VERIFY_CHECK(size / sizeof((*ctx->pre_g_128)[0]) == ((size_t)ECMULT_TABLE_SIZE(WINDOW_G)));
|
||||
ctx->pre_g_128 = (secp256k1_ge_storage (*)[])manual_alloc(prealloc, sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G), base, prealloc_size);
|
||||
|
||||
/* calculate 2^128*generator */
|
||||
g_128j = gj;
|
||||
for (i = 0; i < 128; i++) {
|
||||
secp256k1_gej_double_var(&g_128j, &g_128j, NULL);
|
||||
}
|
||||
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j);
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_context_finalize_memcpy(secp256k1_ecmult_context *dst, const secp256k1_ecmult_context *src) {
|
||||
if (src->pre_g != NULL) {
|
||||
/* We cast to void* first to suppress a -Wcast-align warning. */
|
||||
dst->pre_g = (secp256k1_ge_storage (*)[])(void*)((unsigned char*)dst + ((unsigned char*)(src->pre_g) - (unsigned char*)src));
|
||||
}
|
||||
if (src->pre_g_128 != NULL) {
|
||||
dst->pre_g_128 = (secp256k1_ge_storage (*)[])(void*)((unsigned char*)dst + ((unsigned char*)(src->pre_g_128) - (unsigned char*)src));
|
||||
}
|
||||
}
|
||||
|
||||
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx) {
|
||||
return ctx->pre_g != NULL;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx) {
|
||||
secp256k1_ecmult_context_init(ctx);
|
||||
}
|
||||
|
||||
/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits),
|
||||
* with the following guarantees:
|
||||
* - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1)
|
||||
@ -443,10 +217,10 @@ struct secp256k1_strauss_state {
|
||||
struct secp256k1_strauss_point_state* ps;
|
||||
};
|
||||
|
||||
static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, const struct secp256k1_strauss_state *state, secp256k1_gej *r, size_t num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
|
||||
static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *state, secp256k1_gej *r, size_t num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
|
||||
secp256k1_ge tmpa;
|
||||
secp256k1_fe Z;
|
||||
/* Splitted G factors. */
|
||||
/* Split G factors. */
|
||||
secp256k1_scalar ng_1, ng_128;
|
||||
int wnaf_ng_1[129];
|
||||
int bits_ng_1 = 0;
|
||||
@ -544,11 +318,11 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c
|
||||
}
|
||||
}
|
||||
if (i < bits_ng_1 && (n = wnaf_ng_1[i])) {
|
||||
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G);
|
||||
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, secp256k1_pre_g, n, WINDOW_G);
|
||||
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
|
||||
}
|
||||
if (i < bits_ng_128 && (n = wnaf_ng_128[i])) {
|
||||
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g_128, n, WINDOW_G);
|
||||
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, secp256k1_pre_g_128, n, WINDOW_G);
|
||||
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
|
||||
}
|
||||
}
|
||||
@ -558,7 +332,7 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
|
||||
static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
|
||||
secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)];
|
||||
secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)];
|
||||
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
|
||||
@ -571,7 +345,7 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej
|
||||
state.pre_a = pre_a;
|
||||
state.pre_a_lam = pre_a_lam;
|
||||
state.ps = ps;
|
||||
secp256k1_ecmult_strauss_wnaf(ctx, &state, r, 1, a, na, ng);
|
||||
secp256k1_ecmult_strauss_wnaf(&state, r, 1, a, na, ng);
|
||||
}
|
||||
|
||||
static size_t secp256k1_strauss_scratch_size(size_t n_points) {
|
||||
@ -579,7 +353,7 @@ static size_t secp256k1_strauss_scratch_size(size_t n_points) {
|
||||
return n_points*point_size;
|
||||
}
|
||||
|
||||
static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
|
||||
static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
|
||||
secp256k1_gej* points;
|
||||
secp256k1_scalar* scalars;
|
||||
struct secp256k1_strauss_state state;
|
||||
@ -591,6 +365,9 @@ static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callba
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We allocate STRAUSS_SCRATCH_OBJECTS objects on the scratch space. If these
|
||||
* allocations change, make sure to update the STRAUSS_SCRATCH_OBJECTS
|
||||
* constant and strauss_scratch_size accordingly. */
|
||||
points = (secp256k1_gej*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(secp256k1_gej));
|
||||
scalars = (secp256k1_scalar*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(secp256k1_scalar));
|
||||
state.prej = (secp256k1_gej*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_gej));
|
||||
@ -612,14 +389,14 @@ static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callba
|
||||
}
|
||||
secp256k1_gej_set_ge(&points[i], &point);
|
||||
}
|
||||
secp256k1_ecmult_strauss_wnaf(ctx, &state, r, n_points, points, scalars, inp_g_sc);
|
||||
secp256k1_ecmult_strauss_wnaf(&state, r, n_points, points, scalars, inp_g_sc);
|
||||
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Wrapper for secp256k1_ecmult_multi_func interface */
|
||||
static int secp256k1_ecmult_strauss_batch_single(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *actx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
|
||||
return secp256k1_ecmult_strauss_batch(error_callback, actx, scratch, r, inp_g_sc, cb, cbdata, n, 0);
|
||||
static int secp256k1_ecmult_strauss_batch_single(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
|
||||
return secp256k1_ecmult_strauss_batch(error_callback, scratch, r, inp_g_sc, cb, cbdata, n, 0);
|
||||
}
|
||||
|
||||
static size_t secp256k1_strauss_max_points(const secp256k1_callback* error_callback, secp256k1_scratch *scratch) {
|
||||
@ -866,7 +643,7 @@ static size_t secp256k1_pippenger_scratch_size(size_t n_points, int bucket_windo
|
||||
return (sizeof(secp256k1_gej) << bucket_window) + sizeof(struct secp256k1_pippenger_state) + entries * entry_size;
|
||||
}
|
||||
|
||||
static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
|
||||
static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
|
||||
const size_t scratch_checkpoint = secp256k1_scratch_checkpoint(error_callback, scratch);
|
||||
/* Use 2(n+1) with the endomorphism, when calculating batch
|
||||
* sizes. The reason for +1 is that we add the G scalar to the list of
|
||||
@ -881,13 +658,16 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call
|
||||
int i, j;
|
||||
int bucket_window;
|
||||
|
||||
(void)ctx;
|
||||
secp256k1_gej_set_infinity(r);
|
||||
if (inp_g_sc == NULL && n_points == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
bucket_window = secp256k1_pippenger_bucket_window(n_points);
|
||||
|
||||
/* We allocate PIPPENGER_SCRATCH_OBJECTS objects on the scratch space. If
|
||||
* these allocations change, make sure to update the
|
||||
* PIPPENGER_SCRATCH_OBJECTS constant and pippenger_scratch_size
|
||||
* accordingly. */
|
||||
points = (secp256k1_ge *) secp256k1_scratch_alloc(error_callback, scratch, entries * sizeof(*points));
|
||||
scalars = (secp256k1_scalar *) secp256k1_scratch_alloc(error_callback, scratch, entries * sizeof(*scalars));
|
||||
state_space = (struct secp256k1_pippenger_state *) secp256k1_scratch_alloc(error_callback, scratch, sizeof(*state_space));
|
||||
@ -895,7 +675,6 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call
|
||||
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
|
||||
return 0;
|
||||
}
|
||||
|
||||
state_space->ps = (struct secp256k1_pippenger_point_state *) secp256k1_scratch_alloc(error_callback, scratch, entries * sizeof(*state_space->ps));
|
||||
state_space->wnaf_na = (int *) secp256k1_scratch_alloc(error_callback, scratch, entries*(WNAF_SIZE(bucket_window+1)) * sizeof(int));
|
||||
buckets = (secp256k1_gej *) secp256k1_scratch_alloc(error_callback, scratch, (1<<bucket_window) * sizeof(*buckets));
|
||||
@ -941,8 +720,8 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call
|
||||
}
|
||||
|
||||
/* Wrapper for secp256k1_ecmult_multi_func interface */
|
||||
static int secp256k1_ecmult_pippenger_batch_single(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *actx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
|
||||
return secp256k1_ecmult_pippenger_batch(error_callback, actx, scratch, r, inp_g_sc, cb, cbdata, n, 0);
|
||||
static int secp256k1_ecmult_pippenger_batch_single(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
|
||||
return secp256k1_ecmult_pippenger_batch(error_callback, scratch, r, inp_g_sc, cb, cbdata, n, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -986,7 +765,7 @@ static size_t secp256k1_pippenger_max_points(const secp256k1_callback* error_cal
|
||||
|
||||
/* Computes ecmult_multi by simply multiplying and adding each point. Does not
|
||||
* require a scratch space */
|
||||
static int secp256k1_ecmult_multi_simple_var(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points) {
|
||||
static int secp256k1_ecmult_multi_simple_var(secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points) {
|
||||
size_t point_idx;
|
||||
secp256k1_scalar szero;
|
||||
secp256k1_gej tmpj;
|
||||
@ -995,7 +774,7 @@ static int secp256k1_ecmult_multi_simple_var(const secp256k1_ecmult_context *ctx
|
||||
secp256k1_gej_set_infinity(r);
|
||||
secp256k1_gej_set_infinity(&tmpj);
|
||||
/* r = inp_g_sc*G */
|
||||
secp256k1_ecmult(ctx, r, &tmpj, &szero, inp_g_sc);
|
||||
secp256k1_ecmult(r, &tmpj, &szero, inp_g_sc);
|
||||
for (point_idx = 0; point_idx < n_points; point_idx++) {
|
||||
secp256k1_ge point;
|
||||
secp256k1_gej pointj;
|
||||
@ -1005,7 +784,7 @@ static int secp256k1_ecmult_multi_simple_var(const secp256k1_ecmult_context *ctx
|
||||
}
|
||||
/* r += scalar*point */
|
||||
secp256k1_gej_set_ge(&pointj, &point);
|
||||
secp256k1_ecmult(ctx, &tmpj, &pointj, &scalar, NULL);
|
||||
secp256k1_ecmult(&tmpj, &pointj, &scalar, NULL);
|
||||
secp256k1_gej_add_var(r, r, &tmpj, NULL);
|
||||
}
|
||||
return 1;
|
||||
@ -1031,11 +810,11 @@ static int secp256k1_ecmult_multi_batch_size_helper(size_t *n_batches, size_t *n
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef int (*secp256k1_ecmult_multi_func)(const secp256k1_callback* error_callback, const secp256k1_ecmult_context*, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t);
|
||||
static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
|
||||
typedef int (*secp256k1_ecmult_multi_func)(const secp256k1_callback* error_callback, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t);
|
||||
static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
|
||||
size_t i;
|
||||
|
||||
int (*f)(const secp256k1_callback* error_callback, const secp256k1_ecmult_context*, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t, size_t);
|
||||
int (*f)(const secp256k1_callback* error_callback, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t, size_t);
|
||||
size_t n_batches;
|
||||
size_t n_batch_points;
|
||||
|
||||
@ -1045,11 +824,11 @@ static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback,
|
||||
} else if (n == 0) {
|
||||
secp256k1_scalar szero;
|
||||
secp256k1_scalar_set_int(&szero, 0);
|
||||
secp256k1_ecmult(ctx, r, r, &szero, inp_g_sc);
|
||||
secp256k1_ecmult(r, r, &szero, inp_g_sc);
|
||||
return 1;
|
||||
}
|
||||
if (scratch == NULL) {
|
||||
return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n);
|
||||
return secp256k1_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n);
|
||||
}
|
||||
|
||||
/* Compute the batch sizes for Pippenger's algorithm given a scratch space. If it's greater than
|
||||
@ -1057,13 +836,13 @@ static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback,
|
||||
* As a first step check if there's enough space for Pippenger's algo (which requires less space
|
||||
* than Strauss' algo) and if not, use the simple algorithm. */
|
||||
if (!secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, secp256k1_pippenger_max_points(error_callback, scratch), n)) {
|
||||
return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n);
|
||||
return secp256k1_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n);
|
||||
}
|
||||
if (n_batch_points >= ECMULT_PIPPENGER_THRESHOLD) {
|
||||
f = secp256k1_ecmult_pippenger_batch;
|
||||
} else {
|
||||
if (!secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, secp256k1_strauss_max_points(error_callback, scratch), n)) {
|
||||
return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n);
|
||||
return secp256k1_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n);
|
||||
}
|
||||
f = secp256k1_ecmult_strauss_batch;
|
||||
}
|
||||
@ -1071,7 +850,7 @@ static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback,
|
||||
size_t nbp = n < n_batch_points ? n : n_batch_points;
|
||||
size_t offset = n_batch_points*i;
|
||||
secp256k1_gej tmp;
|
||||
if (!f(error_callback, ctx, scratch, &tmp, i == 0 ? inp_g_sc : NULL, cb, cbdata, nbp, offset)) {
|
||||
if (!f(error_callback, scratch, &tmp, i == 0 ? inp_g_sc : NULL, cb, cbdata, nbp, offset)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_gej_add_var(r, r, &tmp, NULL);
|
||||
|
16611
src/ecmult_static_pre_g.h
generated
Normal file
16611
src/ecmult_static_pre_g.h
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -14,8 +14,8 @@
|
||||
* - Each field element can be normalized or not.
|
||||
* - Each field element has a magnitude, which represents how far away
|
||||
* its representation is away from normalization. Normalized elements
|
||||
* always have a magnitude of 1, but a magnitude of 1 doesn't imply
|
||||
* normality.
|
||||
* always have a magnitude of 0 or 1, but a magnitude of 1 doesn't
|
||||
* imply normality.
|
||||
*/
|
||||
|
||||
#if defined HAVE_CONFIG_H
|
||||
@ -50,7 +50,9 @@ static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r);
|
||||
* without constant-time guarantee. */
|
||||
static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r);
|
||||
|
||||
/** Set a field element equal to a small integer. Resulting field element is normalized. */
|
||||
/** Set a field element equal to a small (not greater than 0x7FFF), non-negative integer.
|
||||
* Resulting field element is normalized; it has magnitude 0 if a == 0, and magnitude 1 otherwise.
|
||||
*/
|
||||
static void secp256k1_fe_set_int(secp256k1_fe *r, int a);
|
||||
|
||||
/** Sets a field element equal to zero, initializing all fields. */
|
||||
|
@ -264,10 +264,11 @@ static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r) {
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) {
|
||||
VERIFY_CHECK(0 <= a && a <= 0x7FFF);
|
||||
r->n[0] = a;
|
||||
r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0;
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->magnitude = (a != 0);
|
||||
r->normalized = 1;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
@ -1162,6 +1163,7 @@ static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const se
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 1;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -227,10 +227,11 @@ static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r) {
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) {
|
||||
VERIFY_CHECK(0 <= a && a <= 0x7FFF);
|
||||
r->n[0] = a;
|
||||
r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->magnitude = (a != 0);
|
||||
r->normalized = 1;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
@ -496,6 +497,7 @@ static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const se
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 1;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -49,14 +49,14 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t
|
||||
c = (uint128_t)a4 * b[4];
|
||||
VERIFY_BITS(c, 112);
|
||||
/* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
d += (c & M) * R; c >>= 52;
|
||||
d += (uint128_t)R * (uint64_t)c; c >>= 64;
|
||||
VERIFY_BITS(d, 115);
|
||||
VERIFY_BITS(c, 60);
|
||||
/* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
VERIFY_BITS(c, 48);
|
||||
/* [(c<<12) 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
t3 = d & M; d >>= 52;
|
||||
VERIFY_BITS(t3, 52);
|
||||
VERIFY_BITS(d, 63);
|
||||
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
/* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
|
||||
d += (uint128_t)a0 * b[4]
|
||||
+ (uint128_t)a1 * b[3]
|
||||
@ -64,8 +64,8 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t
|
||||
+ (uint128_t)a3 * b[1]
|
||||
+ (uint128_t)a4 * b[0];
|
||||
VERIFY_BITS(d, 115);
|
||||
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
d += c * R;
|
||||
/* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
d += (uint128_t)(R << 12) * (uint64_t)c;
|
||||
VERIFY_BITS(d, 116);
|
||||
/* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
t4 = d & M; d >>= 52;
|
||||
@ -129,17 +129,16 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t
|
||||
+ (uint128_t)a4 * b[3];
|
||||
VERIFY_BITS(d, 114);
|
||||
/* [d 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
c += (d & M) * R; d >>= 52;
|
||||
c += (uint128_t)R * (uint64_t)d; d >>= 64;
|
||||
VERIFY_BITS(c, 115);
|
||||
VERIFY_BITS(d, 62);
|
||||
/* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
VERIFY_BITS(d, 50);
|
||||
/* [(d<<12) 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
|
||||
/* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
r[2] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[2], 52);
|
||||
VERIFY_BITS(c, 63);
|
||||
/* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
c += d * R + t3;
|
||||
/* [(d<<12) 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
c += (uint128_t)(R << 12) * (uint64_t)d + t3;
|
||||
VERIFY_BITS(c, 100);
|
||||
/* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
r[3] = c & M; c >>= 52;
|
||||
@ -178,22 +177,22 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t
|
||||
c = (uint128_t)a4 * a4;
|
||||
VERIFY_BITS(c, 112);
|
||||
/* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
d += (c & M) * R; c >>= 52;
|
||||
d += (uint128_t)R * (uint64_t)c; c >>= 64;
|
||||
VERIFY_BITS(d, 115);
|
||||
VERIFY_BITS(c, 60);
|
||||
/* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
VERIFY_BITS(c, 48);
|
||||
/* [(c<<12) 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
t3 = d & M; d >>= 52;
|
||||
VERIFY_BITS(t3, 52);
|
||||
VERIFY_BITS(d, 63);
|
||||
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
/* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
|
||||
a4 *= 2;
|
||||
d += (uint128_t)a0 * a4
|
||||
+ (uint128_t)(a1*2) * a3
|
||||
+ (uint128_t)a2 * a2;
|
||||
VERIFY_BITS(d, 115);
|
||||
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
d += c * R;
|
||||
/* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
d += (uint128_t)(R << 12) * (uint64_t)c;
|
||||
VERIFY_BITS(d, 116);
|
||||
/* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
t4 = d & M; d >>= 52;
|
||||
@ -252,16 +251,16 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t
|
||||
d += (uint128_t)a3 * a4;
|
||||
VERIFY_BITS(d, 114);
|
||||
/* [d 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
c += (d & M) * R; d >>= 52;
|
||||
c += (uint128_t)R * (uint64_t)d; d >>= 64;
|
||||
VERIFY_BITS(c, 115);
|
||||
VERIFY_BITS(d, 62);
|
||||
/* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
VERIFY_BITS(d, 50);
|
||||
/* [(d<<12) 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
r[2] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[2], 52);
|
||||
VERIFY_BITS(c, 63);
|
||||
/* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
/* [(d<<12) 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
|
||||
c += d * R + t3;
|
||||
c += (uint128_t)(R << 12) * (uint64_t)d + t3;
|
||||
VERIFY_BITS(c, 100);
|
||||
/* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
r[3] = c & M; c >>= 52;
|
||||
|
@ -1,95 +0,0 @@
|
||||
/***********************************************************************
|
||||
* Copyright (c) 2013, 2014, 2015 Thomas Daede, Cory Fields *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
||||
***********************************************************************/
|
||||
|
||||
/* Autotools creates libsecp256k1-config.h, of which ECMULT_GEN_PREC_BITS is needed.
|
||||
ifndef guard so downstream users can define their own if they do not use autotools. */
|
||||
#if !defined(ECMULT_GEN_PREC_BITS)
|
||||
#include "libsecp256k1-config.h"
|
||||
#endif
|
||||
|
||||
/* We can't require the precomputed tables when creating them. */
|
||||
#undef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
|
||||
/* In principle we could use ASM, but this yields only a minor speedup in
|
||||
build time and it's very complicated. In particular when cross-compiling, we'd
|
||||
need to build the ASM for the build and the host machine. */
|
||||
#undef USE_EXTERNAL_ASM
|
||||
#undef USE_ASM_X86_64
|
||||
|
||||
#include "../include/secp256k1.h"
|
||||
#include "assumptions.h"
|
||||
#include "util.h"
|
||||
#include "field_impl.h"
|
||||
#include "scalar_impl.h"
|
||||
#include "group_impl.h"
|
||||
#include "ecmult_gen_impl.h"
|
||||
|
||||
static void default_error_callback_fn(const char* str, void* data) {
|
||||
(void)data;
|
||||
fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str);
|
||||
abort();
|
||||
}
|
||||
|
||||
static const secp256k1_callback default_error_callback = {
|
||||
default_error_callback_fn,
|
||||
NULL
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
secp256k1_ecmult_gen_context ctx;
|
||||
void *prealloc, *base;
|
||||
int inner;
|
||||
int outer;
|
||||
FILE* fp;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
fp = fopen("src/ecmult_static_context.h","w");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "Could not open src/ecmult_static_context.h for writing!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(fp, "#ifndef SECP256K1_ECMULT_STATIC_CONTEXT_H\n");
|
||||
fprintf(fp, "#define SECP256K1_ECMULT_STATIC_CONTEXT_H\n");
|
||||
fprintf(fp, "#include \"src/group.h\"\n");
|
||||
fprintf(fp, "#define SC SECP256K1_GE_STORAGE_CONST\n");
|
||||
fprintf(fp, "#if ECMULT_GEN_PREC_N != %d || ECMULT_GEN_PREC_G != %d\n", ECMULT_GEN_PREC_N, ECMULT_GEN_PREC_G);
|
||||
fprintf(fp, " #error configuration mismatch, invalid ECMULT_GEN_PREC_N, ECMULT_GEN_PREC_G. Try deleting ecmult_static_context.h before the build.\n");
|
||||
fprintf(fp, "#endif\n");
|
||||
fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_static_context[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G] = {\n");
|
||||
|
||||
base = checked_malloc(&default_error_callback, SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE);
|
||||
prealloc = base;
|
||||
secp256k1_ecmult_gen_context_init(&ctx);
|
||||
secp256k1_ecmult_gen_context_build(&ctx, &prealloc);
|
||||
for(outer = 0; outer != ECMULT_GEN_PREC_N; outer++) {
|
||||
fprintf(fp,"{\n");
|
||||
for(inner = 0; inner != ECMULT_GEN_PREC_G; inner++) {
|
||||
fprintf(fp," SC(%uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu)", SECP256K1_GE_STORAGE_CONST_GET((*ctx.prec)[outer][inner]));
|
||||
if (inner != ECMULT_GEN_PREC_G - 1) {
|
||||
fprintf(fp,",\n");
|
||||
} else {
|
||||
fprintf(fp,"\n");
|
||||
}
|
||||
}
|
||||
if (outer != ECMULT_GEN_PREC_N - 1) {
|
||||
fprintf(fp,"},\n");
|
||||
} else {
|
||||
fprintf(fp,"}\n");
|
||||
}
|
||||
}
|
||||
fprintf(fp,"};\n");
|
||||
secp256k1_ecmult_gen_context_clear(&ctx);
|
||||
free(base);
|
||||
|
||||
fprintf(fp, "#undef SC\n");
|
||||
fprintf(fp, "#endif\n");
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
83
src/gen_ecmult_gen_static_prec_table.c
Normal file
83
src/gen_ecmult_gen_static_prec_table.c
Normal file
@ -0,0 +1,83 @@
|
||||
/***********************************************************************
|
||||
* Copyright (c) 2013, 2014, 2015 Thomas Daede, Cory Fields *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
||||
***********************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../include/secp256k1.h"
|
||||
#include "assumptions.h"
|
||||
#include "util.h"
|
||||
#include "group.h"
|
||||
#include "ecmult_gen.h"
|
||||
#include "ecmult_gen_prec_impl.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const char outfile[] = "src/ecmult_gen_static_prec_table.h";
|
||||
FILE* fp;
|
||||
int bits;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
fp = fopen(outfile, "w");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "Could not open %s for writing!\n", outfile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(fp, "/* This file was automatically generated by gen_ecmult_gen_static_prec_table. */\n");
|
||||
fprintf(fp, "/* See ecmult_gen_impl.h for details about the contents of this file. */\n");
|
||||
fprintf(fp, "#ifndef SECP256K1_ECMULT_GEN_STATIC_PREC_TABLE_H\n");
|
||||
fprintf(fp, "#define SECP256K1_ECMULT_GEN_STATIC_PREC_TABLE_H\n");
|
||||
|
||||
fprintf(fp, "#include \"group.h\"\n");
|
||||
|
||||
fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) "
|
||||
"SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,"
|
||||
"0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n");
|
||||
|
||||
fprintf(fp, "#ifdef EXHAUSTIVE_TEST_ORDER\n");
|
||||
fprintf(fp, "static secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)];\n");
|
||||
fprintf(fp, "#else\n");
|
||||
fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)] = {\n");
|
||||
|
||||
for (bits = 2; bits <= 8; bits *= 2) {
|
||||
int g = ECMULT_GEN_PREC_G(bits);
|
||||
int n = ECMULT_GEN_PREC_N(bits);
|
||||
int inner, outer;
|
||||
|
||||
secp256k1_ge_storage* table = checked_malloc(&default_error_callback, n * g * sizeof(secp256k1_ge_storage));
|
||||
secp256k1_ecmult_gen_create_prec_table(table, &secp256k1_ge_const_g, bits);
|
||||
|
||||
fprintf(fp, "#if ECMULT_GEN_PREC_BITS == %d\n", bits);
|
||||
for(outer = 0; outer != n; outer++) {
|
||||
fprintf(fp,"{");
|
||||
for(inner = 0; inner != g; inner++) {
|
||||
fprintf(fp, "S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32
|
||||
",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")",
|
||||
SECP256K1_GE_STORAGE_CONST_GET(table[outer * g + inner]));
|
||||
if (inner != g - 1) {
|
||||
fprintf(fp,",\n");
|
||||
}
|
||||
}
|
||||
if (outer != n - 1) {
|
||||
fprintf(fp,"},\n");
|
||||
} else {
|
||||
fprintf(fp,"}\n");
|
||||
}
|
||||
}
|
||||
fprintf(fp, "#endif\n");
|
||||
free(table);
|
||||
}
|
||||
|
||||
fprintf(fp, "};\n");
|
||||
fprintf(fp, "#endif /* EXHAUSTIVE_TEST_ORDER */\n");
|
||||
fprintf(fp, "#undef SC\n");
|
||||
fprintf(fp, "#endif /* SECP256K1_ECMULT_GEN_STATIC_PREC_TABLE_H */\n");
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
131
src/gen_ecmult_static_pre_g.c
Normal file
131
src/gen_ecmult_static_pre_g.c
Normal file
@ -0,0 +1,131 @@
|
||||
/*****************************************************************************************************
|
||||
* Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or https://www.opensource.org/licenses/mit-license.php. *
|
||||
*****************************************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Autotools creates libsecp256k1-config.h, of which ECMULT_WINDOW_SIZE is needed.
|
||||
ifndef guard so downstream users can define their own if they do not use autotools. */
|
||||
#if !defined(ECMULT_WINDOW_SIZE)
|
||||
#include "libsecp256k1-config.h"
|
||||
#endif
|
||||
|
||||
#include "../include/secp256k1.h"
|
||||
#include "assumptions.h"
|
||||
#include "util.h"
|
||||
#include "field_impl.h"
|
||||
#include "group_impl.h"
|
||||
#include "ecmult.h"
|
||||
|
||||
void print_table(FILE *fp, const char *name, int window_g, const secp256k1_gej *gen, int with_conditionals) {
|
||||
static secp256k1_gej gj;
|
||||
static secp256k1_ge ge, dgen;
|
||||
static secp256k1_ge_storage ges;
|
||||
int j;
|
||||
int i;
|
||||
|
||||
gj = *gen;
|
||||
secp256k1_ge_set_gej_var(&ge, &gj);
|
||||
secp256k1_ge_to_storage(&ges, &ge);
|
||||
|
||||
fprintf(fp, "static const secp256k1_ge_storage %s[ECMULT_TABLE_SIZE(WINDOW_G)] = {\n", name);
|
||||
fprintf(fp, " S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32
|
||||
",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n",
|
||||
SECP256K1_GE_STORAGE_CONST_GET(ges));
|
||||
|
||||
secp256k1_gej_double_var(&gj, gen, NULL);
|
||||
secp256k1_ge_set_gej_var(&dgen, &gj);
|
||||
|
||||
j = 1;
|
||||
for(i = 3; i <= window_g; ++i) {
|
||||
if (with_conditionals) {
|
||||
fprintf(fp, "#if ECMULT_TABLE_SIZE(WINDOW_G) > %ld\n", ECMULT_TABLE_SIZE(i-1));
|
||||
}
|
||||
for(;j < ECMULT_TABLE_SIZE(i); ++j) {
|
||||
secp256k1_gej_set_ge(&gj, &ge);
|
||||
secp256k1_gej_add_ge_var(&gj, &gj, &dgen, NULL);
|
||||
secp256k1_ge_set_gej_var(&ge, &gj);
|
||||
secp256k1_ge_to_storage(&ges, &ge);
|
||||
|
||||
fprintf(fp, ",S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32
|
||||
",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n",
|
||||
SECP256K1_GE_STORAGE_CONST_GET(ges));
|
||||
}
|
||||
if (with_conditionals) {
|
||||
fprintf(fp, "#endif\n");
|
||||
}
|
||||
}
|
||||
fprintf(fp, "};\n");
|
||||
}
|
||||
|
||||
void print_two_tables(FILE *fp, int window_g, const secp256k1_ge *g, int with_conditionals) {
|
||||
secp256k1_gej gj;
|
||||
int i;
|
||||
|
||||
secp256k1_gej_set_ge(&gj, g);
|
||||
print_table(fp, "secp256k1_pre_g", window_g, &gj, with_conditionals);
|
||||
for (i = 0; i < 128; ++i) {
|
||||
secp256k1_gej_double_var(&gj, &gj, NULL);
|
||||
}
|
||||
print_table(fp, "secp256k1_pre_g_128", window_g, &gj, with_conditionals);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
const secp256k1_ge g = SECP256K1_G;
|
||||
const secp256k1_ge g_13 = SECP256K1_G_ORDER_13;
|
||||
const secp256k1_ge g_199 = SECP256K1_G_ORDER_199;
|
||||
const int window_g_13 = 4;
|
||||
const int window_g_199 = 8;
|
||||
FILE* fp;
|
||||
|
||||
fp = fopen("src/ecmult_static_pre_g.h","w");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "Could not open src/ecmult_static_pre_g.h for writing!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(fp, "/* This file was automatically generated by gen_ecmult_static_pre_g. */\n");
|
||||
fprintf(fp, "/* This file contains an array secp256k1_pre_g with odd multiples of the base point G and\n");
|
||||
fprintf(fp, " * an array secp256k1_pre_g_128 with odd multiples of 2^128*G for accelerating the computation of a*P + b*G.\n");
|
||||
fprintf(fp, " */\n");
|
||||
fprintf(fp, "#ifndef SECP256K1_ECMULT_STATIC_PRE_G_H\n");
|
||||
fprintf(fp, "#define SECP256K1_ECMULT_STATIC_PRE_G_H\n");
|
||||
fprintf(fp, "#include \"group.h\"\n");
|
||||
fprintf(fp, "#ifdef S\n");
|
||||
fprintf(fp, " #error macro identifier S already in use.\n");
|
||||
fprintf(fp, "#endif\n");
|
||||
fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) "
|
||||
"SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,"
|
||||
"0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n");
|
||||
fprintf(fp, "#if ECMULT_TABLE_SIZE(ECMULT_WINDOW_SIZE) > %ld\n", ECMULT_TABLE_SIZE(ECMULT_WINDOW_SIZE));
|
||||
fprintf(fp, " #error configuration mismatch, invalid ECMULT_WINDOW_SIZE. Try deleting ecmult_static_pre_g.h before the build.\n");
|
||||
fprintf(fp, "#endif\n");
|
||||
fprintf(fp, "#if defined(EXHAUSTIVE_TEST_ORDER)\n");
|
||||
fprintf(fp, "#if EXHAUSTIVE_TEST_ORDER == 13\n");
|
||||
fprintf(fp, "#define WINDOW_G %d\n", window_g_13);
|
||||
|
||||
print_two_tables(fp, window_g_13, &g_13, 0);
|
||||
|
||||
fprintf(fp, "#elif EXHAUSTIVE_TEST_ORDER == 199\n");
|
||||
fprintf(fp, "#define WINDOW_G %d\n", window_g_199);
|
||||
|
||||
print_two_tables(fp, window_g_199, &g_199, 0);
|
||||
|
||||
fprintf(fp, "#else\n");
|
||||
fprintf(fp, " #error No known generator for the specified exhaustive test group order.\n");
|
||||
fprintf(fp, "#endif\n");
|
||||
fprintf(fp, "#else /* !defined(EXHAUSTIVE_TEST_ORDER) */\n");
|
||||
fprintf(fp, "#define WINDOW_G ECMULT_WINDOW_SIZE\n");
|
||||
|
||||
print_two_tables(fp, ECMULT_WINDOW_SIZE, &g, 1);
|
||||
|
||||
fprintf(fp, "#endif\n");
|
||||
fprintf(fp, "#undef S\n");
|
||||
fprintf(fp, "#endif\n");
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
@ -10,6 +10,27 @@
|
||||
#include "field.h"
|
||||
#include "group.h"
|
||||
|
||||
#define SECP256K1_G_ORDER_13 SECP256K1_GE_CONST(\
|
||||
0xc3459c3d, 0x35326167, 0xcd86cce8, 0x07a2417f,\
|
||||
0x5b8bd567, 0xde8538ee, 0x0d507b0c, 0xd128f5bb,\
|
||||
0x8e467fec, 0xcd30000a, 0x6cc1184e, 0x25d382c2,\
|
||||
0xa2f4494e, 0x2fbe9abc, 0x8b64abac, 0xd005fb24\
|
||||
)
|
||||
#define SECP256K1_G_ORDER_199 SECP256K1_GE_CONST(\
|
||||
0x226e653f, 0xc8df7744, 0x9bacbf12, 0x7d1dcbf9,\
|
||||
0x87f05b2a, 0xe7edbd28, 0x1f564575, 0xc48dcf18,\
|
||||
0xa13872c2, 0xe933bb17, 0x5d9ffd5b, 0xb5b6e10c,\
|
||||
0x57fe3c00, 0xbaaaa15a, 0xe003ec3e, 0x9c269bae\
|
||||
)
|
||||
/** Generator for secp256k1, value 'g' defined in
|
||||
* "Standards for Efficient Cryptography" (SEC2) 2.7.1.
|
||||
*/
|
||||
#define SECP256K1_G SECP256K1_GE_CONST(\
|
||||
0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL,\
|
||||
0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL,\
|
||||
0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL,\
|
||||
0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL\
|
||||
)
|
||||
/* These exhaustive group test orders and generators are chosen such that:
|
||||
* - The field size is equal to that of secp256k1, so field code is the same.
|
||||
* - The curve equation is of the form y^2=x^3+B for some constant B.
|
||||
@ -21,23 +42,15 @@
|
||||
*/
|
||||
#if defined(EXHAUSTIVE_TEST_ORDER)
|
||||
# if EXHAUSTIVE_TEST_ORDER == 13
|
||||
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(
|
||||
0xc3459c3d, 0x35326167, 0xcd86cce8, 0x07a2417f,
|
||||
0x5b8bd567, 0xde8538ee, 0x0d507b0c, 0xd128f5bb,
|
||||
0x8e467fec, 0xcd30000a, 0x6cc1184e, 0x25d382c2,
|
||||
0xa2f4494e, 0x2fbe9abc, 0x8b64abac, 0xd005fb24
|
||||
);
|
||||
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_13;
|
||||
|
||||
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(
|
||||
0x3d3486b2, 0x159a9ca5, 0xc75638be, 0xb23a69bc,
|
||||
0x946a45ab, 0x24801247, 0xb4ed2b8e, 0x26b6a417
|
||||
);
|
||||
# elif EXHAUSTIVE_TEST_ORDER == 199
|
||||
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(
|
||||
0x226e653f, 0xc8df7744, 0x9bacbf12, 0x7d1dcbf9,
|
||||
0x87f05b2a, 0xe7edbd28, 0x1f564575, 0xc48dcf18,
|
||||
0xa13872c2, 0xe933bb17, 0x5d9ffd5b, 0xb5b6e10c,
|
||||
0x57fe3c00, 0xbaaaa15a, 0xe003ec3e, 0x9c269bae
|
||||
);
|
||||
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_199;
|
||||
|
||||
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(
|
||||
0x2cca28fa, 0xfc614b80, 0x2a3db42b, 0x00ba00b1,
|
||||
0xbea8d943, 0xdace9ab2, 0x9536daea, 0x0074defb
|
||||
@ -46,15 +59,7 @@ static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(
|
||||
# error No known generator for the specified exhaustive test group order.
|
||||
# endif
|
||||
#else
|
||||
/** Generator for secp256k1, value 'g' defined in
|
||||
* "Standards for Efficient Cryptography" (SEC2) 2.7.1.
|
||||
*/
|
||||
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(
|
||||
0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL,
|
||||
0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL,
|
||||
0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL,
|
||||
0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL
|
||||
);
|
||||
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);
|
||||
#endif
|
||||
@ -62,6 +67,7 @@ static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(0, 0, 0, 0,
|
||||
static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) {
|
||||
secp256k1_fe zi2;
|
||||
secp256k1_fe zi3;
|
||||
VERIFY_CHECK(!a->infinity);
|
||||
secp256k1_fe_sqr(&zi2, zi);
|
||||
secp256k1_fe_mul(&zi3, &zi2, zi);
|
||||
secp256k1_fe_mul(&r->x, &a->x, &zi2);
|
||||
|
@ -1,8 +1,4 @@
|
||||
include_HEADERS += include/secp256k1_ecdh.h
|
||||
noinst_HEADERS += src/modules/ecdh/main_impl.h
|
||||
noinst_HEADERS += src/modules/ecdh/tests_impl.h
|
||||
if USE_BENCHMARK
|
||||
noinst_PROGRAMS += bench_ecdh
|
||||
bench_ecdh_SOURCES = src/bench_ecdh.c
|
||||
bench_ecdh_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB)
|
||||
endif
|
||||
noinst_HEADERS += src/modules/ecdh/bench_impl.h
|
||||
|
@ -4,12 +4,10 @@
|
||||
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
||||
***********************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#ifndef SECP256K1_MODULE_ECDH_BENCH_H
|
||||
#define SECP256K1_MODULE_ECDH_BENCH_H
|
||||
|
||||
#include "../include/secp256k1.h"
|
||||
#include "../include/secp256k1_ecdh.h"
|
||||
#include "util.h"
|
||||
#include "bench.h"
|
||||
|
||||
typedef struct {
|
||||
secp256k1_context *ctx;
|
||||
@ -44,16 +42,16 @@ static void bench_ecdh(void* arg, int iters) {
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
void run_ecdh_bench(int iters, int argc, char** argv) {
|
||||
bench_ecdh_data data;
|
||||
|
||||
int iters = get_iters(20000);
|
||||
int d = argc == 1;
|
||||
|
||||
/* create a context with no capabilities */
|
||||
data.ctx = secp256k1_context_create(SECP256K1_FLAGS_TYPE_CONTEXT);
|
||||
|
||||
run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, iters);
|
||||
if (d || have_flag(argc, argv, "ecdh")) run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, iters);
|
||||
|
||||
secp256k1_context_destroy(data.ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_MODULE_ECDH_BENCH_H */
|
@ -120,12 +120,11 @@ int secp256k1_xonly_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pub
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(output_pubkey != NULL);
|
||||
memset(output_pubkey, 0, sizeof(*output_pubkey));
|
||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
||||
ARG_CHECK(internal_pubkey != NULL);
|
||||
ARG_CHECK(tweak32 != NULL);
|
||||
|
||||
if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey)
|
||||
|| !secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32)) {
|
||||
|| !secp256k1_ec_pubkey_tweak_add_helper(&pk, tweak32)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_pubkey_save(output_pubkey, &pk);
|
||||
@ -137,13 +136,12 @@ int secp256k1_xonly_pubkey_tweak_add_check(const secp256k1_context* ctx, const u
|
||||
unsigned char pk_expected32[32];
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
||||
ARG_CHECK(internal_pubkey != NULL);
|
||||
ARG_CHECK(tweaked_pubkey32 != NULL);
|
||||
ARG_CHECK(tweak32 != NULL);
|
||||
|
||||
if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey)
|
||||
|| !secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32)) {
|
||||
|| !secp256k1_ec_pubkey_tweak_add_helper(&pk, tweak32)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_fe_normalize_var(&pk.x);
|
||||
@ -260,7 +258,6 @@ int secp256k1_keypair_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_ke
|
||||
int ret;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
||||
ARG_CHECK(keypair != NULL);
|
||||
ARG_CHECK(tweak32 != NULL);
|
||||
|
||||
@ -273,7 +270,7 @@ int secp256k1_keypair_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_ke
|
||||
}
|
||||
|
||||
ret &= secp256k1_ec_seckey_tweak_add_helper(&sk, tweak32);
|
||||
ret &= secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32);
|
||||
ret &= secp256k1_ec_pubkey_tweak_add_helper(&pk, tweak32);
|
||||
|
||||
secp256k1_declassify(ctx, &ret, sizeof(ret));
|
||||
if (ret) {
|
||||
|
@ -197,19 +197,19 @@ void test_xonly_pubkey_tweak(void) {
|
||||
CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
|
||||
|
||||
ecount = 0;
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add(none, &output_pk, &internal_xonly_pk, tweak) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add(sign, &output_pk, &internal_xonly_pk, tweak) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add(none, &output_pk, &internal_xonly_pk, tweak) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add(sign, &output_pk, &internal_xonly_pk, tweak) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1);
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, NULL, &internal_xonly_pk, tweak) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, NULL, tweak) == 0);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(ecount == 2);
|
||||
/* NULL internal_xonly_pk zeroes the output_pk */
|
||||
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, NULL) == 0);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(ecount == 3);
|
||||
/* NULL tweak zeroes the output_pk */
|
||||
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
|
||||
|
||||
@ -274,20 +274,20 @@ void test_xonly_pubkey_tweak_check(void) {
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1);
|
||||
CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &output_xonly_pk, &pk_parity, &output_pk) == 1);
|
||||
CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &output_xonly_pk) == 1);
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add_check(none, buf32, pk_parity, &internal_xonly_pk, tweak) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add_check(sign, buf32, pk_parity, &internal_xonly_pk, tweak) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add_check(none, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add_check(sign, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, NULL, pk_parity, &internal_xonly_pk, tweak) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(ecount == 1);
|
||||
/* invalid pk_parity value */
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, 2, &internal_xonly_pk, tweak) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, NULL, tweak) == 0);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, NULL) == 0);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(ecount == 3);
|
||||
|
||||
memset(tweak, 1, sizeof(tweak));
|
||||
CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &internal_xonly_pk, NULL, &internal_pk) == 1);
|
||||
@ -306,7 +306,7 @@ void test_xonly_pubkey_tweak_check(void) {
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, pk_parity, &internal_xonly_pk, overflows) == 0);
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, overflows) == 0);
|
||||
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(ecount == 3);
|
||||
|
||||
secp256k1_context_destroy(none);
|
||||
secp256k1_context_destroy(sign);
|
||||
@ -359,6 +359,9 @@ void test_keypair(void) {
|
||||
secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
|
||||
secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
|
||||
secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
|
||||
secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
|
||||
secp256k1_context_set_error_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
|
||||
CHECK(sizeof(zeros96) == sizeof(keypair));
|
||||
memset(overflows, 0xFF, sizeof(overflows));
|
||||
@ -366,18 +369,22 @@ void test_keypair(void) {
|
||||
/* Test keypair_create */
|
||||
ecount = 0;
|
||||
secp256k1_testrand256(sk);
|
||||
CHECK(secp256k1_keypair_create(none, &keypair, sk) == 0);
|
||||
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
|
||||
CHECK(secp256k1_keypair_create(none, &keypair, sk) == 1);
|
||||
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_keypair_create(verify, &keypair, sk) == 1);
|
||||
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_keypair_create(sign, NULL, sk) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_keypair_create(verify, &keypair, sk) == 0);
|
||||
CHECK(secp256k1_keypair_create(sign, &keypair, NULL) == 0);
|
||||
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
|
||||
CHECK(secp256k1_keypair_create(sign, NULL, sk) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_keypair_create(sign, &keypair, NULL) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_keypair_create(sttc, &keypair, sk) == 0);
|
||||
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(ecount == 3);
|
||||
|
||||
/* Invalid secret key */
|
||||
CHECK(secp256k1_keypair_create(sign, &keypair, zeros96) == 0);
|
||||
@ -459,6 +466,7 @@ void test_keypair(void) {
|
||||
secp256k1_context_destroy(none);
|
||||
secp256k1_context_destroy(sign);
|
||||
secp256k1_context_destroy(verify);
|
||||
secp256k1_context_destroy(sttc);
|
||||
}
|
||||
|
||||
void test_keypair_add(void) {
|
||||
@ -479,15 +487,15 @@ void test_keypair_add(void) {
|
||||
memset(overflows, 0xFF, 32);
|
||||
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
|
||||
|
||||
CHECK(secp256k1_keypair_xonly_tweak_add(none, &keypair, tweak) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_keypair_xonly_tweak_add(sign, &keypair, tweak) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_keypair_xonly_tweak_add(none, &keypair, tweak) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_keypair_xonly_tweak_add(sign, &keypair, tweak) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 1);
|
||||
CHECK(secp256k1_keypair_xonly_tweak_add(verify, NULL, tweak) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, NULL) == 0);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(ecount == 2);
|
||||
/* This does not set the keypair to zeroes */
|
||||
CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) != 0);
|
||||
|
||||
|
@ -2,8 +2,4 @@ include_HEADERS += include/secp256k1_recovery.h
|
||||
noinst_HEADERS += src/modules/recovery/main_impl.h
|
||||
noinst_HEADERS += src/modules/recovery/tests_impl.h
|
||||
noinst_HEADERS += src/modules/recovery/tests_exhaustive_impl.h
|
||||
if USE_BENCHMARK
|
||||
noinst_PROGRAMS += bench_recover
|
||||
bench_recover_SOURCES = src/bench_recover.c
|
||||
bench_recover_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB)
|
||||
endif
|
||||
noinst_HEADERS += src/modules/recovery/bench_impl.h
|
||||
|
@ -4,10 +4,10 @@
|
||||
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
||||
***********************************************************************/
|
||||
|
||||
#include "../include/secp256k1.h"
|
||||
#ifndef SECP256K1_MODULE_RECOVERY_BENCH_H
|
||||
#define SECP256K1_MODULE_RECOVERY_BENCH_H
|
||||
|
||||
#include "../include/secp256k1_recovery.h"
|
||||
#include "util.h"
|
||||
#include "bench.h"
|
||||
|
||||
typedef struct {
|
||||
secp256k1_context *ctx;
|
||||
@ -48,15 +48,15 @@ void bench_recover_setup(void* arg) {
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
void run_recovery_bench(int iters, int argc, char** argv) {
|
||||
bench_recover_data data;
|
||||
|
||||
int iters = get_iters(20000);
|
||||
int d = argc == 1;
|
||||
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
||||
|
||||
run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, iters);
|
||||
if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, iters);
|
||||
|
||||
secp256k1_context_destroy(data.ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_MODULE_RECOVERY_BENCH_H */
|
@ -40,7 +40,7 @@ int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context*
|
||||
int ret = 1;
|
||||
int overflow = 0;
|
||||
|
||||
(void)ctx;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(sig != NULL);
|
||||
ARG_CHECK(input64 != NULL);
|
||||
ARG_CHECK(recid >= 0 && recid <= 3);
|
||||
@ -60,7 +60,7 @@ int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context*
|
||||
int secp256k1_ecdsa_recoverable_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_recoverable_signature* sig) {
|
||||
secp256k1_scalar r, s;
|
||||
|
||||
(void)ctx;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(output64 != NULL);
|
||||
ARG_CHECK(sig != NULL);
|
||||
ARG_CHECK(recid != NULL);
|
||||
@ -75,7 +75,7 @@ int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context* ctx,
|
||||
secp256k1_scalar r, s;
|
||||
int recid;
|
||||
|
||||
(void)ctx;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(sig != NULL);
|
||||
ARG_CHECK(sigin != NULL);
|
||||
|
||||
@ -84,7 +84,7 @@ int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context* ctx,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) {
|
||||
static int secp256k1_ecdsa_sig_recover(const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) {
|
||||
unsigned char brx[32];
|
||||
secp256k1_fe fx;
|
||||
secp256k1_ge x;
|
||||
@ -115,7 +115,7 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, cons
|
||||
secp256k1_scalar_mul(&u1, &rn, message);
|
||||
secp256k1_scalar_negate(&u1, &u1);
|
||||
secp256k1_scalar_mul(&u2, &rn, sigs);
|
||||
secp256k1_ecmult(ctx, &qj, &xj, &u2, &u1);
|
||||
secp256k1_ecmult(&qj, &xj, &u2, &u1);
|
||||
secp256k1_ge_set_gej_var(pubkey, &qj);
|
||||
return !secp256k1_gej_is_infinity(&qj);
|
||||
}
|
||||
@ -140,7 +140,6 @@ int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubk
|
||||
secp256k1_scalar m;
|
||||
int recid;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
||||
ARG_CHECK(msghash32 != NULL);
|
||||
ARG_CHECK(signature != NULL);
|
||||
ARG_CHECK(pubkey != NULL);
|
||||
@ -148,7 +147,7 @@ int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubk
|
||||
secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature);
|
||||
VERIFY_CHECK(recid >= 0 && recid < 4); /* should have been caught in parse_compact */
|
||||
secp256k1_scalar_set_b32(&m, msghash32, NULL);
|
||||
if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) {
|
||||
if (secp256k1_ecdsa_sig_recover(&r, &s, &q, &m, recid)) {
|
||||
secp256k1_pubkey_save(pubkey, &q);
|
||||
return 1;
|
||||
} else {
|
||||
|
@ -34,6 +34,7 @@ void test_ecdsa_recovery_api(void) {
|
||||
secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
|
||||
secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
||||
secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
|
||||
secp256k1_pubkey pubkey;
|
||||
secp256k1_pubkey recpubkey;
|
||||
secp256k1_ecdsa_signature normal_sig;
|
||||
@ -53,10 +54,12 @@ void test_ecdsa_recovery_api(void) {
|
||||
secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
|
||||
/* Construct and verify corresponding public key. */
|
||||
CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1);
|
||||
@ -64,48 +67,50 @@ void test_ecdsa_recovery_api(void) {
|
||||
|
||||
/* Check bad contexts and NULLs for signing */
|
||||
ecount = 0;
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(sign, &recsig, message, privkey, NULL, NULL) == 1);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(vrfy, &recsig, message, privkey, NULL, NULL) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(vrfy, &recsig, message, privkey, NULL, NULL) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(both, NULL, message, privkey, NULL, NULL) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, NULL, privkey, NULL, NULL) == 0);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, NULL, NULL, NULL) == 0);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(sttc, &recsig, message, privkey, NULL, NULL) == 0);
|
||||
CHECK(ecount == 4);
|
||||
/* This will fail or succeed randomly, and in either case will not ARG_CHECK failure */
|
||||
secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, recovery_test_nonce_function, NULL);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(ecount == 4);
|
||||
/* These will all fail, but not in ARG_CHECK way */
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, zero_privkey, NULL, NULL) == 0);
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, over_privkey, NULL, NULL) == 0);
|
||||
/* This one will succeed. */
|
||||
CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(ecount == 4);
|
||||
|
||||
/* Check signing with a goofy nonce function */
|
||||
|
||||
/* Check bad contexts and NULLs for recovery */
|
||||
ecount = 0;
|
||||
CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_ecdsa_recover(vrfy, &recpubkey, &recsig, message) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, message) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_ecdsa_recover(both, NULL, &recsig, message) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_ecdsa_recover(both, &recpubkey, NULL, message) == 0);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(ecount == 3);
|
||||
|
||||
/* Check NULLs for conversion */
|
||||
CHECK(secp256k1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1);
|
||||
@ -145,6 +150,7 @@ void test_ecdsa_recovery_api(void) {
|
||||
secp256k1_context_destroy(sign);
|
||||
secp256k1_context_destroy(vrfy);
|
||||
secp256k1_context_destroy(both);
|
||||
secp256k1_context_destroy(sttc);
|
||||
}
|
||||
|
||||
void test_ecdsa_recovery_end_to_end(void) {
|
||||
|
@ -2,8 +2,4 @@ include_HEADERS += include/secp256k1_schnorrsig.h
|
||||
noinst_HEADERS += src/modules/schnorrsig/main_impl.h
|
||||
noinst_HEADERS += src/modules/schnorrsig/tests_impl.h
|
||||
noinst_HEADERS += src/modules/schnorrsig/tests_exhaustive_impl.h
|
||||
if USE_BENCHMARK
|
||||
noinst_PROGRAMS += bench_schnorrsig
|
||||
bench_schnorrsig_SOURCES = src/bench_schnorrsig.c
|
||||
bench_schnorrsig_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB)
|
||||
endif
|
||||
noinst_HEADERS += src/modules/schnorrsig/bench_impl.h
|
||||
|
@ -4,14 +4,10 @@
|
||||
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
||||
***********************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef SECP256K1_MODULE_SCHNORRSIG_BENCH_H
|
||||
#define SECP256K1_MODULE_SCHNORRSIG_BENCH_H
|
||||
|
||||
|
||||
#include "../include/secp256k1.h"
|
||||
#include "../include/secp256k1_schnorrsig.h"
|
||||
#include "util.h"
|
||||
#include "bench.h"
|
||||
#include "../../../include/secp256k1_schnorrsig.h"
|
||||
|
||||
#define MSGLEN 32
|
||||
|
||||
@ -49,10 +45,10 @@ void bench_schnorrsig_verify(void* arg, int iters) {
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
void run_schnorrsig_bench(int iters, int argc, char** argv) {
|
||||
int i;
|
||||
bench_schnorrsig_data data;
|
||||
int iters = get_iters(10000);
|
||||
int d = argc == 1;
|
||||
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);
|
||||
data.keypairs = (const secp256k1_keypair **)malloc(iters * sizeof(secp256k1_keypair *));
|
||||
@ -86,8 +82,8 @@ int main(void) {
|
||||
CHECK(secp256k1_xonly_pubkey_serialize(data.ctx, pk_char, &pk) == 1);
|
||||
}
|
||||
|
||||
run_benchmark("schnorrsig_sign", bench_schnorrsig_sign, NULL, NULL, (void *) &data, 10, iters);
|
||||
run_benchmark("schnorrsig_verify", bench_schnorrsig_verify, NULL, NULL, (void *) &data, 10, iters);
|
||||
if (d || have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "sign") || have_flag(argc, argv, "schnorrsig_sign")) run_benchmark("schnorrsig_sign", bench_schnorrsig_sign, NULL, NULL, (void *) &data, 10, iters);
|
||||
if (d || have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "verify") || have_flag(argc, argv, "schnorrsig_verify")) run_benchmark("schnorrsig_verify", bench_schnorrsig_verify, NULL, NULL, (void *) &data, 10, iters);
|
||||
|
||||
for (i = 0; i < iters; i++) {
|
||||
free((void *)data.keypairs[i]);
|
||||
@ -101,5 +97,6 @@ int main(void) {
|
||||
free(data.sigs);
|
||||
|
||||
secp256k1_context_destroy(data.ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
@ -65,6 +65,17 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms
|
||||
for (i = 0; i < 32; i++) {
|
||||
masked_key[i] ^= key32[i];
|
||||
}
|
||||
} else {
|
||||
/* Precomputed TaggedHash("BIP0340/aux", 0x0000...00); */
|
||||
static const unsigned char ZERO_MASK[32] = {
|
||||
84, 241, 105, 207, 201, 226, 229, 114,
|
||||
116, 128, 68, 31, 144, 186, 37, 196,
|
||||
136, 244, 97, 199, 11, 94, 165, 220,
|
||||
170, 247, 175, 105, 39, 10, 165, 20
|
||||
};
|
||||
for (i = 0; i < 32; i++) {
|
||||
masked_key[i] = key32[i] ^ ZERO_MASK[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Tag the hash with algo which is important to avoid nonce reuse across
|
||||
@ -77,12 +88,8 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms
|
||||
secp256k1_sha256_initialize_tagged(&sha, algo, algolen);
|
||||
}
|
||||
|
||||
/* Hash (masked-)key||pk||msg using the tagged hash as per the spec */
|
||||
if (data != NULL) {
|
||||
secp256k1_sha256_write(&sha, masked_key, 32);
|
||||
} else {
|
||||
secp256k1_sha256_write(&sha, key32, 32);
|
||||
}
|
||||
/* Hash masked-key||pk||msg using the tagged hash as per the spec */
|
||||
secp256k1_sha256_write(&sha, masked_key, 32);
|
||||
secp256k1_sha256_write(&sha, xonly_pk32, 32);
|
||||
secp256k1_sha256_write(&sha, msg, msglen);
|
||||
secp256k1_sha256_finalize(&sha, nonce32);
|
||||
@ -122,7 +129,7 @@ static void secp256k1_schnorrsig_challenge(secp256k1_scalar* e, const unsigned c
|
||||
secp256k1_scalar_set_b32(e, buf, NULL);
|
||||
}
|
||||
|
||||
int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_keypair *keypair, secp256k1_nonce_function_hardened noncefp, void *ndata) {
|
||||
static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_keypair *keypair, secp256k1_nonce_function_hardened noncefp, void *ndata) {
|
||||
secp256k1_scalar sk;
|
||||
secp256k1_scalar e;
|
||||
secp256k1_scalar k;
|
||||
@ -185,8 +192,9 @@ int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsigned ch
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, unsigned char *aux_rand32) {
|
||||
return secp256k1_schnorrsig_sign_internal(ctx, sig64, msg32, 32, keypair, secp256k1_nonce_function_bip340, aux_rand32);
|
||||
int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, const unsigned char *aux_rand32) {
|
||||
/* We cast away const from the passed aux_rand32 argument since we know the default nonce function does not modify it. */
|
||||
return secp256k1_schnorrsig_sign_internal(ctx, sig64, msg32, 32, keypair, secp256k1_nonce_function_bip340, (unsigned char*)aux_rand32);
|
||||
}
|
||||
|
||||
int secp256k1_schnorrsig_sign_custom(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_keypair *keypair, secp256k1_schnorrsig_extraparams *extraparams) {
|
||||
@ -216,7 +224,6 @@ int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned cha
|
||||
int overflow;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
||||
ARG_CHECK(sig64 != NULL);
|
||||
ARG_CHECK(msg != NULL || msglen == 0);
|
||||
ARG_CHECK(pubkey != NULL);
|
||||
@ -241,7 +248,7 @@ int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned cha
|
||||
/* Compute rj = s*G + (-e)*pkj */
|
||||
secp256k1_scalar_negate(&e, &e);
|
||||
secp256k1_gej_set_ge(&pkj, &pk);
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &rj, &pkj, &e, &s);
|
||||
secp256k1_ecmult(&rj, &pkj, &e, &s);
|
||||
|
||||
secp256k1_ge_set_gej_var(&r, &rj);
|
||||
if (secp256k1_ge_is_infinity(&r)) {
|
||||
|
@ -38,7 +38,7 @@ void run_nonce_function_bip340_tests(void) {
|
||||
size_t algolen = sizeof(algo);
|
||||
secp256k1_sha256 sha;
|
||||
secp256k1_sha256 sha_optimized;
|
||||
unsigned char nonce[32];
|
||||
unsigned char nonce[32], nonce_z[32];
|
||||
unsigned char msg[32];
|
||||
size_t msglen = sizeof(msg);
|
||||
unsigned char key[32];
|
||||
@ -107,8 +107,11 @@ void run_nonce_function_bip340_tests(void) {
|
||||
CHECK(secp256k1_memcmp_var(nonce, nonce2, 32) != 0);
|
||||
}
|
||||
|
||||
/* NULL aux_rand argument is allowed. */
|
||||
/* NULL aux_rand argument is allowed, and identical to passing all zero aux_rand. */
|
||||
memset(aux_rand, 0, 32);
|
||||
CHECK(nonce_function_bip340(nonce_z, msg, msglen, key, pk, algo, algolen, &aux_rand) == 1);
|
||||
CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1);
|
||||
CHECK(secp256k1_memcmp_var(nonce_z, nonce, 32) == 0);
|
||||
}
|
||||
|
||||
void test_schnorrsig_api(void) {
|
||||
@ -129,16 +132,19 @@ void test_schnorrsig_api(void) {
|
||||
secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
|
||||
secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
||||
secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
|
||||
int ecount;
|
||||
|
||||
secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
|
||||
secp256k1_testrand256(sk1);
|
||||
secp256k1_testrand256(sk2);
|
||||
@ -154,66 +160,71 @@ void test_schnorrsig_api(void) {
|
||||
|
||||
/** main test body **/
|
||||
ecount = 0;
|
||||
CHECK(secp256k1_schnorrsig_sign(none, sig, msg, &keypairs[0], NULL) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_schnorrsig_sign(vrfy, sig, msg, &keypairs[0], NULL) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_schnorrsig_sign(none, sig, msg, &keypairs[0], NULL) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_schnorrsig_sign(vrfy, sig, msg, &keypairs[0], NULL) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &keypairs[0], NULL) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_schnorrsig_sign(sign, NULL, msg, &keypairs[0], NULL) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_schnorrsig_sign(sign, sig, NULL, &keypairs[0], NULL) == 0);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, NULL, NULL) == 0);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &invalid_keypair, NULL) == 0);
|
||||
CHECK(ecount == 6);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(secp256k1_schnorrsig_sign(sttc, sig, msg, &keypairs[0], NULL) == 0);
|
||||
CHECK(ecount == 5);
|
||||
|
||||
ecount = 0;
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(none, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(vrfy, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(none, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(vrfy, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sign, NULL, msg, sizeof(msg), &keypairs[0], &extraparams) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, NULL, sizeof(msg), &keypairs[0], &extraparams) == 0);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, NULL, 0, &keypairs[0], &extraparams) == 1);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), NULL, &extraparams) == 0);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &invalid_keypair, &extraparams) == 0);
|
||||
CHECK(ecount == 6);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &keypairs[0], NULL) == 1);
|
||||
CHECK(ecount == 6);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &keypairs[0], &invalid_extraparams) == 0);
|
||||
CHECK(ecount == 7);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(secp256k1_schnorrsig_sign_custom(sttc, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 0);
|
||||
CHECK(ecount == 6);
|
||||
|
||||
ecount = 0;
|
||||
CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &keypairs[0], NULL) == 1);
|
||||
CHECK(secp256k1_schnorrsig_verify(none, sig, msg, sizeof(msg), &pk[0]) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_schnorrsig_verify(sign, sig, msg, sizeof(msg), &pk[0]) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_schnorrsig_verify(none, sig, msg, sizeof(msg), &pk[0]) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_schnorrsig_verify(sign, sig, msg, sizeof(msg), &pk[0]) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), &pk[0]) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_schnorrsig_verify(vrfy, NULL, msg, sizeof(msg), &pk[0]) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, sizeof(msg), &pk[0]) == 0);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, 0, &pk[0]) == 0);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), NULL) == 0);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), &zero_pk) == 0);
|
||||
CHECK(ecount == 6);
|
||||
CHECK(ecount == 4);
|
||||
|
||||
secp256k1_context_destroy(none);
|
||||
secp256k1_context_destroy(sign);
|
||||
secp256k1_context_destroy(vrfy);
|
||||
secp256k1_context_destroy(both);
|
||||
secp256k1_context_destroy(sttc);
|
||||
}
|
||||
|
||||
/* Checks that hash initialized by secp256k1_schnorrsig_sha256_tagged has the
|
||||
@ -230,7 +241,7 @@ void test_schnorrsig_sha256_tagged(void) {
|
||||
|
||||
/* Helper function for schnorrsig_bip_vectors
|
||||
* 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, unsigned char *aux_rand, const unsigned char *msg32, const unsigned char *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) {
|
||||
unsigned char sig[64];
|
||||
secp256k1_keypair keypair;
|
||||
secp256k1_xonly_pubkey pk, pk_expected;
|
||||
|
@ -74,7 +74,7 @@ static void secp256k1_scalar_split_lambda_verify(const secp256k1_scalar *r1, con
|
||||
* Both lambda and beta are primitive cube roots of unity. That is lamba^3 == 1 mod n and
|
||||
* beta^3 == 1 mod p, where n is the curve order and p is the field order.
|
||||
*
|
||||
* Futhermore, because (X^3 - 1) = (X - 1)(X^2 + X + 1), the primitive cube roots of unity are
|
||||
* Furthermore, because (X^3 - 1) = (X - 1)(X^2 + X + 1), the primitive cube roots of unity are
|
||||
* roots of X^2 + X + 1. Therefore lambda^2 + lamba == -1 mod n and beta^2 + beta == -1 mod p.
|
||||
* (The other primitive cube roots of unity are lambda^2 and beta^2 respectively.)
|
||||
*
|
||||
|
@ -44,36 +44,7 @@
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#ifndef USE_EXTERNAL_DEFAULT_CALLBACKS
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
static void secp256k1_default_illegal_callback_fn(const char* str, void* data) {
|
||||
(void)data;
|
||||
fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str);
|
||||
abort();
|
||||
}
|
||||
static void secp256k1_default_error_callback_fn(const char* str, void* data) {
|
||||
(void)data;
|
||||
fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str);
|
||||
abort();
|
||||
}
|
||||
#else
|
||||
void secp256k1_default_illegal_callback_fn(const char* str, void* data);
|
||||
void secp256k1_default_error_callback_fn(const char* str, void* data);
|
||||
#endif
|
||||
|
||||
static const secp256k1_callback default_illegal_callback = {
|
||||
secp256k1_default_illegal_callback_fn,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const secp256k1_callback default_error_callback = {
|
||||
secp256k1_default_error_callback_fn,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct secp256k1_context_struct {
|
||||
secp256k1_ecmult_context ecmult_ctx;
|
||||
secp256k1_ecmult_gen_context ecmult_gen_ctx;
|
||||
secp256k1_callback illegal_callback;
|
||||
secp256k1_callback error_callback;
|
||||
@ -81,7 +52,6 @@ struct secp256k1_context_struct {
|
||||
};
|
||||
|
||||
static const secp256k1_context secp256k1_context_no_precomp_ = {
|
||||
{ 0 },
|
||||
{ 0 },
|
||||
{ secp256k1_default_illegal_callback_fn, 0 },
|
||||
{ secp256k1_default_error_callback_fn, 0 },
|
||||
@ -90,7 +60,7 @@ static const secp256k1_context secp256k1_context_no_precomp_ = {
|
||||
const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_no_precomp_;
|
||||
|
||||
size_t secp256k1_context_preallocated_size(unsigned int flags) {
|
||||
size_t ret = ROUND_TO_ALIGN(sizeof(secp256k1_context));
|
||||
size_t ret = sizeof(secp256k1_context);
|
||||
/* A return value of 0 is reserved as an indicator for errors when we call this function internally. */
|
||||
VERIFY_CHECK(ret != 0);
|
||||
|
||||
@ -100,29 +70,16 @@ size_t secp256k1_context_preallocated_size(unsigned int flags) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {
|
||||
ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE;
|
||||
}
|
||||
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) {
|
||||
ret += SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t secp256k1_context_preallocated_clone_size(const secp256k1_context* ctx) {
|
||||
size_t ret = ROUND_TO_ALIGN(sizeof(secp256k1_context));
|
||||
size_t ret = sizeof(secp256k1_context);
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) {
|
||||
ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE;
|
||||
}
|
||||
if (secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)) {
|
||||
ret += SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigned int flags) {
|
||||
void* const base = prealloc;
|
||||
size_t prealloc_size;
|
||||
secp256k1_context* ret;
|
||||
|
||||
@ -135,24 +92,16 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne
|
||||
return NULL;
|
||||
}
|
||||
VERIFY_CHECK(prealloc != NULL);
|
||||
ret = (secp256k1_context*)manual_alloc(&prealloc, sizeof(secp256k1_context), base, prealloc_size);
|
||||
ret = (secp256k1_context*)prealloc;
|
||||
ret->illegal_callback = default_illegal_callback;
|
||||
ret->error_callback = default_error_callback;
|
||||
|
||||
secp256k1_ecmult_context_init(&ret->ecmult_ctx);
|
||||
secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx);
|
||||
|
||||
/* Flags have been checked by secp256k1_context_preallocated_size. */
|
||||
VERIFY_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_CONTEXT);
|
||||
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {
|
||||
secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &prealloc);
|
||||
}
|
||||
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) {
|
||||
secp256k1_ecmult_context_build(&ret->ecmult_ctx, &prealloc);
|
||||
}
|
||||
secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx);
|
||||
ret->declassify = !!(flags & SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY);
|
||||
|
||||
return (secp256k1_context*) ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
secp256k1_context* secp256k1_context_create(unsigned int flags) {
|
||||
@ -167,16 +116,12 @@ secp256k1_context* secp256k1_context_create(unsigned int flags) {
|
||||
}
|
||||
|
||||
secp256k1_context* secp256k1_context_preallocated_clone(const secp256k1_context* ctx, void* prealloc) {
|
||||
size_t prealloc_size;
|
||||
secp256k1_context* ret;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(prealloc != NULL);
|
||||
|
||||
prealloc_size = secp256k1_context_preallocated_clone_size(ctx);
|
||||
ret = (secp256k1_context*)prealloc;
|
||||
memcpy(ret, ctx, prealloc_size);
|
||||
secp256k1_ecmult_gen_context_finalize_memcpy(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx);
|
||||
secp256k1_ecmult_context_finalize_memcpy(&ret->ecmult_ctx, &ctx->ecmult_ctx);
|
||||
*ret = *ctx;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -194,7 +139,6 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
|
||||
void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) {
|
||||
ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
|
||||
if (ctx != NULL) {
|
||||
secp256k1_ecmult_context_clear(&ctx->ecmult_ctx);
|
||||
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
|
||||
}
|
||||
}
|
||||
@ -458,7 +402,6 @@ int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_s
|
||||
secp256k1_scalar r, s;
|
||||
secp256k1_scalar m;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
||||
ARG_CHECK(msghash32 != NULL);
|
||||
ARG_CHECK(sig != NULL);
|
||||
ARG_CHECK(pubkey != NULL);
|
||||
@ -467,7 +410,7 @@ int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_s
|
||||
secp256k1_ecdsa_signature_load(ctx, &r, &s, sig);
|
||||
return (!secp256k1_scalar_is_high(&s) &&
|
||||
secp256k1_pubkey_load(ctx, &q, pubkey) &&
|
||||
secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m));
|
||||
secp256k1_ecdsa_sig_verify(&r, &s, &q, &m));
|
||||
}
|
||||
|
||||
static SECP256K1_INLINE void buffer_append(unsigned char *buf, unsigned int *offset, const void *data, unsigned int len) {
|
||||
@ -685,24 +628,23 @@ int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *
|
||||
return secp256k1_ec_seckey_tweak_add(ctx, seckey, tweak32);
|
||||
}
|
||||
|
||||
static int secp256k1_ec_pubkey_tweak_add_helper(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_ge *p, const unsigned char *tweak32) {
|
||||
static int secp256k1_ec_pubkey_tweak_add_helper(secp256k1_ge *p, const unsigned char *tweak32) {
|
||||
secp256k1_scalar term;
|
||||
int overflow = 0;
|
||||
secp256k1_scalar_set_b32(&term, tweak32, &overflow);
|
||||
return !overflow && secp256k1_eckey_pubkey_tweak_add(ecmult_ctx, p, &term);
|
||||
return !overflow && secp256k1_eckey_pubkey_tweak_add(p, &term);
|
||||
}
|
||||
|
||||
int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak32) {
|
||||
secp256k1_ge p;
|
||||
int ret = 0;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
||||
ARG_CHECK(pubkey != NULL);
|
||||
ARG_CHECK(tweak32 != NULL);
|
||||
|
||||
ret = secp256k1_pubkey_load(ctx, &p, pubkey);
|
||||
memset(pubkey, 0, sizeof(*pubkey));
|
||||
ret = ret && secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &p, tweak32);
|
||||
ret = ret && secp256k1_ec_pubkey_tweak_add_helper(&p, tweak32);
|
||||
if (ret) {
|
||||
secp256k1_pubkey_save(pubkey, &p);
|
||||
}
|
||||
@ -740,7 +682,6 @@ int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey
|
||||
int ret = 0;
|
||||
int overflow = 0;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
||||
ARG_CHECK(pubkey != NULL);
|
||||
ARG_CHECK(tweak32 != NULL);
|
||||
|
||||
@ -748,7 +689,7 @@ int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey
|
||||
ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey);
|
||||
memset(pubkey, 0, sizeof(*pubkey));
|
||||
if (ret) {
|
||||
if (secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor)) {
|
||||
if (secp256k1_eckey_pubkey_tweak_mul(&p, &factor)) {
|
||||
secp256k1_pubkey_save(pubkey, &p);
|
||||
} else {
|
||||
ret = 0;
|
||||
@ -771,6 +712,7 @@ int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *
|
||||
secp256k1_gej Qj;
|
||||
secp256k1_ge Q;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(pubnonce != NULL);
|
||||
memset(pubnonce, 0, sizeof(*pubnonce));
|
||||
ARG_CHECK(n >= 1);
|
||||
@ -779,6 +721,7 @@ int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *
|
||||
secp256k1_gej_set_infinity(&Qj);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
ARG_CHECK(pubnonces[i] != NULL);
|
||||
secp256k1_pubkey_load(ctx, &Q, pubnonces[i]);
|
||||
secp256k1_gej_add_ge(&Qj, &Qj, &Q);
|
||||
}
|
||||
|
490
src/tests.c
490
src/tests.c
@ -20,16 +20,6 @@
|
||||
#include "testrand_impl.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifdef ENABLE_OPENSSL_TESTS
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
# if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) {*pr = sig->r; *ps = sig->s;}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "../contrib/lax_der_parsing.c"
|
||||
#include "../contrib/lax_der_privatekey_parsing.c"
|
||||
|
||||
@ -153,10 +143,12 @@ void run_context_tests(int use_prealloc) {
|
||||
secp256k1_context *sign;
|
||||
secp256k1_context *vrfy;
|
||||
secp256k1_context *both;
|
||||
secp256k1_context *sttc;
|
||||
void *none_prealloc = NULL;
|
||||
void *sign_prealloc = NULL;
|
||||
void *vrfy_prealloc = NULL;
|
||||
void *both_prealloc = NULL;
|
||||
void *sttc_prealloc = NULL;
|
||||
|
||||
secp256k1_gej pubj;
|
||||
secp256k1_ge pub;
|
||||
@ -168,26 +160,30 @@ void run_context_tests(int use_prealloc) {
|
||||
sign_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN));
|
||||
vrfy_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY));
|
||||
both_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY));
|
||||
sttc_prealloc = malloc(secp256k1_context_preallocated_clone_size(secp256k1_context_no_precomp));
|
||||
CHECK(none_prealloc != NULL);
|
||||
CHECK(sign_prealloc != NULL);
|
||||
CHECK(vrfy_prealloc != NULL);
|
||||
CHECK(both_prealloc != NULL);
|
||||
CHECK(sttc_prealloc != NULL);
|
||||
none = secp256k1_context_preallocated_create(none_prealloc, SECP256K1_CONTEXT_NONE);
|
||||
sign = secp256k1_context_preallocated_create(sign_prealloc, SECP256K1_CONTEXT_SIGN);
|
||||
vrfy = secp256k1_context_preallocated_create(vrfy_prealloc, SECP256K1_CONTEXT_VERIFY);
|
||||
both = secp256k1_context_preallocated_create(both_prealloc, SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
sttc = secp256k1_context_preallocated_clone(secp256k1_context_no_precomp, sttc_prealloc);
|
||||
} else {
|
||||
none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
|
||||
sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
|
||||
vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
||||
both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
|
||||
}
|
||||
|
||||
memset(&zero_pubkey, 0, sizeof(zero_pubkey));
|
||||
|
||||
ecount = 0;
|
||||
ecount2 = 10;
|
||||
secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount2);
|
||||
/* set error callback (to a function that still aborts in case malloc() fails in secp256k1_context_clone() below) */
|
||||
secp256k1_context_set_error_callback(sign, secp256k1_default_illegal_callback_fn, NULL);
|
||||
@ -199,6 +195,7 @@ void run_context_tests(int use_prealloc) {
|
||||
CHECK(secp256k1_context_preallocated_clone_size(sign) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN));
|
||||
CHECK(secp256k1_context_preallocated_clone_size(vrfy) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY));
|
||||
CHECK(secp256k1_context_preallocated_clone_size(both) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY));
|
||||
CHECK(secp256k1_context_preallocated_clone_size(sttc) >= sizeof(secp256k1_context));
|
||||
|
||||
/*** clone and destroy all of them to make sure cloning was complete ***/
|
||||
{
|
||||
@ -262,46 +259,46 @@ void run_context_tests(int use_prealloc) {
|
||||
|
||||
/* Verify context-type checking illegal-argument errors. */
|
||||
memset(ctmp, 1, 32);
|
||||
CHECK(secp256k1_ec_pubkey_create(vrfy, &pubkey, ctmp) == 0);
|
||||
CHECK(secp256k1_ec_pubkey_create(sttc, &pubkey, ctmp) == 0);
|
||||
CHECK(ecount == 1);
|
||||
VG_UNDEF(&pubkey, sizeof(pubkey));
|
||||
CHECK(secp256k1_ec_pubkey_create(sign, &pubkey, ctmp) == 1);
|
||||
VG_CHECK(&pubkey, sizeof(pubkey));
|
||||
CHECK(secp256k1_ecdsa_sign(vrfy, &sig, ctmp, ctmp, NULL, NULL) == 0);
|
||||
CHECK(secp256k1_ecdsa_sign(sttc, &sig, ctmp, ctmp, NULL, NULL) == 0);
|
||||
CHECK(ecount == 2);
|
||||
VG_UNDEF(&sig, sizeof(sig));
|
||||
CHECK(secp256k1_ecdsa_sign(sign, &sig, ctmp, ctmp, NULL, NULL) == 1);
|
||||
VG_CHECK(&sig, sizeof(sig));
|
||||
CHECK(ecount2 == 10);
|
||||
CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 0);
|
||||
CHECK(ecount2 == 11);
|
||||
CHECK(secp256k1_ecdsa_verify(vrfy, &sig, ctmp, &pubkey) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 1);
|
||||
CHECK(ecount2 == 10);
|
||||
CHECK(secp256k1_ecdsa_verify(sttc, &sig, ctmp, &pubkey) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 0);
|
||||
CHECK(ecount2 == 12);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(vrfy, &pubkey, ctmp) == 1);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 1);
|
||||
CHECK(ecount2 == 10);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(sttc, &pubkey, ctmp) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0);
|
||||
CHECK(ecount2 == 13);
|
||||
CHECK(secp256k1_ec_pubkey_negate(vrfy, &pubkey) == 1);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 1);
|
||||
CHECK(ecount2 == 10);
|
||||
CHECK(secp256k1_ec_pubkey_negate(sttc, &pubkey) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ec_pubkey_negate(sign, &pubkey) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ec_pubkey_negate(sign, NULL) == 0);
|
||||
CHECK(ecount2 == 14);
|
||||
CHECK(secp256k1_ec_pubkey_negate(vrfy, &zero_pubkey) == 0);
|
||||
CHECK(ecount2 == 11);
|
||||
CHECK(secp256k1_ec_pubkey_negate(sttc, &zero_pubkey) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_mul(sttc, &pubkey, ctmp) == 1);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_context_randomize(vrfy, ctmp) == 1);
|
||||
CHECK(secp256k1_context_randomize(sttc, ctmp) == 1);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_context_randomize(vrfy, NULL) == 1);
|
||||
CHECK(secp256k1_context_randomize(sttc, NULL) == 1);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_context_randomize(sign, ctmp) == 1);
|
||||
CHECK(ecount2 == 14);
|
||||
CHECK(ecount2 == 11);
|
||||
CHECK(secp256k1_context_randomize(sign, NULL) == 1);
|
||||
CHECK(ecount2 == 14);
|
||||
secp256k1_context_set_illegal_callback(vrfy, NULL, NULL);
|
||||
CHECK(ecount2 == 11);
|
||||
secp256k1_context_set_illegal_callback(sttc, NULL, NULL);
|
||||
secp256k1_context_set_illegal_callback(sign, NULL, NULL);
|
||||
|
||||
/* obtain a working nonce */
|
||||
@ -314,8 +311,8 @@ void run_context_tests(int use_prealloc) {
|
||||
CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
|
||||
|
||||
/* try verifying */
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&vrfy->ecmult_ctx, &sigr, &sigs, &pub, &msg));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&both->ecmult_ctx, &sigr, &sigs, &pub, &msg));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg));
|
||||
|
||||
/* cleanup */
|
||||
if (use_prealloc) {
|
||||
@ -323,15 +320,18 @@ void run_context_tests(int use_prealloc) {
|
||||
secp256k1_context_preallocated_destroy(sign);
|
||||
secp256k1_context_preallocated_destroy(vrfy);
|
||||
secp256k1_context_preallocated_destroy(both);
|
||||
secp256k1_context_preallocated_destroy(sttc);
|
||||
free(none_prealloc);
|
||||
free(sign_prealloc);
|
||||
free(vrfy_prealloc);
|
||||
free(both_prealloc);
|
||||
free(sttc_prealloc);
|
||||
} else {
|
||||
secp256k1_context_destroy(none);
|
||||
secp256k1_context_destroy(sign);
|
||||
secp256k1_context_destroy(vrfy);
|
||||
secp256k1_context_destroy(both);
|
||||
secp256k1_context_destroy(sttc);
|
||||
}
|
||||
/* Defined as no-op. */
|
||||
secp256k1_context_destroy(NULL);
|
||||
@ -3235,7 +3235,7 @@ void test_intialized_inf(void) {
|
||||
secp256k1_gej pj, npj, infj1, infj2, infj3;
|
||||
secp256k1_fe zinv;
|
||||
|
||||
/* Test that adding P+(-P) results in a fully initalized infinity*/
|
||||
/* Test that adding P+(-P) results in a fully initialized infinity*/
|
||||
random_group_element_test(&p);
|
||||
secp256k1_gej_set_ge(&pj, &p);
|
||||
secp256k1_gej_neg(&npj, &pj);
|
||||
@ -3416,6 +3416,80 @@ void run_group_decompress(void) {
|
||||
|
||||
/***** ECMULT TESTS *****/
|
||||
|
||||
void test_pre_g_table(const secp256k1_ge_storage * pre_g, size_t n) {
|
||||
/* Tests the pre_g / pre_g_128 tables for consistency.
|
||||
* For independent verification we take a "geometric" approach to verification.
|
||||
* We check that every entry is on-curve.
|
||||
* We check that for consecutive entries p and q, that p + gg - q = 0 by checking
|
||||
* (1) p, gg, and -q are colinear.
|
||||
* (2) p, gg, and -q are all distinct.
|
||||
* where gg is twice the generator, where the generator is the first table entry.
|
||||
*
|
||||
* Checking the table's generators are correct is done in run_ecmult_pre_g.
|
||||
*/
|
||||
secp256k1_gej g2;
|
||||
secp256k1_ge p, q, gg;
|
||||
secp256k1_fe dpx, dpy, dqx, dqy;
|
||||
size_t i;
|
||||
|
||||
CHECK(0 < n);
|
||||
|
||||
secp256k1_ge_from_storage(&p, &pre_g[0]);
|
||||
CHECK(secp256k1_ge_is_valid_var(&p));
|
||||
|
||||
secp256k1_gej_set_ge(&g2, &p);
|
||||
secp256k1_gej_double_var(&g2, &g2, NULL);
|
||||
secp256k1_ge_set_gej_var(&gg, &g2);
|
||||
for (i = 1; i < n; ++i) {
|
||||
secp256k1_fe_negate(&dpx, &p.x, 1); secp256k1_fe_add(&dpx, &gg.x); secp256k1_fe_normalize_weak(&dpx);
|
||||
secp256k1_fe_negate(&dpy, &p.y, 1); secp256k1_fe_add(&dpy, &gg.y); secp256k1_fe_normalize_weak(&dpy);
|
||||
/* Check that p is not equal to gg */
|
||||
CHECK(!secp256k1_fe_normalizes_to_zero_var(&dpx) || !secp256k1_fe_normalizes_to_zero_var(&dpy));
|
||||
|
||||
secp256k1_ge_from_storage(&q, &pre_g[i]);
|
||||
CHECK(secp256k1_ge_is_valid_var(&q));
|
||||
|
||||
secp256k1_fe_negate(&dqx, &q.x, 1); secp256k1_fe_add(&dqx, &gg.x); secp256k1_fe_normalize_weak(&dqx);
|
||||
dqy = q.y; secp256k1_fe_add(&dqy, &gg.y); secp256k1_fe_normalize_weak(&dqy);
|
||||
/* Check that -q is not equal to gg */
|
||||
CHECK(!secp256k1_fe_normalizes_to_zero_var(&dqx) || !secp256k1_fe_normalizes_to_zero_var(&dqy));
|
||||
|
||||
/* Check that -q is not equal to p */
|
||||
CHECK(!secp256k1_fe_equal_var(&dpx, &dqx) || !secp256k1_fe_equal_var(&dpy, &dqy));
|
||||
|
||||
/* Check that p, -q and gg are colinear */
|
||||
secp256k1_fe_mul(&dpx, &dpx, &dqy);
|
||||
secp256k1_fe_mul(&dpy, &dpy, &dqx);
|
||||
CHECK(secp256k1_fe_equal_var(&dpx, &dpy));
|
||||
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
|
||||
void run_ecmult_pre_g(void) {
|
||||
secp256k1_ge_storage gs;
|
||||
secp256k1_gej gj;
|
||||
secp256k1_ge g;
|
||||
size_t i;
|
||||
|
||||
/* Check that the pre_g and pre_g_128 tables are consistent. */
|
||||
test_pre_g_table(secp256k1_pre_g, ECMULT_TABLE_SIZE(WINDOW_G));
|
||||
test_pre_g_table(secp256k1_pre_g_128, ECMULT_TABLE_SIZE(WINDOW_G));
|
||||
|
||||
/* Check the first entry from the pre_g table. */
|
||||
secp256k1_ge_to_storage(&gs, &secp256k1_ge_const_g);
|
||||
CHECK(secp256k1_memcmp_var(&gs, &secp256k1_pre_g[0], sizeof(gs)) == 0);
|
||||
|
||||
/* Check the first entry from the pre_g_128 table. */
|
||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
|
||||
for (i = 0; i < 128; ++i) {
|
||||
secp256k1_gej_double_var(&gj, &gj, NULL);
|
||||
}
|
||||
secp256k1_ge_set_gej(&g, &gj);
|
||||
secp256k1_ge_to_storage(&gs, &g);
|
||||
CHECK(secp256k1_memcmp_var(&gs, &secp256k1_pre_g_128[0], sizeof(gs)) == 0);
|
||||
}
|
||||
|
||||
void run_ecmult_chain(void) {
|
||||
/* random starting point A (on the curve) */
|
||||
secp256k1_gej a = SECP256K1_GEJ_CONST(
|
||||
@ -3448,7 +3522,7 @@ void run_ecmult_chain(void) {
|
||||
x = a;
|
||||
for (i = 0; i < 200*count; i++) {
|
||||
/* in each iteration, compute X = xn*X + gn*G; */
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &x, &x, &xn, &gn);
|
||||
secp256k1_ecmult(&x, &x, &xn, &gn);
|
||||
/* also compute ae and ge: the actual accumulated factors for A and G */
|
||||
/* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */
|
||||
secp256k1_scalar_mul(&ae, &ae, &xn);
|
||||
@ -3474,7 +3548,7 @@ void run_ecmult_chain(void) {
|
||||
}
|
||||
}
|
||||
/* redo the computation, but directly with the resulting ae and ge coefficients: */
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &x2, &a, &ae, &ge);
|
||||
secp256k1_ecmult(&x2, &a, &ae, &ge);
|
||||
secp256k1_gej_neg(&x2, &x2);
|
||||
secp256k1_gej_add_var(&x2, &x2, &x, NULL);
|
||||
CHECK(secp256k1_gej_is_infinity(&x2));
|
||||
@ -3492,8 +3566,8 @@ void test_point_times_order(const secp256k1_gej *point) {
|
||||
size_t psize = 65;
|
||||
random_scalar_order_test(&x);
|
||||
secp256k1_scalar_negate(&nx, &x);
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &x, &x); /* calc res1 = x * point + x * G; */
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */
|
||||
secp256k1_ecmult(&res1, point, &x, &x); /* calc res1 = x * point + x * G; */
|
||||
secp256k1_ecmult(&res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */
|
||||
secp256k1_gej_add_var(&res1, &res1, &res2, NULL);
|
||||
CHECK(secp256k1_gej_is_infinity(&res1));
|
||||
secp256k1_ge_set_gej(&res3, &res1);
|
||||
@ -3503,13 +3577,13 @@ void test_point_times_order(const secp256k1_gej *point) {
|
||||
psize = 65;
|
||||
CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0);
|
||||
/* check zero/one edge cases */
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &zero);
|
||||
secp256k1_ecmult(&res1, point, &zero, &zero);
|
||||
secp256k1_ge_set_gej(&res3, &res1);
|
||||
CHECK(secp256k1_ge_is_infinity(&res3));
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &one, &zero);
|
||||
secp256k1_ecmult(&res1, point, &one, &zero);
|
||||
secp256k1_ge_set_gej(&res3, &res1);
|
||||
ge_equals_gej(&res3, point);
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &one);
|
||||
secp256k1_ecmult(&res1, point, &zero, &one);
|
||||
secp256k1_ge_set_gej(&res3, &res1);
|
||||
ge_equals_ge(&res3, &secp256k1_ge_const_g);
|
||||
}
|
||||
@ -3568,9 +3642,9 @@ void test_ecmult_target(const secp256k1_scalar* target, int mode) {
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &p2j, &n2);
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &ptj, target);
|
||||
} else if (mode == 1) {
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &p1j, &pj, &n1, &zero);
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &p2j, &pj, &n2, &zero);
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &ptj, &pj, target, &zero);
|
||||
secp256k1_ecmult(&p1j, &pj, &n1, &zero);
|
||||
secp256k1_ecmult(&p2j, &pj, &n2, &zero);
|
||||
secp256k1_ecmult(&ptj, &pj, target, &zero);
|
||||
} else {
|
||||
secp256k1_ecmult_const(&p1j, &p, &n1, 256);
|
||||
secp256k1_ecmult_const(&p2j, &p, &n2, 256);
|
||||
@ -3753,7 +3827,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
|
||||
secp256k1_scalar_set_int(&szero, 0);
|
||||
|
||||
/* No points to multiply */
|
||||
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, NULL, ecmult_multi_callback, &data, 0));
|
||||
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, NULL, ecmult_multi_callback, &data, 0));
|
||||
|
||||
/* Check 1- and 2-point multiplies against ecmult */
|
||||
for (ncount = 0; ncount < count; ncount++) {
|
||||
@ -3768,32 +3842,32 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
|
||||
pt[1] = secp256k1_ge_const_g;
|
||||
|
||||
/* only G scalar */
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &szero, &sc[0]);
|
||||
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &sc[0], ecmult_multi_callback, &data, 0));
|
||||
secp256k1_ecmult(&r2, &ptgj, &szero, &sc[0]);
|
||||
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &sc[0], ecmult_multi_callback, &data, 0));
|
||||
secp256k1_gej_neg(&r2, &r2);
|
||||
secp256k1_gej_add_var(&r, &r, &r2, NULL);
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
|
||||
/* 1-point */
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &szero);
|
||||
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 1));
|
||||
secp256k1_ecmult(&r2, &ptgj, &sc[0], &szero);
|
||||
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 1));
|
||||
secp256k1_gej_neg(&r2, &r2);
|
||||
secp256k1_gej_add_var(&r, &r, &r2, NULL);
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
|
||||
/* Try to multiply 1 point, but callback returns false */
|
||||
CHECK(!ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_false_callback, &data, 1));
|
||||
CHECK(!ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_false_callback, &data, 1));
|
||||
|
||||
/* 2-point */
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &sc[1]);
|
||||
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 2));
|
||||
secp256k1_ecmult(&r2, &ptgj, &sc[0], &sc[1]);
|
||||
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 2));
|
||||
secp256k1_gej_neg(&r2, &r2);
|
||||
secp256k1_gej_add_var(&r, &r, &r2, NULL);
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
|
||||
/* 2-point with G scalar */
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &sc[1]);
|
||||
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &sc[1], ecmult_multi_callback, &data, 1));
|
||||
secp256k1_ecmult(&r2, &ptgj, &sc[0], &sc[1]);
|
||||
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &sc[1], ecmult_multi_callback, &data, 1));
|
||||
secp256k1_gej_neg(&r2, &r2);
|
||||
secp256k1_gej_add_var(&r, &r, &r2, NULL);
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
@ -3810,7 +3884,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
|
||||
random_scalar_order(&sc[i]);
|
||||
secp256k1_ge_set_infinity(&pt[i]);
|
||||
}
|
||||
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
|
||||
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
}
|
||||
|
||||
@ -3820,7 +3894,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
|
||||
pt[i] = ptg;
|
||||
secp256k1_scalar_set_int(&sc[i], 0);
|
||||
}
|
||||
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
|
||||
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
}
|
||||
|
||||
@ -3833,7 +3907,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
|
||||
pt[2 * i + 1] = ptg;
|
||||
}
|
||||
|
||||
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
|
||||
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
|
||||
random_scalar_order(&sc[0]);
|
||||
@ -3846,7 +3920,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
|
||||
secp256k1_ge_neg(&pt[2*i+1], &pt[2*i]);
|
||||
}
|
||||
|
||||
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
|
||||
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
}
|
||||
|
||||
@ -3861,7 +3935,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
|
||||
secp256k1_scalar_negate(&sc[i], &sc[i]);
|
||||
}
|
||||
|
||||
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 32));
|
||||
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 32));
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
}
|
||||
|
||||
@ -3879,8 +3953,8 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
|
||||
secp256k1_gej_add_ge_var(&r, &r, &pt[i], NULL);
|
||||
}
|
||||
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &r, &sc[0], &szero);
|
||||
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
|
||||
secp256k1_ecmult(&r2, &r, &sc[0], &szero);
|
||||
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
|
||||
secp256k1_gej_neg(&r2, &r2);
|
||||
secp256k1_gej_add_var(&r, &r, &r2, NULL);
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
@ -3902,8 +3976,8 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
|
||||
}
|
||||
|
||||
secp256k1_gej_set_ge(&p0j, &pt[0]);
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &p0j, &rs, &szero);
|
||||
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
|
||||
secp256k1_ecmult(&r2, &p0j, &rs, &szero);
|
||||
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
|
||||
secp256k1_gej_neg(&r2, &r2);
|
||||
secp256k1_gej_add_var(&r, &r, &r2, NULL);
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
@ -3916,13 +3990,13 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
|
||||
}
|
||||
|
||||
secp256k1_scalar_clear(&sc[0]);
|
||||
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
|
||||
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
|
||||
secp256k1_scalar_clear(&sc[1]);
|
||||
secp256k1_scalar_clear(&sc[2]);
|
||||
secp256k1_scalar_clear(&sc[3]);
|
||||
secp256k1_scalar_clear(&sc[4]);
|
||||
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 6));
|
||||
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 5));
|
||||
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 6));
|
||||
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 5));
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
|
||||
/* Run through s0*(t0*P) + s1*(t1*P) exhaustively for many small values of s0, s1, t0, t1 */
|
||||
@ -3946,8 +4020,8 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
|
||||
secp256k1_scalar_set_int(&t1, (t1i + 1) / 2);
|
||||
secp256k1_scalar_cond_negate(&t1, t1i & 1);
|
||||
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &t0p, &ptgj, &t0, &szero);
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &t1p, &ptgj, &t1, &szero);
|
||||
secp256k1_ecmult(&t0p, &ptgj, &t0, &szero);
|
||||
secp256k1_ecmult(&t1p, &ptgj, &t1, &szero);
|
||||
|
||||
for(s0i = 0; s0i < TOP; s0i++) {
|
||||
for(s1i = 0; s1i < TOP; s1i++) {
|
||||
@ -3966,8 +4040,8 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
|
||||
secp256k1_scalar_mul(&tmp2, &t1, &sc[1]);
|
||||
secp256k1_scalar_add(&tmp1, &tmp1, &tmp2);
|
||||
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &expected, &ptgj, &tmp1, &szero);
|
||||
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &actual, &szero, ecmult_multi_callback, &data, 2));
|
||||
secp256k1_ecmult(&expected, &ptgj, &tmp1, &szero);
|
||||
CHECK(ecmult_multi(&ctx->error_callback, scratch, &actual, &szero, ecmult_multi_callback, &data, 2));
|
||||
secp256k1_gej_neg(&expected, &expected);
|
||||
secp256k1_gej_add_var(&actual, &actual, &expected, NULL);
|
||||
CHECK(secp256k1_gej_is_infinity(&actual));
|
||||
@ -3994,7 +4068,7 @@ void test_ecmult_multi_batch_single(secp256k1_ecmult_multi_func ecmult_multi) {
|
||||
|
||||
/* Try to multiply 1 point, but scratch space is empty.*/
|
||||
scratch_empty = secp256k1_scratch_create(&ctx->error_callback, 0);
|
||||
CHECK(!ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch_empty, &r, &szero, ecmult_multi_callback, &data, 1));
|
||||
CHECK(!ecmult_multi(&ctx->error_callback, scratch_empty, &r, &szero, ecmult_multi_callback, &data, 1));
|
||||
secp256k1_scratch_destroy(&ctx->error_callback, scratch_empty);
|
||||
}
|
||||
|
||||
@ -4116,7 +4190,7 @@ void test_ecmult_multi_batching(void) {
|
||||
|
||||
/* Get random scalars and group elements and compute result */
|
||||
random_scalar_order(&scG);
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &r2, &szero, &scG);
|
||||
secp256k1_ecmult(&r2, &r2, &szero, &scG);
|
||||
for(i = 0; i < n_points; i++) {
|
||||
secp256k1_ge ptg;
|
||||
secp256k1_gej ptgj;
|
||||
@ -4124,7 +4198,7 @@ void test_ecmult_multi_batching(void) {
|
||||
secp256k1_gej_set_ge(&ptgj, &ptg);
|
||||
pt[i] = ptg;
|
||||
random_scalar_order(&sc[i]);
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &ptgj, &ptgj, &sc[i], NULL);
|
||||
secp256k1_ecmult(&ptgj, &ptgj, &sc[i], NULL);
|
||||
secp256k1_gej_add_var(&r2, &r2, &ptgj, NULL);
|
||||
}
|
||||
data.sc = sc;
|
||||
@ -4134,7 +4208,7 @@ void test_ecmult_multi_batching(void) {
|
||||
/* Test with empty scratch space. It should compute the correct result using
|
||||
* ecmult_mult_simple algorithm which doesn't require a scratch space. */
|
||||
scratch = secp256k1_scratch_create(&ctx->error_callback, 0);
|
||||
CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
|
||||
CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
|
||||
secp256k1_gej_add_var(&r, &r, &r2, NULL);
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
secp256k1_scratch_destroy(&ctx->error_callback, scratch);
|
||||
@ -4143,7 +4217,7 @@ void test_ecmult_multi_batching(void) {
|
||||
* ecmult_multi selects strauss which requires more memory. It should
|
||||
* therefore select the simple algorithm. */
|
||||
scratch = secp256k1_scratch_create(&ctx->error_callback, secp256k1_pippenger_scratch_size(1, 1) + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT);
|
||||
CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
|
||||
CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
|
||||
secp256k1_gej_add_var(&r, &r, &r2, NULL);
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
secp256k1_scratch_destroy(&ctx->error_callback, scratch);
|
||||
@ -4157,7 +4231,7 @@ void test_ecmult_multi_batching(void) {
|
||||
size_t scratch_size = secp256k1_strauss_scratch_size(i);
|
||||
scratch = secp256k1_scratch_create(&ctx->error_callback, scratch_size + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT);
|
||||
}
|
||||
CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
|
||||
CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
|
||||
secp256k1_gej_add_var(&r, &r, &r2, NULL);
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
secp256k1_scratch_destroy(&ctx->error_callback, scratch);
|
||||
@ -4425,37 +4499,89 @@ void run_wnaf(void) {
|
||||
CHECK(secp256k1_scalar_is_zero(&n));
|
||||
}
|
||||
|
||||
static int test_ecmult_accumulate_cb(secp256k1_scalar* sc, secp256k1_ge* pt, size_t idx, void* data) {
|
||||
const secp256k1_scalar* indata = (const secp256k1_scalar*)data;
|
||||
*sc = *indata;
|
||||
*pt = secp256k1_ge_const_g;
|
||||
CHECK(idx == 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void test_ecmult_accumulate(secp256k1_sha256* acc, const secp256k1_scalar* x, secp256k1_scratch* scratch) {
|
||||
/* Compute x*G in 6 different ways, serialize it uncompressed, and feed it into acc. */
|
||||
secp256k1_gej rj1, rj2, rj3, rj4, rj5, rj6, gj, infj;
|
||||
secp256k1_ge r;
|
||||
const secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0);
|
||||
unsigned char bytes[65];
|
||||
size_t size = 65;
|
||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
|
||||
secp256k1_gej_set_infinity(&infj);
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj1, x);
|
||||
secp256k1_ecmult(&rj2, &gj, x, &zero);
|
||||
secp256k1_ecmult(&rj3, &infj, &zero, x);
|
||||
secp256k1_ecmult_multi_var(NULL, scratch, &rj4, x, NULL, NULL, 0);
|
||||
secp256k1_ecmult_multi_var(NULL, scratch, &rj5, &zero, test_ecmult_accumulate_cb, (void*)x, 1);
|
||||
secp256k1_ecmult_const(&rj6, &secp256k1_ge_const_g, x, 256);
|
||||
secp256k1_ge_set_gej_var(&r, &rj1);
|
||||
ge_equals_gej(&r, &rj2);
|
||||
ge_equals_gej(&r, &rj3);
|
||||
ge_equals_gej(&r, &rj4);
|
||||
ge_equals_gej(&r, &rj5);
|
||||
ge_equals_gej(&r, &rj6);
|
||||
if (secp256k1_ge_is_infinity(&r)) {
|
||||
/* Store infinity as 0x00 */
|
||||
const unsigned char zerobyte[1] = {0};
|
||||
secp256k1_sha256_write(acc, zerobyte, 1);
|
||||
} else {
|
||||
/* Store other points using their uncompressed serialization. */
|
||||
secp256k1_eckey_pubkey_serialize(&r, bytes, &size, 0);
|
||||
CHECK(size == 65);
|
||||
secp256k1_sha256_write(acc, bytes, size);
|
||||
}
|
||||
}
|
||||
|
||||
void test_ecmult_constants(void) {
|
||||
/* Test ecmult_gen() for [0..36) and [order-36..0). */
|
||||
/* Test ecmult_gen for:
|
||||
* - For i in 0..36:
|
||||
* - Key i
|
||||
* - Key -i
|
||||
* - For i in 0..255:
|
||||
* - For j in 1..255 (only odd values):
|
||||
* - Key (j*2^i) mod order
|
||||
*/
|
||||
secp256k1_scalar x;
|
||||
secp256k1_gej r;
|
||||
secp256k1_ge ng;
|
||||
int i;
|
||||
int j;
|
||||
secp256k1_ge_neg(&ng, &secp256k1_ge_const_g);
|
||||
for (i = 0; i < 36; i++ ) {
|
||||
secp256k1_scalar_set_int(&x, i);
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &r, &x);
|
||||
for (j = 0; j < i; j++) {
|
||||
if (j == i - 1) {
|
||||
ge_equals_gej(&secp256k1_ge_const_g, &r);
|
||||
}
|
||||
secp256k1_gej_add_ge(&r, &r, &ng);
|
||||
}
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
}
|
||||
for (i = 1; i <= 36; i++ ) {
|
||||
secp256k1_sha256 acc;
|
||||
unsigned char b32[32];
|
||||
int i, j;
|
||||
secp256k1_scratch_space *scratch = secp256k1_scratch_space_create(ctx, 65536);
|
||||
|
||||
/* Expected hash of all the computed points; created with an independent
|
||||
* implementation. */
|
||||
static const unsigned char expected32[32] = {
|
||||
0xe4, 0x71, 0x1b, 0x4d, 0x14, 0x1e, 0x68, 0x48,
|
||||
0xb7, 0xaf, 0x47, 0x2b, 0x4c, 0xd2, 0x04, 0x14,
|
||||
0x3a, 0x75, 0x87, 0x60, 0x1a, 0xf9, 0x63, 0x60,
|
||||
0xd0, 0xcb, 0x1f, 0xaa, 0x85, 0x9a, 0xb7, 0xb4
|
||||
};
|
||||
secp256k1_sha256_initialize(&acc);
|
||||
for (i = 0; i <= 36; ++i) {
|
||||
secp256k1_scalar_set_int(&x, i);
|
||||
test_ecmult_accumulate(&acc, &x, scratch);
|
||||
secp256k1_scalar_negate(&x, &x);
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &r, &x);
|
||||
for (j = 0; j < i; j++) {
|
||||
if (j == i - 1) {
|
||||
ge_equals_gej(&ng, &r);
|
||||
}
|
||||
secp256k1_gej_add_ge(&r, &r, &secp256k1_ge_const_g);
|
||||
test_ecmult_accumulate(&acc, &x, scratch);
|
||||
};
|
||||
for (i = 0; i < 256; ++i) {
|
||||
for (j = 1; j < 256; j += 2) {
|
||||
int k;
|
||||
secp256k1_scalar_set_int(&x, j);
|
||||
for (k = 0; k < i; ++k) secp256k1_scalar_add(&x, &x, &x);
|
||||
test_ecmult_accumulate(&acc, &x, scratch);
|
||||
}
|
||||
CHECK(secp256k1_gej_is_infinity(&r));
|
||||
}
|
||||
secp256k1_sha256_finalize(&acc, b32);
|
||||
CHECK(secp256k1_memcmp_var(b32, expected32, 32) == 0);
|
||||
|
||||
secp256k1_scratch_space_destroy(ctx, scratch);
|
||||
}
|
||||
|
||||
void run_ecmult_constants(void) {
|
||||
@ -5262,22 +5388,24 @@ void test_ecdsa_sign_verify(void) {
|
||||
secp256k1_scalar msg, key;
|
||||
secp256k1_scalar sigr, sigs;
|
||||
int getrec;
|
||||
/* Initialize recid to suppress a false positive -Wconditional-uninitialized in clang.
|
||||
VG_UNDEF ensures that valgrind will still treat the variable as uninitialized. */
|
||||
int recid = -1; VG_UNDEF(&recid, sizeof(recid));
|
||||
int recid;
|
||||
random_scalar_order_test(&msg);
|
||||
random_scalar_order_test(&key);
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubj, &key);
|
||||
secp256k1_ge_set_gej(&pub, &pubj);
|
||||
getrec = secp256k1_testrand_bits(1);
|
||||
random_sign(&sigr, &sigs, &key, &msg, getrec?&recid:NULL);
|
||||
/* The specific way in which this conditional is written sidesteps a potential bug in clang.
|
||||
See the commit messages of the commit that introduced this comment for details. */
|
||||
if (getrec) {
|
||||
random_sign(&sigr, &sigs, &key, &msg, &recid);
|
||||
CHECK(recid >= 0 && recid < 4);
|
||||
} else {
|
||||
random_sign(&sigr, &sigs, &key, &msg, NULL);
|
||||
}
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg));
|
||||
secp256k1_scalar_set_int(&one, 1);
|
||||
secp256k1_scalar_add(&msg, &msg, &one);
|
||||
CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg));
|
||||
CHECK(!secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg));
|
||||
}
|
||||
|
||||
void run_ecdsa_sign_verify(void) {
|
||||
@ -5609,14 +5737,6 @@ void run_ecdsa_end_to_end(void) {
|
||||
|
||||
int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_der, int certainly_not_der) {
|
||||
static const unsigned char zeroes[32] = {0};
|
||||
#ifdef ENABLE_OPENSSL_TESTS
|
||||
static const unsigned char max_scalar[32] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
|
||||
0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
|
||||
0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40
|
||||
};
|
||||
#endif
|
||||
|
||||
int ret = 0;
|
||||
|
||||
@ -5632,15 +5752,6 @@ int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_
|
||||
size_t len_der_lax = 2048;
|
||||
int parsed_der_lax = 0, valid_der_lax = 0, roundtrips_der_lax = 0;
|
||||
|
||||
#ifdef ENABLE_OPENSSL_TESTS
|
||||
ECDSA_SIG *sig_openssl;
|
||||
const BIGNUM *r = NULL, *s = NULL;
|
||||
const unsigned char *sigptr;
|
||||
unsigned char roundtrip_openssl[2048];
|
||||
int len_openssl = 2048;
|
||||
int parsed_openssl, valid_openssl = 0, roundtrips_openssl = 0;
|
||||
#endif
|
||||
|
||||
parsed_der = secp256k1_ecdsa_signature_parse_der(ctx, &sig_der, sig, siglen);
|
||||
if (parsed_der) {
|
||||
ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der, &sig_der)) << 0;
|
||||
@ -5681,43 +5792,6 @@ int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_
|
||||
ret |= (!parsed_der_lax) << 16;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_OPENSSL_TESTS
|
||||
sig_openssl = ECDSA_SIG_new();
|
||||
sigptr = sig;
|
||||
parsed_openssl = (d2i_ECDSA_SIG(&sig_openssl, &sigptr, siglen) != NULL);
|
||||
if (parsed_openssl) {
|
||||
ECDSA_SIG_get0(sig_openssl, &r, &s);
|
||||
valid_openssl = !BN_is_negative(r) && !BN_is_negative(s) && BN_num_bits(r) > 0 && BN_num_bits(r) <= 256 && BN_num_bits(s) > 0 && BN_num_bits(s) <= 256;
|
||||
if (valid_openssl) {
|
||||
unsigned char tmp[32] = {0};
|
||||
BN_bn2bin(r, tmp + 32 - BN_num_bytes(r));
|
||||
valid_openssl = secp256k1_memcmp_var(tmp, max_scalar, 32) < 0;
|
||||
}
|
||||
if (valid_openssl) {
|
||||
unsigned char tmp[32] = {0};
|
||||
BN_bn2bin(s, tmp + 32 - BN_num_bytes(s));
|
||||
valid_openssl = secp256k1_memcmp_var(tmp, max_scalar, 32) < 0;
|
||||
}
|
||||
}
|
||||
len_openssl = i2d_ECDSA_SIG(sig_openssl, NULL);
|
||||
if (len_openssl <= 2048) {
|
||||
unsigned char *ptr = roundtrip_openssl;
|
||||
CHECK(i2d_ECDSA_SIG(sig_openssl, &ptr) == len_openssl);
|
||||
roundtrips_openssl = valid_openssl && ((size_t)len_openssl == siglen) && (secp256k1_memcmp_var(roundtrip_openssl, sig, siglen) == 0);
|
||||
} else {
|
||||
len_openssl = 0;
|
||||
}
|
||||
ECDSA_SIG_free(sig_openssl);
|
||||
|
||||
ret |= (parsed_der && !parsed_openssl) << 4;
|
||||
ret |= (valid_der && !valid_openssl) << 5;
|
||||
ret |= (roundtrips_openssl && !parsed_der) << 6;
|
||||
ret |= (roundtrips_der != roundtrips_openssl) << 7;
|
||||
if (roundtrips_openssl) {
|
||||
ret |= (len_der != (size_t)len_openssl) << 8;
|
||||
ret |= ((len_der != (size_t)len_openssl) || (secp256k1_memcmp_var(roundtrip_der, roundtrip_openssl, len_der) != 0)) << 9;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -5955,7 +6029,7 @@ void test_ecdsa_edge_cases(void) {
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &keyj, &sr);
|
||||
secp256k1_ge_set_gej(&key, &keyj);
|
||||
msg = ss;
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
|
||||
}
|
||||
|
||||
/* Verify signature with r of zero fails. */
|
||||
@ -5974,7 +6048,7 @@ void test_ecdsa_edge_cases(void) {
|
||||
secp256k1_scalar_set_int(&msg, 0);
|
||||
secp256k1_scalar_set_int(&sr, 0);
|
||||
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey_mods_zero, 33));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
|
||||
CHECK(secp256k1_ecdsa_sig_verify( &sr, &ss, &key, &msg) == 0);
|
||||
}
|
||||
|
||||
/* Verify signature with s of zero fails. */
|
||||
@ -5993,7 +6067,7 @@ void test_ecdsa_edge_cases(void) {
|
||||
secp256k1_scalar_set_int(&msg, 0);
|
||||
secp256k1_scalar_set_int(&sr, 1);
|
||||
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
|
||||
}
|
||||
|
||||
/* Verify signature with message 0 passes. */
|
||||
@ -6021,14 +6095,14 @@ void test_ecdsa_edge_cases(void) {
|
||||
secp256k1_scalar_set_int(&sr, 2);
|
||||
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
|
||||
CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1);
|
||||
secp256k1_scalar_negate(&ss, &ss);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1);
|
||||
secp256k1_scalar_set_int(&ss, 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 0);
|
||||
}
|
||||
|
||||
/* Verify signature with message 1 passes. */
|
||||
@ -6062,15 +6136,15 @@ void test_ecdsa_edge_cases(void) {
|
||||
secp256k1_scalar_set_b32(&sr, csr, NULL);
|
||||
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
|
||||
CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1);
|
||||
secp256k1_scalar_negate(&ss, &ss);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1);
|
||||
secp256k1_scalar_set_int(&ss, 2);
|
||||
secp256k1_scalar_inverse_var(&ss, &ss);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 0);
|
||||
}
|
||||
|
||||
/* Verify signature with message -1 passes. */
|
||||
@ -6096,12 +6170,12 @@ void test_ecdsa_edge_cases(void) {
|
||||
secp256k1_scalar_negate(&msg, &msg);
|
||||
secp256k1_scalar_set_b32(&sr, csr, NULL);
|
||||
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
|
||||
secp256k1_scalar_negate(&ss, &ss);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
|
||||
secp256k1_scalar_set_int(&ss, 3);
|
||||
secp256k1_scalar_inverse_var(&ss, &ss);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
|
||||
}
|
||||
|
||||
/* Signature where s would be zero. */
|
||||
@ -6311,62 +6385,6 @@ void run_ecdsa_edge_cases(void) {
|
||||
test_ecdsa_edge_cases();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_OPENSSL_TESTS
|
||||
EC_KEY *get_openssl_key(const unsigned char *key32) {
|
||||
unsigned char privkey[300];
|
||||
size_t privkeylen;
|
||||
const unsigned char* pbegin = privkey;
|
||||
int compr = secp256k1_testrand_bits(1);
|
||||
EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
CHECK(ec_privkey_export_der(ctx, privkey, &privkeylen, key32, compr));
|
||||
CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen));
|
||||
CHECK(EC_KEY_check_key(ec_key));
|
||||
return ec_key;
|
||||
}
|
||||
|
||||
void test_ecdsa_openssl(void) {
|
||||
secp256k1_gej qj;
|
||||
secp256k1_ge q;
|
||||
secp256k1_scalar sigr, sigs;
|
||||
secp256k1_scalar one;
|
||||
secp256k1_scalar msg2;
|
||||
secp256k1_scalar key, msg;
|
||||
EC_KEY *ec_key;
|
||||
unsigned int sigsize = 80;
|
||||
size_t secp_sigsize = 80;
|
||||
unsigned char message[32];
|
||||
unsigned char signature[80];
|
||||
unsigned char key32[32];
|
||||
secp256k1_testrand256_test(message);
|
||||
secp256k1_scalar_set_b32(&msg, message, NULL);
|
||||
random_scalar_order_test(&key);
|
||||
secp256k1_scalar_get_b32(key32, &key);
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &qj, &key);
|
||||
secp256k1_ge_set_gej(&q, &qj);
|
||||
ec_key = get_openssl_key(key32);
|
||||
CHECK(ec_key != NULL);
|
||||
CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key));
|
||||
CHECK(secp256k1_ecdsa_sig_parse(&sigr, &sigs, signature, sigsize));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg));
|
||||
secp256k1_scalar_set_int(&one, 1);
|
||||
secp256k1_scalar_add(&msg2, &msg, &one);
|
||||
CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg2));
|
||||
|
||||
random_sign(&sigr, &sigs, &key, &msg, NULL);
|
||||
CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sigr, &sigs));
|
||||
CHECK(ECDSA_verify(0, message, sizeof(message), signature, secp_sigsize, ec_key) == 1);
|
||||
|
||||
EC_KEY_free(ec_key);
|
||||
}
|
||||
|
||||
void run_ecdsa_openssl(void) {
|
||||
int i;
|
||||
for (i = 0; i < 10*count; i++) {
|
||||
test_ecdsa_openssl();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MODULE_ECDH
|
||||
# include "modules/ecdh/tests_impl.h"
|
||||
#endif
|
||||
@ -6618,6 +6636,7 @@ int main(int argc, char **argv) {
|
||||
run_group_decompress();
|
||||
|
||||
/* ecmult tests */
|
||||
run_ecmult_pre_g();
|
||||
run_wnaf();
|
||||
run_point_times_order();
|
||||
run_ecmult_near_split_bound();
|
||||
@ -6652,9 +6671,6 @@ int main(int argc, char **argv) {
|
||||
run_ecdsa_sign_verify();
|
||||
run_ecdsa_end_to_end();
|
||||
run_ecdsa_edge_cases();
|
||||
#ifdef ENABLE_OPENSSL_TESTS
|
||||
run_ecdsa_openssl();
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MODULE_RECOVERY
|
||||
/* ECDSA pubkey recovery tests */
|
||||
|
@ -12,8 +12,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#undef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
|
||||
#ifndef EXHAUSTIVE_TEST_ORDER
|
||||
/* see group_impl.h for allowable values */
|
||||
#define EXHAUSTIVE_TEST_ORDER 13
|
||||
@ -24,6 +22,7 @@
|
||||
#include "assumptions.h"
|
||||
#include "group.h"
|
||||
#include "testrand_impl.h"
|
||||
#include "ecmult_gen_prec_impl.h"
|
||||
|
||||
static int count = 2;
|
||||
|
||||
@ -163,7 +162,7 @@ void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *gr
|
||||
}
|
||||
}
|
||||
|
||||
void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *group, const secp256k1_gej *groupj) {
|
||||
void test_exhaustive_ecmult(const secp256k1_ge *group, const secp256k1_gej *groupj) {
|
||||
int i, j, r_log;
|
||||
uint64_t iter = 0;
|
||||
for (r_log = 1; r_log < EXHAUSTIVE_TEST_ORDER; r_log++) {
|
||||
@ -175,7 +174,7 @@ void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *gr
|
||||
secp256k1_scalar_set_int(&na, i);
|
||||
secp256k1_scalar_set_int(&ng, j);
|
||||
|
||||
secp256k1_ecmult(&ctx->ecmult_ctx, &tmp, &groupj[r_log], &na, &ng);
|
||||
secp256k1_ecmult(&tmp, &groupj[r_log], &na, &ng);
|
||||
ge_equals_gej(&group[(i * r_log + j) % EXHAUSTIVE_TEST_ORDER], &tmp);
|
||||
|
||||
if (i > 0) {
|
||||
@ -219,7 +218,7 @@ void test_exhaustive_ecmult_multi(const secp256k1_context *ctx, const secp256k1_
|
||||
data.pt[0] = group[x];
|
||||
data.pt[1] = group[y];
|
||||
|
||||
secp256k1_ecmult_multi_var(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2);
|
||||
secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2);
|
||||
ge_equals_gej(&group[(i * x + j * y + k) % EXHAUSTIVE_TEST_ORDER], &tmp);
|
||||
}
|
||||
}
|
||||
@ -390,6 +389,9 @@ int main(int argc, char** argv) {
|
||||
printf("running tests for core %lu (out of [0..%lu])\n", (unsigned long)this_core, (unsigned long)num_cores - 1);
|
||||
}
|
||||
|
||||
/* Recreate the ecmult_gen table using the right generator (as selected via EXHAUSTIVE_TEST_ORDER) */
|
||||
secp256k1_ecmult_gen_create_prec_table(&secp256k1_ecmult_gen_prec_table[0][0], &secp256k1_ge_const_g, ECMULT_GEN_PREC_BITS);
|
||||
|
||||
while (count--) {
|
||||
/* Build context */
|
||||
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
@ -430,7 +432,7 @@ int main(int argc, char** argv) {
|
||||
/* Run the tests */
|
||||
test_exhaustive_endomorphism(group);
|
||||
test_exhaustive_addition(group, groupj);
|
||||
test_exhaustive_ecmult(ctx, group, groupj);
|
||||
test_exhaustive_ecmult(group, groupj);
|
||||
test_exhaustive_ecmult_multi(ctx, group);
|
||||
test_exhaustive_sign(ctx, group);
|
||||
test_exhaustive_verify(ctx, group);
|
||||
|
57
src/util.h
57
src/util.h
@ -25,6 +25,33 @@ static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback *
|
||||
cb->fn(text, (void*)cb->data);
|
||||
}
|
||||
|
||||
#ifndef USE_EXTERNAL_DEFAULT_CALLBACKS
|
||||
static void secp256k1_default_illegal_callback_fn(const char* str, void* data) {
|
||||
(void)data;
|
||||
fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str);
|
||||
abort();
|
||||
}
|
||||
static void secp256k1_default_error_callback_fn(const char* str, void* data) {
|
||||
(void)data;
|
||||
fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str);
|
||||
abort();
|
||||
}
|
||||
#else
|
||||
void secp256k1_default_illegal_callback_fn(const char* str, void* data);
|
||||
void secp256k1_default_error_callback_fn(const char* str, void* data);
|
||||
#endif
|
||||
|
||||
static const secp256k1_callback default_illegal_callback = {
|
||||
secp256k1_default_illegal_callback_fn,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const secp256k1_callback default_error_callback = {
|
||||
secp256k1_default_error_callback_fn,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
#ifdef DETERMINISTIC
|
||||
#define TEST_FAILURE(msg) do { \
|
||||
fprintf(stderr, "%s\n", msg); \
|
||||
@ -115,36 +142,6 @@ static SECP256K1_INLINE void *checked_realloc(const secp256k1_callback* cb, void
|
||||
|
||||
#define ROUND_TO_ALIGN(size) ((((size) + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT)
|
||||
|
||||
/* Assume there is a contiguous memory object with bounds [base, base + max_size)
|
||||
* of which the memory range [base, *prealloc_ptr) is already allocated for usage,
|
||||
* where *prealloc_ptr is an aligned pointer. In that setting, this functions
|
||||
* reserves the subobject [*prealloc_ptr, *prealloc_ptr + alloc_size) of
|
||||
* alloc_size bytes by increasing *prealloc_ptr accordingly, taking into account
|
||||
* alignment requirements.
|
||||
*
|
||||
* The function returns an aligned pointer to the newly allocated subobject.
|
||||
*
|
||||
* This is useful for manual memory management: if we're simply given a block
|
||||
* [base, base + max_size), the caller can use this function to allocate memory
|
||||
* in this block and keep track of the current allocation state with *prealloc_ptr.
|
||||
*
|
||||
* It is VERIFY_CHECKed that there is enough space left in the memory object and
|
||||
* *prealloc_ptr is aligned relative to base.
|
||||
*/
|
||||
static SECP256K1_INLINE void *manual_alloc(void** prealloc_ptr, size_t alloc_size, void* base, size_t max_size) {
|
||||
size_t aligned_alloc_size = ROUND_TO_ALIGN(alloc_size);
|
||||
void* ret;
|
||||
VERIFY_CHECK(prealloc_ptr != NULL);
|
||||
VERIFY_CHECK(*prealloc_ptr != NULL);
|
||||
VERIFY_CHECK(base != NULL);
|
||||
VERIFY_CHECK((unsigned char*)*prealloc_ptr >= (unsigned char*)base);
|
||||
VERIFY_CHECK(((unsigned char*)*prealloc_ptr - (unsigned char*)base) % ALIGNMENT == 0);
|
||||
VERIFY_CHECK((unsigned char*)*prealloc_ptr - (unsigned char*)base + aligned_alloc_size <= max_size);
|
||||
ret = *prealloc_ptr;
|
||||
*prealloc_ptr = (unsigned char*)*prealloc_ptr + aligned_alloc_size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Macro for restrict, when available and not in a VERIFY build. */
|
||||
#if defined(SECP256K1_BUILD) && defined(VERIFY)
|
||||
# define SECP256K1_RESTRICT
|
||||
|
Loading…
x
Reference in New Issue
Block a user