Squashed 'src/secp256k1/' changes from 705ce7ed8c..c545fdc374

c545fdc374 Merge bitcoin-core/secp256k1#1298: Remove randomness tests
b40e2d30b7 Merge bitcoin-core/secp256k1#1378: ellswift: fix probabilistic test failure when swapping sides
c424e2fb43 ellswift: fix probabilistic test failure when swapping sides
907a67212e Merge bitcoin-core/secp256k1#1313: ci: Test on development snapshots of GCC and Clang
0f7657d59c Merge bitcoin-core/secp256k1#1366: field: Use `restrict` consistently in fe_sqrt
cc55757552 Merge bitcoin-core/secp256k1#1340: clean up in-comment Sage code (refer to secp256k1_params.sage, update to Python3)
600c5adcd5 clean up in-comment Sage code (refer to secp256k1_params.sage, update to Python3)
981e5be38c ci: Fix typo in comment
e9e9648219 ci: Reduce number of macOS tasks from 28 to 8
609093b387 ci: Add x86_64 Linux tasks for gcc and clang snapshots
1deecaaf3b ci: Install development snapshots of gcc and clang
b79ba8aa4c field: Use `restrict` consistently in fe_sqrt
c9ebca95f9 Merge bitcoin-core/secp256k1#1363: doc: minor ellswift.md updates
afd7eb4a55 Merge bitcoin-core/secp256k1#1371: Add exhaustive tests for ellswift (with create+decode roundtrip)
2792119278 Add exhaustive test for ellswift (create+decode roundtrip)
c7d900ffd1 doc: minor ellswift.md updates
332af315fc Merge bitcoin-core/secp256k1#1344: group: save normalize_weak calls in `secp256k1_ge_is_valid_var`/`secp256k1_gej_eq_x_var`
9e6d1b0e9b Merge bitcoin-core/secp256k1#1367: build: Improvements to symbol visibility logic on Windows (attempt 3)
0aacf64352 Merge bitcoin-core/secp256k1#1370: Corrected some typos
b6b9834e8d small fixes
07c0e8b82e group: remove unneeded normalize_weak in `secp256k1_gej_eq_x_var`
3fc1de5c55 Merge bitcoin-core/secp256k1#1364: Avoid `-Wmaybe-uninitialized` when compiling with `gcc -O1`
fb758fe8d6 Merge bitcoin-core/secp256k1#1323: tweak_add: fix API doc for tweak=0
c6cd2b15a0 ci: Add task for static library on Windows + CMake
020bf69a44 build: Add extensive docs on visibility issues
0196e8ade1 build: Introduce `SECP256k1_DLL_EXPORT` macro
9f1b1904a3 refactor: Replace `SECP256K1_API_VAR` with `SECP256K1_API`
ae9db95cea build: Introduce `SECP256K1_STATIC` macro for Windows users
7966aee31d Merge bitcoin-core/secp256k1#1369: ci: Print commit in Windows container
a7bec34231 ci: Print commit in Windows container
249c81eaa3 Merge bitcoin-core/secp256k1#1368: ci: Drop manual checkout of merge commit
98579e297b ci: Drop manual checkout of merge commit
5b9f37f136 ci: Add `CFLAGS: -O1` to task matrix
a6ca76cdf2 Avoid `-Wmaybe-uninitialized` when compiling with `gcc -O1`
0fa84f869d Merge bitcoin-core/secp256k1#1358: tests: introduce helper for non-zero `random_fe_test()` results
5a95a268b9 tests: introduce helper for non-zero `random_fe_test` results
304421d57b tests: refactor: remove duplicate function `random_field_element_test`
3aef6ab8e1 Merge bitcoin-core/secp256k1#1345: field: Static-assert that int args affecting magnitude are constant
4494a369b6 Merge bitcoin-core/secp256k1#1357: tests: refactor: take use of `secp256k1_ge_x_on_curve_var`
799f4eec27 Merge bitcoin-core/secp256k1#1356: ci: Adjust Docker image to Debian 12 "bookworm"
c862a9fb49 ci: Adjust Docker image to Debian 12 "bookworm"
a1782098a9 ci: Force DWARF v4 for Clang when Valgrind tests are expected
7d8d5c86df tests: refactor: take use of `secp256k1_ge_x_on_curve_var`
8a7273465b Help the compiler prove that a loop is entered
fd491ea1bb Merge bitcoin-core/secp256k1#1355: Fix a typo in the error message
ac43613d25 Merge bitcoin-core/secp256k1#1354: Add ellswift to CHANGELOG
67887ae65c Fix a typo in the error message
926dd3e962 Merge bitcoin-core/secp256k1#1295: abi: Use dllexport for mingw builds
10836832e7 Merge bitcoin-core/secp256k1#1336: Use `__shiftright128` intrinsic in `secp256k1_u128_rshift` on MSVC
7c7467ab7f Refer to ellswift.md in API docs
c32ffd8d8c Add ellswift to CHANGELOG
3c1a0fd37f Merge bitcoin-core/secp256k1#1347: field: Document return value of fe_sqrt()
5779137457 field: Document return value of fe_sqrt()
be8ff3a02a field: Static-assert that int args affecting magnitude are constant
efa76c4bf7 group: remove unneeded normalize_weak in `secp256k1_ge_is_valid_var`
5b7bf2e9d4 Use `__shiftright128` intrinsic in `secp256k1_u128_rshift` on MSVC
05873bb6b1 tweak_add: fix API doc for tweak=0
6ec3731e8c Simplify test PRNG implementation
fb5bfa4eed Add static test vector for Xoshiro256++
723e8ca8f7 Remove randomness tests
bc7c8db179 abi: Use dllexport for mingw builds

git-subtree-dir: src/secp256k1
git-subtree-split: c545fdc374964424683d9dac31a828adedabe860
This commit is contained in:
fanquake 2023-07-18 15:25:05 +01:00
parent 901336eee7
commit ff061fde18
36 changed files with 373 additions and 331 deletions

View file

@ -54,12 +54,6 @@ cat_logs_snippet: &CAT_LOGS
cat_ci_env_script:
- env
merge_base_script_snippet: &MERGE_BASE
merge_base_script:
- if [ "$CIRRUS_PR" = "" ]; then exit 0; fi
- git fetch --depth=1 $CIRRUS_REPO_CLONE_URL "pull/${CIRRUS_PR}/merge"
- git checkout FETCH_HEAD # Use merged changes to detect silent merge conflicts
linux_container_snippet: &LINUX_CONTAINER
container:
dockerfile: ci/linux-debian.Dockerfile
@ -68,12 +62,12 @@ linux_container_snippet: &LINUX_CONTAINER
# Gives us more CPUs for free if they're available.
greedy: true
# More than enough for our scripts.
memory: 1G
memory: 2G
task:
name: "x86_64: Linux (Debian stable)"
<< : *LINUX_CONTAINER
matrix: &ENV_MATRIX
matrix:
- env: {WIDEMUL: int64, RECOVERY: yes}
- env: {WIDEMUL: int64, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes}
- env: {WIDEMUL: int128}
@ -86,6 +80,7 @@ task:
- env: {BUILD: distcheck, WITH_VALGRIND: no, CTIMETESTS: no, BENCH: no}
- env: {CPPFLAGS: -DDETERMINISTIC}
- env: {CFLAGS: -O0, CTIMETESTS: no}
- env: {CFLAGS: -O1, RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes}
- env: { ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 }
- env: { ECMULTGENPRECISION: 8, ECMULTWINDOW: 4 }
matrix:
@ -93,7 +88,10 @@ task:
CC: gcc
- env:
CC: clang
<< : *MERGE_BASE
- env:
CC: gcc-snapshot
- env:
CC: clang-snapshot
test_script:
- ./ci/cirrus.sh
<< : *CAT_LOGS
@ -111,7 +109,6 @@ task:
CC: i686-linux-gnu-gcc
- env:
CC: clang --target=i686-pc-linux-gnu -isystem /usr/i686-linux-gnu/include
<< : *MERGE_BASE
test_script:
- ./ci/cirrus.sh
<< : *CAT_LOGS
@ -125,20 +122,22 @@ task:
HOMEBREW_NO_INSTALL_CLEANUP: 1
# Cirrus gives us a fixed number of 4 virtual CPUs. Not that we even have that many jobs at the moment...
MAKEFLAGS: -j5
matrix:
<< : *ENV_MATRIX
env:
ASM: no
WITH_VALGRIND: no
CTIMETESTS: no
CC: clang
matrix:
- env:
CC: gcc
- env:
CC: clang
- env: {WIDEMUL: int64, RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes}
- env: {WIDEMUL: int64, RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes, CC: gcc}
- env: {WIDEMUL: int128_struct, ECMULTGENPRECISION: 2, ECMULTWINDOW: 4}
- env: {WIDEMUL: int128, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes}
- env: {WIDEMUL: int128, RECOVERY: yes, SCHNORRSIG: yes}
- env: {WIDEMUL: int128, RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes, CC: gcc}
- env: {WIDEMUL: int128, RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes, CPPFLAGS: -DVERIFY}
- env: {BUILD: distcheck}
brew_script:
- brew install automake libtool gcc
<< : *MERGE_BASE
test_script:
- ./ci/cirrus.sh
<< : *CAT_LOGS
@ -157,7 +156,6 @@ task:
SCHNORRSIG: yes
ELLSWIFT: yes
CTIMETESTS: no
<< : *MERGE_BASE
test_script:
# https://sourceware.org/bugzilla/show_bug.cgi?id=27008
- rm /etc/ld.so.cache
@ -180,7 +178,6 @@ task:
matrix:
- env: {}
- env: {EXPERIMENTAL: yes, ASM: arm32}
<< : *MERGE_BASE
test_script:
- ./ci/cirrus.sh
<< : *CAT_LOGS
@ -198,7 +195,6 @@ task:
SCHNORRSIG: yes
ELLSWIFT: yes
CTIMETESTS: no
<< : *MERGE_BASE
test_script:
- ./ci/cirrus.sh
<< : *CAT_LOGS
@ -216,7 +212,6 @@ task:
SCHNORRSIG: yes
ELLSWIFT: yes
CTIMETESTS: no
<< : *MERGE_BASE
test_script:
- ./ci/cirrus.sh
<< : *CAT_LOGS
@ -237,7 +232,6 @@ task:
- name: "i686 (mingw32-w64): Windows (Debian stable, Wine)"
env:
HOST: i686-w64-mingw32
<< : *MERGE_BASE
test_script:
- ./ci/cirrus.sh
<< : *CAT_LOGS
@ -280,7 +274,6 @@ task:
CC: /opt/msvc/bin/x86/cl
AR: /opt/msvc/bin/x86/lib
NM: /opt/msvc/bin/x86/dumpbin -symbols -headers
<< : *MERGE_BASE
test_script:
- ./ci/cirrus.sh
<< : *CAT_LOGS
@ -325,7 +318,6 @@ task:
- env:
HOST: i686-linux-gnu
CC: i686-linux-gnu-gcc
<< : *MERGE_BASE
test_script:
- ./ci/cirrus.sh
<< : *CAT_LOGS
@ -352,7 +344,6 @@ task:
ECMULTGENPRECISION: 2
ECMULTWINDOW: 2
CFLAGS: "-fsanitize=memory -g -O3"
<< : *MERGE_BASE
test_script:
- ./ci/cirrus.sh
<< : *CAT_LOGS
@ -369,7 +360,6 @@ task:
RECOVERY: yes
SCHNORRSIG: yes
ELLSWIFT: yes
<< : *MERGE_BASE
test_script:
- ./ci/cirrus.sh
<< : *CAT_LOGS
@ -401,11 +391,17 @@ task:
# Ignore MSBuild warning MSB8029.
# See: https://learn.microsoft.com/en-us/visualstudio/msbuild/errors/msb8029?view=vs-2022
IgnoreWarnIntDirInTempDetected: 'true'
merge_script:
- PowerShell -NoLogo -Command if ($env:CIRRUS_PR -ne $null) { git fetch $env:CIRRUS_REPO_CLONE_URL pull/$env:CIRRUS_PR/merge; git reset --hard FETCH_HEAD; }
matrix:
- env:
BUILD_SHARED_LIBS: ON
- env:
BUILD_SHARED_LIBS: OFF
git_show_script:
# Print commit to allow reproducing the job outside of CI.
- git show --no-patch
configure_script:
- '%x64_NATIVE_TOOLS%'
- cmake -E env CFLAGS="/WX" cmake -G "Visual Studio 17 2022" -A x64 -S . -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_BUILD_EXAMPLES=ON
- cmake -E env CFLAGS="/WX" cmake -A x64 -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_BUILD_EXAMPLES=ON -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS%
build_script:
- '%x64_NATIVE_TOOLS%'
- cmake --build build --config RelWithDebInfo -- -property:UseMultiToolTask=true;CL_MPcount=5

View file

@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
#### Added
- New module `ellswift` implements ElligatorSwift encoding for public keys and x-only Diffie-Hellman key exchange for them.
ElligatorSwift permits representing secp256k1 public keys as 64-byte arrays which cannot be distinguished from uniformly random. See:
- Header file `include/secp256k1_ellswift.h` which defines the new API.
- Document `doc/ellswift.md` which explains the mathematical background of the scheme.
- The [paper](https://eprint.iacr.org/2022/759) on which the scheme is based.
#### Changed
- When consuming libsecp256k1 as a static library on Windows, the user must now define the `SECP256K1_STATIC` macro before including `secp256k1.h`.
## [0.3.2] - 2023-05-13
We strongly recommend updating to 0.3.2 if you use or plan to use GCC >=13 to compile libsecp256k1. When in doubt, check the GCC version using `gcc -v`.

View file

@ -153,7 +153,7 @@ endif
if USE_EXAMPLES
noinst_PROGRAMS += ecdsa_example
ecdsa_example_SOURCES = examples/ecdsa.c
ecdsa_example_CPPFLAGS = -I$(top_srcdir)/include
ecdsa_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC
ecdsa_example_LDADD = libsecp256k1.la
ecdsa_example_LDFLAGS = -static
if BUILD_WINDOWS
@ -163,7 +163,7 @@ TESTS += ecdsa_example
if ENABLE_MODULE_ECDH
noinst_PROGRAMS += ecdh_example
ecdh_example_SOURCES = examples/ecdh.c
ecdh_example_CPPFLAGS = -I$(top_srcdir)/include
ecdh_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC
ecdh_example_LDADD = libsecp256k1.la
ecdh_example_LDFLAGS = -static
if BUILD_WINDOWS
@ -174,7 +174,7 @@ endif
if ENABLE_MODULE_SCHNORRSIG
noinst_PROGRAMS += schnorr_example
schnorr_example_SOURCES = examples/schnorr.c
schnorr_example_CPPFLAGS = -I$(top_srcdir)/include
schnorr_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC
schnorr_example_LDADD = libsecp256k1.la
schnorr_example_LDFLAGS = -static
if BUILD_WINDOWS

View file

@ -4,7 +4,8 @@ set -eux
export LC_ALL=C
# Print relevant CI environment to allow reproducing the job outside of CI.
# Print commit and relevant CI environment to allow reproducing the job outside of CI.
git show --no-patch
print_environment() {
# Turn off -x because it messes up the output
set +x
@ -53,6 +54,22 @@ if [ -n "$WRAPPER_CMD" ]; then
$WRAPPER_CMD --version
fi
# Workaround for https://bugs.kde.org/show_bug.cgi?id=452758 (fixed in valgrind 3.20.0).
case "${CC:-undefined}" in
clang*)
if [ "$CTIMETESTS" = "yes" ] && [ "$WITH_VALGRIND" = "yes" ]
then
export CFLAGS="${CFLAGS:+$CFLAGS }-gdwarf-4"
else
case "$WRAPPER_CMD" in
valgrind*)
export CFLAGS="${CFLAGS:+$CFLAGS }-gdwarf-4"
;;
esac
fi
;;
esac
./autogen.sh
./configure \

View file

@ -1,5 +1,7 @@
FROM debian:stable
SHELL ["/bin/bash", "-c"]
RUN dpkg --add-architecture i386 && \
dpkg --add-architecture s390x && \
dpkg --add-architecture armhf && \
@ -9,11 +11,11 @@ RUN dpkg --add-architecture i386 && \
# dkpg-dev: to make pkg-config work in cross-builds
# llvm: for llvm-symbolizer, which is used by clang's UBSan for symbolized stack traces
RUN apt-get update && apt-get install --no-install-recommends -y \
git ca-certificates \
git ca-certificates wget \
make automake libtool pkg-config dpkg-dev valgrind qemu-user \
gcc clang llvm libc6-dbg \
gcc clang llvm libclang-rt-dev libc6-dbg \
g++ \
gcc-i686-linux-gnu libc6-dev-i386-cross libc6-dbg:i386 libubsan1:i386 libasan6:i386 \
gcc-i686-linux-gnu libc6-dev-i386-cross libc6-dbg:i386 libubsan1:i386 libasan8: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 \
@ -23,9 +25,44 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
sagemath
WORKDIR /root
# The "wine" package provides a convience wrapper that we need
# Build and install gcc snapshot
ARG GCC_SNAPSHOT_MAJOR=14
RUN wget --progress=dot:giga --https-only --recursive --accept '*.tar.xz' --level 1 --no-directories "https://gcc.gnu.org/pub/gcc/snapshots/LATEST-${GCC_SNAPSHOT_MAJOR}" && \
wget "https://gcc.gnu.org/pub/gcc/snapshots/LATEST-${GCC_SNAPSHOT_MAJOR}/sha512.sum" && \
sha512sum --check --ignore-missing sha512.sum && \
# We should have downloaded exactly one tar.xz file
ls && \
[[ $(ls *.tar.xz | wc -l) -eq "1" ]] && \
tar xf *.tar.xz && \
mkdir gcc-build && cd gcc-build && \
apt-get update && apt-get install --no-install-recommends -y libgmp-dev libmpfr-dev libmpc-dev flex && \
../*/configure --prefix=/opt/gcc-snapshot --enable-languages=c --disable-bootstrap --disable-multilib --without-isl && \
make -j $(nproc) && \
make install && \
ln -s /opt/gcc-snapshot/bin/gcc /usr/bin/gcc-snapshot
# Install clang snapshot
RUN wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc && \
# Add repository for this Debian release
. /etc/os-release && echo "deb http://apt.llvm.org/${VERSION_CODENAME} llvm-toolchain-${VERSION_CODENAME} main" >> /etc/apt/sources.list && \
# Install clang snapshot
apt-get update && apt-get install --no-install-recommends -y clang && \
# Remove just the "clang" symlink again
apt-get remove -y clang && \
# We should have exactly two clang versions now
ls /usr/bin/clang* && \
[[ $(ls /usr/bin/clang-?? | sort | wc -l) -eq "2" ]] && \
# Create symlinks for them
ln -s $(ls /usr/bin/clang-?? | sort | tail -1) /usr/bin/clang-snapshot && \
ln -s $(ls /usr/bin/clang-?? | sort | head -1) /usr/bin/clang
# The "wine" package provides a convenience wrapper that we need
RUN apt-get update && apt-get install --no-install-recommends -y \
git ca-certificates wine64 wine python3-simplejson python3-six msitools winbind procps && \
# Workaround for `wine` package failure to employ the Debian alternatives system properly.
ln -s /usr/lib/wine/wine64 /usr/bin/wine64 && \
# Set of tools for using MSVC on Linux.
git clone https://github.com/mstorsjo/msvc-wine && \
mkdir /opt/msvc && \
python3 msvc-wine/vsdownload.py --accept-license --dest /opt/msvc Microsoft.VisualStudio.Workload.VCTools && \

View file

@ -127,12 +127,6 @@ AC_DEFUN([SECP_TRY_APPEND_DEFAULT_CFLAGS], [
SECP_TRY_APPEND_CFLAGS([-wd4267], $1) # Disable warning C4267 "'var' : conversion from 'size_t' to 'type', possible loss of data".
# Eliminate deprecation warnings for the older, less secure functions.
CPPFLAGS="-D_CRT_SECURE_NO_WARNINGS $CPPFLAGS"
# We pass -ignore:4217 to the MSVC linker to suppress warning 4217 when
# importing variables from a statically linked secp256k1.
# (See the libtool manual, section "Windows DLLs" for background.)
# Unfortunately, libtool tries to be too clever and strips "-Xlinker arg"
# into "arg", so this will be " -Xlinker -ignore:4217" after stripping.
LDFLAGS="-Xlinker -Xlinker -Xlinker -ignore:4217 $LDFLAGS"
fi
])
SECP_TRY_APPEND_DEFAULT_CFLAGS(SECP_CFLAGS)

View file

@ -88,7 +88,7 @@ $$
\begin{array}{lcl}
X(u, t) & = & \left\\{\begin{array}{ll}
\dfrac{g(u) - t^2}{2t} & a = 0 \\
\dfrac{g(u) + h(u)(Y_0(u) + X_0(u)t)^2}{X_0(u)(1 + h(u)t^2)} & a \neq 0
\dfrac{g(u) + h(u)(Y_0(u) - X_0(u)t)^2}{X_0(u)(1 + h(u)t^2)} & a \neq 0
\end{array}\right. \\
Y(u, t) & = & \left\\{\begin{array}{ll}
\dfrac{X(u, t) + t}{u \sqrt{-3}} = \dfrac{g(u) + t^2}{2tu\sqrt{-3}} & a = 0 \\
@ -329,7 +329,7 @@ $t$ value for multiple $c$ inputs (thereby biasing that encoding):
it requires $g(u)=0$ which is already outlawed on even-ordered curves and impossible on others; in the second it would trigger division by zero.
* Curve-specific special cases also exist that need to be rejected, because they result in $(u,t)$ which is invalid to the decoder, or because of division by zero in the encoder:
* For $a=0$ curves, when $u=0$ or when $t=0$. The latter can only be reached by the encoder when $g(u)=0$, which requires an even-ordered curve.
* For $a \neq 0$ curves, when $X_0(u)=0$, when $h(u)t^2 = -1$, or when $2w(u + 2v) = 2X_0(u)$ while also either $w \neq 2Y_0(u)$ or $h(u)=0$.
* For $a \neq 0$ curves, when $X_0(u)=0$, when $h(u)t^2 = -1$, or when $w(u + 2v) = 2X_0(u)$ while also either $w \neq 2Y_0(u)$ or $h(u)=0$.
**Define** a version of $G_{c,u}(x)$ which deals with all these cases:
* If $a=0$ and $u=0$, return $\bot.$

View file

@ -6,9 +6,6 @@ target_link_libraries(example INTERFACE
secp256k1
$<$<PLATFORM_ID:Windows>:bcrypt>
)
if(NOT BUILD_SHARED_LIBS AND MSVC)
target_link_options(example INTERFACE /IGNORE:4217)
endif()
add_executable(ecdsa_example ecdsa.c)
target_link_libraries(ecdsa_example example)

View file

@ -95,7 +95,7 @@ static void secure_erase(void *ptr, size_t len) {
* As best as we can tell, this is sufficient to break any optimisations that
* might try to eliminate "superfluous" memsets.
* This method used in memzero_explicit() the Linux kernel, too. Its advantage is that it is
* pretty efficient, because the compiler can still implement the memset() efficently,
* pretty efficient, because the compiler can still implement the memset() efficiently,
* just not remove it entirely. See "Dead Store Elimination (Still) Considered Harmful" by
* Yang et al. (USENIX Security 2017) for more background.
*/

View file

@ -133,28 +133,35 @@ typedef int (*secp256k1_nonce_function)(
# define SECP256K1_NO_BUILD
#endif
/* Symbol visibility. See libtool manual, section "Windows DLLs". */
#if defined(_WIN32) && !defined(__GNUC__)
# ifdef SECP256K1_BUILD
# ifdef DLL_EXPORT
# define SECP256K1_API __declspec (dllexport)
# define SECP256K1_API_VAR extern __declspec (dllexport)
/* Symbol visibility. */
#if defined(_WIN32)
/* GCC for Windows (e.g., MinGW) accepts the __declspec syntax
* for MSVC compatibility. A __declspec declaration implies (but is not
* exactly equivalent to) __attribute__ ((visibility("default"))), and so we
* actually want __declspec even on GCC, see "Microsoft Windows Function
* Attributes" in the GCC manual and the recommendations in
* https://gcc.gnu.org/wiki/Visibility. */
# if defined(SECP256K1_BUILD)
# if defined(DLL_EXPORT) || defined(SECP256K1_DLL_EXPORT)
/* Building libsecp256k1 as a DLL.
* 1. If using Libtool, it defines DLL_EXPORT automatically.
* 2. In other cases, SECP256K1_DLL_EXPORT must be defined. */
# define SECP256K1_API extern __declspec (dllexport)
# endif
# elif defined _MSC_VER
# define SECP256K1_API
# define SECP256K1_API_VAR extern __declspec (dllimport)
# elif defined DLL_EXPORT
# define SECP256K1_API __declspec (dllimport)
# define SECP256K1_API_VAR extern __declspec (dllimport)
/* The user must define SECP256K1_STATIC when consuming libsecp256k1 as a static
* library on Windows. */
# elif !defined(SECP256K1_STATIC)
/* Consuming libsecp256k1 as a DLL. */
# define SECP256K1_API extern __declspec (dllimport)
# endif
#endif
#ifndef SECP256K1_API
# if defined(__GNUC__) && (__GNUC__ >= 4) && defined(SECP256K1_BUILD)
# define SECP256K1_API __attribute__ ((visibility ("default")))
# define SECP256K1_API_VAR extern __attribute__ ((visibility ("default")))
/* Building libsecp256k1 on non-Windows using GCC or compatible. */
# define SECP256K1_API extern __attribute__ ((visibility ("default")))
# else
# define SECP256K1_API
# define SECP256K1_API_VAR extern
/* All cases not captured above. */
# define SECP256K1_API extern
# endif
#endif
@ -226,10 +233,10 @@ typedef int (*secp256k1_nonce_function)(
*
* It is highly recommended to call secp256k1_selftest before using this context.
*/
SECP256K1_API_VAR const secp256k1_context *secp256k1_context_static;
SECP256K1_API const secp256k1_context *secp256k1_context_static;
/** Deprecated alias for secp256k1_context_static. */
SECP256K1_API_VAR const secp256k1_context *secp256k1_context_no_precomp
SECP256K1_API const secp256k1_context *secp256k1_context_no_precomp
SECP256K1_DEPRECATED("Use secp256k1_context_static instead");
/** Perform basic self tests (to be used in conjunction with secp256k1_context_static)
@ -626,10 +633,10 @@ SECP256K1_API int secp256k1_ecdsa_signature_normalize(
* If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
* extra entropy.
*/
SECP256K1_API_VAR const secp256k1_nonce_function secp256k1_nonce_function_rfc6979;
SECP256K1_API const secp256k1_nonce_function secp256k1_nonce_function_rfc6979;
/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */
SECP256K1_API_VAR const secp256k1_nonce_function secp256k1_nonce_function_default;
SECP256K1_API const secp256k1_nonce_function secp256k1_nonce_function_default;
/** Create an ECDSA signature.
*
@ -733,10 +740,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate(
* invalid according to secp256k1_ec_seckey_verify, this
* function returns 0. seckey will be set to some unspecified
* 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).
* In: tweak32: pointer to a 32-byte tweak, which must be valid according to
* secp256k1_ec_seckey_verify or 32 zero bytes. For uniformly
* random 32-byte tweaks, the chance of being invalid is
* negligible (around 1 in 2^128).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_add(
const secp256k1_context *ctx,
@ -761,10 +768,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
* Args: ctx: pointer to a context object.
* In/Out: pubkey: pointer to a public key object. pubkey will be set to 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).
* In: tweak32: pointer to a 32-byte tweak, which must be valid according to
* secp256k1_ec_seckey_verify or 32 zero bytes. For uniformly
* random 32-byte tweaks, the chance of being invalid is
* negligible (around 1 in 2^128).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
const secp256k1_context *ctx,

View file

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

View file

@ -41,6 +41,8 @@ extern "C" {
* - The paper uses an additional encoding bit for the parity of y. Here the
* parity of t is used (negating t does not affect the decoded x coordinate,
* so this is possible).
*
* For mathematical background about the scheme, see the doc/ellswift.md file.
*/
/** A pointer to a function used by secp256k1_ellswift_xdh to hash the shared X
@ -70,7 +72,7 @@ typedef int (*secp256k1_ellswift_xdh_hash_function)(
/** An implementation of an secp256k1_ellswift_xdh_hash_function which uses
* SHA256(prefix64 || ell_a64 || ell_b64 || x32), where prefix64 is the 64-byte
* array pointed to by data. */
SECP256K1_API_VAR const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix;
SECP256K1_API const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix;
/** An implementation of an secp256k1_ellswift_xdh_hash_function compatible with
* BIP324. It returns H_tag(ell_a64 || ell_b64 || x32), where H_tag is the
@ -78,7 +80,7 @@ SECP256K1_API_VAR const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_
* to secp256k1_ellswift_xdh_hash_function_prefix with prefix64 set to
* SHA256("bip324_ellswift_xonly_ecdh")||SHA256("bip324_ellswift_xonly_ecdh").
* The data argument is ignored. */
SECP256K1_API_VAR const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324;
SECP256K1_API const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324;
/** Construct a 64-byte ElligatorSwift encoding of a given pubkey.
*
@ -159,7 +161,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ellswift_create(
/** Given a private key, and ElligatorSwift public keys sent in both directions,
* compute a shared secret using x-only Elliptic Curve Diffie-Hellman (ECDH).
*
* Returns: 1: shared secret was succesfully computed
* Returns: 1: shared secret was successfully computed
* 0: secret was invalid or hashfp returned 0
* Args: ctx: pointer to a context object.
* Out: output: pointer to an array to be filled by hashfp.

View file

@ -112,10 +112,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubke
* Out: output_pubkey: pointer to a public key to store the result. Will be set
* to an invalid value if this function returns 0.
* In: internal_pubkey: pointer to an x-only pubkey to apply the tweak to.
* 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).
* tweak32: pointer to a 32-byte tweak, which must be valid
* according to secp256k1_ec_seckey_verify or 32 zero
* bytes. For uniformly random 32-byte tweaks, the 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,
@ -229,10 +229,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub(
* Args: ctx: pointer to a context object.
* In/Out: keypair: pointer to a keypair to apply the tweak to. Will be set to
* 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).
* In: tweak32: pointer to a 32-byte tweak, which must be valid according to
* secp256k1_ec_seckey_verify or 32 zero bytes. For uniformly
* random 32-byte tweaks, the chance of being invalid is
* negligible (around 1 in 2^128).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_tweak_add(
const secp256k1_context *ctx,

View file

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

View file

@ -198,7 +198,7 @@ def normalize_factor(p):
(8) * (-bx + ax)^3
```
"""
# Assert p is not 0 and that its non-zero coeffients are coprime.
# Assert p is not 0 and that its non-zero coefficients are coprime.
# (We could just work with the primitive part p/p.content() but we want to be
# aware if factor() does not return a primitive part in future sage versions.)
assert p.content() == 1

View file

@ -20,10 +20,10 @@ if(SECP256K1_ASM STREQUAL "arm32")
target_link_libraries(secp256k1_asm INTERFACE secp256k1_asm_arm)
endif()
# Define our export symbol only for Win32 and only for shared libs.
# This matches libtool's usage of DLL_EXPORT
if(WIN32)
set_target_properties(secp256k1 PROPERTIES DEFINE_SYMBOL "DLL_EXPORT")
# Define our export symbol only for shared libs.
set_target_properties(secp256k1 PROPERTIES DEFINE_SYMBOL SECP256K1_DLL_EXPORT)
target_compile_definitions(secp256k1 INTERFACE $<$<NOT:$<BOOL:${BUILD_SHARED_LIBS}>>:SECP256K1_STATIC>)
endif()
# Object libs don't know if they're being built for a shared or static lib.

View file

@ -16,17 +16,8 @@
#include "ecdsa.h"
/** Group order for secp256k1 defined as 'n' in "Standards for Efficient Cryptography" (SEC2) 2.7.1
* sage: for t in xrange(1023, -1, -1):
* .. p = 2**256 - 2**32 - t
* .. if p.is_prime():
* .. print '%x'%p
* .. break
* 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'
* sage: a = 0
* sage: b = 7
* sage: F = FiniteField (p)
* sage: '%x' % (EllipticCurve ([F (a), F (b)]).order())
* 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'
* $ sage -c 'load("secp256k1_params.sage"); print(hex(N))'
* 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
*/
static const secp256k1_fe secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST(
0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL,
@ -35,12 +26,8 @@ static const secp256k1_fe secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST
/** Difference between field and order, values 'p' and 'n' values defined in
* "Standards for Efficient Cryptography" (SEC2) 2.7.1.
* sage: p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
* sage: a = 0
* sage: b = 7
* sage: F = FiniteField (p)
* sage: '%x' % (p - EllipticCurve ([F (a), F (b)]).order())
* '14551231950b75fc4402da1722fc9baee'
* $ sage -c 'load("secp256k1_params.sage"); print(hex(P-N))'
* 0x14551231950b75fc4402da1722fc9baee
*/
static const secp256k1_fe secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_CONST(
0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL

View file

@ -22,7 +22,7 @@
# pragma message DEBUG_CONFIG_DEF(ECMULT_WINDOW_SIZE)
#endif
/* Noone will ever need more than a window size of 24. The code might
/* No one 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.
*

View file

@ -276,7 +276,7 @@ static int secp256k1_ecmult_const_xonly(secp256k1_fe* r, const secp256k1_fe *n,
*
* It is easy to verify that both (n*g, g^2, v) and its negation (n*g, -g^2, v) have affine X
* coordinate n/d, and this holds even when the square root function doesn't have a
* determinstic sign. We choose the (n*g, g^2, v) version.
* deterministic sign. We choose the (n*g, g^2, v) version.
*
* Now switch to the effective affine curve using phi_v, where the input point has coordinates
* (n*g, g^2). Compute (X, Y, Z) = q * (n*g, g^2) there.

View file

@ -22,6 +22,9 @@ static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, cons
secp256k1_gej nums_gej;
int i, j;
VERIFY_CHECK(g > 0);
VERIFY_CHECK(n > 0);
/* get the generator */
secp256k1_gej_set_ge(&gj, gen);

View file

@ -288,7 +288,9 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
}
/* Bring them to the same Z denominator. */
secp256k1_ge_table_set_globalz(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, state->aux);
if (no) {
secp256k1_ge_table_set_globalz(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, state->aux);
}
for (np = 0; np < no; ++np) {
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {

View file

@ -88,8 +88,8 @@ static const secp256k1_fe secp256k1_const_beta = SECP256K1_FE_CONST(
# define secp256k1_fe_set_b32_mod secp256k1_fe_impl_set_b32_mod
# define secp256k1_fe_set_b32_limit secp256k1_fe_impl_set_b32_limit
# define secp256k1_fe_get_b32 secp256k1_fe_impl_get_b32
# define secp256k1_fe_negate secp256k1_fe_impl_negate
# define secp256k1_fe_mul_int secp256k1_fe_impl_mul_int
# define secp256k1_fe_negate_unchecked secp256k1_fe_impl_negate_unchecked
# define secp256k1_fe_mul_int_unchecked secp256k1_fe_impl_mul_int_unchecked
# define secp256k1_fe_add secp256k1_fe_impl_add
# define secp256k1_fe_mul secp256k1_fe_impl_mul
# define secp256k1_fe_sqr secp256k1_fe_impl_sqr
@ -192,14 +192,14 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b);
/** Set a field element equal to a provided 32-byte big endian value, reducing it.
*
* On input, r does not need to be initalized. a must be a pointer to an initialized 32-byte array.
* On input, r does not need to be initialized. a must be a pointer to an initialized 32-byte array.
* On output, r = a (mod p). It will have magnitude 1, and not be normalized.
*/
static void secp256k1_fe_set_b32_mod(secp256k1_fe *r, const unsigned char *a);
/** Set a field element equal to a provided 32-byte big endian value, checking for overflow.
*
* On input, r does not need to be initalized. a must be a pointer to an initialized 32-byte array.
* On input, r does not need to be initialized. a must be a pointer to an initialized 32-byte array.
* On output, r = a if (a < p), it will be normalized with magnitude 1, and 1 is returned.
* If a >= p, 0 is returned, and r will be made invalid (and must not be used without overwriting).
*/
@ -214,11 +214,17 @@ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a);
/** Negate a field element.
*
* On input, r does not need to be initialized. a must be a valid field element with
* magnitude not exceeding m. m must be an integer in [0,31].
* magnitude not exceeding m. m must be an integer constant expression in [0,31].
* Performs {r = -a}.
* On output, r will not be normalized, and will have magnitude m+1.
*/
static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m);
#define secp256k1_fe_negate(r, a, m) ASSERT_INT_CONST_AND_DO(m, secp256k1_fe_negate_unchecked(r, a, m))
/** Like secp256k1_fe_negate_unchecked but m is not checked to be an integer constant expression.
*
* Should not be called directly outside of tests.
*/
static void secp256k1_fe_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m);
/** Add a small integer to a field element.
*
@ -229,12 +235,18 @@ static void secp256k1_fe_add_int(secp256k1_fe *r, int a);
/** Multiply a field element with a small integer.
*
* On input, r must be a valid field element. a must be an integer in [0,32].
* On input, r must be a valid field element. a must be an integer constant expression in [0,32].
* The magnitude of r times a must not exceed 32.
* Performs {r *= a}.
* On output, r's magnitude is multiplied by a, and r will not be normalized.
*/
static void secp256k1_fe_mul_int(secp256k1_fe *r, int a);
#define secp256k1_fe_mul_int(r, a) ASSERT_INT_CONST_AND_DO(a, secp256k1_fe_mul_int_unchecked(r, a))
/** Like secp256k1_fe_mul_int but a is not checked to be an integer constant expression.
*
* Should not be called directly outside of tests.
*/
static void secp256k1_fe_mul_int_unchecked(secp256k1_fe *r, int a);
/** Increment a field element by another.
*
@ -267,8 +279,10 @@ static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a);
/** Compute a square root of a field element.
*
* On input, a must be a valid field element with magnitude<=8; r need not be initialized.
* Performs {r = sqrt(a)} or {r = sqrt(-a)}, whichever exists. The resulting value
* represented by r will be a square itself. Variables r and a must not point to the same object.
* If sqrt(a) exists, performs {r = sqrt(a)} and returns 1.
* Otherwise, sqrt(-a) exists. The function performs {r = sqrt(-a)} and returns 0.
* The resulting value represented by r will be a square itself.
* Variables r and a must not point to the same object.
* On output, r will have magnitude 1 but will not be normalized.
*/
static int secp256k1_fe_sqrt(secp256k1_fe * SECP256K1_RESTRICT r, const secp256k1_fe * SECP256K1_RESTRICT a);

View file

@ -344,7 +344,7 @@ static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a) {
r[31] = a->n[0] & 0xff;
}
SECP256K1_INLINE static void secp256k1_fe_impl_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
SECP256K1_INLINE static void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m) {
/* For all legal values of m (0..31), the following properties hold: */
VERIFY_CHECK(0x3FFFC2FUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
VERIFY_CHECK(0x3FFFFBFUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
@ -365,7 +365,7 @@ SECP256K1_INLINE static void secp256k1_fe_impl_negate(secp256k1_fe *r, const sec
r->n[9] = 0x03FFFFFUL * 2 * (m + 1) - a->n[9];
}
SECP256K1_INLINE static void secp256k1_fe_impl_mul_int(secp256k1_fe *r, int a) {
SECP256K1_INLINE static void secp256k1_fe_impl_mul_int_unchecked(secp256k1_fe *r, int a) {
r->n[0] *= a;
r->n[1] *= a;
r->n[2] *= a;

View file

@ -314,7 +314,7 @@ static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a) {
r[31] = a->n[0] & 0xFF;
}
SECP256K1_INLINE static void secp256k1_fe_impl_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
SECP256K1_INLINE static void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m) {
/* For all legal values of m (0..31), the following properties hold: */
VERIFY_CHECK(0xFFFFEFFFFFC2FULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m);
VERIFY_CHECK(0xFFFFFFFFFFFFFULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m);
@ -329,7 +329,7 @@ SECP256K1_INLINE static void secp256k1_fe_impl_negate(secp256k1_fe *r, const sec
r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4];
}
SECP256K1_INLINE static void secp256k1_fe_impl_mul_int(secp256k1_fe *r, int a) {
SECP256K1_INLINE static void secp256k1_fe_impl_mul_int_unchecked(secp256k1_fe *r, int a) {
r->n[0] *= a;
r->n[1] *= a;
r->n[2] *= a;

View file

@ -44,7 +44,7 @@ SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const
return secp256k1_fe_normalizes_to_zero_var(&na);
}
static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) {
static int secp256k1_fe_sqrt(secp256k1_fe * SECP256K1_RESTRICT r, const secp256k1_fe * SECP256K1_RESTRICT a) {
/** Given that p is congruent to 3 mod 4, we can compute the square root of
* a mod p as the (p+1)/4'th power of a.
*
@ -289,23 +289,23 @@ SECP256K1_INLINE static void secp256k1_fe_get_b32(unsigned char *r, const secp25
secp256k1_fe_impl_get_b32(r, a);
}
static void secp256k1_fe_impl_negate(secp256k1_fe *r, const secp256k1_fe *a, int m);
SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
static void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m);
SECP256K1_INLINE static void secp256k1_fe_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m) {
secp256k1_fe_verify(a);
VERIFY_CHECK(m >= 0 && m <= 31);
VERIFY_CHECK(a->magnitude <= m);
secp256k1_fe_impl_negate(r, a, m);
secp256k1_fe_impl_negate_unchecked(r, a, m);
r->magnitude = m + 1;
r->normalized = 0;
secp256k1_fe_verify(r);
}
static void secp256k1_fe_impl_mul_int(secp256k1_fe *r, int a);
SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) {
static void secp256k1_fe_impl_mul_int_unchecked(secp256k1_fe *r, int a);
SECP256K1_INLINE static void secp256k1_fe_mul_int_unchecked(secp256k1_fe *r, int a) {
secp256k1_fe_verify(r);
VERIFY_CHECK(a >= 0 && a <= 32);
VERIFY_CHECK(a*r->magnitude <= 32);
secp256k1_fe_impl_mul_int(r, a);
secp256k1_fe_impl_mul_int_unchecked(r, a);
r->magnitude *= a;
r->normalized = 0;
secp256k1_fe_verify(r);

View file

@ -106,7 +106,8 @@ static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a);
/** Check two group elements (jacobian) for equality in variable time. */
static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b);
/** Compare the X coordinate of a group element (jacobian). */
/** Compare the X coordinate of a group element (jacobian).
* The magnitude of the group element's X coordinate must not exceed 31. */
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a);
/** Set r equal to the inverse of a (i.e., mirrored around the X axis) */

View file

@ -314,13 +314,17 @@ static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b)
}
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) {
secp256k1_fe r, r2;
secp256k1_fe r;
#ifdef VERIFY
secp256k1_fe_verify(x);
VERIFY_CHECK(a->x.magnitude <= 31);
secp256k1_gej_verify(a);
VERIFY_CHECK(!a->infinity);
#endif
secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x);
r2 = a->x; secp256k1_fe_normalize_weak(&r2);
return secp256k1_fe_equal_var(&r, &r2);
return secp256k1_fe_equal_var(&r, &a->x);
}
static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) {
@ -349,7 +353,6 @@ static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) {
secp256k1_fe_sqr(&y2, &a->y);
secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
secp256k1_fe_add_int(&x3, SECP256K1_B);
secp256k1_fe_normalize_weak(&x3);
return secp256k1_fe_equal_var(&y2, &x3);
}

View file

@ -80,7 +80,12 @@ static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigne
r->lo = r->hi >> (n-64);
r->hi = 0;
} else if (n > 0) {
#if defined(_MSC_VER) && defined(_M_X64)
VERIFY_CHECK(n < 64);
r->lo = __shiftright128(r->lo, r->hi, n);
#else
r->lo = ((1U * r->hi) << (64-n)) | r->lo >> n;
#endif
r->hi >>= n;
}
}

View file

@ -2,3 +2,4 @@ include_HEADERS += include/secp256k1_ellswift.h
noinst_HEADERS += src/modules/ellswift/bench_impl.h
noinst_HEADERS += src/modules/ellswift/main_impl.h
noinst_HEADERS += src/modules/ellswift/tests_impl.h
noinst_HEADERS += src/modules/ellswift/tests_exhaustive_impl.h

View file

@ -0,0 +1,39 @@
/***********************************************************************
* Distributed under the MIT software license, see the accompanying *
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
***********************************************************************/
#ifndef SECP256K1_MODULE_ELLSWIFT_TESTS_EXHAUSTIVE_H
#define SECP256K1_MODULE_ELLSWIFT_TESTS_EXHAUSTIVE_H
#include "../../../include/secp256k1_ellswift.h"
#include "main_impl.h"
static void test_exhaustive_ellswift(const secp256k1_context *ctx, const secp256k1_ge *group) {
int i;
/* Note that SwiftEC/ElligatorSwift are inherently curve operations, not
* group operations, and this test only checks the curve points which are in
* a tiny subgroup. In that sense it can't be really seen as exhaustive as
* it doesn't (and for computational reasons obviously cannot) test the
* entire domain ellswift operates under. */
for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) {
secp256k1_scalar scalar_i;
unsigned char sec32[32];
unsigned char ell64[64];
secp256k1_pubkey pub_decoded;
secp256k1_ge ge_decoded;
/* Construct ellswift pubkey from exhaustive loop scalar i. */
secp256k1_scalar_set_int(&scalar_i, i);
secp256k1_scalar_get_b32(sec32, &scalar_i);
CHECK(secp256k1_ellswift_create(ctx, ell64, sec32, NULL));
/* Decode ellswift pubkey and check that it matches the precomputed group element. */
secp256k1_ellswift_decode(ctx, &pub_decoded, ell64);
secp256k1_pubkey_load(ctx, &ge_decoded, &pub_decoded);
ge_equals_ge(&ge_decoded, &group[i]);
}
}
#endif

View file

@ -322,7 +322,9 @@ void run_ellswift_tests(void) {
secp256k1_testrand256_test(auxrnd32a);
secp256k1_testrand256_test(auxrnd32b);
random_scalar_order_test(&seca);
random_scalar_order_test(&secb);
/* Draw secb uniformly at random to make sure that the secret keys
* differ */
random_scalar_order(&secb);
secp256k1_scalar_get_b32(sec32a, &seca);
secp256k1_scalar_get_b32(sec32b, &secb);

View file

@ -56,11 +56,12 @@ static void print_two_tables(FILE *fp, int window_g) {
int main(void) {
/* Always compute all tables for window sizes up to 15. */
int window_g = (ECMULT_WINDOW_SIZE < 15) ? 15 : ECMULT_WINDOW_SIZE;
const char outfile[] = "src/precomputed_ecmult.c";
FILE* fp;
fp = fopen("src/precomputed_ecmult.c","w");
fp = fopen(outfile, "w");
if (fp == NULL) {
fprintf(stderr, "Could not open src/precomputed_ecmult.h for writing!\n");
fprintf(stderr, "Could not open %s for writing!\n", outfile);
return -1;
}

View file

@ -16,8 +16,6 @@
#include "util.h"
static uint64_t secp256k1_test_state[4];
static uint64_t secp256k1_test_rng_integer;
static int secp256k1_test_rng_integer_bits_left = 0;
SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16) {
static const unsigned char PREFIX[19] = "secp256k1 test init";
@ -36,7 +34,6 @@ SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16
for (j = 0; j < 8; ++j) s = (s << 8) | out32[8*i + j];
secp256k1_test_state[i] = s;
}
secp256k1_test_rng_integer_bits_left = 0;
}
SECP256K1_INLINE static uint64_t rotl(const uint64_t x, int k) {
@ -57,58 +54,30 @@ SECP256K1_INLINE static uint64_t secp256k1_testrand64(void) {
}
SECP256K1_INLINE static uint64_t secp256k1_testrand_bits(int bits) {
uint64_t ret;
if (secp256k1_test_rng_integer_bits_left < bits) {
secp256k1_test_rng_integer = secp256k1_testrand64();
secp256k1_test_rng_integer_bits_left = 64;
}
ret = secp256k1_test_rng_integer;
secp256k1_test_rng_integer >>= bits;
secp256k1_test_rng_integer_bits_left -= bits;
ret &= ((~((uint64_t)0)) >> (64 - bits));
return ret;
if (bits == 0) return 0;
return secp256k1_testrand64() >> (64 - bits);
}
SECP256K1_INLINE static uint32_t secp256k1_testrand32(void) {
return secp256k1_testrand_bits(32);
return secp256k1_testrand64() >> 32;
}
static uint32_t secp256k1_testrand_int(uint32_t range) {
/* We want a uniform integer between 0 and range-1, inclusive.
* B is the smallest number such that range <= 2**B.
* two mechanisms implemented here:
* - generate B bits numbers until one below range is found, and return it
* - find the largest multiple M of range that is <= 2**(B+A), generate B+A
* bits numbers until one below M is found, and return it modulo range
* The second mechanism consumes A more bits of entropy in every iteration,
* but may need fewer iterations due to M being closer to 2**(B+A) then
* range is to 2**B. The array below (indexed by B) contains a 0 when the
* first mechanism is to be used, and the number A otherwise.
*/
static const int addbits[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0};
uint32_t trange, mult;
int bits = 0;
if (range <= 1) {
return 0;
uint32_t mask = 0;
uint32_t range_copy;
/* Reduce range by 1, changing its meaning to "maximum value". */
VERIFY_CHECK(range != 0);
range -= 1;
/* Count the number of bits in range. */
range_copy = range;
while (range_copy) {
mask = (mask << 1) | 1U;
range_copy >>= 1;
}
trange = range - 1;
while (trange > 0) {
trange >>= 1;
bits++;
}
if (addbits[bits]) {
bits = bits + addbits[bits];
mult = ((~((uint32_t)0)) >> (32 - bits)) / range;
trange = range * mult;
} else {
trange = range;
mult = 1;
}
while(1) {
uint32_t x = secp256k1_testrand_bits(bits);
if (x < trange) {
return (mult == 1) ? x : (x % range);
}
/* Generation loop. */
while (1) {
uint32_t val = secp256k1_testrand64() & mask;
if (val <= range) return val;
}
}

View file

@ -89,16 +89,6 @@ static void uncounting_illegal_callback_fn(const char* str, void* data) {
(*p)--;
}
static void random_field_element_test(secp256k1_fe *fe) {
do {
unsigned char b32[32];
secp256k1_testrand256_test(b32);
if (secp256k1_fe_set_b32_limit(fe, b32)) {
break;
}
} while(1);
}
static void random_field_element_magnitude(secp256k1_fe *fe) {
secp256k1_fe zero;
int n = secp256k1_testrand_int(9);
@ -108,17 +98,33 @@ static void random_field_element_magnitude(secp256k1_fe *fe) {
}
secp256k1_fe_clear(&zero);
secp256k1_fe_negate(&zero, &zero, 0);
secp256k1_fe_mul_int(&zero, n - 1);
secp256k1_fe_mul_int_unchecked(&zero, n - 1);
secp256k1_fe_add(fe, &zero);
#ifdef VERIFY
CHECK(fe->magnitude == n);
#endif
}
static void random_fe_test(secp256k1_fe *x) {
unsigned char bin[32];
do {
secp256k1_testrand256_test(bin);
if (secp256k1_fe_set_b32_limit(x, bin)) {
return;
}
} while(1);
}
static void random_fe_non_zero_test(secp256k1_fe *fe) {
do {
random_fe_test(fe);
} while(secp256k1_fe_is_zero(fe));
}
static void random_group_element_test(secp256k1_ge *ge) {
secp256k1_fe fe;
do {
random_field_element_test(&fe);
random_fe_test(&fe);
if (secp256k1_ge_set_xo_var(ge, &fe, secp256k1_testrand_bits(1))) {
secp256k1_fe_normalize(&ge->y);
break;
@ -129,12 +135,7 @@ static void random_group_element_test(secp256k1_ge *ge) {
static void random_group_element_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) {
secp256k1_fe z2, z3;
do {
random_field_element_test(&gej->z);
if (!secp256k1_fe_is_zero(&gej->z)) {
break;
}
} while(1);
random_fe_non_zero_test(&gej->z);
secp256k1_fe_sqr(&z2, &gej->z);
secp256k1_fe_mul(&z3, &z2, &gej->z);
secp256k1_fe_mul(&gej->x, &ge->x, &z2);
@ -180,6 +181,35 @@ static void random_scalar_order_b32(unsigned char *b32) {
secp256k1_scalar_get_b32(b32, &num);
}
static void run_xoshiro256pp_tests(void) {
{
size_t i;
/* Sanity check that we run before the actual seeding. */
for (i = 0; i < sizeof(secp256k1_test_state)/sizeof(secp256k1_test_state[0]); i++) {
CHECK(secp256k1_test_state[i] == 0);
}
}
{
int i;
unsigned char buf32[32];
unsigned char seed16[16] = {
'C', 'H', 'I', 'C', 'K', 'E', 'N', '!',
'C', 'H', 'I', 'C', 'K', 'E', 'N', '!',
};
unsigned char buf32_expected[32] = {
0xAF, 0xCC, 0xA9, 0x16, 0xB5, 0x6C, 0xE3, 0xF0,
0x44, 0x3F, 0x45, 0xE0, 0x47, 0xA5, 0x08, 0x36,
0x4C, 0xCC, 0xC1, 0x18, 0xB2, 0xD8, 0x8F, 0xEF,
0x43, 0x26, 0x15, 0x57, 0x37, 0x00, 0xEF, 0x30,
};
secp256k1_testrand_seed(seed16);
for (i = 0; i < 17; i++) {
secp256k1_testrand256(buf32);
}
CHECK(secp256k1_memcmp_var(buf32, buf32_expected, sizeof(buf32)) == 0);
}
}
static void run_selftest_tests(void) {
/* Test public API */
secp256k1_selftest();
@ -823,78 +853,6 @@ static void run_tagged_sha256_tests(void) {
CHECK(secp256k1_memcmp_var(hash32, hash_expected, sizeof(hash32)) == 0);
}
/***** RANDOM TESTS *****/
static void test_rand_bits(int rand32, int bits) {
/* (1-1/2^B)^rounds[B] < 1/10^9, so rounds is the number of iterations to
* get a false negative chance below once in a billion */
static const unsigned int rounds[7] = {1, 30, 73, 156, 322, 653, 1316};
/* We try multiplying the results with various odd numbers, which shouldn't
* influence the uniform distribution modulo a power of 2. */
static const uint32_t mults[6] = {1, 3, 21, 289, 0x9999, 0x80402011};
/* We only select up to 6 bits from the output to analyse */
unsigned int usebits = bits > 6 ? 6 : bits;
unsigned int maxshift = bits - usebits;
/* For each of the maxshift+1 usebits-bit sequences inside a bits-bit
number, track all observed outcomes, one per bit in a uint64_t. */
uint64_t x[6][27] = {{0}};
unsigned int i, shift, m;
/* Multiply the output of all rand calls with the odd number m, which
should not change the uniformity of its distribution. */
for (i = 0; i < rounds[usebits]; i++) {
uint32_t r = (rand32 ? secp256k1_testrand32() : secp256k1_testrand_bits(bits));
CHECK((((uint64_t)r) >> bits) == 0);
for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) {
uint32_t rm = r * mults[m];
for (shift = 0; shift <= maxshift; shift++) {
x[m][shift] |= (((uint64_t)1) << ((rm >> shift) & ((1 << usebits) - 1)));
}
}
}
for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) {
for (shift = 0; shift <= maxshift; shift++) {
/* Test that the lower usebits bits of x[shift] are 1 */
CHECK(((~x[m][shift]) << (64 - (1 << usebits))) == 0);
}
}
}
/* Subrange must be a whole divisor of range, and at most 64 */
static void test_rand_int(uint32_t range, uint32_t subrange) {
/* (1-1/subrange)^rounds < 1/10^9 */
int rounds = (subrange * 2073) / 100;
int i;
uint64_t x = 0;
CHECK((range % subrange) == 0);
for (i = 0; i < rounds; i++) {
uint32_t r = secp256k1_testrand_int(range);
CHECK(r < range);
r = r % subrange;
x |= (((uint64_t)1) << r);
}
/* Test that the lower subrange bits of x are 1. */
CHECK(((~x) << (64 - subrange)) == 0);
}
static void run_rand_bits(void) {
size_t b;
test_rand_bits(1, 32);
for (b = 1; b <= 32; b++) {
test_rand_bits(0, b);
}
}
static void run_rand_int(void) {
static const uint32_t ms[] = {1, 3, 17, 1000, 13771, 999999, 33554432};
static const uint32_t ss[] = {1, 3, 6, 9, 13, 31, 64};
unsigned int m, s;
for (m = 0; m < sizeof(ms) / sizeof(ms[0]); m++) {
for (s = 0; s < sizeof(ss) / sizeof(ss[0]); s++) {
test_rand_int(ms[m] * ss[s], ss[s]);
}
}
}
/***** MODINV TESTS *****/
/* Compute the modular inverse of (odd) x mod 2^64. */
@ -2984,16 +2942,6 @@ static void random_fe(secp256k1_fe *x) {
} while(1);
}
static void random_fe_test(secp256k1_fe *x) {
unsigned char bin[32];
do {
secp256k1_testrand256_test(bin);
if (secp256k1_fe_set_b32_limit(x, bin)) {
return;
}
} while(1);
}
static void random_fe_non_zero(secp256k1_fe *nz) {
int tries = 10;
while (--tries >= 0) {
@ -3234,7 +3182,7 @@ static void run_field_misc(void) {
CHECK(q.normalized && q.magnitude == 1);
#endif
for (j = 0; j < 6; j++) {
secp256k1_fe_negate(&z, &z, j+1);
secp256k1_fe_negate_unchecked(&z, &z, j+1);
secp256k1_fe_normalize_var(&q);
secp256k1_fe_cmov(&q, &z, (j&1));
#ifdef VERIFY
@ -3820,18 +3768,14 @@ static void test_ge(void) {
}
/* Generate random zf, and zfi2 = 1/zf^2, zfi3 = 1/zf^3 */
do {
random_field_element_test(&zf);
} while(secp256k1_fe_is_zero(&zf));
random_fe_non_zero_test(&zf);
random_field_element_magnitude(&zf);
secp256k1_fe_inv_var(&zfi3, &zf);
secp256k1_fe_sqr(&zfi2, &zfi3);
secp256k1_fe_mul(&zfi3, &zfi3, &zfi2);
/* Generate random r */
do {
random_field_element_test(&r);
} while(secp256k1_fe_is_zero(&r));
random_fe_non_zero_test(&r);
for (i1 = 0; i1 < 1 + 4 * runs; i1++) {
int i2;
@ -4048,22 +3992,15 @@ static void test_add_neg_y_diff_x(void) {
* which this test is a regression test for.
*
* These points were generated in sage as
* # secp256k1 params
* F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F)
* C = EllipticCurve ([F (0), F (7)])
* G = C.lift_x(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798)
* N = FiniteField(G.order())
*
* # endomorphism values (lambda is 1^{1/3} in N, beta is 1^{1/3} in F)
* x = polygen(N)
* lam = (1 - x^3).roots()[1][0]
* load("secp256k1_params.sage")
*
* # random "bad pair"
* P = C.random_element()
* Q = -int(lam) * P
* print " P: %x %x" % P.xy()
* print " Q: %x %x" % Q.xy()
* print "P + Q: %x %x" % (P + Q).xy()
* Q = -int(LAMBDA) * P
* print(" P: %x %x" % P.xy())
* print(" Q: %x %x" % Q.xy())
* print("P + Q: %x %x" % (P + Q).xy())
*/
secp256k1_gej aj = SECP256K1_GEJ_CONST(
0x8d24cd95, 0x0a355af1, 0x3c543505, 0x44238d30,
@ -4148,10 +4085,7 @@ static void run_gej(void) {
CHECK(!secp256k1_gej_eq_var(&a, &b));
b = a;
random_field_element_test(&fe);
if (secp256k1_fe_is_zero(&fe)) {
continue;
}
random_fe_non_zero_test(&fe);
secp256k1_gej_rescale(&a, &fe);
CHECK(secp256k1_gej_eq_var(&a, &b));
}
@ -4590,9 +4524,7 @@ static void ecmult_const_mult_xonly(void) {
random_scalar_order_test(&q);
/* If i is odd, n=d*base.x for random non-zero d */
if (i & 1) {
do {
random_field_element_test(&d);
} while (secp256k1_fe_normalizes_to_zero_var(&d));
random_fe_non_zero_test(&d);
secp256k1_fe_mul(&n, &base.x, &d);
} else {
n = base.x;
@ -4611,22 +4543,17 @@ static void ecmult_const_mult_xonly(void) {
/* Test that secp256k1_ecmult_const_xonly correctly rejects X coordinates not on curve. */
for (i = 0; i < 2*COUNT; ++i) {
secp256k1_fe x, n, d, c, r;
secp256k1_fe x, n, d, r;
int res;
secp256k1_scalar q;
random_scalar_order_test(&q);
/* Generate random X coordinate not on the curve. */
do {
random_field_element_test(&x);
secp256k1_fe_sqr(&c, &x);
secp256k1_fe_mul(&c, &c, &x);
secp256k1_fe_add_int(&c, SECP256K1_B);
} while (secp256k1_fe_is_square_var(&c));
random_fe_test(&x);
} while (secp256k1_ge_x_on_curve_var(&x));
/* If i is odd, n=d*x for random non-zero d. */
if (i & 1) {
do {
random_field_element_test(&d);
} while (secp256k1_fe_normalizes_to_zero_var(&d));
random_fe_non_zero_test(&d);
secp256k1_fe_mul(&n, &x, &d);
} else {
n = x;
@ -7765,6 +7692,9 @@ int main(int argc, char **argv) {
}
printf("test count = %i\n", COUNT);
/* run test RNG tests (must run before we really initialize the test RNG) */
run_xoshiro256pp_tests();
/* find random seed */
secp256k1_testrand_init(argc > 2 ? argv[2] : NULL);
@ -7802,10 +7732,6 @@ int main(int argc, char **argv) {
/* scratch tests */
run_scratch_tests();
/* randomness tests */
run_rand_bits();
run_rand_int();
/* integer arithmetic tests */
#ifdef SECP256K1_WIDEMUL_INT128
run_int128_tests();

View file

@ -13,6 +13,9 @@
#define EXHAUSTIVE_TEST_ORDER 13
#endif
/* These values of B are all values in [1, 8] that result in a curve with even order. */
#define EXHAUSTIVE_TEST_CURVE_HAS_EVEN_ORDER (SECP256K1_B == 1 || SECP256K1_B == 6 || SECP256K1_B == 8)
#ifdef USE_EXTERNAL_DEFAULT_CALLBACKS
#pragma message("Ignoring USE_EXTERNAL_CALLBACKS in exhaustive_tests.")
#undef USE_EXTERNAL_DEFAULT_CALLBACKS
@ -395,6 +398,10 @@ static void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_g
#include "modules/schnorrsig/tests_exhaustive_impl.h"
#endif
#ifdef ENABLE_MODULE_ELLSWIFT
#include "modules/ellswift/tests_exhaustive_impl.h"
#endif
int main(int argc, char** argv) {
int i;
secp256k1_gej groupj[EXHAUSTIVE_TEST_ORDER];
@ -490,6 +497,15 @@ int main(int argc, char** argv) {
#ifdef ENABLE_MODULE_SCHNORRSIG
test_exhaustive_schnorrsig(ctx);
#endif
#ifdef ENABLE_MODULE_ELLSWIFT
/* The ellswift algorithm does have additional edge cases when operating on
* curves of even order, which are not included in the code as secp256k1 is
* of odd order. Skip the ellswift tests if the used exhaustive tests curve
* is even-ordered accordingly. */
#if !EXHAUSTIVE_TEST_CURVE_HAS_EVEN_ORDER
test_exhaustive_ellswift(ctx, group);
#endif
#endif
secp256k1_context_destroy(ctx);
}

View file

@ -51,6 +51,19 @@ static void print_buf_plain(const unsigned char *buf, size_t len) {
# define SECP256K1_INLINE inline
# endif
/** Assert statically that expr is an integer constant expression, and run stmt.
*
* Useful for example to enforce that magnitude arguments are constant.
*/
#define ASSERT_INT_CONST_AND_DO(expr, stmt) do { \
switch(42) { \
case /* ERROR: integer argument is not constant */ expr: \
break; \
default: ; \
} \
stmt; \
} while(0)
typedef struct {
void (*fn)(const char *text, void* data);
const void* data;