diff --git a/src/secp256k1/.github/workflows/ci.yml b/src/secp256k1/.github/workflows/ci.yml index 54b2fab1c46..c87de301cd7 100644 --- a/src/secp256k1/.github/workflows/ci.yml +++ b/src/secp256k1/.github/workflows/ci.yml @@ -746,6 +746,8 @@ jobs: cpp_flags: '/DSECP256K1_MSVC_MULH_TEST_OVERRIDE' - job_name: 'x86 (MSVC): Windows (VS 2022)' cmake_options: '-A Win32' + - job_name: 'x64 (MSVC): Windows (clang-cl)' + cmake_options: '-T ClangCL' steps: - name: Checkout diff --git a/src/secp256k1/CHANGELOG.md b/src/secp256k1/CHANGELOG.md index ee447c0c1c7..05222e5ed01 100644 --- a/src/secp256k1/CHANGELOG.md +++ b/src/secp256k1/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + ## [0.6.0] - 2024-11-04 #### Added @@ -162,6 +164,7 @@ This version was in fact never released. The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6). Therefore, this version number does not uniquely identify a set of source files. +[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.6.0...HEAD [0.6.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.1...v0.6.0 [0.5.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.1...v0.5.0 diff --git a/src/secp256k1/CMakeLists.txt b/src/secp256k1/CMakeLists.txt index 041bfa3dca0..520a96efdc7 100644 --- a/src/secp256k1/CMakeLists.txt +++ b/src/secp256k1/CMakeLists.txt @@ -7,7 +7,7 @@ project(libsecp256k1 # The package (a.k.a. release) version is based on semantic versioning 2.0.0 of # the API. All changes in experimental modules are treated as # backwards-compatible and therefore at most increase the minor version. - VERSION 0.6.0 + VERSION 0.6.1 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 @@ -32,7 +32,7 @@ endif() # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. set(${PROJECT_NAME}_LIB_VERSION_CURRENT 5) -set(${PROJECT_NAME}_LIB_VERSION_REVISION 0) +set(${PROJECT_NAME}_LIB_VERSION_REVISION 1) set(${PROJECT_NAME}_LIB_VERSION_AGE 0) #============================= @@ -55,7 +55,7 @@ option(SECP256K1_INSTALL "Enable installation." ${PROJECT_IS_TOP_LEVEL}) ## Modules # We declare all options before processing them, to make sure we can express -# dependendencies while processing. +# dependencies while processing. option(SECP256K1_ENABLE_MODULE_ECDH "Enable ECDH module." ON) option(SECP256K1_ENABLE_MODULE_RECOVERY "Enable ECDSA pubkey recovery module." OFF) option(SECP256K1_ENABLE_MODULE_EXTRAKEYS "Enable extrakeys module." ON) @@ -242,17 +242,21 @@ endif() include(TryAppendCFlags) if(MSVC) - # Keep the following commands ordered lexicographically. + # For both cl and clang-cl compilers. try_append_c_flags(/W3) # Production quality warning level. - try_append_c_flags(/wd4146) # Disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned". - try_append_c_flags(/wd4244) # Disable warning C4244 "'conversion' conversion from 'type1' to 'type2', possible loss of data". - try_append_c_flags(/wd4267) # Disable warning C4267 "'var' : conversion from 'size_t' to 'type', possible loss of data". # Eliminate deprecation warnings for the older, less secure functions. add_compile_definitions(_CRT_SECURE_NO_WARNINGS) +else() + try_append_c_flags(-Wall) # GCC >= 2.95 and probably many other compilers. +endif() +if(CMAKE_C_COMPILER_ID STREQUAL "MSVC") + # Keep the following commands ordered lexicographically. + try_append_c_flags(/wd4146) # Disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned". + try_append_c_flags(/wd4244) # Disable warning C4244 "'conversion' conversion from 'type1' to 'type2', possible loss of data". + try_append_c_flags(/wd4267) # Disable warning C4267 "'var' : conversion from 'size_t' to 'type', possible loss of data". else() # Keep the following commands ordered lexicographically. try_append_c_flags(-pedantic) - try_append_c_flags(-Wall) # GCC >= 2.95 and probably many other compilers. try_append_c_flags(-Wcast-align) # GCC >= 2.95. try_append_c_flags(-Wcast-align=strict) # GCC >= 8.0. try_append_c_flags(-Wconditional-uninitialized) # Clang >= 3.0 only. diff --git a/src/secp256k1/CONTRIBUTING.md b/src/secp256k1/CONTRIBUTING.md index a366d38b0ec..80890fb7068 100644 --- a/src/secp256k1/CONTRIBUTING.md +++ b/src/secp256k1/CONTRIBUTING.md @@ -74,6 +74,7 @@ In addition, libsecp256k1 tries to maintain the following coding conventions: * User-facing comment lines in headers should be limited to 80 chars if possible. * All identifiers in file scope should start with `secp256k1_`. * Avoid trailing whitespace. +* Use the constants `EXIT_SUCCESS`/`EXIT_FAILURE` (defined in `stdlib.h`) to indicate program execution status for examples and other binaries. ### Tests diff --git a/src/secp256k1/README.md b/src/secp256k1/README.md index 222e5fb7685..f7a59b2b966 100644 --- a/src/secp256k1/README.md +++ b/src/secp256k1/README.md @@ -61,14 +61,50 @@ Implementation details * Optional runtime blinding which attempts to frustrate differential power analysis. * The precomputed tables add and eventually subtract points for which no known scalar (secret key) is known, preventing even an attacker with control over the secret key used to control the data internally. +Obtaining and verifying +----------------------- + +The git tag for each release (e.g. `v0.6.0`) is GPG-signed by one of the maintainers. +For a fully verified build of this project, it is recommended to obtain this repository +via git, obtain the GPG keys of the signing maintainer(s), and then verify the release +tag's signature using git. + +This can be done with the following steps: + +1. Obtain the GPG keys listed in [SECURITY.md](./SECURITY.md). +2. If possible, cross-reference these key IDs with another source controlled by its owner (e.g. + social media, personal website). This is to mitigate the unlikely case that incorrect + content is being presented by this repository. +3. Clone the repository: + ``` + git clone https://github.com/bitcoin-core/secp256k1 + ``` +4. Check out the latest release tag, e.g. + ``` + git checkout v0.6.0 + ``` +5. Use git to verify the GPG signature: + ``` + % git tag -v v0.6.0 | grep -C 3 'Good signature' + + gpg: Signature made Mon 04 Nov 2024 12:14:44 PM EST + gpg: using RSA key 4BBB845A6F5A65A69DFAEC234861DBF262123605 + gpg: Good signature from "Jonas Nick " [unknown] + gpg: aka "Jonas Nick " [unknown] + gpg: WARNING: This key is not certified with a trusted signature! + gpg: There is no indication that the signature belongs to the owner. + Primary key fingerprint: 36C7 1A37 C9D9 88BD E825 08D9 B1A7 0E4F 8DCD 0366 + Subkey fingerprint: 4BBB 845A 6F5A 65A6 9DFA EC23 4861 DBF2 6212 3605 + ``` + Building with Autotools ----------------------- - $ ./autogen.sh - $ ./configure - $ make - $ make check # run the test suite - $ sudo make install # optional + $ ./autogen.sh # Generate a ./configure script + $ ./configure # Generate a build system + $ make # Run the actual build process + $ make check # Run the test suite + $ sudo make install # Install the library into the system (optional) To compile optional modules (such as Schnorr signatures), you need to run `./configure` with additional flags (such as `--enable-module-schnorrsig`). Run `./configure --help` to see the full list of available flags. @@ -79,24 +115,23 @@ To maintain a pristine source tree, CMake encourages to perform an out-of-source ### Building on POSIX systems - $ mkdir build && cd build - $ cmake .. - $ cmake --build . - $ ctest # run the test suite - $ sudo cmake --install . # optional + $ cmake -B build # Generate a build system in subdirectory "build" + $ cmake --build build # Run the actual build process + $ ctest --test-dir build # Run the test suite + $ sudo cmake --install build # Install the library into the system (optional) -To compile optional modules (such as Schnorr signatures), you need to run `cmake` with additional flags (such as `-DSECP256K1_ENABLE_MODULE_SCHNORRSIG=ON`). Run `cmake .. -LH` to see the full list of available flags. +To compile optional modules (such as Schnorr signatures), you need to run `cmake` with additional flags (such as `-DSECP256K1_ENABLE_MODULE_SCHNORRSIG=ON`). Run `cmake -B build -LH` or `ccmake -B build` to see the full list of available flags. ### Cross compiling To alleviate issues with cross compiling, preconfigured toolchain files are available in the `cmake` directory. For example, to cross compile for Windows: - $ cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/x86_64-w64-mingw32.toolchain.cmake + $ cmake -B build -DCMAKE_TOOLCHAIN_FILE=cmake/x86_64-w64-mingw32.toolchain.cmake To cross compile for Android with [NDK](https://developer.android.com/ndk/guides/cmake) (using NDK's toolchain file, and assuming the `ANDROID_NDK_ROOT` environment variable has been set): - $ cmake .. -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=28 + $ cmake -B build -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=28 ### Building on Windows @@ -106,7 +141,7 @@ The following example assumes using of Visual Studio 2022 and CMake v3.21+. In "Developer Command Prompt for VS 2022": - >cmake -G "Visual Studio 17 2022" -A x64 -S . -B build + >cmake -G "Visual Studio 17 2022" -A x64 -B build >cmake --build build --config RelWithDebInfo Usage examples diff --git a/src/secp256k1/configure.ac b/src/secp256k1/configure.ac index f880a3578dd..c62a391d781 100644 --- a/src/secp256k1/configure.ac +++ b/src/secp256k1/configure.ac @@ -5,8 +5,8 @@ AC_PREREQ([2.60]) # backwards-compatible and therefore at most increase the minor version. define(_PKG_VERSION_MAJOR, 0) define(_PKG_VERSION_MINOR, 6) -define(_PKG_VERSION_PATCH, 0) -define(_PKG_VERSION_IS_RELEASE, true) +define(_PKG_VERSION_PATCH, 1) +define(_PKG_VERSION_IS_RELEASE, false) # The library version is based on libtool versioning of the ABI. The set of # rules for updating the version can be found here: @@ -14,7 +14,7 @@ define(_PKG_VERSION_IS_RELEASE, true) # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. define(_LIB_VERSION_CURRENT, 5) -define(_LIB_VERSION_REVISION, 0) +define(_LIB_VERSION_REVISION, 1) define(_LIB_VERSION_AGE, 0) AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1]) @@ -254,8 +254,8 @@ fi print_msan_notice=no if test x"$enable_ctime_tests" = x"yes"; then SECP_MSAN_CHECK - # MSan on Clang >=16 reports unitialized memory in function parameters and return values, even if - # the uninitalized variable is never actually "used". This is called "eager" checking, and it's + # MSan on Clang >=16 reports uninitialized memory in function parameters and return values, even if + # the uninitialized variable is never actually "used". This is called "eager" checking, and it's # sounds like good idea for normal use of MSan. However, it yields many false positives in the # ctime_tests because many return values depend on secret (i.e., "uninitialized") values, and # we're only interested in detecting branches (which count as "uses") on secret data. diff --git a/src/secp256k1/examples/ecdh.c b/src/secp256k1/examples/ecdh.c index 13aa760b2dc..67b8c2047ab 100644 --- a/src/secp256k1/examples/ecdh.c +++ b/src/secp256k1/examples/ecdh.c @@ -8,6 +8,7 @@ *************************************************************************/ #include +#include #include #include @@ -33,7 +34,7 @@ int main(void) { secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); if (!fill_random(randomize, sizeof(randomize))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* Randomizing the context is recommended to protect against side-channel * leakage See `secp256k1_context_randomize` in secp256k1.h for more @@ -44,14 +45,14 @@ int main(void) { /*** Key Generation ***/ if (!fill_random(seckey1, sizeof(seckey1)) || !fill_random(seckey2, sizeof(seckey2))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* If the secret key is zero or out of range (greater than secp256k1's * order), we fail. Note that the probability of this occurring is negligible * with a properly functioning random number generator. */ if (!secp256k1_ec_seckey_verify(ctx, seckey1) || !secp256k1_ec_seckey_verify(ctx, seckey2)) { printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); - return 1; + return EXIT_FAILURE; } /* Public key creation using a valid context with a verified secret key should never fail */ @@ -116,5 +117,5 @@ int main(void) { secure_erase(shared_secret1, sizeof(shared_secret1)); secure_erase(shared_secret2, sizeof(shared_secret2)); - return 0; + return EXIT_SUCCESS; } diff --git a/src/secp256k1/examples/ecdsa.c b/src/secp256k1/examples/ecdsa.c index 80ae9d46c52..ae16c180dc9 100644 --- a/src/secp256k1/examples/ecdsa.c +++ b/src/secp256k1/examples/ecdsa.c @@ -8,6 +8,7 @@ *************************************************************************/ #include +#include #include #include @@ -40,7 +41,7 @@ int main(void) { secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); if (!fill_random(randomize, sizeof(randomize))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* Randomizing the context is recommended to protect against side-channel * leakage See `secp256k1_context_randomize` in secp256k1.h for more @@ -51,14 +52,14 @@ int main(void) { /*** Key Generation ***/ if (!fill_random(seckey, sizeof(seckey))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* If the secret key is zero or out of range (greater than secp256k1's * order), we fail. Note that the probability of this occurring is negligible * with a properly functioning random number generator. */ if (!secp256k1_ec_seckey_verify(ctx, seckey)) { printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); - return 1; + return EXIT_FAILURE; } /* Public key creation using a valid context with a verified secret key should never fail */ @@ -92,13 +93,13 @@ int main(void) { /* Deserialize the signature. This will return 0 if the signature can't be parsed correctly. */ if (!secp256k1_ecdsa_signature_parse_compact(ctx, &sig, serialized_signature)) { printf("Failed parsing the signature\n"); - return 1; + return EXIT_FAILURE; } /* Deserialize the public key. This will return 0 if the public key can't be parsed correctly. */ if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, compressed_pubkey, sizeof(compressed_pubkey))) { printf("Failed parsing the public key\n"); - return 1; + return EXIT_FAILURE; } /* Verify a signature. This will return 1 if it's valid and 0 if it's not. */ @@ -133,5 +134,5 @@ int main(void) { * will remove any writes that aren't used. */ secure_erase(seckey, sizeof(seckey)); - return 0; + return EXIT_SUCCESS; } diff --git a/src/secp256k1/examples/ellswift.c b/src/secp256k1/examples/ellswift.c index afb2fee40be..d58e96b053d 100644 --- a/src/secp256k1/examples/ellswift.c +++ b/src/secp256k1/examples/ellswift.c @@ -13,6 +13,7 @@ */ #include +#include #include #include @@ -38,7 +39,7 @@ int main(void) { ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); if (!fill_random(randomize, sizeof(randomize))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* Randomizing the context is recommended to protect against side-channel * leakage. See `secp256k1_context_randomize` in secp256k1.h for more @@ -49,14 +50,14 @@ int main(void) { /*** Generate secret keys ***/ if (!fill_random(seckey1, sizeof(seckey1)) || !fill_random(seckey2, sizeof(seckey2))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* If the secret key is zero or out of range (greater than secp256k1's * order), we fail. Note that the probability of this occurring is negligible * with a properly functioning random number generator. */ if (!secp256k1_ec_seckey_verify(ctx, seckey1) || !secp256k1_ec_seckey_verify(ctx, seckey2)) { printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); - return 1; + return EXIT_FAILURE; } /* Generate ElligatorSwift public keys. This should never fail with valid context and @@ -64,7 +65,7 @@ int main(void) { optional, but recommended. */ if (!fill_random(auxrand1, sizeof(auxrand1)) || !fill_random(auxrand2, sizeof(auxrand2))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } return_val = secp256k1_ellswift_create(ctx, ellswift_pubkey1, seckey1, auxrand1); assert(return_val); @@ -117,5 +118,5 @@ int main(void) { secure_erase(shared_secret1, sizeof(shared_secret1)); secure_erase(shared_secret2, sizeof(shared_secret2)); - return 0; + return EXIT_SUCCESS; } diff --git a/src/secp256k1/examples/musig.c b/src/secp256k1/examples/musig.c index 0352dc40f37..bdb8fced0cf 100644 --- a/src/secp256k1/examples/musig.c +++ b/src/secp256k1/examples/musig.c @@ -12,6 +12,7 @@ */ #include +#include #include #include @@ -193,7 +194,7 @@ int main(void) { for (i = 0; i < N_SIGNERS; i++) { if (!create_keypair(ctx, &signer_secrets[i], &signers[i])) { printf("FAILED\n"); - return 1; + return EXIT_FAILURE; } pubkeys_ptr[i] = &signers[i].pubkey; } @@ -208,7 +209,7 @@ int main(void) { fflush(stdout); if (!secp256k1_ec_pubkey_sort(ctx, pubkeys_ptr, N_SIGNERS)) { printf("FAILED\n"); - return 1; + return EXIT_FAILURE; } printf("ok\n"); @@ -219,7 +220,7 @@ int main(void) { * while providing a non-NULL agg_pk argument. */ if (!secp256k1_musig_pubkey_agg(ctx, NULL, &cache, pubkeys_ptr, N_SIGNERS)) { printf("FAILED\n"); - return 1; + return EXIT_FAILURE; } printf("ok\n"); printf("Tweaking................"); @@ -227,21 +228,21 @@ int main(void) { /* Optionally tweak the aggregate key */ if (!tweak(ctx, &agg_pk, &cache)) { printf("FAILED\n"); - return 1; + return EXIT_FAILURE; } printf("ok\n"); printf("Signing message........."); fflush(stdout); if (!sign(ctx, signer_secrets, signers, &cache, msg, sig)) { printf("FAILED\n"); - return 1; + return EXIT_FAILURE; } printf("ok\n"); printf("Verifying signature....."); fflush(stdout); if (!secp256k1_schnorrsig_verify(ctx, sig, msg, 32, &agg_pk)) { printf("FAILED\n"); - return 1; + return EXIT_FAILURE; } printf("ok\n"); @@ -256,5 +257,5 @@ int main(void) { secure_erase(&signer_secrets[i], sizeof(signer_secrets[i])); } secp256k1_context_destroy(ctx); - return 0; + return EXIT_SUCCESS; } diff --git a/src/secp256k1/examples/schnorr.c b/src/secp256k1/examples/schnorr.c index 909fcaa1f3f..49baed24beb 100644 --- a/src/secp256k1/examples/schnorr.c +++ b/src/secp256k1/examples/schnorr.c @@ -8,6 +8,7 @@ *************************************************************************/ #include +#include #include #include @@ -34,7 +35,7 @@ int main(void) { secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); if (!fill_random(randomize, sizeof(randomize))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* Randomizing the context is recommended to protect against side-channel * leakage See `secp256k1_context_randomize` in secp256k1.h for more @@ -45,7 +46,7 @@ int main(void) { /*** Key Generation ***/ if (!fill_random(seckey, sizeof(seckey))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* Try to create a keypair with a valid context. This only fails if the * secret key is zero or out of range (greater than secp256k1's order). Note @@ -53,7 +54,7 @@ int main(void) { * functioning random number generator. */ if (!secp256k1_keypair_create(ctx, &keypair, seckey)) { printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); - return 1; + return EXIT_FAILURE; } /* Extract the X-only public key from the keypair. We pass NULL for @@ -90,7 +91,7 @@ int main(void) { /* Generate 32 bytes of randomness to use with BIP-340 schnorr signing. */ if (!fill_random(auxiliary_rand, sizeof(auxiliary_rand))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* Generate a Schnorr signature. @@ -110,7 +111,7 @@ int main(void) { * be parsed correctly */ if (!secp256k1_xonly_pubkey_parse(ctx, &pubkey, serialized_pubkey)) { printf("Failed parsing the public key\n"); - return 1; + return EXIT_FAILURE; } /* Compute the tagged hash on the received messages using the same tag as the signer. */ @@ -149,5 +150,5 @@ int main(void) { * Here we are preventing these writes from being optimized out, as any good compiler * will remove any writes that aren't used. */ secure_erase(seckey, sizeof(seckey)); - return 0; + return EXIT_SUCCESS; } diff --git a/src/secp256k1/include/secp256k1.h b/src/secp256k1/include/secp256k1.h index c6e9417f055..ccb7457e3d2 100644 --- a/src/secp256k1/include/secp256k1.h +++ b/src/secp256k1/include/secp256k1.h @@ -230,10 +230,10 @@ typedef int (*secp256k1_nonce_function)( * * It is highly recommended to call secp256k1_selftest before using this context. */ -SECP256K1_API const secp256k1_context *secp256k1_context_static; +SECP256K1_API const secp256k1_context * const secp256k1_context_static; /** Deprecated alias for secp256k1_context_static. */ -SECP256K1_API const secp256k1_context *secp256k1_context_no_precomp +SECP256K1_API const secp256k1_context * const secp256k1_context_no_precomp SECP256K1_DEPRECATED("Use secp256k1_context_static instead"); /** Perform basic self tests (to be used in conjunction with secp256k1_context_static) diff --git a/src/secp256k1/src/bench.c b/src/secp256k1/src/bench.c index 1127df67ae0..149f25fce47 100644 --- a/src/secp256k1/src/bench.c +++ b/src/secp256k1/src/bench.c @@ -5,6 +5,7 @@ ***********************************************************************/ #include +#include #include #include "../include/secp256k1.h" @@ -188,11 +189,11 @@ int main(int argc, char** argv) { || have_flag(argc, argv, "--help") || have_flag(argc, argv, "help")) { help(default_iters); - return 0; + return EXIT_SUCCESS; } else if (invalid_args) { fprintf(stderr, "./bench: unrecognized argument.\n\n"); help(default_iters); - return 1; + return EXIT_FAILURE; } } @@ -201,7 +202,7 @@ int main(int argc, char** argv) { if (have_flag(argc, argv, "ecdh")) { fprintf(stderr, "./bench: ECDH module not enabled.\n"); fprintf(stderr, "Use ./configure --enable-module-ecdh.\n\n"); - return 1; + return EXIT_FAILURE; } #endif @@ -209,7 +210,7 @@ int main(int argc, char** argv) { if (have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) { fprintf(stderr, "./bench: Public key recovery module not enabled.\n"); fprintf(stderr, "Use ./configure --enable-module-recovery.\n\n"); - return 1; + return EXIT_FAILURE; } #endif @@ -217,7 +218,7 @@ int main(int argc, char** argv) { if (have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "schnorrsig_sign") || have_flag(argc, argv, "schnorrsig_verify")) { fprintf(stderr, "./bench: Schnorr signatures module not enabled.\n"); fprintf(stderr, "Use ./configure --enable-module-schnorrsig.\n\n"); - return 1; + return EXIT_FAILURE; } #endif @@ -227,7 +228,7 @@ int main(int argc, char** argv) { have_flag(argc, argv, "ellswift_ecdh")) { fprintf(stderr, "./bench: ElligatorSwift module not enabled.\n"); fprintf(stderr, "Use ./configure --enable-module-ellswift.\n\n"); - return 1; + return EXIT_FAILURE; } #endif @@ -275,5 +276,5 @@ int main(int argc, char** argv) { run_ellswift_bench(iters, argc, argv); #endif - return 0; + return EXIT_SUCCESS; } diff --git a/src/secp256k1/src/bench.h b/src/secp256k1/src/bench.h index 1564b1a1760..232fb35fc0e 100644 --- a/src/secp256k1/src/bench.h +++ b/src/secp256k1/src/bench.h @@ -24,7 +24,7 @@ static int64_t gettime_i64(void) { struct timespec tv; if (!timespec_get(&tv, TIME_UTC)) { fputs("timespec_get failed!", stderr); - exit(1); + exit(EXIT_FAILURE); } return (int64_t)tv.tv_nsec / 1000 + (int64_t)tv.tv_sec * 1000000LL; #else diff --git a/src/secp256k1/src/bench_ecmult.c b/src/secp256k1/src/bench_ecmult.c index 3974af75f44..172292d5706 100644 --- a/src/secp256k1/src/bench_ecmult.c +++ b/src/secp256k1/src/bench_ecmult.c @@ -4,6 +4,7 @@ * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ #include +#include #include "secp256k1.c" #include "../include/secp256k1.h" @@ -287,7 +288,7 @@ int main(int argc, char **argv) { || have_flag(argc, argv, "--help") || have_flag(argc, argv, "help")) { help(argv); - return 0; + return EXIT_SUCCESS; } else if(have_flag(argc, argv, "pippenger_wnaf")) { printf("Using pippenger_wnaf:\n"); data.ecmult_multi = secp256k1_ecmult_pippenger_batch_single; @@ -299,7 +300,7 @@ int main(int argc, char **argv) { } else { fprintf(stderr, "%s: unrecognized argument '%s'.\n\n", argv[0], argv[1]); help(argv); - return 1; + return EXIT_FAILURE; } } @@ -363,5 +364,5 @@ int main(int argc, char **argv) { free(data.output); free(data.expected_output); - return(0); + return EXIT_SUCCESS; } diff --git a/src/secp256k1/src/bench_internal.c b/src/secp256k1/src/bench_internal.c index a700684922a..8688a4dc77c 100644 --- a/src/secp256k1/src/bench_internal.c +++ b/src/secp256k1/src/bench_internal.c @@ -4,6 +4,7 @@ * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ #include +#include #include "secp256k1.c" #include "../include/secp256k1.h" @@ -393,7 +394,7 @@ int main(int argc, char **argv) { || have_flag(argc, argv, "--help") || have_flag(argc, argv, "help")) { help(default_iters); - return 0; + return EXIT_SUCCESS; } } @@ -432,5 +433,5 @@ int main(int argc, char **argv) { if (d || have_flag(argc, argv, "context")) run_benchmark("context_create", bench_context, bench_setup, NULL, &data, 10, iters); - return 0; + return EXIT_SUCCESS; } diff --git a/src/secp256k1/src/ctime_tests.c b/src/secp256k1/src/ctime_tests.c index bbde863d969..f81bdb9228d 100644 --- a/src/secp256k1/src/ctime_tests.c +++ b/src/secp256k1/src/ctime_tests.c @@ -5,6 +5,7 @@ ***********************************************************************/ #include +#include #include #include "../include/secp256k1.h" @@ -49,7 +50,7 @@ int main(void) { if (!SECP256K1_CHECKMEM_RUNNING()) { fprintf(stderr, "This test can only usefully be run inside valgrind because it was not compiled under msan.\n"); fprintf(stderr, "Usage: libtool --mode=execute valgrind ./ctime_tests\n"); - return 1; + return EXIT_FAILURE; } ctx = secp256k1_context_create(SECP256K1_CONTEXT_DECLASSIFY); /** In theory, testing with a single secret input should be sufficient: @@ -69,7 +70,7 @@ int main(void) { CHECK(ret); secp256k1_context_destroy(ctx); - return 0; + return EXIT_SUCCESS; } static void run_tests(secp256k1_context *ctx, unsigned char *key) { diff --git a/src/secp256k1/src/eckey_impl.h b/src/secp256k1/src/eckey_impl.h index 121966f8b5f..a88a5964d81 100644 --- a/src/secp256k1/src/eckey_impl.h +++ b/src/secp256k1/src/eckey_impl.h @@ -9,6 +9,7 @@ #include "eckey.h" +#include "util.h" #include "scalar.h" #include "field.h" #include "group.h" @@ -35,6 +36,8 @@ static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char } static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) { + VERIFY_CHECK(compressed == 0 || compressed == 1); + if (secp256k1_ge_is_infinity(elem)) { return 0; } diff --git a/src/secp256k1/src/group.h b/src/secp256k1/src/group.h index 992ff5c98cf..05ae0d203cf 100644 --- a/src/secp256k1/src/group.h +++ b/src/secp256k1/src/group.h @@ -80,7 +80,11 @@ static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a); /** Set a group element equal to another which is given in jacobian coordinates. */ static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a); -/** Set a batch of group elements equal to the inputs given in jacobian coordinates */ +/** Set group elements r[0:len] (affine) equal to group elements a[0:len] (jacobian). + * None of the group elements in a[0:len] may be infinity. Constant time. */ +static void secp256k1_ge_set_all_gej(secp256k1_ge *r, const secp256k1_gej *a, size_t len); + +/** Set group elements r[0:len] (affine) equal to group elements a[0:len] (jacobian). */ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len); /** Bring a batch of inputs to the same global z "denominator", based on ratios between diff --git a/src/secp256k1/src/group_impl.h b/src/secp256k1/src/group_impl.h index c668fb24010..b8f2395d93a 100644 --- a/src/secp256k1/src/group_impl.h +++ b/src/secp256k1/src/group_impl.h @@ -195,6 +195,44 @@ static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { SECP256K1_GE_VERIFY(r); } +static void secp256k1_ge_set_all_gej(secp256k1_ge *r, const secp256k1_gej *a, size_t len) { + secp256k1_fe u; + size_t i; +#ifdef VERIFY + for (i = 0; i < len; i++) { + SECP256K1_GEJ_VERIFY(&a[i]); + VERIFY_CHECK(!secp256k1_gej_is_infinity(&a[i])); + } +#endif + + if (len == 0) { + return; + } + + /* Use destination's x coordinates as scratch space */ + r[0].x = a[0].z; + for (i = 1; i < len; i++) { + secp256k1_fe_mul(&r[i].x, &r[i - 1].x, &a[i].z); + } + secp256k1_fe_inv(&u, &r[len - 1].x); + + for (i = len - 1; i > 0; i--) { + secp256k1_fe_mul(&r[i].x, &r[i - 1].x, &u); + secp256k1_fe_mul(&u, &u, &a[i].z); + } + r[0].x = u; + + for (i = 0; i < len; i++) { + secp256k1_ge_set_gej_zinv(&r[i], &a[i], &r[i].x); + } + +#ifdef VERIFY + for (i = 0; i < len; i++) { + SECP256K1_GE_VERIFY(&r[i]); + } +#endif +} + static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len) { secp256k1_fe u; size_t i; diff --git a/src/secp256k1/src/modules/musig/session_impl.h b/src/secp256k1/src/modules/musig/session_impl.h index dde38085827..d8dcd00c95a 100644 --- a/src/secp256k1/src/modules/musig/session_impl.h +++ b/src/secp256k1/src/modules/musig/session_impl.h @@ -395,6 +395,7 @@ static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned c static int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, const unsigned char *input_nonce, const unsigned char *seckey, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) { secp256k1_scalar k[2]; secp256k1_ge nonce_pts[2]; + secp256k1_gej nonce_ptj[2]; int i; unsigned char pk_ser[33]; size_t pk_ser_len = sizeof(pk_ser); @@ -444,13 +445,20 @@ static int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp secp256k1_musig_secnonce_save(secnonce, k, &pk); secp256k1_musig_secnonce_invalidate(ctx, secnonce, !ret); + /* Compute pubnonce as two gejs */ for (i = 0; i < 2; i++) { - secp256k1_gej nonce_ptj; - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &nonce_ptj, &k[i]); - secp256k1_ge_set_gej(&nonce_pts[i], &nonce_ptj); - secp256k1_declassify(ctx, &nonce_pts[i], sizeof(nonce_pts[i])); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &nonce_ptj[i], &k[i]); secp256k1_scalar_clear(&k[i]); - secp256k1_gej_clear(&nonce_ptj); + } + + /* Batch convert to two public ges */ + secp256k1_ge_set_all_gej(nonce_pts, nonce_ptj, 2); + for (i = 0; i < 2; i++) { + secp256k1_gej_clear(&nonce_ptj[i]); + } + + for (i = 0; i < 2; i++) { + secp256k1_declassify(ctx, &nonce_pts[i], sizeof(nonce_pts[i])); } /* None of the nonce_pts will be infinity because k != 0 with overwhelming * probability */ diff --git a/src/secp256k1/src/modules/schnorrsig/main_impl.h b/src/secp256k1/src/modules/schnorrsig/main_impl.h index 82bba2f5975..2ed7be677fd 100644 --- a/src/secp256k1/src/modules/schnorrsig/main_impl.h +++ b/src/secp256k1/src/modules/schnorrsig/main_impl.h @@ -94,6 +94,8 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms secp256k1_sha256_write(&sha, msg, msglen); secp256k1_sha256_finalize(&sha, nonce32); secp256k1_sha256_clear(&sha); + secp256k1_memclear(masked_key, sizeof(masked_key)); + return 1; } diff --git a/src/secp256k1/src/precompute_ecmult.c b/src/secp256k1/src/precompute_ecmult.c index 5ef198a7700..021fe3940c5 100644 --- a/src/secp256k1/src/precompute_ecmult.c +++ b/src/secp256k1/src/precompute_ecmult.c @@ -6,6 +6,7 @@ #include #include +#include #include "../include/secp256k1.h" @@ -62,7 +63,7 @@ int main(void) { fp = fopen(outfile, "w"); if (fp == NULL) { fprintf(stderr, "Could not open %s for writing!\n", outfile); - return -1; + return EXIT_FAILURE; } fprintf(fp, "/* This file was automatically generated by precompute_ecmult. */\n"); @@ -86,5 +87,5 @@ int main(void) { fprintf(fp, "#undef S\n"); fclose(fp); - return 0; + return EXIT_SUCCESS; } diff --git a/src/secp256k1/src/precompute_ecmult_gen.c b/src/secp256k1/src/precompute_ecmult_gen.c index 4d153a65744..cd0fe70fc25 100644 --- a/src/secp256k1/src/precompute_ecmult_gen.c +++ b/src/secp256k1/src/precompute_ecmult_gen.c @@ -6,6 +6,7 @@ #include #include +#include #include "../include/secp256k1.h" @@ -64,7 +65,7 @@ int main(int argc, char **argv) { fp = fopen(outfile, "w"); if (fp == NULL) { fprintf(stderr, "Could not open %s for writing!\n", outfile); - return -1; + return EXIT_FAILURE; } fprintf(fp, "/* This file was automatically generated by precompute_ecmult_gen. */\n"); @@ -96,5 +97,5 @@ int main(int argc, char **argv) { fprintf(fp, "#undef S\n"); fclose(fp); - return 0; + return EXIT_SUCCESS; } diff --git a/src/secp256k1/src/scalar_impl.h b/src/secp256k1/src/scalar_impl.h index dbb5b0a01ca..0232a8c223e 100644 --- a/src/secp256k1/src/scalar_impl.h +++ b/src/secp256k1/src/scalar_impl.h @@ -90,11 +90,11 @@ static void secp256k1_scalar_split_lambda_verify(const secp256k1_scalar *r1, con #endif /* - * Both lambda and beta are primitive cube roots of unity. That is lamba^3 == 1 mod n and + * Both lambda and beta are primitive cube roots of unity. That is lambda^3 == 1 mod n and * beta^3 == 1 mod p, where n is the curve order and p is the field order. * * Furthermore, because (X^3 - 1) = (X - 1)(X^2 + X + 1), the primitive cube roots of unity are - * roots of X^2 + X + 1. Therefore lambda^2 + lamba == -1 mod n and beta^2 + beta == -1 mod p. + * roots of X^2 + X + 1. Therefore lambda^2 + lambda == -1 mod n and beta^2 + beta == -1 mod p. * (The other primitive cube roots of unity are lambda^2 and beta^2 respectively.) * * Let l = -1/2 + i*sqrt(3)/2, the complex root of X^2 + X + 1. We can define a ring diff --git a/src/secp256k1/src/secp256k1.c b/src/secp256k1/src/secp256k1.c index a248519dfd8..f047ca9e3fd 100644 --- a/src/secp256k1/src/secp256k1.c +++ b/src/secp256k1/src/secp256k1.c @@ -71,8 +71,8 @@ static const secp256k1_context secp256k1_context_static_ = { { secp256k1_default_error_callback_fn, 0 }, 0 }; -const secp256k1_context *secp256k1_context_static = &secp256k1_context_static_; -const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_static_; +const secp256k1_context * const secp256k1_context_static = &secp256k1_context_static_; +const secp256k1_context * const secp256k1_context_no_precomp = &secp256k1_context_static_; /* Helper function that determines if a context is proper, i.e., is not the static context or a copy thereof. * @@ -280,7 +280,7 @@ int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *o ARG_CHECK(pubkey != NULL); ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION); if (secp256k1_pubkey_load(ctx, &Q, pubkey)) { - ret = secp256k1_eckey_pubkey_serialize(&Q, output, &len, flags & SECP256K1_FLAGS_BIT_COMPRESSION); + ret = secp256k1_eckey_pubkey_serialize(&Q, output, &len, !!(flags & SECP256K1_FLAGS_BIT_COMPRESSION)); if (ret) { *outputlen = len; } diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c index 78533b11c28..b6fcb70387d 100644 --- a/src/secp256k1/src/tests.c +++ b/src/secp256k1/src/tests.c @@ -3821,14 +3821,38 @@ static void test_ge(void) { /* Test batch gej -> ge conversion without known z ratios. */ { + secp256k1_ge *ge_set_all_var = (secp256k1_ge *)checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); secp256k1_ge *ge_set_all = (secp256k1_ge *)checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); - secp256k1_ge_set_all_gej_var(ge_set_all, gej, 4 * runs + 1); + secp256k1_ge_set_all_gej_var(&ge_set_all_var[0], &gej[0], 4 * runs + 1); for (i = 0; i < 4 * runs + 1; i++) { secp256k1_fe s; testutil_random_fe_non_zero(&s); secp256k1_gej_rescale(&gej[i], &s); - CHECK(secp256k1_gej_eq_ge_var(&gej[i], &ge_set_all[i])); + CHECK(secp256k1_gej_eq_ge_var(&gej[i], &ge_set_all_var[i])); } + + /* Skip infinity at &gej[0]. */ + secp256k1_ge_set_all_gej(&ge_set_all[1], &gej[1], 4 * runs); + for (i = 1; i < 4 * runs + 1; i++) { + secp256k1_fe s; + testutil_random_fe_non_zero(&s); + secp256k1_gej_rescale(&gej[i], &s); + CHECK(secp256k1_gej_eq_ge_var(&gej[i], &ge_set_all[i])); + CHECK(secp256k1_ge_eq_var(&ge_set_all_var[i], &ge_set_all[i])); + } + + /* Test with an array of length 1. */ + secp256k1_ge_set_all_gej_var(ge_set_all_var, &gej[1], 1); + secp256k1_ge_set_all_gej(ge_set_all, &gej[1], 1); + CHECK(secp256k1_gej_eq_ge_var(&gej[1], &ge_set_all_var[1])); + CHECK(secp256k1_gej_eq_ge_var(&gej[1], &ge_set_all[1])); + CHECK(secp256k1_ge_eq_var(&ge_set_all_var[1], &ge_set_all[1])); + + /* Test with an array of length 0. */ + secp256k1_ge_set_all_gej_var(NULL, NULL, 0); + secp256k1_ge_set_all_gej(NULL, NULL, 0); + + free(ge_set_all_var); free(ge_set_all); } @@ -7837,5 +7861,5 @@ int main(int argc, char **argv) { testrand_finish(); printf("no problems found\n"); - return 0; + return EXIT_SUCCESS; } diff --git a/src/secp256k1/src/tests_exhaustive.c b/src/secp256k1/src/tests_exhaustive.c index 6efa88982ef..f8bbcaaf5c4 100644 --- a/src/secp256k1/src/tests_exhaustive.c +++ b/src/secp256k1/src/tests_exhaustive.c @@ -383,7 +383,7 @@ int main(int argc, char** argv) { this_core = strtol(argv[4], NULL, 0); if (num_cores < 1 || this_core >= num_cores) { fprintf(stderr, "Usage: %s [count] [seed] [numcores] [thiscore]\n", argv[0]); - return 1; + return EXIT_FAILURE; } printf("running tests for core %lu (out of [0..%lu])\n", (unsigned long)this_core, (unsigned long)num_cores - 1); } @@ -462,5 +462,5 @@ int main(int argc, char** argv) { testrand_finish(); printf("no problems found\n"); - return 0; + return EXIT_SUCCESS; } diff --git a/src/secp256k1/src/util.h b/src/secp256k1/src/util.h index 88a4149421a..5f29f4076ce 100644 --- a/src/secp256k1/src/util.h +++ b/src/secp256k1/src/util.h @@ -232,7 +232,7 @@ static SECP256K1_INLINE void secp256k1_memclear(void *ptr, size_t len) { * As best as we can tell, this is sufficient to break any optimisations that * might try to eliminate "superfluous" memsets. * This method is used in memzero_explicit() the Linux kernel, too. Its advantage is that it - * is pretty efficient, because the compiler can still implement the memset() efficently, + * is pretty efficient, because the compiler can still implement the memset() efficiently, * just not remove it entirely. See "Dead Store Elimination (Still) Considered Harmful" by * Yang et al. (USENIX Security 2017) for more background. */