diff --git a/secp256k1-sys/depend/secp256k1-HEAD-revision.txt b/secp256k1-sys/depend/secp256k1-HEAD-revision.txt index 4a44100c3..96fcb1e98 100644 --- a/secp256k1-sys/depend/secp256k1-HEAD-revision.txt +++ b/secp256k1-sys/depend/secp256k1-HEAD-revision.txt @@ -1,2 +1,2 @@ # This file was automatically created by vendor-libsecp.sh -acf5c55ae6a94e5ca847e07def40427547876101 +199d27cea32203b224b208627533c2e813cd3b21 diff --git a/secp256k1-sys/depend/secp256k1/.cirrus.yml b/secp256k1-sys/depend/secp256k1/.cirrus.yml deleted file mode 100644 index 12e987034..000000000 --- a/secp256k1-sys/depend/secp256k1/.cirrus.yml +++ /dev/null @@ -1,409 +0,0 @@ -env: - ### cirrus config - CIRRUS_CLONE_DEPTH: 1 - ### compiler options - HOST: - WRAPPER_CMD: - # Specific warnings can be disabled with -Wno-error=foo. - # -pedantic-errors is not equivalent to -Werror=pedantic and thus not implied by -Werror according to the GCC manual. - WERROR_CFLAGS: -Werror -pedantic-errors - MAKEFLAGS: -j4 - BUILD: check - ### secp256k1 config - ECMULTWINDOW: auto - ECMULTGENPRECISION: auto - ASM: no - WIDEMUL: auto - WITH_VALGRIND: yes - EXTRAFLAGS: - ### secp256k1 modules - EXPERIMENTAL: no - ECDH: no - RECOVERY: no - SCHNORRSIG: no - ### test options - SECP256K1_TEST_ITERS: - BENCH: yes - SECP256K1_BENCH_ITERS: 2 - CTIMETESTS: yes - # Compile and run the tests - EXAMPLES: yes - -# https://cirrus-ci.org/pricing/#compute-credits -credits_snippet: &CREDITS - # Don't use any credits for now. - use_compute_credits: false - -cat_logs_snippet: &CAT_LOGS - always: - cat_tests_log_script: - - cat tests.log || true - cat_noverify_tests_log_script: - - cat noverify_tests.log || true - cat_exhaustive_tests_log_script: - - cat exhaustive_tests.log || true - cat_ctime_tests_log_script: - - cat ctime_tests.log || true - cat_bench_log_script: - - cat bench.log || true - cat_config_log_script: - - cat config.log || true - cat_test_env_script: - - cat test_env.log || true - 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 - # Reduce number of CPUs to be able to do more builds in parallel. - cpu: 1 - # Gives us more CPUs for free if they're available. - greedy: true - # More than enough for our scripts. - memory: 1G - -task: - name: "x86_64: Linux (Debian stable)" - << : *LINUX_CONTAINER - matrix: &ENV_MATRIX - - env: {WIDEMUL: int64, RECOVERY: yes} - - env: {WIDEMUL: int64, ECDH: yes, SCHNORRSIG: yes} - - env: {WIDEMUL: int128} - - env: {WIDEMUL: int128_struct} - - env: {WIDEMUL: int128, RECOVERY: yes, SCHNORRSIG: yes} - - env: {WIDEMUL: int128, ECDH: yes, SCHNORRSIG: yes} - - env: {WIDEMUL: int128, ASM: x86_64} - - env: { RECOVERY: yes, SCHNORRSIG: yes} - - env: {CTIMETESTS: no, RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, CPPFLAGS: -DVERIFY} - - env: {BUILD: distcheck, WITH_VALGRIND: no, CTIMETESTS: no, BENCH: no} - - env: {CPPFLAGS: -DDETERMINISTIC} - - env: {CFLAGS: -O0, CTIMETESTS: no} - - env: { ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } - - env: { ECMULTGENPRECISION: 8, ECMULTWINDOW: 4 } - matrix: - - env: - CC: gcc - - env: - CC: clang - << : *MERGE_BASE - test_script: - - ./ci/cirrus.sh - << : *CAT_LOGS - -task: - name: "i686: Linux (Debian stable)" - << : *LINUX_CONTAINER - env: - HOST: i686-linux-gnu - ECDH: yes - RECOVERY: yes - SCHNORRSIG: yes - matrix: - - env: - 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 - -task: - name: "arm64: macOS Ventura" - macos_instance: - image: ghcr.io/cirruslabs/macos-ventura-base:latest - env: - HOMEBREW_NO_AUTO_UPDATE: 1 - 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 - matrix: - - env: - CC: gcc - - env: - CC: clang - brew_script: - - brew install automake libtool gcc - << : *MERGE_BASE - test_script: - - ./ci/cirrus.sh - << : *CAT_LOGS - << : *CREDITS - -task: - name: "s390x (big-endian): Linux (Debian stable, QEMU)" - << : *LINUX_CONTAINER - env: - WRAPPER_CMD: qemu-s390x - SECP256K1_TEST_ITERS: 16 - HOST: s390x-linux-gnu - WITH_VALGRIND: no - ECDH: yes - RECOVERY: yes - SCHNORRSIG: yes - CTIMETESTS: no - << : *MERGE_BASE - test_script: - # https://sourceware.org/bugzilla/show_bug.cgi?id=27008 - - rm /etc/ld.so.cache - - ./ci/cirrus.sh - << : *CAT_LOGS - -task: - name: "ARM32: Linux (Debian stable, QEMU)" - << : *LINUX_CONTAINER - env: - WRAPPER_CMD: qemu-arm - SECP256K1_TEST_ITERS: 16 - HOST: arm-linux-gnueabihf - WITH_VALGRIND: no - ECDH: yes - RECOVERY: yes - SCHNORRSIG: yes - CTIMETESTS: no - matrix: - - env: {} - - env: {EXPERIMENTAL: yes, ASM: arm32} - << : *MERGE_BASE - test_script: - - ./ci/cirrus.sh - << : *CAT_LOGS - -task: - name: "ARM64: Linux (Debian stable, QEMU)" - << : *LINUX_CONTAINER - env: - WRAPPER_CMD: qemu-aarch64 - SECP256K1_TEST_ITERS: 16 - HOST: aarch64-linux-gnu - WITH_VALGRIND: no - ECDH: yes - RECOVERY: yes - SCHNORRSIG: yes - CTIMETESTS: no - << : *MERGE_BASE - test_script: - - ./ci/cirrus.sh - << : *CAT_LOGS - -task: - name: "ppc64le: Linux (Debian stable, QEMU)" - << : *LINUX_CONTAINER - env: - WRAPPER_CMD: qemu-ppc64le - SECP256K1_TEST_ITERS: 16 - HOST: powerpc64le-linux-gnu - WITH_VALGRIND: no - ECDH: yes - RECOVERY: yes - SCHNORRSIG: yes - CTIMETESTS: no - << : *MERGE_BASE - test_script: - - ./ci/cirrus.sh - << : *CAT_LOGS - -task: - << : *LINUX_CONTAINER - env: - WRAPPER_CMD: wine - WITH_VALGRIND: no - ECDH: yes - RECOVERY: yes - SCHNORRSIG: yes - CTIMETESTS: no - matrix: - - name: "x86_64 (mingw32-w64): Windows (Debian stable, Wine)" - env: - HOST: x86_64-w64-mingw32 - - name: "i686 (mingw32-w64): Windows (Debian stable, Wine)" - env: - HOST: i686-w64-mingw32 - << : *MERGE_BASE - test_script: - - ./ci/cirrus.sh - << : *CAT_LOGS - -task: - << : *LINUX_CONTAINER - env: - WRAPPER_CMD: wine - WERROR_CFLAGS: -WX - WITH_VALGRIND: no - ECDH: yes - RECOVERY: yes - EXPERIMENTAL: yes - SCHNORRSIG: yes - CTIMETESTS: no - # Use a MinGW-w64 host to tell ./configure we're building for Windows. - # This will detect some MinGW-w64 tools but then make will need only - # the MSVC tools CC, AR and NM as specified below. - HOST: x86_64-w64-mingw32 - CC: /opt/msvc/bin/x64/cl - AR: /opt/msvc/bin/x64/lib - NM: /opt/msvc/bin/x64/dumpbin -symbols -headers - # Set non-essential options that affect the CLI messages here. - # (They depend on the user's taste, so we don't want to set them automatically in configure.ac.) - CFLAGS: -nologo -diagnostics:caret - LDFLAGS: -Xlinker -Xlinker -Xlinker -nologo - matrix: - - name: "x86_64 (MSVC): Windows (Debian stable, Wine)" - - name: "x86_64 (MSVC): Windows (Debian stable, Wine, int128_struct)" - env: - WIDEMUL: int128_struct - - name: "x86_64 (MSVC): Windows (Debian stable, Wine, int128_struct with __(u)mulh)" - env: - WIDEMUL: int128_struct - CPPFLAGS: -DSECP256K1_MSVC_MULH_TEST_OVERRIDE - - name: "i686 (MSVC): Windows (Debian stable, Wine)" - env: - HOST: i686-w64-mingw32 - 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 - -# Sanitizers -task: - << : *LINUX_CONTAINER - env: - ECDH: yes - RECOVERY: yes - SCHNORRSIG: yes - CTIMETESTS: no - matrix: - - name: "Valgrind (memcheck)" - container: - cpu: 2 - env: - # The `--error-exitcode` is required to make the test fail if valgrind found errors, otherwise it'll return 0 (https://www.valgrind.org/docs/manual/manual-core.html) - WRAPPER_CMD: "valgrind --error-exitcode=42" - SECP256K1_TEST_ITERS: 2 - - name: "UBSan, ASan, LSan" - container: - memory: 2G - env: - CFLAGS: "-fsanitize=undefined,address -g" - UBSAN_OPTIONS: "print_stacktrace=1:halt_on_error=1" - ASAN_OPTIONS: "strict_string_checks=1:detect_stack_use_after_return=1:detect_leaks=1" - LSAN_OPTIONS: "use_unaligned=1" - SECP256K1_TEST_ITERS: 32 - # Try to cover many configurations with just a tiny matrix. - matrix: - - env: - ASM: auto - - env: - ASM: no - ECMULTGENPRECISION: 2 - ECMULTWINDOW: 2 - matrix: - - env: - CC: clang - - env: - HOST: i686-linux-gnu - CC: i686-linux-gnu-gcc - << : *MERGE_BASE - test_script: - - ./ci/cirrus.sh - << : *CAT_LOGS - -# Memory sanitizers -task: - << : *LINUX_CONTAINER - name: "MSan" - env: - ECDH: yes - RECOVERY: yes - SCHNORRSIG: yes - CTIMETESTS: yes - CC: clang - SECP256K1_TEST_ITERS: 32 - ASM: no - WITH_VALGRIND: no - container: - memory: 2G - matrix: - - env: - CFLAGS: "-fsanitize=memory -g" - - env: - ECMULTGENPRECISION: 2 - ECMULTWINDOW: 2 - CFLAGS: "-fsanitize=memory -g -O3" - << : *MERGE_BASE - test_script: - - ./ci/cirrus.sh - << : *CAT_LOGS - -task: - name: "C++ -fpermissive (entire project)" - << : *LINUX_CONTAINER - env: - CC: g++ - CFLAGS: -fpermissive -g - CPPFLAGS: -DSECP256K1_CPLUSPLUS_TEST_OVERRIDE - WERROR_CFLAGS: - ECDH: yes - RECOVERY: yes - SCHNORRSIG: yes - << : *MERGE_BASE - test_script: - - ./ci/cirrus.sh - << : *CAT_LOGS - -task: - name: "C++ (public headers)" - << : *LINUX_CONTAINER - test_script: - - g++ -Werror include/*.h - - clang -Werror -x c++-header include/*.h - - /opt/msvc/bin/x64/cl.exe -c -WX -TP include/*.h - -task: - name: "sage prover" - << : *LINUX_CONTAINER - test_script: - - cd sage - - sage prove_group_implementations.sage - -task: - name: "x86_64: Windows (VS 2022)" - windows_container: - image: cirrusci/windowsservercore:visualstudio2022 - cpu: 4 - memory: 3840MB - env: - PATH: '%CIRRUS_WORKING_DIR%\build\src\RelWithDebInfo;%PATH%' - x64_NATIVE_TOOLS: '"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvars64.bat"' - # 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; } - 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 - build_script: - - '%x64_NATIVE_TOOLS%' - - cmake --build build --config RelWithDebInfo -- -property:UseMultiToolTask=true;CL_MPcount=5 - check_script: - - '%x64_NATIVE_TOOLS%' - - ctest -C RelWithDebInfo --test-dir build -j 5 - - build\src\RelWithDebInfo\bench_ecmult.exe - - build\src\RelWithDebInfo\bench_internal.exe - - build\src\RelWithDebInfo\bench.exe diff --git a/secp256k1-sys/depend/secp256k1/.github/actions/install-homebrew-valgrind/action.yml b/secp256k1-sys/depend/secp256k1/.github/actions/install-homebrew-valgrind/action.yml new file mode 100644 index 000000000..094ff891f --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/.github/actions/install-homebrew-valgrind/action.yml @@ -0,0 +1,33 @@ +name: "Install Valgrind" +description: "Install Homebrew's Valgrind package and cache it." +runs: + using: "composite" + steps: + - run: | + brew tap LouisBrunner/valgrind + brew fetch --HEAD LouisBrunner/valgrind/valgrind + echo "CI_HOMEBREW_CELLAR_VALGRIND=$(brew --cellar valgrind)" >> "$GITHUB_ENV" + shell: bash + + - run: | + sw_vers > valgrind_fingerprint + brew --version >> valgrind_fingerprint + git -C "$(brew --cache)/valgrind--git" rev-parse HEAD >> valgrind_fingerprint + cat valgrind_fingerprint + shell: bash + + - uses: actions/cache@v3 + id: cache + with: + path: ${{ env.CI_HOMEBREW_CELLAR_VALGRIND }} + key: ${{ github.job }}-valgrind-${{ hashFiles('valgrind_fingerprint') }} + + - if: steps.cache.outputs.cache-hit != 'true' + run: | + brew install --HEAD LouisBrunner/valgrind/valgrind + shell: bash + + - if: steps.cache.outputs.cache-hit == 'true' + run: | + brew link valgrind + shell: bash diff --git a/secp256k1-sys/depend/secp256k1/.github/actions/run-in-docker-action/action.yml b/secp256k1-sys/depend/secp256k1/.github/actions/run-in-docker-action/action.yml new file mode 100644 index 000000000..d357c3cf7 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/.github/actions/run-in-docker-action/action.yml @@ -0,0 +1,49 @@ +name: 'Run in Docker with environment' +description: 'Run a command in a Docker container, while passing explicitly set environment variables into the container.' +inputs: + dockerfile: + description: 'A Dockerfile that defines an image' + required: true + tag: + description: 'A tag of an image' + required: true + command: + description: 'A command to run in a container' + required: false + default: ./ci/ci.sh +runs: + using: "composite" + steps: + - uses: docker/setup-buildx-action@v2 + + - uses: docker/build-push-action@v4 + id: main_builder + continue-on-error: true + with: + context: . + file: ${{ inputs.dockerfile }} + tags: ${{ inputs.tag }} + load: true + cache-from: type=gha + + - uses: docker/build-push-action@v4 + id: retry_builder + if: steps.main_builder.outcome == 'failure' + with: + context: . + file: ${{ inputs.dockerfile }} + tags: ${{ inputs.tag }} + load: true + cache-from: type=gha + + - # Tell Docker to pass environment variables in `env` into the container. + run: > + docker run \ + $(echo '${{ toJSON(env) }}' | jq -r 'keys[] | "--env \(.) "') \ + --volume ${{ github.workspace }}:${{ github.workspace }} \ + --workdir ${{ github.workspace }} \ + ${{ inputs.tag }} bash -c " + git config --global --add safe.directory ${{ github.workspace }} + ${{ inputs.command }} + " + shell: bash diff --git a/secp256k1-sys/depend/secp256k1/.github/workflows/ci.yml b/secp256k1-sys/depend/secp256k1/.github/workflows/ci.yml new file mode 100644 index 000000000..b9a9eaa82 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/.github/workflows/ci.yml @@ -0,0 +1,806 @@ +name: CI +on: + pull_request: + push: + branches: + - '**' + tags-ignore: + - '**' + +concurrency: + group: ${{ github.event_name != 'pull_request' && github.run_id || github.ref }} + cancel-in-progress: true + +env: + ### compiler options + HOST: + WRAPPER_CMD: + # Specific warnings can be disabled with -Wno-error=foo. + # -pedantic-errors is not equivalent to -Werror=pedantic and thus not implied by -Werror according to the GCC manual. + WERROR_CFLAGS: '-Werror -pedantic-errors' + MAKEFLAGS: '-j4' + BUILD: 'check' + ### secp256k1 config + ECMULTWINDOW: 'auto' + ECMULTGENPRECISION: 'auto' + ASM: 'no' + WIDEMUL: 'auto' + WITH_VALGRIND: 'yes' + EXTRAFLAGS: + ### secp256k1 modules + EXPERIMENTAL: 'no' + ECDH: 'no' + RECOVERY: 'no' + SCHNORRSIG: 'no' + ELLSWIFT: 'no' + ### test options + SECP256K1_TEST_ITERS: + BENCH: 'yes' + SECP256K1_BENCH_ITERS: 2 + CTIMETESTS: 'yes' + # Compile and run the examples. + EXAMPLES: 'yes' + +jobs: + docker_cache: + name: "Build Docker image" + runs-on: ubuntu-latest + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + with: + # See: https://github.com/moby/buildkit/issues/3969. + driver-opts: | + network=host + + - name: Build container + uses: docker/build-push-action@v4 + with: + file: ./ci/linux-debian.Dockerfile + tags: linux-debian-image + cache-from: type=gha + cache-to: type=gha,mode=min + + linux_debian: + name: "x86_64: Linux (Debian stable)" + runs-on: ubuntu-latest + needs: docker_cache + + strategy: + fail-fast: false + matrix: + configuration: + - env_vars: { WIDEMUL: 'int64', RECOVERY: 'yes' } + - env_vars: { WIDEMUL: 'int64', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - env_vars: { WIDEMUL: 'int128' } + - env_vars: { WIDEMUL: 'int128_struct', ELLSWIFT: 'yes' } + - env_vars: { WIDEMUL: 'int128', RECOVERY: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - env_vars: { WIDEMUL: 'int128', ECDH: 'yes', SCHNORRSIG: 'yes' } + - env_vars: { WIDEMUL: 'int128', ASM: 'x86_64', ELLSWIFT: 'yes' } + - env_vars: { RECOVERY: 'yes', SCHNORRSIG: 'yes' } + - env_vars: { CTIMETESTS: 'no', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', CPPFLAGS: '-DVERIFY' } + - env_vars: { BUILD: 'distcheck', WITH_VALGRIND: 'no', CTIMETESTS: 'no', BENCH: 'no' } + - env_vars: { CPPFLAGS: '-DDETERMINISTIC' } + - env_vars: { CFLAGS: '-O0', CTIMETESTS: 'no' } + - env_vars: { CFLAGS: '-O1', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - env_vars: { ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } + - env_vars: { ECMULTGENPRECISION: 8, ECMULTWINDOW: 4 } + cc: + - 'gcc' + - 'clang' + - 'gcc-snapshot' + - 'clang-snapshot' + + env: + CC: ${{ matrix.cc }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: CI script + env: ${{ matrix.configuration.env_vars }} + uses: ./.github/actions/run-in-docker-action + with: + dockerfile: ./ci/linux-debian.Dockerfile + tag: linux-debian-image + + - run: cat tests.log || true + if: ${{ always() }} + - run: cat noverify_tests.log || true + if: ${{ always() }} + - run: cat exhaustive_tests.log || true + if: ${{ always() }} + - run: cat ctime_tests.log || true + if: ${{ always() }} + - run: cat bench.log || true + if: ${{ always() }} + - run: cat config.log || true + if: ${{ always() }} + - run: cat test_env.log || true + if: ${{ always() }} + - name: CI env + run: env + if: ${{ always() }} + + i686_debian: + name: "i686: Linux (Debian stable)" + runs-on: ubuntu-latest + needs: docker_cache + + strategy: + fail-fast: false + matrix: + cc: + - 'i686-linux-gnu-gcc' + - 'clang --target=i686-pc-linux-gnu -isystem /usr/i686-linux-gnu/include' + + env: + HOST: 'i686-linux-gnu' + ECDH: 'yes' + RECOVERY: 'yes' + SCHNORRSIG: 'yes' + ELLSWIFT: 'yes' + CC: ${{ matrix.cc }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: CI script + uses: ./.github/actions/run-in-docker-action + with: + dockerfile: ./ci/linux-debian.Dockerfile + tag: linux-debian-image + + - run: cat tests.log || true + if: ${{ always() }} + - run: cat noverify_tests.log || true + if: ${{ always() }} + - run: cat exhaustive_tests.log || true + if: ${{ always() }} + - run: cat ctime_tests.log || true + if: ${{ always() }} + - run: cat bench.log || true + if: ${{ always() }} + - run: cat config.log || true + if: ${{ always() }} + - run: cat test_env.log || true + if: ${{ always() }} + - name: CI env + run: env + if: ${{ always() }} + + s390x_debian: + name: "s390x (big-endian): Linux (Debian stable, QEMU)" + runs-on: ubuntu-latest + needs: docker_cache + + env: + WRAPPER_CMD: 'qemu-s390x' + SECP256K1_TEST_ITERS: 16 + HOST: 's390x-linux-gnu' + WITH_VALGRIND: 'no' + ECDH: 'yes' + RECOVERY: 'yes' + SCHNORRSIG: 'yes' + ELLSWIFT: 'yes' + CTIMETESTS: 'no' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: CI script + uses: ./.github/actions/run-in-docker-action + with: + dockerfile: ./ci/linux-debian.Dockerfile + tag: linux-debian-image + + - run: cat tests.log || true + if: ${{ always() }} + - run: cat noverify_tests.log || true + if: ${{ always() }} + - run: cat exhaustive_tests.log || true + if: ${{ always() }} + - run: cat ctime_tests.log || true + if: ${{ always() }} + - run: cat bench.log || true + if: ${{ always() }} + - run: cat config.log || true + if: ${{ always() }} + - run: cat test_env.log || true + if: ${{ always() }} + - name: CI env + run: env + if: ${{ always() }} + + arm32_debian: + name: "ARM32: Linux (Debian stable, QEMU)" + runs-on: ubuntu-latest + needs: docker_cache + + strategy: + fail-fast: false + matrix: + configuration: + - env_vars: {} + - env_vars: { EXPERIMENTAL: 'yes', ASM: 'arm32' } + + env: + WRAPPER_CMD: 'qemu-arm' + SECP256K1_TEST_ITERS: 16 + HOST: 'arm-linux-gnueabihf' + WITH_VALGRIND: 'no' + ECDH: 'yes' + RECOVERY: 'yes' + SCHNORRSIG: 'yes' + ELLSWIFT: 'yes' + CTIMETESTS: 'no' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: CI script + env: ${{ matrix.configuration.env_vars }} + uses: ./.github/actions/run-in-docker-action + with: + dockerfile: ./ci/linux-debian.Dockerfile + tag: linux-debian-image + + - run: cat tests.log || true + if: ${{ always() }} + - run: cat noverify_tests.log || true + if: ${{ always() }} + - run: cat exhaustive_tests.log || true + if: ${{ always() }} + - run: cat ctime_tests.log || true + if: ${{ always() }} + - run: cat bench.log || true + if: ${{ always() }} + - run: cat config.log || true + if: ${{ always() }} + - run: cat test_env.log || true + if: ${{ always() }} + - name: CI env + run: env + if: ${{ always() }} + + arm64_debian: + name: "ARM64: Linux (Debian stable, QEMU)" + runs-on: ubuntu-latest + needs: docker_cache + + env: + WRAPPER_CMD: 'qemu-aarch64' + SECP256K1_TEST_ITERS: 16 + HOST: 'aarch64-linux-gnu' + WITH_VALGRIND: 'no' + ECDH: 'yes' + RECOVERY: 'yes' + SCHNORRSIG: 'yes' + ELLSWIFT: 'yes' + CTIMETESTS: 'no' + + strategy: + fail-fast: false + matrix: + configuration: + - env_vars: { } # gcc + - env_vars: # clang + CC: 'clang --target=aarch64-linux-gnu' + - env_vars: # clang-snapshot + CC: 'clang-snapshot --target=aarch64-linux-gnu' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: CI script + env: ${{ matrix.configuration.env_vars }} + uses: ./.github/actions/run-in-docker-action + with: + dockerfile: ./ci/linux-debian.Dockerfile + tag: linux-debian-image + + - run: cat tests.log || true + if: ${{ always() }} + - run: cat noverify_tests.log || true + if: ${{ always() }} + - run: cat exhaustive_tests.log || true + if: ${{ always() }} + - run: cat ctime_tests.log || true + if: ${{ always() }} + - run: cat bench.log || true + if: ${{ always() }} + - run: cat config.log || true + if: ${{ always() }} + - run: cat test_env.log || true + if: ${{ always() }} + - name: CI env + run: env + if: ${{ always() }} + + ppc64le_debian: + name: "ppc64le: Linux (Debian stable, QEMU)" + runs-on: ubuntu-latest + needs: docker_cache + + env: + WRAPPER_CMD: 'qemu-ppc64le' + SECP256K1_TEST_ITERS: 16 + HOST: 'powerpc64le-linux-gnu' + WITH_VALGRIND: 'no' + ECDH: 'yes' + RECOVERY: 'yes' + SCHNORRSIG: 'yes' + ELLSWIFT: 'yes' + CTIMETESTS: 'no' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: CI script + uses: ./.github/actions/run-in-docker-action + with: + dockerfile: ./ci/linux-debian.Dockerfile + tag: linux-debian-image + + - run: cat tests.log || true + if: ${{ always() }} + - run: cat noverify_tests.log || true + if: ${{ always() }} + - run: cat exhaustive_tests.log || true + if: ${{ always() }} + - run: cat ctime_tests.log || true + if: ${{ always() }} + - run: cat bench.log || true + if: ${{ always() }} + - run: cat config.log || true + if: ${{ always() }} + - run: cat test_env.log || true + if: ${{ always() }} + - name: CI env + run: env + if: ${{ always() }} + + valgrind_debian: + name: "Valgrind (memcheck)" + runs-on: ubuntu-latest + needs: docker_cache + + strategy: + fail-fast: false + matrix: + configuration: + - env_vars: { CC: 'clang', ASM: 'auto' } + - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'auto' } + - env_vars: { CC: 'clang', ASM: 'no', ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } + - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } + + env: + # The `--error-exitcode` is required to make the test fail if valgrind found errors, + # otherwise it will return 0 (https://www.valgrind.org/docs/manual/manual-core.html). + WRAPPER_CMD: 'valgrind --error-exitcode=42' + ECDH: 'yes' + RECOVERY: 'yes' + SCHNORRSIG: 'yes' + ELLSWIFT: 'yes' + CTIMETESTS: 'no' + SECP256K1_TEST_ITERS: 2 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: CI script + env: ${{ matrix.configuration.env_vars }} + uses: ./.github/actions/run-in-docker-action + with: + dockerfile: ./ci/linux-debian.Dockerfile + tag: linux-debian-image + + - run: cat tests.log || true + if: ${{ always() }} + - run: cat noverify_tests.log || true + if: ${{ always() }} + - run: cat exhaustive_tests.log || true + if: ${{ always() }} + - run: cat ctime_tests.log || true + if: ${{ always() }} + - run: cat bench.log || true + if: ${{ always() }} + - run: cat config.log || true + if: ${{ always() }} + - run: cat test_env.log || true + if: ${{ always() }} + - name: CI env + run: env + if: ${{ always() }} + + sanitizers_debian: + name: "UBSan, ASan, LSan" + runs-on: ubuntu-latest + needs: docker_cache + + strategy: + fail-fast: false + matrix: + configuration: + - env_vars: { CC: 'clang', ASM: 'auto' } + - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'auto' } + - env_vars: { CC: 'clang', ASM: 'no', ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } + - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } + + env: + ECDH: 'yes' + RECOVERY: 'yes' + SCHNORRSIG: 'yes' + ELLSWIFT: 'yes' + CTIMETESTS: 'no' + CFLAGS: '-fsanitize=undefined,address -g' + UBSAN_OPTIONS: 'print_stacktrace=1:halt_on_error=1' + ASAN_OPTIONS: 'strict_string_checks=1:detect_stack_use_after_return=1:detect_leaks=1' + LSAN_OPTIONS: 'use_unaligned=1' + SECP256K1_TEST_ITERS: 32 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: CI script + env: ${{ matrix.configuration.env_vars }} + uses: ./.github/actions/run-in-docker-action + with: + dockerfile: ./ci/linux-debian.Dockerfile + tag: linux-debian-image + + - run: cat tests.log || true + if: ${{ always() }} + - run: cat noverify_tests.log || true + if: ${{ always() }} + - run: cat exhaustive_tests.log || true + if: ${{ always() }} + - run: cat ctime_tests.log || true + if: ${{ always() }} + - run: cat bench.log || true + if: ${{ always() }} + - run: cat config.log || true + if: ${{ always() }} + - run: cat test_env.log || true + if: ${{ always() }} + - name: CI env + run: env + if: ${{ always() }} + + msan_debian: + name: "MSan" + runs-on: ubuntu-latest + needs: docker_cache + + strategy: + fail-fast: false + matrix: + configuration: + - env_vars: + CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -g' + - env_vars: + ECMULTGENPRECISION: 2 + ECMULTWINDOW: 2 + CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -g -O3' + + env: + ECDH: 'yes' + RECOVERY: 'yes' + SCHNORRSIG: 'yes' + ELLSWIFT: 'yes' + CTIMETESTS: 'yes' + CC: 'clang' + SECP256K1_TEST_ITERS: 32 + ASM: 'no' + WITH_VALGRIND: 'no' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: CI script + env: ${{ matrix.configuration.env_vars }} + uses: ./.github/actions/run-in-docker-action + with: + dockerfile: ./ci/linux-debian.Dockerfile + tag: linux-debian-image + + - run: cat tests.log || true + if: ${{ always() }} + - run: cat noverify_tests.log || true + if: ${{ always() }} + - run: cat exhaustive_tests.log || true + if: ${{ always() }} + - run: cat ctime_tests.log || true + if: ${{ always() }} + - run: cat bench.log || true + if: ${{ always() }} + - run: cat config.log || true + if: ${{ always() }} + - run: cat test_env.log || true + if: ${{ always() }} + - name: CI env + run: env + if: ${{ always() }} + + mingw_debian: + name: ${{ matrix.configuration.job_name }} + runs-on: ubuntu-latest + needs: docker_cache + + env: + WRAPPER_CMD: 'wine' + WITH_VALGRIND: 'no' + ECDH: 'yes' + RECOVERY: 'yes' + SCHNORRSIG: 'yes' + ELLSWIFT: 'yes' + CTIMETESTS: 'no' + + strategy: + fail-fast: false + matrix: + configuration: + - job_name: 'x86_64 (mingw32-w64): Windows (Debian stable, Wine)' + env_vars: + HOST: 'x86_64-w64-mingw32' + - job_name: 'i686 (mingw32-w64): Windows (Debian stable, Wine)' + env_vars: + HOST: 'i686-w64-mingw32' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: CI script + env: ${{ matrix.configuration.env_vars }} + uses: ./.github/actions/run-in-docker-action + with: + dockerfile: ./ci/linux-debian.Dockerfile + tag: linux-debian-image + + - run: cat tests.log || true + if: ${{ always() }} + - run: cat noverify_tests.log || true + if: ${{ always() }} + - run: cat exhaustive_tests.log || true + if: ${{ always() }} + - run: cat ctime_tests.log || true + if: ${{ always() }} + - run: cat bench.log || true + if: ${{ always() }} + - run: cat config.log || true + if: ${{ always() }} + - run: cat test_env.log || true + if: ${{ always() }} + - name: CI env + run: env + if: ${{ always() }} + + macos-native: + name: "x86_64: macOS Monterey" + # See: https://github.com/actions/runner-images#available-images. + runs-on: macos-12 # Use M1 once available https://github.com/github/roadmap/issues/528 + + env: + CC: 'clang' + HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 + + strategy: + fail-fast: false + matrix: + env_vars: + - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128_struct', ECMULTGENPRECISION: 2, ECMULTWINDOW: 4 } + - { WIDEMUL: 'int128', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128', RECOVERY: 'yes' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY', CTIMETESTS: 'no' } + - BUILD: 'distcheck' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Homebrew packages + run: | + brew install automake libtool gcc + ln -s $(brew --prefix gcc)/bin/gcc-?? /usr/local/bin/gcc + + - name: Install and cache Valgrind + uses: ./.github/actions/install-homebrew-valgrind + + - name: CI script + env: ${{ matrix.env_vars }} + run: ./ci/ci.sh + + - run: cat tests.log || true + if: ${{ always() }} + - run: cat noverify_tests.log || true + if: ${{ always() }} + - run: cat exhaustive_tests.log || true + if: ${{ always() }} + - run: cat ctime_tests.log || true + if: ${{ always() }} + - run: cat bench.log || true + if: ${{ always() }} + - run: cat config.log || true + if: ${{ always() }} + - run: cat test_env.log || true + if: ${{ always() }} + - name: CI env + run: env + if: ${{ always() }} + + win64-native: + name: ${{ matrix.configuration.job_name }} + # See: https://github.com/actions/runner-images#available-images. + runs-on: windows-2022 + + strategy: + fail-fast: false + matrix: + configuration: + - job_name: 'x64 (MSVC): Windows (VS 2022, shared)' + cmake_options: '-A x64 -DBUILD_SHARED_LIBS=ON' + - job_name: 'x64 (MSVC): Windows (VS 2022, static)' + cmake_options: '-A x64 -DBUILD_SHARED_LIBS=OFF' + - job_name: 'x64 (MSVC): Windows (VS 2022, int128_struct)' + cmake_options: '-A x64 -DSECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY=int128_struct' + - job_name: 'x64 (MSVC): Windows (VS 2022, int128_struct with __(u)mulh)' + cmake_options: '-A x64 -DSECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY=int128_struct' + cpp_flags: '/DSECP256K1_MSVC_MULH_TEST_OVERRIDE' + - job_name: 'x86 (MSVC): Windows (VS 2022)' + cmake_options: '-A Win32' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Generate buildsystem + run: cmake -E env CFLAGS="/WX ${{ matrix.configuration.cpp_flags }}" cmake -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_BUILD_EXAMPLES=ON ${{ matrix.configuration.cmake_options }} + + - name: Build + run: cmake --build build --config RelWithDebInfo -- /p:UseMultiToolTask=true /maxCpuCount + + - name: Binaries info + # Use the bash shell included with Git for Windows. + shell: bash + run: | + cd build/src/RelWithDebInfo && file *tests.exe bench*.exe libsecp256k1-*.dll || true + + - name: Check + run: | + ctest -C RelWithDebInfo --test-dir build -j ([int]$env:NUMBER_OF_PROCESSORS + 1) + build\src\RelWithDebInfo\bench_ecmult.exe + build\src\RelWithDebInfo\bench_internal.exe + build\src\RelWithDebInfo\bench.exe + + win64-native-headers: + name: "x64 (MSVC): C++ (public headers)" + # See: https://github.com/actions/runner-images#available-images. + runs-on: windows-2022 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Add cl.exe to PATH + uses: ilammy/msvc-dev-cmd@v1 + + - name: C++ (public headers) + run: | + cl.exe -c -WX -TP include/*.h + + cxx_fpermissive_debian: + name: "C++ -fpermissive (entire project)" + runs-on: ubuntu-latest + needs: docker_cache + + env: + CC: 'g++' + CFLAGS: '-fpermissive -g' + CPPFLAGS: '-DSECP256K1_CPLUSPLUS_TEST_OVERRIDE' + WERROR_CFLAGS: + ECDH: 'yes' + RECOVERY: 'yes' + SCHNORRSIG: 'yes' + ELLSWIFT: 'yes' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: CI script + uses: ./.github/actions/run-in-docker-action + with: + dockerfile: ./ci/linux-debian.Dockerfile + tag: linux-debian-image + + - run: cat tests.log || true + if: ${{ always() }} + - run: cat noverify_tests.log || true + if: ${{ always() }} + - run: cat exhaustive_tests.log || true + if: ${{ always() }} + - run: cat ctime_tests.log || true + if: ${{ always() }} + - run: cat bench.log || true + if: ${{ always() }} + - run: cat config.log || true + if: ${{ always() }} + - run: cat test_env.log || true + if: ${{ always() }} + - name: CI env + run: env + if: ${{ always() }} + + cxx_headers_debian: + name: "C++ (public headers)" + runs-on: ubuntu-latest + needs: docker_cache + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: CI script + uses: ./.github/actions/run-in-docker-action + with: + dockerfile: ./ci/linux-debian.Dockerfile + tag: linux-debian-image + command: | + g++ -Werror include/*.h + clang -Werror -x c++-header include/*.h + + sage: + name: "SageMath prover" + runs-on: ubuntu-latest + container: + image: sagemath/sagemath:latest + options: --user root + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: CI script + run: | + cd sage + sage prove_group_implementations.sage + + release: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - run: ./autogen.sh && ./configure --enable-dev-mode && make distcheck + + - name: Check installation with Autotools + env: + CI_INSTALL: ${{ runner.temp }}/${{ github.run_id }}${{ github.action }} + run: | + ./autogen.sh && ./configure --prefix=${{ env.CI_INSTALL }} && make clean && make install && ls -RlAh ${{ env.CI_INSTALL }} + gcc -o ecdsa examples/ecdsa.c $(PKG_CONFIG_PATH=${{ env.CI_INSTALL }}/lib/pkgconfig pkg-config --cflags --libs libsecp256k1) -Wl,-rpath,"${{ env.CI_INSTALL }}/lib" && ./ecdsa + + - name: Check installation with CMake + env: + CI_BUILD: ${{ runner.temp }}/${{ github.run_id }}${{ github.action }}/build + CI_INSTALL: ${{ runner.temp }}/${{ github.run_id }}${{ github.action }}/install + run: | + cmake -B ${{ env.CI_BUILD }} -DCMAKE_INSTALL_PREFIX=${{ env.CI_INSTALL }} && cmake --build ${{ env.CI_BUILD }} --target install && ls -RlAh ${{ env.CI_INSTALL }} + gcc -o ecdsa examples/ecdsa.c -I ${{ env.CI_INSTALL }}/include -L ${{ env.CI_INSTALL }}/lib*/ -l secp256k1 -Wl,-rpath,"${{ env.CI_INSTALL }}/lib",-rpath,"${{ env.CI_INSTALL }}/lib64" && ./ecdsa diff --git a/secp256k1-sys/depend/secp256k1/CHANGELOG.md b/secp256k1-sys/depend/secp256k1/CHANGELOG.md index 6c5dbb843..e8d8db5a1 100644 --- a/secp256k1-sys/depend/secp256k1/CHANGELOG.md +++ b/secp256k1-sys/depend/secp256k1/CHANGELOG.md @@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.4.0] - 2023-09-04 + +#### 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. + - We now test the library with unreleased development snapshots of GCC and Clang. This gives us an early chance to catch miscompilations and constant-time issues introduced by the compiler (such as those that led to the previous two releases). + +#### Fixed + - Fixed symbol visibility in Windows DLL builds, where three internal library symbols were wrongly exported. + +#### Changed + - When consuming libsecp256k1 as a static library on Windows, the user must now define the `SECP256K1_STATIC` macro before including `secp256k1.h`. + +#### ABI Compatibility +This release is backward compatible with the ABI of 0.3.0, 0.3.1, and 0.3.2. Symbol visibility is now believed to be handled properly on supported platforms and is now considered to be part of the ABI. Please report any improperly exported symbols as a bug. + ## [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`. @@ -85,7 +104,8 @@ This version was in fact never released. The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6). Therefore, this version number does not uniquely identify a set of source files. -[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.2...HEAD +[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.0...HEAD +[0.4.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.2...v0.4.0 [0.3.2]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.1...v0.3.2 [0.3.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.2.0...v0.3.0 diff --git a/secp256k1-sys/depend/secp256k1/CMakeLists.txt b/secp256k1-sys/depend/secp256k1/CMakeLists.txt index f1dac7b24..cdac47ba9 100644 --- a/secp256k1-sys/depend/secp256k1/CMakeLists.txt +++ b/secp256k1-sys/depend/secp256k1/CMakeLists.txt @@ -11,7 +11,7 @@ project(libsecp256k1 # The package (a.k.a. release) version is based on semantic versioning 2.0.0 of # the API. All changes in experimental modules are treated as # backwards-compatible and therefore at most increase the minor version. - VERSION 0.3.2 + VERSION 0.4.0 DESCRIPTION "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1." HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1" LANGUAGES C @@ -34,9 +34,9 @@ endif() # https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. -set(${PROJECT_NAME}_LIB_VERSION_CURRENT 2) -set(${PROJECT_NAME}_LIB_VERSION_REVISION 2) -set(${PROJECT_NAME}_LIB_VERSION_AGE 0) +set(${PROJECT_NAME}_LIB_VERSION_CURRENT 3) +set(${PROJECT_NAME}_LIB_VERSION_REVISION 0) +set(${PROJECT_NAME}_LIB_VERSION_AGE 1) set(CMAKE_C_STANDARD 90) set(CMAKE_C_EXTENSIONS OFF) @@ -71,6 +71,11 @@ if(SECP256K1_ENABLE_MODULE_EXTRAKEYS) add_compile_definitions(ENABLE_MODULE_EXTRAKEYS=1) endif() +option(SECP256K1_ENABLE_MODULE_ELLSWIFT "Enable ElligatorSwift module." ON) +if(SECP256K1_ENABLE_MODULE_ELLSWIFT) + add_compile_definitions(ENABLE_MODULE_ELLSWIFT=1) +endif() + option(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS "Enable external default callback functions." OFF) if(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS) add_compile_definitions(USE_EXTERNAL_DEFAULT_CALLBACKS=1) @@ -212,8 +217,12 @@ endif() include(TryAppendCFlags) if(MSVC) # Keep the following commands ordered lexicographically. - try_append_c_flags(/W2) # Moderate warning level. + try_append_c_flags(/W3) # Production quality warning level. try_append_c_flags(/wd4146) # Disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned". + try_append_c_flags(/wd4244) # Disable warning C4244 "'conversion' conversion from 'type1' to 'type2', possible loss of data". + try_append_c_flags(/wd4267) # Disable warning C4267 "'var' : conversion from 'size_t' to 'type', possible loss of data". + # Eliminate deprecation warnings for the older, less secure functions. + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) else() # Keep the following commands ordered lexicographically. try_append_c_flags(-pedantic) @@ -266,6 +275,7 @@ message(" ECDH ................................ ${SECP256K1_ENABLE_MODULE_ECDH} message(" ECDSA pubkey recovery ............... ${SECP256K1_ENABLE_MODULE_RECOVERY}") message(" extrakeys ........................... ${SECP256K1_ENABLE_MODULE_EXTRAKEYS}") message(" schnorrsig .......................... ${SECP256K1_ENABLE_MODULE_SCHNORRSIG}") +message(" ElligatorSwift ...................... ${SECP256K1_ENABLE_MODULE_ELLSWIFT}") message("Parameters:") message(" ecmult window size .................. ${SECP256K1_ECMULT_WINDOW_SIZE}") message(" ecmult gen precision bits ........... ${SECP256K1_ECMULT_GEN_PREC_BITS}") diff --git a/secp256k1-sys/depend/secp256k1/Makefile.am b/secp256k1-sys/depend/secp256k1/Makefile.am index 350b2ee9f..3edc37096 100644 --- a/secp256k1-sys/depend/secp256k1/Makefile.am +++ b/secp256k1-sys/depend/secp256k1/Makefile.am @@ -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 @@ -189,11 +189,11 @@ EXTRA_PROGRAMS = precompute_ecmult precompute_ecmult_gen CLEANFILES = $(EXTRA_PROGRAMS) precompute_ecmult_SOURCES = src/precompute_ecmult.c -precompute_ecmult_CPPFLAGS = $(SECP_CONFIG_DEFINES) +precompute_ecmult_CPPFLAGS = $(SECP_CONFIG_DEFINES) -DVERIFY precompute_ecmult_LDADD = $(COMMON_LIB) precompute_ecmult_gen_SOURCES = src/precompute_ecmult_gen.c -precompute_ecmult_gen_CPPFLAGS = $(SECP_CONFIG_DEFINES) +precompute_ecmult_gen_CPPFLAGS = $(SECP_CONFIG_DEFINES) -DVERIFY precompute_ecmult_gen_LDADD = $(COMMON_LIB) # See Automake manual, Section "Errors with distclean". @@ -267,3 +267,7 @@ endif if ENABLE_MODULE_SCHNORRSIG include src/modules/schnorrsig/Makefile.am.include endif + +if ENABLE_MODULE_ELLSWIFT +include src/modules/ellswift/Makefile.am.include +endif diff --git a/secp256k1-sys/depend/secp256k1/ci/cirrus.sh b/secp256k1-sys/depend/secp256k1/ci/ci.sh similarity index 75% rename from secp256k1-sys/depend/secp256k1/ci/cirrus.sh rename to secp256k1-sys/depend/secp256k1/ci/ci.sh index b2af03bb5..719e7851e 100755 --- a/secp256k1-sys/depend/secp256k1/ci/cirrus.sh +++ b/secp256k1-sys/depend/secp256k1/ci/ci.sh @@ -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 @@ -12,7 +13,7 @@ print_environment() { # does not rely on bash. for var in WERROR_CFLAGS MAKEFLAGS BUILD \ ECMULTWINDOW ECMULTGENPRECISION ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \ - EXPERIMENTAL ECDH RECOVERY SCHNORRSIG \ + EXPERIMENTAL ECDH RECOVERY SCHNORRSIG ELLSWIFT \ SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETESTS\ EXAMPLES \ HOST WRAPPER_CMD \ @@ -30,19 +31,15 @@ print_environment() { } print_environment -# Start persistent wineserver if necessary. -# This speeds up jobs with many invocations of wine (e.g., ./configure with MSVC) tremendously. -case "$WRAPPER_CMD" in - *wine*) - # Make sure to shutdown wineserver whenever we exit. - trap "wineserver -k || true" EXIT INT HUP - # This is apparently only reliable when we run a dummy command such as "hh.exe" afterwards. - wineserver -p && wine hh.exe +env >> test_env.log + +# If gcc is requested, assert that it's in fact gcc (and not some symlinked Apple clang). +case "${CC:-undefined}" in + *gcc*) + $CC -v 2>&1 | grep -q "gcc version" || exit 1; ;; esac -env >> test_env.log - if [ -n "${CC+x}" ]; then # The MSVC compiler "cl" doesn't understand "-v" $CC -v || true @@ -54,6 +51,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 \ @@ -62,6 +75,7 @@ fi --with-ecmult-window="$ECMULTWINDOW" \ --with-ecmult-gen-precision="$ECMULTGENPRECISION" \ --enable-module-ecdh="$ECDH" --enable-module-recovery="$RECOVERY" \ + --enable-module-ellswift="$ELLSWIFT" \ --enable-module-schnorrsig="$SCHNORRSIG" \ --enable-examples="$EXAMPLES" \ --enable-ctime-tests="$CTIMETESTS" \ diff --git a/secp256k1-sys/depend/secp256k1/ci/linux-debian.Dockerfile b/secp256k1-sys/depend/secp256k1/ci/linux-debian.Dockerfile index a83a4e36d..e719907e8 100644 --- a/secp256k1-sys/depend/secp256k1/ci/linux-debian.Dockerfile +++ b/secp256k1-sys/depend/secp256k1/ci/linux-debian.Dockerfile @@ -1,4 +1,17 @@ -FROM debian:stable +FROM debian:stable-slim + +SHELL ["/bin/bash", "-c"] + +WORKDIR /root + +# A too high maximum number of file descriptors (with the default value +# inherited from the docker host) can cause issues with some of our tools: +# - sanitizers hanging: https://github.com/google/sanitizers/issues/1662 +# - valgrind crashing: https://stackoverflow.com/a/75293014 +# This is not be a problem on our CI hosts, but developers who run the image +# on their machines may run into this (e.g., on Arch Linux), so warn them. +# (Note that .bashrc is only executed in interactive bash shells.) +RUN echo 'if [[ $(ulimit -n) -gt 200000 ]]; then echo "WARNING: Very high value reported by \"ulimit -n\". Consider passing \"--ulimit nofile=32768\" to \"docker run\"."; fi' >> /root/.bashrc RUN dpkg --add-architecture i386 && \ dpkg --add-architecture s390x && \ @@ -11,27 +24,52 @@ RUN dpkg --add-architecture i386 && \ RUN apt-get update && apt-get install --no-install-recommends -y \ git ca-certificates \ 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 \ gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross libc6-dbg:ppc64el \ gcc-mingw-w64-x86-64-win32 wine64 wine \ gcc-mingw-w64-i686-win32 wine32 \ - sagemath + python3 + +# Build and install gcc snapshot +ARG GCC_SNAPSHOT_MAJOR=14 +RUN apt-get update && apt-get install --no-install-recommends -y wget libgmp-dev libmpfr-dev libmpc-dev flex && \ + mkdir gcc && cd gcc && \ + 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 && \ + ../*/configure --prefix=/opt/gcc-snapshot --enable-languages=c --disable-bootstrap --disable-multilib --without-isl && \ + make -j $(nproc) && \ + make install && \ + cd ../.. && rm -rf gcc && \ + ln -s /opt/gcc-snapshot/bin/gcc /usr/bin/gcc-snapshot && \ + apt-get autoremove -y wget libgmp-dev libmpfr-dev libmpc-dev flex && \ + apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install clang snapshot, see https://apt.llvm.org/ +RUN \ + # Setup GPG keys of LLVM repository + apt-get update && apt-get install --no-install-recommends -y wget && \ + 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 && \ + apt-get update && \ + # Determine the version number of the LLVM development branch + LLVM_VERSION=$(apt-cache search --names-only '^clang-[0-9]+$' | sort -V | tail -1 | cut -f1 -d" " | cut -f2 -d"-" ) && \ + # Install + apt-get install --no-install-recommends -y "clang-${LLVM_VERSION}" && \ + # Create symlink + ln -s "/usr/bin/clang-${LLVM_VERSION}" /usr/bin/clang-snapshot && \ + # Clean up + apt-get autoremove -y wget && \ + apt-get clean && rm -rf /var/lib/apt/lists/* -WORKDIR /root -# The "wine" package provides a convience 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 && \ - 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 && \ - msvc-wine/install.sh /opt/msvc - -# Initialize the wine environment. Wait until the wineserver process has -# exited before closing the session, to avoid corrupting the wine prefix. -RUN wine64 wineboot --init && \ - while (ps -A | grep wineserver) > /dev/null; do sleep 1; done diff --git a/secp256k1-sys/depend/secp256k1/configure.ac b/secp256k1-sys/depend/secp256k1/configure.ac index e55be1503..e3877850d 100644 --- a/secp256k1-sys/depend/secp256k1/configure.ac +++ b/secp256k1-sys/depend/secp256k1/configure.ac @@ -4,8 +4,8 @@ AC_PREREQ([2.60]) # the API. All changes in experimental modules are treated as # backwards-compatible and therefore at most increase the minor version. define(_PKG_VERSION_MAJOR, 0) -define(_PKG_VERSION_MINOR, 3) -define(_PKG_VERSION_PATCH, 2) +define(_PKG_VERSION_MINOR, 4) +define(_PKG_VERSION_PATCH, 0) define(_PKG_VERSION_IS_RELEASE, true) # The library version is based on libtool versioning of the ABI. The set of @@ -13,9 +13,9 @@ define(_PKG_VERSION_IS_RELEASE, true) # https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. -define(_LIB_VERSION_CURRENT, 2) -define(_LIB_VERSION_REVISION, 2) -define(_LIB_VERSION_AGE, 0) +define(_LIB_VERSION_CURRENT, 3) +define(_LIB_VERSION_REVISION, 0) +define(_LIB_VERSION_AGE, 1) AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1]) @@ -121,13 +121,12 @@ AC_DEFUN([SECP_TRY_APPEND_DEFAULT_CFLAGS], [ # libtool makes the same assumption internally. # Note that "/opt" and "-opt" are equivalent for MSVC; we use "-opt" because "/opt" looks like a path. if test x"$GCC" != x"yes" && test x"$build_windows" = x"yes"; then - SECP_TRY_APPEND_CFLAGS([-W2 -wd4146], $1) # Moderate warning level, disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned" - # 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" + SECP_TRY_APPEND_CFLAGS([-W3], $1) # Production quality warning level. + SECP_TRY_APPEND_CFLAGS([-wd4146], $1) # Disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned". + SECP_TRY_APPEND_CFLAGS([-wd4244], $1) # Disable warning C4244 "'conversion' conversion from 'type1' to 'type2', possible loss of data". + 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" fi ]) SECP_TRY_APPEND_DEFAULT_CFLAGS(SECP_CFLAGS) @@ -185,6 +184,10 @@ AC_ARG_ENABLE(module_schnorrsig, AS_HELP_STRING([--enable-module-schnorrsig],[enable schnorrsig module [default=yes]]), [], [SECP_SET_DEFAULT([enable_module_schnorrsig], [yes], [yes])]) +AC_ARG_ENABLE(module_ellswift, + AS_HELP_STRING([--enable-module-ellswift],[enable ElligatorSwift module [default=yes]]), [], + [SECP_SET_DEFAULT([enable_module_ellswift], [yes], [yes])]) + AC_ARG_ENABLE(external_default_callbacks, AS_HELP_STRING([--enable-external-default-callbacks],[enable external default callback functions [default=no]]), [], [SECP_SET_DEFAULT([enable_external_default_callbacks], [no], [no])]) @@ -397,6 +400,10 @@ if test x"$enable_module_schnorrsig" = x"yes"; then enable_module_extrakeys=yes fi +if test x"$enable_module_ellswift" = x"yes"; then + SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_ELLSWIFT=1" +fi + # Test if extrakeys is set after the schnorrsig module to allow the schnorrsig # module to set enable_module_extrakeys=yes if test x"$enable_module_extrakeys" = x"yes"; then @@ -439,6 +446,7 @@ AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_EXTRAKEYS], [test x"$enable_module_extrakeys" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_SCHNORRSIG], [test x"$enable_module_schnorrsig" = x"yes"]) +AM_CONDITIONAL([ENABLE_MODULE_ELLSWIFT], [test x"$enable_module_ellswift" = x"yes"]) AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$enable_external_asm" = x"yes"]) AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm32"]) AM_CONDITIONAL([BUILD_WINDOWS], [test "$build_windows" = "yes"]) @@ -460,6 +468,7 @@ echo " module ecdh = $enable_module_ecdh" echo " module recovery = $enable_module_recovery" echo " module extrakeys = $enable_module_extrakeys" echo " module schnorrsig = $enable_module_schnorrsig" +echo " module ellswift = $enable_module_ellswift" echo echo " asm = $set_asm" echo " ecmult window size = $set_ecmult_window" diff --git a/secp256k1-sys/depend/secp256k1/doc/ellswift.md b/secp256k1-sys/depend/secp256k1/doc/ellswift.md new file mode 100644 index 000000000..e3b25ec7a --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/doc/ellswift.md @@ -0,0 +1,483 @@ +# ElligatorSwift for secp256k1 explained + +In this document we explain how the `ellswift` module implementation is related to the +construction in the +["SwiftEC: Shallue–van de Woestijne Indifferentiable Function To Elliptic Curves"](https://eprint.iacr.org/2022/759) +paper by Jorge Chávez-Saab, Francisco Rodríguez-Henríquez, and Mehdi Tibouchi. + +* [1. Introduction](#1-introduction) +* [2. The decoding function](#2-the-decoding-function) + + [2.1 Decoding for `secp256k1`](#21-decoding-for-secp256k1) +* [3. The encoding function](#3-the-encoding-function) + + [3.1 Switching to *v, w* coordinates](#31-switching-to-v-w-coordinates) + + [3.2 Avoiding computing all inverses](#32-avoiding-computing-all-inverses) + + [3.3 Finding the inverse](#33-finding-the-inverse) + + [3.4 Dealing with special cases](#34-dealing-with-special-cases) + + [3.5 Encoding for `secp256k1`](#35-encoding-for-secp256k1) +* [4. Encoding and decoding full *(x, y)* coordinates](#4-encoding-and-decoding-full-x-y-coordinates) + + [4.1 Full *(x, y)* coordinates for `secp256k1`](#41-full-x-y-coordinates-for-secp256k1) + +## 1. Introduction + +The `ellswift` module effectively introduces a new 64-byte public key format, with the property +that (uniformly random) public keys can be encoded as 64-byte arrays which are computationally +indistinguishable from uniform byte arrays. The module provides functions to convert public keys +from and to this format, as well as convenience functions for key generation and ECDH that operate +directly on ellswift-encoded keys. + +The encoding consists of the concatenation of two (32-byte big endian) encoded field elements $u$ +and $t.$ Together they encode an x-coordinate on the curve $x$, or (see further) a full point $(x, y)$ on +the curve. + +**Decoding** consists of decoding the field elements $u$ and $t$ (values above the field size $p$ +are taken modulo $p$), and then evaluating $F_u(t)$, which for every $u$ and $t$ results in a valid +x-coordinate on the curve. The functions $F_u$ will be defined in [Section 2](#2-the-decoding-function). + +**Encoding** a given $x$ coordinate is conceptually done as follows: +* Loop: + * Pick a uniformly random field element $u.$ + * Compute the set $L = F_u^{-1}(x)$ of $t$ values for which $F_u(t) = x$, which may have up to *8* elements. + * With probability $1 - \dfrac{\\#L}{8}$, restart the loop. + * Select a uniformly random $t \in L$ and return $(u, t).$ + +This is the *ElligatorSwift* algorithm, here given for just x-coordinates. An extension to full +$(x, y)$ points will be given in [Section 4](#4-encoding-and-decoding-full-x-y-coordinates). +The algorithm finds a uniformly random $(u, t)$ among (almost all) those +for which $F_u(t) = x.$ Section 3.2 in the paper proves that the number of such encodings for +almost all x-coordinates on the curve (all but at most 39) is close to two times the field size +(specifically, it lies in the range $2q \pm (22\sqrt{q} + O(1))$, where $q$ is the size of the field). + +## 2. The decoding function + +First some definitions: +* $\mathbb{F}$ is the finite field of size $q$, of characteristic 5 or more, and $q \equiv 1 \mod 3.$ + * For `secp256k1`, $q = 2^{256} - 2^{32} - 977$, which satisfies that requirement. +* Let $E$ be the elliptic curve of points $(x, y) \in \mathbb{F}^2$ for which $y^2 = x^3 + ax + b$, with $a$ and $b$ + public constants, for which $\Delta_E = -16(4a^3 + 27b^2)$ is a square, and at least one of $(-b \pm \sqrt{-3 \Delta_E} / 36)/2$ is a square. + This implies that the order of $E$ is either odd, or a multiple of *4*. + If $a=0$, this condition is always fulfilled. + * For `secp256k1`, $a=0$ and $b=7.$ +* Let the function $g(x) = x^3 + ax + b$, so the $E$ curve equation is also $y^2 = g(x).$ +* Let the function $h(x) = 3x^3 + 4a.$ +* Define $V$ as the set of solutions $(x_1, x_2, x_3, z)$ to $z^2 = g(x_1)g(x_2)g(x_3).$ +* Define $S_u$ as the set of solutions $(X, Y)$ to $X^2 + h(u)Y^2 = -g(u)$ and $Y \neq 0.$ +* $P_u$ is a function from $\mathbb{F}$ to $S_u$ that will be defined below. +* $\psi_u$ is a function from $S_u$ to $V$ that will be defined below. + +**Note**: In the paper: +* $F_u$ corresponds to $F_{0,u}$ there. +* $P_u(t)$ is called $P$ there. +* All $S_u$ sets together correspond to $S$ there. +* All $\psi_u$ functions together (operating on elements of $S$) correspond to $\psi$ there. + +Note that for $V$, the left hand side of the equation $z^2$ is square, and thus the right +hand must also be square. As multiplying non-squares results in a square in $\mathbb{F}$, +out of the three right-hand side factors an even number must be non-squares. +This implies that exactly *1* or exactly *3* out of +$\\{g(x_1), g(x_2), g(x_3)\\}$ must be square, and thus that for any $(x_1,x_2,x_3,z) \in V$, +at least one of $\\{x_1, x_2, x_3\\}$ must be a valid x-coordinate on $E.$ There is one exception +to this, namely when $z=0$, but even then one of the three values is a valid x-coordinate. + +**Define** the decoding function $F_u(t)$ as: +* Let $(x_1, x_2, x_3, z) = \psi_u(P_u(t)).$ +* Return the first element $x$ of $(x_3, x_2, x_1)$ which is a valid x-coordinate on $E$ (i.e., $g(x)$ is square). + +$P_u(t) = (X(u, t), Y(u, t))$, where: + +$$ +\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 +\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 \\ + Y_0(u) + t(X(u, t) - X_0(u)) & a \neq 0 +\end{array}\right. +\end{array} +$$ + +$P_u(t)$ is defined: +* For $a=0$, unless: + * $u = 0$ or $t = 0$ (division by zero) + * $g(u) = -t^2$ (would give $Y=0$). +* For $a \neq 0$, unless: + * $X_0(u) = 0$ or $h(u)t^2 = -1$ (division by zero) + * $Y_0(u) (1 - h(u)t^2) = 2X_0(u)t$ (would give $Y=0$). + +The functions $X_0(u)$ and $Y_0(u)$ are defined in Appendix A of the paper, and depend on various properties of $E.$ + +The function $\psi_u$ is the same for all curves: $\psi_u(X, Y) = (x_1, x_2, x_3, z)$, where: + +$$ +\begin{array}{lcl} + x_1 & = & \dfrac{X}{2Y} - \dfrac{u}{2} && \\ + x_2 & = & -\dfrac{X}{2Y} - \dfrac{u}{2} && \\ + x_3 & = & u + 4Y^2 && \\ + z & = & \dfrac{g(x_3)}{2Y}(u^2 + ux_1 + x_1^2 + a) = \dfrac{-g(u)g(x_3)}{8Y^3} +\end{array} +$$ + +### 2.1 Decoding for `secp256k1` + +Put together and specialized for $a=0$ curves, decoding $(u, t)$ to an x-coordinate is: + +**Define** $F_u(t)$ as: +* Let $X = \dfrac{u^3 + b - t^2}{2t}.$ +* Let $Y = \dfrac{X + t}{u\sqrt{-3}}.$ +* Return the first $x$ in $(u + 4Y^2, \dfrac{-X}{2Y} - \dfrac{u}{2}, \dfrac{X}{2Y} - \dfrac{u}{2})$ for which $g(x)$ is square. + +To make sure that every input decodes to a valid x-coordinate, we remap the inputs in case +$P_u$ is not defined (when $u=0$, $t=0$, or $g(u) = -t^2$): + +**Define** $F_u(t)$ as: +* Let $u'=u$ if $u \neq 0$; $1$ otherwise (guaranteeing $u' \neq 0$). +* Let $t'=t$ if $t \neq 0$; $1$ otherwise (guaranteeing $t' \neq 0$). +* Let $t''=t'$ if $g(u') \neq -t'^2$; $2t'$ otherwise (guaranteeing $t'' \neq 0$ and $g(u') \neq -t''^2$). +* Let $X = \dfrac{u'^3 + b - t''^2}{2t''}.$ +* Let $Y = \dfrac{X + t''}{u'\sqrt{-3}}.$ +* Return the first $x$ in $(u' + 4Y^2, \dfrac{-X}{2Y} - \dfrac{u'}{2}, \dfrac{X}{2Y} - \dfrac{u'}{2})$ for which $x^3 + b$ is square. + +The choices here are not strictly necessary. Just returning a fixed constant in any of the undefined cases would suffice, +but the approach here is simple enough and gives fairly uniform output even in these cases. + +**Note**: in the paper these conditions result in $\infty$ as output, due to the use of projective coordinates there. +We wish to avoid the need for callers to deal with this special case. + +This is implemented in `rustsecp256k1_v0_9_0_ellswift_xswiftec_frac_var` (which decodes to an x-coordinate represented as a fraction), and +in `rustsecp256k1_v0_9_0_ellswift_xswiftec_var` (which outputs the actual x-coordinate). + +## 3. The encoding function + +To implement $F_u^{-1}(x)$, the function to find the set of inverses $t$ for which $F_u(t) = x$, we have to reverse the process: +* Find all the $(X, Y) \in S_u$ that could have given rise to $x$, through the $x_1$, $x_2$, or $x_3$ formulas in $\psi_u.$ +* Map those $(X, Y)$ solutions to $t$ values using $P_u^{-1}(X, Y).$ +* For each of the found $t$ values, verify that $F_u(t) = x.$ +* Return the remaining $t$ values. + +The function $P_u^{-1}$, which finds $t$ given $(X, Y) \in S_u$, is significantly simpler than $P_u:$ + +$$ +P_u^{-1}(X, Y) = \left\\{\begin{array}{ll} +Yu\sqrt{-3} - X & a = 0 \\ +\dfrac{Y-Y_0(u)}{X-X_0(u)} & a \neq 0 \land X \neq X_0(u) \\ +\dfrac{-X_0(u)}{h(u)Y_0(u)} & a \neq 0 \land X = X_0(u) \land Y = Y_0(u) +\end{array}\right. +$$ + +The third step above, verifying that $F_u(t) = x$, is necessary because for the $(X, Y)$ values found through the $x_1$ and $x_2$ expressions, +it is possible that decoding through $\psi_u(X, Y)$ yields a valid $x_3$ on the curve, which would take precedence over the +$x_1$ or $x_2$ decoding. These $(X, Y)$ solutions must be rejected. + +Since we know that exactly one or exactly three out of $\\{x_1, x_2, x_3\\}$ are valid x-coordinates for any $t$, +the case where either $x_1$ or $x_2$ is valid and in addition also $x_3$ is valid must mean that all three are valid. +This means that instead of checking whether $x_3$ is on the curve, it is also possible to check whether the other one out of +$x_1$ and $x_2$ is on the curve. This is significantly simpler, as it turns out. + +Observe that $\psi_u$ guarantees that $x_1 + x_2 = -u.$ So given either $x = x_1$ or $x = x_2$, the other one of the two can be computed as +$-u - x.$ Thus, when encoding $x$ through the $x_1$ or $x_2$ expressions, one can simply check whether $g(-u-x)$ is a square, +and if so, not include the corresponding $t$ values in the returned set. As this does not need $X$, $Y$, or $t$, this condition can be determined +before those values are computed. + +It is not possible that an encoding found through the $x_1$ expression decodes to a different valid x-coordinate using $x_2$ (which would +take precedence), for the same reason: if both $x_1$ and $x_2$ decodings were valid, $x_3$ would be valid as well, and thus take +precedence over both. Because of this, the $g(-u-x)$ being square test for $x_1$ and $x_2$ is the only test necessary to guarantee the found $t$ +values round-trip back to the input $x$ correctly. This is the reason for choosing the $(x_3, x_2, x_1)$ precedence order in the decoder; +any order which does not place $x_3$ first requires more complicated round-trip checks in the encoder. + +### 3.1 Switching to *v, w* coordinates + +Before working out the formulas for all this, we switch to different variables for $S_u.$ Let $v = (X/Y - u)/2$, and +$w = 2Y.$ Or in the other direction, $X = w(u/2 + v)$ and $Y = w/2:$ +* $S_u'$ becomes the set of $(v, w)$ for which $w^2 (u^2 + uv + v^2 + a) = -g(u)$ and $w \neq 0.$ +* For $a=0$ curves, $P_u^{-1}$ can be stated for $(v,w)$ as $P_u^{'-1}(v, w) = w\left(\frac{\sqrt{-3}-1}{2}u - v\right).$ +* $\psi_u$ can be stated for $(v, w)$ as $\psi_u'(v, w) = (x_1, x_2, x_3, z)$, where + +$$ +\begin{array}{lcl} + x_1 & = & v \\ + x_2 & = & -u - v \\ + x_3 & = & u + w^2 \\ + z & = & \dfrac{g(x_3)}{w}(u^2 + uv + v^2 + a) = \dfrac{-g(u)g(x_3)}{w^3} +\end{array} +$$ + +We can now write the expressions for finding $(v, w)$ given $x$ explicitly, by solving each of the $\\{x_1, x_2, x_3\\}$ +expressions for $v$ or $w$, and using the $S_u'$ equation to find the other variable: +* Assuming $x = x_1$, we find $v = x$ and $w = \pm\sqrt{-g(u)/(u^2 + uv + v^2 + a)}$ (two solutions). +* Assuming $x = x_2$, we find $v = -u-x$ and $w = \pm\sqrt{-g(u)/(u^2 + uv + v^2 + a)}$ (two solutions). +* Assuming $x = x_3$, we find $w = \pm\sqrt{x-u}$ and $v = -u/2 \pm \sqrt{-w^2(4g(u) + w^2h(u))}/(2w^2)$ (four solutions). + +### 3.2 Avoiding computing all inverses + +The *ElligatorSwift* algorithm as stated in Section 1 requires the computation of $L = F_u^{-1}(x)$ (the +set of all $t$ such that $(u, t)$ decode to $x$) in full. This is unnecessary. + +Observe that the procedure of restarting with probability $(1 - \frac{\\#L}{8})$ and otherwise returning a +uniformly random element from $L$ is actually equivalent to always padding $L$ with $\bot$ values up to length 8, +picking a uniformly random element from that, restarting whenever $\bot$ is picked: + +**Define** *ElligatorSwift(x)* as: +* Loop: + * Pick a uniformly random field element $u.$ + * Compute the set $L = F_u^{-1}(x).$ + * Let $T$ be the 8-element vector consisting of the elements of $L$, plus $8 - \\#L$ times $\\{\bot\\}.$ + * Select a uniformly random $t \in T.$ + * If $t \neq \bot$, return $(u, t)$; restart loop otherwise. + +Now notice that the order of elements in $T$ does not matter, as all we do is pick a uniformly +random element in it, so we do not need to have all $\bot$ values at the end. +As we have 8 distinct formulas for finding $(v, w)$ (taking the variants due to $\pm$ into account), +we can associate every index in $T$ with exactly one of those formulas, making sure that: +* Formulas that yield no solutions (due to division by zero or non-existing square roots) or invalid solutions are made to return $\bot.$ +* For the $x_1$ and $x_2$ cases, if $g(-u-x)$ is a square, $\bot$ is returned instead (the round-trip check). +* In case multiple formulas would return the same non- $\bot$ result, all but one of those must be turned into $\bot$ to avoid biasing those. + +The last condition above only occurs with negligible probability for cryptographically-sized curves, but is interesting +to take into account as it allows exhaustive testing in small groups. See [Section 3.4](#34-dealing-with-special-cases) +for an analysis of all the negligible cases. + +If we define $T = (G_{0,u}(x), G_{1,u}(x), \ldots, G_{7,u}(x))$, with each $G_{i,u}$ matching one of the formulas, +the loop can be simplified to only compute one of the inverses instead of all of them: + +**Define** *ElligatorSwift(x)* as: +* Loop: + * Pick a uniformly random field element $u.$ + * Pick a uniformly random integer $c$ in $[0,8).$ + * Let $t = G_{c,u}(x).$ + * If $t \neq \bot$, return $(u, t)$; restart loop otherwise. + +This is implemented in `rustsecp256k1_v0_9_0_ellswift_xelligatorswift_var`. + +### 3.3 Finding the inverse + +To implement $G_{c,u}$, we map $c=0$ to the $x_1$ formula, $c=1$ to the $x_2$ formula, and $c=2$ and $c=3$ to the $x_3$ formula. +Those are then repeated as $c=4$ through $c=7$ for the other sign of $w$ (noting that in each formula, $w$ is a square root of some expression). +Ignoring the negligible cases, we get: + +**Define** $G_{c,u}(x)$ as: +* If $c \in \\{0, 1, 4, 5\\}$ (for $x_1$ and $x_2$ formulas): + * If $g(-u-x)$ is square, return $\bot$ (as $x_3$ would be valid and take precedence). + * If $c \in \\{0, 4\\}$ (the $x_1$ formula) let $v = x$, otherwise let $v = -u-x$ (the $x_2$ formula) + * Let $s = -g(u)/(u^2 + uv + v^2 + a)$ (using $s = w^2$ in what follows). +* Otherwise, when $c \in \\{2, 3, 6, 7\\}$ (for $x_3$ formulas): + * Let $s = x-u.$ + * Let $r = \sqrt{-s(4g(u) + sh(u))}.$ + * Let $v = (r/s - u)/2$ if $c \in \\{3, 7\\}$; $(-r/s - u)/2$ otherwise. +* Let $w = \sqrt{s}.$ +* Depending on $c:$ + * If $c \in \\{0, 1, 2, 3\\}:$ return $P_u^{'-1}(v, w).$ + * If $c \in \\{4, 5, 6, 7\\}:$ return $P_u^{'-1}(v, -w).$ + +Whenever a square root of a non-square is taken, $\bot$ is returned; for both square roots this happens with roughly +50% on random inputs. Similarly, when a division by 0 would occur, $\bot$ is returned as well; this will only happen +with negligible probability. A division by 0 in the first branch in fact cannot occur at all, because $u^2 + uv + v^2 + a = 0$ +implies $g(-u-x) = g(x)$ which would mean the $g(-u-x)$ is square condition has triggered +and $\bot$ would have been returned already. + +**Note**: In the paper, the $case$ variable corresponds roughly to the $c$ above, but only takes on 4 possible values (1 to 4). +The conditional negation of $w$ at the end is done randomly, which is equivalent, but makes testing harder. We choose to +have the $G_{c,u}$ be deterministic, and capture all choices in $c.$ + +Now observe that the $c \in \\{1, 5\\}$ and $c \in \\{3, 7\\}$ conditions effectively perform the same $v \rightarrow -u-v$ +transformation. Furthermore, that transformation has no effect on $s$ in the first branch +as $u^2 + ux + x^2 + a = u^2 + u(-u-x) + (-u-x)^2 + a.$ Thus we can extract it out and move it down: + +**Define** $G_{c,u}(x)$ as: +* If $c \in \\{0, 1, 4, 5\\}:$ + * If $g(-u-x)$ is square, return $\bot.$ + * Let $s = -g(u)/(u^2 + ux + x^2 + a).$ + * Let $v = x.$ +* Otherwise, when $c \in \\{2, 3, 6, 7\\}:$ + * Let $s = x-u.$ + * Let $r = \sqrt{-s(4g(u) + sh(u))}.$ + * Let $v = (r/s - u)/2.$ +* Let $w = \sqrt{s}.$ +* Depending on $c:$ + * If $c \in \\{0, 2\\}:$ return $P_u^{'-1}(v, w).$ + * If $c \in \\{1, 3\\}:$ return $P_u^{'-1}(-u-v, w).$ + * If $c \in \\{4, 6\\}:$ return $P_u^{'-1}(v, -w).$ + * If $c \in \\{5, 7\\}:$ return $P_u^{'-1}(-u-v, -w).$ + +This shows there will always be exactly 0, 4, or 8 $t$ values for a given $(u, x)$ input. +There can be 0, 1, or 2 $(v, w)$ pairs before invoking $P_u^{'-1}$, and each results in 4 distinct $t$ values. + +### 3.4 Dealing with special cases + +As mentioned before there are a few cases to deal with which only happen in a negligibly small subset of inputs. +For cryptographically sized fields, if only random inputs are going to be considered, it is unnecessary to deal with these. Still, for completeness +we analyse them here. They generally fall into two categories: cases in which the encoder would produce $t$ values that +do not decode back to $x$ (or at least cannot guarantee that they do), and cases in which the encoder might produce the same +$t$ value for multiple $c$ inputs (thereby biasing that encoding): + +* In the branch for $x_1$ and $x_2$ (where $c \in \\{0, 1, 4, 5\\}$): + * When $g(u) = 0$, we would have $s=w=Y=0$, which is not on $S_u.$ This is only possible on even-ordered curves. + Excluding this also removes the one condition under which the simplified check for $x_3$ on the curve + fails (namely when $g(x_1)=g(x_2)=0$ but $g(x_3)$ is not square). + This does exclude some valid encodings: when both $g(u)=0$ and $u^2+ux+x^2+a=0$ (also implying $g(x)=0$), + the $S_u'$ equation degenerates to $0 = 0$, and many valid $t$ values may exist. Yet, these cannot be targeted uniformly by the + encoder anyway as there will generally be more than 8. + * When $g(x) = 0$, the same $t$ would be produced as in the $x_3$ branch (where $c \in \\{2, 3, 6, 7\\}$) which we give precedence + as it can deal with $g(u)=0$. + This is again only possible on even-ordered curves. +* In the branch for $x_3$ (where $c \in \\{2, 3, 6, 7\\}$): + * When $s=0$, a division by zero would occur. + * When $v = -u-v$ and $c \in \\{3, 7\\}$, the same $t$ would be returned as in the $c \in \\{2, 6\\}$ cases. + It is equivalent to checking whether $r=0$. + This cannot occur in the $x_1$ or $x_2$ branches, as it would trigger the $g(-u-x)$ is square condition. + A similar concern for $w = -w$ does not exist, as $w=0$ is already impossible in both branches: in the first + 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 $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.$ +* If $a \neq 0$ and $X_0(u)=0$, return $\bot.$ +* If $c \in \\{0, 1, 4, 5\\}:$ + * If $g(u) = 0$ or $g(x) = 0$, return $\bot$ (even curves only). + * If $g(-u-x)$ is square, return $\bot.$ + * Let $s = -g(u)/(u^2 + ux + x^2 + a)$ (cannot cause division by zero). + * Let $v = x.$ +* Otherwise, when $c \in \\{2, 3, 6, 7\\}:$ + * Let $s = x-u.$ + * Let $r = \sqrt{-s(4g(u) + sh(u))}$; return $\bot$ if not square. + * If $c \in \\{3, 7\\}$ and $r=0$, return $\bot.$ + * If $s = 0$, return $\bot.$ + * Let $v = (r/s - u)/2.$ +* Let $w = \sqrt{s}$; return $\bot$ if not square. +* If $a \neq 0$ and $w(u+2v) = 2X_0(u)$ and either $w \neq 2Y_0(u)$ or $h(u) = 0$, return $\bot.$ +* Depending on $c:$ + * If $c \in \\{0, 2\\}$, let $t = P_u^{'-1}(v, w).$ + * If $c \in \\{1, 3\\}$, let $t = P_u^{'-1}(-u-v, w).$ + * If $c \in \\{4, 6\\}$, let $t = P_u^{'-1}(v, -w).$ + * If $c \in \\{5, 7\\}$, let $t = P_u^{'-1}(-u-v, -w).$ +* If $a=0$ and $t=0$, return $\bot$ (even curves only). +* If $a \neq 0$ and $h(u)t^2 = -1$, return $\bot.$ +* Return $t.$ + +Given any $u$, using this algorithm over all $x$ and $c$ values, every $t$ value will be reached exactly once, +for an $x$ for which $F_u(t) = x$ holds, except for these cases that will not be reached: +* All cases where $P_u(t)$ is not defined: + * For $a=0$ curves, when $u=0$, $t=0$, or $g(u) = -t^2.$ + * For $a \neq 0$ curves, when $h(u)t^2 = -1$, $X_0(u) = 0$, or $Y_0(u) (1 - h(u) t^2) = 2X_0(u)t.$ +* When $g(u)=0$, the potentially many $t$ values that decode to an $x$ satisfying $g(x)=0$ using the $x_2$ formula. These were excluded by the $g(u)=0$ condition in the $c \in \\{0, 1, 4, 5\\}$ branch. + +These cases form a negligible subset of all $(u, t)$ for cryptographically sized curves. + +### 3.5 Encoding for `secp256k1` + +Specialized for odd-ordered $a=0$ curves: + +**Define** $G_{c,u}(x)$ as: +* If $u=0$, return $\bot.$ +* If $c \in \\{0, 1, 4, 5\\}:$ + * If $(-u-x)^3 + b$ is square, return $\bot$ + * Let $s = -(u^3 + b)/(u^2 + ux + x^2)$ (cannot cause division by 0). + * Let $v = x.$ +* Otherwise, when $c \in \\{2, 3, 6, 7\\}:$ + * Let $s = x-u.$ + * Let $r = \sqrt{-s(4(u^3 + b) + 3su^2)}$; return $\bot$ if not square. + * If $c \in \\{3, 7\\}$ and $r=0$, return $\bot.$ + * If $s = 0$, return $\bot.$ + * Let $v = (r/s - u)/2.$ +* Let $w = \sqrt{s}$; return $\bot$ if not square. +* Depending on $c:$ + * If $c \in \\{0, 2\\}:$ return $w(\frac{\sqrt{-3}-1}{2}u - v).$ + * If $c \in \\{1, 3\\}:$ return $w(\frac{\sqrt{-3}+1}{2}u + v).$ + * If $c \in \\{4, 6\\}:$ return $w(\frac{-\sqrt{-3}+1}{2}u + v).$ + * If $c \in \\{5, 7\\}:$ return $w(\frac{-\sqrt{-3}-1}{2}u - v).$ + +This is implemented in `rustsecp256k1_v0_9_0_ellswift_xswiftec_inv_var`. + +And the x-only ElligatorSwift encoding algorithm is still: + +**Define** *ElligatorSwift(x)* as: +* Loop: + * Pick a uniformly random field element $u.$ + * Pick a uniformly random integer $c$ in $[0,8).$ + * Let $t = G_{c,u}(x).$ + * If $t \neq \bot$, return $(u, t)$; restart loop otherwise. + +Note that this logic does not take the remapped $u=0$, $t=0$, and $g(u) = -t^2$ cases into account; it just avoids them. +While it is not impossible to make the encoder target them, this would increase the maximum number of $t$ values for a given $(u, x)$ +combination beyond 8, and thereby slow down the ElligatorSwift loop proportionally, for a negligible gain in uniformity. + +## 4. Encoding and decoding full *(x, y)* coordinates + +So far we have only addressed encoding and decoding x-coordinates, but in some cases an encoding +for full points with $(x, y)$ coordinates is desirable. It is possible to encode this information +in $t$ as well. + +Note that for any $(X, Y) \in S_u$, $(\pm X, \pm Y)$ are all on $S_u.$ Moreover, all of these are +mapped to the same x-coordinate. Negating $X$ or negating $Y$ just results in $x_1$ and $x_2$ +being swapped, and does not affect $x_3.$ This will not change the outcome x-coordinate as the order +of $x_1$ and $x_2$ only matters if both were to be valid, and in that case $x_3$ would be used instead. + +Still, these four $(X, Y)$ combinations all correspond to distinct $t$ values, so we can encode +the sign of the y-coordinate in the sign of $X$ or the sign of $Y.$ They correspond to the +four distinct $P_u^{'-1}$ calls in the definition of $G_{u,c}.$ + +**Note**: In the paper, the sign of the y coordinate is encoded in a separately-coded bit. + +To encode the sign of $y$ in the sign of $Y:$ + +**Define** *Decode(u, t)* for full $(x, y)$ as: +* Let $(X, Y) = P_u(t).$ +* Let $x$ be the first value in $(u + 4Y^2, \frac{-X}{2Y} - \frac{u}{2}, \frac{X}{2Y} - \frac{u}{2})$ for which $g(x)$ is square. +* Let $y = \sqrt{g(x)}.$ +* If $sign(y) = sign(Y)$, return $(x, y)$; otherwise return $(x, -y).$ + +And encoding would be done using a $G_{c,u}(x, y)$ function defined as: + +**Define** $G_{c,u}(x, y)$ as: +* If $c \in \\{0, 1\\}:$ + * If $g(u) = 0$ or $g(x) = 0$, return $\bot$ (even curves only). + * If $g(-u-x)$ is square, return $\bot.$ + * Let $s = -g(u)/(u^2 + ux + x^2 + a)$ (cannot cause division by zero). + * Let $v = x.$ +* Otherwise, when $c \in \\{2, 3\\}:$ + * Let $s = x-u.$ + * Let $r = \sqrt{-s(4g(u) + sh(u))}$; return $\bot$ if not square. + * If $c = 3$ and $r = 0$, return $\bot.$ + * Let $v = (r/s - u)/2.$ +* Let $w = \sqrt{s}$; return $\bot$ if not square. +* Let $w' = w$ if $sign(w/2) = sign(y)$; $-w$ otherwise. +* Depending on $c:$ + * If $c \in \\{0, 2\\}:$ return $P_u^{'-1}(v, w').$ + * If $c \in \\{1, 3\\}:$ return $P_u^{'-1}(-u-v, w').$ + +Note that $c$ now only ranges $[0,4)$, as the sign of $w'$ is decided based on that of $y$, rather than on $c.$ +This change makes some valid encodings unreachable: when $y = 0$ and $sign(Y) \neq sign(0)$. + +In the above logic, $sign$ can be implemented in several ways, such as parity of the integer representation +of the input field element (for prime-sized fields) or the quadratic residuosity (for fields where +$-1$ is not square). The choice does not matter, as long as it only takes on two possible values, and for $x \neq 0$ it holds that $sign(x) \neq sign(-x)$. + +### 4.1 Full *(x, y)* coordinates for `secp256k1` + +For $a=0$ curves, there is another option. Note that for those, +the $P_u(t)$ function translates negations of $t$ to negations of (both) $X$ and $Y.$ Thus, we can use $sign(t)$ to +encode the y-coordinate directly. Combined with the earlier remapping to guarantee all inputs land on the curve, we get +as decoder: + +**Define** *Decode(u, t)* as: +* Let $u'=u$ if $u \neq 0$; $1$ otherwise. +* Let $t'=t$ if $t \neq 0$; $1$ otherwise. +* Let $t''=t'$ if $u'^3 + b + t'^2 \neq 0$; $2t'$ otherwise. +* Let $X = \dfrac{u'^3 + b - t''^2}{2t''}.$ +* Let $Y = \dfrac{X + t''}{u'\sqrt{-3}}.$ +* Let $x$ be the first element of $(u' + 4Y^2, \frac{-X}{2Y} - \frac{u'}{2}, \frac{X}{2Y} - \frac{u'}{2})$ for which $g(x)$ is square. +* Let $y = \sqrt{g(x)}.$ +* Return $(x, y)$ if $sign(y) = sign(t)$; $(x, -y)$ otherwise. + +This is implemented in `rustsecp256k1_v0_9_0_ellswift_swiftec_var`. The used $sign(x)$ function is the parity of $x$ when represented as in integer in $[0,q).$ + +The corresponding encoder would invoke the x-only one, but negating the output $t$ if $sign(t) \neq sign(y).$ + +This is implemented in `rustsecp256k1_v0_9_0_ellswift_elligatorswift_var`. + +Note that this is only intended for encoding points where both the x-coordinate and y-coordinate are unpredictable. When encoding x-only points +where the y-coordinate is implicitly even (or implicitly square, or implicitly in $[0,q/2]$), the encoder in +[Section 3.5](#35-encoding-for-secp256k1) must be used, or a bias is reintroduced that undoes all the benefit of using ElligatorSwift +in the first place. diff --git a/secp256k1-sys/depend/secp256k1/doc/release-process.md b/secp256k1-sys/depend/secp256k1/doc/release-process.md index 79dc36ecc..ea6087c9f 100644 --- a/secp256k1-sys/depend/secp256k1/doc/release-process.md +++ b/secp256k1-sys/depend/secp256k1/doc/release-process.md @@ -12,10 +12,36 @@ It is best if the maintainers are present during the release, so they can help e This process also assumes that there will be no minor releases for old major releases. +We aim to cut a regular release every 3-4 months, approximately twice as frequent as major Bitcoin Core releases. Every second release should be published one month before the feature freeze of the next major Bitcoin Core release, allowing sufficient time to update the library in Core. + +## Sanity Checks +Perform these checks before creating a release: + +1. Ensure `make distcheck` doesn't fail. +```shell +./autogen.sh && ./configure --enable-dev-mode && make distcheck +``` +2. Check installation with autotools: +```shell +dir=$(mktemp -d) +./autogen.sh && ./configure --prefix=$dir && make clean && make install && ls -l $dir/include $dir/lib +gcc -o ecdsa examples/ecdsa.c $(PKG_CONFIG_PATH=$dir/lib/pkgconfig pkg-config --cflags --libs libsecp256k1) -Wl,-rpath,"$dir/lib" && ./ecdsa +``` +3. Check installation with CMake: +```shell +dir=$(mktemp -d) +build=$(mktemp -d) +cmake -B $build -DCMAKE_INSTALL_PREFIX=$dir && cmake --build $build --target install && ls -l $dir/include $dir/lib* +gcc -o ecdsa examples/ecdsa.c -I $dir/include -L $dir/lib*/ -l secp256k1 -Wl,-rpath,"$dir/lib",-rpath,"$dir/lib64" && ./ecdsa +``` + ## Regular release 1. Open a PR to the master branch with a commit (using message `"release: prepare for $MAJOR.$MINOR.$PATCH"`, for example) that - * finalizes the release notes in [CHANGELOG.md](../CHANGELOG.md) (make sure to include an entry for `### ABI Compatibility`), + * finalizes the release notes in [CHANGELOG.md](../CHANGELOG.md) by + * adding a section for the release (make sure that the version number is a link to a diff between the previous and new version), + * removing the `[Unreleased]` section header, and + * including an entry for `### ABI Compatibility` if it doesn't exist that mentions the library soname of the release, * sets `_PKG_VERSION_IS_RELEASE` to `true` in `configure.ac`, and * if this is not a patch release * updates `_PKG_VERSION_*` and `_LIB_VERSION_*` in `configure.ac` and @@ -27,8 +53,9 @@ This process also assumes that there will be no minor releases for old major rel git push git@github.com:bitcoin-core/secp256k1.git v$MAJOR.$MINOR.$PATCH ``` 3. Open a PR to the master branch with a commit (using message `"release cleanup: bump version after $MAJOR.$MINOR.$PATCH"`, for example) that - * sets `_PKG_VERSION_IS_RELEASE` to `false` and increments `_PKG_VERSION_PATCH` and `_LIB_VERSION_REVISION` in `configure.ac`, and - * increments the `$PATCH` component of `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_REVISION` in `CMakeLists.txt`. + * sets `_PKG_VERSION_IS_RELEASE` to `false` and increments `_PKG_VERSION_PATCH` and `_LIB_VERSION_REVISION` in `configure.ac`, + * increments the `$PATCH` component of `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_REVISION` in `CMakeLists.txt`, and + * adds an `[Unreleased]` section header to the [CHANGELOG.md](../CHANGELOG.md). If other maintainers are not present to approve the PR, it can be merged without ACKs. 4. Create a new GitHub release with a link to the corresponding entry in [CHANGELOG.md](../CHANGELOG.md). @@ -37,14 +64,14 @@ This process also assumes that there will be no minor releases for old major rel Note that bugfixes only need to be backported to releases for which no compatible release without the bug exists. -1. If `$PATCH = 1`, create maintenance branch `$MAJOR.$MINOR`: +1. If there's no maintenance branch `$MAJOR.$MINOR`, create one: ``` - git checkout -b $MAJOR.$MINOR v$MAJOR.$MINOR.0 + git checkout -b $MAJOR.$MINOR v$MAJOR.$MINOR.$((PATCH - 1)) git push git@github.com:bitcoin-core/secp256k1.git $MAJOR.$MINOR ``` 2. Open a pull request to the `$MAJOR.$MINOR` branch that * includes the bugfixes, - * finalizes the release notes, + * finalizes the release notes similar to a regular release, * increments `_PKG_VERSION_PATCH` and `_LIB_VERSION_REVISION` in `configure.ac` and the `$PATCH` component of `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_REVISION` in `CMakeLists.txt` (with commit message `"release: bump versions for $MAJOR.$MINOR.$PATCH"`, for example). diff --git a/secp256k1-sys/depend/secp256k1/examples/CMakeLists.txt b/secp256k1-sys/depend/secp256k1/examples/CMakeLists.txt index e095b7f84..607bb6777 100644 --- a/secp256k1-sys/depend/secp256k1/examples/CMakeLists.txt +++ b/secp256k1-sys/depend/secp256k1/examples/CMakeLists.txt @@ -1,27 +1,30 @@ -add_library(example INTERFACE) -target_include_directories(example INTERFACE - ${PROJECT_SOURCE_DIR}/include -) -target_link_libraries(example INTERFACE - secp256k1 - $<$:bcrypt> -) -if(NOT BUILD_SHARED_LIBS AND MSVC) - target_link_options(example INTERFACE /IGNORE:4217) -endif() +function(add_example name) + set(target_name ${name}_example) + add_executable(${target_name} ${name}.c) + target_include_directories(${target_name} PRIVATE + ${PROJECT_SOURCE_DIR}/include + ) + target_link_libraries(${target_name} + secp256k1 + $<$:bcrypt> + ) + set(test_name ${name}_example) + add_test(NAME ${test_name} COMMAND ${target_name}) + if(BUILD_SHARED_LIBS AND MSVC) + # The DLL must reside either in the same folder where the executable is + # or somewhere in PATH. Using the latter option. + set_tests_properties(${test_name} PROPERTIES + ENVIRONMENT "PATH=$;$ENV{PATH}" + ) + endif() +endfunction() -add_executable(ecdsa_example ecdsa.c) -target_link_libraries(ecdsa_example example) -add_test(NAME ecdsa_example COMMAND ecdsa_example) +add_example(ecdsa) if(SECP256K1_ENABLE_MODULE_ECDH) - add_executable(ecdh_example ecdh.c) - target_link_libraries(ecdh_example example) - add_test(NAME ecdh_example COMMAND ecdh_example) + add_example(ecdh) endif() if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) - add_executable(schnorr_example schnorr.c) - target_link_libraries(schnorr_example example) - add_test(NAME schnorr_example COMMAND schnorr_example) + add_example(schnorr) endif() diff --git a/secp256k1-sys/depend/secp256k1/examples/examples_util.h b/secp256k1-sys/depend/secp256k1/examples/examples_util.h index 8e3a8f00c..3293b6403 100644 --- a/secp256k1-sys/depend/secp256k1/examples/examples_util.h +++ b/secp256k1-sys/depend/secp256k1/examples/examples_util.h @@ -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. */ diff --git a/secp256k1-sys/depend/secp256k1/include/secp256k1.h b/secp256k1-sys/depend/secp256k1/include/secp256k1.h index b37f8be19..5c644dc93 100644 --- a/secp256k1-sys/depend/secp256k1/include/secp256k1.h +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1.h @@ -133,28 +133,35 @@ typedef int (*rustsecp256k1_v0_9_0_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 (*rustsecp256k1_v0_9_0_nonce_function)( * * It is highly recommended to call rustsecp256k1_v0_9_0_selftest before using this context. */ -SECP256K1_API_VAR const rustsecp256k1_v0_9_0_context *rustsecp256k1_v0_9_0_context_static; +SECP256K1_API const rustsecp256k1_v0_9_0_context *rustsecp256k1_v0_9_0_context_static; /** Deprecated alias for rustsecp256k1_v0_9_0_context_static. */ -SECP256K1_API_VAR const rustsecp256k1_v0_9_0_context *rustsecp256k1_v0_9_0_context_no_precomp +SECP256K1_API const rustsecp256k1_v0_9_0_context *rustsecp256k1_v0_9_0_context_no_precomp SECP256K1_DEPRECATED("Use rustsecp256k1_v0_9_0_context_static instead"); /** Perform basic self tests (to be used in conjunction with rustsecp256k1_v0_9_0_context_static) @@ -609,10 +616,10 @@ SECP256K1_API int rustsecp256k1_v0_9_0_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 rustsecp256k1_v0_9_0_nonce_function rustsecp256k1_v0_9_0_nonce_function_rfc6979; +SECP256K1_API const rustsecp256k1_v0_9_0_nonce_function rustsecp256k1_v0_9_0_nonce_function_rfc6979; /** A default safe nonce generation function (currently equal to rustsecp256k1_v0_9_0_nonce_function_rfc6979). */ -SECP256K1_API_VAR const rustsecp256k1_v0_9_0_nonce_function rustsecp256k1_v0_9_0_nonce_function_default; +SECP256K1_API const rustsecp256k1_v0_9_0_nonce_function rustsecp256k1_v0_9_0_nonce_function_default; /** Create an ECDSA signature. * @@ -716,10 +723,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ec_pubkey_ne * invalid according to rustsecp256k1_v0_9_0_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 - * rustsecp256k1_v0_9_0_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 + * rustsecp256k1_v0_9_0_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 rustsecp256k1_v0_9_0_ec_seckey_tweak_add( const rustsecp256k1_v0_9_0_context *ctx, @@ -744,10 +751,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ec_privkey_t * 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 - * rustsecp256k1_v0_9_0_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 + * rustsecp256k1_v0_9_0_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 rustsecp256k1_v0_9_0_ec_pubkey_tweak_add( const rustsecp256k1_v0_9_0_context *ctx, diff --git a/secp256k1-sys/depend/secp256k1/include/secp256k1.h.orig b/secp256k1-sys/depend/secp256k1/include/secp256k1.h.orig new file mode 100644 index 000000000..76775bd36 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1.h.orig @@ -0,0 +1,909 @@ +#ifndef SECP256K1_H +#define SECP256K1_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** Unless explicitly stated all pointer arguments must not be NULL. + * + * The following rules specify the order of arguments in API calls: + * + * 1. Context pointers go first, followed by output arguments, combined + * output/input arguments, and finally input-only arguments. + * 2. Array lengths always immediately follow the argument whose length + * they describe, even if this violates rule 1. + * 3. Within the OUT/OUTIN/IN groups, pointers to data that is typically generated + * later go first. This means: signatures, public nonces, secret nonces, + * messages, public keys, secret keys, tweaks. + * 4. Arguments that are not data pointers go last, from more complex to less + * complex: function pointers, algorithm names, messages, void pointers, + * counts, flags, booleans. + * 5. Opaque data pointers follow the function pointer they are to be passed to. + */ + +/** Opaque data structure that holds context information + * + * The primary purpose of context objects is to store randomization data for + * enhanced protection against side-channel leakage. This protection is only + * effective if the context is randomized after its creation. See + * rustsecp256k1_v0_9_0_context_create for creation of contexts and + * rustsecp256k1_v0_9_0_context_randomize for randomization. + * + * A secondary purpose of context objects is to store pointers to callback + * functions that the library will call when certain error states arise. See + * rustsecp256k1_v0_9_0_context_set_error_callback as well as + * rustsecp256k1_v0_9_0_context_set_illegal_callback for details. Future library versions + * may use context objects for additional purposes. + * + * A constructed context can safely be used from multiple threads + * simultaneously, but API calls that take a non-const pointer to a context + * need exclusive access to it. In particular this is the case for + * rustsecp256k1_v0_9_0_context_destroy, rustsecp256k1_v0_9_0_context_preallocated_destroy, + * and rustsecp256k1_v0_9_0_context_randomize. + * + * Regarding randomization, either do it once at creation time (in which case + * you do not need any locking for the other calls), or use a read-write lock. + */ +typedef struct rustsecp256k1_v0_9_0_context_struct rustsecp256k1_v0_9_0_context; + +/** Opaque data structure that holds rewritable "scratch space" + * + * The purpose of this structure is to replace dynamic memory allocations, + * because we target architectures where this may not be available. It is + * essentially a resizable (within specified parameters) block of bytes, + * which is initially created either by memory allocation or TODO as a pointer + * into some fixed rewritable space. + * + * Unlike the context object, this cannot safely be shared between threads + * without additional synchronization logic. + */ +typedef struct rustsecp256k1_v0_9_0_scratch_space_struct rustsecp256k1_v0_9_0_scratch_space; + +/** Opaque data structure that holds a parsed and valid public key. + * + * The exact representation of data inside is implementation defined and not + * guaranteed to be portable between different platforms or versions. It is + * however guaranteed to be 64 bytes in size, and can be safely copied/moved. + * If you need to convert to a format suitable for storage or transmission, + * use rustsecp256k1_v0_9_0_ec_pubkey_serialize and rustsecp256k1_v0_9_0_ec_pubkey_parse. To + * compare keys, use rustsecp256k1_v0_9_0_ec_pubkey_cmp. + */ +typedef struct { + unsigned char data[64]; +} rustsecp256k1_v0_9_0_pubkey; + +/** Opaque data structured that holds a parsed ECDSA signature. + * + * The exact representation of data inside is implementation defined and not + * guaranteed to be portable between different platforms or versions. It is + * however guaranteed to be 64 bytes in size, and can be safely copied/moved. + * If you need to convert to a format suitable for storage, transmission, or + * comparison, use the rustsecp256k1_v0_9_0_ecdsa_signature_serialize_* and + * rustsecp256k1_v0_9_0_ecdsa_signature_parse_* functions. + */ +typedef struct { + unsigned char data[64]; +} rustsecp256k1_v0_9_0_ecdsa_signature; + +/** A pointer to a function to deterministically generate a nonce. + * + * Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail. + * Out: nonce32: pointer to a 32-byte array to be filled by the function. + * In: msg32: the 32-byte message hash being verified (will not be NULL) + * key32: pointer to a 32-byte secret key (will not be NULL) + * algo16: pointer to a 16-byte array describing the signature + * algorithm (will be NULL for ECDSA for compatibility). + * data: Arbitrary data pointer that is passed through. + * attempt: how many iterations we have tried to find a nonce. + * This will almost always be 0, but different attempt values + * are required to result in a different nonce. + * + * Except for test cases, this function should compute some cryptographic hash of + * the message, the algorithm, the key and the attempt. + */ +typedef int (*rustsecp256k1_v0_9_0_nonce_function)( + unsigned char *nonce32, + const unsigned char *msg32, + const unsigned char *key32, + const unsigned char *algo16, + void *data, + unsigned int attempt +); + +# if !defined(SECP256K1_GNUC_PREREQ) +# if defined(__GNUC__)&&defined(__GNUC_MINOR__) +# define SECP256K1_GNUC_PREREQ(_maj,_min) \ + ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) +# else +# define SECP256K1_GNUC_PREREQ(_maj,_min) 0 +# endif +# endif + +/* When this header is used at build-time the SECP256K1_BUILD define needs to be set + * to correctly setup export attributes and nullness checks. This is normally done + * by secp256k1.c but to guard against this header being included before secp256k1.c + * has had a chance to set the define (e.g. via test harnesses that just includes + * secp256k1.c) we set SECP256K1_NO_BUILD when this header is processed without the + * BUILD define so this condition can be caught. + */ +#ifndef SECP256K1_BUILD +# define SECP256K1_NO_BUILD +#endif + +/* 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 + /* 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) + /* Building libsecp256k1 on non-Windows using GCC or compatible. */ +# define SECP256K1_API extern __attribute__ ((visibility ("default"))) +# else + /* All cases not captured above. */ +# define SECP256K1_API extern +# endif +#endif + +/* Warning attributes + * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out + * some paranoid null checks. */ +# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) +# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) +# else +# define SECP256K1_WARN_UNUSED_RESULT +# endif +# if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) +# define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x))) +# else +# define SECP256K1_ARG_NONNULL(_x) +# endif + +/* Attribute for marking functions, types, and variables as deprecated */ +#if !defined(SECP256K1_BUILD) && defined(__has_attribute) +# if __has_attribute(__deprecated__) +# define SECP256K1_DEPRECATED(_msg) __attribute__ ((__deprecated__(_msg))) +# else +# define SECP256K1_DEPRECATED(_msg) +# endif +#else +# define SECP256K1_DEPRECATED(_msg) +#endif + +/* All flags' lower 8 bits indicate what they're for. Do not use directly. */ +#define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1) +#define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0) +#define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1) +/* The higher bits contain the actual data. Do not use directly. */ +#define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8) +#define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9) +#define SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY (1 << 10) +#define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8) + +/** Context flags to pass to rustsecp256k1_v0_9_0_context_create, rustsecp256k1_v0_9_0_context_preallocated_size, and + * rustsecp256k1_v0_9_0_context_preallocated_create. */ +#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT) + +/** Deprecated context flags. These flags are treated equivalent to SECP256K1_CONTEXT_NONE. */ +#define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) +#define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN) + +/* Testing flag. Do not use. */ +#define SECP256K1_CONTEXT_DECLASSIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY) + +/** Flag to pass to rustsecp256k1_v0_9_0_ec_pubkey_serialize. */ +#define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) +#define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION) + +/** Prefix byte used to tag various encoded curvepoints for specific purposes */ +#define SECP256K1_TAG_PUBKEY_EVEN 0x02 +#define SECP256K1_TAG_PUBKEY_ODD 0x03 +#define SECP256K1_TAG_PUBKEY_UNCOMPRESSED 0x04 +#define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06 +#define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07 + +/** A built-in constant secp256k1 context object with static storage duration, to be + * used in conjunction with rustsecp256k1_v0_9_0_selftest. + * + * This context object offers *only limited functionality* , i.e., it cannot be used + * for API functions that perform computations involving secret keys, e.g., signing + * and public key generation. If this restriction applies to a specific API function, + * it is mentioned in its documentation. See rustsecp256k1_v0_9_0_context_create if you need a + * full context object that supports all functionality offered by the library. + * + * It is highly recommended to call rustsecp256k1_v0_9_0_selftest before using this context. + */ +SECP256K1_API const rustsecp256k1_v0_9_0_context *rustsecp256k1_v0_9_0_context_static; + +/** Deprecated alias for rustsecp256k1_v0_9_0_context_static. */ +SECP256K1_API const rustsecp256k1_v0_9_0_context *rustsecp256k1_v0_9_0_context_no_precomp +SECP256K1_DEPRECATED("Use rustsecp256k1_v0_9_0_context_static instead"); + +/** Perform basic self tests (to be used in conjunction with rustsecp256k1_v0_9_0_context_static) + * + * This function performs self tests that detect some serious usage errors and + * similar conditions, e.g., when the library is compiled for the wrong endianness. + * This is a last resort measure to be used in production. The performed tests are + * very rudimentary and are not intended as a replacement for running the test + * binaries. + * + * It is highly recommended to call this before using rustsecp256k1_v0_9_0_context_static. + * It is not necessary to call this function before using a context created with + * rustsecp256k1_v0_9_0_context_create (or rustsecp256k1_v0_9_0_context_preallocated_create), which will + * take care of performing the self tests. + * + * If the tests fail, this function will call the default error handler to abort the + * program (see rustsecp256k1_v0_9_0_context_set_error_callback). + */ +SECP256K1_API void rustsecp256k1_v0_9_0_selftest(void); + + +/** Create a secp256k1 context object (in dynamically allocated memory). + * + * This function uses malloc to allocate memory. It is guaranteed that malloc is + * called at most once for every call of this function. If you need to avoid dynamic + * memory allocation entirely, see rustsecp256k1_v0_9_0_context_static and the functions in + * rustsecp256k1_v0_9_0_preallocated.h. + * + * Returns: a newly created context object. + * In: flags: Always set to SECP256K1_CONTEXT_NONE (see below). + * + * The only valid non-deprecated flag in recent library versions is + * SECP256K1_CONTEXT_NONE, which will create a context sufficient for all functionality + * offered by the library. All other (deprecated) flags will be treated as equivalent + * to the SECP256K1_CONTEXT_NONE flag. Though the flags parameter primarily exists for + * historical reasons, future versions of the library may introduce new flags. + * + * If the context is intended to be used for API functions that perform computations + * involving secret keys, e.g., signing and public key generation, then it is highly + * recommended to call rustsecp256k1_v0_9_0_context_randomize on the context before calling + * those API functions. This will provide enhanced protection against side-channel + * leakage, see rustsecp256k1_v0_9_0_context_randomize for details. + * + * Do not create a new context object for each operation, as construction and + * randomization can take non-negligible time. + */ +SECP256K1_API rustsecp256k1_v0_9_0_context *rustsecp256k1_v0_9_0_context_create( + unsigned int flags +) SECP256K1_WARN_UNUSED_RESULT; + +/** Copy a secp256k1 context object (into dynamically allocated memory). + * + * This function uses malloc to allocate memory. It is guaranteed that malloc is + * called at most once for every call of this function. If you need to avoid dynamic + * memory allocation entirely, see the functions in rustsecp256k1_v0_9_0_preallocated.h. + * + * Cloning rustsecp256k1_v0_9_0_context_static is not possible, and should not be emulated by + * the caller (e.g., using memcpy). Create a new context instead. + * + * Returns: a newly created context object. + * Args: ctx: an existing context to copy (not rustsecp256k1_v0_9_0_context_static) + */ +SECP256K1_API rustsecp256k1_v0_9_0_context *rustsecp256k1_v0_9_0_context_clone( + const rustsecp256k1_v0_9_0_context *ctx +) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; + +/** Destroy a secp256k1 context object (created in dynamically allocated memory). + * + * The context pointer may not be used afterwards. + * + * The context to destroy must have been created using rustsecp256k1_v0_9_0_context_create + * or rustsecp256k1_v0_9_0_context_clone. If the context has instead been created using + * rustsecp256k1_v0_9_0_context_preallocated_create or rustsecp256k1_v0_9_0_context_preallocated_clone, the + * behaviour is undefined. In that case, rustsecp256k1_v0_9_0_context_preallocated_destroy must + * be used instead. + * + * Args: ctx: an existing context to destroy, constructed using + * rustsecp256k1_v0_9_0_context_create or rustsecp256k1_v0_9_0_context_clone + * (i.e., not rustsecp256k1_v0_9_0_context_static). + */ +SECP256K1_API void rustsecp256k1_v0_9_0_context_destroy( + rustsecp256k1_v0_9_0_context *ctx +) SECP256K1_ARG_NONNULL(1); + +/** Set a callback function to be called when an illegal argument is passed to + * an API call. It will only trigger for violations that are mentioned + * explicitly in the header. + * + * The philosophy is that these shouldn't be dealt with through a + * specific return value, as calling code should not have branches to deal with + * the case that this code itself is broken. + * + * On the other hand, during debug stage, one would want to be informed about + * such mistakes, and the default (crashing) may be inadvisable. + * When this callback is triggered, the API function called is guaranteed not + * to cause a crash, though its return value and output arguments are + * undefined. + * + * When this function has not been called (or called with fn==NULL), then the + * default handler will be used. The library provides a default handler which + * writes the message to stderr and calls abort. This default handler can be + * replaced at link time if the preprocessor macro + * USE_EXTERNAL_DEFAULT_CALLBACKS is defined, which is the case if the build + * has been configured with --enable-external-default-callbacks. Then the + * following two symbols must be provided to link against: + * - void rustsecp256k1_v0_9_0_default_illegal_callback_fn(const char *message, void *data); + * - void rustsecp256k1_v0_9_0_default_error_callback_fn(const char *message, void *data); + * The library can call these default handlers even before a proper callback data + * pointer could have been set using rustsecp256k1_v0_9_0_context_set_illegal_callback or + * rustsecp256k1_v0_9_0_context_set_error_callback, e.g., when the creation of a context + * fails. In this case, the corresponding default handler will be called with + * the data pointer argument set to NULL. + * + * Args: ctx: an existing context object. + * In: fun: a pointer to a function to call when an illegal argument is + * passed to the API, taking a message and an opaque pointer. + * (NULL restores the default handler.) + * data: the opaque pointer to pass to fun above, must be NULL for the default handler. + * + * See also rustsecp256k1_v0_9_0_context_set_error_callback. + */ +SECP256K1_API void rustsecp256k1_v0_9_0_context_set_illegal_callback( + rustsecp256k1_v0_9_0_context *ctx, + void (*fun)(const char *message, void *data), + const void *data +) SECP256K1_ARG_NONNULL(1); + +/** Set a callback function to be called when an internal consistency check + * fails. + * + * The default callback writes an error message to stderr and calls abort + * to abort the program. + * + * This can only trigger in case of a hardware failure, miscompilation, + * memory corruption, serious bug in the library, or other error would can + * otherwise result in undefined behaviour. It will not trigger due to mere + * incorrect usage of the API (see rustsecp256k1_v0_9_0_context_set_illegal_callback + * for that). After this callback returns, anything may happen, including + * crashing. + * + * Args: ctx: an existing context object. + * In: fun: a pointer to a function to call when an internal error occurs, + * taking a message and an opaque pointer (NULL restores the + * default handler, see rustsecp256k1_v0_9_0_context_set_illegal_callback + * for details). + * data: the opaque pointer to pass to fun above, must be NULL for the default handler. + * + * See also rustsecp256k1_v0_9_0_context_set_illegal_callback. + */ +SECP256K1_API void rustsecp256k1_v0_9_0_context_set_error_callback( + rustsecp256k1_v0_9_0_context *ctx, + void (*fun)(const char *message, void *data), + const void *data +) SECP256K1_ARG_NONNULL(1); + +/** Create a secp256k1 scratch space object. + * + * Returns: a newly created scratch space. + * Args: ctx: an existing context object. + * In: size: amount of memory to be available as scratch space. Some extra + * (<100 bytes) will be allocated for extra accounting. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT rustsecp256k1_v0_9_0_scratch_space *rustsecp256k1_v0_9_0_scratch_space_create( + const rustsecp256k1_v0_9_0_context *ctx, + size_t size +) SECP256K1_ARG_NONNULL(1); + +/** Destroy a secp256k1 scratch space. + * + * The pointer may not be used afterwards. + * Args: ctx: a secp256k1 context object. + * scratch: space to destroy + */ +SECP256K1_API void rustsecp256k1_v0_9_0_scratch_space_destroy( + const rustsecp256k1_v0_9_0_context *ctx, + rustsecp256k1_v0_9_0_scratch_space *scratch +) SECP256K1_ARG_NONNULL(1); + +/** Parse a variable-length public key into the pubkey object. + * + * Returns: 1 if the public key was fully valid. + * 0 if the public key could not be parsed or is invalid. + * Args: ctx: a secp256k1 context object. + * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a + * parsed version of input. If not, its value is undefined. + * In: input: pointer to a serialized public key + * inputlen: length of the array pointed to by input + * + * This function supports parsing compressed (33 bytes, header byte 0x02 or + * 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header + * byte 0x06 or 0x07) format public keys. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ec_pubkey_parse( + const rustsecp256k1_v0_9_0_context *ctx, + rustsecp256k1_v0_9_0_pubkey *pubkey, + const unsigned char *input, + size_t inputlen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize a pubkey object into a serialized byte sequence. + * + * Returns: 1 always. + * Args: ctx: a secp256k1 context object. + * Out: output: a pointer to a 65-byte (if compressed==0) or 33-byte (if + * compressed==1) byte array to place the serialized key + * in. + * In/Out: outputlen: a pointer to an integer which is initially set to the + * size of output, and is overwritten with the written + * size. + * In: pubkey: a pointer to a rustsecp256k1_v0_9_0_pubkey containing an + * initialized public key. + * flags: SECP256K1_EC_COMPRESSED if serialization should be in + * compressed format, otherwise SECP256K1_EC_UNCOMPRESSED. + */ +SECP256K1_API int rustsecp256k1_v0_9_0_ec_pubkey_serialize( + const rustsecp256k1_v0_9_0_context *ctx, + unsigned char *output, + size_t *outputlen, + const rustsecp256k1_v0_9_0_pubkey *pubkey, + unsigned int flags +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Compare two public keys using lexicographic (of compressed serialization) order + * + * Returns: <0 if the first public key is less than the second + * >0 if the first public key is greater than the second + * 0 if the two public keys are equal + * Args: ctx: a secp256k1 context object. + * In: pubkey1: first public key to compare + * pubkey2: second public key to compare + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ec_pubkey_cmp( + const rustsecp256k1_v0_9_0_context *ctx, + const rustsecp256k1_v0_9_0_pubkey *pubkey1, + const rustsecp256k1_v0_9_0_pubkey *pubkey2 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Parse an ECDSA signature in compact (64 bytes) format. + * + * Returns: 1 when the signature could be parsed, 0 otherwise. + * Args: ctx: a secp256k1 context object + * Out: sig: a pointer to a signature object + * In: input64: a pointer to the 64-byte array to parse + * + * The signature must consist of a 32-byte big endian R value, followed by a + * 32-byte big endian S value. If R or S fall outside of [0..order-1], the + * encoding is invalid. R and S with value 0 are allowed in the encoding. + * + * After the call, sig will always be initialized. If parsing failed or R or + * S are zero, the resulting sig value is guaranteed to fail verification for + * any message and public key. + */ +SECP256K1_API int rustsecp256k1_v0_9_0_ecdsa_signature_parse_compact( + const rustsecp256k1_v0_9_0_context *ctx, + rustsecp256k1_v0_9_0_ecdsa_signature *sig, + const unsigned char *input64 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Parse a DER ECDSA signature. + * + * Returns: 1 when the signature could be parsed, 0 otherwise. + * Args: ctx: a secp256k1 context object + * Out: sig: a pointer to a signature object + * In: input: a pointer to the signature to be parsed + * inputlen: the length of the array pointed to be input + * + * This function will accept any valid DER encoded signature, even if the + * encoded numbers are out of range. + * + * After the call, sig will always be initialized. If parsing failed or the + * encoded numbers are out of range, signature verification with it is + * guaranteed to fail for every message and public key. + */ +SECP256K1_API int rustsecp256k1_v0_9_0_ecdsa_signature_parse_der( + const rustsecp256k1_v0_9_0_context *ctx, + rustsecp256k1_v0_9_0_ecdsa_signature *sig, + const unsigned char *input, + size_t inputlen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize an ECDSA signature in DER format. + * + * Returns: 1 if enough space was available to serialize, 0 otherwise + * Args: ctx: a secp256k1 context object + * Out: output: a pointer to an array to store the DER serialization + * In/Out: outputlen: a pointer to a length integer. Initially, this integer + * should be set to the length of output. After the call + * it will be set to the length of the serialization (even + * if 0 was returned). + * In: sig: a pointer to an initialized signature object + */ +SECP256K1_API int rustsecp256k1_v0_9_0_ecdsa_signature_serialize_der( + const rustsecp256k1_v0_9_0_context *ctx, + unsigned char *output, + size_t *outputlen, + const rustsecp256k1_v0_9_0_ecdsa_signature *sig +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Serialize an ECDSA signature in compact (64 byte) format. + * + * Returns: 1 + * Args: ctx: a secp256k1 context object + * Out: output64: a pointer to a 64-byte array to store the compact serialization + * In: sig: a pointer to an initialized signature object + * + * See rustsecp256k1_v0_9_0_ecdsa_signature_parse_compact for details about the encoding. + */ +SECP256K1_API int rustsecp256k1_v0_9_0_ecdsa_signature_serialize_compact( + const rustsecp256k1_v0_9_0_context *ctx, + unsigned char *output64, + const rustsecp256k1_v0_9_0_ecdsa_signature *sig +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Verify an ECDSA signature. + * + * Returns: 1: correct signature + * 0: incorrect or unparseable signature + * Args: ctx: a secp256k1 context object. + * In: sig: the signature being verified. + * msghash32: the 32-byte message hash being verified. + * The verifier must make sure to apply a cryptographic + * hash function to the message by itself and not accept an + * msghash32 value directly. Otherwise, it would be easy to + * create a "valid" signature without knowledge of the + * secret key. See also + * https://bitcoin.stackexchange.com/a/81116/35586 for more + * background on this topic. + * pubkey: pointer to an initialized public key to verify with. + * + * To avoid accepting malleable signatures, only ECDSA signatures in lower-S + * form are accepted. + * + * If you need to accept ECDSA signatures from sources that do not obey this + * rule, apply rustsecp256k1_v0_9_0_ecdsa_signature_normalize to the signature prior to + * verification, but be aware that doing so results in malleable signatures. + * + * For details, see the comments for that function. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ecdsa_verify( + const rustsecp256k1_v0_9_0_context *ctx, + const rustsecp256k1_v0_9_0_ecdsa_signature *sig, + const unsigned char *msghash32, + const rustsecp256k1_v0_9_0_pubkey *pubkey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Convert a signature to a normalized lower-S form. + * + * Returns: 1 if sigin was not normalized, 0 if it already was. + * Args: ctx: a secp256k1 context object + * Out: sigout: a pointer to a signature to fill with the normalized form, + * or copy if the input was already normalized. (can be NULL if + * you're only interested in whether the input was already + * normalized). + * In: sigin: a pointer to a signature to check/normalize (can be identical to sigout) + * + * With ECDSA a third-party can forge a second distinct signature of the same + * message, given a single initial signature, but without knowing the key. This + * is done by negating the S value modulo the order of the curve, 'flipping' + * the sign of the random point R which is not included in the signature. + * + * Forgery of the same message isn't universally problematic, but in systems + * where message malleability or uniqueness of signatures is important this can + * cause issues. This forgery can be blocked by all verifiers forcing signers + * to use a normalized form. + * + * The lower-S form reduces the size of signatures slightly on average when + * variable length encodings (such as DER) are used and is cheap to verify, + * making it a good choice. Security of always using lower-S is assured because + * anyone can trivially modify a signature after the fact to enforce this + * property anyway. + * + * The lower S value is always between 0x1 and + * 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, + * inclusive. + * + * No other forms of ECDSA malleability are known and none seem likely, but + * there is no formal proof that ECDSA, even with this additional restriction, + * is free of other malleability. Commonly used serialization schemes will also + * accept various non-unique encodings, so care should be taken when this + * property is required for an application. + * + * The rustsecp256k1_v0_9_0_ecdsa_sign function will by default create signatures in the + * lower-S form, and rustsecp256k1_v0_9_0_ecdsa_verify will not accept others. In case + * signatures come from a system that cannot enforce this property, + * rustsecp256k1_v0_9_0_ecdsa_signature_normalize must be called before verification. + */ +SECP256K1_API int rustsecp256k1_v0_9_0_ecdsa_signature_normalize( + const rustsecp256k1_v0_9_0_context *ctx, + rustsecp256k1_v0_9_0_ecdsa_signature *sigout, + const rustsecp256k1_v0_9_0_ecdsa_signature *sigin +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3); + +/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. + * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of + * extra entropy. + */ +SECP256K1_API const rustsecp256k1_v0_9_0_nonce_function rustsecp256k1_v0_9_0_nonce_function_rfc6979; + +/** A default safe nonce generation function (currently equal to rustsecp256k1_v0_9_0_nonce_function_rfc6979). */ +SECP256K1_API const rustsecp256k1_v0_9_0_nonce_function rustsecp256k1_v0_9_0_nonce_function_default; + +/** Create an ECDSA signature. + * + * Returns: 1: signature created + * 0: the nonce generation function failed, or the secret key was invalid. + * Args: ctx: pointer to a context object (not rustsecp256k1_v0_9_0_context_static). + * Out: sig: pointer to an array where the signature will be placed. + * In: msghash32: the 32-byte message hash being signed. + * seckey: pointer to a 32-byte secret key. + * noncefp: pointer to a nonce generation function. If NULL, + * rustsecp256k1_v0_9_0_nonce_function_default is used. + * ndata: pointer to arbitrary data used by the nonce generation function + * (can be NULL). If it is non-NULL and + * rustsecp256k1_v0_9_0_nonce_function_default is used, then ndata must be a + * pointer to 32-bytes of additional data. + * + * The created signature is always in lower-S form. See + * rustsecp256k1_v0_9_0_ecdsa_signature_normalize for more details. + */ +SECP256K1_API int rustsecp256k1_v0_9_0_ecdsa_sign( + const rustsecp256k1_v0_9_0_context *ctx, + rustsecp256k1_v0_9_0_ecdsa_signature *sig, + const unsigned char *msghash32, + const unsigned char *seckey, + rustsecp256k1_v0_9_0_nonce_function noncefp, + const void *ndata +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Verify an ECDSA secret key. + * + * A secret key is valid if it is not 0 and less than the secp256k1 curve order + * when interpreted as an integer (most significant byte first). The + * probability of choosing a 32-byte string uniformly at random which is an + * invalid secret key is negligible. + * + * Returns: 1: secret key is valid + * 0: secret key is invalid + * Args: ctx: pointer to a context object. + * In: seckey: pointer to a 32-byte secret key. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ec_seckey_verify( + const rustsecp256k1_v0_9_0_context *ctx, + const unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + +/** Compute the public key for a secret key. + * + * Returns: 1: secret was valid, public key stores. + * 0: secret was invalid, try again. + * Args: ctx: pointer to a context object (not rustsecp256k1_v0_9_0_context_static). + * Out: pubkey: pointer to the created public key. + * In: seckey: pointer to a 32-byte secret key. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ec_pubkey_create( + const rustsecp256k1_v0_9_0_context *ctx, + rustsecp256k1_v0_9_0_pubkey *pubkey, + const unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Negates a secret key in place. + * + * Returns: 0 if the given secret key is invalid according to + * rustsecp256k1_v0_9_0_ec_seckey_verify. 1 otherwise + * Args: ctx: pointer to a context object + * In/Out: seckey: pointer to the 32-byte secret key to be negated. If the + * secret key is invalid according to + * rustsecp256k1_v0_9_0_ec_seckey_verify, this function returns 0 and + * seckey will be set to some unspecified value. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ec_seckey_negate( + const rustsecp256k1_v0_9_0_context *ctx, + unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + +/** Same as rustsecp256k1_v0_9_0_ec_seckey_negate, but DEPRECATED. Will be removed in + * future versions. */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ec_privkey_negate( + const rustsecp256k1_v0_9_0_context *ctx, + unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) + SECP256K1_DEPRECATED("Use rustsecp256k1_v0_9_0_ec_seckey_negate instead"); + +/** Negates a public key in place. + * + * Returns: 1 always + * Args: ctx: pointer to a context object + * In/Out: pubkey: pointer to the public key to be negated. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ec_pubkey_negate( + const rustsecp256k1_v0_9_0_context *ctx, + rustsecp256k1_v0_9_0_pubkey *pubkey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + +/** Tweak a secret key by adding tweak to it. + * + * Returns: 0 if the arguments are invalid or the resulting secret key would be + * invalid (only when the tweak is the negation of the secret key). 1 + * otherwise. + * Args: ctx: pointer to a context object. + * In/Out: seckey: pointer to a 32-byte secret key. If the secret key is + * invalid according to rustsecp256k1_v0_9_0_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, which must be valid according to + * rustsecp256k1_v0_9_0_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 rustsecp256k1_v0_9_0_ec_seckey_tweak_add( + const rustsecp256k1_v0_9_0_context *ctx, + unsigned char *seckey, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Same as rustsecp256k1_v0_9_0_ec_seckey_tweak_add, but DEPRECATED. Will be removed in + * future versions. */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ec_privkey_tweak_add( + const rustsecp256k1_v0_9_0_context *ctx, + unsigned char *seckey, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) + SECP256K1_DEPRECATED("Use rustsecp256k1_v0_9_0_ec_seckey_tweak_add instead"); + +/** Tweak a public key by adding tweak times the generator to it. + * + * Returns: 0 if the arguments are invalid or the resulting public key would be + * invalid (only when the tweak is the negation of the corresponding + * secret key). 1 otherwise. + * Args: ctx: pointer to a context object. + * 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, which must be valid according to + * rustsecp256k1_v0_9_0_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 rustsecp256k1_v0_9_0_ec_pubkey_tweak_add( + const rustsecp256k1_v0_9_0_context *ctx, + rustsecp256k1_v0_9_0_pubkey *pubkey, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Tweak a secret key by multiplying it by a tweak. + * + * Returns: 0 if the arguments are invalid. 1 otherwise. + * Args: ctx: pointer to a context object. + * In/Out: seckey: pointer to a 32-byte secret key. If the secret key is + * invalid according to rustsecp256k1_v0_9_0_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 + * rustsecp256k1_v0_9_0_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). + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ec_seckey_tweak_mul( + const rustsecp256k1_v0_9_0_context *ctx, + unsigned char *seckey, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Same as rustsecp256k1_v0_9_0_ec_seckey_tweak_mul, but DEPRECATED. Will be removed in + * future versions. */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ec_privkey_tweak_mul( + const rustsecp256k1_v0_9_0_context *ctx, + unsigned char *seckey, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) + SECP256K1_DEPRECATED("Use rustsecp256k1_v0_9_0_ec_seckey_tweak_mul instead"); + +/** Tweak a public key by multiplying it by a tweak value. + * + * Returns: 0 if the arguments are invalid. 1 otherwise. + * Args: ctx: pointer to a context object. + * 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 + * rustsecp256k1_v0_9_0_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). + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ec_pubkey_tweak_mul( + const rustsecp256k1_v0_9_0_context *ctx, + rustsecp256k1_v0_9_0_pubkey *pubkey, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Randomizes the context to provide enhanced protection against side-channel leakage. + * + * Returns: 1: randomization successful + * 0: error + * Args: ctx: pointer to a context object (not rustsecp256k1_v0_9_0_context_static). + * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state). + * + * While secp256k1 code is written and tested to be constant-time no matter what + * secret values are, it is possible that a compiler may output code which is not, + * and also that the CPU may not emit the same radio frequencies or draw the same + * amount of power for all values. Randomization of the context shields against + * side-channel observations which aim to exploit secret-dependent behaviour in + * certain computations which involve secret keys. + * + * It is highly recommended to call this function on contexts returned from + * rustsecp256k1_v0_9_0_context_create or rustsecp256k1_v0_9_0_context_clone (or from the corresponding + * functions in rustsecp256k1_v0_9_0_preallocated.h) before using these contexts to call API + * functions that perform computations involving secret keys, e.g., signing and + * public key generation. It is possible to call this function more than once on + * the same context, and doing so before every few computations involving secret + * keys is recommended as a defense-in-depth measure. Randomization of the static + * context rustsecp256k1_v0_9_0_context_static is not supported. + * + * Currently, the random seed is mainly used for blinding multiplications of a + * secret scalar with the elliptic curve base point. Multiplications of this + * kind are performed by exactly those API functions which are documented to + * require a context that is not rustsecp256k1_v0_9_0_context_static. As a rule of thumb, + * these are all functions which take a secret key (or a keypair) as an input. + * A notable exception to that rule is the ECDH module, which relies on a different + * kind of elliptic curve point multiplication and thus does not benefit from + * enhanced protection against side-channel leakage currently. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_context_randomize( + rustsecp256k1_v0_9_0_context *ctx, + const unsigned char *seed32 +) SECP256K1_ARG_NONNULL(1); + +/** Add a number of public keys together. + * + * Returns: 1: the sum of the public keys is valid. + * 0: the sum of the public keys is not valid. + * Args: ctx: pointer to a context object. + * Out: out: pointer to a public key object for placing the resulting public key. + * In: ins: pointer to array of pointers to public keys. + * n: the number of public keys to add together (must be at least 1). + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ec_pubkey_combine( + const rustsecp256k1_v0_9_0_context *ctx, + rustsecp256k1_v0_9_0_pubkey *out, + const rustsecp256k1_v0_9_0_pubkey * const *ins, + size_t n +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Compute a tagged hash as defined in BIP-340. + * + * This is useful for creating a message hash and achieving domain separation + * through an application-specific tag. This function returns + * SHA256(SHA256(tag)||SHA256(tag)||msg). Therefore, tagged hash + * implementations optimized for a specific tag can precompute the SHA256 state + * after hashing the tag hashes. + * + * Returns: 1 always. + * Args: ctx: pointer to a context object + * Out: hash32: pointer to a 32-byte array to store the resulting hash + * In: tag: pointer to an array containing the tag + * taglen: length of the tag array + * msg: pointer to an array containing the message + * msglen: length of the message array + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_tagged_sha256( + const rustsecp256k1_v0_9_0_context *ctx, + unsigned char *hash32, + const unsigned char *tag, + size_t taglen, + const unsigned char *msg, + size_t msglen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5); + +#ifdef __cplusplus +} +#endif + +#endif /* SECP256K1_H */ diff --git a/secp256k1-sys/depend/secp256k1/include/secp256k1_ecdh.h b/secp256k1-sys/depend/secp256k1/include/secp256k1_ecdh.h index 8373dc475..4bf3e00c0 100644 --- a/secp256k1-sys/depend/secp256k1/include/secp256k1_ecdh.h +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1_ecdh.h @@ -27,11 +27,11 @@ typedef int (*rustsecp256k1_v0_9_0_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 rustsecp256k1_v0_9_0_ecdh_hash_function rustsecp256k1_v0_9_0_ecdh_hash_function_sha256; +SECP256K1_API const rustsecp256k1_v0_9_0_ecdh_hash_function rustsecp256k1_v0_9_0_ecdh_hash_function_sha256; /** A default ECDH hash function (currently equal to rustsecp256k1_v0_9_0_ecdh_hash_function_sha256). * Populates the output parameter with 32 bytes. */ -SECP256K1_API_VAR const rustsecp256k1_v0_9_0_ecdh_hash_function rustsecp256k1_v0_9_0_ecdh_hash_function_default; +SECP256K1_API const rustsecp256k1_v0_9_0_ecdh_hash_function rustsecp256k1_v0_9_0_ecdh_hash_function_default; /** Compute an EC Diffie-Hellman secret in constant time * diff --git a/secp256k1-sys/depend/secp256k1/include/secp256k1_ellswift.h b/secp256k1-sys/depend/secp256k1/include/secp256k1_ellswift.h new file mode 100644 index 000000000..c047e24c2 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1_ellswift.h @@ -0,0 +1,200 @@ +#ifndef SECP256K1_ELLSWIFT_H +#define SECP256K1_ELLSWIFT_H + +#include "secp256k1.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This module provides an implementation of ElligatorSwift as well as a + * version of x-only ECDH using it (including compatibility with BIP324). + * + * ElligatorSwift is described in https://eprint.iacr.org/2022/759 by + * Chavez-Saab, Rodriguez-Henriquez, and Tibouchi. It permits encoding + * uniformly chosen public keys as 64-byte arrays which are indistinguishable + * from uniformly random arrays. + * + * Let f be the function from pairs of field elements to point X coordinates, + * defined as follows (all operations modulo p = 2^256 - 2^32 - 977) + * f(u,t): + * - Let C = 0xa2d2ba93507f1df233770c2a797962cc61f6d15da14ecd47d8d27ae1cd5f852, + * a square root of -3. + * - If u=0, set u=1 instead. + * - If t=0, set t=1 instead. + * - If u^3 + t^2 + 7 = 0, multiply t by 2. + * - Let X = (u^3 + 7 - t^2) / (2 * t) + * - Let Y = (X + t) / (C * u) + * - Return the first in [u + 4 * Y^2, (-X/Y - u) / 2, (X/Y - u) / 2] that is an + * X coordinate on the curve (at least one of them is, for any u and t). + * + * Then an ElligatorSwift encoding of x consists of the 32-byte big-endian + * encodings of field elements u and t concatenated, where f(u,t) = x. + * The encoding algorithm is described in the paper, and effectively picks a + * uniformly random pair (u,t) among those which encode x. + * + * If the Y coordinate is relevant, it is given the same parity as t. + * + * Changes w.r.t. the the paper: + * - The u=0, t=0, and u^3+t^2+7=0 conditions result in decoding to the point + * at infinity in the paper. Here they are remapped to finite points. + * - 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 rustsecp256k1_v0_9_0_ellswift_xdh to hash the shared X + * coordinate along with the encoded public keys to a uniform shared secret. + * + * Returns: 1 if a shared secret was successfully computed. + * 0 will cause rustsecp256k1_v0_9_0_ellswift_xdh to fail and return 0. + * Other return values are not allowed, and the behaviour of + * rustsecp256k1_v0_9_0_ellswift_xdh is undefined for other return values. + * Out: output: pointer to an array to be filled by the function + * In: x32: pointer to the 32-byte serialized X coordinate + * of the resulting shared point (will not be NULL) + * ell_a64: pointer to the 64-byte encoded public key of party A + * (will not be NULL) + * ell_b64: pointer to the 64-byte encoded public key of party B + * (will not be NULL) + * data: arbitrary data pointer that is passed through + */ +typedef int (*rustsecp256k1_v0_9_0_ellswift_xdh_hash_function)( + unsigned char *output, + const unsigned char *x32, + const unsigned char *ell_a64, + const unsigned char *ell_b64, + void *data +); + +/** An implementation of an rustsecp256k1_v0_9_0_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 const rustsecp256k1_v0_9_0_ellswift_xdh_hash_function rustsecp256k1_v0_9_0_ellswift_xdh_hash_function_prefix; + +/** An implementation of an rustsecp256k1_v0_9_0_ellswift_xdh_hash_function compatible with + * BIP324. It returns H_tag(ell_a64 || ell_b64 || x32), where H_tag is the + * BIP340 tagged hash function with tag "bip324_ellswift_xonly_ecdh". Equivalent + * to rustsecp256k1_v0_9_0_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 const rustsecp256k1_v0_9_0_ellswift_xdh_hash_function rustsecp256k1_v0_9_0_ellswift_xdh_hash_function_bip324; + +/** Construct a 64-byte ElligatorSwift encoding of a given pubkey. + * + * Returns: 1 always. + * Args: ctx: pointer to a context object + * Out: ell64: pointer to a 64-byte array to be filled + * In: pubkey: a pointer to a rustsecp256k1_v0_9_0_pubkey containing an + * initialized public key + * rnd32: pointer to 32 bytes of randomness + * + * It is recommended that rnd32 consists of 32 uniformly random bytes, not + * known to any adversary trying to detect whether public keys are being + * encoded, though 16 bytes of randomness (padded to an array of 32 bytes, + * e.g., with zeros) suffice to make the result indistinguishable from + * uniform. The randomness in rnd32 must not be a deterministic function of + * the pubkey (it can be derived from the private key, though). + * + * It is not guaranteed that the computed encoding is stable across versions + * of the library, even if all arguments to this function (including rnd32) + * are the same. + * + * This function runs in variable time. + */ +SECP256K1_API int rustsecp256k1_v0_9_0_ellswift_encode( + const rustsecp256k1_v0_9_0_context *ctx, + unsigned char *ell64, + const rustsecp256k1_v0_9_0_pubkey *pubkey, + const unsigned char *rnd32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Decode a 64-bytes ElligatorSwift encoded public key. + * + * Returns: always 1 + * Args: ctx: pointer to a context object + * Out: pubkey: pointer to a rustsecp256k1_v0_9_0_pubkey that will be filled + * In: ell64: pointer to a 64-byte array to decode + * + * This function runs in variable time. + */ +SECP256K1_API int rustsecp256k1_v0_9_0_ellswift_decode( + const rustsecp256k1_v0_9_0_context *ctx, + rustsecp256k1_v0_9_0_pubkey *pubkey, + const unsigned char *ell64 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Compute an ElligatorSwift public key for a secret key. + * + * Returns: 1: secret was valid, public key was stored. + * 0: secret was invalid, try again. + * Args: ctx: pointer to a context object + * Out: ell64: pointer to a 64-byte array to receive the ElligatorSwift + * public key + * In: seckey32: pointer to a 32-byte secret key + * auxrnd32: (optional) pointer to 32 bytes of randomness + * + * Constant time in seckey and auxrnd32, but not in the resulting public key. + * + * It is recommended that auxrnd32 contains 32 uniformly random bytes, though + * it is optional (and does result in encodings that are indistinguishable from + * uniform even without any auxrnd32). It differs from the (mandatory) rnd32 + * argument to rustsecp256k1_v0_9_0_ellswift_encode in this regard. + * + * This function can be used instead of calling rustsecp256k1_v0_9_0_ec_pubkey_create + * followed by rustsecp256k1_v0_9_0_ellswift_encode. It is safer, as it uses the secret + * key as entropy for the encoding (supplemented with auxrnd32, if provided). + * + * Like rustsecp256k1_v0_9_0_ellswift_encode, this function does not guarantee that the + * computed encoding is stable across versions of the library, even if all + * arguments (including auxrnd32) are the same. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ellswift_create( + const rustsecp256k1_v0_9_0_context *ctx, + unsigned char *ell64, + const unsigned char *seckey32, + const unsigned char *auxrnd32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** 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 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. + * In: ell_a64: pointer to the 64-byte encoded public key of party A + * (will not be NULL) + * ell_b64: pointer to the 64-byte encoded public key of party B + * (will not be NULL) + * seckey32: a pointer to our 32-byte secret key + * party: boolean indicating which party we are: zero if we are + * party A, non-zero if we are party B. seckey32 must be + * the private key corresponding to that party's ell_?64. + * This correspondence is not checked. + * hashfp: pointer to a hash function. + * data: arbitrary data pointer passed through to hashfp. + * + * Constant time in seckey32. + * + * This function is more efficient than decoding the public keys, and performing + * ECDH on them. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_ellswift_xdh( + const rustsecp256k1_v0_9_0_context *ctx, + unsigned char *output, + const unsigned char *ell_a64, + const unsigned char *ell_b64, + const unsigned char *seckey32, + int party, + rustsecp256k1_v0_9_0_ellswift_xdh_hash_function hashfp, + void *data +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(7); + +#ifdef __cplusplus +} +#endif + +#endif /* SECP256K1_ELLSWIFT_H */ diff --git a/secp256k1-sys/depend/secp256k1/include/secp256k1_extrakeys.h b/secp256k1-sys/depend/secp256k1/include/secp256k1_extrakeys.h index 967624baf..b16021d7b 100644 --- a/secp256k1-sys/depend/secp256k1/include/secp256k1_extrakeys.h +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1_extrakeys.h @@ -112,10 +112,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_xonly_pubkey * 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 rustsecp256k1_v0_9_0_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 rustsecp256k1_v0_9_0_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 rustsecp256k1_v0_9_0_xonly_pubkey_tweak_add( const rustsecp256k1_v0_9_0_context *ctx, @@ -185,9 +185,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_keypair_sec( /** Get the public key from a keypair. * * Returns: 1 always. - * Args: ctx: pointer to a context object. - * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to - * the keypair public key. If not, it's set to an invalid value. + * Args: ctx: pointer to a context object. + * Out: pubkey: pointer to a pubkey object, set to the keypair public key. * In: keypair: pointer to a keypair. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_keypair_pub( @@ -203,9 +202,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_keypair_pub( * * Returns: 1 always. * Args: ctx: pointer to a context object. - * Out: pubkey: pointer to an xonly_pubkey object. If 1 is returned, it is set - * to the keypair public key after converting it to an - * xonly_pubkey. If not, it's set to an invalid value. + * Out: pubkey: pointer to an xonly_pubkey object, set to the keypair + * public key after converting it to an xonly_pubkey. * pk_parity: Ignored if NULL. Otherwise, pointer to an integer that will be set to the * pk_parity argument of rustsecp256k1_v0_9_0_xonly_pubkey_from_pubkey. * In: keypair: pointer to a keypair. @@ -231,10 +229,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_9_0_keypair_xonl * 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 rustsecp256k1_v0_9_0_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 + * rustsecp256k1_v0_9_0_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 rustsecp256k1_v0_9_0_keypair_xonly_tweak_add( const rustsecp256k1_v0_9_0_context *ctx, diff --git a/secp256k1-sys/depend/secp256k1/include/secp256k1_schnorrsig.h b/secp256k1-sys/depend/secp256k1/include/secp256k1_schnorrsig.h index 999c78a68..c33caf579 100644 --- a/secp256k1-sys/depend/secp256k1/include/secp256k1_schnorrsig.h +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1_schnorrsig.h @@ -61,7 +61,7 @@ typedef int (*rustsecp256k1_v0_9_0_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 rustsecp256k1_v0_9_0_nonce_function_hardened rustsecp256k1_v0_9_0_nonce_function_bip340; +SECP256K1_API const rustsecp256k1_v0_9_0_nonce_function_hardened rustsecp256k1_v0_9_0_nonce_function_bip340; /** Data structure that contains additional arguments for schnorrsig_sign_custom. * diff --git a/secp256k1-sys/depend/secp256k1/sage/group_prover.sage b/secp256k1-sys/depend/secp256k1/sage/group_prover.sage index 9305c215d..bb0929536 100644 --- a/secp256k1-sys/depend/secp256k1/sage/group_prover.sage +++ b/secp256k1-sys/depend/secp256k1/sage/group_prover.sage @@ -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 diff --git a/secp256k1-sys/depend/secp256k1/src/CMakeLists.txt b/secp256k1-sys/depend/secp256k1/src/CMakeLists.txt index 26e7c56d6..f09dc7309 100644 --- a/secp256k1-sys/depend/secp256k1/src/CMakeLists.txt +++ b/secp256k1-sys/depend/secp256k1/src/CMakeLists.txt @@ -20,10 +20,10 @@ if(SECP256K1_ASM STREQUAL "arm32") target_link_libraries(rustsecp256k1_v0_9_0_asm INTERFACE rustsecp256k1_v0_9_0_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 $<$>:SECP256K1_STATIC>) endif() # Object libs don't know if they're being built for a shared or static lib. @@ -132,6 +132,9 @@ if(SECP256K1_INSTALL) if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/rustsecp256k1_v0_9_0_schnorrsig.h") endif() + if(SECP256K1_ENABLE_MODULE_ELLSWIFT) + list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/rustsecp256k1_v0_9_0_ellswift.h") + endif() install(FILES ${${PROJECT_NAME}_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) diff --git a/secp256k1-sys/depend/secp256k1/src/bench.c b/secp256k1-sys/depend/secp256k1/src/bench.c index dc40202ca..bf3f76d41 100644 --- a/secp256k1-sys/depend/secp256k1/src/bench.c +++ b/secp256k1-sys/depend/secp256k1/src/bench.c @@ -38,6 +38,8 @@ static void help(int default_iters) { printf(" ecdsa : all ECDSA algorithms--sign, verify, recovery (if enabled)\n"); printf(" ecdsa_sign : ECDSA siging algorithm\n"); printf(" ecdsa_verify : ECDSA verification algorithm\n"); + printf(" ec : all EC public key algorithms (keygen)\n"); + printf(" ec_keygen : EC public key generation\n"); #ifdef ENABLE_MODULE_RECOVERY printf(" ecdsa_recover : ECDSA public key recovery algorithm\n"); @@ -53,6 +55,14 @@ static void help(int default_iters) { printf(" schnorrsig_verify : Schnorr verification algorithm\n"); #endif +#ifdef ENABLE_MODULE_ELLSWIFT + printf(" ellswift : all ElligatorSwift benchmarks (encode, decode, keygen, ecdh)\n"); + printf(" ellswift_encode : ElligatorSwift encoding\n"); + printf(" ellswift_decode : ElligatorSwift decoding\n"); + printf(" ellswift_keygen : ElligatorSwift key generation\n"); + printf(" ellswift_ecdh : ECDH on ElligatorSwift keys\n"); +#endif + printf("\n"); } @@ -115,6 +125,30 @@ static void bench_sign_run(void* arg, int iters) { } } +static void bench_keygen_setup(void* arg) { + int i; + bench_data *data = (bench_data*)arg; + + for (i = 0; i < 32; i++) { + data->key[i] = i + 65; + } +} + +static void bench_keygen_run(void *arg, int iters) { + int i; + bench_data *data = (bench_data*)arg; + + for (i = 0; i < iters; i++) { + unsigned char pub33[33]; + size_t len = 33; + rustsecp256k1_v0_9_0_pubkey pubkey; + CHECK(rustsecp256k1_v0_9_0_ec_pubkey_create(data->ctx, &pubkey, data->key)); + CHECK(rustsecp256k1_v0_9_0_ec_pubkey_serialize(data->ctx, pub33, &len, &pubkey, SECP256K1_EC_COMPRESSED)); + memcpy(data->key, pub33 + 1, 32); + } +} + + #ifdef ENABLE_MODULE_ECDH # include "modules/ecdh/bench_impl.h" #endif @@ -127,6 +161,10 @@ static void bench_sign_run(void* arg, int iters) { # include "modules/schnorrsig/bench_impl.h" #endif +#ifdef ENABLE_MODULE_ELLSWIFT +# include "modules/ellswift/bench_impl.h" +#endif + int main(int argc, char** argv) { int i; rustsecp256k1_v0_9_0_pubkey pubkey; @@ -139,7 +177,9 @@ int main(int argc, char** argv) { /* Check for invalid user arguments */ char* valid_args[] = {"ecdsa", "verify", "ecdsa_verify", "sign", "ecdsa_sign", "ecdh", "recover", - "ecdsa_recover", "schnorrsig", "schnorrsig_verify", "schnorrsig_sign"}; + "ecdsa_recover", "schnorrsig", "schnorrsig_verify", "schnorrsig_sign", "ec", + "keygen", "ec_keygen", "ellswift", "encode", "ellswift_encode", "decode", + "ellswift_decode", "ellswift_keygen", "ellswift_ecdh"}; size_t valid_args_size = sizeof(valid_args)/sizeof(valid_args[0]); int invalid_args = have_invalid_args(argc, argv, valid_args, valid_args_size); @@ -181,6 +221,16 @@ int main(int argc, char** argv) { } #endif +#ifndef ENABLE_MODULE_ELLSWIFT + if (have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "ellswift_encode") || have_flag(argc, argv, "ellswift_decode") || + have_flag(argc, argv, "encode") || have_flag(argc, argv, "decode") || have_flag(argc, argv, "ellswift_keygen") || + have_flag(argc, argv, "ellswift_ecdh")) { + fprintf(stderr, "./bench: ElligatorSwift module not enabled.\n"); + fprintf(stderr, "Use ./configure --enable-module-ellswift.\n\n"); + return 1; + } +#endif + /* ECDSA benchmark */ data.ctx = rustsecp256k1_v0_9_0_context_create(SECP256K1_CONTEXT_NONE); @@ -201,6 +251,7 @@ int main(int argc, char** argv) { if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "verify") || have_flag(argc, argv, "ecdsa_verify")) run_benchmark("ecdsa_verify", bench_verify, NULL, NULL, &data, 10, iters); if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "sign") || have_flag(argc, argv, "ecdsa_sign")) run_benchmark("ecdsa_sign", bench_sign_run, bench_sign_setup, NULL, &data, 10, iters); + if (d || have_flag(argc, argv, "ec") || have_flag(argc, argv, "keygen") || have_flag(argc, argv, "ec_keygen")) run_benchmark("ec_keygen", bench_keygen_run, bench_keygen_setup, NULL, &data, 10, iters); rustsecp256k1_v0_9_0_context_destroy(data.ctx); @@ -219,5 +270,10 @@ int main(int argc, char** argv) { run_schnorrsig_bench(iters, argc, argv); #endif +#ifdef ENABLE_MODULE_ELLSWIFT + /* ElligatorSwift benchmarks */ + run_ellswift_bench(iters, argc, argv); +#endif + return 0; } diff --git a/secp256k1-sys/depend/secp256k1/src/bench_ecmult.c b/secp256k1-sys/depend/secp256k1/src/bench_ecmult.c index 287535d04..ec2358ed5 100644 --- a/secp256k1-sys/depend/secp256k1/src/bench_ecmult.c +++ b/secp256k1-sys/depend/secp256k1/src/bench_ecmult.c @@ -138,12 +138,10 @@ static void bench_ecmult_1p_teardown(void* arg, int iters) { static void bench_ecmult_0p_g(void* arg, int iters) { bench_data* data = (bench_data*)arg; - rustsecp256k1_v0_9_0_scalar zero; int i; - rustsecp256k1_v0_9_0_scalar_set_int(&zero, 0); for (i = 0; i < iters; ++i) { - rustsecp256k1_v0_9_0_ecmult(&data->output[i], NULL, &zero, &data->scalars[(data->offset1+i) % POINTS]); + rustsecp256k1_v0_9_0_ecmult(&data->output[i], NULL, &rustsecp256k1_v0_9_0_scalar_zero, &data->scalars[(data->offset1+i) % POINTS]); } } @@ -246,7 +244,6 @@ static void generate_scalar(uint32_t num, rustsecp256k1_v0_9_0_scalar* scalar) { static void run_ecmult_multi_bench(bench_data* data, size_t count, int includes_g, int num_iters) { char str[32]; - static const rustsecp256k1_v0_9_0_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); size_t iters = 1 + num_iters / count; size_t iter; @@ -264,7 +261,7 @@ static void run_ecmult_multi_bench(bench_data* data, size_t count, int includes_ rustsecp256k1_v0_9_0_scalar_add(&total, &total, &tmp); } rustsecp256k1_v0_9_0_scalar_negate(&total, &total); - rustsecp256k1_v0_9_0_ecmult(&data->expected_output[iter], NULL, &zero, &total); + rustsecp256k1_v0_9_0_ecmult(&data->expected_output[iter], NULL, &rustsecp256k1_v0_9_0_scalar_zero, &total); } /* Run the benchmark. */ diff --git a/secp256k1-sys/depend/secp256k1/src/checkmem.h b/secp256k1-sys/depend/secp256k1/src/checkmem.h index 571e4cc38..f2169decf 100644 --- a/secp256k1-sys/depend/secp256k1/src/checkmem.h +++ b/secp256k1-sys/depend/secp256k1/src/checkmem.h @@ -58,7 +58,14 @@ #if !defined SECP256K1_CHECKMEM_ENABLED # if defined VALGRIND # include +# if defined(__clang__) && defined(__APPLE__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wreserved-identifier" +# endif # include +# if defined(__clang__) && defined(__APPLE__) +# pragma clang diagnostic pop +# endif # define SECP256K1_CHECKMEM_ENABLED 1 # define SECP256K1_CHECKMEM_UNDEFINE(p, len) VALGRIND_MAKE_MEM_UNDEFINED((p), (len)) # define SECP256K1_CHECKMEM_DEFINE(p, len) VALGRIND_MAKE_MEM_DEFINED((p), (len)) diff --git a/secp256k1-sys/depend/secp256k1/src/ctime_tests.c b/secp256k1-sys/depend/secp256k1/src/ctime_tests.c index e18ef8abc..9ebf2a9d7 100644 --- a/secp256k1-sys/depend/secp256k1/src/ctime_tests.c +++ b/secp256k1-sys/depend/secp256k1/src/ctime_tests.c @@ -30,6 +30,10 @@ #include "../include/secp256k1_schnorrsig.h" #endif +#ifdef ENABLE_MODULE_ELLSWIFT +#include "../include/secp256k1_ellswift.h" +#endif + static void run_tests(rustsecp256k1_v0_9_0_context *ctx, unsigned char *key); int main(void) { @@ -80,6 +84,10 @@ static void run_tests(rustsecp256k1_v0_9_0_context *ctx, unsigned char *key) { #ifdef ENABLE_MODULE_EXTRAKEYS rustsecp256k1_v0_9_0_keypair keypair; #endif +#ifdef ENABLE_MODULE_ELLSWIFT + unsigned char ellswift[64]; + static const unsigned char prefix[64] = {'t', 'e', 's', 't'}; +#endif for (i = 0; i < 32; i++) { msg[i] = i + 1; @@ -171,4 +179,31 @@ static void run_tests(rustsecp256k1_v0_9_0_context *ctx, unsigned char *key) { SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); #endif + +#ifdef ENABLE_MODULE_ELLSWIFT + SECP256K1_CHECKMEM_UNDEFINE(key, 32); + ret = rustsecp256k1_v0_9_0_ellswift_create(ctx, ellswift, key, NULL); + SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); + CHECK(ret == 1); + + SECP256K1_CHECKMEM_UNDEFINE(key, 32); + ret = rustsecp256k1_v0_9_0_ellswift_create(ctx, ellswift, key, ellswift); + SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); + CHECK(ret == 1); + + for (i = 0; i < 2; i++) { + SECP256K1_CHECKMEM_UNDEFINE(key, 32); + SECP256K1_CHECKMEM_DEFINE(&ellswift, sizeof(ellswift)); + ret = rustsecp256k1_v0_9_0_ellswift_xdh(ctx, msg, ellswift, ellswift, key, i, rustsecp256k1_v0_9_0_ellswift_xdh_hash_function_bip324, NULL); + SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); + CHECK(ret == 1); + + SECP256K1_CHECKMEM_UNDEFINE(key, 32); + SECP256K1_CHECKMEM_DEFINE(&ellswift, sizeof(ellswift)); + ret = rustsecp256k1_v0_9_0_ellswift_xdh(ctx, msg, ellswift, ellswift, key, i, rustsecp256k1_v0_9_0_ellswift_xdh_hash_function_prefix, (void *)prefix); + SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); + CHECK(ret == 1); + } + +#endif } diff --git a/secp256k1-sys/depend/secp256k1/src/ecdsa_impl.h b/secp256k1-sys/depend/secp256k1/src/ecdsa_impl.h index 0b0ada18b..5f5726b74 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecdsa_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/ecdsa_impl.h @@ -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("rustsecp256k1_v0_9_0_params.sage"); print(hex(N))' + * 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 */ static const rustsecp256k1_v0_9_0_fe rustsecp256k1_v0_9_0_ecdsa_const_order_as_fe = SECP256K1_FE_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, @@ -35,12 +26,8 @@ static const rustsecp256k1_v0_9_0_fe rustsecp256k1_v0_9_0_ecdsa_const_order_as_f /** 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("rustsecp256k1_v0_9_0_params.sage"); print(hex(P-N))' + * 0x14551231950b75fc4402da1722fc9baee */ static const rustsecp256k1_v0_9_0_fe rustsecp256k1_v0_9_0_ecdsa_const_p_minus_order = SECP256K1_FE_CONST( 0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL diff --git a/secp256k1-sys/depend/secp256k1/src/eckey_impl.h b/secp256k1-sys/depend/secp256k1/src/eckey_impl.h index 6199fe55c..2ea03e301 100644 --- a/secp256k1-sys/depend/secp256k1/src/eckey_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/eckey_impl.h @@ -59,10 +59,8 @@ static int rustsecp256k1_v0_9_0_eckey_privkey_tweak_add(rustsecp256k1_v0_9_0_sca static int rustsecp256k1_v0_9_0_eckey_pubkey_tweak_add(rustsecp256k1_v0_9_0_ge *key, const rustsecp256k1_v0_9_0_scalar *tweak) { rustsecp256k1_v0_9_0_gej pt; - rustsecp256k1_v0_9_0_scalar one; rustsecp256k1_v0_9_0_gej_set_ge(&pt, key); - rustsecp256k1_v0_9_0_scalar_set_int(&one, 1); - rustsecp256k1_v0_9_0_ecmult(&pt, &pt, &one, tweak); + rustsecp256k1_v0_9_0_ecmult(&pt, &pt, &rustsecp256k1_v0_9_0_scalar_one, tweak); if (rustsecp256k1_v0_9_0_gej_is_infinity(&pt)) { return 0; @@ -80,15 +78,13 @@ static int rustsecp256k1_v0_9_0_eckey_privkey_tweak_mul(rustsecp256k1_v0_9_0_sca } static int rustsecp256k1_v0_9_0_eckey_pubkey_tweak_mul(rustsecp256k1_v0_9_0_ge *key, const rustsecp256k1_v0_9_0_scalar *tweak) { - rustsecp256k1_v0_9_0_scalar zero; rustsecp256k1_v0_9_0_gej pt; if (rustsecp256k1_v0_9_0_scalar_is_zero(tweak)) { return 0; } - rustsecp256k1_v0_9_0_scalar_set_int(&zero, 0); rustsecp256k1_v0_9_0_gej_set_ge(&pt, key); - rustsecp256k1_v0_9_0_ecmult(&pt, &pt, tweak, &zero); + rustsecp256k1_v0_9_0_ecmult(&pt, &pt, tweak, &rustsecp256k1_v0_9_0_scalar_zero); rustsecp256k1_v0_9_0_ge_set_gej(key, &pt); return 1; } diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult.h b/secp256k1-sys/depend/secp256k1/src/ecmult.h index c36db0c5b..326933561 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecmult.h +++ b/secp256k1-sys/depend/secp256k1/src/ecmult.h @@ -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. * diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_const_impl.h b/secp256k1-sys/depend/secp256k1/src/ecmult_const_impl.h index b9edb8524..fa2dbe115 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecmult_const_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/ecmult_const_impl.h @@ -276,7 +276,7 @@ static int rustsecp256k1_v0_9_0_ecmult_const_xonly(rustsecp256k1_v0_9_0_fe* r, c * * 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. diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_gen_compute_table_impl.h b/secp256k1-sys/depend/secp256k1/src/ecmult_gen_compute_table_impl.h index 5871fa454..de9c02fa6 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecmult_gen_compute_table_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/ecmult_gen_compute_table_impl.h @@ -22,6 +22,9 @@ static void rustsecp256k1_v0_9_0_ecmult_gen_compute_table(rustsecp256k1_v0_9_0_g rustsecp256k1_v0_9_0_gej nums_gej; int i, j; + VERIFY_CHECK(g > 0); + VERIFY_CHECK(n > 0); + /* get the generator */ rustsecp256k1_v0_9_0_gej_set_ge(&gj, gen); diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_gen_impl.h b/secp256k1-sys/depend/secp256k1/src/ecmult_gen_impl.h index 12f83562d..8b1f29473 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecmult_gen_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/ecmult_gen_impl.h @@ -87,7 +87,6 @@ static void rustsecp256k1_v0_9_0_ecmult_gen_blind(rustsecp256k1_v0_9_0_ecmult_ge rustsecp256k1_v0_9_0_fe s; unsigned char nonce32[32]; rustsecp256k1_v0_9_0_rfc6979_hmac_sha256 rng; - int overflow; unsigned char keydata[64]; if (seed32 == NULL) { /* When seed is NULL, reset the initial point and blinding value. */ @@ -106,11 +105,9 @@ static void rustsecp256k1_v0_9_0_ecmult_gen_blind(rustsecp256k1_v0_9_0_ecmult_ge memcpy(keydata + 32, seed32, 32); rustsecp256k1_v0_9_0_rfc6979_hmac_sha256_initialize(&rng, keydata, 64); memset(keydata, 0, sizeof(keydata)); - /* Accept unobservably small non-uniformity. */ rustsecp256k1_v0_9_0_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); - overflow = !rustsecp256k1_v0_9_0_fe_set_b32_limit(&s, nonce32); - overflow |= rustsecp256k1_v0_9_0_fe_is_zero(&s); - rustsecp256k1_v0_9_0_fe_cmov(&s, &rustsecp256k1_v0_9_0_fe_one, overflow); + rustsecp256k1_v0_9_0_fe_set_b32_mod(&s, nonce32); + rustsecp256k1_v0_9_0_fe_cmov(&s, &rustsecp256k1_v0_9_0_fe_one, rustsecp256k1_v0_9_0_fe_normalizes_to_zero(&s)); /* Randomize the projection to defend against multiplier sidechannels. Do this before our own call to rustsecp256k1_v0_9_0_ecmult_gen below. */ rustsecp256k1_v0_9_0_gej_rescale(&ctx->initial, &s); diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_impl.h b/secp256k1-sys/depend/secp256k1/src/ecmult_impl.h index 1f34db515..dda532939 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecmult_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/ecmult_impl.h @@ -288,7 +288,9 @@ static void rustsecp256k1_v0_9_0_ecmult_strauss_wnaf(const struct rustsecp256k1_ } /* Bring them to the same Z denominator. */ - rustsecp256k1_v0_9_0_ge_table_set_globalz(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, state->aux); + if (no) { + rustsecp256k1_v0_9_0_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++) { @@ -770,14 +772,12 @@ static size_t rustsecp256k1_v0_9_0_pippenger_max_points(const rustsecp256k1_v0_9 * require a scratch space */ static int rustsecp256k1_v0_9_0_ecmult_multi_simple_var(rustsecp256k1_v0_9_0_gej *r, const rustsecp256k1_v0_9_0_scalar *inp_g_sc, rustsecp256k1_v0_9_0_ecmult_multi_callback cb, void *cbdata, size_t n_points) { size_t point_idx; - rustsecp256k1_v0_9_0_scalar szero; rustsecp256k1_v0_9_0_gej tmpj; - rustsecp256k1_v0_9_0_scalar_set_int(&szero, 0); rustsecp256k1_v0_9_0_gej_set_infinity(r); rustsecp256k1_v0_9_0_gej_set_infinity(&tmpj); /* r = inp_g_sc*G */ - rustsecp256k1_v0_9_0_ecmult(r, &tmpj, &szero, inp_g_sc); + rustsecp256k1_v0_9_0_ecmult(r, &tmpj, &rustsecp256k1_v0_9_0_scalar_zero, inp_g_sc); for (point_idx = 0; point_idx < n_points; point_idx++) { rustsecp256k1_v0_9_0_ge point; rustsecp256k1_v0_9_0_gej pointj; @@ -825,9 +825,7 @@ static int rustsecp256k1_v0_9_0_ecmult_multi_var(const rustsecp256k1_v0_9_0_call if (inp_g_sc == NULL && n == 0) { return 1; } else if (n == 0) { - rustsecp256k1_v0_9_0_scalar szero; - rustsecp256k1_v0_9_0_scalar_set_int(&szero, 0); - rustsecp256k1_v0_9_0_ecmult(r, r, &szero, inp_g_sc); + rustsecp256k1_v0_9_0_ecmult(r, r, &rustsecp256k1_v0_9_0_scalar_zero, inp_g_sc); return 1; } if (scratch == NULL) { diff --git a/secp256k1-sys/depend/secp256k1/src/field.h b/secp256k1-sys/depend/secp256k1/src/field.h index e3f7dad1c..dfa5c1199 100644 --- a/secp256k1-sys/depend/secp256k1/src/field.h +++ b/secp256k1-sys/depend/secp256k1/src/field.h @@ -88,8 +88,8 @@ static const rustsecp256k1_v0_9_0_fe rustsecp256k1_v0_9_0_const_beta = SECP256K1 # define rustsecp256k1_v0_9_0_fe_set_b32_mod rustsecp256k1_v0_9_0_fe_impl_set_b32_mod # define rustsecp256k1_v0_9_0_fe_set_b32_limit rustsecp256k1_v0_9_0_fe_impl_set_b32_limit # define rustsecp256k1_v0_9_0_fe_get_b32 rustsecp256k1_v0_9_0_fe_impl_get_b32 -# define rustsecp256k1_v0_9_0_fe_negate rustsecp256k1_v0_9_0_fe_impl_negate -# define rustsecp256k1_v0_9_0_fe_mul_int rustsecp256k1_v0_9_0_fe_impl_mul_int +# define rustsecp256k1_v0_9_0_fe_negate_unchecked rustsecp256k1_v0_9_0_fe_impl_negate_unchecked +# define rustsecp256k1_v0_9_0_fe_mul_int_unchecked rustsecp256k1_v0_9_0_fe_impl_mul_int_unchecked # define rustsecp256k1_v0_9_0_fe_add rustsecp256k1_v0_9_0_fe_impl_add # define rustsecp256k1_v0_9_0_fe_mul rustsecp256k1_v0_9_0_fe_impl_mul # define rustsecp256k1_v0_9_0_fe_sqr rustsecp256k1_v0_9_0_fe_impl_sqr @@ -176,12 +176,6 @@ static int rustsecp256k1_v0_9_0_fe_is_odd(const rustsecp256k1_v0_9_0_fe *a); */ static int rustsecp256k1_v0_9_0_fe_equal(const rustsecp256k1_v0_9_0_fe *a, const rustsecp256k1_v0_9_0_fe *b); -/** Determine whether two field elements are equal, without constant-time guarantee. - * - * Identical in behavior to rustsecp256k1_v0_9_0_fe_equal, but not constant time in either a or b. - */ -static int rustsecp256k1_v0_9_0_fe_equal_var(const rustsecp256k1_v0_9_0_fe *a, const rustsecp256k1_v0_9_0_fe *b); - /** Compare the values represented by 2 field elements, without constant-time guarantee. * * On input, a and b must be valid normalized field elements. @@ -192,14 +186,14 @@ static int rustsecp256k1_v0_9_0_fe_cmp_var(const rustsecp256k1_v0_9_0_fe *a, con /** 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 rustsecp256k1_v0_9_0_fe_set_b32_mod(rustsecp256k1_v0_9_0_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,27 +208,39 @@ static void rustsecp256k1_v0_9_0_fe_get_b32(unsigned char *r, const rustsecp256k /** 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 rustsecp256k1_v0_9_0_fe_negate(rustsecp256k1_v0_9_0_fe *r, const rustsecp256k1_v0_9_0_fe *a, int m); +#define rustsecp256k1_v0_9_0_fe_negate(r, a, m) ASSERT_INT_CONST_AND_DO(m, rustsecp256k1_v0_9_0_fe_negate_unchecked(r, a, m)) + +/** Like rustsecp256k1_v0_9_0_fe_negate_unchecked but m is not checked to be an integer constant expression. + * + * Should not be called directly outside of tests. + */ +static void rustsecp256k1_v0_9_0_fe_negate_unchecked(rustsecp256k1_v0_9_0_fe *r, const rustsecp256k1_v0_9_0_fe *a, int m); /** Add a small integer to a field element. * * Performs {r += a}. The magnitude of r increases by 1, and normalized is cleared. - * a must be in range [0,0xFFFF]. + * a must be in range [0,0x7FFF]. */ static void rustsecp256k1_v0_9_0_fe_add_int(rustsecp256k1_v0_9_0_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 rustsecp256k1_v0_9_0_fe_mul_int(rustsecp256k1_v0_9_0_fe *r, int a); +#define rustsecp256k1_v0_9_0_fe_mul_int(r, a) ASSERT_INT_CONST_AND_DO(a, rustsecp256k1_v0_9_0_fe_mul_int_unchecked(r, a)) + +/** Like rustsecp256k1_v0_9_0_fe_mul_int but a is not checked to be an integer constant expression. + * + * Should not be called directly outside of tests. + */ +static void rustsecp256k1_v0_9_0_fe_mul_int_unchecked(rustsecp256k1_v0_9_0_fe *r, int a); /** Increment a field element by another. * @@ -267,8 +273,10 @@ static void rustsecp256k1_v0_9_0_fe_sqr(rustsecp256k1_v0_9_0_fe *r, const rustse /** 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 rustsecp256k1_v0_9_0_fe_sqrt(rustsecp256k1_v0_9_0_fe * SECP256K1_RESTRICT r, const rustsecp256k1_v0_9_0_fe * SECP256K1_RESTRICT a); @@ -310,7 +318,9 @@ static void rustsecp256k1_v0_9_0_fe_storage_cmov(rustsecp256k1_v0_9_0_fe_storage * * On input, both r and a must be valid field elements. Flag must be 0 or 1. * Performs {r = flag ? a : r}. - * On output, r's magnitude and normalized will equal a's in case of flag=1, unchanged otherwise. + * + * On output, r's magnitude will be the maximum of both input magnitudes. + * It will be normalized if and only if both inputs were normalized. */ static void rustsecp256k1_v0_9_0_fe_cmov(rustsecp256k1_v0_9_0_fe *r, const rustsecp256k1_v0_9_0_fe *a, int flag); @@ -336,4 +346,7 @@ static int rustsecp256k1_v0_9_0_fe_is_square_var(const rustsecp256k1_v0_9_0_fe * /** Check invariants on a field element (no-op unless VERIFY is enabled). */ static void rustsecp256k1_v0_9_0_fe_verify(const rustsecp256k1_v0_9_0_fe *a); +/** Check that magnitude of a is at most m (no-op unless VERIFY is enabled). */ +static void rustsecp256k1_v0_9_0_fe_verify_magnitude(const rustsecp256k1_v0_9_0_fe *a, int m); + #endif /* SECP256K1_FIELD_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/field_10x26_impl.h b/secp256k1-sys/depend/secp256k1/src/field_10x26_impl.h index e15e84c67..0eb0db4bf 100644 --- a/secp256k1-sys/depend/secp256k1/src/field_10x26_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/field_10x26_impl.h @@ -344,7 +344,7 @@ static void rustsecp256k1_v0_9_0_fe_impl_get_b32(unsigned char *r, const rustsec r[31] = a->n[0] & 0xff; } -SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_impl_negate(rustsecp256k1_v0_9_0_fe *r, const rustsecp256k1_v0_9_0_fe *a, int m) { +SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_impl_negate_unchecked(rustsecp256k1_v0_9_0_fe *r, const rustsecp256k1_v0_9_0_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 rustsecp256k1_v0_9_0_fe_impl_negate(rustsecp256k1_v r->n[9] = 0x03FFFFFUL * 2 * (m + 1) - a->n[9]; } -SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_impl_mul_int(rustsecp256k1_v0_9_0_fe *r, int a) { +SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_impl_mul_int_unchecked(rustsecp256k1_v0_9_0_fe *r, int a) { r->n[0] *= a; r->n[1] *= a; r->n[2] *= a; diff --git a/secp256k1-sys/depend/secp256k1/src/field_5x52_impl.h b/secp256k1-sys/depend/secp256k1/src/field_5x52_impl.h index 01c372067..5c1c8dc7a 100644 --- a/secp256k1-sys/depend/secp256k1/src/field_5x52_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/field_5x52_impl.h @@ -314,7 +314,7 @@ static void rustsecp256k1_v0_9_0_fe_impl_get_b32(unsigned char *r, const rustsec r[31] = a->n[0] & 0xFF; } -SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_impl_negate(rustsecp256k1_v0_9_0_fe *r, const rustsecp256k1_v0_9_0_fe *a, int m) { +SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_impl_negate_unchecked(rustsecp256k1_v0_9_0_fe *r, const rustsecp256k1_v0_9_0_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 rustsecp256k1_v0_9_0_fe_impl_negate(rustsecp256k1_v r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4]; } -SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_impl_mul_int(rustsecp256k1_v0_9_0_fe *r, int a) { +SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_impl_mul_int_unchecked(rustsecp256k1_v0_9_0_fe *r, int a) { r->n[0] *= a; r->n[1] *= a; r->n[2] *= a; diff --git a/secp256k1-sys/depend/secp256k1/src/field_impl.h b/secp256k1-sys/depend/secp256k1/src/field_impl.h index 42e413517..823faf271 100644 --- a/secp256k1-sys/depend/secp256k1/src/field_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/field_impl.h @@ -23,28 +23,15 @@ SECP256K1_INLINE static int rustsecp256k1_v0_9_0_fe_equal(const rustsecp256k1_v0 #ifdef VERIFY rustsecp256k1_v0_9_0_fe_verify(a); rustsecp256k1_v0_9_0_fe_verify(b); - VERIFY_CHECK(a->magnitude <= 1); - VERIFY_CHECK(b->magnitude <= 31); + rustsecp256k1_v0_9_0_fe_verify_magnitude(a, 1); + rustsecp256k1_v0_9_0_fe_verify_magnitude(b, 31); #endif rustsecp256k1_v0_9_0_fe_negate(&na, a, 1); rustsecp256k1_v0_9_0_fe_add(&na, b); return rustsecp256k1_v0_9_0_fe_normalizes_to_zero(&na); } -SECP256K1_INLINE static int rustsecp256k1_v0_9_0_fe_equal_var(const rustsecp256k1_v0_9_0_fe *a, const rustsecp256k1_v0_9_0_fe *b) { - rustsecp256k1_v0_9_0_fe na; -#ifdef VERIFY - rustsecp256k1_v0_9_0_fe_verify(a); - rustsecp256k1_v0_9_0_fe_verify(b); - VERIFY_CHECK(a->magnitude <= 1); - VERIFY_CHECK(b->magnitude <= 31); -#endif - rustsecp256k1_v0_9_0_fe_negate(&na, a, 1); - rustsecp256k1_v0_9_0_fe_add(&na, b); - return rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(&na); -} - -static int rustsecp256k1_v0_9_0_fe_sqrt(rustsecp256k1_v0_9_0_fe *r, const rustsecp256k1_v0_9_0_fe *a) { +static int rustsecp256k1_v0_9_0_fe_sqrt(rustsecp256k1_v0_9_0_fe * SECP256K1_RESTRICT r, const rustsecp256k1_v0_9_0_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. * @@ -60,7 +47,7 @@ static int rustsecp256k1_v0_9_0_fe_sqrt(rustsecp256k1_v0_9_0_fe *r, const rustse #ifdef VERIFY VERIFY_CHECK(r != a); rustsecp256k1_v0_9_0_fe_verify(a); - VERIFY_CHECK(a->magnitude <= 8); + rustsecp256k1_v0_9_0_fe_verify_magnitude(a, 8); #endif /** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in @@ -151,7 +138,7 @@ static int rustsecp256k1_v0_9_0_fe_sqrt(rustsecp256k1_v0_9_0_fe *r, const rustse if (!ret) { rustsecp256k1_v0_9_0_fe_negate(&t1, &t1, 1); rustsecp256k1_v0_9_0_fe_normalize_var(&t1); - VERIFY_CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&t1, a)); + VERIFY_CHECK(rustsecp256k1_v0_9_0_fe_equal(&t1, a)); } #endif return ret; @@ -159,19 +146,26 @@ static int rustsecp256k1_v0_9_0_fe_sqrt(rustsecp256k1_v0_9_0_fe *r, const rustse #ifndef VERIFY static void rustsecp256k1_v0_9_0_fe_verify(const rustsecp256k1_v0_9_0_fe *a) { (void)a; } +static void rustsecp256k1_v0_9_0_fe_verify_magnitude(const rustsecp256k1_v0_9_0_fe *a, int m) { (void)a; (void)m; } #else static void rustsecp256k1_v0_9_0_fe_impl_verify(const rustsecp256k1_v0_9_0_fe *a); static void rustsecp256k1_v0_9_0_fe_verify(const rustsecp256k1_v0_9_0_fe *a) { /* Magnitude between 0 and 32. */ - VERIFY_CHECK((a->magnitude >= 0) && (a->magnitude <= 32)); + rustsecp256k1_v0_9_0_fe_verify_magnitude(a, 32); /* Normalized is 0 or 1. */ VERIFY_CHECK((a->normalized == 0) || (a->normalized == 1)); /* If normalized, magnitude must be 0 or 1. */ - if (a->normalized) VERIFY_CHECK(a->magnitude <= 1); + if (a->normalized) rustsecp256k1_v0_9_0_fe_verify_magnitude(a, 1); /* Invoke implementation-specific checks. */ rustsecp256k1_v0_9_0_fe_impl_verify(a); } +static void rustsecp256k1_v0_9_0_fe_verify_magnitude(const rustsecp256k1_v0_9_0_fe *a, int m) { + VERIFY_CHECK(m >= 0); + VERIFY_CHECK(m <= 32); + VERIFY_CHECK(a->magnitude <= m); +} + static void rustsecp256k1_v0_9_0_fe_impl_normalize(rustsecp256k1_v0_9_0_fe *r); SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_normalize(rustsecp256k1_v0_9_0_fe *r) { rustsecp256k1_v0_9_0_fe_verify(r); @@ -289,23 +283,23 @@ SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_get_b32(unsigned char *r, c rustsecp256k1_v0_9_0_fe_impl_get_b32(r, a); } -static void rustsecp256k1_v0_9_0_fe_impl_negate(rustsecp256k1_v0_9_0_fe *r, const rustsecp256k1_v0_9_0_fe *a, int m); -SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_negate(rustsecp256k1_v0_9_0_fe *r, const rustsecp256k1_v0_9_0_fe *a, int m) { +static void rustsecp256k1_v0_9_0_fe_impl_negate_unchecked(rustsecp256k1_v0_9_0_fe *r, const rustsecp256k1_v0_9_0_fe *a, int m); +SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_negate_unchecked(rustsecp256k1_v0_9_0_fe *r, const rustsecp256k1_v0_9_0_fe *a, int m) { rustsecp256k1_v0_9_0_fe_verify(a); VERIFY_CHECK(m >= 0 && m <= 31); - VERIFY_CHECK(a->magnitude <= m); - rustsecp256k1_v0_9_0_fe_impl_negate(r, a, m); + rustsecp256k1_v0_9_0_fe_verify_magnitude(a, m); + rustsecp256k1_v0_9_0_fe_impl_negate_unchecked(r, a, m); r->magnitude = m + 1; r->normalized = 0; rustsecp256k1_v0_9_0_fe_verify(r); } -static void rustsecp256k1_v0_9_0_fe_impl_mul_int(rustsecp256k1_v0_9_0_fe *r, int a); -SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_mul_int(rustsecp256k1_v0_9_0_fe *r, int a) { +static void rustsecp256k1_v0_9_0_fe_impl_mul_int_unchecked(rustsecp256k1_v0_9_0_fe *r, int a); +SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_mul_int_unchecked(rustsecp256k1_v0_9_0_fe *r, int a) { rustsecp256k1_v0_9_0_fe_verify(r); VERIFY_CHECK(a >= 0 && a <= 32); VERIFY_CHECK(a*r->magnitude <= 32); - rustsecp256k1_v0_9_0_fe_impl_mul_int(r, a); + rustsecp256k1_v0_9_0_fe_impl_mul_int_unchecked(r, a); r->magnitude *= a; r->normalized = 0; rustsecp256k1_v0_9_0_fe_verify(r); @@ -326,8 +320,8 @@ static void rustsecp256k1_v0_9_0_fe_impl_mul(rustsecp256k1_v0_9_0_fe *r, const r SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_mul(rustsecp256k1_v0_9_0_fe *r, const rustsecp256k1_v0_9_0_fe *a, const rustsecp256k1_v0_9_0_fe * SECP256K1_RESTRICT b) { rustsecp256k1_v0_9_0_fe_verify(a); rustsecp256k1_v0_9_0_fe_verify(b); - VERIFY_CHECK(a->magnitude <= 8); - VERIFY_CHECK(b->magnitude <= 8); + rustsecp256k1_v0_9_0_fe_verify_magnitude(a, 8); + rustsecp256k1_v0_9_0_fe_verify_magnitude(b, 8); VERIFY_CHECK(r != b); VERIFY_CHECK(a != b); rustsecp256k1_v0_9_0_fe_impl_mul(r, a, b); @@ -339,7 +333,7 @@ SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_mul(rustsecp256k1_v0_9_0_fe static void rustsecp256k1_v0_9_0_fe_impl_sqr(rustsecp256k1_v0_9_0_fe *r, const rustsecp256k1_v0_9_0_fe *a); SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_sqr(rustsecp256k1_v0_9_0_fe *r, const rustsecp256k1_v0_9_0_fe *a) { rustsecp256k1_v0_9_0_fe_verify(a); - VERIFY_CHECK(a->magnitude <= 8); + rustsecp256k1_v0_9_0_fe_verify_magnitude(a, 8); rustsecp256k1_v0_9_0_fe_impl_sqr(r, a); r->magnitude = 1; r->normalized = 0; @@ -352,10 +346,8 @@ SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_cmov(rustsecp256k1_v0_9_0_f rustsecp256k1_v0_9_0_fe_verify(a); rustsecp256k1_v0_9_0_fe_verify(r); rustsecp256k1_v0_9_0_fe_impl_cmov(r, a, flag); - if (flag) { - r->magnitude = a->magnitude; - r->normalized = a->normalized; - } + if (a->magnitude > r->magnitude) r->magnitude = a->magnitude; + if (!a->normalized) r->normalized = 0; rustsecp256k1_v0_9_0_fe_verify(r); } @@ -420,7 +412,7 @@ SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_get_bounds(rustsecp256k1_v0 static void rustsecp256k1_v0_9_0_fe_impl_half(rustsecp256k1_v0_9_0_fe *r); SECP256K1_INLINE static void rustsecp256k1_v0_9_0_fe_half(rustsecp256k1_v0_9_0_fe *r) { rustsecp256k1_v0_9_0_fe_verify(r); - VERIFY_CHECK(r->magnitude < 32); + rustsecp256k1_v0_9_0_fe_verify_magnitude(r, 31); rustsecp256k1_v0_9_0_fe_impl_half(r); r->magnitude = (r->magnitude >> 1) + 1; r->normalized = 0; diff --git a/secp256k1-sys/depend/secp256k1/src/group.h b/secp256k1-sys/depend/secp256k1/src/group.h index 98569e574..329a7651c 100644 --- a/secp256k1-sys/depend/secp256k1/src/group.h +++ b/secp256k1-sys/depend/secp256k1/src/group.h @@ -44,6 +44,14 @@ typedef struct { #define SECP256K1_GE_STORAGE_CONST_GET(t) SECP256K1_FE_STORAGE_CONST_GET(t.x), SECP256K1_FE_STORAGE_CONST_GET(t.y) +/** Maximum allowed magnitudes for group element coordinates + * in affine (x, y) and jacobian (x, y, z) representation. */ +#define SECP256K1_GE_X_MAGNITUDE_MAX 4 +#define SECP256K1_GE_Y_MAGNITUDE_MAX 3 +#define SECP256K1_GEJ_X_MAGNITUDE_MAX 4 +#define SECP256K1_GEJ_Y_MAGNITUDE_MAX 4 +#define SECP256K1_GEJ_Z_MAGNITUDE_MAX 1 + /** Set a group element equal to the point with given X and Y coordinates */ static void rustsecp256k1_v0_9_0_ge_set_xy(rustsecp256k1_v0_9_0_ge *r, const rustsecp256k1_v0_9_0_fe *x, const rustsecp256k1_v0_9_0_fe *y); @@ -51,6 +59,12 @@ static void rustsecp256k1_v0_9_0_ge_set_xy(rustsecp256k1_v0_9_0_ge *r, const rus * for Y. Return value indicates whether the result is valid. */ static int rustsecp256k1_v0_9_0_ge_set_xo_var(rustsecp256k1_v0_9_0_ge *r, const rustsecp256k1_v0_9_0_fe *x, int odd); +/** Determine whether x is a valid X coordinate on the curve. */ +static int rustsecp256k1_v0_9_0_ge_x_on_curve_var(const rustsecp256k1_v0_9_0_fe *x); + +/** Determine whether fraction xn/xd is a valid X coordinate on the curve (xd != 0). */ +static int rustsecp256k1_v0_9_0_ge_x_frac_on_curve_var(const rustsecp256k1_v0_9_0_fe *xn, const rustsecp256k1_v0_9_0_fe *xd); + /** Check whether a group element is the point at infinity. */ static int rustsecp256k1_v0_9_0_ge_is_infinity(const rustsecp256k1_v0_9_0_ge *a); @@ -100,7 +114,8 @@ static void rustsecp256k1_v0_9_0_gej_set_ge(rustsecp256k1_v0_9_0_gej *r, const r /** Check two group elements (jacobian) for equality in variable time. */ static int rustsecp256k1_v0_9_0_gej_eq_var(const rustsecp256k1_v0_9_0_gej *a, const rustsecp256k1_v0_9_0_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 rustsecp256k1_v0_9_0_gej_eq_x_var(const rustsecp256k1_v0_9_0_fe *x, const rustsecp256k1_v0_9_0_gej *a); /** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ diff --git a/secp256k1-sys/depend/secp256k1/src/group_impl.h b/secp256k1-sys/depend/secp256k1/src/group_impl.h index 5f68d94a7..3ece1a305 100644 --- a/secp256k1-sys/depend/secp256k1/src/group_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/group_impl.h @@ -77,6 +77,8 @@ static void rustsecp256k1_v0_9_0_ge_verify(const rustsecp256k1_v0_9_0_ge *a) { #ifdef VERIFY rustsecp256k1_v0_9_0_fe_verify(&a->x); rustsecp256k1_v0_9_0_fe_verify(&a->y); + rustsecp256k1_v0_9_0_fe_verify_magnitude(&a->x, SECP256K1_GE_X_MAGNITUDE_MAX); + rustsecp256k1_v0_9_0_fe_verify_magnitude(&a->y, SECP256K1_GE_Y_MAGNITUDE_MAX); VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); #endif (void)a; @@ -87,6 +89,9 @@ static void rustsecp256k1_v0_9_0_gej_verify(const rustsecp256k1_v0_9_0_gej *a) { rustsecp256k1_v0_9_0_fe_verify(&a->x); rustsecp256k1_v0_9_0_fe_verify(&a->y); rustsecp256k1_v0_9_0_fe_verify(&a->z); + rustsecp256k1_v0_9_0_fe_verify_magnitude(&a->x, SECP256K1_GEJ_X_MAGNITUDE_MAX); + rustsecp256k1_v0_9_0_fe_verify_magnitude(&a->y, SECP256K1_GEJ_Y_MAGNITUDE_MAX); + rustsecp256k1_v0_9_0_fe_verify_magnitude(&a->z, SECP256K1_GEJ_Z_MAGNITUDE_MAX); VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); #endif (void)a; @@ -99,11 +104,13 @@ static void rustsecp256k1_v0_9_0_ge_set_gej_zinv(rustsecp256k1_v0_9_0_ge *r, con rustsecp256k1_v0_9_0_gej_verify(a); rustsecp256k1_v0_9_0_fe_verify(zi); VERIFY_CHECK(!a->infinity); + rustsecp256k1_v0_9_0_fe_sqr(&zi2, zi); rustsecp256k1_v0_9_0_fe_mul(&zi3, &zi2, zi); rustsecp256k1_v0_9_0_fe_mul(&r->x, &a->x, &zi2); rustsecp256k1_v0_9_0_fe_mul(&r->y, &a->y, &zi3); r->infinity = a->infinity; + rustsecp256k1_v0_9_0_ge_verify(r); } @@ -114,39 +121,47 @@ static void rustsecp256k1_v0_9_0_ge_set_ge_zinv(rustsecp256k1_v0_9_0_ge *r, cons rustsecp256k1_v0_9_0_ge_verify(a); rustsecp256k1_v0_9_0_fe_verify(zi); VERIFY_CHECK(!a->infinity); + rustsecp256k1_v0_9_0_fe_sqr(&zi2, zi); rustsecp256k1_v0_9_0_fe_mul(&zi3, &zi2, zi); rustsecp256k1_v0_9_0_fe_mul(&r->x, &a->x, &zi2); rustsecp256k1_v0_9_0_fe_mul(&r->y, &a->y, &zi3); r->infinity = a->infinity; + rustsecp256k1_v0_9_0_ge_verify(r); } static void rustsecp256k1_v0_9_0_ge_set_xy(rustsecp256k1_v0_9_0_ge *r, const rustsecp256k1_v0_9_0_fe *x, const rustsecp256k1_v0_9_0_fe *y) { rustsecp256k1_v0_9_0_fe_verify(x); rustsecp256k1_v0_9_0_fe_verify(y); + r->infinity = 0; r->x = *x; r->y = *y; + rustsecp256k1_v0_9_0_ge_verify(r); } static int rustsecp256k1_v0_9_0_ge_is_infinity(const rustsecp256k1_v0_9_0_ge *a) { rustsecp256k1_v0_9_0_ge_verify(a); + return a->infinity; } static void rustsecp256k1_v0_9_0_ge_neg(rustsecp256k1_v0_9_0_ge *r, const rustsecp256k1_v0_9_0_ge *a) { rustsecp256k1_v0_9_0_ge_verify(a); + *r = *a; rustsecp256k1_v0_9_0_fe_normalize_weak(&r->y); rustsecp256k1_v0_9_0_fe_negate(&r->y, &r->y, 1); + rustsecp256k1_v0_9_0_ge_verify(r); } static void rustsecp256k1_v0_9_0_ge_set_gej(rustsecp256k1_v0_9_0_ge *r, rustsecp256k1_v0_9_0_gej *a) { rustsecp256k1_v0_9_0_fe z2, z3; rustsecp256k1_v0_9_0_gej_verify(a); + r->infinity = a->infinity; rustsecp256k1_v0_9_0_fe_inv(&a->z, &a->z); rustsecp256k1_v0_9_0_fe_sqr(&z2, &a->z); @@ -156,12 +171,15 @@ static void rustsecp256k1_v0_9_0_ge_set_gej(rustsecp256k1_v0_9_0_ge *r, rustsecp rustsecp256k1_v0_9_0_fe_set_int(&a->z, 1); r->x = a->x; r->y = a->y; + + rustsecp256k1_v0_9_0_gej_verify(a); rustsecp256k1_v0_9_0_ge_verify(r); } static void rustsecp256k1_v0_9_0_ge_set_gej_var(rustsecp256k1_v0_9_0_ge *r, rustsecp256k1_v0_9_0_gej *a) { rustsecp256k1_v0_9_0_fe z2, z3; rustsecp256k1_v0_9_0_gej_verify(a); + if (rustsecp256k1_v0_9_0_gej_is_infinity(a)) { rustsecp256k1_v0_9_0_ge_set_infinity(r); return; @@ -174,6 +192,8 @@ static void rustsecp256k1_v0_9_0_ge_set_gej_var(rustsecp256k1_v0_9_0_ge *r, rust rustsecp256k1_v0_9_0_fe_mul(&a->y, &a->y, &z3); rustsecp256k1_v0_9_0_fe_set_int(&a->z, 1); rustsecp256k1_v0_9_0_ge_set_xy(r, &a->x, &a->y); + + rustsecp256k1_v0_9_0_gej_verify(a); rustsecp256k1_v0_9_0_ge_verify(r); } @@ -181,9 +201,13 @@ static void rustsecp256k1_v0_9_0_ge_set_all_gej_var(rustsecp256k1_v0_9_0_ge *r, rustsecp256k1_v0_9_0_fe u; size_t i; size_t last_i = SIZE_MAX; - +#ifdef VERIFY for (i = 0; i < len; i++) { rustsecp256k1_v0_9_0_gej_verify(&a[i]); + } +#endif + + for (i = 0; i < len; i++) { if (a[i].infinity) { rustsecp256k1_v0_9_0_ge_set_infinity(&r[i]); } else { @@ -217,36 +241,46 @@ static void rustsecp256k1_v0_9_0_ge_set_all_gej_var(rustsecp256k1_v0_9_0_ge *r, if (!a[i].infinity) { rustsecp256k1_v0_9_0_ge_set_gej_zinv(&r[i], &a[i], &r[i].x); } + } + +#ifdef VERIFY + for (i = 0; i < len; i++) { rustsecp256k1_v0_9_0_ge_verify(&r[i]); } +#endif } static void rustsecp256k1_v0_9_0_ge_table_set_globalz(size_t len, rustsecp256k1_v0_9_0_ge *a, const rustsecp256k1_v0_9_0_fe *zr) { - size_t i = len - 1; + size_t i; rustsecp256k1_v0_9_0_fe zs; - - if (len > 0) { - /* Verify inputs a[len-1] and zr[len-1]. */ +#ifdef VERIFY + for (i = 0; i < len; i++) { rustsecp256k1_v0_9_0_ge_verify(&a[i]); rustsecp256k1_v0_9_0_fe_verify(&zr[i]); + } +#endif + + if (len > 0) { + i = len - 1; /* Ensure all y values are in weak normal form for fast negation of points */ rustsecp256k1_v0_9_0_fe_normalize_weak(&a[i].y); zs = zr[i]; /* Work our way backwards, using the z-ratios to scale the x/y values. */ while (i > 0) { - /* Verify all inputs a[i] and zr[i]. */ - rustsecp256k1_v0_9_0_fe_verify(&zr[i]); - rustsecp256k1_v0_9_0_ge_verify(&a[i]); if (i != len - 1) { rustsecp256k1_v0_9_0_fe_mul(&zs, &zs, &zr[i]); } i--; rustsecp256k1_v0_9_0_ge_set_ge_zinv(&a[i], &a[i], &zs); - /* Verify the output a[i]. */ - rustsecp256k1_v0_9_0_ge_verify(&a[i]); } } + +#ifdef VERIFY + for (i = 0; i < len; i++) { + rustsecp256k1_v0_9_0_ge_verify(&a[i]); + } +#endif } static void rustsecp256k1_v0_9_0_gej_set_infinity(rustsecp256k1_v0_9_0_gej *r) { @@ -254,6 +288,7 @@ static void rustsecp256k1_v0_9_0_gej_set_infinity(rustsecp256k1_v0_9_0_gej *r) { rustsecp256k1_v0_9_0_fe_clear(&r->x); rustsecp256k1_v0_9_0_fe_clear(&r->y); rustsecp256k1_v0_9_0_fe_clear(&r->z); + rustsecp256k1_v0_9_0_gej_verify(r); } @@ -261,6 +296,7 @@ static void rustsecp256k1_v0_9_0_ge_set_infinity(rustsecp256k1_v0_9_0_ge *r) { r->infinity = 1; rustsecp256k1_v0_9_0_fe_clear(&r->x); rustsecp256k1_v0_9_0_fe_clear(&r->y); + rustsecp256k1_v0_9_0_ge_verify(r); } @@ -269,18 +305,23 @@ static void rustsecp256k1_v0_9_0_gej_clear(rustsecp256k1_v0_9_0_gej *r) { rustsecp256k1_v0_9_0_fe_clear(&r->x); rustsecp256k1_v0_9_0_fe_clear(&r->y); rustsecp256k1_v0_9_0_fe_clear(&r->z); + + rustsecp256k1_v0_9_0_gej_verify(r); } static void rustsecp256k1_v0_9_0_ge_clear(rustsecp256k1_v0_9_0_ge *r) { r->infinity = 0; rustsecp256k1_v0_9_0_fe_clear(&r->x); rustsecp256k1_v0_9_0_fe_clear(&r->y); + + rustsecp256k1_v0_9_0_ge_verify(r); } static int rustsecp256k1_v0_9_0_ge_set_xo_var(rustsecp256k1_v0_9_0_ge *r, const rustsecp256k1_v0_9_0_fe *x, int odd) { rustsecp256k1_v0_9_0_fe x2, x3; int ret; rustsecp256k1_v0_9_0_fe_verify(x); + r->x = *x; rustsecp256k1_v0_9_0_fe_sqr(&x2, x); rustsecp256k1_v0_9_0_fe_mul(&x3, x, &x2); @@ -291,16 +332,19 @@ static int rustsecp256k1_v0_9_0_ge_set_xo_var(rustsecp256k1_v0_9_0_ge *r, const if (rustsecp256k1_v0_9_0_fe_is_odd(&r->y) != odd) { rustsecp256k1_v0_9_0_fe_negate(&r->y, &r->y, 1); } + rustsecp256k1_v0_9_0_ge_verify(r); return ret; } static void rustsecp256k1_v0_9_0_gej_set_ge(rustsecp256k1_v0_9_0_gej *r, const rustsecp256k1_v0_9_0_ge *a) { rustsecp256k1_v0_9_0_ge_verify(a); + r->infinity = a->infinity; r->x = a->x; r->y = a->y; rustsecp256k1_v0_9_0_fe_set_int(&r->z, 1); + rustsecp256k1_v0_9_0_gej_verify(r); } @@ -308,40 +352,47 @@ static int rustsecp256k1_v0_9_0_gej_eq_var(const rustsecp256k1_v0_9_0_gej *a, co rustsecp256k1_v0_9_0_gej tmp; rustsecp256k1_v0_9_0_gej_verify(b); rustsecp256k1_v0_9_0_gej_verify(a); + rustsecp256k1_v0_9_0_gej_neg(&tmp, a); rustsecp256k1_v0_9_0_gej_add_var(&tmp, &tmp, b, NULL); return rustsecp256k1_v0_9_0_gej_is_infinity(&tmp); } static int rustsecp256k1_v0_9_0_gej_eq_x_var(const rustsecp256k1_v0_9_0_fe *x, const rustsecp256k1_v0_9_0_gej *a) { - rustsecp256k1_v0_9_0_fe r, r2; + rustsecp256k1_v0_9_0_fe r; rustsecp256k1_v0_9_0_fe_verify(x); rustsecp256k1_v0_9_0_gej_verify(a); +#ifdef VERIFY VERIFY_CHECK(!a->infinity); +#endif + rustsecp256k1_v0_9_0_fe_sqr(&r, &a->z); rustsecp256k1_v0_9_0_fe_mul(&r, &r, x); - r2 = a->x; rustsecp256k1_v0_9_0_fe_normalize_weak(&r2); - return rustsecp256k1_v0_9_0_fe_equal_var(&r, &r2); + return rustsecp256k1_v0_9_0_fe_equal(&r, &a->x); } static void rustsecp256k1_v0_9_0_gej_neg(rustsecp256k1_v0_9_0_gej *r, const rustsecp256k1_v0_9_0_gej *a) { rustsecp256k1_v0_9_0_gej_verify(a); + r->infinity = a->infinity; r->x = a->x; r->y = a->y; r->z = a->z; rustsecp256k1_v0_9_0_fe_normalize_weak(&r->y); rustsecp256k1_v0_9_0_fe_negate(&r->y, &r->y, 1); + rustsecp256k1_v0_9_0_gej_verify(r); } static int rustsecp256k1_v0_9_0_gej_is_infinity(const rustsecp256k1_v0_9_0_gej *a) { rustsecp256k1_v0_9_0_gej_verify(a); + return a->infinity; } static int rustsecp256k1_v0_9_0_ge_is_valid_var(const rustsecp256k1_v0_9_0_ge *a) { rustsecp256k1_v0_9_0_fe y2, x3; rustsecp256k1_v0_9_0_ge_verify(a); + if (a->infinity) { return 0; } @@ -349,15 +400,14 @@ static int rustsecp256k1_v0_9_0_ge_is_valid_var(const rustsecp256k1_v0_9_0_ge *a rustsecp256k1_v0_9_0_fe_sqr(&y2, &a->y); rustsecp256k1_v0_9_0_fe_sqr(&x3, &a->x); rustsecp256k1_v0_9_0_fe_mul(&x3, &x3, &a->x); rustsecp256k1_v0_9_0_fe_add_int(&x3, SECP256K1_B); - rustsecp256k1_v0_9_0_fe_normalize_weak(&x3); - return rustsecp256k1_v0_9_0_fe_equal_var(&y2, &x3); + return rustsecp256k1_v0_9_0_fe_equal(&y2, &x3); } static SECP256K1_INLINE void rustsecp256k1_v0_9_0_gej_double(rustsecp256k1_v0_9_0_gej *r, const rustsecp256k1_v0_9_0_gej *a) { /* Operations: 3 mul, 4 sqr, 8 add/half/mul_int/negate */ rustsecp256k1_v0_9_0_fe l, s, t; - rustsecp256k1_v0_9_0_gej_verify(a); + r->infinity = a->infinity; /* Formula used: @@ -384,10 +434,13 @@ static SECP256K1_INLINE void rustsecp256k1_v0_9_0_gej_double(rustsecp256k1_v0_9_ rustsecp256k1_v0_9_0_fe_mul(&r->y, &t, &l); /* Y3 = L*(X3 + T) (1) */ rustsecp256k1_v0_9_0_fe_add(&r->y, &s); /* Y3 = L*(X3 + T) + S^2 (2) */ rustsecp256k1_v0_9_0_fe_negate(&r->y, &r->y, 2); /* Y3 = -(L*(X3 + T) + S^2) (3) */ + rustsecp256k1_v0_9_0_gej_verify(r); } static void rustsecp256k1_v0_9_0_gej_double_var(rustsecp256k1_v0_9_0_gej *r, const rustsecp256k1_v0_9_0_gej *a, rustsecp256k1_v0_9_0_fe *rzr) { + rustsecp256k1_v0_9_0_gej_verify(a); + /** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity, * Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have * y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p. @@ -398,7 +451,6 @@ static void rustsecp256k1_v0_9_0_gej_double_var(rustsecp256k1_v0_9_0_gej *r, con * the infinity flag even though the point doubles to infinity, and the result * point will be gibberish (z = 0 but infinity = 0). */ - rustsecp256k1_v0_9_0_gej_verify(a); if (a->infinity) { rustsecp256k1_v0_9_0_gej_set_infinity(r); if (rzr != NULL) { @@ -413,15 +465,16 @@ static void rustsecp256k1_v0_9_0_gej_double_var(rustsecp256k1_v0_9_0_gej *r, con } rustsecp256k1_v0_9_0_gej_double(r, a); + rustsecp256k1_v0_9_0_gej_verify(r); } static void rustsecp256k1_v0_9_0_gej_add_var(rustsecp256k1_v0_9_0_gej *r, const rustsecp256k1_v0_9_0_gej *a, const rustsecp256k1_v0_9_0_gej *b, rustsecp256k1_v0_9_0_fe *rzr) { /* 12 mul, 4 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */ rustsecp256k1_v0_9_0_fe z22, z12, u1, u2, s1, s2, h, i, h2, h3, t; - rustsecp256k1_v0_9_0_gej_verify(a); rustsecp256k1_v0_9_0_gej_verify(b); + if (a->infinity) { VERIFY_CHECK(rzr == NULL); *r = *b; @@ -476,14 +529,16 @@ static void rustsecp256k1_v0_9_0_gej_add_var(rustsecp256k1_v0_9_0_gej *r, const rustsecp256k1_v0_9_0_fe_mul(&r->y, &t, &i); rustsecp256k1_v0_9_0_fe_mul(&h3, &h3, &s1); rustsecp256k1_v0_9_0_fe_add(&r->y, &h3); + rustsecp256k1_v0_9_0_gej_verify(r); } static void rustsecp256k1_v0_9_0_gej_add_ge_var(rustsecp256k1_v0_9_0_gej *r, const rustsecp256k1_v0_9_0_gej *a, const rustsecp256k1_v0_9_0_ge *b, rustsecp256k1_v0_9_0_fe *rzr) { - /* 8 mul, 3 sqr, 13 add/negate/normalize_weak/normalizes_to_zero (ignoring special cases) */ + /* Operations: 8 mul, 3 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */ rustsecp256k1_v0_9_0_fe z12, u1, u2, s1, s2, h, i, h2, h3, t; rustsecp256k1_v0_9_0_gej_verify(a); rustsecp256k1_v0_9_0_ge_verify(b); + if (a->infinity) { VERIFY_CHECK(rzr == NULL); rustsecp256k1_v0_9_0_gej_set_ge(r, b); @@ -498,11 +553,11 @@ static void rustsecp256k1_v0_9_0_gej_add_ge_var(rustsecp256k1_v0_9_0_gej *r, con } rustsecp256k1_v0_9_0_fe_sqr(&z12, &a->z); - u1 = a->x; rustsecp256k1_v0_9_0_fe_normalize_weak(&u1); + u1 = a->x; rustsecp256k1_v0_9_0_fe_mul(&u2, &b->x, &z12); - s1 = a->y; rustsecp256k1_v0_9_0_fe_normalize_weak(&s1); + s1 = a->y; rustsecp256k1_v0_9_0_fe_mul(&s2, &b->y, &z12); rustsecp256k1_v0_9_0_fe_mul(&s2, &s2, &a->z); - rustsecp256k1_v0_9_0_fe_negate(&h, &u1, 1); rustsecp256k1_v0_9_0_fe_add(&h, &u2); + rustsecp256k1_v0_9_0_fe_negate(&h, &u1, SECP256K1_GEJ_X_MAGNITUDE_MAX); rustsecp256k1_v0_9_0_fe_add(&h, &u2); rustsecp256k1_v0_9_0_fe_negate(&i, &s2, 1); rustsecp256k1_v0_9_0_fe_add(&i, &s1); if (rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(&h)) { if (rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(&i)) { @@ -536,16 +591,18 @@ static void rustsecp256k1_v0_9_0_gej_add_ge_var(rustsecp256k1_v0_9_0_gej *r, con rustsecp256k1_v0_9_0_fe_mul(&r->y, &t, &i); rustsecp256k1_v0_9_0_fe_mul(&h3, &h3, &s1); rustsecp256k1_v0_9_0_fe_add(&r->y, &h3); + rustsecp256k1_v0_9_0_gej_verify(r); if (rzr != NULL) rustsecp256k1_v0_9_0_fe_verify(rzr); } static void rustsecp256k1_v0_9_0_gej_add_zinv_var(rustsecp256k1_v0_9_0_gej *r, const rustsecp256k1_v0_9_0_gej *a, const rustsecp256k1_v0_9_0_ge *b, const rustsecp256k1_v0_9_0_fe *bzinv) { - /* 9 mul, 3 sqr, 13 add/negate/normalize_weak/normalizes_to_zero (ignoring special cases) */ + /* Operations: 9 mul, 3 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */ rustsecp256k1_v0_9_0_fe az, z12, u1, u2, s1, s2, h, i, h2, h3, t; - + rustsecp256k1_v0_9_0_gej_verify(a); rustsecp256k1_v0_9_0_ge_verify(b); rustsecp256k1_v0_9_0_fe_verify(bzinv); + if (a->infinity) { rustsecp256k1_v0_9_0_fe bzinv2, bzinv3; r->infinity = b->infinity; @@ -554,6 +611,7 @@ static void rustsecp256k1_v0_9_0_gej_add_zinv_var(rustsecp256k1_v0_9_0_gej *r, c rustsecp256k1_v0_9_0_fe_mul(&r->x, &b->x, &bzinv2); rustsecp256k1_v0_9_0_fe_mul(&r->y, &b->y, &bzinv3); rustsecp256k1_v0_9_0_fe_set_int(&r->z, 1); + rustsecp256k1_v0_9_0_gej_verify(r); return; } if (b->infinity) { @@ -572,11 +630,11 @@ static void rustsecp256k1_v0_9_0_gej_add_zinv_var(rustsecp256k1_v0_9_0_gej *r, c rustsecp256k1_v0_9_0_fe_mul(&az, &a->z, bzinv); rustsecp256k1_v0_9_0_fe_sqr(&z12, &az); - u1 = a->x; rustsecp256k1_v0_9_0_fe_normalize_weak(&u1); + u1 = a->x; rustsecp256k1_v0_9_0_fe_mul(&u2, &b->x, &z12); - s1 = a->y; rustsecp256k1_v0_9_0_fe_normalize_weak(&s1); + s1 = a->y; rustsecp256k1_v0_9_0_fe_mul(&s2, &b->y, &z12); rustsecp256k1_v0_9_0_fe_mul(&s2, &s2, &az); - rustsecp256k1_v0_9_0_fe_negate(&h, &u1, 1); rustsecp256k1_v0_9_0_fe_add(&h, &u2); + rustsecp256k1_v0_9_0_fe_negate(&h, &u1, SECP256K1_GEJ_X_MAGNITUDE_MAX); rustsecp256k1_v0_9_0_fe_add(&h, &u2); rustsecp256k1_v0_9_0_fe_negate(&i, &s2, 1); rustsecp256k1_v0_9_0_fe_add(&i, &s1); if (rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(&h)) { if (rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(&i)) { @@ -604,19 +662,19 @@ static void rustsecp256k1_v0_9_0_gej_add_zinv_var(rustsecp256k1_v0_9_0_gej *r, c rustsecp256k1_v0_9_0_fe_mul(&r->y, &t, &i); rustsecp256k1_v0_9_0_fe_mul(&h3, &h3, &s1); rustsecp256k1_v0_9_0_fe_add(&r->y, &h3); + rustsecp256k1_v0_9_0_gej_verify(r); } static void rustsecp256k1_v0_9_0_gej_add_ge(rustsecp256k1_v0_9_0_gej *r, const rustsecp256k1_v0_9_0_gej *a, const rustsecp256k1_v0_9_0_ge *b) { - /* Operations: 7 mul, 5 sqr, 24 add/cmov/half/mul_int/negate/normalize_weak/normalizes_to_zero */ + /* Operations: 7 mul, 5 sqr, 21 add/cmov/half/mul_int/negate/normalizes_to_zero */ rustsecp256k1_v0_9_0_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr; rustsecp256k1_v0_9_0_fe m_alt, rr_alt; int degenerate; rustsecp256k1_v0_9_0_gej_verify(a); rustsecp256k1_v0_9_0_ge_verify(b); VERIFY_CHECK(!b->infinity); - VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); /* In: * Eric Brier and Marc Joye, Weierstrass Elliptic Curves and Side-Channel Attacks. @@ -669,17 +727,17 @@ static void rustsecp256k1_v0_9_0_gej_add_ge(rustsecp256k1_v0_9_0_gej *r, const r */ rustsecp256k1_v0_9_0_fe_sqr(&zz, &a->z); /* z = Z1^2 */ - u1 = a->x; rustsecp256k1_v0_9_0_fe_normalize_weak(&u1); /* u1 = U1 = X1*Z2^2 (1) */ + u1 = a->x; /* u1 = U1 = X1*Z2^2 (GEJ_X_M) */ rustsecp256k1_v0_9_0_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */ - s1 = a->y; rustsecp256k1_v0_9_0_fe_normalize_weak(&s1); /* s1 = S1 = Y1*Z2^3 (1) */ + s1 = a->y; /* s1 = S1 = Y1*Z2^3 (GEJ_Y_M) */ rustsecp256k1_v0_9_0_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z1^2 (1) */ rustsecp256k1_v0_9_0_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */ - t = u1; rustsecp256k1_v0_9_0_fe_add(&t, &u2); /* t = T = U1+U2 (2) */ - m = s1; rustsecp256k1_v0_9_0_fe_add(&m, &s2); /* m = M = S1+S2 (2) */ + t = u1; rustsecp256k1_v0_9_0_fe_add(&t, &u2); /* t = T = U1+U2 (GEJ_X_M+1) */ + m = s1; rustsecp256k1_v0_9_0_fe_add(&m, &s2); /* m = M = S1+S2 (GEJ_Y_M+1) */ rustsecp256k1_v0_9_0_fe_sqr(&rr, &t); /* rr = T^2 (1) */ - rustsecp256k1_v0_9_0_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 */ - rustsecp256k1_v0_9_0_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (2) */ - rustsecp256k1_v0_9_0_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (3) */ + rustsecp256k1_v0_9_0_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 (2) */ + rustsecp256k1_v0_9_0_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (1) */ + rustsecp256k1_v0_9_0_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (2) */ /* If lambda = R/M = R/0 we have a problem (except in the "trivial" * case that Z = z1z2 = 0, and this is special-cased later on). */ degenerate = rustsecp256k1_v0_9_0_fe_normalizes_to_zero(&m); @@ -689,24 +747,25 @@ static void rustsecp256k1_v0_9_0_gej_add_ge(rustsecp256k1_v0_9_0_gej *r, const r * non-indeterminate expression for lambda is (y1 - y2)/(x1 - x2), * so we set R/M equal to this. */ rr_alt = s1; - rustsecp256k1_v0_9_0_fe_mul_int(&rr_alt, 2); /* rr = Y1*Z2^3 - Y2*Z1^3 (2) */ - rustsecp256k1_v0_9_0_fe_add(&m_alt, &u1); /* Malt = X1*Z2^2 - X2*Z1^2 */ + rustsecp256k1_v0_9_0_fe_mul_int(&rr_alt, 2); /* rr_alt = Y1*Z2^3 - Y2*Z1^3 (GEJ_Y_M*2) */ + rustsecp256k1_v0_9_0_fe_add(&m_alt, &u1); /* Malt = X1*Z2^2 - X2*Z1^2 (GEJ_X_M+2) */ - rustsecp256k1_v0_9_0_fe_cmov(&rr_alt, &rr, !degenerate); - rustsecp256k1_v0_9_0_fe_cmov(&m_alt, &m, !degenerate); + rustsecp256k1_v0_9_0_fe_cmov(&rr_alt, &rr, !degenerate); /* rr_alt (GEJ_Y_M*2) */ + rustsecp256k1_v0_9_0_fe_cmov(&m_alt, &m, !degenerate); /* m_alt (GEJ_X_M+2) */ /* Now Ralt / Malt = lambda and is guaranteed not to be Ralt / 0. * From here on out Ralt and Malt represent the numerator * and denominator of lambda; R and M represent the explicit * expressions x1^2 + x2^2 + x1x2 and y1 + y2. */ rustsecp256k1_v0_9_0_fe_sqr(&n, &m_alt); /* n = Malt^2 (1) */ - rustsecp256k1_v0_9_0_fe_negate(&q, &t, 2); /* q = -T (3) */ + rustsecp256k1_v0_9_0_fe_negate(&q, &t, + SECP256K1_GEJ_X_MAGNITUDE_MAX + 1); /* q = -T (GEJ_X_M+2) */ rustsecp256k1_v0_9_0_fe_mul(&q, &q, &n); /* q = Q = -T*Malt^2 (1) */ /* These two lines use the observation that either M == Malt or M == 0, * so M^3 * Malt is either Malt^4 (which is computed by squaring), or * zero (which is "computed" by cmov). So the cost is one squaring * versus two multiplications. */ - rustsecp256k1_v0_9_0_fe_sqr(&n, &n); - rustsecp256k1_v0_9_0_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (2) */ + rustsecp256k1_v0_9_0_fe_sqr(&n, &n); /* n = Malt^4 (1) */ + rustsecp256k1_v0_9_0_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (GEJ_Y_M+1) */ rustsecp256k1_v0_9_0_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */ rustsecp256k1_v0_9_0_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Z3 = Malt*Z (1) */ rustsecp256k1_v0_9_0_fe_add(&t, &q); /* t = Ralt^2 + Q (2) */ @@ -714,9 +773,10 @@ static void rustsecp256k1_v0_9_0_gej_add_ge(rustsecp256k1_v0_9_0_gej *r, const r rustsecp256k1_v0_9_0_fe_mul_int(&t, 2); /* t = 2*X3 (4) */ rustsecp256k1_v0_9_0_fe_add(&t, &q); /* t = 2*X3 + Q (5) */ rustsecp256k1_v0_9_0_fe_mul(&t, &t, &rr_alt); /* t = Ralt*(2*X3 + Q) (1) */ - rustsecp256k1_v0_9_0_fe_add(&t, &n); /* t = Ralt*(2*X3 + Q) + M^3*Malt (3) */ - rustsecp256k1_v0_9_0_fe_negate(&r->y, &t, 3); /* r->y = -(Ralt*(2*X3 + Q) + M^3*Malt) (4) */ - rustsecp256k1_v0_9_0_fe_half(&r->y); /* r->y = Y3 = -(Ralt*(2*X3 + Q) + M^3*Malt)/2 (3) */ + rustsecp256k1_v0_9_0_fe_add(&t, &n); /* t = Ralt*(2*X3 + Q) + M^3*Malt (GEJ_Y_M+2) */ + rustsecp256k1_v0_9_0_fe_negate(&r->y, &t, + SECP256K1_GEJ_Y_MAGNITUDE_MAX + 2); /* r->y = -(Ralt*(2*X3 + Q) + M^3*Malt) (GEJ_Y_M+3) */ + rustsecp256k1_v0_9_0_fe_half(&r->y); /* r->y = Y3 = -(Ralt*(2*X3 + Q) + M^3*Malt)/2 ((GEJ_Y_M+3)/2 + 1) */ /* In case a->infinity == 1, replace r with (b->x, b->y, 1). */ rustsecp256k1_v0_9_0_fe_cmov(&r->x, &b->x, a->infinity); @@ -740,6 +800,7 @@ static void rustsecp256k1_v0_9_0_gej_add_ge(rustsecp256k1_v0_9_0_gej *r, const r * We have degenerate = false, r->z = (y1 + y2) * Z. * Then r->infinity = ((y1 + y2)Z == 0) = (y1 == -y2) = false. */ r->infinity = rustsecp256k1_v0_9_0_fe_normalizes_to_zero(&r->z); + rustsecp256k1_v0_9_0_gej_verify(r); } @@ -751,11 +812,13 @@ static void rustsecp256k1_v0_9_0_gej_rescale(rustsecp256k1_v0_9_0_gej *r, const #ifdef VERIFY VERIFY_CHECK(!rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(s)); #endif + rustsecp256k1_v0_9_0_fe_sqr(&zz, s); rustsecp256k1_v0_9_0_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */ rustsecp256k1_v0_9_0_fe_mul(&r->y, &r->y, &zz); rustsecp256k1_v0_9_0_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */ rustsecp256k1_v0_9_0_fe_mul(&r->z, &r->z, s); /* r->z *= s */ + rustsecp256k1_v0_9_0_gej_verify(r); } @@ -763,6 +826,7 @@ static void rustsecp256k1_v0_9_0_ge_to_storage(rustsecp256k1_v0_9_0_ge_storage * rustsecp256k1_v0_9_0_fe x, y; rustsecp256k1_v0_9_0_ge_verify(a); VERIFY_CHECK(!a->infinity); + x = a->x; rustsecp256k1_v0_9_0_fe_normalize(&x); y = a->y; @@ -775,17 +839,19 @@ static void rustsecp256k1_v0_9_0_ge_from_storage(rustsecp256k1_v0_9_0_ge *r, con rustsecp256k1_v0_9_0_fe_from_storage(&r->x, &a->x); rustsecp256k1_v0_9_0_fe_from_storage(&r->y, &a->y); r->infinity = 0; + rustsecp256k1_v0_9_0_ge_verify(r); } static SECP256K1_INLINE void rustsecp256k1_v0_9_0_gej_cmov(rustsecp256k1_v0_9_0_gej *r, const rustsecp256k1_v0_9_0_gej *a, int flag) { rustsecp256k1_v0_9_0_gej_verify(r); rustsecp256k1_v0_9_0_gej_verify(a); + rustsecp256k1_v0_9_0_fe_cmov(&r->x, &a->x, flag); rustsecp256k1_v0_9_0_fe_cmov(&r->y, &a->y, flag); rustsecp256k1_v0_9_0_fe_cmov(&r->z, &a->z, flag); - r->infinity ^= (r->infinity ^ a->infinity) & flag; + rustsecp256k1_v0_9_0_gej_verify(r); } @@ -795,9 +861,11 @@ static SECP256K1_INLINE void rustsecp256k1_v0_9_0_ge_storage_cmov(rustsecp256k1_ } static void rustsecp256k1_v0_9_0_ge_mul_lambda(rustsecp256k1_v0_9_0_ge *r, const rustsecp256k1_v0_9_0_ge *a) { - *r = *a; rustsecp256k1_v0_9_0_ge_verify(a); + + *r = *a; rustsecp256k1_v0_9_0_fe_mul(&r->x, &r->x, &rustsecp256k1_v0_9_0_const_beta); + rustsecp256k1_v0_9_0_ge_verify(r); } @@ -805,8 +873,8 @@ static int rustsecp256k1_v0_9_0_ge_is_in_correct_subgroup(const rustsecp256k1_v0 #ifdef EXHAUSTIVE_TEST_ORDER rustsecp256k1_v0_9_0_gej out; int i; - rustsecp256k1_v0_9_0_ge_verify(ge); + /* A very simple EC multiplication ladder that avoids a dependency on ecmult. */ rustsecp256k1_v0_9_0_gej_set_infinity(&out); for (i = 0; i < 32; ++i) { @@ -817,10 +885,40 @@ static int rustsecp256k1_v0_9_0_ge_is_in_correct_subgroup(const rustsecp256k1_v0 } return rustsecp256k1_v0_9_0_gej_is_infinity(&out); #else + rustsecp256k1_v0_9_0_ge_verify(ge); + (void)ge; /* The real secp256k1 group has cofactor 1, so the subgroup is the entire curve. */ return 1; #endif } +static int rustsecp256k1_v0_9_0_ge_x_on_curve_var(const rustsecp256k1_v0_9_0_fe *x) { + rustsecp256k1_v0_9_0_fe c; + rustsecp256k1_v0_9_0_fe_sqr(&c, x); + rustsecp256k1_v0_9_0_fe_mul(&c, &c, x); + rustsecp256k1_v0_9_0_fe_add_int(&c, SECP256K1_B); + return rustsecp256k1_v0_9_0_fe_is_square_var(&c); +} + +static int rustsecp256k1_v0_9_0_ge_x_frac_on_curve_var(const rustsecp256k1_v0_9_0_fe *xn, const rustsecp256k1_v0_9_0_fe *xd) { + /* We want to determine whether (xn/xd) is on the curve. + * + * (xn/xd)^3 + 7 is square <=> xd*xn^3 + 7*xd^4 is square (multiplying by xd^4, a square). + */ + rustsecp256k1_v0_9_0_fe r, t; +#ifdef VERIFY + VERIFY_CHECK(!rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(xd)); +#endif + rustsecp256k1_v0_9_0_fe_mul(&r, xd, xn); /* r = xd*xn */ + rustsecp256k1_v0_9_0_fe_sqr(&t, xn); /* t = xn^2 */ + rustsecp256k1_v0_9_0_fe_mul(&r, &r, &t); /* r = xd*xn^3 */ + rustsecp256k1_v0_9_0_fe_sqr(&t, xd); /* t = xd^2 */ + rustsecp256k1_v0_9_0_fe_sqr(&t, &t); /* t = xd^4 */ + VERIFY_CHECK(SECP256K1_B <= 31); + rustsecp256k1_v0_9_0_fe_mul_int(&t, SECP256K1_B); /* t = 7*xd^4 */ + rustsecp256k1_v0_9_0_fe_add(&r, &t); /* r = xd*xn^3 + 7*xd^4 */ + return rustsecp256k1_v0_9_0_fe_is_square_var(&r); +} + #endif /* SECP256K1_GROUP_IMPL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/hash_impl.h b/secp256k1-sys/depend/secp256k1/src/hash_impl.h index 1e064f226..c45adef6b 100644 --- a/secp256k1-sys/depend/secp256k1/src/hash_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/hash_impl.h @@ -138,7 +138,7 @@ static void rustsecp256k1_v0_9_0_sha256_write(rustsecp256k1_v0_9_0_sha256 *hash, } if (len) { /* Fill the buffer with what remains. */ - memcpy(((unsigned char*)hash->buf) + bufsize, data, len); + memcpy(hash->buf + bufsize, data, len); } } diff --git a/secp256k1-sys/depend/secp256k1/src/int128_struct_impl.h b/secp256k1-sys/depend/secp256k1/src/int128_struct_impl.h index a37452881..644ccb6bf 100644 --- a/secp256k1-sys/depend/secp256k1/src/int128_struct_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/int128_struct_impl.h @@ -80,7 +80,12 @@ static SECP256K1_INLINE void rustsecp256k1_v0_9_0_u128_rshift(rustsecp256k1_v0_9 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; } } diff --git a/secp256k1-sys/depend/secp256k1/src/modules/ellswift/Makefile.am.include b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/Makefile.am.include new file mode 100644 index 000000000..4e0045e33 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/Makefile.am.include @@ -0,0 +1,5 @@ +include_HEADERS += include/rustsecp256k1_v0_9_0_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 diff --git a/secp256k1-sys/depend/secp256k1/src/modules/ellswift/bench_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/bench_impl.h new file mode 100644 index 000000000..e9ec83e5b --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/bench_impl.h @@ -0,0 +1,106 @@ +/*********************************************************************** + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_MODULE_ELLSWIFT_BENCH_H +#define SECP256K1_MODULE_ELLSWIFT_BENCH_H + +#include "../../../include/secp256k1_ellswift.h" + +typedef struct { + rustsecp256k1_v0_9_0_context *ctx; + rustsecp256k1_v0_9_0_pubkey point[256]; + unsigned char rnd64[64]; +} bench_ellswift_data; + +static void bench_ellswift_setup(void *arg) { + int i; + bench_ellswift_data *data = (bench_ellswift_data*)arg; + static const unsigned char init[64] = { + 0x78, 0x1f, 0xb7, 0xd4, 0x67, 0x7f, 0x08, 0x68, + 0xdb, 0xe3, 0x1d, 0x7f, 0x1b, 0xb0, 0xf6, 0x9e, + 0x0a, 0x64, 0xca, 0x32, 0x9e, 0xc6, 0x20, 0x79, + 0x03, 0xf3, 0xd0, 0x46, 0x7a, 0x0f, 0xd2, 0x21, + 0xb0, 0x2c, 0x46, 0xd8, 0xba, 0xca, 0x26, 0x4f, + 0x8f, 0x8c, 0xd4, 0xdd, 0x2d, 0x04, 0xbe, 0x30, + 0x48, 0x51, 0x1e, 0xd4, 0x16, 0xfd, 0x42, 0x85, + 0x62, 0xc9, 0x02, 0xf9, 0x89, 0x84, 0xff, 0xdc + }; + memcpy(data->rnd64, init, 64); + for (i = 0; i < 256; ++i) { + int j; + CHECK(rustsecp256k1_v0_9_0_ellswift_decode(data->ctx, &data->point[i], data->rnd64)); + for (j = 0; j < 64; ++j) { + data->rnd64[j] += 1; + } + } + CHECK(rustsecp256k1_v0_9_0_ellswift_encode(data->ctx, data->rnd64, &data->point[255], init + 16)); +} + +static void bench_ellswift_encode(void *arg, int iters) { + int i; + bench_ellswift_data *data = (bench_ellswift_data*)arg; + + for (i = 0; i < iters; i++) { + CHECK(rustsecp256k1_v0_9_0_ellswift_encode(data->ctx, data->rnd64, &data->point[i & 255], data->rnd64 + 16)); + } +} + +static void bench_ellswift_create(void *arg, int iters) { + int i; + bench_ellswift_data *data = (bench_ellswift_data*)arg; + + for (i = 0; i < iters; i++) { + unsigned char buf[64]; + CHECK(rustsecp256k1_v0_9_0_ellswift_create(data->ctx, buf, data->rnd64, data->rnd64 + 32)); + memcpy(data->rnd64, buf, 64); + } +} + +static void bench_ellswift_decode(void *arg, int iters) { + int i; + rustsecp256k1_v0_9_0_pubkey out; + size_t len; + bench_ellswift_data *data = (bench_ellswift_data*)arg; + + for (i = 0; i < iters; i++) { + CHECK(rustsecp256k1_v0_9_0_ellswift_decode(data->ctx, &out, data->rnd64) == 1); + len = 33; + CHECK(rustsecp256k1_v0_9_0_ec_pubkey_serialize(data->ctx, data->rnd64 + (i % 32), &len, &out, SECP256K1_EC_COMPRESSED)); + } +} + +static void bench_ellswift_xdh(void *arg, int iters) { + int i; + bench_ellswift_data *data = (bench_ellswift_data*)arg; + + for (i = 0; i < iters; i++) { + int party = i & 1; + CHECK(rustsecp256k1_v0_9_0_ellswift_xdh(data->ctx, + data->rnd64 + (i % 33), + data->rnd64, + data->rnd64, + data->rnd64 + ((i + 16) % 33), + party, + rustsecp256k1_v0_9_0_ellswift_xdh_hash_function_bip324, + NULL) == 1); + } +} + +void run_ellswift_bench(int iters, int argc, char **argv) { + bench_ellswift_data data; + int d = argc == 1; + + /* create a context with signing capabilities */ + data.ctx = rustsecp256k1_v0_9_0_context_create(SECP256K1_CONTEXT_NONE); + + if (d || have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "encode") || have_flag(argc, argv, "ellswift_encode")) run_benchmark("ellswift_encode", bench_ellswift_encode, bench_ellswift_setup, NULL, &data, 10, iters); + if (d || have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "decode") || have_flag(argc, argv, "ellswift_decode")) run_benchmark("ellswift_decode", bench_ellswift_decode, bench_ellswift_setup, NULL, &data, 10, iters); + if (d || have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "keygen") || have_flag(argc, argv, "ellswift_keygen")) run_benchmark("ellswift_keygen", bench_ellswift_create, bench_ellswift_setup, NULL, &data, 10, iters); + if (d || have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "ecdh") || have_flag(argc, argv, "ellswift_ecdh")) run_benchmark("ellswift_ecdh", bench_ellswift_xdh, bench_ellswift_setup, NULL, &data, 10, iters); + + rustsecp256k1_v0_9_0_context_destroy(data.ctx); +} + +#endif diff --git a/secp256k1-sys/depend/secp256k1/src/modules/ellswift/main_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/main_impl.h new file mode 100644 index 000000000..4205d20fe --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/main_impl.h @@ -0,0 +1,589 @@ +/*********************************************************************** + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_MODULE_ELLSWIFT_MAIN_H +#define SECP256K1_MODULE_ELLSWIFT_MAIN_H + +#include "../../../include/secp256k1.h" +#include "../../../include/secp256k1_ellswift.h" +#include "../../eckey.h" +#include "../../hash.h" + +/** c1 = (sqrt(-3)-1)/2 */ +static const rustsecp256k1_v0_9_0_fe rustsecp256k1_v0_9_0_ellswift_c1 = SECP256K1_FE_CONST(0x851695d4, 0x9a83f8ef, 0x919bb861, 0x53cbcb16, 0x630fb68a, 0xed0a766a, 0x3ec693d6, 0x8e6afa40); +/** c2 = (-sqrt(-3)-1)/2 = -(c1+1) */ +static const rustsecp256k1_v0_9_0_fe rustsecp256k1_v0_9_0_ellswift_c2 = SECP256K1_FE_CONST(0x7ae96a2b, 0x657c0710, 0x6e64479e, 0xac3434e9, 0x9cf04975, 0x12f58995, 0xc1396c28, 0x719501ee); +/** c3 = (-sqrt(-3)+1)/2 = -c1 = c2+1 */ +static const rustsecp256k1_v0_9_0_fe rustsecp256k1_v0_9_0_ellswift_c3 = SECP256K1_FE_CONST(0x7ae96a2b, 0x657c0710, 0x6e64479e, 0xac3434e9, 0x9cf04975, 0x12f58995, 0xc1396c28, 0x719501ef); +/** c4 = (sqrt(-3)+1)/2 = -c2 = c1+1 */ +static const rustsecp256k1_v0_9_0_fe rustsecp256k1_v0_9_0_ellswift_c4 = SECP256K1_FE_CONST(0x851695d4, 0x9a83f8ef, 0x919bb861, 0x53cbcb16, 0x630fb68a, 0xed0a766a, 0x3ec693d6, 0x8e6afa41); + +/** Decode ElligatorSwift encoding (u, t) to a fraction xn/xd representing a curve X coordinate. */ +static void rustsecp256k1_v0_9_0_ellswift_xswiftec_frac_var(rustsecp256k1_v0_9_0_fe *xn, rustsecp256k1_v0_9_0_fe *xd, const rustsecp256k1_v0_9_0_fe *u, const rustsecp256k1_v0_9_0_fe *t) { + /* The implemented algorithm is the following (all operations in GF(p)): + * + * - Let c0 = sqrt(-3) = 0xa2d2ba93507f1df233770c2a797962cc61f6d15da14ecd47d8d27ae1cd5f852. + * - If u = 0, set u = 1. + * - If t = 0, set t = 1. + * - If u^3+7+t^2 = 0, set t = 2*t. + * - Let X = (u^3+7-t^2)/(2*t). + * - Let Y = (X+t)/(c0*u). + * - If x3 = u+4*Y^2 is a valid x coordinate, return it. + * - If x2 = (-X/Y-u)/2 is a valid x coordinate, return it. + * - Return x1 = (X/Y-u)/2 (which is now guaranteed to be a valid x coordinate). + * + * Introducing s=t^2, g=u^3+7, and simplifying x1=-(x2+u) we get: + * + * - Let c0 = ... + * - If u = 0, set u = 1. + * - If t = 0, set t = 1. + * - Let s = t^2 + * - Let g = u^3+7 + * - If g+s = 0, set t = 2*t, s = 4*s + * - Let X = (g-s)/(2*t). + * - Let Y = (X+t)/(c0*u) = (g+s)/(2*c0*t*u). + * - If x3 = u+4*Y^2 is a valid x coordinate, return it. + * - If x2 = (-X/Y-u)/2 is a valid x coordinate, return it. + * - Return x1 = -(x2+u). + * + * Now substitute Y^2 = -(g+s)^2/(12*s*u^2) and X/Y = c0*u*(g-s)/(g+s). This + * means X and Y do not need to be evaluated explicitly anymore. + * + * - ... + * - If g+s = 0, set s = 4*s. + * - If x3 = u-(g+s)^2/(3*s*u^2) is a valid x coordinate, return it. + * - If x2 = (-c0*u*(g-s)/(g+s)-u)/2 is a valid x coordinate, return it. + * - Return x1 = -(x2+u). + * + * Simplifying x2 using 2 additional constants: + * + * - Let c1 = (c0-1)/2 = 0x851695d49a83f8ef919bb86153cbcb16630fb68aed0a766a3ec693d68e6afa40. + * - Let c2 = (-c0-1)/2 = 0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee. + * - ... + * - If x2 = u*(c1*s+c2*g)/(g+s) is a valid x coordinate, return it. + * - ... + * + * Writing x3 as a fraction: + * + * - ... + * - If x3 = (3*s*u^3-(g+s)^2)/(3*s*u^2) ... + * - ... + + * Overall, we get: + * + * - Let c1 = 0x851695d49a83f8ef919bb86153cbcb16630fb68aed0a766a3ec693d68e6afa40. + * - Let c2 = 0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee. + * - If u = 0, set u = 1. + * - If t = 0, set s = 1, else set s = t^2. + * - Let g = u^3+7. + * - If g+s = 0, set s = 4*s. + * - If x3 = (3*s*u^3-(g+s)^2)/(3*s*u^2) is a valid x coordinate, return it. + * - If x2 = u*(c1*s+c2*g)/(g+s) is a valid x coordinate, return it. + * - Return x1 = -(x2+u). + */ + rustsecp256k1_v0_9_0_fe u1, s, g, p, d, n, l; + u1 = *u; + if (EXPECT(rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(&u1), 0)) u1 = rustsecp256k1_v0_9_0_fe_one; + rustsecp256k1_v0_9_0_fe_sqr(&s, t); + if (EXPECT(rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(t), 0)) s = rustsecp256k1_v0_9_0_fe_one; + rustsecp256k1_v0_9_0_fe_sqr(&l, &u1); /* l = u^2 */ + rustsecp256k1_v0_9_0_fe_mul(&g, &l, &u1); /* g = u^3 */ + rustsecp256k1_v0_9_0_fe_add_int(&g, SECP256K1_B); /* g = u^3 + 7 */ + p = g; /* p = g */ + rustsecp256k1_v0_9_0_fe_add(&p, &s); /* p = g+s */ + if (EXPECT(rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(&p), 0)) { + rustsecp256k1_v0_9_0_fe_mul_int(&s, 4); + /* Recompute p = g+s */ + p = g; /* p = g */ + rustsecp256k1_v0_9_0_fe_add(&p, &s); /* p = g+s */ + } + rustsecp256k1_v0_9_0_fe_mul(&d, &s, &l); /* d = s*u^2 */ + rustsecp256k1_v0_9_0_fe_mul_int(&d, 3); /* d = 3*s*u^2 */ + rustsecp256k1_v0_9_0_fe_sqr(&l, &p); /* l = (g+s)^2 */ + rustsecp256k1_v0_9_0_fe_negate(&l, &l, 1); /* l = -(g+s)^2 */ + rustsecp256k1_v0_9_0_fe_mul(&n, &d, &u1); /* n = 3*s*u^3 */ + rustsecp256k1_v0_9_0_fe_add(&n, &l); /* n = 3*s*u^3-(g+s)^2 */ + if (rustsecp256k1_v0_9_0_ge_x_frac_on_curve_var(&n, &d)) { + /* Return x3 = n/d = (3*s*u^3-(g+s)^2)/(3*s*u^2) */ + *xn = n; + *xd = d; + return; + } + *xd = p; + rustsecp256k1_v0_9_0_fe_mul(&l, &rustsecp256k1_v0_9_0_ellswift_c1, &s); /* l = c1*s */ + rustsecp256k1_v0_9_0_fe_mul(&n, &rustsecp256k1_v0_9_0_ellswift_c2, &g); /* n = c2*g */ + rustsecp256k1_v0_9_0_fe_add(&n, &l); /* n = c1*s+c2*g */ + rustsecp256k1_v0_9_0_fe_mul(&n, &n, &u1); /* n = u*(c1*s+c2*g) */ + /* Possible optimization: in the invocation below, p^2 = (g+s)^2 is computed, + * which we already have computed above. This could be deduplicated. */ + if (rustsecp256k1_v0_9_0_ge_x_frac_on_curve_var(&n, &p)) { + /* Return x2 = n/p = u*(c1*s+c2*g)/(g+s) */ + *xn = n; + return; + } + rustsecp256k1_v0_9_0_fe_mul(&l, &p, &u1); /* l = u*(g+s) */ + rustsecp256k1_v0_9_0_fe_add(&n, &l); /* n = u*(c1*s+c2*g)+u*(g+s) */ + rustsecp256k1_v0_9_0_fe_negate(xn, &n, 2); /* n = -u*(c1*s+c2*g)-u*(g+s) */ +#ifdef VERIFY + VERIFY_CHECK(rustsecp256k1_v0_9_0_ge_x_frac_on_curve_var(xn, &p)); +#endif + /* Return x3 = n/p = -(u*(c1*s+c2*g)/(g+s)+u) */ +} + +/** Decode ElligatorSwift encoding (u, t) to X coordinate. */ +static void rustsecp256k1_v0_9_0_ellswift_xswiftec_var(rustsecp256k1_v0_9_0_fe *x, const rustsecp256k1_v0_9_0_fe *u, const rustsecp256k1_v0_9_0_fe *t) { + rustsecp256k1_v0_9_0_fe xn, xd; + rustsecp256k1_v0_9_0_ellswift_xswiftec_frac_var(&xn, &xd, u, t); + rustsecp256k1_v0_9_0_fe_inv_var(&xd, &xd); + rustsecp256k1_v0_9_0_fe_mul(x, &xn, &xd); +} + +/** Decode ElligatorSwift encoding (u, t) to point P. */ +static void rustsecp256k1_v0_9_0_ellswift_swiftec_var(rustsecp256k1_v0_9_0_ge *p, const rustsecp256k1_v0_9_0_fe *u, const rustsecp256k1_v0_9_0_fe *t) { + rustsecp256k1_v0_9_0_fe x; + rustsecp256k1_v0_9_0_ellswift_xswiftec_var(&x, u, t); + rustsecp256k1_v0_9_0_ge_set_xo_var(p, &x, rustsecp256k1_v0_9_0_fe_is_odd(t)); +} + +/* Try to complete an ElligatorSwift encoding (u, t) for X coordinate x, given u and x. + * + * There may be up to 8 distinct t values such that (u, t) decodes back to x, but also + * fewer, or none at all. Each such partial inverse can be accessed individually using a + * distinct input argument c (in range 0-7), and some or all of these may return failure. + * The following guarantees exist: + * - Given (x, u), no two distinct c values give the same successful result t. + * - Every successful result maps back to x through rustsecp256k1_v0_9_0_ellswift_xswiftec_var. + * - Given (x, u), all t values that map back to x can be reached by combining the + * successful results from this function over all c values, with the exception of: + * - this function cannot be called with u=0 + * - no result with t=0 will be returned + * - no result for which u^3 + t^2 + 7 = 0 will be returned. + * + * The rather unusual encoding of bits in c (a large "if" based on the middle bit, and then + * using the low and high bits to pick signs of square roots) is to match the paper's + * encoding more closely: c=0 through c=3 match branches 1..4 in the paper, while c=4 through + * c=7 are copies of those with an additional negation of sqrt(w). + */ +static int rustsecp256k1_v0_9_0_ellswift_xswiftec_inv_var(rustsecp256k1_v0_9_0_fe *t, const rustsecp256k1_v0_9_0_fe *x_in, const rustsecp256k1_v0_9_0_fe *u_in, int c) { + /* The implemented algorithm is this (all arithmetic, except involving c, is mod p): + * + * - If (c & 2) = 0: + * - If (-x-u) is a valid X coordinate, fail. + * - Let s=-(u^3+7)/(u^2+u*x+x^2). + * - If s is not square, fail. + * - Let v=x. + * - If (c & 2) = 2: + * - Let s=x-u. + * - If s is not square, fail. + * - Let r=sqrt(-s*(4*(u^3+7)+3*u^2*s)); fail if it doesn't exist. + * - If (c & 1) = 1 and r = 0, fail. + * - If s=0, fail. + * - Let v=(r/s-u)/2. + * - Let w=sqrt(s). + * - If (c & 5) = 0: return -w*(c3*u + v). + * - If (c & 5) = 1: return w*(c4*u + v). + * - If (c & 5) = 4: return w*(c3*u + v). + * - If (c & 5) = 5: return -w*(c4*u + v). + */ + rustsecp256k1_v0_9_0_fe x = *x_in, u = *u_in, g, v, s, m, r, q; + int ret; + + rustsecp256k1_v0_9_0_fe_normalize_weak(&x); + rustsecp256k1_v0_9_0_fe_normalize_weak(&u); + +#ifdef VERIFY + VERIFY_CHECK(c >= 0 && c < 8); + VERIFY_CHECK(rustsecp256k1_v0_9_0_ge_x_on_curve_var(&x)); +#endif + + if (!(c & 2)) { + /* c is in {0, 1, 4, 5}. In this case we look for an inverse under the x1 (if c=0 or + * c=4) formula, or x2 (if c=1 or c=5) formula. */ + + /* If -u-x is a valid X coordinate, fail. This would yield an encoding that roundtrips + * back under the x3 formula instead (which has priority over x1 and x2, so the decoding + * would not match x). */ + m = x; /* m = x */ + rustsecp256k1_v0_9_0_fe_add(&m, &u); /* m = u+x */ + rustsecp256k1_v0_9_0_fe_negate(&m, &m, 2); /* m = -u-x */ + /* Test if (-u-x) is a valid X coordinate. If so, fail. */ + if (rustsecp256k1_v0_9_0_ge_x_on_curve_var(&m)) return 0; + + /* Let s = -(u^3 + 7)/(u^2 + u*x + x^2) [first part] */ + rustsecp256k1_v0_9_0_fe_sqr(&s, &m); /* s = (u+x)^2 */ + rustsecp256k1_v0_9_0_fe_negate(&s, &s, 1); /* s = -(u+x)^2 */ + rustsecp256k1_v0_9_0_fe_mul(&m, &u, &x); /* m = u*x */ + rustsecp256k1_v0_9_0_fe_add(&s, &m); /* s = -(u^2 + u*x + x^2) */ + + /* Note that at this point, s = 0 is impossible. If it were the case: + * s = -(u^2 + u*x + x^2) = 0 + * => u^2 + u*x + x^2 = 0 + * => (u + 2*x) * (u^2 + u*x + x^2) = 0 + * => 2*x^3 + 3*x^2*u + 3*x*u^2 + u^3 = 0 + * => (x + u)^3 + x^3 = 0 + * => x^3 = -(x + u)^3 + * => x^3 + B = (-u - x)^3 + B + * + * However, we know x^3 + B is square (because x is on the curve) and + * that (-u-x)^3 + B is not square (the rustsecp256k1_v0_9_0_ge_x_on_curve_var(&m) + * test above would have failed). This is a contradiction, and thus the + * assumption s=0 is false. */ +#ifdef VERIFY + VERIFY_CHECK(!rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(&s)); +#endif + + /* If s is not square, fail. We have not fully computed s yet, but s is square iff + * -(u^3+7)*(u^2+u*x+x^2) is square (because a/b is square iff a*b is square and b is + * nonzero). */ + rustsecp256k1_v0_9_0_fe_sqr(&g, &u); /* g = u^2 */ + rustsecp256k1_v0_9_0_fe_mul(&g, &g, &u); /* g = u^3 */ + rustsecp256k1_v0_9_0_fe_add_int(&g, SECP256K1_B); /* g = u^3+7 */ + rustsecp256k1_v0_9_0_fe_mul(&m, &s, &g); /* m = -(u^3 + 7)*(u^2 + u*x + x^2) */ + if (!rustsecp256k1_v0_9_0_fe_is_square_var(&m)) return 0; + + /* Let s = -(u^3 + 7)/(u^2 + u*x + x^2) [second part] */ + rustsecp256k1_v0_9_0_fe_inv_var(&s, &s); /* s = -1/(u^2 + u*x + x^2) [no div by 0] */ + rustsecp256k1_v0_9_0_fe_mul(&s, &s, &g); /* s = -(u^3 + 7)/(u^2 + u*x + x^2) */ + + /* Let v = x. */ + v = x; + } else { + /* c is in {2, 3, 6, 7}. In this case we look for an inverse under the x3 formula. */ + + /* Let s = x-u. */ + rustsecp256k1_v0_9_0_fe_negate(&m, &u, 1); /* m = -u */ + s = m; /* s = -u */ + rustsecp256k1_v0_9_0_fe_add(&s, &x); /* s = x-u */ + + /* If s is not square, fail. */ + if (!rustsecp256k1_v0_9_0_fe_is_square_var(&s)) return 0; + + /* Let r = sqrt(-s*(4*(u^3+7)+3*u^2*s)); fail if it doesn't exist. */ + rustsecp256k1_v0_9_0_fe_sqr(&g, &u); /* g = u^2 */ + rustsecp256k1_v0_9_0_fe_mul(&q, &s, &g); /* q = s*u^2 */ + rustsecp256k1_v0_9_0_fe_mul_int(&q, 3); /* q = 3*s*u^2 */ + rustsecp256k1_v0_9_0_fe_mul(&g, &g, &u); /* g = u^3 */ + rustsecp256k1_v0_9_0_fe_mul_int(&g, 4); /* g = 4*u^3 */ + rustsecp256k1_v0_9_0_fe_add_int(&g, 4 * SECP256K1_B); /* g = 4*(u^3+7) */ + rustsecp256k1_v0_9_0_fe_add(&q, &g); /* q = 4*(u^3+7)+3*s*u^2 */ + rustsecp256k1_v0_9_0_fe_mul(&q, &q, &s); /* q = s*(4*(u^3+7)+3*u^2*s) */ + rustsecp256k1_v0_9_0_fe_negate(&q, &q, 1); /* q = -s*(4*(u^3+7)+3*u^2*s) */ + if (!rustsecp256k1_v0_9_0_fe_is_square_var(&q)) return 0; + ret = rustsecp256k1_v0_9_0_fe_sqrt(&r, &q); /* r = sqrt(-s*(4*(u^3+7)+3*u^2*s)) */ + VERIFY_CHECK(ret); + + /* If (c & 1) = 1 and r = 0, fail. */ + if (EXPECT((c & 1) && rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(&r), 0)) return 0; + + /* If s = 0, fail. */ + if (EXPECT(rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(&s), 0)) return 0; + + /* Let v = (r/s-u)/2. */ + rustsecp256k1_v0_9_0_fe_inv_var(&v, &s); /* v = 1/s [no div by 0] */ + rustsecp256k1_v0_9_0_fe_mul(&v, &v, &r); /* v = r/s */ + rustsecp256k1_v0_9_0_fe_add(&v, &m); /* v = r/s-u */ + rustsecp256k1_v0_9_0_fe_half(&v); /* v = (r/s-u)/2 */ + } + + /* Let w = sqrt(s). */ + ret = rustsecp256k1_v0_9_0_fe_sqrt(&m, &s); /* m = sqrt(s) = w */ + VERIFY_CHECK(ret); + + /* Return logic. */ + if ((c & 5) == 0 || (c & 5) == 5) { + rustsecp256k1_v0_9_0_fe_negate(&m, &m, 1); /* m = -w */ + } + /* Now m = {-w if c&5=0 or c&5=5; w otherwise}. */ + rustsecp256k1_v0_9_0_fe_mul(&u, &u, c&1 ? &rustsecp256k1_v0_9_0_ellswift_c4 : &rustsecp256k1_v0_9_0_ellswift_c3); + /* u = {c4 if c&1=1; c3 otherwise}*u */ + rustsecp256k1_v0_9_0_fe_add(&u, &v); /* u = {c4 if c&1=1; c3 otherwise}*u + v */ + rustsecp256k1_v0_9_0_fe_mul(t, &m, &u); + return 1; +} + +/** Use SHA256 as a PRNG, returning SHA256(hasher || cnt). + * + * hasher is a SHA256 object to which an incrementing 4-byte counter is written to generate randomness. + * Writing 13 bytes (4 bytes for counter, plus 9 bytes for the SHA256 padding) cannot cross a + * 64-byte block size boundary (to make sure it only triggers a single SHA256 compression). */ +static void rustsecp256k1_v0_9_0_ellswift_prng(unsigned char* out32, const rustsecp256k1_v0_9_0_sha256 *hasher, uint32_t cnt) { + rustsecp256k1_v0_9_0_sha256 hash = *hasher; + unsigned char buf4[4]; +#ifdef VERIFY + size_t blocks = hash.bytes >> 6; +#endif + buf4[0] = cnt; + buf4[1] = cnt >> 8; + buf4[2] = cnt >> 16; + buf4[3] = cnt >> 24; + rustsecp256k1_v0_9_0_sha256_write(&hash, buf4, 4); + rustsecp256k1_v0_9_0_sha256_finalize(&hash, out32); +#ifdef VERIFY + /* Writing and finalizing together should trigger exactly one SHA256 compression. */ + VERIFY_CHECK(((hash.bytes) >> 6) == (blocks + 1)); +#endif +} + +/** Find an ElligatorSwift encoding (u, t) for X coordinate x, and random Y coordinate. + * + * u32 is the 32-byte big endian encoding of u; t is the output field element t that still + * needs encoding. + * + * hasher is a hasher in the rustsecp256k1_v0_9_0_ellswift_prng sense, with the same restrictions. */ +static void rustsecp256k1_v0_9_0_ellswift_xelligatorswift_var(unsigned char *u32, rustsecp256k1_v0_9_0_fe *t, const rustsecp256k1_v0_9_0_fe *x, const rustsecp256k1_v0_9_0_sha256 *hasher) { + /* Pool of 3-bit branch values. */ + unsigned char branch_hash[32]; + /* Number of 3-bit values in branch_hash left. */ + int branches_left = 0; + /* Field elements u and branch values are extracted from RNG based on hasher for consecutive + * values of cnt. cnt==0 is first used to populate a pool of 64 4-bit branch values. The 64 + * cnt values that follow are used to generate field elements u. cnt==65 (and multiples + * thereof) are used to repopulate the pool and start over, if that were ever necessary. + * On average, 4 iterations are needed. */ + uint32_t cnt = 0; + while (1) { + int branch; + rustsecp256k1_v0_9_0_fe u; + /* If the pool of branch values is empty, populate it. */ + if (branches_left == 0) { + rustsecp256k1_v0_9_0_ellswift_prng(branch_hash, hasher, cnt++); + branches_left = 64; + } + /* Take a 3-bit branch value from the branch pool (top bit is discarded). */ + --branches_left; + branch = (branch_hash[branches_left >> 1] >> ((branches_left & 1) << 2)) & 7; + /* Compute a new u value by hashing. */ + rustsecp256k1_v0_9_0_ellswift_prng(u32, hasher, cnt++); + /* overflow is not a problem (we prefer uniform u32 over uniform u). */ + rustsecp256k1_v0_9_0_fe_set_b32_mod(&u, u32); + /* Since u is the output of a hash, it should practically never be 0. We could apply the + * u=0 to u=1 correction here too to deal with that case still, but it's such a low + * probability event that we do not bother. */ +#ifdef VERIFY + VERIFY_CHECK(!rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(&u)); +#endif + /* Find a remainder t, and return it if found. */ + if (EXPECT(rustsecp256k1_v0_9_0_ellswift_xswiftec_inv_var(t, x, &u, branch), 0)) break; + } +} + +/** Find an ElligatorSwift encoding (u, t) for point P. + * + * This is similar rustsecp256k1_v0_9_0_ellswift_xelligatorswift_var, except it takes a full group element p + * as input, and returns an encoding that matches the provided Y coordinate rather than a random + * one. + */ +static void rustsecp256k1_v0_9_0_ellswift_elligatorswift_var(unsigned char *u32, rustsecp256k1_v0_9_0_fe *t, const rustsecp256k1_v0_9_0_ge *p, const rustsecp256k1_v0_9_0_sha256 *hasher) { + rustsecp256k1_v0_9_0_ellswift_xelligatorswift_var(u32, t, &p->x, hasher); + rustsecp256k1_v0_9_0_fe_normalize_var(t); + if (rustsecp256k1_v0_9_0_fe_is_odd(t) != rustsecp256k1_v0_9_0_fe_is_odd(&p->y)) { + rustsecp256k1_v0_9_0_fe_negate(t, t, 1); + rustsecp256k1_v0_9_0_fe_normalize_var(t); + } +} + +/** Set hash state to the BIP340 tagged hash midstate for "rustsecp256k1_v0_9_0_ellswift_encode". */ +static void rustsecp256k1_v0_9_0_ellswift_sha256_init_encode(rustsecp256k1_v0_9_0_sha256* hash) { + rustsecp256k1_v0_9_0_sha256_initialize(hash); + hash->s[0] = 0xd1a6524bul; + hash->s[1] = 0x028594b3ul; + hash->s[2] = 0x96e42f4eul; + hash->s[3] = 0x1037a177ul; + hash->s[4] = 0x1b8fcb8bul; + hash->s[5] = 0x56023885ul; + hash->s[6] = 0x2560ede1ul; + hash->s[7] = 0xd626b715ul; + + hash->bytes = 64; +} + +int rustsecp256k1_v0_9_0_ellswift_encode(const rustsecp256k1_v0_9_0_context *ctx, unsigned char *ell64, const rustsecp256k1_v0_9_0_pubkey *pubkey, const unsigned char *rnd32) { + rustsecp256k1_v0_9_0_ge p; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(ell64 != NULL); + ARG_CHECK(pubkey != NULL); + ARG_CHECK(rnd32 != NULL); + + if (rustsecp256k1_v0_9_0_pubkey_load(ctx, &p, pubkey)) { + rustsecp256k1_v0_9_0_fe t; + unsigned char p64[64] = {0}; + size_t ser_size; + int ser_ret; + rustsecp256k1_v0_9_0_sha256 hash; + + /* Set up hasher state; the used RNG is H(pubkey || "\x00"*31 || rnd32 || cnt++), using + * BIP340 tagged hash with tag "rustsecp256k1_v0_9_0_ellswift_encode". */ + rustsecp256k1_v0_9_0_ellswift_sha256_init_encode(&hash); + ser_ret = rustsecp256k1_v0_9_0_eckey_pubkey_serialize(&p, p64, &ser_size, 1); + VERIFY_CHECK(ser_ret && ser_size == 33); + rustsecp256k1_v0_9_0_sha256_write(&hash, p64, sizeof(p64)); + rustsecp256k1_v0_9_0_sha256_write(&hash, rnd32, 32); + + /* Compute ElligatorSwift encoding and construct output. */ + rustsecp256k1_v0_9_0_ellswift_elligatorswift_var(ell64, &t, &p, &hash); /* puts u in ell64[0..32] */ + rustsecp256k1_v0_9_0_fe_get_b32(ell64 + 32, &t); /* puts t in ell64[32..64] */ + return 1; + } + /* Only reached in case the provided pubkey is invalid. */ + memset(ell64, 0, 64); + return 0; +} + +/** Set hash state to the BIP340 tagged hash midstate for "rustsecp256k1_v0_9_0_ellswift_create". */ +static void rustsecp256k1_v0_9_0_ellswift_sha256_init_create(rustsecp256k1_v0_9_0_sha256* hash) { + rustsecp256k1_v0_9_0_sha256_initialize(hash); + hash->s[0] = 0xd29e1bf5ul; + hash->s[1] = 0xf7025f42ul; + hash->s[2] = 0x9b024773ul; + hash->s[3] = 0x094cb7d5ul; + hash->s[4] = 0xe59ed789ul; + hash->s[5] = 0x03bc9786ul; + hash->s[6] = 0x68335b35ul; + hash->s[7] = 0x4e363b53ul; + + hash->bytes = 64; +} + +int rustsecp256k1_v0_9_0_ellswift_create(const rustsecp256k1_v0_9_0_context *ctx, unsigned char *ell64, const unsigned char *seckey32, const unsigned char *auxrnd32) { + rustsecp256k1_v0_9_0_ge p; + rustsecp256k1_v0_9_0_fe t; + rustsecp256k1_v0_9_0_sha256 hash; + rustsecp256k1_v0_9_0_scalar seckey_scalar; + int ret; + static const unsigned char zero32[32] = {0}; + + /* Sanity check inputs. */ + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(ell64 != NULL); + memset(ell64, 0, 64); + ARG_CHECK(rustsecp256k1_v0_9_0_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(seckey32 != NULL); + + /* Compute (affine) public key */ + ret = rustsecp256k1_v0_9_0_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &seckey_scalar, &p, seckey32); + rustsecp256k1_v0_9_0_declassify(ctx, &p, sizeof(p)); /* not constant time in produced pubkey */ + rustsecp256k1_v0_9_0_fe_normalize_var(&p.x); + rustsecp256k1_v0_9_0_fe_normalize_var(&p.y); + + /* Set up hasher state. The used RNG is H(privkey || "\x00"*32 [|| auxrnd32] || cnt++), + * using BIP340 tagged hash with tag "rustsecp256k1_v0_9_0_ellswift_create". */ + rustsecp256k1_v0_9_0_ellswift_sha256_init_create(&hash); + rustsecp256k1_v0_9_0_sha256_write(&hash, seckey32, 32); + rustsecp256k1_v0_9_0_sha256_write(&hash, zero32, sizeof(zero32)); + rustsecp256k1_v0_9_0_declassify(ctx, &hash, sizeof(hash)); /* private key is hashed now */ + if (auxrnd32) rustsecp256k1_v0_9_0_sha256_write(&hash, auxrnd32, 32); + + /* Compute ElligatorSwift encoding and construct output. */ + rustsecp256k1_v0_9_0_ellswift_elligatorswift_var(ell64, &t, &p, &hash); /* puts u in ell64[0..32] */ + rustsecp256k1_v0_9_0_fe_get_b32(ell64 + 32, &t); /* puts t in ell64[32..64] */ + + rustsecp256k1_v0_9_0_memczero(ell64, 64, !ret); + rustsecp256k1_v0_9_0_scalar_clear(&seckey_scalar); + + return ret; +} + +int rustsecp256k1_v0_9_0_ellswift_decode(const rustsecp256k1_v0_9_0_context *ctx, rustsecp256k1_v0_9_0_pubkey *pubkey, const unsigned char *ell64) { + rustsecp256k1_v0_9_0_fe u, t; + rustsecp256k1_v0_9_0_ge p; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubkey != NULL); + ARG_CHECK(ell64 != NULL); + + rustsecp256k1_v0_9_0_fe_set_b32_mod(&u, ell64); + rustsecp256k1_v0_9_0_fe_set_b32_mod(&t, ell64 + 32); + rustsecp256k1_v0_9_0_fe_normalize_var(&t); + rustsecp256k1_v0_9_0_ellswift_swiftec_var(&p, &u, &t); + rustsecp256k1_v0_9_0_pubkey_save(pubkey, &p); + return 1; +} + +static int ellswift_xdh_hash_function_prefix(unsigned char *output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { + rustsecp256k1_v0_9_0_sha256 sha; + + rustsecp256k1_v0_9_0_sha256_initialize(&sha); + rustsecp256k1_v0_9_0_sha256_write(&sha, data, 64); + rustsecp256k1_v0_9_0_sha256_write(&sha, ell_a64, 64); + rustsecp256k1_v0_9_0_sha256_write(&sha, ell_b64, 64); + rustsecp256k1_v0_9_0_sha256_write(&sha, x32, 32); + rustsecp256k1_v0_9_0_sha256_finalize(&sha, output); + + return 1; +} + +/** Set hash state to the BIP340 tagged hash midstate for "bip324_ellswift_xonly_ecdh". */ +static void rustsecp256k1_v0_9_0_ellswift_sha256_init_bip324(rustsecp256k1_v0_9_0_sha256* hash) { + rustsecp256k1_v0_9_0_sha256_initialize(hash); + hash->s[0] = 0x8c12d730ul; + hash->s[1] = 0x827bd392ul; + hash->s[2] = 0x9e4fb2eeul; + hash->s[3] = 0x207b373eul; + hash->s[4] = 0x2292bd7aul; + hash->s[5] = 0xaa5441bcul; + hash->s[6] = 0x15c3779ful; + hash->s[7] = 0xcfb52549ul; + + hash->bytes = 64; +} + +static int ellswift_xdh_hash_function_bip324(unsigned char* output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { + rustsecp256k1_v0_9_0_sha256 sha; + + (void)data; + + rustsecp256k1_v0_9_0_ellswift_sha256_init_bip324(&sha); + rustsecp256k1_v0_9_0_sha256_write(&sha, ell_a64, 64); + rustsecp256k1_v0_9_0_sha256_write(&sha, ell_b64, 64); + rustsecp256k1_v0_9_0_sha256_write(&sha, x32, 32); + rustsecp256k1_v0_9_0_sha256_finalize(&sha, output); + + return 1; +} + +const rustsecp256k1_v0_9_0_ellswift_xdh_hash_function rustsecp256k1_v0_9_0_ellswift_xdh_hash_function_prefix = ellswift_xdh_hash_function_prefix; +const rustsecp256k1_v0_9_0_ellswift_xdh_hash_function rustsecp256k1_v0_9_0_ellswift_xdh_hash_function_bip324 = ellswift_xdh_hash_function_bip324; + +int rustsecp256k1_v0_9_0_ellswift_xdh(const rustsecp256k1_v0_9_0_context *ctx, unsigned char *output, const unsigned char *ell_a64, const unsigned char *ell_b64, const unsigned char *seckey32, int party, rustsecp256k1_v0_9_0_ellswift_xdh_hash_function hashfp, void *data) { + int ret = 0; + int overflow; + rustsecp256k1_v0_9_0_scalar s; + rustsecp256k1_v0_9_0_fe xn, xd, px, u, t; + unsigned char sx[32]; + const unsigned char* theirs64; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(output != NULL); + ARG_CHECK(ell_a64 != NULL); + ARG_CHECK(ell_b64 != NULL); + ARG_CHECK(seckey32 != NULL); + ARG_CHECK(hashfp != NULL); + + /* Load remote public key (as fraction). */ + theirs64 = party ? ell_a64 : ell_b64; + rustsecp256k1_v0_9_0_fe_set_b32_mod(&u, theirs64); + rustsecp256k1_v0_9_0_fe_set_b32_mod(&t, theirs64 + 32); + rustsecp256k1_v0_9_0_ellswift_xswiftec_frac_var(&xn, &xd, &u, &t); + + /* Load private key (using one if invalid). */ + rustsecp256k1_v0_9_0_scalar_set_b32(&s, seckey32, &overflow); + overflow = rustsecp256k1_v0_9_0_scalar_is_zero(&s); + rustsecp256k1_v0_9_0_scalar_cmov(&s, &rustsecp256k1_v0_9_0_scalar_one, overflow); + + /* Compute shared X coordinate. */ + rustsecp256k1_v0_9_0_ecmult_const_xonly(&px, &xn, &xd, &s, 1); + rustsecp256k1_v0_9_0_fe_normalize(&px); + rustsecp256k1_v0_9_0_fe_get_b32(sx, &px); + + /* Invoke hasher */ + ret = hashfp(output, sx, ell_a64, ell_b64, data); + + memset(sx, 0, 32); + rustsecp256k1_v0_9_0_fe_clear(&px); + rustsecp256k1_v0_9_0_scalar_clear(&s); + + return !!ret & !overflow; +} + +#endif diff --git a/secp256k1-sys/depend/secp256k1/src/modules/ellswift/tests_exhaustive_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/tests_exhaustive_impl.h new file mode 100644 index 000000000..577145838 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/tests_exhaustive_impl.h @@ -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 rustsecp256k1_v0_9_0_context *ctx, const rustsecp256k1_v0_9_0_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++) { + rustsecp256k1_v0_9_0_scalar scalar_i; + unsigned char sec32[32]; + unsigned char ell64[64]; + rustsecp256k1_v0_9_0_pubkey pub_decoded; + rustsecp256k1_v0_9_0_ge ge_decoded; + + /* Construct ellswift pubkey from exhaustive loop scalar i. */ + rustsecp256k1_v0_9_0_scalar_set_int(&scalar_i, i); + rustsecp256k1_v0_9_0_scalar_get_b32(sec32, &scalar_i); + CHECK(rustsecp256k1_v0_9_0_ellswift_create(ctx, ell64, sec32, NULL)); + + /* Decode ellswift pubkey and check that it matches the precomputed group element. */ + rustsecp256k1_v0_9_0_ellswift_decode(ctx, &pub_decoded, ell64); + rustsecp256k1_v0_9_0_pubkey_load(ctx, &ge_decoded, &pub_decoded); + ge_equals_ge(&ge_decoded, &group[i]); + } +} + +#endif diff --git a/secp256k1-sys/depend/secp256k1/src/modules/ellswift/tests_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/tests_impl.h new file mode 100644 index 000000000..4adf62950 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/tests_impl.h @@ -0,0 +1,436 @@ +/*********************************************************************** + * 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_H +#define SECP256K1_MODULE_ELLSWIFT_TESTS_H + +#include "../../../include/secp256k1_ellswift.h" + +struct ellswift_xswiftec_inv_test { + int enc_bitmap; + rustsecp256k1_v0_9_0_fe u; + rustsecp256k1_v0_9_0_fe x; + rustsecp256k1_v0_9_0_fe encs[8]; +}; + +struct ellswift_decode_test { + unsigned char enc[64]; + rustsecp256k1_v0_9_0_fe x; + int odd_y; +}; + +struct ellswift_xdh_test { + unsigned char priv_ours[32]; + unsigned char ellswift_ours[64]; + unsigned char ellswift_theirs[64]; + int initiating; + unsigned char shared_secret[32]; +}; + +/* Set of (point, encodings) test vectors, selected to maximize branch coverage, part of the BIP324 + * test vectors. Created using an independent implementation, and tested decoding against paper + * authors' code. */ +static const struct ellswift_xswiftec_inv_test ellswift_xswiftec_inv_tests[] = { + {0xcc, SECP256K1_FE_CONST(0x05ff6bda, 0xd900fc32, 0x61bc7fe3, 0x4e2fb0f5, 0x69f06e09, 0x1ae437d3, 0xa52e9da0, 0xcbfb9590), SECP256K1_FE_CONST(0x80cdf637, 0x74ec7022, 0xc89a5a85, 0x58e373a2, 0x79170285, 0xe0ab2741, 0x2dbce510, 0xbdfe23fc), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x45654798, 0xece071ba, 0x79286d04, 0xf7f3eb1c, 0x3f1d17dd, 0x883610f2, 0xad2efd82, 0xa287466b), SECP256K1_FE_CONST(0x0aeaa886, 0xf6b76c71, 0x58452418, 0xcbf5033a, 0xdc5747e9, 0xe9b5d3b2, 0x303db969, 0x36528557), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xba9ab867, 0x131f8e45, 0x86d792fb, 0x080c14e3, 0xc0e2e822, 0x77c9ef0d, 0x52d1027c, 0x5d78b5c4), SECP256K1_FE_CONST(0xf5155779, 0x0948938e, 0xa7badbe7, 0x340afcc5, 0x23a8b816, 0x164a2c4d, 0xcfc24695, 0xc9ad76d8)}}, + {0x33, SECP256K1_FE_CONST(0x1737a85f, 0x4c8d146c, 0xec96e3ff, 0xdca76d99, 0x03dcf3bd, 0x53061868, 0xd478c78c, 0x63c2aa9e), SECP256K1_FE_CONST(0x39e48dd1, 0x50d2f429, 0xbe088dfd, 0x5b61882e, 0x7e840748, 0x3702ae9a, 0x5ab35927, 0xb15f85ea), {SECP256K1_FE_CONST(0x1be8cc0b, 0x04be0c68, 0x1d0c6a68, 0xf733f82c, 0x6c896e0c, 0x8a262fcd, 0x392918e3, 0x03a7abf4), SECP256K1_FE_CONST(0x605b5814, 0xbf9b8cb0, 0x66667c9e, 0x5480d22d, 0xc5b6c92f, 0x14b4af3e, 0xe0a9eb83, 0xb03685e3), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xe41733f4, 0xfb41f397, 0xe2f39597, 0x08cc07d3, 0x937691f3, 0x75d9d032, 0xc6d6e71b, 0xfc58503b), SECP256K1_FE_CONST(0x9fa4a7eb, 0x4064734f, 0x99998361, 0xab7f2dd2, 0x3a4936d0, 0xeb4b50c1, 0x1f56147b, 0x4fc9764c), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0x00, SECP256K1_FE_CONST(0x1aaa1cce, 0xbf9c7241, 0x91033df3, 0x66b36f69, 0x1c4d902c, 0x228033ff, 0x4516d122, 0xb2564f68), SECP256K1_FE_CONST(0xc7554125, 0x9d3ba98f, 0x207eaa30, 0xc69634d1, 0x87d0b6da, 0x594e719e, 0x420f4898, 0x638fc5b0), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0x33, SECP256K1_FE_CONST(0x2323a1d0, 0x79b0fd72, 0xfc8bb62e, 0xc34230a8, 0x15cb0596, 0xc2bfac99, 0x8bd6b842, 0x60f5dc26), SECP256K1_FE_CONST(0x239342df, 0xb675500a, 0x34a19631, 0x0b8d87d5, 0x4f49dcac, 0x9da50c17, 0x43ceab41, 0xa7b249ff), {SECP256K1_FE_CONST(0xf63580b8, 0xaa49c484, 0x6de56e39, 0xe1b3e73f, 0x171e881e, 0xba8c66f6, 0x14e67e5c, 0x975dfc07), SECP256K1_FE_CONST(0xb6307b33, 0x2e699f1c, 0xf77841d9, 0x0af25365, 0x404deb7f, 0xed5edb30, 0x90db49e6, 0x42a156b6), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x09ca7f47, 0x55b63b7b, 0x921a91c6, 0x1e4c18c0, 0xe8e177e1, 0x45739909, 0xeb1981a2, 0x68a20028), SECP256K1_FE_CONST(0x49cf84cc, 0xd19660e3, 0x0887be26, 0xf50dac9a, 0xbfb21480, 0x12a124cf, 0x6f24b618, 0xbd5ea579), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0x33, SECP256K1_FE_CONST(0x2dc90e64, 0x0cb646ae, 0x9164c0b5, 0xa9ef0169, 0xfebe34dc, 0x4437d6e4, 0x6acb0e27, 0xe219d1e8), SECP256K1_FE_CONST(0xd236f19b, 0xf349b951, 0x6e9b3f4a, 0x5610fe96, 0x0141cb23, 0xbbc8291b, 0x9534f1d7, 0x1de62a47), {SECP256K1_FE_CONST(0xe69df7d9, 0xc026c366, 0x00ebdf58, 0x80726758, 0x47c0c431, 0xc8eb7306, 0x82533e96, 0x4b6252c9), SECP256K1_FE_CONST(0x4f18bbdf, 0x7c2d6c5f, 0x818c1880, 0x2fa35cd0, 0x69eaa79f, 0xff74e4fc, 0x837c80d9, 0x3fece2f8), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x19620826, 0x3fd93c99, 0xff1420a7, 0x7f8d98a7, 0xb83f3bce, 0x37148cf9, 0x7dacc168, 0xb49da966), SECP256K1_FE_CONST(0xb0e74420, 0x83d293a0, 0x7e73e77f, 0xd05ca32f, 0x96155860, 0x008b1b03, 0x7c837f25, 0xc0131937), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0xcc, SECP256K1_FE_CONST(0x3edd7b39, 0x80e2f2f3, 0x4d1409a2, 0x07069f88, 0x1fda5f96, 0xf08027ac, 0x4465b63d, 0xc278d672), SECP256K1_FE_CONST(0x053a98de, 0x4a27b196, 0x1155822b, 0x3a3121f0, 0x3b2a1445, 0x8bd80eb4, 0xa560c4c7, 0xa85c149c), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xb3dae4b7, 0xdcf858e4, 0xc6968057, 0xcef2b156, 0x46543152, 0x6538199c, 0xf52dc1b2, 0xd62fda30), SECP256K1_FE_CONST(0x4aa77dd5, 0x5d6b6d3c, 0xfa10cc9d, 0x0fe42f79, 0x232e4575, 0x661049ae, 0x36779c1d, 0x0c666d88), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x4c251b48, 0x2307a71b, 0x39697fa8, 0x310d4ea9, 0xb9abcead, 0x9ac7e663, 0x0ad23e4c, 0x29d021ff), SECP256K1_FE_CONST(0xb558822a, 0xa29492c3, 0x05ef3362, 0xf01bd086, 0xdcd1ba8a, 0x99efb651, 0xc98863e1, 0xf3998ea7)}}, + {0x00, SECP256K1_FE_CONST(0x4295737e, 0xfcb1da6f, 0xb1d96b9c, 0xa7dcd1e3, 0x20024b37, 0xa736c494, 0x8b625981, 0x73069f70), SECP256K1_FE_CONST(0xfa7ffe4f, 0x25f88362, 0x831c087a, 0xfe2e8a9b, 0x0713e2ca, 0xc1ddca6a, 0x383205a2, 0x66f14307), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0xff, SECP256K1_FE_CONST(0x587c1a0c, 0xee91939e, 0x7f784d23, 0xb963004a, 0x3bf44f5d, 0x4e32a008, 0x1995ba20, 0xb0fca59e), SECP256K1_FE_CONST(0x2ea98853, 0x0715e8d1, 0x0363907f, 0xf2512452, 0x4d471ba2, 0x454d5ce3, 0xbe3f0419, 0x4dfd3a3c), {SECP256K1_FE_CONST(0xcfd5a094, 0xaa0b9b88, 0x91b76c6a, 0xb9438f66, 0xaa1c095a, 0x65f9f701, 0x35e81712, 0x92245e74), SECP256K1_FE_CONST(0xa89057d7, 0xc6563f0d, 0x6efa19ae, 0x84412b8a, 0x7b47e791, 0xa191ecdf, 0xdf2af84f, 0xd97bc339), SECP256K1_FE_CONST(0x475d0ae9, 0xef46920d, 0xf07b3411, 0x7be5a081, 0x7de1023e, 0x3cc32689, 0xe9be145b, 0x406b0aef), SECP256K1_FE_CONST(0xa0759178, 0xad802324, 0x54f827ef, 0x05ea3e72, 0xad8d7541, 0x8e6d4cc1, 0xcd4f5306, 0xc5e7c453), SECP256K1_FE_CONST(0x302a5f6b, 0x55f46477, 0x6e489395, 0x46bc7099, 0x55e3f6a5, 0x9a0608fe, 0xca17e8ec, 0x6ddb9dbb), SECP256K1_FE_CONST(0x576fa828, 0x39a9c0f2, 0x9105e651, 0x7bbed475, 0x84b8186e, 0x5e6e1320, 0x20d507af, 0x268438f6), SECP256K1_FE_CONST(0xb8a2f516, 0x10b96df2, 0x0f84cbee, 0x841a5f7e, 0x821efdc1, 0xc33cd976, 0x1641eba3, 0xbf94f140), SECP256K1_FE_CONST(0x5f8a6e87, 0x527fdcdb, 0xab07d810, 0xfa15c18d, 0x52728abe, 0x7192b33e, 0x32b0acf8, 0x3a1837dc)}}, + {0xcc, SECP256K1_FE_CONST(0x5fa88b33, 0x65a635cb, 0xbcee003c, 0xce9ef51d, 0xd1a310de, 0x277e441a, 0xbccdb7be, 0x1e4ba249), SECP256K1_FE_CONST(0x79461ff6, 0x2bfcbcac, 0x4249ba84, 0xdd040f2c, 0xec3c63f7, 0x25204dc7, 0xf464c16b, 0xf0ff3170), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x6bb700e1, 0xf4d7e236, 0xe8d193ff, 0x4a76c1b3, 0xbcd4e2b2, 0x5acac3d5, 0x1c8dac65, 0x3fe909a0), SECP256K1_FE_CONST(0xf4c73410, 0x633da7f6, 0x3a4f1d55, 0xaec6dd32, 0xc4c6d89e, 0xe74075ed, 0xb5515ed9, 0x0da9e683), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x9448ff1e, 0x0b281dc9, 0x172e6c00, 0xb5893e4c, 0x432b1d4d, 0xa5353c2a, 0xe3725399, 0xc016f28f), SECP256K1_FE_CONST(0x0b38cbef, 0x9cc25809, 0xc5b0e2aa, 0x513922cd, 0x3b392761, 0x18bf8a12, 0x4aaea125, 0xf25615ac)}}, + {0xcc, SECP256K1_FE_CONST(0x6fb31c75, 0x31f03130, 0xb42b155b, 0x952779ef, 0xbb46087d, 0xd9807d24, 0x1a48eac6, 0x3c3d96d6), SECP256K1_FE_CONST(0x56f81be7, 0x53e8d4ae, 0x4940ea6f, 0x46f6ec9f, 0xda66a6f9, 0x6cc95f50, 0x6cb2b574, 0x90e94260), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x59059774, 0x795bdb7a, 0x837fbe11, 0x40a5fa59, 0x984f48af, 0x8df95d57, 0xdd6d1c05, 0x437dcec1), SECP256K1_FE_CONST(0x22a644db, 0x79376ad4, 0xe7b3a009, 0xe58b3f13, 0x137c54fd, 0xf911122c, 0xc93667c4, 0x7077d784), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xa6fa688b, 0x86a42485, 0x7c8041ee, 0xbf5a05a6, 0x67b0b750, 0x7206a2a8, 0x2292e3f9, 0xbc822d6e), SECP256K1_FE_CONST(0xdd59bb24, 0x86c8952b, 0x184c5ff6, 0x1a74c0ec, 0xec83ab02, 0x06eeedd3, 0x36c9983a, 0x8f8824ab)}}, + {0x00, SECP256K1_FE_CONST(0x704cd226, 0xe71cb682, 0x6a590e80, 0xdac90f2d, 0x2f5830f0, 0xfdf135a3, 0xeae3965b, 0xff25ff12), SECP256K1_FE_CONST(0x138e0afa, 0x68936ee6, 0x70bd2b8d, 0xb53aedbb, 0x7bea2a85, 0x97388b24, 0xd0518edd, 0x22ad66ec), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0x33, SECP256K1_FE_CONST(0x725e9147, 0x92cb8c89, 0x49e7e116, 0x8b7cdd8a, 0x8094c91c, 0x6ec2202c, 0xcd53a6a1, 0x8771edeb), SECP256K1_FE_CONST(0x8da16eb8, 0x6d347376, 0xb6181ee9, 0x74832275, 0x7f6b36e3, 0x913ddfd3, 0x32ac595d, 0x788e0e44), {SECP256K1_FE_CONST(0xdd357786, 0xb9f68733, 0x30391aa5, 0x62580965, 0x4e43116e, 0x82a5a5d8, 0x2ffd1d66, 0x24101fc4), SECP256K1_FE_CONST(0xa0b7efca, 0x01814594, 0xc59c9aae, 0x8e497001, 0x86ca5d95, 0xe88bcc80, 0x399044d9, 0xc2d8613d), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x22ca8879, 0x460978cc, 0xcfc6e55a, 0x9da7f69a, 0xb1bcee91, 0x7d5a5a27, 0xd002e298, 0xdbefdc6b), SECP256K1_FE_CONST(0x5f481035, 0xfe7eba6b, 0x3a636551, 0x71b68ffe, 0x7935a26a, 0x1774337f, 0xc66fbb25, 0x3d279af2), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0x00, SECP256K1_FE_CONST(0x78fe6b71, 0x7f2ea4a3, 0x2708d79c, 0x151bf503, 0xa5312a18, 0xc0963437, 0xe865cc6e, 0xd3f6ae97), SECP256K1_FE_CONST(0x8701948e, 0x80d15b5c, 0xd8f72863, 0xeae40afc, 0x5aced5e7, 0x3f69cbc8, 0x179a3390, 0x2c094d98), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0x44, SECP256K1_FE_CONST(0x7c37bb9c, 0x5061dc07, 0x413f11ac, 0xd5a34006, 0xe64c5c45, 0x7fdb9a43, 0x8f217255, 0xa961f50d), SECP256K1_FE_CONST(0x5c1a76b4, 0x4568eb59, 0xd6789a74, 0x42d9ed7c, 0xdc6226b7, 0x752b4ff8, 0xeaf8e1a9, 0x5736e507), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xb94d30cd, 0x7dbff60b, 0x64620c17, 0xca0fafaa, 0x40b3d1f5, 0x2d077a60, 0xa2e0cafd, 0x145086c2), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x46b2cf32, 0x824009f4, 0x9b9df3e8, 0x35f05055, 0xbf4c2e0a, 0xd2f8859f, 0x5d1f3501, 0xebaf756d), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0x00, SECP256K1_FE_CONST(0x82388888, 0x967f82a6, 0xb444438a, 0x7d44838e, 0x13c0d478, 0xb9ca060d, 0xa95a41fb, 0x94303de6), SECP256K1_FE_CONST(0x29e96541, 0x70628fec, 0x8b497289, 0x8b113cf9, 0x8807f460, 0x9274f4f3, 0x140d0674, 0x157c90a0), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0x33, SECP256K1_FE_CONST(0x91298f57, 0x70af7a27, 0xf0a47188, 0xd24c3b7b, 0xf98ab299, 0x0d84b0b8, 0x98507e3c, 0x561d6472), SECP256K1_FE_CONST(0x144f4ccb, 0xd9a74698, 0xa88cbf6f, 0xd00ad886, 0xd339d29e, 0xa19448f2, 0xc572cac0, 0xa07d5562), {SECP256K1_FE_CONST(0xe6a0ffa3, 0x807f09da, 0xdbe71e0f, 0x4be4725f, 0x2832e76c, 0xad8dc1d9, 0x43ce8393, 0x75eff248), SECP256K1_FE_CONST(0x837b8e68, 0xd4917544, 0x764ad090, 0x3cb11f86, 0x15d2823c, 0xefbb06d8, 0x9049dbab, 0xc69befda), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x195f005c, 0x7f80f625, 0x2418e1f0, 0xb41b8da0, 0xd7cd1893, 0x52723e26, 0xbc317c6b, 0x8a1009e7), SECP256K1_FE_CONST(0x7c847197, 0x2b6e8abb, 0x89b52f6f, 0xc34ee079, 0xea2d7dc3, 0x1044f927, 0x6fb62453, 0x39640c55), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0x00, SECP256K1_FE_CONST(0xb682f3d0, 0x3bbb5dee, 0x4f54b5eb, 0xfba931b4, 0xf52f6a19, 0x1e5c2f48, 0x3c73c66e, 0x9ace97e1), SECP256K1_FE_CONST(0x904717bf, 0x0bc0cb78, 0x73fcdc38, 0xaa97f19e, 0x3a626309, 0x72acff92, 0xb24cc6dd, 0xa197cb96), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0x77, SECP256K1_FE_CONST(0xc17ec69e, 0x665f0fb0, 0xdbab48d9, 0xc2f94d12, 0xec8a9d7e, 0xacb58084, 0x83309180, 0x1eb0b80b), SECP256K1_FE_CONST(0x147756e6, 0x6d96e31c, 0x426d3cc8, 0x5ed0c4cf, 0xbef6341d, 0xd8b28558, 0x5aa574ea, 0x0204b55e), {SECP256K1_FE_CONST(0x6f4aea43, 0x1a0043bd, 0xd03134d6, 0xd9159119, 0xce034b88, 0xc32e50e8, 0xe36c4ee4, 0x5eac7ae9), SECP256K1_FE_CONST(0xfd5be16d, 0x4ffa2690, 0x126c67c3, 0xef7cb9d2, 0x9b74d397, 0xc78b06b3, 0x605fda34, 0xdc9696a6), SECP256K1_FE_CONST(0x5e9c6079, 0x2a2f000e, 0x45c6250f, 0x296f875e, 0x174efc0e, 0x9703e628, 0x706103a9, 0xdd2d82c7), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x90b515bc, 0xe5ffbc42, 0x2fcecb29, 0x26ea6ee6, 0x31fcb477, 0x3cd1af17, 0x1c93b11a, 0xa1538146), SECP256K1_FE_CONST(0x02a41e92, 0xb005d96f, 0xed93983c, 0x1083462d, 0x648b2c68, 0x3874f94c, 0x9fa025ca, 0x23696589), SECP256K1_FE_CONST(0xa1639f86, 0xd5d0fff1, 0xba39daf0, 0xd69078a1, 0xe8b103f1, 0x68fc19d7, 0x8f9efc55, 0x22d27968), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0xcc, SECP256K1_FE_CONST(0xc25172fc, 0x3f29b6fc, 0x4a1155b8, 0x57523315, 0x5486b274, 0x64b74b8b, 0x260b499a, 0x3f53cb14), SECP256K1_FE_CONST(0x1ea9cbdb, 0x35cf6e03, 0x29aa31b0, 0xbb0a702a, 0x65123ed0, 0x08655a93, 0xb7dcd528, 0x0e52e1ab), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x7422edc7, 0x843136af, 0x0053bb88, 0x54448a82, 0x99994f9d, 0xdcefd3a9, 0xa92d4546, 0x2c59298a), SECP256K1_FE_CONST(0x78c7774a, 0x266f8b97, 0xea23d05d, 0x064f033c, 0x77319f92, 0x3f6b78bc, 0xe4e20bf0, 0x5fa5398d), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x8bdd1238, 0x7bcec950, 0xffac4477, 0xabbb757d, 0x6666b062, 0x23102c56, 0x56d2bab8, 0xd3a6d2a5), SECP256K1_FE_CONST(0x873888b5, 0xd9907468, 0x15dc2fa2, 0xf9b0fcc3, 0x88ce606d, 0xc0948743, 0x1b1df40e, 0xa05ac2a2)}}, + {0x00, SECP256K1_FE_CONST(0xcab6626f, 0x832a4b12, 0x80ba7add, 0x2fc5322f, 0xf011caed, 0xedf7ff4d, 0xb6735d50, 0x26dc0367), SECP256K1_FE_CONST(0x2b2bef08, 0x52c6f7c9, 0x5d72ac99, 0xa23802b8, 0x75029cd5, 0x73b248d1, 0xf1b3fc80, 0x33788eb6), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0x33, SECP256K1_FE_CONST(0xd8621b4f, 0xfc85b9ed, 0x56e99d8d, 0xd1dd24ae, 0xdcecb147, 0x63b861a1, 0x7112dc77, 0x1a104fd2), SECP256K1_FE_CONST(0x812cabe9, 0x72a22aa6, 0x7c7da0c9, 0x4d8a9362, 0x96eb9949, 0xd70c37cb, 0x2b248757, 0x4cb3ce58), {SECP256K1_FE_CONST(0xfbc5febc, 0x6fdbc9ae, 0x3eb88a93, 0xb982196e, 0x8b6275a6, 0xd5a73c17, 0x387e000c, 0x711bd0e3), SECP256K1_FE_CONST(0x8724c96b, 0xd4e5527f, 0x2dd195a5, 0x1c468d2d, 0x211ba2fa, 0xc7cbe0b4, 0xb3434253, 0x409fb42d), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x043a0143, 0x90243651, 0xc147756c, 0x467de691, 0x749d8a59, 0x2a58c3e8, 0xc781fff2, 0x8ee42b4c), SECP256K1_FE_CONST(0x78db3694, 0x2b1aad80, 0xd22e6a5a, 0xe3b972d2, 0xdee45d05, 0x38341f4b, 0x4cbcbdab, 0xbf604802), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0x00, SECP256K1_FE_CONST(0xda463164, 0xc6f4bf71, 0x29ee5f0e, 0xc00f65a6, 0x75a8adf1, 0xbd931b39, 0xb64806af, 0xdcda9a22), SECP256K1_FE_CONST(0x25b9ce9b, 0x390b408e, 0xd611a0f1, 0x3ff09a59, 0x8a57520e, 0x426ce4c6, 0x49b7f94f, 0x2325620d), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0xcc, SECP256K1_FE_CONST(0xdafc971e, 0x4a3a7b6d, 0xcfb42a08, 0xd9692d82, 0xad9e7838, 0x523fcbda, 0x1d4827e1, 0x4481ae2d), SECP256K1_FE_CONST(0x250368e1, 0xb5c58492, 0x304bd5f7, 0x2696d27d, 0x526187c7, 0xadc03425, 0xe2b7d81d, 0xbb7e4e02), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x370c28f1, 0xbe665efa, 0xcde6aa43, 0x6bf86fe2, 0x1e6e314c, 0x1e53dd04, 0x0e6c73a4, 0x6b4c8c49), SECP256K1_FE_CONST(0xcd8acee9, 0x8ffe5653, 0x1a84d7eb, 0x3e48fa40, 0x34206ce8, 0x25ace907, 0xd0edf0ea, 0xeb5e9ca2), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xc8f3d70e, 0x4199a105, 0x321955bc, 0x9407901d, 0xe191ceb3, 0xe1ac22fb, 0xf1938c5a, 0x94b36fe6), SECP256K1_FE_CONST(0x32753116, 0x7001a9ac, 0xe57b2814, 0xc1b705bf, 0xcbdf9317, 0xda5316f8, 0x2f120f14, 0x14a15f8d)}}, + {0x44, SECP256K1_FE_CONST(0xe0294c8b, 0xc1a36b41, 0x66ee92bf, 0xa70a5c34, 0x976fa982, 0x9405efea, 0x8f9cd54d, 0xcb29b99e), SECP256K1_FE_CONST(0xae9690d1, 0x3b8d20a0, 0xfbbf37be, 0xd8474f67, 0xa04e142f, 0x56efd787, 0x70a76b35, 0x9165d8a1), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xdcd45d93, 0x5613916a, 0xf167b029, 0x058ba3a7, 0x00d37150, 0xb9df3472, 0x8cb05412, 0xc16d4182), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x232ba26c, 0xa9ec6e95, 0x0e984fd6, 0xfa745c58, 0xff2c8eaf, 0x4620cb8d, 0x734fabec, 0x3e92baad), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0x00, SECP256K1_FE_CONST(0xe148441c, 0xd7b92b8b, 0x0e4fa3bd, 0x68712cfd, 0x0d709ad1, 0x98cace61, 0x1493c10e, 0x97f5394e), SECP256K1_FE_CONST(0x164a6397, 0x94d74c53, 0xafc4d329, 0x4e79cdb3, 0xcd25f99f, 0x6df45c00, 0x0f758aba, 0x54d699c0), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0xff, SECP256K1_FE_CONST(0xe4b00ec9, 0x7aadcca9, 0x7644d3b0, 0xc8a931b1, 0x4ce7bcf7, 0xbc877954, 0x6d6e35aa, 0x5937381c), SECP256K1_FE_CONST(0x94e9588d, 0x41647b3f, 0xcc772dc8, 0xd83c67ce, 0x3be00353, 0x8517c834, 0x103d2cd4, 0x9d62ef4d), {SECP256K1_FE_CONST(0xc88d25f4, 0x1407376b, 0xb2c03a7f, 0xffeb3ec7, 0x811cc434, 0x91a0c3aa, 0xc0378cdc, 0x78357bee), SECP256K1_FE_CONST(0x51c02636, 0xce00c234, 0x5ecd89ad, 0xb6089fe4, 0xd5e18ac9, 0x24e3145e, 0x6669501c, 0xd37a00d4), SECP256K1_FE_CONST(0x205b3512, 0xdb40521c, 0xb200952e, 0x67b46f67, 0xe09e7839, 0xe0de4400, 0x4138329e, 0xbd9138c5), SECP256K1_FE_CONST(0x58aab390, 0xab6fb55c, 0x1d1b8089, 0x7a207ce9, 0x4a78fa5b, 0x4aa61a33, 0x398bcae9, 0xadb20d3e), SECP256K1_FE_CONST(0x3772da0b, 0xebf8c894, 0x4d3fc580, 0x0014c138, 0x7ee33bcb, 0x6e5f3c55, 0x3fc87322, 0x87ca8041), SECP256K1_FE_CONST(0xae3fd9c9, 0x31ff3dcb, 0xa1327652, 0x49f7601b, 0x2a1e7536, 0xdb1ceba1, 0x9996afe2, 0x2c85fb5b), SECP256K1_FE_CONST(0xdfa4caed, 0x24bfade3, 0x4dff6ad1, 0x984b9098, 0x1f6187c6, 0x1f21bbff, 0xbec7cd60, 0x426ec36a), SECP256K1_FE_CONST(0xa7554c6f, 0x54904aa3, 0xe2e47f76, 0x85df8316, 0xb58705a4, 0xb559e5cc, 0xc6743515, 0x524deef1)}}, + {0x00, SECP256K1_FE_CONST(0xe5bbb9ef, 0x360d0a50, 0x1618f006, 0x7d36dceb, 0x75f5be9a, 0x620232aa, 0x9fd5139d, 0x0863fde5), SECP256K1_FE_CONST(0xe5bbb9ef, 0x360d0a50, 0x1618f006, 0x7d36dceb, 0x75f5be9a, 0x620232aa, 0x9fd5139d, 0x0863fde5), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0xff, SECP256K1_FE_CONST(0xe6bcb5c3, 0xd63467d4, 0x90bfa54f, 0xbbc6092a, 0x7248c25e, 0x11b248dc, 0x2964a6e1, 0x5edb1457), SECP256K1_FE_CONST(0x19434a3c, 0x29cb982b, 0x6f405ab0, 0x4439f6d5, 0x8db73da1, 0xee4db723, 0xd69b591d, 0xa124e7d8), {SECP256K1_FE_CONST(0x67119877, 0x832ab8f4, 0x59a82165, 0x6d8261f5, 0x44a553b8, 0x9ae4f25c, 0x52a97134, 0xb70f3426), SECP256K1_FE_CONST(0xffee02f5, 0xe649c07f, 0x0560eff1, 0x867ec7b3, 0x2d0e595e, 0x9b1c0ea6, 0xe2a4fc70, 0xc97cd71f), SECP256K1_FE_CONST(0xb5e0c189, 0xeb5b4bac, 0xd025b744, 0x4d74178b, 0xe8d5246c, 0xfa4a9a20, 0x7964a057, 0xee969992), SECP256K1_FE_CONST(0x5746e459, 0x1bf7f4c3, 0x044609ea, 0x372e9086, 0x03975d27, 0x9fdef834, 0x9f0b08d3, 0x2f07619d), SECP256K1_FE_CONST(0x98ee6788, 0x7cd5470b, 0xa657de9a, 0x927d9e0a, 0xbb5aac47, 0x651b0da3, 0xad568eca, 0x48f0c809), SECP256K1_FE_CONST(0x0011fd0a, 0x19b63f80, 0xfa9f100e, 0x7981384c, 0xd2f1a6a1, 0x64e3f159, 0x1d5b038e, 0x36832510), SECP256K1_FE_CONST(0x4a1f3e76, 0x14a4b453, 0x2fda48bb, 0xb28be874, 0x172adb93, 0x05b565df, 0x869b5fa7, 0x1169629d), SECP256K1_FE_CONST(0xa8b91ba6, 0xe4080b3c, 0xfbb9f615, 0xc8d16f79, 0xfc68a2d8, 0x602107cb, 0x60f4f72b, 0xd0f89a92)}}, + {0x33, SECP256K1_FE_CONST(0xf28fba64, 0xaf766845, 0xeb2f4302, 0x456e2b9f, 0x8d80affe, 0x57e7aae4, 0x2738d7cd, 0xdb1c2ce6), SECP256K1_FE_CONST(0xf28fba64, 0xaf766845, 0xeb2f4302, 0x456e2b9f, 0x8d80affe, 0x57e7aae4, 0x2738d7cd, 0xdb1c2ce6), {SECP256K1_FE_CONST(0x4f867ad8, 0xbb3d8404, 0x09d26b67, 0x307e6210, 0x0153273f, 0x72fa4b74, 0x84becfa1, 0x4ebe7408), SECP256K1_FE_CONST(0x5bbc4f59, 0xe452cc5f, 0x22a99144, 0xb10ce898, 0x9a89a995, 0xec3cea1c, 0x91ae10e8, 0xf721bb5d), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xb0798527, 0x44c27bfb, 0xf62d9498, 0xcf819def, 0xfeacd8c0, 0x8d05b48b, 0x7b41305d, 0xb1418827), SECP256K1_FE_CONST(0xa443b0a6, 0x1bad33a0, 0xdd566ebb, 0x4ef31767, 0x6576566a, 0x13c315e3, 0x6e51ef16, 0x08de40d2), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, + {0xcc, SECP256K1_FE_CONST(0xf455605b, 0xc85bf48e, 0x3a908c31, 0x023faf98, 0x381504c6, 0xc6d3aeb9, 0xede55f8d, 0xd528924d), SECP256K1_FE_CONST(0xd31fbcd5, 0xcdb798f6, 0xc00db669, 0x2f8fe896, 0x7fa9c79d, 0xd10958f4, 0xa194f013, 0x74905e99), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x0c00c571, 0x5b56fe63, 0x2d814ad8, 0xa77f8e66, 0x628ea47a, 0x6116834f, 0x8c1218f3, 0xa03cbd50), SECP256K1_FE_CONST(0xdf88e44f, 0xac84fa52, 0xdf4d59f4, 0x8819f18f, 0x6a8cd415, 0x1d162afa, 0xf773166f, 0x57c7ff46), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xf3ff3a8e, 0xa4a9019c, 0xd27eb527, 0x58807199, 0x9d715b85, 0x9ee97cb0, 0x73ede70b, 0x5fc33edf), SECP256K1_FE_CONST(0x20771bb0, 0x537b05ad, 0x20b2a60b, 0x77e60e70, 0x95732bea, 0xe2e9d505, 0x088ce98f, 0xa837fce9)}}, + {0xff, SECP256K1_FE_CONST(0xf58cd4d9, 0x830bad32, 0x2699035e, 0x8246007d, 0x4be27e19, 0xb6f53621, 0x317b4f30, 0x9b3daa9d), SECP256K1_FE_CONST(0x78ec2b3d, 0xc0948de5, 0x60148bbc, 0x7c6dc963, 0x3ad5df70, 0xa5a5750c, 0xbed72180, 0x4f082a3b), {SECP256K1_FE_CONST(0x6c4c580b, 0x76c75940, 0x43569f9d, 0xae16dc28, 0x01c16a1f, 0xbe128608, 0x81b75f8e, 0xf929bce5), SECP256K1_FE_CONST(0x94231355, 0xe7385c5f, 0x25ca436a, 0xa6419147, 0x1aea4393, 0xd6e86ab7, 0xa35fe2af, 0xacaefd0d), SECP256K1_FE_CONST(0xdff2a195, 0x1ada6db5, 0x74df8340, 0x48149da3, 0x397a75b8, 0x29abf58c, 0x7e69db1b, 0x41ac0989), SECP256K1_FE_CONST(0xa52b66d3, 0xc9070355, 0x48028bf8, 0x04711bf4, 0x22aba95f, 0x1a666fc8, 0x6f4648e0, 0x5f29caae), SECP256K1_FE_CONST(0x93b3a7f4, 0x8938a6bf, 0xbca96062, 0x51e923d7, 0xfe3e95e0, 0x41ed79f7, 0x7e48a070, 0x06d63f4a), SECP256K1_FE_CONST(0x6bdcecaa, 0x18c7a3a0, 0xda35bc95, 0x59be6eb8, 0xe515bc6c, 0x29179548, 0x5ca01d4f, 0x5350ff22), SECP256K1_FE_CONST(0x200d5e6a, 0xe525924a, 0x8b207cbf, 0xb7eb625c, 0xc6858a47, 0xd6540a73, 0x819624e3, 0xbe53f2a6), SECP256K1_FE_CONST(0x5ad4992c, 0x36f8fcaa, 0xb7fd7407, 0xfb8ee40b, 0xdd5456a0, 0xe5999037, 0x90b9b71e, 0xa0d63181)}}, + {0x00, SECP256K1_FE_CONST(0xfd7d912a, 0x40f182a3, 0x588800d6, 0x9ebfb504, 0x8766da20, 0x6fd7ebc8, 0xd2436c81, 0xcbef6421), SECP256K1_FE_CONST(0x8d37c862, 0x054debe7, 0x31694536, 0xff46b273, 0xec122b35, 0xa9bf1445, 0xac3c4ff9, 0xf262c952), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, +}; + +/* Set of (encoding, xcoord) test vectors, selected to maximize branch coverage, part of the BIP324 + * test vectors. Created using an independent implementation, and tested decoding against the paper + * authors' code. */ +static const struct ellswift_decode_test ellswift_decode_tests[] = { + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0xedd1fd3e, 0x327ce90c, 0xc7a35426, 0x14289aee, 0x9682003e, 0x9cf7dcc9, 0xcf2ca974, 0x3be5aa0c), 0}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd3, 0x47, 0x5b, 0xf7, 0x65, 0x5b, 0x0f, 0xb2, 0xd8, 0x52, 0x92, 0x10, 0x35, 0xb2, 0xef, 0x60, 0x7f, 0x49, 0x06, 0x9b, 0x97, 0x45, 0x4e, 0x67, 0x95, 0x25, 0x10, 0x62, 0x74, 0x17, 0x71}, SECP256K1_FE_CONST(0xb5da00b7, 0x3cd65605, 0x20e7c364, 0x086e7cd2, 0x3a34bf60, 0xd0e707be, 0x9fc34d4c, 0xd5fdfa2c), 1}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x27, 0x7c, 0x4a, 0x71, 0xf9, 0xd2, 0x2e, 0x66, 0xec, 0xe5, 0x23, 0xf8, 0xfa, 0x08, 0x74, 0x1a, 0x7c, 0x09, 0x12, 0xc6, 0x6a, 0x69, 0xce, 0x68, 0x51, 0x4b, 0xfd, 0x35, 0x15, 0xb4, 0x9f}, SECP256K1_FE_CONST(0xf482f2e2, 0x41753ad0, 0xfb89150d, 0x8491dc1e, 0x34ff0b8a, 0xcfbb442c, 0xfe999e2e, 0x5e6fd1d2), 1}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x21, 0xcc, 0x93, 0x0e, 0x77, 0xc9, 0xf5, 0x14, 0xb6, 0x91, 0x5c, 0x3d, 0xbe, 0x2a, 0x94, 0xc6, 0xd8, 0xf6, 0x90, 0xb5, 0xb7, 0x39, 0x86, 0x4b, 0xa6, 0x78, 0x9f, 0xb8, 0xa5, 0x5d, 0xd0}, SECP256K1_FE_CONST(0x9f59c402, 0x75f5085a, 0x006f05da, 0xe77eb98c, 0x6fd0db1a, 0xb4a72ac4, 0x7eae90a4, 0xfc9e57e0), 0}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xe7, 0x0d, 0xf5, 0x19, 0x39, 0xb9, 0x4c, 0x9c, 0x24, 0x97, 0x9f, 0xa7, 0xdd, 0x04, 0xeb, 0xd9, 0xb3, 0x57, 0x2d, 0xa7, 0x80, 0x22, 0x90, 0x43, 0x8a, 0xf2, 0xa6, 0x81, 0x89, 0x54, 0x41}, SECP256K1_FE_CONST(0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaa9, 0xfffffd6b), 1}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x9c, 0x18, 0x2d, 0x27, 0x59, 0xcd, 0x99, 0x82, 0x42, 0x28, 0xd9, 0x47, 0x99, 0xf8, 0xc6, 0x55, 0x7c, 0x38, 0xa1, 0xc0, 0xd6, 0x77, 0x9b, 0x9d, 0x4b, 0x72, 0x9c, 0x6f, 0x1c, 0xcc, 0x42}, SECP256K1_FE_CONST(0x70720db7, 0xe238d041, 0x21f5b1af, 0xd8cc5ad9, 0xd18944c6, 0xbdc94881, 0xf502b7a3, 0xaf3aecff), 0}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0xedd1fd3e, 0x327ce90c, 0xc7a35426, 0x14289aee, 0x9682003e, 0x9cf7dcc9, 0xcf2ca974, 0x3be5aa0c), 0}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x26, 0x64, 0xbb, 0xd5}, SECP256K1_FE_CONST(0x50873db3, 0x1badcc71, 0x890e4f67, 0x753a6575, 0x7f97aaa7, 0xdd5f1e82, 0xb753ace3, 0x2219064b), 0}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x28, 0xde, 0x7d}, SECP256K1_FE_CONST(0x1eea9cc5, 0x9cfcf2fa, 0x151ac6c2, 0x74eea411, 0x0feb4f7b, 0x68c59657, 0x32e9992e, 0x976ef68e), 0}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcb, 0xcf, 0xb7, 0xe7}, SECP256K1_FE_CONST(0x12303941, 0xaedc2088, 0x80735b1f, 0x1795c8e5, 0x5be520ea, 0x93e10335, 0x7b5d2adb, 0x7ed59b8e), 0}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x11, 0x3a, 0xd9}, SECP256K1_FE_CONST(0x7eed6b70, 0xe7b0767c, 0x7d7feac0, 0x4e57aa2a, 0x12fef5e0, 0xf48f878f, 0xcbb88b3b, 0x6b5e0783), 0}, + {{0x0a, 0x2d, 0x2b, 0xa9, 0x35, 0x07, 0xf1, 0xdf, 0x23, 0x37, 0x70, 0xc2, 0xa7, 0x97, 0x96, 0x2c, 0xc6, 0x1f, 0x6d, 0x15, 0xda, 0x14, 0xec, 0xd4, 0x7d, 0x8d, 0x27, 0xae, 0x1c, 0xd5, 0xf8, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x532167c1, 0x1200b08c, 0x0e84a354, 0xe74dcc40, 0xf8b25f4f, 0xe686e308, 0x69526366, 0x278a0688), 0}, + {{0x0a, 0x2d, 0x2b, 0xa9, 0x35, 0x07, 0xf1, 0xdf, 0x23, 0x37, 0x70, 0xc2, 0xa7, 0x97, 0x96, 0x2c, 0xc6, 0x1f, 0x6d, 0x15, 0xda, 0x14, 0xec, 0xd4, 0x7d, 0x8d, 0x27, 0xae, 0x1c, 0xd5, 0xf8, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x532167c1, 0x1200b08c, 0x0e84a354, 0xe74dcc40, 0xf8b25f4f, 0xe686e308, 0x69526366, 0x278a0688), 0}, + {{0x0f, 0xfd, 0xe9, 0xca, 0x81, 0xd7, 0x51, 0xe9, 0xcd, 0xaf, 0xfc, 0x1a, 0x50, 0x77, 0x92, 0x45, 0x32, 0x0b, 0x28, 0x99, 0x6d, 0xba, 0xf3, 0x2f, 0x82, 0x2f, 0x20, 0x11, 0x7c, 0x22, 0xfb, 0xd6, 0xc7, 0x4d, 0x99, 0xef, 0xce, 0xaa, 0x55, 0x0f, 0x1a, 0xd1, 0xc0, 0xf4, 0x3f, 0x46, 0xe7, 0xff, 0x1e, 0xe3, 0xbd, 0x01, 0x62, 0xb7, 0xbf, 0x55, 0xf2, 0x96, 0x5d, 0xa9, 0xc3, 0x45, 0x06, 0x46}, SECP256K1_FE_CONST(0x74e880b3, 0xffd18fe3, 0xcddf7902, 0x522551dd, 0xf97fa4a3, 0x5a3cfda8, 0x197f9470, 0x81a57b8f), 0}, + {{0x0f, 0xfd, 0xe9, 0xca, 0x81, 0xd7, 0x51, 0xe9, 0xcd, 0xaf, 0xfc, 0x1a, 0x50, 0x77, 0x92, 0x45, 0x32, 0x0b, 0x28, 0x99, 0x6d, 0xba, 0xf3, 0x2f, 0x82, 0x2f, 0x20, 0x11, 0x7c, 0x22, 0xfb, 0xd6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x6c, 0xa8, 0x96}, SECP256K1_FE_CONST(0x377b643f, 0xce2271f6, 0x4e5c8101, 0x566107c1, 0xbe498074, 0x50917838, 0x04f65478, 0x1ac9217c), 1}, + {{0x12, 0x36, 0x58, 0x44, 0x4f, 0x32, 0xbe, 0x8f, 0x02, 0xea, 0x20, 0x34, 0xaf, 0xa7, 0xef, 0x4b, 0xbe, 0x8a, 0xdc, 0x91, 0x8c, 0xeb, 0x49, 0xb1, 0x27, 0x73, 0xb6, 0x25, 0xf4, 0x90, 0xb3, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8d, 0xc5, 0xfe, 0x11}, SECP256K1_FE_CONST(0xed16d65c, 0xf3a9538f, 0xcb2c139f, 0x1ecbc143, 0xee148271, 0x20cbc265, 0x9e667256, 0x800b8142), 0}, + {{0x14, 0x6f, 0x92, 0x46, 0x4d, 0x15, 0xd3, 0x6e, 0x35, 0x38, 0x2b, 0xd3, 0xca, 0x5b, 0x0f, 0x97, 0x6c, 0x95, 0xcb, 0x08, 0xac, 0xdc, 0xf2, 0xd5, 0xb3, 0x57, 0x06, 0x17, 0x99, 0x08, 0x39, 0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x31, 0x45, 0xe9, 0x3b}, SECP256K1_FE_CONST(0x0d5cd840, 0x427f941f, 0x65193079, 0xab8e2e83, 0x024ef2ee, 0x7ca558d8, 0x8879ffd8, 0x79fb6657), 0}, + {{0x15, 0xfd, 0xf5, 0xcf, 0x09, 0xc9, 0x07, 0x59, 0xad, 0xd2, 0x27, 0x2d, 0x57, 0x4d, 0x2b, 0xb5, 0xfe, 0x14, 0x29, 0xf9, 0xf3, 0xc1, 0x4c, 0x65, 0xe3, 0x19, 0x4b, 0xf6, 0x1b, 0x82, 0xaa, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x04, 0xcf, 0xd9, 0x06}, SECP256K1_FE_CONST(0x16d0e439, 0x46aec93f, 0x62d57eb8, 0xcde68951, 0xaf136cf4, 0xb307938d, 0xd1447411, 0xe07bffe1), 1}, + {{0x1f, 0x67, 0xed, 0xf7, 0x79, 0xa8, 0xa6, 0x49, 0xd6, 0xde, 0xf6, 0x00, 0x35, 0xf2, 0xfa, 0x22, 0xd0, 0x22, 0xdd, 0x35, 0x90, 0x79, 0xa1, 0xa1, 0x44, 0x07, 0x3d, 0x84, 0xf1, 0x9b, 0x92, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x025661f9, 0xaba9d15c, 0x3118456b, 0xbe980e3e, 0x1b8ba2e0, 0x47c737a4, 0xeb48a040, 0xbb566f6c), 0}, + {{0x1f, 0x67, 0xed, 0xf7, 0x79, 0xa8, 0xa6, 0x49, 0xd6, 0xde, 0xf6, 0x00, 0x35, 0xf2, 0xfa, 0x22, 0xd0, 0x22, 0xdd, 0x35, 0x90, 0x79, 0xa1, 0xa1, 0x44, 0x07, 0x3d, 0x84, 0xf1, 0x9b, 0x92, 0xd5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x025661f9, 0xaba9d15c, 0x3118456b, 0xbe980e3e, 0x1b8ba2e0, 0x47c737a4, 0xeb48a040, 0xbb566f6c), 0}, + {{0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x98bec3b2, 0xa351fa96, 0xcfd191c1, 0x77835193, 0x1b9e9ba9, 0xad1149f6, 0xd9eadca8, 0x0981b801), 0}, + {{0x40, 0x56, 0xa3, 0x4a, 0x21, 0x0e, 0xec, 0x78, 0x92, 0xe8, 0x82, 0x06, 0x75, 0xc8, 0x60, 0x09, 0x9f, 0x85, 0x7b, 0x26, 0xaa, 0xd8, 0x54, 0x70, 0xee, 0x6d, 0x3c, 0xf1, 0x30, 0x4a, 0x9d, 0xcf, 0x37, 0x5e, 0x70, 0x37, 0x42, 0x71, 0xf2, 0x0b, 0x13, 0xc9, 0x98, 0x6e, 0xd7, 0xd3, 0xc1, 0x77, 0x99, 0x69, 0x8c, 0xfc, 0x43, 0x5d, 0xbe, 0xd3, 0xa9, 0xf3, 0x4b, 0x38, 0xc8, 0x23, 0xc2, 0xb4}, SECP256K1_FE_CONST(0x868aac20, 0x03b29dbc, 0xad1a3e80, 0x3855e078, 0xa89d1654, 0x3ac64392, 0xd1224172, 0x98cec76e), 0}, + {{0x41, 0x97, 0xec, 0x37, 0x23, 0xc6, 0x54, 0xcf, 0xdd, 0x32, 0xab, 0x07, 0x55, 0x06, 0x64, 0x8b, 0x2f, 0xf5, 0x07, 0x03, 0x62, 0xd0, 0x1a, 0x4f, 0xff, 0x14, 0xb3, 0x36, 0xb7, 0x8f, 0x96, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb3, 0xab, 0x1e, 0x95}, SECP256K1_FE_CONST(0xba5a6314, 0x502a8952, 0xb8f456e0, 0x85928105, 0xf665377a, 0x8ce27726, 0xa5b0eb7e, 0xc1ac0286), 0}, + {{0x47, 0xeb, 0x3e, 0x20, 0x8f, 0xed, 0xcd, 0xf8, 0x23, 0x4c, 0x94, 0x21, 0xe9, 0xcd, 0x9a, 0x7a, 0xe8, 0x73, 0xbf, 0xbd, 0xbc, 0x39, 0x37, 0x23, 0xd1, 0xba, 0x1e, 0x1e, 0x6a, 0x8e, 0x6b, 0x24, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7c, 0xd1, 0x2c, 0xb1}, SECP256K1_FE_CONST(0xd192d520, 0x07e541c9, 0x807006ed, 0x0468df77, 0xfd214af0, 0xa795fe11, 0x9359666f, 0xdcf08f7c), 0}, + {{0x5e, 0xb9, 0x69, 0x6a, 0x23, 0x36, 0xfe, 0x2c, 0x3c, 0x66, 0x6b, 0x02, 0xc7, 0x55, 0xdb, 0x4c, 0x0c, 0xfd, 0x62, 0x82, 0x5c, 0x7b, 0x58, 0x9a, 0x7b, 0x7b, 0xb4, 0x42, 0xe1, 0x41, 0xc1, 0xd6, 0x93, 0x41, 0x3f, 0x00, 0x52, 0xd4, 0x9e, 0x64, 0xab, 0xec, 0x6d, 0x58, 0x31, 0xd6, 0x6c, 0x43, 0x61, 0x28, 0x30, 0xa1, 0x7d, 0xf1, 0xfe, 0x43, 0x83, 0xdb, 0x89, 0x64, 0x68, 0x10, 0x02, 0x21}, SECP256K1_FE_CONST(0xef6e1da6, 0xd6c7627e, 0x80f7a723, 0x4cb08a02, 0x2c1ee1cf, 0x29e4d0f9, 0x642ae924, 0xcef9eb38), 1}, + {{0x7b, 0xf9, 0x6b, 0x7b, 0x6d, 0xa1, 0x5d, 0x34, 0x76, 0xa2, 0xb1, 0x95, 0x93, 0x4b, 0x69, 0x0a, 0x3a, 0x3d, 0xe3, 0xe8, 0xab, 0x84, 0x74, 0x85, 0x68, 0x63, 0xb0, 0xde, 0x3a, 0xf9, 0x0b, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x50851dfc, 0x9f418c31, 0x4a437295, 0xb24feeea, 0x27af3d0c, 0xd2308348, 0xfda6e21c, 0x463e46ff), 0}, + {{0x7b, 0xf9, 0x6b, 0x7b, 0x6d, 0xa1, 0x5d, 0x34, 0x76, 0xa2, 0xb1, 0x95, 0x93, 0x4b, 0x69, 0x0a, 0x3a, 0x3d, 0xe3, 0xe8, 0xab, 0x84, 0x74, 0x85, 0x68, 0x63, 0xb0, 0xde, 0x3a, 0xf9, 0x0b, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x50851dfc, 0x9f418c31, 0x4a437295, 0xb24feeea, 0x27af3d0c, 0xd2308348, 0xfda6e21c, 0x463e46ff), 0}, + {{0x85, 0x1b, 0x1c, 0xa9, 0x45, 0x49, 0x37, 0x1c, 0x4f, 0x1f, 0x71, 0x87, 0x32, 0x1d, 0x39, 0xbf, 0x51, 0xc6, 0xb7, 0xfb, 0x61, 0xf7, 0xcb, 0xf0, 0x27, 0xc9, 0xda, 0x62, 0x02, 0x1b, 0x7a, 0x65, 0xfc, 0x54, 0xc9, 0x68, 0x37, 0xfb, 0x22, 0xb3, 0x62, 0xed, 0xa6, 0x3e, 0xc5, 0x2e, 0xc8, 0x3d, 0x81, 0xbe, 0xdd, 0x16, 0x0c, 0x11, 0xb2, 0x2d, 0x96, 0x5d, 0x9f, 0x4a, 0x6d, 0x64, 0xd2, 0x51}, SECP256K1_FE_CONST(0x3e731051, 0xe12d3323, 0x7eb324f2, 0xaa5b16bb, 0x868eb49a, 0x1aa1fadc, 0x19b6e876, 0x1b5a5f7b), 1}, + {{0x94, 0x3c, 0x2f, 0x77, 0x51, 0x08, 0xb7, 0x37, 0xfe, 0x65, 0xa9, 0x53, 0x1e, 0x19, 0xf2, 0xfc, 0x2a, 0x19, 0x7f, 0x56, 0x03, 0xe3, 0xa2, 0x88, 0x1d, 0x1d, 0x83, 0xe4, 0x00, 0x8f, 0x91, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x311c61f0, 0xab2f32b7, 0xb1f0223f, 0xa72f0a78, 0x752b8146, 0xe46107f8, 0x876dd9c4, 0xf92b2942), 0}, + {{0x94, 0x3c, 0x2f, 0x77, 0x51, 0x08, 0xb7, 0x37, 0xfe, 0x65, 0xa9, 0x53, 0x1e, 0x19, 0xf2, 0xfc, 0x2a, 0x19, 0x7f, 0x56, 0x03, 0xe3, 0xa2, 0x88, 0x1d, 0x1d, 0x83, 0xe4, 0x00, 0x8f, 0x91, 0x25, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x311c61f0, 0xab2f32b7, 0xb1f0223f, 0xa72f0a78, 0x752b8146, 0xe46107f8, 0x876dd9c4, 0xf92b2942), 0}, + {{0xa0, 0xf1, 0x84, 0x92, 0x18, 0x3e, 0x61, 0xe8, 0x06, 0x3e, 0x57, 0x36, 0x06, 0x59, 0x14, 0x21, 0xb0, 0x6b, 0xc3, 0x51, 0x36, 0x31, 0x57, 0x8a, 0x73, 0xa3, 0x9c, 0x1c, 0x33, 0x06, 0x23, 0x9f, 0x2f, 0x32, 0x90, 0x4f, 0x0d, 0x2a, 0x33, 0xec, 0xca, 0x8a, 0x54, 0x51, 0x70, 0x5b, 0xb5, 0x37, 0xd3, 0xbf, 0x44, 0xe0, 0x71, 0x22, 0x60, 0x25, 0xcd, 0xbf, 0xd2, 0x49, 0xfe, 0x0f, 0x7a, 0xd6}, SECP256K1_FE_CONST(0x97a09cf1, 0xa2eae7c4, 0x94df3c6f, 0x8a9445bf, 0xb8c09d60, 0x832f9b0b, 0x9d5eabe2, 0x5fbd14b9), 0}, + {{0xa1, 0xed, 0x0a, 0x0b, 0xd7, 0x9d, 0x8a, 0x23, 0xcf, 0xe4, 0xec, 0x5f, 0xef, 0x5b, 0xa5, 0xcc, 0xcf, 0xd8, 0x44, 0xe4, 0xff, 0x5c, 0xb4, 0xb0, 0xf2, 0xe7, 0x16, 0x27, 0x34, 0x1f, 0x1c, 0x5b, 0x17, 0xc4, 0x99, 0x24, 0x9e, 0x0a, 0xc0, 0x8d, 0x5d, 0x11, 0xea, 0x1c, 0x2c, 0x8c, 0xa7, 0x00, 0x16, 0x16, 0x55, 0x9a, 0x79, 0x94, 0xea, 0xde, 0xc9, 0xca, 0x10, 0xfb, 0x4b, 0x85, 0x16, 0xdc}, SECP256K1_FE_CONST(0x65a89640, 0x744192cd, 0xac64b2d2, 0x1ddf989c, 0xdac75007, 0x25b645be, 0xf8e2200a, 0xe39691f2), 0}, + {{0xba, 0x94, 0x59, 0x4a, 0x43, 0x27, 0x21, 0xaa, 0x35, 0x80, 0xb8, 0x4c, 0x16, 0x1d, 0x0d, 0x13, 0x4b, 0xc3, 0x54, 0xb6, 0x90, 0x40, 0x4d, 0x7c, 0xd4, 0xec, 0x57, 0xc1, 0x6d, 0x3f, 0xbe, 0x98, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xea, 0x50, 0x7d, 0xd7}, SECP256K1_FE_CONST(0x5e0d7656, 0x4aae92cb, 0x347e01a6, 0x2afd389a, 0x9aa401c7, 0x6c8dd227, 0x543dc9cd, 0x0efe685a), 0}, + {{0xbc, 0xaf, 0x72, 0x19, 0xf2, 0xf6, 0xfb, 0xf5, 0x5f, 0xe5, 0xe0, 0x62, 0xdc, 0xe0, 0xe4, 0x8c, 0x18, 0xf6, 0x81, 0x03, 0xf1, 0x0b, 0x81, 0x98, 0xe9, 0x74, 0xc1, 0x84, 0x75, 0x0e, 0x1b, 0xe3, 0x93, 0x20, 0x16, 0xcb, 0xf6, 0x9c, 0x44, 0x71, 0xbd, 0x1f, 0x65, 0x6c, 0x6a, 0x10, 0x7f, 0x19, 0x73, 0xde, 0x4a, 0xf7, 0x08, 0x6d, 0xb8, 0x97, 0x27, 0x70, 0x60, 0xe2, 0x56, 0x77, 0xf1, 0x9a}, SECP256K1_FE_CONST(0x2d97f96c, 0xac882dfe, 0x73dc44db, 0x6ce0f1d3, 0x1d624135, 0x8dd5d74e, 0xb3d3b500, 0x03d24c2b), 0}, + {{0xbc, 0xaf, 0x72, 0x19, 0xf2, 0xf6, 0xfb, 0xf5, 0x5f, 0xe5, 0xe0, 0x62, 0xdc, 0xe0, 0xe4, 0x8c, 0x18, 0xf6, 0x81, 0x03, 0xf1, 0x0b, 0x81, 0x98, 0xe9, 0x74, 0xc1, 0x84, 0x75, 0x0e, 0x1b, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x65, 0x07, 0xd0, 0x9a}, SECP256K1_FE_CONST(0xe7008afe, 0x6e8cbd50, 0x55df120b, 0xd748757c, 0x686dadb4, 0x1cce75e4, 0xaddcc5e0, 0x2ec02b44), 1}, + {{0xc5, 0x98, 0x1b, 0xae, 0x27, 0xfd, 0x84, 0x40, 0x1c, 0x72, 0xa1, 0x55, 0xe5, 0x70, 0x7f, 0xbb, 0x81, 0x1b, 0x2b, 0x62, 0x06, 0x45, 0xd1, 0x02, 0x8e, 0xa2, 0x70, 0xcb, 0xe0, 0xee, 0x22, 0x5d, 0x4b, 0x62, 0xaa, 0x4d, 0xca, 0x65, 0x06, 0xc1, 0xac, 0xdb, 0xec, 0xc0, 0x55, 0x25, 0x69, 0xb4, 0xb2, 0x14, 0x36, 0xa5, 0x69, 0x2e, 0x25, 0xd9, 0x0d, 0x3b, 0xc2, 0xeb, 0x7c, 0xe2, 0x40, 0x78}, SECP256K1_FE_CONST(0x948b40e7, 0x181713bc, 0x018ec170, 0x2d3d054d, 0x15746c59, 0xa7020730, 0xdd13ecf9, 0x85a010d7), 0}, + {{0xc8, 0x94, 0xce, 0x48, 0xbf, 0xec, 0x43, 0x30, 0x14, 0xb9, 0x31, 0xa6, 0xad, 0x42, 0x26, 0xd7, 0xdb, 0xd8, 0xea, 0xa7, 0xb6, 0xe3, 0xfa, 0xa8, 0xd0, 0xef, 0x94, 0x05, 0x2b, 0xcf, 0x8c, 0xff, 0x33, 0x6e, 0xeb, 0x39, 0x19, 0xe2, 0xb4, 0xef, 0xb7, 0x46, 0xc7, 0xf7, 0x1b, 0xbc, 0xa7, 0xe9, 0x38, 0x32, 0x30, 0xfb, 0xbc, 0x48, 0xff, 0xaf, 0xe7, 0x7e, 0x8b, 0xcc, 0x69, 0x54, 0x24, 0x71}, SECP256K1_FE_CONST(0xf1c91acd, 0xc2525330, 0xf9b53158, 0x434a4d43, 0xa1c547cf, 0xf29f1550, 0x6f5da4eb, 0x4fe8fa5a), 1}, + {{0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x872d81ed, 0x8831d999, 0x8b67cb71, 0x05243edb, 0xf86c10ed, 0xfebb786c, 0x110b02d0, 0x7b2e67cd), 0}, + {{0xd9, 0x17, 0xb7, 0x86, 0xda, 0xc3, 0x56, 0x70, 0xc3, 0x30, 0xc9, 0xc5, 0xae, 0x59, 0x71, 0xdf, 0xb4, 0x95, 0xc8, 0xae, 0x52, 0x3e, 0xd9, 0x7e, 0xe2, 0x42, 0x01, 0x17, 0xb1, 0x71, 0xf4, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x20, 0x01, 0xf6, 0xf6}, SECP256K1_FE_CONST(0xe45b71e1, 0x10b831f2, 0xbdad8651, 0x994526e5, 0x8393fde4, 0x328b1ec0, 0x4d598971, 0x42584691), 1}, + {{0xe2, 0x8b, 0xd8, 0xf5, 0x92, 0x9b, 0x46, 0x7e, 0xb7, 0x0e, 0x04, 0x33, 0x23, 0x74, 0xff, 0xb7, 0xe7, 0x18, 0x02, 0x18, 0xad, 0x16, 0xea, 0xa4, 0x6b, 0x71, 0x61, 0xaa, 0x67, 0x9e, 0xb4, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x66b8c980, 0xa75c72e5, 0x98d383a3, 0x5a62879f, 0x844242ad, 0x1e73ff12, 0xedaa59f4, 0xe58632b5), 0}, + {{0xe2, 0x8b, 0xd8, 0xf5, 0x92, 0x9b, 0x46, 0x7e, 0xb7, 0x0e, 0x04, 0x33, 0x23, 0x74, 0xff, 0xb7, 0xe7, 0x18, 0x02, 0x18, 0xad, 0x16, 0xea, 0xa4, 0x6b, 0x71, 0x61, 0xaa, 0x67, 0x9e, 0xb4, 0x26, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x66b8c980, 0xa75c72e5, 0x98d383a3, 0x5a62879f, 0x844242ad, 0x1e73ff12, 0xedaa59f4, 0xe58632b5), 0}, + {{0xe7, 0xee, 0x58, 0x14, 0xc1, 0x70, 0x6b, 0xf8, 0xa8, 0x93, 0x96, 0xa9, 0xb0, 0x32, 0xbc, 0x01, 0x4c, 0x2c, 0xac, 0x9c, 0x12, 0x11, 0x27, 0xdb, 0xf6, 0xc9, 0x92, 0x78, 0xf8, 0xbb, 0x53, 0xd1, 0xdf, 0xd0, 0x4d, 0xbc, 0xda, 0x8e, 0x35, 0x24, 0x66, 0xb6, 0xfc, 0xd5, 0xf2, 0xde, 0xa3, 0xe1, 0x7d, 0x5e, 0x13, 0x31, 0x15, 0x88, 0x6e, 0xda, 0x20, 0xdb, 0x8a, 0x12, 0xb5, 0x4d, 0xe7, 0x1b}, SECP256K1_FE_CONST(0xe842c6e3, 0x529b2342, 0x70a5e977, 0x44edc34a, 0x04d7ba94, 0xe44b6d25, 0x23c9cf01, 0x95730a50), 1}, + {{0xf2, 0x92, 0xe4, 0x68, 0x25, 0xf9, 0x22, 0x5a, 0xd2, 0x3d, 0xc0, 0x57, 0xc1, 0xd9, 0x1c, 0x4f, 0x57, 0xfc, 0xb1, 0x38, 0x6f, 0x29, 0xef, 0x10, 0x48, 0x1c, 0xb1, 0xd2, 0x25, 0x18, 0x59, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x11, 0xc9, 0x89}, SECP256K1_FE_CONST(0x3cea2c53, 0xb8b01701, 0x66ac7da6, 0x7194694a, 0xdacc84d5, 0x6389225e, 0x330134da, 0xb85a4d55), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0xedd1fd3e, 0x327ce90c, 0xc7a35426, 0x14289aee, 0x9682003e, 0x9cf7dcc9, 0xcf2ca974, 0x3be5aa0c), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x01, 0xd3, 0x47, 0x5b, 0xf7, 0x65, 0x5b, 0x0f, 0xb2, 0xd8, 0x52, 0x92, 0x10, 0x35, 0xb2, 0xef, 0x60, 0x7f, 0x49, 0x06, 0x9b, 0x97, 0x45, 0x4e, 0x67, 0x95, 0x25, 0x10, 0x62, 0x74, 0x17, 0x71}, SECP256K1_FE_CONST(0xb5da00b7, 0x3cd65605, 0x20e7c364, 0x086e7cd2, 0x3a34bf60, 0xd0e707be, 0x9fc34d4c, 0xd5fdfa2c), 1}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee}, SECP256K1_FE_CONST(0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaa9, 0xfffffd6b), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x82, 0x27, 0x7c, 0x4a, 0x71, 0xf9, 0xd2, 0x2e, 0x66, 0xec, 0xe5, 0x23, 0xf8, 0xfa, 0x08, 0x74, 0x1a, 0x7c, 0x09, 0x12, 0xc6, 0x6a, 0x69, 0xce, 0x68, 0x51, 0x4b, 0xfd, 0x35, 0x15, 0xb4, 0x9f}, SECP256K1_FE_CONST(0xf482f2e2, 0x41753ad0, 0xfb89150d, 0x8491dc1e, 0x34ff0b8a, 0xcfbb442c, 0xfe999e2e, 0x5e6fd1d2), 1}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x84, 0x21, 0xcc, 0x93, 0x0e, 0x77, 0xc9, 0xf5, 0x14, 0xb6, 0x91, 0x5c, 0x3d, 0xbe, 0x2a, 0x94, 0xc6, 0xd8, 0xf6, 0x90, 0xb5, 0xb7, 0x39, 0x86, 0x4b, 0xa6, 0x78, 0x9f, 0xb8, 0xa5, 0x5d, 0xd0}, SECP256K1_FE_CONST(0x9f59c402, 0x75f5085a, 0x006f05da, 0xe77eb98c, 0x6fd0db1a, 0xb4a72ac4, 0x7eae90a4, 0xfc9e57e0), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0xd1, 0x9c, 0x18, 0x2d, 0x27, 0x59, 0xcd, 0x99, 0x82, 0x42, 0x28, 0xd9, 0x47, 0x99, 0xf8, 0xc6, 0x55, 0x7c, 0x38, 0xa1, 0xc0, 0xd6, 0x77, 0x9b, 0x9d, 0x4b, 0x72, 0x9c, 0x6f, 0x1c, 0xcc, 0x42}, SECP256K1_FE_CONST(0x70720db7, 0xe238d041, 0x21f5b1af, 0xd8cc5ad9, 0xd18944c6, 0xbdc94881, 0xf502b7a3, 0xaf3aecff), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0xedd1fd3e, 0x327ce90c, 0xc7a35426, 0x14289aee, 0x9682003e, 0x9cf7dcc9, 0xcf2ca974, 0x3be5aa0c), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x26, 0x64, 0xbb, 0xd5}, SECP256K1_FE_CONST(0x50873db3, 0x1badcc71, 0x890e4f67, 0x753a6575, 0x7f97aaa7, 0xdd5f1e82, 0xb753ace3, 0x2219064b), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x28, 0xde, 0x7d}, SECP256K1_FE_CONST(0x1eea9cc5, 0x9cfcf2fa, 0x151ac6c2, 0x74eea411, 0x0feb4f7b, 0x68c59657, 0x32e9992e, 0x976ef68e), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcb, 0xcf, 0xb7, 0xe7}, SECP256K1_FE_CONST(0x12303941, 0xaedc2088, 0x80735b1f, 0x1795c8e5, 0x5be520ea, 0x93e10335, 0x7b5d2adb, 0x7ed59b8e), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x11, 0x3a, 0xd9}, SECP256K1_FE_CONST(0x7eed6b70, 0xe7b0767c, 0x7d7feac0, 0x4e57aa2a, 0x12fef5e0, 0xf48f878f, 0xcbb88b3b, 0x6b5e0783), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13, 0xce, 0xa4, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x64998443, 0x5b62b4a2, 0x5d40c613, 0x3e8d9ab8, 0xc53d4b05, 0x9ee8a154, 0xa3be0fcf, 0x4e892edb), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13, 0xce, 0xa4, 0xa7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x64998443, 0x5b62b4a2, 0x5d40c613, 0x3e8d9ab8, 0xc53d4b05, 0x9ee8a154, 0xa3be0fcf, 0x4e892edb), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x02, 0x8c, 0x59, 0x00, 0x63, 0xf6, 0x4d, 0x5a, 0x7f, 0x1c, 0x14, 0x91, 0x5c, 0xd6, 0x1e, 0xac, 0x88, 0x6a, 0xb2, 0x95, 0xbe, 0xbd, 0x91, 0x99, 0x25, 0x04, 0xcf, 0x77, 0xed, 0xb0, 0x28, 0xbd, 0xd6, 0x26, 0x7f}, SECP256K1_FE_CONST(0x3fde5713, 0xf8282eea, 0xd7d39d42, 0x01f44a7c, 0x85a5ac8a, 0x0681f35e, 0x54085c6b, 0x69543374), 1}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x27, 0x15, 0xde, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x3524f77f, 0xa3a6eb43, 0x89c3cb5d, 0x27f1f914, 0x62086429, 0xcd6c0cb0, 0xdf43ea8f, 0x1e7b3fb4), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x27, 0x15, 0xde, 0x86, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x3524f77f, 0xa3a6eb43, 0x89c3cb5d, 0x27f1f914, 0x62086429, 0xcd6c0cb0, 0xdf43ea8f, 0x1e7b3fb4), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2c, 0x2c, 0x57, 0x09, 0xe7, 0x15, 0x6c, 0x41, 0x77, 0x17, 0xf2, 0xfe, 0xab, 0x14, 0x71, 0x41, 0xec, 0x3d, 0xa1, 0x9f, 0xb7, 0x59, 0x57, 0x5c, 0xc6, 0xe3, 0x7b, 0x2e, 0xa5, 0xac, 0x93, 0x09, 0xf2, 0x6f, 0x0f, 0x66}, SECP256K1_FE_CONST(0xd2469ab3, 0xe04acbb2, 0x1c65a180, 0x9f39caaf, 0xe7a77c13, 0xd10f9dd3, 0x8f391c01, 0xdc499c52), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3a, 0x08, 0xcc, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x60, 0xe9, 0xf0}, SECP256K1_FE_CONST(0x38e2a5ce, 0x6a93e795, 0xe16d2c39, 0x8bc99f03, 0x69202ce2, 0x1e8f09d5, 0x6777b40f, 0xc512bccc), 1}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0x91, 0x25, 0x7d, 0x93, 0x20, 0x16, 0xcb, 0xf6, 0x9c, 0x44, 0x71, 0xbd, 0x1f, 0x65, 0x6c, 0x6a, 0x10, 0x7f, 0x19, 0x73, 0xde, 0x4a, 0xf7, 0x08, 0x6d, 0xb8, 0x97, 0x27, 0x70, 0x60, 0xe2, 0x56, 0x77, 0xf1, 0x9a}, SECP256K1_FE_CONST(0x864b3dc9, 0x02c37670, 0x9c10a93a, 0xd4bbe29f, 0xce0012f3, 0xdc8672c6, 0x286bba28, 0xd7d6d6fc), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x79, 0x5d, 0x6c, 0x1c, 0x32, 0x2c, 0xad, 0xf5, 0x99, 0xdb, 0xb8, 0x64, 0x81, 0x52, 0x2b, 0x3c, 0xc5, 0x5f, 0x15, 0xa6, 0x79, 0x32, 0xdb, 0x2a, 0xfa, 0x01, 0x11, 0xd9, 0xed, 0x69, 0x81, 0xbc, 0xd1, 0x24, 0xbf, 0x44}, SECP256K1_FE_CONST(0x766dfe4a, 0x700d9bee, 0x288b903a, 0xd58870e3, 0xd4fe2f0e, 0xf780bcac, 0x5c823f32, 0x0d9a9bef), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8e, 0x42, 0x6f, 0x03, 0x92, 0x38, 0x90, 0x78, 0xc1, 0x2b, 0x1a, 0x89, 0xe9, 0x54, 0x2f, 0x05, 0x93, 0xbc, 0x96, 0xb6, 0xbf, 0xde, 0x82, 0x24, 0xf8, 0x65, 0x4e, 0xf5, 0xd5, 0xcd, 0xa9, 0x35, 0xa3, 0x58, 0x21, 0x94}, SECP256K1_FE_CONST(0xfaec7bc1, 0x987b6323, 0x3fbc5f95, 0x6edbf37d, 0x54404e74, 0x61c58ab8, 0x631bc68e, 0x451a0478), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x91, 0x19, 0x21, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x45, 0xf0, 0xf1, 0xeb}, SECP256K1_FE_CONST(0xec29a50b, 0xae138dbf, 0x7d8e2482, 0x5006bb5f, 0xc1a2cc12, 0x43ba335b, 0xc6116fb9, 0xe498ec1f), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x98, 0xeb, 0x9a, 0xb7, 0x6e, 0x84, 0x49, 0x9c, 0x48, 0x3b, 0x3b, 0xf0, 0x62, 0x14, 0xab, 0xfe, 0x06, 0x5d, 0xdd, 0xf4, 0x3b, 0x86, 0x01, 0xde, 0x59, 0x6d, 0x63, 0xb9, 0xe4, 0x5a, 0x16, 0x6a, 0x58, 0x05, 0x41, 0xfe}, SECP256K1_FE_CONST(0x1e0ff2de, 0xe9b09b13, 0x6292a9e9, 0x10f0d6ac, 0x3e552a64, 0x4bba39e6, 0x4e9dd3e3, 0xbbd3d4d4), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9b, 0x77, 0xb7, 0xf2, 0xc7, 0x4d, 0x99, 0xef, 0xce, 0xaa, 0x55, 0x0f, 0x1a, 0xd1, 0xc0, 0xf4, 0x3f, 0x46, 0xe7, 0xff, 0x1e, 0xe3, 0xbd, 0x01, 0x62, 0xb7, 0xbf, 0x55, 0xf2, 0x96, 0x5d, 0xa9, 0xc3, 0x45, 0x06, 0x46}, SECP256K1_FE_CONST(0x8b7dd5c3, 0xedba9ee9, 0x7b70eff4, 0x38f22dca, 0x9849c825, 0x4a2f3345, 0xa0a572ff, 0xeaae0928), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9b, 0x77, 0xb7, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x6c, 0xa8, 0x96}, SECP256K1_FE_CONST(0x0881950c, 0x8f51d6b9, 0xa6387465, 0xd5f12609, 0xef1bb254, 0x12a08a74, 0xcb2dfb20, 0x0c74bfbf), 1}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa2, 0xf5, 0xcd, 0x83, 0x88, 0x16, 0xc1, 0x6c, 0x4f, 0xe8, 0xa1, 0x66, 0x1d, 0x60, 0x6f, 0xdb, 0x13, 0xcf, 0x9a, 0xf0, 0x4b, 0x97, 0x9a, 0x2e, 0x15, 0x9a, 0x09, 0x40, 0x9e, 0xbc, 0x86, 0x45, 0xd5, 0x8f, 0xde, 0x02}, SECP256K1_FE_CONST(0x2f083207, 0xb9fd9b55, 0x0063c31c, 0xd62b8746, 0xbd543bdc, 0x5bbf10e3, 0xa35563e9, 0x27f440c8), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb1, 0x3f, 0x75, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x4f51e0be, 0x078e0cdd, 0xab274215, 0x6adba7e7, 0xa148e731, 0x57072fd6, 0x18cd6094, 0x2b146bd0), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb1, 0x3f, 0x75, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x4f51e0be, 0x078e0cdd, 0xab274215, 0x6adba7e7, 0xa148e731, 0x57072fd6, 0x18cd6094, 0x2b146bd0), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xbc, 0x1f, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x16c2ccb5, 0x4352ff4b, 0xd794f6ef, 0xd613c721, 0x97ab7082, 0xda5b563b, 0xdf9cb3ed, 0xaafe74c2), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xbc, 0x1f, 0x8d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x16c2ccb5, 0x4352ff4b, 0xd794f6ef, 0xd613c721, 0x97ab7082, 0xda5b563b, 0xdf9cb3ed, 0xaafe74c2), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x64, 0xd1, 0x62, 0x75, 0x05, 0x46, 0xce, 0x42, 0xb0, 0x43, 0x13, 0x61, 0xe5, 0x2d, 0x4f, 0x52, 0x42, 0xd8, 0xf2, 0x4f, 0x33, 0xe6, 0xb1, 0xf9, 0x9b, 0x59, 0x16, 0x47, 0xcb, 0xc8, 0x08, 0xf4, 0x62, 0xaf, 0x51}, SECP256K1_FE_CONST(0xd41244d1, 0x1ca4f652, 0x40687759, 0xf95ca9ef, 0xbab767ed, 0xedb38fd1, 0x8c36e18c, 0xd3b6f6a9), 1}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xe5, 0xbe, 0x52, 0x37, 0x2d, 0xd6, 0xe8, 0x94, 0xb2, 0xa3, 0x26, 0xfc, 0x36, 0x05, 0xa6, 0xe8, 0xf3, 0xc6, 0x9c, 0x71, 0x0b, 0xf2, 0x7d, 0x63, 0x0d, 0xfe, 0x20, 0x04, 0x98, 0x8b, 0x78, 0xeb, 0x6e, 0xab, 0x36}, SECP256K1_FE_CONST(0x64bf84dd, 0x5e03670f, 0xdb24c0f5, 0xd3c2c365, 0x736f51db, 0x6c92d950, 0x10716ad2, 0xd36134c8), 0}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfb, 0xb9, 0x82, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xd6, 0xdb, 0x1f}, SECP256K1_FE_CONST(0x1c92ccdf, 0xcf4ac550, 0xc28db57c, 0xff0c8515, 0xcb26936c, 0x786584a7, 0x0114008d, 0x6c33a34b), 0}, +}; + +/* Set of expected ellswift_xdh BIP324 shared secrets, given private key, encodings, initiating, + * taken from the BIP324 test vectors. Created using an independent implementation, and tested + * against the paper authors' decoding code. */ +static const struct ellswift_xdh_test ellswift_xdh_tests_bip324[] = { + {{0x61, 0x06, 0x2e, 0xa5, 0x07, 0x1d, 0x80, 0x0b, 0xbf, 0xd5, 0x9e, 0x2e, 0x8b, 0x53, 0xd4, 0x7d, 0x19, 0x4b, 0x09, 0x5a, 0xe5, 0xa4, 0xdf, 0x04, 0x93, 0x6b, 0x49, 0x77, 0x2e, 0xf0, 0xd4, 0xd7}, {0xec, 0x0a, 0xdf, 0xf2, 0x57, 0xbb, 0xfe, 0x50, 0x0c, 0x18, 0x8c, 0x80, 0xb4, 0xfd, 0xd6, 0x40, 0xf6, 0xb4, 0x5a, 0x48, 0x2b, 0xbc, 0x15, 0xfc, 0x7c, 0xef, 0x59, 0x31, 0xde, 0xff, 0x0a, 0xa1, 0x86, 0xf6, 0xeb, 0x9b, 0xba, 0x7b, 0x85, 0xdc, 0x4d, 0xcc, 0x28, 0xb2, 0x87, 0x22, 0xde, 0x1e, 0x3d, 0x91, 0x08, 0xb9, 0x85, 0xe2, 0x96, 0x70, 0x45, 0x66, 0x8f, 0x66, 0x09, 0x8e, 0x47, 0x5b}, {0xa4, 0xa9, 0x4d, 0xfc, 0xe6, 0x9b, 0x4a, 0x2a, 0x0a, 0x09, 0x93, 0x13, 0xd1, 0x0f, 0x9f, 0x7e, 0x7d, 0x64, 0x9d, 0x60, 0x50, 0x1c, 0x9e, 0x1d, 0x27, 0x4c, 0x30, 0x0e, 0x0d, 0x89, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xaf, 0x88, 0xd5}, 1, {0xc6, 0x99, 0x2a, 0x11, 0x7f, 0x5e, 0xdb, 0xea, 0x70, 0xc3, 0xf5, 0x11, 0xd3, 0x2d, 0x26, 0xb9, 0x79, 0x8b, 0xe4, 0xb8, 0x1a, 0x62, 0xea, 0xee, 0x1a, 0x5a, 0xca, 0xa8, 0x45, 0x9a, 0x35, 0x92}}, + {{0x1f, 0x9c, 0x58, 0x1b, 0x35, 0x23, 0x18, 0x38, 0xf0, 0xf1, 0x7c, 0xf0, 0xc9, 0x79, 0x83, 0x5b, 0xac, 0xcb, 0x7f, 0x3a, 0xbb, 0xbb, 0x96, 0xff, 0xcc, 0x31, 0x8a, 0xb7, 0x1e, 0x6e, 0x12, 0x6f}, {0xa1, 0x85, 0x5e, 0x10, 0xe9, 0x4e, 0x00, 0xba, 0xa2, 0x30, 0x41, 0xd9, 0x16, 0xe2, 0x59, 0xf7, 0x04, 0x4e, 0x49, 0x1d, 0xa6, 0x17, 0x12, 0x69, 0x69, 0x47, 0x63, 0xf0, 0x18, 0xc7, 0xe6, 0x36, 0x93, 0xd2, 0x95, 0x75, 0xdc, 0xb4, 0x64, 0xac, 0x81, 0x6b, 0xaa, 0x1b, 0xe3, 0x53, 0xba, 0x12, 0xe3, 0x87, 0x6c, 0xba, 0x76, 0x28, 0xbd, 0x0b, 0xd8, 0xe7, 0x55, 0xe7, 0x21, 0xeb, 0x01, 0x40}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0, {0xa0, 0x13, 0x8f, 0x56, 0x4f, 0x74, 0xd0, 0xad, 0x70, 0xbc, 0x33, 0x7d, 0xac, 0xc9, 0xd0, 0xbf, 0x1d, 0x23, 0x49, 0x36, 0x4c, 0xaf, 0x11, 0x88, 0xa1, 0xe6, 0xe8, 0xdd, 0xb3, 0xb7, 0xb1, 0x84}}, + {{0x02, 0x86, 0xc4, 0x1c, 0xd3, 0x09, 0x13, 0xdb, 0x0f, 0xdf, 0xf7, 0xa6, 0x4e, 0xbd, 0xa5, 0xc8, 0xe3, 0xe7, 0xce, 0xf1, 0x0f, 0x2a, 0xeb, 0xc0, 0x0a, 0x76, 0x50, 0x44, 0x3c, 0xf4, 0xc6, 0x0d}, {0xd1, 0xee, 0x8a, 0x93, 0xa0, 0x11, 0x30, 0xcb, 0xf2, 0x99, 0x24, 0x9a, 0x25, 0x8f, 0x94, 0xfe, 0xb5, 0xf4, 0x69, 0xe7, 0xd0, 0xf2, 0xf2, 0x8f, 0x69, 0xee, 0x5e, 0x9a, 0xa8, 0xf9, 0xb5, 0x4a, 0x60, 0xf2, 0xc3, 0xff, 0x2d, 0x02, 0x36, 0x34, 0xec, 0x7f, 0x41, 0x27, 0xa9, 0x6c, 0xc1, 0x16, 0x62, 0xe4, 0x02, 0x89, 0x4c, 0xf1, 0xf6, 0x94, 0xfb, 0x9a, 0x7e, 0xaa, 0x5f, 0x1d, 0x92, 0x44}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x22, 0xd5, 0xe4, 0x41, 0x52, 0x4d, 0x57, 0x1a, 0x52, 0xb3, 0xde, 0xf1, 0x26, 0x18, 0x9d, 0x3f, 0x41, 0x68, 0x90, 0xa9, 0x9d, 0x4d, 0xa6, 0xed, 0xe2, 0xb0, 0xcd, 0xe1, 0x76, 0x0c, 0xe2, 0xc3, 0xf9, 0x84, 0x57, 0xae}, 1, {0x25, 0x0b, 0x93, 0x57, 0x0d, 0x41, 0x11, 0x49, 0x10, 0x5a, 0xb8, 0xcb, 0x0b, 0xc5, 0x07, 0x99, 0x14, 0x90, 0x63, 0x06, 0x36, 0x8c, 0x23, 0xe9, 0xd7, 0x7c, 0x2a, 0x33, 0x26, 0x5b, 0x99, 0x4c}}, + {{0x6c, 0x77, 0x43, 0x2d, 0x1f, 0xda, 0x31, 0xe9, 0xf9, 0x42, 0xf8, 0xaf, 0x44, 0x60, 0x7e, 0x10, 0xf3, 0xad, 0x38, 0xa6, 0x5f, 0x8a, 0x4b, 0xdd, 0xae, 0x82, 0x3e, 0x5e, 0xff, 0x90, 0xdc, 0x38}, {0xd2, 0x68, 0x50, 0x70, 0xc1, 0xe6, 0x37, 0x6e, 0x63, 0x3e, 0x82, 0x52, 0x96, 0x63, 0x4f, 0xd4, 0x61, 0xfa, 0x9e, 0x5b, 0xdf, 0x21, 0x09, 0xbc, 0xeb, 0xd7, 0x35, 0xe5, 0xa9, 0x1f, 0x3e, 0x58, 0x7c, 0x5c, 0xb7, 0x82, 0xab, 0xb7, 0x97, 0xfb, 0xf6, 0xbb, 0x50, 0x74, 0xfd, 0x15, 0x42, 0xa4, 0x74, 0xf2, 0xa4, 0x5b, 0x67, 0x37, 0x63, 0xec, 0x2d, 0xb7, 0xfb, 0x99, 0xb7, 0x37, 0xbb, 0xb9}, {0x56, 0xbd, 0x0c, 0x06, 0xf1, 0x03, 0x52, 0xc3, 0xa1, 0xa9, 0xf4, 0xb4, 0xc9, 0x2f, 0x6f, 0xa2, 0xb2, 0x6d, 0xf1, 0x24, 0xb5, 0x78, 0x78, 0x35, 0x3c, 0x1f, 0xc6, 0x91, 0xc5, 0x1a, 0xbe, 0xa7, 0x7c, 0x88, 0x17, 0xda, 0xee, 0xb9, 0xfa, 0x54, 0x6b, 0x77, 0xc8, 0xda, 0xf7, 0x9d, 0x89, 0xb2, 0x2b, 0x0e, 0x1b, 0x87, 0x57, 0x4e, 0xce, 0x42, 0x37, 0x1f, 0x00, 0x23, 0x7a, 0xa9, 0xd8, 0x3a}, 0, {0x19, 0x18, 0xb7, 0x41, 0xef, 0x5f, 0x9d, 0x1d, 0x76, 0x70, 0xb0, 0x50, 0xc1, 0x52, 0xb4, 0xa4, 0xea, 0xd2, 0xc3, 0x1b, 0xe9, 0xae, 0xcb, 0x06, 0x81, 0xc0, 0xcd, 0x43, 0x24, 0x15, 0x08, 0x53}}, + {{0xa6, 0xec, 0x25, 0x12, 0x7c, 0xa1, 0xaa, 0x4c, 0xf1, 0x6b, 0x20, 0x08, 0x4b, 0xa1, 0xe6, 0x51, 0x6b, 0xaa, 0xe4, 0xd3, 0x24, 0x22, 0x28, 0x8e, 0x9b, 0x36, 0xd8, 0xbd, 0xdd, 0x2d, 0xe3, 0x5a}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x05, 0x3d, 0x7e, 0xcc, 0xa5, 0x3e, 0x33, 0xe1, 0x85, 0xa8, 0xb9, 0xbe, 0x4e, 0x76, 0x99, 0xa9, 0x7c, 0x6f, 0xf4, 0xc7, 0x95, 0x52, 0x2e, 0x59, 0x18, 0xab, 0x7c, 0xd6, 0xb6, 0x88, 0x4f, 0x67, 0xe6, 0x83, 0xf3, 0xdc}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, 0x73, 0x0b, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 1, {0xdd, 0x21, 0x0a, 0xa6, 0x62, 0x9f, 0x20, 0xbb, 0x32, 0x8e, 0x5d, 0x89, 0xda, 0xa6, 0xeb, 0x2a, 0xc3, 0xd1, 0xc6, 0x58, 0xa7, 0x25, 0x53, 0x6f, 0xf1, 0x54, 0xf3, 0x1b, 0x53, 0x6c, 0x23, 0xb2}}, + {{0x0a, 0xf9, 0x52, 0x65, 0x9e, 0xd7, 0x6f, 0x80, 0xf5, 0x85, 0x96, 0x6b, 0x95, 0xab, 0x6e, 0x6f, 0xd6, 0x86, 0x54, 0x67, 0x28, 0x27, 0x87, 0x86, 0x84, 0xc8, 0xb5, 0x47, 0xb1, 0xb9, 0x4f, 0x5a}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc8, 0x10, 0x17, 0xfd, 0x92, 0xfd, 0x31, 0x63, 0x7c, 0x26, 0xc9, 0x06, 0xb4, 0x20, 0x92, 0xe1, 0x1c, 0xc0, 0xd3, 0xaf, 0xae, 0x8d, 0x90, 0x19, 0xd2, 0x57, 0x8a, 0xf2, 0x27, 0x35, 0xce, 0x7b, 0xc4, 0x69, 0xc7, 0x2d}, {0x96, 0x52, 0xd7, 0x8b, 0xae, 0xfc, 0x02, 0x8c, 0xd3, 0x7a, 0x6a, 0x92, 0x62, 0x5b, 0x8b, 0x8f, 0x85, 0xfd, 0xe1, 0xe4, 0xc9, 0x44, 0xad, 0x3f, 0x20, 0xe1, 0x98, 0xbe, 0xf8, 0xc0, 0x2f, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xe9, 0x18, 0x70}, 0, {0x35, 0x68, 0xf2, 0xae, 0xa2, 0xe1, 0x4e, 0xf4, 0xee, 0x4a, 0x3c, 0x2a, 0x8b, 0x8d, 0x31, 0xbc, 0x5e, 0x31, 0x87, 0xba, 0x86, 0xdb, 0x10, 0x73, 0x9b, 0x4f, 0xf8, 0xec, 0x92, 0xff, 0x66, 0x55}}, + {{0xf9, 0x0e, 0x08, 0x0c, 0x64, 0xb0, 0x58, 0x24, 0xc5, 0xa2, 0x4b, 0x25, 0x01, 0xd5, 0xae, 0xaf, 0x08, 0xaf, 0x38, 0x72, 0xee, 0x86, 0x0a, 0xa8, 0x0b, 0xdc, 0xd4, 0x30, 0xf7, 0xb6, 0x34, 0x94}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0x51, 0x73, 0x76, 0x5d, 0xc2, 0x02, 0xcf, 0x02, 0x9a, 0xd3, 0xf1, 0x54, 0x79, 0x73, 0x5d, 0x57, 0x69, 0x7a, 0xf1, 0x2b, 0x01, 0x31, 0xdd, 0x21, 0x43, 0x0d, 0x57, 0x72, 0xe4, 0xef, 0x11, 0x47, 0x4d, 0x58, 0xb9}, {0x12, 0xa5, 0x0f, 0x3f, 0xaf, 0xea, 0x7c, 0x1e, 0xea, 0xda, 0x4c, 0xf8, 0xd3, 0x37, 0x77, 0x70, 0x4b, 0x77, 0x36, 0x14, 0x53, 0xaf, 0xc8, 0x3b, 0xda, 0x91, 0xee, 0xf3, 0x49, 0xae, 0x04, 0x4d, 0x20, 0x12, 0x6c, 0x62, 0x00, 0x54, 0x7e, 0xa5, 0xa6, 0x91, 0x17, 0x76, 0xc0, 0x5d, 0xee, 0x2a, 0x7f, 0x1a, 0x9b, 0xa7, 0xdf, 0xba, 0xbb, 0xbd, 0x27, 0x3c, 0x3e, 0xf2, 0x9e, 0xf4, 0x6e, 0x46}, 1, {0xe2, 0x54, 0x61, 0xfb, 0x0e, 0x4c, 0x16, 0x2e, 0x18, 0x12, 0x3e, 0xcd, 0xe8, 0x83, 0x42, 0xd5, 0x4d, 0x44, 0x96, 0x31, 0xe9, 0xb7, 0x5a, 0x26, 0x6f, 0xd9, 0x26, 0x0c, 0x2b, 0xb2, 0xf4, 0x1d}}, +}; + +/** This is a hasher for ellswift_xdh which just returns the shared X coordinate. + * + * This is generally a bad idea as it means changes to the encoding of the + * exchanged public keys do not affect the shared secret. However, it's used here + * in tests to be able to verify the X coordinate through other means. + */ +static int ellswift_xdh_hash_x32(unsigned char *output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { + (void)ell_a64; + (void)ell_b64; + (void)data; + memcpy(output, x32, 32); + return 1; +} + +void run_ellswift_tests(void) { + int i = 0; + /* Test vectors. */ + for (i = 0; (unsigned)i < sizeof(ellswift_xswiftec_inv_tests) / sizeof(ellswift_xswiftec_inv_tests[0]); ++i) { + const struct ellswift_xswiftec_inv_test *testcase = &ellswift_xswiftec_inv_tests[i]; + int c; + for (c = 0; c < 8; ++c) { + rustsecp256k1_v0_9_0_fe t; + int ret = rustsecp256k1_v0_9_0_ellswift_xswiftec_inv_var(&t, &testcase->x, &testcase->u, c); + CHECK(ret == ((testcase->enc_bitmap >> c) & 1)); + if (ret) { + rustsecp256k1_v0_9_0_fe x2; + CHECK(check_fe_equal(&t, &testcase->encs[c])); + rustsecp256k1_v0_9_0_ellswift_xswiftec_var(&x2, &testcase->u, &testcase->encs[c]); + CHECK(check_fe_equal(&testcase->x, &x2)); + } + } + } + for (i = 0; (unsigned)i < sizeof(ellswift_decode_tests) / sizeof(ellswift_decode_tests[0]); ++i) { + const struct ellswift_decode_test *testcase = &ellswift_decode_tests[i]; + rustsecp256k1_v0_9_0_pubkey pubkey; + rustsecp256k1_v0_9_0_ge ge; + int ret; + ret = rustsecp256k1_v0_9_0_ellswift_decode(CTX, &pubkey, testcase->enc); + CHECK(ret); + ret = rustsecp256k1_v0_9_0_pubkey_load(CTX, &ge, &pubkey); + CHECK(ret); + CHECK(check_fe_equal(&testcase->x, &ge.x)); + CHECK(rustsecp256k1_v0_9_0_fe_is_odd(&ge.y) == testcase->odd_y); + } + for (i = 0; (unsigned)i < sizeof(ellswift_xdh_tests_bip324) / sizeof(ellswift_xdh_tests_bip324[0]); ++i) { + const struct ellswift_xdh_test *test = &ellswift_xdh_tests_bip324[i]; + unsigned char shared_secret[32]; + int ret; + int party = !test->initiating; + const unsigned char* ell_a64 = party ? test->ellswift_theirs : test->ellswift_ours; + const unsigned char* ell_b64 = party ? test->ellswift_ours : test->ellswift_theirs; + ret = rustsecp256k1_v0_9_0_ellswift_xdh(CTX, shared_secret, + ell_a64, ell_b64, + test->priv_ours, + party, + rustsecp256k1_v0_9_0_ellswift_xdh_hash_function_bip324, + NULL); + CHECK(ret); + CHECK(rustsecp256k1_v0_9_0_memcmp_var(shared_secret, test->shared_secret, 32) == 0); + } + /* Verify that rustsecp256k1_v0_9_0_ellswift_encode + decode roundtrips. */ + for (i = 0; i < 1000 * COUNT; i++) { + unsigned char rnd32[32]; + unsigned char ell64[64]; + rustsecp256k1_v0_9_0_ge g, g2; + rustsecp256k1_v0_9_0_pubkey pubkey, pubkey2; + /* Generate random public key and random randomizer. */ + random_group_element_test(&g); + rustsecp256k1_v0_9_0_pubkey_save(&pubkey, &g); + rustsecp256k1_v0_9_0_testrand256(rnd32); + /* Convert the public key to ElligatorSwift and back. */ + rustsecp256k1_v0_9_0_ellswift_encode(CTX, ell64, &pubkey, rnd32); + rustsecp256k1_v0_9_0_ellswift_decode(CTX, &pubkey2, ell64); + rustsecp256k1_v0_9_0_pubkey_load(CTX, &g2, &pubkey2); + /* Compare with original. */ + ge_equals_ge(&g, &g2); + } + /* Verify the behavior of rustsecp256k1_v0_9_0_ellswift_create */ + for (i = 0; i < 400 * COUNT; i++) { + unsigned char auxrnd32[32], sec32[32]; + rustsecp256k1_v0_9_0_scalar sec; + rustsecp256k1_v0_9_0_gej res; + rustsecp256k1_v0_9_0_ge dec; + rustsecp256k1_v0_9_0_pubkey pub; + unsigned char ell64[64]; + int ret; + /* Generate random secret key and random randomizer. */ + if (i & 1) rustsecp256k1_v0_9_0_testrand256_test(auxrnd32); + random_scalar_order_test(&sec); + rustsecp256k1_v0_9_0_scalar_get_b32(sec32, &sec); + /* Construct ElligatorSwift-encoded public keys for that key. */ + ret = rustsecp256k1_v0_9_0_ellswift_create(CTX, ell64, sec32, (i & 1) ? auxrnd32 : NULL); + CHECK(ret); + /* Decode it, and compare with traditionally-computed public key. */ + rustsecp256k1_v0_9_0_ellswift_decode(CTX, &pub, ell64); + rustsecp256k1_v0_9_0_pubkey_load(CTX, &dec, &pub); + rustsecp256k1_v0_9_0_ecmult(&res, NULL, &rustsecp256k1_v0_9_0_scalar_zero, &sec); + ge_equals_gej(&dec, &res); + } + /* Verify that rustsecp256k1_v0_9_0_ellswift_xdh computes the right shared X coordinate. */ + for (i = 0; i < 800 * COUNT; i++) { + unsigned char ell64[64], sec32[32], share32[32]; + rustsecp256k1_v0_9_0_scalar sec; + rustsecp256k1_v0_9_0_ge dec, res; + rustsecp256k1_v0_9_0_fe share_x; + rustsecp256k1_v0_9_0_gej decj, resj; + rustsecp256k1_v0_9_0_pubkey pub; + int ret; + /* Generate random secret key. */ + random_scalar_order_test(&sec); + rustsecp256k1_v0_9_0_scalar_get_b32(sec32, &sec); + /* Generate random ElligatorSwift encoding for the remote key and decode it. */ + rustsecp256k1_v0_9_0_testrand256_test(ell64); + rustsecp256k1_v0_9_0_testrand256_test(ell64 + 32); + rustsecp256k1_v0_9_0_ellswift_decode(CTX, &pub, ell64); + rustsecp256k1_v0_9_0_pubkey_load(CTX, &dec, &pub); + rustsecp256k1_v0_9_0_gej_set_ge(&decj, &dec); + /* Compute the X coordinate of seckey*pubkey using ellswift_xdh. Note that we + * pass ell64 as claimed (but incorrect) encoding for sec32 here; this works + * because the "hasher" function we use here ignores the ell64 arguments. */ + ret = rustsecp256k1_v0_9_0_ellswift_xdh(CTX, share32, ell64, ell64, sec32, i & 1, &ellswift_xdh_hash_x32, NULL); + CHECK(ret); + (void)rustsecp256k1_v0_9_0_fe_set_b32_limit(&share_x, share32); /* no overflow is possible */ + rustsecp256k1_v0_9_0_fe_verify(&share_x); + /* Compute seckey*pubkey directly. */ + rustsecp256k1_v0_9_0_ecmult(&resj, &decj, &sec, NULL); + rustsecp256k1_v0_9_0_ge_set_gej(&res, &resj); + /* Compare. */ + CHECK(check_fe_equal(&res.x, &share_x)); + } + /* Verify the joint behavior of rustsecp256k1_v0_9_0_ellswift_xdh */ + for (i = 0; i < 200 * COUNT; i++) { + unsigned char auxrnd32a[32], auxrnd32b[32], auxrnd32a_bad[32], auxrnd32b_bad[32]; + unsigned char sec32a[32], sec32b[32], sec32a_bad[32], sec32b_bad[32]; + rustsecp256k1_v0_9_0_scalar seca, secb; + unsigned char ell64a[64], ell64b[64], ell64a_bad[64], ell64b_bad[64]; + unsigned char share32a[32], share32b[32], share32_bad[32]; + unsigned char prefix64[64]; + rustsecp256k1_v0_9_0_ellswift_xdh_hash_function hash_function; + void* data; + int ret; + + /* Pick hasher to use. */ + if ((i % 3) == 0) { + hash_function = ellswift_xdh_hash_x32; + data = NULL; + } else if ((i % 3) == 1) { + hash_function = rustsecp256k1_v0_9_0_ellswift_xdh_hash_function_bip324; + data = NULL; + } else { + hash_function = rustsecp256k1_v0_9_0_ellswift_xdh_hash_function_prefix; + rustsecp256k1_v0_9_0_testrand256_test(prefix64); + rustsecp256k1_v0_9_0_testrand256_test(prefix64 + 32); + data = prefix64; + } + + /* Generate random secret keys and random randomizers. */ + rustsecp256k1_v0_9_0_testrand256_test(auxrnd32a); + rustsecp256k1_v0_9_0_testrand256_test(auxrnd32b); + random_scalar_order_test(&seca); + /* Draw secb uniformly at random to make sure that the secret keys + * differ */ + random_scalar_order(&secb); + rustsecp256k1_v0_9_0_scalar_get_b32(sec32a, &seca); + rustsecp256k1_v0_9_0_scalar_get_b32(sec32b, &secb); + + /* Construct ElligatorSwift-encoded public keys for those keys. */ + /* For A: */ + ret = rustsecp256k1_v0_9_0_ellswift_create(CTX, ell64a, sec32a, auxrnd32a); + CHECK(ret); + /* For B: */ + ret = rustsecp256k1_v0_9_0_ellswift_create(CTX, ell64b, sec32b, auxrnd32b); + CHECK(ret); + + /* Compute the shared secret both ways and compare with each other. */ + /* For A: */ + ret = rustsecp256k1_v0_9_0_ellswift_xdh(CTX, share32a, ell64a, ell64b, sec32a, 0, hash_function, data); + CHECK(ret); + /* For B: */ + ret = rustsecp256k1_v0_9_0_ellswift_xdh(CTX, share32b, ell64a, ell64b, sec32b, 1, hash_function, data); + CHECK(ret); + /* And compare: */ + CHECK(rustsecp256k1_v0_9_0_memcmp_var(share32a, share32b, 32) == 0); + + /* Verify that the shared secret doesn't match if other side's public key is incorrect. */ + /* For A (using a bad public key for B): */ + memcpy(ell64b_bad, ell64b, sizeof(ell64a_bad)); + rustsecp256k1_v0_9_0_testrand_flip(ell64b_bad, sizeof(ell64b_bad)); + ret = rustsecp256k1_v0_9_0_ellswift_xdh(CTX, share32_bad, ell64a, ell64b_bad, sec32a, 0, hash_function, data); + CHECK(ret); /* Mismatching encodings don't get detected by rustsecp256k1_v0_9_0_ellswift_xdh. */ + CHECK(rustsecp256k1_v0_9_0_memcmp_var(share32_bad, share32a, 32) != 0); + /* For B (using a bad public key for A): */ + memcpy(ell64a_bad, ell64a, sizeof(ell64a_bad)); + rustsecp256k1_v0_9_0_testrand_flip(ell64a_bad, sizeof(ell64a_bad)); + ret = rustsecp256k1_v0_9_0_ellswift_xdh(CTX, share32_bad, ell64a_bad, ell64b, sec32b, 1, hash_function, data); + CHECK(ret); + CHECK(rustsecp256k1_v0_9_0_memcmp_var(share32_bad, share32b, 32) != 0); + + /* Verify that the shared secret doesn't match if the private key is incorrect. */ + /* For A: */ + memcpy(sec32a_bad, sec32a, sizeof(sec32a_bad)); + rustsecp256k1_v0_9_0_testrand_flip(sec32a_bad, sizeof(sec32a_bad)); + ret = rustsecp256k1_v0_9_0_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32a_bad, 0, hash_function, data); + CHECK(!ret || rustsecp256k1_v0_9_0_memcmp_var(share32_bad, share32a, 32) != 0); + /* For B: */ + memcpy(sec32b_bad, sec32b, sizeof(sec32b_bad)); + rustsecp256k1_v0_9_0_testrand_flip(sec32b_bad, sizeof(sec32b_bad)); + ret = rustsecp256k1_v0_9_0_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32b_bad, 1, hash_function, data); + CHECK(!ret || rustsecp256k1_v0_9_0_memcmp_var(share32_bad, share32b, 32) != 0); + + if (hash_function != ellswift_xdh_hash_x32) { + /* Verify that the shared secret doesn't match when a different encoding of the same public key is used. */ + /* For A (changing B's public key): */ + memcpy(auxrnd32b_bad, auxrnd32b, sizeof(auxrnd32b_bad)); + rustsecp256k1_v0_9_0_testrand_flip(auxrnd32b_bad, sizeof(auxrnd32b_bad)); + ret = rustsecp256k1_v0_9_0_ellswift_create(CTX, ell64b_bad, sec32b, auxrnd32b_bad); + CHECK(ret); + ret = rustsecp256k1_v0_9_0_ellswift_xdh(CTX, share32_bad, ell64a, ell64b_bad, sec32a, 0, hash_function, data); + CHECK(ret); + CHECK(rustsecp256k1_v0_9_0_memcmp_var(share32_bad, share32a, 32) != 0); + /* For B (changing A's public key): */ + memcpy(auxrnd32a_bad, auxrnd32a, sizeof(auxrnd32a_bad)); + rustsecp256k1_v0_9_0_testrand_flip(auxrnd32a_bad, sizeof(auxrnd32a_bad)); + ret = rustsecp256k1_v0_9_0_ellswift_create(CTX, ell64a_bad, sec32a, auxrnd32a_bad); + CHECK(ret); + ret = rustsecp256k1_v0_9_0_ellswift_xdh(CTX, share32_bad, ell64a_bad, ell64b, sec32b, 1, hash_function, data); + CHECK(ret); + CHECK(rustsecp256k1_v0_9_0_memcmp_var(share32_bad, share32b, 32) != 0); + + /* Verify that swapping sides changes the shared secret. */ + /* For A (claiming to be B): */ + ret = rustsecp256k1_v0_9_0_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32a, 1, hash_function, data); + CHECK(ret); + CHECK(rustsecp256k1_v0_9_0_memcmp_var(share32_bad, share32a, 32) != 0); + /* For B (claiming to be A): */ + ret = rustsecp256k1_v0_9_0_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32b, 0, hash_function, data); + CHECK(ret); + CHECK(rustsecp256k1_v0_9_0_memcmp_var(share32_bad, share32b, 32) != 0); + } + } + + /* Test hash initializers. */ + { + rustsecp256k1_v0_9_0_sha256 sha, sha_optimized; + static const unsigned char encode_tag[25] = "rustsecp256k1_v0_9_0_ellswift_encode"; + static const unsigned char create_tag[25] = "rustsecp256k1_v0_9_0_ellswift_create"; + static const unsigned char bip324_tag[26] = "bip324_ellswift_xonly_ecdh"; + + /* Check that hash initialized by + * rustsecp256k1_v0_9_0_ellswift_sha256_init_encode has the expected + * state. */ + rustsecp256k1_v0_9_0_sha256_initialize_tagged(&sha, encode_tag, sizeof(encode_tag)); + rustsecp256k1_v0_9_0_ellswift_sha256_init_encode(&sha_optimized); + test_sha256_eq(&sha, &sha_optimized); + + /* Check that hash initialized by + * rustsecp256k1_v0_9_0_ellswift_sha256_init_create has the expected + * state. */ + rustsecp256k1_v0_9_0_sha256_initialize_tagged(&sha, create_tag, sizeof(create_tag)); + rustsecp256k1_v0_9_0_ellswift_sha256_init_create(&sha_optimized); + test_sha256_eq(&sha, &sha_optimized); + + /* Check that hash initialized by + * rustsecp256k1_v0_9_0_ellswift_sha256_init_bip324 has the expected + * state. */ + rustsecp256k1_v0_9_0_sha256_initialize_tagged(&sha, bip324_tag, sizeof(bip324_tag)); + rustsecp256k1_v0_9_0_ellswift_sha256_init_bip324(&sha_optimized); + test_sha256_eq(&sha, &sha_optimized); + } +} + +#endif diff --git a/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h index 55b115c02..fd97b5660 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h @@ -48,7 +48,7 @@ static void test_exhaustive_extrakeys(const rustsecp256k1_v0_9_0_context *ctx, c /* Compare the xonly_pubkey bytes against the precomputed group. */ rustsecp256k1_v0_9_0_fe_set_b32_mod(&fe, xonly_pubkey_bytes[i - 1]); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&fe, &group[i].x)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&fe, &group[i].x)); /* Check the parity against the precomputed group. */ fe = group[i].y; diff --git a/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/main_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/main_impl.h index 694bd0bd4..7aa554cc3 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/main_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/main_impl.h @@ -261,7 +261,7 @@ int rustsecp256k1_v0_9_0_schnorrsig_verify(const rustsecp256k1_v0_9_0_context* c rustsecp256k1_v0_9_0_fe_normalize_var(&r.y); return !rustsecp256k1_v0_9_0_fe_is_odd(&r.y) && - rustsecp256k1_v0_9_0_fe_equal_var(&rx, &r.x); + rustsecp256k1_v0_9_0_fe_equal(&rx, &r.x); } #endif diff --git a/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h index cd722dde1..9fa9f7e53 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h @@ -110,15 +110,15 @@ static void test_exhaustive_schnorrsig_verify(const rustsecp256k1_v0_9_0_context if (!e_done[e]) { /* Iterate over the possible valid last 32 bytes in the signature. 0..order=that s value; order+1=random bytes */ - int count_valid = 0, s; + int count_valid = 0; + unsigned int s; for (s = 0; s <= EXHAUSTIVE_TEST_ORDER + 1; ++s) { int expect_valid, valid; if (s <= EXHAUSTIVE_TEST_ORDER) { - rustsecp256k1_v0_9_0_scalar s_s; - rustsecp256k1_v0_9_0_scalar_set_int(&s_s, s); - rustsecp256k1_v0_9_0_scalar_get_b32(sig64 + 32, &s_s); + memset(sig64 + 32, 0, 32); + rustsecp256k1_v0_9_0_write_be32(sig64 + 60, s); expect_valid = actual_k != -1 && s != EXHAUSTIVE_TEST_ORDER && - (s_s == (actual_k + actual_d * e) % EXHAUSTIVE_TEST_ORDER); + (s == (actual_k + actual_d * e) % EXHAUSTIVE_TEST_ORDER); } else { rustsecp256k1_v0_9_0_testrand256(sig64 + 32); expect_valid = 0; diff --git a/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/tests_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/tests_impl.h index fc035a230..6d7a11e6e 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/tests_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/tests_impl.h @@ -20,17 +20,6 @@ static void nonce_function_bip340_bitflip(unsigned char **args, size_t n_flip, s CHECK(rustsecp256k1_v0_9_0_memcmp_var(nonces[0], nonces[1], 32) != 0); } -/* Tests for the equality of two sha256 structs. This function only produces a - * correct result if an integer multiple of 64 many bytes have been written - * into the hash functions. */ -static void test_sha256_eq(const rustsecp256k1_v0_9_0_sha256 *sha1, const rustsecp256k1_v0_9_0_sha256 *sha2) { - /* Is buffer fully consumed? */ - CHECK((sha1->bytes & 0x3F) == 0); - - CHECK(sha1->bytes == sha2->bytes); - CHECK(rustsecp256k1_v0_9_0_memcmp_var(sha1->s, sha2->s, sizeof(sha1->s)) == 0); -} - static void run_nonce_function_bip340_tests(void) { unsigned char tag[13] = "BIP0340/nonce"; unsigned char aux_tag[11] = "BIP0340/aux"; diff --git a/secp256k1-sys/depend/secp256k1/src/precompute_ecmult.c b/secp256k1-sys/depend/secp256k1/src/precompute_ecmult.c index 89d9c70f7..644e573d7 100644 --- a/secp256k1-sys/depend/secp256k1/src/precompute_ecmult.c +++ b/secp256k1-sys/depend/secp256k1/src/precompute_ecmult.c @@ -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; } @@ -68,7 +69,6 @@ int main(void) { fprintf(fp, "/* This file contains an array rustsecp256k1_v0_9_0_pre_g with odd multiples of the base point G and\n"); fprintf(fp, " * an array rustsecp256k1_v0_9_0_pre_g_128 with odd multiples of 2^128*G for accelerating the computation of a*P + b*G.\n"); fprintf(fp, " */\n"); - fprintf(fp, "#include \"../include/secp256k1.h\"\n"); fprintf(fp, "#include \"group.h\"\n"); fprintf(fp, "#include \"ecmult.h\"\n"); fprintf(fp, "#include \"precomputed_ecmult.h\"\n"); diff --git a/secp256k1-sys/depend/secp256k1/src/precompute_ecmult_gen.c b/secp256k1-sys/depend/secp256k1/src/precompute_ecmult_gen.c index 30ada721e..169292766 100644 --- a/secp256k1-sys/depend/secp256k1/src/precompute_ecmult_gen.c +++ b/secp256k1-sys/depend/secp256k1/src/precompute_ecmult_gen.c @@ -33,7 +33,6 @@ int main(int argc, char **argv) { fprintf(fp, "/* This file was automatically generated by precompute_ecmult_gen. */\n"); fprintf(fp, "/* See ecmult_gen_impl.h for details about the contents of this file. */\n"); - fprintf(fp, "#include \"../include/secp256k1.h\"\n"); fprintf(fp, "#include \"group.h\"\n"); fprintf(fp, "#include \"ecmult_gen.h\"\n"); fprintf(fp, "#include \"precomputed_ecmult_gen.h\"\n"); diff --git a/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult.c b/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult.c index e96495bc7..5cc74cfc3 100644 --- a/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult.c +++ b/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult.c @@ -2,7 +2,6 @@ /* This file contains an array rustsecp256k1_v0_9_0_pre_g with odd multiples of the base point G and * an array rustsecp256k1_v0_9_0_pre_g_128 with odd multiples of 2^128*G for accelerating the computation of a*P + b*G. */ -#include "../include/secp256k1.h" #include "group.h" #include "ecmult.h" #include "precomputed_ecmult.h" diff --git a/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult.h b/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult.h index 18f6562fb..b00f27a16 100644 --- a/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult.h +++ b/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult.h @@ -11,6 +11,7 @@ extern "C" { #endif +#include "ecmult.h" #include "group.h" #if defined(EXHAUSTIVE_TEST_ORDER) # if EXHAUSTIVE_TEST_ORDER == 7 diff --git a/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult_gen.c b/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult_gen.c index 0c035cc29..f073822b2 100644 --- a/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult_gen.c +++ b/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult_gen.c @@ -1,6 +1,5 @@ /* This file was automatically generated by precompute_ecmult_gen. */ /* See ecmult_gen_impl.h for details about the contents of this file. */ -#include "../include/secp256k1.h" #include "group.h" #include "ecmult_gen.h" #include "precomputed_ecmult_gen.h" diff --git a/secp256k1-sys/depend/secp256k1/src/scalar.h b/secp256k1-sys/depend/secp256k1/src/scalar.h index 6ab9c3543..63a89ab94 100644 --- a/secp256k1-sys/depend/secp256k1/src/scalar.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar.h @@ -99,4 +99,7 @@ static void rustsecp256k1_v0_9_0_scalar_mul_shift_var(rustsecp256k1_v0_9_0_scala /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/ static void rustsecp256k1_v0_9_0_scalar_cmov(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_scalar *a, int flag); +/** Check invariants on a scalar (no-op unless VERIFY is enabled). */ +static void rustsecp256k1_v0_9_0_scalar_verify(const rustsecp256k1_v0_9_0_scalar *r); + #endif /* SECP256K1_SCALAR_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/scalar_4x64_impl.h b/secp256k1-sys/depend/secp256k1/src/scalar_4x64_impl.h index 95fcadcb2..af9ebabeb 100644 --- a/secp256k1-sys/depend/secp256k1/src/scalar_4x64_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar_4x64_impl.h @@ -41,16 +41,22 @@ SECP256K1_INLINE static void rustsecp256k1_v0_9_0_scalar_set_int(rustsecp256k1_v r->d[1] = 0; r->d[2] = 0; r->d[3] = 0; + + rustsecp256k1_v0_9_0_scalar_verify(r); } SECP256K1_INLINE static unsigned int rustsecp256k1_v0_9_0_scalar_get_bits(const rustsecp256k1_v0_9_0_scalar *a, unsigned int offset, unsigned int count) { + rustsecp256k1_v0_9_0_scalar_verify(a); VERIFY_CHECK((offset + count - 1) >> 6 == offset >> 6); + return (a->d[offset >> 6] >> (offset & 0x3F)) & ((((uint64_t)1) << count) - 1); } SECP256K1_INLINE static unsigned int rustsecp256k1_v0_9_0_scalar_get_bits_var(const rustsecp256k1_v0_9_0_scalar *a, unsigned int offset, unsigned int count) { + rustsecp256k1_v0_9_0_scalar_verify(a); VERIFY_CHECK(count < 32); VERIFY_CHECK(offset + count <= 256); + if ((offset + count - 1) >> 6 == offset >> 6) { return rustsecp256k1_v0_9_0_scalar_get_bits(a, offset, count); } else { @@ -74,6 +80,7 @@ SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_check_overflow(const rus SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_reduce(rustsecp256k1_v0_9_0_scalar *r, unsigned int overflow) { rustsecp256k1_v0_9_0_uint128 t; VERIFY_CHECK(overflow <= 1); + rustsecp256k1_v0_9_0_u128_from_u64(&t, r->d[0]); rustsecp256k1_v0_9_0_u128_accum_u64(&t, overflow * SECP256K1_N_C_0); r->d[0] = rustsecp256k1_v0_9_0_u128_to_u64(&t); rustsecp256k1_v0_9_0_u128_rshift(&t, 64); @@ -85,12 +92,17 @@ SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_reduce(rustsecp256k1_v0_ r->d[2] = rustsecp256k1_v0_9_0_u128_to_u64(&t); rustsecp256k1_v0_9_0_u128_rshift(&t, 64); rustsecp256k1_v0_9_0_u128_accum_u64(&t, r->d[3]); r->d[3] = rustsecp256k1_v0_9_0_u128_to_u64(&t); + + rustsecp256k1_v0_9_0_scalar_verify(r); return overflow; } static int rustsecp256k1_v0_9_0_scalar_add(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_scalar *a, const rustsecp256k1_v0_9_0_scalar *b) { int overflow; rustsecp256k1_v0_9_0_uint128 t; + rustsecp256k1_v0_9_0_scalar_verify(a); + rustsecp256k1_v0_9_0_scalar_verify(b); + rustsecp256k1_v0_9_0_u128_from_u64(&t, a->d[0]); rustsecp256k1_v0_9_0_u128_accum_u64(&t, b->d[0]); r->d[0] = rustsecp256k1_v0_9_0_u128_to_u64(&t); rustsecp256k1_v0_9_0_u128_rshift(&t, 64); @@ -106,13 +118,17 @@ static int rustsecp256k1_v0_9_0_scalar_add(rustsecp256k1_v0_9_0_scalar *r, const overflow = rustsecp256k1_v0_9_0_u128_to_u64(&t) + rustsecp256k1_v0_9_0_scalar_check_overflow(r); VERIFY_CHECK(overflow == 0 || overflow == 1); rustsecp256k1_v0_9_0_scalar_reduce(r, overflow); + + rustsecp256k1_v0_9_0_scalar_verify(r); return overflow; } static void rustsecp256k1_v0_9_0_scalar_cadd_bit(rustsecp256k1_v0_9_0_scalar *r, unsigned int bit, int flag) { rustsecp256k1_v0_9_0_uint128 t; volatile int vflag = flag; + rustsecp256k1_v0_9_0_scalar_verify(r); VERIFY_CHECK(bit < 256); + bit += ((uint32_t) vflag - 1) & 0x100; /* forcing (bit >> 6) > 3 makes this a noop */ rustsecp256k1_v0_9_0_u128_from_u64(&t, r->d[0]); rustsecp256k1_v0_9_0_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F)); @@ -126,6 +142,8 @@ static void rustsecp256k1_v0_9_0_scalar_cadd_bit(rustsecp256k1_v0_9_0_scalar *r, rustsecp256k1_v0_9_0_u128_accum_u64(&t, r->d[3]); rustsecp256k1_v0_9_0_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F)); r->d[3] = rustsecp256k1_v0_9_0_u128_to_u64(&t); + + rustsecp256k1_v0_9_0_scalar_verify(r); #ifdef VERIFY VERIFY_CHECK(rustsecp256k1_v0_9_0_u128_hi_u64(&t) == 0); #endif @@ -133,30 +151,38 @@ static void rustsecp256k1_v0_9_0_scalar_cadd_bit(rustsecp256k1_v0_9_0_scalar *r, static void rustsecp256k1_v0_9_0_scalar_set_b32(rustsecp256k1_v0_9_0_scalar *r, const unsigned char *b32, int *overflow) { int over; - r->d[0] = (uint64_t)b32[31] | (uint64_t)b32[30] << 8 | (uint64_t)b32[29] << 16 | (uint64_t)b32[28] << 24 | (uint64_t)b32[27] << 32 | (uint64_t)b32[26] << 40 | (uint64_t)b32[25] << 48 | (uint64_t)b32[24] << 56; - r->d[1] = (uint64_t)b32[23] | (uint64_t)b32[22] << 8 | (uint64_t)b32[21] << 16 | (uint64_t)b32[20] << 24 | (uint64_t)b32[19] << 32 | (uint64_t)b32[18] << 40 | (uint64_t)b32[17] << 48 | (uint64_t)b32[16] << 56; - r->d[2] = (uint64_t)b32[15] | (uint64_t)b32[14] << 8 | (uint64_t)b32[13] << 16 | (uint64_t)b32[12] << 24 | (uint64_t)b32[11] << 32 | (uint64_t)b32[10] << 40 | (uint64_t)b32[9] << 48 | (uint64_t)b32[8] << 56; - r->d[3] = (uint64_t)b32[7] | (uint64_t)b32[6] << 8 | (uint64_t)b32[5] << 16 | (uint64_t)b32[4] << 24 | (uint64_t)b32[3] << 32 | (uint64_t)b32[2] << 40 | (uint64_t)b32[1] << 48 | (uint64_t)b32[0] << 56; + r->d[0] = rustsecp256k1_v0_9_0_read_be64(&b32[24]); + r->d[1] = rustsecp256k1_v0_9_0_read_be64(&b32[16]); + r->d[2] = rustsecp256k1_v0_9_0_read_be64(&b32[8]); + r->d[3] = rustsecp256k1_v0_9_0_read_be64(&b32[0]); over = rustsecp256k1_v0_9_0_scalar_reduce(r, rustsecp256k1_v0_9_0_scalar_check_overflow(r)); if (overflow) { *overflow = over; } + + rustsecp256k1_v0_9_0_scalar_verify(r); } static void rustsecp256k1_v0_9_0_scalar_get_b32(unsigned char *bin, const rustsecp256k1_v0_9_0_scalar* a) { - bin[0] = a->d[3] >> 56; bin[1] = a->d[3] >> 48; bin[2] = a->d[3] >> 40; bin[3] = a->d[3] >> 32; bin[4] = a->d[3] >> 24; bin[5] = a->d[3] >> 16; bin[6] = a->d[3] >> 8; bin[7] = a->d[3]; - bin[8] = a->d[2] >> 56; bin[9] = a->d[2] >> 48; bin[10] = a->d[2] >> 40; bin[11] = a->d[2] >> 32; bin[12] = a->d[2] >> 24; bin[13] = a->d[2] >> 16; bin[14] = a->d[2] >> 8; bin[15] = a->d[2]; - bin[16] = a->d[1] >> 56; bin[17] = a->d[1] >> 48; bin[18] = a->d[1] >> 40; bin[19] = a->d[1] >> 32; bin[20] = a->d[1] >> 24; bin[21] = a->d[1] >> 16; bin[22] = a->d[1] >> 8; bin[23] = a->d[1]; - bin[24] = a->d[0] >> 56; bin[25] = a->d[0] >> 48; bin[26] = a->d[0] >> 40; bin[27] = a->d[0] >> 32; bin[28] = a->d[0] >> 24; bin[29] = a->d[0] >> 16; bin[30] = a->d[0] >> 8; bin[31] = a->d[0]; + rustsecp256k1_v0_9_0_scalar_verify(a); + + rustsecp256k1_v0_9_0_write_be64(&bin[0], a->d[3]); + rustsecp256k1_v0_9_0_write_be64(&bin[8], a->d[2]); + rustsecp256k1_v0_9_0_write_be64(&bin[16], a->d[1]); + rustsecp256k1_v0_9_0_write_be64(&bin[24], a->d[0]); } SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_is_zero(const rustsecp256k1_v0_9_0_scalar *a) { + rustsecp256k1_v0_9_0_scalar_verify(a); + return (a->d[0] | a->d[1] | a->d[2] | a->d[3]) == 0; } static void rustsecp256k1_v0_9_0_scalar_negate(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_scalar *a) { uint64_t nonzero = 0xFFFFFFFFFFFFFFFFULL * (rustsecp256k1_v0_9_0_scalar_is_zero(a) == 0); rustsecp256k1_v0_9_0_uint128 t; + rustsecp256k1_v0_9_0_scalar_verify(a); + rustsecp256k1_v0_9_0_u128_from_u64(&t, ~a->d[0]); rustsecp256k1_v0_9_0_u128_accum_u64(&t, SECP256K1_N_0 + 1); r->d[0] = rustsecp256k1_v0_9_0_u128_to_u64(&t) & nonzero; rustsecp256k1_v0_9_0_u128_rshift(&t, 64); @@ -169,15 +195,21 @@ static void rustsecp256k1_v0_9_0_scalar_negate(rustsecp256k1_v0_9_0_scalar *r, c rustsecp256k1_v0_9_0_u128_accum_u64(&t, ~a->d[3]); rustsecp256k1_v0_9_0_u128_accum_u64(&t, SECP256K1_N_3); r->d[3] = rustsecp256k1_v0_9_0_u128_to_u64(&t) & nonzero; + + rustsecp256k1_v0_9_0_scalar_verify(r); } SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_is_one(const rustsecp256k1_v0_9_0_scalar *a) { + rustsecp256k1_v0_9_0_scalar_verify(a); + return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3]) == 0; } static int rustsecp256k1_v0_9_0_scalar_is_high(const rustsecp256k1_v0_9_0_scalar *a) { int yes = 0; int no = 0; + rustsecp256k1_v0_9_0_scalar_verify(a); + no |= (a->d[3] < SECP256K1_N_H_3); yes |= (a->d[3] > SECP256K1_N_H_3) & ~no; no |= (a->d[2] < SECP256K1_N_H_2) & ~yes; /* No need for a > check. */ @@ -194,6 +226,8 @@ static int rustsecp256k1_v0_9_0_scalar_cond_negate(rustsecp256k1_v0_9_0_scalar * uint64_t mask = -vflag; uint64_t nonzero = (rustsecp256k1_v0_9_0_scalar_is_zero(r) != 0) - 1; rustsecp256k1_v0_9_0_uint128 t; + rustsecp256k1_v0_9_0_scalar_verify(r); + rustsecp256k1_v0_9_0_u128_from_u64(&t, r->d[0] ^ mask); rustsecp256k1_v0_9_0_u128_accum_u64(&t, (SECP256K1_N_0 + 1) & mask); r->d[0] = rustsecp256k1_v0_9_0_u128_to_u64(&t) & nonzero; rustsecp256k1_v0_9_0_u128_rshift(&t, 64); @@ -206,6 +240,8 @@ static int rustsecp256k1_v0_9_0_scalar_cond_negate(rustsecp256k1_v0_9_0_scalar * rustsecp256k1_v0_9_0_u128_accum_u64(&t, r->d[3] ^ mask); rustsecp256k1_v0_9_0_u128_accum_u64(&t, SECP256K1_N_3 & mask); r->d[3] = rustsecp256k1_v0_9_0_u128_to_u64(&t) & nonzero; + + rustsecp256k1_v0_9_0_scalar_verify(r); return 2 * (mask == 0) - 1; } @@ -764,23 +800,34 @@ static void rustsecp256k1_v0_9_0_scalar_mul_512(uint64_t l[8], const rustsecp256 static void rustsecp256k1_v0_9_0_scalar_mul(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_scalar *a, const rustsecp256k1_v0_9_0_scalar *b) { uint64_t l[8]; + rustsecp256k1_v0_9_0_scalar_verify(a); + rustsecp256k1_v0_9_0_scalar_verify(b); + rustsecp256k1_v0_9_0_scalar_mul_512(l, a, b); rustsecp256k1_v0_9_0_scalar_reduce_512(r, l); + + rustsecp256k1_v0_9_0_scalar_verify(r); } static int rustsecp256k1_v0_9_0_scalar_shr_int(rustsecp256k1_v0_9_0_scalar *r, int n) { int ret; + rustsecp256k1_v0_9_0_scalar_verify(r); VERIFY_CHECK(n > 0); VERIFY_CHECK(n < 16); + ret = r->d[0] & ((1 << n) - 1); r->d[0] = (r->d[0] >> n) + (r->d[1] << (64 - n)); r->d[1] = (r->d[1] >> n) + (r->d[2] << (64 - n)); r->d[2] = (r->d[2] >> n) + (r->d[3] << (64 - n)); r->d[3] = (r->d[3] >> n); + + rustsecp256k1_v0_9_0_scalar_verify(r); return ret; } static void rustsecp256k1_v0_9_0_scalar_split_128(rustsecp256k1_v0_9_0_scalar *r1, rustsecp256k1_v0_9_0_scalar *r2, const rustsecp256k1_v0_9_0_scalar *k) { + rustsecp256k1_v0_9_0_scalar_verify(k); + r1->d[0] = k->d[0]; r1->d[1] = k->d[1]; r1->d[2] = 0; @@ -789,9 +836,15 @@ static void rustsecp256k1_v0_9_0_scalar_split_128(rustsecp256k1_v0_9_0_scalar *r r2->d[1] = k->d[3]; r2->d[2] = 0; r2->d[3] = 0; + + rustsecp256k1_v0_9_0_scalar_verify(r1); + rustsecp256k1_v0_9_0_scalar_verify(r2); } SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_eq(const rustsecp256k1_v0_9_0_scalar *a, const rustsecp256k1_v0_9_0_scalar *b) { + rustsecp256k1_v0_9_0_scalar_verify(a); + rustsecp256k1_v0_9_0_scalar_verify(b); + return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3])) == 0; } @@ -800,7 +853,10 @@ SECP256K1_INLINE static void rustsecp256k1_v0_9_0_scalar_mul_shift_var(rustsecp2 unsigned int shiftlimbs; unsigned int shiftlow; unsigned int shifthigh; + rustsecp256k1_v0_9_0_scalar_verify(a); + rustsecp256k1_v0_9_0_scalar_verify(b); VERIFY_CHECK(shift >= 256); + rustsecp256k1_v0_9_0_scalar_mul_512(l, a, b); shiftlimbs = shift >> 6; shiftlow = shift & 0x3F; @@ -810,18 +866,24 @@ SECP256K1_INLINE static void rustsecp256k1_v0_9_0_scalar_mul_shift_var(rustsecp2 r->d[2] = shift < 384 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0; r->d[3] = shift < 320 ? (l[3 + shiftlimbs] >> shiftlow) : 0; rustsecp256k1_v0_9_0_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1); + + rustsecp256k1_v0_9_0_scalar_verify(r); } static SECP256K1_INLINE void rustsecp256k1_v0_9_0_scalar_cmov(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_scalar *a, int flag) { uint64_t mask0, mask1; volatile int vflag = flag; + rustsecp256k1_v0_9_0_scalar_verify(a); SECP256K1_CHECKMEM_CHECK_VERIFY(r->d, sizeof(r->d)); + mask0 = vflag + ~((uint64_t)0); mask1 = ~mask0; r->d[0] = (r->d[0] & mask0) | (a->d[0] & mask1); r->d[1] = (r->d[1] & mask0) | (a->d[1] & mask1); r->d[2] = (r->d[2] & mask0) | (a->d[2] & mask1); r->d[3] = (r->d[3] & mask0) | (a->d[3] & mask1); + + rustsecp256k1_v0_9_0_scalar_verify(r); } static void rustsecp256k1_v0_9_0_scalar_from_signed62(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_modinv64_signed62 *a) { @@ -841,18 +903,13 @@ static void rustsecp256k1_v0_9_0_scalar_from_signed62(rustsecp256k1_v0_9_0_scala r->d[2] = a2 >> 4 | a3 << 58; r->d[3] = a3 >> 6 | a4 << 56; -#ifdef VERIFY - VERIFY_CHECK(rustsecp256k1_v0_9_0_scalar_check_overflow(r) == 0); -#endif + rustsecp256k1_v0_9_0_scalar_verify(r); } static void rustsecp256k1_v0_9_0_scalar_to_signed62(rustsecp256k1_v0_9_0_modinv64_signed62 *r, const rustsecp256k1_v0_9_0_scalar *a) { const uint64_t M62 = UINT64_MAX >> 2; const uint64_t a0 = a->d[0], a1 = a->d[1], a2 = a->d[2], a3 = a->d[3]; - -#ifdef VERIFY - VERIFY_CHECK(rustsecp256k1_v0_9_0_scalar_check_overflow(a) == 0); -#endif + rustsecp256k1_v0_9_0_scalar_verify(a); r->v[0] = a0 & M62; r->v[1] = (a0 >> 62 | a1 << 2) & M62; @@ -871,10 +928,13 @@ static void rustsecp256k1_v0_9_0_scalar_inverse(rustsecp256k1_v0_9_0_scalar *r, #ifdef VERIFY int zero_in = rustsecp256k1_v0_9_0_scalar_is_zero(x); #endif + rustsecp256k1_v0_9_0_scalar_verify(x); + rustsecp256k1_v0_9_0_scalar_to_signed62(&s, x); rustsecp256k1_v0_9_0_modinv64(&s, &rustsecp256k1_v0_9_0_const_modinfo_scalar); rustsecp256k1_v0_9_0_scalar_from_signed62(r, &s); + rustsecp256k1_v0_9_0_scalar_verify(r); #ifdef VERIFY VERIFY_CHECK(rustsecp256k1_v0_9_0_scalar_is_zero(r) == zero_in); #endif @@ -885,16 +945,21 @@ static void rustsecp256k1_v0_9_0_scalar_inverse_var(rustsecp256k1_v0_9_0_scalar #ifdef VERIFY int zero_in = rustsecp256k1_v0_9_0_scalar_is_zero(x); #endif + rustsecp256k1_v0_9_0_scalar_verify(x); + rustsecp256k1_v0_9_0_scalar_to_signed62(&s, x); rustsecp256k1_v0_9_0_modinv64_var(&s, &rustsecp256k1_v0_9_0_const_modinfo_scalar); rustsecp256k1_v0_9_0_scalar_from_signed62(r, &s); + rustsecp256k1_v0_9_0_scalar_verify(r); #ifdef VERIFY VERIFY_CHECK(rustsecp256k1_v0_9_0_scalar_is_zero(r) == zero_in); #endif } SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_is_even(const rustsecp256k1_v0_9_0_scalar *a) { + rustsecp256k1_v0_9_0_scalar_verify(a); + return !(a->d[0] & 1); } diff --git a/secp256k1-sys/depend/secp256k1/src/scalar_8x32_impl.h b/secp256k1-sys/depend/secp256k1/src/scalar_8x32_impl.h index 75a5a9829..bb7babd6d 100644 --- a/secp256k1-sys/depend/secp256k1/src/scalar_8x32_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar_8x32_impl.h @@ -58,16 +58,22 @@ SECP256K1_INLINE static void rustsecp256k1_v0_9_0_scalar_set_int(rustsecp256k1_v r->d[5] = 0; r->d[6] = 0; r->d[7] = 0; + + rustsecp256k1_v0_9_0_scalar_verify(r); } SECP256K1_INLINE static unsigned int rustsecp256k1_v0_9_0_scalar_get_bits(const rustsecp256k1_v0_9_0_scalar *a, unsigned int offset, unsigned int count) { + rustsecp256k1_v0_9_0_scalar_verify(a); VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5); + return (a->d[offset >> 5] >> (offset & 0x1F)) & ((1 << count) - 1); } SECP256K1_INLINE static unsigned int rustsecp256k1_v0_9_0_scalar_get_bits_var(const rustsecp256k1_v0_9_0_scalar *a, unsigned int offset, unsigned int count) { + rustsecp256k1_v0_9_0_scalar_verify(a); VERIFY_CHECK(count < 32); VERIFY_CHECK(offset + count <= 256); + if ((offset + count - 1) >> 5 == offset >> 5) { return rustsecp256k1_v0_9_0_scalar_get_bits(a, offset, count); } else { @@ -97,6 +103,7 @@ SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_check_overflow(const rus SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_reduce(rustsecp256k1_v0_9_0_scalar *r, uint32_t overflow) { uint64_t t; VERIFY_CHECK(overflow <= 1); + t = (uint64_t)r->d[0] + overflow * SECP256K1_N_C_0; r->d[0] = t & 0xFFFFFFFFUL; t >>= 32; t += (uint64_t)r->d[1] + overflow * SECP256K1_N_C_1; @@ -113,12 +120,17 @@ SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_reduce(rustsecp256k1_v0_ r->d[6] = t & 0xFFFFFFFFUL; t >>= 32; t += (uint64_t)r->d[7]; r->d[7] = t & 0xFFFFFFFFUL; + + rustsecp256k1_v0_9_0_scalar_verify(r); return overflow; } static int rustsecp256k1_v0_9_0_scalar_add(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_scalar *a, const rustsecp256k1_v0_9_0_scalar *b) { int overflow; uint64_t t = (uint64_t)a->d[0] + b->d[0]; + rustsecp256k1_v0_9_0_scalar_verify(a); + rustsecp256k1_v0_9_0_scalar_verify(b); + r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)a->d[1] + b->d[1]; r->d[1] = t & 0xFFFFFFFFULL; t >>= 32; @@ -137,13 +149,17 @@ static int rustsecp256k1_v0_9_0_scalar_add(rustsecp256k1_v0_9_0_scalar *r, const overflow = t + rustsecp256k1_v0_9_0_scalar_check_overflow(r); VERIFY_CHECK(overflow == 0 || overflow == 1); rustsecp256k1_v0_9_0_scalar_reduce(r, overflow); + + rustsecp256k1_v0_9_0_scalar_verify(r); return overflow; } static void rustsecp256k1_v0_9_0_scalar_cadd_bit(rustsecp256k1_v0_9_0_scalar *r, unsigned int bit, int flag) { uint64_t t; volatile int vflag = flag; + rustsecp256k1_v0_9_0_scalar_verify(r); VERIFY_CHECK(bit < 256); + bit += ((uint32_t) vflag - 1) & 0x100; /* forcing (bit >> 5) > 7 makes this a noop */ t = (uint64_t)r->d[0] + (((uint32_t)((bit >> 5) == 0)) << (bit & 0x1F)); r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; @@ -161,46 +177,55 @@ static void rustsecp256k1_v0_9_0_scalar_cadd_bit(rustsecp256k1_v0_9_0_scalar *r, r->d[6] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)r->d[7] + (((uint32_t)((bit >> 5) == 7)) << (bit & 0x1F)); r->d[7] = t & 0xFFFFFFFFULL; + + rustsecp256k1_v0_9_0_scalar_verify(r); #ifdef VERIFY VERIFY_CHECK((t >> 32) == 0); - VERIFY_CHECK(rustsecp256k1_v0_9_0_scalar_check_overflow(r) == 0); #endif } static void rustsecp256k1_v0_9_0_scalar_set_b32(rustsecp256k1_v0_9_0_scalar *r, const unsigned char *b32, int *overflow) { int over; - r->d[0] = (uint32_t)b32[31] | (uint32_t)b32[30] << 8 | (uint32_t)b32[29] << 16 | (uint32_t)b32[28] << 24; - r->d[1] = (uint32_t)b32[27] | (uint32_t)b32[26] << 8 | (uint32_t)b32[25] << 16 | (uint32_t)b32[24] << 24; - r->d[2] = (uint32_t)b32[23] | (uint32_t)b32[22] << 8 | (uint32_t)b32[21] << 16 | (uint32_t)b32[20] << 24; - r->d[3] = (uint32_t)b32[19] | (uint32_t)b32[18] << 8 | (uint32_t)b32[17] << 16 | (uint32_t)b32[16] << 24; - r->d[4] = (uint32_t)b32[15] | (uint32_t)b32[14] << 8 | (uint32_t)b32[13] << 16 | (uint32_t)b32[12] << 24; - r->d[5] = (uint32_t)b32[11] | (uint32_t)b32[10] << 8 | (uint32_t)b32[9] << 16 | (uint32_t)b32[8] << 24; - r->d[6] = (uint32_t)b32[7] | (uint32_t)b32[6] << 8 | (uint32_t)b32[5] << 16 | (uint32_t)b32[4] << 24; - r->d[7] = (uint32_t)b32[3] | (uint32_t)b32[2] << 8 | (uint32_t)b32[1] << 16 | (uint32_t)b32[0] << 24; + r->d[0] = rustsecp256k1_v0_9_0_read_be32(&b32[28]); + r->d[1] = rustsecp256k1_v0_9_0_read_be32(&b32[24]); + r->d[2] = rustsecp256k1_v0_9_0_read_be32(&b32[20]); + r->d[3] = rustsecp256k1_v0_9_0_read_be32(&b32[16]); + r->d[4] = rustsecp256k1_v0_9_0_read_be32(&b32[12]); + r->d[5] = rustsecp256k1_v0_9_0_read_be32(&b32[8]); + r->d[6] = rustsecp256k1_v0_9_0_read_be32(&b32[4]); + r->d[7] = rustsecp256k1_v0_9_0_read_be32(&b32[0]); over = rustsecp256k1_v0_9_0_scalar_reduce(r, rustsecp256k1_v0_9_0_scalar_check_overflow(r)); if (overflow) { *overflow = over; } + + rustsecp256k1_v0_9_0_scalar_verify(r); } static void rustsecp256k1_v0_9_0_scalar_get_b32(unsigned char *bin, const rustsecp256k1_v0_9_0_scalar* a) { - bin[0] = a->d[7] >> 24; bin[1] = a->d[7] >> 16; bin[2] = a->d[7] >> 8; bin[3] = a->d[7]; - bin[4] = a->d[6] >> 24; bin[5] = a->d[6] >> 16; bin[6] = a->d[6] >> 8; bin[7] = a->d[6]; - bin[8] = a->d[5] >> 24; bin[9] = a->d[5] >> 16; bin[10] = a->d[5] >> 8; bin[11] = a->d[5]; - bin[12] = a->d[4] >> 24; bin[13] = a->d[4] >> 16; bin[14] = a->d[4] >> 8; bin[15] = a->d[4]; - bin[16] = a->d[3] >> 24; bin[17] = a->d[3] >> 16; bin[18] = a->d[3] >> 8; bin[19] = a->d[3]; - bin[20] = a->d[2] >> 24; bin[21] = a->d[2] >> 16; bin[22] = a->d[2] >> 8; bin[23] = a->d[2]; - bin[24] = a->d[1] >> 24; bin[25] = a->d[1] >> 16; bin[26] = a->d[1] >> 8; bin[27] = a->d[1]; - bin[28] = a->d[0] >> 24; bin[29] = a->d[0] >> 16; bin[30] = a->d[0] >> 8; bin[31] = a->d[0]; + rustsecp256k1_v0_9_0_scalar_verify(a); + + rustsecp256k1_v0_9_0_write_be32(&bin[0], a->d[7]); + rustsecp256k1_v0_9_0_write_be32(&bin[4], a->d[6]); + rustsecp256k1_v0_9_0_write_be32(&bin[8], a->d[5]); + rustsecp256k1_v0_9_0_write_be32(&bin[12], a->d[4]); + rustsecp256k1_v0_9_0_write_be32(&bin[16], a->d[3]); + rustsecp256k1_v0_9_0_write_be32(&bin[20], a->d[2]); + rustsecp256k1_v0_9_0_write_be32(&bin[24], a->d[1]); + rustsecp256k1_v0_9_0_write_be32(&bin[28], a->d[0]); } SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_is_zero(const rustsecp256k1_v0_9_0_scalar *a) { + rustsecp256k1_v0_9_0_scalar_verify(a); + return (a->d[0] | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; } static void rustsecp256k1_v0_9_0_scalar_negate(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_scalar *a) { uint32_t nonzero = 0xFFFFFFFFUL * (rustsecp256k1_v0_9_0_scalar_is_zero(a) == 0); uint64_t t = (uint64_t)(~a->d[0]) + SECP256K1_N_0 + 1; + rustsecp256k1_v0_9_0_scalar_verify(a); + r->d[0] = t & nonzero; t >>= 32; t += (uint64_t)(~a->d[1]) + SECP256K1_N_1; r->d[1] = t & nonzero; t >>= 32; @@ -216,15 +241,21 @@ static void rustsecp256k1_v0_9_0_scalar_negate(rustsecp256k1_v0_9_0_scalar *r, c r->d[6] = t & nonzero; t >>= 32; t += (uint64_t)(~a->d[7]) + SECP256K1_N_7; r->d[7] = t & nonzero; + + rustsecp256k1_v0_9_0_scalar_verify(r); } SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_is_one(const rustsecp256k1_v0_9_0_scalar *a) { + rustsecp256k1_v0_9_0_scalar_verify(a); + return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; } static int rustsecp256k1_v0_9_0_scalar_is_high(const rustsecp256k1_v0_9_0_scalar *a) { int yes = 0; int no = 0; + rustsecp256k1_v0_9_0_scalar_verify(a); + no |= (a->d[7] < SECP256K1_N_H_7); yes |= (a->d[7] > SECP256K1_N_H_7) & ~no; no |= (a->d[6] < SECP256K1_N_H_6) & ~yes; /* No need for a > check. */ @@ -247,6 +278,8 @@ static int rustsecp256k1_v0_9_0_scalar_cond_negate(rustsecp256k1_v0_9_0_scalar * uint32_t mask = -vflag; uint32_t nonzero = 0xFFFFFFFFUL * (rustsecp256k1_v0_9_0_scalar_is_zero(r) == 0); uint64_t t = (uint64_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask); + rustsecp256k1_v0_9_0_scalar_verify(r); + r->d[0] = t & nonzero; t >>= 32; t += (uint64_t)(r->d[1] ^ mask) + (SECP256K1_N_1 & mask); r->d[1] = t & nonzero; t >>= 32; @@ -262,6 +295,8 @@ static int rustsecp256k1_v0_9_0_scalar_cond_negate(rustsecp256k1_v0_9_0_scalar * r->d[6] = t & nonzero; t >>= 32; t += (uint64_t)(r->d[7] ^ mask) + (SECP256K1_N_7 & mask); r->d[7] = t & nonzero; + + rustsecp256k1_v0_9_0_scalar_verify(r); return 2 * (mask == 0) - 1; } @@ -569,14 +604,21 @@ static void rustsecp256k1_v0_9_0_scalar_mul_512(uint32_t *l, const rustsecp256k1 static void rustsecp256k1_v0_9_0_scalar_mul(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_scalar *a, const rustsecp256k1_v0_9_0_scalar *b) { uint32_t l[16]; + rustsecp256k1_v0_9_0_scalar_verify(a); + rustsecp256k1_v0_9_0_scalar_verify(b); + rustsecp256k1_v0_9_0_scalar_mul_512(l, a, b); rustsecp256k1_v0_9_0_scalar_reduce_512(r, l); + + rustsecp256k1_v0_9_0_scalar_verify(r); } static int rustsecp256k1_v0_9_0_scalar_shr_int(rustsecp256k1_v0_9_0_scalar *r, int n) { int ret; + rustsecp256k1_v0_9_0_scalar_verify(r); VERIFY_CHECK(n > 0); VERIFY_CHECK(n < 16); + ret = r->d[0] & ((1 << n) - 1); r->d[0] = (r->d[0] >> n) + (r->d[1] << (32 - n)); r->d[1] = (r->d[1] >> n) + (r->d[2] << (32 - n)); @@ -586,10 +628,14 @@ static int rustsecp256k1_v0_9_0_scalar_shr_int(rustsecp256k1_v0_9_0_scalar *r, i r->d[5] = (r->d[5] >> n) + (r->d[6] << (32 - n)); r->d[6] = (r->d[6] >> n) + (r->d[7] << (32 - n)); r->d[7] = (r->d[7] >> n); + + rustsecp256k1_v0_9_0_scalar_verify(r); return ret; } static void rustsecp256k1_v0_9_0_scalar_split_128(rustsecp256k1_v0_9_0_scalar *r1, rustsecp256k1_v0_9_0_scalar *r2, const rustsecp256k1_v0_9_0_scalar *k) { + rustsecp256k1_v0_9_0_scalar_verify(k); + r1->d[0] = k->d[0]; r1->d[1] = k->d[1]; r1->d[2] = k->d[2]; @@ -606,9 +652,15 @@ static void rustsecp256k1_v0_9_0_scalar_split_128(rustsecp256k1_v0_9_0_scalar *r r2->d[5] = 0; r2->d[6] = 0; r2->d[7] = 0; + + rustsecp256k1_v0_9_0_scalar_verify(r1); + rustsecp256k1_v0_9_0_scalar_verify(r2); } SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_eq(const rustsecp256k1_v0_9_0_scalar *a, const rustsecp256k1_v0_9_0_scalar *b) { + rustsecp256k1_v0_9_0_scalar_verify(a); + rustsecp256k1_v0_9_0_scalar_verify(b); + return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3]) | (a->d[4] ^ b->d[4]) | (a->d[5] ^ b->d[5]) | (a->d[6] ^ b->d[6]) | (a->d[7] ^ b->d[7])) == 0; } @@ -617,7 +669,10 @@ SECP256K1_INLINE static void rustsecp256k1_v0_9_0_scalar_mul_shift_var(rustsecp2 unsigned int shiftlimbs; unsigned int shiftlow; unsigned int shifthigh; + rustsecp256k1_v0_9_0_scalar_verify(a); + rustsecp256k1_v0_9_0_scalar_verify(b); VERIFY_CHECK(shift >= 256); + rustsecp256k1_v0_9_0_scalar_mul_512(l, a, b); shiftlimbs = shift >> 5; shiftlow = shift & 0x1F; @@ -631,12 +686,16 @@ SECP256K1_INLINE static void rustsecp256k1_v0_9_0_scalar_mul_shift_var(rustsecp2 r->d[6] = shift < 320 ? (l[6 + shiftlimbs] >> shiftlow | (shift < 288 && shiftlow ? (l[7 + shiftlimbs] << shifthigh) : 0)) : 0; r->d[7] = shift < 288 ? (l[7 + shiftlimbs] >> shiftlow) : 0; rustsecp256k1_v0_9_0_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1); + + rustsecp256k1_v0_9_0_scalar_verify(r); } static SECP256K1_INLINE void rustsecp256k1_v0_9_0_scalar_cmov(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_scalar *a, int flag) { uint32_t mask0, mask1; volatile int vflag = flag; + rustsecp256k1_v0_9_0_scalar_verify(a); SECP256K1_CHECKMEM_CHECK_VERIFY(r->d, sizeof(r->d)); + mask0 = vflag + ~((uint32_t)0); mask1 = ~mask0; r->d[0] = (r->d[0] & mask0) | (a->d[0] & mask1); @@ -647,6 +706,8 @@ static SECP256K1_INLINE void rustsecp256k1_v0_9_0_scalar_cmov(rustsecp256k1_v0_9 r->d[5] = (r->d[5] & mask0) | (a->d[5] & mask1); r->d[6] = (r->d[6] & mask0) | (a->d[6] & mask1); r->d[7] = (r->d[7] & mask0) | (a->d[7] & mask1); + + rustsecp256k1_v0_9_0_scalar_verify(r); } static void rustsecp256k1_v0_9_0_scalar_from_signed30(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_modinv32_signed30 *a) { @@ -675,19 +736,14 @@ static void rustsecp256k1_v0_9_0_scalar_from_signed30(rustsecp256k1_v0_9_0_scala r->d[6] = a6 >> 12 | a7 << 18; r->d[7] = a7 >> 14 | a8 << 16; -#ifdef VERIFY - VERIFY_CHECK(rustsecp256k1_v0_9_0_scalar_check_overflow(r) == 0); -#endif + rustsecp256k1_v0_9_0_scalar_verify(r); } static void rustsecp256k1_v0_9_0_scalar_to_signed30(rustsecp256k1_v0_9_0_modinv32_signed30 *r, const rustsecp256k1_v0_9_0_scalar *a) { const uint32_t M30 = UINT32_MAX >> 2; const uint32_t a0 = a->d[0], a1 = a->d[1], a2 = a->d[2], a3 = a->d[3], a4 = a->d[4], a5 = a->d[5], a6 = a->d[6], a7 = a->d[7]; - -#ifdef VERIFY - VERIFY_CHECK(rustsecp256k1_v0_9_0_scalar_check_overflow(a) == 0); -#endif + rustsecp256k1_v0_9_0_scalar_verify(a); r->v[0] = a0 & M30; r->v[1] = (a0 >> 30 | a1 << 2) & M30; @@ -710,10 +766,13 @@ static void rustsecp256k1_v0_9_0_scalar_inverse(rustsecp256k1_v0_9_0_scalar *r, #ifdef VERIFY int zero_in = rustsecp256k1_v0_9_0_scalar_is_zero(x); #endif + rustsecp256k1_v0_9_0_scalar_verify(x); + rustsecp256k1_v0_9_0_scalar_to_signed30(&s, x); rustsecp256k1_v0_9_0_modinv32(&s, &rustsecp256k1_v0_9_0_const_modinfo_scalar); rustsecp256k1_v0_9_0_scalar_from_signed30(r, &s); + rustsecp256k1_v0_9_0_scalar_verify(r); #ifdef VERIFY VERIFY_CHECK(rustsecp256k1_v0_9_0_scalar_is_zero(r) == zero_in); #endif @@ -724,16 +783,21 @@ static void rustsecp256k1_v0_9_0_scalar_inverse_var(rustsecp256k1_v0_9_0_scalar #ifdef VERIFY int zero_in = rustsecp256k1_v0_9_0_scalar_is_zero(x); #endif + rustsecp256k1_v0_9_0_scalar_verify(x); + rustsecp256k1_v0_9_0_scalar_to_signed30(&s, x); rustsecp256k1_v0_9_0_modinv32_var(&s, &rustsecp256k1_v0_9_0_const_modinfo_scalar); rustsecp256k1_v0_9_0_scalar_from_signed30(r, &s); + rustsecp256k1_v0_9_0_scalar_verify(r); #ifdef VERIFY VERIFY_CHECK(rustsecp256k1_v0_9_0_scalar_is_zero(r) == zero_in); #endif } SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_is_even(const rustsecp256k1_v0_9_0_scalar *a) { + rustsecp256k1_v0_9_0_scalar_verify(a); + return !(a->d[0] & 1); } diff --git a/secp256k1-sys/depend/secp256k1/src/scalar_impl.h b/secp256k1-sys/depend/secp256k1/src/scalar_impl.h index 10e0c2814..6207fa8de 100644 --- a/secp256k1-sys/depend/secp256k1/src/scalar_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar_impl.h @@ -30,9 +30,19 @@ static const rustsecp256k1_v0_9_0_scalar rustsecp256k1_v0_9_0_scalar_zero = SECP static int rustsecp256k1_v0_9_0_scalar_set_b32_seckey(rustsecp256k1_v0_9_0_scalar *r, const unsigned char *bin) { int overflow; rustsecp256k1_v0_9_0_scalar_set_b32(r, bin, &overflow); + + rustsecp256k1_v0_9_0_scalar_verify(r); return (!overflow) & (!rustsecp256k1_v0_9_0_scalar_is_zero(r)); } +static void rustsecp256k1_v0_9_0_scalar_verify(const rustsecp256k1_v0_9_0_scalar *r) { +#ifdef VERIFY + VERIFY_CHECK(rustsecp256k1_v0_9_0_scalar_check_overflow(r) == 0); +#endif + + (void)r; +} + #if defined(EXHAUSTIVE_TEST_ORDER) /* Begin of section generated by sage/gen_exhaustive_groups.sage. */ # if EXHAUSTIVE_TEST_ORDER == 7 @@ -53,11 +63,16 @@ static int rustsecp256k1_v0_9_0_scalar_set_b32_seckey(rustsecp256k1_v0_9_0_scala * (arbitrarily) set r2 = k + 5 (mod n) and r1 = k - r2 * lambda (mod n). */ static void rustsecp256k1_v0_9_0_scalar_split_lambda(rustsecp256k1_v0_9_0_scalar * SECP256K1_RESTRICT r1, rustsecp256k1_v0_9_0_scalar * SECP256K1_RESTRICT r2, const rustsecp256k1_v0_9_0_scalar * SECP256K1_RESTRICT k) { + rustsecp256k1_v0_9_0_scalar_verify(k); VERIFY_CHECK(r1 != k); VERIFY_CHECK(r2 != k); VERIFY_CHECK(r1 != r2); + *r2 = (*k + 5) % EXHAUSTIVE_TEST_ORDER; *r1 = (*k + (EXHAUSTIVE_TEST_ORDER - *r2) * EXHAUSTIVE_TEST_LAMBDA) % EXHAUSTIVE_TEST_ORDER; + + rustsecp256k1_v0_9_0_scalar_verify(r1); + rustsecp256k1_v0_9_0_scalar_verify(r2); } #else /** @@ -140,9 +155,11 @@ static void rustsecp256k1_v0_9_0_scalar_split_lambda(rustsecp256k1_v0_9_0_scalar 0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C4UL, 0x221208ACUL, 0x9DF506C6UL, 0x1571B4AEUL, 0x8AC47F71UL ); + rustsecp256k1_v0_9_0_scalar_verify(k); VERIFY_CHECK(r1 != k); VERIFY_CHECK(r2 != k); VERIFY_CHECK(r1 != r2); + /* these _var calls are constant time since the shift amount is constant */ rustsecp256k1_v0_9_0_scalar_mul_shift_var(&c1, k, &g1, 384); rustsecp256k1_v0_9_0_scalar_mul_shift_var(&c2, k, &g2, 384); @@ -153,6 +170,8 @@ static void rustsecp256k1_v0_9_0_scalar_split_lambda(rustsecp256k1_v0_9_0_scalar rustsecp256k1_v0_9_0_scalar_negate(r1, r1); rustsecp256k1_v0_9_0_scalar_add(r1, r1, k); + rustsecp256k1_v0_9_0_scalar_verify(r1); + rustsecp256k1_v0_9_0_scalar_verify(r2); #ifdef VERIFY rustsecp256k1_v0_9_0_scalar_split_lambda_verify(r1, r2, k); #endif diff --git a/secp256k1-sys/depend/secp256k1/src/scalar_low_impl.h b/secp256k1-sys/depend/secp256k1/src/scalar_low_impl.h index 53855ad74..505aad700 100644 --- a/secp256k1-sys/depend/secp256k1/src/scalar_low_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar_low_impl.h @@ -14,13 +14,22 @@ #include SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_is_even(const rustsecp256k1_v0_9_0_scalar *a) { + rustsecp256k1_v0_9_0_scalar_verify(a); + return !(*a & 1); } SECP256K1_INLINE static void rustsecp256k1_v0_9_0_scalar_clear(rustsecp256k1_v0_9_0_scalar *r) { *r = 0; } -SECP256K1_INLINE static void rustsecp256k1_v0_9_0_scalar_set_int(rustsecp256k1_v0_9_0_scalar *r, unsigned int v) { *r = v; } + +SECP256K1_INLINE static void rustsecp256k1_v0_9_0_scalar_set_int(rustsecp256k1_v0_9_0_scalar *r, unsigned int v) { + *r = v % EXHAUSTIVE_TEST_ORDER; + + rustsecp256k1_v0_9_0_scalar_verify(r); +} SECP256K1_INLINE static unsigned int rustsecp256k1_v0_9_0_scalar_get_bits(const rustsecp256k1_v0_9_0_scalar *a, unsigned int offset, unsigned int count) { + rustsecp256k1_v0_9_0_scalar_verify(a); + if (offset < 32) return ((*a >> offset) & ((((uint32_t)1) << count) - 1)); else @@ -28,24 +37,34 @@ SECP256K1_INLINE static unsigned int rustsecp256k1_v0_9_0_scalar_get_bits(const } SECP256K1_INLINE static unsigned int rustsecp256k1_v0_9_0_scalar_get_bits_var(const rustsecp256k1_v0_9_0_scalar *a, unsigned int offset, unsigned int count) { + rustsecp256k1_v0_9_0_scalar_verify(a); + return rustsecp256k1_v0_9_0_scalar_get_bits(a, offset, count); } SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_check_overflow(const rustsecp256k1_v0_9_0_scalar *a) { return *a >= EXHAUSTIVE_TEST_ORDER; } static int rustsecp256k1_v0_9_0_scalar_add(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_scalar *a, const rustsecp256k1_v0_9_0_scalar *b) { + rustsecp256k1_v0_9_0_scalar_verify(a); + rustsecp256k1_v0_9_0_scalar_verify(b); + *r = (*a + *b) % EXHAUSTIVE_TEST_ORDER; + + rustsecp256k1_v0_9_0_scalar_verify(r); return *r < *b; } static void rustsecp256k1_v0_9_0_scalar_cadd_bit(rustsecp256k1_v0_9_0_scalar *r, unsigned int bit, int flag) { + rustsecp256k1_v0_9_0_scalar_verify(r); + if (flag && bit < 32) *r += ((uint32_t)1 << bit); + + rustsecp256k1_v0_9_0_scalar_verify(r); #ifdef VERIFY VERIFY_CHECK(bit < 32); /* Verify that adding (1 << bit) will not overflow any in-range scalar *r by overflowing the underlying uint32_t. */ VERIFY_CHECK(((uint32_t)1 << bit) - 1 <= UINT32_MAX - EXHAUSTIVE_TEST_ORDER); - VERIFY_CHECK(rustsecp256k1_v0_9_0_scalar_check_overflow(r) == 0); #endif } @@ -61,82 +80,129 @@ static void rustsecp256k1_v0_9_0_scalar_set_b32(rustsecp256k1_v0_9_0_scalar *r, } } if (overflow) *overflow = over; + + rustsecp256k1_v0_9_0_scalar_verify(r); } static void rustsecp256k1_v0_9_0_scalar_get_b32(unsigned char *bin, const rustsecp256k1_v0_9_0_scalar* a) { + rustsecp256k1_v0_9_0_scalar_verify(a); + memset(bin, 0, 32); bin[28] = *a >> 24; bin[29] = *a >> 16; bin[30] = *a >> 8; bin[31] = *a; } SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_is_zero(const rustsecp256k1_v0_9_0_scalar *a) { + rustsecp256k1_v0_9_0_scalar_verify(a); + return *a == 0; } static void rustsecp256k1_v0_9_0_scalar_negate(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_scalar *a) { + rustsecp256k1_v0_9_0_scalar_verify(a); + if (*a == 0) { *r = 0; } else { *r = EXHAUSTIVE_TEST_ORDER - *a; } + + rustsecp256k1_v0_9_0_scalar_verify(r); } SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_is_one(const rustsecp256k1_v0_9_0_scalar *a) { + rustsecp256k1_v0_9_0_scalar_verify(a); + return *a == 1; } static int rustsecp256k1_v0_9_0_scalar_is_high(const rustsecp256k1_v0_9_0_scalar *a) { + rustsecp256k1_v0_9_0_scalar_verify(a); + return *a > EXHAUSTIVE_TEST_ORDER / 2; } static int rustsecp256k1_v0_9_0_scalar_cond_negate(rustsecp256k1_v0_9_0_scalar *r, int flag) { + rustsecp256k1_v0_9_0_scalar_verify(r); + if (flag) rustsecp256k1_v0_9_0_scalar_negate(r, r); + + rustsecp256k1_v0_9_0_scalar_verify(r); return flag ? -1 : 1; } static void rustsecp256k1_v0_9_0_scalar_mul(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_scalar *a, const rustsecp256k1_v0_9_0_scalar *b) { + rustsecp256k1_v0_9_0_scalar_verify(a); + rustsecp256k1_v0_9_0_scalar_verify(b); + *r = (*a * *b) % EXHAUSTIVE_TEST_ORDER; + + rustsecp256k1_v0_9_0_scalar_verify(r); } static int rustsecp256k1_v0_9_0_scalar_shr_int(rustsecp256k1_v0_9_0_scalar *r, int n) { int ret; + rustsecp256k1_v0_9_0_scalar_verify(r); VERIFY_CHECK(n > 0); VERIFY_CHECK(n < 16); + ret = *r & ((1 << n) - 1); *r >>= n; + + rustsecp256k1_v0_9_0_scalar_verify(r); return ret; } static void rustsecp256k1_v0_9_0_scalar_split_128(rustsecp256k1_v0_9_0_scalar *r1, rustsecp256k1_v0_9_0_scalar *r2, const rustsecp256k1_v0_9_0_scalar *a) { + rustsecp256k1_v0_9_0_scalar_verify(a); + *r1 = *a; *r2 = 0; + + rustsecp256k1_v0_9_0_scalar_verify(r1); + rustsecp256k1_v0_9_0_scalar_verify(r2); } SECP256K1_INLINE static int rustsecp256k1_v0_9_0_scalar_eq(const rustsecp256k1_v0_9_0_scalar *a, const rustsecp256k1_v0_9_0_scalar *b) { + rustsecp256k1_v0_9_0_scalar_verify(a); + rustsecp256k1_v0_9_0_scalar_verify(b); + return *a == *b; } static SECP256K1_INLINE void rustsecp256k1_v0_9_0_scalar_cmov(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_scalar *a, int flag) { uint32_t mask0, mask1; volatile int vflag = flag; + rustsecp256k1_v0_9_0_scalar_verify(a); SECP256K1_CHECKMEM_CHECK_VERIFY(r, sizeof(*r)); + mask0 = vflag + ~((uint32_t)0); mask1 = ~mask0; *r = (*r & mask0) | (*a & mask1); + + rustsecp256k1_v0_9_0_scalar_verify(r); } static void rustsecp256k1_v0_9_0_scalar_inverse(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_scalar *x) { int i; *r = 0; + rustsecp256k1_v0_9_0_scalar_verify(x); + for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) if ((i * *x) % EXHAUSTIVE_TEST_ORDER == 1) *r = i; + + rustsecp256k1_v0_9_0_scalar_verify(r); /* If this VERIFY_CHECK triggers we were given a noninvertible scalar (and thus * have a composite group order; fix it in exhaustive_tests.c). */ VERIFY_CHECK(*r != 0); } static void rustsecp256k1_v0_9_0_scalar_inverse_var(rustsecp256k1_v0_9_0_scalar *r, const rustsecp256k1_v0_9_0_scalar *x) { + rustsecp256k1_v0_9_0_scalar_verify(x); + rustsecp256k1_v0_9_0_scalar_inverse(r, x); + + rustsecp256k1_v0_9_0_scalar_verify(r); } #endif /* SECP256K1_SCALAR_REPR_IMPL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/secp256k1.c b/secp256k1-sys/depend/secp256k1/src/secp256k1.c index 602eb4a4e..1ffb81414 100644 --- a/secp256k1-sys/depend/secp256k1/src/secp256k1.c +++ b/secp256k1-sys/depend/secp256k1/src/secp256k1.c @@ -201,8 +201,8 @@ static int rustsecp256k1_v0_9_0_pubkey_load(const rustsecp256k1_v0_9_0_context* } else { /* Otherwise, fall back to 32-byte big endian for X and Y. */ rustsecp256k1_v0_9_0_fe x, y; - rustsecp256k1_v0_9_0_fe_set_b32_mod(&x, pubkey->data); - rustsecp256k1_v0_9_0_fe_set_b32_mod(&y, pubkey->data + 32); + ARG_CHECK(rustsecp256k1_v0_9_0_fe_set_b32_limit(&x, pubkey->data)); + ARG_CHECK(rustsecp256k1_v0_9_0_fe_set_b32_limit(&y, pubkey->data + 32)); rustsecp256k1_v0_9_0_ge_set_xy(ge, &x, &y); } ARG_CHECK(!rustsecp256k1_v0_9_0_fe_is_zero(&ge->x)); @@ -765,3 +765,7 @@ int rustsecp256k1_v0_9_0_tagged_sha256(const rustsecp256k1_v0_9_0_context* ctx, #ifdef ENABLE_MODULE_SCHNORRSIG # include "modules/schnorrsig/main_impl.h" #endif + +#ifdef ENABLE_MODULE_ELLSWIFT +# include "modules/ellswift/main_impl.h" +#endif diff --git a/secp256k1-sys/depend/secp256k1/src/testrand_impl.h b/secp256k1-sys/depend/secp256k1/src/testrand_impl.h index 0f7201903..3c05a5725 100644 --- a/secp256k1-sys/depend/secp256k1/src/testrand_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/testrand_impl.h @@ -16,8 +16,6 @@ #include "util.h" static uint64_t rustsecp256k1_v0_9_0_test_state[4]; -static uint64_t rustsecp256k1_v0_9_0_test_rng_integer; -static int rustsecp256k1_v0_9_0_test_rng_integer_bits_left = 0; SECP256K1_INLINE static void rustsecp256k1_v0_9_0_testrand_seed(const unsigned char *seed16) { static const unsigned char PREFIX[19] = "secp256k1 test init"; @@ -36,7 +34,6 @@ SECP256K1_INLINE static void rustsecp256k1_v0_9_0_testrand_seed(const unsigned c for (j = 0; j < 8; ++j) s = (s << 8) | out32[8*i + j]; rustsecp256k1_v0_9_0_test_state[i] = s; } - rustsecp256k1_v0_9_0_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 rustsecp256k1_v0_9_0_testrand64(void) { } SECP256K1_INLINE static uint64_t rustsecp256k1_v0_9_0_testrand_bits(int bits) { - uint64_t ret; - if (rustsecp256k1_v0_9_0_test_rng_integer_bits_left < bits) { - rustsecp256k1_v0_9_0_test_rng_integer = rustsecp256k1_v0_9_0_testrand64(); - rustsecp256k1_v0_9_0_test_rng_integer_bits_left = 64; - } - ret = rustsecp256k1_v0_9_0_test_rng_integer; - rustsecp256k1_v0_9_0_test_rng_integer >>= bits; - rustsecp256k1_v0_9_0_test_rng_integer_bits_left -= bits; - ret &= ((~((uint64_t)0)) >> (64 - bits)); - return ret; + if (bits == 0) return 0; + return rustsecp256k1_v0_9_0_testrand64() >> (64 - bits); } SECP256K1_INLINE static uint32_t rustsecp256k1_v0_9_0_testrand32(void) { - return rustsecp256k1_v0_9_0_testrand_bits(32); + return rustsecp256k1_v0_9_0_testrand64() >> 32; } static uint32_t rustsecp256k1_v0_9_0_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; - } - trange = range - 1; - while (trange > 0) { - trange >>= 1; - bits++; + 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; } - 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 = rustsecp256k1_v0_9_0_testrand_bits(bits); - if (x < trange) { - return (mult == 1) ? x : (x % range); - } + /* Generation loop. */ + while (1) { + uint32_t val = rustsecp256k1_v0_9_0_testrand64() & mask; + if (val <= range) return val; } } diff --git a/secp256k1-sys/depend/secp256k1/src/tests.c b/secp256k1-sys/depend/secp256k1/src/tests.c index a48efd01c..030bbf5b9 100644 --- a/secp256k1-sys/depend/secp256k1/src/tests.c +++ b/secp256k1-sys/depend/secp256k1/src/tests.c @@ -14,6 +14,9 @@ #pragma message("Ignoring USE_EXTERNAL_CALLBACKS in tests.") #undef USE_EXTERNAL_DEFAULT_CALLBACKS #endif +#if defined(VERIFY) && defined(COVERAGE) + #pragma message("Defining VERIFY for tests being built for coverage analysis support is meaningless.") +#endif #include "secp256k1.c" #include "../include/secp256k1.h" @@ -86,36 +89,66 @@ static void uncounting_illegal_callback_fn(const char* str, void* data) { (*p)--; } -static void random_field_element_test(rustsecp256k1_v0_9_0_fe *fe) { - do { - unsigned char b32[32]; - rustsecp256k1_v0_9_0_testrand256_test(b32); - if (rustsecp256k1_v0_9_0_fe_set_b32_limit(fe, b32)) { - break; - } - } while(1); -} - -static void random_field_element_magnitude(rustsecp256k1_v0_9_0_fe *fe) { +static void random_field_element_magnitude(rustsecp256k1_v0_9_0_fe *fe, int m) { rustsecp256k1_v0_9_0_fe zero; - int n = rustsecp256k1_v0_9_0_testrand_int(9); + int n = rustsecp256k1_v0_9_0_testrand_int(m + 1); rustsecp256k1_v0_9_0_fe_normalize(fe); if (n == 0) { return; } rustsecp256k1_v0_9_0_fe_clear(&zero); rustsecp256k1_v0_9_0_fe_negate(&zero, &zero, 0); - rustsecp256k1_v0_9_0_fe_mul_int(&zero, n - 1); + rustsecp256k1_v0_9_0_fe_mul_int_unchecked(&zero, n - 1); rustsecp256k1_v0_9_0_fe_add(fe, &zero); #ifdef VERIFY CHECK(fe->magnitude == n); #endif } +static void random_fe_test(rustsecp256k1_v0_9_0_fe *x) { + unsigned char bin[32]; + do { + rustsecp256k1_v0_9_0_testrand256_test(bin); + if (rustsecp256k1_v0_9_0_fe_set_b32_limit(x, bin)) { + return; + } + } while(1); +} + +static void random_fe_non_zero_test(rustsecp256k1_v0_9_0_fe *fe) { + do { + random_fe_test(fe); + } while(rustsecp256k1_v0_9_0_fe_is_zero(fe)); +} + +static void random_fe_magnitude(rustsecp256k1_v0_9_0_fe *fe) { + random_field_element_magnitude(fe, 8); +} + +static void random_ge_x_magnitude(rustsecp256k1_v0_9_0_ge *ge) { + random_field_element_magnitude(&ge->x, SECP256K1_GE_X_MAGNITUDE_MAX); +} + +static void random_ge_y_magnitude(rustsecp256k1_v0_9_0_ge *ge) { + random_field_element_magnitude(&ge->y, SECP256K1_GE_Y_MAGNITUDE_MAX); +} + +static void random_gej_x_magnitude(rustsecp256k1_v0_9_0_gej *gej) { + random_field_element_magnitude(&gej->x, SECP256K1_GEJ_X_MAGNITUDE_MAX); +} + +static void random_gej_y_magnitude(rustsecp256k1_v0_9_0_gej *gej) { + random_field_element_magnitude(&gej->y, SECP256K1_GEJ_Y_MAGNITUDE_MAX); +} + +static void random_gej_z_magnitude(rustsecp256k1_v0_9_0_gej *gej) { + random_field_element_magnitude(&gej->z, SECP256K1_GEJ_Z_MAGNITUDE_MAX); +} + static void random_group_element_test(rustsecp256k1_v0_9_0_ge *ge) { rustsecp256k1_v0_9_0_fe fe; do { - random_field_element_test(&fe); + random_fe_test(&fe); if (rustsecp256k1_v0_9_0_ge_set_xo_var(ge, &fe, rustsecp256k1_v0_9_0_testrand_bits(1))) { rustsecp256k1_v0_9_0_fe_normalize(&ge->y); break; @@ -126,12 +159,7 @@ static void random_group_element_test(rustsecp256k1_v0_9_0_ge *ge) { static void random_group_element_jacobian_test(rustsecp256k1_v0_9_0_gej *gej, const rustsecp256k1_v0_9_0_ge *ge) { rustsecp256k1_v0_9_0_fe z2, z3; - do { - random_field_element_test(&gej->z); - if (!rustsecp256k1_v0_9_0_fe_is_zero(&gej->z)) { - break; - } - } while(1); + random_fe_non_zero_test(&gej->z); rustsecp256k1_v0_9_0_fe_sqr(&z2, &gej->z); rustsecp256k1_v0_9_0_fe_mul(&z3, &z2, &gej->z); rustsecp256k1_v0_9_0_fe_mul(&gej->x, &ge->x, &z2); @@ -177,6 +205,35 @@ static void random_scalar_order_b32(unsigned char *b32) { rustsecp256k1_v0_9_0_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(rustsecp256k1_v0_9_0_test_state)/sizeof(rustsecp256k1_v0_9_0_test_state[0]); i++) { + CHECK(rustsecp256k1_v0_9_0_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, + }; + rustsecp256k1_v0_9_0_testrand_seed(seed16); + for (i = 0; i < 17; i++) { + rustsecp256k1_v0_9_0_testrand256(buf32); + } + CHECK(rustsecp256k1_v0_9_0_memcmp_var(buf32, buf32_expected, sizeof(buf32)) == 0); + } +} + static void run_selftest_tests(void) { /* Test public API */ rustsecp256k1_v0_9_0_selftest(); @@ -694,6 +751,17 @@ static void run_sha256_counter_tests(void) { } } +/* Tests for the equality of two sha256 structs. This function only produces a + * correct result if an integer multiple of 64 many bytes have been written + * into the hash functions. This function is used by some module tests. */ +static void test_sha256_eq(const rustsecp256k1_v0_9_0_sha256 *sha1, const rustsecp256k1_v0_9_0_sha256 *sha2) { + /* Is buffer fully consumed? */ + CHECK((sha1->bytes & 0x3F) == 0); + + CHECK(sha1->bytes == sha2->bytes); + CHECK(rustsecp256k1_v0_9_0_memcmp_var(sha1->s, sha2->s, sizeof(sha1->s)) == 0); +} + static void run_hmac_sha256_tests(void) { static const char *keys[6] = { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", @@ -809,78 +877,6 @@ static void run_tagged_sha256_tests(void) { CHECK(rustsecp256k1_v0_9_0_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 ? rustsecp256k1_v0_9_0_testrand32() : rustsecp256k1_v0_9_0_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 = rustsecp256k1_v0_9_0_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. */ @@ -2304,26 +2300,23 @@ static void scalar_test(void) { { /* Test multiplicative identity. */ - rustsecp256k1_v0_9_0_scalar r1, v1; - rustsecp256k1_v0_9_0_scalar_set_int(&v1,1); - rustsecp256k1_v0_9_0_scalar_mul(&r1, &s1, &v1); + rustsecp256k1_v0_9_0_scalar r1; + rustsecp256k1_v0_9_0_scalar_mul(&r1, &s1, &rustsecp256k1_v0_9_0_scalar_one); CHECK(rustsecp256k1_v0_9_0_scalar_eq(&r1, &s1)); } { /* Test additive identity. */ - rustsecp256k1_v0_9_0_scalar r1, v0; - rustsecp256k1_v0_9_0_scalar_set_int(&v0,0); - rustsecp256k1_v0_9_0_scalar_add(&r1, &s1, &v0); + rustsecp256k1_v0_9_0_scalar r1; + rustsecp256k1_v0_9_0_scalar_add(&r1, &s1, &rustsecp256k1_v0_9_0_scalar_zero); CHECK(rustsecp256k1_v0_9_0_scalar_eq(&r1, &s1)); } { /* Test zero product property. */ - rustsecp256k1_v0_9_0_scalar r1, v0; - rustsecp256k1_v0_9_0_scalar_set_int(&v0,0); - rustsecp256k1_v0_9_0_scalar_mul(&r1, &s1, &v0); - CHECK(rustsecp256k1_v0_9_0_scalar_eq(&r1, &v0)); + rustsecp256k1_v0_9_0_scalar r1; + rustsecp256k1_v0_9_0_scalar_mul(&r1, &s1, &rustsecp256k1_v0_9_0_scalar_zero); + CHECK(rustsecp256k1_v0_9_0_scalar_eq(&r1, &rustsecp256k1_v0_9_0_scalar_zero)); } } @@ -2354,13 +2347,25 @@ static void run_scalar_tests(void) { run_scalar_set_b32_seckey_tests(); } + { + /* Check that the scalar constants rustsecp256k1_v0_9_0_scalar_zero and + rustsecp256k1_v0_9_0_scalar_one contain the expected values. */ + rustsecp256k1_v0_9_0_scalar zero, one; + + CHECK(rustsecp256k1_v0_9_0_scalar_is_zero(&rustsecp256k1_v0_9_0_scalar_zero)); + rustsecp256k1_v0_9_0_scalar_set_int(&zero, 0); + CHECK(rustsecp256k1_v0_9_0_scalar_eq(&zero, &rustsecp256k1_v0_9_0_scalar_zero)); + + CHECK(rustsecp256k1_v0_9_0_scalar_is_one(&rustsecp256k1_v0_9_0_scalar_one)); + rustsecp256k1_v0_9_0_scalar_set_int(&one, 1); + CHECK(rustsecp256k1_v0_9_0_scalar_eq(&one, &rustsecp256k1_v0_9_0_scalar_one)); + } + { /* (-1)+1 should be zero. */ - rustsecp256k1_v0_9_0_scalar s, o; - rustsecp256k1_v0_9_0_scalar_set_int(&s, 1); - CHECK(rustsecp256k1_v0_9_0_scalar_is_one(&s)); - rustsecp256k1_v0_9_0_scalar_negate(&o, &s); - rustsecp256k1_v0_9_0_scalar_add(&o, &o, &s); + rustsecp256k1_v0_9_0_scalar o; + rustsecp256k1_v0_9_0_scalar_negate(&o, &rustsecp256k1_v0_9_0_scalar_one); + rustsecp256k1_v0_9_0_scalar_add(&o, &o, &rustsecp256k1_v0_9_0_scalar_one); CHECK(rustsecp256k1_v0_9_0_scalar_is_zero(&o)); rustsecp256k1_v0_9_0_scalar_negate(&o, &o); CHECK(rustsecp256k1_v0_9_0_scalar_is_zero(&o)); @@ -2385,7 +2390,6 @@ static void run_scalar_tests(void) { rustsecp256k1_v0_9_0_scalar y; rustsecp256k1_v0_9_0_scalar z; rustsecp256k1_v0_9_0_scalar zz; - rustsecp256k1_v0_9_0_scalar one; rustsecp256k1_v0_9_0_scalar r1; rustsecp256k1_v0_9_0_scalar r2; rustsecp256k1_v0_9_0_scalar zzv; @@ -2922,7 +2926,6 @@ static void run_scalar_tests(void) { 0x1e, 0x86, 0x5d, 0x89, 0x63, 0xe6, 0x0a, 0x46, 0x5c, 0x02, 0x97, 0x1b, 0x62, 0x43, 0x86, 0xf5}} }; - rustsecp256k1_v0_9_0_scalar_set_int(&one, 1); for (i = 0; i < 33; i++) { rustsecp256k1_v0_9_0_scalar_set_b32(&x, chal[i][0], &overflow); CHECK(!overflow); @@ -2945,7 +2948,7 @@ static void run_scalar_tests(void) { CHECK(rustsecp256k1_v0_9_0_scalar_eq(&x, &z)); rustsecp256k1_v0_9_0_scalar_mul(&zz, &zz, &y); CHECK(!rustsecp256k1_v0_9_0_scalar_check_overflow(&zz)); - CHECK(rustsecp256k1_v0_9_0_scalar_eq(&one, &zz)); + CHECK(rustsecp256k1_v0_9_0_scalar_eq(&rustsecp256k1_v0_9_0_scalar_one, &zz)); } } } @@ -2963,16 +2966,6 @@ static void random_fe(rustsecp256k1_v0_9_0_fe *x) { } while(1); } -static void random_fe_test(rustsecp256k1_v0_9_0_fe *x) { - unsigned char bin[32]; - do { - rustsecp256k1_v0_9_0_testrand256_test(bin); - if (rustsecp256k1_v0_9_0_fe_set_b32_limit(x, bin)) { - return; - } - } while(1); -} - static void random_fe_non_zero(rustsecp256k1_v0_9_0_fe *nz) { int tries = 10; while (--tries >= 0) { @@ -2998,8 +2991,7 @@ static int check_fe_equal(const rustsecp256k1_v0_9_0_fe *a, const rustsecp256k1_ rustsecp256k1_v0_9_0_fe an = *a; rustsecp256k1_v0_9_0_fe bn = *b; rustsecp256k1_v0_9_0_fe_normalize_weak(&an); - rustsecp256k1_v0_9_0_fe_normalize_var(&bn); - return rustsecp256k1_v0_9_0_fe_equal_var(&an, &bn); + return rustsecp256k1_v0_9_0_fe_equal(&an, &bn); } static void run_field_convert(void) { @@ -3022,9 +3014,9 @@ static void run_field_convert(void) { rustsecp256k1_v0_9_0_fe_storage fes2; /* Check conversions to fe. */ CHECK(rustsecp256k1_v0_9_0_fe_set_b32_limit(&fe2, b32)); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&fe, &fe2)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&fe, &fe2)); rustsecp256k1_v0_9_0_fe_from_storage(&fe2, &fes); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&fe, &fe2)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&fe, &fe2)); /* Check conversion from fe. */ rustsecp256k1_v0_9_0_fe_get_b32(b322, &fe); CHECK(rustsecp256k1_v0_9_0_memcmp_var(b322, b32, 32) == 0); @@ -3101,10 +3093,6 @@ static void run_field_be32_overflow(void) { /* Returns true if two field elements have the same representation. */ static int fe_identical(const rustsecp256k1_v0_9_0_fe *a, const rustsecp256k1_v0_9_0_fe *b) { int ret = 1; -#ifdef VERIFY - ret &= (a->magnitude == b->magnitude); - ret &= (a->normalized == b->normalized); -#endif /* Compare the struct member that holds the limbs. */ ret &= (rustsecp256k1_v0_9_0_memcmp_var(a->n, b->n, sizeof(a->n)) == 0); return ret; @@ -3185,37 +3173,43 @@ static void run_field_misc(void) { CHECK(check_fe_equal(&q, &z)); /* Test the fe equality and comparison operations. */ CHECK(rustsecp256k1_v0_9_0_fe_cmp_var(&x, &x) == 0); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&x, &x)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&x, &x)); z = x; rustsecp256k1_v0_9_0_fe_add(&z,&y); /* Test fe conditional move; z is not normalized here. */ q = x; rustsecp256k1_v0_9_0_fe_cmov(&x, &z, 0); #ifdef VERIFY - CHECK(x.normalized && x.magnitude == 1); + CHECK(!x.normalized); + CHECK((x.magnitude == q.magnitude) || (x.magnitude == z.magnitude)); + CHECK((x.magnitude >= q.magnitude) && (x.magnitude >= z.magnitude)); #endif + x = q; rustsecp256k1_v0_9_0_fe_cmov(&x, &x, 1); CHECK(!fe_identical(&x, &z)); CHECK(fe_identical(&x, &q)); rustsecp256k1_v0_9_0_fe_cmov(&q, &z, 1); #ifdef VERIFY - CHECK(!q.normalized && q.magnitude == z.magnitude); + CHECK(!q.normalized); + CHECK((q.magnitude == x.magnitude) || (q.magnitude == z.magnitude)); + CHECK((q.magnitude >= x.magnitude) && (q.magnitude >= z.magnitude)); #endif CHECK(fe_identical(&q, &z)); + q = z; rustsecp256k1_v0_9_0_fe_normalize_var(&x); rustsecp256k1_v0_9_0_fe_normalize_var(&z); - CHECK(!rustsecp256k1_v0_9_0_fe_equal_var(&x, &z)); + CHECK(!rustsecp256k1_v0_9_0_fe_equal(&x, &z)); rustsecp256k1_v0_9_0_fe_normalize_var(&q); rustsecp256k1_v0_9_0_fe_cmov(&q, &z, (i&1)); #ifdef VERIFY CHECK(q.normalized && q.magnitude == 1); #endif for (j = 0; j < 6; j++) { - rustsecp256k1_v0_9_0_fe_negate(&z, &z, j+1); + rustsecp256k1_v0_9_0_fe_negate_unchecked(&z, &z, j+1); rustsecp256k1_v0_9_0_fe_normalize_var(&q); rustsecp256k1_v0_9_0_fe_cmov(&q, &z, (j&1)); #ifdef VERIFY - CHECK((q.normalized != (j&1)) && q.magnitude == ((j&1) ? z.magnitude : 1)); + CHECK(!q.normalized && q.magnitude == z.magnitude); #endif } rustsecp256k1_v0_9_0_fe_normalize_var(&z); @@ -3308,13 +3302,13 @@ static void run_fe_mul(void) { for (i = 0; i < 100 * COUNT; ++i) { rustsecp256k1_v0_9_0_fe a, b, c, d; random_fe(&a); - random_field_element_magnitude(&a); + random_fe_magnitude(&a); random_fe(&b); - random_field_element_magnitude(&b); + random_fe_magnitude(&b); random_fe_test(&c); - random_field_element_magnitude(&c); + random_fe_magnitude(&c); random_fe_test(&d); - random_field_element_magnitude(&d); + random_fe_magnitude(&d); test_fe_mul(&a, &a, 1); test_fe_mul(&c, &c, 1); test_fe_mul(&a, &b, 0); @@ -3709,8 +3703,8 @@ static void ge_equals_ge(const rustsecp256k1_v0_9_0_ge *a, const rustsecp256k1_v if (a->infinity) { return; } - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&a->x, &b->x)); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&a->y, &b->y)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&a->x, &b->x)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&a->y, &b->y)); } /* This compares jacobian points including their Z, not just their geometric meaning. */ @@ -3745,11 +3739,11 @@ static void ge_equals_gej(const rustsecp256k1_v0_9_0_ge *a, const rustsecp256k1_ /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */ rustsecp256k1_v0_9_0_fe_sqr(&z2s, &b->z); rustsecp256k1_v0_9_0_fe_mul(&u1, &a->x, &z2s); - u2 = b->x; rustsecp256k1_v0_9_0_fe_normalize_weak(&u2); + u2 = b->x; rustsecp256k1_v0_9_0_fe_mul(&s1, &a->y, &z2s); rustsecp256k1_v0_9_0_fe_mul(&s1, &s1, &b->z); - s2 = b->y; rustsecp256k1_v0_9_0_fe_normalize_weak(&s2); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&u1, &u2)); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&s1, &s2)); + s2 = b->y; + CHECK(rustsecp256k1_v0_9_0_fe_equal(&u1, &u2)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&s1, &s2)); } static void test_ge(void) { @@ -3763,7 +3757,7 @@ static void test_ge(void) { */ rustsecp256k1_v0_9_0_ge *ge = (rustsecp256k1_v0_9_0_ge *)checked_malloc(&CTX->error_callback, sizeof(rustsecp256k1_v0_9_0_ge) * (1 + 4 * runs)); rustsecp256k1_v0_9_0_gej *gej = (rustsecp256k1_v0_9_0_gej *)checked_malloc(&CTX->error_callback, sizeof(rustsecp256k1_v0_9_0_gej) * (1 + 4 * runs)); - rustsecp256k1_v0_9_0_fe zf; + rustsecp256k1_v0_9_0_fe zf, r; rustsecp256k1_v0_9_0_fe zfi2, zfi3; rustsecp256k1_v0_9_0_gej_set_infinity(&gej[0]); @@ -3788,23 +3782,24 @@ static void test_ge(void) { rustsecp256k1_v0_9_0_gej_set_ge(&gej[3 + 4 * i], &ge[3 + 4 * i]); random_group_element_jacobian_test(&gej[4 + 4 * i], &ge[4 + 4 * i]); for (j = 0; j < 4; j++) { - random_field_element_magnitude(&ge[1 + j + 4 * i].x); - random_field_element_magnitude(&ge[1 + j + 4 * i].y); - random_field_element_magnitude(&gej[1 + j + 4 * i].x); - random_field_element_magnitude(&gej[1 + j + 4 * i].y); - random_field_element_magnitude(&gej[1 + j + 4 * i].z); + random_ge_x_magnitude(&ge[1 + j + 4 * i]); + random_ge_y_magnitude(&ge[1 + j + 4 * i]); + random_gej_x_magnitude(&gej[1 + j + 4 * i]); + random_gej_y_magnitude(&gej[1 + j + 4 * i]); + random_gej_z_magnitude(&gej[1 + j + 4 * i]); } } /* Generate random zf, and zfi2 = 1/zf^2, zfi3 = 1/zf^3 */ - do { - random_field_element_test(&zf); - } while(rustsecp256k1_v0_9_0_fe_is_zero(&zf)); - random_field_element_magnitude(&zf); + random_fe_non_zero_test(&zf); + random_fe_magnitude(&zf); rustsecp256k1_v0_9_0_fe_inv_var(&zfi3, &zf); rustsecp256k1_v0_9_0_fe_sqr(&zfi2, &zfi3); rustsecp256k1_v0_9_0_fe_mul(&zfi3, &zfi3, &zfi2); + /* Generate random r */ + random_fe_non_zero_test(&r); + for (i1 = 0; i1 < 1 + 4 * runs; i1++) { int i2; for (i2 = 0; i2 < 1 + 4 * runs; i2++) { @@ -3816,7 +3811,7 @@ static void test_ge(void) { /* Check Z ratio. */ if (!rustsecp256k1_v0_9_0_gej_is_infinity(&gej[i1]) && !rustsecp256k1_v0_9_0_gej_is_infinity(&refj)) { rustsecp256k1_v0_9_0_fe zrz; rustsecp256k1_v0_9_0_fe_mul(&zrz, &zr, &gej[i1].z); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&zrz, &refj.z)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&zrz, &refj.z)); } rustsecp256k1_v0_9_0_ge_set_gej_var(&ref, &refj); @@ -3825,7 +3820,7 @@ static void test_ge(void) { ge_equals_gej(&ref, &resj); if (!rustsecp256k1_v0_9_0_gej_is_infinity(&gej[i1]) && !rustsecp256k1_v0_9_0_gej_is_infinity(&resj)) { rustsecp256k1_v0_9_0_fe zrz; rustsecp256k1_v0_9_0_fe_mul(&zrz, &zr, &gej[i1].z); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&zrz, &resj.z)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&zrz, &resj.z)); } /* Test gej + ge (var, with additional Z factor). */ @@ -3833,8 +3828,8 @@ static void test_ge(void) { rustsecp256k1_v0_9_0_ge ge2_zfi = ge[i2]; /* the second term with x and y rescaled for z = 1/zf */ rustsecp256k1_v0_9_0_fe_mul(&ge2_zfi.x, &ge2_zfi.x, &zfi2); rustsecp256k1_v0_9_0_fe_mul(&ge2_zfi.y, &ge2_zfi.y, &zfi3); - random_field_element_magnitude(&ge2_zfi.x); - random_field_element_magnitude(&ge2_zfi.y); + random_ge_x_magnitude(&ge2_zfi); + random_ge_y_magnitude(&ge2_zfi); rustsecp256k1_v0_9_0_gej_add_zinv_var(&resj, &gej[i1], &ge2_zfi, &zf); ge_equals_gej(&ref, &resj); } @@ -3854,7 +3849,7 @@ static void test_ge(void) { ge_equals_gej(&ref, &resj); /* Check Z ratio. */ rustsecp256k1_v0_9_0_fe_mul(&zr2, &zr2, &gej[i1].z); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&zr2, &resj.z)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&zr2, &resj.z)); /* Normal doubling. */ rustsecp256k1_v0_9_0_gej_double_var(&resj, &gej[i2], NULL); ge_equals_gej(&ref, &resj); @@ -3917,6 +3912,29 @@ static void test_ge(void) { free(ge_set_all); } + /* Test that all elements have X coordinates on the curve. */ + for (i = 1; i < 4 * runs + 1; i++) { + rustsecp256k1_v0_9_0_fe n; + CHECK(rustsecp256k1_v0_9_0_ge_x_on_curve_var(&ge[i].x)); + /* And the same holds after random rescaling. */ + rustsecp256k1_v0_9_0_fe_mul(&n, &zf, &ge[i].x); + CHECK(rustsecp256k1_v0_9_0_ge_x_frac_on_curve_var(&n, &zf)); + } + + /* Test correspondence of rustsecp256k1_v0_9_0_ge_x{,_frac}_on_curve_var with ge_set_xo. */ + { + rustsecp256k1_v0_9_0_fe n; + rustsecp256k1_v0_9_0_ge q; + int ret_on_curve, ret_frac_on_curve, ret_set_xo; + rustsecp256k1_v0_9_0_fe_mul(&n, &zf, &r); + ret_on_curve = rustsecp256k1_v0_9_0_ge_x_on_curve_var(&r); + ret_frac_on_curve = rustsecp256k1_v0_9_0_ge_x_frac_on_curve_var(&n, &zf); + ret_set_xo = rustsecp256k1_v0_9_0_ge_set_xo_var(&q, &r, 0); + CHECK(ret_on_curve == ret_frac_on_curve); + CHECK(ret_on_curve == ret_set_xo); + if (ret_set_xo) CHECK(rustsecp256k1_v0_9_0_fe_equal(&r, &q.x)); + } + /* Test batch gej -> ge conversion with many infinities. */ for (i = 0; i < 4 * runs + 1; i++) { int odd; @@ -3997,22 +4015,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("rustsecp256k1_v0_9_0_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()) */ rustsecp256k1_v0_9_0_gej aj = SECP256K1_GEJ_CONST( 0x8d24cd95, 0x0a355af1, 0x3c543505, 0x44238d30, @@ -4097,17 +4108,14 @@ static void run_gej(void) { CHECK(!rustsecp256k1_v0_9_0_gej_eq_var(&a, &b)); b = a; - random_field_element_test(&fe); - if (rustsecp256k1_v0_9_0_fe_is_zero(&fe)) { - continue; - } + random_fe_non_zero_test(&fe); rustsecp256k1_v0_9_0_gej_rescale(&a, &fe); CHECK(rustsecp256k1_v0_9_0_gej_eq_var(&a, &b)); } } static void test_ec_combine(void) { - rustsecp256k1_v0_9_0_scalar sum = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + rustsecp256k1_v0_9_0_scalar sum = rustsecp256k1_v0_9_0_scalar_zero; rustsecp256k1_v0_9_0_pubkey data[6]; const rustsecp256k1_v0_9_0_pubkey* d[6]; rustsecp256k1_v0_9_0_pubkey sd; @@ -4164,8 +4172,8 @@ static void test_group_decompress(const rustsecp256k1_v0_9_0_fe* x) { CHECK(!ge_odd.infinity); /* Check that the x coordinates check out. */ - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&ge_even.x, x)); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&ge_odd.x, x)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&ge_even.x, x)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&ge_odd.x, x)); /* Check odd/even Y in ge_odd, ge_even. */ CHECK(rustsecp256k1_v0_9_0_fe_is_odd(&ge_odd.y)); @@ -4217,18 +4225,18 @@ static void test_pre_g_table(const rustsecp256k1_v0_9_0_ge_storage * pre_g, size rustsecp256k1_v0_9_0_ge_from_storage(&q, &pre_g[i]); CHECK(rustsecp256k1_v0_9_0_ge_is_valid_var(&q)); - rustsecp256k1_v0_9_0_fe_negate(&dqx, &q.x, 1); rustsecp256k1_v0_9_0_fe_add(&dqx, &gg.x); rustsecp256k1_v0_9_0_fe_normalize_weak(&dqx); - dqy = q.y; rustsecp256k1_v0_9_0_fe_add(&dqy, &gg.y); rustsecp256k1_v0_9_0_fe_normalize_weak(&dqy); + rustsecp256k1_v0_9_0_fe_negate(&dqx, &q.x, 1); rustsecp256k1_v0_9_0_fe_add(&dqx, &gg.x); + dqy = q.y; rustsecp256k1_v0_9_0_fe_add(&dqy, &gg.y); /* Check that -q is not equal to gg */ CHECK(!rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(&dqx) || !rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(&dqy)); /* Check that -q is not equal to p */ - CHECK(!rustsecp256k1_v0_9_0_fe_equal_var(&dpx, &dqx) || !rustsecp256k1_v0_9_0_fe_equal_var(&dpy, &dqy)); + CHECK(!rustsecp256k1_v0_9_0_fe_equal(&dpx, &dqx) || !rustsecp256k1_v0_9_0_fe_equal(&dpy, &dqy)); /* Check that p, -q and gg are colinear */ rustsecp256k1_v0_9_0_fe_mul(&dpx, &dpx, &dqy); rustsecp256k1_v0_9_0_fe_mul(&dpy, &dpy, &dqx); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&dpx, &dpy)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&dpx, &dpy)); p = q; } @@ -4279,8 +4287,8 @@ static void run_ecmult_chain(void) { static const rustsecp256k1_v0_9_0_scalar xf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x1337); static const rustsecp256k1_v0_9_0_scalar gf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x7113); /* accumulators with the resulting coefficients to A and G */ - rustsecp256k1_v0_9_0_scalar ae = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); - rustsecp256k1_v0_9_0_scalar ge = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + rustsecp256k1_v0_9_0_scalar ae = rustsecp256k1_v0_9_0_scalar_one; + rustsecp256k1_v0_9_0_scalar ge = rustsecp256k1_v0_9_0_scalar_zero; /* actual points */ rustsecp256k1_v0_9_0_gej x; rustsecp256k1_v0_9_0_gej x2; @@ -4321,8 +4329,6 @@ static void test_point_times_order(const rustsecp256k1_v0_9_0_gej *point) { /* X * (point + G) + (order-X) * (pointer + G) = 0 */ rustsecp256k1_v0_9_0_scalar x; rustsecp256k1_v0_9_0_scalar nx; - rustsecp256k1_v0_9_0_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); - rustsecp256k1_v0_9_0_scalar one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); rustsecp256k1_v0_9_0_gej res1, res2; rustsecp256k1_v0_9_0_ge res3; unsigned char pub[65]; @@ -4340,13 +4346,13 @@ static void test_point_times_order(const rustsecp256k1_v0_9_0_gej *point) { psize = 65; CHECK(rustsecp256k1_v0_9_0_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0); /* check zero/one edge cases */ - rustsecp256k1_v0_9_0_ecmult(&res1, point, &zero, &zero); + rustsecp256k1_v0_9_0_ecmult(&res1, point, &rustsecp256k1_v0_9_0_scalar_zero, &rustsecp256k1_v0_9_0_scalar_zero); rustsecp256k1_v0_9_0_ge_set_gej(&res3, &res1); CHECK(rustsecp256k1_v0_9_0_ge_is_infinity(&res3)); - rustsecp256k1_v0_9_0_ecmult(&res1, point, &one, &zero); + rustsecp256k1_v0_9_0_ecmult(&res1, point, &rustsecp256k1_v0_9_0_scalar_one, &rustsecp256k1_v0_9_0_scalar_zero); rustsecp256k1_v0_9_0_ge_set_gej(&res3, &res1); ge_equals_gej(&res3, point); - rustsecp256k1_v0_9_0_ecmult(&res1, point, &zero, &one); + rustsecp256k1_v0_9_0_ecmult(&res1, point, &rustsecp256k1_v0_9_0_scalar_zero, &rustsecp256k1_v0_9_0_scalar_one); rustsecp256k1_v0_9_0_ge_set_gej(&res3, &res1); ge_equals_ge(&res3, &rustsecp256k1_v0_9_0_ge_const_g); } @@ -4386,7 +4392,6 @@ static void test_ecmult_target(const rustsecp256k1_v0_9_0_scalar* target, int mo rustsecp256k1_v0_9_0_scalar n1, n2; rustsecp256k1_v0_9_0_ge p; rustsecp256k1_v0_9_0_gej pj, p1j, p2j, ptj; - static const rustsecp256k1_v0_9_0_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); /* Generate random n1,n2 such that n1+n2 = -target. */ random_scalar_order_test(&n1); @@ -4405,9 +4410,9 @@ static void test_ecmult_target(const rustsecp256k1_v0_9_0_scalar* target, int mo rustsecp256k1_v0_9_0_ecmult_gen(&CTX->ecmult_gen_ctx, &p2j, &n2); rustsecp256k1_v0_9_0_ecmult_gen(&CTX->ecmult_gen_ctx, &ptj, target); } else if (mode == 1) { - rustsecp256k1_v0_9_0_ecmult(&p1j, &pj, &n1, &zero); - rustsecp256k1_v0_9_0_ecmult(&p2j, &pj, &n2, &zero); - rustsecp256k1_v0_9_0_ecmult(&ptj, &pj, target, &zero); + rustsecp256k1_v0_9_0_ecmult(&p1j, &pj, &n1, &rustsecp256k1_v0_9_0_scalar_zero); + rustsecp256k1_v0_9_0_ecmult(&p2j, &pj, &n2, &rustsecp256k1_v0_9_0_scalar_zero); + rustsecp256k1_v0_9_0_ecmult(&ptj, &pj, target, &rustsecp256k1_v0_9_0_scalar_zero); } else { rustsecp256k1_v0_9_0_ecmult_const(&p1j, &p, &n1); rustsecp256k1_v0_9_0_ecmult_const(&p2j, &p, &n2); @@ -4450,7 +4455,7 @@ static void run_point_times_order(void) { rustsecp256k1_v0_9_0_fe_sqr(&x, &x); } rustsecp256k1_v0_9_0_fe_normalize_var(&x); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&x, &xr)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&x, &xr)); } static void ecmult_const_random_mult(void) { @@ -4502,19 +4507,17 @@ static void ecmult_const_commutativity(void) { } static void ecmult_const_mult_zero_one(void) { - rustsecp256k1_v0_9_0_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); - rustsecp256k1_v0_9_0_scalar one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); rustsecp256k1_v0_9_0_scalar negone; rustsecp256k1_v0_9_0_gej res1; rustsecp256k1_v0_9_0_ge res2; rustsecp256k1_v0_9_0_ge point; - rustsecp256k1_v0_9_0_scalar_negate(&negone, &one); + rustsecp256k1_v0_9_0_scalar_negate(&negone, &rustsecp256k1_v0_9_0_scalar_one); random_group_element_test(&point); - rustsecp256k1_v0_9_0_ecmult_const(&res1, &point, &zero); + rustsecp256k1_v0_9_0_ecmult_const(&res1, &point, &rustsecp256k1_v0_9_0_scalar_zero); rustsecp256k1_v0_9_0_ge_set_gej(&res2, &res1); CHECK(rustsecp256k1_v0_9_0_ge_is_infinity(&res2)); - rustsecp256k1_v0_9_0_ecmult_const(&res1, &point, &one); + rustsecp256k1_v0_9_0_ecmult_const(&res1, &point, &rustsecp256k1_v0_9_0_scalar_one); rustsecp256k1_v0_9_0_ge_set_gej(&res2, &res1); ge_equals_ge(&res2, &point); rustsecp256k1_v0_9_0_ecmult_const(&res1, &point, &negone); @@ -4539,9 +4542,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 (rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(&d)); + random_fe_non_zero_test(&d); rustsecp256k1_v0_9_0_fe_mul(&n, &base.x, &d); } else { n = base.x; @@ -4560,22 +4561,17 @@ static void ecmult_const_mult_xonly(void) { /* Test that rustsecp256k1_v0_9_0_ecmult_const_xonly correctly rejects X coordinates not on curve. */ for (i = 0; i < 2*COUNT; ++i) { - rustsecp256k1_v0_9_0_fe x, n, d, c, r; + rustsecp256k1_v0_9_0_fe x, n, d, r; int res; rustsecp256k1_v0_9_0_scalar q; random_scalar_order_test(&q); /* Generate random X coordinate not on the curve. */ do { - random_field_element_test(&x); - rustsecp256k1_v0_9_0_fe_sqr(&c, &x); - rustsecp256k1_v0_9_0_fe_mul(&c, &c, &x); - rustsecp256k1_v0_9_0_fe_add_int(&c, SECP256K1_B); - } while (rustsecp256k1_v0_9_0_fe_is_square_var(&c)); + random_fe_test(&x); + } while (rustsecp256k1_v0_9_0_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 (rustsecp256k1_v0_9_0_fe_normalizes_to_zero_var(&d)); + random_fe_non_zero_test(&d); rustsecp256k1_v0_9_0_fe_mul(&n, &x, &d); } else { n = x; @@ -4641,7 +4637,6 @@ static int ecmult_multi_false_callback(rustsecp256k1_v0_9_0_scalar *sc, rustsecp static void test_ecmult_multi(rustsecp256k1_v0_9_0_scratch *scratch, rustsecp256k1_v0_9_0_ecmult_multi_func ecmult_multi) { int ncount; - rustsecp256k1_v0_9_0_scalar szero; rustsecp256k1_v0_9_0_scalar sc[32]; rustsecp256k1_v0_9_0_ge pt[32]; rustsecp256k1_v0_9_0_gej r; @@ -4650,7 +4645,6 @@ static void test_ecmult_multi(rustsecp256k1_v0_9_0_scratch *scratch, rustsecp256 data.sc = sc; data.pt = pt; - rustsecp256k1_v0_9_0_scalar_set_int(&szero, 0); /* No points to multiply */ CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, NULL, ecmult_multi_callback, &data, 0)); @@ -4668,21 +4662,21 @@ static void test_ecmult_multi(rustsecp256k1_v0_9_0_scratch *scratch, rustsecp256 pt[1] = rustsecp256k1_v0_9_0_ge_const_g; /* only G scalar */ - rustsecp256k1_v0_9_0_ecmult(&r2, &ptgj, &szero, &sc[0]); + rustsecp256k1_v0_9_0_ecmult(&r2, &ptgj, &rustsecp256k1_v0_9_0_scalar_zero, &sc[0]); CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &sc[0], ecmult_multi_callback, &data, 0)); CHECK(rustsecp256k1_v0_9_0_gej_eq_var(&r, &r2)); /* 1-point */ - rustsecp256k1_v0_9_0_ecmult(&r2, &ptgj, &sc[0], &szero); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 1)); + rustsecp256k1_v0_9_0_ecmult(&r2, &ptgj, &sc[0], &rustsecp256k1_v0_9_0_scalar_zero); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_9_0_scalar_zero, ecmult_multi_callback, &data, 1)); CHECK(rustsecp256k1_v0_9_0_gej_eq_var(&r, &r2)); /* Try to multiply 1 point, but callback returns false */ - CHECK(!ecmult_multi(&CTX->error_callback, scratch, &r, &szero, ecmult_multi_false_callback, &data, 1)); + CHECK(!ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_9_0_scalar_zero, ecmult_multi_false_callback, &data, 1)); /* 2-point */ rustsecp256k1_v0_9_0_ecmult(&r2, &ptgj, &sc[0], &sc[1]); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 2)); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_9_0_scalar_zero, ecmult_multi_callback, &data, 2)); CHECK(rustsecp256k1_v0_9_0_gej_eq_var(&r, &r2)); /* 2-point with G scalar */ @@ -4702,7 +4696,7 @@ static void test_ecmult_multi(rustsecp256k1_v0_9_0_scratch *scratch, rustsecp256 random_scalar_order(&sc[i]); rustsecp256k1_v0_9_0_ge_set_infinity(&pt[i]); } - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_9_0_scalar_zero, ecmult_multi_callback, &data, sizes[j])); CHECK(rustsecp256k1_v0_9_0_gej_is_infinity(&r)); } @@ -4712,7 +4706,7 @@ static void test_ecmult_multi(rustsecp256k1_v0_9_0_scratch *scratch, rustsecp256 pt[i] = ptg; rustsecp256k1_v0_9_0_scalar_set_int(&sc[i], 0); } - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_9_0_scalar_zero, ecmult_multi_callback, &data, sizes[j])); CHECK(rustsecp256k1_v0_9_0_gej_is_infinity(&r)); } @@ -4725,7 +4719,7 @@ static void test_ecmult_multi(rustsecp256k1_v0_9_0_scratch *scratch, rustsecp256 pt[2 * i + 1] = ptg; } - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_9_0_scalar_zero, ecmult_multi_callback, &data, sizes[j])); CHECK(rustsecp256k1_v0_9_0_gej_is_infinity(&r)); random_scalar_order(&sc[0]); @@ -4738,7 +4732,7 @@ static void test_ecmult_multi(rustsecp256k1_v0_9_0_scratch *scratch, rustsecp256 rustsecp256k1_v0_9_0_ge_neg(&pt[2*i+1], &pt[2*i]); } - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_9_0_scalar_zero, ecmult_multi_callback, &data, sizes[j])); CHECK(rustsecp256k1_v0_9_0_gej_is_infinity(&r)); } @@ -4753,7 +4747,7 @@ static void test_ecmult_multi(rustsecp256k1_v0_9_0_scratch *scratch, rustsecp256 rustsecp256k1_v0_9_0_scalar_negate(&sc[i], &sc[i]); } - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 32)); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_9_0_scalar_zero, ecmult_multi_callback, &data, 32)); CHECK(rustsecp256k1_v0_9_0_gej_is_infinity(&r)); } @@ -4771,8 +4765,8 @@ static void test_ecmult_multi(rustsecp256k1_v0_9_0_scratch *scratch, rustsecp256 rustsecp256k1_v0_9_0_gej_add_ge_var(&r, &r, &pt[i], NULL); } - rustsecp256k1_v0_9_0_ecmult(&r2, &r, &sc[0], &szero); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20)); + rustsecp256k1_v0_9_0_ecmult(&r2, &r, &sc[0], &rustsecp256k1_v0_9_0_scalar_zero); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_9_0_scalar_zero, ecmult_multi_callback, &data, 20)); CHECK(rustsecp256k1_v0_9_0_gej_eq_var(&r, &r2)); } @@ -4792,8 +4786,8 @@ static void test_ecmult_multi(rustsecp256k1_v0_9_0_scratch *scratch, rustsecp256 } rustsecp256k1_v0_9_0_gej_set_ge(&p0j, &pt[0]); - rustsecp256k1_v0_9_0_ecmult(&r2, &p0j, &rs, &szero); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20)); + rustsecp256k1_v0_9_0_ecmult(&r2, &p0j, &rs, &rustsecp256k1_v0_9_0_scalar_zero); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_9_0_scalar_zero, ecmult_multi_callback, &data, 20)); CHECK(rustsecp256k1_v0_9_0_gej_eq_var(&r, &r2)); } @@ -4804,13 +4798,13 @@ static void test_ecmult_multi(rustsecp256k1_v0_9_0_scratch *scratch, rustsecp256 } rustsecp256k1_v0_9_0_scalar_clear(&sc[0]); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20)); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_9_0_scalar_zero, ecmult_multi_callback, &data, 20)); rustsecp256k1_v0_9_0_scalar_clear(&sc[1]); rustsecp256k1_v0_9_0_scalar_clear(&sc[2]); rustsecp256k1_v0_9_0_scalar_clear(&sc[3]); rustsecp256k1_v0_9_0_scalar_clear(&sc[4]); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 6)); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 5)); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_9_0_scalar_zero, ecmult_multi_callback, &data, 6)); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_9_0_scalar_zero, ecmult_multi_callback, &data, 5)); CHECK(rustsecp256k1_v0_9_0_gej_is_infinity(&r)); /* Run through s0*(t0*P) + s1*(t1*P) exhaustively for many small values of s0, s1, t0, t1 */ @@ -4834,8 +4828,8 @@ static void test_ecmult_multi(rustsecp256k1_v0_9_0_scratch *scratch, rustsecp256 rustsecp256k1_v0_9_0_scalar_set_int(&t1, (t1i + 1) / 2); rustsecp256k1_v0_9_0_scalar_cond_negate(&t1, t1i & 1); - rustsecp256k1_v0_9_0_ecmult(&t0p, &ptgj, &t0, &szero); - rustsecp256k1_v0_9_0_ecmult(&t1p, &ptgj, &t1, &szero); + rustsecp256k1_v0_9_0_ecmult(&t0p, &ptgj, &t0, &rustsecp256k1_v0_9_0_scalar_zero); + rustsecp256k1_v0_9_0_ecmult(&t1p, &ptgj, &t1, &rustsecp256k1_v0_9_0_scalar_zero); for(s0i = 0; s0i < TOP; s0i++) { for(s1i = 0; s1i < TOP; s1i++) { @@ -4854,8 +4848,8 @@ static void test_ecmult_multi(rustsecp256k1_v0_9_0_scratch *scratch, rustsecp256 rustsecp256k1_v0_9_0_scalar_mul(&tmp2, &t1, &sc[1]); rustsecp256k1_v0_9_0_scalar_add(&tmp1, &tmp1, &tmp2); - rustsecp256k1_v0_9_0_ecmult(&expected, &ptgj, &tmp1, &szero); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &actual, &szero, ecmult_multi_callback, &data, 2)); + rustsecp256k1_v0_9_0_ecmult(&expected, &ptgj, &tmp1, &rustsecp256k1_v0_9_0_scalar_zero); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &actual, &rustsecp256k1_v0_9_0_scalar_zero, ecmult_multi_callback, &data, 2)); CHECK(rustsecp256k1_v0_9_0_gej_eq_var(&actual, &expected)); } } @@ -4878,7 +4872,7 @@ static int test_ecmult_multi_random(rustsecp256k1_v0_9_0_scratch *scratch) { * scalars[0..filled-1] and gejs[0..filled-1] are the scalars and points * which form its normal inputs. */ int filled = 0; - rustsecp256k1_v0_9_0_scalar g_scalar = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + rustsecp256k1_v0_9_0_scalar g_scalar = rustsecp256k1_v0_9_0_scalar_zero; rustsecp256k1_v0_9_0_scalar scalars[128]; rustsecp256k1_v0_9_0_gej gejs[128]; /* The expected result, and the computed result. */ @@ -5031,7 +5025,6 @@ static int test_ecmult_multi_random(rustsecp256k1_v0_9_0_scratch *scratch) { } static void test_ecmult_multi_batch_single(rustsecp256k1_v0_9_0_ecmult_multi_func ecmult_multi) { - rustsecp256k1_v0_9_0_scalar szero; rustsecp256k1_v0_9_0_scalar sc; rustsecp256k1_v0_9_0_ge pt; rustsecp256k1_v0_9_0_gej r; @@ -5042,11 +5035,10 @@ static void test_ecmult_multi_batch_single(rustsecp256k1_v0_9_0_ecmult_multi_fun random_scalar_order(&sc); data.sc = ≻ data.pt = &pt; - rustsecp256k1_v0_9_0_scalar_set_int(&szero, 0); /* Try to multiply 1 point, but scratch space is empty.*/ scratch_empty = rustsecp256k1_v0_9_0_scratch_create(&CTX->error_callback, 0); - CHECK(!ecmult_multi(&CTX->error_callback, scratch_empty, &r, &szero, ecmult_multi_callback, &data, 1)); + CHECK(!ecmult_multi(&CTX->error_callback, scratch_empty, &r, &rustsecp256k1_v0_9_0_scalar_zero, ecmult_multi_callback, &data, 1)); rustsecp256k1_v0_9_0_scratch_destroy(&CTX->error_callback, scratch_empty); } @@ -5154,7 +5146,6 @@ static void test_ecmult_multi_batch_size_helper(void) { static void test_ecmult_multi_batching(void) { static const int n_points = 2*ECMULT_PIPPENGER_THRESHOLD; rustsecp256k1_v0_9_0_scalar scG; - rustsecp256k1_v0_9_0_scalar szero; rustsecp256k1_v0_9_0_scalar *sc = (rustsecp256k1_v0_9_0_scalar *)checked_malloc(&CTX->error_callback, sizeof(rustsecp256k1_v0_9_0_scalar) * n_points); rustsecp256k1_v0_9_0_ge *pt = (rustsecp256k1_v0_9_0_ge *)checked_malloc(&CTX->error_callback, sizeof(rustsecp256k1_v0_9_0_ge) * n_points); rustsecp256k1_v0_9_0_gej r; @@ -5164,11 +5155,10 @@ static void test_ecmult_multi_batching(void) { rustsecp256k1_v0_9_0_scratch *scratch; rustsecp256k1_v0_9_0_gej_set_infinity(&r2); - rustsecp256k1_v0_9_0_scalar_set_int(&szero, 0); /* Get random scalars and group elements and compute result */ random_scalar_order(&scG); - rustsecp256k1_v0_9_0_ecmult(&r2, &r2, &szero, &scG); + rustsecp256k1_v0_9_0_ecmult(&r2, &r2, &rustsecp256k1_v0_9_0_scalar_zero, &scG); for(i = 0; i < n_points; i++) { rustsecp256k1_v0_9_0_ge ptg; rustsecp256k1_v0_9_0_gej ptgj; @@ -5493,16 +5483,15 @@ static void test_ecmult_accumulate(rustsecp256k1_v0_9_0_sha256* acc, const rusts /* Compute x*G in 6 different ways, serialize it uncompressed, and feed it into acc. */ rustsecp256k1_v0_9_0_gej rj1, rj2, rj3, rj4, rj5, rj6, gj, infj; rustsecp256k1_v0_9_0_ge r; - const rustsecp256k1_v0_9_0_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); unsigned char bytes[65]; size_t size = 65; rustsecp256k1_v0_9_0_gej_set_ge(&gj, &rustsecp256k1_v0_9_0_ge_const_g); rustsecp256k1_v0_9_0_gej_set_infinity(&infj); rustsecp256k1_v0_9_0_ecmult_gen(&CTX->ecmult_gen_ctx, &rj1, x); - rustsecp256k1_v0_9_0_ecmult(&rj2, &gj, x, &zero); - rustsecp256k1_v0_9_0_ecmult(&rj3, &infj, &zero, x); + rustsecp256k1_v0_9_0_ecmult(&rj2, &gj, x, &rustsecp256k1_v0_9_0_scalar_zero); + rustsecp256k1_v0_9_0_ecmult(&rj3, &infj, &rustsecp256k1_v0_9_0_scalar_zero, x); rustsecp256k1_v0_9_0_ecmult_multi_var(NULL, scratch, &rj4, x, NULL, NULL, 0); - rustsecp256k1_v0_9_0_ecmult_multi_var(NULL, scratch, &rj5, &zero, test_ecmult_accumulate_cb, (void*)x, 1); + rustsecp256k1_v0_9_0_ecmult_multi_var(NULL, scratch, &rj5, &rustsecp256k1_v0_9_0_scalar_zero, test_ecmult_accumulate_cb, (void*)x, 1); rustsecp256k1_v0_9_0_ecmult_const(&rj6, &rustsecp256k1_v0_9_0_ge_const_g, x); rustsecp256k1_v0_9_0_ge_set_gej_var(&r, &rj1); ge_equals_gej(&r, &rj2); @@ -7494,6 +7483,10 @@ static void run_ecdsa_wycheproof(void) { # include "modules/schnorrsig/tests_impl.h" #endif +#ifdef ENABLE_MODULE_ELLSWIFT +# include "modules/ellswift/tests_impl.h" +#endif + static void run_rustsecp256k1_v0_9_0_memczero_test(void) { unsigned char buf1[6] = {1, 2, 3, 4, 5, 6}; unsigned char buf2[sizeof(buf1)]; @@ -7510,16 +7503,31 @@ static void run_rustsecp256k1_v0_9_0_memczero_test(void) { } static void run_rustsecp256k1_v0_9_0_byteorder_tests(void) { - const uint32_t x = 0xFF03AB45; - const unsigned char x_be[4] = {0xFF, 0x03, 0xAB, 0x45}; - unsigned char buf[4]; - uint32_t x_; + { + const uint32_t x = 0xFF03AB45; + const unsigned char x_be[4] = {0xFF, 0x03, 0xAB, 0x45}; + unsigned char buf[4]; + uint32_t x_; - rustsecp256k1_v0_9_0_write_be32(buf, x); - CHECK(rustsecp256k1_v0_9_0_memcmp_var(buf, x_be, sizeof(buf)) == 0); + rustsecp256k1_v0_9_0_write_be32(buf, x); + CHECK(rustsecp256k1_v0_9_0_memcmp_var(buf, x_be, sizeof(buf)) == 0); - x_ = rustsecp256k1_v0_9_0_read_be32(buf); - CHECK(x == x_); + x_ = rustsecp256k1_v0_9_0_read_be32(buf); + CHECK(x == x_); + } + + { + const uint64_t x = 0xCAFE0123BEEF4567; + const unsigned char x_be[8] = {0xCA, 0xFE, 0x01, 0x23, 0xBE, 0xEF, 0x45, 0x67}; + unsigned char buf[8]; + uint64_t x_; + + rustsecp256k1_v0_9_0_write_be64(buf, x); + CHECK(rustsecp256k1_v0_9_0_memcmp_var(buf, x_be, sizeof(buf)) == 0); + + x_ = rustsecp256k1_v0_9_0_read_be64(buf); + CHECK(x == x_); + } } static void int_cmov_test(void) { @@ -7558,23 +7566,23 @@ static void fe_cmov_test(void) { rustsecp256k1_v0_9_0_fe a = zero; rustsecp256k1_v0_9_0_fe_cmov(&r, &a, 0); - CHECK(rustsecp256k1_v0_9_0_memcmp_var(&r, &max, sizeof(r)) == 0); + CHECK(fe_identical(&r, &max)); r = zero; a = max; rustsecp256k1_v0_9_0_fe_cmov(&r, &a, 1); - CHECK(rustsecp256k1_v0_9_0_memcmp_var(&r, &max, sizeof(r)) == 0); + CHECK(fe_identical(&r, &max)); a = zero; rustsecp256k1_v0_9_0_fe_cmov(&r, &a, 1); - CHECK(rustsecp256k1_v0_9_0_memcmp_var(&r, &zero, sizeof(r)) == 0); + CHECK(fe_identical(&r, &zero)); a = one; rustsecp256k1_v0_9_0_fe_cmov(&r, &a, 1); - CHECK(rustsecp256k1_v0_9_0_memcmp_var(&r, &one, sizeof(r)) == 0); + CHECK(fe_identical(&r, &one)); r = one; a = zero; rustsecp256k1_v0_9_0_fe_cmov(&r, &a, 0); - CHECK(rustsecp256k1_v0_9_0_memcmp_var(&r, &one, sizeof(r)) == 0); + CHECK(fe_identical(&r, &one)); } static void fe_storage_cmov_test(void) { @@ -7608,33 +7616,31 @@ static void fe_storage_cmov_test(void) { } static void scalar_cmov_test(void) { - static const rustsecp256k1_v0_9_0_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); - static const rustsecp256k1_v0_9_0_scalar one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); static const rustsecp256k1_v0_9_0_scalar max = SECP256K1_SCALAR_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, + 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364140UL ); rustsecp256k1_v0_9_0_scalar r = max; - rustsecp256k1_v0_9_0_scalar a = zero; + rustsecp256k1_v0_9_0_scalar a = rustsecp256k1_v0_9_0_scalar_zero; rustsecp256k1_v0_9_0_scalar_cmov(&r, &a, 0); CHECK(rustsecp256k1_v0_9_0_memcmp_var(&r, &max, sizeof(r)) == 0); - r = zero; a = max; + r = rustsecp256k1_v0_9_0_scalar_zero; a = max; rustsecp256k1_v0_9_0_scalar_cmov(&r, &a, 1); CHECK(rustsecp256k1_v0_9_0_memcmp_var(&r, &max, sizeof(r)) == 0); - a = zero; + a = rustsecp256k1_v0_9_0_scalar_zero; rustsecp256k1_v0_9_0_scalar_cmov(&r, &a, 1); - CHECK(rustsecp256k1_v0_9_0_memcmp_var(&r, &zero, sizeof(r)) == 0); + CHECK(rustsecp256k1_v0_9_0_memcmp_var(&r, &rustsecp256k1_v0_9_0_scalar_zero, sizeof(r)) == 0); - a = one; + a = rustsecp256k1_v0_9_0_scalar_one; rustsecp256k1_v0_9_0_scalar_cmov(&r, &a, 1); - CHECK(rustsecp256k1_v0_9_0_memcmp_var(&r, &one, sizeof(r)) == 0); + CHECK(rustsecp256k1_v0_9_0_memcmp_var(&r, &rustsecp256k1_v0_9_0_scalar_one, sizeof(r)) == 0); - r = one; a = zero; + r = rustsecp256k1_v0_9_0_scalar_one; a = rustsecp256k1_v0_9_0_scalar_zero; rustsecp256k1_v0_9_0_scalar_cmov(&r, &a, 0); - CHECK(rustsecp256k1_v0_9_0_memcmp_var(&r, &one, sizeof(r)) == 0); + CHECK(rustsecp256k1_v0_9_0_memcmp_var(&r, &rustsecp256k1_v0_9_0_scalar_one, sizeof(r)) == 0); } static void ge_storage_cmov_test(void) { @@ -7701,6 +7707,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 */ rustsecp256k1_v0_9_0_testrand_init(argc > 2 ? argv[2] : NULL); @@ -7738,10 +7747,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(); @@ -7826,6 +7831,10 @@ int main(int argc, char **argv) { run_schnorrsig_tests(); #endif +#ifdef ENABLE_MODULE_ELLSWIFT + run_ellswift_tests(); +#endif + /* util tests */ run_rustsecp256k1_v0_9_0_memczero_test(); run_rustsecp256k1_v0_9_0_byteorder_tests(); diff --git a/secp256k1-sys/depend/secp256k1/src/tests_exhaustive.c b/secp256k1-sys/depend/secp256k1/src/tests_exhaustive.c index bad4c3c13..e4c6915e7 100644 --- a/secp256k1-sys/depend/secp256k1/src/tests_exhaustive.c +++ b/secp256k1-sys/depend/secp256k1/src/tests_exhaustive.c @@ -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 @@ -35,8 +38,8 @@ static void ge_equals_ge(const rustsecp256k1_v0_9_0_ge *a, const rustsecp256k1_v if (a->infinity) { return; } - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&a->x, &b->x)); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&a->y, &b->y)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&a->x, &b->x)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&a->y, &b->y)); } static void ge_equals_gej(const rustsecp256k1_v0_9_0_ge *a, const rustsecp256k1_v0_9_0_gej *b) { @@ -49,11 +52,11 @@ static void ge_equals_gej(const rustsecp256k1_v0_9_0_ge *a, const rustsecp256k1_ /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */ rustsecp256k1_v0_9_0_fe_sqr(&z2s, &b->z); rustsecp256k1_v0_9_0_fe_mul(&u1, &a->x, &z2s); - u2 = b->x; rustsecp256k1_v0_9_0_fe_normalize_weak(&u2); + u2 = b->x; rustsecp256k1_v0_9_0_fe_mul(&s1, &a->y, &z2s); rustsecp256k1_v0_9_0_fe_mul(&s1, &s1, &b->z); - s2 = b->y; rustsecp256k1_v0_9_0_fe_normalize_weak(&s2); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&u1, &u2)); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&s1, &s2)); + s2 = b->y; + CHECK(rustsecp256k1_v0_9_0_fe_equal(&u1, &u2)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&s1, &s2)); } static void random_fe(rustsecp256k1_v0_9_0_fe *x) { @@ -216,14 +219,14 @@ static void test_exhaustive_ecmult(const rustsecp256k1_v0_9_0_ge *group, const r /* Test rustsecp256k1_v0_9_0_ecmult_const_xonly with all curve X coordinates, and xd=NULL. */ ret = rustsecp256k1_v0_9_0_ecmult_const_xonly(&tmpf, &group[i].x, NULL, &ng, 0); CHECK(ret); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x)); /* Test rustsecp256k1_v0_9_0_ecmult_const_xonly with all curve X coordinates, with random xd. */ random_fe_non_zero(&xd); rustsecp256k1_v0_9_0_fe_mul(&xn, &xd, &group[i].x); ret = rustsecp256k1_v0_9_0_ecmult_const_xonly(&tmpf, &xn, &xd, &ng, 0); CHECK(ret); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x)); } } } @@ -395,6 +398,10 @@ static void test_exhaustive_sign(const rustsecp256k1_v0_9_0_context *ctx, const #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; rustsecp256k1_v0_9_0_gej groupj[EXHAUSTIVE_TEST_ORDER]; @@ -468,8 +475,8 @@ int main(int argc, char** argv) { CHECK(group[i].infinity == 0); CHECK(generated.infinity == 0); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&generated.x, &group[i].x)); - CHECK(rustsecp256k1_v0_9_0_fe_equal_var(&generated.y, &group[i].y)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&generated.x, &group[i].x)); + CHECK(rustsecp256k1_v0_9_0_fe_equal(&generated.y, &group[i].y)); } } @@ -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 rustsecp256k1_v0_9_0_context_destroy(ctx); } diff --git a/secp256k1-sys/depend/secp256k1/src/util.h b/secp256k1-sys/depend/secp256k1/src/util.h index 42280f793..dfedf5f0e 100644 --- a/secp256k1-sys/depend/secp256k1/src/util.h +++ b/secp256k1-sys/depend/secp256k1/src/util.h @@ -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; @@ -337,4 +350,28 @@ SECP256K1_INLINE static void rustsecp256k1_v0_9_0_write_be32(unsigned char* p, u p[0] = x >> 24; } +/* Read a uint64_t in big endian */ +SECP256K1_INLINE static uint64_t rustsecp256k1_v0_9_0_read_be64(const unsigned char* p) { + return (uint64_t)p[0] << 56 | + (uint64_t)p[1] << 48 | + (uint64_t)p[2] << 40 | + (uint64_t)p[3] << 32 | + (uint64_t)p[4] << 24 | + (uint64_t)p[5] << 16 | + (uint64_t)p[6] << 8 | + (uint64_t)p[7]; +} + +/* Write a uint64_t in big endian */ +SECP256K1_INLINE static void rustsecp256k1_v0_9_0_write_be64(unsigned char* p, uint64_t x) { + p[7] = x; + p[6] = x >> 8; + p[5] = x >> 16; + p[4] = x >> 24; + p[3] = x >> 32; + p[2] = x >> 40; + p[1] = x >> 48; + p[0] = x >> 56; +} + #endif /* SECP256K1_UTIL_H */