Merge bitcoin-core/secp256k1#988: Make signing table fully static
7dfceceea692c4118829c06128c41623b2373ac2 build: Remove #undef hack for ASM in the precomputation programs (Tim Ruffing) bb36fe9be0998c81ebc9f18e122bb7617d919877 ci: Test `make precomp` (Tim Ruffing) d94a37a20c3b5b44f1bcf60d309ffc50727e18e4 build: Remove CC_FOR_BUILD stuff (Tim Ruffing) ad63bb4c296e6007dab22cda05fd599b20139362 build: Prebuild and distribute ecmult_gen table (Tim Ruffing) ac49361ed0a342e01eafb1410c5b43e1214efaac prealloc: Get rid of manual memory management for prealloc contexts (Tim Ruffing) 6573c08f656f8ec305a2db801d57bfe6441e83e0 ecmult_gen: Tidy precomputed file and save space (Tim Ruffing) 5eba83f17c5aa1cf3698bb057a4b3ee35f3b6c30 ecmult_gen: Precompute tables for all values of ECMULT_GEN_PREC_BITS (Tim Ruffing) fdb33dd1227f935ca95c7f8bd9429f42e18a870e refactor: Make PREC_BITS a parameter of ecmult_gen_build_prec_table (Tim Ruffing) a4875e30a631d67b77b41f37fc3bf06ffb8ff11f refactor: Move default callbacks to util.h (Tim Ruffing) 4c94c55bce9e1fae8fd2e8993726c8ec74cc0f7d doc: Remove obsolete hint for valgrind stack size (Tim Ruffing) 5106226991117da78f85ca88b7ea66c2ac8fe0b3 exhaustive_tests: Fix with ecmult_gen table with custom generator (Tim Ruffing) e1a76530db40b8aa8953717d9f984b6bdf845308 refactor: Make generator a parameter of ecmult_gen_create_prec_table (Tim Ruffing) 9ad09f6911906a1fa9af2c5540a8004e44f3ccc6 refactor: Rename program that generates static ecmult_gen table (Tim Ruffing) 8ae18f1ab3dce4c487bab75c2f0cdf4fe311b318 refactor: Rename file that contains static ecmult_gen table (Tim Ruffing) 00d2fa116ed7a8c2d049723aca8d8b6d1c49f6a8 ecmult_gen: Make code consistent with comment (Tim Ruffing) 3b0c2185eab0fe5cb910fffee4c88e134f6d3cad ecmult_gen: Simplify ecmult_gen context after making table static (Tim Ruffing) e43ba02cfc836dba48c8c9a483e79b7589ce9ae1 refactor: Decouple table generation and ecmult_gen context (Tim Ruffing) 22dc2c0a0dc3b321e72253f492cfa8bcbf00169b ecmult_gen: Move table creation to new file and force static prec (Tim Ruffing) Pull request description: This resolves #893, resolves #692 (and also resolves bitcoin/bitcoin#22854). - [x] Extract table generation to separate function in separate file (to be used by generation script and exhaustive tests) - [x] Tidy up - [x] Remove code that deals with non-static tables - [x] Make functions that need ecmult_gen not depend on signing context - [x] Rename stuff to make it fit the new structure and consistent with how we hande verification tables (#956) - [x] Fix exhaustive tests - [x] Make table generation function take generator as input - [x] Overwrite the static tables with a table with custom generator in exhaustive tests - [x] Overhaul script that generates table files - [x] Make table generation function take PREC_BITS as input (I have some code already, just not yet in this branch) - [x] Change generation script to generate three tables (for all three values of ECMULT_GEN_PREC_BITS) - [x] Ship pre-built tables - [x] Add pregenerated table file to repo - [x] Remove generation of table file from build process (like in #956) - [x] Remove left-over stuff (e.g., detecting a compiler running on the build machine) from build system - [x] Final cleanups (copyright headers, commit, messages, etc.) - [ ] (separate PR:) Make sure link-time optimization remove corresponding static tables (and code) when no signing/verifcation function is called - [ ] (separate PR:) Compile precomputation as a separate object file and link it (https://github.com/bitcoin-core/secp256k1/pull/988#issuecomment-977813538) - [ ] (separate PR:) Document the backwards-compatible API changes made in this PR and in #956. - [ ] Maybe deprecate the static context ACKs for top commit: sipa: ACK 7dfceceea692c4118829c06128c41623b2373ac2 robot-dreams: ACK 7dfceceea692c4118829c06128c41623b2373ac2 (based on range-diff between 56284c7d44c0ed46e636588bfbf6c403b7dfa6c1 and 7dfceceea692c4118829c06128c41623b2373ac2) Tree-SHA512: 6efb3f36f05efe3b79bbd877881fe1409f71fd6488d24c811b2e77d9f053bed78670dd1dcbb42ad780458a51c4ffa36de9cd6567271b22041dc7a122ceb677c5
This commit is contained in:
commit
0559fc6e41
@ -294,7 +294,6 @@ task:
|
||||
- name: "UBSan, ASan, LSan"
|
||||
env:
|
||||
CFLAGS: "-fsanitize=undefined,address -g"
|
||||
CFLAGS_FOR_BUILD: "-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"
|
||||
|
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1 +1,2 @@
|
||||
src/ecmult_static_pre_g.h linguist-generated
|
||||
src/ecmult_gen_static_prec_table.h linguist-generated
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -3,7 +3,7 @@ bench_ecmult
|
||||
bench_internal
|
||||
tests
|
||||
exhaustive_tests
|
||||
gen_context
|
||||
gen_ecmult_gen_static_prec_table
|
||||
gen_ecmult_static_pre_g
|
||||
valgrind_ctime_test
|
||||
*.exe
|
||||
@ -41,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
|
||||
|
58
Makefile.am
58
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
|
||||
@ -115,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
|
||||
@ -124,36 +129,45 @@ exhaustive_tests_LDFLAGS = -static
|
||||
TESTS += exhaustive_tests
|
||||
endif
|
||||
|
||||
EXTRA_PROGRAMS = gen_ecmult_static_pre_g
|
||||
### Precomputed tables
|
||||
EXTRA_PROGRAMS = gen_ecmult_static_pre_g gen_ecmult_gen_static_prec_table
|
||||
CLEANFILES = $(EXTRA_PROGRAMS)
|
||||
|
||||
gen_ecmult_static_pre_g_SOURCES = src/gen_ecmult_static_pre_g.c
|
||||
# See Automake manual, Section "Errors with distclean"
|
||||
gen_ecmult_static_pre_g_CPPFLAGS = $(SECP_INCLUDES)
|
||||
gen_ecmult_static_pre_g_LDADD = $(SECP_LIBS) $(COMMON_LIB)
|
||||
|
||||
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)
|
||||
|
||||
# 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)
|
||||
|
||||
if USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) -I$(builddir)/src
|
||||
PRECOMP = src/ecmult_gen_static_prec_table.h src/ecmult_static_pre_g.h
|
||||
noinst_HEADERS += $(PRECOMP)
|
||||
precomp: $(PRECOMP)
|
||||
|
||||
gen_context_OBJECTS = gen_context.o
|
||||
gen_context_BIN = gen_context$(BUILD_EXEEXT)
|
||||
$(gen_context_OBJECTS): src/gen_context.c src/libsecp256k1-config.h
|
||||
$(CC_FOR_BUILD) $(DEFS) $(CPPFLAGS_FOR_BUILD) $(SECP_CFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@
|
||||
# Ensure the prebuilt files will be build first (only if they don't exist,
|
||||
# e.g., after `make maintainer-clean`).
|
||||
BUILT_SOURCES = $(PRECOMP)
|
||||
|
||||
$(gen_context_BIN): $(gen_context_OBJECTS)
|
||||
$(CC_FOR_BUILD) $(SECP_CFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) $^ -o $@
|
||||
maintainer-clean-local: clean-precomp
|
||||
|
||||
$(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
|
||||
clean-precomp:
|
||||
rm -f $(PRECOMP)
|
||||
|
||||
src/ecmult_static_context.h: $(gen_context_BIN)
|
||||
./$(gen_context_BIN)
|
||||
|
||||
CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h
|
||||
endif
|
||||
|
||||
EXTRA_DIST = autogen.sh src/gen_context.c src/ecmult_static_pre_g.h src/basic-config.h
|
||||
EXTRA_DIST = autogen.sh SECURITY.md
|
||||
|
||||
if ENABLE_MODULE_ECDH
|
||||
include src/modules/ecdh/Makefile.am.include
|
||||
|
11
README.md
11
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
|
||||
-----------
|
||||
|
||||
|
@ -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
|
||||
])
|
12
ci/cirrus.sh
12
ci/cirrus.sh
@ -48,7 +48,19 @@ then
|
||||
$EXEC ./bench
|
||||
} >> bench.log 2>&1
|
||||
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
|
||||
|
96
configure.ac
96
configure.ac
@ -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
|
||||
# accidentally 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])
|
||||
@ -125,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],
|
||||
@ -213,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
|
||||
@ -325,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
|
||||
###
|
||||
@ -461,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"])
|
||||
@ -478,7 +391,6 @@ 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"
|
||||
@ -502,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
|
||||
|
@ -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
@ -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;
|
||||
}
|
@ -13,12 +13,6 @@
|
||||
#include "libsecp256k1-config.h"
|
||||
#endif
|
||||
|
||||
/* 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"
|
||||
|
@ -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) {
|
||||
|
@ -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,29 +67,31 @@ 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 */
|
||||
|
||||
@ -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) {
|
||||
|
@ -132,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);
|
||||
@ -157,42 +160,46 @@ 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);
|
||||
@ -217,6 +224,7 @@ void test_schnorrsig_api(void) {
|
||||
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
|
||||
|
@ -44,34 +44,6 @@
|
||||
} \
|
||||
} 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_gen_context ecmult_gen_ctx;
|
||||
secp256k1_callback illegal_callback;
|
||||
@ -88,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);
|
||||
|
||||
@ -98,23 +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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigned int flags) {
|
||||
void* const base = prealloc;
|
||||
size_t prealloc_size;
|
||||
secp256k1_context* ret;
|
||||
|
||||
@ -127,20 +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_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);
|
||||
}
|
||||
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) {
|
||||
@ -155,15 +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);
|
||||
*ret = *ctx;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
32
src/tests.c
32
src/tests.c
@ -143,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;
|
||||
@ -158,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);
|
||||
@ -189,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 ***/
|
||||
{
|
||||
@ -252,12 +259,12 @@ 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);
|
||||
@ -265,33 +272,33 @@ void run_context_tests(int use_prealloc) {
|
||||
CHECK(ecount2 == 10);
|
||||
CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 1);
|
||||
CHECK(ecount2 == 10);
|
||||
CHECK(secp256k1_ecdsa_verify(vrfy, &sig, ctmp, &pubkey) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(sttc, &sig, ctmp, &pubkey) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 1);
|
||||
CHECK(ecount2 == 10);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(vrfy, &pubkey, ctmp) == 1);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(sttc, &pubkey, ctmp) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 1);
|
||||
CHECK(ecount2 == 10);
|
||||
CHECK(secp256k1_ec_pubkey_negate(vrfy, &pubkey) == 1);
|
||||
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 == 11);
|
||||
CHECK(secp256k1_ec_pubkey_negate(vrfy, &zero_pubkey) == 0);
|
||||
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 == 11);
|
||||
CHECK(secp256k1_context_randomize(sign, NULL) == 1);
|
||||
CHECK(ecount2 == 11);
|
||||
secp256k1_context_set_illegal_callback(vrfy, NULL, NULL);
|
||||
secp256k1_context_set_illegal_callback(sttc, NULL, NULL);
|
||||
secp256k1_context_set_illegal_callback(sign, NULL, NULL);
|
||||
|
||||
/* obtain a working nonce */
|
||||
@ -313,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);
|
||||
|
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
59
src/util.h
59
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,38 +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);
|
||||
/* Avoid unused parameter warnings when building without VERIFY */
|
||||
(void) base; (void) 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