├── .cirrus.yml ├── .gitattributes ├── .github ├── actions │ ├── install-homebrew-valgrind │ │ └── action.yml │ ├── print-logs │ │ └── action.yml │ └── run-in-docker-action │ │ └── action.yml └── workflows │ └── ci.yml ├── .gitignore ├── CHANGELOG.md ├── CMakeLists.txt ├── CMakePresets.json ├── CONTRIBUTING.md ├── COPYING ├── Makefile.am ├── README.md ├── SECURITY.md ├── autogen.sh ├── build-aux └── m4 │ └── bitcoin_secp.m4 ├── ci ├── ci.sh └── linux-debian.Dockerfile ├── cmake ├── CheckArm32Assembly.cmake ├── CheckMemorySanitizer.cmake ├── CheckStringOptionValue.cmake ├── CheckX86_64Assembly.cmake ├── FindValgrind.cmake ├── GeneratePkgConfigFile.cmake ├── TryAppendCFlags.cmake ├── arm-linux-gnueabihf.toolchain.cmake ├── config.cmake.in ├── source_arm32.s └── x86_64-w64-mingw32.toolchain.cmake ├── configure.ac ├── contrib ├── lax_der_parsing.c ├── lax_der_parsing.h ├── lax_der_privatekey_parsing.c └── lax_der_privatekey_parsing.h ├── doc ├── ellswift.md ├── musig.md ├── release-process.md └── safegcd_implementation.md ├── examples ├── CMakeLists.txt ├── EXAMPLES_COPYING ├── ecdh.c ├── ecdsa.c ├── ellswift.c ├── examples_util.h ├── musig.c └── schnorr.c ├── include ├── secp256k1.h ├── secp256k1_ecdh.h ├── secp256k1_ellswift.h ├── secp256k1_extrakeys.h ├── secp256k1_musig.h ├── secp256k1_preallocated.h ├── secp256k1_recovery.h └── secp256k1_schnorrsig.h ├── libsecp256k1.pc.in ├── sage ├── gen_exhaustive_groups.sage ├── gen_split_lambda_constants.sage ├── group_prover.sage ├── prove_group_implementations.sage ├── secp256k1_params.sage └── weierstrass_prover.sage ├── src ├── CMakeLists.txt ├── asm │ └── field_10x26_arm.s ├── assumptions.h ├── bench.c ├── bench.h ├── bench_ecmult.c ├── bench_internal.c ├── checkmem.h ├── ctime_tests.c ├── ecdsa.h ├── ecdsa_impl.h ├── eckey.h ├── eckey_impl.h ├── ecmult.h ├── ecmult_compute_table.h ├── ecmult_compute_table_impl.h ├── ecmult_const.h ├── ecmult_const_impl.h ├── ecmult_gen.h ├── ecmult_gen_compute_table.h ├── ecmult_gen_compute_table_impl.h ├── ecmult_gen_impl.h ├── ecmult_impl.h ├── field.h ├── field_10x26.h ├── field_10x26_impl.h ├── field_5x52.h ├── field_5x52_impl.h ├── field_5x52_int128_impl.h ├── field_impl.h ├── group.h ├── group_impl.h ├── hash.h ├── hash_impl.h ├── hsort.h ├── hsort_impl.h ├── int128.h ├── int128_impl.h ├── int128_native.h ├── int128_native_impl.h ├── int128_struct.h ├── int128_struct_impl.h ├── modinv32.h ├── modinv32_impl.h ├── modinv64.h ├── modinv64_impl.h ├── modules │ ├── ecdh │ │ ├── Makefile.am.include │ │ ├── bench_impl.h │ │ ├── main_impl.h │ │ └── tests_impl.h │ ├── ellswift │ │ ├── Makefile.am.include │ │ ├── bench_impl.h │ │ ├── main_impl.h │ │ ├── tests_exhaustive_impl.h │ │ └── tests_impl.h │ ├── extrakeys │ │ ├── Makefile.am.include │ │ ├── main_impl.h │ │ ├── tests_exhaustive_impl.h │ │ └── tests_impl.h │ ├── musig │ │ ├── Makefile.am.include │ │ ├── keyagg.h │ │ ├── keyagg_impl.h │ │ ├── main_impl.h │ │ ├── session.h │ │ ├── session_impl.h │ │ ├── tests_impl.h │ │ └── vectors.h │ ├── recovery │ │ ├── Makefile.am.include │ │ ├── bench_impl.h │ │ ├── main_impl.h │ │ ├── tests_exhaustive_impl.h │ │ └── tests_impl.h │ └── schnorrsig │ │ ├── Makefile.am.include │ │ ├── bench_impl.h │ │ ├── main_impl.h │ │ ├── tests_exhaustive_impl.h │ │ └── tests_impl.h ├── precompute_ecmult.c ├── precompute_ecmult_gen.c ├── precomputed_ecmult.c ├── precomputed_ecmult.h ├── precomputed_ecmult_gen.c ├── precomputed_ecmult_gen.h ├── scalar.h ├── scalar_4x64.h ├── scalar_4x64_impl.h ├── scalar_8x32.h ├── scalar_8x32_impl.h ├── scalar_impl.h ├── scalar_low.h ├── scalar_low_impl.h ├── scratch.h ├── scratch_impl.h ├── secp256k1.c ├── selftest.h ├── testrand.h ├── testrand_impl.h ├── tests.c ├── tests_exhaustive.c ├── testutil.h ├── util.h ├── util_local_visibility.h └── wycheproof │ ├── WYCHEPROOF_COPYING │ ├── ecdh_secp256k1_test.h │ ├── ecdh_secp256k1_test.json │ ├── ecdsa_secp256k1_sha256_bitcoin_test.h │ └── ecdsa_secp256k1_sha256_bitcoin_test.json └── tools ├── check-abi.sh ├── symbol-check.py ├── test_vectors_musig2_generate.py ├── tests_wycheproof_generate_ecdh.py ├── tests_wycheproof_generate_ecdsa.py └── wycheproof_utils.py /.cirrus.yml: -------------------------------------------------------------------------------- 1 | env: 2 | ### cirrus config 3 | CIRRUS_CLONE_DEPTH: 1 4 | ### compiler options 5 | HOST: 6 | WRAPPER_CMD: 7 | # Specific warnings can be disabled with -Wno-error=foo. 8 | # -pedantic-errors is not equivalent to -Werror=pedantic and thus not implied by -Werror according to the GCC manual. 9 | WERROR_CFLAGS: -Werror -pedantic-errors 10 | MAKEFLAGS: -j4 11 | BUILD: check 12 | ### secp256k1 config 13 | ECMULTWINDOW: 15 14 | ECMULTGENKB: 22 15 | ASM: no 16 | WIDEMUL: auto 17 | WITH_VALGRIND: yes 18 | EXTRAFLAGS: 19 | ### secp256k1 modules 20 | EXPERIMENTAL: no 21 | ECDH: no 22 | RECOVERY: no 23 | EXTRAKEYS: no 24 | SCHNORRSIG: no 25 | MUSIG: no 26 | ELLSWIFT: no 27 | ### test options 28 | SECP256K1_TEST_ITERS: 64 29 | BENCH: yes 30 | SECP256K1_BENCH_ITERS: 2 31 | CTIMETESTS: yes 32 | SYMBOL_CHECK: yes 33 | VIRTUAL_ENV: /root/venv 34 | # Compile and run the tests 35 | EXAMPLES: yes 36 | 37 | cat_logs_snippet: &CAT_LOGS 38 | always: 39 | cat_tests_log_script: 40 | - cat tests.log || true 41 | cat_noverify_tests_log_script: 42 | - cat noverify_tests.log || true 43 | cat_exhaustive_tests_log_script: 44 | - cat exhaustive_tests.log || true 45 | cat_ctime_tests_log_script: 46 | - cat ctime_tests.log || true 47 | cat_bench_log_script: 48 | - cat bench.log || true 49 | cat_config_log_script: 50 | - cat config.log || true 51 | cat_test_env_script: 52 | - cat test_env.log || true 53 | cat_ci_env_script: 54 | - env 55 | 56 | linux_arm64_container_snippet: &LINUX_ARM64_CONTAINER 57 | env_script: 58 | - export PATH="$VIRTUAL_ENV/bin:$PATH" 59 | - env | tee /tmp/env 60 | build_script: 61 | - DOCKER_BUILDKIT=1 docker build --file "ci/linux-debian.Dockerfile" --tag="ci_secp256k1_arm" 62 | - docker image prune --force # Cleanup stale layers 63 | test_script: 64 | - docker run --rm --mount "type=bind,src=./,dst=/ci_secp256k1" --env-file /tmp/env --replace --name "ci_secp256k1_arm" "ci_secp256k1_arm" bash -c "cd /ci_secp256k1/ && ./ci/ci.sh" 65 | 66 | task: 67 | name: "ARM64: Linux (Debian stable)" 68 | persistent_worker: 69 | labels: 70 | type: arm64 71 | env: 72 | ECDH: yes 73 | RECOVERY: yes 74 | EXTRAKEYS: yes 75 | SCHNORRSIG: yes 76 | MUSIG: yes 77 | ELLSWIFT: yes 78 | matrix: 79 | # Currently only gcc-snapshot, the other compilers are tested on GHA with QEMU 80 | - env: { CC: 'gcc-snapshot' } 81 | << : *LINUX_ARM64_CONTAINER 82 | << : *CAT_LOGS 83 | 84 | task: 85 | name: "ARM64: Linux (Debian stable), Valgrind" 86 | persistent_worker: 87 | labels: 88 | type: arm64 89 | env: 90 | ECDH: yes 91 | RECOVERY: yes 92 | EXTRAKEYS: yes 93 | SCHNORRSIG: yes 94 | MUSIG: yes 95 | ELLSWIFT: yes 96 | WRAPPER_CMD: 'valgrind --error-exitcode=42' 97 | SECP256K1_TEST_ITERS: 2 98 | matrix: 99 | - env: { CC: 'gcc' } 100 | - env: { CC: 'clang' } 101 | - env: { CC: 'gcc-snapshot' } 102 | - env: { CC: 'clang-snapshot' } 103 | << : *LINUX_ARM64_CONTAINER 104 | << : *CAT_LOGS 105 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | src/precomputed_ecmult.c linguist-generated 2 | src/precomputed_ecmult_gen.c linguist-generated 3 | -------------------------------------------------------------------------------- /.github/actions/install-homebrew-valgrind/action.yml: -------------------------------------------------------------------------------- 1 | name: "Install Valgrind" 2 | description: "Install Homebrew's Valgrind package and cache it." 3 | runs: 4 | using: "composite" 5 | steps: 6 | - run: | 7 | brew tap LouisBrunner/valgrind 8 | brew fetch --HEAD LouisBrunner/valgrind/valgrind 9 | echo "CI_HOMEBREW_CELLAR_VALGRIND=$(brew --cellar valgrind)" >> "$GITHUB_ENV" 10 | shell: bash 11 | 12 | - run: | 13 | sw_vers > valgrind_fingerprint 14 | brew --version >> valgrind_fingerprint 15 | git -C "$(brew --cache)/valgrind--git" rev-parse HEAD >> valgrind_fingerprint 16 | cat valgrind_fingerprint 17 | shell: bash 18 | 19 | - uses: actions/cache@v4 20 | id: cache 21 | with: 22 | path: ${{ env.CI_HOMEBREW_CELLAR_VALGRIND }} 23 | key: ${{ github.job }}-valgrind-${{ hashFiles('valgrind_fingerprint') }} 24 | 25 | - if: steps.cache.outputs.cache-hit != 'true' 26 | run: | 27 | brew install --HEAD LouisBrunner/valgrind/valgrind 28 | shell: bash 29 | 30 | - if: steps.cache.outputs.cache-hit == 'true' 31 | run: | 32 | brew link valgrind 33 | shell: bash 34 | -------------------------------------------------------------------------------- /.github/actions/print-logs/action.yml: -------------------------------------------------------------------------------- 1 | name: "Print logs" 2 | description: "Print the log files produced by ci/ci.sh" 3 | runs: 4 | using: "composite" 5 | steps: 6 | - shell: bash 7 | run: | 8 | # Print the log files produced by ci/ci.sh 9 | 10 | # Helper functions 11 | group() { 12 | title=$1 13 | echo "::group::$title" 14 | } 15 | endgroup() { 16 | echo "::endgroup::" 17 | } 18 | cat_file() { 19 | file=$1 20 | group "$file" 21 | cat "$file" 22 | endgroup 23 | } 24 | 25 | # Print all *.log files 26 | shopt -s nullglob 27 | for file in *.log; do 28 | cat_file "$file" 29 | done 30 | 31 | # Print environment 32 | group "CI env" 33 | env 34 | endgroup 35 | -------------------------------------------------------------------------------- /.github/actions/run-in-docker-action/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Run in Docker with environment' 2 | description: 'Run a command in a Docker container, while passing explicitly set environment variables into the container.' 3 | inputs: 4 | dockerfile: 5 | description: 'A Dockerfile that defines an image' 6 | required: true 7 | tag: 8 | description: 'A tag of an image' 9 | required: true 10 | command: 11 | description: 'A command to run in a container' 12 | required: false 13 | default: ./ci/ci.sh 14 | runs: 15 | using: "composite" 16 | steps: 17 | - uses: docker/setup-buildx-action@v3 18 | 19 | - uses: docker/build-push-action@v5 20 | id: main_builder 21 | continue-on-error: true 22 | with: 23 | context: . 24 | file: ${{ inputs.dockerfile }} 25 | tags: ${{ inputs.tag }} 26 | load: true 27 | cache-from: type=gha 28 | 29 | - uses: docker/build-push-action@v5 30 | id: retry_builder 31 | if: steps.main_builder.outcome == 'failure' 32 | with: 33 | context: . 34 | file: ${{ inputs.dockerfile }} 35 | tags: ${{ inputs.tag }} 36 | load: true 37 | cache-from: type=gha 38 | 39 | - # Workaround for https://github.com/google/sanitizers/issues/1614 . 40 | # The underlying issue has been fixed in clang 18.1.3. 41 | run: sudo sysctl -w vm.mmap_rnd_bits=28 42 | shell: bash 43 | 44 | - # Tell Docker to pass environment variables in `env` into the container. 45 | run: > 46 | docker run \ 47 | $(echo '${{ toJSON(env) }}' | jq -r 'keys[] | "--env \(.) "') \ 48 | --volume ${{ github.workspace }}:${{ github.workspace }} \ 49 | --workdir ${{ github.workspace }} \ 50 | ${{ inputs.tag }} bash -c " 51 | git config --global --add safe.directory ${{ github.workspace }} 52 | ${{ inputs.command }} 53 | " 54 | shell: bash 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bench 2 | bench_ecmult 3 | bench_internal 4 | noverify_tests 5 | tests 6 | exhaustive_tests 7 | precompute_ecmult_gen 8 | precompute_ecmult 9 | ctime_tests 10 | ecdh_example 11 | ecdsa_example 12 | schnorr_example 13 | ellswift_example 14 | musig_example 15 | *.exe 16 | *.so 17 | *.a 18 | *.csv 19 | *.log 20 | *.trs 21 | *.sage.py 22 | 23 | Makefile 24 | configure 25 | .libs/ 26 | Makefile.in 27 | aclocal.m4 28 | autom4te.cache/ 29 | config.log 30 | config.status 31 | conftest* 32 | *.tar.gz 33 | *.la 34 | libtool 35 | .deps/ 36 | .dirstamp 37 | *.lo 38 | *.o 39 | *~ 40 | 41 | coverage/ 42 | coverage.html 43 | coverage.*.html 44 | *.gcda 45 | *.gcno 46 | *.gcov 47 | 48 | build-aux/ar-lib 49 | build-aux/config.guess 50 | build-aux/config.sub 51 | build-aux/depcomp 52 | build-aux/install-sh 53 | build-aux/ltmain.sh 54 | build-aux/m4/libtool.m4 55 | build-aux/m4/lt~obsolete.m4 56 | build-aux/m4/ltoptions.m4 57 | build-aux/m4/ltsugar.m4 58 | build-aux/m4/ltversion.m4 59 | build-aux/missing 60 | build-aux/compile 61 | build-aux/test-driver 62 | libsecp256k1.pc 63 | 64 | ### CMake 65 | /CMakeUserPresets.json 66 | # Default CMake build directory. 67 | /build 68 | 69 | ### Python 70 | __pycache__/ 71 | *.py[oc] 72 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "configurePresets": [ 4 | { 5 | "name": "dev-mode", 6 | "displayName": "Development mode (intended only for developers of the library)", 7 | "cacheVariables": { 8 | "SECP256K1_EXPERIMENTAL": "ON", 9 | "SECP256K1_ENABLE_MODULE_RECOVERY": "ON", 10 | "SECP256K1_BUILD_EXAMPLES": "ON" 11 | }, 12 | "warnings": { 13 | "dev": true, 14 | "uninitialized": true 15 | } 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Pieter Wuille 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | To report security issues send an email to secp256k1-security@bitcoincore.org (not for support). 6 | 7 | The following keys may be used to communicate sensitive information to developers: 8 | 9 | | Name | Fingerprint | 10 | |------|-------------| 11 | | Pieter Wuille | 133E AC17 9436 F14A 5CF1 B794 860F EB80 4E66 9320 | 12 | | Jonas Nick | 36C7 1A37 C9D9 88BD E825 08D9 B1A7 0E4F 8DCD 0366 | 13 | | Tim Ruffing | 09E0 3F87 1092 E40E 106E 902B 33BC 86AB 80FF 5516 | 14 | 15 | You can import a key by running the following command with that individual’s fingerprint: `gpg --keyserver hkps://keys.openpgp.org --recv-keys ""` Ensure that you put quotes around fingerprints containing spaces. 16 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | autoreconf -if --warnings=all 4 | -------------------------------------------------------------------------------- /build-aux/m4/bitcoin_secp.m4: -------------------------------------------------------------------------------- 1 | dnl escape "$0x" below using the m4 quadrigaph @S|@, and escape it again with a \ for the shell. 2 | AC_DEFUN([SECP_X86_64_ASM_CHECK],[ 3 | AC_MSG_CHECKING(for x86_64 assembly availability) 4 | AC_LINK_IFELSE([AC_LANG_PROGRAM([[ 5 | #include ]],[[ 6 | uint64_t a = 11, tmp; 7 | __asm__ __volatile__("movq \@S|@0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx"); 8 | ]])], [has_x86_64_asm=yes], [has_x86_64_asm=no]) 9 | AC_MSG_RESULT([$has_x86_64_asm]) 10 | ]) 11 | 12 | AC_DEFUN([SECP_ARM32_ASM_CHECK], [ 13 | AC_MSG_CHECKING(for ARM32 assembly availability) 14 | SECP_ARM32_ASM_CHECK_CFLAGS_saved_CFLAGS="$CFLAGS" 15 | CFLAGS="-x assembler" 16 | AC_LINK_IFELSE([AC_LANG_SOURCE([[ 17 | .syntax unified 18 | .eabi_attribute 24, 1 19 | .eabi_attribute 25, 1 20 | .text 21 | .global main 22 | main: 23 | ldr r0, =0x002A 24 | mov r7, #1 25 | swi 0 26 | ]])], [has_arm32_asm=yes], [has_arm32_asm=no]) 27 | AC_MSG_RESULT([$has_arm32_asm]) 28 | CFLAGS="$SECP_ARM32_ASM_CHECK_CFLAGS_saved_CFLAGS" 29 | ]) 30 | 31 | AC_DEFUN([SECP_VALGRIND_CHECK],[ 32 | AC_MSG_CHECKING([for valgrind support]) 33 | if test x"$has_valgrind" != x"yes"; then 34 | CPPFLAGS_TEMP="$CPPFLAGS" 35 | CPPFLAGS="$VALGRIND_CPPFLAGS $CPPFLAGS" 36 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 37 | #include 38 | ]], [[ 39 | #if defined(NVALGRIND) 40 | # error "Valgrind does not support this platform." 41 | #endif 42 | ]])], [has_valgrind=yes]) 43 | CPPFLAGS="$CPPFLAGS_TEMP" 44 | fi 45 | AC_MSG_RESULT($has_valgrind) 46 | ]) 47 | 48 | AC_DEFUN([SECP_MSAN_CHECK], [ 49 | AC_MSG_CHECKING(whether MemorySanitizer is enabled) 50 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ 51 | #if defined(__has_feature) 52 | # if __has_feature(memory_sanitizer) 53 | /* MemorySanitizer is enabled. */ 54 | # elif 55 | # error "MemorySanitizer is disabled." 56 | # endif 57 | #else 58 | # error "__has_feature is not defined." 59 | #endif 60 | ]])], [msan_enabled=yes], [msan_enabled=no]) 61 | AC_MSG_RESULT([$msan_enabled]) 62 | ]) 63 | 64 | dnl SECP_TRY_APPEND_CFLAGS(flags, VAR) 65 | dnl Append flags to VAR if CC accepts them. 66 | AC_DEFUN([SECP_TRY_APPEND_CFLAGS], [ 67 | AC_MSG_CHECKING([if ${CC} supports $1]) 68 | SECP_TRY_APPEND_CFLAGS_saved_CFLAGS="$CFLAGS" 69 | CFLAGS="$1 $CFLAGS" 70 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], [flag_works=yes], [flag_works=no]) 71 | AC_MSG_RESULT($flag_works) 72 | CFLAGS="$SECP_TRY_APPEND_CFLAGS_saved_CFLAGS" 73 | if test x"$flag_works" = x"yes"; then 74 | $2="$$2 $1" 75 | fi 76 | unset flag_works 77 | AC_SUBST($2) 78 | ]) 79 | 80 | dnl SECP_SET_DEFAULT(VAR, default, default-dev-mode) 81 | dnl Set VAR to default or default-dev-mode, depending on whether dev mode is enabled 82 | AC_DEFUN([SECP_SET_DEFAULT], [ 83 | if test "${enable_dev_mode+set}" != set; then 84 | AC_MSG_ERROR([[Set enable_dev_mode before calling SECP_SET_DEFAULT]]) 85 | fi 86 | if test x"$enable_dev_mode" = x"yes"; then 87 | $1="$3" 88 | else 89 | $1="$2" 90 | fi 91 | ]) 92 | -------------------------------------------------------------------------------- /ci/ci.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eux 4 | 5 | export LC_ALL=C 6 | 7 | # Print commit and relevant CI environment to allow reproducing the job outside of CI. 8 | git show --no-patch 9 | print_environment() { 10 | # Turn off -x because it messes up the output 11 | set +x 12 | # There are many ways to print variable names and their content. This one 13 | # does not rely on bash. 14 | for var in WERROR_CFLAGS MAKEFLAGS BUILD \ 15 | ECMULTWINDOW ECMULTGENKB ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \ 16 | EXPERIMENTAL ECDH RECOVERY EXTRAKEYS MUSIG SCHNORRSIG ELLSWIFT \ 17 | SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETESTS SYMBOL_CHECK \ 18 | EXAMPLES \ 19 | HOST WRAPPER_CMD \ 20 | CC CFLAGS CPPFLAGS AR NM \ 21 | UBSAN_OPTIONS ASAN_OPTIONS LSAN_OPTIONS 22 | do 23 | eval "isset=\${$var+x}" 24 | if [ -n "$isset" ]; then 25 | eval "val=\${$var}" 26 | # shellcheck disable=SC2154 27 | printf '%s="%s" ' "$var" "$val" 28 | fi 29 | done 30 | echo "$0" 31 | set -x 32 | } 33 | print_environment 34 | 35 | env >> test_env.log 36 | 37 | # If gcc is requested, assert that it's in fact gcc (and not some symlinked Apple clang). 38 | case "${CC:-undefined}" in 39 | *gcc*) 40 | $CC -v 2>&1 | grep -q "gcc version" || exit 1; 41 | ;; 42 | esac 43 | 44 | if [ -n "${CC+x}" ]; then 45 | # The MSVC compiler "cl" doesn't understand "-v" 46 | $CC -v || true 47 | fi 48 | if [ "$WITH_VALGRIND" = "yes" ]; then 49 | valgrind --version 50 | fi 51 | if [ -n "$WRAPPER_CMD" ]; then 52 | $WRAPPER_CMD --version 53 | fi 54 | 55 | # Workaround for https://bugs.kde.org/show_bug.cgi?id=452758 (fixed in valgrind 3.20.0). 56 | case "${CC:-undefined}" in 57 | clang*) 58 | if [ "$CTIMETESTS" = "yes" ] && [ "$WITH_VALGRIND" = "yes" ] 59 | then 60 | export CFLAGS="${CFLAGS:+$CFLAGS }-gdwarf-4" 61 | else 62 | case "$WRAPPER_CMD" in 63 | valgrind*) 64 | export CFLAGS="${CFLAGS:+$CFLAGS }-gdwarf-4" 65 | ;; 66 | esac 67 | fi 68 | ;; 69 | esac 70 | 71 | ./autogen.sh 72 | 73 | ./configure \ 74 | --enable-experimental="$EXPERIMENTAL" \ 75 | --with-test-override-wide-multiply="$WIDEMUL" --with-asm="$ASM" \ 76 | --with-ecmult-window="$ECMULTWINDOW" \ 77 | --with-ecmult-gen-kb="$ECMULTGENKB" \ 78 | --enable-module-ecdh="$ECDH" --enable-module-recovery="$RECOVERY" \ 79 | --enable-module-ellswift="$ELLSWIFT" \ 80 | --enable-module-extrakeys="$EXTRAKEYS" \ 81 | --enable-module-schnorrsig="$SCHNORRSIG" \ 82 | --enable-module-musig="$MUSIG" \ 83 | --enable-examples="$EXAMPLES" \ 84 | --enable-ctime-tests="$CTIMETESTS" \ 85 | --with-valgrind="$WITH_VALGRIND" \ 86 | --host="$HOST" $EXTRAFLAGS 87 | 88 | # We have set "-j" in MAKEFLAGS. 89 | build_exit_code=0 90 | make > make.log 2>&1 || build_exit_code=$? 91 | cat make.log 92 | if [ $build_exit_code -ne 0 ]; then 93 | case "${CC:-undefined}" in 94 | *snapshot*) 95 | # Ignore internal compiler errors in gcc-snapshot and clang-snapshot 96 | grep -e "internal compiler error:" -e "PLEASE submit a bug report" make.log 97 | exit $? 98 | ;; 99 | *) 100 | exit 1 101 | ;; 102 | esac 103 | fi 104 | 105 | # Print information about binaries so that we can see that the architecture is correct 106 | file *tests* || true 107 | file bench* || true 108 | file .libs/* || true 109 | 110 | if [ "$SYMBOL_CHECK" = "yes" ] 111 | then 112 | python3 --version 113 | case "$HOST" in 114 | *mingw*) 115 | ls -l .libs 116 | python3 ./tools/symbol-check.py .libs/libsecp256k1-5.dll 117 | ;; 118 | *) 119 | python3 ./tools/symbol-check.py .libs/libsecp256k1.so 120 | ;; 121 | esac 122 | fi 123 | 124 | # This tells `make check` to wrap test invocations. 125 | export LOG_COMPILER="$WRAPPER_CMD" 126 | 127 | make "$BUILD" 128 | 129 | # Using the local `libtool` because on macOS the system's libtool has nothing to do with GNU libtool 130 | EXEC='./libtool --mode=execute' 131 | if [ -n "$WRAPPER_CMD" ] 132 | then 133 | EXEC="$EXEC $WRAPPER_CMD" 134 | fi 135 | 136 | if [ "$BENCH" = "yes" ] 137 | then 138 | { 139 | $EXEC ./bench_ecmult 140 | $EXEC ./bench_internal 141 | $EXEC ./bench 142 | } >> bench.log 2>&1 143 | fi 144 | 145 | if [ "$CTIMETESTS" = "yes" ] 146 | then 147 | if [ "$WITH_VALGRIND" = "yes" ]; then 148 | ./libtool --mode=execute valgrind --error-exitcode=42 ./ctime_tests > ctime_tests.log 2>&1 149 | else 150 | $EXEC ./ctime_tests > ctime_tests.log 2>&1 151 | fi 152 | fi 153 | 154 | # Rebuild precomputed files (if not cross-compiling). 155 | if [ -z "$HOST" ] 156 | then 157 | make clean-precomp clean-testvectors 158 | make precomp testvectors 159 | fi 160 | 161 | # Check that no repo files have been modified by the build. 162 | # (This fails for example if the precomp files need to be updated in the repo.) 163 | git diff --exit-code 164 | -------------------------------------------------------------------------------- /ci/linux-debian.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:stable-slim 2 | 3 | SHELL ["/bin/bash", "-c"] 4 | 5 | WORKDIR /root 6 | 7 | # A too high maximum number of file descriptors (with the default value 8 | # inherited from the docker host) can cause issues with some of our tools: 9 | # - sanitizers hanging: https://github.com/google/sanitizers/issues/1662 10 | # - valgrind crashing: https://stackoverflow.com/a/75293014 11 | # This is not be a problem on our CI hosts, but developers who run the image 12 | # on their machines may run into this (e.g., on Arch Linux), so warn them. 13 | # (Note that .bashrc is only executed in interactive bash shells.) 14 | 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 15 | 16 | RUN dpkg --add-architecture i386 && \ 17 | dpkg --add-architecture s390x && \ 18 | dpkg --add-architecture armhf && \ 19 | dpkg --add-architecture arm64 && \ 20 | dpkg --add-architecture ppc64el 21 | 22 | # dkpg-dev: to make pkg-config work in cross-builds 23 | # llvm: for llvm-symbolizer, which is used by clang's UBSan for symbolized stack traces 24 | RUN apt-get update && apt-get install --no-install-recommends -y \ 25 | git ca-certificates \ 26 | make automake libtool pkg-config dpkg-dev valgrind qemu-user \ 27 | gcc clang llvm libclang-rt-dev libc6-dbg \ 28 | g++ \ 29 | gcc-i686-linux-gnu libc6-dev-i386-cross libc6-dbg:i386 libubsan1:i386 libasan8:i386 \ 30 | gcc-s390x-linux-gnu libc6-dev-s390x-cross libc6-dbg:s390x \ 31 | gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libc6-dbg:armhf \ 32 | gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross libc6-dbg:ppc64el \ 33 | gcc-mingw-w64-x86-64-win32 wine64 wine \ 34 | gcc-mingw-w64-i686-win32 wine32 \ 35 | python3-full && \ 36 | if ! ( dpkg --print-architecture | grep --quiet "arm64" ) ; then \ 37 | apt-get install --no-install-recommends -y \ 38 | gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6-dbg:arm64 ;\ 39 | fi && \ 40 | apt-get clean && rm -rf /var/lib/apt/lists/* 41 | 42 | # Build and install gcc snapshot 43 | ARG GCC_SNAPSHOT_MAJOR=15 44 | RUN apt-get update && apt-get install --no-install-recommends -y wget libgmp-dev libmpfr-dev libmpc-dev flex && \ 45 | mkdir gcc && cd gcc && \ 46 | 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}" && \ 47 | wget "https://gcc.gnu.org/pub/gcc/snapshots/LATEST-${GCC_SNAPSHOT_MAJOR}/sha512.sum" && \ 48 | sha512sum --check --ignore-missing sha512.sum && \ 49 | # We should have downloaded exactly one tar.xz file 50 | ls && \ 51 | [ $(ls *.tar.xz | wc -l) -eq "1" ] && \ 52 | tar xf *.tar.xz && \ 53 | mkdir gcc-build && cd gcc-build && \ 54 | ../*/configure --prefix=/opt/gcc-snapshot --enable-languages=c --disable-bootstrap --disable-multilib --without-isl && \ 55 | make -j $(nproc) && \ 56 | make install && \ 57 | cd ../.. && rm -rf gcc && \ 58 | ln -s /opt/gcc-snapshot/bin/gcc /usr/bin/gcc-snapshot && \ 59 | apt-get autoremove -y wget libgmp-dev libmpfr-dev libmpc-dev flex && \ 60 | apt-get clean && rm -rf /var/lib/apt/lists/* 61 | 62 | # Install clang snapshot, see https://apt.llvm.org/ 63 | RUN \ 64 | # Setup GPG keys of LLVM repository 65 | apt-get update && apt-get install --no-install-recommends -y wget && \ 66 | wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc && \ 67 | # Add repository for this Debian release 68 | . /etc/os-release && echo "deb http://apt.llvm.org/${VERSION_CODENAME} llvm-toolchain-${VERSION_CODENAME} main" >> /etc/apt/sources.list && \ 69 | apt-get update && \ 70 | # Determine the version number of the LLVM development branch 71 | LLVM_VERSION=$(apt-cache search --names-only '^clang-[0-9]+$' | sort -V | tail -1 | cut -f1 -d" " | cut -f2 -d"-" ) && \ 72 | # Install 73 | apt-get install --no-install-recommends -y "clang-${LLVM_VERSION}" && \ 74 | # Create symlink 75 | ln -s "/usr/bin/clang-${LLVM_VERSION}" /usr/bin/clang-snapshot && \ 76 | # Clean up 77 | apt-get autoremove -y wget && \ 78 | apt-get clean && rm -rf /var/lib/apt/lists/* 79 | 80 | ENV VIRTUAL_ENV=/root/venv 81 | RUN python3 -m venv $VIRTUAL_ENV 82 | ENV PATH="$VIRTUAL_ENV/bin:$PATH" 83 | RUN pip install lief 84 | -------------------------------------------------------------------------------- /cmake/CheckArm32Assembly.cmake: -------------------------------------------------------------------------------- 1 | function(check_arm32_assembly) 2 | try_compile(HAVE_ARM32_ASM 3 | ${PROJECT_BINARY_DIR}/check_arm32_assembly 4 | SOURCES ${PROJECT_SOURCE_DIR}/cmake/source_arm32.s 5 | ) 6 | endfunction() 7 | -------------------------------------------------------------------------------- /cmake/CheckMemorySanitizer.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | include(CheckCSourceCompiles) 3 | 4 | function(check_memory_sanitizer output) 5 | set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) 6 | check_c_source_compiles(" 7 | #if defined(__has_feature) 8 | # if __has_feature(memory_sanitizer) 9 | /* MemorySanitizer is enabled. */ 10 | # elif 11 | # error \"MemorySanitizer is disabled.\" 12 | # endif 13 | #else 14 | # error \"__has_feature is not defined.\" 15 | #endif 16 | " HAVE_MSAN) 17 | set(${output} ${HAVE_MSAN} PARENT_SCOPE) 18 | endfunction() 19 | -------------------------------------------------------------------------------- /cmake/CheckStringOptionValue.cmake: -------------------------------------------------------------------------------- 1 | function(check_string_option_value option) 2 | get_property(expected_values CACHE ${option} PROPERTY STRINGS) 3 | if(expected_values) 4 | if(${option} IN_LIST expected_values) 5 | return() 6 | endif() 7 | message(FATAL_ERROR "${option} value is \"${${option}}\", but must be one of ${expected_values}.") 8 | endif() 9 | message(AUTHOR_WARNING "The STRINGS property must be set before invoking `check_string_option_value' function.") 10 | endfunction() 11 | -------------------------------------------------------------------------------- /cmake/CheckX86_64Assembly.cmake: -------------------------------------------------------------------------------- 1 | include(CheckCSourceCompiles) 2 | 3 | function(check_x86_64_assembly) 4 | check_c_source_compiles(" 5 | #include 6 | 7 | int main() 8 | { 9 | uint64_t a = 11, tmp; 10 | __asm__ __volatile__(\"movq $0x100000000,%1; mulq %%rsi\" : \"+a\"(a) : \"S\"(tmp) : \"cc\", \"%rdx\"); 11 | } 12 | " HAVE_X86_64_ASM) 13 | set(HAVE_X86_64_ASM ${HAVE_X86_64_ASM} PARENT_SCOPE) 14 | endfunction() 15 | -------------------------------------------------------------------------------- /cmake/FindValgrind.cmake: -------------------------------------------------------------------------------- 1 | if(CMAKE_HOST_APPLE) 2 | find_program(BREW_COMMAND brew) 3 | execute_process( 4 | COMMAND ${BREW_COMMAND} --prefix valgrind 5 | OUTPUT_VARIABLE valgrind_brew_prefix 6 | ERROR_QUIET 7 | OUTPUT_STRIP_TRAILING_WHITESPACE 8 | ) 9 | endif() 10 | 11 | set(hints_paths) 12 | if(valgrind_brew_prefix) 13 | set(hints_paths ${valgrind_brew_prefix}/include) 14 | endif() 15 | 16 | find_path(Valgrind_INCLUDE_DIR 17 | NAMES valgrind/memcheck.h 18 | HINTS ${hints_paths} 19 | ) 20 | 21 | if(Valgrind_INCLUDE_DIR) 22 | include(CheckCSourceCompiles) 23 | set(CMAKE_REQUIRED_INCLUDES ${Valgrind_INCLUDE_DIR}) 24 | check_c_source_compiles(" 25 | #include 26 | #if defined(NVALGRIND) 27 | # error \"Valgrind does not support this platform.\" 28 | #endif 29 | 30 | int main() {} 31 | " Valgrind_WORKS) 32 | endif() 33 | 34 | include(FindPackageHandleStandardArgs) 35 | find_package_handle_standard_args(Valgrind 36 | REQUIRED_VARS Valgrind_INCLUDE_DIR Valgrind_WORKS 37 | ) 38 | 39 | mark_as_advanced( 40 | Valgrind_INCLUDE_DIR 41 | ) 42 | -------------------------------------------------------------------------------- /cmake/GeneratePkgConfigFile.cmake: -------------------------------------------------------------------------------- 1 | function(generate_pkg_config_file in_file) 2 | set(prefix ${CMAKE_INSTALL_PREFIX}) 3 | set(exec_prefix \${prefix}) 4 | set(libdir \${exec_prefix}/${CMAKE_INSTALL_LIBDIR}) 5 | set(includedir \${prefix}/${CMAKE_INSTALL_INCLUDEDIR}) 6 | set(PACKAGE_VERSION ${PROJECT_VERSION}) 7 | configure_file(${in_file} ${PROJECT_NAME}.pc @ONLY) 8 | endfunction() 9 | -------------------------------------------------------------------------------- /cmake/TryAppendCFlags.cmake: -------------------------------------------------------------------------------- 1 | include(CheckCCompilerFlag) 2 | 3 | function(secp256k1_check_c_flags_internal flags output) 4 | string(MAKE_C_IDENTIFIER "${flags}" result) 5 | string(TOUPPER "${result}" result) 6 | set(result "C_SUPPORTS_${result}") 7 | if(NOT MSVC) 8 | set(CMAKE_REQUIRED_FLAGS "-Werror") 9 | endif() 10 | 11 | # This avoids running a linker. 12 | set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) 13 | check_c_compiler_flag("${flags}" ${result}) 14 | 15 | set(${output} ${${result}} PARENT_SCOPE) 16 | endfunction() 17 | 18 | # Append flags to the COMPILE_OPTIONS directory property if CC accepts them. 19 | macro(try_append_c_flags) 20 | secp256k1_check_c_flags_internal("${ARGV}" result) 21 | if(result) 22 | add_compile_options(${ARGV}) 23 | endif() 24 | endmacro() 25 | -------------------------------------------------------------------------------- /cmake/arm-linux-gnueabihf.toolchain.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_SYSTEM_NAME Linux) 2 | set(CMAKE_SYSTEM_PROCESSOR arm) 3 | set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc) 4 | -------------------------------------------------------------------------------- /cmake/config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake") 4 | 5 | check_required_components(@PROJECT_NAME@) 6 | -------------------------------------------------------------------------------- /cmake/source_arm32.s: -------------------------------------------------------------------------------- 1 | .syntax unified 2 | .eabi_attribute 24, 1 3 | .eabi_attribute 25, 1 4 | .text 5 | .global main 6 | main: 7 | ldr r0, =0x002A 8 | mov r7, #1 9 | swi 0 10 | -------------------------------------------------------------------------------- /cmake/x86_64-w64-mingw32.toolchain.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_SYSTEM_NAME Windows) 2 | set(CMAKE_SYSTEM_PROCESSOR x86_64) 3 | set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) 4 | -------------------------------------------------------------------------------- /contrib/lax_der_parsing.c: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2015 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #include 8 | 9 | #include "lax_der_parsing.h" 10 | 11 | int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { 12 | size_t rpos, rlen, spos, slen; 13 | size_t pos = 0; 14 | size_t lenbyte; 15 | unsigned char tmpsig[64] = {0}; 16 | int overflow = 0; 17 | 18 | /* Hack to initialize sig with a correctly-parsed but invalid signature. */ 19 | secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); 20 | 21 | /* Sequence tag byte */ 22 | if (pos == inputlen || input[pos] != 0x30) { 23 | return 0; 24 | } 25 | pos++; 26 | 27 | /* Sequence length bytes */ 28 | if (pos == inputlen) { 29 | return 0; 30 | } 31 | lenbyte = input[pos++]; 32 | if (lenbyte & 0x80) { 33 | lenbyte -= 0x80; 34 | if (lenbyte > inputlen - pos) { 35 | return 0; 36 | } 37 | pos += lenbyte; 38 | } 39 | 40 | /* Integer tag byte for R */ 41 | if (pos == inputlen || input[pos] != 0x02) { 42 | return 0; 43 | } 44 | pos++; 45 | 46 | /* Integer length for R */ 47 | if (pos == inputlen) { 48 | return 0; 49 | } 50 | lenbyte = input[pos++]; 51 | if (lenbyte & 0x80) { 52 | lenbyte -= 0x80; 53 | if (lenbyte > inputlen - pos) { 54 | return 0; 55 | } 56 | while (lenbyte > 0 && input[pos] == 0) { 57 | pos++; 58 | lenbyte--; 59 | } 60 | if (lenbyte >= sizeof(size_t)) { 61 | return 0; 62 | } 63 | rlen = 0; 64 | while (lenbyte > 0) { 65 | rlen = (rlen << 8) + input[pos]; 66 | pos++; 67 | lenbyte--; 68 | } 69 | } else { 70 | rlen = lenbyte; 71 | } 72 | if (rlen > inputlen - pos) { 73 | return 0; 74 | } 75 | rpos = pos; 76 | pos += rlen; 77 | 78 | /* Integer tag byte for S */ 79 | if (pos == inputlen || input[pos] != 0x02) { 80 | return 0; 81 | } 82 | pos++; 83 | 84 | /* Integer length for S */ 85 | if (pos == inputlen) { 86 | return 0; 87 | } 88 | lenbyte = input[pos++]; 89 | if (lenbyte & 0x80) { 90 | lenbyte -= 0x80; 91 | if (lenbyte > inputlen - pos) { 92 | return 0; 93 | } 94 | while (lenbyte > 0 && input[pos] == 0) { 95 | pos++; 96 | lenbyte--; 97 | } 98 | if (lenbyte >= sizeof(size_t)) { 99 | return 0; 100 | } 101 | slen = 0; 102 | while (lenbyte > 0) { 103 | slen = (slen << 8) + input[pos]; 104 | pos++; 105 | lenbyte--; 106 | } 107 | } else { 108 | slen = lenbyte; 109 | } 110 | if (slen > inputlen - pos) { 111 | return 0; 112 | } 113 | spos = pos; 114 | 115 | /* Ignore leading zeroes in R */ 116 | while (rlen > 0 && input[rpos] == 0) { 117 | rlen--; 118 | rpos++; 119 | } 120 | /* Copy R value */ 121 | if (rlen > 32) { 122 | overflow = 1; 123 | } else if (rlen) { 124 | memcpy(tmpsig + 32 - rlen, input + rpos, rlen); 125 | } 126 | 127 | /* Ignore leading zeroes in S */ 128 | while (slen > 0 && input[spos] == 0) { 129 | slen--; 130 | spos++; 131 | } 132 | /* Copy S value */ 133 | if (slen > 32) { 134 | overflow = 1; 135 | } else if (slen) { 136 | memcpy(tmpsig + 64 - slen, input + spos, slen); 137 | } 138 | 139 | if (!overflow) { 140 | overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); 141 | } 142 | if (overflow) { 143 | memset(tmpsig, 0, 64); 144 | secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); 145 | } 146 | return 1; 147 | } 148 | 149 | -------------------------------------------------------------------------------- /contrib/lax_der_parsing.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2015 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | /**** 8 | * Please do not link this file directly. It is not part of the libsecp256k1 9 | * project and does not promise any stability in its API, functionality or 10 | * presence. Projects which use this code should instead copy this header 11 | * and its accompanying .c file directly into their codebase. 12 | ****/ 13 | 14 | /* This file defines a function that parses DER with various errors and 15 | * violations. This is not a part of the library itself, because the allowed 16 | * violations are chosen arbitrarily and do not follow or establish any 17 | * standard. 18 | * 19 | * In many places it matters that different implementations do not only accept 20 | * the same set of valid signatures, but also reject the same set of signatures. 21 | * The only means to accomplish that is by strictly obeying a standard, and not 22 | * accepting anything else. 23 | * 24 | * Nonetheless, sometimes there is a need for compatibility with systems that 25 | * use signatures which do not strictly obey DER. The snippet below shows how 26 | * certain violations are easily supported. You may need to adapt it. 27 | * 28 | * Do not use this for new systems. Use well-defined DER or compact signatures 29 | * instead if you have the choice (see secp256k1_ecdsa_signature_parse_der and 30 | * secp256k1_ecdsa_signature_parse_compact). 31 | * 32 | * The supported violations are: 33 | * - All numbers are parsed as nonnegative integers, even though X.609-0207 34 | * section 8.3.3 specifies that integers are always encoded as two's 35 | * complement. 36 | * - Integers can have length 0, even though section 8.3.1 says they can't. 37 | * - Integers with overly long padding are accepted, violation section 38 | * 8.3.2. 39 | * - 127-byte long length descriptors are accepted, even though section 40 | * 8.1.3.5.c says that they are not. 41 | * - Trailing garbage data inside or after the signature is ignored. 42 | * - The length descriptor of the sequence is ignored. 43 | * 44 | * Compared to for example OpenSSL, many violations are NOT supported: 45 | * - Using overly long tag descriptors for the sequence or integers inside, 46 | * violating section 8.1.2.2. 47 | * - Encoding primitive integers as constructed values, violating section 48 | * 8.3.1. 49 | */ 50 | 51 | #ifndef SECP256K1_CONTRIB_LAX_DER_PARSING_H 52 | #define SECP256K1_CONTRIB_LAX_DER_PARSING_H 53 | 54 | /* #include secp256k1.h only when it hasn't been included yet. 55 | This enables this file to be #included directly in other project 56 | files (such as tests.c) without the need to set an explicit -I flag, 57 | which would be necessary to locate secp256k1.h. */ 58 | #ifndef SECP256K1_H 59 | #include 60 | #endif 61 | 62 | #ifdef __cplusplus 63 | extern "C" { 64 | #endif 65 | 66 | /** Parse a signature in "lax DER" format 67 | * 68 | * Returns: 1 when the signature could be parsed, 0 otherwise. 69 | * Args: ctx: a secp256k1 context object 70 | * Out: sig: pointer to a signature object 71 | * In: input: pointer to the signature to be parsed 72 | * inputlen: the length of the array pointed to be input 73 | * 74 | * This function will accept any valid DER encoded signature, even if the 75 | * encoded numbers are out of range. In addition, it will accept signatures 76 | * which violate the DER spec in various ways. Its purpose is to allow 77 | * validation of the Bitcoin blockchain, which includes non-DER signatures 78 | * from before the network rules were updated to enforce DER. Note that 79 | * the set of supported violations is a strict subset of what OpenSSL will 80 | * accept. 81 | * 82 | * After the call, sig will always be initialized. If parsing failed or the 83 | * encoded numbers are out of range, signature validation with it is 84 | * guaranteed to fail for every message and public key. 85 | */ 86 | int ecdsa_signature_parse_der_lax( 87 | const secp256k1_context* ctx, 88 | secp256k1_ecdsa_signature* sig, 89 | const unsigned char *input, 90 | size_t inputlen 91 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); 92 | 93 | #ifdef __cplusplus 94 | } 95 | #endif 96 | 97 | #endif /* SECP256K1_CONTRIB_LAX_DER_PARSING_H */ 98 | -------------------------------------------------------------------------------- /contrib/lax_der_privatekey_parsing.c: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2014, 2015 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #include 8 | 9 | #include "lax_der_privatekey_parsing.h" 10 | 11 | int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *out32, const unsigned char *privkey, size_t privkeylen) { 12 | const unsigned char *end = privkey + privkeylen; 13 | int lenb = 0; 14 | int len = 0; 15 | memset(out32, 0, 32); 16 | /* sequence header */ 17 | if (end < privkey+1 || *privkey != 0x30) { 18 | return 0; 19 | } 20 | privkey++; 21 | /* sequence length constructor */ 22 | if (end < privkey+1 || !(*privkey & 0x80)) { 23 | return 0; 24 | } 25 | lenb = *privkey & ~0x80; privkey++; 26 | if (lenb < 1 || lenb > 2) { 27 | return 0; 28 | } 29 | if (end < privkey+lenb) { 30 | return 0; 31 | } 32 | /* sequence length */ 33 | len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0); 34 | privkey += lenb; 35 | if (end < privkey+len) { 36 | return 0; 37 | } 38 | /* sequence element 0: version number (=1) */ 39 | if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) { 40 | return 0; 41 | } 42 | privkey += 3; 43 | /* sequence element 1: octet string, up to 32 bytes */ 44 | if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) { 45 | return 0; 46 | } 47 | if (privkey[1]) memcpy(out32 + 32 - privkey[1], privkey + 2, privkey[1]); 48 | if (!secp256k1_ec_seckey_verify(ctx, out32)) { 49 | memset(out32, 0, 32); 50 | return 0; 51 | } 52 | return 1; 53 | } 54 | 55 | int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, int compressed) { 56 | secp256k1_pubkey pubkey; 57 | size_t pubkeylen = 0; 58 | if (!secp256k1_ec_pubkey_create(ctx, &pubkey, key32)) { 59 | *privkeylen = 0; 60 | return 0; 61 | } 62 | if (compressed) { 63 | static const unsigned char begin[] = { 64 | 0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20 65 | }; 66 | static const unsigned char middle[] = { 67 | 0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, 68 | 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 69 | 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 70 | 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, 71 | 0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, 72 | 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, 73 | 0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 74 | 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, 75 | 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00 76 | }; 77 | unsigned char *ptr = privkey; 78 | memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); 79 | memcpy(ptr, key32, 32); ptr += 32; 80 | memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); 81 | pubkeylen = 33; 82 | secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED); 83 | ptr += pubkeylen; 84 | *privkeylen = ptr - privkey; 85 | } else { 86 | static const unsigned char begin[] = { 87 | 0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 88 | }; 89 | static const unsigned char middle[] = { 90 | 0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, 91 | 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 92 | 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 93 | 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, 94 | 0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, 95 | 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, 96 | 0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11, 97 | 0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10, 98 | 0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 99 | 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, 100 | 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00 101 | }; 102 | unsigned char *ptr = privkey; 103 | memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); 104 | memcpy(ptr, key32, 32); ptr += 32; 105 | memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); 106 | pubkeylen = 65; 107 | secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_UNCOMPRESSED); 108 | ptr += pubkeylen; 109 | *privkeylen = ptr - privkey; 110 | } 111 | return 1; 112 | } 113 | -------------------------------------------------------------------------------- /contrib/lax_der_privatekey_parsing.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2014, 2015 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | /**** 8 | * Please do not link this file directly. It is not part of the libsecp256k1 9 | * project and does not promise any stability in its API, functionality or 10 | * presence. Projects which use this code should instead copy this header 11 | * and its accompanying .c file directly into their codebase. 12 | ****/ 13 | 14 | /* This file contains code snippets that parse DER private keys with 15 | * various errors and violations. This is not a part of the library 16 | * itself, because the allowed violations are chosen arbitrarily and 17 | * do not follow or establish any standard. 18 | * 19 | * It also contains code to serialize private keys in a compatible 20 | * manner. 21 | * 22 | * These functions are meant for compatibility with applications 23 | * that require BER encoded keys. When working with secp256k1-specific 24 | * code, the simple 32-byte private keys normally used by the 25 | * library are sufficient. 26 | */ 27 | 28 | #ifndef SECP256K1_CONTRIB_BER_PRIVATEKEY_H 29 | #define SECP256K1_CONTRIB_BER_PRIVATEKEY_H 30 | 31 | /* #include secp256k1.h only when it hasn't been included yet. 32 | This enables this file to be #included directly in other project 33 | files (such as tests.c) without the need to set an explicit -I flag, 34 | which would be necessary to locate secp256k1.h. */ 35 | #ifndef SECP256K1_H 36 | #include 37 | #endif 38 | 39 | #ifdef __cplusplus 40 | extern "C" { 41 | #endif 42 | 43 | /** Export a private key in DER format. 44 | * 45 | * Returns: 1 if the private key was valid. 46 | * Args: ctx: pointer to a context object (not secp256k1_context_static). 47 | * Out: privkey: pointer to an array for storing the private key in BER. 48 | * Should have space for 279 bytes, and cannot be NULL. 49 | * privkeylen: Pointer to an int where the length of the private key in 50 | * privkey will be stored. 51 | * In: seckey: pointer to a 32-byte secret key to export. 52 | * compressed: 1 if the key should be exported in 53 | * compressed format, 0 otherwise 54 | * 55 | * This function is purely meant for compatibility with applications that 56 | * require BER encoded keys. When working with secp256k1-specific code, the 57 | * simple 32-byte private keys are sufficient. 58 | * 59 | * Note that this function does not guarantee correct DER output. It is 60 | * guaranteed to be parsable by secp256k1_ec_privkey_import_der 61 | */ 62 | SECP256K1_WARN_UNUSED_RESULT int ec_privkey_export_der( 63 | const secp256k1_context* ctx, 64 | unsigned char *privkey, 65 | size_t *privkeylen, 66 | const unsigned char *seckey, 67 | int compressed 68 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); 69 | 70 | /** Import a private key in DER format. 71 | * Returns: 1 if a private key was extracted. 72 | * Args: ctx: pointer to a context object (cannot be NULL). 73 | * Out: seckey: pointer to a 32-byte array for storing the private key. 74 | * (cannot be NULL). 75 | * In: privkey: pointer to a private key in DER format (cannot be NULL). 76 | * privkeylen: length of the DER private key pointed to be privkey. 77 | * 78 | * This function will accept more than just strict DER, and even allow some BER 79 | * violations. The public key stored inside the DER-encoded private key is not 80 | * verified for correctness, nor are the curve parameters. Use this function 81 | * only if you know in advance it is supposed to contain a secp256k1 private 82 | * key. 83 | */ 84 | SECP256K1_WARN_UNUSED_RESULT int ec_privkey_import_der( 85 | const secp256k1_context* ctx, 86 | unsigned char *seckey, 87 | const unsigned char *privkey, 88 | size_t privkeylen 89 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); 90 | 91 | #ifdef __cplusplus 92 | } 93 | #endif 94 | 95 | #endif /* SECP256K1_CONTRIB_BER_PRIVATEKEY_H */ 96 | -------------------------------------------------------------------------------- /doc/musig.md: -------------------------------------------------------------------------------- 1 | Notes on the musig module API 2 | =========================== 3 | 4 | The following sections contain additional notes on the API of the musig module (`include/secp256k1_musig.h`). 5 | A usage example can be found in `examples/musig.c`. 6 | 7 | ## API misuse 8 | 9 | The musig API is designed with a focus on misuse resistance. 10 | However, due to the interactive nature of the MuSig protocol, there are additional failure modes that are not present in regular (single-party) Schnorr signature creation. 11 | While the results can be catastrophic (e.g. leaking of the secret key), it is unfortunately not possible for the musig implementation to prevent all such failure modes. 12 | 13 | Therefore, users of the musig module must take great care to make sure of the following: 14 | 15 | 1. A unique nonce per signing session is generated in `secp256k1_musig_nonce_gen`. 16 | See the corresponding comment in `include/secp256k1_musig.h` for how to ensure that. 17 | 2. The `secp256k1_musig_secnonce` structure is never copied or serialized. 18 | See also the comment on `secp256k1_musig_secnonce` in `include/secp256k1_musig.h`. 19 | 3. Opaque data structures are never written to or read from directly. 20 | Instead, only the provided accessor functions are used. 21 | 22 | ## Key Aggregation and (Taproot) Tweaking 23 | 24 | Given a set of public keys, the aggregate public key is computed with `secp256k1_musig_pubkey_agg`. 25 | A plain tweak can be added to the resulting public key with `secp256k1_ec_pubkey_tweak_add` by setting the `tweak32` argument to the hash defined in BIP 32. Similarly, a Taproot tweak can be added with `secp256k1_xonly_pubkey_tweak_add` by setting the `tweak32` argument to the TapTweak hash defined in BIP 341. 26 | Both types of tweaking can be combined and invoked multiple times if the specific application requires it. 27 | 28 | ## Signing 29 | 30 | This is covered by `examples/musig.c`. 31 | Essentially, the protocol proceeds in the following steps: 32 | 33 | 1. Generate a keypair with `secp256k1_keypair_create` and obtain the public key with `secp256k1_keypair_pub`. 34 | 2. Call `secp256k1_musig_pubkey_agg` with the pubkeys of all participants. 35 | 3. Optionally add a (Taproot) tweak with `secp256k1_musig_pubkey_xonly_tweak_add` and a plain tweak with `secp256k1_musig_pubkey_ec_tweak_add`. 36 | 4. Generate a pair of secret and public nonce with `secp256k1_musig_nonce_gen` and send the public nonce to the other signers. 37 | 5. Someone (not necessarily the signer) aggregates the public nonces with `secp256k1_musig_nonce_agg` and sends it to the signers. 38 | 6. Process the aggregate nonce with `secp256k1_musig_nonce_process`. 39 | 7. Create a partial signature with `secp256k1_musig_partial_sign`. 40 | 8. Verify the partial signatures (optional in some scenarios) with `secp256k1_musig_partial_sig_verify`. 41 | 9. Someone (not necessarily the signer) obtains all partial signatures and aggregates them into the final Schnorr signature using `secp256k1_musig_partial_sig_agg`. 42 | 43 | The aggregate signature can be verified with `secp256k1_schnorrsig_verify`. 44 | 45 | Steps 1 through 5 above can occur before or after the signers are aware of the message to be signed. 46 | Whenever possible, it is recommended to generate the nonces only after the message is known. 47 | This provides enhanced defense-in-depth measures, protecting against potential API misuse in certain scenarios. 48 | However, it does require two rounds of communication during the signing process. 49 | The alternative, generating the nonces in a pre-processing step before the message is known, eliminates these additional protective measures but allows for non-interactive signing. 50 | Similarly, the API supports an alternative protocol flow where generating the aggregate key (steps 1 to 3) is allowed to happen after exchanging nonces (steps 4 to 5). 51 | 52 | ## Verification 53 | 54 | A participant who wants to verify the partial signatures, but does not sign itself may do so using the above instructions except that the verifier skips steps 1, 4 and 7. 55 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | function(add_example name) 2 | set(target_name ${name}_example) 3 | add_executable(${target_name} ${name}.c) 4 | target_include_directories(${target_name} PRIVATE 5 | ${PROJECT_SOURCE_DIR}/include 6 | ) 7 | target_link_libraries(${target_name} 8 | secp256k1 9 | $<$:bcrypt> 10 | ) 11 | set(test_name ${name}_example) 12 | add_test(NAME secp256k1_${test_name} COMMAND ${target_name}) 13 | endfunction() 14 | 15 | add_example(ecdsa) 16 | 17 | if(SECP256K1_ENABLE_MODULE_ECDH) 18 | add_example(ecdh) 19 | endif() 20 | 21 | if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) 22 | add_example(schnorr) 23 | endif() 24 | 25 | if(SECP256K1_ENABLE_MODULE_ELLSWIFT) 26 | add_example(ellswift) 27 | endif() 28 | 29 | if(SECP256K1_ENABLE_MODULE_MUSIG) 30 | add_example(musig) 31 | endif() 32 | -------------------------------------------------------------------------------- /examples/ecdh.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * Written in 2020-2022 by Elichai Turkel * 3 | * To the extent possible under law, the author(s) have dedicated all * 4 | * copyright and related and neighboring rights to the software in this * 5 | * file to the public domain worldwide. This software is distributed * 6 | * without any warranty. For the CC0 Public Domain Dedication, see * 7 | * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * 8 | *************************************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #include "examples_util.h" 19 | 20 | int main(void) { 21 | unsigned char seckey1[32]; 22 | unsigned char seckey2[32]; 23 | unsigned char compressed_pubkey1[33]; 24 | unsigned char compressed_pubkey2[33]; 25 | unsigned char shared_secret1[32]; 26 | unsigned char shared_secret2[32]; 27 | unsigned char randomize[32]; 28 | int return_val; 29 | size_t len; 30 | secp256k1_pubkey pubkey1; 31 | secp256k1_pubkey pubkey2; 32 | 33 | /* Before we can call actual API functions, we need to create a "context". */ 34 | secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); 35 | if (!fill_random(randomize, sizeof(randomize))) { 36 | printf("Failed to generate randomness\n"); 37 | return EXIT_FAILURE; 38 | } 39 | /* Randomizing the context is recommended to protect against side-channel 40 | * leakage See `secp256k1_context_randomize` in secp256k1.h for more 41 | * information about it. This should never fail. */ 42 | return_val = secp256k1_context_randomize(ctx, randomize); 43 | assert(return_val); 44 | 45 | /*** Key Generation ***/ 46 | if (!fill_random(seckey1, sizeof(seckey1)) || !fill_random(seckey2, sizeof(seckey2))) { 47 | printf("Failed to generate randomness\n"); 48 | return EXIT_FAILURE; 49 | } 50 | /* If the secret key is zero or out of range (greater than secp256k1's 51 | * order), we fail. Note that the probability of this occurring is negligible 52 | * with a properly functioning random number generator. */ 53 | if (!secp256k1_ec_seckey_verify(ctx, seckey1) || !secp256k1_ec_seckey_verify(ctx, seckey2)) { 54 | printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); 55 | return EXIT_FAILURE; 56 | } 57 | 58 | /* Public key creation using a valid context with a verified secret key should never fail */ 59 | return_val = secp256k1_ec_pubkey_create(ctx, &pubkey1, seckey1); 60 | assert(return_val); 61 | return_val = secp256k1_ec_pubkey_create(ctx, &pubkey2, seckey2); 62 | assert(return_val); 63 | 64 | /* Serialize pubkey1 in a compressed form (33 bytes), should always return 1 */ 65 | len = sizeof(compressed_pubkey1); 66 | return_val = secp256k1_ec_pubkey_serialize(ctx, compressed_pubkey1, &len, &pubkey1, SECP256K1_EC_COMPRESSED); 67 | assert(return_val); 68 | /* Should be the same size as the size of the output, because we passed a 33 byte array. */ 69 | assert(len == sizeof(compressed_pubkey1)); 70 | 71 | /* Serialize pubkey2 in a compressed form (33 bytes) */ 72 | len = sizeof(compressed_pubkey2); 73 | return_val = secp256k1_ec_pubkey_serialize(ctx, compressed_pubkey2, &len, &pubkey2, SECP256K1_EC_COMPRESSED); 74 | assert(return_val); 75 | /* Should be the same size as the size of the output, because we passed a 33 byte array. */ 76 | assert(len == sizeof(compressed_pubkey2)); 77 | 78 | /*** Creating the shared secret ***/ 79 | 80 | /* Perform ECDH with seckey1 and pubkey2. Should never fail with a verified 81 | * seckey and valid pubkey */ 82 | return_val = secp256k1_ecdh(ctx, shared_secret1, &pubkey2, seckey1, NULL, NULL); 83 | assert(return_val); 84 | 85 | /* Perform ECDH with seckey2 and pubkey1. Should never fail with a verified 86 | * seckey and valid pubkey */ 87 | return_val = secp256k1_ecdh(ctx, shared_secret2, &pubkey1, seckey2, NULL, NULL); 88 | assert(return_val); 89 | 90 | /* Both parties should end up with the same shared secret */ 91 | return_val = memcmp(shared_secret1, shared_secret2, sizeof(shared_secret1)); 92 | assert(return_val == 0); 93 | 94 | printf("Secret Key1: "); 95 | print_hex(seckey1, sizeof(seckey1)); 96 | printf("Compressed Pubkey1: "); 97 | print_hex(compressed_pubkey1, sizeof(compressed_pubkey1)); 98 | printf("\nSecret Key2: "); 99 | print_hex(seckey2, sizeof(seckey2)); 100 | printf("Compressed Pubkey2: "); 101 | print_hex(compressed_pubkey2, sizeof(compressed_pubkey2)); 102 | printf("\nShared Secret: "); 103 | print_hex(shared_secret1, sizeof(shared_secret1)); 104 | 105 | /* This will clear everything from the context and free the memory */ 106 | secp256k1_context_destroy(ctx); 107 | 108 | /* It's best practice to try to clear secrets from memory after using them. 109 | * This is done because some bugs can allow an attacker to leak memory, for 110 | * example through "out of bounds" array access (see Heartbleed), or the OS 111 | * swapping them to disk. Hence, we overwrite the secret key buffer with zeros. 112 | * 113 | * Here we are preventing these writes from being optimized out, as any good compiler 114 | * will remove any writes that aren't used. */ 115 | secure_erase(seckey1, sizeof(seckey1)); 116 | secure_erase(seckey2, sizeof(seckey2)); 117 | secure_erase(shared_secret1, sizeof(shared_secret1)); 118 | secure_erase(shared_secret2, sizeof(shared_secret2)); 119 | 120 | return EXIT_SUCCESS; 121 | } 122 | -------------------------------------------------------------------------------- /examples/ellswift.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * Written in 2024 by Sebastian Falbesoner * 3 | * To the extent possible under law, the author(s) have dedicated all * 4 | * copyright and related and neighboring rights to the software in this * 5 | * file to the public domain worldwide. This software is distributed * 6 | * without any warranty. For the CC0 Public Domain Dedication, see * 7 | * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * 8 | *************************************************************************/ 9 | 10 | /** This file demonstrates how to use the ElligatorSwift module to perform 11 | * a key exchange according to BIP 324. Additionally, see the documentation 12 | * in include/secp256k1_ellswift.h and doc/ellswift.md. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | #include "examples_util.h" 24 | 25 | int main(void) { 26 | secp256k1_context* ctx; 27 | unsigned char randomize[32]; 28 | unsigned char auxrand1[32]; 29 | unsigned char auxrand2[32]; 30 | unsigned char seckey1[32]; 31 | unsigned char seckey2[32]; 32 | unsigned char ellswift_pubkey1[64]; 33 | unsigned char ellswift_pubkey2[64]; 34 | unsigned char shared_secret1[32]; 35 | unsigned char shared_secret2[32]; 36 | int return_val; 37 | 38 | /* Create a secp256k1 context */ 39 | ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); 40 | if (!fill_random(randomize, sizeof(randomize))) { 41 | printf("Failed to generate randomness\n"); 42 | return EXIT_FAILURE; 43 | } 44 | /* Randomizing the context is recommended to protect against side-channel 45 | * leakage. See `secp256k1_context_randomize` in secp256k1.h for more 46 | * information about it. This should never fail. */ 47 | return_val = secp256k1_context_randomize(ctx, randomize); 48 | assert(return_val); 49 | 50 | /*** Generate secret keys ***/ 51 | if (!fill_random(seckey1, sizeof(seckey1)) || !fill_random(seckey2, sizeof(seckey2))) { 52 | printf("Failed to generate randomness\n"); 53 | return EXIT_FAILURE; 54 | } 55 | /* If the secret key is zero or out of range (greater than secp256k1's 56 | * order), we fail. Note that the probability of this occurring is negligible 57 | * with a properly functioning random number generator. */ 58 | if (!secp256k1_ec_seckey_verify(ctx, seckey1) || !secp256k1_ec_seckey_verify(ctx, seckey2)) { 59 | printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); 60 | return EXIT_FAILURE; 61 | } 62 | 63 | /* Generate ElligatorSwift public keys. This should never fail with valid context and 64 | verified secret keys. Note that providing additional randomness (fourth parameter) is 65 | optional, but recommended. */ 66 | if (!fill_random(auxrand1, sizeof(auxrand1)) || !fill_random(auxrand2, sizeof(auxrand2))) { 67 | printf("Failed to generate randomness\n"); 68 | return EXIT_FAILURE; 69 | } 70 | return_val = secp256k1_ellswift_create(ctx, ellswift_pubkey1, seckey1, auxrand1); 71 | assert(return_val); 72 | return_val = secp256k1_ellswift_create(ctx, ellswift_pubkey2, seckey2, auxrand2); 73 | assert(return_val); 74 | 75 | /*** Create the shared secret on each side ***/ 76 | 77 | /* Perform x-only ECDH with seckey1 and ellswift_pubkey2. Should never fail 78 | * with a verified seckey and valid pubkey. Note that both parties pass both 79 | * EllSwift pubkeys in the same order; the pubkey of the calling party is 80 | * determined by the "party" boolean (sixth parameter). */ 81 | return_val = secp256k1_ellswift_xdh(ctx, shared_secret1, ellswift_pubkey1, ellswift_pubkey2, 82 | seckey1, 0, secp256k1_ellswift_xdh_hash_function_bip324, NULL); 83 | assert(return_val); 84 | 85 | /* Perform x-only ECDH with seckey2 and ellswift_pubkey1. Should never fail 86 | * with a verified seckey and valid pubkey. */ 87 | return_val = secp256k1_ellswift_xdh(ctx, shared_secret2, ellswift_pubkey1, ellswift_pubkey2, 88 | seckey2, 1, secp256k1_ellswift_xdh_hash_function_bip324, NULL); 89 | assert(return_val); 90 | 91 | /* Both parties should end up with the same shared secret */ 92 | return_val = memcmp(shared_secret1, shared_secret2, sizeof(shared_secret1)); 93 | assert(return_val == 0); 94 | 95 | printf( " Secret Key1: "); 96 | print_hex(seckey1, sizeof(seckey1)); 97 | printf( "EllSwift Pubkey1: "); 98 | print_hex(ellswift_pubkey1, sizeof(ellswift_pubkey1)); 99 | printf("\n Secret Key2: "); 100 | print_hex(seckey2, sizeof(seckey2)); 101 | printf( "EllSwift Pubkey2: "); 102 | print_hex(ellswift_pubkey2, sizeof(ellswift_pubkey2)); 103 | printf("\n Shared Secret: "); 104 | print_hex(shared_secret1, sizeof(shared_secret1)); 105 | 106 | /* This will clear everything from the context and free the memory */ 107 | secp256k1_context_destroy(ctx); 108 | 109 | /* It's best practice to try to clear secrets from memory after using them. 110 | * This is done because some bugs can allow an attacker to leak memory, for 111 | * example through "out of bounds" array access (see Heartbleed), or the OS 112 | * swapping them to disk. Hence, we overwrite the secret key buffer with zeros. 113 | * 114 | * Here we are preventing these writes from being optimized out, as any good compiler 115 | * will remove any writes that aren't used. */ 116 | secure_erase(seckey1, sizeof(seckey1)); 117 | secure_erase(seckey2, sizeof(seckey2)); 118 | secure_erase(shared_secret1, sizeof(shared_secret1)); 119 | secure_erase(shared_secret2, sizeof(shared_secret2)); 120 | 121 | return EXIT_SUCCESS; 122 | } 123 | -------------------------------------------------------------------------------- /examples/examples_util.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * Copyright (c) 2020-2021 Elichai Turkel * 3 | * Distributed under the CC0 software license, see the accompanying file * 4 | * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * 5 | *************************************************************************/ 6 | 7 | /* 8 | * This file is an attempt at collecting best practice methods for obtaining randomness with different operating systems. 9 | * It may be out-of-date. Consult the documentation of the operating system before considering to use the methods below. 10 | * 11 | * Platform randomness sources: 12 | * Linux -> `getrandom(2)`(`sys/random.h`), if not available `/dev/urandom` should be used. http://man7.org/linux/man-pages/man2/getrandom.2.html, https://linux.die.net/man/4/urandom 13 | * macOS -> `getentropy(2)`(`sys/random.h`), if not available `/dev/urandom` should be used. https://www.unix.com/man-page/mojave/2/getentropy, https://opensource.apple.com/source/xnu/xnu-517.12.7/bsd/man/man4/random.4.auto.html 14 | * FreeBSD -> `getrandom(2)`(`sys/random.h`), if not available `kern.arandom` should be used. https://www.freebsd.org/cgi/man.cgi?query=getrandom, https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4 15 | * OpenBSD -> `getentropy(2)`(`unistd.h`), if not available `/dev/urandom` should be used. https://man.openbsd.org/getentropy, https://man.openbsd.org/urandom 16 | * Windows -> `BCryptGenRandom`(`bcrypt.h`). https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom 17 | */ 18 | 19 | #if defined(_WIN32) 20 | /* 21 | * The defined WIN32_NO_STATUS macro disables return code definitions in 22 | * windows.h, which avoids "macro redefinition" MSVC warnings in ntstatus.h. 23 | */ 24 | #define WIN32_NO_STATUS 25 | #include 26 | #undef WIN32_NO_STATUS 27 | #include 28 | #include 29 | #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) 30 | #include 31 | #elif defined(__OpenBSD__) 32 | #include 33 | #else 34 | #error "Couldn't identify the OS" 35 | #endif 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | 42 | /* Returns 1 on success, and 0 on failure. */ 43 | static int fill_random(unsigned char* data, size_t size) { 44 | #if defined(_WIN32) 45 | NTSTATUS res = BCryptGenRandom(NULL, data, size, BCRYPT_USE_SYSTEM_PREFERRED_RNG); 46 | if (res != STATUS_SUCCESS || size > ULONG_MAX) { 47 | return 0; 48 | } else { 49 | return 1; 50 | } 51 | #elif defined(__linux__) || defined(__FreeBSD__) 52 | /* If `getrandom(2)` is not available you should fallback to /dev/urandom */ 53 | ssize_t res = getrandom(data, size, 0); 54 | if (res < 0 || (size_t)res != size ) { 55 | return 0; 56 | } else { 57 | return 1; 58 | } 59 | #elif defined(__APPLE__) || defined(__OpenBSD__) 60 | /* If `getentropy(2)` is not available you should fallback to either 61 | * `SecRandomCopyBytes` or /dev/urandom */ 62 | int res = getentropy(data, size); 63 | if (res == 0) { 64 | return 1; 65 | } else { 66 | return 0; 67 | } 68 | #endif 69 | return 0; 70 | } 71 | 72 | static void print_hex(unsigned char* data, size_t size) { 73 | size_t i; 74 | printf("0x"); 75 | for (i = 0; i < size; i++) { 76 | printf("%02x", data[i]); 77 | } 78 | printf("\n"); 79 | } 80 | 81 | #if defined(_MSC_VER) 82 | // For SecureZeroMemory 83 | #include 84 | #endif 85 | /* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */ 86 | static void secure_erase(void *ptr, size_t len) { 87 | #if defined(_MSC_VER) 88 | /* SecureZeroMemory is guaranteed not to be optimized out by MSVC. */ 89 | SecureZeroMemory(ptr, len); 90 | #elif defined(__GNUC__) 91 | /* We use a memory barrier that scares the compiler away from optimizing out the memset. 92 | * 93 | * Quoting Adam Langley in commit ad1907fe73334d6c696c8539646c21b11178f20f 94 | * in BoringSSL (ISC License): 95 | * As best as we can tell, this is sufficient to break any optimisations that 96 | * might try to eliminate "superfluous" memsets. 97 | * This method used in memzero_explicit() the Linux kernel, too. Its advantage is that it is 98 | * pretty efficient, because the compiler can still implement the memset() efficiently, 99 | * just not remove it entirely. See "Dead Store Elimination (Still) Considered Harmful" by 100 | * Yang et al. (USENIX Security 2017) for more background. 101 | */ 102 | memset(ptr, 0, len); 103 | __asm__ __volatile__("" : : "r"(ptr) : "memory"); 104 | #else 105 | void *(*volatile const volatile_memset)(void *, int, size_t) = memset; 106 | volatile_memset(ptr, 0, len); 107 | #endif 108 | } 109 | -------------------------------------------------------------------------------- /include/secp256k1_ecdh.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_ECDH_H 2 | #define SECP256K1_ECDH_H 3 | 4 | #include "secp256k1.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /** A pointer to a function that hashes an EC point to obtain an ECDH secret 11 | * 12 | * Returns: 1 if the point was successfully hashed. 13 | * 0 will cause secp256k1_ecdh to fail and return 0. 14 | * Other return values are not allowed, and the behaviour of 15 | * secp256k1_ecdh is undefined for other return values. 16 | * Out: output: pointer to an array to be filled by the function 17 | * In: x32: pointer to a 32-byte x coordinate 18 | * y32: pointer to a 32-byte y coordinate 19 | * data: arbitrary data pointer that is passed through 20 | */ 21 | typedef int (*secp256k1_ecdh_hash_function)( 22 | unsigned char *output, 23 | const unsigned char *x32, 24 | const unsigned char *y32, 25 | void *data 26 | ); 27 | 28 | /** An implementation of SHA256 hash function that applies to compressed public key. 29 | * Populates the output parameter with 32 bytes. */ 30 | SECP256K1_API const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256; 31 | 32 | /** A default ECDH hash function (currently equal to secp256k1_ecdh_hash_function_sha256). 33 | * Populates the output parameter with 32 bytes. */ 34 | SECP256K1_API const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default; 35 | 36 | /** Compute an EC Diffie-Hellman secret in constant time 37 | * 38 | * Returns: 1: exponentiation was successful 39 | * 0: scalar was invalid (zero or overflow) or hashfp returned 0 40 | * Args: ctx: pointer to a context object. 41 | * Out: output: pointer to an array to be filled by hashfp. 42 | * In: pubkey: pointer to a secp256k1_pubkey containing an initialized public key. 43 | * seckey: a 32-byte scalar with which to multiply the point. 44 | * hashfp: pointer to a hash function. If NULL, 45 | * secp256k1_ecdh_hash_function_sha256 is used 46 | * (in which case, 32 bytes will be written to output). 47 | * data: arbitrary data pointer that is passed through to hashfp 48 | * (can be NULL for secp256k1_ecdh_hash_function_sha256). 49 | */ 50 | SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh( 51 | const secp256k1_context *ctx, 52 | unsigned char *output, 53 | const secp256k1_pubkey *pubkey, 54 | const unsigned char *seckey, 55 | secp256k1_ecdh_hash_function hashfp, 56 | void *data 57 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif /* SECP256K1_ECDH_H */ 64 | -------------------------------------------------------------------------------- /include/secp256k1_recovery.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_RECOVERY_H 2 | #define SECP256K1_RECOVERY_H 3 | 4 | #include "secp256k1.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /** Opaque data structure that holds a parsed ECDSA signature, 11 | * supporting pubkey recovery. 12 | * 13 | * The exact representation of data inside is implementation defined and not 14 | * guaranteed to be portable between different platforms or versions. It is 15 | * however guaranteed to be 65 bytes in size, and can be safely copied/moved. 16 | * If you need to convert to a format suitable for storage or transmission, use 17 | * the secp256k1_ecdsa_signature_serialize_* and 18 | * secp256k1_ecdsa_signature_parse_* functions. 19 | * 20 | * Furthermore, it is guaranteed that identical signatures (including their 21 | * recoverability) will have identical representation, so they can be 22 | * memcmp'ed. 23 | */ 24 | typedef struct secp256k1_ecdsa_recoverable_signature { 25 | unsigned char data[65]; 26 | } secp256k1_ecdsa_recoverable_signature; 27 | 28 | /** Parse a compact ECDSA signature (64 bytes + recovery id). 29 | * 30 | * Returns: 1 when the signature could be parsed, 0 otherwise 31 | * Args: ctx: pointer to a context object 32 | * Out: sig: pointer to a signature object 33 | * In: input64: pointer to a 64-byte compact signature 34 | * recid: the recovery id (0, 1, 2 or 3) 35 | */ 36 | SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact( 37 | const secp256k1_context *ctx, 38 | secp256k1_ecdsa_recoverable_signature *sig, 39 | const unsigned char *input64, 40 | int recid 41 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); 42 | 43 | /** Convert a recoverable signature into a normal signature. 44 | * 45 | * Returns: 1 46 | * Args: ctx: pointer to a context object. 47 | * Out: sig: pointer to a normal signature. 48 | * In: sigin: pointer to a recoverable signature. 49 | */ 50 | SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert( 51 | const secp256k1_context *ctx, 52 | secp256k1_ecdsa_signature *sig, 53 | const secp256k1_ecdsa_recoverable_signature *sigin 54 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); 55 | 56 | /** Serialize an ECDSA signature in compact format (64 bytes + recovery id). 57 | * 58 | * Returns: 1 59 | * Args: ctx: pointer to a context object. 60 | * Out: output64: pointer to a 64-byte array of the compact signature. 61 | * recid: pointer to an integer to hold the recovery id. 62 | * In: sig: pointer to an initialized signature object. 63 | */ 64 | SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact( 65 | const secp256k1_context *ctx, 66 | unsigned char *output64, 67 | int *recid, 68 | const secp256k1_ecdsa_recoverable_signature *sig 69 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); 70 | 71 | /** Create a recoverable ECDSA signature. 72 | * 73 | * Returns: 1: signature created 74 | * 0: the nonce generation function failed, or the secret key was invalid. 75 | * Args: ctx: pointer to a context object (not secp256k1_context_static). 76 | * Out: sig: pointer to an array where the signature will be placed. 77 | * In: msghash32: the 32-byte message hash being signed. 78 | * seckey: pointer to a 32-byte secret key. 79 | * noncefp: pointer to a nonce generation function. If NULL, 80 | * secp256k1_nonce_function_default is used. 81 | * ndata: pointer to arbitrary data used by the nonce generation function 82 | * (can be NULL for secp256k1_nonce_function_default). 83 | */ 84 | SECP256K1_API int secp256k1_ecdsa_sign_recoverable( 85 | const secp256k1_context *ctx, 86 | secp256k1_ecdsa_recoverable_signature *sig, 87 | const unsigned char *msghash32, 88 | const unsigned char *seckey, 89 | secp256k1_nonce_function noncefp, 90 | const void *ndata 91 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); 92 | 93 | /** Recover an ECDSA public key from a signature. 94 | * 95 | * Returns: 1: public key successfully recovered (which guarantees a correct signature). 96 | * 0: otherwise. 97 | * Args: ctx: pointer to a context object. 98 | * Out: pubkey: pointer to the recovered public key. 99 | * In: sig: pointer to initialized signature that supports pubkey recovery. 100 | * msghash32: the 32-byte message hash assumed to be signed. 101 | */ 102 | SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover( 103 | const secp256k1_context *ctx, 104 | secp256k1_pubkey *pubkey, 105 | const secp256k1_ecdsa_recoverable_signature *sig, 106 | const unsigned char *msghash32 107 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); 108 | 109 | #ifdef __cplusplus 110 | } 111 | #endif 112 | 113 | #endif /* SECP256K1_RECOVERY_H */ 114 | -------------------------------------------------------------------------------- /libsecp256k1.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libsecp256k1 7 | Description: Optimized C library for EC operations on curve secp256k1 8 | URL: https://github.com/bitcoin-core/secp256k1 9 | Version: @PACKAGE_VERSION@ 10 | Cflags: -I${includedir} 11 | Libs: -L${libdir} -lsecp256k1 12 | 13 | -------------------------------------------------------------------------------- /sage/gen_split_lambda_constants.sage: -------------------------------------------------------------------------------- 1 | """ Generates the constants used in secp256k1_scalar_split_lambda. 2 | 3 | See the comments for secp256k1_scalar_split_lambda in src/scalar_impl.h for detailed explanations. 4 | """ 5 | 6 | load("secp256k1_params.sage") 7 | 8 | def inf_norm(v): 9 | """Returns the infinity norm of a vector.""" 10 | return max(map(abs, v)) 11 | 12 | def gauss_reduction(i1, i2): 13 | v1, v2 = i1.copy(), i2.copy() 14 | while True: 15 | if inf_norm(v2) < inf_norm(v1): 16 | v1, v2 = v2, v1 17 | # This is essentially 18 | # m = round((v1[0]*v2[0] + v1[1]*v2[1]) / (inf_norm(v1)**2)) 19 | # (rounding to the nearest integer) without relying on floating point arithmetic. 20 | m = ((v1[0]*v2[0] + v1[1]*v2[1]) + (inf_norm(v1)**2) // 2) // (inf_norm(v1)**2) 21 | if m == 0: 22 | return v1, v2 23 | v2[0] -= m*v1[0] 24 | v2[1] -= m*v1[1] 25 | 26 | def find_split_constants_gauss(): 27 | """Find constants for secp256k1_scalar_split_lamdba using gauss reduction.""" 28 | (v11, v12), (v21, v22) = gauss_reduction([0, N], [1, int(LAMBDA)]) 29 | 30 | # We use related vectors in secp256k1_scalar_split_lambda. 31 | A1, B1 = -v21, -v11 32 | A2, B2 = v22, -v21 33 | 34 | return A1, B1, A2, B2 35 | 36 | def find_split_constants_explicit_tof(): 37 | """Find constants for secp256k1_scalar_split_lamdba using the trace of Frobenius. 38 | 39 | See Benjamin Smith: "Easy scalar decompositions for efficient scalar multiplication on 40 | elliptic curves and genus 2 Jacobians" (https://eprint.iacr.org/2013/672), Example 2 41 | """ 42 | assert P % 3 == 1 # The paper says P % 3 == 2 but that appears to be a mistake, see [10]. 43 | assert C.j_invariant() == 0 44 | 45 | t = C.trace_of_frobenius() 46 | 47 | c = Integer(sqrt((4*P - t**2)/3)) 48 | A1 = Integer((t - c)/2 - 1) 49 | B1 = c 50 | 51 | A2 = Integer((t + c)/2 - 1) 52 | B2 = Integer(1 - (t - c)/2) 53 | 54 | # We use a negated b values in secp256k1_scalar_split_lambda. 55 | B1, B2 = -B1, -B2 56 | 57 | return A1, B1, A2, B2 58 | 59 | A1, B1, A2, B2 = find_split_constants_explicit_tof() 60 | 61 | # For extra fun, use an independent method to recompute the constants. 62 | assert (A1, B1, A2, B2) == find_split_constants_gauss() 63 | 64 | # PHI : Z[l] -> Z_n where phi(a + b*l) == a + b*lambda mod n. 65 | def PHI(a,b): 66 | return Z(a + LAMBDA*b) 67 | 68 | # Check that (A1, B1) and (A2, B2) are in the kernel of PHI. 69 | assert PHI(A1, B1) == Z(0) 70 | assert PHI(A2, B2) == Z(0) 71 | 72 | # Check that the parallelogram generated by (A1, A2) and (B1, B2) 73 | # is a fundamental domain by containing exactly N points. 74 | # Since the LHS is the determinant and N != 0, this also checks that 75 | # (A1, A2) and (B1, B2) are linearly independent. By the previous 76 | # assertions, (A1, A2) and (B1, B2) are a basis of the kernel. 77 | assert A1*B2 - B1*A2 == N 78 | 79 | # Check that their components are short enough. 80 | assert (A1 + A2)/2 < sqrt(N) 81 | assert B1 < sqrt(N) 82 | assert B2 < sqrt(N) 83 | 84 | G1 = round((2**384)*B2/N) 85 | G2 = round((2**384)*(-B1)/N) 86 | 87 | def rnddiv2(v): 88 | if v & 1: 89 | v += 1 90 | return v >> 1 91 | 92 | def scalar_lambda_split(k): 93 | """Equivalent to secp256k1_scalar_lambda_split().""" 94 | c1 = rnddiv2((k * G1) >> 383) 95 | c2 = rnddiv2((k * G2) >> 383) 96 | c1 = (c1 * -B1) % N 97 | c2 = (c2 * -B2) % N 98 | r2 = (c1 + c2) % N 99 | r1 = (k + r2 * -LAMBDA) % N 100 | return (r1, r2) 101 | 102 | # The result of scalar_lambda_split can depend on the representation of k (mod n). 103 | SPECIAL = (2**383) // G2 + 1 104 | assert scalar_lambda_split(SPECIAL) != scalar_lambda_split(SPECIAL + N) 105 | 106 | print(' A1 =', hex(A1)) 107 | print(' -B1 =', hex(-B1)) 108 | print(' A2 =', hex(A2)) 109 | print(' -B2 =', hex(-B2)) 110 | print(' =', hex(Z(-B2))) 111 | print(' -LAMBDA =', hex(-LAMBDA)) 112 | 113 | print(' G1 =', hex(G1)) 114 | print(' G2 =', hex(G2)) 115 | -------------------------------------------------------------------------------- /sage/secp256k1_params.sage: -------------------------------------------------------------------------------- 1 | """Prime order of finite field underlying secp256k1 (2^256 - 2^32 - 977)""" 2 | P = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F 3 | 4 | """Finite field underlying secp256k1""" 5 | F = FiniteField(P) 6 | 7 | """Elliptic curve secp256k1: y^2 = x^3 + 7""" 8 | C = EllipticCurve([F(0), F(7)]) 9 | 10 | """Base point of secp256k1""" 11 | G = C.lift_x(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798) 12 | if int(G[1]) & 1: 13 | # G.y is even 14 | G = -G 15 | 16 | """Prime order of secp256k1""" 17 | N = C.order() 18 | 19 | """Finite field of scalars of secp256k1""" 20 | Z = FiniteField(N) 21 | 22 | """ Beta value of secp256k1 non-trivial endomorphism: lambda * (x, y) = (beta * x, y)""" 23 | BETA = F(2)^((P-1)/3) 24 | 25 | """ Lambda value of secp256k1 non-trivial endomorphism: lambda * (x, y) = (beta * x, y)""" 26 | LAMBDA = Z(3)^((N-1)/3) 27 | 28 | assert is_prime(P) 29 | assert is_prime(N) 30 | 31 | assert BETA != F(1) 32 | assert BETA^3 == F(1) 33 | assert BETA^2 + BETA + 1 == 0 34 | 35 | assert LAMBDA != Z(1) 36 | assert LAMBDA^3 == Z(1) 37 | assert LAMBDA^2 + LAMBDA + 1 == 0 38 | 39 | assert Integer(LAMBDA)*G == C(BETA*G[0], G[1]) 40 | -------------------------------------------------------------------------------- /src/assumptions.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2020 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ASSUMPTIONS_H 8 | #define SECP256K1_ASSUMPTIONS_H 9 | 10 | #include 11 | 12 | #include "util.h" 13 | #if defined(SECP256K1_INT128_NATIVE) 14 | #include "int128_native.h" 15 | #endif 16 | 17 | /* This library, like most software, relies on a number of compiler implementation defined (but not undefined) 18 | behaviours. Although the behaviours we require are essentially universal we test them specifically here to 19 | reduce the odds of experiencing an unwelcome surprise. 20 | */ 21 | 22 | #if defined(__has_attribute) 23 | # if __has_attribute(__unavailable__) 24 | __attribute__((__unavailable__("Don't call this function. It only exists because STATIC_ASSERT cannot be used outside a function."))) 25 | # endif 26 | #endif 27 | static void secp256k1_assumption_checker(void) { 28 | /* Bytes are 8 bits. */ 29 | STATIC_ASSERT(CHAR_BIT == 8); 30 | 31 | /* No integer promotion for uint32_t. This ensures that we can multiply uintXX_t values where XX >= 32 32 | without signed overflow, which would be undefined behaviour. */ 33 | STATIC_ASSERT(UINT_MAX <= UINT32_MAX); 34 | 35 | /* Conversions from unsigned to signed outside of the bounds of the signed type are 36 | implementation-defined. Verify that they function as reinterpreting the lower 37 | bits of the input in two's complement notation. Do this for conversions: 38 | - from uint(N)_t to int(N)_t with negative result 39 | - from uint(2N)_t to int(N)_t with negative result 40 | - from int(2N)_t to int(N)_t with negative result 41 | - from int(2N)_t to int(N)_t with positive result */ 42 | 43 | /* To int8_t. */ 44 | STATIC_ASSERT(((int8_t)(uint8_t)0xAB == (int8_t)-(int8_t)0x55)); 45 | STATIC_ASSERT((int8_t)(uint16_t)0xABCD == (int8_t)-(int8_t)0x33); 46 | STATIC_ASSERT((int8_t)(int16_t)(uint16_t)0xCDEF == (int8_t)(uint8_t)0xEF); 47 | STATIC_ASSERT((int8_t)(int16_t)(uint16_t)0x9234 == (int8_t)(uint8_t)0x34); 48 | 49 | /* To int16_t. */ 50 | STATIC_ASSERT((int16_t)(uint16_t)0xBCDE == (int16_t)-(int16_t)0x4322); 51 | STATIC_ASSERT((int16_t)(uint32_t)0xA1B2C3D4 == (int16_t)-(int16_t)0x3C2C); 52 | STATIC_ASSERT((int16_t)(int32_t)(uint32_t)0xC1D2E3F4 == (int16_t)(uint16_t)0xE3F4); 53 | STATIC_ASSERT((int16_t)(int32_t)(uint32_t)0x92345678 == (int16_t)(uint16_t)0x5678); 54 | 55 | /* To int32_t. */ 56 | STATIC_ASSERT((int32_t)(uint32_t)0xB2C3D4E5 == (int32_t)-(int32_t)0x4D3C2B1B); 57 | STATIC_ASSERT((int32_t)(uint64_t)0xA123B456C789D012ULL == (int32_t)-(int32_t)0x38762FEE); 58 | STATIC_ASSERT((int32_t)(int64_t)(uint64_t)0xC1D2E3F4A5B6C7D8ULL == (int32_t)(uint32_t)0xA5B6C7D8); 59 | STATIC_ASSERT((int32_t)(int64_t)(uint64_t)0xABCDEF0123456789ULL == (int32_t)(uint32_t)0x23456789); 60 | 61 | /* To int64_t. */ 62 | STATIC_ASSERT((int64_t)(uint64_t)0xB123C456D789E012ULL == (int64_t)-(int64_t)0x4EDC3BA928761FEEULL); 63 | #if defined(SECP256K1_INT128_NATIVE) 64 | STATIC_ASSERT((int64_t)(((uint128_t)0xA1234567B8901234ULL << 64) + 0xC5678901D2345678ULL) == (int64_t)-(int64_t)0x3A9876FE2DCBA988ULL); 65 | STATIC_ASSERT(((int64_t)(int128_t)(((uint128_t)0xB1C2D3E4F5A6B7C8ULL << 64) + 0xD9E0F1A2B3C4D5E6ULL)) == (int64_t)(uint64_t)0xD9E0F1A2B3C4D5E6ULL); 66 | STATIC_ASSERT(((int64_t)(int128_t)(((uint128_t)0xABCDEF0123456789ULL << 64) + 0x0123456789ABCDEFULL)) == (int64_t)(uint64_t)0x0123456789ABCDEFULL); 67 | 68 | /* To int128_t. */ 69 | STATIC_ASSERT((int128_t)(((uint128_t)0xB1234567C8901234ULL << 64) + 0xD5678901E2345678ULL) == (int128_t)(-(int128_t)0x8E1648B3F50E80DCULL * 0x8E1648B3F50E80DDULL + 0x5EA688D5482F9464ULL)); 70 | #endif 71 | 72 | /* Right shift on negative signed values is implementation defined. Verify that it 73 | acts as a right shift in two's complement with sign extension (i.e duplicating 74 | the top bit into newly added bits). */ 75 | STATIC_ASSERT((((int8_t)0xE8) >> 2) == (int8_t)(uint8_t)0xFA); 76 | STATIC_ASSERT((((int16_t)0xE9AC) >> 4) == (int16_t)(uint16_t)0xFE9A); 77 | STATIC_ASSERT((((int32_t)0x937C918A) >> 9) == (int32_t)(uint32_t)0xFFC9BE48); 78 | STATIC_ASSERT((((int64_t)0xA8B72231DF9CF4B9ULL) >> 19) == (int64_t)(uint64_t)0xFFFFF516E4463BF3ULL); 79 | #if defined(SECP256K1_INT128_NATIVE) 80 | STATIC_ASSERT((((int128_t)(((uint128_t)0xCD833A65684A0DBCULL << 64) + 0xB349312F71EA7637ULL)) >> 39) == (int128_t)(((uint128_t)0xFFFFFFFFFF9B0674ULL << 64) + 0xCAD0941B79669262ULL)); 81 | #endif 82 | 83 | /* This function is not supposed to be called. */ 84 | VERIFY_CHECK(0); 85 | } 86 | 87 | #endif /* SECP256K1_ASSUMPTIONS_H */ 88 | -------------------------------------------------------------------------------- /src/bench.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_BENCH_H 8 | #define SECP256K1_BENCH_H 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #if (defined(_MSC_VER) && _MSC_VER >= 1900) 16 | # include 17 | #else 18 | # include 19 | #endif 20 | 21 | static int64_t gettime_i64(void) { 22 | #if (defined(_MSC_VER) && _MSC_VER >= 1900) 23 | /* C11 way to get wallclock time */ 24 | struct timespec tv; 25 | if (!timespec_get(&tv, TIME_UTC)) { 26 | fputs("timespec_get failed!", stderr); 27 | exit(EXIT_FAILURE); 28 | } 29 | return (int64_t)tv.tv_nsec / 1000 + (int64_t)tv.tv_sec * 1000000LL; 30 | #else 31 | struct timeval tv; 32 | gettimeofday(&tv, NULL); 33 | return (int64_t)tv.tv_usec + (int64_t)tv.tv_sec * 1000000LL; 34 | #endif 35 | } 36 | 37 | #define FP_EXP (6) 38 | #define FP_MULT (1000000LL) 39 | 40 | /* Format fixed point number. */ 41 | static void print_number(const int64_t x) { 42 | int64_t x_abs, y; 43 | int c, i, rounding, g; /* g = integer part size, c = fractional part size */ 44 | size_t ptr; 45 | char buffer[30]; 46 | 47 | if (x == INT64_MIN) { 48 | /* Prevent UB. */ 49 | printf("ERR"); 50 | return; 51 | } 52 | x_abs = x < 0 ? -x : x; 53 | 54 | /* Determine how many decimals we want to show (more than FP_EXP makes no 55 | * sense). */ 56 | y = x_abs; 57 | c = 0; 58 | while (y > 0LL && y < 100LL * FP_MULT && c < FP_EXP) { 59 | y *= 10LL; 60 | c++; 61 | } 62 | 63 | /* Round to 'c' decimals. */ 64 | y = x_abs; 65 | rounding = 0; 66 | for (i = c; i < FP_EXP; ++i) { 67 | rounding = (y % 10) >= 5; 68 | y /= 10; 69 | } 70 | y += rounding; 71 | 72 | /* Format and print the number. */ 73 | ptr = sizeof(buffer) - 1; 74 | buffer[ptr] = 0; 75 | g = 0; 76 | if (c != 0) { /* non zero fractional part */ 77 | for (i = 0; i < c; ++i) { 78 | buffer[--ptr] = '0' + (y % 10); 79 | y /= 10; 80 | } 81 | } else if (c == 0) { /* fractional part is 0 */ 82 | buffer[--ptr] = '0'; 83 | } 84 | buffer[--ptr] = '.'; 85 | do { 86 | buffer[--ptr] = '0' + (y % 10); 87 | y /= 10; 88 | g++; 89 | } while (y != 0); 90 | if (x < 0) { 91 | buffer[--ptr] = '-'; 92 | g++; 93 | } 94 | printf("%5.*s", g, &buffer[ptr]); /* Prints integer part */ 95 | printf("%-*s", FP_EXP, &buffer[ptr + g]); /* Prints fractional part */ 96 | } 97 | 98 | static void run_benchmark(char *name, void (*benchmark)(void*, int), void (*setup)(void*), void (*teardown)(void*, int), void* data, int count, int iter) { 99 | int i; 100 | int64_t min = INT64_MAX; 101 | int64_t sum = 0; 102 | int64_t max = 0; 103 | for (i = 0; i < count; i++) { 104 | int64_t begin, total; 105 | if (setup != NULL) { 106 | setup(data); 107 | } 108 | begin = gettime_i64(); 109 | benchmark(data, iter); 110 | total = gettime_i64() - begin; 111 | if (teardown != NULL) { 112 | teardown(data, iter); 113 | } 114 | if (total < min) { 115 | min = total; 116 | } 117 | if (total > max) { 118 | max = total; 119 | } 120 | sum += total; 121 | } 122 | /* ',' is used as a column delimiter */ 123 | printf("%-30s, ", name); 124 | print_number(min * FP_MULT / iter); 125 | printf(" , "); 126 | print_number(((sum * FP_MULT) / count) / iter); 127 | printf(" , "); 128 | print_number(max * FP_MULT / iter); 129 | printf("\n"); 130 | } 131 | 132 | static int have_flag(int argc, char** argv, char *flag) { 133 | char** argm = argv + argc; 134 | argv++; 135 | while (argv != argm) { 136 | if (strcmp(*argv, flag) == 0) { 137 | return 1; 138 | } 139 | argv++; 140 | } 141 | return 0; 142 | } 143 | 144 | /* takes an array containing the arguments that the user is allowed to enter on the command-line 145 | returns: 146 | - 1 if the user entered an invalid argument 147 | - 0 if all the user entered arguments are valid */ 148 | static int have_invalid_args(int argc, char** argv, char** valid_args, size_t n) { 149 | size_t i; 150 | int found_valid; 151 | char** argm = argv + argc; 152 | argv++; 153 | 154 | while (argv != argm) { 155 | found_valid = 0; 156 | for (i = 0; i < n; i++) { 157 | if (strcmp(*argv, valid_args[i]) == 0) { 158 | found_valid = 1; /* user entered a valid arg from the list */ 159 | break; 160 | } 161 | } 162 | if (found_valid == 0) { 163 | return 1; /* invalid arg found */ 164 | } 165 | argv++; 166 | } 167 | return 0; 168 | } 169 | 170 | static int get_iters(int default_iters) { 171 | char* env = getenv("SECP256K1_BENCH_ITERS"); 172 | if (env) { 173 | return strtol(env, NULL, 0); 174 | } else { 175 | return default_iters; 176 | } 177 | } 178 | 179 | static void print_output_table_header_row(void) { 180 | char* bench_str = "Benchmark"; /* left justified */ 181 | char* min_str = " Min(us) "; /* center alignment */ 182 | char* avg_str = " Avg(us) "; 183 | char* max_str = " Max(us) "; 184 | printf("%-30s,%-15s,%-15s,%-15s\n", bench_str, min_str, avg_str, max_str); 185 | printf("\n"); 186 | } 187 | 188 | #endif /* SECP256K1_BENCH_H */ 189 | -------------------------------------------------------------------------------- /src/checkmem.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2022 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | /* The code here is inspired by Kris Kwiatkowski's approach in 8 | * https://github.com/kriskwiatkowski/pqc/blob/main/src/common/ct_check.h 9 | * to provide a general interface for memory-checking mechanisms, primarily 10 | * for constant-time checking. 11 | */ 12 | 13 | /* These macros are defined by this header file: 14 | * 15 | * - SECP256K1_CHECKMEM_ENABLED: 16 | * - 1 if memory-checking integration is available, 0 otherwise. 17 | * This is just a compile-time macro. Use the next macro to check it is actually 18 | * available at runtime. 19 | * - SECP256K1_CHECKMEM_RUNNING(): 20 | * - Acts like a function call, returning 1 if memory checking is available 21 | * at runtime. 22 | * - SECP256K1_CHECKMEM_CHECK(p, len): 23 | * - Assert or otherwise fail in case the len-byte memory block pointed to by p is 24 | * not considered entirely defined. 25 | * - SECP256K1_CHECKMEM_CHECK_VERIFY(p, len): 26 | * - Like SECP256K1_CHECKMEM_CHECK, but only works in VERIFY mode. 27 | * - SECP256K1_CHECKMEM_UNDEFINE(p, len): 28 | * - marks the len-byte memory block pointed to by p as undefined data (secret data, 29 | * in the context of constant-time checking). 30 | * - SECP256K1_CHECKMEM_DEFINE(p, len): 31 | * - marks the len-byte memory pointed to by p as defined data (public data, in the 32 | * context of constant-time checking). 33 | * - SECP256K1_CHECKMEM_MSAN_DEFINE(p, len): 34 | * - Like SECP256K1_CHECKMEM_DEFINE, but applies only to memory_sanitizer. 35 | * 36 | */ 37 | 38 | #ifndef SECP256K1_CHECKMEM_H 39 | #define SECP256K1_CHECKMEM_H 40 | 41 | /* Define a statement-like macro that ignores the arguments. */ 42 | #define SECP256K1_CHECKMEM_NOOP(p, len) do { (void)(p); (void)(len); } while(0) 43 | 44 | /* If compiling under msan, map the SECP256K1_CHECKMEM_* functionality to msan. 45 | * Choose this preferentially, even when VALGRIND is defined, as msan-compiled 46 | * binaries can't be run under valgrind anyway. */ 47 | #if defined(__has_feature) 48 | # if __has_feature(memory_sanitizer) 49 | # include 50 | # define SECP256K1_CHECKMEM_ENABLED 1 51 | # define SECP256K1_CHECKMEM_UNDEFINE(p, len) __msan_allocated_memory((p), (len)) 52 | # define SECP256K1_CHECKMEM_DEFINE(p, len) __msan_unpoison((p), (len)) 53 | # define SECP256K1_CHECKMEM_MSAN_DEFINE(p, len) __msan_unpoison((p), (len)) 54 | # define SECP256K1_CHECKMEM_CHECK(p, len) __msan_check_mem_is_initialized((p), (len)) 55 | # define SECP256K1_CHECKMEM_RUNNING() (1) 56 | # endif 57 | #endif 58 | 59 | #if !defined SECP256K1_CHECKMEM_MSAN_DEFINE 60 | # define SECP256K1_CHECKMEM_MSAN_DEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) 61 | #endif 62 | 63 | /* If valgrind integration is desired (through the VALGRIND define), implement the 64 | * SECP256K1_CHECKMEM_* macros using valgrind. */ 65 | #if !defined SECP256K1_CHECKMEM_ENABLED 66 | # if defined VALGRIND 67 | # include 68 | # if defined(__clang__) && defined(__APPLE__) 69 | # pragma clang diagnostic push 70 | # pragma clang diagnostic ignored "-Wreserved-identifier" 71 | # endif 72 | # include 73 | # if defined(__clang__) && defined(__APPLE__) 74 | # pragma clang diagnostic pop 75 | # endif 76 | # define SECP256K1_CHECKMEM_ENABLED 1 77 | # define SECP256K1_CHECKMEM_UNDEFINE(p, len) VALGRIND_MAKE_MEM_UNDEFINED((p), (len)) 78 | # define SECP256K1_CHECKMEM_DEFINE(p, len) VALGRIND_MAKE_MEM_DEFINED((p), (len)) 79 | # define SECP256K1_CHECKMEM_CHECK(p, len) VALGRIND_CHECK_MEM_IS_DEFINED((p), (len)) 80 | /* VALGRIND_MAKE_MEM_DEFINED returns 0 iff not running on memcheck. 81 | * This is more precise than the RUNNING_ON_VALGRIND macro, which 82 | * checks for valgrind in general instead of memcheck specifically. */ 83 | # define SECP256K1_CHECKMEM_RUNNING() (VALGRIND_MAKE_MEM_DEFINED(NULL, 0) != 0) 84 | # endif 85 | #endif 86 | 87 | /* As a fall-back, map these macros to dummy statements. */ 88 | #if !defined SECP256K1_CHECKMEM_ENABLED 89 | # define SECP256K1_CHECKMEM_ENABLED 0 90 | # define SECP256K1_CHECKMEM_UNDEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) 91 | # define SECP256K1_CHECKMEM_DEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) 92 | # define SECP256K1_CHECKMEM_CHECK(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) 93 | # define SECP256K1_CHECKMEM_RUNNING() (0) 94 | #endif 95 | 96 | #if defined VERIFY 97 | #define SECP256K1_CHECKMEM_CHECK_VERIFY(p, len) SECP256K1_CHECKMEM_CHECK((p), (len)) 98 | #else 99 | #define SECP256K1_CHECKMEM_CHECK_VERIFY(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) 100 | #endif 101 | 102 | #endif /* SECP256K1_CHECKMEM_H */ 103 | -------------------------------------------------------------------------------- /src/ecdsa.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECDSA_H 8 | #define SECP256K1_ECDSA_H 9 | 10 | #include 11 | 12 | #include "scalar.h" 13 | #include "group.h" 14 | #include "ecmult.h" 15 | 16 | static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, const unsigned char *sig, size_t size); 17 | static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s); 18 | static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message); 19 | static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid); 20 | 21 | #endif /* SECP256K1_ECDSA_H */ 22 | -------------------------------------------------------------------------------- /src/eckey.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECKEY_H 8 | #define SECP256K1_ECKEY_H 9 | 10 | #include 11 | 12 | #include "group.h" 13 | #include "scalar.h" 14 | #include "ecmult.h" 15 | #include "ecmult_gen.h" 16 | 17 | static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size); 18 | static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed); 19 | 20 | static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak); 21 | static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge *key, const secp256k1_scalar *tweak); 22 | static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak); 23 | static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge *key, const secp256k1_scalar *tweak); 24 | 25 | #endif /* SECP256K1_ECKEY_H */ 26 | -------------------------------------------------------------------------------- /src/eckey_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECKEY_IMPL_H 8 | #define SECP256K1_ECKEY_IMPL_H 9 | 10 | #include "eckey.h" 11 | 12 | #include "util.h" 13 | #include "scalar.h" 14 | #include "field.h" 15 | #include "group.h" 16 | #include "ecmult_gen.h" 17 | 18 | static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) { 19 | if (size == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) { 20 | secp256k1_fe x; 21 | return secp256k1_fe_set_b32_limit(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD); 22 | } else if (size == 65 && (pub[0] == SECP256K1_TAG_PUBKEY_UNCOMPRESSED || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) { 23 | secp256k1_fe x, y; 24 | if (!secp256k1_fe_set_b32_limit(&x, pub+1) || !secp256k1_fe_set_b32_limit(&y, pub+33)) { 25 | return 0; 26 | } 27 | secp256k1_ge_set_xy(elem, &x, &y); 28 | if ((pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD) && 29 | secp256k1_fe_is_odd(&y) != (pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) { 30 | return 0; 31 | } 32 | return secp256k1_ge_is_valid_var(elem); 33 | } else { 34 | return 0; 35 | } 36 | } 37 | 38 | static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) { 39 | VERIFY_CHECK(compressed == 0 || compressed == 1); 40 | 41 | if (secp256k1_ge_is_infinity(elem)) { 42 | return 0; 43 | } 44 | secp256k1_fe_normalize_var(&elem->x); 45 | secp256k1_fe_normalize_var(&elem->y); 46 | secp256k1_fe_get_b32(&pub[1], &elem->x); 47 | if (compressed) { 48 | *size = 33; 49 | pub[0] = secp256k1_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN; 50 | } else { 51 | *size = 65; 52 | pub[0] = SECP256K1_TAG_PUBKEY_UNCOMPRESSED; 53 | secp256k1_fe_get_b32(&pub[33], &elem->y); 54 | } 55 | return 1; 56 | } 57 | 58 | static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak) { 59 | secp256k1_scalar_add(key, key, tweak); 60 | return !secp256k1_scalar_is_zero(key); 61 | } 62 | 63 | static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge *key, const secp256k1_scalar *tweak) { 64 | secp256k1_gej pt; 65 | secp256k1_gej_set_ge(&pt, key); 66 | secp256k1_ecmult(&pt, &pt, &secp256k1_scalar_one, tweak); 67 | 68 | if (secp256k1_gej_is_infinity(&pt)) { 69 | return 0; 70 | } 71 | secp256k1_ge_set_gej(key, &pt); 72 | return 1; 73 | } 74 | 75 | static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak) { 76 | int ret; 77 | ret = !secp256k1_scalar_is_zero(tweak); 78 | 79 | secp256k1_scalar_mul(key, key, tweak); 80 | return ret; 81 | } 82 | 83 | static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge *key, const secp256k1_scalar *tweak) { 84 | secp256k1_gej pt; 85 | if (secp256k1_scalar_is_zero(tweak)) { 86 | return 0; 87 | } 88 | 89 | secp256k1_gej_set_ge(&pt, key); 90 | secp256k1_ecmult(&pt, &pt, tweak, &secp256k1_scalar_zero); 91 | secp256k1_ge_set_gej(key, &pt); 92 | return 1; 93 | } 94 | 95 | #endif /* SECP256K1_ECKEY_IMPL_H */ 96 | -------------------------------------------------------------------------------- /src/ecmult.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECMULT_H 8 | #define SECP256K1_ECMULT_H 9 | 10 | #include "group.h" 11 | #include "scalar.h" 12 | #include "scratch.h" 13 | 14 | #ifndef ECMULT_WINDOW_SIZE 15 | # define ECMULT_WINDOW_SIZE 15 16 | # ifdef DEBUG_CONFIG 17 | # pragma message DEBUG_CONFIG_MSG("ECMULT_WINDOW_SIZE undefined, assuming default value") 18 | # endif 19 | #endif 20 | 21 | #ifdef DEBUG_CONFIG 22 | # pragma message DEBUG_CONFIG_DEF(ECMULT_WINDOW_SIZE) 23 | #endif 24 | 25 | /* No one will ever need more than a window size of 24. The code might 26 | * be correct for larger values of ECMULT_WINDOW_SIZE but this is not 27 | * tested. 28 | * 29 | * The following limitations are known, and there are probably more: 30 | * If WINDOW_G > 27 and size_t has 32 bits, then the code is incorrect 31 | * because the size of the memory object that we allocate (in bytes) 32 | * will not fit in a size_t. 33 | * If WINDOW_G > 31 and int has 32 bits, then the code is incorrect 34 | * because certain expressions will overflow. 35 | */ 36 | #if ECMULT_WINDOW_SIZE < 2 || ECMULT_WINDOW_SIZE > 24 37 | # error Set ECMULT_WINDOW_SIZE to an integer in range [2..24]. 38 | #endif 39 | 40 | /** The number of entries a table with precomputed multiples needs to have. */ 41 | #define ECMULT_TABLE_SIZE(w) (1L << ((w)-2)) 42 | 43 | /** Double multiply: R = na*A + ng*G */ 44 | static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng); 45 | 46 | typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data); 47 | 48 | /** 49 | * Multi-multiply: R = inp_g_sc * G + sum_i ni * Ai. 50 | * Chooses the right algorithm for a given number of points and scratch space 51 | * size. Resets and overwrites the given scratch space. If the points do not 52 | * fit in the scratch space the algorithm is repeatedly run with batches of 53 | * points. If no scratch space is given then a simple algorithm is used that 54 | * simply multiplies the points with the corresponding scalars and adds them up. 55 | * Returns: 1 on success (including when inp_g_sc is NULL and n is 0) 56 | * 0 if there is not enough scratch space for a single point or 57 | * callback returns 0 58 | */ 59 | static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n); 60 | 61 | #endif /* SECP256K1_ECMULT_H */ 62 | -------------------------------------------------------------------------------- /src/ecmult_compute_table.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************************************** 2 | * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php. * 5 | *****************************************************************************************************/ 6 | 7 | #ifndef SECP256K1_ECMULT_COMPUTE_TABLE_H 8 | #define SECP256K1_ECMULT_COMPUTE_TABLE_H 9 | 10 | /* Construct table of all odd multiples of gen in range 1..(2**(window_g-1)-1). */ 11 | static void secp256k1_ecmult_compute_table(secp256k1_ge_storage* table, int window_g, const secp256k1_gej* gen); 12 | 13 | /* Like secp256k1_ecmult_compute_table, but one for both gen and gen*2^128. */ 14 | static void secp256k1_ecmult_compute_two_tables(secp256k1_ge_storage* table, secp256k1_ge_storage* table_128, int window_g, const secp256k1_ge* gen); 15 | 16 | #endif /* SECP256K1_ECMULT_COMPUTE_TABLE_H */ 17 | -------------------------------------------------------------------------------- /src/ecmult_compute_table_impl.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************************************** 2 | * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php. * 5 | *****************************************************************************************************/ 6 | 7 | #ifndef SECP256K1_ECMULT_COMPUTE_TABLE_IMPL_H 8 | #define SECP256K1_ECMULT_COMPUTE_TABLE_IMPL_H 9 | 10 | #include "ecmult_compute_table.h" 11 | #include "group_impl.h" 12 | #include "field_impl.h" 13 | #include "ecmult.h" 14 | #include "util.h" 15 | 16 | static void secp256k1_ecmult_compute_table(secp256k1_ge_storage* table, int window_g, const secp256k1_gej* gen) { 17 | secp256k1_gej gj; 18 | secp256k1_ge ge, dgen; 19 | int j; 20 | 21 | gj = *gen; 22 | secp256k1_ge_set_gej_var(&ge, &gj); 23 | secp256k1_ge_to_storage(&table[0], &ge); 24 | 25 | secp256k1_gej_double_var(&gj, gen, NULL); 26 | secp256k1_ge_set_gej_var(&dgen, &gj); 27 | 28 | for (j = 1; j < ECMULT_TABLE_SIZE(window_g); ++j) { 29 | secp256k1_gej_set_ge(&gj, &ge); 30 | secp256k1_gej_add_ge_var(&gj, &gj, &dgen, NULL); 31 | secp256k1_ge_set_gej_var(&ge, &gj); 32 | secp256k1_ge_to_storage(&table[j], &ge); 33 | } 34 | } 35 | 36 | /* Like secp256k1_ecmult_compute_table, but one for both gen and gen*2^128. */ 37 | static void secp256k1_ecmult_compute_two_tables(secp256k1_ge_storage* table, secp256k1_ge_storage* table_128, int window_g, const secp256k1_ge* gen) { 38 | secp256k1_gej gj; 39 | int i; 40 | 41 | secp256k1_gej_set_ge(&gj, gen); 42 | secp256k1_ecmult_compute_table(table, window_g, &gj); 43 | for (i = 0; i < 128; ++i) { 44 | secp256k1_gej_double_var(&gj, &gj, NULL); 45 | } 46 | secp256k1_ecmult_compute_table(table_128, window_g, &gj); 47 | } 48 | 49 | #endif /* SECP256K1_ECMULT_COMPUTE_TABLE_IMPL_H */ 50 | -------------------------------------------------------------------------------- /src/ecmult_const.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2015 Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECMULT_CONST_H 8 | #define SECP256K1_ECMULT_CONST_H 9 | 10 | #include "scalar.h" 11 | #include "group.h" 12 | 13 | /** 14 | * Multiply: R = q*A (in constant-time for q) 15 | */ 16 | static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q); 17 | 18 | /** 19 | * Same as secp256k1_ecmult_const, but takes in an x coordinate of the base point 20 | * only, specified as fraction n/d (numerator/denominator). Only the x coordinate of the result is 21 | * returned. 22 | * 23 | * If known_on_curve is 0, a verification is performed that n/d is a valid X 24 | * coordinate, and 0 is returned if not. Otherwise, 1 is returned. 25 | * 26 | * d being NULL is interpreted as d=1. If non-NULL, d must not be zero. q must not be zero. 27 | * 28 | * Constant time in the value of q, but not any other inputs. 29 | */ 30 | static int secp256k1_ecmult_const_xonly( 31 | secp256k1_fe *r, 32 | const secp256k1_fe *n, 33 | const secp256k1_fe *d, 34 | const secp256k1_scalar *q, 35 | int known_on_curve 36 | ); 37 | 38 | #endif /* SECP256K1_ECMULT_CONST_H */ 39 | -------------------------------------------------------------------------------- /src/ecmult_gen.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) Pieter Wuille, Peter Dettman * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECMULT_GEN_H 8 | #define SECP256K1_ECMULT_GEN_H 9 | 10 | #include "scalar.h" 11 | #include "group.h" 12 | 13 | 14 | /* Configuration parameters for the signed-digit multi-comb algorithm: 15 | * 16 | * - COMB_BLOCKS is the number of blocks the input is split into. Each 17 | * has a corresponding table. 18 | * - COMB_TEETH is the number of bits simultaneously covered by one table. 19 | * - COMB_RANGE is the number of bits in supported scalars. For production 20 | * purposes, only 256 is reasonable, but smaller numbers are supported for 21 | * exhaustive test mode. 22 | * 23 | * The comb's spacing (COMB_SPACING), or the distance between the teeth, 24 | * is defined as ceil(COMB_RANGE / (COMB_BLOCKS * COMB_TEETH)). Each block covers 25 | * COMB_SPACING * COMB_TEETH consecutive bits in the input. 26 | * 27 | * The size of the precomputed table is COMB_BLOCKS * (1 << (COMB_TEETH - 1)) 28 | * secp256k1_ge_storages. 29 | * 30 | * The number of point additions equals COMB_BLOCKS * COMB_SPACING. Each point 31 | * addition involves a cmov from (1 << (COMB_TEETH - 1)) table entries and a 32 | * conditional negation. 33 | * 34 | * The number of point doublings is COMB_SPACING - 1. */ 35 | 36 | #if defined(EXHAUSTIVE_TEST_ORDER) 37 | /* We need to control these values for exhaustive tests because 38 | * the table cannot have infinities in them (secp256k1_ge_storage 39 | * doesn't support infinities) */ 40 | # undef COMB_BLOCKS 41 | # undef COMB_TEETH 42 | # if EXHAUSTIVE_TEST_ORDER == 7 43 | # define COMB_RANGE 3 44 | # define COMB_BLOCKS 1 45 | # define COMB_TEETH 2 46 | # elif EXHAUSTIVE_TEST_ORDER == 13 47 | # define COMB_RANGE 4 48 | # define COMB_BLOCKS 1 49 | # define COMB_TEETH 2 50 | # elif EXHAUSTIVE_TEST_ORDER == 199 51 | # define COMB_RANGE 8 52 | # define COMB_BLOCKS 2 53 | # define COMB_TEETH 3 54 | # else 55 | # error "Unknown exhaustive test order" 56 | # endif 57 | # if (COMB_RANGE >= 32) || ((EXHAUSTIVE_TEST_ORDER >> (COMB_RANGE - 1)) != 1) 58 | # error "COMB_RANGE != ceil(log2(EXHAUSTIVE_TEST_ORDER+1))" 59 | # endif 60 | #else /* !defined(EXHAUSTIVE_TEST_ORDER) */ 61 | # define COMB_RANGE 256 62 | #endif /* defined(EXHAUSTIVE_TEST_ORDER) */ 63 | 64 | /* Use (11, 6) as default configuration, which results in a 22 kB table. */ 65 | #ifndef COMB_BLOCKS 66 | # define COMB_BLOCKS 11 67 | # ifdef DEBUG_CONFIG 68 | # pragma message DEBUG_CONFIG_MSG("COMB_BLOCKS undefined, assuming default value") 69 | # endif 70 | #endif 71 | #ifndef COMB_TEETH 72 | # define COMB_TEETH 6 73 | # ifdef DEBUG_CONFIG 74 | # pragma message DEBUG_CONFIG_MSG("COMB_TEETH undefined, assuming default value") 75 | # endif 76 | #endif 77 | /* Use ceil(COMB_RANGE / (COMB_BLOCKS * COMB_TEETH)) as COMB_SPACING. */ 78 | #define COMB_SPACING CEIL_DIV(COMB_RANGE, COMB_BLOCKS * COMB_TEETH) 79 | 80 | /* Range checks on the parameters. */ 81 | 82 | /* The remaining COMB_* parameters are derived values, don't modify these. */ 83 | /* - The number of bits covered by all the blocks; must be at least COMB_RANGE. */ 84 | #define COMB_BITS (COMB_BLOCKS * COMB_TEETH * COMB_SPACING) 85 | /* - The number of entries per table. */ 86 | #define COMB_POINTS (1 << (COMB_TEETH - 1)) 87 | 88 | /* Sanity checks. */ 89 | #if !(1 <= COMB_BLOCKS && COMB_BLOCKS <= 256) 90 | # error "COMB_BLOCKS must be in the range [1, 256]" 91 | #endif 92 | #if !(1 <= COMB_TEETH && COMB_TEETH <= 8) 93 | # error "COMB_TEETH must be in the range [1, 8]" 94 | #endif 95 | #if COMB_BITS < COMB_RANGE 96 | # error "COMB_BLOCKS * COMB_TEETH * COMB_SPACING is too low" 97 | #endif 98 | 99 | /* These last 2 checks are not strictly required, but prevent gratuitously inefficient 100 | * configurations. Note that they compare with 256 rather than COMB_RANGE, so they do 101 | * permit somewhat excessive values for the exhaustive test case, where testing with 102 | * suboptimal parameters may be desirable. */ 103 | #if (COMB_BLOCKS - 1) * COMB_TEETH * COMB_SPACING >= 256 104 | # error "COMB_BLOCKS can be reduced" 105 | #endif 106 | #if COMB_BLOCKS * (COMB_TEETH - 1) * COMB_SPACING >= 256 107 | # error "COMB_TEETH can be reduced" 108 | #endif 109 | 110 | #ifdef DEBUG_CONFIG 111 | # pragma message DEBUG_CONFIG_DEF(COMB_RANGE) 112 | # pragma message DEBUG_CONFIG_DEF(COMB_BLOCKS) 113 | # pragma message DEBUG_CONFIG_DEF(COMB_TEETH) 114 | # pragma message DEBUG_CONFIG_DEF(COMB_SPACING) 115 | #endif 116 | 117 | typedef struct { 118 | /* Whether the context has been built. */ 119 | int built; 120 | 121 | /* Values chosen such that 122 | * 123 | * n*G == comb(n + scalar_offset, G/2) + ge_offset. 124 | * 125 | * This expression lets us use scalar blinding and optimize the comb precomputation. See 126 | * ecmult_gen_impl.h for more details. */ 127 | secp256k1_scalar scalar_offset; 128 | secp256k1_ge ge_offset; 129 | 130 | /* Factor used for projective blinding. This value is used to rescale the Z 131 | * coordinate of the first table lookup. */ 132 | secp256k1_fe proj_blind; 133 | } secp256k1_ecmult_gen_context; 134 | 135 | static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx); 136 | static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx); 137 | 138 | /** Multiply with the generator: R = a*G */ 139 | static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a); 140 | 141 | static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32); 142 | 143 | #endif /* SECP256K1_ECMULT_GEN_H */ 144 | -------------------------------------------------------------------------------- /src/ecmult_gen_compute_table.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) Pieter Wuille, Gregory Maxwell * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H 8 | #define SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H 9 | 10 | #include "ecmult_gen.h" 11 | 12 | static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int blocks, int teeth, int spacing); 13 | 14 | #endif /* SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H */ 15 | -------------------------------------------------------------------------------- /src/ecmult_gen_compute_table_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) Pieter Wuille, Gregory Maxwell, Peter Dettman * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECMULT_GEN_COMPUTE_TABLE_IMPL_H 8 | #define SECP256K1_ECMULT_GEN_COMPUTE_TABLE_IMPL_H 9 | 10 | #include "ecmult_gen_compute_table.h" 11 | #include "group_impl.h" 12 | #include "field_impl.h" 13 | #include "scalar_impl.h" 14 | #include "ecmult_gen.h" 15 | #include "util.h" 16 | 17 | static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int blocks, int teeth, int spacing) { 18 | size_t points = ((size_t)1) << (teeth - 1); 19 | size_t points_total = points * blocks; 20 | secp256k1_ge* prec = checked_malloc(&default_error_callback, points_total * sizeof(*prec)); 21 | secp256k1_gej* ds = checked_malloc(&default_error_callback, teeth * sizeof(*ds)); 22 | secp256k1_gej* vs = checked_malloc(&default_error_callback, points_total * sizeof(*vs)); 23 | secp256k1_gej u; 24 | size_t vs_pos = 0; 25 | secp256k1_scalar half; 26 | int block, i; 27 | 28 | VERIFY_CHECK(points_total > 0); 29 | 30 | /* u is the running power of two times gen we're working with, initially gen/2. */ 31 | secp256k1_scalar_half(&half, &secp256k1_scalar_one); 32 | secp256k1_gej_set_infinity(&u); 33 | for (i = 255; i >= 0; --i) { 34 | /* Use a very simple multiplication ladder to avoid dependency on ecmult. */ 35 | secp256k1_gej_double_var(&u, &u, NULL); 36 | if (secp256k1_scalar_get_bits_limb32(&half, i, 1)) { 37 | secp256k1_gej_add_ge_var(&u, &u, gen, NULL); 38 | } 39 | } 40 | #ifdef VERIFY 41 | { 42 | /* Verify that u*2 = gen. */ 43 | secp256k1_gej double_u; 44 | secp256k1_gej_double_var(&double_u, &u, NULL); 45 | VERIFY_CHECK(secp256k1_gej_eq_ge_var(&double_u, gen)); 46 | } 47 | #endif 48 | 49 | for (block = 0; block < blocks; ++block) { 50 | int tooth; 51 | /* Here u = 2^(block*teeth*spacing) * gen/2. */ 52 | secp256k1_gej sum; 53 | secp256k1_gej_set_infinity(&sum); 54 | for (tooth = 0; tooth < teeth; ++tooth) { 55 | /* Here u = 2^((block*teeth + tooth)*spacing) * gen/2. */ 56 | /* Make sum = sum(2^((block*teeth + t)*spacing), t=0..tooth) * gen/2. */ 57 | secp256k1_gej_add_var(&sum, &sum, &u, NULL); 58 | /* Make u = 2^((block*teeth + tooth)*spacing + 1) * gen/2. */ 59 | secp256k1_gej_double_var(&u, &u, NULL); 60 | /* Make ds[tooth] = u = 2^((block*teeth + tooth)*spacing + 1) * gen/2. */ 61 | ds[tooth] = u; 62 | /* Make u = 2^((block*teeth + tooth + 1)*spacing) * gen/2, unless at the end. */ 63 | if (block + tooth != blocks + teeth - 2) { 64 | int bit_off; 65 | for (bit_off = 1; bit_off < spacing; ++bit_off) { 66 | secp256k1_gej_double_var(&u, &u, NULL); 67 | } 68 | } 69 | } 70 | /* Now u = 2^((block*teeth + teeth)*spacing) * gen/2 71 | * = 2^((block+1)*teeth*spacing) * gen/2 */ 72 | 73 | /* Next, compute the table entries for block number block in Jacobian coordinates. 74 | * The entries will occupy vs[block*points + i] for i=0..points-1. 75 | * We start by computing the first (i=0) value corresponding to all summed 76 | * powers of two times G being negative. */ 77 | secp256k1_gej_neg(&vs[vs_pos++], &sum); 78 | /* And then teeth-1 times "double" the range of i values for which the table 79 | * is computed: in each iteration, double the table by taking an existing 80 | * table entry and adding ds[tooth]. */ 81 | for (tooth = 0; tooth < teeth - 1; ++tooth) { 82 | size_t stride = ((size_t)1) << tooth; 83 | size_t index; 84 | for (index = 0; index < stride; ++index, ++vs_pos) { 85 | secp256k1_gej_add_var(&vs[vs_pos], &vs[vs_pos - stride], &ds[tooth], NULL); 86 | } 87 | } 88 | } 89 | VERIFY_CHECK(vs_pos == points_total); 90 | 91 | /* Convert all points simultaneously from secp256k1_gej to secp256k1_ge. */ 92 | secp256k1_ge_set_all_gej_var(prec, vs, points_total); 93 | /* Convert all points from secp256k1_ge to secp256k1_ge_storage output. */ 94 | for (block = 0; block < blocks; ++block) { 95 | size_t index; 96 | for (index = 0; index < points; ++index) { 97 | VERIFY_CHECK(!secp256k1_ge_is_infinity(&prec[block * points + index])); 98 | secp256k1_ge_to_storage(&table[block * points + index], &prec[block * points + index]); 99 | } 100 | } 101 | 102 | /* Free memory. */ 103 | free(vs); 104 | free(ds); 105 | free(prec); 106 | } 107 | 108 | #endif /* SECP256K1_ECMULT_GEN_COMPUTE_TABLE_IMPL_H */ 109 | -------------------------------------------------------------------------------- /src/field_10x26.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_FIELD_REPR_H 8 | #define SECP256K1_FIELD_REPR_H 9 | 10 | #include 11 | 12 | /** This field implementation represents the value as 10 uint32_t limbs in base 13 | * 2^26. */ 14 | typedef struct { 15 | /* A field element f represents the sum(i=0..9, f.n[i] << (i*26)) mod p, 16 | * where p is the field modulus, 2^256 - 2^32 - 977. 17 | * 18 | * The individual limbs f.n[i] can exceed 2^26; the field's magnitude roughly 19 | * corresponds to how much excess is allowed. The value 20 | * sum(i=0..9, f.n[i] << (i*26)) may exceed p, unless the field element is 21 | * normalized. */ 22 | uint32_t n[10]; 23 | /* 24 | * Magnitude m requires: 25 | * n[i] <= 2 * m * (2^26 - 1) for i=0..8 26 | * n[9] <= 2 * m * (2^22 - 1) 27 | * 28 | * Normalized requires: 29 | * n[i] <= (2^26 - 1) for i=0..8 30 | * sum(i=0..9, n[i] << (i*26)) < p 31 | * (together these imply n[9] <= 2^22 - 1) 32 | */ 33 | SECP256K1_FE_VERIFY_FIELDS 34 | } secp256k1_fe; 35 | 36 | /* Unpacks a constant into a overlapping multi-limbed FE element. */ 37 | #define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ 38 | (d0) & 0x3FFFFFFUL, \ 39 | (((uint32_t)d0) >> 26) | (((uint32_t)(d1) & 0xFFFFFUL) << 6), \ 40 | (((uint32_t)d1) >> 20) | (((uint32_t)(d2) & 0x3FFFUL) << 12), \ 41 | (((uint32_t)d2) >> 14) | (((uint32_t)(d3) & 0xFFUL) << 18), \ 42 | (((uint32_t)d3) >> 8) | (((uint32_t)(d4) & 0x3UL) << 24), \ 43 | (((uint32_t)d4) >> 2) & 0x3FFFFFFUL, \ 44 | (((uint32_t)d4) >> 28) | (((uint32_t)(d5) & 0x3FFFFFUL) << 4), \ 45 | (((uint32_t)d5) >> 22) | (((uint32_t)(d6) & 0xFFFFUL) << 10), \ 46 | (((uint32_t)d6) >> 16) | (((uint32_t)(d7) & 0x3FFUL) << 16), \ 47 | (((uint32_t)d7) >> 10) \ 48 | } 49 | 50 | typedef struct { 51 | uint32_t n[8]; 52 | } secp256k1_fe_storage; 53 | 54 | #define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }} 55 | #define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0] 56 | 57 | #endif /* SECP256K1_FIELD_REPR_H */ 58 | -------------------------------------------------------------------------------- /src/field_5x52.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_FIELD_REPR_H 8 | #define SECP256K1_FIELD_REPR_H 9 | 10 | #include 11 | 12 | /** This field implementation represents the value as 5 uint64_t limbs in base 13 | * 2^52. */ 14 | typedef struct { 15 | /* A field element f represents the sum(i=0..4, f.n[i] << (i*52)) mod p, 16 | * where p is the field modulus, 2^256 - 2^32 - 977. 17 | * 18 | * The individual limbs f.n[i] can exceed 2^52; the field's magnitude roughly 19 | * corresponds to how much excess is allowed. The value 20 | * sum(i=0..4, f.n[i] << (i*52)) may exceed p, unless the field element is 21 | * normalized. */ 22 | uint64_t n[5]; 23 | /* 24 | * Magnitude m requires: 25 | * n[i] <= 2 * m * (2^52 - 1) for i=0..3 26 | * n[4] <= 2 * m * (2^48 - 1) 27 | * 28 | * Normalized requires: 29 | * n[i] <= (2^52 - 1) for i=0..3 30 | * sum(i=0..4, n[i] << (i*52)) < p 31 | * (together these imply n[4] <= 2^48 - 1) 32 | */ 33 | SECP256K1_FE_VERIFY_FIELDS 34 | } secp256k1_fe; 35 | 36 | /* Unpacks a constant into a overlapping multi-limbed FE element. */ 37 | #define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ 38 | (d0) | (((uint64_t)(d1) & 0xFFFFFUL) << 32), \ 39 | ((uint64_t)(d1) >> 20) | (((uint64_t)(d2)) << 12) | (((uint64_t)(d3) & 0xFFUL) << 44), \ 40 | ((uint64_t)(d3) >> 8) | (((uint64_t)(d4) & 0xFFFFFFFUL) << 24), \ 41 | ((uint64_t)(d4) >> 28) | (((uint64_t)(d5)) << 4) | (((uint64_t)(d6) & 0xFFFFUL) << 36), \ 42 | ((uint64_t)(d6) >> 16) | (((uint64_t)(d7)) << 16) \ 43 | } 44 | 45 | typedef struct { 46 | uint64_t n[4]; 47 | } secp256k1_fe_storage; 48 | 49 | #define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ \ 50 | (d0) | (((uint64_t)(d1)) << 32), \ 51 | (d2) | (((uint64_t)(d3)) << 32), \ 52 | (d4) | (((uint64_t)(d5)) << 32), \ 53 | (d6) | (((uint64_t)(d7)) << 32) \ 54 | }} 55 | 56 | #define SECP256K1_FE_STORAGE_CONST_GET(d) \ 57 | (uint32_t)(d.n[3] >> 32), (uint32_t)d.n[3], \ 58 | (uint32_t)(d.n[2] >> 32), (uint32_t)d.n[2], \ 59 | (uint32_t)(d.n[1] >> 32), (uint32_t)d.n[1], \ 60 | (uint32_t)(d.n[0] >> 32), (uint32_t)d.n[0] 61 | 62 | #endif /* SECP256K1_FIELD_REPR_H */ 63 | -------------------------------------------------------------------------------- /src/hash.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_HASH_H 8 | #define SECP256K1_HASH_H 9 | 10 | #include 11 | #include 12 | 13 | typedef struct { 14 | uint32_t s[8]; 15 | unsigned char buf[64]; 16 | uint64_t bytes; 17 | } secp256k1_sha256; 18 | 19 | static void secp256k1_sha256_initialize(secp256k1_sha256 *hash); 20 | static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size); 21 | static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32); 22 | static void secp256k1_sha256_clear(secp256k1_sha256 *hash); 23 | 24 | typedef struct { 25 | secp256k1_sha256 inner, outer; 26 | } secp256k1_hmac_sha256; 27 | 28 | static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size); 29 | static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size); 30 | static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32); 31 | static void secp256k1_hmac_sha256_clear(secp256k1_hmac_sha256 *hash); 32 | 33 | typedef struct { 34 | unsigned char v[32]; 35 | unsigned char k[32]; 36 | int retry; 37 | } secp256k1_rfc6979_hmac_sha256; 38 | 39 | static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen); 40 | static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen); 41 | static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng); 42 | static void secp256k1_rfc6979_hmac_sha256_clear(secp256k1_rfc6979_hmac_sha256 *rng); 43 | 44 | #endif /* SECP256K1_HASH_H */ 45 | -------------------------------------------------------------------------------- /src/hsort.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2021 Russell O'Connor, Jonas Nick * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_HSORT_H 8 | #define SECP256K1_HSORT_H 9 | 10 | #include 11 | #include 12 | 13 | /* In-place, iterative heapsort with an interface matching glibc's qsort_r. This 14 | * is preferred over standard library implementations because they generally 15 | * make no guarantee about being fast for malicious inputs. 16 | * Remember that heapsort is unstable. 17 | * 18 | * In/Out: ptr: pointer to the array to sort. The contents of the array are 19 | * sorted in ascending order according to the comparison function. 20 | * In: count: number of elements in the array. 21 | * size: size in bytes of each element. 22 | * cmp: pointer to a comparison function that is called with two 23 | * arguments that point to the objects being compared. The cmp_data 24 | * argument of secp256k1_hsort is passed as third argument. The 25 | * function must return an integer less than, equal to, or greater 26 | * than zero if the first argument is considered to be respectively 27 | * less than, equal to, or greater than the second. 28 | * cmp_data: pointer passed as third argument to cmp. 29 | */ 30 | static void secp256k1_hsort(void *ptr, size_t count, size_t size, 31 | int (*cmp)(const void *, const void *, void *), 32 | void *cmp_data); 33 | #endif 34 | -------------------------------------------------------------------------------- /src/hsort_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2021 Russell O'Connor, Jonas Nick * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_HSORT_IMPL_H 8 | #define SECP256K1_HSORT_IMPL_H 9 | 10 | #include "hsort.h" 11 | 12 | /* An array is a heap when, for all non-zero indexes i, the element at index i 13 | * compares as less than or equal to the element at index parent(i) = (i-1)/2. 14 | */ 15 | 16 | static SECP256K1_INLINE size_t secp256k1_heap_child1(size_t i) { 17 | VERIFY_CHECK(i <= (SIZE_MAX - 1)/2); 18 | return 2*i + 1; 19 | } 20 | 21 | static SECP256K1_INLINE size_t secp256k1_heap_child2(size_t i) { 22 | VERIFY_CHECK(i <= SIZE_MAX/2 - 1); 23 | return secp256k1_heap_child1(i)+1; 24 | } 25 | 26 | static SECP256K1_INLINE void secp256k1_heap_swap64(unsigned char *a, unsigned char *b, size_t len) { 27 | unsigned char tmp[64]; 28 | VERIFY_CHECK(len <= 64); 29 | memcpy(tmp, a, len); 30 | memmove(a, b, len); 31 | memcpy(b, tmp, len); 32 | } 33 | 34 | static SECP256K1_INLINE void secp256k1_heap_swap(unsigned char *arr, size_t i, size_t j, size_t stride) { 35 | unsigned char *a = arr + i*stride; 36 | unsigned char *b = arr + j*stride; 37 | size_t len = stride; 38 | while (64 < len) { 39 | secp256k1_heap_swap64(a + (len - 64), b + (len - 64), 64); 40 | len -= 64; 41 | } 42 | secp256k1_heap_swap64(a, b, len); 43 | } 44 | 45 | /* This function accepts an array arr containing heap_size elements, each of 46 | * size stride. The elements in the array at indices >i satisfy the max-heap 47 | * property, i.e., for any element at index j (where j > i), all of its children 48 | * are smaller than the element itself. The purpose of the function is to update 49 | * the array so that all elements at indices >=i satisfy the max-heap 50 | * property. */ 51 | static SECP256K1_INLINE void secp256k1_heap_down(unsigned char *arr, size_t i, size_t heap_size, size_t stride, 52 | int (*cmp)(const void *, const void *, void *), void *cmp_data) { 53 | while (i < heap_size/2) { 54 | VERIFY_CHECK(i <= SIZE_MAX/2 - 1); 55 | /* Proof: 56 | * i < heap_size/2 57 | * i + 1 <= heap_size/2 58 | * 2*i + 2 <= heap_size <= SIZE_MAX 59 | * 2*i <= SIZE_MAX - 2 60 | */ 61 | 62 | VERIFY_CHECK(secp256k1_heap_child1(i) < heap_size); 63 | /* Proof: 64 | * i < heap_size/2 65 | * i + 1 <= heap_size/2 66 | * 2*i + 2 <= heap_size 67 | * 2*i + 1 < heap_size 68 | * child1(i) < heap_size 69 | */ 70 | 71 | /* Let [x] be notation for the contents at arr[x*stride]. 72 | * 73 | * If [child1(i)] > [i] and [child2(i)] > [i], 74 | * swap [i] with the larger child to ensure the new parent is larger 75 | * than both children. When [child1(i)] == [child2(i)], swap [i] with 76 | * [child2(i)]. 77 | * Else if [child1(i)] > [i], swap [i] with [child1(i)]. 78 | * Else if [child2(i)] > [i], swap [i] with [child2(i)]. 79 | */ 80 | if (secp256k1_heap_child2(i) < heap_size 81 | && 0 <= cmp(arr + secp256k1_heap_child2(i)*stride, arr + secp256k1_heap_child1(i)*stride, cmp_data)) { 82 | if (0 < cmp(arr + secp256k1_heap_child2(i)*stride, arr + i*stride, cmp_data)) { 83 | secp256k1_heap_swap(arr, i, secp256k1_heap_child2(i), stride); 84 | i = secp256k1_heap_child2(i); 85 | } else { 86 | /* At this point we have [child2(i)] >= [child1(i)] and we have 87 | * [child2(i)] <= [i], and thus [child1(i)] <= [i] which means 88 | * that the next comparison can be skipped. */ 89 | return; 90 | } 91 | } else if (0 < cmp(arr + secp256k1_heap_child1(i)*stride, arr + i*stride, cmp_data)) { 92 | secp256k1_heap_swap(arr, i, secp256k1_heap_child1(i), stride); 93 | i = secp256k1_heap_child1(i); 94 | } else { 95 | return; 96 | } 97 | } 98 | /* heap_size/2 <= i 99 | * heap_size/2 < i + 1 100 | * heap_size < 2*i + 2 101 | * heap_size <= 2*i + 1 102 | * heap_size <= child1(i) 103 | * Thus child1(i) and child2(i) are now out of bounds and we are at a leaf. 104 | */ 105 | } 106 | 107 | /* In-place heap sort. */ 108 | static void secp256k1_hsort(void *ptr, size_t count, size_t size, 109 | int (*cmp)(const void *, const void *, void *), 110 | void *cmp_data) { 111 | size_t i; 112 | 113 | for (i = count/2; 0 < i; --i) { 114 | secp256k1_heap_down(ptr, i-1, count, size, cmp, cmp_data); 115 | } 116 | for (i = count; 1 < i; --i) { 117 | /* Extract the largest value from the heap */ 118 | secp256k1_heap_swap(ptr, 0, i-1, size); 119 | 120 | /* Repair the heap condition */ 121 | secp256k1_heap_down(ptr, 0, i-1, size, cmp, cmp_data); 122 | } 123 | } 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /src/int128.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_INT128_H 2 | #define SECP256K1_INT128_H 3 | 4 | #include "util.h" 5 | 6 | #if defined(SECP256K1_WIDEMUL_INT128) 7 | # if defined(SECP256K1_INT128_NATIVE) 8 | # include "int128_native.h" 9 | # elif defined(SECP256K1_INT128_STRUCT) 10 | # include "int128_struct.h" 11 | # else 12 | # error "Please select int128 implementation" 13 | # endif 14 | 15 | /* Construct an unsigned 128-bit value from a high and a low 64-bit value. */ 16 | static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo); 17 | 18 | /* Multiply two unsigned 64-bit values a and b and write the result to r. */ 19 | static SECP256K1_INLINE void secp256k1_u128_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b); 20 | 21 | /* Multiply two unsigned 64-bit values a and b and add the result to r. 22 | * The final result is taken modulo 2^128. 23 | */ 24 | static SECP256K1_INLINE void secp256k1_u128_accum_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b); 25 | 26 | /* Add an unsigned 64-bit value a to r. 27 | * The final result is taken modulo 2^128. 28 | */ 29 | static SECP256K1_INLINE void secp256k1_u128_accum_u64(secp256k1_uint128 *r, uint64_t a); 30 | 31 | /* Unsigned (logical) right shift. 32 | * Non-constant time in n. 33 | */ 34 | static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigned int n); 35 | 36 | /* Return the low 64-bits of a 128-bit value as an unsigned 64-bit value. */ 37 | static SECP256K1_INLINE uint64_t secp256k1_u128_to_u64(const secp256k1_uint128 *a); 38 | 39 | /* Return the high 64-bits of a 128-bit value as an unsigned 64-bit value. */ 40 | static SECP256K1_INLINE uint64_t secp256k1_u128_hi_u64(const secp256k1_uint128 *a); 41 | 42 | /* Write an unsigned 64-bit value to r. */ 43 | static SECP256K1_INLINE void secp256k1_u128_from_u64(secp256k1_uint128 *r, uint64_t a); 44 | 45 | /* Tests if r is strictly less than to 2^n. 46 | * n must be strictly less than 128. 47 | */ 48 | static SECP256K1_INLINE int secp256k1_u128_check_bits(const secp256k1_uint128 *r, unsigned int n); 49 | 50 | /* Construct an signed 128-bit value from a high and a low 64-bit value. */ 51 | static SECP256K1_INLINE void secp256k1_i128_load(secp256k1_int128 *r, int64_t hi, uint64_t lo); 52 | 53 | /* Multiply two signed 64-bit values a and b and write the result to r. */ 54 | static SECP256K1_INLINE void secp256k1_i128_mul(secp256k1_int128 *r, int64_t a, int64_t b); 55 | 56 | /* Multiply two signed 64-bit values a and b and add the result to r. 57 | * Overflow or underflow from the addition is undefined behaviour. 58 | */ 59 | static SECP256K1_INLINE void secp256k1_i128_accum_mul(secp256k1_int128 *r, int64_t a, int64_t b); 60 | 61 | /* Compute a*d - b*c from signed 64-bit values and write the result to r. */ 62 | static SECP256K1_INLINE void secp256k1_i128_det(secp256k1_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d); 63 | 64 | /* Signed (arithmetic) right shift. 65 | * Non-constant time in b. 66 | */ 67 | static SECP256K1_INLINE void secp256k1_i128_rshift(secp256k1_int128 *r, unsigned int b); 68 | 69 | /* Return the input value modulo 2^64. */ 70 | static SECP256K1_INLINE uint64_t secp256k1_i128_to_u64(const secp256k1_int128 *a); 71 | 72 | /* Return the value as a signed 64-bit value. 73 | * Requires the input to be between INT64_MIN and INT64_MAX. 74 | */ 75 | static SECP256K1_INLINE int64_t secp256k1_i128_to_i64(const secp256k1_int128 *a); 76 | 77 | /* Write a signed 64-bit value to r. */ 78 | static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_t a); 79 | 80 | /* Compare two 128-bit values for equality. */ 81 | static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b); 82 | 83 | /* Tests if r is equal to sign*2^n (sign must be 1 or -1). 84 | * n must be strictly less than 127. 85 | */ 86 | static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n, int sign); 87 | 88 | #endif 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /src/int128_impl.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_INT128_IMPL_H 2 | #define SECP256K1_INT128_IMPL_H 3 | 4 | #include "util.h" 5 | 6 | #include "int128.h" 7 | 8 | #if defined(SECP256K1_WIDEMUL_INT128) 9 | # if defined(SECP256K1_INT128_NATIVE) 10 | # include "int128_native_impl.h" 11 | # elif defined(SECP256K1_INT128_STRUCT) 12 | # include "int128_struct_impl.h" 13 | # else 14 | # error "Please select int128 implementation" 15 | # endif 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/int128_native.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_INT128_NATIVE_H 2 | #define SECP256K1_INT128_NATIVE_H 3 | 4 | #include 5 | #include "util.h" 6 | 7 | #if !defined(UINT128_MAX) && defined(__SIZEOF_INT128__) 8 | SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t; 9 | SECP256K1_GNUC_EXT typedef __int128 int128_t; 10 | # define UINT128_MAX ((uint128_t)(-1)) 11 | # define INT128_MAX ((int128_t)(UINT128_MAX >> 1)) 12 | # define INT128_MIN (-INT128_MAX - 1) 13 | /* No (U)INT128_C macros because compilers providing __int128 do not support 128-bit literals. */ 14 | #endif 15 | 16 | typedef uint128_t secp256k1_uint128; 17 | typedef int128_t secp256k1_int128; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/int128_native_impl.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_INT128_NATIVE_IMPL_H 2 | #define SECP256K1_INT128_NATIVE_IMPL_H 3 | 4 | #include "int128.h" 5 | #include "util.h" 6 | 7 | static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo) { 8 | *r = (((uint128_t)hi) << 64) + lo; 9 | } 10 | 11 | static SECP256K1_INLINE void secp256k1_u128_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) { 12 | *r = (uint128_t)a * b; 13 | } 14 | 15 | static SECP256K1_INLINE void secp256k1_u128_accum_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) { 16 | *r += (uint128_t)a * b; 17 | } 18 | 19 | static SECP256K1_INLINE void secp256k1_u128_accum_u64(secp256k1_uint128 *r, uint64_t a) { 20 | *r += a; 21 | } 22 | 23 | static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigned int n) { 24 | VERIFY_CHECK(n < 128); 25 | *r >>= n; 26 | } 27 | 28 | static SECP256K1_INLINE uint64_t secp256k1_u128_to_u64(const secp256k1_uint128 *a) { 29 | return (uint64_t)(*a); 30 | } 31 | 32 | static SECP256K1_INLINE uint64_t secp256k1_u128_hi_u64(const secp256k1_uint128 *a) { 33 | return (uint64_t)(*a >> 64); 34 | } 35 | 36 | static SECP256K1_INLINE void secp256k1_u128_from_u64(secp256k1_uint128 *r, uint64_t a) { 37 | *r = a; 38 | } 39 | 40 | static SECP256K1_INLINE int secp256k1_u128_check_bits(const secp256k1_uint128 *r, unsigned int n) { 41 | VERIFY_CHECK(n < 128); 42 | return (*r >> n == 0); 43 | } 44 | 45 | static SECP256K1_INLINE void secp256k1_i128_load(secp256k1_int128 *r, int64_t hi, uint64_t lo) { 46 | *r = (((uint128_t)(uint64_t)hi) << 64) + lo; 47 | } 48 | 49 | static SECP256K1_INLINE void secp256k1_i128_mul(secp256k1_int128 *r, int64_t a, int64_t b) { 50 | *r = (int128_t)a * b; 51 | } 52 | 53 | static SECP256K1_INLINE void secp256k1_i128_accum_mul(secp256k1_int128 *r, int64_t a, int64_t b) { 54 | int128_t ab = (int128_t)a * b; 55 | VERIFY_CHECK(0 <= ab ? *r <= INT128_MAX - ab : INT128_MIN - ab <= *r); 56 | *r += ab; 57 | } 58 | 59 | static SECP256K1_INLINE void secp256k1_i128_det(secp256k1_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d) { 60 | int128_t ad = (int128_t)a * d; 61 | int128_t bc = (int128_t)b * c; 62 | VERIFY_CHECK(0 <= bc ? INT128_MIN + bc <= ad : ad <= INT128_MAX + bc); 63 | *r = ad - bc; 64 | } 65 | 66 | static SECP256K1_INLINE void secp256k1_i128_rshift(secp256k1_int128 *r, unsigned int n) { 67 | VERIFY_CHECK(n < 128); 68 | *r >>= n; 69 | } 70 | 71 | static SECP256K1_INLINE uint64_t secp256k1_i128_to_u64(const secp256k1_int128 *a) { 72 | return (uint64_t)*a; 73 | } 74 | 75 | static SECP256K1_INLINE int64_t secp256k1_i128_to_i64(const secp256k1_int128 *a) { 76 | VERIFY_CHECK(INT64_MIN <= *a && *a <= INT64_MAX); 77 | return *a; 78 | } 79 | 80 | static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_t a) { 81 | *r = a; 82 | } 83 | 84 | static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b) { 85 | return *a == *b; 86 | } 87 | 88 | static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n, int sign) { 89 | VERIFY_CHECK(n < 127); 90 | VERIFY_CHECK(sign == 1 || sign == -1); 91 | return (*r == (int128_t)((uint128_t)sign << n)); 92 | } 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /src/int128_struct.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_INT128_STRUCT_H 2 | #define SECP256K1_INT128_STRUCT_H 3 | 4 | #include 5 | #include "util.h" 6 | 7 | typedef struct { 8 | uint64_t lo; 9 | uint64_t hi; 10 | } secp256k1_uint128; 11 | 12 | typedef secp256k1_uint128 secp256k1_int128; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/modinv32.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2020 Peter Dettman * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODINV32_H 8 | #define SECP256K1_MODINV32_H 9 | 10 | #include "util.h" 11 | 12 | /* A signed 30-bit limb representation of integers. 13 | * 14 | * Its value is sum(v[i] * 2^(30*i), i=0..8). */ 15 | typedef struct { 16 | int32_t v[9]; 17 | } secp256k1_modinv32_signed30; 18 | 19 | typedef struct { 20 | /* The modulus in signed30 notation, must be odd and in [3, 2^256]. */ 21 | secp256k1_modinv32_signed30 modulus; 22 | 23 | /* modulus^{-1} mod 2^30 */ 24 | uint32_t modulus_inv30; 25 | } secp256k1_modinv32_modinfo; 26 | 27 | /* Replace x with its modular inverse mod modinfo->modulus. x must be in range [0, modulus). 28 | * If x is zero, the result will be zero as well. If not, the inverse must exist (i.e., the gcd of 29 | * x and modulus must be 1). These rules are automatically satisfied if the modulus is prime. 30 | * 31 | * On output, all of x's limbs will be in [0, 2^30). 32 | */ 33 | static void secp256k1_modinv32_var(secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo); 34 | 35 | /* Same as secp256k1_modinv32_var, but constant time in x (not in the modulus). */ 36 | static void secp256k1_modinv32(secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo); 37 | 38 | /* Compute the Jacobi symbol for (x | modinfo->modulus). x must be coprime with modulus (and thus 39 | * cannot be 0, as modulus >= 3). All limbs of x must be non-negative. Returns 0 if the result 40 | * cannot be computed. */ 41 | static int secp256k1_jacobi32_maybe_var(const secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo); 42 | 43 | #endif /* SECP256K1_MODINV32_H */ 44 | -------------------------------------------------------------------------------- /src/modinv64.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2020 Peter Dettman * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODINV64_H 8 | #define SECP256K1_MODINV64_H 9 | 10 | #include "util.h" 11 | 12 | #ifndef SECP256K1_WIDEMUL_INT128 13 | #error "modinv64 requires 128-bit wide multiplication support" 14 | #endif 15 | 16 | /* A signed 62-bit limb representation of integers. 17 | * 18 | * Its value is sum(v[i] * 2^(62*i), i=0..4). */ 19 | typedef struct { 20 | int64_t v[5]; 21 | } secp256k1_modinv64_signed62; 22 | 23 | typedef struct { 24 | /* The modulus in signed62 notation, must be odd and in [3, 2^256]. */ 25 | secp256k1_modinv64_signed62 modulus; 26 | 27 | /* modulus^{-1} mod 2^62 */ 28 | uint64_t modulus_inv62; 29 | } secp256k1_modinv64_modinfo; 30 | 31 | /* Replace x with its modular inverse mod modinfo->modulus. x must be in range [0, modulus). 32 | * If x is zero, the result will be zero as well. If not, the inverse must exist (i.e., the gcd of 33 | * x and modulus must be 1). These rules are automatically satisfied if the modulus is prime. 34 | * 35 | * On output, all of x's limbs will be in [0, 2^62). 36 | */ 37 | static void secp256k1_modinv64_var(secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo); 38 | 39 | /* Same as secp256k1_modinv64_var, but constant time in x (not in the modulus). */ 40 | static void secp256k1_modinv64(secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo); 41 | 42 | /* Compute the Jacobi symbol for (x | modinfo->modulus). x must be coprime with modulus (and thus 43 | * cannot be 0, as modulus >= 3). All limbs of x must be non-negative. Returns 0 if the result 44 | * cannot be computed. */ 45 | static int secp256k1_jacobi64_maybe_var(const secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo); 46 | 47 | #endif /* SECP256K1_MODINV64_H */ 48 | -------------------------------------------------------------------------------- /src/modules/ecdh/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_ecdh.h 2 | noinst_HEADERS += src/modules/ecdh/main_impl.h 3 | noinst_HEADERS += src/modules/ecdh/tests_impl.h 4 | noinst_HEADERS += src/modules/ecdh/bench_impl.h 5 | noinst_HEADERS += src/wycheproof/ecdh_secp256k1_test.h 6 | -------------------------------------------------------------------------------- /src/modules/ecdh/bench_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODULE_ECDH_BENCH_H 8 | #define SECP256K1_MODULE_ECDH_BENCH_H 9 | 10 | #include "../../../include/secp256k1_ecdh.h" 11 | 12 | typedef struct { 13 | secp256k1_context *ctx; 14 | secp256k1_pubkey point; 15 | unsigned char scalar[32]; 16 | } bench_ecdh_data; 17 | 18 | static void bench_ecdh_setup(void* arg) { 19 | int i; 20 | bench_ecdh_data *data = (bench_ecdh_data*)arg; 21 | const unsigned char point[] = { 22 | 0x03, 23 | 0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06, 24 | 0xc2, 0x39, 0x5f, 0x94, 0x34, 0x87, 0x45, 0xfd, 25 | 0x75, 0x7c, 0xe3, 0x0e, 0x4e, 0x8c, 0x90, 0xfb, 26 | 0xa2, 0xba, 0xd1, 0x84, 0xf8, 0x83, 0xc6, 0x9f 27 | }; 28 | 29 | for (i = 0; i < 32; i++) { 30 | data->scalar[i] = i + 1; 31 | } 32 | CHECK(secp256k1_ec_pubkey_parse(data->ctx, &data->point, point, sizeof(point)) == 1); 33 | } 34 | 35 | static void bench_ecdh(void* arg, int iters) { 36 | int i; 37 | unsigned char res[32]; 38 | bench_ecdh_data *data = (bench_ecdh_data*)arg; 39 | 40 | for (i = 0; i < iters; i++) { 41 | CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar, NULL, NULL) == 1); 42 | } 43 | } 44 | 45 | static void run_ecdh_bench(int iters, int argc, char** argv) { 46 | bench_ecdh_data data; 47 | int d = argc == 1; 48 | 49 | /* create a context with no capabilities */ 50 | data.ctx = secp256k1_context_create(SECP256K1_FLAGS_TYPE_CONTEXT); 51 | 52 | if (d || have_flag(argc, argv, "ecdh")) run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, iters); 53 | 54 | secp256k1_context_destroy(data.ctx); 55 | } 56 | 57 | #endif /* SECP256K1_MODULE_ECDH_BENCH_H */ 58 | -------------------------------------------------------------------------------- /src/modules/ecdh/main_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2015 Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODULE_ECDH_MAIN_H 8 | #define SECP256K1_MODULE_ECDH_MAIN_H 9 | 10 | #include "../../../include/secp256k1_ecdh.h" 11 | #include "../../ecmult_const_impl.h" 12 | 13 | static int ecdh_hash_function_sha256(unsigned char *output, const unsigned char *x32, const unsigned char *y32, void *data) { 14 | unsigned char version = (y32[31] & 0x01) | 0x02; 15 | secp256k1_sha256 sha; 16 | (void)data; 17 | 18 | secp256k1_sha256_initialize(&sha); 19 | secp256k1_sha256_write(&sha, &version, 1); 20 | secp256k1_sha256_write(&sha, x32, 32); 21 | secp256k1_sha256_finalize(&sha, output); 22 | secp256k1_sha256_clear(&sha); 23 | 24 | return 1; 25 | } 26 | 27 | const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256 = ecdh_hash_function_sha256; 28 | const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default = ecdh_hash_function_sha256; 29 | 30 | int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const secp256k1_pubkey *point, const unsigned char *scalar, secp256k1_ecdh_hash_function hashfp, void *data) { 31 | int ret = 0; 32 | int overflow = 0; 33 | secp256k1_gej res; 34 | secp256k1_ge pt; 35 | secp256k1_scalar s; 36 | unsigned char x[32]; 37 | unsigned char y[32]; 38 | 39 | VERIFY_CHECK(ctx != NULL); 40 | ARG_CHECK(output != NULL); 41 | ARG_CHECK(point != NULL); 42 | ARG_CHECK(scalar != NULL); 43 | 44 | if (hashfp == NULL) { 45 | hashfp = secp256k1_ecdh_hash_function_default; 46 | } 47 | 48 | secp256k1_pubkey_load(ctx, &pt, point); 49 | secp256k1_scalar_set_b32(&s, scalar, &overflow); 50 | 51 | overflow |= secp256k1_scalar_is_zero(&s); 52 | secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, overflow); 53 | 54 | secp256k1_ecmult_const(&res, &pt, &s); 55 | secp256k1_ge_set_gej(&pt, &res); 56 | 57 | /* Compute a hash of the point */ 58 | secp256k1_fe_normalize(&pt.x); 59 | secp256k1_fe_normalize(&pt.y); 60 | secp256k1_fe_get_b32(x, &pt.x); 61 | secp256k1_fe_get_b32(y, &pt.y); 62 | 63 | ret = hashfp(output, x, y, data); 64 | 65 | secp256k1_memclear(x, sizeof(x)); 66 | secp256k1_memclear(y, sizeof(y)); 67 | secp256k1_scalar_clear(&s); 68 | secp256k1_ge_clear(&pt); 69 | secp256k1_gej_clear(&res); 70 | 71 | return !!ret & !overflow; 72 | } 73 | 74 | #endif /* SECP256K1_MODULE_ECDH_MAIN_H */ 75 | -------------------------------------------------------------------------------- /src/modules/ellswift/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_ellswift.h 2 | noinst_HEADERS += src/modules/ellswift/bench_impl.h 3 | noinst_HEADERS += src/modules/ellswift/main_impl.h 4 | noinst_HEADERS += src/modules/ellswift/tests_impl.h 5 | noinst_HEADERS += src/modules/ellswift/tests_exhaustive_impl.h 6 | -------------------------------------------------------------------------------- /src/modules/ellswift/bench_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Distributed under the MIT software license, see the accompanying * 3 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 4 | ***********************************************************************/ 5 | 6 | #ifndef SECP256K1_MODULE_ELLSWIFT_BENCH_H 7 | #define SECP256K1_MODULE_ELLSWIFT_BENCH_H 8 | 9 | #include "../../../include/secp256k1_ellswift.h" 10 | 11 | typedef struct { 12 | secp256k1_context *ctx; 13 | secp256k1_pubkey point[256]; 14 | unsigned char rnd64[64]; 15 | } bench_ellswift_data; 16 | 17 | static void bench_ellswift_setup(void *arg) { 18 | int i; 19 | bench_ellswift_data *data = (bench_ellswift_data*)arg; 20 | static const unsigned char init[64] = { 21 | 0x78, 0x1f, 0xb7, 0xd4, 0x67, 0x7f, 0x08, 0x68, 22 | 0xdb, 0xe3, 0x1d, 0x7f, 0x1b, 0xb0, 0xf6, 0x9e, 23 | 0x0a, 0x64, 0xca, 0x32, 0x9e, 0xc6, 0x20, 0x79, 24 | 0x03, 0xf3, 0xd0, 0x46, 0x7a, 0x0f, 0xd2, 0x21, 25 | 0xb0, 0x2c, 0x46, 0xd8, 0xba, 0xca, 0x26, 0x4f, 26 | 0x8f, 0x8c, 0xd4, 0xdd, 0x2d, 0x04, 0xbe, 0x30, 27 | 0x48, 0x51, 0x1e, 0xd4, 0x16, 0xfd, 0x42, 0x85, 28 | 0x62, 0xc9, 0x02, 0xf9, 0x89, 0x84, 0xff, 0xdc 29 | }; 30 | memcpy(data->rnd64, init, 64); 31 | for (i = 0; i < 256; ++i) { 32 | int j; 33 | CHECK(secp256k1_ellswift_decode(data->ctx, &data->point[i], data->rnd64)); 34 | for (j = 0; j < 64; ++j) { 35 | data->rnd64[j] += 1; 36 | } 37 | } 38 | CHECK(secp256k1_ellswift_encode(data->ctx, data->rnd64, &data->point[255], init + 16)); 39 | } 40 | 41 | static void bench_ellswift_encode(void *arg, int iters) { 42 | int i; 43 | bench_ellswift_data *data = (bench_ellswift_data*)arg; 44 | 45 | for (i = 0; i < iters; i++) { 46 | CHECK(secp256k1_ellswift_encode(data->ctx, data->rnd64, &data->point[i & 255], data->rnd64 + 16)); 47 | } 48 | } 49 | 50 | static void bench_ellswift_create(void *arg, int iters) { 51 | int i; 52 | bench_ellswift_data *data = (bench_ellswift_data*)arg; 53 | 54 | for (i = 0; i < iters; i++) { 55 | unsigned char buf[64]; 56 | CHECK(secp256k1_ellswift_create(data->ctx, buf, data->rnd64, data->rnd64 + 32)); 57 | memcpy(data->rnd64, buf, 64); 58 | } 59 | } 60 | 61 | static void bench_ellswift_decode(void *arg, int iters) { 62 | int i; 63 | secp256k1_pubkey out; 64 | size_t len; 65 | bench_ellswift_data *data = (bench_ellswift_data*)arg; 66 | 67 | for (i = 0; i < iters; i++) { 68 | CHECK(secp256k1_ellswift_decode(data->ctx, &out, data->rnd64) == 1); 69 | len = 33; 70 | CHECK(secp256k1_ec_pubkey_serialize(data->ctx, data->rnd64 + (i % 32), &len, &out, SECP256K1_EC_COMPRESSED)); 71 | } 72 | } 73 | 74 | static void bench_ellswift_xdh(void *arg, int iters) { 75 | int i; 76 | bench_ellswift_data *data = (bench_ellswift_data*)arg; 77 | 78 | for (i = 0; i < iters; i++) { 79 | int party = i & 1; 80 | CHECK(secp256k1_ellswift_xdh(data->ctx, 81 | data->rnd64 + (i % 33), 82 | data->rnd64, 83 | data->rnd64, 84 | data->rnd64 + ((i + 16) % 33), 85 | party, 86 | secp256k1_ellswift_xdh_hash_function_bip324, 87 | NULL) == 1); 88 | } 89 | } 90 | 91 | void run_ellswift_bench(int iters, int argc, char **argv) { 92 | bench_ellswift_data data; 93 | int d = argc == 1; 94 | 95 | /* create a context with signing capabilities */ 96 | data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); 97 | 98 | 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); 99 | 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); 100 | 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); 101 | 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); 102 | 103 | secp256k1_context_destroy(data.ctx); 104 | } 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /src/modules/ellswift/tests_exhaustive_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Distributed under the MIT software license, see the accompanying * 3 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 4 | ***********************************************************************/ 5 | 6 | #ifndef SECP256K1_MODULE_ELLSWIFT_TESTS_EXHAUSTIVE_H 7 | #define SECP256K1_MODULE_ELLSWIFT_TESTS_EXHAUSTIVE_H 8 | 9 | #include "../../../include/secp256k1_ellswift.h" 10 | #include "main_impl.h" 11 | 12 | static void test_exhaustive_ellswift(const secp256k1_context *ctx, const secp256k1_ge *group) { 13 | int i; 14 | 15 | /* Note that SwiftEC/ElligatorSwift are inherently curve operations, not 16 | * group operations, and this test only checks the curve points which are in 17 | * a tiny subgroup. In that sense it can't be really seen as exhaustive as 18 | * it doesn't (and for computational reasons obviously cannot) test the 19 | * entire domain ellswift operates under. */ 20 | for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { 21 | secp256k1_scalar scalar_i; 22 | unsigned char sec32[32]; 23 | unsigned char ell64[64]; 24 | secp256k1_pubkey pub_decoded; 25 | secp256k1_ge ge_decoded; 26 | 27 | /* Construct ellswift pubkey from exhaustive loop scalar i. */ 28 | secp256k1_scalar_set_int(&scalar_i, i); 29 | secp256k1_scalar_get_b32(sec32, &scalar_i); 30 | CHECK(secp256k1_ellswift_create(ctx, ell64, sec32, NULL)); 31 | 32 | /* Decode ellswift pubkey and check that it matches the precomputed group element. */ 33 | secp256k1_ellswift_decode(ctx, &pub_decoded, ell64); 34 | secp256k1_pubkey_load(ctx, &ge_decoded, &pub_decoded); 35 | CHECK(secp256k1_ge_eq_var(&ge_decoded, &group[i])); 36 | } 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/modules/extrakeys/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_extrakeys.h 2 | noinst_HEADERS += src/modules/extrakeys/tests_impl.h 3 | noinst_HEADERS += src/modules/extrakeys/tests_exhaustive_impl.h 4 | noinst_HEADERS += src/modules/extrakeys/main_impl.h 5 | -------------------------------------------------------------------------------- /src/modules/extrakeys/tests_exhaustive_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2020 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODULE_EXTRAKEYS_TESTS_EXHAUSTIVE_H 8 | #define SECP256K1_MODULE_EXTRAKEYS_TESTS_EXHAUSTIVE_H 9 | 10 | #include "../../../include/secp256k1_extrakeys.h" 11 | #include "main_impl.h" 12 | 13 | static void test_exhaustive_extrakeys(const secp256k1_context *ctx, const secp256k1_ge* group) { 14 | secp256k1_keypair keypair[EXHAUSTIVE_TEST_ORDER - 1]; 15 | secp256k1_pubkey pubkey[EXHAUSTIVE_TEST_ORDER - 1]; 16 | secp256k1_xonly_pubkey xonly_pubkey[EXHAUSTIVE_TEST_ORDER - 1]; 17 | int parities[EXHAUSTIVE_TEST_ORDER - 1]; 18 | unsigned char xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - 1][32]; 19 | int i; 20 | 21 | for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { 22 | secp256k1_fe fe; 23 | secp256k1_scalar scalar_i; 24 | unsigned char buf[33]; 25 | int parity; 26 | 27 | secp256k1_scalar_set_int(&scalar_i, i); 28 | secp256k1_scalar_get_b32(buf, &scalar_i); 29 | 30 | /* Construct pubkey and keypair. */ 31 | CHECK(secp256k1_keypair_create(ctx, &keypair[i - 1], buf)); 32 | CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey[i - 1], buf)); 33 | 34 | /* Construct serialized xonly_pubkey from keypair. */ 35 | CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pubkey[i - 1], &parities[i - 1], &keypair[i - 1])); 36 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, xonly_pubkey_bytes[i - 1], &xonly_pubkey[i - 1])); 37 | 38 | /* Parse the xonly_pubkey back and verify it matches the previously serialized value. */ 39 | CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pubkey[i - 1], xonly_pubkey_bytes[i - 1])); 40 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1])); 41 | CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0); 42 | 43 | /* Construct the xonly_pubkey from the pubkey, and verify it matches the same. */ 44 | CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pubkey[i - 1], &parity, &pubkey[i - 1])); 45 | CHECK(parity == parities[i - 1]); 46 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1])); 47 | CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0); 48 | 49 | /* Compare the xonly_pubkey bytes against the precomputed group. */ 50 | secp256k1_fe_set_b32_mod(&fe, xonly_pubkey_bytes[i - 1]); 51 | CHECK(secp256k1_fe_equal(&fe, &group[i].x)); 52 | 53 | /* Check the parity against the precomputed group. */ 54 | fe = group[i].y; 55 | secp256k1_fe_normalize_var(&fe); 56 | CHECK(secp256k1_fe_is_odd(&fe) == parities[i - 1]); 57 | 58 | /* Verify that the higher half is identical to the lower half mirrored. */ 59 | if (i > EXHAUSTIVE_TEST_ORDER / 2) { 60 | CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - i - 1], 32) == 0); 61 | CHECK(parities[i - 1] == 1 - parities[EXHAUSTIVE_TEST_ORDER - i - 1]); 62 | } 63 | } 64 | 65 | /* TODO: keypair/xonly_pubkey tweak tests */ 66 | } 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /src/modules/musig/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_musig.h 2 | noinst_HEADERS += src/modules/musig/main_impl.h 3 | noinst_HEADERS += src/modules/musig/keyagg.h 4 | noinst_HEADERS += src/modules/musig/keyagg_impl.h 5 | noinst_HEADERS += src/modules/musig/session.h 6 | noinst_HEADERS += src/modules/musig/session_impl.h 7 | noinst_HEADERS += src/modules/musig/tests_impl.h 8 | noinst_HEADERS += src/modules/musig/vectors.h 9 | -------------------------------------------------------------------------------- /src/modules/musig/keyagg.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Distributed under the MIT software license, see the accompanying * 3 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 4 | ***********************************************************************/ 5 | 6 | #ifndef SECP256K1_MODULE_MUSIG_KEYAGG_H 7 | #define SECP256K1_MODULE_MUSIG_KEYAGG_H 8 | 9 | #include "../../../include/secp256k1.h" 10 | #include "../../../include/secp256k1_musig.h" 11 | 12 | #include "../../group.h" 13 | #include "../../scalar.h" 14 | 15 | typedef struct { 16 | secp256k1_ge pk; 17 | /* If there is no "second" public key, second_pk is set to the point at 18 | * infinity */ 19 | secp256k1_ge second_pk; 20 | unsigned char pks_hash[32]; 21 | /* tweak is identical to value tacc[v] in the specification. */ 22 | secp256k1_scalar tweak; 23 | /* parity_acc corresponds to (1 - gacc[v])/2 in the spec. So if gacc[v] is 24 | * -1, parity_acc is 1. Otherwise, parity_acc is 0. */ 25 | int parity_acc; 26 | } secp256k1_keyagg_cache_internal; 27 | 28 | static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_keyagg_cache_internal *cache_i, const secp256k1_musig_keyagg_cache *cache); 29 | 30 | static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/modules/musig/main_impl.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Distributed under the MIT software license, see the accompanying * 3 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* 4 | **********************************************************************/ 5 | 6 | #ifndef SECP256K1_MODULE_MUSIG_MAIN_H 7 | #define SECP256K1_MODULE_MUSIG_MAIN_H 8 | 9 | #include "keyagg_impl.h" 10 | #include "session_impl.h" 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/modules/musig/session.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Distributed under the MIT software license, see the accompanying * 3 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 4 | ***********************************************************************/ 5 | 6 | #ifndef SECP256K1_MODULE_MUSIG_SESSION_H 7 | #define SECP256K1_MODULE_MUSIG_SESSION_H 8 | 9 | #include "../../../include/secp256k1.h" 10 | #include "../../../include/secp256k1_musig.h" 11 | 12 | #include "../../scalar.h" 13 | 14 | typedef struct { 15 | int fin_nonce_parity; 16 | unsigned char fin_nonce[32]; 17 | secp256k1_scalar noncecoef; 18 | secp256k1_scalar challenge; 19 | secp256k1_scalar s_part; 20 | } secp256k1_musig_session_internal; 21 | 22 | static int secp256k1_musig_session_load(const secp256k1_context* ctx, secp256k1_musig_session_internal *session_i, const secp256k1_musig_session *session); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/modules/recovery/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_recovery.h 2 | noinst_HEADERS += src/modules/recovery/main_impl.h 3 | noinst_HEADERS += src/modules/recovery/tests_impl.h 4 | noinst_HEADERS += src/modules/recovery/tests_exhaustive_impl.h 5 | noinst_HEADERS += src/modules/recovery/bench_impl.h 6 | -------------------------------------------------------------------------------- /src/modules/recovery/bench_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2014-2015 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODULE_RECOVERY_BENCH_H 8 | #define SECP256K1_MODULE_RECOVERY_BENCH_H 9 | 10 | #include "../../../include/secp256k1_recovery.h" 11 | 12 | typedef struct { 13 | secp256k1_context *ctx; 14 | unsigned char msg[32]; 15 | unsigned char sig[64]; 16 | } bench_recover_data; 17 | 18 | static void bench_recover(void* arg, int iters) { 19 | int i; 20 | bench_recover_data *data = (bench_recover_data*)arg; 21 | secp256k1_pubkey pubkey; 22 | unsigned char pubkeyc[33]; 23 | 24 | for (i = 0; i < iters; i++) { 25 | int j; 26 | size_t pubkeylen = 33; 27 | secp256k1_ecdsa_recoverable_signature sig; 28 | CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(data->ctx, &sig, data->sig, i % 2)); 29 | CHECK(secp256k1_ecdsa_recover(data->ctx, &pubkey, &sig, data->msg)); 30 | CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); 31 | for (j = 0; j < 32; j++) { 32 | data->sig[j + 32] = data->msg[j]; /* Move former message to S. */ 33 | data->msg[j] = data->sig[j]; /* Move former R to message. */ 34 | data->sig[j] = pubkeyc[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */ 35 | } 36 | } 37 | } 38 | 39 | static void bench_recover_setup(void* arg) { 40 | int i; 41 | bench_recover_data *data = (bench_recover_data*)arg; 42 | 43 | for (i = 0; i < 32; i++) { 44 | data->msg[i] = 1 + i; 45 | } 46 | for (i = 0; i < 64; i++) { 47 | data->sig[i] = 65 + i; 48 | } 49 | } 50 | 51 | static void run_recovery_bench(int iters, int argc, char** argv) { 52 | bench_recover_data data; 53 | int d = argc == 1; 54 | 55 | data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); 56 | 57 | if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, iters); 58 | 59 | secp256k1_context_destroy(data.ctx); 60 | } 61 | 62 | #endif /* SECP256K1_MODULE_RECOVERY_BENCH_H */ 63 | -------------------------------------------------------------------------------- /src/modules/schnorrsig/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_schnorrsig.h 2 | noinst_HEADERS += src/modules/schnorrsig/main_impl.h 3 | noinst_HEADERS += src/modules/schnorrsig/tests_impl.h 4 | noinst_HEADERS += src/modules/schnorrsig/tests_exhaustive_impl.h 5 | noinst_HEADERS += src/modules/schnorrsig/bench_impl.h 6 | -------------------------------------------------------------------------------- /src/modules/schnorrsig/bench_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODULE_SCHNORRSIG_BENCH_H 8 | #define SECP256K1_MODULE_SCHNORRSIG_BENCH_H 9 | 10 | #include "../../../include/secp256k1_schnorrsig.h" 11 | 12 | #define MSGLEN 32 13 | 14 | typedef struct { 15 | secp256k1_context *ctx; 16 | int n; 17 | 18 | const secp256k1_keypair **keypairs; 19 | const unsigned char **pk; 20 | const unsigned char **sigs; 21 | const unsigned char **msgs; 22 | } bench_schnorrsig_data; 23 | 24 | static void bench_schnorrsig_sign(void* arg, int iters) { 25 | bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg; 26 | int i; 27 | unsigned char msg[MSGLEN] = {0}; 28 | unsigned char sig[64]; 29 | 30 | for (i = 0; i < iters; i++) { 31 | msg[0] = i; 32 | msg[1] = i >> 8; 33 | CHECK(secp256k1_schnorrsig_sign_custom(data->ctx, sig, msg, MSGLEN, data->keypairs[i], NULL)); 34 | } 35 | } 36 | 37 | static void bench_schnorrsig_verify(void* arg, int iters) { 38 | bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg; 39 | int i; 40 | 41 | for (i = 0; i < iters; i++) { 42 | secp256k1_xonly_pubkey pk; 43 | CHECK(secp256k1_xonly_pubkey_parse(data->ctx, &pk, data->pk[i]) == 1); 44 | CHECK(secp256k1_schnorrsig_verify(data->ctx, data->sigs[i], data->msgs[i], MSGLEN, &pk)); 45 | } 46 | } 47 | 48 | static void run_schnorrsig_bench(int iters, int argc, char** argv) { 49 | int i; 50 | bench_schnorrsig_data data; 51 | int d = argc == 1; 52 | 53 | data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); 54 | data.keypairs = (const secp256k1_keypair **)malloc(iters * sizeof(secp256k1_keypair *)); 55 | data.pk = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); 56 | data.msgs = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); 57 | data.sigs = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); 58 | 59 | CHECK(MSGLEN >= 4); 60 | for (i = 0; i < iters; i++) { 61 | unsigned char sk[32]; 62 | unsigned char *msg = (unsigned char *)malloc(MSGLEN); 63 | unsigned char *sig = (unsigned char *)malloc(64); 64 | secp256k1_keypair *keypair = (secp256k1_keypair *)malloc(sizeof(*keypair)); 65 | unsigned char *pk_char = (unsigned char *)malloc(32); 66 | secp256k1_xonly_pubkey pk; 67 | msg[0] = sk[0] = i; 68 | msg[1] = sk[1] = i >> 8; 69 | msg[2] = sk[2] = i >> 16; 70 | msg[3] = sk[3] = i >> 24; 71 | memset(&msg[4], 'm', MSGLEN - 4); 72 | memset(&sk[4], 's', 28); 73 | 74 | data.keypairs[i] = keypair; 75 | data.pk[i] = pk_char; 76 | data.msgs[i] = msg; 77 | data.sigs[i] = sig; 78 | 79 | CHECK(secp256k1_keypair_create(data.ctx, keypair, sk)); 80 | CHECK(secp256k1_schnorrsig_sign_custom(data.ctx, sig, msg, MSGLEN, keypair, NULL)); 81 | CHECK(secp256k1_keypair_xonly_pub(data.ctx, &pk, NULL, keypair)); 82 | CHECK(secp256k1_xonly_pubkey_serialize(data.ctx, pk_char, &pk) == 1); 83 | } 84 | 85 | if (d || have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "sign") || have_flag(argc, argv, "schnorrsig_sign")) run_benchmark("schnorrsig_sign", bench_schnorrsig_sign, NULL, NULL, (void *) &data, 10, iters); 86 | if (d || have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "verify") || have_flag(argc, argv, "schnorrsig_verify")) run_benchmark("schnorrsig_verify", bench_schnorrsig_verify, NULL, NULL, (void *) &data, 10, iters); 87 | 88 | for (i = 0; i < iters; i++) { 89 | free((void *)data.keypairs[i]); 90 | free((void *)data.pk[i]); 91 | free((void *)data.msgs[i]); 92 | free((void *)data.sigs[i]); 93 | } 94 | 95 | /* Casting to (void *) avoids a stupid warning in MSVC. */ 96 | free((void *)data.keypairs); 97 | free((void *)data.pk); 98 | free((void *)data.msgs); 99 | free((void *)data.sigs); 100 | 101 | secp256k1_context_destroy(data.ctx); 102 | } 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /src/precompute_ecmult.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************************************** 2 | * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php. * 5 | *****************************************************************************************************/ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "../include/secp256k1.h" 12 | 13 | #include "assumptions.h" 14 | #include "util.h" 15 | 16 | #include "field_impl.h" 17 | #include "group_impl.h" 18 | #include "int128_impl.h" 19 | #include "ecmult.h" 20 | #include "ecmult_compute_table_impl.h" 21 | 22 | static void print_table(FILE *fp, const char *name, int window_g, const secp256k1_ge_storage* table) { 23 | int j; 24 | int i; 25 | 26 | fprintf(fp, "const secp256k1_ge_storage %s[ECMULT_TABLE_SIZE(WINDOW_G)] = {\n", name); 27 | fprintf(fp, " S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32 28 | ",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n", 29 | SECP256K1_GE_STORAGE_CONST_GET(table[0])); 30 | 31 | j = 1; 32 | for(i = 3; i <= window_g; ++i) { 33 | fprintf(fp, "#if WINDOW_G > %d\n", i-1); 34 | for(;j < ECMULT_TABLE_SIZE(i); ++j) { 35 | fprintf(fp, ",S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32 36 | ",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n", 37 | SECP256K1_GE_STORAGE_CONST_GET(table[j])); 38 | } 39 | fprintf(fp, "#endif\n"); 40 | } 41 | fprintf(fp, "};\n"); 42 | } 43 | 44 | static void print_two_tables(FILE *fp, int window_g) { 45 | secp256k1_ge_storage* table = malloc(ECMULT_TABLE_SIZE(window_g) * sizeof(secp256k1_ge_storage)); 46 | secp256k1_ge_storage* table_128 = malloc(ECMULT_TABLE_SIZE(window_g) * sizeof(secp256k1_ge_storage)); 47 | 48 | secp256k1_ecmult_compute_two_tables(table, table_128, window_g, &secp256k1_ge_const_g); 49 | 50 | print_table(fp, "secp256k1_pre_g", window_g, table); 51 | print_table(fp, "secp256k1_pre_g_128", window_g, table_128); 52 | 53 | free(table); 54 | free(table_128); 55 | } 56 | 57 | int main(void) { 58 | /* Always compute all tables for window sizes up to 15. */ 59 | int window_g = (ECMULT_WINDOW_SIZE < 15) ? 15 : ECMULT_WINDOW_SIZE; 60 | const char outfile[] = "src/precomputed_ecmult.c"; 61 | FILE* fp; 62 | 63 | fp = fopen(outfile, "w"); 64 | if (fp == NULL) { 65 | fprintf(stderr, "Could not open %s for writing!\n", outfile); 66 | return EXIT_FAILURE; 67 | } 68 | 69 | fprintf(fp, "/* This file was automatically generated by precompute_ecmult. */\n"); 70 | fprintf(fp, "/* This file contains an array secp256k1_pre_g with odd multiples of the base point G and\n"); 71 | fprintf(fp, " * an array secp256k1_pre_g_128 with odd multiples of 2^128*G for accelerating the computation of a*P + b*G.\n"); 72 | fprintf(fp, " */\n"); 73 | fprintf(fp, "#include \"group.h\"\n"); 74 | fprintf(fp, "#include \"ecmult.h\"\n"); 75 | fprintf(fp, "#include \"precomputed_ecmult.h\"\n"); 76 | fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n"); 77 | fprintf(fp, "#if ECMULT_WINDOW_SIZE > %d\n", window_g); 78 | fprintf(fp, " #error configuration mismatch, invalid ECMULT_WINDOW_SIZE. Try deleting precomputed_ecmult.c before the build.\n"); 79 | fprintf(fp, "#endif\n"); 80 | fprintf(fp, "#ifdef EXHAUSTIVE_TEST_ORDER\n"); 81 | fprintf(fp, "# error Cannot compile precomputed_ecmult.c in exhaustive test mode\n"); 82 | fprintf(fp, "#endif /* EXHAUSTIVE_TEST_ORDER */\n"); 83 | fprintf(fp, "#define WINDOW_G ECMULT_WINDOW_SIZE\n"); 84 | 85 | print_two_tables(fp, window_g); 86 | 87 | fprintf(fp, "#undef S\n"); 88 | fclose(fp); 89 | 90 | return EXIT_SUCCESS; 91 | } 92 | -------------------------------------------------------------------------------- /src/precompute_ecmult_gen.c: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2013, 2014, 2015, 2021 Thomas Daede, Cory Fields, Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php. * 5 | *********************************************************************************/ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "../include/secp256k1.h" 12 | 13 | #include "assumptions.h" 14 | #include "util.h" 15 | 16 | #include "group.h" 17 | #include "int128_impl.h" 18 | #include "ecmult_gen.h" 19 | #include "ecmult_gen_compute_table_impl.h" 20 | 21 | static const int CONFIGS[][2] = { 22 | {2, 5}, 23 | {11, 6}, 24 | {43, 6} 25 | }; 26 | 27 | static void print_table(FILE* fp, int blocks, int teeth) { 28 | int spacing = CEIL_DIV(256, blocks * teeth); 29 | size_t points = ((size_t)1) << (teeth - 1); 30 | int outer; 31 | size_t inner; 32 | 33 | secp256k1_ge_storage* table = checked_malloc(&default_error_callback, blocks * points * sizeof(secp256k1_ge_storage)); 34 | secp256k1_ecmult_gen_compute_table(table, &secp256k1_ge_const_g, blocks, teeth, spacing); 35 | 36 | fprintf(fp, "#elif (COMB_BLOCKS == %d) && (COMB_TEETH == %d) && (COMB_SPACING == %d)\n", blocks, teeth, spacing); 37 | for (outer = 0; outer != blocks; outer++) { 38 | fprintf(fp,"{"); 39 | for (inner = 0; inner != points; inner++) { 40 | fprintf(fp, "S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32 41 | ",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")", 42 | SECP256K1_GE_STORAGE_CONST_GET(table[outer * points + inner])); 43 | if (inner != points - 1) { 44 | fprintf(fp,",\n"); 45 | } 46 | } 47 | if (outer != blocks - 1) { 48 | fprintf(fp,"},\n"); 49 | } else { 50 | fprintf(fp,"}\n"); 51 | } 52 | } 53 | free(table); 54 | } 55 | 56 | int main(int argc, char **argv) { 57 | const char outfile[] = "src/precomputed_ecmult_gen.c"; 58 | FILE* fp; 59 | size_t config; 60 | int did_current_config = 0; 61 | 62 | (void)argc; 63 | (void)argv; 64 | 65 | fp = fopen(outfile, "w"); 66 | if (fp == NULL) { 67 | fprintf(stderr, "Could not open %s for writing!\n", outfile); 68 | return EXIT_FAILURE; 69 | } 70 | 71 | fprintf(fp, "/* This file was automatically generated by precompute_ecmult_gen. */\n"); 72 | fprintf(fp, "/* See ecmult_gen_impl.h for details about the contents of this file. */\n"); 73 | fprintf(fp, "#include \"group.h\"\n"); 74 | fprintf(fp, "#include \"ecmult_gen.h\"\n"); 75 | fprintf(fp, "#include \"precomputed_ecmult_gen.h\"\n"); 76 | fprintf(fp, "#ifdef EXHAUSTIVE_TEST_ORDER\n"); 77 | fprintf(fp, "# error Cannot compile precomputed_ecmult_gen.c in exhaustive test mode\n"); 78 | fprintf(fp, "#endif /* EXHAUSTIVE_TEST_ORDER */\n"); 79 | fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n"); 80 | 81 | fprintf(fp, "const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS] = {\n"); 82 | fprintf(fp, "#if 0\n"); 83 | for (config = 0; config < sizeof(CONFIGS) / sizeof(*CONFIGS); ++config) { 84 | print_table(fp, CONFIGS[config][0], CONFIGS[config][1]); 85 | if (CONFIGS[config][0] == COMB_BLOCKS && CONFIGS[config][1] == COMB_TEETH) { 86 | did_current_config = 1; 87 | } 88 | } 89 | if (!did_current_config) { 90 | print_table(fp, COMB_BLOCKS, COMB_TEETH); 91 | } 92 | fprintf(fp, "#else\n"); 93 | fprintf(fp, "# error Configuration mismatch, invalid COMB_* parameters. Try deleting precomputed_ecmult_gen.c before the build.\n"); 94 | fprintf(fp, "#endif\n"); 95 | 96 | fprintf(fp, "};\n"); 97 | fprintf(fp, "#undef S\n"); 98 | fclose(fp); 99 | 100 | return EXIT_SUCCESS; 101 | } 102 | -------------------------------------------------------------------------------- /src/precomputed_ecmult.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************************************** 2 | * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php. * 5 | *****************************************************************************************************/ 6 | 7 | #ifndef SECP256K1_PRECOMPUTED_ECMULT_H 8 | #define SECP256K1_PRECOMPUTED_ECMULT_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #include "ecmult.h" 15 | #include "group.h" 16 | #include "util_local_visibility.h" 17 | 18 | #if defined(EXHAUSTIVE_TEST_ORDER) 19 | # if EXHAUSTIVE_TEST_ORDER == 7 20 | # define WINDOW_G 3 21 | # elif EXHAUSTIVE_TEST_ORDER == 13 22 | # define WINDOW_G 4 23 | # elif EXHAUSTIVE_TEST_ORDER == 199 24 | # define WINDOW_G 8 25 | # else 26 | # error No known generator for the specified exhaustive test group order. 27 | # endif 28 | static secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; 29 | static secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; 30 | #else /* !defined(EXHAUSTIVE_TEST_ORDER) */ 31 | # define WINDOW_G ECMULT_WINDOW_SIZE 32 | SECP256K1_LOCAL_VAR const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; 33 | SECP256K1_LOCAL_VAR const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; 34 | #endif /* defined(EXHAUSTIVE_TEST_ORDER) */ 35 | 36 | #ifdef __cplusplus 37 | } 38 | #endif 39 | 40 | #endif /* SECP256K1_PRECOMPUTED_ECMULT_H */ 41 | -------------------------------------------------------------------------------- /src/precomputed_ecmult_gen.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2013, 2014, 2015, 2021 Thomas Daede, Cory Fields, Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php. * 5 | *********************************************************************************/ 6 | 7 | #ifndef SECP256K1_PRECOMPUTED_ECMULT_GEN_H 8 | #define SECP256K1_PRECOMPUTED_ECMULT_GEN_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #include "group.h" 15 | #include "ecmult_gen.h" 16 | #include "util_local_visibility.h" 17 | 18 | #ifdef EXHAUSTIVE_TEST_ORDER 19 | static secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS]; 20 | #else 21 | SECP256K1_LOCAL_VAR const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS]; 22 | #endif /* defined(EXHAUSTIVE_TEST_ORDER) */ 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | 28 | #endif /* SECP256K1_PRECOMPUTED_ECMULT_GEN_H */ 29 | -------------------------------------------------------------------------------- /src/scalar.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_SCALAR_H 8 | #define SECP256K1_SCALAR_H 9 | 10 | #include "util.h" 11 | 12 | #if defined(EXHAUSTIVE_TEST_ORDER) 13 | #include "scalar_low.h" 14 | #elif defined(SECP256K1_WIDEMUL_INT128) 15 | #include "scalar_4x64.h" 16 | #elif defined(SECP256K1_WIDEMUL_INT64) 17 | #include "scalar_8x32.h" 18 | #else 19 | #error "Please select wide multiplication implementation" 20 | #endif 21 | 22 | /** Clear a scalar to prevent the leak of sensitive data. */ 23 | static void secp256k1_scalar_clear(secp256k1_scalar *r); 24 | 25 | /** Access bits (1 < count <= 32) from a scalar. All requested bits must belong to the same 32-bit limb. */ 26 | static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count); 27 | 28 | /** Access bits (1 < count <= 32) from a scalar. offset + count must be < 256. Not constant time in offset and count. */ 29 | static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count); 30 | 31 | /** Set a scalar from a big endian byte array. The scalar will be reduced modulo group order `n`. 32 | * In: bin: pointer to a 32-byte array. 33 | * Out: r: scalar to be set. 34 | * overflow: non-zero if the scalar was bigger or equal to `n` before reduction, zero otherwise (can be NULL). 35 | */ 36 | static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *bin, int *overflow); 37 | 38 | /** Set a scalar from a big endian byte array and returns 1 if it is a valid 39 | * seckey and 0 otherwise. */ 40 | static int secp256k1_scalar_set_b32_seckey(secp256k1_scalar *r, const unsigned char *bin); 41 | 42 | /** Set a scalar to an unsigned integer. */ 43 | static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v); 44 | 45 | /** Convert a scalar to a byte array. */ 46 | static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a); 47 | 48 | /** Add two scalars together (modulo the group order). Returns whether it overflowed. */ 49 | static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); 50 | 51 | /** Conditionally add a power of two to a scalar. The result is not allowed to overflow. */ 52 | static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag); 53 | 54 | /** Multiply two scalars (modulo the group order). */ 55 | static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); 56 | 57 | /** Compute the inverse of a scalar (modulo the group order). */ 58 | static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *a); 59 | 60 | /** Compute the inverse of a scalar (modulo the group order), without constant-time guarantee. */ 61 | static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *a); 62 | 63 | /** Compute the complement of a scalar (modulo the group order). */ 64 | static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a); 65 | 66 | /** Multiply a scalar with the multiplicative inverse of 2. */ 67 | static void secp256k1_scalar_half(secp256k1_scalar *r, const secp256k1_scalar *a); 68 | 69 | /** Check whether a scalar equals zero. */ 70 | static int secp256k1_scalar_is_zero(const secp256k1_scalar *a); 71 | 72 | /** Check whether a scalar equals one. */ 73 | static int secp256k1_scalar_is_one(const secp256k1_scalar *a); 74 | 75 | /** Check whether a scalar, considered as an nonnegative integer, is even. */ 76 | static int secp256k1_scalar_is_even(const secp256k1_scalar *a); 77 | 78 | /** Check whether a scalar is higher than the group order divided by 2. */ 79 | static int secp256k1_scalar_is_high(const secp256k1_scalar *a); 80 | 81 | /** Conditionally negate a number, in constant time. 82 | * Returns -1 if the number was negated, 1 otherwise */ 83 | static int secp256k1_scalar_cond_negate(secp256k1_scalar *a, int flag); 84 | 85 | /** Compare two scalars. */ 86 | static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b); 87 | 88 | /** Find r1 and r2 such that r1+r2*2^128 = k. */ 89 | static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k); 90 | /** Find r1 and r2 such that r1+r2*lambda = k, where r1 and r2 or their 91 | * negations are maximum 128 bits long (see secp256k1_ge_mul_lambda). It is 92 | * required that r1, r2, and k all point to different objects. */ 93 | static void secp256k1_scalar_split_lambda(secp256k1_scalar * SECP256K1_RESTRICT r1, secp256k1_scalar * SECP256K1_RESTRICT r2, const secp256k1_scalar * SECP256K1_RESTRICT k); 94 | 95 | /** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */ 96 | static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift); 97 | 98 | /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/ 99 | static void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag); 100 | 101 | /** Check invariants on a scalar (no-op unless VERIFY is enabled). */ 102 | static void secp256k1_scalar_verify(const secp256k1_scalar *r); 103 | #define SECP256K1_SCALAR_VERIFY(r) secp256k1_scalar_verify(r) 104 | 105 | #endif /* SECP256K1_SCALAR_H */ 106 | -------------------------------------------------------------------------------- /src/scalar_4x64.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_SCALAR_REPR_H 8 | #define SECP256K1_SCALAR_REPR_H 9 | 10 | #include 11 | 12 | /** A scalar modulo the group order of the secp256k1 curve. */ 13 | typedef struct { 14 | uint64_t d[4]; 15 | } secp256k1_scalar; 16 | 17 | #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{((uint64_t)(d1)) << 32 | (d0), ((uint64_t)(d3)) << 32 | (d2), ((uint64_t)(d5)) << 32 | (d4), ((uint64_t)(d7)) << 32 | (d6)}} 18 | 19 | #endif /* SECP256K1_SCALAR_REPR_H */ 20 | -------------------------------------------------------------------------------- /src/scalar_8x32.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_SCALAR_REPR_H 8 | #define SECP256K1_SCALAR_REPR_H 9 | 10 | #include 11 | 12 | /** A scalar modulo the group order of the secp256k1 curve. */ 13 | typedef struct { 14 | uint32_t d[8]; 15 | } secp256k1_scalar; 16 | 17 | #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}} 18 | 19 | #endif /* SECP256K1_SCALAR_REPR_H */ 20 | -------------------------------------------------------------------------------- /src/scalar_low.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2015, 2022 Andrew Poelstra, Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_SCALAR_REPR_H 8 | #define SECP256K1_SCALAR_REPR_H 9 | 10 | #include 11 | 12 | /** A scalar modulo the group order of the secp256k1 curve. */ 13 | typedef uint32_t secp256k1_scalar; 14 | 15 | /* A compile-time constant equal to 2^32 (modulo order). */ 16 | #define SCALAR_2P32 ((0xffffffffUL % EXHAUSTIVE_TEST_ORDER) + 1U) 17 | 18 | /* Compute a*2^32 + b (modulo order). */ 19 | #define SCALAR_HORNER(a, b) (((uint64_t)(a) * SCALAR_2P32 + (b)) % EXHAUSTIVE_TEST_ORDER) 20 | 21 | /* Evaluates to the provided 256-bit constant reduced modulo order. */ 22 | #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) SCALAR_HORNER(SCALAR_HORNER(SCALAR_HORNER(SCALAR_HORNER(SCALAR_HORNER(SCALAR_HORNER(SCALAR_HORNER((d7), (d6)), (d5)), (d4)), (d3)), (d2)), (d1)), (d0)) 23 | 24 | #endif /* SECP256K1_SCALAR_REPR_H */ 25 | -------------------------------------------------------------------------------- /src/scratch.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2017 Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_SCRATCH_H 8 | #define SECP256K1_SCRATCH_H 9 | 10 | /* The typedef is used internally; the struct name is used in the public API 11 | * (where it is exposed as a different typedef) */ 12 | typedef struct secp256k1_scratch_space_struct { 13 | /** guard against interpreting this object as other types */ 14 | unsigned char magic[8]; 15 | /** actual allocated data */ 16 | void *data; 17 | /** amount that has been allocated (i.e. `data + offset` is the next 18 | * available pointer) */ 19 | size_t alloc_size; 20 | /** maximum size available to allocate */ 21 | size_t max_size; 22 | } secp256k1_scratch; 23 | 24 | typedef struct secp256k1_scratch_space_struct secp256k1_scratch_space; 25 | 26 | static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t max_size); 27 | 28 | static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback, secp256k1_scratch* scratch); 29 | 30 | /** Returns an opaque object used to "checkpoint" a scratch space. Used 31 | * with `secp256k1_scratch_apply_checkpoint` to undo allocations. */ 32 | static size_t secp256k1_scratch_checkpoint(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch); 33 | 34 | /** Applies a check point received from `secp256k1_scratch_checkpoint`, 35 | * undoing all allocations since that point. */ 36 | static void secp256k1_scratch_apply_checkpoint(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t checkpoint); 37 | 38 | /** Returns the maximum allocation the scratch space will allow */ 39 | static size_t secp256k1_scratch_max_allocation(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch, size_t n_objects); 40 | 41 | /** Returns a pointer into the most recently allocated frame, or NULL if there is insufficient available space */ 42 | static void *secp256k1_scratch_alloc(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t n); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/scratch_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2017 Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_SCRATCH_IMPL_H 8 | #define SECP256K1_SCRATCH_IMPL_H 9 | 10 | #include "util.h" 11 | #include "scratch.h" 12 | 13 | static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t size) { 14 | const size_t base_alloc = ROUND_TO_ALIGN(sizeof(secp256k1_scratch)); 15 | void *alloc = checked_malloc(error_callback, base_alloc + size); 16 | secp256k1_scratch* ret = (secp256k1_scratch *)alloc; 17 | if (ret != NULL) { 18 | memset(ret, 0, sizeof(*ret)); 19 | memcpy(ret->magic, "scratch", 8); 20 | ret->data = (void *) ((char *) alloc + base_alloc); 21 | ret->max_size = size; 22 | } 23 | return ret; 24 | } 25 | 26 | static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback, secp256k1_scratch* scratch) { 27 | if (scratch != NULL) { 28 | if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { 29 | secp256k1_callback_call(error_callback, "invalid scratch space"); 30 | return; 31 | } 32 | VERIFY_CHECK(scratch->alloc_size == 0); /* all checkpoints should be applied */ 33 | memset(scratch->magic, 0, sizeof(scratch->magic)); 34 | free(scratch); 35 | } 36 | } 37 | 38 | static size_t secp256k1_scratch_checkpoint(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch) { 39 | if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { 40 | secp256k1_callback_call(error_callback, "invalid scratch space"); 41 | return 0; 42 | } 43 | return scratch->alloc_size; 44 | } 45 | 46 | static void secp256k1_scratch_apply_checkpoint(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t checkpoint) { 47 | if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { 48 | secp256k1_callback_call(error_callback, "invalid scratch space"); 49 | return; 50 | } 51 | if (checkpoint > scratch->alloc_size) { 52 | secp256k1_callback_call(error_callback, "invalid checkpoint"); 53 | return; 54 | } 55 | scratch->alloc_size = checkpoint; 56 | } 57 | 58 | static size_t secp256k1_scratch_max_allocation(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch, size_t objects) { 59 | if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { 60 | secp256k1_callback_call(error_callback, "invalid scratch space"); 61 | return 0; 62 | } 63 | /* Ensure that multiplication will not wrap around */ 64 | if (ALIGNMENT > 1 && objects > SIZE_MAX/(ALIGNMENT - 1)) { 65 | return 0; 66 | } 67 | if (scratch->max_size - scratch->alloc_size <= objects * (ALIGNMENT - 1)) { 68 | return 0; 69 | } 70 | return scratch->max_size - scratch->alloc_size - objects * (ALIGNMENT - 1); 71 | } 72 | 73 | static void *secp256k1_scratch_alloc(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t size) { 74 | void *ret; 75 | size_t rounded_size; 76 | 77 | rounded_size = ROUND_TO_ALIGN(size); 78 | /* Check that rounding did not wrap around */ 79 | if (rounded_size < size) { 80 | return NULL; 81 | } 82 | size = rounded_size; 83 | 84 | if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { 85 | secp256k1_callback_call(error_callback, "invalid scratch space"); 86 | return NULL; 87 | } 88 | 89 | if (size > scratch->max_size - scratch->alloc_size) { 90 | return NULL; 91 | } 92 | ret = (void *) ((char *) scratch->data + scratch->alloc_size); 93 | memset(ret, 0, size); 94 | scratch->alloc_size += size; 95 | 96 | return ret; 97 | } 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /src/selftest.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2020 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_SELFTEST_H 8 | #define SECP256K1_SELFTEST_H 9 | 10 | #include "hash.h" 11 | 12 | #include 13 | 14 | static int secp256k1_selftest_sha256(void) { 15 | static const char *input63 = "For this sample, this 63-byte string will be used as input data"; 16 | static const unsigned char output32[32] = { 17 | 0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, 18 | 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42, 19 | }; 20 | unsigned char out[32]; 21 | secp256k1_sha256 hasher; 22 | secp256k1_sha256_initialize(&hasher); 23 | secp256k1_sha256_write(&hasher, (const unsigned char*)input63, 63); 24 | secp256k1_sha256_finalize(&hasher, out); 25 | return secp256k1_memcmp_var(out, output32, 32) == 0; 26 | } 27 | 28 | static int secp256k1_selftest_passes(void) { 29 | return secp256k1_selftest_sha256(); 30 | } 31 | 32 | #endif /* SECP256K1_SELFTEST_H */ 33 | -------------------------------------------------------------------------------- /src/testrand.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_TESTRAND_H 8 | #define SECP256K1_TESTRAND_H 9 | 10 | #include "util.h" 11 | 12 | /* A non-cryptographic RNG used only for test infrastructure. */ 13 | 14 | /** Seed the pseudorandom number generator for testing. */ 15 | SECP256K1_INLINE static void testrand_seed(const unsigned char *seed16); 16 | 17 | /** Generate a pseudorandom number in the range [0..2**32-1]. */ 18 | SECP256K1_INLINE static uint32_t testrand32(void); 19 | 20 | /** Generate a pseudorandom number in the range [0..2**64-1]. */ 21 | SECP256K1_INLINE static uint64_t testrand64(void); 22 | 23 | /** Generate a pseudorandom number in the range [0..2**bits-1]. Bits must be 1 or 24 | * more. */ 25 | SECP256K1_INLINE static uint64_t testrand_bits(int bits); 26 | 27 | /** Generate a pseudorandom number in the range [0..range-1]. */ 28 | static uint32_t testrand_int(uint32_t range); 29 | 30 | /** Generate a pseudorandom 32-byte array. */ 31 | static void testrand256(unsigned char *b32); 32 | 33 | /** Generate a pseudorandom 32-byte array with long sequences of zero and one bits. */ 34 | static void testrand256_test(unsigned char *b32); 35 | 36 | /** Generate pseudorandom bytes with long sequences of zero and one bits. */ 37 | static void testrand_bytes_test(unsigned char *bytes, size_t len); 38 | 39 | /** Flip a single random bit in a byte array */ 40 | static void testrand_flip(unsigned char *b, size_t len); 41 | 42 | /** Initialize the test RNG using (hex encoded) array up to 16 bytes, or randomly if hexseed is NULL. */ 43 | static void testrand_init(const char* hexseed); 44 | 45 | /** Print final test information. */ 46 | static void testrand_finish(void); 47 | 48 | #endif /* SECP256K1_TESTRAND_H */ 49 | -------------------------------------------------------------------------------- /src/testutil.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Distributed under the MIT software license, see the accompanying * 3 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 4 | ***********************************************************************/ 5 | 6 | #ifndef SECP256K1_TESTUTIL_H 7 | #define SECP256K1_TESTUTIL_H 8 | 9 | #include "field.h" 10 | #include "group.h" 11 | #include "testrand.h" 12 | #include "util.h" 13 | 14 | static void testutil_random_fe(secp256k1_fe *x) { 15 | unsigned char bin[32]; 16 | do { 17 | testrand256(bin); 18 | if (secp256k1_fe_set_b32_limit(x, bin)) { 19 | return; 20 | } 21 | } while(1); 22 | } 23 | 24 | static void testutil_random_fe_non_zero(secp256k1_fe *nz) { 25 | do { 26 | testutil_random_fe(nz); 27 | } while (secp256k1_fe_is_zero(nz)); 28 | } 29 | 30 | static void testutil_random_fe_magnitude(secp256k1_fe *fe, int m) { 31 | secp256k1_fe zero; 32 | int n = testrand_int(m + 1); 33 | secp256k1_fe_normalize(fe); 34 | if (n == 0) { 35 | return; 36 | } 37 | secp256k1_fe_set_int(&zero, 0); 38 | secp256k1_fe_negate(&zero, &zero, 0); 39 | secp256k1_fe_mul_int_unchecked(&zero, n - 1); 40 | secp256k1_fe_add(fe, &zero); 41 | #ifdef VERIFY 42 | CHECK(fe->magnitude == n); 43 | #endif 44 | } 45 | 46 | static void testutil_random_fe_test(secp256k1_fe *x) { 47 | unsigned char bin[32]; 48 | do { 49 | testrand256_test(bin); 50 | if (secp256k1_fe_set_b32_limit(x, bin)) { 51 | return; 52 | } 53 | } while(1); 54 | } 55 | 56 | static void testutil_random_fe_non_zero_test(secp256k1_fe *fe) { 57 | do { 58 | testutil_random_fe_test(fe); 59 | } while(secp256k1_fe_is_zero(fe)); 60 | } 61 | 62 | static void testutil_random_ge_x_magnitude(secp256k1_ge *ge) { 63 | testutil_random_fe_magnitude(&ge->x, SECP256K1_GE_X_MAGNITUDE_MAX); 64 | } 65 | 66 | static void testutil_random_ge_y_magnitude(secp256k1_ge *ge) { 67 | testutil_random_fe_magnitude(&ge->y, SECP256K1_GE_Y_MAGNITUDE_MAX); 68 | } 69 | 70 | static void testutil_random_gej_x_magnitude(secp256k1_gej *gej) { 71 | testutil_random_fe_magnitude(&gej->x, SECP256K1_GEJ_X_MAGNITUDE_MAX); 72 | } 73 | 74 | static void testutil_random_gej_y_magnitude(secp256k1_gej *gej) { 75 | testutil_random_fe_magnitude(&gej->y, SECP256K1_GEJ_Y_MAGNITUDE_MAX); 76 | } 77 | 78 | static void testutil_random_gej_z_magnitude(secp256k1_gej *gej) { 79 | testutil_random_fe_magnitude(&gej->z, SECP256K1_GEJ_Z_MAGNITUDE_MAX); 80 | } 81 | 82 | static void testutil_random_ge_test(secp256k1_ge *ge) { 83 | secp256k1_fe fe; 84 | do { 85 | testutil_random_fe_test(&fe); 86 | if (secp256k1_ge_set_xo_var(ge, &fe, testrand_bits(1))) { 87 | secp256k1_fe_normalize(&ge->y); 88 | break; 89 | } 90 | } while(1); 91 | ge->infinity = 0; 92 | } 93 | 94 | static void testutil_random_ge_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) { 95 | secp256k1_fe z2, z3; 96 | testutil_random_fe_non_zero_test(&gej->z); 97 | secp256k1_fe_sqr(&z2, &gej->z); 98 | secp256k1_fe_mul(&z3, &z2, &gej->z); 99 | secp256k1_fe_mul(&gej->x, &ge->x, &z2); 100 | secp256k1_fe_mul(&gej->y, &ge->y, &z3); 101 | gej->infinity = ge->infinity; 102 | } 103 | 104 | static void testutil_random_gej_test(secp256k1_gej *gej) { 105 | secp256k1_ge ge; 106 | testutil_random_ge_test(&ge); 107 | testutil_random_ge_jacobian_test(gej, &ge); 108 | } 109 | 110 | static void testutil_random_pubkey_test(secp256k1_pubkey *pk) { 111 | secp256k1_ge ge; 112 | testutil_random_ge_test(&ge); 113 | secp256k1_pubkey_save(pk, &ge); 114 | } 115 | 116 | static void testutil_random_scalar_order_test(secp256k1_scalar *num) { 117 | do { 118 | unsigned char b32[32]; 119 | int overflow = 0; 120 | testrand256_test(b32); 121 | secp256k1_scalar_set_b32(num, b32, &overflow); 122 | if (overflow || secp256k1_scalar_is_zero(num)) { 123 | continue; 124 | } 125 | break; 126 | } while(1); 127 | } 128 | 129 | static void testutil_random_scalar_order(secp256k1_scalar *num) { 130 | do { 131 | unsigned char b32[32]; 132 | int overflow = 0; 133 | testrand256(b32); 134 | secp256k1_scalar_set_b32(num, b32, &overflow); 135 | if (overflow || secp256k1_scalar_is_zero(num)) { 136 | continue; 137 | } 138 | break; 139 | } while(1); 140 | } 141 | 142 | static void testutil_random_scalar_order_b32(unsigned char *b32) { 143 | secp256k1_scalar num; 144 | testutil_random_scalar_order(&num); 145 | secp256k1_scalar_get_b32(b32, &num); 146 | } 147 | 148 | #endif /* SECP256K1_TESTUTIL_H */ 149 | -------------------------------------------------------------------------------- /src/util_local_visibility.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_LOCAL_VISIBILITY_H 2 | #define SECP256K1_LOCAL_VISIBILITY_H 3 | 4 | /* Global variable visibility */ 5 | /* See: https://github.com/bitcoin-core/secp256k1/issues/1181 */ 6 | #if !defined(_WIN32) && defined(__GNUC__) && (__GNUC__ >= 4) 7 | # define SECP256K1_LOCAL_VAR extern __attribute__ ((visibility ("hidden"))) 8 | #else 9 | # define SECP256K1_LOCAL_VAR extern 10 | #endif 11 | 12 | #endif /* SECP256K1_LOCAL_VISIBILITY_H */ 13 | -------------------------------------------------------------------------------- /tools/check-abi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | default_base_version="$(git describe --match "v*.*.*" --abbrev=0)" 6 | default_new_version="HEAD" 7 | 8 | display_help_and_exit() { 9 | echo "Usage: $0 [ []]" 10 | echo "" 11 | echo "Description: This script uses the ABI Compliance Checker tool to determine if the ABI" 12 | echo " of a new version of libsecp256k1 has changed in a backward-incompatible way." 13 | echo "" 14 | echo "Options:" 15 | echo " base_ver Specify the base version as a git commit-ish" 16 | echo " (default: most recent reachable tag matching \"v.*.*\", currently \"$default_base_version\")" 17 | echo " new_ver Specify the new version as a git commit-ish" 18 | echo " (default: $default_new_version)" 19 | echo " -h, --help Display this help message" 20 | exit 0 21 | } 22 | 23 | if [ "$#" -eq 0 ]; then 24 | base_version="$default_base_version" 25 | new_version="$default_new_version" 26 | elif [ "$#" -eq 1 ] && { [ "$1" = "-h" ] || [ "$1" = "--help" ]; }; then 27 | display_help_and_exit 28 | elif [ "$#" -eq 1 ] || [ "$#" -eq 2 ]; then 29 | base_version="$1" 30 | if [ "$#" -eq 2 ]; then 31 | new_version="$2" 32 | fi 33 | else 34 | echo "Invalid usage. See help:" 35 | echo "" 36 | display_help_and_exit 37 | fi 38 | 39 | checkout_and_build() { 40 | _orig_dir="$(pwd)" 41 | git worktree add --detach "$1" "$2" 42 | cd "$1" 43 | mkdir build && cd build 44 | cmake -S .. --preset dev-mode \ 45 | -DCMAKE_C_COMPILER=gcc -DCMAKE_BUILD_TYPE=None -DCMAKE_C_FLAGS="-g -Og -gdwarf-4" \ 46 | -DSECP256K1_BUILD_BENCHMARK=OFF \ 47 | -DSECP256K1_BUILD_TESTS=OFF \ 48 | -DSECP256K1_BUILD_EXHAUSTIVE_TESTS=OFF \ 49 | -DSECP256K1_BUILD_CTIME_TESTS=OFF \ 50 | -DSECP256K1_BUILD_EXAMPLES=OFF 51 | cmake --build . -j "$(nproc)" 52 | # FIXME: Just set LIBPATH to lib/libsecp256k1.so once version 0.6.0 is 53 | # released. 54 | if [ -f "src/libsecp256k1.so" ]; then 55 | LIBPATH="src/libsecp256k1.so" 56 | else 57 | LIBPATH="lib/libsecp256k1.so" 58 | fi 59 | abi-dumper $LIBPATH -o ABI.dump -lver "$2" -public-headers ../include/ 60 | cd "$_orig_dir" 61 | } 62 | 63 | echo "Comparing $base_version (base version) to $new_version (new version)" 64 | echo 65 | 66 | base_source_dir="$(mktemp -d)" 67 | checkout_and_build "$base_source_dir" "$base_version" 68 | 69 | new_source_dir="$(mktemp -d)" 70 | checkout_and_build "$new_source_dir" "$new_version" 71 | 72 | abi-compliance-checker -lib libsecp256k1 -old "${base_source_dir}/build/ABI.dump" -new "${new_source_dir}/build/ABI.dump" 73 | git worktree remove "$base_source_dir" 74 | git worktree remove "$new_source_dir" 75 | -------------------------------------------------------------------------------- /tools/symbol-check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Check that a libsecp256k1 shared library exports only expected symbols. 3 | 4 | Usage examples: 5 | - When building with Autotools: 6 | ./tools/symbol-check.py .libs/libsecp256k1.so 7 | ./tools/symbol-check.py .libs/libsecp256k1-.dll 8 | ./tools/symbol-check.py .libs/libsecp256k1.dylib 9 | 10 | - When building with CMake: 11 | ./tools/symbol-check.py build/lib/libsecp256k1.so 12 | ./tools/symbol-check.py build/bin/libsecp256k1-.dll 13 | ./tools/symbol-check.py build/lib/libsecp256k1.dylib""" 14 | 15 | import re 16 | import sys 17 | import subprocess 18 | 19 | import lief 20 | 21 | 22 | class UnexpectedExport(RuntimeError): 23 | pass 24 | 25 | 26 | def get_exported_exports(library) -> list[str]: 27 | """Adapter function to get exported symbols based on the library format.""" 28 | if library.format == lief.Binary.FORMATS.ELF: 29 | return [symbol.name for symbol in library.exported_symbols] 30 | elif library.format == lief.Binary.FORMATS.PE: 31 | return [entry.name for entry in library.get_export().entries] 32 | elif library.format == lief.Binary.FORMATS.MACHO: 33 | return [symbol.name[1:] for symbol in library.exported_symbols] 34 | raise NotImplementedError(f"Unsupported format: {library.format}") 35 | 36 | 37 | def grep_expected_symbols() -> list[str]: 38 | """Guess the list of expected exported symbols from the source code.""" 39 | grep_output = subprocess.check_output( 40 | ["git", "grep", r"^\s*SECP256K1_API", "--", "include"], 41 | universal_newlines=True, 42 | encoding="utf-8" 43 | ) 44 | lines = grep_output.split("\n") 45 | pattern = re.compile(r'\bsecp256k1_\w+') 46 | exported: list[str] = [pattern.findall(line)[-1] for line in lines if line.strip()] 47 | return exported 48 | 49 | 50 | def check_symbols(library, expected_exports) -> None: 51 | """Check that the library exports only the expected symbols.""" 52 | actual_exports = get_exported_exports(library) 53 | unexpected_exports = set(actual_exports) - set(expected_exports) 54 | if unexpected_exports != set(): 55 | raise UnexpectedExport(f"Unexpected exported symbols: {unexpected_exports}") 56 | 57 | def main(): 58 | if len(sys.argv) != 2: 59 | print(__doc__) 60 | return 1 61 | library = lief.parse(sys.argv[1]) 62 | expected_exports = grep_expected_symbols() 63 | try: 64 | check_symbols(library, expected_exports) 65 | except UnexpectedExport as e: 66 | print(f"{sys.argv[0]}: In {sys.argv[1]}: {e}") 67 | return 1 68 | return 0 69 | 70 | 71 | if __name__ == "__main__": 72 | sys.exit(main()) 73 | -------------------------------------------------------------------------------- /tools/tests_wycheproof_generate_ecdsa.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (c) 2023 Random "Randy" Lattice and Sean Andersen 3 | # Distributed under the MIT software license, see the accompanying 4 | # file COPYING or https://www.opensource.org/licenses/mit-license.php. 5 | ''' 6 | Generate a C file with ECDSA testvectors from the Wycheproof project. 7 | ''' 8 | 9 | import json 10 | import sys 11 | 12 | from wycheproof_utils import to_c_array 13 | 14 | filename_input = sys.argv[1] 15 | 16 | with open(filename_input) as f: 17 | doc = json.load(f) 18 | 19 | num_groups = len(doc['testGroups']) 20 | 21 | 22 | num_vectors = 0 23 | offset_msg_running, offset_pk_running, offset_sig = 0, 0, 0 24 | out = "" 25 | messages = "" 26 | signatures = "" 27 | public_keys = "" 28 | cache_msgs = {} 29 | cache_public_keys = {} 30 | 31 | for i in range(num_groups): 32 | group = doc['testGroups'][i] 33 | num_tests = len(group['tests']) 34 | public_key = group['publicKey'] 35 | for j in range(num_tests): 36 | test_vector = group['tests'][j] 37 | # // 2 to convert hex to byte length 38 | sig_size = len(test_vector['sig']) // 2 39 | msg_size = len(test_vector['msg']) // 2 40 | 41 | if test_vector['result'] == "invalid": 42 | expected_verify = 0 43 | elif test_vector['result'] == "valid": 44 | expected_verify = 1 45 | else: 46 | raise ValueError("invalid result field") 47 | 48 | if num_vectors != 0 and sig_size != 0: 49 | signatures += ",\n " 50 | 51 | new_msg = False 52 | msg = to_c_array(test_vector['msg']) 53 | msg_offset = offset_msg_running 54 | # check for repeated msg 55 | if msg not in cache_msgs: 56 | if num_vectors != 0 and msg_size != 0: 57 | messages += ",\n " 58 | cache_msgs[msg] = offset_msg_running 59 | messages += msg 60 | new_msg = True 61 | else: 62 | msg_offset = cache_msgs[msg] 63 | 64 | new_pk = False 65 | pk = to_c_array(public_key['uncompressed']) 66 | pk_offset = offset_pk_running 67 | # check for repeated pk 68 | if pk not in cache_public_keys: 69 | if num_vectors != 0: 70 | public_keys += ",\n " 71 | cache_public_keys[pk] = offset_pk_running 72 | public_keys += pk 73 | new_pk = True 74 | else: 75 | pk_offset = cache_public_keys[pk] 76 | 77 | signatures += to_c_array(test_vector['sig']) 78 | 79 | out += " /" + "* tcId: " + str(test_vector['tcId']) + ". " + test_vector['comment'] + " *" + "/\n" 80 | out += f" {{{pk_offset}, {msg_offset}, {msg_size}, {offset_sig}, {sig_size}, {expected_verify} }},\n" 81 | if new_msg: 82 | offset_msg_running += msg_size 83 | if new_pk: 84 | offset_pk_running += 65 85 | offset_sig += sig_size 86 | num_vectors += 1 87 | 88 | struct_definition = """ 89 | typedef struct { 90 | size_t pk_offset; 91 | size_t msg_offset; 92 | size_t msg_len; 93 | size_t sig_offset; 94 | size_t sig_len; 95 | int expected_verify; 96 | } wycheproof_ecdsa_testvector; 97 | """ 98 | 99 | 100 | print("/* Note: this file was autogenerated using tests_wycheproof_generate_ecdsa.py. Do not edit. */") 101 | print(f"#define SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS ({num_vectors})") 102 | 103 | print(struct_definition) 104 | 105 | print("static const unsigned char wycheproof_ecdsa_messages[] = { " + messages + "};\n") 106 | print("static const unsigned char wycheproof_ecdsa_public_keys[] = { " + public_keys + "};\n") 107 | print("static const unsigned char wycheproof_ecdsa_signatures[] = { " + signatures + "};\n") 108 | 109 | print("static const wycheproof_ecdsa_testvector testvectors[SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS] = {") 110 | print(out) 111 | print("};") 112 | -------------------------------------------------------------------------------- /tools/wycheproof_utils.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024 Random "Randy" Lattice and Sean Andersen 2 | # Distributed under the MIT software license, see the accompanying 3 | # file COPYING or https://www.opensource.org/licenses/mit-license.php. 4 | ''' 5 | Utility functions for generating C files for testvectors from the Wycheproof project. 6 | ''' 7 | 8 | def to_c_array(x): 9 | if x == "": 10 | return "" 11 | s = ',0x'.join(a + b for a, b in zip(x[::2], x[1::2])) 12 | return "0x" + s 13 | --------------------------------------------------------------------------------