Merge commits '3bab71cf 4258c54f 566faa17 9ce9984f 04bf3f67 5be353d6 2e035af2 5b0444a3 a6f4bcf6 5ec1333d f6bef03c 1f33bb2b 1c895367 6b7e5b71 596b336f 4b84f4bf 024a4094 222ecaf6 4b0f711d 3c818388 f30c7486 1cf15ebd 24c768ae 341cc197 c63ec88e 54d34b6c 073d98a0 9eb6934f ab5a9171 fb3a8063 006ddc1f 3353d3c7 b54a0672 7d4f86d2 e8295d07 3e3d125b acf5c55a ' into temp-merge-1312
This commit is contained in:
commit
7a07f3d33f
@ -201,7 +201,7 @@ task:
|
|||||||
CTIMETESTS: no
|
CTIMETESTS: no
|
||||||
matrix:
|
matrix:
|
||||||
- env: {}
|
- env: {}
|
||||||
- env: {EXPERIMENTAL: yes, ASM: arm}
|
- env: {EXPERIMENTAL: yes, ASM: arm32}
|
||||||
<< : *MERGE_BASE
|
<< : *MERGE_BASE
|
||||||
test_script:
|
test_script:
|
||||||
- ./ci/cirrus.sh
|
- ./ci/cirrus.sh
|
||||||
@ -446,13 +446,13 @@ task:
|
|||||||
- PowerShell -NoLogo -Command if ($env:CIRRUS_PR -ne $null) { git fetch $env:CIRRUS_REPO_CLONE_URL pull/$env:CIRRUS_PR/merge; git reset --hard FETCH_HEAD; }
|
- PowerShell -NoLogo -Command if ($env:CIRRUS_PR -ne $null) { git fetch $env:CIRRUS_REPO_CLONE_URL pull/$env:CIRRUS_PR/merge; git reset --hard FETCH_HEAD; }
|
||||||
configure_script:
|
configure_script:
|
||||||
- '%x64_NATIVE_TOOLS%'
|
- '%x64_NATIVE_TOOLS%'
|
||||||
- cmake -G "Visual Studio 17 2022" -A x64 -S . -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_BUILD_EXAMPLES=ON
|
- cmake -E env CFLAGS="/WX" cmake -G "Visual Studio 17 2022" -A x64 -S . -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_BUILD_EXAMPLES=ON
|
||||||
build_script:
|
build_script:
|
||||||
- '%x64_NATIVE_TOOLS%'
|
- '%x64_NATIVE_TOOLS%'
|
||||||
- cmake --build build --config RelWithDebInfo -- -property:UseMultiToolTask=true;CL_MPcount=5
|
- cmake --build build --config RelWithDebInfo -- -property:UseMultiToolTask=true;CL_MPcount=5
|
||||||
check_script:
|
check_script:
|
||||||
- '%x64_NATIVE_TOOLS%'
|
- '%x64_NATIVE_TOOLS%'
|
||||||
- ctest --test-dir build -j 5
|
- ctest -C RelWithDebInfo --test-dir build -j 5
|
||||||
- build\src\RelWithDebInfo\bench_ecmult.exe
|
- build\src\RelWithDebInfo\bench_ecmult.exe
|
||||||
- build\src\RelWithDebInfo\bench_internal.exe
|
- build\src\RelWithDebInfo\bench_internal.exe
|
||||||
- build\src\RelWithDebInfo\bench.exe
|
- build\src\RelWithDebInfo\bench.exe
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -67,5 +67,7 @@ contrib/gh-pr-create.sh
|
|||||||
|
|
||||||
musig_example
|
musig_example
|
||||||
|
|
||||||
|
### CMake
|
||||||
|
/CMakeUserPresets.json
|
||||||
# Default CMake build directory.
|
# Default CMake build directory.
|
||||||
/build
|
/build
|
||||||
|
22
CHANGELOG.md
22
CHANGELOG.md
@ -8,6 +8,25 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [0.3.2] - 2023-05-13
|
||||||
|
We strongly recommend updating to 0.3.2 if you use or plan to use GCC >=13 to compile libsecp256k1. When in doubt, check the GCC version using `gcc -v`.
|
||||||
|
|
||||||
|
#### Security
|
||||||
|
- Module `ecdh`: Fix "constant-timeness" issue with GCC 13.1 (and potentially future versions of GCC) that could leave applications using libsecp256k1's ECDH module vulnerable to a timing side-channel attack. The fix avoids secret-dependent control flow during ECDH computations when libsecp256k1 is compiled with GCC 13.1.
|
||||||
|
|
||||||
|
#### Fixed
|
||||||
|
- Fixed an old bug that permitted compilers to potentially output bad assembly code on x86_64. In theory, it could lead to a crash or a read of unrelated memory, but this has never been observed on any compilers so far.
|
||||||
|
|
||||||
|
#### Changed
|
||||||
|
- Various improvements and changes to CMake builds. CMake builds remain experimental.
|
||||||
|
- Made API versioning consistent with GNU Autotools builds.
|
||||||
|
- Switched to `BUILD_SHARED_LIBS` variable for controlling whether to build a static or a shared library.
|
||||||
|
- Added `SECP256K1_INSTALL` variable for the controlling whether to install the build artefacts.
|
||||||
|
- Renamed asm build option `arm` to `arm32`. Use `--with-asm=arm32` instead of `--with-asm=arm` (GNU Autotools), and `-DSECP256K1_ASM=arm32` instead of `-DSECP256K1_ASM=arm` (CMake).
|
||||||
|
|
||||||
|
#### ABI Compatibility
|
||||||
|
The ABI is compatible with versions 0.3.0 and 0.3.1.
|
||||||
|
|
||||||
## [0.3.1] - 2023-04-10
|
## [0.3.1] - 2023-04-10
|
||||||
We strongly recommend updating to 0.3.1 if you use or plan to use Clang >=14 to compile libsecp256k1, e.g., Xcode >=14 on macOS has Clang >=14. When in doubt, check the Clang version using `clang -v`.
|
We strongly recommend updating to 0.3.1 if you use or plan to use Clang >=14 to compile libsecp256k1, e.g., Xcode >=14 on macOS has Clang >=14. When in doubt, check the Clang version using `clang -v`.
|
||||||
|
|
||||||
@ -69,7 +88,8 @@ This version was in fact never released.
|
|||||||
The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6).
|
The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6).
|
||||||
Therefore, this version number does not uniquely identify a set of source files.
|
Therefore, this version number does not uniquely identify a set of source files.
|
||||||
|
|
||||||
[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.0...HEAD
|
[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.2...HEAD
|
||||||
|
[0.3.2]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.1...v0.3.2
|
||||||
[0.3.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.0...v0.3.1
|
[0.3.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.0...v0.3.1
|
||||||
[0.3.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.2.0...v0.3.0
|
[0.3.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.2.0...v0.3.0
|
||||||
[0.2.0]: https://github.com/bitcoin-core/secp256k1/compare/423b6d19d373f1224fd671a982584d7e7900bc93..v0.2.0
|
[0.2.0]: https://github.com/bitcoin-core/secp256k1/compare/423b6d19d373f1224fd671a982584d7e7900bc93..v0.2.0
|
||||||
|
164
CMakeLists.txt
164
CMakeLists.txt
@ -1,16 +1,33 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
if(CMAKE_VERSION VERSION_GREATER 3.14)
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.15)
|
||||||
# MSVC runtime library flags are selected by the CMAKE_MSVC_RUNTIME_LIBRARY abstraction.
|
# MSVC runtime library flags are selected by the CMAKE_MSVC_RUNTIME_LIBRARY abstraction.
|
||||||
cmake_policy(SET CMP0091 NEW)
|
cmake_policy(SET CMP0091 NEW)
|
||||||
# MSVC warning flags are not in CMAKE_<LANG>_FLAGS by default.
|
# MSVC warning flags are not in CMAKE_<LANG>_FLAGS by default.
|
||||||
cmake_policy(SET CMP0092 NEW)
|
cmake_policy(SET CMP0092 NEW)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# The package (a.k.a. release) version is based on semantic versioning 2.0.0 of
|
project(libsecp256k1
|
||||||
# the API. All changes in experimental modules are treated as
|
# The package (a.k.a. release) version is based on semantic versioning 2.0.0 of
|
||||||
# backwards-compatible and therefore at most increase the minor version.
|
# the API. All changes in experimental modules are treated as
|
||||||
project(libsecp256k1 VERSION 0.3.1 LANGUAGES C)
|
# backwards-compatible and therefore at most increase the minor version.
|
||||||
|
VERSION 0.3.2
|
||||||
|
DESCRIPTION "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1."
|
||||||
|
HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1"
|
||||||
|
LANGUAGES C
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CMAKE_VERSION VERSION_LESS 3.21)
|
||||||
|
get_directory_property(parent_directory PARENT_DIRECTORY)
|
||||||
|
if(parent_directory)
|
||||||
|
set(PROJECT_IS_TOP_LEVEL OFF CACHE INTERNAL "Emulates CMake 3.21+ behavior.")
|
||||||
|
set(${PROJECT_NAME}_IS_TOP_LEVEL OFF CACHE INTERNAL "Emulates CMake 3.21+ behavior.")
|
||||||
|
else()
|
||||||
|
set(PROJECT_IS_TOP_LEVEL ON CACHE INTERNAL "Emulates CMake 3.21+ behavior.")
|
||||||
|
set(${PROJECT_NAME}_IS_TOP_LEVEL ON CACHE INTERNAL "Emulates CMake 3.21+ behavior.")
|
||||||
|
endif()
|
||||||
|
unset(parent_directory)
|
||||||
|
endif()
|
||||||
|
|
||||||
# The library version is based on libtool versioning of the ABI. The set of
|
# The library version is based on libtool versioning of the ABI. The set of
|
||||||
# rules for updating the version can be found here:
|
# rules for updating the version can be found here:
|
||||||
@ -18,7 +35,7 @@ project(libsecp256k1 VERSION 0.3.1 LANGUAGES C)
|
|||||||
# All changes in experimental modules are treated as if they don't affect the
|
# All changes in experimental modules are treated as if they don't affect the
|
||||||
# interface and therefore only increase the revision.
|
# interface and therefore only increase the revision.
|
||||||
set(${PROJECT_NAME}_LIB_VERSION_CURRENT 2)
|
set(${PROJECT_NAME}_LIB_VERSION_CURRENT 2)
|
||||||
set(${PROJECT_NAME}_LIB_VERSION_REVISION 1)
|
set(${PROJECT_NAME}_LIB_VERSION_REVISION 2)
|
||||||
set(${PROJECT_NAME}_LIB_VERSION_AGE 0)
|
set(${PROJECT_NAME}_LIB_VERSION_AGE 0)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 90)
|
set(CMAKE_C_STANDARD 90)
|
||||||
@ -26,36 +43,37 @@ set(CMAKE_C_EXTENSIONS OFF)
|
|||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||||
|
|
||||||
# We do not use CMake's BUILD_SHARED_LIBS option.
|
option(BUILD_SHARED_LIBS "Build shared libraries." ON)
|
||||||
option(SECP256K1_BUILD_SHARED "Build shared library." ON)
|
option(SECP256K1_DISABLE_SHARED "Disable shared library. Overrides BUILD_SHARED_LIBS." OFF)
|
||||||
option(SECP256K1_BUILD_STATIC "Build static library." ON)
|
if(SECP256K1_DISABLE_SHARED)
|
||||||
if(NOT SECP256K1_BUILD_SHARED AND NOT SECP256K1_BUILD_STATIC)
|
set(BUILD_SHARED_LIBS OFF)
|
||||||
message(FATAL_ERROR "At least one of SECP256K1_BUILD_SHARED and SECP256K1_BUILD_STATIC must be enabled.")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
option(SECP256K1_INSTALL "Enable installation." ${PROJECT_IS_TOP_LEVEL})
|
||||||
|
|
||||||
option(SECP256K1_ENABLE_MODULE_ECDH "Enable ECDH module." ON)
|
option(SECP256K1_ENABLE_MODULE_ECDH "Enable ECDH module." ON)
|
||||||
if(SECP256K1_ENABLE_MODULE_ECDH)
|
if(SECP256K1_ENABLE_MODULE_ECDH)
|
||||||
add_definitions(-DENABLE_MODULE_ECDH=1)
|
add_compile_definitions(ENABLE_MODULE_ECDH=1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(SECP256K1_ENABLE_MODULE_RECOVERY "Enable ECDSA pubkey recovery module." OFF)
|
option(SECP256K1_ENABLE_MODULE_RECOVERY "Enable ECDSA pubkey recovery module." OFF)
|
||||||
if(SECP256K1_ENABLE_MODULE_RECOVERY)
|
if(SECP256K1_ENABLE_MODULE_RECOVERY)
|
||||||
add_definitions(-DENABLE_MODULE_RECOVERY=1)
|
add_compile_definitions(ENABLE_MODULE_RECOVERY=1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(SECP256K1_ENABLE_MODULE_EXTRAKEYS "Enable extrakeys module." ON)
|
option(SECP256K1_ENABLE_MODULE_EXTRAKEYS "Enable extrakeys module." ON)
|
||||||
option(SECP256K1_ENABLE_MODULE_SCHNORRSIG "Enable schnorrsig module." ON)
|
option(SECP256K1_ENABLE_MODULE_SCHNORRSIG "Enable schnorrsig module." ON)
|
||||||
if(SECP256K1_ENABLE_MODULE_SCHNORRSIG)
|
if(SECP256K1_ENABLE_MODULE_SCHNORRSIG)
|
||||||
set(SECP256K1_ENABLE_MODULE_EXTRAKEYS ON)
|
set(SECP256K1_ENABLE_MODULE_EXTRAKEYS ON)
|
||||||
add_definitions(-DENABLE_MODULE_SCHNORRSIG=1)
|
add_compile_definitions(ENABLE_MODULE_SCHNORRSIG=1)
|
||||||
endif()
|
endif()
|
||||||
if(SECP256K1_ENABLE_MODULE_EXTRAKEYS)
|
if(SECP256K1_ENABLE_MODULE_EXTRAKEYS)
|
||||||
add_definitions(-DENABLE_MODULE_EXTRAKEYS=1)
|
add_compile_definitions(ENABLE_MODULE_EXTRAKEYS=1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS "Enable external default callback functions." OFF)
|
option(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS "Enable external default callback functions." OFF)
|
||||||
if(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS)
|
if(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS)
|
||||||
add_definitions(-DUSE_EXTERNAL_DEFAULT_CALLBACKS=1)
|
add_compile_definitions(USE_EXTERNAL_DEFAULT_CALLBACKS=1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(SECP256K1_ECMULT_WINDOW_SIZE "AUTO" CACHE STRING "Window size for ecmult precomputation for verification, specified as integer in range [2..24]. \"AUTO\" is a reasonable setting for desktop machines (currently 15). [default=AUTO]")
|
set(SECP256K1_ECMULT_WINDOW_SIZE "AUTO" CACHE STRING "Window size for ecmult precomputation for verification, specified as integer in range [2..24]. \"AUTO\" is a reasonable setting for desktop machines (currently 15). [default=AUTO]")
|
||||||
@ -65,7 +83,7 @@ check_string_option_value(SECP256K1_ECMULT_WINDOW_SIZE)
|
|||||||
if(SECP256K1_ECMULT_WINDOW_SIZE STREQUAL "AUTO")
|
if(SECP256K1_ECMULT_WINDOW_SIZE STREQUAL "AUTO")
|
||||||
set(SECP256K1_ECMULT_WINDOW_SIZE 15)
|
set(SECP256K1_ECMULT_WINDOW_SIZE 15)
|
||||||
endif()
|
endif()
|
||||||
add_definitions(-DECMULT_WINDOW_SIZE=${SECP256K1_ECMULT_WINDOW_SIZE})
|
add_compile_definitions(ECMULT_WINDOW_SIZE=${SECP256K1_ECMULT_WINDOW_SIZE})
|
||||||
|
|
||||||
set(SECP256K1_ECMULT_GEN_PREC_BITS "AUTO" CACHE STRING "Precision bits to tune the precomputed table size for signing, specified as integer 2, 4 or 8. \"AUTO\" is a reasonable setting for desktop machines (currently 4). [default=AUTO]")
|
set(SECP256K1_ECMULT_GEN_PREC_BITS "AUTO" CACHE STRING "Precision bits to tune the precomputed table size for signing, specified as integer 2, 4 or 8. \"AUTO\" is a reasonable setting for desktop machines (currently 4). [default=AUTO]")
|
||||||
set_property(CACHE SECP256K1_ECMULT_GEN_PREC_BITS PROPERTY STRINGS "AUTO" 2 4 8)
|
set_property(CACHE SECP256K1_ECMULT_GEN_PREC_BITS PROPERTY STRINGS "AUTO" 2 4 8)
|
||||||
@ -73,29 +91,35 @@ check_string_option_value(SECP256K1_ECMULT_GEN_PREC_BITS)
|
|||||||
if(SECP256K1_ECMULT_GEN_PREC_BITS STREQUAL "AUTO")
|
if(SECP256K1_ECMULT_GEN_PREC_BITS STREQUAL "AUTO")
|
||||||
set(SECP256K1_ECMULT_GEN_PREC_BITS 4)
|
set(SECP256K1_ECMULT_GEN_PREC_BITS 4)
|
||||||
endif()
|
endif()
|
||||||
add_definitions(-DECMULT_GEN_PREC_BITS=${SECP256K1_ECMULT_GEN_PREC_BITS})
|
add_compile_definitions(ECMULT_GEN_PREC_BITS=${SECP256K1_ECMULT_GEN_PREC_BITS})
|
||||||
|
|
||||||
set(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY "OFF" CACHE STRING "Test-only override of the (autodetected by the C code) \"widemul\" setting. Legal values are: \"OFF\", \"int128_struct\", \"int128\" or \"int64\". [default=OFF]")
|
set(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY "OFF" CACHE STRING "Test-only override of the (autodetected by the C code) \"widemul\" setting. Legal values are: \"OFF\", \"int128_struct\", \"int128\" or \"int64\". [default=OFF]")
|
||||||
set_property(CACHE SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY PROPERTY STRINGS "OFF" "int128_struct" "int128" "int64")
|
set_property(CACHE SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY PROPERTY STRINGS "OFF" "int128_struct" "int128" "int64")
|
||||||
check_string_option_value(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY)
|
check_string_option_value(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY)
|
||||||
if(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY)
|
if(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY)
|
||||||
string(TOUPPER "${SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY}" widemul_upper_value)
|
string(TOUPPER "${SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY}" widemul_upper_value)
|
||||||
add_definitions(-DUSE_FORCE_WIDEMUL_${widemul_upper_value}=1)
|
add_compile_definitions(USE_FORCE_WIDEMUL_${widemul_upper_value}=1)
|
||||||
endif()
|
endif()
|
||||||
mark_as_advanced(FORCE SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY)
|
mark_as_advanced(FORCE SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY)
|
||||||
|
|
||||||
set(SECP256K1_ASM "AUTO" CACHE STRING "Assembly optimizations to use: \"AUTO\", \"OFF\", \"x86_64\" or \"arm\" (experimental). [default=AUTO]")
|
set(SECP256K1_ASM "AUTO" CACHE STRING "Assembly optimizations to use: \"AUTO\", \"OFF\", \"x86_64\" or \"arm32\" (experimental). [default=AUTO]")
|
||||||
set_property(CACHE SECP256K1_ASM PROPERTY STRINGS "AUTO" "OFF" "x86_64" "arm")
|
set_property(CACHE SECP256K1_ASM PROPERTY STRINGS "AUTO" "OFF" "x86_64" "arm32")
|
||||||
check_string_option_value(SECP256K1_ASM)
|
check_string_option_value(SECP256K1_ASM)
|
||||||
if(SECP256K1_ASM STREQUAL "arm")
|
if(SECP256K1_ASM STREQUAL "arm32")
|
||||||
enable_language(ASM)
|
enable_language(ASM)
|
||||||
add_definitions(-DUSE_EXTERNAL_ASM=1)
|
include(CheckArm32Assembly)
|
||||||
|
check_arm32_assembly()
|
||||||
|
if(HAVE_ARM32_ASM)
|
||||||
|
add_compile_definitions(USE_EXTERNAL_ASM=1)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "ARM32 assembly optimization requested but not available.")
|
||||||
|
endif()
|
||||||
elseif(SECP256K1_ASM)
|
elseif(SECP256K1_ASM)
|
||||||
include(Check64bitAssembly)
|
include(CheckX86_64Assembly)
|
||||||
check_64bit_assembly()
|
check_x86_64_assembly()
|
||||||
if(HAS_64BIT_ASM)
|
if(HAVE_X86_64_ASM)
|
||||||
set(SECP256K1_ASM "x86_64")
|
set(SECP256K1_ASM "x86_64")
|
||||||
add_definitions(-DUSE_ASM_X86_64=1)
|
add_compile_definitions(USE_ASM_X86_64=1)
|
||||||
elseif(SECP256K1_ASM STREQUAL "AUTO")
|
elseif(SECP256K1_ASM STREQUAL "AUTO")
|
||||||
set(SECP256K1_ASM "OFF")
|
set(SECP256K1_ASM "OFF")
|
||||||
else()
|
else()
|
||||||
@ -105,8 +129,8 @@ endif()
|
|||||||
|
|
||||||
option(SECP256K1_EXPERIMENTAL "Allow experimental configuration options." OFF)
|
option(SECP256K1_EXPERIMENTAL "Allow experimental configuration options." OFF)
|
||||||
if(NOT SECP256K1_EXPERIMENTAL)
|
if(NOT SECP256K1_EXPERIMENTAL)
|
||||||
if(SECP256K1_ASM STREQUAL "arm")
|
if(SECP256K1_ASM STREQUAL "arm32")
|
||||||
message(FATAL_ERROR "ARM assembly optimization is experimental. Use -DSECP256K1_EXPERIMENTAL=ON to allow.")
|
message(FATAL_ERROR "ARM32 assembly optimization is experimental. Use -DSECP256K1_EXPERIMENTAL=ON to allow.")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -118,7 +142,7 @@ if(SECP256K1_VALGRIND)
|
|||||||
if(Valgrind_FOUND)
|
if(Valgrind_FOUND)
|
||||||
set(SECP256K1_VALGRIND ON)
|
set(SECP256K1_VALGRIND ON)
|
||||||
include_directories(${Valgrind_INCLUDE_DIR})
|
include_directories(${Valgrind_INCLUDE_DIR})
|
||||||
add_definitions(-DVALGRIND)
|
add_compile_definitions(VALGRIND)
|
||||||
elseif(SECP256K1_VALGRIND STREQUAL "AUTO")
|
elseif(SECP256K1_VALGRIND STREQUAL "AUTO")
|
||||||
set(SECP256K1_VALGRIND OFF)
|
set(SECP256K1_VALGRIND OFF)
|
||||||
else()
|
else()
|
||||||
@ -165,42 +189,47 @@ mark_as_advanced(
|
|||||||
CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
||||||
)
|
)
|
||||||
|
|
||||||
if(CMAKE_CONFIGURATION_TYPES)
|
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||||
set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo" "Release" "Debug" "MinSizeRel" "Coverage")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
get_property(cached_cmake_build_type CACHE CMAKE_BUILD_TYPE PROPERTY TYPE)
|
|
||||||
if(cached_cmake_build_type)
|
|
||||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
|
|
||||||
STRINGS "RelWithDebInfo" "Release" "Debug" "MinSizeRel" "Coverage"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(default_build_type "RelWithDebInfo")
|
set(default_build_type "RelWithDebInfo")
|
||||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
if(is_multi_config)
|
||||||
message(STATUS "Setting build type to \"${default_build_type}\" as none was specified")
|
set(CMAKE_CONFIGURATION_TYPES "${default_build_type}" "Release" "Debug" "MinSizeRel" "Coverage" CACHE STRING
|
||||||
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE)
|
"Supported configuration types."
|
||||||
|
FORCE
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
|
||||||
|
STRINGS "${default_build_type}" "Release" "Debug" "MinSizeRel" "Coverage"
|
||||||
|
)
|
||||||
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
|
message(STATUS "Setting build type to \"${default_build_type}\" as none was specified")
|
||||||
|
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING
|
||||||
|
"Choose the type of build."
|
||||||
|
FORCE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(TryAddCompileOption)
|
include(TryAppendCFlags)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
try_add_compile_option(/W2)
|
# Keep the following commands ordered lexicographically.
|
||||||
try_add_compile_option(/wd4146)
|
try_append_c_flags(/W2) # Moderate warning level.
|
||||||
|
try_append_c_flags(/wd4146) # Disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned".
|
||||||
else()
|
else()
|
||||||
try_add_compile_option(-pedantic)
|
# Keep the following commands ordered lexicographically.
|
||||||
try_add_compile_option(-Wall)
|
try_append_c_flags(-pedantic)
|
||||||
try_add_compile_option(-Wcast-align)
|
try_append_c_flags(-Wall) # GCC >= 2.95 and probably many other compilers.
|
||||||
try_add_compile_option(-Wcast-align=strict)
|
try_append_c_flags(-Wcast-align) # GCC >= 2.95.
|
||||||
try_add_compile_option(-Wconditional-uninitialized)
|
try_append_c_flags(-Wcast-align=strict) # GCC >= 8.0.
|
||||||
try_add_compile_option(-Wextra)
|
try_append_c_flags(-Wconditional-uninitialized) # Clang >= 3.0 only.
|
||||||
try_add_compile_option(-Wnested-externs)
|
try_append_c_flags(-Wextra) # GCC >= 3.4, this is the newer name of -W, which we don't use because older GCCs will warn about unused functions.
|
||||||
try_add_compile_option(-Wno-long-long)
|
try_append_c_flags(-Wnested-externs)
|
||||||
try_add_compile_option(-Wno-overlength-strings)
|
try_append_c_flags(-Wno-long-long) # GCC >= 3.0, -Wlong-long is implied by -pedantic.
|
||||||
try_add_compile_option(-Wno-unused-function)
|
try_append_c_flags(-Wno-overlength-strings) # GCC >= 4.2, -Woverlength-strings is implied by -pedantic.
|
||||||
try_add_compile_option(-Wreserved-identifier)
|
try_append_c_flags(-Wno-unused-function) # GCC >= 3.0, -Wunused-function is implied by -Wall.
|
||||||
try_add_compile_option(-Wshadow)
|
try_append_c_flags(-Wreserved-identifier) # Clang >= 13.0 only.
|
||||||
try_add_compile_option(-Wstrict-prototypes)
|
try_append_c_flags(-Wshadow)
|
||||||
try_add_compile_option(-Wundef)
|
try_append_c_flags(-Wstrict-prototypes)
|
||||||
|
try_append_c_flags(-Wundef)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_C_VISIBILITY_PRESET hidden)
|
set(CMAKE_C_VISIBILITY_PRESET hidden)
|
||||||
@ -225,8 +254,13 @@ message("\n")
|
|||||||
message("secp256k1 configure summary")
|
message("secp256k1 configure summary")
|
||||||
message("===========================")
|
message("===========================")
|
||||||
message("Build artifacts:")
|
message("Build artifacts:")
|
||||||
message(" shared library ...................... ${SECP256K1_BUILD_SHARED}")
|
if(BUILD_SHARED_LIBS)
|
||||||
message(" static library ...................... ${SECP256K1_BUILD_STATIC}")
|
set(library_type "Shared")
|
||||||
|
else()
|
||||||
|
set(library_type "Static")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(" library type ........................ ${library_type}")
|
||||||
message("Optional modules:")
|
message("Optional modules:")
|
||||||
message(" ECDH ................................ ${SECP256K1_ENABLE_MODULE_ECDH}")
|
message(" ECDH ................................ ${SECP256K1_ENABLE_MODULE_ECDH}")
|
||||||
message(" ECDSA pubkey recovery ............... ${SECP256K1_ENABLE_MODULE_RECOVERY}")
|
message(" ECDSA pubkey recovery ............... ${SECP256K1_ENABLE_MODULE_RECOVERY}")
|
||||||
@ -268,7 +302,7 @@ message("CFLAGS ................................ ${CMAKE_C_FLAGS}")
|
|||||||
get_directory_property(compile_options COMPILE_OPTIONS)
|
get_directory_property(compile_options COMPILE_OPTIONS)
|
||||||
string(REPLACE ";" " " compile_options "${compile_options}")
|
string(REPLACE ";" " " compile_options "${compile_options}")
|
||||||
message("Compile options ....................... " ${compile_options})
|
message("Compile options ....................... " ${compile_options})
|
||||||
if(DEFINED CMAKE_BUILD_TYPE)
|
if(NOT is_multi_config)
|
||||||
message("Build type:")
|
message("Build type:")
|
||||||
message(" - CMAKE_BUILD_TYPE ................... ${CMAKE_BUILD_TYPE}")
|
message(" - CMAKE_BUILD_TYPE ................... ${CMAKE_BUILD_TYPE}")
|
||||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type)
|
string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type)
|
||||||
@ -276,7 +310,7 @@ if(DEFINED CMAKE_BUILD_TYPE)
|
|||||||
message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_${build_type}}")
|
message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_${build_type}}")
|
||||||
message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_${build_type}}")
|
message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_${build_type}}")
|
||||||
else()
|
else()
|
||||||
message("Available configurations .............. ${CMAKE_CONFIGURATION_TYPES}")
|
message("Supported configurations .............. ${CMAKE_CONFIGURATION_TYPES}")
|
||||||
message("RelWithDebInfo configuration:")
|
message("RelWithDebInfo configuration:")
|
||||||
message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
|
message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
|
||||||
message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}")
|
message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}")
|
||||||
|
19
CMakePresets.json
Normal file
19
CMakePresets.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"cmakeMinimumRequired": {"major": 3, "minor": 21, "patch": 0},
|
||||||
|
"version": 3,
|
||||||
|
"configurePresets": [
|
||||||
|
{
|
||||||
|
"name": "dev-mode",
|
||||||
|
"displayName": "Development mode (intended only for developers of the library)",
|
||||||
|
"cacheVariables": {
|
||||||
|
"SECP256K1_EXPERIMENTAL": "ON",
|
||||||
|
"SECP256K1_ENABLE_MODULE_RECOVERY": "ON",
|
||||||
|
"SECP256K1_BUILD_EXAMPLES": "ON"
|
||||||
|
},
|
||||||
|
"warnings": {
|
||||||
|
"dev": true,
|
||||||
|
"uninitialized": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
47
Makefile.am
47
Makefile.am
@ -1,5 +1,3 @@
|
|||||||
.PHONY: clean-precomp precomp
|
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I build-aux/m4
|
ACLOCAL_AMFLAGS = -I build-aux/m4
|
||||||
|
|
||||||
# AM_CFLAGS will be automatically prepended to CFLAGS by Automake when compiling some foo
|
# AM_CFLAGS will be automatically prepended to CFLAGS by Automake when compiling some foo
|
||||||
@ -67,6 +65,7 @@ noinst_HEADERS += src/hash_impl.h
|
|||||||
noinst_HEADERS += src/field.h
|
noinst_HEADERS += src/field.h
|
||||||
noinst_HEADERS += src/field_impl.h
|
noinst_HEADERS += src/field_impl.h
|
||||||
noinst_HEADERS += src/bench.h
|
noinst_HEADERS += src/bench.h
|
||||||
|
noinst_HEADERS += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h
|
||||||
noinst_HEADERS += contrib/lax_der_parsing.h
|
noinst_HEADERS += contrib/lax_der_parsing.h
|
||||||
noinst_HEADERS += contrib/lax_der_parsing.c
|
noinst_HEADERS += contrib/lax_der_parsing.c
|
||||||
noinst_HEADERS += contrib/lax_der_privatekey_parsing.h
|
noinst_HEADERS += contrib/lax_der_privatekey_parsing.h
|
||||||
@ -215,7 +214,7 @@ precompute_ecmult_gen_LDADD = $(COMMON_LIB)
|
|||||||
# otherwise make's decision whether to rebuild them (even in the first
|
# otherwise make's decision whether to rebuild them (even in the first
|
||||||
# build by a normal user) depends on mtimes, and thus is very fragile.
|
# build by a normal user) depends on mtimes, and thus is very fragile.
|
||||||
# This means that rebuilds of the prebuilt files always need to be
|
# This means that rebuilds of the prebuilt files always need to be
|
||||||
# forced by deleting them, e.g., by invoking `make clean-precomp`.
|
# forced by deleting them.
|
||||||
src/precomputed_ecmult.c:
|
src/precomputed_ecmult.c:
|
||||||
$(MAKE) $(AM_MAKEFLAGS) precompute_ecmult$(EXEEXT)
|
$(MAKE) $(AM_MAKEFLAGS) precompute_ecmult$(EXEEXT)
|
||||||
./precompute_ecmult$(EXEEXT)
|
./precompute_ecmult$(EXEEXT)
|
||||||
@ -230,11 +229,29 @@ precomp: $(PRECOMP)
|
|||||||
# e.g., after `make maintainer-clean`).
|
# e.g., after `make maintainer-clean`).
|
||||||
BUILT_SOURCES = $(PRECOMP)
|
BUILT_SOURCES = $(PRECOMP)
|
||||||
|
|
||||||
maintainer-clean-local: clean-precomp
|
.PHONY: clean-precomp
|
||||||
|
|
||||||
clean-precomp:
|
clean-precomp:
|
||||||
rm -f $(PRECOMP)
|
rm -f $(PRECOMP)
|
||||||
|
maintainer-clean-local: clean-precomp
|
||||||
|
|
||||||
|
### Pregenerated test vectors
|
||||||
|
### (see the comments in the previous section for detailed rationale)
|
||||||
|
TESTVECTORS = src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h
|
||||||
|
|
||||||
|
src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h:
|
||||||
|
mkdir -p $(@D)
|
||||||
|
python3 $(top_srcdir)/tools/tests_wycheproof_generate.py $(top_srcdir)/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json > $@
|
||||||
|
|
||||||
|
testvectors: $(TESTVECTORS)
|
||||||
|
|
||||||
|
BUILT_SOURCES += $(TESTVECTORS)
|
||||||
|
|
||||||
|
.PHONY: clean-testvectors
|
||||||
|
clean-testvectors:
|
||||||
|
rm -f $(TESTVECTORS)
|
||||||
|
maintainer-clean-local: clean-testvectors
|
||||||
|
|
||||||
|
### Additional files to distribute
|
||||||
EXTRA_DIST = autogen.sh CHANGELOG.md SECURITY.md
|
EXTRA_DIST = autogen.sh CHANGELOG.md SECURITY.md
|
||||||
EXTRA_DIST += doc/release-process.md doc/safegcd_implementation.md
|
EXTRA_DIST += doc/release-process.md doc/safegcd_implementation.md
|
||||||
EXTRA_DIST += examples/EXAMPLES_COPYING
|
EXTRA_DIST += examples/EXAMPLES_COPYING
|
||||||
@ -244,6 +261,9 @@ EXTRA_DIST += sage/group_prover.sage
|
|||||||
EXTRA_DIST += sage/prove_group_implementations.sage
|
EXTRA_DIST += sage/prove_group_implementations.sage
|
||||||
EXTRA_DIST += sage/secp256k1_params.sage
|
EXTRA_DIST += sage/secp256k1_params.sage
|
||||||
EXTRA_DIST += sage/weierstrass_prover.sage
|
EXTRA_DIST += sage/weierstrass_prover.sage
|
||||||
|
EXTRA_DIST += src/wycheproof/WYCHEPROOF_COPYING
|
||||||
|
EXTRA_DIST += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json
|
||||||
|
EXTRA_DIST += tools/tests_wycheproof_generate.py
|
||||||
|
|
||||||
if ENABLE_MODULE_BPPP
|
if ENABLE_MODULE_BPPP
|
||||||
include src/modules/bppp/Makefile.am.include
|
include src/modules/bppp/Makefile.am.include
|
||||||
@ -292,20 +312,3 @@ endif
|
|||||||
if ENABLE_MODULE_ECDSA_ADAPTOR
|
if ENABLE_MODULE_ECDSA_ADAPTOR
|
||||||
include src/modules/ecdsa_adaptor/Makefile.am.include
|
include src/modules/ecdsa_adaptor/Makefile.am.include
|
||||||
endif
|
endif
|
||||||
|
|
||||||
EXTRA_DIST += src/wycheproof/WYCHEPROOF_COPYING
|
|
||||||
EXTRA_DIST += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h
|
|
||||||
EXTRA_DIST += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json
|
|
||||||
EXTRA_DIST += tools/tests_wycheproof_generate.py
|
|
||||||
|
|
||||||
TESTVECTORS = src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h
|
|
||||||
|
|
||||||
src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h: src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json
|
|
||||||
python3 tools/tests_wycheproof_generate.py $< > $@
|
|
||||||
|
|
||||||
testvectors: $(TESTVECTORS)
|
|
||||||
|
|
||||||
maintainer-clean-testvectors: clean-testvectors
|
|
||||||
|
|
||||||
clean-testvectors:
|
|
||||||
rm -f $(TESTVECTORS)
|
|
||||||
|
@ -1,12 +1,31 @@
|
|||||||
dnl escape "$0x" below using the m4 quadrigaph @S|@, and escape it again with a \ for the shell.
|
dnl escape "$0x" below using the m4 quadrigaph @S|@, and escape it again with a \ for the shell.
|
||||||
AC_DEFUN([SECP_64BIT_ASM_CHECK],[
|
AC_DEFUN([SECP_X86_64_ASM_CHECK],[
|
||||||
AC_MSG_CHECKING(for x86_64 assembly availability)
|
AC_MSG_CHECKING(for x86_64 assembly availability)
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||||
#include <stdint.h>]],[[
|
#include <stdint.h>]],[[
|
||||||
uint64_t a = 11, tmp;
|
uint64_t a = 11, tmp;
|
||||||
__asm__ __volatile__("movq \@S|@0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx");
|
__asm__ __volatile__("movq \@S|@0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx");
|
||||||
]])],[has_64bit_asm=yes],[has_64bit_asm=no])
|
]])], [has_x86_64_asm=yes], [has_x86_64_asm=no])
|
||||||
AC_MSG_RESULT([$has_64bit_asm])
|
AC_MSG_RESULT([$has_x86_64_asm])
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFUN([SECP_ARM32_ASM_CHECK], [
|
||||||
|
AC_MSG_CHECKING(for ARM32 assembly availability)
|
||||||
|
SECP_ARM32_ASM_CHECK_CFLAGS_saved_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="-x assembler"
|
||||||
|
AC_LINK_IFELSE([AC_LANG_SOURCE([[
|
||||||
|
.syntax unified
|
||||||
|
.eabi_attribute 24, 1
|
||||||
|
.eabi_attribute 25, 1
|
||||||
|
.text
|
||||||
|
.global main
|
||||||
|
main:
|
||||||
|
ldr r0, =0x002A
|
||||||
|
mov r7, #1
|
||||||
|
swi 0
|
||||||
|
]])], [has_arm32_asm=yes], [has_arm32_asm=no])
|
||||||
|
AC_MSG_RESULT([$has_arm32_asm])
|
||||||
|
CFLAGS="$SECP_ARM32_ASM_CHECK_CFLAGS_saved_CFLAGS"
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN([SECP_VALGRIND_CHECK],[
|
AC_DEFUN([SECP_VALGRIND_CHECK],[
|
||||||
@ -21,6 +40,7 @@ if test x"$has_valgrind" != x"yes"; then
|
|||||||
# error "Valgrind does not support this platform."
|
# error "Valgrind does not support this platform."
|
||||||
#endif
|
#endif
|
||||||
]])], [has_valgrind=yes])
|
]])], [has_valgrind=yes])
|
||||||
|
CPPFLAGS="$CPPFLAGS_TEMP"
|
||||||
fi
|
fi
|
||||||
AC_MSG_RESULT($has_valgrind)
|
AC_MSG_RESULT($has_valgrind)
|
||||||
])
|
])
|
||||||
|
6
cmake/CheckArm32Assembly.cmake
Normal file
6
cmake/CheckArm32Assembly.cmake
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
function(check_arm32_assembly)
|
||||||
|
try_compile(HAVE_ARM32_ASM
|
||||||
|
${CMAKE_BINARY_DIR}/check_arm32_assembly
|
||||||
|
SOURCES ${CMAKE_SOURCE_DIR}/cmake/source_arm32.s
|
||||||
|
)
|
||||||
|
endfunction()
|
@ -1,11 +1,9 @@
|
|||||||
function(check_string_option_value option)
|
function(check_string_option_value option)
|
||||||
get_property(expected_values CACHE ${option} PROPERTY STRINGS)
|
get_property(expected_values CACHE ${option} PROPERTY STRINGS)
|
||||||
if(expected_values)
|
if(expected_values)
|
||||||
foreach(value IN LISTS expected_values)
|
if(${option} IN_LIST expected_values)
|
||||||
if(value STREQUAL "${${option}}")
|
return()
|
||||||
return()
|
endif()
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
message(FATAL_ERROR "${option} value is \"${${option}}\", but must be one of ${expected_values}.")
|
message(FATAL_ERROR "${option} value is \"${${option}}\", but must be one of ${expected_values}.")
|
||||||
endif()
|
endif()
|
||||||
message(AUTHOR_WARNING "The STRINGS property must be set before invoking `check_string_option_value' function.")
|
message(AUTHOR_WARNING "The STRINGS property must be set before invoking `check_string_option_value' function.")
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
include(CheckCSourceCompiles)
|
include(CheckCSourceCompiles)
|
||||||
|
|
||||||
function(check_64bit_assembly)
|
function(check_x86_64_assembly)
|
||||||
check_c_source_compiles("
|
check_c_source_compiles("
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -9,6 +9,6 @@ function(check_64bit_assembly)
|
|||||||
uint64_t a = 11, tmp;
|
uint64_t a = 11, tmp;
|
||||||
__asm__ __volatile__(\"movq $0x100000000,%1; mulq %%rsi\" : \"+a\"(a) : \"S\"(tmp) : \"cc\", \"%rdx\");
|
__asm__ __volatile__(\"movq $0x100000000,%1; mulq %%rsi\" : \"+a\"(a) : \"S\"(tmp) : \"cc\", \"%rdx\");
|
||||||
}
|
}
|
||||||
" HAS_64BIT_ASM)
|
" HAVE_X86_64_ASM)
|
||||||
set(HAS_64BIT_ASM ${HAS_64BIT_ASM} PARENT_SCOPE)
|
set(HAVE_X86_64_ASM ${HAVE_X86_64_ASM} PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
@ -1,4 +1,4 @@
|
|||||||
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
|
if(CMAKE_HOST_APPLE)
|
||||||
find_program(BREW_COMMAND brew)
|
find_program(BREW_COMMAND brew)
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND ${BREW_COMMAND} --prefix valgrind
|
COMMAND ${BREW_COMMAND} --prefix valgrind
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
include(CheckCCompilerFlag)
|
|
||||||
|
|
||||||
function(try_add_compile_option option)
|
|
||||||
string(MAKE_C_IDENTIFIER ${option} result)
|
|
||||||
string(TOUPPER ${result} result)
|
|
||||||
set(result "C_SUPPORTS${result}")
|
|
||||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
|
||||||
if(NOT MSVC)
|
|
||||||
set(CMAKE_REQUIRED_FLAGS "-Werror")
|
|
||||||
endif()
|
|
||||||
check_c_compiler_flag(${option} ${result})
|
|
||||||
if(${result})
|
|
||||||
get_property(compile_options
|
|
||||||
DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
PROPERTY COMPILE_OPTIONS
|
|
||||||
)
|
|
||||||
list(APPEND compile_options "${option}")
|
|
||||||
set_property(
|
|
||||||
DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
PROPERTY COMPILE_OPTIONS "${compile_options}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
24
cmake/TryAppendCFlags.cmake
Normal file
24
cmake/TryAppendCFlags.cmake
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
include(CheckCCompilerFlag)
|
||||||
|
|
||||||
|
function(secp256k1_check_c_flags_internal flags output)
|
||||||
|
string(MAKE_C_IDENTIFIER "${flags}" result)
|
||||||
|
string(TOUPPER "${result}" result)
|
||||||
|
set(result "C_SUPPORTS_${result}")
|
||||||
|
if(NOT MSVC)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "-Werror")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# This avoids running a linker.
|
||||||
|
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||||
|
check_c_compiler_flag("${flags}" ${result})
|
||||||
|
|
||||||
|
set(${output} ${${result}} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Append flags to the COMPILE_OPTIONS directory property if CC accepts them.
|
||||||
|
macro(try_append_c_flags)
|
||||||
|
secp256k1_check_c_flags_internal("${ARGV}" result)
|
||||||
|
if(result)
|
||||||
|
add_compile_options(${ARGV})
|
||||||
|
endif()
|
||||||
|
endmacro()
|
9
cmake/source_arm32.s
Normal file
9
cmake/source_arm32.s
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.syntax unified
|
||||||
|
.eabi_attribute 24, 1
|
||||||
|
.eabi_attribute 25, 1
|
||||||
|
.text
|
||||||
|
.global main
|
||||||
|
main:
|
||||||
|
ldr r0, =0x002A
|
||||||
|
mov r7, #1
|
||||||
|
swi 0
|
29
configure.ac
29
configure.ac
@ -122,7 +122,6 @@ AC_DEFUN([SECP_TRY_APPEND_DEFAULT_CFLAGS], [
|
|||||||
# Note that "/opt" and "-opt" are equivalent for MSVC; we use "-opt" because "/opt" looks like a path.
|
# Note that "/opt" and "-opt" are equivalent for MSVC; we use "-opt" because "/opt" looks like a path.
|
||||||
if test x"$GCC" != x"yes" && test x"$build_windows" = x"yes"; then
|
if test x"$GCC" != x"yes" && test x"$build_windows" = x"yes"; then
|
||||||
SECP_TRY_APPEND_CFLAGS([-W2 -wd4146], $1) # Moderate warning level, disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned"
|
SECP_TRY_APPEND_CFLAGS([-W2 -wd4146], $1) # Moderate warning level, disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned"
|
||||||
SECP_TRY_APPEND_CFLAGS([-external:anglebrackets -external:W0], $1) # Suppress warnings from #include <...> files
|
|
||||||
# We pass -ignore:4217 to the MSVC linker to suppress warning 4217 when
|
# We pass -ignore:4217 to the MSVC linker to suppress warning 4217 when
|
||||||
# importing variables from a statically linked secp256k1.
|
# importing variables from a statically linked secp256k1.
|
||||||
# (See the libtool manual, section "Windows DLLs" for background.)
|
# (See the libtool manual, section "Windows DLLs" for background.)
|
||||||
@ -243,8 +242,8 @@ AC_ARG_ENABLE(reduced_surjection_proof_size,
|
|||||||
# * and auto (the default).
|
# * and auto (the default).
|
||||||
AC_ARG_WITH([test-override-wide-multiply], [] ,[set_widemul=$withval], [set_widemul=auto])
|
AC_ARG_WITH([test-override-wide-multiply], [] ,[set_widemul=$withval], [set_widemul=auto])
|
||||||
|
|
||||||
AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto],
|
AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm32|no|auto],
|
||||||
[assembly optimizations to use (experimental: arm) [default=auto]])],[req_asm=$withval], [req_asm=auto])
|
[assembly optimizations to use (experimental: arm32) [default=auto]])],[req_asm=$withval], [req_asm=auto])
|
||||||
|
|
||||||
AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE|auto],
|
AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE|auto],
|
||||||
[window size for ecmult precomputation for verification, specified as integer in range [2..24].]
|
[window size for ecmult precomputation for verification, specified as integer in range [2..24].]
|
||||||
@ -321,8 +320,8 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([[void myfunc() { __builtin_clzll(1);}]])],
|
|||||||
])
|
])
|
||||||
|
|
||||||
if test x"$req_asm" = x"auto"; then
|
if test x"$req_asm" = x"auto"; then
|
||||||
SECP_64BIT_ASM_CHECK
|
SECP_X86_64_ASM_CHECK
|
||||||
if test x"$has_64bit_asm" = x"yes"; then
|
if test x"$has_x86_64_asm" = x"yes"; then
|
||||||
set_asm=x86_64
|
set_asm=x86_64
|
||||||
fi
|
fi
|
||||||
if test x"$set_asm" = x; then
|
if test x"$set_asm" = x; then
|
||||||
@ -332,12 +331,16 @@ else
|
|||||||
set_asm=$req_asm
|
set_asm=$req_asm
|
||||||
case $set_asm in
|
case $set_asm in
|
||||||
x86_64)
|
x86_64)
|
||||||
SECP_64BIT_ASM_CHECK
|
SECP_X86_64_ASM_CHECK
|
||||||
if test x"$has_64bit_asm" != x"yes"; then
|
if test x"$has_x86_64_asm" != x"yes"; then
|
||||||
AC_MSG_ERROR([x86_64 assembly optimization requested but not available])
|
AC_MSG_ERROR([x86_64 assembly optimization requested but not available])
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
arm)
|
arm32)
|
||||||
|
SECP_ARM32_ASM_CHECK
|
||||||
|
if test x"$has_arm32_asm" != x"yes"; then
|
||||||
|
AC_MSG_ERROR([ARM32 assembly optimization requested but not available])
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
no)
|
no)
|
||||||
;;
|
;;
|
||||||
@ -354,7 +357,7 @@ case $set_asm in
|
|||||||
x86_64)
|
x86_64)
|
||||||
SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DUSE_ASM_X86_64=1"
|
SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DUSE_ASM_X86_64=1"
|
||||||
;;
|
;;
|
||||||
arm)
|
arm32)
|
||||||
enable_external_asm=yes
|
enable_external_asm=yes
|
||||||
;;
|
;;
|
||||||
no)
|
no)
|
||||||
@ -542,8 +545,8 @@ else
|
|||||||
if test x"$enable_module_ecdsa_adaptor" = x"yes"; then
|
if test x"$enable_module_ecdsa_adaptor" = x"yes"; then
|
||||||
AC_MSG_ERROR([ecdsa adaptor signatures module is experimental. Use --enable-experimental to allow.])
|
AC_MSG_ERROR([ecdsa adaptor signatures module is experimental. Use --enable-experimental to allow.])
|
||||||
fi
|
fi
|
||||||
if test x"$set_asm" = x"arm"; then
|
if test x"$set_asm" = x"arm32"; then
|
||||||
AC_MSG_ERROR([ARM assembly optimization is experimental. Use --enable-experimental to allow.])
|
AC_MSG_ERROR([ARM32 assembly optimization is experimental. Use --enable-experimental to allow.])
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -571,10 +574,10 @@ AM_CONDITIONAL([ENABLE_MODULE_EXTRAKEYS], [test x"$enable_module_extrakeys" = x"
|
|||||||
AM_CONDITIONAL([ENABLE_MODULE_SCHNORRSIG], [test x"$enable_module_schnorrsig" = x"yes"])
|
AM_CONDITIONAL([ENABLE_MODULE_SCHNORRSIG], [test x"$enable_module_schnorrsig" = x"yes"])
|
||||||
AM_CONDITIONAL([ENABLE_MODULE_ECDSA_S2C], [test x"$enable_module_ecdsa_s2c" = x"yes"])
|
AM_CONDITIONAL([ENABLE_MODULE_ECDSA_S2C], [test x"$enable_module_ecdsa_s2c" = x"yes"])
|
||||||
AM_CONDITIONAL([ENABLE_MODULE_ECDSA_ADAPTOR], [test x"$enable_module_ecdsa_adaptor" = x"yes"])
|
AM_CONDITIONAL([ENABLE_MODULE_ECDSA_ADAPTOR], [test x"$enable_module_ecdsa_adaptor" = x"yes"])
|
||||||
AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$enable_external_asm" = x"yes"])
|
|
||||||
AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm"])
|
|
||||||
AM_CONDITIONAL([ENABLE_MODULE_SURJECTIONPROOF], [test x"$enable_module_surjectionproof" = x"yes"])
|
AM_CONDITIONAL([ENABLE_MODULE_SURJECTIONPROOF], [test x"$enable_module_surjectionproof" = x"yes"])
|
||||||
AM_CONDITIONAL([USE_REDUCED_SURJECTION_PROOF_SIZE], [test x"$use_reduced_surjection_proof_size" = x"yes"])
|
AM_CONDITIONAL([USE_REDUCED_SURJECTION_PROOF_SIZE], [test x"$use_reduced_surjection_proof_size" = x"yes"])
|
||||||
|
AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$enable_external_asm" = x"yes"])
|
||||||
|
AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm32"])
|
||||||
AM_CONDITIONAL([BUILD_WINDOWS], [test "$build_windows" = "yes"])
|
AM_CONDITIONAL([BUILD_WINDOWS], [test "$build_windows" = "yes"])
|
||||||
AC_SUBST(LIB_VERSION_CURRENT, _LIB_VERSION_CURRENT)
|
AC_SUBST(LIB_VERSION_CURRENT, _LIB_VERSION_CURRENT)
|
||||||
AC_SUBST(LIB_VERSION_REVISION, _LIB_VERSION_REVISION)
|
AC_SUBST(LIB_VERSION_REVISION, _LIB_VERSION_REVISION)
|
||||||
|
@ -16,8 +16,10 @@ This process also assumes that there will be no minor releases for old major rel
|
|||||||
|
|
||||||
1. Open a PR to the master branch with a commit (using message `"release: prepare for $MAJOR.$MINOR.$PATCH"`, for example) that
|
1. Open a PR to the master branch with a commit (using message `"release: prepare for $MAJOR.$MINOR.$PATCH"`, for example) that
|
||||||
* finalizes the release notes in [CHANGELOG.md](../CHANGELOG.md) (make sure to include an entry for `### ABI Compatibility`),
|
* finalizes the release notes in [CHANGELOG.md](../CHANGELOG.md) (make sure to include an entry for `### ABI Compatibility`),
|
||||||
* updates `_PKG_VERSION_*` and `_LIB_VERSION_*` and sets `_PKG_VERSION_IS_RELEASE` to `true` in `configure.ac`, and
|
* sets `_PKG_VERSION_IS_RELEASE` to `true` in `configure.ac`, and
|
||||||
* updates `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_*` in `CMakeLists.txt`.
|
* if this is not a patch release
|
||||||
|
* updates `_PKG_VERSION_*` and `_LIB_VERSION_*` in `configure.ac` and
|
||||||
|
* updates `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_*` in `CMakeLists.txt`.
|
||||||
2. After the PR is merged, tag the commit and push it:
|
2. After the PR is merged, tag the commit and push it:
|
||||||
```
|
```
|
||||||
RELEASE_COMMIT=<merge commit of step 1>
|
RELEASE_COMMIT=<merge commit of step 1>
|
||||||
|
@ -2,33 +2,26 @@ add_library(example INTERFACE)
|
|||||||
target_include_directories(example INTERFACE
|
target_include_directories(example INTERFACE
|
||||||
${PROJECT_SOURCE_DIR}/include
|
${PROJECT_SOURCE_DIR}/include
|
||||||
)
|
)
|
||||||
target_compile_options(example INTERFACE
|
|
||||||
$<$<C_COMPILER_ID:MSVC>:/wd4005>
|
|
||||||
)
|
|
||||||
target_link_libraries(example INTERFACE
|
target_link_libraries(example INTERFACE
|
||||||
|
secp256k1
|
||||||
$<$<PLATFORM_ID:Windows>:bcrypt>
|
$<$<PLATFORM_ID:Windows>:bcrypt>
|
||||||
)
|
)
|
||||||
if(SECP256K1_BUILD_SHARED)
|
if(NOT BUILD_SHARED_LIBS AND MSVC)
|
||||||
target_link_libraries(example INTERFACE secp256k1)
|
target_link_options(example INTERFACE /IGNORE:4217)
|
||||||
elseif(SECP256K1_BUILD_STATIC)
|
|
||||||
target_link_libraries(example INTERFACE secp256k1_static)
|
|
||||||
if(MSVC)
|
|
||||||
target_link_options(example INTERFACE /IGNORE:4217)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(ecdsa_example ecdsa.c)
|
add_executable(ecdsa_example ecdsa.c)
|
||||||
target_link_libraries(ecdsa_example example)
|
target_link_libraries(ecdsa_example example)
|
||||||
add_test(ecdsa_example ecdsa_example)
|
add_test(NAME ecdsa_example COMMAND ecdsa_example)
|
||||||
|
|
||||||
if(SECP256K1_ENABLE_MODULE_ECDH)
|
if(SECP256K1_ENABLE_MODULE_ECDH)
|
||||||
add_executable(ecdh_example ecdh.c)
|
add_executable(ecdh_example ecdh.c)
|
||||||
target_link_libraries(ecdh_example example)
|
target_link_libraries(ecdh_example example)
|
||||||
add_test(ecdh_example ecdh_example)
|
add_test(NAME ecdh_example COMMAND ecdh_example)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(SECP256K1_ENABLE_MODULE_SCHNORRSIG)
|
if(SECP256K1_ENABLE_MODULE_SCHNORRSIG)
|
||||||
add_executable(schnorr_example schnorr.c)
|
add_executable(schnorr_example schnorr.c)
|
||||||
target_link_libraries(schnorr_example example)
|
target_link_libraries(schnorr_example example)
|
||||||
add_test(schnorr_example schnorr_example)
|
add_test(NAME schnorr_example COMMAND schnorr_example)
|
||||||
endif()
|
endif()
|
||||||
|
@ -17,7 +17,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
/*
|
||||||
|
* The defined WIN32_NO_STATUS macro disables return code definitions in
|
||||||
|
* windows.h, which avoids "macro redefinition" MSVC warnings in ntstatus.h.
|
||||||
|
*/
|
||||||
|
#define WIN32_NO_STATUS
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#undef WIN32_NO_STATUS
|
||||||
#include <ntstatus.h>
|
#include <ntstatus.h>
|
||||||
#include <bcrypt.h>
|
#include <bcrypt.h>
|
||||||
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
|
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
|
||||||
@ -77,7 +83,7 @@ static void print_hex(unsigned char* data, size_t size) {
|
|||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#endif
|
#endif
|
||||||
/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */
|
/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */
|
||||||
static SECP256K1_INLINE void secure_erase(void *ptr, size_t len) {
|
static void secure_erase(void *ptr, size_t len) {
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
/* SecureZeroMemory is guaranteed not to be optimized out by MSVC. */
|
/* SecureZeroMemory is guaranteed not to be optimized out by MSVC. */
|
||||||
SecureZeroMemory(ptr, len);
|
SecureZeroMemory(ptr, len);
|
||||||
|
@ -122,18 +122,6 @@ typedef int (*secp256k1_nonce_function)(
|
|||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
|
|
||||||
# if SECP256K1_GNUC_PREREQ(2,7)
|
|
||||||
# define SECP256K1_INLINE __inline__
|
|
||||||
# elif (defined(_MSC_VER))
|
|
||||||
# define SECP256K1_INLINE __inline
|
|
||||||
# else
|
|
||||||
# define SECP256K1_INLINE
|
|
||||||
# endif
|
|
||||||
# else
|
|
||||||
# define SECP256K1_INLINE inline
|
|
||||||
# endif
|
|
||||||
|
|
||||||
/* When this header is used at build-time the SECP256K1_BUILD define needs to be set
|
/* When this header is used at build-time the SECP256K1_BUILD define needs to be set
|
||||||
* to correctly setup export attributes and nullness checks. This is normally done
|
* to correctly setup export attributes and nullness checks. This is normally done
|
||||||
* by secp256k1.c but to guard against this header being included before secp256k1.c
|
* by secp256k1.c but to guard against this header being included before secp256k1.c
|
||||||
|
@ -141,12 +141,20 @@ SECP256K1_API int secp256k1_schnorrsig_sign(
|
|||||||
* variable length messages and accepts a pointer to an extraparams object that
|
* variable length messages and accepts a pointer to an extraparams object that
|
||||||
* allows customizing signing by passing additional arguments.
|
* allows customizing signing by passing additional arguments.
|
||||||
*
|
*
|
||||||
* Creates the same signatures as schnorrsig_sign if msglen is 32 and the
|
* Equivalent to secp256k1_schnorrsig_sign32(..., aux_rand32) if msglen is 32
|
||||||
* extraparams.ndata is the same as aux_rand32.
|
* and extraparams is initialized as follows:
|
||||||
|
* ```
|
||||||
|
* secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT;
|
||||||
|
* extraparams.ndata = (unsigned char*)aux_rand32;
|
||||||
|
* ```
|
||||||
*
|
*
|
||||||
|
* Returns 1 on success, 0 on failure.
|
||||||
|
* Args: ctx: pointer to a context object (not secp256k1_context_static).
|
||||||
|
* Out: sig64: pointer to a 64-byte array to store the serialized signature.
|
||||||
* In: msg: the message being signed. Can only be NULL if msglen is 0.
|
* In: msg: the message being signed. Can only be NULL if msglen is 0.
|
||||||
* msglen: length of the message
|
* msglen: length of the message.
|
||||||
* extraparams: pointer to a extraparams object (can be NULL)
|
* keypair: pointer to an initialized keypair.
|
||||||
|
* extraparams: pointer to an extraparams object (can be NULL).
|
||||||
*/
|
*/
|
||||||
SECP256K1_API int secp256k1_schnorrsig_sign_custom(
|
SECP256K1_API int secp256k1_schnorrsig_sign_custom(
|
||||||
const secp256k1_context *ctx,
|
const secp256k1_context *ctx,
|
||||||
|
@ -1,151 +1,162 @@
|
|||||||
# Must be included before CMAKE_INSTALL_INCLUDEDIR is used.
|
# Must be included before CMAKE_INSTALL_INCLUDEDIR is used.
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
set(${PROJECT_NAME}_installables "")
|
|
||||||
|
|
||||||
if(SECP256K1_ASM STREQUAL "arm")
|
add_library(secp256k1_precomputed OBJECT EXCLUDE_FROM_ALL
|
||||||
add_library(common OBJECT
|
|
||||||
asm/field_10x26_arm.s
|
|
||||||
)
|
|
||||||
set(common_obj "$<TARGET_OBJECTS:common>")
|
|
||||||
else()
|
|
||||||
set(common_obj "")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_library(precomputed OBJECT
|
|
||||||
precomputed_ecmult.c
|
precomputed_ecmult.c
|
||||||
precomputed_ecmult_gen.c
|
precomputed_ecmult_gen.c
|
||||||
)
|
)
|
||||||
set(internal_obj "$<TARGET_OBJECTS:precomputed>" "${common_obj}")
|
|
||||||
|
|
||||||
add_library(secp256k1 SHARED EXCLUDE_FROM_ALL
|
# Add objects explicitly rather than linking to the object libs to keep them
|
||||||
secp256k1.c
|
# from being exported.
|
||||||
${internal_obj}
|
add_library(secp256k1 secp256k1.c $<TARGET_OBJECTS:secp256k1_precomputed>)
|
||||||
)
|
|
||||||
target_include_directories(secp256k1 INTERFACE
|
|
||||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
|
||||||
)
|
|
||||||
target_compile_definitions(secp256k1 PRIVATE
|
|
||||||
$<$<PLATFORM_ID:Windows>:DLL_EXPORT>
|
|
||||||
)
|
|
||||||
set_target_properties(secp256k1 PROPERTIES
|
|
||||||
VERSION "${${PROJECT_NAME}_LIB_VERSION_CURRENT}.${${PROJECT_NAME}_LIB_VERSION_AGE}.${${PROJECT_NAME}_LIB_VERSION_REVISION}"
|
|
||||||
SOVERSION "${${PROJECT_NAME}_LIB_VERSION_CURRENT}"
|
|
||||||
)
|
|
||||||
if(SECP256K1_BUILD_SHARED)
|
|
||||||
get_target_property(use_pic secp256k1 POSITION_INDEPENDENT_CODE)
|
|
||||||
set_target_properties(precomputed PROPERTIES POSITION_INDEPENDENT_CODE ${use_pic})
|
|
||||||
set_target_properties(secp256k1 PROPERTIES EXCLUDE_FROM_ALL FALSE)
|
|
||||||
list(APPEND ${PROJECT_NAME}_installables secp256k1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_library(secp256k1_static STATIC EXCLUDE_FROM_ALL
|
add_library(secp256k1_asm INTERFACE)
|
||||||
secp256k1.c
|
if(SECP256K1_ASM STREQUAL "arm32")
|
||||||
${internal_obj}
|
add_library(secp256k1_asm_arm OBJECT EXCLUDE_FROM_ALL)
|
||||||
)
|
target_sources(secp256k1_asm_arm PUBLIC
|
||||||
target_include_directories(secp256k1_static INTERFACE
|
asm/field_10x26_arm.s
|
||||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
|
||||||
)
|
|
||||||
if(NOT MSVC)
|
|
||||||
set_target_properties(secp256k1_static PROPERTIES
|
|
||||||
OUTPUT_NAME secp256k1
|
|
||||||
)
|
)
|
||||||
endif()
|
target_sources(secp256k1 PRIVATE $<TARGET_OBJECTS:secp256k1_asm_arm>)
|
||||||
if(SECP256K1_BUILD_STATIC)
|
target_link_libraries(secp256k1_asm INTERFACE secp256k1_asm_arm)
|
||||||
set_target_properties(secp256k1_static PROPERTIES EXCLUDE_FROM_ALL FALSE)
|
|
||||||
list(APPEND ${PROJECT_NAME}_installables secp256k1_static)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(binary_interface INTERFACE)
|
# Define our export symbol only for Win32 and only for shared libs.
|
||||||
target_compile_definitions(binary_interface INTERFACE
|
# This matches libtool's usage of DLL_EXPORT
|
||||||
$<$<C_COMPILER_ID:MSVC>:_CRT_SECURE_NO_WARNINGS>
|
if(WIN32)
|
||||||
|
set_target_properties(secp256k1 PROPERTIES DEFINE_SYMBOL "DLL_EXPORT")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Object libs don't know if they're being built for a shared or static lib.
|
||||||
|
# Grab the PIC property from secp256k1 which knows.
|
||||||
|
get_target_property(use_pic secp256k1 POSITION_INDEPENDENT_CODE)
|
||||||
|
set_target_properties(secp256k1_precomputed PROPERTIES POSITION_INDEPENDENT_CODE ${use_pic})
|
||||||
|
|
||||||
|
target_include_directories(secp256k1 INTERFACE
|
||||||
|
# Add the include path for parent projects so that they don't have to manually add it.
|
||||||
|
$<BUILD_INTERFACE:$<$<NOT:$<BOOL:${PROJECT_IS_TOP_LEVEL}>>:${PROJECT_SOURCE_DIR}/include>>
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(link_library INTERFACE)
|
# This emulates Libtool to make sure Libtool and CMake agree on the ABI version,
|
||||||
if(SECP256K1_BUILD_SHARED)
|
# see below "Calculate the version variables" in build-aux/ltmain.sh.
|
||||||
target_link_libraries(link_library INTERFACE secp256k1)
|
math(EXPR ${PROJECT_NAME}_soversion "${${PROJECT_NAME}_LIB_VERSION_CURRENT} - ${${PROJECT_NAME}_LIB_VERSION_AGE}")
|
||||||
elseif(SECP256K1_BUILD_STATIC)
|
set_target_properties(secp256k1 PROPERTIES
|
||||||
target_link_libraries(link_library INTERFACE secp256k1_static)
|
SOVERSION ${${PROJECT_NAME}_soversion}
|
||||||
|
)
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
set_target_properties(secp256k1 PROPERTIES
|
||||||
|
VERSION ${${PROJECT_NAME}_soversion}.${${PROJECT_NAME}_LIB_VERSION_AGE}.${${PROJECT_NAME}_LIB_VERSION_REVISION}
|
||||||
|
)
|
||||||
|
elseif(APPLE)
|
||||||
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.17)
|
||||||
|
math(EXPR ${PROJECT_NAME}_compatibility_version "${${PROJECT_NAME}_LIB_VERSION_CURRENT} + 1")
|
||||||
|
set_target_properties(secp256k1 PROPERTIES
|
||||||
|
MACHO_COMPATIBILITY_VERSION ${${PROJECT_NAME}_compatibility_version}
|
||||||
|
MACHO_CURRENT_VERSION ${${PROJECT_NAME}_compatibility_version}.${${PROJECT_NAME}_LIB_VERSION_REVISION}
|
||||||
|
)
|
||||||
|
unset(${PROJECT_NAME}_compatibility_version)
|
||||||
|
elseif(BUILD_SHARED_LIBS)
|
||||||
|
message(WARNING
|
||||||
|
"The 'compatibility version' and 'current version' values of the DYLIB "
|
||||||
|
"will diverge from the values set by the GNU Libtool. To ensure "
|
||||||
|
"compatibility, it is recommended to upgrade CMake to at least version 3.17."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
set(${PROJECT_NAME}_windows "secp256k1")
|
||||||
|
if(MSVC)
|
||||||
|
set(${PROJECT_NAME}_windows "${PROJECT_NAME}")
|
||||||
|
endif()
|
||||||
|
set_target_properties(secp256k1 PROPERTIES
|
||||||
|
ARCHIVE_OUTPUT_NAME "${${PROJECT_NAME}_windows}"
|
||||||
|
RUNTIME_OUTPUT_NAME "${${PROJECT_NAME}_windows}-${${PROJECT_NAME}_soversion}"
|
||||||
|
)
|
||||||
|
unset(${PROJECT_NAME}_windows)
|
||||||
endif()
|
endif()
|
||||||
|
unset(${PROJECT_NAME}_soversion)
|
||||||
|
|
||||||
if(SECP256K1_BUILD_BENCHMARK)
|
if(SECP256K1_BUILD_BENCHMARK)
|
||||||
add_executable(bench bench.c)
|
add_executable(bench bench.c)
|
||||||
target_link_libraries(bench binary_interface link_library)
|
target_link_libraries(bench secp256k1)
|
||||||
add_executable(bench_internal bench_internal.c ${internal_obj})
|
add_executable(bench_internal bench_internal.c)
|
||||||
target_link_libraries(bench_internal binary_interface)
|
target_link_libraries(bench_internal secp256k1_precomputed secp256k1_asm)
|
||||||
add_executable(bench_ecmult bench_ecmult.c ${internal_obj})
|
add_executable(bench_ecmult bench_ecmult.c)
|
||||||
target_link_libraries(bench_ecmult binary_interface)
|
target_link_libraries(bench_ecmult secp256k1_precomputed secp256k1_asm)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(SECP256K1_BUILD_TESTS)
|
if(SECP256K1_BUILD_TESTS)
|
||||||
add_executable(noverify_tests tests.c ${internal_obj})
|
add_executable(noverify_tests tests.c)
|
||||||
target_link_libraries(noverify_tests binary_interface)
|
target_link_libraries(noverify_tests secp256k1_precomputed secp256k1_asm)
|
||||||
add_test(noverify_tests noverify_tests)
|
add_test(NAME noverify_tests COMMAND noverify_tests)
|
||||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Coverage")
|
if(NOT CMAKE_BUILD_TYPE STREQUAL "Coverage")
|
||||||
add_executable(tests tests.c ${internal_obj})
|
add_executable(tests tests.c)
|
||||||
target_compile_definitions(tests PRIVATE VERIFY)
|
target_compile_definitions(tests PRIVATE VERIFY)
|
||||||
target_link_libraries(tests binary_interface)
|
target_link_libraries(tests secp256k1_precomputed secp256k1_asm)
|
||||||
add_test(tests tests)
|
add_test(NAME tests COMMAND tests)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(SECP256K1_BUILD_EXHAUSTIVE_TESTS)
|
if(SECP256K1_BUILD_EXHAUSTIVE_TESTS)
|
||||||
# Note: do not include $<TARGET_OBJECTS:precomputed> in exhaustive_tests (it uses runtime-generated tables).
|
# Note: do not include secp256k1_precomputed in exhaustive_tests (it uses runtime-generated tables).
|
||||||
add_executable(exhaustive_tests tests_exhaustive.c ${common_obj})
|
add_executable(exhaustive_tests tests_exhaustive.c)
|
||||||
|
target_link_libraries(exhaustive_tests secp256k1_asm)
|
||||||
target_compile_definitions(exhaustive_tests PRIVATE $<$<NOT:$<CONFIG:Coverage>>:VERIFY>)
|
target_compile_definitions(exhaustive_tests PRIVATE $<$<NOT:$<CONFIG:Coverage>>:VERIFY>)
|
||||||
target_link_libraries(exhaustive_tests binary_interface)
|
add_test(NAME exhaustive_tests COMMAND exhaustive_tests)
|
||||||
add_test(exhaustive_tests exhaustive_tests)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(SECP256K1_BUILD_CTIME_TESTS)
|
if(SECP256K1_BUILD_CTIME_TESTS)
|
||||||
add_executable(ctime_tests ctime_tests.c)
|
add_executable(ctime_tests ctime_tests.c)
|
||||||
target_link_libraries(ctime_tests binary_interface link_library)
|
target_link_libraries(ctime_tests secp256k1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
install(TARGETS ${${PROJECT_NAME}_installables}
|
if(SECP256K1_INSTALL)
|
||||||
EXPORT ${PROJECT_NAME}-targets
|
install(TARGETS secp256k1
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
EXPORT ${PROJECT_NAME}-targets
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
)
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
set(${PROJECT_NAME}_headers
|
)
|
||||||
"${PROJECT_SOURCE_DIR}/include/secp256k1.h"
|
set(${PROJECT_NAME}_headers
|
||||||
"${PROJECT_SOURCE_DIR}/include/secp256k1_preallocated.h"
|
"${PROJECT_SOURCE_DIR}/include/secp256k1.h"
|
||||||
)
|
"${PROJECT_SOURCE_DIR}/include/secp256k1_preallocated.h"
|
||||||
if(SECP256K1_ENABLE_MODULE_ECDH)
|
)
|
||||||
list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_ecdh.h")
|
if(SECP256K1_ENABLE_MODULE_ECDH)
|
||||||
endif()
|
list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_ecdh.h")
|
||||||
if(SECP256K1_ENABLE_MODULE_RECOVERY)
|
endif()
|
||||||
list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_recovery.h")
|
if(SECP256K1_ENABLE_MODULE_RECOVERY)
|
||||||
endif()
|
list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_recovery.h")
|
||||||
if(SECP256K1_ENABLE_MODULE_EXTRAKEYS)
|
endif()
|
||||||
list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_extrakeys.h")
|
if(SECP256K1_ENABLE_MODULE_EXTRAKEYS)
|
||||||
endif()
|
list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_extrakeys.h")
|
||||||
if(SECP256K1_ENABLE_MODULE_SCHNORRSIG)
|
endif()
|
||||||
list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_schnorrsig.h")
|
if(SECP256K1_ENABLE_MODULE_SCHNORRSIG)
|
||||||
endif()
|
list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_schnorrsig.h")
|
||||||
install(FILES ${${PROJECT_NAME}_headers}
|
endif()
|
||||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
install(FILES ${${PROJECT_NAME}_headers}
|
||||||
)
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
)
|
||||||
|
|
||||||
install(EXPORT ${PROJECT_NAME}-targets
|
install(EXPORT ${PROJECT_NAME}-targets
|
||||||
FILE ${PROJECT_NAME}-targets.cmake
|
FILE ${PROJECT_NAME}-targets.cmake
|
||||||
NAMESPACE ${PROJECT_NAME}::
|
NAMESPACE ${PROJECT_NAME}::
|
||||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
||||||
)
|
)
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
configure_package_config_file(
|
configure_package_config_file(
|
||||||
${PROJECT_SOURCE_DIR}/cmake/config.cmake.in
|
${PROJECT_SOURCE_DIR}/cmake/config.cmake.in
|
||||||
${PROJECT_NAME}-config.cmake
|
${PROJECT_NAME}-config.cmake
|
||||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
||||||
NO_SET_AND_CHECK_MACRO
|
NO_SET_AND_CHECK_MACRO
|
||||||
)
|
)
|
||||||
write_basic_package_version_file(${PROJECT_NAME}-config-version.cmake
|
write_basic_package_version_file(${PROJECT_NAME}-config-version.cmake
|
||||||
COMPATIBILITY SameMajorVersion
|
COMPATIBILITY SameMinorVersion
|
||||||
)
|
)
|
||||||
install(
|
|
||||||
FILES
|
install(
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
|
FILES
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
|
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
|
||||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
|
||||||
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
|
16
src/bench.c
16
src/bench.c
@ -64,11 +64,11 @@ typedef struct {
|
|||||||
size_t siglen;
|
size_t siglen;
|
||||||
unsigned char pubkey[33];
|
unsigned char pubkey[33];
|
||||||
size_t pubkeylen;
|
size_t pubkeylen;
|
||||||
} bench_verify_data;
|
} bench_data;
|
||||||
|
|
||||||
static void bench_verify(void* arg, int iters) {
|
static void bench_verify(void* arg, int iters) {
|
||||||
int i;
|
int i;
|
||||||
bench_verify_data* data = (bench_verify_data*)arg;
|
bench_data* data = (bench_data*)arg;
|
||||||
|
|
||||||
for (i = 0; i < iters; i++) {
|
for (i = 0; i < iters; i++) {
|
||||||
secp256k1_pubkey pubkey;
|
secp256k1_pubkey pubkey;
|
||||||
@ -85,15 +85,9 @@ static void bench_verify(void* arg, int iters) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
secp256k1_context* ctx;
|
|
||||||
unsigned char msg[32];
|
|
||||||
unsigned char key[32];
|
|
||||||
} bench_sign_data;
|
|
||||||
|
|
||||||
static void bench_sign_setup(void* arg) {
|
static void bench_sign_setup(void* arg) {
|
||||||
int i;
|
int i;
|
||||||
bench_sign_data *data = (bench_sign_data*)arg;
|
bench_data *data = (bench_data*)arg;
|
||||||
|
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
data->msg[i] = i + 1;
|
data->msg[i] = i + 1;
|
||||||
@ -105,7 +99,7 @@ static void bench_sign_setup(void* arg) {
|
|||||||
|
|
||||||
static void bench_sign_run(void* arg, int iters) {
|
static void bench_sign_run(void* arg, int iters) {
|
||||||
int i;
|
int i;
|
||||||
bench_sign_data *data = (bench_sign_data*)arg;
|
bench_data *data = (bench_data*)arg;
|
||||||
|
|
||||||
unsigned char sig[74];
|
unsigned char sig[74];
|
||||||
for (i = 0; i < iters; i++) {
|
for (i = 0; i < iters; i++) {
|
||||||
@ -137,7 +131,7 @@ int main(int argc, char** argv) {
|
|||||||
int i;
|
int i;
|
||||||
secp256k1_pubkey pubkey;
|
secp256k1_pubkey pubkey;
|
||||||
secp256k1_ecdsa_signature sig;
|
secp256k1_ecdsa_signature sig;
|
||||||
bench_verify_data data;
|
bench_data data;
|
||||||
|
|
||||||
int d = argc == 1;
|
int d = argc == 1;
|
||||||
int default_iters = 20000;
|
int default_iters = 20000;
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#if (defined(_MSC_VER) && _MSC_VER >= 1900)
|
#if (defined(_MSC_VER) && _MSC_VER >= 1900)
|
||||||
# include <time.h>
|
# include <time.h>
|
||||||
#else
|
#else
|
||||||
# include "sys/time.h"
|
# include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int64_t gettime_i64(void) {
|
static int64_t gettime_i64(void) {
|
||||||
|
@ -113,7 +113,7 @@ static void bench_ecmult_const(void* arg, int iters) {
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < iters; ++i) {
|
for (i = 0; i < iters; ++i) {
|
||||||
secp256k1_ecmult_const(&data->output[i], &data->pubkeys[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], 256);
|
secp256k1_ecmult_const(&data->output[i], &data->pubkeys[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,10 +65,10 @@ static void bench_setup(void* arg) {
|
|||||||
|
|
||||||
secp256k1_scalar_set_b32(&data->scalar[0], init[0], NULL);
|
secp256k1_scalar_set_b32(&data->scalar[0], init[0], NULL);
|
||||||
secp256k1_scalar_set_b32(&data->scalar[1], init[1], NULL);
|
secp256k1_scalar_set_b32(&data->scalar[1], init[1], NULL);
|
||||||
secp256k1_fe_set_b32(&data->fe[0], init[0]);
|
secp256k1_fe_set_b32_limit(&data->fe[0], init[0]);
|
||||||
secp256k1_fe_set_b32(&data->fe[1], init[1]);
|
secp256k1_fe_set_b32_limit(&data->fe[1], init[1]);
|
||||||
secp256k1_fe_set_b32(&data->fe[2], init[2]);
|
secp256k1_fe_set_b32_limit(&data->fe[2], init[2]);
|
||||||
secp256k1_fe_set_b32(&data->fe[3], init[3]);
|
secp256k1_fe_set_b32_limit(&data->fe[3], init[3]);
|
||||||
CHECK(secp256k1_ge_set_xo_var(&data->ge[0], &data->fe[0], 0));
|
CHECK(secp256k1_ge_set_xo_var(&data->ge[0], &data->fe[0], 0));
|
||||||
CHECK(secp256k1_ge_set_xo_var(&data->ge[1], &data->fe[1], 1));
|
CHECK(secp256k1_ge_set_xo_var(&data->ge[1], &data->fe[1], 1));
|
||||||
secp256k1_gej_set_ge(&data->gej[0], &data->ge[0]);
|
secp256k1_gej_set_ge(&data->gej[0], &data->ge[0]);
|
||||||
|
@ -239,7 +239,8 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar *sigr, const secp25
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
secp256k1_scalar_get_b32(c, sigr);
|
secp256k1_scalar_get_b32(c, sigr);
|
||||||
secp256k1_fe_set_b32(&xr, c);
|
/* we can ignore the fe_set_b32_limit return value, because we know the input is in range */
|
||||||
|
(void)secp256k1_fe_set_b32_limit(&xr, c);
|
||||||
|
|
||||||
/** We now have the recomputed R point in pr, and its claimed x coordinate (modulo n)
|
/** We now have the recomputed R point in pr, and its claimed x coordinate (modulo n)
|
||||||
* in xr. Naively, we would extract the x coordinate from pr (requiring a inversion modulo p),
|
* in xr. Naively, we would extract the x coordinate from pr (requiring a inversion modulo p),
|
||||||
|
@ -17,10 +17,10 @@
|
|||||||
static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) {
|
static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) {
|
||||||
if (size == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) {
|
if (size == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) {
|
||||||
secp256k1_fe x;
|
secp256k1_fe x;
|
||||||
return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD);
|
return secp256k1_fe_set_b32_limit(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD);
|
||||||
} else if (size == 65 && (pub[0] == SECP256K1_TAG_PUBKEY_UNCOMPRESSED || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) {
|
} else if (size == 65 && (pub[0] == SECP256K1_TAG_PUBKEY_UNCOMPRESSED || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) {
|
||||||
secp256k1_fe x, y;
|
secp256k1_fe x, y;
|
||||||
if (!secp256k1_fe_set_b32(&x, pub+1) || !secp256k1_fe_set_b32(&y, pub+33)) {
|
if (!secp256k1_fe_set_b32_limit(&x, pub+1) || !secp256k1_fe_set_b32_limit(&y, pub+33)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
secp256k1_ge_set_xy(elem, &x, &y);
|
secp256k1_ge_set_xy(elem, &x, &y);
|
||||||
|
@ -11,12 +11,9 @@
|
|||||||
#include "group.h"
|
#include "group.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multiply: R = q*A (in constant-time)
|
* Multiply: R = q*A (in constant-time for q)
|
||||||
* Here `bits` should be set to the maximum bitlength of the _absolute value_ of `q`, plus
|
|
||||||
* one because we internally sometimes add 2 to the number during the WNAF conversion.
|
|
||||||
* A must not be infinity.
|
|
||||||
*/
|
*/
|
||||||
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q, int bits);
|
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as secp256k1_ecmult_const, but takes in an x coordinate of the base point
|
* Same as secp256k1_ecmult_const, but takes in an x coordinate of the base point
|
||||||
@ -35,7 +32,6 @@ static int secp256k1_ecmult_const_xonly(
|
|||||||
const secp256k1_fe *n,
|
const secp256k1_fe *n,
|
||||||
const secp256k1_fe *d,
|
const secp256k1_fe *d,
|
||||||
const secp256k1_scalar *q,
|
const secp256k1_scalar *q,
|
||||||
int bits,
|
|
||||||
int known_on_curve
|
int known_on_curve
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ static int secp256k1_wnaf_const(int *wnaf, const secp256k1_scalar *scalar, int w
|
|||||||
return skew;
|
return skew;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar, int size) {
|
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar) {
|
||||||
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
|
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
|
||||||
secp256k1_ge tmpa;
|
secp256k1_ge tmpa;
|
||||||
secp256k1_fe Z;
|
secp256k1_fe Z;
|
||||||
@ -144,20 +144,17 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
|
|||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* build wnaf representation for q. */
|
if (secp256k1_ge_is_infinity(a)) {
|
||||||
int rsize = size;
|
secp256k1_gej_set_infinity(r);
|
||||||
if (size > 128) {
|
return;
|
||||||
rsize = 128;
|
|
||||||
/* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */
|
|
||||||
secp256k1_scalar_split_lambda(&q_1, &q_lam, scalar);
|
|
||||||
skew_1 = secp256k1_wnaf_const(wnaf_1, &q_1, WINDOW_A - 1, 128);
|
|
||||||
skew_lam = secp256k1_wnaf_const(wnaf_lam, &q_lam, WINDOW_A - 1, 128);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
skew_1 = secp256k1_wnaf_const(wnaf_1, scalar, WINDOW_A - 1, size);
|
|
||||||
skew_lam = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* build wnaf representation for q. */
|
||||||
|
/* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */
|
||||||
|
secp256k1_scalar_split_lambda(&q_1, &q_lam, scalar);
|
||||||
|
skew_1 = secp256k1_wnaf_const(wnaf_1, &q_1, WINDOW_A - 1, 128);
|
||||||
|
skew_lam = secp256k1_wnaf_const(wnaf_lam, &q_lam, WINDOW_A - 1, 128);
|
||||||
|
|
||||||
/* Calculate odd multiples of a.
|
/* Calculate odd multiples of a.
|
||||||
* All multiples are brought to the same Z 'denominator', which is stored
|
* All multiples are brought to the same Z 'denominator', which is stored
|
||||||
* in Z. Due to secp256k1' isomorphism we can do all operations pretending
|
* in Z. Due to secp256k1' isomorphism we can do all operations pretending
|
||||||
@ -170,28 +167,23 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
|
|||||||
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
|
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
|
||||||
secp256k1_fe_normalize_weak(&pre_a[i].y);
|
secp256k1_fe_normalize_weak(&pre_a[i].y);
|
||||||
}
|
}
|
||||||
if (size > 128) {
|
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
|
||||||
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
|
secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]);
|
||||||
secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* first loop iteration (separated out so we can directly set r, rather
|
/* first loop iteration (separated out so we can directly set r, rather
|
||||||
* than having it start at infinity, get doubled several times, then have
|
* than having it start at infinity, get doubled several times, then have
|
||||||
* its new value added to it) */
|
* its new value added to it) */
|
||||||
i = wnaf_1[WNAF_SIZE_BITS(rsize, WINDOW_A - 1)];
|
i = wnaf_1[WNAF_SIZE_BITS(128, WINDOW_A - 1)];
|
||||||
VERIFY_CHECK(i != 0);
|
VERIFY_CHECK(i != 0);
|
||||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A);
|
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A);
|
||||||
secp256k1_gej_set_ge(r, &tmpa);
|
secp256k1_gej_set_ge(r, &tmpa);
|
||||||
if (size > 128) {
|
i = wnaf_lam[WNAF_SIZE_BITS(128, WINDOW_A - 1)];
|
||||||
i = wnaf_lam[WNAF_SIZE_BITS(rsize, WINDOW_A - 1)];
|
VERIFY_CHECK(i != 0);
|
||||||
VERIFY_CHECK(i != 0);
|
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A);
|
||||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A);
|
secp256k1_gej_add_ge(r, r, &tmpa);
|
||||||
secp256k1_gej_add_ge(r, r, &tmpa);
|
|
||||||
}
|
|
||||||
/* remaining loop iterations */
|
/* remaining loop iterations */
|
||||||
for (i = WNAF_SIZE_BITS(rsize, WINDOW_A - 1) - 1; i >= 0; i--) {
|
for (i = WNAF_SIZE_BITS(128, WINDOW_A - 1) - 1; i >= 0; i--) {
|
||||||
int n;
|
int n;
|
||||||
int j;
|
int j;
|
||||||
for (j = 0; j < WINDOW_A - 1; ++j) {
|
for (j = 0; j < WINDOW_A - 1; ++j) {
|
||||||
@ -202,12 +194,10 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
|
|||||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A);
|
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A);
|
||||||
VERIFY_CHECK(n != 0);
|
VERIFY_CHECK(n != 0);
|
||||||
secp256k1_gej_add_ge(r, r, &tmpa);
|
secp256k1_gej_add_ge(r, r, &tmpa);
|
||||||
if (size > 128) {
|
n = wnaf_lam[i];
|
||||||
n = wnaf_lam[i];
|
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A);
|
||||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A);
|
VERIFY_CHECK(n != 0);
|
||||||
VERIFY_CHECK(n != 0);
|
secp256k1_gej_add_ge(r, r, &tmpa);
|
||||||
secp256k1_gej_add_ge(r, r, &tmpa);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -218,17 +208,15 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
|
|||||||
secp256k1_gej_add_ge(&tmpj, r, &tmpa);
|
secp256k1_gej_add_ge(&tmpj, r, &tmpa);
|
||||||
secp256k1_gej_cmov(r, &tmpj, skew_1);
|
secp256k1_gej_cmov(r, &tmpj, skew_1);
|
||||||
|
|
||||||
if (size > 128) {
|
secp256k1_ge_neg(&tmpa, &pre_a_lam[0]);
|
||||||
secp256k1_ge_neg(&tmpa, &pre_a_lam[0]);
|
secp256k1_gej_add_ge(&tmpj, r, &tmpa);
|
||||||
secp256k1_gej_add_ge(&tmpj, r, &tmpa);
|
secp256k1_gej_cmov(r, &tmpj, skew_lam);
|
||||||
secp256k1_gej_cmov(r, &tmpj, skew_lam);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
secp256k1_fe_mul(&r->z, &r->z, &Z);
|
secp256k1_fe_mul(&r->z, &r->z, &Z);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_ecmult_const_xonly(secp256k1_fe* r, const secp256k1_fe *n, const secp256k1_fe *d, const secp256k1_scalar *q, int bits, int known_on_curve) {
|
static int secp256k1_ecmult_const_xonly(secp256k1_fe* r, const secp256k1_fe *n, const secp256k1_fe *d, const secp256k1_scalar *q, int known_on_curve) {
|
||||||
|
|
||||||
/* This algorithm is a generalization of Peter Dettman's technique for
|
/* This algorithm is a generalization of Peter Dettman's technique for
|
||||||
* avoiding the square root in a random-basepoint x-only multiplication
|
* avoiding the square root in a random-basepoint x-only multiplication
|
||||||
@ -346,7 +334,7 @@ static int secp256k1_ecmult_const_xonly(secp256k1_fe* r, const secp256k1_fe *n,
|
|||||||
#ifdef VERIFY
|
#ifdef VERIFY
|
||||||
VERIFY_CHECK(!secp256k1_scalar_is_zero(q));
|
VERIFY_CHECK(!secp256k1_scalar_is_zero(q));
|
||||||
#endif
|
#endif
|
||||||
secp256k1_ecmult_const(&rj, &p, q, bits);
|
secp256k1_ecmult_const(&rj, &p, q);
|
||||||
#ifdef VERIFY
|
#ifdef VERIFY
|
||||||
VERIFY_CHECK(!secp256k1_gej_is_infinity(&rj));
|
VERIFY_CHECK(!secp256k1_gej_is_infinity(&rj));
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,7 +31,7 @@ static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, cons
|
|||||||
secp256k1_fe nums_x;
|
secp256k1_fe nums_x;
|
||||||
secp256k1_ge nums_ge;
|
secp256k1_ge nums_ge;
|
||||||
int r;
|
int r;
|
||||||
r = secp256k1_fe_set_b32(&nums_x, nums_b32);
|
r = secp256k1_fe_set_b32_limit(&nums_x, nums_b32);
|
||||||
(void)r;
|
(void)r;
|
||||||
VERIFY_CHECK(r);
|
VERIFY_CHECK(r);
|
||||||
r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0);
|
r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0);
|
||||||
|
@ -108,7 +108,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
|
|||||||
memset(keydata, 0, sizeof(keydata));
|
memset(keydata, 0, sizeof(keydata));
|
||||||
/* Accept unobservably small non-uniformity. */
|
/* Accept unobservably small non-uniformity. */
|
||||||
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
|
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
|
||||||
overflow = !secp256k1_fe_set_b32(&s, nonce32);
|
overflow = !secp256k1_fe_set_b32_limit(&s, nonce32);
|
||||||
overflow |= secp256k1_fe_is_zero(&s);
|
overflow |= secp256k1_fe_is_zero(&s);
|
||||||
secp256k1_fe_cmov(&s, &secp256k1_fe_one, overflow);
|
secp256k1_fe_cmov(&s, &secp256k1_fe_one, overflow);
|
||||||
/* Randomize the projection to defend against multiplier sidechannels.
|
/* Randomize the projection to defend against multiplier sidechannels.
|
||||||
|
@ -279,9 +279,6 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
|
|||||||
*/
|
*/
|
||||||
tmp = a[np];
|
tmp = a[np];
|
||||||
if (no) {
|
if (no) {
|
||||||
#ifdef VERIFY
|
|
||||||
secp256k1_fe_normalize_var(&Z);
|
|
||||||
#endif
|
|
||||||
secp256k1_gej_rescale(&tmp, &Z);
|
secp256k1_gej_rescale(&tmp, &Z);
|
||||||
}
|
}
|
||||||
secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->pre_a + no * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), &Z, &tmp);
|
secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->pre_a + no * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), &Z, &tmp);
|
||||||
@ -683,7 +680,7 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call
|
|||||||
}
|
}
|
||||||
state_space->ps = (struct secp256k1_pippenger_point_state *) secp256k1_scratch_alloc(error_callback, scratch, entries * sizeof(*state_space->ps));
|
state_space->ps = (struct secp256k1_pippenger_point_state *) secp256k1_scratch_alloc(error_callback, scratch, entries * sizeof(*state_space->ps));
|
||||||
state_space->wnaf_na = (int *) secp256k1_scratch_alloc(error_callback, scratch, entries*(WNAF_SIZE(bucket_window+1)) * sizeof(int));
|
state_space->wnaf_na = (int *) secp256k1_scratch_alloc(error_callback, scratch, entries*(WNAF_SIZE(bucket_window+1)) * sizeof(int));
|
||||||
buckets = (secp256k1_gej *) secp256k1_scratch_alloc(error_callback, scratch, (1<<bucket_window) * sizeof(*buckets));
|
buckets = (secp256k1_gej *) secp256k1_scratch_alloc(error_callback, scratch, ((size_t)1 << bucket_window) * sizeof(*buckets));
|
||||||
if (state_space->ps == NULL || state_space->wnaf_na == NULL || buckets == NULL) {
|
if (state_space->ps == NULL || state_space->wnaf_na == NULL || buckets == NULL) {
|
||||||
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
|
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
|
||||||
return 0;
|
return 0;
|
||||||
|
312
src/field.h
312
src/field.h
@ -7,19 +7,36 @@
|
|||||||
#ifndef SECP256K1_FIELD_H
|
#ifndef SECP256K1_FIELD_H
|
||||||
#define SECP256K1_FIELD_H
|
#define SECP256K1_FIELD_H
|
||||||
|
|
||||||
/** Field element module.
|
|
||||||
*
|
|
||||||
* Field elements can be represented in several ways, but code accessing
|
|
||||||
* it (and implementations) need to take certain properties into account:
|
|
||||||
* - Each field element can be normalized or not.
|
|
||||||
* - Each field element has a magnitude, which represents how far away
|
|
||||||
* its representation is away from normalization. Normalized elements
|
|
||||||
* always have a magnitude of 0 or 1, but a magnitude of 1 doesn't
|
|
||||||
* imply normality.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
/* This file defines the generic interface for working with secp256k1_fe
|
||||||
|
* objects, which represent field elements (integers modulo 2^256 - 2^32 - 977).
|
||||||
|
*
|
||||||
|
* The actual definition of the secp256k1_fe type depends on the chosen field
|
||||||
|
* implementation; see the field_5x52.h and field_10x26.h files for details.
|
||||||
|
*
|
||||||
|
* All secp256k1_fe objects have implicit properties that determine what
|
||||||
|
* operations are permitted on it. These are purely a function of what
|
||||||
|
* secp256k1_fe_ operations are applied on it, generally (implicitly) fixed at
|
||||||
|
* compile time, and do not depend on the chosen field implementation. Despite
|
||||||
|
* that, what these properties actually entail for the field representation
|
||||||
|
* values depends on the chosen field implementation. These properties are:
|
||||||
|
* - magnitude: an integer in [0,32]
|
||||||
|
* - normalized: 0 or 1; normalized=1 implies magnitude <= 1.
|
||||||
|
*
|
||||||
|
* In VERIFY mode, they are materialized explicitly as fields in the struct,
|
||||||
|
* allowing run-time verification of these properties. In that case, the field
|
||||||
|
* implementation also provides a secp256k1_fe_verify routine to verify that
|
||||||
|
* these fields match the run-time value and perform internal consistency
|
||||||
|
* checks. */
|
||||||
|
#ifdef VERIFY
|
||||||
|
# define SECP256K1_FE_VERIFY_FIELDS \
|
||||||
|
int magnitude; \
|
||||||
|
int normalized;
|
||||||
|
#else
|
||||||
|
# define SECP256K1_FE_VERIFY_FIELDS
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(SECP256K1_WIDEMUL_INT128)
|
#if defined(SECP256K1_WIDEMUL_INT128)
|
||||||
#include "field_5x52.h"
|
#include "field_5x52.h"
|
||||||
#elif defined(SECP256K1_WIDEMUL_INT64)
|
#elif defined(SECP256K1_WIDEMUL_INT64)
|
||||||
@ -28,120 +45,295 @@
|
|||||||
#error "Please select wide multiplication implementation"
|
#error "Please select wide multiplication implementation"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef VERIFY
|
||||||
|
/* Magnitude and normalized value for constants. */
|
||||||
|
#define SECP256K1_FE_VERIFY_CONST(d7, d6, d5, d4, d3, d2, d1, d0) \
|
||||||
|
/* Magnitude is 0 for constant 0; 1 otherwise. */ \
|
||||||
|
, (((d7) | (d6) | (d5) | (d4) | (d3) | (d2) | (d1) | (d0)) != 0) \
|
||||||
|
/* Normalized is 1 unless sum(d_i<<(32*i) for i=0..7) exceeds field modulus. */ \
|
||||||
|
, (!(((d7) & (d6) & (d5) & (d4) & (d3) & (d2)) == 0xfffffffful && ((d1) == 0xfffffffful || ((d1) == 0xfffffffe && (d0 >= 0xfffffc2f)))))
|
||||||
|
#else
|
||||||
|
#define SECP256K1_FE_VERIFY_CONST(d7, d6, d5, d4, d3, d2, d1, d0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** This expands to an initializer for a secp256k1_fe valued sum((i*32) * d_i, i=0..7) mod p.
|
||||||
|
*
|
||||||
|
* It has magnitude 1, unless d_i are all 0, in which case the magnitude is 0.
|
||||||
|
* It is normalized, unless sum(2^(i*32) * d_i, i=0..7) >= p.
|
||||||
|
*
|
||||||
|
* SECP256K1_FE_CONST_INNER is provided by the implementation.
|
||||||
|
*/
|
||||||
|
#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)) SECP256K1_FE_VERIFY_CONST((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)) }
|
||||||
|
|
||||||
static const secp256k1_fe secp256k1_fe_one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1);
|
static const secp256k1_fe secp256k1_fe_one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1);
|
||||||
static const secp256k1_fe secp256k1_const_beta = SECP256K1_FE_CONST(
|
static const secp256k1_fe secp256k1_const_beta = SECP256K1_FE_CONST(
|
||||||
0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul,
|
0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul,
|
||||||
0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul
|
0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul
|
||||||
);
|
);
|
||||||
|
|
||||||
/** Normalize a field element. This brings the field element to a canonical representation, reduces
|
#ifndef VERIFY
|
||||||
* its magnitude to 1, and reduces it modulo field size `p`.
|
/* In non-VERIFY mode, we #define the fe operations to be identical to their
|
||||||
|
* internal field implementation, to avoid the potential overhead of a
|
||||||
|
* function call (even though presumably inlinable). */
|
||||||
|
# define secp256k1_fe_normalize secp256k1_fe_impl_normalize
|
||||||
|
# define secp256k1_fe_normalize_weak secp256k1_fe_impl_normalize_weak
|
||||||
|
# define secp256k1_fe_normalize_var secp256k1_fe_impl_normalize_var
|
||||||
|
# define secp256k1_fe_normalizes_to_zero secp256k1_fe_impl_normalizes_to_zero
|
||||||
|
# define secp256k1_fe_normalizes_to_zero_var secp256k1_fe_impl_normalizes_to_zero_var
|
||||||
|
# define secp256k1_fe_set_int secp256k1_fe_impl_set_int
|
||||||
|
# define secp256k1_fe_clear secp256k1_fe_impl_clear
|
||||||
|
# define secp256k1_fe_is_zero secp256k1_fe_impl_is_zero
|
||||||
|
# define secp256k1_fe_is_odd secp256k1_fe_impl_is_odd
|
||||||
|
# define secp256k1_fe_cmp_var secp256k1_fe_impl_cmp_var
|
||||||
|
# define secp256k1_fe_set_b32_mod secp256k1_fe_impl_set_b32_mod
|
||||||
|
# define secp256k1_fe_set_b32_limit secp256k1_fe_impl_set_b32_limit
|
||||||
|
# define secp256k1_fe_get_b32 secp256k1_fe_impl_get_b32
|
||||||
|
# define secp256k1_fe_negate secp256k1_fe_impl_negate
|
||||||
|
# define secp256k1_fe_mul_int secp256k1_fe_impl_mul_int
|
||||||
|
# define secp256k1_fe_add secp256k1_fe_impl_add
|
||||||
|
# define secp256k1_fe_mul secp256k1_fe_impl_mul
|
||||||
|
# define secp256k1_fe_sqr secp256k1_fe_impl_sqr
|
||||||
|
# define secp256k1_fe_cmov secp256k1_fe_impl_cmov
|
||||||
|
# define secp256k1_fe_to_storage secp256k1_fe_impl_to_storage
|
||||||
|
# define secp256k1_fe_from_storage secp256k1_fe_impl_from_storage
|
||||||
|
# define secp256k1_fe_inv secp256k1_fe_impl_inv
|
||||||
|
# define secp256k1_fe_inv_var secp256k1_fe_impl_inv_var
|
||||||
|
# define secp256k1_fe_get_bounds secp256k1_fe_impl_get_bounds
|
||||||
|
# define secp256k1_fe_half secp256k1_fe_impl_half
|
||||||
|
# define secp256k1_fe_add_int secp256k1_fe_impl_add_int
|
||||||
|
# define secp256k1_fe_is_square_var secp256k1_fe_impl_is_square_var
|
||||||
|
#endif /* !defined(VERIFY) */
|
||||||
|
|
||||||
|
/** Normalize a field element.
|
||||||
|
*
|
||||||
|
* On input, r must be a valid field element.
|
||||||
|
* On output, r represents the same value but has normalized=1 and magnitude=1.
|
||||||
*/
|
*/
|
||||||
static void secp256k1_fe_normalize(secp256k1_fe *r);
|
static void secp256k1_fe_normalize(secp256k1_fe *r);
|
||||||
|
|
||||||
/** Weakly normalize a field element: reduce its magnitude to 1, but don't fully normalize. */
|
/** Give a field element magnitude 1.
|
||||||
|
*
|
||||||
|
* On input, r must be a valid field element.
|
||||||
|
* On output, r represents the same value but has magnitude=1. Normalized is unchanged.
|
||||||
|
*/
|
||||||
static void secp256k1_fe_normalize_weak(secp256k1_fe *r);
|
static void secp256k1_fe_normalize_weak(secp256k1_fe *r);
|
||||||
|
|
||||||
/** Normalize a field element, without constant-time guarantee. */
|
/** Normalize a field element, without constant-time guarantee.
|
||||||
|
*
|
||||||
|
* Identical in behavior to secp256k1_fe_normalize, but not constant time in r.
|
||||||
|
*/
|
||||||
static void secp256k1_fe_normalize_var(secp256k1_fe *r);
|
static void secp256k1_fe_normalize_var(secp256k1_fe *r);
|
||||||
|
|
||||||
/** Verify whether a field element represents zero i.e. would normalize to a zero value. */
|
/** Determine whether r represents field element 0.
|
||||||
|
*
|
||||||
|
* On input, r must be a valid field element.
|
||||||
|
* Returns whether r = 0 (mod p).
|
||||||
|
*/
|
||||||
static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r);
|
static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r);
|
||||||
|
|
||||||
/** Verify whether a field element represents zero i.e. would normalize to a zero value,
|
/** Determine whether r represents field element 0, without constant-time guarantee.
|
||||||
* without constant-time guarantee. */
|
*
|
||||||
|
* Identical in behavior to secp256k1_normalizes_to_zero, but not constant time in r.
|
||||||
|
*/
|
||||||
static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r);
|
static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r);
|
||||||
|
|
||||||
/** Set a field element equal to a small (not greater than 0x7FFF), non-negative integer.
|
/** Set a field element to an integer in range [0,0x7FFF].
|
||||||
* Resulting field element is normalized; it has magnitude 0 if a == 0, and magnitude 1 otherwise.
|
*
|
||||||
|
* On input, r does not need to be initialized, a must be in [0,0x7FFF].
|
||||||
|
* On output, r represents value a, is normalized and has magnitude (a!=0).
|
||||||
*/
|
*/
|
||||||
static void secp256k1_fe_set_int(secp256k1_fe *r, int a);
|
static void secp256k1_fe_set_int(secp256k1_fe *r, int a);
|
||||||
|
|
||||||
/** Sets a field element equal to zero, initializing all fields. */
|
/** Set a field element to 0.
|
||||||
|
*
|
||||||
|
* On input, a does not need to be initialized.
|
||||||
|
* On output, a represents 0, is normalized and has magnitude 0.
|
||||||
|
*/
|
||||||
static void secp256k1_fe_clear(secp256k1_fe *a);
|
static void secp256k1_fe_clear(secp256k1_fe *a);
|
||||||
|
|
||||||
/** Verify whether a field element is zero. Requires the input to be normalized. */
|
/** Determine whether a represents field element 0.
|
||||||
|
*
|
||||||
|
* On input, a must be a valid normalized field element.
|
||||||
|
* Returns whether a = 0 (mod p).
|
||||||
|
*
|
||||||
|
* This behaves identical to secp256k1_normalizes_to_zero{,_var}, but requires
|
||||||
|
* normalized input (and is much faster).
|
||||||
|
*/
|
||||||
static int secp256k1_fe_is_zero(const secp256k1_fe *a);
|
static int secp256k1_fe_is_zero(const secp256k1_fe *a);
|
||||||
|
|
||||||
/** Check the "oddness" of a field element. Requires the input to be normalized. */
|
/** Determine whether a (mod p) is odd.
|
||||||
|
*
|
||||||
|
* On input, a must be a valid normalized field element.
|
||||||
|
* Returns (int(a) mod p) & 1.
|
||||||
|
*/
|
||||||
static int secp256k1_fe_is_odd(const secp256k1_fe *a);
|
static int secp256k1_fe_is_odd(const secp256k1_fe *a);
|
||||||
|
|
||||||
/** Compare two field elements. Requires magnitude-1 inputs. */
|
/** Determine whether two field elements are equal.
|
||||||
|
*
|
||||||
|
* On input, a and b must be valid field elements with magnitudes not exceeding
|
||||||
|
* 1 and 31, respectively.
|
||||||
|
* Returns a = b (mod p).
|
||||||
|
*/
|
||||||
static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b);
|
static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b);
|
||||||
|
|
||||||
/** Same as secp256k1_fe_equal, but may be variable time. */
|
/** Determine whether two field elements are equal, without constant-time guarantee.
|
||||||
|
*
|
||||||
|
* Identical in behavior to secp256k1_fe_equal, but not constant time in either a or b.
|
||||||
|
*/
|
||||||
static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b);
|
static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b);
|
||||||
|
|
||||||
/** Compare two field elements. Requires both inputs to be normalized */
|
/** Compare the values represented by 2 field elements, without constant-time guarantee.
|
||||||
|
*
|
||||||
|
* On input, a and b must be valid normalized field elements.
|
||||||
|
* Returns 1 if a > b, -1 if a < b, and 0 if a = b (comparisons are done as integers
|
||||||
|
* in range 0..p-1).
|
||||||
|
*/
|
||||||
static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b);
|
static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b);
|
||||||
|
|
||||||
/** Set a field element equal to 32-byte big endian value. If successful, the resulting field element is normalized. */
|
/** Set a field element equal to a provided 32-byte big endian value, reducing it.
|
||||||
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a);
|
*
|
||||||
|
* On input, r does not need to be initalized. a must be a pointer to an initialized 32-byte array.
|
||||||
|
* On output, r = a (mod p). It will have magnitude 1, and not be normalized.
|
||||||
|
*/
|
||||||
|
static void secp256k1_fe_set_b32_mod(secp256k1_fe *r, const unsigned char *a);
|
||||||
|
|
||||||
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
|
/** Set a field element equal to a provided 32-byte big endian value, checking for overflow.
|
||||||
|
*
|
||||||
|
* On input, r does not need to be initalized. a must be a pointer to an initialized 32-byte array.
|
||||||
|
* On output, r = a if (a < p), it will be normalized with magnitude 1, and 1 is returned.
|
||||||
|
* If a >= p, 0 is returned, and r will be made invalid (and must not be used without overwriting).
|
||||||
|
*/
|
||||||
|
static int secp256k1_fe_set_b32_limit(secp256k1_fe *r, const unsigned char *a);
|
||||||
|
|
||||||
|
/** Convert a field element to 32-byte big endian byte array.
|
||||||
|
* On input, a must be a valid normalized field element, and r a pointer to a 32-byte array.
|
||||||
|
* On output, r = a (mod p).
|
||||||
|
*/
|
||||||
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a);
|
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a);
|
||||||
|
|
||||||
/** Set a field element equal to the additive inverse of another. Takes a maximum magnitude of the input
|
/** Negate a field element.
|
||||||
* as an argument. The magnitude of the output is one higher. */
|
*
|
||||||
|
* On input, r does not need to be initialized. a must be a valid field element with
|
||||||
|
* magnitude not exceeding m. m must be an integer in [0,31].
|
||||||
|
* Performs {r = -a}.
|
||||||
|
* On output, r will not be normalized, and will have magnitude m+1.
|
||||||
|
*/
|
||||||
static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m);
|
static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m);
|
||||||
|
|
||||||
/** Adds a small integer (up to 0x7FFF) to r. The resulting magnitude increases by one. */
|
/** Add a small integer to a field element.
|
||||||
|
*
|
||||||
|
* Performs {r += a}. The magnitude of r increases by 1, and normalized is cleared.
|
||||||
|
* a must be in range [0,0xFFFF].
|
||||||
|
*/
|
||||||
static void secp256k1_fe_add_int(secp256k1_fe *r, int a);
|
static void secp256k1_fe_add_int(secp256k1_fe *r, int a);
|
||||||
|
|
||||||
/** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that
|
/** Multiply a field element with a small integer.
|
||||||
* small integer. */
|
*
|
||||||
|
* On input, r must be a valid field element. a must be an integer in [0,32].
|
||||||
|
* The magnitude of r times a must not exceed 32.
|
||||||
|
* Performs {r *= a}.
|
||||||
|
* On output, r's magnitude is multiplied by a, and r will not be normalized.
|
||||||
|
*/
|
||||||
static void secp256k1_fe_mul_int(secp256k1_fe *r, int a);
|
static void secp256k1_fe_mul_int(secp256k1_fe *r, int a);
|
||||||
|
|
||||||
/** Adds a field element to another. The result has the sum of the inputs' magnitudes as magnitude. */
|
/** Increment a field element by another.
|
||||||
|
*
|
||||||
|
* On input, r and a must be valid field elements, not necessarily normalized.
|
||||||
|
* The sum of their magnitudes must not exceed 32.
|
||||||
|
* Performs {r += a}.
|
||||||
|
* On output, r will not be normalized, and will have magnitude incremented by a's.
|
||||||
|
*/
|
||||||
static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a);
|
static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a);
|
||||||
|
|
||||||
/** Sets a field element to be the product of two others. Requires the inputs' magnitudes to be at most 8.
|
/** Multiply two field elements.
|
||||||
* The output magnitude is 1 (but not guaranteed to be normalized). */
|
*
|
||||||
|
* On input, a and b must be valid field elements; r does not need to be initialized.
|
||||||
|
* r and a may point to the same object, but neither can be equal to b. The magnitudes
|
||||||
|
* of a and b must not exceed 8.
|
||||||
|
* Performs {r = a * b}
|
||||||
|
* On output, r will have magnitude 1, but won't be normalized.
|
||||||
|
*/
|
||||||
static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b);
|
static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b);
|
||||||
|
|
||||||
/** Sets a field element to be the square of another. Requires the input's magnitude to be at most 8.
|
/** Square a field element.
|
||||||
* The output magnitude is 1 (but not guaranteed to be normalized). */
|
*
|
||||||
|
* On input, a must be a valid field element; r does not need to be initialized. The magnitude
|
||||||
|
* of a must not exceed 8.
|
||||||
|
* Performs {r = a**2}
|
||||||
|
* On output, r will have magnitude 1, but won't be normalized.
|
||||||
|
*/
|
||||||
static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a);
|
static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a);
|
||||||
|
|
||||||
/** If a has a square root, it is computed in r and 1 is returned. If a does not
|
/** Compute a square root of a field element.
|
||||||
* have a square root, the root of its negation is computed and 0 is returned.
|
*
|
||||||
* The input's magnitude can be at most 8. The output magnitude is 1 (but not
|
* On input, a must be a valid field element with magnitude<=8; r need not be initialized.
|
||||||
* guaranteed to be normalized). The result in r will always be a square
|
* Performs {r = sqrt(a)} or {r = sqrt(-a)}, whichever exists. The resulting value
|
||||||
* itself. */
|
* represented by r will be a square itself. Variables r and a must not point to the same object.
|
||||||
static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a);
|
* On output, r will have magnitude 1 but will not be normalized.
|
||||||
|
*/
|
||||||
|
static int secp256k1_fe_sqrt(secp256k1_fe * SECP256K1_RESTRICT r, const secp256k1_fe * SECP256K1_RESTRICT a);
|
||||||
|
|
||||||
/** Checks whether a field element is a quadratic residue. */
|
/** Compute the modular inverse of a field element.
|
||||||
static int secp256k1_fe_is_quad_var(const secp256k1_fe *a);
|
*
|
||||||
|
* On input, a must be a valid field element; r need not be initialized.
|
||||||
/** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be
|
* Performs {r = a**(p-2)} (which maps 0 to 0, and every other element to its
|
||||||
* at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */
|
* inverse).
|
||||||
|
* On output, r will have magnitude (a.magnitude != 0) and be normalized.
|
||||||
|
*/
|
||||||
static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a);
|
static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a);
|
||||||
|
|
||||||
/** Potentially faster version of secp256k1_fe_inv, without constant-time guarantee. */
|
/** Compute the modular inverse of a field element, without constant-time guarantee.
|
||||||
|
*
|
||||||
|
* Behaves identically to secp256k1_fe_inv, but is not constant-time in a.
|
||||||
|
*/
|
||||||
static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a);
|
static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a);
|
||||||
|
|
||||||
/** Convert a field element to the storage type. */
|
/** Convert a field element to secp256k1_fe_storage.
|
||||||
|
*
|
||||||
|
* On input, a must be a valid normalized field element.
|
||||||
|
* Performs {r = a}.
|
||||||
|
*/
|
||||||
static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a);
|
static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a);
|
||||||
|
|
||||||
/** Convert a field element back from the storage type. */
|
/** Convert a field element back from secp256k1_fe_storage.
|
||||||
|
*
|
||||||
|
* On input, r need not be initialized.
|
||||||
|
* Performs {r = a}.
|
||||||
|
* On output, r will be normalized and will have magnitude 1.
|
||||||
|
*/
|
||||||
static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a);
|
static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a);
|
||||||
|
|
||||||
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
|
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
|
||||||
static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag);
|
static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag);
|
||||||
|
|
||||||
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
|
/** Conditionally move a field element in constant time.
|
||||||
|
*
|
||||||
|
* On input, both r and a must be valid field elements. Flag must be 0 or 1.
|
||||||
|
* Performs {r = flag ? a : r}.
|
||||||
|
* On output, r's magnitude and normalized will equal a's in case of flag=1, unchanged otherwise.
|
||||||
|
*/
|
||||||
static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag);
|
static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag);
|
||||||
|
|
||||||
/** Halves the value of a field element modulo the field prime. Constant-time.
|
/** Halve the value of a field element modulo the field prime in constant-time.
|
||||||
* For an input magnitude 'm', the output magnitude is set to 'floor(m/2) + 1'.
|
*
|
||||||
* The output is not guaranteed to be normalized, regardless of the input. */
|
* On input, r must be a valid field element.
|
||||||
|
* On output, r will be normalized and have magnitude floor(m/2) + 1 where m is
|
||||||
|
* the magnitude of r on input.
|
||||||
|
*/
|
||||||
static void secp256k1_fe_half(secp256k1_fe *r);
|
static void secp256k1_fe_half(secp256k1_fe *r);
|
||||||
|
|
||||||
/** Sets each limb of 'r' to its upper bound at magnitude 'm'. The output will also have its
|
/** Sets r to a field element with magnitude m, normalized if (and only if) m==0.
|
||||||
* magnitude set to 'm' and is normalized if (and only if) 'm' is zero. */
|
* The value is chosen so that it is likely to trigger edge cases related to
|
||||||
|
* internal overflows. */
|
||||||
static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m);
|
static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m);
|
||||||
|
|
||||||
/** Determine whether a is a square (modulo p). */
|
/** Determine whether a is a square (modulo p).
|
||||||
|
*
|
||||||
|
* On input, a must be a valid field element.
|
||||||
|
*/
|
||||||
static int secp256k1_fe_is_square_var(const secp256k1_fe *a);
|
static int secp256k1_fe_is_square_var(const secp256k1_fe *a);
|
||||||
|
|
||||||
|
/** Check invariants on a field element (no-op unless VERIFY is enabled). */
|
||||||
|
static void secp256k1_fe_verify(const secp256k1_fe *a);
|
||||||
|
|
||||||
#endif /* SECP256K1_FIELD_H */
|
#endif /* SECP256K1_FIELD_H */
|
||||||
|
@ -9,15 +9,28 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/** This field implementation represents the value as 10 uint32_t limbs in base
|
||||||
|
* 2^26. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* X = sum(i=0..9, n[i]*2^(i*26)) mod p
|
/* A field element f represents the sum(i=0..9, f.n[i] << (i*26)) mod p,
|
||||||
* where p = 2^256 - 0x1000003D1
|
* where p is the field modulus, 2^256 - 2^32 - 977.
|
||||||
*/
|
*
|
||||||
|
* The individual limbs f.n[i] can exceed 2^26; the field's magnitude roughly
|
||||||
|
* corresponds to how much excess is allowed. The value
|
||||||
|
* sum(i=0..9, f.n[i] << (i*26)) may exceed p, unless the field element is
|
||||||
|
* normalized. */
|
||||||
uint32_t n[10];
|
uint32_t n[10];
|
||||||
#ifdef VERIFY
|
/*
|
||||||
int magnitude;
|
* Magnitude m requires:
|
||||||
int normalized;
|
* n[i] <= 2 * m * (2^26 - 1) for i=0..8
|
||||||
#endif
|
* n[9] <= 2 * m * (2^22 - 1)
|
||||||
|
*
|
||||||
|
* Normalized requires:
|
||||||
|
* n[i] <= (2^26 - 1) for i=0..8
|
||||||
|
* sum(i=0..9, n[i] << (i*26)) < p
|
||||||
|
* (together these imply n[9] <= 2^22 - 1)
|
||||||
|
*/
|
||||||
|
SECP256K1_FE_VERIFY_FIELDS
|
||||||
} secp256k1_fe;
|
} secp256k1_fe;
|
||||||
|
|
||||||
/* Unpacks a constant into a overlapping multi-limbed FE element. */
|
/* Unpacks a constant into a overlapping multi-limbed FE element. */
|
||||||
@ -34,12 +47,6 @@ typedef struct {
|
|||||||
(((uint32_t)d7) >> 10) \
|
(((uint32_t)d7) >> 10) \
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1}
|
|
||||||
#else
|
|
||||||
#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t n[8];
|
uint32_t n[8];
|
||||||
} secp256k1_fe_storage;
|
} secp256k1_fe_storage;
|
||||||
|
@ -12,47 +12,32 @@
|
|||||||
#include "field.h"
|
#include "field.h"
|
||||||
#include "modinv32_impl.h"
|
#include "modinv32_impl.h"
|
||||||
|
|
||||||
/** See the comment at the top of field_5x52_impl.h for more details.
|
|
||||||
*
|
|
||||||
* Here, we represent field elements as 10 uint32_t's in base 2^26, least significant first,
|
|
||||||
* where limbs can contain >26 bits.
|
|
||||||
* A magnitude M means:
|
|
||||||
* - 2*M*(2^22-1) is the max (inclusive) of the most significant limb
|
|
||||||
* - 2*M*(2^26-1) is the max (inclusive) of the remaining limbs
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef VERIFY
|
#ifdef VERIFY
|
||||||
static void secp256k1_fe_verify(const secp256k1_fe *a) {
|
static void secp256k1_fe_impl_verify(const secp256k1_fe *a) {
|
||||||
const uint32_t *d = a->n;
|
const uint32_t *d = a->n;
|
||||||
int m = a->normalized ? 1 : 2 * a->magnitude, r = 1;
|
int m = a->normalized ? 1 : 2 * a->magnitude;
|
||||||
r &= (d[0] <= 0x3FFFFFFUL * m);
|
VERIFY_CHECK(d[0] <= 0x3FFFFFFUL * m);
|
||||||
r &= (d[1] <= 0x3FFFFFFUL * m);
|
VERIFY_CHECK(d[1] <= 0x3FFFFFFUL * m);
|
||||||
r &= (d[2] <= 0x3FFFFFFUL * m);
|
VERIFY_CHECK(d[2] <= 0x3FFFFFFUL * m);
|
||||||
r &= (d[3] <= 0x3FFFFFFUL * m);
|
VERIFY_CHECK(d[3] <= 0x3FFFFFFUL * m);
|
||||||
r &= (d[4] <= 0x3FFFFFFUL * m);
|
VERIFY_CHECK(d[4] <= 0x3FFFFFFUL * m);
|
||||||
r &= (d[5] <= 0x3FFFFFFUL * m);
|
VERIFY_CHECK(d[5] <= 0x3FFFFFFUL * m);
|
||||||
r &= (d[6] <= 0x3FFFFFFUL * m);
|
VERIFY_CHECK(d[6] <= 0x3FFFFFFUL * m);
|
||||||
r &= (d[7] <= 0x3FFFFFFUL * m);
|
VERIFY_CHECK(d[7] <= 0x3FFFFFFUL * m);
|
||||||
r &= (d[8] <= 0x3FFFFFFUL * m);
|
VERIFY_CHECK(d[8] <= 0x3FFFFFFUL * m);
|
||||||
r &= (d[9] <= 0x03FFFFFUL * m);
|
VERIFY_CHECK(d[9] <= 0x03FFFFFUL * m);
|
||||||
r &= (a->magnitude >= 0);
|
|
||||||
r &= (a->magnitude <= 32);
|
|
||||||
if (a->normalized) {
|
if (a->normalized) {
|
||||||
r &= (a->magnitude <= 1);
|
if (d[9] == 0x03FFFFFUL) {
|
||||||
if (r && (d[9] == 0x03FFFFFUL)) {
|
|
||||||
uint32_t mid = d[8] & d[7] & d[6] & d[5] & d[4] & d[3] & d[2];
|
uint32_t mid = d[8] & d[7] & d[6] & d[5] & d[4] & d[3] & d[2];
|
||||||
if (mid == 0x3FFFFFFUL) {
|
if (mid == 0x3FFFFFFUL) {
|
||||||
r &= ((d[1] + 0x40UL + ((d[0] + 0x3D1UL) >> 26)) <= 0x3FFFFFFUL);
|
VERIFY_CHECK((d[1] + 0x40UL + ((d[0] + 0x3D1UL) >> 26)) <= 0x3FFFFFFUL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VERIFY_CHECK(r == 1);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m) {
|
static void secp256k1_fe_impl_get_bounds(secp256k1_fe *r, int m) {
|
||||||
VERIFY_CHECK(m >= 0);
|
|
||||||
VERIFY_CHECK(m <= 2048);
|
|
||||||
r->n[0] = 0x3FFFFFFUL * 2 * m;
|
r->n[0] = 0x3FFFFFFUL * 2 * m;
|
||||||
r->n[1] = 0x3FFFFFFUL * 2 * m;
|
r->n[1] = 0x3FFFFFFUL * 2 * m;
|
||||||
r->n[2] = 0x3FFFFFFUL * 2 * m;
|
r->n[2] = 0x3FFFFFFUL * 2 * m;
|
||||||
@ -63,14 +48,9 @@ static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m) {
|
|||||||
r->n[7] = 0x3FFFFFFUL * 2 * m;
|
r->n[7] = 0x3FFFFFFUL * 2 * m;
|
||||||
r->n[8] = 0x3FFFFFFUL * 2 * m;
|
r->n[8] = 0x3FFFFFFUL * 2 * m;
|
||||||
r->n[9] = 0x03FFFFFUL * 2 * m;
|
r->n[9] = 0x03FFFFFUL * 2 * m;
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = m;
|
|
||||||
r->normalized = (m == 0);
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_normalize(secp256k1_fe *r) {
|
static void secp256k1_fe_impl_normalize(secp256k1_fe *r) {
|
||||||
uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
|
uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
|
||||||
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
|
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
|
||||||
|
|
||||||
@ -117,15 +97,9 @@ static void secp256k1_fe_normalize(secp256k1_fe *r) {
|
|||||||
|
|
||||||
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
||||||
r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9;
|
r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9;
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = 1;
|
|
||||||
r->normalized = 1;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_normalize_weak(secp256k1_fe *r) {
|
static void secp256k1_fe_impl_normalize_weak(secp256k1_fe *r) {
|
||||||
uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
|
uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
|
||||||
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
|
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
|
||||||
|
|
||||||
@ -149,14 +123,9 @@ static void secp256k1_fe_normalize_weak(secp256k1_fe *r) {
|
|||||||
|
|
||||||
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
||||||
r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9;
|
r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9;
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = 1;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_normalize_var(secp256k1_fe *r) {
|
static void secp256k1_fe_impl_normalize_var(secp256k1_fe *r) {
|
||||||
uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
|
uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
|
||||||
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
|
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
|
||||||
|
|
||||||
@ -204,15 +173,9 @@ static void secp256k1_fe_normalize_var(secp256k1_fe *r) {
|
|||||||
|
|
||||||
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
||||||
r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9;
|
r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9;
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = 1;
|
|
||||||
r->normalized = 1;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r) {
|
static int secp256k1_fe_impl_normalizes_to_zero(const secp256k1_fe *r) {
|
||||||
uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
|
uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
|
||||||
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
|
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
|
||||||
|
|
||||||
@ -241,7 +204,7 @@ static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r) {
|
|||||||
return (z0 == 0) | (z1 == 0x3FFFFFFUL);
|
return (z0 == 0) | (z1 == 0x3FFFFFFUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r) {
|
static int secp256k1_fe_impl_normalizes_to_zero_var(const secp256k1_fe *r) {
|
||||||
uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9;
|
uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9;
|
||||||
uint32_t z0, z1;
|
uint32_t z0, z1;
|
||||||
uint32_t x;
|
uint32_t x;
|
||||||
@ -293,53 +256,29 @@ static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r) {
|
|||||||
return (z0 == 0) | (z1 == 0x3FFFFFFUL);
|
return (z0 == 0) | (z1 == 0x3FFFFFFUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_set_int(secp256k1_fe *r, int a) {
|
||||||
VERIFY_CHECK(0 <= a && a <= 0x7FFF);
|
|
||||||
r->n[0] = a;
|
r->n[0] = a;
|
||||||
r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0;
|
r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0;
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = (a != 0);
|
|
||||||
r->normalized = 1;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) {
|
SECP256K1_INLINE static int secp256k1_fe_impl_is_zero(const secp256k1_fe *a) {
|
||||||
const uint32_t *t = a->n;
|
const uint32_t *t = a->n;
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(a->normalized);
|
|
||||||
secp256k1_fe_verify(a);
|
|
||||||
#endif
|
|
||||||
return (t[0] | t[1] | t[2] | t[3] | t[4] | t[5] | t[6] | t[7] | t[8] | t[9]) == 0;
|
return (t[0] | t[1] | t[2] | t[3] | t[4] | t[5] | t[6] | t[7] | t[8] | t[9]) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) {
|
SECP256K1_INLINE static int secp256k1_fe_impl_is_odd(const secp256k1_fe *a) {
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(a->normalized);
|
|
||||||
secp256k1_fe_verify(a);
|
|
||||||
#endif
|
|
||||||
return a->n[0] & 1;
|
return a->n[0] & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_clear(secp256k1_fe *a) {
|
||||||
int i;
|
int i;
|
||||||
#ifdef VERIFY
|
|
||||||
a->magnitude = 0;
|
|
||||||
a->normalized = 1;
|
|
||||||
#endif
|
|
||||||
for (i=0; i<10; i++) {
|
for (i=0; i<10; i++) {
|
||||||
a->n[i] = 0;
|
a->n[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
|
static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
|
||||||
int i;
|
int i;
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(a->normalized);
|
|
||||||
VERIFY_CHECK(b->normalized);
|
|
||||||
secp256k1_fe_verify(a);
|
|
||||||
secp256k1_fe_verify(b);
|
|
||||||
#endif
|
|
||||||
for (i = 9; i >= 0; i--) {
|
for (i = 9; i >= 0; i--) {
|
||||||
if (a->n[i] > b->n[i]) {
|
if (a->n[i] > b->n[i]) {
|
||||||
return 1;
|
return 1;
|
||||||
@ -351,8 +290,7 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
|
static void secp256k1_fe_impl_set_b32_mod(secp256k1_fe *r, const unsigned char *a) {
|
||||||
int ret;
|
|
||||||
r->n[0] = (uint32_t)a[31] | ((uint32_t)a[30] << 8) | ((uint32_t)a[29] << 16) | ((uint32_t)(a[28] & 0x3) << 24);
|
r->n[0] = (uint32_t)a[31] | ((uint32_t)a[30] << 8) | ((uint32_t)a[29] << 16) | ((uint32_t)(a[28] & 0x3) << 24);
|
||||||
r->n[1] = (uint32_t)((a[28] >> 2) & 0x3f) | ((uint32_t)a[27] << 6) | ((uint32_t)a[26] << 14) | ((uint32_t)(a[25] & 0xf) << 22);
|
r->n[1] = (uint32_t)((a[28] >> 2) & 0x3f) | ((uint32_t)a[27] << 6) | ((uint32_t)a[26] << 14) | ((uint32_t)(a[25] & 0xf) << 22);
|
||||||
r->n[2] = (uint32_t)((a[25] >> 4) & 0xf) | ((uint32_t)a[24] << 4) | ((uint32_t)a[23] << 12) | ((uint32_t)(a[22] & 0x3f) << 20);
|
r->n[2] = (uint32_t)((a[25] >> 4) & 0xf) | ((uint32_t)a[24] << 4) | ((uint32_t)a[23] << 12) | ((uint32_t)(a[22] & 0x3f) << 20);
|
||||||
@ -363,26 +301,15 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
|
|||||||
r->n[7] = (uint32_t)((a[9] >> 6) & 0x3) | ((uint32_t)a[8] << 2) | ((uint32_t)a[7] << 10) | ((uint32_t)a[6] << 18);
|
r->n[7] = (uint32_t)((a[9] >> 6) & 0x3) | ((uint32_t)a[8] << 2) | ((uint32_t)a[7] << 10) | ((uint32_t)a[6] << 18);
|
||||||
r->n[8] = (uint32_t)a[5] | ((uint32_t)a[4] << 8) | ((uint32_t)a[3] << 16) | ((uint32_t)(a[2] & 0x3) << 24);
|
r->n[8] = (uint32_t)a[5] | ((uint32_t)a[4] << 8) | ((uint32_t)a[3] << 16) | ((uint32_t)(a[2] & 0x3) << 24);
|
||||||
r->n[9] = (uint32_t)((a[2] >> 2) & 0x3f) | ((uint32_t)a[1] << 6) | ((uint32_t)a[0] << 14);
|
r->n[9] = (uint32_t)((a[2] >> 2) & 0x3f) | ((uint32_t)a[1] << 6) | ((uint32_t)a[0] << 14);
|
||||||
|
}
|
||||||
|
|
||||||
ret = !((r->n[9] == 0x3FFFFFUL) & ((r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL) & ((r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL));
|
static int secp256k1_fe_impl_set_b32_limit(secp256k1_fe *r, const unsigned char *a) {
|
||||||
#ifdef VERIFY
|
secp256k1_fe_impl_set_b32_mod(r, a);
|
||||||
r->magnitude = 1;
|
return !((r->n[9] == 0x3FFFFFUL) & ((r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL) & ((r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL));
|
||||||
if (ret) {
|
|
||||||
r->normalized = 1;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
} else {
|
|
||||||
r->normalized = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
|
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
|
||||||
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) {
|
static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a) {
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(a->normalized);
|
|
||||||
secp256k1_fe_verify(a);
|
|
||||||
#endif
|
|
||||||
r[0] = (a->n[9] >> 14) & 0xff;
|
r[0] = (a->n[9] >> 14) & 0xff;
|
||||||
r[1] = (a->n[9] >> 6) & 0xff;
|
r[1] = (a->n[9] >> 6) & 0xff;
|
||||||
r[2] = ((a->n[9] & 0x3F) << 2) | ((a->n[8] >> 24) & 0x3);
|
r[2] = ((a->n[9] & 0x3F) << 2) | ((a->n[8] >> 24) & 0x3);
|
||||||
@ -417,15 +344,15 @@ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) {
|
|||||||
r[31] = a->n[0] & 0xff;
|
r[31] = a->n[0] & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
|
||||||
#ifdef VERIFY
|
/* For all legal values of m (0..31), the following properties hold: */
|
||||||
VERIFY_CHECK(a->magnitude <= m);
|
|
||||||
secp256k1_fe_verify(a);
|
|
||||||
VERIFY_CHECK(0x3FFFC2FUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
|
VERIFY_CHECK(0x3FFFC2FUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
|
||||||
VERIFY_CHECK(0x3FFFFBFUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
|
VERIFY_CHECK(0x3FFFFBFUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
|
||||||
VERIFY_CHECK(0x3FFFFFFUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
|
VERIFY_CHECK(0x3FFFFFFUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
|
||||||
VERIFY_CHECK(0x03FFFFFUL * 2 * (m + 1) >= 0x03FFFFFUL * 2 * m);
|
VERIFY_CHECK(0x03FFFFFUL * 2 * (m + 1) >= 0x03FFFFFUL * 2 * m);
|
||||||
#endif
|
|
||||||
|
/* Due to the properties above, the left hand in the subtractions below is never less than
|
||||||
|
* the right hand. */
|
||||||
r->n[0] = 0x3FFFC2FUL * 2 * (m + 1) - a->n[0];
|
r->n[0] = 0x3FFFC2FUL * 2 * (m + 1) - a->n[0];
|
||||||
r->n[1] = 0x3FFFFBFUL * 2 * (m + 1) - a->n[1];
|
r->n[1] = 0x3FFFFBFUL * 2 * (m + 1) - a->n[1];
|
||||||
r->n[2] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[2];
|
r->n[2] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[2];
|
||||||
@ -436,14 +363,9 @@ SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k
|
|||||||
r->n[7] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[7];
|
r->n[7] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[7];
|
||||||
r->n[8] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[8];
|
r->n[8] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[8];
|
||||||
r->n[9] = 0x03FFFFFUL * 2 * (m + 1) - a->n[9];
|
r->n[9] = 0x03FFFFFUL * 2 * (m + 1) - a->n[9];
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = m + 1;
|
|
||||||
r->normalized = 0;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_mul_int(secp256k1_fe *r, int a) {
|
||||||
r->n[0] *= a;
|
r->n[0] *= a;
|
||||||
r->n[1] *= a;
|
r->n[1] *= a;
|
||||||
r->n[2] *= a;
|
r->n[2] *= a;
|
||||||
@ -454,17 +376,9 @@ SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) {
|
|||||||
r->n[7] *= a;
|
r->n[7] *= a;
|
||||||
r->n[8] *= a;
|
r->n[8] *= a;
|
||||||
r->n[9] *= a;
|
r->n[9] *= a;
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude *= a;
|
|
||||||
r->normalized = 0;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_add(secp256k1_fe *r, const secp256k1_fe *a) {
|
||||||
#ifdef VERIFY
|
|
||||||
secp256k1_fe_verify(a);
|
|
||||||
#endif
|
|
||||||
r->n[0] += a->n[0];
|
r->n[0] += a->n[0];
|
||||||
r->n[1] += a->n[1];
|
r->n[1] += a->n[1];
|
||||||
r->n[2] += a->n[2];
|
r->n[2] += a->n[2];
|
||||||
@ -475,25 +389,10 @@ SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_f
|
|||||||
r->n[7] += a->n[7];
|
r->n[7] += a->n[7];
|
||||||
r->n[8] += a->n[8];
|
r->n[8] += a->n[8];
|
||||||
r->n[9] += a->n[9];
|
r->n[9] += a->n[9];
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude += a->magnitude;
|
|
||||||
r->normalized = 0;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_add_int(secp256k1_fe *r, int a) {
|
||||||
#ifdef VERIFY
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
VERIFY_CHECK(a >= 0);
|
|
||||||
VERIFY_CHECK(a <= 0x7FFF);
|
|
||||||
#endif
|
|
||||||
r->n[0] += a;
|
r->n[0] += a;
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude += 1;
|
|
||||||
r->normalized = 0;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(USE_EXTERNAL_ASM)
|
#if defined(USE_EXTERNAL_ASM)
|
||||||
@ -1115,37 +1014,15 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) {
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(a->magnitude <= 8);
|
|
||||||
VERIFY_CHECK(b->magnitude <= 8);
|
|
||||||
secp256k1_fe_verify(a);
|
|
||||||
secp256k1_fe_verify(b);
|
|
||||||
VERIFY_CHECK(r != b);
|
|
||||||
VERIFY_CHECK(a != b);
|
|
||||||
#endif
|
|
||||||
secp256k1_fe_mul_inner(r->n, a->n, b->n);
|
secp256k1_fe_mul_inner(r->n, a->n, b->n);
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = 1;
|
|
||||||
r->normalized = 0;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(a->magnitude <= 8);
|
|
||||||
secp256k1_fe_verify(a);
|
|
||||||
#endif
|
|
||||||
secp256k1_fe_sqr_inner(r->n, a->n);
|
secp256k1_fe_sqr_inner(r->n, a->n);
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = 1;
|
|
||||||
r->normalized = 0;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
|
||||||
uint32_t mask0, mask1;
|
uint32_t mask0, mask1;
|
||||||
volatile int vflag = flag;
|
volatile int vflag = flag;
|
||||||
SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
|
SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
|
||||||
@ -1161,25 +1038,14 @@ static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_
|
|||||||
r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1);
|
r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1);
|
||||||
r->n[8] = (r->n[8] & mask0) | (a->n[8] & mask1);
|
r->n[8] = (r->n[8] & mask0) | (a->n[8] & mask1);
|
||||||
r->n[9] = (r->n[9] & mask0) | (a->n[9] & mask1);
|
r->n[9] = (r->n[9] & mask0) | (a->n[9] & mask1);
|
||||||
#ifdef VERIFY
|
|
||||||
if (flag) {
|
|
||||||
r->magnitude = a->magnitude;
|
|
||||||
r->normalized = a->normalized;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
|
static SECP256K1_INLINE void secp256k1_fe_impl_half(secp256k1_fe *r) {
|
||||||
uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
|
uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
|
||||||
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
|
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
|
||||||
uint32_t one = (uint32_t)1;
|
uint32_t one = (uint32_t)1;
|
||||||
uint32_t mask = -(t0 & one) >> 6;
|
uint32_t mask = -(t0 & one) >> 6;
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
VERIFY_CHECK(r->magnitude < 32);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Bounds analysis (over the rationals).
|
/* Bounds analysis (over the rationals).
|
||||||
*
|
*
|
||||||
* Let m = r->magnitude
|
* Let m = r->magnitude
|
||||||
@ -1226,10 +1092,8 @@ static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
|
|||||||
*
|
*
|
||||||
* Current bounds: t0..t8 <= C * (m/2 + 1/2)
|
* Current bounds: t0..t8 <= C * (m/2 + 1/2)
|
||||||
* t9 <= D * (m/2 + 1/4)
|
* t9 <= D * (m/2 + 1/4)
|
||||||
*/
|
*
|
||||||
|
* Therefore the output magnitude (M) has to be set such that:
|
||||||
#ifdef VERIFY
|
|
||||||
/* Therefore the output magnitude (M) has to be set such that:
|
|
||||||
* t0..t8: C * M >= C * (m/2 + 1/2)
|
* t0..t8: C * M >= C * (m/2 + 1/2)
|
||||||
* t9: D * M >= D * (m/2 + 1/4)
|
* t9: D * M >= D * (m/2 + 1/4)
|
||||||
*
|
*
|
||||||
@ -1239,10 +1103,6 @@ static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
|
|||||||
* and since we want the smallest such integer value for M:
|
* and since we want the smallest such integer value for M:
|
||||||
* M == floor(m/2) + 1
|
* M == floor(m/2) + 1
|
||||||
*/
|
*/
|
||||||
r->magnitude = (r->magnitude >> 1) + 1;
|
|
||||||
r->normalized = 0;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) {
|
static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) {
|
||||||
@ -1261,10 +1121,7 @@ static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r,
|
|||||||
r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1);
|
r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) {
|
static void secp256k1_fe_impl_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) {
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(a->normalized);
|
|
||||||
#endif
|
|
||||||
r->n[0] = a->n[0] | a->n[1] << 26;
|
r->n[0] = a->n[0] | a->n[1] << 26;
|
||||||
r->n[1] = a->n[1] >> 6 | a->n[2] << 20;
|
r->n[1] = a->n[1] >> 6 | a->n[2] << 20;
|
||||||
r->n[2] = a->n[2] >> 12 | a->n[3] << 14;
|
r->n[2] = a->n[2] >> 12 | a->n[3] << 14;
|
||||||
@ -1275,7 +1132,7 @@ static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe
|
|||||||
r->n[7] = a->n[8] >> 16 | a->n[9] << 10;
|
r->n[7] = a->n[8] >> 16 | a->n[9] << 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) {
|
static SECP256K1_INLINE void secp256k1_fe_impl_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) {
|
||||||
r->n[0] = a->n[0] & 0x3FFFFFFUL;
|
r->n[0] = a->n[0] & 0x3FFFFFFUL;
|
||||||
r->n[1] = a->n[0] >> 26 | ((a->n[1] << 6) & 0x3FFFFFFUL);
|
r->n[1] = a->n[0] >> 26 | ((a->n[1] << 6) & 0x3FFFFFFUL);
|
||||||
r->n[2] = a->n[1] >> 20 | ((a->n[2] << 12) & 0x3FFFFFFUL);
|
r->n[2] = a->n[1] >> 20 | ((a->n[2] << 12) & 0x3FFFFFFUL);
|
||||||
@ -1286,11 +1143,6 @@ static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const se
|
|||||||
r->n[7] = a->n[5] >> 22 | ((a->n[6] << 10) & 0x3FFFFFFUL);
|
r->n[7] = a->n[5] >> 22 | ((a->n[6] << 10) & 0x3FFFFFFUL);
|
||||||
r->n[8] = a->n[6] >> 16 | ((a->n[7] << 16) & 0x3FFFFFFUL);
|
r->n[8] = a->n[6] >> 16 | ((a->n[7] << 16) & 0x3FFFFFFUL);
|
||||||
r->n[9] = a->n[7] >> 10;
|
r->n[9] = a->n[7] >> 10;
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = 1;
|
|
||||||
r->normalized = 1;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_from_signed30(secp256k1_fe *r, const secp256k1_modinv32_signed30 *a) {
|
static void secp256k1_fe_from_signed30(secp256k1_fe *r, const secp256k1_modinv32_signed30 *a) {
|
||||||
@ -1321,12 +1173,6 @@ static void secp256k1_fe_from_signed30(secp256k1_fe *r, const secp256k1_modinv32
|
|||||||
r->n[7] = (a6 >> 2 ) & M26;
|
r->n[7] = (a6 >> 2 ) & M26;
|
||||||
r->n[8] = (a6 >> 28 | a7 << 2) & M26;
|
r->n[8] = (a6 >> 28 | a7 << 2) & M26;
|
||||||
r->n[9] = (a7 >> 24 | a8 << 6);
|
r->n[9] = (a7 >> 24 | a8 << 6);
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = 1;
|
|
||||||
r->normalized = 1;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_to_signed30(secp256k1_modinv32_signed30 *r, const secp256k1_fe *a) {
|
static void secp256k1_fe_to_signed30(secp256k1_modinv32_signed30 *r, const secp256k1_fe *a) {
|
||||||
@ -1334,10 +1180,6 @@ static void secp256k1_fe_to_signed30(secp256k1_modinv32_signed30 *r, const secp2
|
|||||||
const uint64_t a0 = a->n[0], a1 = a->n[1], a2 = a->n[2], a3 = a->n[3], a4 = a->n[4],
|
const uint64_t a0 = a->n[0], a1 = a->n[1], a2 = a->n[2], a3 = a->n[3], a4 = a->n[4],
|
||||||
a5 = a->n[5], a6 = a->n[6], a7 = a->n[7], a8 = a->n[8], a9 = a->n[9];
|
a5 = a->n[5], a6 = a->n[6], a7 = a->n[7], a8 = a->n[8], a9 = a->n[9];
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(a->normalized);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
r->v[0] = (a0 | a1 << 26) & M30;
|
r->v[0] = (a0 | a1 << 26) & M30;
|
||||||
r->v[1] = (a1 >> 4 | a2 << 22) & M30;
|
r->v[1] = (a1 >> 4 | a2 << 22) & M30;
|
||||||
r->v[2] = (a2 >> 8 | a3 << 18) & M30;
|
r->v[2] = (a2 >> 8 | a3 << 18) & M30;
|
||||||
@ -1355,37 +1197,27 @@ static const secp256k1_modinv32_modinfo secp256k1_const_modinfo_fe = {
|
|||||||
0x2DDACACFL
|
0x2DDACACFL
|
||||||
};
|
};
|
||||||
|
|
||||||
static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *x) {
|
static void secp256k1_fe_impl_inv(secp256k1_fe *r, const secp256k1_fe *x) {
|
||||||
secp256k1_fe tmp;
|
secp256k1_fe tmp = *x;
|
||||||
secp256k1_modinv32_signed30 s;
|
secp256k1_modinv32_signed30 s;
|
||||||
|
|
||||||
tmp = *x;
|
|
||||||
secp256k1_fe_normalize(&tmp);
|
secp256k1_fe_normalize(&tmp);
|
||||||
secp256k1_fe_to_signed30(&s, &tmp);
|
secp256k1_fe_to_signed30(&s, &tmp);
|
||||||
secp256k1_modinv32(&s, &secp256k1_const_modinfo_fe);
|
secp256k1_modinv32(&s, &secp256k1_const_modinfo_fe);
|
||||||
secp256k1_fe_from_signed30(r, &s);
|
secp256k1_fe_from_signed30(r, &s);
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == secp256k1_fe_normalizes_to_zero(&tmp));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *x) {
|
static void secp256k1_fe_impl_inv_var(secp256k1_fe *r, const secp256k1_fe *x) {
|
||||||
secp256k1_fe tmp;
|
secp256k1_fe tmp = *x;
|
||||||
secp256k1_modinv32_signed30 s;
|
secp256k1_modinv32_signed30 s;
|
||||||
|
|
||||||
tmp = *x;
|
|
||||||
secp256k1_fe_normalize_var(&tmp);
|
secp256k1_fe_normalize_var(&tmp);
|
||||||
secp256k1_fe_to_signed30(&s, &tmp);
|
secp256k1_fe_to_signed30(&s, &tmp);
|
||||||
secp256k1_modinv32_var(&s, &secp256k1_const_modinfo_fe);
|
secp256k1_modinv32_var(&s, &secp256k1_const_modinfo_fe);
|
||||||
secp256k1_fe_from_signed30(r, &s);
|
secp256k1_fe_from_signed30(r, &s);
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == secp256k1_fe_normalizes_to_zero(&tmp));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_fe_is_square_var(const secp256k1_fe *x) {
|
static int secp256k1_fe_impl_is_square_var(const secp256k1_fe *x) {
|
||||||
secp256k1_fe tmp;
|
secp256k1_fe tmp;
|
||||||
secp256k1_modinv32_signed30 s;
|
secp256k1_modinv32_signed30 s;
|
||||||
int jac, ret;
|
int jac, ret;
|
||||||
@ -1403,10 +1235,6 @@ static int secp256k1_fe_is_square_var(const secp256k1_fe *x) {
|
|||||||
secp256k1_fe dummy;
|
secp256k1_fe dummy;
|
||||||
ret = secp256k1_fe_sqrt(&dummy, &tmp);
|
ret = secp256k1_fe_sqrt(&dummy, &tmp);
|
||||||
} else {
|
} else {
|
||||||
#ifdef VERIFY
|
|
||||||
secp256k1_fe dummy;
|
|
||||||
VERIFY_CHECK(jac == 2*secp256k1_fe_sqrt(&dummy, &tmp) - 1);
|
|
||||||
#endif
|
|
||||||
ret = jac >= 0;
|
ret = jac >= 0;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -9,15 +9,28 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/** This field implementation represents the value as 5 uint64_t limbs in base
|
||||||
|
* 2^52. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* X = sum(i=0..4, n[i]*2^(i*52)) mod p
|
/* A field element f represents the sum(i=0..4, f.n[i] << (i*52)) mod p,
|
||||||
* where p = 2^256 - 0x1000003D1
|
* where p is the field modulus, 2^256 - 2^32 - 977.
|
||||||
*/
|
*
|
||||||
|
* The individual limbs f.n[i] can exceed 2^52; the field's magnitude roughly
|
||||||
|
* corresponds to how much excess is allowed. The value
|
||||||
|
* sum(i=0..4, f.n[i] << (i*52)) may exceed p, unless the field element is
|
||||||
|
* normalized. */
|
||||||
uint64_t n[5];
|
uint64_t n[5];
|
||||||
#ifdef VERIFY
|
/*
|
||||||
int magnitude;
|
* Magnitude m requires:
|
||||||
int normalized;
|
* n[i] <= 2 * m * (2^52 - 1) for i=0..3
|
||||||
#endif
|
* n[4] <= 2 * m * (2^48 - 1)
|
||||||
|
*
|
||||||
|
* Normalized requires:
|
||||||
|
* n[i] <= (2^52 - 1) for i=0..3
|
||||||
|
* sum(i=0..4, n[i] << (i*52)) < p
|
||||||
|
* (together these imply n[4] <= 2^48 - 1)
|
||||||
|
*/
|
||||||
|
SECP256K1_FE_VERIFY_FIELDS
|
||||||
} secp256k1_fe;
|
} secp256k1_fe;
|
||||||
|
|
||||||
/* Unpacks a constant into a overlapping multi-limbed FE element. */
|
/* Unpacks a constant into a overlapping multi-limbed FE element. */
|
||||||
@ -29,12 +42,6 @@ typedef struct {
|
|||||||
((uint64_t)(d6) >> 16) | (((uint64_t)(d7)) << 16) \
|
((uint64_t)(d6) >> 16) | (((uint64_t)(d7)) << 16) \
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1}
|
|
||||||
#else
|
|
||||||
#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t n[4];
|
uint64_t n[4];
|
||||||
} secp256k1_fe_storage;
|
} secp256k1_fe_storage;
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#ifndef SECP256K1_FIELD_INNER5X52_IMPL_H
|
#ifndef SECP256K1_FIELD_INNER5X52_IMPL_H
|
||||||
#define SECP256K1_FIELD_INNER5X52_IMPL_H
|
#define SECP256K1_FIELD_INNER5X52_IMPL_H
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
|
SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
|
||||||
/**
|
/**
|
||||||
* Registers: rdx:rax = multiplication accumulator
|
* Registers: rdx:rax = multiplication accumulator
|
||||||
|
@ -18,59 +18,33 @@
|
|||||||
#include "field_5x52_int128_impl.h"
|
#include "field_5x52_int128_impl.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F,
|
|
||||||
* represented as 5 uint64_t's in base 2^52, least significant first. Note that the limbs are allowed to
|
|
||||||
* contain >52 bits each.
|
|
||||||
*
|
|
||||||
* Each field element has a 'magnitude' associated with it. Internally, a magnitude M means:
|
|
||||||
* - 2*M*(2^48-1) is the max (inclusive) of the most significant limb
|
|
||||||
* - 2*M*(2^52-1) is the max (inclusive) of the remaining limbs
|
|
||||||
*
|
|
||||||
* Operations have different rules for propagating magnitude to their outputs. If an operation takes a
|
|
||||||
* magnitude M as a parameter, that means the magnitude of input field elements can be at most M (inclusive).
|
|
||||||
*
|
|
||||||
* Each field element also has a 'normalized' flag. A field element is normalized if its magnitude is either
|
|
||||||
* 0 or 1, and its value is already reduced modulo the order of the field.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef VERIFY
|
#ifdef VERIFY
|
||||||
static void secp256k1_fe_verify(const secp256k1_fe *a) {
|
static void secp256k1_fe_impl_verify(const secp256k1_fe *a) {
|
||||||
const uint64_t *d = a->n;
|
const uint64_t *d = a->n;
|
||||||
int m = a->normalized ? 1 : 2 * a->magnitude, r = 1;
|
int m = a->normalized ? 1 : 2 * a->magnitude;
|
||||||
/* secp256k1 'p' value defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */
|
/* secp256k1 'p' value defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */
|
||||||
r &= (d[0] <= 0xFFFFFFFFFFFFFULL * m);
|
VERIFY_CHECK(d[0] <= 0xFFFFFFFFFFFFFULL * m);
|
||||||
r &= (d[1] <= 0xFFFFFFFFFFFFFULL * m);
|
VERIFY_CHECK(d[1] <= 0xFFFFFFFFFFFFFULL * m);
|
||||||
r &= (d[2] <= 0xFFFFFFFFFFFFFULL * m);
|
VERIFY_CHECK(d[2] <= 0xFFFFFFFFFFFFFULL * m);
|
||||||
r &= (d[3] <= 0xFFFFFFFFFFFFFULL * m);
|
VERIFY_CHECK(d[3] <= 0xFFFFFFFFFFFFFULL * m);
|
||||||
r &= (d[4] <= 0x0FFFFFFFFFFFFULL * m);
|
VERIFY_CHECK(d[4] <= 0x0FFFFFFFFFFFFULL * m);
|
||||||
r &= (a->magnitude >= 0);
|
|
||||||
r &= (a->magnitude <= 2048);
|
|
||||||
if (a->normalized) {
|
if (a->normalized) {
|
||||||
r &= (a->magnitude <= 1);
|
if ((d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) {
|
||||||
if (r && (d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) {
|
VERIFY_CHECK(d[0] < 0xFFFFEFFFFFC2FULL);
|
||||||
r &= (d[0] < 0xFFFFEFFFFFC2FULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VERIFY_CHECK(r == 1);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m) {
|
static void secp256k1_fe_impl_get_bounds(secp256k1_fe *r, int m) {
|
||||||
VERIFY_CHECK(m >= 0);
|
|
||||||
VERIFY_CHECK(m <= 2048);
|
|
||||||
r->n[0] = 0xFFFFFFFFFFFFFULL * 2 * m;
|
r->n[0] = 0xFFFFFFFFFFFFFULL * 2 * m;
|
||||||
r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * m;
|
r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * m;
|
||||||
r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * m;
|
r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * m;
|
||||||
r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * m;
|
r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * m;
|
||||||
r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * m;
|
r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * m;
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = m;
|
|
||||||
r->normalized = (m == 0);
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_normalize(secp256k1_fe *r) {
|
static void secp256k1_fe_impl_normalize(secp256k1_fe *r) {
|
||||||
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
||||||
|
|
||||||
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
|
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
|
||||||
@ -105,15 +79,9 @@ static void secp256k1_fe_normalize(secp256k1_fe *r) {
|
|||||||
t4 &= 0x0FFFFFFFFFFFFULL;
|
t4 &= 0x0FFFFFFFFFFFFULL;
|
||||||
|
|
||||||
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = 1;
|
|
||||||
r->normalized = 1;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_normalize_weak(secp256k1_fe *r) {
|
static void secp256k1_fe_impl_normalize_weak(secp256k1_fe *r) {
|
||||||
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
||||||
|
|
||||||
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
|
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
|
||||||
@ -130,14 +98,9 @@ static void secp256k1_fe_normalize_weak(secp256k1_fe *r) {
|
|||||||
VERIFY_CHECK(t4 >> 49 == 0);
|
VERIFY_CHECK(t4 >> 49 == 0);
|
||||||
|
|
||||||
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = 1;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_normalize_var(secp256k1_fe *r) {
|
static void secp256k1_fe_impl_normalize_var(secp256k1_fe *r) {
|
||||||
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
||||||
|
|
||||||
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
|
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
|
||||||
@ -173,15 +136,9 @@ static void secp256k1_fe_normalize_var(secp256k1_fe *r) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = 1;
|
|
||||||
r->normalized = 1;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r) {
|
static int secp256k1_fe_impl_normalizes_to_zero(const secp256k1_fe *r) {
|
||||||
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
||||||
|
|
||||||
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
|
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
|
||||||
@ -204,7 +161,7 @@ static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r) {
|
|||||||
return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL);
|
return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r) {
|
static int secp256k1_fe_impl_normalizes_to_zero_var(const secp256k1_fe *r) {
|
||||||
uint64_t t0, t1, t2, t3, t4;
|
uint64_t t0, t1, t2, t3, t4;
|
||||||
uint64_t z0, z1;
|
uint64_t z0, z1;
|
||||||
uint64_t x;
|
uint64_t x;
|
||||||
@ -245,53 +202,29 @@ static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r) {
|
|||||||
return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL);
|
return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_set_int(secp256k1_fe *r, int a) {
|
||||||
VERIFY_CHECK(0 <= a && a <= 0x7FFF);
|
|
||||||
r->n[0] = a;
|
r->n[0] = a;
|
||||||
r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
|
r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = (a != 0);
|
|
||||||
r->normalized = 1;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) {
|
SECP256K1_INLINE static int secp256k1_fe_impl_is_zero(const secp256k1_fe *a) {
|
||||||
const uint64_t *t = a->n;
|
const uint64_t *t = a->n;
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(a->normalized);
|
|
||||||
secp256k1_fe_verify(a);
|
|
||||||
#endif
|
|
||||||
return (t[0] | t[1] | t[2] | t[3] | t[4]) == 0;
|
return (t[0] | t[1] | t[2] | t[3] | t[4]) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) {
|
SECP256K1_INLINE static int secp256k1_fe_impl_is_odd(const secp256k1_fe *a) {
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(a->normalized);
|
|
||||||
secp256k1_fe_verify(a);
|
|
||||||
#endif
|
|
||||||
return a->n[0] & 1;
|
return a->n[0] & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_clear(secp256k1_fe *a) {
|
||||||
int i;
|
int i;
|
||||||
#ifdef VERIFY
|
|
||||||
a->magnitude = 0;
|
|
||||||
a->normalized = 1;
|
|
||||||
#endif
|
|
||||||
for (i=0; i<5; i++) {
|
for (i=0; i<5; i++) {
|
||||||
a->n[i] = 0;
|
a->n[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
|
static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
|
||||||
int i;
|
int i;
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(a->normalized);
|
|
||||||
VERIFY_CHECK(b->normalized);
|
|
||||||
secp256k1_fe_verify(a);
|
|
||||||
secp256k1_fe_verify(b);
|
|
||||||
#endif
|
|
||||||
for (i = 4; i >= 0; i--) {
|
for (i = 4; i >= 0; i--) {
|
||||||
if (a->n[i] > b->n[i]) {
|
if (a->n[i] > b->n[i]) {
|
||||||
return 1;
|
return 1;
|
||||||
@ -303,8 +236,7 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
|
static void secp256k1_fe_impl_set_b32_mod(secp256k1_fe *r, const unsigned char *a) {
|
||||||
int ret;
|
|
||||||
r->n[0] = (uint64_t)a[31]
|
r->n[0] = (uint64_t)a[31]
|
||||||
| ((uint64_t)a[30] << 8)
|
| ((uint64_t)a[30] << 8)
|
||||||
| ((uint64_t)a[29] << 16)
|
| ((uint64_t)a[29] << 16)
|
||||||
@ -339,25 +271,15 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
|
|||||||
| ((uint64_t)a[2] << 24)
|
| ((uint64_t)a[2] << 24)
|
||||||
| ((uint64_t)a[1] << 32)
|
| ((uint64_t)a[1] << 32)
|
||||||
| ((uint64_t)a[0] << 40);
|
| ((uint64_t)a[0] << 40);
|
||||||
ret = !((r->n[4] == 0x0FFFFFFFFFFFFULL) & ((r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL) & (r->n[0] >= 0xFFFFEFFFFFC2FULL));
|
}
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = 1;
|
static int secp256k1_fe_impl_set_b32_limit(secp256k1_fe *r, const unsigned char *a) {
|
||||||
if (ret) {
|
secp256k1_fe_impl_set_b32_mod(r, a);
|
||||||
r->normalized = 1;
|
return !((r->n[4] == 0x0FFFFFFFFFFFFULL) & ((r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL) & (r->n[0] >= 0xFFFFEFFFFFC2FULL));
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
} else {
|
|
||||||
r->normalized = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
|
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
|
||||||
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) {
|
static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a) {
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(a->normalized);
|
|
||||||
secp256k1_fe_verify(a);
|
|
||||||
#endif
|
|
||||||
r[0] = (a->n[4] >> 40) & 0xFF;
|
r[0] = (a->n[4] >> 40) & 0xFF;
|
||||||
r[1] = (a->n[4] >> 32) & 0xFF;
|
r[1] = (a->n[4] >> 32) & 0xFF;
|
||||||
r[2] = (a->n[4] >> 24) & 0xFF;
|
r[2] = (a->n[4] >> 24) & 0xFF;
|
||||||
@ -392,100 +314,50 @@ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) {
|
|||||||
r[31] = a->n[0] & 0xFF;
|
r[31] = a->n[0] & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
|
||||||
#ifdef VERIFY
|
/* For all legal values of m (0..31), the following properties hold: */
|
||||||
VERIFY_CHECK(a->magnitude <= m);
|
|
||||||
secp256k1_fe_verify(a);
|
|
||||||
VERIFY_CHECK(0xFFFFEFFFFFC2FULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m);
|
VERIFY_CHECK(0xFFFFEFFFFFC2FULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m);
|
||||||
VERIFY_CHECK(0xFFFFFFFFFFFFFULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m);
|
VERIFY_CHECK(0xFFFFFFFFFFFFFULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m);
|
||||||
VERIFY_CHECK(0x0FFFFFFFFFFFFULL * 2 * (m + 1) >= 0x0FFFFFFFFFFFFULL * 2 * m);
|
VERIFY_CHECK(0x0FFFFFFFFFFFFULL * 2 * (m + 1) >= 0x0FFFFFFFFFFFFULL * 2 * m);
|
||||||
#endif
|
|
||||||
|
/* Due to the properties above, the left hand in the subtractions below is never less than
|
||||||
|
* the right hand. */
|
||||||
r->n[0] = 0xFFFFEFFFFFC2FULL * 2 * (m + 1) - a->n[0];
|
r->n[0] = 0xFFFFEFFFFFC2FULL * 2 * (m + 1) - a->n[0];
|
||||||
r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[1];
|
r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[1];
|
||||||
r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[2];
|
r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[2];
|
||||||
r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[3];
|
r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[3];
|
||||||
r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4];
|
r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4];
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = m + 1;
|
|
||||||
r->normalized = 0;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_mul_int(secp256k1_fe *r, int a) {
|
||||||
r->n[0] *= a;
|
r->n[0] *= a;
|
||||||
r->n[1] *= a;
|
r->n[1] *= a;
|
||||||
r->n[2] *= a;
|
r->n[2] *= a;
|
||||||
r->n[3] *= a;
|
r->n[3] *= a;
|
||||||
r->n[4] *= a;
|
r->n[4] *= a;
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude *= a;
|
|
||||||
r->normalized = 0;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_add_int(secp256k1_fe *r, int a) {
|
||||||
#ifdef VERIFY
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
VERIFY_CHECK(a >= 0);
|
|
||||||
VERIFY_CHECK(a <= 0x7FFF);
|
|
||||||
#endif
|
|
||||||
r->n[0] += a;
|
r->n[0] += a;
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude += 1;
|
|
||||||
r->normalized = 0;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_add(secp256k1_fe *r, const secp256k1_fe *a) {
|
||||||
#ifdef VERIFY
|
|
||||||
secp256k1_fe_verify(a);
|
|
||||||
#endif
|
|
||||||
r->n[0] += a->n[0];
|
r->n[0] += a->n[0];
|
||||||
r->n[1] += a->n[1];
|
r->n[1] += a->n[1];
|
||||||
r->n[2] += a->n[2];
|
r->n[2] += a->n[2];
|
||||||
r->n[3] += a->n[3];
|
r->n[3] += a->n[3];
|
||||||
r->n[4] += a->n[4];
|
r->n[4] += a->n[4];
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude += a->magnitude;
|
|
||||||
r->normalized = 0;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) {
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(a->magnitude <= 8);
|
|
||||||
VERIFY_CHECK(b->magnitude <= 8);
|
|
||||||
secp256k1_fe_verify(a);
|
|
||||||
secp256k1_fe_verify(b);
|
|
||||||
VERIFY_CHECK(r != b);
|
|
||||||
VERIFY_CHECK(a != b);
|
|
||||||
#endif
|
|
||||||
secp256k1_fe_mul_inner(r->n, a->n, b->n);
|
secp256k1_fe_mul_inner(r->n, a->n, b->n);
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = 1;
|
|
||||||
r->normalized = 0;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(a->magnitude <= 8);
|
|
||||||
secp256k1_fe_verify(a);
|
|
||||||
#endif
|
|
||||||
secp256k1_fe_sqr_inner(r->n, a->n);
|
secp256k1_fe_sqr_inner(r->n, a->n);
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = 1;
|
|
||||||
r->normalized = 0;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
|
SECP256K1_INLINE static void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
|
||||||
uint64_t mask0, mask1;
|
uint64_t mask0, mask1;
|
||||||
volatile int vflag = flag;
|
volatile int vflag = flag;
|
||||||
SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
|
SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
|
||||||
@ -496,24 +368,13 @@ static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_
|
|||||||
r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1);
|
r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1);
|
||||||
r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1);
|
r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1);
|
||||||
r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1);
|
r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1);
|
||||||
#ifdef VERIFY
|
|
||||||
if (flag) {
|
|
||||||
r->magnitude = a->magnitude;
|
|
||||||
r->normalized = a->normalized;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
|
static SECP256K1_INLINE void secp256k1_fe_impl_half(secp256k1_fe *r) {
|
||||||
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
||||||
uint64_t one = (uint64_t)1;
|
uint64_t one = (uint64_t)1;
|
||||||
uint64_t mask = -(t0 & one) >> 12;
|
uint64_t mask = -(t0 & one) >> 12;
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
VERIFY_CHECK(r->magnitude < 32);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Bounds analysis (over the rationals).
|
/* Bounds analysis (over the rationals).
|
||||||
*
|
*
|
||||||
* Let m = r->magnitude
|
* Let m = r->magnitude
|
||||||
@ -550,10 +411,8 @@ static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
|
|||||||
*
|
*
|
||||||
* Current bounds: t0..t3 <= C * (m/2 + 1/2)
|
* Current bounds: t0..t3 <= C * (m/2 + 1/2)
|
||||||
* t4 <= D * (m/2 + 1/4)
|
* t4 <= D * (m/2 + 1/4)
|
||||||
*/
|
*
|
||||||
|
* Therefore the output magnitude (M) has to be set such that:
|
||||||
#ifdef VERIFY
|
|
||||||
/* Therefore the output magnitude (M) has to be set such that:
|
|
||||||
* t0..t3: C * M >= C * (m/2 + 1/2)
|
* t0..t3: C * M >= C * (m/2 + 1/2)
|
||||||
* t4: D * M >= D * (m/2 + 1/4)
|
* t4: D * M >= D * (m/2 + 1/4)
|
||||||
*
|
*
|
||||||
@ -563,10 +422,6 @@ static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
|
|||||||
* and since we want the smallest such integer value for M:
|
* and since we want the smallest such integer value for M:
|
||||||
* M == floor(m/2) + 1
|
* M == floor(m/2) + 1
|
||||||
*/
|
*/
|
||||||
r->magnitude = (r->magnitude >> 1) + 1;
|
|
||||||
r->normalized = 0;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) {
|
static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) {
|
||||||
@ -581,27 +436,19 @@ static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r,
|
|||||||
r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1);
|
r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) {
|
static void secp256k1_fe_impl_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) {
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(a->normalized);
|
|
||||||
#endif
|
|
||||||
r->n[0] = a->n[0] | a->n[1] << 52;
|
r->n[0] = a->n[0] | a->n[1] << 52;
|
||||||
r->n[1] = a->n[1] >> 12 | a->n[2] << 40;
|
r->n[1] = a->n[1] >> 12 | a->n[2] << 40;
|
||||||
r->n[2] = a->n[2] >> 24 | a->n[3] << 28;
|
r->n[2] = a->n[2] >> 24 | a->n[3] << 28;
|
||||||
r->n[3] = a->n[3] >> 36 | a->n[4] << 16;
|
r->n[3] = a->n[3] >> 36 | a->n[4] << 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) {
|
static SECP256K1_INLINE void secp256k1_fe_impl_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) {
|
||||||
r->n[0] = a->n[0] & 0xFFFFFFFFFFFFFULL;
|
r->n[0] = a->n[0] & 0xFFFFFFFFFFFFFULL;
|
||||||
r->n[1] = a->n[0] >> 52 | ((a->n[1] << 12) & 0xFFFFFFFFFFFFFULL);
|
r->n[1] = a->n[0] >> 52 | ((a->n[1] << 12) & 0xFFFFFFFFFFFFFULL);
|
||||||
r->n[2] = a->n[1] >> 40 | ((a->n[2] << 24) & 0xFFFFFFFFFFFFFULL);
|
r->n[2] = a->n[1] >> 40 | ((a->n[2] << 24) & 0xFFFFFFFFFFFFFULL);
|
||||||
r->n[3] = a->n[2] >> 28 | ((a->n[3] << 36) & 0xFFFFFFFFFFFFFULL);
|
r->n[3] = a->n[2] >> 28 | ((a->n[3] << 36) & 0xFFFFFFFFFFFFFULL);
|
||||||
r->n[4] = a->n[3] >> 16;
|
r->n[4] = a->n[3] >> 16;
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = 1;
|
|
||||||
r->normalized = 1;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_from_signed62(secp256k1_fe *r, const secp256k1_modinv64_signed62 *a) {
|
static void secp256k1_fe_from_signed62(secp256k1_fe *r, const secp256k1_modinv64_signed62 *a) {
|
||||||
@ -622,22 +469,12 @@ static void secp256k1_fe_from_signed62(secp256k1_fe *r, const secp256k1_modinv64
|
|||||||
r->n[2] = (a1 >> 42 | a2 << 20) & M52;
|
r->n[2] = (a1 >> 42 | a2 << 20) & M52;
|
||||||
r->n[3] = (a2 >> 32 | a3 << 30) & M52;
|
r->n[3] = (a2 >> 32 | a3 << 30) & M52;
|
||||||
r->n[4] = (a3 >> 22 | a4 << 40);
|
r->n[4] = (a3 >> 22 | a4 << 40);
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
r->magnitude = 1;
|
|
||||||
r->normalized = 1;
|
|
||||||
secp256k1_fe_verify(r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_to_signed62(secp256k1_modinv64_signed62 *r, const secp256k1_fe *a) {
|
static void secp256k1_fe_to_signed62(secp256k1_modinv64_signed62 *r, const secp256k1_fe *a) {
|
||||||
const uint64_t M62 = UINT64_MAX >> 2;
|
const uint64_t M62 = UINT64_MAX >> 2;
|
||||||
const uint64_t a0 = a->n[0], a1 = a->n[1], a2 = a->n[2], a3 = a->n[3], a4 = a->n[4];
|
const uint64_t a0 = a->n[0], a1 = a->n[1], a2 = a->n[2], a3 = a->n[3], a4 = a->n[4];
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(a->normalized);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
r->v[0] = (a0 | a1 << 52) & M62;
|
r->v[0] = (a0 | a1 << 52) & M62;
|
||||||
r->v[1] = (a1 >> 10 | a2 << 42) & M62;
|
r->v[1] = (a1 >> 10 | a2 << 42) & M62;
|
||||||
r->v[2] = (a2 >> 20 | a3 << 32) & M62;
|
r->v[2] = (a2 >> 20 | a3 << 32) & M62;
|
||||||
@ -650,37 +487,27 @@ static const secp256k1_modinv64_modinfo secp256k1_const_modinfo_fe = {
|
|||||||
0x27C7F6E22DDACACFLL
|
0x27C7F6E22DDACACFLL
|
||||||
};
|
};
|
||||||
|
|
||||||
static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *x) {
|
static void secp256k1_fe_impl_inv(secp256k1_fe *r, const secp256k1_fe *x) {
|
||||||
secp256k1_fe tmp;
|
secp256k1_fe tmp = *x;
|
||||||
secp256k1_modinv64_signed62 s;
|
secp256k1_modinv64_signed62 s;
|
||||||
|
|
||||||
tmp = *x;
|
|
||||||
secp256k1_fe_normalize(&tmp);
|
secp256k1_fe_normalize(&tmp);
|
||||||
secp256k1_fe_to_signed62(&s, &tmp);
|
secp256k1_fe_to_signed62(&s, &tmp);
|
||||||
secp256k1_modinv64(&s, &secp256k1_const_modinfo_fe);
|
secp256k1_modinv64(&s, &secp256k1_const_modinfo_fe);
|
||||||
secp256k1_fe_from_signed62(r, &s);
|
secp256k1_fe_from_signed62(r, &s);
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == secp256k1_fe_normalizes_to_zero(&tmp));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *x) {
|
static void secp256k1_fe_impl_inv_var(secp256k1_fe *r, const secp256k1_fe *x) {
|
||||||
secp256k1_fe tmp;
|
secp256k1_fe tmp = *x;
|
||||||
secp256k1_modinv64_signed62 s;
|
secp256k1_modinv64_signed62 s;
|
||||||
|
|
||||||
tmp = *x;
|
|
||||||
secp256k1_fe_normalize_var(&tmp);
|
secp256k1_fe_normalize_var(&tmp);
|
||||||
secp256k1_fe_to_signed62(&s, &tmp);
|
secp256k1_fe_to_signed62(&s, &tmp);
|
||||||
secp256k1_modinv64_var(&s, &secp256k1_const_modinfo_fe);
|
secp256k1_modinv64_var(&s, &secp256k1_const_modinfo_fe);
|
||||||
secp256k1_fe_from_signed62(r, &s);
|
secp256k1_fe_from_signed62(r, &s);
|
||||||
|
|
||||||
#ifdef VERIFY
|
|
||||||
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == secp256k1_fe_normalizes_to_zero(&tmp));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_fe_is_square_var(const secp256k1_fe *x) {
|
static int secp256k1_fe_impl_is_square_var(const secp256k1_fe *x) {
|
||||||
secp256k1_fe tmp;
|
secp256k1_fe tmp;
|
||||||
secp256k1_modinv64_signed62 s;
|
secp256k1_modinv64_signed62 s;
|
||||||
int jac, ret;
|
int jac, ret;
|
||||||
@ -698,10 +525,6 @@ static int secp256k1_fe_is_square_var(const secp256k1_fe *x) {
|
|||||||
secp256k1_fe dummy;
|
secp256k1_fe dummy;
|
||||||
ret = secp256k1_fe_sqrt(&dummy, &tmp);
|
ret = secp256k1_fe_sqrt(&dummy, &tmp);
|
||||||
} else {
|
} else {
|
||||||
#ifdef VERIFY
|
|
||||||
secp256k1_fe dummy;
|
|
||||||
VERIFY_CHECK(jac == 2*secp256k1_fe_sqrt(&dummy, &tmp) - 1);
|
|
||||||
#endif
|
|
||||||
ret = jac >= 0;
|
ret = jac >= 0;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "int128.h"
|
#include "int128.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#ifdef VERIFY
|
#ifdef VERIFY
|
||||||
#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0)
|
#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0)
|
||||||
|
303
src/field_impl.h
303
src/field_impl.h
@ -7,6 +7,7 @@
|
|||||||
#ifndef SECP256K1_FIELD_IMPL_H
|
#ifndef SECP256K1_FIELD_IMPL_H
|
||||||
#define SECP256K1_FIELD_IMPL_H
|
#define SECP256K1_FIELD_IMPL_H
|
||||||
|
|
||||||
|
#include "field.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#if defined(SECP256K1_WIDEMUL_INT128)
|
#if defined(SECP256K1_WIDEMUL_INT128)
|
||||||
@ -19,6 +20,12 @@
|
|||||||
|
|
||||||
SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) {
|
SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) {
|
||||||
secp256k1_fe na;
|
secp256k1_fe na;
|
||||||
|
#ifdef VERIFY
|
||||||
|
secp256k1_fe_verify(a);
|
||||||
|
secp256k1_fe_verify(b);
|
||||||
|
VERIFY_CHECK(a->magnitude <= 1);
|
||||||
|
VERIFY_CHECK(b->magnitude <= 31);
|
||||||
|
#endif
|
||||||
secp256k1_fe_negate(&na, a, 1);
|
secp256k1_fe_negate(&na, a, 1);
|
||||||
secp256k1_fe_add(&na, b);
|
secp256k1_fe_add(&na, b);
|
||||||
return secp256k1_fe_normalizes_to_zero(&na);
|
return secp256k1_fe_normalizes_to_zero(&na);
|
||||||
@ -26,6 +33,12 @@ SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp
|
|||||||
|
|
||||||
SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b) {
|
SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b) {
|
||||||
secp256k1_fe na;
|
secp256k1_fe na;
|
||||||
|
#ifdef VERIFY
|
||||||
|
secp256k1_fe_verify(a);
|
||||||
|
secp256k1_fe_verify(b);
|
||||||
|
VERIFY_CHECK(a->magnitude <= 1);
|
||||||
|
VERIFY_CHECK(b->magnitude <= 31);
|
||||||
|
#endif
|
||||||
secp256k1_fe_negate(&na, a, 1);
|
secp256k1_fe_negate(&na, a, 1);
|
||||||
secp256k1_fe_add(&na, b);
|
secp256k1_fe_add(&na, b);
|
||||||
return secp256k1_fe_normalizes_to_zero_var(&na);
|
return secp256k1_fe_normalizes_to_zero_var(&na);
|
||||||
@ -42,9 +55,13 @@ static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) {
|
|||||||
* itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)).
|
* itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)).
|
||||||
*/
|
*/
|
||||||
secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
|
secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
|
||||||
int j;
|
int j, ret;
|
||||||
|
|
||||||
|
#ifdef VERIFY
|
||||||
VERIFY_CHECK(r != a);
|
VERIFY_CHECK(r != a);
|
||||||
|
secp256k1_fe_verify(a);
|
||||||
|
VERIFY_CHECK(a->magnitude <= 8);
|
||||||
|
#endif
|
||||||
|
|
||||||
/** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in
|
/** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in
|
||||||
* { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
|
* { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
|
||||||
@ -128,12 +145,288 @@ static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) {
|
|||||||
/* Check that a square root was actually calculated */
|
/* Check that a square root was actually calculated */
|
||||||
|
|
||||||
secp256k1_fe_sqr(&t1, r);
|
secp256k1_fe_sqr(&t1, r);
|
||||||
return secp256k1_fe_equal(&t1, a);
|
ret = secp256k1_fe_equal(&t1, a);
|
||||||
|
|
||||||
|
#ifdef VERIFY
|
||||||
|
if (!ret) {
|
||||||
|
secp256k1_fe_negate(&t1, &t1, 1);
|
||||||
|
secp256k1_fe_normalize_var(&t1);
|
||||||
|
VERIFY_CHECK(secp256k1_fe_equal_var(&t1, a));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_fe_is_quad_var(const secp256k1_fe *a) {
|
#ifndef VERIFY
|
||||||
secp256k1_fe r;
|
static void secp256k1_fe_verify(const secp256k1_fe *a) { (void)a; }
|
||||||
return secp256k1_fe_sqrt(&r, a);
|
#else
|
||||||
|
static void secp256k1_fe_impl_verify(const secp256k1_fe *a);
|
||||||
|
static void secp256k1_fe_verify(const secp256k1_fe *a) {
|
||||||
|
/* Magnitude between 0 and 32. */
|
||||||
|
VERIFY_CHECK((a->magnitude >= 0) && (a->magnitude <= 32));
|
||||||
|
/* Normalized is 0 or 1. */
|
||||||
|
VERIFY_CHECK((a->normalized == 0) || (a->normalized == 1));
|
||||||
|
/* If normalized, magnitude must be 0 or 1. */
|
||||||
|
if (a->normalized) VERIFY_CHECK(a->magnitude <= 1);
|
||||||
|
/* Invoke implementation-specific checks. */
|
||||||
|
secp256k1_fe_impl_verify(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_normalize(secp256k1_fe *r);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_normalize(secp256k1_fe *r) {
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
secp256k1_fe_impl_normalize(r);
|
||||||
|
r->magnitude = 1;
|
||||||
|
r->normalized = 1;
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_normalize_weak(secp256k1_fe *r);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_normalize_weak(secp256k1_fe *r) {
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
secp256k1_fe_impl_normalize_weak(r);
|
||||||
|
r->magnitude = 1;
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_normalize_var(secp256k1_fe *r);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_normalize_var(secp256k1_fe *r) {
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
secp256k1_fe_impl_normalize_var(r);
|
||||||
|
r->magnitude = 1;
|
||||||
|
r->normalized = 1;
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int secp256k1_fe_impl_normalizes_to_zero(const secp256k1_fe *r);
|
||||||
|
SECP256K1_INLINE static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r) {
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
return secp256k1_fe_impl_normalizes_to_zero(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int secp256k1_fe_impl_normalizes_to_zero_var(const secp256k1_fe *r);
|
||||||
|
SECP256K1_INLINE static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r) {
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
return secp256k1_fe_impl_normalizes_to_zero_var(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_set_int(secp256k1_fe *r, int a);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) {
|
||||||
|
VERIFY_CHECK(0 <= a && a <= 0x7FFF);
|
||||||
|
secp256k1_fe_impl_set_int(r, a);
|
||||||
|
r->magnitude = (a != 0);
|
||||||
|
r->normalized = 1;
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_add_int(secp256k1_fe *r, int a);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) {
|
||||||
|
VERIFY_CHECK(0 <= a && a <= 0x7FFF);
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
secp256k1_fe_impl_add_int(r, a);
|
||||||
|
r->magnitude += 1;
|
||||||
|
r->normalized = 0;
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_clear(secp256k1_fe *a);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) {
|
||||||
|
a->magnitude = 0;
|
||||||
|
a->normalized = 1;
|
||||||
|
secp256k1_fe_impl_clear(a);
|
||||||
|
secp256k1_fe_verify(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int secp256k1_fe_impl_is_zero(const secp256k1_fe *a);
|
||||||
|
SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) {
|
||||||
|
secp256k1_fe_verify(a);
|
||||||
|
VERIFY_CHECK(a->normalized);
|
||||||
|
return secp256k1_fe_impl_is_zero(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int secp256k1_fe_impl_is_odd(const secp256k1_fe *a);
|
||||||
|
SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) {
|
||||||
|
secp256k1_fe_verify(a);
|
||||||
|
VERIFY_CHECK(a->normalized);
|
||||||
|
return secp256k1_fe_impl_is_odd(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b);
|
||||||
|
SECP256K1_INLINE static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
|
||||||
|
secp256k1_fe_verify(a);
|
||||||
|
secp256k1_fe_verify(b);
|
||||||
|
VERIFY_CHECK(a->normalized);
|
||||||
|
VERIFY_CHECK(b->normalized);
|
||||||
|
return secp256k1_fe_impl_cmp_var(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_set_b32_mod(secp256k1_fe *r, const unsigned char *a);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_set_b32_mod(secp256k1_fe *r, const unsigned char *a) {
|
||||||
|
secp256k1_fe_impl_set_b32_mod(r, a);
|
||||||
|
r->magnitude = 1;
|
||||||
|
r->normalized = 0;
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int secp256k1_fe_impl_set_b32_limit(secp256k1_fe *r, const unsigned char *a);
|
||||||
|
SECP256K1_INLINE static int secp256k1_fe_set_b32_limit(secp256k1_fe *r, const unsigned char *a) {
|
||||||
|
if (secp256k1_fe_impl_set_b32_limit(r, a)) {
|
||||||
|
r->magnitude = 1;
|
||||||
|
r->normalized = 1;
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
/* Mark the output field element as invalid. */
|
||||||
|
r->magnitude = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) {
|
||||||
|
secp256k1_fe_verify(a);
|
||||||
|
VERIFY_CHECK(a->normalized);
|
||||||
|
secp256k1_fe_impl_get_b32(r, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_negate(secp256k1_fe *r, const secp256k1_fe *a, int m);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
|
||||||
|
secp256k1_fe_verify(a);
|
||||||
|
VERIFY_CHECK(m >= 0 && m <= 31);
|
||||||
|
VERIFY_CHECK(a->magnitude <= m);
|
||||||
|
secp256k1_fe_impl_negate(r, a, m);
|
||||||
|
r->magnitude = m + 1;
|
||||||
|
r->normalized = 0;
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_mul_int(secp256k1_fe *r, int a);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) {
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
VERIFY_CHECK(a >= 0 && a <= 32);
|
||||||
|
VERIFY_CHECK(a*r->magnitude <= 32);
|
||||||
|
secp256k1_fe_impl_mul_int(r, a);
|
||||||
|
r->magnitude *= a;
|
||||||
|
r->normalized = 0;
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_add(secp256k1_fe *r, const secp256k1_fe *a);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) {
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
secp256k1_fe_verify(a);
|
||||||
|
VERIFY_CHECK(r->magnitude + a->magnitude <= 32);
|
||||||
|
secp256k1_fe_impl_add(r, a);
|
||||||
|
r->magnitude += a->magnitude;
|
||||||
|
r->normalized = 0;
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) {
|
||||||
|
secp256k1_fe_verify(a);
|
||||||
|
secp256k1_fe_verify(b);
|
||||||
|
VERIFY_CHECK(a->magnitude <= 8);
|
||||||
|
VERIFY_CHECK(b->magnitude <= 8);
|
||||||
|
VERIFY_CHECK(r != b);
|
||||||
|
VERIFY_CHECK(a != b);
|
||||||
|
secp256k1_fe_impl_mul(r, a, b);
|
||||||
|
r->magnitude = 1;
|
||||||
|
r->normalized = 0;
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
|
||||||
|
secp256k1_fe_verify(a);
|
||||||
|
VERIFY_CHECK(a->magnitude <= 8);
|
||||||
|
secp256k1_fe_impl_sqr(r, a);
|
||||||
|
r->magnitude = 1;
|
||||||
|
r->normalized = 0;
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
|
||||||
|
VERIFY_CHECK(flag == 0 || flag == 1);
|
||||||
|
secp256k1_fe_verify(a);
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
secp256k1_fe_impl_cmov(r, a, flag);
|
||||||
|
if (flag) {
|
||||||
|
r->magnitude = a->magnitude;
|
||||||
|
r->normalized = a->normalized;
|
||||||
|
}
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) {
|
||||||
|
secp256k1_fe_verify(a);
|
||||||
|
VERIFY_CHECK(a->normalized);
|
||||||
|
secp256k1_fe_impl_to_storage(r, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) {
|
||||||
|
secp256k1_fe_impl_from_storage(r, a);
|
||||||
|
r->magnitude = 1;
|
||||||
|
r->normalized = 1;
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_inv(secp256k1_fe *r, const secp256k1_fe *x);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *x) {
|
||||||
|
int input_is_zero = secp256k1_fe_normalizes_to_zero(x);
|
||||||
|
secp256k1_fe_verify(x);
|
||||||
|
secp256k1_fe_impl_inv(r, x);
|
||||||
|
r->magnitude = x->magnitude > 0;
|
||||||
|
r->normalized = 1;
|
||||||
|
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == input_is_zero);
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_inv_var(secp256k1_fe *r, const secp256k1_fe *x);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *x) {
|
||||||
|
int input_is_zero = secp256k1_fe_normalizes_to_zero(x);
|
||||||
|
secp256k1_fe_verify(x);
|
||||||
|
secp256k1_fe_impl_inv_var(r, x);
|
||||||
|
r->magnitude = x->magnitude > 0;
|
||||||
|
r->normalized = 1;
|
||||||
|
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == input_is_zero);
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int secp256k1_fe_impl_is_square_var(const secp256k1_fe *x);
|
||||||
|
SECP256K1_INLINE static int secp256k1_fe_is_square_var(const secp256k1_fe *x) {
|
||||||
|
int ret;
|
||||||
|
secp256k1_fe tmp = *x, sqrt;
|
||||||
|
secp256k1_fe_verify(x);
|
||||||
|
ret = secp256k1_fe_impl_is_square_var(x);
|
||||||
|
secp256k1_fe_normalize_weak(&tmp);
|
||||||
|
VERIFY_CHECK(ret == secp256k1_fe_sqrt(&sqrt, &tmp));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_get_bounds(secp256k1_fe* r, int m);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_get_bounds(secp256k1_fe* r, int m) {
|
||||||
|
VERIFY_CHECK(m >= 0);
|
||||||
|
VERIFY_CHECK(m <= 32);
|
||||||
|
secp256k1_fe_impl_get_bounds(r, m);
|
||||||
|
r->magnitude = m;
|
||||||
|
r->normalized = (m == 0);
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_fe_impl_half(secp256k1_fe *r);
|
||||||
|
SECP256K1_INLINE static void secp256k1_fe_half(secp256k1_fe *r) {
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
VERIFY_CHECK(r->magnitude < 32);
|
||||||
|
secp256k1_fe_impl_half(r);
|
||||||
|
r->magnitude = (r->magnitude >> 1) + 1;
|
||||||
|
r->normalized = 0;
|
||||||
|
secp256k1_fe_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* defined(VERIFY) */
|
||||||
|
|
||||||
#endif /* SECP256K1_FIELD_IMPL_H */
|
#endif /* SECP256K1_FIELD_IMPL_H */
|
||||||
|
@ -173,4 +173,10 @@ static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b);
|
|||||||
*/
|
*/
|
||||||
static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge);
|
static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge);
|
||||||
|
|
||||||
|
/** Check invariants on an affine group element (no-op unless VERIFY is enabled). */
|
||||||
|
static void secp256k1_ge_verify(const secp256k1_ge *a);
|
||||||
|
|
||||||
|
/** Check invariants on a Jacobian group element (no-op unless VERIFY is enabled). */
|
||||||
|
static void secp256k1_gej_verify(const secp256k1_gej *a);
|
||||||
|
|
||||||
#endif /* SECP256K1_GROUP_H */
|
#endif /* SECP256K1_GROUP_H */
|
||||||
|
124
src/group_impl.h
124
src/group_impl.h
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "field.h"
|
#include "field.h"
|
||||||
#include "group.h"
|
#include "group.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
/* Begin of section generated by sage/gen_exhaustive_groups.sage. */
|
/* Begin of section generated by sage/gen_exhaustive_groups.sage. */
|
||||||
#define SECP256K1_G_ORDER_7 SECP256K1_GE_CONST(\
|
#define SECP256K1_G_ORDER_7 SECP256K1_GE_CONST(\
|
||||||
@ -72,37 +73,80 @@ static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G;
|
|||||||
#endif
|
#endif
|
||||||
/* End of section generated by sage/gen_exhaustive_groups.sage. */
|
/* End of section generated by sage/gen_exhaustive_groups.sage. */
|
||||||
|
|
||||||
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, SECP256K1_B);
|
static void secp256k1_ge_verify(const secp256k1_ge *a) {
|
||||||
|
#ifdef VERIFY
|
||||||
|
secp256k1_fe_verify(&a->x);
|
||||||
|
secp256k1_fe_verify(&a->y);
|
||||||
|
VERIFY_CHECK(a->infinity == 0 || a->infinity == 1);
|
||||||
|
#endif
|
||||||
|
(void)a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secp256k1_gej_verify(const secp256k1_gej *a) {
|
||||||
|
#ifdef VERIFY
|
||||||
|
secp256k1_fe_verify(&a->x);
|
||||||
|
secp256k1_fe_verify(&a->y);
|
||||||
|
secp256k1_fe_verify(&a->z);
|
||||||
|
VERIFY_CHECK(a->infinity == 0 || a->infinity == 1);
|
||||||
|
#endif
|
||||||
|
(void)a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set r to the affine coordinates of Jacobian point (a.x, a.y, 1/zi). */
|
||||||
static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) {
|
static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) {
|
||||||
secp256k1_fe zi2;
|
secp256k1_fe zi2;
|
||||||
secp256k1_fe zi3;
|
secp256k1_fe zi3;
|
||||||
|
secp256k1_gej_verify(a);
|
||||||
|
secp256k1_fe_verify(zi);
|
||||||
VERIFY_CHECK(!a->infinity);
|
VERIFY_CHECK(!a->infinity);
|
||||||
secp256k1_fe_sqr(&zi2, zi);
|
secp256k1_fe_sqr(&zi2, zi);
|
||||||
secp256k1_fe_mul(&zi3, &zi2, zi);
|
secp256k1_fe_mul(&zi3, &zi2, zi);
|
||||||
secp256k1_fe_mul(&r->x, &a->x, &zi2);
|
secp256k1_fe_mul(&r->x, &a->x, &zi2);
|
||||||
secp256k1_fe_mul(&r->y, &a->y, &zi3);
|
secp256k1_fe_mul(&r->y, &a->y, &zi3);
|
||||||
r->infinity = a->infinity;
|
r->infinity = a->infinity;
|
||||||
|
secp256k1_ge_verify(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set r to the affine coordinates of Jacobian point (a.x, a.y, 1/zi). */
|
||||||
|
static void secp256k1_ge_set_ge_zinv(secp256k1_ge *r, const secp256k1_ge *a, const secp256k1_fe *zi) {
|
||||||
|
secp256k1_fe zi2;
|
||||||
|
secp256k1_fe zi3;
|
||||||
|
secp256k1_ge_verify(a);
|
||||||
|
secp256k1_fe_verify(zi);
|
||||||
|
VERIFY_CHECK(!a->infinity);
|
||||||
|
secp256k1_fe_sqr(&zi2, zi);
|
||||||
|
secp256k1_fe_mul(&zi3, &zi2, zi);
|
||||||
|
secp256k1_fe_mul(&r->x, &a->x, &zi2);
|
||||||
|
secp256k1_fe_mul(&r->y, &a->y, &zi3);
|
||||||
|
r->infinity = a->infinity;
|
||||||
|
secp256k1_ge_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) {
|
static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) {
|
||||||
|
secp256k1_fe_verify(x);
|
||||||
|
secp256k1_fe_verify(y);
|
||||||
r->infinity = 0;
|
r->infinity = 0;
|
||||||
r->x = *x;
|
r->x = *x;
|
||||||
r->y = *y;
|
r->y = *y;
|
||||||
|
secp256k1_ge_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_ge_is_infinity(const secp256k1_ge *a) {
|
static int secp256k1_ge_is_infinity(const secp256k1_ge *a) {
|
||||||
|
secp256k1_ge_verify(a);
|
||||||
return a->infinity;
|
return a->infinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) {
|
static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) {
|
||||||
|
secp256k1_ge_verify(a);
|
||||||
*r = *a;
|
*r = *a;
|
||||||
secp256k1_fe_normalize_weak(&r->y);
|
secp256k1_fe_normalize_weak(&r->y);
|
||||||
secp256k1_fe_negate(&r->y, &r->y, 1);
|
secp256k1_fe_negate(&r->y, &r->y, 1);
|
||||||
|
secp256k1_ge_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) {
|
static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) {
|
||||||
secp256k1_fe z2, z3;
|
secp256k1_fe z2, z3;
|
||||||
|
secp256k1_gej_verify(a);
|
||||||
r->infinity = a->infinity;
|
r->infinity = a->infinity;
|
||||||
secp256k1_fe_inv(&a->z, &a->z);
|
secp256k1_fe_inv(&a->z, &a->z);
|
||||||
secp256k1_fe_sqr(&z2, &a->z);
|
secp256k1_fe_sqr(&z2, &a->z);
|
||||||
@ -112,14 +156,17 @@ static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) {
|
|||||||
secp256k1_fe_set_int(&a->z, 1);
|
secp256k1_fe_set_int(&a->z, 1);
|
||||||
r->x = a->x;
|
r->x = a->x;
|
||||||
r->y = a->y;
|
r->y = a->y;
|
||||||
|
secp256k1_ge_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) {
|
static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) {
|
||||||
secp256k1_fe z2, z3;
|
secp256k1_fe z2, z3;
|
||||||
if (a->infinity) {
|
secp256k1_gej_verify(a);
|
||||||
|
if (secp256k1_gej_is_infinity(a)) {
|
||||||
secp256k1_ge_set_infinity(r);
|
secp256k1_ge_set_infinity(r);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
r->infinity = 0;
|
||||||
secp256k1_fe_inv_var(&a->z, &a->z);
|
secp256k1_fe_inv_var(&a->z, &a->z);
|
||||||
secp256k1_fe_sqr(&z2, &a->z);
|
secp256k1_fe_sqr(&z2, &a->z);
|
||||||
secp256k1_fe_mul(&z3, &a->z, &z2);
|
secp256k1_fe_mul(&z3, &a->z, &z2);
|
||||||
@ -127,6 +174,7 @@ static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) {
|
|||||||
secp256k1_fe_mul(&a->y, &a->y, &z3);
|
secp256k1_fe_mul(&a->y, &a->y, &z3);
|
||||||
secp256k1_fe_set_int(&a->z, 1);
|
secp256k1_fe_set_int(&a->z, 1);
|
||||||
secp256k1_ge_set_xy(r, &a->x, &a->y);
|
secp256k1_ge_set_xy(r, &a->x, &a->y);
|
||||||
|
secp256k1_ge_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len) {
|
static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len) {
|
||||||
@ -135,6 +183,7 @@ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a
|
|||||||
size_t last_i = SIZE_MAX;
|
size_t last_i = SIZE_MAX;
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
|
secp256k1_gej_verify(&a[i]);
|
||||||
if (a[i].infinity) {
|
if (a[i].infinity) {
|
||||||
secp256k1_ge_set_infinity(&r[i]);
|
secp256k1_ge_set_infinity(&r[i]);
|
||||||
} else {
|
} else {
|
||||||
@ -168,6 +217,7 @@ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a
|
|||||||
if (!a[i].infinity) {
|
if (!a[i].infinity) {
|
||||||
secp256k1_ge_set_gej_zinv(&r[i], &a[i], &r[i].x);
|
secp256k1_ge_set_gej_zinv(&r[i], &a[i], &r[i].x);
|
||||||
}
|
}
|
||||||
|
secp256k1_ge_verify(&r[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,21 +226,25 @@ static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const se
|
|||||||
secp256k1_fe zs;
|
secp256k1_fe zs;
|
||||||
|
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
|
/* Verify inputs a[len-1] and zr[len-1]. */
|
||||||
|
secp256k1_ge_verify(&a[i]);
|
||||||
|
secp256k1_fe_verify(&zr[i]);
|
||||||
/* Ensure all y values are in weak normal form for fast negation of points */
|
/* Ensure all y values are in weak normal form for fast negation of points */
|
||||||
secp256k1_fe_normalize_weak(&a[i].y);
|
secp256k1_fe_normalize_weak(&a[i].y);
|
||||||
zs = zr[i];
|
zs = zr[i];
|
||||||
|
|
||||||
/* Work our way backwards, using the z-ratios to scale the x/y values. */
|
/* Work our way backwards, using the z-ratios to scale the x/y values. */
|
||||||
while (i > 0) {
|
while (i > 0) {
|
||||||
secp256k1_gej tmpa;
|
/* Verify all inputs a[i] and zr[i]. */
|
||||||
|
secp256k1_fe_verify(&zr[i]);
|
||||||
|
secp256k1_ge_verify(&a[i]);
|
||||||
if (i != len - 1) {
|
if (i != len - 1) {
|
||||||
secp256k1_fe_mul(&zs, &zs, &zr[i]);
|
secp256k1_fe_mul(&zs, &zs, &zr[i]);
|
||||||
}
|
}
|
||||||
i--;
|
i--;
|
||||||
tmpa.x = a[i].x;
|
secp256k1_ge_set_ge_zinv(&a[i], &a[i], &zs);
|
||||||
tmpa.y = a[i].y;
|
/* Verify the output a[i]. */
|
||||||
tmpa.infinity = 0;
|
secp256k1_ge_verify(&a[i]);
|
||||||
secp256k1_ge_set_gej_zinv(&a[i], &tmpa, &zs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,12 +254,14 @@ static void secp256k1_gej_set_infinity(secp256k1_gej *r) {
|
|||||||
secp256k1_fe_clear(&r->x);
|
secp256k1_fe_clear(&r->x);
|
||||||
secp256k1_fe_clear(&r->y);
|
secp256k1_fe_clear(&r->y);
|
||||||
secp256k1_fe_clear(&r->z);
|
secp256k1_fe_clear(&r->z);
|
||||||
|
secp256k1_gej_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_ge_set_infinity(secp256k1_ge *r) {
|
static void secp256k1_ge_set_infinity(secp256k1_ge *r) {
|
||||||
r->infinity = 1;
|
r->infinity = 1;
|
||||||
secp256k1_fe_clear(&r->x);
|
secp256k1_fe_clear(&r->x);
|
||||||
secp256k1_fe_clear(&r->y);
|
secp256k1_fe_clear(&r->y);
|
||||||
|
secp256k1_ge_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_gej_clear(secp256k1_gej *r) {
|
static void secp256k1_gej_clear(secp256k1_gej *r) {
|
||||||
@ -223,6 +279,7 @@ static void secp256k1_ge_clear(secp256k1_ge *r) {
|
|||||||
|
|
||||||
static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) {
|
static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) {
|
||||||
secp256k1_fe x2, x3;
|
secp256k1_fe x2, x3;
|
||||||
|
secp256k1_fe_verify(x);
|
||||||
r->x = *x;
|
r->x = *x;
|
||||||
secp256k1_fe_sqr(&x2, x);
|
secp256k1_fe_sqr(&x2, x);
|
||||||
secp256k1_fe_mul(&x3, x, &x2);
|
secp256k1_fe_mul(&x3, x, &x2);
|
||||||
@ -232,26 +289,29 @@ static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) {
|
static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) {
|
||||||
if (!secp256k1_ge_set_xquad(r, x)) {
|
int ret;
|
||||||
return 0;
|
ret = secp256k1_ge_set_xquad(r, x);
|
||||||
}
|
|
||||||
secp256k1_fe_normalize_var(&r->y);
|
secp256k1_fe_normalize_var(&r->y);
|
||||||
if (secp256k1_fe_is_odd(&r->y) != odd) {
|
if (secp256k1_fe_is_odd(&r->y) != odd) {
|
||||||
secp256k1_fe_negate(&r->y, &r->y, 1);
|
secp256k1_fe_negate(&r->y, &r->y, 1);
|
||||||
}
|
}
|
||||||
return 1;
|
secp256k1_ge_verify(r);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) {
|
static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) {
|
||||||
|
secp256k1_ge_verify(a);
|
||||||
r->infinity = a->infinity;
|
r->infinity = a->infinity;
|
||||||
r->x = a->x;
|
r->x = a->x;
|
||||||
r->y = a->y;
|
r->y = a->y;
|
||||||
secp256k1_fe_set_int(&r->z, 1);
|
secp256k1_fe_set_int(&r->z, 1);
|
||||||
|
secp256k1_gej_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b) {
|
static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b) {
|
||||||
secp256k1_gej tmp;
|
secp256k1_gej tmp;
|
||||||
|
secp256k1_gej_verify(b);
|
||||||
|
secp256k1_gej_verify(a);
|
||||||
secp256k1_gej_neg(&tmp, a);
|
secp256k1_gej_neg(&tmp, a);
|
||||||
secp256k1_gej_add_var(&tmp, &tmp, b, NULL);
|
secp256k1_gej_add_var(&tmp, &tmp, b, NULL);
|
||||||
return secp256k1_gej_is_infinity(&tmp);
|
return secp256k1_gej_is_infinity(&tmp);
|
||||||
@ -259,6 +319,8 @@ static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b)
|
|||||||
|
|
||||||
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) {
|
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) {
|
||||||
secp256k1_fe r, r2;
|
secp256k1_fe r, r2;
|
||||||
|
secp256k1_fe_verify(x);
|
||||||
|
secp256k1_gej_verify(a);
|
||||||
VERIFY_CHECK(!a->infinity);
|
VERIFY_CHECK(!a->infinity);
|
||||||
secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x);
|
secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x);
|
||||||
r2 = a->x; secp256k1_fe_normalize_weak(&r2);
|
r2 = a->x; secp256k1_fe_normalize_weak(&r2);
|
||||||
@ -266,20 +328,24 @@ static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) {
|
static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) {
|
||||||
|
secp256k1_gej_verify(a);
|
||||||
r->infinity = a->infinity;
|
r->infinity = a->infinity;
|
||||||
r->x = a->x;
|
r->x = a->x;
|
||||||
r->y = a->y;
|
r->y = a->y;
|
||||||
r->z = a->z;
|
r->z = a->z;
|
||||||
secp256k1_fe_normalize_weak(&r->y);
|
secp256k1_fe_normalize_weak(&r->y);
|
||||||
secp256k1_fe_negate(&r->y, &r->y, 1);
|
secp256k1_fe_negate(&r->y, &r->y, 1);
|
||||||
|
secp256k1_gej_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_gej_is_infinity(const secp256k1_gej *a) {
|
static int secp256k1_gej_is_infinity(const secp256k1_gej *a) {
|
||||||
|
secp256k1_gej_verify(a);
|
||||||
return a->infinity;
|
return a->infinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) {
|
static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) {
|
||||||
secp256k1_fe y2, x3;
|
secp256k1_fe y2, x3;
|
||||||
|
secp256k1_ge_verify(a);
|
||||||
if (a->infinity) {
|
if (a->infinity) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -295,6 +361,7 @@ static SECP256K1_INLINE void secp256k1_gej_double(secp256k1_gej *r, const secp25
|
|||||||
/* Operations: 3 mul, 4 sqr, 8 add/half/mul_int/negate */
|
/* Operations: 3 mul, 4 sqr, 8 add/half/mul_int/negate */
|
||||||
secp256k1_fe l, s, t;
|
secp256k1_fe l, s, t;
|
||||||
|
|
||||||
|
secp256k1_gej_verify(a);
|
||||||
r->infinity = a->infinity;
|
r->infinity = a->infinity;
|
||||||
|
|
||||||
/* Formula used:
|
/* Formula used:
|
||||||
@ -321,6 +388,7 @@ static SECP256K1_INLINE void secp256k1_gej_double(secp256k1_gej *r, const secp25
|
|||||||
secp256k1_fe_mul(&r->y, &t, &l); /* Y3 = L*(X3 + T) (1) */
|
secp256k1_fe_mul(&r->y, &t, &l); /* Y3 = L*(X3 + T) (1) */
|
||||||
secp256k1_fe_add(&r->y, &s); /* Y3 = L*(X3 + T) + S^2 (2) */
|
secp256k1_fe_add(&r->y, &s); /* Y3 = L*(X3 + T) + S^2 (2) */
|
||||||
secp256k1_fe_negate(&r->y, &r->y, 2); /* Y3 = -(L*(X3 + T) + S^2) (3) */
|
secp256k1_fe_negate(&r->y, &r->y, 2); /* Y3 = -(L*(X3 + T) + S^2) (3) */
|
||||||
|
secp256k1_gej_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) {
|
static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) {
|
||||||
@ -334,6 +402,7 @@ static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, s
|
|||||||
* the infinity flag even though the point doubles to infinity, and the result
|
* the infinity flag even though the point doubles to infinity, and the result
|
||||||
* point will be gibberish (z = 0 but infinity = 0).
|
* point will be gibberish (z = 0 but infinity = 0).
|
||||||
*/
|
*/
|
||||||
|
secp256k1_gej_verify(a);
|
||||||
if (a->infinity) {
|
if (a->infinity) {
|
||||||
secp256k1_gej_set_infinity(r);
|
secp256k1_gej_set_infinity(r);
|
||||||
if (rzr != NULL) {
|
if (rzr != NULL) {
|
||||||
@ -348,12 +417,15 @@ static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
secp256k1_gej_double(r, a);
|
secp256k1_gej_double(r, a);
|
||||||
|
secp256k1_gej_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) {
|
static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) {
|
||||||
/* 12 mul, 4 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */
|
/* 12 mul, 4 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */
|
||||||
secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, h2, h3, t;
|
secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, h2, h3, t;
|
||||||
|
|
||||||
|
secp256k1_gej_verify(a);
|
||||||
|
secp256k1_gej_verify(b);
|
||||||
if (a->infinity) {
|
if (a->infinity) {
|
||||||
VERIFY_CHECK(rzr == NULL);
|
VERIFY_CHECK(rzr == NULL);
|
||||||
*r = *b;
|
*r = *b;
|
||||||
@ -408,11 +480,14 @@ static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, cons
|
|||||||
secp256k1_fe_mul(&r->y, &t, &i);
|
secp256k1_fe_mul(&r->y, &t, &i);
|
||||||
secp256k1_fe_mul(&h3, &h3, &s1);
|
secp256k1_fe_mul(&h3, &h3, &s1);
|
||||||
secp256k1_fe_add(&r->y, &h3);
|
secp256k1_fe_add(&r->y, &h3);
|
||||||
|
secp256k1_gej_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) {
|
static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) {
|
||||||
/* 8 mul, 3 sqr, 13 add/negate/normalize_weak/normalizes_to_zero (ignoring special cases) */
|
/* 8 mul, 3 sqr, 13 add/negate/normalize_weak/normalizes_to_zero (ignoring special cases) */
|
||||||
secp256k1_fe z12, u1, u2, s1, s2, h, i, h2, h3, t;
|
secp256k1_fe z12, u1, u2, s1, s2, h, i, h2, h3, t;
|
||||||
|
secp256k1_gej_verify(a);
|
||||||
|
secp256k1_ge_verify(b);
|
||||||
if (a->infinity) {
|
if (a->infinity) {
|
||||||
VERIFY_CHECK(rzr == NULL);
|
VERIFY_CHECK(rzr == NULL);
|
||||||
secp256k1_gej_set_ge(r, b);
|
secp256k1_gej_set_ge(r, b);
|
||||||
@ -465,12 +540,16 @@ static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, c
|
|||||||
secp256k1_fe_mul(&r->y, &t, &i);
|
secp256k1_fe_mul(&r->y, &t, &i);
|
||||||
secp256k1_fe_mul(&h3, &h3, &s1);
|
secp256k1_fe_mul(&h3, &h3, &s1);
|
||||||
secp256k1_fe_add(&r->y, &h3);
|
secp256k1_fe_add(&r->y, &h3);
|
||||||
|
secp256k1_gej_verify(r);
|
||||||
|
if (rzr != NULL) secp256k1_fe_verify(rzr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) {
|
static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) {
|
||||||
/* 9 mul, 3 sqr, 13 add/negate/normalize_weak/normalizes_to_zero (ignoring special cases) */
|
/* 9 mul, 3 sqr, 13 add/negate/normalize_weak/normalizes_to_zero (ignoring special cases) */
|
||||||
secp256k1_fe az, z12, u1, u2, s1, s2, h, i, h2, h3, t;
|
secp256k1_fe az, z12, u1, u2, s1, s2, h, i, h2, h3, t;
|
||||||
|
|
||||||
|
secp256k1_ge_verify(b);
|
||||||
|
secp256k1_fe_verify(bzinv);
|
||||||
if (a->infinity) {
|
if (a->infinity) {
|
||||||
secp256k1_fe bzinv2, bzinv3;
|
secp256k1_fe bzinv2, bzinv3;
|
||||||
r->infinity = b->infinity;
|
r->infinity = b->infinity;
|
||||||
@ -529,6 +608,7 @@ static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a,
|
|||||||
secp256k1_fe_mul(&r->y, &t, &i);
|
secp256k1_fe_mul(&r->y, &t, &i);
|
||||||
secp256k1_fe_mul(&h3, &h3, &s1);
|
secp256k1_fe_mul(&h3, &h3, &s1);
|
||||||
secp256k1_fe_add(&r->y, &h3);
|
secp256k1_fe_add(&r->y, &h3);
|
||||||
|
secp256k1_gej_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -537,6 +617,8 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const
|
|||||||
secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr;
|
secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr;
|
||||||
secp256k1_fe m_alt, rr_alt;
|
secp256k1_fe m_alt, rr_alt;
|
||||||
int degenerate;
|
int degenerate;
|
||||||
|
secp256k1_gej_verify(a);
|
||||||
|
secp256k1_ge_verify(b);
|
||||||
VERIFY_CHECK(!b->infinity);
|
VERIFY_CHECK(!b->infinity);
|
||||||
VERIFY_CHECK(a->infinity == 0 || a->infinity == 1);
|
VERIFY_CHECK(a->infinity == 0 || a->infinity == 1);
|
||||||
|
|
||||||
@ -662,21 +744,28 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const
|
|||||||
* We have degenerate = false, r->z = (y1 + y2) * Z.
|
* We have degenerate = false, r->z = (y1 + y2) * Z.
|
||||||
* Then r->infinity = ((y1 + y2)Z == 0) = (y1 == -y2) = false. */
|
* Then r->infinity = ((y1 + y2)Z == 0) = (y1 == -y2) = false. */
|
||||||
r->infinity = secp256k1_fe_normalizes_to_zero(&r->z);
|
r->infinity = secp256k1_fe_normalizes_to_zero(&r->z);
|
||||||
|
secp256k1_gej_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) {
|
static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) {
|
||||||
/* Operations: 4 mul, 1 sqr */
|
/* Operations: 4 mul, 1 sqr */
|
||||||
secp256k1_fe zz;
|
secp256k1_fe zz;
|
||||||
VERIFY_CHECK(!secp256k1_fe_is_zero(s));
|
secp256k1_gej_verify(r);
|
||||||
|
secp256k1_fe_verify(s);
|
||||||
|
#ifdef VERIFY
|
||||||
|
VERIFY_CHECK(!secp256k1_fe_normalizes_to_zero_var(s));
|
||||||
|
#endif
|
||||||
secp256k1_fe_sqr(&zz, s);
|
secp256k1_fe_sqr(&zz, s);
|
||||||
secp256k1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */
|
secp256k1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */
|
||||||
secp256k1_fe_mul(&r->y, &r->y, &zz);
|
secp256k1_fe_mul(&r->y, &r->y, &zz);
|
||||||
secp256k1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */
|
secp256k1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */
|
||||||
secp256k1_fe_mul(&r->z, &r->z, s); /* r->z *= s */
|
secp256k1_fe_mul(&r->z, &r->z, s); /* r->z *= s */
|
||||||
|
secp256k1_gej_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) {
|
static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) {
|
||||||
secp256k1_fe x, y;
|
secp256k1_fe x, y;
|
||||||
|
secp256k1_ge_verify(a);
|
||||||
VERIFY_CHECK(!a->infinity);
|
VERIFY_CHECK(!a->infinity);
|
||||||
x = a->x;
|
x = a->x;
|
||||||
secp256k1_fe_normalize(&x);
|
secp256k1_fe_normalize(&x);
|
||||||
@ -690,14 +779,18 @@ static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storag
|
|||||||
secp256k1_fe_from_storage(&r->x, &a->x);
|
secp256k1_fe_from_storage(&r->x, &a->x);
|
||||||
secp256k1_fe_from_storage(&r->y, &a->y);
|
secp256k1_fe_from_storage(&r->y, &a->y);
|
||||||
r->infinity = 0;
|
r->infinity = 0;
|
||||||
|
secp256k1_ge_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SECP256K1_INLINE void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag) {
|
static SECP256K1_INLINE void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag) {
|
||||||
|
secp256k1_gej_verify(r);
|
||||||
|
secp256k1_gej_verify(a);
|
||||||
secp256k1_fe_cmov(&r->x, &a->x, flag);
|
secp256k1_fe_cmov(&r->x, &a->x, flag);
|
||||||
secp256k1_fe_cmov(&r->y, &a->y, flag);
|
secp256k1_fe_cmov(&r->y, &a->y, flag);
|
||||||
secp256k1_fe_cmov(&r->z, &a->z, flag);
|
secp256k1_fe_cmov(&r->z, &a->z, flag);
|
||||||
|
|
||||||
r->infinity ^= (r->infinity ^ a->infinity) & flag;
|
r->infinity ^= (r->infinity ^ a->infinity) & flag;
|
||||||
|
secp256k1_gej_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) {
|
static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) {
|
||||||
@ -707,7 +800,9 @@ static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r,
|
|||||||
|
|
||||||
static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) {
|
static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) {
|
||||||
*r = *a;
|
*r = *a;
|
||||||
|
secp256k1_ge_verify(a);
|
||||||
secp256k1_fe_mul(&r->x, &r->x, &secp256k1_const_beta);
|
secp256k1_fe_mul(&r->x, &r->x, &secp256k1_const_beta);
|
||||||
|
secp256k1_ge_verify(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) {
|
static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) {
|
||||||
@ -721,7 +816,7 @@ static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) {
|
|||||||
* that of a->z. Thus a->y / a->z^3 is a quadratic residue iff a->y * a->z
|
* that of a->z. Thus a->y / a->z^3 is a quadratic residue iff a->y * a->z
|
||||||
is */
|
is */
|
||||||
secp256k1_fe_mul(&yz, &a->y, &a->z);
|
secp256k1_fe_mul(&yz, &a->y, &a->z);
|
||||||
return secp256k1_fe_is_quad_var(&yz);
|
return secp256k1_fe_is_square_var(&yz);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) {
|
static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) {
|
||||||
@ -729,6 +824,7 @@ static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) {
|
|||||||
secp256k1_gej out;
|
secp256k1_gej out;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
secp256k1_ge_verify(ge);
|
||||||
/* A very simple EC multiplication ladder that avoids a dependency on ecmult. */
|
/* A very simple EC multiplication ladder that avoids a dependency on ecmult. */
|
||||||
secp256k1_gej_set_infinity(&out);
|
secp256k1_gej_set_infinity(&out);
|
||||||
for (i = 0; i < 32; ++i) {
|
for (i = 0; i < 32; ++i) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define SECP256K1_INT128_NATIVE_IMPL_H
|
#define SECP256K1_INT128_NATIVE_IMPL_H
|
||||||
|
|
||||||
#include "int128.h"
|
#include "int128.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo) {
|
static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo) {
|
||||||
*r = (((uint128_t)hi) << 64) + lo;
|
*r = (((uint128_t)hi) << 64) + lo;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define SECP256K1_INT128_STRUCT_IMPL_H
|
#define SECP256K1_INT128_STRUCT_IMPL_H
|
||||||
|
|
||||||
#include "int128.h"
|
#include "int128.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) /* MSVC */
|
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) /* MSVC */
|
||||||
# include <intrin.h>
|
# include <intrin.h>
|
||||||
|
@ -50,7 +50,7 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const se
|
|||||||
overflow |= secp256k1_scalar_is_zero(&s);
|
overflow |= secp256k1_scalar_is_zero(&s);
|
||||||
secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, overflow);
|
secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, overflow);
|
||||||
|
|
||||||
secp256k1_ecmult_const(&res, &pt, &s, 256);
|
secp256k1_ecmult_const(&res, &pt, &s);
|
||||||
secp256k1_ge_set_gej(&pt, &res);
|
secp256k1_ge_set_gej(&pt, &res);
|
||||||
|
|
||||||
/* Compute a hash of the point */
|
/* Compute a hash of the point */
|
||||||
|
@ -81,7 +81,7 @@ static void secp256k1_dleq_pair(const secp256k1_ecmult_gen_context *ecmult_gen_c
|
|||||||
|
|
||||||
secp256k1_ecmult_gen(ecmult_gen_ctx, &p1j, sk);
|
secp256k1_ecmult_gen(ecmult_gen_ctx, &p1j, sk);
|
||||||
secp256k1_ge_set_gej(p1, &p1j);
|
secp256k1_ge_set_gej(p1, &p1j);
|
||||||
secp256k1_ecmult_const(&p2j, gen2, sk, 256);
|
secp256k1_ecmult_const(&p2j, gen2, sk);
|
||||||
secp256k1_ge_set_gej(p2, &p2j);
|
secp256k1_ge_set_gej(p2, &p2j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char
|
|||||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rpj, &k);
|
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rpj, &k);
|
||||||
secp256k1_ge_set_gej(&rp, &rpj);
|
secp256k1_ge_set_gej(&rp, &rpj);
|
||||||
/* R = k*Y; */
|
/* R = k*Y; */
|
||||||
secp256k1_ecmult_const(&rj, &enckey_ge, &k, 256);
|
secp256k1_ecmult_const(&rj, &enckey_ge, &k);
|
||||||
secp256k1_ge_set_gej(&r, &rj);
|
secp256k1_ge_set_gej(&r, &rj);
|
||||||
/* We declassify the non-secret values rp and r to allow using them
|
/* We declassify the non-secret values rp and r to allow using them
|
||||||
* as branch points. */
|
* as branch points. */
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "../../../include/secp256k1.h"
|
#include "../../../include/secp256k1.h"
|
||||||
#include "../../../include/secp256k1_extrakeys.h"
|
#include "../../../include/secp256k1_extrakeys.h"
|
||||||
#include "hsort_impl.h"
|
#include "hsort_impl.h"
|
||||||
|
#include "../../util.h"
|
||||||
|
|
||||||
static SECP256K1_INLINE int secp256k1_xonly_pubkey_load(const secp256k1_context* ctx, secp256k1_ge *ge, const secp256k1_xonly_pubkey *pubkey) {
|
static SECP256K1_INLINE int secp256k1_xonly_pubkey_load(const secp256k1_context* ctx, secp256k1_ge *ge, const secp256k1_xonly_pubkey *pubkey) {
|
||||||
return secp256k1_pubkey_load(ctx, ge, (const secp256k1_pubkey *) pubkey);
|
return secp256k1_pubkey_load(ctx, ge, (const secp256k1_pubkey *) pubkey);
|
||||||
@ -28,7 +29,7 @@ int secp256k1_xonly_pubkey_parse(const secp256k1_context* ctx, secp256k1_xonly_p
|
|||||||
memset(pubkey, 0, sizeof(*pubkey));
|
memset(pubkey, 0, sizeof(*pubkey));
|
||||||
ARG_CHECK(input32 != NULL);
|
ARG_CHECK(input32 != NULL);
|
||||||
|
|
||||||
if (!secp256k1_fe_set_b32(&x, input32)) {
|
if (!secp256k1_fe_set_b32_limit(&x, input32)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!secp256k1_ge_set_xo_var(&pk, &x, 0)) {
|
if (!secp256k1_ge_set_xo_var(&pk, &x, 0)) {
|
||||||
|
@ -47,7 +47,7 @@ static void test_exhaustive_extrakeys(const secp256k1_context *ctx, const secp25
|
|||||||
CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0);
|
CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0);
|
||||||
|
|
||||||
/* Compare the xonly_pubkey bytes against the precomputed group. */
|
/* Compare the xonly_pubkey bytes against the precomputed group. */
|
||||||
secp256k1_fe_set_b32(&fe, xonly_pubkey_bytes[i - 1]);
|
secp256k1_fe_set_b32_mod(&fe, xonly_pubkey_bytes[i - 1]);
|
||||||
CHECK(secp256k1_fe_equal_var(&fe, &group[i].x));
|
CHECK(secp256k1_fe_equal_var(&fe, &group[i].x));
|
||||||
|
|
||||||
/* Check the parity against the precomputed group. */
|
/* Check the parity against the precomputed group. */
|
||||||
|
@ -39,9 +39,9 @@ const secp256k1_generator *secp256k1_generator_h = &secp256k1_generator_h_intern
|
|||||||
|
|
||||||
static void secp256k1_generator_load(secp256k1_ge* ge, const secp256k1_generator* gen) {
|
static void secp256k1_generator_load(secp256k1_ge* ge, const secp256k1_generator* gen) {
|
||||||
int succeed;
|
int succeed;
|
||||||
succeed = secp256k1_fe_set_b32(&ge->x, &gen->data[0]);
|
succeed = secp256k1_fe_set_b32_limit(&ge->x, &gen->data[0]);
|
||||||
VERIFY_CHECK(succeed != 0);
|
VERIFY_CHECK(succeed != 0);
|
||||||
succeed = secp256k1_fe_set_b32(&ge->y, &gen->data[32]);
|
succeed = secp256k1_fe_set_b32_limit(&ge->y, &gen->data[32]);
|
||||||
VERIFY_CHECK(succeed != 0);
|
VERIFY_CHECK(succeed != 0);
|
||||||
ge->infinity = 0;
|
ge->infinity = 0;
|
||||||
(void) succeed;
|
(void) succeed;
|
||||||
@ -64,7 +64,7 @@ int secp256k1_generator_parse(const secp256k1_context* ctx, secp256k1_generator*
|
|||||||
ARG_CHECK(input != NULL);
|
ARG_CHECK(input != NULL);
|
||||||
|
|
||||||
if ((input[0] & 0xFE) != 10 ||
|
if ((input[0] & 0xFE) != 10 ||
|
||||||
!secp256k1_fe_set_b32(&x, &input[1]) ||
|
!secp256k1_fe_set_b32_limit(&x, &input[1]) ||
|
||||||
!secp256k1_ge_set_xquad(&ge, &x)) {
|
!secp256k1_ge_set_xquad(&ge, &x)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -84,7 +84,7 @@ int secp256k1_generator_serialize(const secp256k1_context* ctx, unsigned char *o
|
|||||||
|
|
||||||
secp256k1_generator_load(&ge, gen);
|
secp256k1_generator_load(&ge, gen);
|
||||||
|
|
||||||
output[0] = 11 ^ secp256k1_fe_is_quad_var(&ge.y);
|
output[0] = 11 ^ secp256k1_fe_is_square_var(&ge.y);
|
||||||
secp256k1_fe_normalize_var(&ge.x);
|
secp256k1_fe_normalize_var(&ge.x);
|
||||||
secp256k1_fe_get_b32(&output[1], &ge.x);
|
secp256k1_fe_get_b32(&output[1], &ge.x);
|
||||||
return 1;
|
return 1;
|
||||||
@ -205,7 +205,7 @@ static int secp256k1_generator_generate_internal(const secp256k1_context* ctx, s
|
|||||||
secp256k1_sha256_write(&sha256, prefix1, 16);
|
secp256k1_sha256_write(&sha256, prefix1, 16);
|
||||||
secp256k1_sha256_write(&sha256, key32, 32);
|
secp256k1_sha256_write(&sha256, key32, 32);
|
||||||
secp256k1_sha256_finalize(&sha256, b32);
|
secp256k1_sha256_finalize(&sha256, b32);
|
||||||
ret &= secp256k1_fe_set_b32(&t, b32);
|
ret &= secp256k1_fe_set_b32_limit(&t, b32);
|
||||||
shallue_van_de_woestijne(&add, &t);
|
shallue_van_de_woestijne(&add, &t);
|
||||||
if (blind32) {
|
if (blind32) {
|
||||||
secp256k1_gej_add_ge(&accum, &accum, &add);
|
secp256k1_gej_add_ge(&accum, &accum, &add);
|
||||||
@ -217,7 +217,7 @@ static int secp256k1_generator_generate_internal(const secp256k1_context* ctx, s
|
|||||||
secp256k1_sha256_write(&sha256, prefix2, 16);
|
secp256k1_sha256_write(&sha256, prefix2, 16);
|
||||||
secp256k1_sha256_write(&sha256, key32, 32);
|
secp256k1_sha256_write(&sha256, key32, 32);
|
||||||
secp256k1_sha256_finalize(&sha256, b32);
|
secp256k1_sha256_finalize(&sha256, b32);
|
||||||
ret &= secp256k1_fe_set_b32(&t, b32);
|
ret &= secp256k1_fe_set_b32_limit(&t, b32);
|
||||||
shallue_van_de_woestijne(&add, &t);
|
shallue_van_de_woestijne(&add, &t);
|
||||||
secp256k1_gej_add_ge(&accum, &accum, &add);
|
secp256k1_gej_add_ge(&accum, &accum, &add);
|
||||||
|
|
||||||
@ -244,7 +244,7 @@ int secp256k1_generator_generate_blinded(const secp256k1_context* ctx, secp256k1
|
|||||||
|
|
||||||
static void secp256k1_pedersen_commitment_load(secp256k1_ge* ge, const secp256k1_pedersen_commitment* commit) {
|
static void secp256k1_pedersen_commitment_load(secp256k1_ge* ge, const secp256k1_pedersen_commitment* commit) {
|
||||||
secp256k1_fe fe;
|
secp256k1_fe fe;
|
||||||
secp256k1_fe_set_b32(&fe, &commit->data[1]);
|
secp256k1_fe_set_b32_mod(&fe, &commit->data[1]);
|
||||||
secp256k1_ge_set_xquad(ge, &fe);
|
secp256k1_ge_set_xquad(ge, &fe);
|
||||||
if (commit->data[0] & 1) {
|
if (commit->data[0] & 1) {
|
||||||
secp256k1_ge_neg(ge, ge);
|
secp256k1_ge_neg(ge, ge);
|
||||||
@ -254,7 +254,7 @@ static void secp256k1_pedersen_commitment_load(secp256k1_ge* ge, const secp256k1
|
|||||||
static void secp256k1_pedersen_commitment_save(secp256k1_pedersen_commitment* commit, secp256k1_ge* ge) {
|
static void secp256k1_pedersen_commitment_save(secp256k1_pedersen_commitment* commit, secp256k1_ge* ge) {
|
||||||
secp256k1_fe_normalize(&ge->x);
|
secp256k1_fe_normalize(&ge->x);
|
||||||
secp256k1_fe_get_b32(&commit->data[1], &ge->x);
|
secp256k1_fe_get_b32(&commit->data[1], &ge->x);
|
||||||
commit->data[0] = 9 ^ secp256k1_fe_is_quad_var(&ge->y);
|
commit->data[0] = 9 ^ secp256k1_fe_is_square_var(&ge->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
int secp256k1_pedersen_commitment_parse(const secp256k1_context* ctx, secp256k1_pedersen_commitment* commit, const unsigned char *input) {
|
int secp256k1_pedersen_commitment_parse(const secp256k1_context* ctx, secp256k1_pedersen_commitment* commit, const unsigned char *input) {
|
||||||
@ -267,7 +267,7 @@ int secp256k1_pedersen_commitment_parse(const secp256k1_context* ctx, secp256k1_
|
|||||||
(void) ctx;
|
(void) ctx;
|
||||||
|
|
||||||
if ((input[0] & 0xFE) != 8 ||
|
if ((input[0] & 0xFE) != 8 ||
|
||||||
!secp256k1_fe_set_b32(&x, &input[1]) ||
|
!secp256k1_fe_set_b32_limit(&x, &input[1]) ||
|
||||||
!secp256k1_ge_set_xquad(&ge, &x)) {
|
!secp256k1_ge_set_xquad(&ge, &x)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -287,7 +287,7 @@ int secp256k1_pedersen_commitment_serialize(const secp256k1_context* ctx, unsign
|
|||||||
|
|
||||||
secp256k1_pedersen_commitment_load(&ge, commit);
|
secp256k1_pedersen_commitment_load(&ge, commit);
|
||||||
|
|
||||||
output[0] = 9 ^ secp256k1_fe_is_quad_var(&ge.y);
|
output[0] = 9 ^ secp256k1_fe_is_square_var(&ge.y);
|
||||||
secp256k1_fe_normalize_var(&ge.x);
|
secp256k1_fe_normalize_var(&ge.x);
|
||||||
secp256k1_fe_get_b32(&output[1], &ge.x);
|
secp256k1_fe_get_b32(&output[1], &ge.x);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -34,7 +34,7 @@ static void secp256k1_pedersen_scalar_set_u64(secp256k1_scalar *sec, uint64_t va
|
|||||||
static void secp256k1_pedersen_ecmult_small(secp256k1_gej *r, uint64_t gn, const secp256k1_ge* genp) {
|
static void secp256k1_pedersen_ecmult_small(secp256k1_gej *r, uint64_t gn, const secp256k1_ge* genp) {
|
||||||
secp256k1_scalar s;
|
secp256k1_scalar s;
|
||||||
secp256k1_pedersen_scalar_set_u64(&s, gn);
|
secp256k1_pedersen_scalar_set_u64(&s, gn);
|
||||||
secp256k1_ecmult_const(r, genp, &s, 64);
|
secp256k1_ecmult_const(r, genp, &s);
|
||||||
secp256k1_scalar_clear(&s);
|
secp256k1_scalar_clear(&s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,8 +41,8 @@ static void secp256k1_point_load(secp256k1_ge *ge, const unsigned char *data) {
|
|||||||
} else {
|
} else {
|
||||||
/* Otherwise, fall back to 32-byte big endian for X and Y. */
|
/* Otherwise, fall back to 32-byte big endian for X and Y. */
|
||||||
secp256k1_fe x, y;
|
secp256k1_fe x, y;
|
||||||
secp256k1_fe_set_b32(&x, data);
|
secp256k1_fe_set_b32_mod(&x, data);
|
||||||
secp256k1_fe_set_b32(&y, data + 32);
|
secp256k1_fe_set_b32_mod(&y, data + 32);
|
||||||
secp256k1_ge_set_xy(ge, &x, &y);
|
secp256k1_ge_set_xy(ge, &x, &y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ SECP256K1_INLINE static void secp256k1_rangeproof_serialize_point(unsigned char*
|
|||||||
secp256k1_fe pointx;
|
secp256k1_fe pointx;
|
||||||
pointx = point->x;
|
pointx = point->x;
|
||||||
secp256k1_fe_normalize(&pointx);
|
secp256k1_fe_normalize(&pointx);
|
||||||
data[0] = !secp256k1_fe_is_quad_var(&point->y);
|
data[0] = !secp256k1_fe_is_square_var(&point->y);
|
||||||
secp256k1_fe_get_b32(data + 1, &pointx);
|
secp256k1_fe_get_b32(data + 1, &pointx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,7 +606,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecm
|
|||||||
}
|
}
|
||||||
for(i = 0; i < rings - 1; i++) {
|
for(i = 0; i < rings - 1; i++) {
|
||||||
secp256k1_fe fe;
|
secp256k1_fe fe;
|
||||||
if (!secp256k1_fe_set_b32(&fe, &proof[offset]) ||
|
if (!secp256k1_fe_set_b32_limit(&fe, &proof[offset]) ||
|
||||||
!secp256k1_ge_set_xquad(&c, &fe)) {
|
!secp256k1_ge_set_xquad(&c, &fe)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_scalar *sigr, const secp2
|
|||||||
}
|
}
|
||||||
|
|
||||||
secp256k1_scalar_get_b32(brx, sigr);
|
secp256k1_scalar_get_b32(brx, sigr);
|
||||||
r = secp256k1_fe_set_b32(&fx, brx);
|
r = secp256k1_fe_set_b32_limit(&fx, brx);
|
||||||
(void)r;
|
(void)r;
|
||||||
VERIFY_CHECK(r); /* brx comes from a scalar, so is less than the order; certainly less than p */
|
VERIFY_CHECK(r); /* brx comes from a scalar, so is less than the order; certainly less than p */
|
||||||
if (recid & 2) {
|
if (recid & 2) {
|
||||||
|
@ -232,7 +232,7 @@ int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned cha
|
|||||||
ARG_CHECK(msg != NULL || msglen == 0);
|
ARG_CHECK(msg != NULL || msglen == 0);
|
||||||
ARG_CHECK(pubkey != NULL);
|
ARG_CHECK(pubkey != NULL);
|
||||||
|
|
||||||
if (!secp256k1_fe_set_b32(&rx, &sig64[0])) {
|
if (!secp256k1_fe_set_b32_limit(&rx, &sig64[0])) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,28 +215,36 @@ static void test_schnorrsig_sha256_tagged(void) {
|
|||||||
|
|
||||||
/* Helper function for schnorrsig_bip_vectors
|
/* Helper function for schnorrsig_bip_vectors
|
||||||
* Signs the message and checks that it's the same as expected_sig. */
|
* Signs the message and checks that it's the same as expected_sig. */
|
||||||
static void test_schnorrsig_bip_vectors_check_signing(const unsigned char *sk, const unsigned char *pk_serialized, const unsigned char *aux_rand, const unsigned char *msg32, const unsigned char *expected_sig) {
|
static void test_schnorrsig_bip_vectors_check_signing(const unsigned char *sk, const unsigned char *pk_serialized, const unsigned char *aux_rand, const unsigned char *msg, size_t msglen, const unsigned char *expected_sig) {
|
||||||
unsigned char sig[64];
|
unsigned char sig[64];
|
||||||
secp256k1_keypair keypair;
|
secp256k1_keypair keypair;
|
||||||
secp256k1_xonly_pubkey pk, pk_expected;
|
secp256k1_xonly_pubkey pk, pk_expected;
|
||||||
|
|
||||||
|
secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT;
|
||||||
|
extraparams.ndata = (unsigned char*)aux_rand;
|
||||||
|
|
||||||
CHECK(secp256k1_keypair_create(CTX, &keypair, sk));
|
CHECK(secp256k1_keypair_create(CTX, &keypair, sk));
|
||||||
CHECK(secp256k1_schnorrsig_sign32(CTX, sig, msg32, &keypair, aux_rand));
|
CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig, msg, msglen, &keypair, &extraparams));
|
||||||
CHECK(secp256k1_memcmp_var(sig, expected_sig, 64) == 0);
|
CHECK(secp256k1_memcmp_var(sig, expected_sig, 64) == 0);
|
||||||
|
if (msglen == 32) {
|
||||||
|
memset(sig, 0, 64);
|
||||||
|
CHECK(secp256k1_schnorrsig_sign32(CTX, sig, msg, &keypair, aux_rand));
|
||||||
|
CHECK(secp256k1_memcmp_var(sig, expected_sig, 64) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
CHECK(secp256k1_xonly_pubkey_parse(CTX, &pk_expected, pk_serialized));
|
CHECK(secp256k1_xonly_pubkey_parse(CTX, &pk_expected, pk_serialized));
|
||||||
CHECK(secp256k1_keypair_xonly_pub(CTX, &pk, NULL, &keypair));
|
CHECK(secp256k1_keypair_xonly_pub(CTX, &pk, NULL, &keypair));
|
||||||
CHECK(secp256k1_memcmp_var(&pk, &pk_expected, sizeof(pk)) == 0);
|
CHECK(secp256k1_memcmp_var(&pk, &pk_expected, sizeof(pk)) == 0);
|
||||||
CHECK(secp256k1_schnorrsig_verify(CTX, sig, msg32, 32, &pk));
|
CHECK(secp256k1_schnorrsig_verify(CTX, sig, msg, msglen, &pk));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper function for schnorrsig_bip_vectors
|
/* Helper function for schnorrsig_bip_vectors
|
||||||
* Checks that both verify and verify_batch (TODO) return the same value as expected. */
|
* Checks that both verify and verify_batch (TODO) return the same value as expected. */
|
||||||
static void test_schnorrsig_bip_vectors_check_verify(const unsigned char *pk_serialized, const unsigned char *msg32, const unsigned char *sig, int expected) {
|
static void test_schnorrsig_bip_vectors_check_verify(const unsigned char *pk_serialized, const unsigned char *msg, size_t msglen, const unsigned char *sig, int expected) {
|
||||||
secp256k1_xonly_pubkey pk;
|
secp256k1_xonly_pubkey pk;
|
||||||
|
|
||||||
CHECK(secp256k1_xonly_pubkey_parse(CTX, &pk, pk_serialized));
|
CHECK(secp256k1_xonly_pubkey_parse(CTX, &pk, pk_serialized));
|
||||||
CHECK(expected == secp256k1_schnorrsig_verify(CTX, sig, msg32, 32, &pk));
|
CHECK(expected == secp256k1_schnorrsig_verify(CTX, sig, msg, msglen, &pk));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test vectors according to BIP-340 ("Schnorr Signatures for secp256k1"). See
|
/* Test vectors according to BIP-340 ("Schnorr Signatures for secp256k1"). See
|
||||||
@ -256,7 +264,7 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0,
|
0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0,
|
||||||
0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9
|
0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9
|
||||||
};
|
};
|
||||||
unsigned char aux_rand[32] = {
|
const unsigned char aux_rand[32] = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
@ -278,8 +286,8 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0xEB, 0xEE, 0xE8, 0xFD, 0xB2, 0x17, 0x2F, 0x47,
|
0xEB, 0xEE, 0xE8, 0xFD, 0xB2, 0x17, 0x2F, 0x47,
|
||||||
0x7D, 0xF4, 0x90, 0x0D, 0x31, 0x05, 0x36, 0xC0
|
0x7D, 0xF4, 0x90, 0x0D, 0x31, 0x05, 0x36, 0xC0
|
||||||
};
|
};
|
||||||
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig);
|
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig);
|
||||||
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1);
|
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
/* Test vector 1 */
|
/* Test vector 1 */
|
||||||
@ -295,7 +303,7 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8,
|
0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8,
|
||||||
0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59
|
0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59
|
||||||
};
|
};
|
||||||
unsigned char aux_rand[32] = {
|
const unsigned char aux_rand[32] = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
@ -317,8 +325,8 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0x89, 0x7E, 0xFC, 0xB6, 0x39, 0xEA, 0x87, 0x1C,
|
0x89, 0x7E, 0xFC, 0xB6, 0x39, 0xEA, 0x87, 0x1C,
|
||||||
0xFA, 0x95, 0xF6, 0xDE, 0x33, 0x9E, 0x4B, 0x0A
|
0xFA, 0x95, 0xF6, 0xDE, 0x33, 0x9E, 0x4B, 0x0A
|
||||||
};
|
};
|
||||||
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig);
|
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig);
|
||||||
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1);
|
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
/* Test vector 2 */
|
/* Test vector 2 */
|
||||||
@ -334,7 +342,7 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0x01, 0x39, 0x71, 0x53, 0x09, 0xB0, 0x86, 0xC9,
|
0x01, 0x39, 0x71, 0x53, 0x09, 0xB0, 0x86, 0xC9,
|
||||||
0x60, 0xE1, 0x8F, 0xD9, 0x69, 0x77, 0x4E, 0xB8
|
0x60, 0xE1, 0x8F, 0xD9, 0x69, 0x77, 0x4E, 0xB8
|
||||||
};
|
};
|
||||||
unsigned char aux_rand[32] = {
|
const unsigned char aux_rand[32] = {
|
||||||
0xC8, 0x7A, 0xA5, 0x38, 0x24, 0xB4, 0xD7, 0xAE,
|
0xC8, 0x7A, 0xA5, 0x38, 0x24, 0xB4, 0xD7, 0xAE,
|
||||||
0x2E, 0xB0, 0x35, 0xA2, 0xB5, 0xBB, 0xBC, 0xCC,
|
0x2E, 0xB0, 0x35, 0xA2, 0xB5, 0xBB, 0xBC, 0xCC,
|
||||||
0x08, 0x0E, 0x76, 0xCD, 0xC6, 0xD1, 0x69, 0x2C,
|
0x08, 0x0E, 0x76, 0xCD, 0xC6, 0xD1, 0x69, 0x2C,
|
||||||
@ -356,8 +364,8 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0x7A, 0xDE, 0xA9, 0x8D, 0x82, 0xF8, 0x48, 0x1E,
|
0x7A, 0xDE, 0xA9, 0x8D, 0x82, 0xF8, 0x48, 0x1E,
|
||||||
0x0E, 0x1E, 0x03, 0x67, 0x4A, 0x6F, 0x3F, 0xB7
|
0x0E, 0x1E, 0x03, 0x67, 0x4A, 0x6F, 0x3F, 0xB7
|
||||||
};
|
};
|
||||||
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig);
|
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig);
|
||||||
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1);
|
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
/* Test vector 3 */
|
/* Test vector 3 */
|
||||||
@ -373,7 +381,7 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0x3A, 0x0D, 0x95, 0xFB, 0xF2, 0x1D, 0x46, 0x8A,
|
0x3A, 0x0D, 0x95, 0xFB, 0xF2, 0x1D, 0x46, 0x8A,
|
||||||
0x1B, 0x33, 0xF8, 0xC1, 0x60, 0xD8, 0xF5, 0x17
|
0x1B, 0x33, 0xF8, 0xC1, 0x60, 0xD8, 0xF5, 0x17
|
||||||
};
|
};
|
||||||
unsigned char aux_rand[32] = {
|
const unsigned char aux_rand[32] = {
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
@ -395,8 +403,8 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0xF2, 0x5F, 0xD7, 0x88, 0x81, 0xEB, 0xB3, 0x27,
|
0xF2, 0x5F, 0xD7, 0x88, 0x81, 0xEB, 0xB3, 0x27,
|
||||||
0x71, 0xFC, 0x59, 0x22, 0xEF, 0xC6, 0x6E, 0xA3
|
0x71, 0xFC, 0x59, 0x22, 0xEF, 0xC6, 0x6E, 0xA3
|
||||||
};
|
};
|
||||||
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig);
|
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig);
|
||||||
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1);
|
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
/* Test vector 4 */
|
/* Test vector 4 */
|
||||||
@ -422,7 +430,7 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0x60, 0xCB, 0x71, 0xC0, 0x4E, 0x80, 0xF5, 0x93,
|
0x60, 0xCB, 0x71, 0xC0, 0x4E, 0x80, 0xF5, 0x93,
|
||||||
0x06, 0x0B, 0x07, 0xD2, 0x83, 0x08, 0xD7, 0xF4
|
0x06, 0x0B, 0x07, 0xD2, 0x83, 0x08, 0xD7, 0xF4
|
||||||
};
|
};
|
||||||
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1);
|
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
/* Test vector 5 */
|
/* Test vector 5 */
|
||||||
@ -460,7 +468,7 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0x7A, 0x73, 0xC6, 0x43, 0xE1, 0x66, 0xBE, 0x5E,
|
0x7A, 0x73, 0xC6, 0x43, 0xE1, 0x66, 0xBE, 0x5E,
|
||||||
0xBE, 0xAF, 0xA3, 0x4B, 0x1A, 0xC5, 0x53, 0xE2
|
0xBE, 0xAF, 0xA3, 0x4B, 0x1A, 0xC5, 0x53, 0xE2
|
||||||
};
|
};
|
||||||
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
|
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
/* Test vector 7 */
|
/* Test vector 7 */
|
||||||
@ -486,7 +494,7 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0x62, 0x2A, 0x95, 0x4C, 0xFE, 0x54, 0x57, 0x35,
|
0x62, 0x2A, 0x95, 0x4C, 0xFE, 0x54, 0x57, 0x35,
|
||||||
0xAA, 0xEA, 0x51, 0x34, 0xFC, 0xCD, 0xB2, 0xBD
|
0xAA, 0xEA, 0x51, 0x34, 0xFC, 0xCD, 0xB2, 0xBD
|
||||||
};
|
};
|
||||||
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
|
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
/* Test vector 8 */
|
/* Test vector 8 */
|
||||||
@ -512,7 +520,7 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0xE8, 0xD7, 0xC9, 0x3E, 0x00, 0xC5, 0xED, 0x0C,
|
0xE8, 0xD7, 0xC9, 0x3E, 0x00, 0xC5, 0xED, 0x0C,
|
||||||
0x18, 0x34, 0xFF, 0x0D, 0x0C, 0x2E, 0x6D, 0xA6
|
0x18, 0x34, 0xFF, 0x0D, 0x0C, 0x2E, 0x6D, 0xA6
|
||||||
};
|
};
|
||||||
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
|
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
/* Test vector 9 */
|
/* Test vector 9 */
|
||||||
@ -538,7 +546,7 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0x4F, 0xB7, 0x34, 0x76, 0xF0, 0xD5, 0x94, 0xDC,
|
0x4F, 0xB7, 0x34, 0x76, 0xF0, 0xD5, 0x94, 0xDC,
|
||||||
0xB6, 0x5C, 0x64, 0x25, 0xBD, 0x18, 0x60, 0x51
|
0xB6, 0x5C, 0x64, 0x25, 0xBD, 0x18, 0x60, 0x51
|
||||||
};
|
};
|
||||||
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
|
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
/* Test vector 10 */
|
/* Test vector 10 */
|
||||||
@ -564,7 +572,7 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0xDB, 0xA8, 0x7F, 0x11, 0xAC, 0x67, 0x54, 0xF9,
|
0xDB, 0xA8, 0x7F, 0x11, 0xAC, 0x67, 0x54, 0xF9,
|
||||||
0x37, 0x80, 0xD5, 0xA1, 0x83, 0x7C, 0xF1, 0x97
|
0x37, 0x80, 0xD5, 0xA1, 0x83, 0x7C, 0xF1, 0x97
|
||||||
};
|
};
|
||||||
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
|
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
/* Test vector 11 */
|
/* Test vector 11 */
|
||||||
@ -590,7 +598,7 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0xD1, 0xD7, 0x13, 0xA8, 0xAE, 0x82, 0xB3, 0x2F,
|
0xD1, 0xD7, 0x13, 0xA8, 0xAE, 0x82, 0xB3, 0x2F,
|
||||||
0xA7, 0x9D, 0x5F, 0x7F, 0xC4, 0x07, 0xD3, 0x9B
|
0xA7, 0x9D, 0x5F, 0x7F, 0xC4, 0x07, 0xD3, 0x9B
|
||||||
};
|
};
|
||||||
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
|
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
/* Test vector 12 */
|
/* Test vector 12 */
|
||||||
@ -616,7 +624,7 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0xD1, 0xD7, 0x13, 0xA8, 0xAE, 0x82, 0xB3, 0x2F,
|
0xD1, 0xD7, 0x13, 0xA8, 0xAE, 0x82, 0xB3, 0x2F,
|
||||||
0xA7, 0x9D, 0x5F, 0x7F, 0xC4, 0x07, 0xD3, 0x9B
|
0xA7, 0x9D, 0x5F, 0x7F, 0xC4, 0x07, 0xD3, 0x9B
|
||||||
};
|
};
|
||||||
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
|
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
/* Test vector 13 */
|
/* Test vector 13 */
|
||||||
@ -642,7 +650,7 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
|
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
|
||||||
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41
|
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41
|
||||||
};
|
};
|
||||||
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
|
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
/* Test vector 14 */
|
/* Test vector 14 */
|
||||||
@ -656,6 +664,147 @@ static void test_schnorrsig_bip_vectors(void) {
|
|||||||
/* No need to check the signature of the test vector as parsing the pubkey already fails */
|
/* No need to check the signature of the test vector as parsing the pubkey already fails */
|
||||||
CHECK(!secp256k1_xonly_pubkey_parse(CTX, &pk_parsed, pk));
|
CHECK(!secp256k1_xonly_pubkey_parse(CTX, &pk_parsed, pk));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
/* Test vector 15 */
|
||||||
|
const unsigned char sk[32] = {
|
||||||
|
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
|
||||||
|
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
|
||||||
|
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
|
||||||
|
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
|
||||||
|
};
|
||||||
|
const unsigned char pk[32] = {
|
||||||
|
0x77, 0x8C, 0xAA, 0x53, 0xB4, 0x39, 0x3A, 0xC4,
|
||||||
|
0x67, 0x77, 0x4D, 0x09, 0x49, 0x7A, 0x87, 0x22,
|
||||||
|
0x4B, 0xF9, 0xFA, 0xB6, 0xF6, 0xE6, 0x8B, 0x23,
|
||||||
|
0x08, 0x64, 0x97, 0x32, 0x4D, 0x6F, 0xD1, 0x17,
|
||||||
|
};
|
||||||
|
const unsigned char aux_rand[32] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
/* const unsigned char msg[0] = {}; */
|
||||||
|
const unsigned char sig[64] = {
|
||||||
|
0x71, 0x53, 0x5D, 0xB1, 0x65, 0xEC, 0xD9, 0xFB,
|
||||||
|
0xBC, 0x04, 0x6E, 0x5F, 0xFA, 0xEA, 0x61, 0x18,
|
||||||
|
0x6B, 0xB6, 0xAD, 0x43, 0x67, 0x32, 0xFC, 0xCC,
|
||||||
|
0x25, 0x29, 0x1A, 0x55, 0x89, 0x54, 0x64, 0xCF,
|
||||||
|
0x60, 0x69, 0xCE, 0x26, 0xBF, 0x03, 0x46, 0x62,
|
||||||
|
0x28, 0xF1, 0x9A, 0x3A, 0x62, 0xDB, 0x8A, 0x64,
|
||||||
|
0x9F, 0x2D, 0x56, 0x0F, 0xAC, 0x65, 0x28, 0x27,
|
||||||
|
0xD1, 0xAF, 0x05, 0x74, 0xE4, 0x27, 0xAB, 0x63,
|
||||||
|
};
|
||||||
|
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, NULL, 0, sig);
|
||||||
|
test_schnorrsig_bip_vectors_check_verify(pk, NULL, 0, sig, 1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/* Test vector 16 */
|
||||||
|
const unsigned char sk[32] = {
|
||||||
|
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
|
||||||
|
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
|
||||||
|
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
|
||||||
|
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
|
||||||
|
};
|
||||||
|
const unsigned char pk[32] = {
|
||||||
|
0x77, 0x8C, 0xAA, 0x53, 0xB4, 0x39, 0x3A, 0xC4,
|
||||||
|
0x67, 0x77, 0x4D, 0x09, 0x49, 0x7A, 0x87, 0x22,
|
||||||
|
0x4B, 0xF9, 0xFA, 0xB6, 0xF6, 0xE6, 0x8B, 0x23,
|
||||||
|
0x08, 0x64, 0x97, 0x32, 0x4D, 0x6F, 0xD1, 0x17,
|
||||||
|
};
|
||||||
|
const unsigned char aux_rand[32] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
const unsigned char msg[] = { 0x11 };
|
||||||
|
const unsigned char sig[64] = {
|
||||||
|
0x08, 0xA2, 0x0A, 0x0A, 0xFE, 0xF6, 0x41, 0x24,
|
||||||
|
0x64, 0x92, 0x32, 0xE0, 0x69, 0x3C, 0x58, 0x3A,
|
||||||
|
0xB1, 0xB9, 0x93, 0x4A, 0xE6, 0x3B, 0x4C, 0x35,
|
||||||
|
0x11, 0xF3, 0xAE, 0x11, 0x34, 0xC6, 0xA3, 0x03,
|
||||||
|
0xEA, 0x31, 0x73, 0xBF, 0xEA, 0x66, 0x83, 0xBD,
|
||||||
|
0x10, 0x1F, 0xA5, 0xAA, 0x5D, 0xBC, 0x19, 0x96,
|
||||||
|
0xFE, 0x7C, 0xAC, 0xFC, 0x5A, 0x57, 0x7D, 0x33,
|
||||||
|
0xEC, 0x14, 0x56, 0x4C, 0xEC, 0x2B, 0xAC, 0xBF,
|
||||||
|
};
|
||||||
|
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig);
|
||||||
|
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/* Test vector 17 */
|
||||||
|
const unsigned char sk[32] = {
|
||||||
|
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
|
||||||
|
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
|
||||||
|
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
|
||||||
|
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
|
||||||
|
};
|
||||||
|
const unsigned char pk[32] = {
|
||||||
|
0x77, 0x8C, 0xAA, 0x53, 0xB4, 0x39, 0x3A, 0xC4,
|
||||||
|
0x67, 0x77, 0x4D, 0x09, 0x49, 0x7A, 0x87, 0x22,
|
||||||
|
0x4B, 0xF9, 0xFA, 0xB6, 0xF6, 0xE6, 0x8B, 0x23,
|
||||||
|
0x08, 0x64, 0x97, 0x32, 0x4D, 0x6F, 0xD1, 0x17,
|
||||||
|
};
|
||||||
|
const unsigned char aux_rand[32] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
const unsigned char msg[] = {
|
||||||
|
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||||
|
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
|
||||||
|
0x11,
|
||||||
|
};
|
||||||
|
const unsigned char sig[64] = {
|
||||||
|
0x51, 0x30, 0xF3, 0x9A, 0x40, 0x59, 0xB4, 0x3B,
|
||||||
|
0xC7, 0xCA, 0xC0, 0x9A, 0x19, 0xEC, 0xE5, 0x2B,
|
||||||
|
0x5D, 0x86, 0x99, 0xD1, 0xA7, 0x1E, 0x3C, 0x52,
|
||||||
|
0xDA, 0x9A, 0xFD, 0xB6, 0xB5, 0x0A, 0xC3, 0x70,
|
||||||
|
0xC4, 0xA4, 0x82, 0xB7, 0x7B, 0xF9, 0x60, 0xF8,
|
||||||
|
0x68, 0x15, 0x40, 0xE2, 0x5B, 0x67, 0x71, 0xEC,
|
||||||
|
0xE1, 0xE5, 0xA3, 0x7F, 0xD8, 0x0E, 0x5A, 0x51,
|
||||||
|
0x89, 0x7C, 0x55, 0x66, 0xA9, 0x7E, 0xA5, 0xA5,
|
||||||
|
};
|
||||||
|
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig);
|
||||||
|
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/* Test vector 18 */
|
||||||
|
const unsigned char sk[32] = {
|
||||||
|
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
|
||||||
|
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
|
||||||
|
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
|
||||||
|
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
|
||||||
|
};
|
||||||
|
const unsigned char pk[32] = {
|
||||||
|
0x77, 0x8C, 0xAA, 0x53, 0xB4, 0x39, 0x3A, 0xC4,
|
||||||
|
0x67, 0x77, 0x4D, 0x09, 0x49, 0x7A, 0x87, 0x22,
|
||||||
|
0x4B, 0xF9, 0xFA, 0xB6, 0xF6, 0xE6, 0x8B, 0x23,
|
||||||
|
0x08, 0x64, 0x97, 0x32, 0x4D, 0x6F, 0xD1, 0x17,
|
||||||
|
};
|
||||||
|
const unsigned char aux_rand[32] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
const unsigned char sig[64] = {
|
||||||
|
0x40, 0x3B, 0x12, 0xB0, 0xD8, 0x55, 0x5A, 0x34,
|
||||||
|
0x41, 0x75, 0xEA, 0x7E, 0xC7, 0x46, 0x56, 0x63,
|
||||||
|
0x03, 0x32, 0x1E, 0x5D, 0xBF, 0xA8, 0xBE, 0x6F,
|
||||||
|
0x09, 0x16, 0x35, 0x16, 0x3E, 0xCA, 0x79, 0xA8,
|
||||||
|
0x58, 0x5E, 0xD3, 0xE3, 0x17, 0x08, 0x07, 0xE7,
|
||||||
|
0xC0, 0x3B, 0x72, 0x0F, 0xC5, 0x4C, 0x7B, 0x23,
|
||||||
|
0x89, 0x7F, 0xCB, 0xA0, 0xE9, 0xD0, 0xB4, 0xA0,
|
||||||
|
0x68, 0x94, 0xCF, 0xD2, 0x49, 0xF2, 0x23, 0x67,
|
||||||
|
};
|
||||||
|
unsigned char msg[100];
|
||||||
|
memset(msg, 0x99, sizeof(msg));
|
||||||
|
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig);
|
||||||
|
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nonce function that returns constant 0 */
|
/* Nonce function that returns constant 0 */
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "checkmem.h"
|
#include "checkmem.h"
|
||||||
#include "int128.h"
|
#include "int128.h"
|
||||||
#include "modinv64_impl.h"
|
#include "modinv64_impl.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
/* Limbs of the secp256k1 order. */
|
/* Limbs of the secp256k1 order. */
|
||||||
#define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL)
|
#define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL)
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "checkmem.h"
|
#include "checkmem.h"
|
||||||
#include "modinv32_impl.h"
|
#include "modinv32_impl.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
/* Limbs of the secp256k1 order. */
|
/* Limbs of the secp256k1 order. */
|
||||||
#define SECP256K1_N_0 ((uint32_t)0xD0364141UL)
|
#define SECP256K1_N_0 ((uint32_t)0xD0364141UL)
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "checkmem.h"
|
#include "checkmem.h"
|
||||||
#include "scalar.h"
|
#include "scalar.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -268,8 +268,8 @@ static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge,
|
|||||||
} else {
|
} else {
|
||||||
/* Otherwise, fall back to 32-byte big endian for X and Y. */
|
/* Otherwise, fall back to 32-byte big endian for X and Y. */
|
||||||
secp256k1_fe x, y;
|
secp256k1_fe x, y;
|
||||||
secp256k1_fe_set_b32(&x, pubkey->data);
|
secp256k1_fe_set_b32_mod(&x, pubkey->data);
|
||||||
secp256k1_fe_set_b32(&y, pubkey->data + 32);
|
secp256k1_fe_set_b32_mod(&y, pubkey->data + 32);
|
||||||
secp256k1_ge_set_xy(ge, &x, &y);
|
secp256k1_ge_set_xy(ge, &x, &y);
|
||||||
}
|
}
|
||||||
ARG_CHECK(!secp256k1_fe_is_zero(&ge->x));
|
ARG_CHECK(!secp256k1_fe_is_zero(&ge->x));
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#ifndef SECP256K1_TESTRAND_H
|
#ifndef SECP256K1_TESTRAND_H
|
||||||
#define SECP256K1_TESTRAND_H
|
#define SECP256K1_TESTRAND_H
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
/* A non-cryptographic RNG used only for test infrastructure. */
|
/* A non-cryptographic RNG used only for test infrastructure. */
|
||||||
|
|
||||||
/** Seed the pseudorandom number generator for testing. */
|
/** Seed the pseudorandom number generator for testing. */
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "testrand.h"
|
#include "testrand.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
static uint64_t secp256k1_test_state[4];
|
static uint64_t secp256k1_test_state[4];
|
||||||
static uint64_t secp256k1_test_rng_integer;
|
static uint64_t secp256k1_test_rng_integer;
|
||||||
|
120
src/tests.c
120
src/tests.c
@ -10,7 +10,12 @@
|
|||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#ifdef USE_EXTERNAL_DEFAULT_CALLBACKS
|
||||||
|
#pragma message("Ignoring USE_EXTERNAL_CALLBACKS in tests.")
|
||||||
|
#undef USE_EXTERNAL_DEFAULT_CALLBACKS
|
||||||
|
#endif
|
||||||
#include "secp256k1.c"
|
#include "secp256k1.c"
|
||||||
|
|
||||||
#include "../include/secp256k1.h"
|
#include "../include/secp256k1.h"
|
||||||
#include "../include/secp256k1_preallocated.h"
|
#include "../include/secp256k1_preallocated.h"
|
||||||
#include "testrand_impl.h"
|
#include "testrand_impl.h"
|
||||||
@ -85,7 +90,7 @@ static void random_field_element_test(secp256k1_fe *fe) {
|
|||||||
do {
|
do {
|
||||||
unsigned char b32[32];
|
unsigned char b32[32];
|
||||||
secp256k1_testrand256_test(b32);
|
secp256k1_testrand256_test(b32);
|
||||||
if (secp256k1_fe_set_b32(fe, b32)) {
|
if (secp256k1_fe_set_b32_limit(fe, b32)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while(1);
|
} while(1);
|
||||||
@ -2267,7 +2272,7 @@ static void scalar_test(void) {
|
|||||||
for (i = 0; i < 100; ++i) {
|
for (i = 0; i < 100; ++i) {
|
||||||
int low;
|
int low;
|
||||||
int shift = 1 + secp256k1_testrand_int(15);
|
int shift = 1 + secp256k1_testrand_int(15);
|
||||||
int expected = r.d[0] % (1 << shift);
|
int expected = r.d[0] % (1ULL << shift);
|
||||||
low = secp256k1_scalar_shr_int(&r, shift);
|
low = secp256k1_scalar_shr_int(&r, shift);
|
||||||
CHECK(expected == low);
|
CHECK(expected == low);
|
||||||
}
|
}
|
||||||
@ -3122,7 +3127,7 @@ static void random_fe(secp256k1_fe *x) {
|
|||||||
unsigned char bin[32];
|
unsigned char bin[32];
|
||||||
do {
|
do {
|
||||||
secp256k1_testrand256(bin);
|
secp256k1_testrand256(bin);
|
||||||
if (secp256k1_fe_set_b32(x, bin)) {
|
if (secp256k1_fe_set_b32_limit(x, bin)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} while(1);
|
} while(1);
|
||||||
@ -3132,7 +3137,7 @@ static void random_fe_test(secp256k1_fe *x) {
|
|||||||
unsigned char bin[32];
|
unsigned char bin[32];
|
||||||
do {
|
do {
|
||||||
secp256k1_testrand256_test(bin);
|
secp256k1_testrand256_test(bin);
|
||||||
if (secp256k1_fe_set_b32(x, bin)) {
|
if (secp256k1_fe_set_b32_limit(x, bin)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} while(1);
|
} while(1);
|
||||||
@ -3186,7 +3191,7 @@ static void run_field_convert(void) {
|
|||||||
unsigned char b322[32];
|
unsigned char b322[32];
|
||||||
secp256k1_fe_storage fes2;
|
secp256k1_fe_storage fes2;
|
||||||
/* Check conversions to fe. */
|
/* Check conversions to fe. */
|
||||||
CHECK(secp256k1_fe_set_b32(&fe2, b32));
|
CHECK(secp256k1_fe_set_b32_limit(&fe2, b32));
|
||||||
CHECK(secp256k1_fe_equal_var(&fe, &fe2));
|
CHECK(secp256k1_fe_equal_var(&fe, &fe2));
|
||||||
secp256k1_fe_from_storage(&fe2, &fes);
|
secp256k1_fe_from_storage(&fe2, &fes);
|
||||||
CHECK(secp256k1_fe_equal_var(&fe, &fe2));
|
CHECK(secp256k1_fe_equal_var(&fe, &fe2));
|
||||||
@ -3197,6 +3202,72 @@ static void run_field_convert(void) {
|
|||||||
CHECK(secp256k1_memcmp_var(&fes2, &fes, sizeof(fes)) == 0);
|
CHECK(secp256k1_memcmp_var(&fes2, &fes, sizeof(fes)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void run_field_be32_overflow(void) {
|
||||||
|
{
|
||||||
|
static const unsigned char zero_overflow[32] = {
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F,
|
||||||
|
};
|
||||||
|
static const unsigned char zero[32] = { 0x00 };
|
||||||
|
unsigned char out[32];
|
||||||
|
secp256k1_fe fe;
|
||||||
|
CHECK(secp256k1_fe_set_b32_limit(&fe, zero_overflow) == 0);
|
||||||
|
secp256k1_fe_set_b32_mod(&fe, zero_overflow);
|
||||||
|
CHECK(secp256k1_fe_normalizes_to_zero(&fe) == 1);
|
||||||
|
secp256k1_fe_normalize(&fe);
|
||||||
|
CHECK(secp256k1_fe_is_zero(&fe) == 1);
|
||||||
|
secp256k1_fe_get_b32(out, &fe);
|
||||||
|
CHECK(secp256k1_memcmp_var(out, zero, 32) == 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
static const unsigned char one_overflow[32] = {
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30,
|
||||||
|
};
|
||||||
|
static const unsigned char one[32] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||||
|
};
|
||||||
|
unsigned char out[32];
|
||||||
|
secp256k1_fe fe;
|
||||||
|
CHECK(secp256k1_fe_set_b32_limit(&fe, one_overflow) == 0);
|
||||||
|
secp256k1_fe_set_b32_mod(&fe, one_overflow);
|
||||||
|
secp256k1_fe_normalize(&fe);
|
||||||
|
CHECK(secp256k1_fe_cmp_var(&fe, &secp256k1_fe_one) == 0);
|
||||||
|
secp256k1_fe_get_b32(out, &fe);
|
||||||
|
CHECK(secp256k1_memcmp_var(out, one, 32) == 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
static const unsigned char ff_overflow[32] = {
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
};
|
||||||
|
static const unsigned char ff[32] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0xD0,
|
||||||
|
};
|
||||||
|
unsigned char out[32];
|
||||||
|
secp256k1_fe fe;
|
||||||
|
const secp256k1_fe fe_ff = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0x01, 0x000003d0);
|
||||||
|
CHECK(secp256k1_fe_set_b32_limit(&fe, ff_overflow) == 0);
|
||||||
|
secp256k1_fe_set_b32_mod(&fe, ff_overflow);
|
||||||
|
secp256k1_fe_normalize(&fe);
|
||||||
|
CHECK(secp256k1_fe_cmp_var(&fe, &fe_ff) == 0);
|
||||||
|
secp256k1_fe_get_b32(out, &fe);
|
||||||
|
CHECK(secp256k1_memcmp_var(out, ff, 32) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns true if two field elements have the same representation. */
|
/* Returns true if two field elements have the same representation. */
|
||||||
static int fe_identical(const secp256k1_fe *a, const secp256k1_fe *b) {
|
static int fe_identical(const secp256k1_fe *a, const secp256k1_fe *b) {
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
@ -3775,7 +3846,7 @@ static void run_inverse_tests(void)
|
|||||||
b32[31] = i & 0xff;
|
b32[31] = i & 0xff;
|
||||||
b32[30] = (i >> 8) & 0xff;
|
b32[30] = (i >> 8) & 0xff;
|
||||||
secp256k1_scalar_set_b32(&x_scalar, b32, NULL);
|
secp256k1_scalar_set_b32(&x_scalar, b32, NULL);
|
||||||
secp256k1_fe_set_b32(&x_fe, b32);
|
secp256k1_fe_set_b32_mod(&x_fe, b32);
|
||||||
for (var = 0; var <= 1; ++var) {
|
for (var = 0; var <= 1; ++var) {
|
||||||
test_inverse_scalar(NULL, &x_scalar, var);
|
test_inverse_scalar(NULL, &x_scalar, var);
|
||||||
test_inverse_field(NULL, &x_fe, var);
|
test_inverse_field(NULL, &x_fe, var);
|
||||||
@ -3792,7 +3863,7 @@ static void run_inverse_tests(void)
|
|||||||
for (i = 0; i < 64 * COUNT; ++i) {
|
for (i = 0; i < 64 * COUNT; ++i) {
|
||||||
(testrand ? secp256k1_testrand256_test : secp256k1_testrand256)(b32);
|
(testrand ? secp256k1_testrand256_test : secp256k1_testrand256)(b32);
|
||||||
secp256k1_scalar_set_b32(&x_scalar, b32, NULL);
|
secp256k1_scalar_set_b32(&x_scalar, b32, NULL);
|
||||||
secp256k1_fe_set_b32(&x_fe, b32);
|
secp256k1_fe_set_b32_mod(&x_fe, b32);
|
||||||
for (var = 0; var <= 1; ++var) {
|
for (var = 0; var <= 1; ++var) {
|
||||||
test_inverse_scalar(NULL, &x_scalar, var);
|
test_inverse_scalar(NULL, &x_scalar, var);
|
||||||
test_inverse_field(NULL, &x_fe, var);
|
test_inverse_field(NULL, &x_fe, var);
|
||||||
@ -4352,7 +4423,7 @@ static void test_group_decompress(const secp256k1_fe* x) {
|
|||||||
CHECK(secp256k1_fe_equal_var(&ge_odd.x, x));
|
CHECK(secp256k1_fe_equal_var(&ge_odd.x, x));
|
||||||
|
|
||||||
/* Check that the Y coordinate result in ge_quad is a square. */
|
/* Check that the Y coordinate result in ge_quad is a square. */
|
||||||
CHECK(secp256k1_fe_is_quad_var(&ge_quad.y));
|
CHECK(secp256k1_fe_is_square_var(&ge_quad.y));
|
||||||
|
|
||||||
/* Check odd/even Y in ge_odd, ge_even. */
|
/* Check odd/even Y in ge_odd, ge_even. */
|
||||||
CHECK(secp256k1_fe_is_odd(&ge_odd.y));
|
CHECK(secp256k1_fe_is_odd(&ge_odd.y));
|
||||||
@ -4614,9 +4685,9 @@ static void test_ecmult_target(const secp256k1_scalar* target, int mode) {
|
|||||||
secp256k1_ecmult(&p2j, &pj, &n2, &zero);
|
secp256k1_ecmult(&p2j, &pj, &n2, &zero);
|
||||||
secp256k1_ecmult(&ptj, &pj, target, &zero);
|
secp256k1_ecmult(&ptj, &pj, target, &zero);
|
||||||
} else {
|
} else {
|
||||||
secp256k1_ecmult_const(&p1j, &p, &n1, 256);
|
secp256k1_ecmult_const(&p1j, &p, &n1);
|
||||||
secp256k1_ecmult_const(&p2j, &p, &n2, 256);
|
secp256k1_ecmult_const(&p2j, &p, &n2);
|
||||||
secp256k1_ecmult_const(&ptj, &p, target, 256);
|
secp256k1_ecmult_const(&ptj, &p, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add them all up: n1*P + n2*P + target*P = (n1+n2+target)*P = (n1+n1-n1-n2)*P = 0. */
|
/* Add them all up: n1*P + n2*P + target*P = (n1+n2+target)*P = (n1+n1-n1-n2)*P = 0. */
|
||||||
@ -4679,7 +4750,7 @@ static void ecmult_const_random_mult(void) {
|
|||||||
0xb84e4e1b, 0xfb77e21f, 0x96baae2a, 0x63dec956
|
0xb84e4e1b, 0xfb77e21f, 0x96baae2a, 0x63dec956
|
||||||
);
|
);
|
||||||
secp256k1_gej b;
|
secp256k1_gej b;
|
||||||
secp256k1_ecmult_const(&b, &a, &xn, 256);
|
secp256k1_ecmult_const(&b, &a, &xn);
|
||||||
|
|
||||||
CHECK(secp256k1_ge_is_valid_var(&a));
|
CHECK(secp256k1_ge_is_valid_var(&a));
|
||||||
ge_equals_gej(&expected_b, &b);
|
ge_equals_gej(&expected_b, &b);
|
||||||
@ -4695,12 +4766,12 @@ static void ecmult_const_commutativity(void) {
|
|||||||
random_scalar_order_test(&a);
|
random_scalar_order_test(&a);
|
||||||
random_scalar_order_test(&b);
|
random_scalar_order_test(&b);
|
||||||
|
|
||||||
secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a, 256);
|
secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a);
|
||||||
secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b, 256);
|
secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b);
|
||||||
secp256k1_ge_set_gej(&mid1, &res1);
|
secp256k1_ge_set_gej(&mid1, &res1);
|
||||||
secp256k1_ge_set_gej(&mid2, &res2);
|
secp256k1_ge_set_gej(&mid2, &res2);
|
||||||
secp256k1_ecmult_const(&res1, &mid1, &b, 256);
|
secp256k1_ecmult_const(&res1, &mid1, &b);
|
||||||
secp256k1_ecmult_const(&res2, &mid2, &a, 256);
|
secp256k1_ecmult_const(&res2, &mid2, &a);
|
||||||
secp256k1_ge_set_gej(&mid1, &res1);
|
secp256k1_ge_set_gej(&mid1, &res1);
|
||||||
secp256k1_ge_set_gej(&mid2, &res2);
|
secp256k1_ge_set_gej(&mid2, &res2);
|
||||||
ge_equals_ge(&mid1, &mid2);
|
ge_equals_ge(&mid1, &mid2);
|
||||||
@ -4716,13 +4787,13 @@ static void ecmult_const_mult_zero_one(void) {
|
|||||||
secp256k1_scalar_negate(&negone, &one);
|
secp256k1_scalar_negate(&negone, &one);
|
||||||
|
|
||||||
random_group_element_test(&point);
|
random_group_element_test(&point);
|
||||||
secp256k1_ecmult_const(&res1, &point, &zero, 3);
|
secp256k1_ecmult_const(&res1, &point, &zero);
|
||||||
secp256k1_ge_set_gej(&res2, &res1);
|
secp256k1_ge_set_gej(&res2, &res1);
|
||||||
CHECK(secp256k1_ge_is_infinity(&res2));
|
CHECK(secp256k1_ge_is_infinity(&res2));
|
||||||
secp256k1_ecmult_const(&res1, &point, &one, 2);
|
secp256k1_ecmult_const(&res1, &point, &one);
|
||||||
secp256k1_ge_set_gej(&res2, &res1);
|
secp256k1_ge_set_gej(&res2, &res1);
|
||||||
ge_equals_ge(&res2, &point);
|
ge_equals_ge(&res2, &point);
|
||||||
secp256k1_ecmult_const(&res1, &point, &negone, 256);
|
secp256k1_ecmult_const(&res1, &point, &negone);
|
||||||
secp256k1_gej_neg(&res1, &res1);
|
secp256k1_gej_neg(&res1, &res1);
|
||||||
secp256k1_ge_set_gej(&res2, &res1);
|
secp256k1_ge_set_gej(&res2, &res1);
|
||||||
ge_equals_ge(&res2, &point);
|
ge_equals_ge(&res2, &point);
|
||||||
@ -4752,7 +4823,7 @@ static void ecmult_const_mult_xonly(void) {
|
|||||||
n = base.x;
|
n = base.x;
|
||||||
}
|
}
|
||||||
/* Perform x-only multiplication. */
|
/* Perform x-only multiplication. */
|
||||||
res = secp256k1_ecmult_const_xonly(&resx, &n, (i & 1) ? &d : NULL, &q, 256, i & 2);
|
res = secp256k1_ecmult_const_xonly(&resx, &n, (i & 1) ? &d : NULL, &q, i & 2);
|
||||||
CHECK(res);
|
CHECK(res);
|
||||||
/* Perform normal multiplication. */
|
/* Perform normal multiplication. */
|
||||||
secp256k1_gej_set_ge(&basej, &base);
|
secp256k1_gej_set_ge(&basej, &base);
|
||||||
@ -4774,7 +4845,7 @@ static void ecmult_const_mult_xonly(void) {
|
|||||||
random_field_element_test(&x);
|
random_field_element_test(&x);
|
||||||
secp256k1_fe_sqr(&c, &x);
|
secp256k1_fe_sqr(&c, &x);
|
||||||
secp256k1_fe_mul(&c, &c, &x);
|
secp256k1_fe_mul(&c, &c, &x);
|
||||||
secp256k1_fe_add(&c, &secp256k1_fe_const_b);
|
secp256k1_fe_add_int(&c, SECP256K1_B);
|
||||||
} while (secp256k1_fe_is_square_var(&c));
|
} while (secp256k1_fe_is_square_var(&c));
|
||||||
/* If i is odd, n=d*x for random non-zero d. */
|
/* If i is odd, n=d*x for random non-zero d. */
|
||||||
if (i & 1) {
|
if (i & 1) {
|
||||||
@ -4785,7 +4856,7 @@ static void ecmult_const_mult_xonly(void) {
|
|||||||
} else {
|
} else {
|
||||||
n = x;
|
n = x;
|
||||||
}
|
}
|
||||||
res = secp256k1_ecmult_const_xonly(&r, &n, (i & 1) ? &d : NULL, &q, 256, 0);
|
res = secp256k1_ecmult_const_xonly(&r, &n, (i & 1) ? &d : NULL, &q, 0);
|
||||||
CHECK(res == 0);
|
CHECK(res == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4810,7 +4881,7 @@ static void ecmult_const_chain_multiply(void) {
|
|||||||
for (i = 0; i < 100; ++i) {
|
for (i = 0; i < 100; ++i) {
|
||||||
secp256k1_ge tmp;
|
secp256k1_ge tmp;
|
||||||
secp256k1_ge_set_gej(&tmp, &point);
|
secp256k1_ge_set_gej(&tmp, &point);
|
||||||
secp256k1_ecmult_const(&point, &tmp, &scalar, 256);
|
secp256k1_ecmult_const(&point, &tmp, &scalar);
|
||||||
}
|
}
|
||||||
secp256k1_ge_set_gej(&res, &point);
|
secp256k1_ge_set_gej(&res, &point);
|
||||||
ge_equals_gej(&res, &expected_point);
|
ge_equals_gej(&res, &expected_point);
|
||||||
@ -5708,7 +5779,7 @@ static void test_ecmult_accumulate(secp256k1_sha256* acc, const secp256k1_scalar
|
|||||||
secp256k1_ecmult(&rj3, &infj, &zero, x);
|
secp256k1_ecmult(&rj3, &infj, &zero, x);
|
||||||
secp256k1_ecmult_multi_var(NULL, scratch, &rj4, x, NULL, NULL, 0);
|
secp256k1_ecmult_multi_var(NULL, scratch, &rj4, x, NULL, NULL, 0);
|
||||||
secp256k1_ecmult_multi_var(NULL, scratch, &rj5, &zero, test_ecmult_accumulate_cb, (void*)x, 1);
|
secp256k1_ecmult_multi_var(NULL, scratch, &rj5, &zero, test_ecmult_accumulate_cb, (void*)x, 1);
|
||||||
secp256k1_ecmult_const(&rj6, &secp256k1_ge_const_g, x, 256);
|
secp256k1_ecmult_const(&rj6, &secp256k1_ge_const_g, x);
|
||||||
secp256k1_ge_set_gej_var(&r, &rj1);
|
secp256k1_ge_set_gej_var(&r, &rj1);
|
||||||
ge_equals_gej(&r, &rj2);
|
ge_equals_gej(&r, &rj2);
|
||||||
ge_equals_gej(&r, &rj3);
|
ge_equals_gej(&r, &rj3);
|
||||||
@ -8002,6 +8073,7 @@ int main(int argc, char **argv) {
|
|||||||
run_field_half();
|
run_field_half();
|
||||||
run_field_misc();
|
run_field_misc();
|
||||||
run_field_convert();
|
run_field_convert();
|
||||||
|
run_field_be32_overflow();
|
||||||
run_fe_mul();
|
run_fe_mul();
|
||||||
run_sqr();
|
run_sqr();
|
||||||
run_sqrt();
|
run_sqrt();
|
||||||
|
@ -13,13 +13,19 @@
|
|||||||
#define EXHAUSTIVE_TEST_ORDER 13
|
#define EXHAUSTIVE_TEST_ORDER 13
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_EXTERNAL_DEFAULT_CALLBACKS
|
||||||
|
#pragma message("Ignoring USE_EXTERNAL_CALLBACKS in exhaustive_tests.")
|
||||||
|
#undef USE_EXTERNAL_DEFAULT_CALLBACKS
|
||||||
|
#endif
|
||||||
#include "secp256k1.c"
|
#include "secp256k1.c"
|
||||||
|
|
||||||
#include "../include/secp256k1.h"
|
#include "../include/secp256k1.h"
|
||||||
#include "assumptions.h"
|
#include "assumptions.h"
|
||||||
#include "group.h"
|
#include "group.h"
|
||||||
#include "testrand_impl.h"
|
#include "testrand_impl.h"
|
||||||
#include "ecmult_compute_table_impl.h"
|
#include "ecmult_compute_table_impl.h"
|
||||||
#include "ecmult_gen_compute_table_impl.h"
|
#include "ecmult_gen_compute_table_impl.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
static int count = 2;
|
static int count = 2;
|
||||||
|
|
||||||
@ -54,7 +60,7 @@ static void random_fe(secp256k1_fe *x) {
|
|||||||
unsigned char bin[32];
|
unsigned char bin[32];
|
||||||
do {
|
do {
|
||||||
secp256k1_testrand256(bin);
|
secp256k1_testrand256(bin);
|
||||||
if (secp256k1_fe_set_b32(x, bin)) {
|
if (secp256k1_fe_set_b32_limit(x, bin)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} while(1);
|
} while(1);
|
||||||
@ -192,7 +198,7 @@ static void test_exhaustive_ecmult(const secp256k1_ge *group, const secp256k1_ge
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < EXHAUSTIVE_TEST_ORDER; j++) {
|
for (j = 0; j < EXHAUSTIVE_TEST_ORDER; j++) {
|
||||||
for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) {
|
for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) {
|
||||||
int ret;
|
int ret;
|
||||||
secp256k1_gej tmp;
|
secp256k1_gej tmp;
|
||||||
secp256k1_fe xn, xd, tmpf;
|
secp256k1_fe xn, xd, tmpf;
|
||||||
@ -203,19 +209,19 @@ static void test_exhaustive_ecmult(const secp256k1_ge *group, const secp256k1_ge
|
|||||||
secp256k1_scalar_set_int(&ng, j);
|
secp256k1_scalar_set_int(&ng, j);
|
||||||
|
|
||||||
/* Test secp256k1_ecmult_const. */
|
/* Test secp256k1_ecmult_const. */
|
||||||
secp256k1_ecmult_const(&tmp, &group[i], &ng, 256);
|
secp256k1_ecmult_const(&tmp, &group[i], &ng);
|
||||||
ge_equals_gej(&group[(i * j) % EXHAUSTIVE_TEST_ORDER], &tmp);
|
ge_equals_gej(&group[(i * j) % EXHAUSTIVE_TEST_ORDER], &tmp);
|
||||||
|
|
||||||
if (j != 0) {
|
if (i != 0 && j != 0) {
|
||||||
/* Test secp256k1_ecmult_const_xonly with all curve X coordinates, and xd=NULL. */
|
/* Test secp256k1_ecmult_const_xonly with all curve X coordinates, and xd=NULL. */
|
||||||
ret = secp256k1_ecmult_const_xonly(&tmpf, &group[i].x, NULL, &ng, 256, 0);
|
ret = secp256k1_ecmult_const_xonly(&tmpf, &group[i].x, NULL, &ng, 0);
|
||||||
CHECK(ret);
|
CHECK(ret);
|
||||||
CHECK(secp256k1_fe_equal_var(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x));
|
CHECK(secp256k1_fe_equal_var(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x));
|
||||||
|
|
||||||
/* Test secp256k1_ecmult_const_xonly with all curve X coordinates, with random xd. */
|
/* Test secp256k1_ecmult_const_xonly with all curve X coordinates, with random xd. */
|
||||||
random_fe_non_zero(&xd);
|
random_fe_non_zero(&xd);
|
||||||
secp256k1_fe_mul(&xn, &xd, &group[i].x);
|
secp256k1_fe_mul(&xn, &xd, &group[i].x);
|
||||||
ret = secp256k1_ecmult_const_xonly(&tmpf, &xn, &xd, &ng, 256, 0);
|
ret = secp256k1_ecmult_const_xonly(&tmpf, &xn, &xd, &ng, 0);
|
||||||
CHECK(ret);
|
CHECK(ret);
|
||||||
CHECK(secp256k1_fe_equal_var(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x));
|
CHECK(secp256k1_fe_equal_var(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x));
|
||||||
}
|
}
|
||||||
|
34
src/util.h
34
src/util.h
@ -7,6 +7,8 @@
|
|||||||
#ifndef SECP256K1_UTIL_H
|
#ifndef SECP256K1_UTIL_H
|
||||||
#define SECP256K1_UTIL_H
|
#define SECP256K1_UTIL_H
|
||||||
|
|
||||||
|
#include "../include/secp256k1.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -17,6 +19,38 @@
|
|||||||
#define DEBUG_CONFIG_MSG(x) "DEBUG_CONFIG: " x
|
#define DEBUG_CONFIG_MSG(x) "DEBUG_CONFIG: " x
|
||||||
#define DEBUG_CONFIG_DEF(x) DEBUG_CONFIG_MSG(#x "=" STR(x))
|
#define DEBUG_CONFIG_DEF(x) DEBUG_CONFIG_MSG(#x "=" STR(x))
|
||||||
|
|
||||||
|
/* Debug helper for printing arrays of unsigned char. */
|
||||||
|
#define PRINT_BUF(buf, len) do { \
|
||||||
|
printf("%s[%lu] = ", #buf, (unsigned long)len); \
|
||||||
|
print_buf_plain(buf, len); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
static void print_buf_plain(const unsigned char *buf, size_t len) {
|
||||||
|
size_t i;
|
||||||
|
printf("{");
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (i % 8 == 0) {
|
||||||
|
printf("\n ");
|
||||||
|
} else {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
printf("0x%02X,", buf[i]);
|
||||||
|
}
|
||||||
|
printf("\n}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
|
||||||
|
# if SECP256K1_GNUC_PREREQ(2,7)
|
||||||
|
# define SECP256K1_INLINE __inline__
|
||||||
|
# elif (defined(_MSC_VER))
|
||||||
|
# define SECP256K1_INLINE __inline
|
||||||
|
# else
|
||||||
|
# define SECP256K1_INLINE
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# define SECP256K1_INLINE inline
|
||||||
|
# endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void (*fn)(const char *text, void* data);
|
void (*fn)(const char *text, void* data);
|
||||||
const void* data;
|
const void* data;
|
||||||
|
@ -7,8 +7,6 @@ Generate a C file with ECDSA testvectors from the Wycheproof project.
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import hashlib
|
|
||||||
import urllib.request
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
filename_input = sys.argv[1]
|
filename_input = sys.argv[1]
|
||||||
@ -19,7 +17,8 @@ with open(filename_input) as f:
|
|||||||
num_groups = len(doc['testGroups'])
|
num_groups = len(doc['testGroups'])
|
||||||
|
|
||||||
def to_c_array(x):
|
def to_c_array(x):
|
||||||
if x == "": return ""
|
if x == "":
|
||||||
|
return ""
|
||||||
s = ',0x'.join(a+b for a,b in zip(x[::2], x[1::2]))
|
s = ',0x'.join(a+b for a,b in zip(x[::2], x[1::2]))
|
||||||
return "0x" + s
|
return "0x" + s
|
||||||
|
|
||||||
@ -43,18 +42,23 @@ for i in range(num_groups):
|
|||||||
sig_size = len(test_vector['sig']) // 2
|
sig_size = len(test_vector['sig']) // 2
|
||||||
msg_size = len(test_vector['msg']) // 2
|
msg_size = len(test_vector['msg']) // 2
|
||||||
|
|
||||||
if test_vector['result'] == "invalid": expected_verify = 0
|
if test_vector['result'] == "invalid":
|
||||||
elif test_vector['result'] == "valid": expected_verify = 1
|
expected_verify = 0
|
||||||
else: raise ValueError("invalid result field")
|
elif test_vector['result'] == "valid":
|
||||||
|
expected_verify = 1
|
||||||
|
else:
|
||||||
|
raise ValueError("invalid result field")
|
||||||
|
|
||||||
if num_vectors != 0 and sig_size != 0: signatures += ",\n "
|
if num_vectors != 0 and sig_size != 0:
|
||||||
|
signatures += ",\n "
|
||||||
|
|
||||||
new_msg = False
|
new_msg = False
|
||||||
msg = to_c_array(test_vector['msg'])
|
msg = to_c_array(test_vector['msg'])
|
||||||
msg_offset = offset_msg_running
|
msg_offset = offset_msg_running
|
||||||
# check for repeated msg
|
# check for repeated msg
|
||||||
if msg not in cache_msgs.keys():
|
if msg not in cache_msgs:
|
||||||
if num_vectors != 0 and msg_size != 0: messages += ",\n "
|
if num_vectors != 0 and msg_size != 0:
|
||||||
|
messages += ",\n "
|
||||||
cache_msgs[msg] = offset_msg_running
|
cache_msgs[msg] = offset_msg_running
|
||||||
messages += msg
|
messages += msg
|
||||||
new_msg = True
|
new_msg = True
|
||||||
@ -65,8 +69,9 @@ for i in range(num_groups):
|
|||||||
pk = to_c_array(public_key['uncompressed'])
|
pk = to_c_array(public_key['uncompressed'])
|
||||||
pk_offset = offset_pk_running
|
pk_offset = offset_pk_running
|
||||||
# check for repeated pk
|
# check for repeated pk
|
||||||
if pk not in cache_public_keys.keys():
|
if pk not in cache_public_keys:
|
||||||
if num_vectors != 0: public_keys += ",\n "
|
if num_vectors != 0:
|
||||||
|
public_keys += ",\n "
|
||||||
cache_public_keys[pk] = offset_pk_running
|
cache_public_keys[pk] = offset_pk_running
|
||||||
public_keys += pk
|
public_keys += pk
|
||||||
new_pk = True
|
new_pk = True
|
||||||
@ -76,15 +81,11 @@ for i in range(num_groups):
|
|||||||
signatures += to_c_array(test_vector['sig'])
|
signatures += to_c_array(test_vector['sig'])
|
||||||
|
|
||||||
out += " /" + "* tcId: " + str(test_vector['tcId']) + ". " + test_vector['comment'] + " *" + "/\n"
|
out += " /" + "* tcId: " + str(test_vector['tcId']) + ". " + test_vector['comment'] + " *" + "/\n"
|
||||||
out += " {" + "{0}, {1}, {2}, {3}, {4}, {5}".format(
|
out += f" {{{pk_offset}, {msg_offset}, {msg_size}, {offset_sig}, {sig_size}, {expected_verify} }},\n"
|
||||||
pk_offset,
|
if new_msg:
|
||||||
msg_offset,
|
offset_msg_running += msg_size
|
||||||
msg_size,
|
if new_pk:
|
||||||
offset_sig,
|
offset_pk_running += 65
|
||||||
sig_size,
|
|
||||||
expected_verify) + " },\n"
|
|
||||||
if new_msg: offset_msg_running += msg_size
|
|
||||||
if new_pk: offset_pk_running += 65
|
|
||||||
offset_sig += sig_size
|
offset_sig += sig_size
|
||||||
num_vectors += 1
|
num_vectors += 1
|
||||||
|
|
||||||
@ -101,7 +102,7 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
print("/* Note: this file was autogenerated using tests_wycheproof_generate.py. Do not edit. */")
|
print("/* Note: this file was autogenerated using tests_wycheproof_generate.py. Do not edit. */")
|
||||||
print("#define SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS ({})".format(num_vectors))
|
print(f"#define SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS ({num_vectors})")
|
||||||
|
|
||||||
print(struct_definition)
|
print(struct_definition)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user