Skip to content

Commit ff061fd

Browse files
committedJul 18, 2023
Squashed 'src/secp256k1/' changes from 705ce7e..c545fdc
c545fdc Merge bitcoin-core/secp256k1#1298: Remove randomness tests b40e2d3 Merge bitcoin-core/secp256k1#1378: ellswift: fix probabilistic test failure when swapping sides c424e2f ellswift: fix probabilistic test failure when swapping sides 907a672 Merge bitcoin-core/secp256k1#1313: ci: Test on development snapshots of GCC and Clang 0f7657d Merge bitcoin-core/secp256k1#1366: field: Use `restrict` consistently in fe_sqrt cc55757 Merge bitcoin-core/secp256k1#1340: clean up in-comment Sage code (refer to secp256k1_params.sage, update to Python3) 600c5ad clean up in-comment Sage code (refer to secp256k1_params.sage, update to Python3) 981e5be ci: Fix typo in comment e9e9648 ci: Reduce number of macOS tasks from 28 to 8 609093b ci: Add x86_64 Linux tasks for gcc and clang snapshots 1deecaa ci: Install development snapshots of gcc and clang b79ba8a field: Use `restrict` consistently in fe_sqrt c9ebca9 Merge bitcoin-core/secp256k1#1363: doc: minor ellswift.md updates afd7eb4 Merge bitcoin-core/secp256k1#1371: Add exhaustive tests for ellswift (with create+decode roundtrip) 2792119 Add exhaustive test for ellswift (create+decode roundtrip) c7d900f doc: minor ellswift.md updates 332af31 Merge bitcoin-core/secp256k1#1344: group: save normalize_weak calls in `secp256k1_ge_is_valid_var`/`secp256k1_gej_eq_x_var` 9e6d1b0 Merge bitcoin-core/secp256k1#1367: build: Improvements to symbol visibility logic on Windows (attempt 3) 0aacf64 Merge bitcoin-core/secp256k1#1370: Corrected some typos b6b9834 small fixes 07c0e8b group: remove unneeded normalize_weak in `secp256k1_gej_eq_x_var` 3fc1de5 Merge bitcoin-core/secp256k1#1364: Avoid `-Wmaybe-uninitialized` when compiling with `gcc -O1` fb758fe Merge bitcoin-core/secp256k1#1323: tweak_add: fix API doc for tweak=0 c6cd2b1 ci: Add task for static library on Windows + CMake 020bf69 build: Add extensive docs on visibility issues 0196e8a build: Introduce `SECP256k1_DLL_EXPORT` macro 9f1b190 refactor: Replace `SECP256K1_API_VAR` with `SECP256K1_API` ae9db95 build: Introduce `SECP256K1_STATIC` macro for Windows users 7966aee Merge bitcoin-core/secp256k1#1369: ci: Print commit in Windows container a7bec34 ci: Print commit in Windows container 249c81e Merge bitcoin-core/secp256k1#1368: ci: Drop manual checkout of merge commit 98579e2 ci: Drop manual checkout of merge commit 5b9f37f ci: Add `CFLAGS: -O1` to task matrix a6ca76c Avoid `-Wmaybe-uninitialized` when compiling with `gcc -O1` 0fa84f8 Merge bitcoin-core/secp256k1#1358: tests: introduce helper for non-zero `random_fe_test()` results 5a95a26 tests: introduce helper for non-zero `random_fe_test` results 304421d tests: refactor: remove duplicate function `random_field_element_test` 3aef6ab Merge bitcoin-core/secp256k1#1345: field: Static-assert that int args affecting magnitude are constant 4494a36 Merge bitcoin-core/secp256k1#1357: tests: refactor: take use of `secp256k1_ge_x_on_curve_var` 799f4ee Merge bitcoin-core/secp256k1#1356: ci: Adjust Docker image to Debian 12 "bookworm" c862a9f ci: Adjust Docker image to Debian 12 "bookworm" a178209 ci: Force DWARF v4 for Clang when Valgrind tests are expected 7d8d5c8 tests: refactor: take use of `secp256k1_ge_x_on_curve_var` 8a72734 Help the compiler prove that a loop is entered fd491ea Merge bitcoin-core/secp256k1#1355: Fix a typo in the error message ac43613 Merge bitcoin-core/secp256k1#1354: Add ellswift to CHANGELOG 67887ae Fix a typo in the error message 926dd3e Merge bitcoin-core/secp256k1#1295: abi: Use dllexport for mingw builds 1083683 Merge bitcoin-core/secp256k1#1336: Use `__shiftright128` intrinsic in `secp256k1_u128_rshift` on MSVC 7c7467a Refer to ellswift.md in API docs c32ffd8 Add ellswift to CHANGELOG 3c1a0fd Merge bitcoin-core/secp256k1#1347: field: Document return value of fe_sqrt() 5779137 field: Document return value of fe_sqrt() be8ff3a field: Static-assert that int args affecting magnitude are constant efa76c4 group: remove unneeded normalize_weak in `secp256k1_ge_is_valid_var` 5b7bf2e Use `__shiftright128` intrinsic in `secp256k1_u128_rshift` on MSVC 05873bb tweak_add: fix API doc for tweak=0 6ec3731 Simplify test PRNG implementation fb5bfa4 Add static test vector for Xoshiro256++ 723e8ca Remove randomness tests bc7c8db abi: Use dllexport for mingw builds git-subtree-dir: src/secp256k1 git-subtree-split: c545fdc
1 parent 901336e commit ff061fd

36 files changed

+373
-331
lines changed
 

‎.cirrus.yml

+25-29
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,6 @@ cat_logs_snippet: &CAT_LOGS
5454
cat_ci_env_script:
5555
- env
5656

57-
merge_base_script_snippet: &MERGE_BASE
58-
merge_base_script:
59-
- if [ "$CIRRUS_PR" = "" ]; then exit 0; fi
60-
- git fetch --depth=1 $CIRRUS_REPO_CLONE_URL "pull/${CIRRUS_PR}/merge"
61-
- git checkout FETCH_HEAD # Use merged changes to detect silent merge conflicts
62-
6357
linux_container_snippet: &LINUX_CONTAINER
6458
container:
6559
dockerfile: ci/linux-debian.Dockerfile
@@ -68,12 +62,12 @@ linux_container_snippet: &LINUX_CONTAINER
6862
# Gives us more CPUs for free if they're available.
6963
greedy: true
7064
# More than enough for our scripts.
71-
memory: 1G
65+
memory: 2G
7266

7367
task:
7468
name: "x86_64: Linux (Debian stable)"
7569
<< : *LINUX_CONTAINER
76-
matrix: &ENV_MATRIX
70+
matrix:
7771
- env: {WIDEMUL: int64, RECOVERY: yes}
7872
- env: {WIDEMUL: int64, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes}
7973
- env: {WIDEMUL: int128}
@@ -86,14 +80,18 @@ task:
8680
- env: {BUILD: distcheck, WITH_VALGRIND: no, CTIMETESTS: no, BENCH: no}
8781
- env: {CPPFLAGS: -DDETERMINISTIC}
8882
- env: {CFLAGS: -O0, CTIMETESTS: no}
83+
- env: {CFLAGS: -O1, RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes}
8984
- env: { ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 }
9085
- env: { ECMULTGENPRECISION: 8, ECMULTWINDOW: 4 }
9186
matrix:
9287
- env:
9388
CC: gcc
9489
- env:
9590
CC: clang
96-
<< : *MERGE_BASE
91+
- env:
92+
CC: gcc-snapshot
93+
- env:
94+
CC: clang-snapshot
9795
test_script:
9896
- ./ci/cirrus.sh
9997
<< : *CAT_LOGS
@@ -111,7 +109,6 @@ task:
111109
CC: i686-linux-gnu-gcc
112110
- env:
113111
CC: clang --target=i686-pc-linux-gnu -isystem /usr/i686-linux-gnu/include
114-
<< : *MERGE_BASE
115112
test_script:
116113
- ./ci/cirrus.sh
117114
<< : *CAT_LOGS
@@ -125,20 +122,22 @@ task:
125122
HOMEBREW_NO_INSTALL_CLEANUP: 1
126123
# Cirrus gives us a fixed number of 4 virtual CPUs. Not that we even have that many jobs at the moment...
127124
MAKEFLAGS: -j5
128-
matrix:
129-
<< : *ENV_MATRIX
130125
env:
131126
ASM: no
132127
WITH_VALGRIND: no
133128
CTIMETESTS: no
129+
CC: clang
134130
matrix:
135-
- env:
136-
CC: gcc
137-
- env:
138-
CC: clang
131+
- env: {WIDEMUL: int64, RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes}
132+
- env: {WIDEMUL: int64, RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes, CC: gcc}
133+
- env: {WIDEMUL: int128_struct, ECMULTGENPRECISION: 2, ECMULTWINDOW: 4}
134+
- env: {WIDEMUL: int128, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes}
135+
- env: {WIDEMUL: int128, RECOVERY: yes, SCHNORRSIG: yes}
136+
- env: {WIDEMUL: int128, RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes, CC: gcc}
137+
- env: {WIDEMUL: int128, RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes, CPPFLAGS: -DVERIFY}
138+
- env: {BUILD: distcheck}
139139
brew_script:
140140
- brew install automake libtool gcc
141-
<< : *MERGE_BASE
142141
test_script:
143142
- ./ci/cirrus.sh
144143
<< : *CAT_LOGS
@@ -157,7 +156,6 @@ task:
157156
SCHNORRSIG: yes
158157
ELLSWIFT: yes
159158
CTIMETESTS: no
160-
<< : *MERGE_BASE
161159
test_script:
162160
# https://sourceware.org/bugzilla/show_bug.cgi?id=27008
163161
- rm /etc/ld.so.cache
@@ -180,7 +178,6 @@ task:
180178
matrix:
181179
- env: {}
182180
- env: {EXPERIMENTAL: yes, ASM: arm32}
183-
<< : *MERGE_BASE
184181
test_script:
185182
- ./ci/cirrus.sh
186183
<< : *CAT_LOGS
@@ -198,7 +195,6 @@ task:
198195
SCHNORRSIG: yes
199196
ELLSWIFT: yes
200197
CTIMETESTS: no
201-
<< : *MERGE_BASE
202198
test_script:
203199
- ./ci/cirrus.sh
204200
<< : *CAT_LOGS
@@ -216,7 +212,6 @@ task:
216212
SCHNORRSIG: yes
217213
ELLSWIFT: yes
218214
CTIMETESTS: no
219-
<< : *MERGE_BASE
220215
test_script:
221216
- ./ci/cirrus.sh
222217
<< : *CAT_LOGS
@@ -237,7 +232,6 @@ task:
237232
- name: "i686 (mingw32-w64): Windows (Debian stable, Wine)"
238233
env:
239234
HOST: i686-w64-mingw32
240-
<< : *MERGE_BASE
241235
test_script:
242236
- ./ci/cirrus.sh
243237
<< : *CAT_LOGS
@@ -280,7 +274,6 @@ task:
280274
CC: /opt/msvc/bin/x86/cl
281275
AR: /opt/msvc/bin/x86/lib
282276
NM: /opt/msvc/bin/x86/dumpbin -symbols -headers
283-
<< : *MERGE_BASE
284277
test_script:
285278
- ./ci/cirrus.sh
286279
<< : *CAT_LOGS
@@ -325,7 +318,6 @@ task:
325318
- env:
326319
HOST: i686-linux-gnu
327320
CC: i686-linux-gnu-gcc
328-
<< : *MERGE_BASE
329321
test_script:
330322
- ./ci/cirrus.sh
331323
<< : *CAT_LOGS
@@ -352,7 +344,6 @@ task:
352344
ECMULTGENPRECISION: 2
353345
ECMULTWINDOW: 2
354346
CFLAGS: "-fsanitize=memory -g -O3"
355-
<< : *MERGE_BASE
356347
test_script:
357348
- ./ci/cirrus.sh
358349
<< : *CAT_LOGS
@@ -369,7 +360,6 @@ task:
369360
RECOVERY: yes
370361
SCHNORRSIG: yes
371362
ELLSWIFT: yes
372-
<< : *MERGE_BASE
373363
test_script:
374364
- ./ci/cirrus.sh
375365
<< : *CAT_LOGS
@@ -401,11 +391,17 @@ task:
401391
# Ignore MSBuild warning MSB8029.
402392
# See: https://learn.microsoft.com/en-us/visualstudio/msbuild/errors/msb8029?view=vs-2022
403393
IgnoreWarnIntDirInTempDetected: 'true'
404-
merge_script:
405-
- 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; }
394+
matrix:
395+
- env:
396+
BUILD_SHARED_LIBS: ON
397+
- env:
398+
BUILD_SHARED_LIBS: OFF
399+
git_show_script:
400+
# Print commit to allow reproducing the job outside of CI.
401+
- git show --no-patch
406402
configure_script:
407403
- '%x64_NATIVE_TOOLS%'
408-
- 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
404+
- 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%
409405
build_script:
410406
- '%x64_NATIVE_TOOLS%'
411407
- cmake --build build --config RelWithDebInfo -- -property:UseMultiToolTask=true;CL_MPcount=5

‎CHANGELOG.md

+10
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
#### Added
11+
- New module `ellswift` implements ElligatorSwift encoding for public keys and x-only Diffie-Hellman key exchange for them.
12+
ElligatorSwift permits representing secp256k1 public keys as 64-byte arrays which cannot be distinguished from uniformly random. See:
13+
- Header file `include/secp256k1_ellswift.h` which defines the new API.
14+
- Document `doc/ellswift.md` which explains the mathematical background of the scheme.
15+
- The [paper](https://eprint.iacr.org/2022/759) on which the scheme is based.
16+
17+
#### Changed
18+
- When consuming libsecp256k1 as a static library on Windows, the user must now define the `SECP256K1_STATIC` macro before including `secp256k1.h`.
19+
1020
## [0.3.2] - 2023-05-13
1121
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`.
1222

‎Makefile.am

+3-3
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ endif
153153
if USE_EXAMPLES
154154
noinst_PROGRAMS += ecdsa_example
155155
ecdsa_example_SOURCES = examples/ecdsa.c
156-
ecdsa_example_CPPFLAGS = -I$(top_srcdir)/include
156+
ecdsa_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC
157157
ecdsa_example_LDADD = libsecp256k1.la
158158
ecdsa_example_LDFLAGS = -static
159159
if BUILD_WINDOWS
@@ -163,7 +163,7 @@ TESTS += ecdsa_example
163163
if ENABLE_MODULE_ECDH
164164
noinst_PROGRAMS += ecdh_example
165165
ecdh_example_SOURCES = examples/ecdh.c
166-
ecdh_example_CPPFLAGS = -I$(top_srcdir)/include
166+
ecdh_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC
167167
ecdh_example_LDADD = libsecp256k1.la
168168
ecdh_example_LDFLAGS = -static
169169
if BUILD_WINDOWS
@@ -174,7 +174,7 @@ endif
174174
if ENABLE_MODULE_SCHNORRSIG
175175
noinst_PROGRAMS += schnorr_example
176176
schnorr_example_SOURCES = examples/schnorr.c
177-
schnorr_example_CPPFLAGS = -I$(top_srcdir)/include
177+
schnorr_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC
178178
schnorr_example_LDADD = libsecp256k1.la
179179
schnorr_example_LDFLAGS = -static
180180
if BUILD_WINDOWS

‎ci/cirrus.sh

+18-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ set -eux
44

55
export LC_ALL=C
66

7-
# Print relevant CI environment to allow reproducing the job outside of CI.
7+
# Print commit and relevant CI environment to allow reproducing the job outside of CI.
8+
git show --no-patch
89
print_environment() {
910
# Turn off -x because it messes up the output
1011
set +x
@@ -53,6 +54,22 @@ if [ -n "$WRAPPER_CMD" ]; then
5354
$WRAPPER_CMD --version
5455
fi
5556

57+
# Workaround for https://bugs.kde.org/show_bug.cgi?id=452758 (fixed in valgrind 3.20.0).
58+
case "${CC:-undefined}" in
59+
clang*)
60+
if [ "$CTIMETESTS" = "yes" ] && [ "$WITH_VALGRIND" = "yes" ]
61+
then
62+
export CFLAGS="${CFLAGS:+$CFLAGS }-gdwarf-4"
63+
else
64+
case "$WRAPPER_CMD" in
65+
valgrind*)
66+
export CFLAGS="${CFLAGS:+$CFLAGS }-gdwarf-4"
67+
;;
68+
esac
69+
fi
70+
;;
71+
esac
72+
5673
./autogen.sh
5774

5875
./configure \

‎ci/linux-debian.Dockerfile

+41-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
FROM debian:stable
22

3+
SHELL ["/bin/bash", "-c"]
4+
35
RUN dpkg --add-architecture i386 && \
46
dpkg --add-architecture s390x && \
57
dpkg --add-architecture armhf && \
@@ -9,11 +11,11 @@ RUN dpkg --add-architecture i386 && \
911
# dkpg-dev: to make pkg-config work in cross-builds
1012
# llvm: for llvm-symbolizer, which is used by clang's UBSan for symbolized stack traces
1113
RUN apt-get update && apt-get install --no-install-recommends -y \
12-
git ca-certificates \
14+
git ca-certificates wget \
1315
make automake libtool pkg-config dpkg-dev valgrind qemu-user \
14-
gcc clang llvm libc6-dbg \
16+
gcc clang llvm libclang-rt-dev libc6-dbg \
1517
g++ \
16-
gcc-i686-linux-gnu libc6-dev-i386-cross libc6-dbg:i386 libubsan1:i386 libasan6:i386 \
18+
gcc-i686-linux-gnu libc6-dev-i386-cross libc6-dbg:i386 libubsan1:i386 libasan8:i386 \
1719
gcc-s390x-linux-gnu libc6-dev-s390x-cross libc6-dbg:s390x \
1820
gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libc6-dbg:armhf \
1921
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 \
2325
sagemath
2426

2527
WORKDIR /root
26-
# The "wine" package provides a convience wrapper that we need
28+
29+
# Build and install gcc snapshot
30+
ARG GCC_SNAPSHOT_MAJOR=14
31+
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}" && \
32+
wget "https://gcc.gnu.org/pub/gcc/snapshots/LATEST-${GCC_SNAPSHOT_MAJOR}/sha512.sum" && \
33+
sha512sum --check --ignore-missing sha512.sum && \
34+
# We should have downloaded exactly one tar.xz file
35+
ls && \
36+
[[ $(ls *.tar.xz | wc -l) -eq "1" ]] && \
37+
tar xf *.tar.xz && \
38+
mkdir gcc-build && cd gcc-build && \
39+
apt-get update && apt-get install --no-install-recommends -y libgmp-dev libmpfr-dev libmpc-dev flex && \
40+
../*/configure --prefix=/opt/gcc-snapshot --enable-languages=c --disable-bootstrap --disable-multilib --without-isl && \
41+
make -j $(nproc) && \
42+
make install && \
43+
ln -s /opt/gcc-snapshot/bin/gcc /usr/bin/gcc-snapshot
44+
45+
# Install clang snapshot
46+
RUN wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc && \
47+
# Add repository for this Debian release
48+
. /etc/os-release && echo "deb http://apt.llvm.org/${VERSION_CODENAME} llvm-toolchain-${VERSION_CODENAME} main" >> /etc/apt/sources.list && \
49+
# Install clang snapshot
50+
apt-get update && apt-get install --no-install-recommends -y clang && \
51+
# Remove just the "clang" symlink again
52+
apt-get remove -y clang && \
53+
# We should have exactly two clang versions now
54+
ls /usr/bin/clang* && \
55+
[[ $(ls /usr/bin/clang-?? | sort | wc -l) -eq "2" ]] && \
56+
# Create symlinks for them
57+
ln -s $(ls /usr/bin/clang-?? | sort | tail -1) /usr/bin/clang-snapshot && \
58+
ln -s $(ls /usr/bin/clang-?? | sort | head -1) /usr/bin/clang
59+
60+
# The "wine" package provides a convenience wrapper that we need
2761
RUN apt-get update && apt-get install --no-install-recommends -y \
2862
git ca-certificates wine64 wine python3-simplejson python3-six msitools winbind procps && \
63+
# Workaround for `wine` package failure to employ the Debian alternatives system properly.
64+
ln -s /usr/lib/wine/wine64 /usr/bin/wine64 && \
65+
# Set of tools for using MSVC on Linux.
2966
git clone https://github.com/mstorsjo/msvc-wine && \
3067
mkdir /opt/msvc && \
3168
python3 msvc-wine/vsdownload.py --accept-license --dest /opt/msvc Microsoft.VisualStudio.Workload.VCTools && \

‎configure.ac

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

‎doc/ellswift.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ $$
8888
\begin{array}{lcl}
8989
X(u, t) & = & \left\\{\begin{array}{ll}
9090
\dfrac{g(u) - t^2}{2t} & a = 0 \\
91-
\dfrac{g(u) + h(u)(Y_0(u) + X_0(u)t)^2}{X_0(u)(1 + h(u)t^2)} & a \neq 0
91+
\dfrac{g(u) + h(u)(Y_0(u) - X_0(u)t)^2}{X_0(u)(1 + h(u)t^2)} & a \neq 0
9292
\end{array}\right. \\
9393
Y(u, t) & = & \left\\{\begin{array}{ll}
9494
\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):
329329
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.
330330
* 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:
331331
* 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.
332-
* 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$.
332+
* 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$.
333333

334334
**Define** a version of $G_{c,u}(x)$ which deals with all these cases:
335335
* If $a=0$ and $u=0$, return $\bot.$

‎examples/CMakeLists.txt

-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ target_link_libraries(example INTERFACE
66
secp256k1
77
$<$<PLATFORM_ID:Windows>:bcrypt>
88
)
9-
if(NOT BUILD_SHARED_LIBS AND MSVC)
10-
target_link_options(example INTERFACE /IGNORE:4217)
11-
endif()
129

1310
add_executable(ecdsa_example ecdsa.c)
1411
target_link_libraries(ecdsa_example example)

‎examples/examples_util.h

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

‎include/secp256k1.h

+35-28
Original file line numberDiff line numberDiff line change
@@ -133,28 +133,35 @@ typedef int (*secp256k1_nonce_function)(
133133
# define SECP256K1_NO_BUILD
134134
#endif
135135

136-
/* Symbol visibility. See libtool manual, section "Windows DLLs". */
137-
#if defined(_WIN32) && !defined(__GNUC__)
138-
# ifdef SECP256K1_BUILD
139-
# ifdef DLL_EXPORT
140-
# define SECP256K1_API __declspec (dllexport)
141-
# define SECP256K1_API_VAR extern __declspec (dllexport)
136+
/* Symbol visibility. */
137+
#if defined(_WIN32)
138+
/* GCC for Windows (e.g., MinGW) accepts the __declspec syntax
139+
* for MSVC compatibility. A __declspec declaration implies (but is not
140+
* exactly equivalent to) __attribute__ ((visibility("default"))), and so we
141+
* actually want __declspec even on GCC, see "Microsoft Windows Function
142+
* Attributes" in the GCC manual and the recommendations in
143+
* https://gcc.gnu.org/wiki/Visibility. */
144+
# if defined(SECP256K1_BUILD)
145+
# if defined(DLL_EXPORT) || defined(SECP256K1_DLL_EXPORT)
146+
/* Building libsecp256k1 as a DLL.
147+
* 1. If using Libtool, it defines DLL_EXPORT automatically.
148+
* 2. In other cases, SECP256K1_DLL_EXPORT must be defined. */
149+
# define SECP256K1_API extern __declspec (dllexport)
142150
# endif
143-
# elif defined _MSC_VER
144-
# define SECP256K1_API
145-
# define SECP256K1_API_VAR extern __declspec (dllimport)
146-
# elif defined DLL_EXPORT
147-
# define SECP256K1_API __declspec (dllimport)
148-
# define SECP256K1_API_VAR extern __declspec (dllimport)
151+
/* The user must define SECP256K1_STATIC when consuming libsecp256k1 as a static
152+
* library on Windows. */
153+
# elif !defined(SECP256K1_STATIC)
154+
/* Consuming libsecp256k1 as a DLL. */
155+
# define SECP256K1_API extern __declspec (dllimport)
149156
# endif
150157
#endif
151158
#ifndef SECP256K1_API
152159
# if defined(__GNUC__) && (__GNUC__ >= 4) && defined(SECP256K1_BUILD)
153-
# define SECP256K1_API __attribute__ ((visibility ("default")))
154-
# define SECP256K1_API_VAR extern __attribute__ ((visibility ("default")))
160+
/* Building libsecp256k1 on non-Windows using GCC or compatible. */
161+
# define SECP256K1_API extern __attribute__ ((visibility ("default")))
155162
# else
156-
# define SECP256K1_API
157-
# define SECP256K1_API_VAR extern
163+
/* All cases not captured above. */
164+
# define SECP256K1_API extern
158165
# endif
159166
#endif
160167

@@ -226,10 +233,10 @@ typedef int (*secp256k1_nonce_function)(
226233
*
227234
* It is highly recommended to call secp256k1_selftest before using this context.
228235
*/
229-
SECP256K1_API_VAR const secp256k1_context *secp256k1_context_static;
236+
SECP256K1_API const secp256k1_context *secp256k1_context_static;
230237

231238
/** Deprecated alias for secp256k1_context_static. */
232-
SECP256K1_API_VAR const secp256k1_context *secp256k1_context_no_precomp
239+
SECP256K1_API const secp256k1_context *secp256k1_context_no_precomp
233240
SECP256K1_DEPRECATED("Use secp256k1_context_static instead");
234241

235242
/** Perform basic self tests (to be used in conjunction with secp256k1_context_static)
@@ -626,10 +633,10 @@ SECP256K1_API int secp256k1_ecdsa_signature_normalize(
626633
* If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
627634
* extra entropy.
628635
*/
629-
SECP256K1_API_VAR const secp256k1_nonce_function secp256k1_nonce_function_rfc6979;
636+
SECP256K1_API const secp256k1_nonce_function secp256k1_nonce_function_rfc6979;
630637

631638
/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */
632-
SECP256K1_API_VAR const secp256k1_nonce_function secp256k1_nonce_function_default;
639+
SECP256K1_API const secp256k1_nonce_function secp256k1_nonce_function_default;
633640

634641
/** Create an ECDSA signature.
635642
*
@@ -733,10 +740,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate(
733740
* invalid according to secp256k1_ec_seckey_verify, this
734741
* function returns 0. seckey will be set to some unspecified
735742
* value if this function returns 0.
736-
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
737-
* secp256k1_ec_seckey_verify, this function returns 0. For
738-
* uniformly random 32-byte arrays the chance of being invalid
739-
* is negligible (around 1 in 2^128).
743+
* In: tweak32: pointer to a 32-byte tweak, which must be valid according to
744+
* secp256k1_ec_seckey_verify or 32 zero bytes. For uniformly
745+
* random 32-byte tweaks, the chance of being invalid is
746+
* negligible (around 1 in 2^128).
740747
*/
741748
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_add(
742749
const secp256k1_context *ctx,
@@ -761,10 +768,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
761768
* Args: ctx: pointer to a context object.
762769
* In/Out: pubkey: pointer to a public key object. pubkey will be set to an
763770
* invalid value if this function returns 0.
764-
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
765-
* secp256k1_ec_seckey_verify, this function returns 0. For
766-
* uniformly random 32-byte arrays the chance of being invalid
767-
* is negligible (around 1 in 2^128).
771+
* In: tweak32: pointer to a 32-byte tweak, which must be valid according to
772+
* secp256k1_ec_seckey_verify or 32 zero bytes. For uniformly
773+
* random 32-byte tweaks, the chance of being invalid is
774+
* negligible (around 1 in 2^128).
768775
*/
769776
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
770777
const secp256k1_context *ctx,

‎include/secp256k1_ecdh.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ typedef int (*secp256k1_ecdh_hash_function)(
2727

2828
/** An implementation of SHA256 hash function that applies to compressed public key.
2929
* Populates the output parameter with 32 bytes. */
30-
SECP256K1_API_VAR const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256;
30+
SECP256K1_API const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256;
3131

3232
/** A default ECDH hash function (currently equal to secp256k1_ecdh_hash_function_sha256).
3333
* Populates the output parameter with 32 bytes. */
34-
SECP256K1_API_VAR const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default;
34+
SECP256K1_API const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default;
3535

3636
/** Compute an EC Diffie-Hellman secret in constant time
3737
*

‎include/secp256k1_ellswift.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ extern "C" {
4141
* - The paper uses an additional encoding bit for the parity of y. Here the
4242
* parity of t is used (negating t does not affect the decoded x coordinate,
4343
* so this is possible).
44+
*
45+
* For mathematical background about the scheme, see the doc/ellswift.md file.
4446
*/
4547

4648
/** A pointer to a function used by secp256k1_ellswift_xdh to hash the shared X
@@ -70,15 +72,15 @@ typedef int (*secp256k1_ellswift_xdh_hash_function)(
7072
/** An implementation of an secp256k1_ellswift_xdh_hash_function which uses
7173
* SHA256(prefix64 || ell_a64 || ell_b64 || x32), where prefix64 is the 64-byte
7274
* array pointed to by data. */
73-
SECP256K1_API_VAR const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix;
75+
SECP256K1_API const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix;
7476

7577
/** An implementation of an secp256k1_ellswift_xdh_hash_function compatible with
7678
* BIP324. It returns H_tag(ell_a64 || ell_b64 || x32), where H_tag is the
7779
* BIP340 tagged hash function with tag "bip324_ellswift_xonly_ecdh". Equivalent
7880
* to secp256k1_ellswift_xdh_hash_function_prefix with prefix64 set to
7981
* SHA256("bip324_ellswift_xonly_ecdh")||SHA256("bip324_ellswift_xonly_ecdh").
8082
* The data argument is ignored. */
81-
SECP256K1_API_VAR const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324;
83+
SECP256K1_API const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324;
8284

8385
/** Construct a 64-byte ElligatorSwift encoding of a given pubkey.
8486
*
@@ -159,7 +161,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ellswift_create(
159161
/** Given a private key, and ElligatorSwift public keys sent in both directions,
160162
* compute a shared secret using x-only Elliptic Curve Diffie-Hellman (ECDH).
161163
*
162-
* Returns: 1: shared secret was succesfully computed
164+
* Returns: 1: shared secret was successfully computed
163165
* 0: secret was invalid or hashfp returned 0
164166
* Args: ctx: pointer to a context object.
165167
* Out: output: pointer to an array to be filled by hashfp.

‎include/secp256k1_extrakeys.h

+8-8
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubke
112112
* Out: output_pubkey: pointer to a public key to store the result. Will be set
113113
* to an invalid value if this function returns 0.
114114
* In: internal_pubkey: pointer to an x-only pubkey to apply the tweak to.
115-
* tweak32: pointer to a 32-byte tweak. If the tweak is invalid
116-
* according to secp256k1_ec_seckey_verify, this function
117-
* returns 0. For uniformly random 32-byte arrays the
118-
* chance of being invalid is negligible (around 1 in 2^128).
115+
* tweak32: pointer to a 32-byte tweak, which must be valid
116+
* according to secp256k1_ec_seckey_verify or 32 zero
117+
* bytes. For uniformly random 32-byte tweaks, the chance of
118+
* being invalid is negligible (around 1 in 2^128).
119119
*/
120120
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add(
121121
const secp256k1_context *ctx,
@@ -229,10 +229,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub(
229229
* Args: ctx: pointer to a context object.
230230
* In/Out: keypair: pointer to a keypair to apply the tweak to. Will be set to
231231
* an invalid value if this function returns 0.
232-
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according
233-
* to secp256k1_ec_seckey_verify, this function returns 0. For
234-
* uniformly random 32-byte arrays the chance of being invalid
235-
* is negligible (around 1 in 2^128).
232+
* In: tweak32: pointer to a 32-byte tweak, which must be valid according to
233+
* secp256k1_ec_seckey_verify or 32 zero bytes. For uniformly
234+
* random 32-byte tweaks, the chance of being invalid is
235+
* negligible (around 1 in 2^128).
236236
*/
237237
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_tweak_add(
238238
const secp256k1_context *ctx,

‎include/secp256k1_schnorrsig.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ typedef int (*secp256k1_nonce_function_hardened)(
6161
* Therefore, to create BIP-340 compliant signatures, algo must be set to
6262
* "BIP0340/nonce" and algolen to 13.
6363
*/
64-
SECP256K1_API_VAR const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340;
64+
SECP256K1_API const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340;
6565

6666
/** Data structure that contains additional arguments for schnorrsig_sign_custom.
6767
*

‎sage/group_prover.sage

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

‎src/CMakeLists.txt

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ if(SECP256K1_ASM STREQUAL "arm32")
2020
target_link_libraries(secp256k1_asm INTERFACE secp256k1_asm_arm)
2121
endif()
2222

23-
# Define our export symbol only for Win32 and only for shared libs.
24-
# This matches libtool's usage of DLL_EXPORT
2523
if(WIN32)
26-
set_target_properties(secp256k1 PROPERTIES DEFINE_SYMBOL "DLL_EXPORT")
24+
# Define our export symbol only for shared libs.
25+
set_target_properties(secp256k1 PROPERTIES DEFINE_SYMBOL SECP256K1_DLL_EXPORT)
26+
target_compile_definitions(secp256k1 INTERFACE $<$<NOT:$<BOOL:${BUILD_SHARED_LIBS}>>:SECP256K1_STATIC>)
2727
endif()
2828

2929
# Object libs don't know if they're being built for a shared or static lib.

‎src/ecdsa_impl.h

+4-17
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,8 @@
1616
#include "ecdsa.h"
1717

1818
/** Group order for secp256k1 defined as 'n' in "Standards for Efficient Cryptography" (SEC2) 2.7.1
19-
* sage: for t in xrange(1023, -1, -1):
20-
* .. p = 2**256 - 2**32 - t
21-
* .. if p.is_prime():
22-
* .. print '%x'%p
23-
* .. break
24-
* 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'
25-
* sage: a = 0
26-
* sage: b = 7
27-
* sage: F = FiniteField (p)
28-
* sage: '%x' % (EllipticCurve ([F (a), F (b)]).order())
29-
* 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'
19+
* $ sage -c 'load("secp256k1_params.sage"); print(hex(N))'
20+
* 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
3021
*/
3122
static const secp256k1_fe secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST(
3223
0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL,
@@ -35,12 +26,8 @@ static const secp256k1_fe secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST
3526

3627
/** Difference between field and order, values 'p' and 'n' values defined in
3728
* "Standards for Efficient Cryptography" (SEC2) 2.7.1.
38-
* sage: p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
39-
* sage: a = 0
40-
* sage: b = 7
41-
* sage: F = FiniteField (p)
42-
* sage: '%x' % (p - EllipticCurve ([F (a), F (b)]).order())
43-
* '14551231950b75fc4402da1722fc9baee'
29+
* $ sage -c 'load("secp256k1_params.sage"); print(hex(P-N))'
30+
* 0x14551231950b75fc4402da1722fc9baee
4431
*/
4532
static const secp256k1_fe secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_CONST(
4633
0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL

‎src/ecmult.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
# pragma message DEBUG_CONFIG_DEF(ECMULT_WINDOW_SIZE)
2323
#endif
2424

25-
/* Noone will ever need more than a window size of 24. The code might
25+
/* No one will ever need more than a window size of 24. The code might
2626
* be correct for larger values of ECMULT_WINDOW_SIZE but this is not
2727
* tested.
2828
*

‎src/ecmult_const_impl.h

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

‎src/ecmult_gen_compute_table_impl.h

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, cons
2222
secp256k1_gej nums_gej;
2323
int i, j;
2424

25+
VERIFY_CHECK(g > 0);
26+
VERIFY_CHECK(n > 0);
27+
2528
/* get the generator */
2629
secp256k1_gej_set_ge(&gj, gen);
2730

‎src/ecmult_impl.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,9 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
288288
}
289289

290290
/* Bring them to the same Z denominator. */
291-
secp256k1_ge_table_set_globalz(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, state->aux);
291+
if (no) {
292+
secp256k1_ge_table_set_globalz(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, state->aux);
293+
}
292294

293295
for (np = 0; np < no; ++np) {
294296
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {

‎src/field.h

+24-10
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ static const secp256k1_fe secp256k1_const_beta = SECP256K1_FE_CONST(
8888
# define secp256k1_fe_set_b32_mod secp256k1_fe_impl_set_b32_mod
8989
# define secp256k1_fe_set_b32_limit secp256k1_fe_impl_set_b32_limit
9090
# define secp256k1_fe_get_b32 secp256k1_fe_impl_get_b32
91-
# define secp256k1_fe_negate secp256k1_fe_impl_negate
92-
# define secp256k1_fe_mul_int secp256k1_fe_impl_mul_int
91+
# define secp256k1_fe_negate_unchecked secp256k1_fe_impl_negate_unchecked
92+
# define secp256k1_fe_mul_int_unchecked secp256k1_fe_impl_mul_int_unchecked
9393
# define secp256k1_fe_add secp256k1_fe_impl_add
9494
# define secp256k1_fe_mul secp256k1_fe_impl_mul
9595
# 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);
192192

193193
/** Set a field element equal to a provided 32-byte big endian value, reducing it.
194194
*
195-
* On input, r does not need to be initalized. a must be a pointer to an initialized 32-byte array.
195+
* On input, r does not need to be initialized. a must be a pointer to an initialized 32-byte array.
196196
* On output, r = a (mod p). It will have magnitude 1, and not be normalized.
197197
*/
198198
static void secp256k1_fe_set_b32_mod(secp256k1_fe *r, const unsigned char *a);
199199

200200
/** Set a field element equal to a provided 32-byte big endian value, checking for overflow.
201201
*
202-
* On input, r does not need to be initalized. a must be a pointer to an initialized 32-byte array.
202+
* On input, r does not need to be initialized. a must be a pointer to an initialized 32-byte array.
203203
* On output, r = a if (a < p), it will be normalized with magnitude 1, and 1 is returned.
204204
* If a >= p, 0 is returned, and r will be made invalid (and must not be used without overwriting).
205205
*/
@@ -214,11 +214,17 @@ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a);
214214
/** Negate a field element.
215215
*
216216
* On input, r does not need to be initialized. a must be a valid field element with
217-
* magnitude not exceeding m. m must be an integer in [0,31].
217+
* magnitude not exceeding m. m must be an integer constant expression in [0,31].
218218
* Performs {r = -a}.
219219
* On output, r will not be normalized, and will have magnitude m+1.
220220
*/
221-
static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m);
221+
#define secp256k1_fe_negate(r, a, m) ASSERT_INT_CONST_AND_DO(m, secp256k1_fe_negate_unchecked(r, a, m))
222+
223+
/** Like secp256k1_fe_negate_unchecked but m is not checked to be an integer constant expression.
224+
*
225+
* Should not be called directly outside of tests.
226+
*/
227+
static void secp256k1_fe_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m);
222228

223229
/** Add a small integer to a field element.
224230
*
@@ -229,12 +235,18 @@ static void secp256k1_fe_add_int(secp256k1_fe *r, int a);
229235

230236
/** Multiply a field element with a small integer.
231237
*
232-
* On input, r must be a valid field element. a must be an integer in [0,32].
238+
* On input, r must be a valid field element. a must be an integer constant expression in [0,32].
233239
* The magnitude of r times a must not exceed 32.
234240
* Performs {r *= a}.
235241
* On output, r's magnitude is multiplied by a, and r will not be normalized.
236242
*/
237-
static void secp256k1_fe_mul_int(secp256k1_fe *r, int a);
243+
#define secp256k1_fe_mul_int(r, a) ASSERT_INT_CONST_AND_DO(a, secp256k1_fe_mul_int_unchecked(r, a))
244+
245+
/** Like secp256k1_fe_mul_int but a is not checked to be an integer constant expression.
246+
*
247+
* Should not be called directly outside of tests.
248+
*/
249+
static void secp256k1_fe_mul_int_unchecked(secp256k1_fe *r, int a);
238250

239251
/** Increment a field element by another.
240252
*
@@ -267,8 +279,10 @@ static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a);
267279
/** Compute a square root of a field element.
268280
*
269281
* On input, a must be a valid field element with magnitude<=8; r need not be initialized.
270-
* Performs {r = sqrt(a)} or {r = sqrt(-a)}, whichever exists. The resulting value
271-
* represented by r will be a square itself. Variables r and a must not point to the same object.
282+
* If sqrt(a) exists, performs {r = sqrt(a)} and returns 1.
283+
* Otherwise, sqrt(-a) exists. The function performs {r = sqrt(-a)} and returns 0.
284+
* The resulting value represented by r will be a square itself.
285+
* Variables r and a must not point to the same object.
272286
* On output, r will have magnitude 1 but will not be normalized.
273287
*/
274288
static int secp256k1_fe_sqrt(secp256k1_fe * SECP256K1_RESTRICT r, const secp256k1_fe * SECP256K1_RESTRICT a);

‎src/field_10x26_impl.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a) {
344344
r[31] = a->n[0] & 0xff;
345345
}
346346

347-
SECP256K1_INLINE static void secp256k1_fe_impl_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
347+
SECP256K1_INLINE static void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m) {
348348
/* For all legal values of m (0..31), the following properties hold: */
349349
VERIFY_CHECK(0x3FFFC2FUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
350350
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
365365
r->n[9] = 0x03FFFFFUL * 2 * (m + 1) - a->n[9];
366366
}
367367

368-
SECP256K1_INLINE static void secp256k1_fe_impl_mul_int(secp256k1_fe *r, int a) {
368+
SECP256K1_INLINE static void secp256k1_fe_impl_mul_int_unchecked(secp256k1_fe *r, int a) {
369369
r->n[0] *= a;
370370
r->n[1] *= a;
371371
r->n[2] *= a;

‎src/field_5x52_impl.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a) {
314314
r[31] = a->n[0] & 0xFF;
315315
}
316316

317-
SECP256K1_INLINE static void secp256k1_fe_impl_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
317+
SECP256K1_INLINE static void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m) {
318318
/* For all legal values of m (0..31), the following properties hold: */
319319
VERIFY_CHECK(0xFFFFEFFFFFC2FULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m);
320320
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
329329
r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4];
330330
}
331331

332-
SECP256K1_INLINE static void secp256k1_fe_impl_mul_int(secp256k1_fe *r, int a) {
332+
SECP256K1_INLINE static void secp256k1_fe_impl_mul_int_unchecked(secp256k1_fe *r, int a) {
333333
r->n[0] *= a;
334334
r->n[1] *= a;
335335
r->n[2] *= a;

‎src/field_impl.h

+7-7
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const
4444
return secp256k1_fe_normalizes_to_zero_var(&na);
4545
}
4646

47-
static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) {
47+
static int secp256k1_fe_sqrt(secp256k1_fe * SECP256K1_RESTRICT r, const secp256k1_fe * SECP256K1_RESTRICT a) {
4848
/** Given that p is congruent to 3 mod 4, we can compute the square root of
4949
* a mod p as the (p+1)/4'th power of a.
5050
*
@@ -289,23 +289,23 @@ SECP256K1_INLINE static void secp256k1_fe_get_b32(unsigned char *r, const secp25
289289
secp256k1_fe_impl_get_b32(r, a);
290290
}
291291

292-
static void secp256k1_fe_impl_negate(secp256k1_fe *r, const secp256k1_fe *a, int m);
293-
SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
292+
static void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m);
293+
SECP256K1_INLINE static void secp256k1_fe_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m) {
294294
secp256k1_fe_verify(a);
295295
VERIFY_CHECK(m >= 0 && m <= 31);
296296
VERIFY_CHECK(a->magnitude <= m);
297-
secp256k1_fe_impl_negate(r, a, m);
297+
secp256k1_fe_impl_negate_unchecked(r, a, m);
298298
r->magnitude = m + 1;
299299
r->normalized = 0;
300300
secp256k1_fe_verify(r);
301301
}
302302

303-
static void secp256k1_fe_impl_mul_int(secp256k1_fe *r, int a);
304-
SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) {
303+
static void secp256k1_fe_impl_mul_int_unchecked(secp256k1_fe *r, int a);
304+
SECP256K1_INLINE static void secp256k1_fe_mul_int_unchecked(secp256k1_fe *r, int a) {
305305
secp256k1_fe_verify(r);
306306
VERIFY_CHECK(a >= 0 && a <= 32);
307307
VERIFY_CHECK(a*r->magnitude <= 32);
308-
secp256k1_fe_impl_mul_int(r, a);
308+
secp256k1_fe_impl_mul_int_unchecked(r, a);
309309
r->magnitude *= a;
310310
r->normalized = 0;
311311
secp256k1_fe_verify(r);

‎src/group.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a);
106106
/** Check two group elements (jacobian) for equality in variable time. */
107107
static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b);
108108

109-
/** Compare the X coordinate of a group element (jacobian). */
109+
/** Compare the X coordinate of a group element (jacobian).
110+
* The magnitude of the group element's X coordinate must not exceed 31. */
110111
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a);
111112

112113
/** Set r equal to the inverse of a (i.e., mirrored around the X axis) */

‎src/group_impl.h

+7-4
Original file line numberDiff line numberDiff line change
@@ -314,13 +314,17 @@ static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b)
314314
}
315315

316316
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) {
317-
secp256k1_fe r, r2;
317+
secp256k1_fe r;
318+
319+
#ifdef VERIFY
318320
secp256k1_fe_verify(x);
321+
VERIFY_CHECK(a->x.magnitude <= 31);
319322
secp256k1_gej_verify(a);
320323
VERIFY_CHECK(!a->infinity);
324+
#endif
325+
321326
secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x);
322-
r2 = a->x; secp256k1_fe_normalize_weak(&r2);
323-
return secp256k1_fe_equal_var(&r, &r2);
327+
return secp256k1_fe_equal_var(&r, &a->x);
324328
}
325329

326330
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) {
349353
secp256k1_fe_sqr(&y2, &a->y);
350354
secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
351355
secp256k1_fe_add_int(&x3, SECP256K1_B);
352-
secp256k1_fe_normalize_weak(&x3);
353356
return secp256k1_fe_equal_var(&y2, &x3);
354357
}
355358

‎src/int128_struct_impl.h

+5
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,12 @@ static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigne
8080
r->lo = r->hi >> (n-64);
8181
r->hi = 0;
8282
} else if (n > 0) {
83+
#if defined(_MSC_VER) && defined(_M_X64)
84+
VERIFY_CHECK(n < 64);
85+
r->lo = __shiftright128(r->lo, r->hi, n);
86+
#else
8387
r->lo = ((1U * r->hi) << (64-n)) | r->lo >> n;
88+
#endif
8489
r->hi >>= n;
8590
}
8691
}

‎src/modules/ellswift/Makefile.am.include

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ include_HEADERS += include/secp256k1_ellswift.h
22
noinst_HEADERS += src/modules/ellswift/bench_impl.h
33
noinst_HEADERS += src/modules/ellswift/main_impl.h
44
noinst_HEADERS += src/modules/ellswift/tests_impl.h
5+
noinst_HEADERS += src/modules/ellswift/tests_exhaustive_impl.h
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/***********************************************************************
2+
* Distributed under the MIT software license, see the accompanying *
3+
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
4+
***********************************************************************/
5+
6+
#ifndef SECP256K1_MODULE_ELLSWIFT_TESTS_EXHAUSTIVE_H
7+
#define SECP256K1_MODULE_ELLSWIFT_TESTS_EXHAUSTIVE_H
8+
9+
#include "../../../include/secp256k1_ellswift.h"
10+
#include "main_impl.h"
11+
12+
static void test_exhaustive_ellswift(const secp256k1_context *ctx, const secp256k1_ge *group) {
13+
int i;
14+
15+
/* Note that SwiftEC/ElligatorSwift are inherently curve operations, not
16+
* group operations, and this test only checks the curve points which are in
17+
* a tiny subgroup. In that sense it can't be really seen as exhaustive as
18+
* it doesn't (and for computational reasons obviously cannot) test the
19+
* entire domain ellswift operates under. */
20+
for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) {
21+
secp256k1_scalar scalar_i;
22+
unsigned char sec32[32];
23+
unsigned char ell64[64];
24+
secp256k1_pubkey pub_decoded;
25+
secp256k1_ge ge_decoded;
26+
27+
/* Construct ellswift pubkey from exhaustive loop scalar i. */
28+
secp256k1_scalar_set_int(&scalar_i, i);
29+
secp256k1_scalar_get_b32(sec32, &scalar_i);
30+
CHECK(secp256k1_ellswift_create(ctx, ell64, sec32, NULL));
31+
32+
/* Decode ellswift pubkey and check that it matches the precomputed group element. */
33+
secp256k1_ellswift_decode(ctx, &pub_decoded, ell64);
34+
secp256k1_pubkey_load(ctx, &ge_decoded, &pub_decoded);
35+
ge_equals_ge(&ge_decoded, &group[i]);
36+
}
37+
}
38+
39+
#endif

‎src/modules/ellswift/tests_impl.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,9 @@ void run_ellswift_tests(void) {
322322
secp256k1_testrand256_test(auxrnd32a);
323323
secp256k1_testrand256_test(auxrnd32b);
324324
random_scalar_order_test(&seca);
325-
random_scalar_order_test(&secb);
325+
/* Draw secb uniformly at random to make sure that the secret keys
326+
* differ */
327+
random_scalar_order(&secb);
326328
secp256k1_scalar_get_b32(sec32a, &seca);
327329
secp256k1_scalar_get_b32(sec32b, &secb);
328330

‎src/precompute_ecmult.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,12 @@ static void print_two_tables(FILE *fp, int window_g) {
5656
int main(void) {
5757
/* Always compute all tables for window sizes up to 15. */
5858
int window_g = (ECMULT_WINDOW_SIZE < 15) ? 15 : ECMULT_WINDOW_SIZE;
59+
const char outfile[] = "src/precomputed_ecmult.c";
5960
FILE* fp;
6061

61-
fp = fopen("src/precomputed_ecmult.c","w");
62+
fp = fopen(outfile, "w");
6263
if (fp == NULL) {
63-
fprintf(stderr, "Could not open src/precomputed_ecmult.h for writing!\n");
64+
fprintf(stderr, "Could not open %s for writing!\n", outfile);
6465
return -1;
6566
}
6667

‎src/testrand_impl.h

+17-48
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
#include "util.h"
1717

1818
static uint64_t secp256k1_test_state[4];
19-
static uint64_t secp256k1_test_rng_integer;
20-
static int secp256k1_test_rng_integer_bits_left = 0;
2119

2220
SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16) {
2321
static const unsigned char PREFIX[19] = "secp256k1 test init";
@@ -36,7 +34,6 @@ SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16
3634
for (j = 0; j < 8; ++j) s = (s << 8) | out32[8*i + j];
3735
secp256k1_test_state[i] = s;
3836
}
39-
secp256k1_test_rng_integer_bits_left = 0;
4037
}
4138

4239
SECP256K1_INLINE static uint64_t rotl(const uint64_t x, int k) {
@@ -57,58 +54,30 @@ SECP256K1_INLINE static uint64_t secp256k1_testrand64(void) {
5754
}
5855

5956
SECP256K1_INLINE static uint64_t secp256k1_testrand_bits(int bits) {
60-
uint64_t ret;
61-
if (secp256k1_test_rng_integer_bits_left < bits) {
62-
secp256k1_test_rng_integer = secp256k1_testrand64();
63-
secp256k1_test_rng_integer_bits_left = 64;
64-
}
65-
ret = secp256k1_test_rng_integer;
66-
secp256k1_test_rng_integer >>= bits;
67-
secp256k1_test_rng_integer_bits_left -= bits;
68-
ret &= ((~((uint64_t)0)) >> (64 - bits));
69-
return ret;
57+
if (bits == 0) return 0;
58+
return secp256k1_testrand64() >> (64 - bits);
7059
}
7160

7261
SECP256K1_INLINE static uint32_t secp256k1_testrand32(void) {
73-
return secp256k1_testrand_bits(32);
62+
return secp256k1_testrand64() >> 32;
7463
}
7564

7665
static uint32_t secp256k1_testrand_int(uint32_t range) {
77-
/* We want a uniform integer between 0 and range-1, inclusive.
78-
* B is the smallest number such that range <= 2**B.
79-
* two mechanisms implemented here:
80-
* - generate B bits numbers until one below range is found, and return it
81-
* - find the largest multiple M of range that is <= 2**(B+A), generate B+A
82-
* bits numbers until one below M is found, and return it modulo range
83-
* The second mechanism consumes A more bits of entropy in every iteration,
84-
* but may need fewer iterations due to M being closer to 2**(B+A) then
85-
* range is to 2**B. The array below (indexed by B) contains a 0 when the
86-
* first mechanism is to be used, and the number A otherwise.
87-
*/
88-
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};
89-
uint32_t trange, mult;
90-
int bits = 0;
91-
if (range <= 1) {
92-
return 0;
93-
}
94-
trange = range - 1;
95-
while (trange > 0) {
96-
trange >>= 1;
97-
bits++;
66+
uint32_t mask = 0;
67+
uint32_t range_copy;
68+
/* Reduce range by 1, changing its meaning to "maximum value". */
69+
VERIFY_CHECK(range != 0);
70+
range -= 1;
71+
/* Count the number of bits in range. */
72+
range_copy = range;
73+
while (range_copy) {
74+
mask = (mask << 1) | 1U;
75+
range_copy >>= 1;
9876
}
99-
if (addbits[bits]) {
100-
bits = bits + addbits[bits];
101-
mult = ((~((uint32_t)0)) >> (32 - bits)) / range;
102-
trange = range * mult;
103-
} else {
104-
trange = range;
105-
mult = 1;
106-
}
107-
while(1) {
108-
uint32_t x = secp256k1_testrand_bits(bits);
109-
if (x < trange) {
110-
return (mult == 1) ? x : (x % range);
111-
}
77+
/* Generation loop. */
78+
while (1) {
79+
uint32_t val = secp256k1_testrand64() & mask;
80+
if (val <= range) return val;
11281
}
11382
}
11483

‎src/tests.c

+65-139
Original file line numberDiff line numberDiff line change
@@ -89,16 +89,6 @@ static void uncounting_illegal_callback_fn(const char* str, void* data) {
8989
(*p)--;
9090
}
9191

92-
static void random_field_element_test(secp256k1_fe *fe) {
93-
do {
94-
unsigned char b32[32];
95-
secp256k1_testrand256_test(b32);
96-
if (secp256k1_fe_set_b32_limit(fe, b32)) {
97-
break;
98-
}
99-
} while(1);
100-
}
101-
10292
static void random_field_element_magnitude(secp256k1_fe *fe) {
10393
secp256k1_fe zero;
10494
int n = secp256k1_testrand_int(9);
@@ -108,17 +98,33 @@ static void random_field_element_magnitude(secp256k1_fe *fe) {
10898
}
10999
secp256k1_fe_clear(&zero);
110100
secp256k1_fe_negate(&zero, &zero, 0);
111-
secp256k1_fe_mul_int(&zero, n - 1);
101+
secp256k1_fe_mul_int_unchecked(&zero, n - 1);
112102
secp256k1_fe_add(fe, &zero);
113103
#ifdef VERIFY
114104
CHECK(fe->magnitude == n);
115105
#endif
116106
}
117107

108+
static void random_fe_test(secp256k1_fe *x) {
109+
unsigned char bin[32];
110+
do {
111+
secp256k1_testrand256_test(bin);
112+
if (secp256k1_fe_set_b32_limit(x, bin)) {
113+
return;
114+
}
115+
} while(1);
116+
}
117+
118+
static void random_fe_non_zero_test(secp256k1_fe *fe) {
119+
do {
120+
random_fe_test(fe);
121+
} while(secp256k1_fe_is_zero(fe));
122+
}
123+
118124
static void random_group_element_test(secp256k1_ge *ge) {
119125
secp256k1_fe fe;
120126
do {
121-
random_field_element_test(&fe);
127+
random_fe_test(&fe);
122128
if (secp256k1_ge_set_xo_var(ge, &fe, secp256k1_testrand_bits(1))) {
123129
secp256k1_fe_normalize(&ge->y);
124130
break;
@@ -129,12 +135,7 @@ static void random_group_element_test(secp256k1_ge *ge) {
129135

130136
static void random_group_element_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) {
131137
secp256k1_fe z2, z3;
132-
do {
133-
random_field_element_test(&gej->z);
134-
if (!secp256k1_fe_is_zero(&gej->z)) {
135-
break;
136-
}
137-
} while(1);
138+
random_fe_non_zero_test(&gej->z);
138139
secp256k1_fe_sqr(&z2, &gej->z);
139140
secp256k1_fe_mul(&z3, &z2, &gej->z);
140141
secp256k1_fe_mul(&gej->x, &ge->x, &z2);
@@ -180,6 +181,35 @@ static void random_scalar_order_b32(unsigned char *b32) {
180181
secp256k1_scalar_get_b32(b32, &num);
181182
}
182183

184+
static void run_xoshiro256pp_tests(void) {
185+
{
186+
size_t i;
187+
/* Sanity check that we run before the actual seeding. */
188+
for (i = 0; i < sizeof(secp256k1_test_state)/sizeof(secp256k1_test_state[0]); i++) {
189+
CHECK(secp256k1_test_state[i] == 0);
190+
}
191+
}
192+
{
193+
int i;
194+
unsigned char buf32[32];
195+
unsigned char seed16[16] = {
196+
'C', 'H', 'I', 'C', 'K', 'E', 'N', '!',
197+
'C', 'H', 'I', 'C', 'K', 'E', 'N', '!',
198+
};
199+
unsigned char buf32_expected[32] = {
200+
0xAF, 0xCC, 0xA9, 0x16, 0xB5, 0x6C, 0xE3, 0xF0,
201+
0x44, 0x3F, 0x45, 0xE0, 0x47, 0xA5, 0x08, 0x36,
202+
0x4C, 0xCC, 0xC1, 0x18, 0xB2, 0xD8, 0x8F, 0xEF,
203+
0x43, 0x26, 0x15, 0x57, 0x37, 0x00, 0xEF, 0x30,
204+
};
205+
secp256k1_testrand_seed(seed16);
206+
for (i = 0; i < 17; i++) {
207+
secp256k1_testrand256(buf32);
208+
}
209+
CHECK(secp256k1_memcmp_var(buf32, buf32_expected, sizeof(buf32)) == 0);
210+
}
211+
}
212+
183213
static void run_selftest_tests(void) {
184214
/* Test public API */
185215
secp256k1_selftest();
@@ -823,78 +853,6 @@ static void run_tagged_sha256_tests(void) {
823853
CHECK(secp256k1_memcmp_var(hash32, hash_expected, sizeof(hash32)) == 0);
824854
}
825855

826-
/***** RANDOM TESTS *****/
827-
828-
static void test_rand_bits(int rand32, int bits) {
829-
/* (1-1/2^B)^rounds[B] < 1/10^9, so rounds is the number of iterations to
830-
* get a false negative chance below once in a billion */
831-
static const unsigned int rounds[7] = {1, 30, 73, 156, 322, 653, 1316};
832-
/* We try multiplying the results with various odd numbers, which shouldn't
833-
* influence the uniform distribution modulo a power of 2. */
834-
static const uint32_t mults[6] = {1, 3, 21, 289, 0x9999, 0x80402011};
835-
/* We only select up to 6 bits from the output to analyse */
836-
unsigned int usebits = bits > 6 ? 6 : bits;
837-
unsigned int maxshift = bits - usebits;
838-
/* For each of the maxshift+1 usebits-bit sequences inside a bits-bit
839-
number, track all observed outcomes, one per bit in a uint64_t. */
840-
uint64_t x[6][27] = {{0}};
841-
unsigned int i, shift, m;
842-
/* Multiply the output of all rand calls with the odd number m, which
843-
should not change the uniformity of its distribution. */
844-
for (i = 0; i < rounds[usebits]; i++) {
845-
uint32_t r = (rand32 ? secp256k1_testrand32() : secp256k1_testrand_bits(bits));
846-
CHECK((((uint64_t)r) >> bits) == 0);
847-
for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) {
848-
uint32_t rm = r * mults[m];
849-
for (shift = 0; shift <= maxshift; shift++) {
850-
x[m][shift] |= (((uint64_t)1) << ((rm >> shift) & ((1 << usebits) - 1)));
851-
}
852-
}
853-
}
854-
for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) {
855-
for (shift = 0; shift <= maxshift; shift++) {
856-
/* Test that the lower usebits bits of x[shift] are 1 */
857-
CHECK(((~x[m][shift]) << (64 - (1 << usebits))) == 0);
858-
}
859-
}
860-
}
861-
862-
/* Subrange must be a whole divisor of range, and at most 64 */
863-
static void test_rand_int(uint32_t range, uint32_t subrange) {
864-
/* (1-1/subrange)^rounds < 1/10^9 */
865-
int rounds = (subrange * 2073) / 100;
866-
int i;
867-
uint64_t x = 0;
868-
CHECK((range % subrange) == 0);
869-
for (i = 0; i < rounds; i++) {
870-
uint32_t r = secp256k1_testrand_int(range);
871-
CHECK(r < range);
872-
r = r % subrange;
873-
x |= (((uint64_t)1) << r);
874-
}
875-
/* Test that the lower subrange bits of x are 1. */
876-
CHECK(((~x) << (64 - subrange)) == 0);
877-
}
878-
879-
static void run_rand_bits(void) {
880-
size_t b;
881-
test_rand_bits(1, 32);
882-
for (b = 1; b <= 32; b++) {
883-
test_rand_bits(0, b);
884-
}
885-
}
886-
887-
static void run_rand_int(void) {
888-
static const uint32_t ms[] = {1, 3, 17, 1000, 13771, 999999, 33554432};
889-
static const uint32_t ss[] = {1, 3, 6, 9, 13, 31, 64};
890-
unsigned int m, s;
891-
for (m = 0; m < sizeof(ms) / sizeof(ms[0]); m++) {
892-
for (s = 0; s < sizeof(ss) / sizeof(ss[0]); s++) {
893-
test_rand_int(ms[m] * ss[s], ss[s]);
894-
}
895-
}
896-
}
897-
898856
/***** MODINV TESTS *****/
899857

900858
/* Compute the modular inverse of (odd) x mod 2^64. */
@@ -2984,16 +2942,6 @@ static void random_fe(secp256k1_fe *x) {
29842942
} while(1);
29852943
}
29862944

2987-
static void random_fe_test(secp256k1_fe *x) {
2988-
unsigned char bin[32];
2989-
do {
2990-
secp256k1_testrand256_test(bin);
2991-
if (secp256k1_fe_set_b32_limit(x, bin)) {
2992-
return;
2993-
}
2994-
} while(1);
2995-
}
2996-
29972945
static void random_fe_non_zero(secp256k1_fe *nz) {
29982946
int tries = 10;
29992947
while (--tries >= 0) {
@@ -3234,7 +3182,7 @@ static void run_field_misc(void) {
32343182
CHECK(q.normalized && q.magnitude == 1);
32353183
#endif
32363184
for (j = 0; j < 6; j++) {
3237-
secp256k1_fe_negate(&z, &z, j+1);
3185+
secp256k1_fe_negate_unchecked(&z, &z, j+1);
32383186
secp256k1_fe_normalize_var(&q);
32393187
secp256k1_fe_cmov(&q, &z, (j&1));
32403188
#ifdef VERIFY
@@ -3820,18 +3768,14 @@ static void test_ge(void) {
38203768
}
38213769

38223770
/* Generate random zf, and zfi2 = 1/zf^2, zfi3 = 1/zf^3 */
3823-
do {
3824-
random_field_element_test(&zf);
3825-
} while(secp256k1_fe_is_zero(&zf));
3771+
random_fe_non_zero_test(&zf);
38263772
random_field_element_magnitude(&zf);
38273773
secp256k1_fe_inv_var(&zfi3, &zf);
38283774
secp256k1_fe_sqr(&zfi2, &zfi3);
38293775
secp256k1_fe_mul(&zfi3, &zfi3, &zfi2);
38303776

38313777
/* Generate random r */
3832-
do {
3833-
random_field_element_test(&r);
3834-
} while(secp256k1_fe_is_zero(&r));
3778+
random_fe_non_zero_test(&r);
38353779

38363780
for (i1 = 0; i1 < 1 + 4 * runs; i1++) {
38373781
int i2;
@@ -4048,22 +3992,15 @@ static void test_add_neg_y_diff_x(void) {
40483992
* which this test is a regression test for.
40493993
*
40503994
* These points were generated in sage as
4051-
* # secp256k1 params
4052-
* F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F)
4053-
* C = EllipticCurve ([F (0), F (7)])
4054-
* G = C.lift_x(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798)
4055-
* N = FiniteField(G.order())
40563995
*
4057-
* # endomorphism values (lambda is 1^{1/3} in N, beta is 1^{1/3} in F)
4058-
* x = polygen(N)
4059-
* lam = (1 - x^3).roots()[1][0]
3996+
* load("secp256k1_params.sage")
40603997
*
40613998
* # random "bad pair"
40623999
* P = C.random_element()
4063-
* Q = -int(lam) * P
4064-
* print " P: %x %x" % P.xy()
4065-
* print " Q: %x %x" % Q.xy()
4066-
* print "P + Q: %x %x" % (P + Q).xy()
4000+
* Q = -int(LAMBDA) * P
4001+
* print(" P: %x %x" % P.xy())
4002+
* print(" Q: %x %x" % Q.xy())
4003+
* print("P + Q: %x %x" % (P + Q).xy())
40674004
*/
40684005
secp256k1_gej aj = SECP256K1_GEJ_CONST(
40694006
0x8d24cd95, 0x0a355af1, 0x3c543505, 0x44238d30,
@@ -4148,10 +4085,7 @@ static void run_gej(void) {
41484085
CHECK(!secp256k1_gej_eq_var(&a, &b));
41494086

41504087
b = a;
4151-
random_field_element_test(&fe);
4152-
if (secp256k1_fe_is_zero(&fe)) {
4153-
continue;
4154-
}
4088+
random_fe_non_zero_test(&fe);
41554089
secp256k1_gej_rescale(&a, &fe);
41564090
CHECK(secp256k1_gej_eq_var(&a, &b));
41574091
}
@@ -4590,9 +4524,7 @@ static void ecmult_const_mult_xonly(void) {
45904524
random_scalar_order_test(&q);
45914525
/* If i is odd, n=d*base.x for random non-zero d */
45924526
if (i & 1) {
4593-
do {
4594-
random_field_element_test(&d);
4595-
} while (secp256k1_fe_normalizes_to_zero_var(&d));
4527+
random_fe_non_zero_test(&d);
45964528
secp256k1_fe_mul(&n, &base.x, &d);
45974529
} else {
45984530
n = base.x;
@@ -4611,22 +4543,17 @@ static void ecmult_const_mult_xonly(void) {
46114543

46124544
/* Test that secp256k1_ecmult_const_xonly correctly rejects X coordinates not on curve. */
46134545
for (i = 0; i < 2*COUNT; ++i) {
4614-
secp256k1_fe x, n, d, c, r;
4546+
secp256k1_fe x, n, d, r;
46154547
int res;
46164548
secp256k1_scalar q;
46174549
random_scalar_order_test(&q);
46184550
/* Generate random X coordinate not on the curve. */
46194551
do {
4620-
random_field_element_test(&x);
4621-
secp256k1_fe_sqr(&c, &x);
4622-
secp256k1_fe_mul(&c, &c, &x);
4623-
secp256k1_fe_add_int(&c, SECP256K1_B);
4624-
} while (secp256k1_fe_is_square_var(&c));
4552+
random_fe_test(&x);
4553+
} while (secp256k1_ge_x_on_curve_var(&x));
46254554
/* If i is odd, n=d*x for random non-zero d. */
46264555
if (i & 1) {
4627-
do {
4628-
random_field_element_test(&d);
4629-
} while (secp256k1_fe_normalizes_to_zero_var(&d));
4556+
random_fe_non_zero_test(&d);
46304557
secp256k1_fe_mul(&n, &x, &d);
46314558
} else {
46324559
n = x;
@@ -7765,6 +7692,9 @@ int main(int argc, char **argv) {
77657692
}
77667693
printf("test count = %i\n", COUNT);
77677694

7695+
/* run test RNG tests (must run before we really initialize the test RNG) */
7696+
run_xoshiro256pp_tests();
7697+
77687698
/* find random seed */
77697699
secp256k1_testrand_init(argc > 2 ? argv[2] : NULL);
77707700

@@ -7802,10 +7732,6 @@ int main(int argc, char **argv) {
78027732
/* scratch tests */
78037733
run_scratch_tests();
78047734

7805-
/* randomness tests */
7806-
run_rand_bits();
7807-
run_rand_int();
7808-
78097735
/* integer arithmetic tests */
78107736
#ifdef SECP256K1_WIDEMUL_INT128
78117737
run_int128_tests();

‎src/tests_exhaustive.c

+16
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
#define EXHAUSTIVE_TEST_ORDER 13
1414
#endif
1515

16+
/* These values of B are all values in [1, 8] that result in a curve with even order. */
17+
#define EXHAUSTIVE_TEST_CURVE_HAS_EVEN_ORDER (SECP256K1_B == 1 || SECP256K1_B == 6 || SECP256K1_B == 8)
18+
1619
#ifdef USE_EXTERNAL_DEFAULT_CALLBACKS
1720
#pragma message("Ignoring USE_EXTERNAL_CALLBACKS in exhaustive_tests.")
1821
#undef USE_EXTERNAL_DEFAULT_CALLBACKS
@@ -395,6 +398,10 @@ static void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_g
395398
#include "modules/schnorrsig/tests_exhaustive_impl.h"
396399
#endif
397400

401+
#ifdef ENABLE_MODULE_ELLSWIFT
402+
#include "modules/ellswift/tests_exhaustive_impl.h"
403+
#endif
404+
398405
int main(int argc, char** argv) {
399406
int i;
400407
secp256k1_gej groupj[EXHAUSTIVE_TEST_ORDER];
@@ -490,6 +497,15 @@ int main(int argc, char** argv) {
490497
#ifdef ENABLE_MODULE_SCHNORRSIG
491498
test_exhaustive_schnorrsig(ctx);
492499
#endif
500+
#ifdef ENABLE_MODULE_ELLSWIFT
501+
/* The ellswift algorithm does have additional edge cases when operating on
502+
* curves of even order, which are not included in the code as secp256k1 is
503+
* of odd order. Skip the ellswift tests if the used exhaustive tests curve
504+
* is even-ordered accordingly. */
505+
#if !EXHAUSTIVE_TEST_CURVE_HAS_EVEN_ORDER
506+
test_exhaustive_ellswift(ctx, group);
507+
#endif
508+
#endif
493509

494510
secp256k1_context_destroy(ctx);
495511
}

‎src/util.h

+13
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,19 @@ static void print_buf_plain(const unsigned char *buf, size_t len) {
5151
# define SECP256K1_INLINE inline
5252
# endif
5353

54+
/** Assert statically that expr is an integer constant expression, and run stmt.
55+
*
56+
* Useful for example to enforce that magnitude arguments are constant.
57+
*/
58+
#define ASSERT_INT_CONST_AND_DO(expr, stmt) do { \
59+
switch(42) { \
60+
case /* ERROR: integer argument is not constant */ expr: \
61+
break; \
62+
default: ; \
63+
} \
64+
stmt; \
65+
} while(0)
66+
5467
typedef struct {
5568
void (*fn)(const char *text, void* data);
5669
const void* data;

0 commit comments

Comments
 (0)
Please sign in to comment.