Merge bitcoin/bitcoin#35959: Update secp256k1 subtree to latest master
What changed, and why it matters
This commit updates Bitcoin Core's embedded copy of the secp256k1 cryptographic library to a newer version. The update adds a new Silent Payments module, lets advanced users swap in a custom SHA256 compression function, removes some old deprecated names, and tightens one edge-case check in the ElligatorSwift key-exchange code. The change is a routine dependency refresh; nothing in the commit message or diff is described by the vendor as a security fix, and the one behavior change (rejecting certain oversized secret keys in ellswift_xdh) is explicitly called out as not being a security issue.
Treat as a normal dependency update. Review the upstream secp256k1 0.8.0 release notes and the listed upstream PRs for any security-relevant fixes not captured in this merge commit. Run the existing Bitcoin Core test suite (including secp256k1 tests) and verify no downstream code relies on the removed deprecated symbols. No emergency patching is indicated by the supplied materials.
Security signals we found
Dependency update of a core cryptographic library (libsecp256k1)
New runtime SHA256 compression callback with self-test/smoke test to catch mis-implementations early
Behavior change in ellswift_xdh to reject secret keys >= curve order (vendor states not a security issue)
Removal of deprecated public symbols (ABI break, not a vulnerability)
Silent Payments module added (new functionality, not a vulnerability fix)
Evidence from the diff
The commit is a subtree merge of bitcoin-core/secp256k1 master (post-0.8.0 release) into Bitcoin Core. Notable changes visible in the diff include: addition of the silentpayments module and API; a new secp256k1_context_set_sha256_compression callback with a smoke-test self-test; removal of deprecated symbols secp256k1_context_no_precomp and secp256k1_schnorrsig_sign; ECDH and ECDSA signing now route to the context-aware SHA256 implementation when the default hash/nonce function pointer is passed explicitly; ElligatorSwift secret-key handling is tightened to reject keys >= curve order (documented behavior, vendor states not a security issue); build/version bumps to 0.8.1; and various test-only CHECK additions. No CVE, advisory, or vendor security disclosure is present in the supplied materials.
Changed components
src/secp256k1/ (entire libsecp256k1 subtree)src/secp256k1/src/modules/silentpaymentssrc/secp256k1/src/modules/ellswiftsrc/secp256k1/src/modules/ecdhsrc/secp256k1/src/modules/schnorrsigsrc/secp256k1/src/hash_impl.hsrc/secp256k1/src/secp256k1.cInspect captured patch +297 / −116
### src/secp256k1/CHANGELOG.md
@@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+## [0.8.0] - 2026-08-03
+
+#### Added
+ - New function `secp256k1_context_set_sha256_compression` for overriding the internal SHA256 compression function used by the library at runtime (e.g., to route SHA256 through a hardware-accelerated implementation).
+ - New module `silentpayments` implements sending and receiving of Silent Payments according to [BIP 352](https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki). See:
+ - Header file `include/secp256k1_silentpayments.h` which defines the new API.
+ - Usage example `examples/silentpayments.c`.
+ - The `silentpayments` API currently requires full access to the transaction data (light client scanning is not implemented).
+
+#### Fixed
+ - Module `ellswift`: `secp256k1_ellswift_xdh` now treats secret keys greater than or equal to the curve order as invalid and returns 0 as documented. Previously, keys greater than the curve order were silently reduced modulo the order and accepted. The probability that a securely generated key is greater than the curve order is negligible, and thus the old behavior does not constitute a security issue.
+
+#### Changed
+ - The field multiplication and squaring routines of the 5x52 (64-bit) implementation are now force-inlined. This speeds up many library functions with GCC and MSVC (Clang is largely unaffected), e.g. `secp256k1_ecdsa_verify` and `secp256k1_schnorrsig_verify` by up to ~11%, at the cost of a somewhat larger compiled library. Force-inlining is disabled in unoptimized builds and when optimizing for size.
+ - CMake: Shared libraries built with CMake on OpenBSD and NetBSD now create the full versioned filename (e.g. `libsecp256k1.so.6.2` instead of `libsecp256k1.so.6`) and symlink chain, matching the behavior of GNU Autotools builds.
+
+#### Removed
+- Removed previously deprecated pointer `secp256k1_context_no_precomp`. Use `secp256k1_context_static` instead.
+- Removed previously deprecated function alias `secp256k1_schnorrsig_sign`. Use `secp256k1_schnorrsig_sign32` instead.
+- Removed macro `SECP256K1_GNUC_PREREQ` defined in the header file `include/secp256k1.h`. This macro was used in the library headers to check for GNU C extensions. The macro was not actually meant to be part of the public API of libsecp256k1. If you happened to use it in your code nevertheless, use the macros `__GNUC__` and `__GNUC_MINOR__` (defined by compilers with GNU C extensions) directly, or copy the macro definition from an old libsecp256k1 header file into your code.
+
+#### ABI Compatibility
+The symbols `secp256k1_context_no_precomp` and `secp256k1_schnorrsig_sign` were removed.
+Otherwise, the library maintains backward compatibility with versions 0.7.0 and 0.7.1.
+
## [0.7.1] - 2026-01-26
#### Changed
@@ -30,7 +55,8 @@ The ABI is backward compatible with version 0.7.0.
- Removed `SECP256K1_WARN_UNUSED_RESULT` attribute (defined as `__attribute__ ((__warn_unused_result__))`) from several API functions that always return 1. Compilers will no longer warn if the return value is unused.
- CMake: Building with CMake is no longer considered experimental.
- CMake: The minimum required CMake version was increased to 3.22.
- - CMake: Shared libraries built with CMake on FreeBSD now create the full versioned filename and symlink chain, matching the behavior of autotools builds.
+ - CMake: Shared libraries built with CMake on FreeBSD now create the full versioned filename (e.g. `libsecp256k1.so.5.0.1` instead of `libsecp256k1.so.5`) and symlink chain, matching the behavior of GNU Autotools builds.
+
#### Removed
- Removed previously deprecated function aliases `secp256k1_ec_privkey_negate`, `secp256k1_ec_privkey_tweak_add` and
@@ -199,7 +225,8 @@ This version was in fact never released.
The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6).
Therefore, this version number does not uniquely identify a set of source files.
-[Unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.7.1...HEAD
+[Unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.8.0...HEAD
+[0.8.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.7.1...v0.8.0
[0.7.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.7.0...v0.7.1
[0.7.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.6.0...v0.7.0
[0.6.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.1...v0.6.0
### 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.7.2
+ VERSION 0.8.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
@@ -21,8 +21,8 @@ list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
# All changes in experimental modules are treated as if they don't affect the
# interface and therefore only increase the revision.
-set(${PROJECT_NAME}_LIB_VERSION_CURRENT 6)
-set(${PROJECT_NAME}_LIB_VERSION_REVISION 2)
+set(${PROJECT_NAME}_LIB_VERSION_CURRENT 7)
+set(${PROJECT_NAME}_LIB_VERSION_REVISION 1)
set(${PROJECT_NAME}_LIB_VERSION_AGE 0)
#=============================
### src/secp256k1/configure.ac
@@ -4,17 +4,17 @@ AC_PREREQ([2.60])
# the API. All changes in experimental modules are treated as
# backwards-compatible and therefore at most increase the minor version.
define(_PKG_VERSION_MAJOR, 0)
-define(_PKG_VERSION_MINOR, 7)
-define(_PKG_VERSION_PATCH, 2)
+define(_PKG_VERSION_MINOR, 8)
+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:
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
# All changes in experimental modules are treated as if they don't affect the
# interface and therefore only increase the revision.
-define(_LIB_VERSION_CURRENT, 6)
-define(_LIB_VERSION_REVISION, 2)
+define(_LIB_VERSION_CURRENT, 7)
+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])
### src/secp256k1/doc/release-process.md
@@ -15,6 +15,7 @@ This process also assumes that there will be no minor releases for old major rel
We aim to cut a regular release every 3-4 months, approximately twice as frequent as major Bitcoin Core releases. Every second release should be published one month before the feature freeze of the next major Bitcoin Core release, allowing sufficient time to update the library in Core.
## Sanity checks
+
Perform these checks when reviewing the release PR (see below):
1. Ensure `make distcheck` doesn't fail.
@@ -39,20 +40,27 @@ Perform these checks when reviewing the release PR (see below):
tools/check-abi.sh
```
-## Regular release
+## Preparing and tagging a release
+
+If you're going to sign the release, make sure that your default GPG signing key is the [expected one](../SECURITY.md).
+You can see your default key by running `echo "test" | gpg --sign --verbose > /dev/null`.
+
+### Regular release
1. Open a PR to the master branch with a commit (using message `"release: prepare for $MAJOR.$MINOR.$PATCH"`, for example) that
* finalizes the release notes in [CHANGELOG.md](../CHANGELOG.md) by
* adding a section for the release (make sure that the version number is a link to a diff between the previous and new version),
* removing the `[Unreleased]` section header,
- * ensuring that the release notes are not missing entries (check the `needs-changelog` label on github), and
+ * ensuring that the release notes are not missing entries
+ (check the `needs-changelog` label on GitHub and also go manually through the list of commits since the previous release), and
* including an entry for `### ABI Compatibility` if it doesn't exist,
* sets `_PKG_VERSION_IS_RELEASE` to `true` in `configure.ac`, and,
* if this is not a patch release,
* updates `_PKG_VERSION_*` and `_LIB_VERSION_*` in `configure.ac`, and
* updates `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_*` in `CMakeLists.txt`.
-2. Perform the [sanity checks](#sanity-checks) on the PR branch.
-3. After the PR is merged, tag the commit, and push the tag:
+2. Perform the [sanity checks](#sanity-checks) on the PR branch
+ and attach the output of the [`check-abi`](/tools/check-abi.sh) tool (screenshot of the generated compatibility HTML report) to the PR description.
+3. After the PR has been merged, tag the commit, and push the tag:
```
RELEASE_COMMIT=<merge commit of step 1>
git tag -s v$MAJOR.$MINOR.$PATCH -m "libsecp256k1 $MAJOR.$MINOR.$PATCH" $RELEASE_COMMIT
@@ -64,10 +72,8 @@ Perform these checks when reviewing the release PR (see below):
* adds an `[Unreleased]` section header and a corresponding `[Unreleased]` link at the bottom of [CHANGELOG.md](../CHANGELOG.md).
If other maintainers are not present to approve the PR, it can be merged without ACKs.
-5. Create a new GitHub release with a link to the corresponding entry in [CHANGELOG.md](../CHANGELOG.md).
-6. Send an announcement email to the bitcoin-dev mailing list.
-## Maintenance release
+### Maintenance release
Note that bug fixes need to be backported only to releases for which no compatible release without the bug exists.
@@ -83,12 +89,29 @@ Note that bug fixes need to be backported only to releases for which no compatib
and the `$PATCH` component of `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_REVISION` in `CMakeLists.txt`
(with commit message `"release: bump versions for $MAJOR.$MINOR.$PATCH"`, for example).
3. Perform the [sanity checks](#sanity-checks) on the PR branch.
-4. After the PRs are merged, update the release branch, tag the commit, and push the tag:
+4. After the PR has been merged, update the release branch, tag the commit, and push the tag:
```
git checkout $MAJOR.$MINOR && git pull
git tag -s v$MAJOR.$MINOR.$PATCH -m "libsecp256k1 $MAJOR.$MINOR.$PATCH"
git push git@github.com:bitcoin-core/secp256k1.git v$MAJOR.$MINOR.$PATCH
```
-6. Create a new GitHub release with a link to the corresponding entry in [CHANGELOG.md](../CHANGELOG.md).
-7. Send an announcement email to the bitcoin-dev mailing list.
-8. Open PR to the master branch that includes a commit (with commit message `"release notes: add $MAJOR.$MINOR.$PATCH"`, for example) that adds release notes to [CHANGELOG.md](../CHANGELOG.md).
+5. Open a PR to the master branch that includes a commit (with commit message `"release notes: add $MAJOR.$MINOR.$PATCH"`, for example) that adds release notes to [CHANGELOG.md](../CHANGELOG.md).
+6. Get the PR merged to ensure that the [CHANGELOG.md](../CHANGELOG.md) file on the master branch is current before announcing the release.
+
+## Creating a tarball and announcing the release
+
+1. Create a tarball and a detached GPG signature covering it, and check that the signature verifies under the expected key.
+ ```
+ git archive --output "libsecp256k1-$MAJOR.$MINOR.$PATCH.tar.gz" --prefix "libsecp256k1-$MAJOR.$MINOR.$PATCH/" v$MAJOR.$MINOR.$PATCH
+ gpg --detach-sign "libsecp256k1-$MAJOR.$MINOR.$PATCH.tar.gz"
+ gpg --verify "libsecp256k1-$MAJOR.$MINOR.$PATCH.tar.gz.sig"
+ ```
+2. Create a new GitHub release with a link to the corresponding entry in [CHANGELOG.md](../CHANGELOG.md).
+ Attach the tarball and the detached signature.
+3. Send an announcement email to the bitcoin-dev mailing list.
+
+
+## Cleaning up
+
+1. Close the GitHub milestone, and create a new one. Consider moving unresolved issues to the new milestone.
+2. Remove the `needs-changelog` label from all merged PRs.
### src/secp256k1/examples/silentpayments.c
@@ -295,7 +295,7 @@ int main(void) {
NULL, 0
);
if (!ret) {
- printf("Something went wrong, a recipient provided an invalid address.\n");
+ printf("Something went wrong, group limit exceeded or input secret keys sum to zero.\n");
return EXIT_FAILURE;
}
printf("Alice created the following outputs for Bob and Carol:\n");
### src/secp256k1/include/secp256k1.h
@@ -101,15 +101,6 @@ typedef int (*secp256k1_nonce_function)(
unsigned int attempt
);
-# if !defined(SECP256K1_GNUC_PREREQ)
-# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
-# define SECP256K1_GNUC_PREREQ(_maj,_min) \
- ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
-# else
-# define SECP256K1_GNUC_PREREQ(_maj,_min) 0
-# endif
-# endif
-
/* When this header is used at build-time the SECP256K1_BUILD define needs to be set
* to correctly setup export attributes and nullness checks. This is normally done
* by secp256k1.c but to guard against this header being included before secp256k1.c
@@ -178,12 +169,12 @@ typedef int (*secp256k1_nonce_function)(
/* Warning attributes
* NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out
* some paranoid null checks. */
-# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4)
+# if defined(__GNUC__)
# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
# else
# define SECP256K1_WARN_UNUSED_RESULT
# endif
-# if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4)
+# if !defined(SECP256K1_BUILD) && defined(__GNUC__)
# define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x)))
# else
# define SECP256K1_ARG_NONNULL(_x)
@@ -245,10 +236,6 @@ typedef int (*secp256k1_nonce_function)(
*/
SECP256K1_API const secp256k1_context * const secp256k1_context_static;
-/** Deprecated alias for secp256k1_context_static. */
-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)
*
* This function performs self tests that detect some serious usage errors and
@@ -426,7 +413,7 @@ typedef void (*secp256k1_sha256_compression_function)(
/**
* Set a callback function to override the internal SHA256 compression function.
*
- * This installs a function to replace the built-in block-compression
+ * This installs a callback to replace the built-in block-compression
* step used by the library's internal SHA256 implementation.
* The provided callback must exactly implement the effect of n_blocks
* repeated applications of the SHA256 compression function.
@@ -436,6 +423,21 @@ typedef void (*secp256k1_sha256_compression_function)(
* specialized implementation. It is NOT meant for replacing SHA256
* with a different hash function.
*
+ * Since auxiliary functions exposed by the library via a function
+ * pointer such as secp256k1_nonce_function_default do not take a
+ * context object, they will not use the callback when called directly
+ * from user code. (But they will use the callback when called from
+ * other library functions that do take a context object, e.g., when
+ * noncefp==NULL or noncefp==secp256k1_nonce_function_default is passed
+ * as an argument to secp256k1_ecdsa_sign.)
+ *
+ * Note: The provided function is tested against a set of known SHA256
+ * digests; invokes the context's illegal callback on any mismatch
+ * (which aborts by default), in order to catch basic misbehavior early.
+ * It takes well under 2.5 ms on a desktop machine.
+ * This is NOT a substitute for having proper test coverage of the
+ * supplied function outside this library.
+ *
* Args: ctx: pointer to a context object.
* In: fn_compression: pointer to a function implementing the compression function;
* passing NULL restores the default implementation.
### src/secp256k1/include/secp256k1_schnorrsig.h
@@ -124,20 +124,9 @@ SECP256K1_API int secp256k1_schnorrsig_sign32(
const unsigned char *aux_rand32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
-/** Same as secp256k1_schnorrsig_sign32, but DEPRECATED. Will be removed in
- * future versions. */
-SECP256K1_API int secp256k1_schnorrsig_sign(
- const secp256k1_context *ctx,
- unsigned char *sig64,
- const unsigned char *msg32,
- const secp256k1_keypair *keypair,
- const unsigned char *aux_rand32
-) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
- SECP256K1_DEPRECATED("Use secp256k1_schnorrsig_sign32 instead");
-
/** Create a Schnorr signature with a more flexible API.
*
- * Same arguments as secp256k1_schnorrsig_sign except that it allows signing
+ * Same arguments as secp256k1_schnorrsig_sign32 except that it allows signing
* variable length messages and accepts a pointer to an extraparams object that
* allows customizing signing by passing additional arguments.
*
### src/secp256k1/include/secp256k1_silentpayments.h
@@ -75,15 +75,14 @@ typedef struct secp256k1_silentpayments_recipient {
* unfindable by the recipient.
*
* Returns: 1 if creation of outputs was successful.
- * 0 on failure. This is expected only with an adversarially chosen
- * recipient spend key. Specifically, failure occurs when:
- * - Input secret keys sum to 0
- * (negligible probability if at least one of the input secret
- * keys is uniformly random and independent of all other keys)
- * - A hash output is not a valid scalar (negligible probability
- * per hash evaluation)
- * - Any group (i.e. recipients sharing the same scan public key) exceeds
- * the protocol limit SECP256K1_SILENTPAYMENTS_RECIPIENT_GROUP_LIMIT
+ * 0 on failure, i.e., when one of the following occurs:
+ * - The size of any group (i.e. recipients sharing the same scan public key)
+ * exceeds the protocol limit SECP256K1_SILENTPAYMENTS_RECIPIENT_GROUP_LIMIT.
+ * - The sum of all input secret keys is 0.
+ * (This occurs only with negligible probability if at least one of the
+ * input secret keys is uniformly random and independent of all other keys.)
+ * - An invalid output public key is created. (This can only happen for an
+ * adversarially chosen recipient spend public key.)
*
* Args: ctx: pointer to a context object
* (not secp256k1_context_static).
@@ -97,16 +96,14 @@ typedef struct secp256k1_silentpayments_recipient {
* In: recipients: pointer to an array of pointers to Silent Payments
* recipients, where each recipient is a scan public
* key, a spend public key, and an index indicating
- * its position in the original ordering. The
- * recipient array will be grouped by scan public key
- * in place (as specified in BIP0352), but generated
- * outputs are saved in the `generated_outputs` array
- * to match the original ordering (using the index
- * field). This ensures the caller is able to match
- * the generated outputs to the correct Silent
- * Payments addresses. The same recipient can be
- * passed multiple times to create multiple outputs
- * for the same recipient.
+ * its position in the original ordering. This function
+ * may reorder the pointers to the recipient objects
+ * within the array, i.e., after the call (including on
+ * failure), the index fields of the recipient objects
+ * may no longer correspond to the positions in the
+ * array. Multiple recipient objects with the same scan
+ * public key and/or same spend public key can be passed
+ * if they carry different indices.
* n_recipients: the size of the recipients array.
* outpoint_smallest36: serialized (36-byte) smallest outpoint
* (lexicographically) from the transaction inputs
### src/secp256k1/src/hash.h
@@ -10,6 +10,8 @@
#include <stdlib.h>
#include <stdint.h>
+#include "../include/secp256k1.h"
+
typedef struct {
secp256k1_sha256_compression_function fn_sha256_compression;
} secp256k1_hash_ctx;
### src/secp256k1/src/hash_impl.h
@@ -137,6 +137,71 @@ static void secp256k1_sha256_transform(uint32_t *state, const unsigned char *blo
}
}
+/* Perform a smoke test on a supplied SHA256 compression function. */
+static int secp256k1_sha256_smoke_test(const secp256k1_sha256_compression_function fn_compression) {
+ secp256k1_hash_ctx ctx;
+ secp256k1_sha256 sha_msg, sha_accum;
+ unsigned char out[32];
+ size_t i, j;
+
+ /* SHA256 works on 64 byte blocks, secp256k1_sha256_write gives as many blocks
+ * at once to compression, so the count is what varies here. A SIMD implementation
+ * typically hashes four or eight at a time, then any left over one by one.
+ * These lengths cover every number from 1 to 9, which includes counts that
+ * divide evenly and counts leaving one, two or three over. */
+ static const size_t msg_lens[] = {
+ 0, 1, 28, /* Shorter than a block, so padding makes up the rest */
+ 55, 56, /* Final 0x80 and 8 byte length fit in the last block, and don't */
+ 64, 128, 192, 256, 320, /* 1 to 5 blocks */
+ 384, 448, 512, 576 /* 6 to 9 blocks */
+ };
+ unsigned char msg[640]; /* Longest message, plus 64 for the shifted start */
+
+ /* Accumulated digest of every message, hashed with the built-in secp256k1_sha256_transform.
+ * Note: To regenerate set 'ctx.fn_sha256_compression = secp256k1_sha256_transform' below
+ * and print the sha_accum digest. */
+ static const unsigned char accum_expected[32] = {
+ 0x22, 0x8E, 0x6A, 0x1F, 0x78, 0x02, 0x1B, 0xCF,
+ 0x4E, 0xF4, 0xEA, 0xB3, 0x8A, 0x40, 0x69, 0xBF,
+ 0x8D, 0xF3, 0x72, 0xAB, 0xE2, 0x11, 0x93, 0xA6,
+ 0xE6, 0x46, 0x98, 0xBF, 0xD4, 0x3D, 0x19, 0x84,
+ };
+ /* The purpose of this VERIFY_CHECK is to make anyone aware that they
+ * should also change the size of msg_buf when changing the length of the
+ * longest message. */
+ VERIFY_CHECK(msg_lens[ARRAY_SIZE(msg_lens) - 1] == 576);
+
+ VERIFY_CHECK(fn_compression != NULL);
+ secp256k1_hash_ctx_init(&ctx);
+ ctx.fn_sha256_compression = fn_compression;
+ secp256k1_sha256_initialize(&sha_accum);
+
+ /* No two blocks of a message are equal, so a function that doesn't advance the block
+ * pointer gives a different digest. 251 is prime, so its repeats only line up with
+ * block starts every 251 blocks; wrapping at 256 would do so every 4. */
+ for (i = 0; i < sizeof(msg); i++) {
+ msg[i] = (unsigned char)(i % 251);
+ }
+
+ /* Each round starts one byte further along to check different alignments,
+ * secp256k1_sha256_write invokes compression directly on input >= 64 bytes */
+ for (i = 0; i < 64; i++) {
+ unsigned char *m = msg + i;
+ m[0] ^= 0xff; /* Changes the first byte, so every state after it changes too */
+ for (j = 0; j < ARRAY_SIZE(msg_lens); j++) {
+ secp256k1_sha256_initialize(&sha_msg);
+ secp256k1_sha256_write(&ctx, &sha_msg, m, msg_lens[j]);
+ secp256k1_sha256_finalize(&ctx, &sha_msg, out);
+ secp256k1_sha256_write(&ctx, &sha_accum, out, 32);
+ }
+ m[0] ^= 0xff; /* Reset first byte */
+ }
+
+ /* Compare against pre-computed accumulated digest */
+ secp256k1_sha256_finalize(&ctx, &sha_accum, out);
+ return secp256k1_memcmp_var(accum_expected, out, 32) == 0;
+}
+
static void secp256k1_hash_ctx_init(secp256k1_hash_ctx *hash_ctx) {
VERIFY_CHECK(hash_ctx != NULL);
hash_ctx->fn_sha256_compression = secp256k1_sha256_transform;
### src/secp256k1/src/modules/ecdh/main_impl.h
@@ -60,7 +60,7 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const se
secp256k1_fe_get_b32(x, &pt.x);
secp256k1_fe_get_b32(y, &pt.y);
- if (hashfp == NULL) {
+ if (hashfp == NULL || hashfp == secp256k1_ecdh_hash_function_sha256) {
/* Use ctx-aware function by default */
ret = ecdh_hash_function_sha256_impl(secp256k1_get_hash_context(ctx), output, x, y, data);
} else {
### src/secp256k1/src/modules/ellswift/main_impl.h
@@ -449,12 +449,13 @@ int secp256k1_ellswift_create(const secp256k1_context *ctx, unsigned char *ell64
secp256k1_fe_normalize_var(&p.x);
secp256k1_fe_normalize_var(&p.y);
- /* Set up hasher state. The used RNG is H(privkey || "\x00"*32 [|| auxrnd32] || cnt++),
+ /* Set up hasher state. The used RNG is H(seckey32 || "\x00"*32 [|| auxrnd32] || cnt++),
* using BIP340 tagged hash with tag "secp256k1_ellswift_create". */
secp256k1_ellswift_sha256_init_create(&hash);
secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &hash, seckey32, 32);
secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &hash, zero32, sizeof(zero32));
- secp256k1_declassify(ctx, &hash, sizeof(hash)); /* private key is hashed now */
+ /* Declassify only hash state. seckey32 has been hashed, but copy remains in the hash buffer */
+ secp256k1_declassify(ctx, &hash.s, sizeof(hash.s));
if (auxrnd32) secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &hash, auxrnd32, 32);
/* Compute ElligatorSwift encoding and construct output. */
@@ -463,6 +464,7 @@ int secp256k1_ellswift_create(const secp256k1_context *ctx, unsigned char *ell64
secp256k1_memczero(ell64, 64, !ret);
secp256k1_scalar_clear(&seckey_scalar);
+ secp256k1_sha256_clear(&hash);
return ret;
}
### src/secp256k1/src/modules/ellswift/tests_exhaustive_impl.h
@@ -30,8 +30,8 @@ static void test_exhaustive_ellswift(const secp256k1_context *ctx, const secp256
CHECK(secp256k1_ellswift_create(ctx, ell64, sec32, NULL));
/* Decode ellswift pubkey and check that it matches the precomputed group element. */
- secp256k1_ellswift_decode(ctx, &pub_decoded, ell64);
- secp256k1_pubkey_load(ctx, &ge_decoded, &pub_decoded);
+ CHECK(secp256k1_ellswift_decode(ctx, &pub_decoded, ell64) == 1);
+ CHECK(secp256k1_pubkey_load(ctx, &ge_decoded, &pub_decoded) == 1);
CHECK(secp256k1_ge_eq_var(&ge_decoded, &group[i]));
}
}
### src/secp256k1/src/modules/ellswift/tests_impl.h
@@ -249,9 +249,9 @@ void ellswift_encode_decode_roundtrip_tests(void) {
secp256k1_pubkey_save(&pubkey, &g);
testrand256(rnd32);
/* Convert the public key to ElligatorSwift and back. */
- secp256k1_ellswift_encode(CTX, ell64, &pubkey, rnd32);
- secp256k1_ellswift_decode(CTX, &pubkey2, ell64);
- secp256k1_pubkey_load(CTX, &g2, &pubkey2);
+ CHECK(secp256k1_ellswift_encode(CTX, ell64, &pubkey, rnd32) == 1);
+ CHECK(secp256k1_ellswift_decode(CTX, &pubkey2, ell64) == 1);
+ CHECK(secp256k1_pubkey_load(CTX, &g2, &pubkey2) == 1);
/* Compare with original. */
CHECK(secp256k1_ge_eq_var(&g, &g2));
}
@@ -276,8 +276,8 @@ void ellswift_create_tests(void) {
ret = secp256k1_ellswift_create(CTX, ell64, sec32, (i & 1) ? auxrnd32 : NULL);
CHECK(ret);
/* Decode it, and compare with traditionally-computed public key. */
- secp256k1_ellswift_decode(CTX, &pub, ell64);
- secp256k1_pubkey_load(CTX, &dec, &pub);
+ CHECK(secp256k1_ellswift_decode(CTX, &pub, ell64) == 1);
+ CHECK(secp256k1_pubkey_load(CTX, &dec, &pub) == 1);
secp256k1_ecmult(&res, NULL, &secp256k1_scalar_zero, &sec);
CHECK(secp256k1_gej_eq_ge_var(&res, &dec));
}
@@ -300,15 +300,15 @@ void ellswift_compute_shared_secret_tests(void) {
/* Generate random ElligatorSwift encoding for the remote key and decode it. */
testrand256_test(ell64);
testrand256_test(ell64 + 32);
- secp256k1_ellswift_decode(CTX, &pub, ell64);
- secp256k1_pubkey_load(CTX, &dec, &pub);
+ CHECK(secp256k1_ellswift_decode(CTX, &pub, ell64) == 1);
+ CHECK(secp256k1_pubkey_load(CTX, &dec, &pub) == 1);
secp256k1_gej_set_ge(&decj, &dec);
/* Compute the X coordinate of seckey*pubkey using ellswift_xdh. Note that we
* pass ell64 as claimed (but incorrect) encoding for sec32 here; this works
* because the "hasher" function we use here ignores the ell64 arguments. */
ret = secp256k1_ellswift_xdh(CTX, share32, ell64, ell64, sec32, i & 1, &ellswift_xdh_hash_x32, NULL);
CHECK(ret);
- (void)secp256k1_fe_set_b32_limit(&share_x, share32); /* no overflow is possible */
+ CHECK(secp256k1_fe_set_b32_limit(&share_x, share32)); /* no overflow is possible */
SECP256K1_FE_VERIFY(&share_x);
/* Compute seckey*pubkey directly. */
secp256k1_ecmult(&resj, &decj, &sec, NULL);
### src/secp256k1/src/modules/extrakeys/tests_impl.h
@@ -53,8 +53,8 @@ static void test_xonly_pubkey(void) {
CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1);
CHECK(secp256k1_memcmp_var(&xonly_pk, &pk, sizeof(xonly_pk)) != 0);
CHECK(pk_parity == 1);
- secp256k1_pubkey_load(CTX, &pk1, &pk);
- secp256k1_pubkey_load(CTX, &pk2, (secp256k1_pubkey *) &xonly_pk);
+ CHECK(secp256k1_pubkey_load(CTX, &pk1, &pk) == 1);
+ CHECK(secp256k1_pubkey_load(CTX, &pk2, (secp256k1_pubkey *) &xonly_pk) == 1);
CHECK(secp256k1_fe_equal(&pk1.x, &pk2.x) == 1);
secp256k1_fe_negate(&y, &pk2.y, 1);
CHECK(secp256k1_fe_equal(&pk1.y, &y) == 1);
### src/secp256k1/src/modules/musig/tests_impl.h
@@ -104,7 +104,7 @@ static void pubnonce_summing_to_inf(secp256k1_musig_pubnonce *pubnonce) {
secp256k1_ge_neg(&ge[1], &ge[1]);
}
- secp256k1_musig_sum_pubnonces(CTX, summed_pubnonces, pubnonce_ptr, 2);
+ CHECK(secp256k1_musig_sum_pubnonces(CTX, summed_pubnonces, pubnonce_ptr, 2) == 1);
CHECK(secp256k1_gej_is_infinity(&summed_pubnonces[0]));
CHECK(secp256k1_gej_is_infinity(&summed_pubnonces[1]));
}
@@ -372,7 +372,7 @@ static void musig_api_tests(void) {
{
/* Check that the aggnonce encodes two points at infinity */
secp256k1_ge aggnonce_pt[2];
- secp256k1_musig_aggnonce_load(CTX, aggnonce_pt, &aggnonce);
+ CHECK(secp256k1_musig_aggnonce_load(CTX, aggnonce_pt, &aggnonce) == 1);
for (i = 0; i < 2; i++) {
CHECK(secp256k1_ge_is_infinity(&aggnonce_pt[i]) == 1);
}
### src/secp256k1/src/modules/recovery/tests_exhaustive_impl.h
@@ -33,7 +33,7 @@ static void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const se
secp256k1_scalar_get_b32(sk32, &sk);
secp256k1_scalar_get_b32(msg32, &msg);
- secp256k1_ecdsa_sign_recoverable(ctx, &rsig, msg32, sk32, secp256k1_nonce_function_smallint, &k);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsig, msg32, sk32, secp256k1_nonce_function_smallint, &k) == 1);
/* Check directly */
secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, &rsig);
@@ -59,7 +59,7 @@ static void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const se
CHECK(recid == expected_recid);
/* Convert to a standard sig then check */
- secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig);
+ CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig) == 1);
secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig);
/* Note that we compute expected_r *after* signing -- this is important
* because our nonce-computing function function might change k during
@@ -129,7 +129,7 @@ static void test_exhaustive_recovery_verify(const secp256k1_context *ctx, const
/* Verify by converting to a standard signature and calling verify */
secp256k1_ecdsa_recoverable_signature_save(&rsig, &r_s, &s_s, recid);
- secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig);
+ CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig) == 1);
memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge));
secp256k1_pubkey_save(&pk, &nonconst_ge);
CHECK(should_verify ==
### src/secp256k1/src/modules/schnorrsig/main_impl.h
@@ -190,10 +190,6 @@ int secp256k1_schnorrsig_sign32(const secp256k1_context* ctx, unsigned char *sig
return secp256k1_schnorrsig_sign_internal(ctx, sig64, msg32, 32, keypair, secp256k1_nonce_function_bip340, (unsigned char*)aux_rand32);
}
-int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, const unsigned char *aux_rand32) {
- return secp256k1_schnorrsig_sign32(ctx, sig64, msg32, keypair, aux_rand32);
-}
-
int secp256k1_schnorrsig_sign_custom(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_keypair *keypair, secp256k1_schnorrsig_extraparams *extraparams) {
secp256k1_nonce_function_hardened noncefp = NULL;
void *ndata = NULL;
### src/secp256k1/src/modules/schnorrsig/tests_impl.h
@@ -823,9 +823,6 @@ static void test_schnorrsig_sign_internal(void) {
CHECK(secp256k1_keypair_xonly_pub(CTX, &pk, NULL, &keypair));
CHECK(secp256k1_schnorrsig_sign32(CTX, sig, msg, &keypair, NULL) == 1);
CHECK(secp256k1_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &pk));
- /* Check that deprecated alias gives the same result */
- CHECK(secp256k1_schnorrsig_sign(CTX, sig2, msg, &keypair, NULL) == 1);
- CHECK(secp256k1_memcmp_var(sig, sig2, sizeof(sig)) == 0);
/* Test different nonce functions */
CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 1);
### src/secp256k1/src/modules/silentpayments/main_impl.h
@@ -588,8 +588,11 @@ static int secp256k1_silentpayments_check_label_batch(
*label_tweak = NULL;
secp256k1_ge_set_all_gej_var(label_candidates_ge, label_candidates_gej, 2 * n_batch);
for (i = 0; i < 2 * n_batch; i++) {
- /* Serialize only non-infinity points because candidates are collected only when
- * tx_output != unlabeled_output_xonly. */
+ /* Note: serialize will only fail if a label candidate is the point at infinity, but we know
+ * this cannot happen since we only collect candidates if tx_output != unlabeled_output. Thus,
+ * we know that label_candidate = tx_output - unlabeled_output cannot be the point at infinity.
+ */
+ VERIFY_CHECK(!secp256k1_ge_is_infinity(&label_candidates_ge[i]));
secp256k1_eckey_pubkey_serialize33(&label_candidates_ge[i], label33);
*label_tweak = label_lookup(label33, label_context);
if (*label_tweak != NULL) {
@@ -648,6 +651,8 @@ int secp256k1_silentpayments_recipient_scan_outputs(
}
secp256k1_ge_from_bytes(&prevouts_pubkey_sum_ge, &prevouts_summary->data[5]);
combined = (int)prevouts_summary->data[4];
+ /* Note that the "combined" flag can currently only be 0, as we only have support for full nodes, i.e.,
+ * the following branch is always taken. "combined" can also be 1 once we add light client support. */
if (!combined) {
secp256k1_scalar input_hash_scalar;
secp256k1_scalar_set_b32(&input_hash_scalar, &prevouts_summary->data[5 + 64], NULL);
### src/secp256k1/src/modules/silentpayments/tests_impl.h
@@ -138,7 +138,7 @@ static void test_recipient_sort_helper(unsigned char (*sp_addresses[3])[2][33],
);
CHECK(ret == 1);
for (i = 0; i < 3; i++) {
- secp256k1_xonly_pubkey_serialize(CTX, xonly_ser, &generated_outputs[i]);
+ CHECK(secp256k1_xonly_pubkey_serialize(CTX, xonly_ser, &generated_outputs[i]) == 1);
CHECK(secp256k1_memcmp_var(xonly_ser, (*sp_outputs[i]), 32) == 0);
}
}
### src/secp256k1/src/secp256k1.c
@@ -74,7 +74,6 @@ static const secp256k1_context secp256k1_context_static_ = {
0
};
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.
*
@@ -559,7 +558,7 @@ static int secp256k1_ecdsa_sign_inner(const secp256k1_context* ctx, secp256k1_sc
while (1) {
int is_nonce_valid;
- if (noncefp == NULL) {
+ if (noncefp == NULL || noncefp == secp256k1_nonce_function_rfc6979) {
/* Use ctx-aware function by default */
ret = nonce_function_rfc6979_impl(secp256k1_get_hash_context(ctx), nonce32, msg32, seckey, NULL, (void*)noncedata, count);
} else {
### src/secp256k1/src/selftest.h
@@ -24,7 +24,13 @@ static int secp256k1_selftest_sha256(secp256k1_sha256_compression_function fn_co
hash_ctx.fn_sha256_compression = fn_compression;
secp256k1_sha256_write(&hash_ctx, &hasher, (const unsigned char*)input63, 63);
secp256k1_sha256_finalize(&hash_ctx, &hasher, out);
- return secp256k1_memcmp_var(out, output32, 32) == 0;
+ if (secp256k1_memcmp_var(out, output32, 32) != 0) {
+ return 0;
+ }
+ if (fn_compression != secp256k1_sha256_transform && !secp256k1_sha256_smoke_test(fn_compression)) {
+ return 0;
+ }
+ return 1;
}
static int secp256k1_selftest_passes(void) {
### src/secp256k1/src/tests.c
@@ -6,6 +6,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <stdint.h>
#include <string.h>
#include <time.h>
@@ -194,9 +195,6 @@ static void run_ec_illegal_argument_tests(void) {
}
static void run_static_context_tests(int use_prealloc) {
- /* Check that deprecated secp256k1_context_no_precomp is an alias to secp256k1_context_static. */
- CHECK(secp256k1_context_no_precomp == secp256k1_context_static);
-
{
unsigned char seed[32] = {0x17};
@@ -488,6 +486,79 @@ static void run_plug_sha256_compression_tests(void) {
secp256k1_context_destroy(ctx_cloned);
}
+/* Hashes the first block over and over instead of moving on. */
+static void sha256_transform_noadvance(uint32_t *s, const unsigned char *chunk, size_t blocks) {
+ size_t i;
+ for (i = 0; i < blocks; i++) {
+ secp256k1_sha256_transform(s, chunk, 1);
+ }
+}
+
+/* Drops the last block of a multi-block call. */
+static void sha256_transform_short(uint32_t *s, const unsigned char *chunk, size_t blocks) {
+ secp256k1_sha256_transform(s, chunk, blocks > 0 ? blocks - 1 : 0);
+}
+
+/* Starts from the IV instead of the state it was given. */
+static void sha256_transform_ivreset(uint32_t *s, const unsigned char *chunk, size_t blocks) {
+ secp256k1_sha256 h;
+ secp256k1_sha256_initialize(&h);
+ memcpy(s, h.s, sizeof(h.s));
+ secp256k1_sha256_transform(s, chunk, blocks);
+}
+
+/* Correct only on multiples of four blocks. */
+static void sha256_transform_batch4(uint32_t *s, const unsigned char *chunk, size_t blocks) {
+ secp256k1_sha256_transform(s, chunk, blocks - (blocks & 3));
+}
+
+/* Right digest, one bit off. */
+static void sha256_transform_corrupt(uint32_t *s, const unsigned char *chunk, size_t blocks) {
+ secp256k1_sha256_transform(s, chunk, blocks);
+ s[0] ^= 1;
+}
+
+#ifdef UINTPTR_MAX
+
+/* Wrong when input is 64-byte aligned, like a broken SIMD fast path. */
+static void sha256_transform_align64_fail(uint32_t *s, const unsigned char *chunk, size_t blocks) {
+ int aligned = ((uintptr_t)chunk % 64) == 0;
+ secp256k1_sha256_transform(s, chunk, blocks);
+ if (aligned) s[0] ^= 1;
+}
+
+/* Wrong when input is 32-byte aligned but not 64 */
+static void sha256_transform_align32_fail(uint32_t *s, const unsigned char *chunk, size_t blocks) {
+ int align32_not64 = (((uintptr_t)chunk % 32) == 0) && (((uintptr_t)chunk % 64) != 0);
+ secp256k1_sha256_transform(s, chunk, blocks);
+ if (align32_not64) {
+ s[0] ^= 1;
+ }
+}
+
+/* Wrong on any unaligned input. */
+static void sha256_transform_unaligned_fail(uint32_t *s, const unsigned char *chunk, size_t blocks) {
+ int aligned = ((uintptr_t)chunk % 64) == 0;
+ secp256k1_sha256_transform(s, chunk, blocks);
+ if (!aligned) s[0] ^= 1;
+}
+
+#endif /* UINTPTR_MAX */
+
+static void run_sha256_compression_smoke_test_tests(void) {
+ CHECK(secp256k1_sha256_smoke_test(sha256_transform_noadvance) == 0);
+ CHECK(secp256k1_sha256_smoke_test(sha256_transform_short) == 0);
+ CHECK(secp256k1_sha256_smoke_test(sha256_transform_ivreset) == 0);
+ CHECK(secp256k1_sha256_smoke_test(sha256_transform_batch4) == 0);
+ CHECK(secp256k1_sha256_smoke_test(sha256_transform_corrupt) == 0);
+#ifdef UINTPTR_MAX
+ CHECK(secp256k1_sha256_smoke_test(sha256_transform_align64_fail) == 0);
+ CHECK(secp256k1_sha256_smoke_test(sha256_transform_align32_fail) == 0);
+ CHECK(secp256k1_sha256_smoke_test(sha256_transform_unaligned_fail) == 0);
+#endif
+ CHECK(secp256k1_sha256_smoke_test(good_sha256_compression) == 1);
+}
+
static void run_sha256_multi_block_compression_tests(void) {
secp256k1_hash_ctx hash_ctx;
secp256k1_sha256 sha256_one;
@@ -6873,7 +6944,7 @@ static void test_sort_helper(secp256k1_pubkey *pk, size_t *pk_order, size_t n_pk
for (i = 0; i < n_pk; i++) {
pk_test[i] = &pk[pk_order[i]];
}
- secp256k1_ec_pubkey_sort(CTX, pk_test, n_pk);
+ CHECK(secp256k1_ec_pubkey_sort(CTX, pk_test, n_pk) == 1);
for (i = 0; i < n_pk; i++) {
CHECK(secp256k1_memcmp_var(pk_test[i], &pk[i], sizeof(*pk_test[i])) == 0);
}
@@ -6962,7 +7033,7 @@ static void test_sort(void) {
testutil_random_pubkey_test(&pk[j]);
pk_ptr[j] = &pk[j];
}
- secp256k1_ec_pubkey_sort(CTX, pk_ptr, 5);
+ CHECK(secp256k1_ec_pubkey_sort(CTX, pk_ptr, 5) == 1);
for (j = 1; j < 5; j++) {
CHECK(secp256k1_ec_pubkey_sort_cmp(&pk_ptr[j - 1], &pk_ptr[j], CTX) <= 0);
}
@@ -7958,6 +8029,7 @@ static const struct tf_test_entry tests_general[] = {
CASE(scratch_tests),
CASE(invalid_scratch_space_tests),
CASE(plug_sha256_compression_tests),
+ CASE(sha256_compression_smoke_test_tests),
CASE(sha256_multi_block_compression_tests),
};
### src/secp256k1/src/tests_exhaustive.c
@@ -220,7 +220,7 @@ static void test_exhaustive_ecmult_multi(const secp256k1_context *ctx, const sec
data.pt[0] = group[x];
data.pt[1] = group[y];
- secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2);
+ CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2) == 1);
CHECK(secp256k1_gej_eq_ge_var(&tmp, &group[(i * x + j * y + k) % EXHAUSTIVE_TEST_ORDER]));
}
}
### src/secp256k1/src/util.h
@@ -7,7 +7,6 @@
#ifndef SECP256K1_UTIL_H
#define SECP256K1_UTIL_H
-#include "../include/secp256k1.h"
#include "checkmem.h"
#include <string.h>
@@ -46,7 +45,7 @@ static void print_buf_plain(const unsigned char *buf, size_t len) {
}
# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
-# if SECP256K1_GNUC_PREREQ(2,7)
+# if defined(__GNUC__)
# define SECP256K1_INLINE __inline__
# elif (defined(_MSC_VER))
# define SECP256K1_INLINE __inline
@@ -58,7 +57,7 @@ static void print_buf_plain(const unsigned char *buf, size_t len) {
# endif
# if !defined(_DEBUG) && !defined(__NO_INLINE__) && !defined(__OPTIMIZE_SIZE__)
-# if defined(__OPTIMIZE__) && (SECP256K1_GNUC_PREREQ(3, 0) || defined(__clang__))
+# if defined(__OPTIMIZE__) && defined(__GNUC__)
# define SECP256K1_FORCE_INLINE SECP256K1_INLINE __attribute__((always_inline))
# elif defined(_MSC_VER)
# define SECP256K1_FORCE_INLINE __forceinline
@@ -143,7 +142,7 @@ static const secp256k1_callback default_error_callback = {
} while(0)
#endif
-#if SECP256K1_GNUC_PREREQ(3, 0)
+#if defined(__GNUC__)
#define EXPECT(x,c) __builtin_expect((x),(c))
#else
#define EXPECT(x,c) (x)
@@ -199,7 +198,7 @@ static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_
# define SECP256K1_RESTRICT
#else
# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
-# if SECP256K1_GNUC_PREREQ(3,0)
+# if defined(__GNUC__)
# define SECP256K1_RESTRICT __restrict__
# elif (defined(_MSC_VER) && _MSC_VER >= 1400)
# define SECP256K1_RESTRICT __restrict
@@ -392,13 +391,13 @@ static SECP256K1_INLINE int secp256k1_ctz64_var_debruijn(uint64_t x) {
/* Determine the number of trailing zero bits in a (non-zero) 32-bit x. */
static SECP256K1_INLINE int secp256k1_ctz32_var(uint32_t x) {
VERIFY_CHECK(x != 0);
-#if (__has_builtin(__builtin_ctz) || SECP256K1_GNUC_PREREQ(3,4))
+#if (__has_builtin(__builtin_ctz) || defined(__GNUC__))
/* If the unsigned type is sufficient to represent the largest uint32_t, consider __builtin_ctz. */
if (((unsigned)UINT32_MAX) == UINT32_MAX) {
return __builtin_ctz(x);
}
#endif
-#if (__has_builtin(__builtin_ctzl) || SECP256K1_GNUC_PREREQ(3,4))
+#if (__has_builtin(__builtin_ctzl) || defined(__GNUC__))
/* Otherwise consider __builtin_ctzl (the unsigned long type is always at least 32 bits). */
return __builtin_ctzl(x);
#else
@@ -410,13 +409,13 @@ static SECP256K1_INLINE int secp256k1_ctz32_var(uint32_t x) {
/* Determine the number of trailing zero bits in a (non-zero) 64-bit x. */
static SECP256K1_INLINE int secp256k1_ctz64_var(uint64_t x) {
VERIFY_CHECK(x != 0);
-#if (__has_builtin(__builtin_ctzl) || SECP256K1_GNUC_PREREQ(3,4))
+#if (__has_builtin(__builtin_ctzl) || defined(__GNUC__))
/* If the unsigned long type is sufficient to represent the largest uint64_t, consider __builtin_ctzl. */
if (((unsigned long)UINT64_MAX) == UINT64_MAX) {
return __builtin_ctzl(x);
}
#endif
-#if (__has_builtin(__builtin_ctzll) || SECP256K1_GNUC_PREREQ(3,4))
+#if (__has_builtin(__builtin_ctzll) || defined(__GNUC__))
/* Otherwise consider __builtin_ctzll (the unsigned long long type is always at least 64 bits). */
return __builtin_ctzll(x);
#elseWhy this scored 28/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.