From 75ccf99a0751d84e098aab7c4a13170e825c0496 Mon Sep 17 00:00:00 2001 From: furszy Date: Mon, 24 Nov 2025 15:57:43 -0500 Subject: [PATCH 1/2] Add ability to provide SHA256 compression at compile-time Introduces a new `sha` module that exposes the SHA256 compression function and allows users to provide their own implementation. This moves the built-in transform logic out of `hash_impl.h` into a dedicated module (`src/modules/sha`), adds the corresponding public header (`secp256k1_sha.h`), and wires the module through Autotools and CMake via: `--with-external-sha256` / SECP256K1_EXTERNAL_SHA256_PATH. Existing behavior is unchanged; the library compiles and links the default transform function by default. --- CMakeLists.txt | 1 + Makefile.am | 6 ++ configure.ac | 14 +++ include/secp256k1_sha.h | 39 +++++++++ src/CMakeLists.txt | 16 ++++ src/hash_impl.h | 109 +----------------------- src/modules/sha/Makefile.am.include | 2 + src/modules/sha/main_impl.h | 127 ++++++++++++++++++++++++++++ src/secp256k1.c | 6 ++ 9 files changed, 214 insertions(+), 106 deletions(-) create mode 100644 include/secp256k1_sha.h create mode 100644 src/modules/sha/Makefile.am.include create mode 100644 src/modules/sha/main_impl.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 11dc3f6e53..f0bf4a6fad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -285,6 +285,7 @@ message(" extrakeys ........................... ${SECP256K1_ENABLE_MODULE_EXTRA message(" schnorrsig .......................... ${SECP256K1_ENABLE_MODULE_SCHNORRSIG}") message(" musig ............................... ${SECP256K1_ENABLE_MODULE_MUSIG}") message(" ElligatorSwift ...................... ${SECP256K1_ENABLE_MODULE_ELLSWIFT}") +message(" External SHA256 ..................... ${SECP256K1_EXTERNAL_SHA256_PATH-NONE}") message("Parameters:") message(" ecmult window size .................. ${SECP256K1_ECMULT_WINDOW_SIZE}") message(" ecmult gen table size ............... ${SECP256K1_ECMULT_GEN_KB} KiB") diff --git a/Makefile.am b/Makefile.am index dc798575e3..7dd9f68664 100644 --- a/Makefile.am +++ b/Makefile.am @@ -62,6 +62,9 @@ noinst_HEADERS += src/scratch_impl.h noinst_HEADERS += src/selftest.h noinst_HEADERS += src/testrand.h noinst_HEADERS += src/testrand_impl.h +if !SECP256K1_EXTERNAL_SHA256 +noinst_HEADERS += src/modules/sha/main_impl.h +endif noinst_HEADERS += src/hash.h noinst_HEADERS += src/hash_impl.h noinst_HEADERS += src/field.h @@ -314,3 +317,6 @@ endif if ENABLE_MODULE_ELLSWIFT include src/modules/ellswift/Makefile.am.include endif + +# Always include SHA module files, but they conditionally compile +include src/modules/sha/Makefile.am.include diff --git a/configure.ac b/configure.ac index 6028ee288d..cf0a2e748f 100644 --- a/configure.ac +++ b/configure.ac @@ -134,6 +134,12 @@ SECP_TRY_APPEND_DEFAULT_CFLAGS(SECP_CFLAGS) ### Define config arguments ### +AC_ARG_WITH([external-sha256], + AS_HELP_STRING([--with-external-sha256=PATH], [use external SHA256 compression implementation]), + [external_sha256_path="$withval"], + [external_sha256_path=""] +) + # In dev mode, we enable all binaries and modules by default but individual options can still be overridden explicitly. # Check for dev mode first because SECP_SET_DEFAULT needs enable_dev_mode set. AC_ARG_ENABLE(dev_mode, [], [], @@ -397,6 +403,12 @@ SECP_CFLAGS="$SECP_CFLAGS $WERROR_CFLAGS" # Processing must be done in a reverse topological sorting of the dependency graph # (dependent module first). + +if test "x$external_sha256_path" != "x"; then + SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DSECP256K1_EXTERNAL_SHA256=1" + SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DSECP256K1_EXTERNAL_SHA256_HEADER='\"$external_sha256_path\"'" +fi + if test x"$enable_module_ellswift" = x"yes"; then SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_ELLSWIFT=1" fi @@ -470,6 +482,7 @@ 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_MUSIG], [test x"$enable_module_musig" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_ELLSWIFT], [test x"$enable_module_ellswift" = x"yes"]) +AM_CONDITIONAL([SECP256K1_EXTERNAL_SHA256], [test "x$SHA256_EXTERNAL_SRC" != "x"]) 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"]) @@ -494,6 +507,7 @@ echo " module extrakeys = $enable_module_extrakeys" echo " module schnorrsig = $enable_module_schnorrsig" echo " module musig = $enable_module_musig" echo " module ellswift = $enable_module_ellswift" +echo " external sha256 = ${external_sha256_path:-none}" echo echo " asm = $set_asm" echo " ecmult window size = $set_ecmult_window" diff --git a/include/secp256k1_sha.h b/include/secp256k1_sha.h new file mode 100644 index 0000000000..1d017f4450 --- /dev/null +++ b/include/secp256k1_sha.h @@ -0,0 +1,39 @@ +#ifndef SECP256K1_SHA_H +#define SECP256K1_SHA_H + +#include "secp256k1.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * SHA-256 block compression function. + * + * Performs the SHA-256 transform step on a single 64-byte message block, + * updating the 8-word `state` in place. This is the raw block-level primitive: + * no padding, no message scheduling across blocks, and no length encoding. + * Only the compression function is applied. + * + * If `rounds` is greater than 1, the same 64-byte block is re-compressed + * repeatedly onto the updated state. + * + * The caller must supply a fully-formed, 64-byte, block-aligned message block. + * + * @param state Current hash state (8 x 32-bit words), updated in place. + * @param block Pointer to a 64-byte message block. + * @param rounds Number of times to apply the compression to this block. + */ +SECP256K1_API void secp256k1_sha256_transform( + uint32_t *state, + const unsigned char *block, + size_t rounds +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + +#ifdef __cplusplus +} +#endif + +#endif /* SECP256K1_SHA_H */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ecbbbbe8e9..beb4e46a8f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,10 +3,26 @@ add_library(secp256k1) set_property(TARGET secp256k1 PROPERTY PUBLIC_HEADER ${PROJECT_SOURCE_DIR}/include/secp256k1.h ${PROJECT_SOURCE_DIR}/include/secp256k1_preallocated.h + ${PROJECT_SOURCE_DIR}/include/secp256k1_sha.h ) # Processing must be done in a topological sorting of the dependency graph # (dependent module first). + +if(SECP256K1_EXTERNAL_SHA256_PATH) + if(EXISTS "${SECP256K1_EXTERNAL_SHA256_PATH}") + add_compile_definitions(SECP256K1_EXTERNAL_SHA256=1) + add_compile_definitions(SECP256K1_EXTERNAL_SHA256_HEADER="${SECP256K1_EXTERNAL_SHA256_PATH}") + else() + message(FATAL_ERROR "SECP256K1_EXTERNAL_SHA256_PATH does not exist: ${SECP256K1_EXTERNAL_SHA256_PATH}") + endif() +else() + # No external override. Compile internal implementation + target_sources(secp256k1 PRIVATE + ${PROJECT_SOURCE_DIR}/src/modules/sha/main_impl.h + ) +endif() + if(SECP256K1_ENABLE_MODULE_ELLSWIFT) add_compile_definitions(ENABLE_MODULE_ELLSWIFT=1) set_property(TARGET secp256k1 APPEND PROPERTY PUBLIC_HEADER ${PROJECT_SOURCE_DIR}/include/secp256k1_ellswift.h) diff --git a/src/hash_impl.h b/src/hash_impl.h index 4341917773..bbeb550c58 100644 --- a/src/hash_impl.h +++ b/src/hash_impl.h @@ -10,24 +10,12 @@ #include "hash.h" #include "util.h" +#include "../include/secp256k1_sha.h" + #include #include #include -#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) -#define Maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) -#define Sigma0(x) (((x) >> 2 | (x) << 30) ^ ((x) >> 13 | (x) << 19) ^ ((x) >> 22 | (x) << 10)) -#define Sigma1(x) (((x) >> 6 | (x) << 26) ^ ((x) >> 11 | (x) << 21) ^ ((x) >> 25 | (x) << 7)) -#define sigma0(x) (((x) >> 7 | (x) << 25) ^ ((x) >> 18 | (x) << 14) ^ ((x) >> 3)) -#define sigma1(x) (((x) >> 17 | (x) << 15) ^ ((x) >> 19 | (x) << 13) ^ ((x) >> 10)) - -#define Round(a,b,c,d,e,f,g,h,k,w) do { \ - uint32_t t1 = (h) + Sigma1(e) + Ch((e), (f), (g)) + (k) + (w); \ - uint32_t t2 = Sigma0(a) + Maj((a), (b), (c)); \ - (d) += t1; \ - (h) = t1 + t2; \ -} while(0) - static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) { hash->s[0] = 0x6a09e667ul; hash->s[1] = 0xbb67ae85ul; @@ -40,89 +28,6 @@ static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) { hash->bytes = 0; } -/** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */ -static void secp256k1_sha256_transform(uint32_t* s, const unsigned char* buf) { - uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; - uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; - - Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = secp256k1_read_be32(&buf[0])); - Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = secp256k1_read_be32(&buf[4])); - Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = secp256k1_read_be32(&buf[8])); - Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = secp256k1_read_be32(&buf[12])); - Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = secp256k1_read_be32(&buf[16])); - Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = secp256k1_read_be32(&buf[20])); - Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = secp256k1_read_be32(&buf[24])); - Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = secp256k1_read_be32(&buf[28])); - Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = secp256k1_read_be32(&buf[32])); - Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = secp256k1_read_be32(&buf[36])); - Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = secp256k1_read_be32(&buf[40])); - Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = secp256k1_read_be32(&buf[44])); - Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = secp256k1_read_be32(&buf[48])); - Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = secp256k1_read_be32(&buf[52])); - Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = secp256k1_read_be32(&buf[56])); - Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = secp256k1_read_be32(&buf[60])); - - Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); - - Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); - - Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); - - s[0] += a; - s[1] += b; - s[2] += c; - s[3] += d; - s[4] += e; - s[5] += f; - s[6] += g; - s[7] += h; -} - static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t len) { size_t bufsize = hash->bytes & 0x3F; hash->bytes += len; @@ -133,7 +38,7 @@ static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char * memcpy(hash->buf + bufsize, data, chunk_len); data += chunk_len; len -= chunk_len; - secp256k1_sha256_transform(hash->s, hash->buf); + secp256k1_sha256_transform(hash->s, hash->buf, 1); bufsize = 0; } if (len) { @@ -288,12 +193,4 @@ static void secp256k1_rfc6979_hmac_sha256_clear(secp256k1_rfc6979_hmac_sha256 *r secp256k1_memclear_explicit(rng, sizeof(*rng)); } -#undef Round -#undef sigma1 -#undef sigma0 -#undef Sigma1 -#undef Sigma0 -#undef Maj -#undef Ch - #endif /* SECP256K1_HASH_IMPL_H */ diff --git a/src/modules/sha/Makefile.am.include b/src/modules/sha/Makefile.am.include new file mode 100644 index 0000000000..17e42a1b38 --- /dev/null +++ b/src/modules/sha/Makefile.am.include @@ -0,0 +1,2 @@ +include_HEADERS += include/secp256k1_sha.h +noinst_HEADERS += src/modules/sha/main_impl.h diff --git a/src/modules/sha/main_impl.h b/src/modules/sha/main_impl.h new file mode 100644 index 0000000000..da75a370d8 --- /dev/null +++ b/src/modules/sha/main_impl.h @@ -0,0 +1,127 @@ +/*********************************************************************** + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_MODULE_SHA_MAIN_H +#define SECP256K1_MODULE_SHA_MAIN_H + +#if !defined(SECP256K1_EXTERNAL_SHA256) + +#include "../../../include/secp256k1_sha.h" +#include "../../util.h" + +#include + +#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define Maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define Sigma0(x) (((x) >> 2 | (x) << 30) ^ ((x) >> 13 | (x) << 19) ^ ((x) >> 22 | (x) << 10)) +#define Sigma1(x) (((x) >> 6 | (x) << 26) ^ ((x) >> 11 | (x) << 21) ^ ((x) >> 25 | (x) << 7)) +#define sigma0(x) (((x) >> 7 | (x) << 25) ^ ((x) >> 18 | (x) << 14) ^ ((x) >> 3)) +#define sigma1(x) (((x) >> 17 | (x) << 15) ^ ((x) >> 19 | (x) << 13) ^ ((x) >> 10)) + +#define Round(a,b,c,d,e,f,g,h,k,w) do { \ + uint32_t t1 = (h) + Sigma1(e) + Ch((e), (f), (g)) + (k) + (w); \ + uint32_t t2 = Sigma0(a) + Maj((a), (b), (c)); \ + (d) += t1; \ + (h) = t1 + t2; \ +} while(0) + +/** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */ +static void secp256k1_sha256_transform_impl(uint32_t* s, const unsigned char* buf) { + uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; + uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; + + Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = secp256k1_read_be32(&buf[0])); + Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = secp256k1_read_be32(&buf[4])); + Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = secp256k1_read_be32(&buf[8])); + Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = secp256k1_read_be32(&buf[12])); + Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = secp256k1_read_be32(&buf[16])); + Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = secp256k1_read_be32(&buf[20])); + Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = secp256k1_read_be32(&buf[24])); + Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = secp256k1_read_be32(&buf[28])); + Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = secp256k1_read_be32(&buf[32])); + Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = secp256k1_read_be32(&buf[36])); + Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = secp256k1_read_be32(&buf[40])); + Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = secp256k1_read_be32(&buf[44])); + Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = secp256k1_read_be32(&buf[48])); + Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = secp256k1_read_be32(&buf[52])); + Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = secp256k1_read_be32(&buf[56])); + Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = secp256k1_read_be32(&buf[60])); + + Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); + + s[0] += a; + s[1] += b; + s[2] += c; + s[3] += d; + s[4] += e; + s[5] += f; + s[6] += g; + s[7] += h; +} + +void secp256k1_sha256_transform(uint32_t *state, const unsigned char *block, size_t rounds) { + while (rounds--) secp256k1_sha256_transform_impl(state, block); +} + +#undef Round +#undef sigma1 +#undef sigma0 +#undef Sigma1 +#undef Sigma0 +#undef Maj +#undef Ch + +#endif /* !SECP256K1_EXTERNAL_SHA256 */ + +#endif /* SECP256K1_MODULE_SHA_MAIN_H */ diff --git a/src/secp256k1.c b/src/secp256k1.c index c2d3fcbddb..ec5937cfe4 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -821,3 +821,9 @@ int secp256k1_tagged_sha256(const secp256k1_context* ctx, unsigned char *hash32, #ifdef ENABLE_MODULE_ELLSWIFT # include "modules/ellswift/main_impl.h" #endif + +#ifdef SECP256K1_EXTERNAL_SHA256 +#include SECP256K1_EXTERNAL_SHA256_HEADER +#else +#include "modules/sha/main_impl.h" +#endif From 7fefa9c851d36214a4a03aeae36b59aee9d08263 Mon Sep 17 00:00:00 2001 From: furszy Date: Mon, 24 Nov 2025 14:33:58 -0500 Subject: [PATCH 2/2] Add API to override SHA256 transform at runtime This introduces `secp256k1_context_set_sha256_transform_callback()`, which allows users to provide their own SHA256 block-compression function at runtime. This is useful in setups where the optimal implementation is detected dynamically, where rebuilding the library is not possible, or when the compression function is not written in bare C89. The callback is installed on the `secp256k1_context` and is then used by all operations that compute SHA256 hashes. As part of the setup, the library performs sanity checks to ensure that the supplied function is equivalent to the default transform. Passing NULL to the callback setter restores the built-in implementation. --- include/secp256k1.h | 25 ++++ include/secp256k1_ecdh.h | 1 + include/secp256k1_ellswift.h | 1 + include/secp256k1_schnorrsig.h | 1 + src/bench_ecmult.c | 2 +- src/bench_internal.c | 12 +- src/ecmult_gen_impl.h | 9 +- src/hash.h | 15 +- src/hash_impl.h | 78 +++++++--- src/modules/ecdh/main_impl.h | 6 +- src/modules/ecdh/tests_impl.h | 12 +- src/modules/ellswift/main_impl.h | 26 ++-- src/modules/ellswift/tests_impl.h | 16 +- src/modules/musig/keyagg.h | 2 +- src/modules/musig/keyagg_impl.h | 20 +-- src/modules/musig/session_impl.h | 36 ++--- src/modules/musig/tests_impl.h | 52 +++---- src/modules/recovery/tests_impl.h | 3 +- src/modules/schnorrsig/main_impl.h | 30 ++-- .../schnorrsig/tests_exhaustive_impl.h | 9 +- src/modules/schnorrsig/tests_impl.h | 56 +++---- src/secp256k1.c | 33 ++++- src/selftest.h | 7 +- src/testrand_impl.h | 3 +- src/tests.c | 139 +++++++++++++----- src/tests_exhaustive.c | 7 +- 26 files changed, 393 insertions(+), 208 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index b0a13b144d..7a4f4b35ed 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -6,6 +6,7 @@ extern "C" { #endif #include +#include /** Unless explicitly stated all pointer arguments must not be NULL. * @@ -92,6 +93,7 @@ typedef struct secp256k1_ecdsa_signature { * the message, the algorithm, the key and the attempt. */ typedef int (*secp256k1_nonce_function)( + const secp256k1_context *ctx, unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, @@ -403,6 +405,29 @@ SECP256K1_API void secp256k1_context_set_error_callback( const void *data ) SECP256K1_ARG_NONNULL(1); +/** + * Set a callback function to override the internal SHA-256 transform. + * + * This installs a function to replace the built-in block-compression + * step used by the library's internal SHA-256 implementation. + * The provided callback must be functionally identical (bit-for-bit) + * to the default transform. Any deviation will cause incorrect results + * and undefined behaviour. + * + * This API exists to support environments that wish to route the + * SHA-256 compression step through a hardware-accelerated or otherwise + * specialized implementation. It is not meant for modifying the + * semantics of SHA-256. + * + * Args: ctx: pointer to a context object. + * In: callback: pointer to a function implementing the transform step. + * (passing NULL restores the default implementation) + */ +SECP256K1_API void secp256k1_context_set_sha256_transform_callback( + secp256k1_context *ctx, + void (*sha256_transform_callback)(uint32_t *state, const unsigned char *block, size_t rounds) +) SECP256K1_ARG_NONNULL(1); + /** Parse a variable-length public key into the pubkey object. * * Returns: 1 if the public key was fully valid. diff --git a/include/secp256k1_ecdh.h b/include/secp256k1_ecdh.h index 4d9da3461d..81b13672d1 100644 --- a/include/secp256k1_ecdh.h +++ b/include/secp256k1_ecdh.h @@ -19,6 +19,7 @@ extern "C" { * data: arbitrary data pointer that is passed through */ typedef int (*secp256k1_ecdh_hash_function)( + const secp256k1_context *ctx, unsigned char *output, const unsigned char *x32, const unsigned char *y32, diff --git a/include/secp256k1_ellswift.h b/include/secp256k1_ellswift.h index 4cda5d5ca0..4aff0efe5d 100644 --- a/include/secp256k1_ellswift.h +++ b/include/secp256k1_ellswift.h @@ -62,6 +62,7 @@ extern "C" { * data: arbitrary data pointer that is passed through */ typedef int (*secp256k1_ellswift_xdh_hash_function)( + const secp256k1_context *ctx, unsigned char *output, const unsigned char *x32, const unsigned char *ell_a64, diff --git a/include/secp256k1_schnorrsig.h b/include/secp256k1_schnorrsig.h index 013d4ee73d..a42ea4b746 100644 --- a/include/secp256k1_schnorrsig.h +++ b/include/secp256k1_schnorrsig.h @@ -39,6 +39,7 @@ extern "C" { * the message, the key, the pubkey, the algorithm description, and data. */ typedef int (*secp256k1_nonce_function_hardened)( + const secp256k1_context *ctx, unsigned char *nonce32, const unsigned char *msg, size_t msglen, diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index c9a1d90026..97a9ebf49a 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -265,7 +265,7 @@ static void generate_scalar(uint32_t num, secp256k1_scalar* scalar) { c[7] = num >> 8; c[8] = num >> 16; c[9] = num >> 24; - secp256k1_sha256_initialize(&sha256); + secp256k1_sha256_initialize(&sha256, /*fn_transform=*/NULL); secp256k1_sha256_write(&sha256, c, sizeof(c)); secp256k1_sha256_finalize(&sha256, buf); secp256k1_scalar_set_b32(scalar, buf, &overflow); diff --git a/src/bench_internal.c b/src/bench_internal.c index 8688a4dc77..6f7d499d49 100644 --- a/src/bench_internal.c +++ b/src/bench_internal.c @@ -38,6 +38,7 @@ static void help(int default_iters) { } typedef struct { + const secp256k1_context* ctx; secp256k1_scalar scalar[2]; secp256k1_fe fe[4]; secp256k1_ge ge[2]; @@ -82,6 +83,9 @@ static void bench_setup(void* arg) { } }; + /* Customize context if needed */ + data->ctx = secp256k1_context_static; + secp256k1_scalar_set_b32(&data->scalar[0], init[0], NULL); secp256k1_scalar_set_b32(&data->scalar[1], init[1], NULL); secp256k1_fe_set_b32_limit(&data->fe[0], init[0]); @@ -346,7 +350,7 @@ static void bench_sha256(void* arg, int iters) { secp256k1_sha256 sha; for (i = 0; i < iters; i++) { - secp256k1_sha256_initialize(&sha); + secp256k1_sha256_initialize(&sha, data->ctx->hash_context.fn_sha256_transform); secp256k1_sha256_write(&sha, data->data, 32); secp256k1_sha256_finalize(&sha, data->data); } @@ -358,7 +362,7 @@ static void bench_hmac_sha256(void* arg, int iters) { secp256k1_hmac_sha256 hmac; for (i = 0; i < iters; i++) { - secp256k1_hmac_sha256_initialize(&hmac, data->data, 32); + secp256k1_hmac_sha256_initialize(&hmac, data->data, 32, data->ctx->hash_context.fn_sha256_transform); secp256k1_hmac_sha256_write(&hmac, data->data, 32); secp256k1_hmac_sha256_finalize(&hmac, data->data); } @@ -370,8 +374,8 @@ static void bench_rfc6979_hmac_sha256(void* arg, int iters) { secp256k1_rfc6979_hmac_sha256 rng; for (i = 0; i < iters; i++) { - secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64); - secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32); + secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64, data->ctx->hash_context.fn_sha256_transform); + secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32, data->ctx->hash_context.fn_sha256_transform); } } diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index 2159eed5e1..6ae87bb677 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -291,6 +291,9 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_rfc6979_hmac_sha256 rng; unsigned char keydata[64]; + /* future: use context callback */ + const sha256_transform_callback fn_sha256_transform = NULL; + /* Compute the (2^COMB_BITS - 1)/2 term once. */ secp256k1_ecmult_gen_scalar_diff(&diff); @@ -309,17 +312,17 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const */ VERIFY_CHECK(seed32 != NULL); memcpy(keydata + 32, seed32, 32); - secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, 64); + secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, 64, fn_sha256_transform); secp256k1_memclear_explicit(keydata, sizeof(keydata)); /* Compute projective blinding factor (cannot be 0). */ - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32, fn_sha256_transform); secp256k1_fe_set_b32_mod(&f, nonce32); secp256k1_fe_cmov(&f, &secp256k1_fe_one, secp256k1_fe_normalizes_to_zero(&f)); ctx->proj_blind = f; /* For a random blinding value b, set scalar_offset=diff-b, ge_offset=bG */ - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32, fn_sha256_transform); secp256k1_scalar_set_b32(&b, nonce32, NULL); /* The blinding value cannot be zero, as that would mean ge_offset = infinity, * which secp256k1_gej_add_ge cannot handle. */ diff --git a/src/hash.h b/src/hash.h index 6d903ca7e0..a7138fa9db 100644 --- a/src/hash.h +++ b/src/hash.h @@ -10,13 +10,20 @@ #include #include +typedef void (*sha256_transform_callback)(uint32_t *state, const unsigned char *block, size_t rounds); + +/* Validate user-supplied SHA-256 transform by comparing its output against + * the library's linked implementation */ +static int secp256k1_sha256_check_transform(sha256_transform_callback fn_transform); + typedef struct { uint32_t s[8]; unsigned char buf[64]; uint64_t bytes; + sha256_transform_callback fn_transform; } secp256k1_sha256; -static void secp256k1_sha256_initialize(secp256k1_sha256 *hash); +static void secp256k1_sha256_initialize(secp256k1_sha256 *hash, sha256_transform_callback fn_transform); static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size); static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32); static void secp256k1_sha256_clear(secp256k1_sha256 *hash); @@ -25,7 +32,7 @@ typedef struct { secp256k1_sha256 inner, outer; } secp256k1_hmac_sha256; -static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size); +static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size, sha256_transform_callback fn_sha256_transform); static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size); static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32); static void secp256k1_hmac_sha256_clear(secp256k1_hmac_sha256 *hash); @@ -36,8 +43,8 @@ typedef struct { int retry; } secp256k1_rfc6979_hmac_sha256; -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen); -static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen); +static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen, sha256_transform_callback fn_sha256_transform); +static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen, sha256_transform_callback fn_sha256_transform); static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng); static void secp256k1_rfc6979_hmac_sha256_clear(secp256k1_rfc6979_hmac_sha256 *rng); diff --git a/src/hash_impl.h b/src/hash_impl.h index bbeb550c58..14d1072e36 100644 --- a/src/hash_impl.h +++ b/src/hash_impl.h @@ -16,7 +16,7 @@ #include #include -static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) { +static void secp256k1_sha256_initialize(secp256k1_sha256 *hash, sha256_transform_callback fn_transform) { hash->s[0] = 0x6a09e667ul; hash->s[1] = 0xbb67ae85ul; hash->s[2] = 0x3c6ef372ul; @@ -26,6 +26,7 @@ static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) { hash->s[6] = 0x1f83d9abul; hash->s[7] = 0x5be0cd19ul; hash->bytes = 0; + hash->fn_transform = fn_transform == NULL ? secp256k1_sha256_transform : fn_transform; } static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t len) { @@ -38,7 +39,7 @@ static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char * memcpy(hash->buf + bufsize, data, chunk_len); data += chunk_len; len -= chunk_len; - secp256k1_sha256_transform(hash->s, hash->buf, 1); + hash->fn_transform(hash->s, hash->buf, 1); bufsize = 0; } if (len) { @@ -63,15 +64,56 @@ static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out } } +static int secp256k1_sha256_check_transform(sha256_transform_callback fn_transform) { + secp256k1_sha256 sha256; + unsigned char out[2][32]; + + /* Four messages of different sizes: 1, 24, 64 and 81 bytes */ + unsigned char* msgs[4]; + size_t lens[4]; + unsigned char msg_0 = 0; + unsigned char msg_1[24] = "secp256k1_verif_round_i"; + unsigned char msg_2[64] = "For this test, this 63-byte string will be used as input data i"; + unsigned char msg_3[81] = "Genesis: The Times 03/Jan/2009 Chancellor on brink of second bailout for banks i"; + msgs[0] = &msg_0; lens[0] = sizeof(msg_0); + msgs[1] = msg_1; lens[1] = sizeof(msg_1); + msgs[2] = msg_2; lens[2] = sizeof(msg_2); + msgs[3] = msg_3; lens[3] = sizeof(msg_3); + + /* Compare hashes between built-in transform vs the one provided by the user */ + { + unsigned char i, j, k; + sha256_transform_callback funcs[2]; + funcs[0] = secp256k1_sha256_transform; /* Built-in */ + funcs[1] = fn_transform; /* User provided */ + + for (i = 0; i < 10; i++) { + msg_0 = i; + msg_1[23] = i; + msg_2[63] = i; + msg_3[80] = i; + for (j = 0; j < 4; j++) { + for (k = 0; k < 2; k++) { + secp256k1_sha256_initialize(&sha256, funcs[k]); + secp256k1_sha256_write(&sha256, msgs[j], lens[j]); + secp256k1_sha256_finalize(&sha256, out[k]); + } + if (memcmp(out[0], out[1], 32) != 0) return 0; + } + } + } + return 1; +} + /* Initializes a sha256 struct and writes the 64 byte string * SHA256(tag)||SHA256(tag) into it. */ -static void secp256k1_sha256_initialize_tagged(secp256k1_sha256 *hash, const unsigned char *tag, size_t taglen) { +static void secp256k1_sha256_initialize_tagged(secp256k1_sha256 *hash, const unsigned char *tag, size_t taglen, sha256_transform_callback fn_sha256_transform) { unsigned char buf[32]; - secp256k1_sha256_initialize(hash); + secp256k1_sha256_initialize(hash, fn_sha256_transform); secp256k1_sha256_write(hash, tag, taglen); secp256k1_sha256_finalize(hash, buf); - secp256k1_sha256_initialize(hash); + secp256k1_sha256_initialize(hash, fn_sha256_transform); secp256k1_sha256_write(hash, buf, 32); secp256k1_sha256_write(hash, buf, 32); } @@ -80,7 +122,7 @@ static void secp256k1_sha256_clear(secp256k1_sha256 *hash) { secp256k1_memclear_explicit(hash, sizeof(*hash)); } -static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) { +static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen, sha256_transform_callback fn_sha256_transform) { size_t n; unsigned char rkey[64]; if (keylen <= sizeof(rkey)) { @@ -88,19 +130,19 @@ static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const memset(rkey + keylen, 0, sizeof(rkey) - keylen); } else { secp256k1_sha256 sha256; - secp256k1_sha256_initialize(&sha256); + secp256k1_sha256_initialize(&sha256, fn_sha256_transform); secp256k1_sha256_write(&sha256, key, keylen); secp256k1_sha256_finalize(&sha256, rkey); memset(rkey + 32, 0, 32); } - secp256k1_sha256_initialize(&hash->outer); + secp256k1_sha256_initialize(&hash->outer, fn_sha256_transform); for (n = 0; n < sizeof(rkey); n++) { rkey[n] ^= 0x5c; } secp256k1_sha256_write(&hash->outer, rkey, sizeof(rkey)); - secp256k1_sha256_initialize(&hash->inner); + secp256k1_sha256_initialize(&hash->inner, fn_sha256_transform); for (n = 0; n < sizeof(rkey); n++) { rkey[n] ^= 0x5c ^ 0x36; } @@ -124,7 +166,7 @@ static void secp256k1_hmac_sha256_clear(secp256k1_hmac_sha256 *hash) { secp256k1_memclear_explicit(hash, sizeof(*hash)); } -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) { +static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen, sha256_transform_callback fn_sha256_transform) { secp256k1_hmac_sha256 hmac; static const unsigned char zero[1] = {0x00}; static const unsigned char one[1] = {0x01}; @@ -133,37 +175,37 @@ static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha2 memset(rng->k, 0x00, 32); /* RFC6979 3.2.c. */ /* RFC6979 3.2.d. */ - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32, fn_sha256_transform); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_write(&hmac, zero, 1); secp256k1_hmac_sha256_write(&hmac, key, keylen); secp256k1_hmac_sha256_finalize(&hmac, rng->k); - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32, fn_sha256_transform); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_finalize(&hmac, rng->v); /* RFC6979 3.2.f. */ - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32, fn_sha256_transform); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_write(&hmac, one, 1); secp256k1_hmac_sha256_write(&hmac, key, keylen); secp256k1_hmac_sha256_finalize(&hmac, rng->k); - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32, fn_sha256_transform); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_finalize(&hmac, rng->v); rng->retry = 0; } -static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen) { +static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen, sha256_transform_callback fn_sha256_transform) { /* RFC6979 3.2.h. */ static const unsigned char zero[1] = {0x00}; if (rng->retry) { secp256k1_hmac_sha256 hmac; - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32, fn_sha256_transform); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_write(&hmac, zero, 1); secp256k1_hmac_sha256_finalize(&hmac, rng->k); - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32, fn_sha256_transform); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_finalize(&hmac, rng->v); } @@ -171,7 +213,7 @@ static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 while (outlen > 0) { secp256k1_hmac_sha256 hmac; size_t now = outlen; - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32, fn_sha256_transform); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_finalize(&hmac, rng->v); if (now > 32) { diff --git a/src/modules/ecdh/main_impl.h b/src/modules/ecdh/main_impl.h index 9f2dfdd56a..ab10388714 100644 --- a/src/modules/ecdh/main_impl.h +++ b/src/modules/ecdh/main_impl.h @@ -10,12 +10,12 @@ #include "../../../include/secp256k1_ecdh.h" #include "../../ecmult_const_impl.h" -static int ecdh_hash_function_sha256(unsigned char *output, const unsigned char *x32, const unsigned char *y32, void *data) { +static int ecdh_hash_function_sha256(const secp256k1_context *ctx, unsigned char *output, const unsigned char *x32, const unsigned char *y32, void *data) { unsigned char version = (y32[31] & 0x01) | 0x02; secp256k1_sha256 sha; (void)data; - secp256k1_sha256_initialize(&sha); + secp256k1_sha256_initialize(&sha, ctx->hash_context.fn_sha256_transform); secp256k1_sha256_write(&sha, &version, 1); secp256k1_sha256_write(&sha, x32, 32); secp256k1_sha256_finalize(&sha, output); @@ -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); - ret = hashfp(output, x, y, data); + ret = hashfp(ctx, output, x, y, data); secp256k1_memclear_explicit(x, sizeof(x)); secp256k1_memclear_explicit(y, sizeof(y)); diff --git a/src/modules/ecdh/tests_impl.h b/src/modules/ecdh/tests_impl.h index cb1d953d2a..685c79921f 100644 --- a/src/modules/ecdh/tests_impl.h +++ b/src/modules/ecdh/tests_impl.h @@ -9,14 +9,16 @@ #include "../../unit_test.h" -static int ecdh_hash_function_test_xpassthru(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) { +static int ecdh_hash_function_test_xpassthru(const secp256k1_context *ctx, unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) { + (void)ctx; (void)y; (void)data; memcpy(output, x, 32); return 1; } -static int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) { +static int ecdh_hash_function_test_fail(const secp256k1_context *ctx, unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) { + (void)ctx; (void)output; (void)x; (void)y; @@ -24,7 +26,8 @@ static int ecdh_hash_function_test_fail(unsigned char *output, const unsigned ch return 0; } -static int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) { +static int ecdh_hash_function_custom(const secp256k1_context *ctx, unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) { + (void)ctx; (void)data; /* Save x and y as uncompressed public key */ output[0] = 0x04; @@ -53,6 +56,7 @@ static void test_ecdh_generator_basepoint(void) { unsigned char s_one[32] = { 0 }; secp256k1_pubkey point[2]; int i; + const secp256k1_context *ctx = secp256k1_context_static; s_one[31] = 1; /* Check against pubkey creation when the basepoint is the generator */ @@ -82,7 +86,7 @@ static void test_ecdh_generator_basepoint(void) { CHECK(secp256k1_ecdh(CTX, output_ecdh, &point[0], s_b32, NULL, NULL) == 1); /* compute "explicitly" */ CHECK(secp256k1_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1); - secp256k1_sha256_initialize(&sha); + secp256k1_sha256_initialize(&sha, ctx->hash_context.fn_sha256_transform); secp256k1_sha256_write(&sha, point_ser, point_ser_len); secp256k1_sha256_finalize(&sha, output_ser); /* compare */ diff --git a/src/modules/ellswift/main_impl.h b/src/modules/ellswift/main_impl.h index 096f4a3c71..bd1f7c6b6c 100644 --- a/src/modules/ellswift/main_impl.h +++ b/src/modules/ellswift/main_impl.h @@ -382,8 +382,8 @@ static void secp256k1_ellswift_elligatorswift_var(unsigned char *u32, secp256k1_ } /** Set hash state to the BIP340 tagged hash midstate for "secp256k1_ellswift_encode". */ -static void secp256k1_ellswift_sha256_init_encode(secp256k1_sha256* hash) { - secp256k1_sha256_initialize(hash); +static void secp256k1_ellswift_sha256_init_encode(const secp256k1_context *ctx, secp256k1_sha256* hash) { + secp256k1_sha256_initialize(hash, ctx->hash_context.fn_sha256_transform); hash->s[0] = 0xd1a6524bul; hash->s[1] = 0x028594b3ul; hash->s[2] = 0x96e42f4eul; @@ -410,7 +410,7 @@ int secp256k1_ellswift_encode(const secp256k1_context *ctx, unsigned char *ell64 /* Set up hasher state; the used RNG is H(pubkey || "\x00"*31 || rnd32 || cnt++), using * BIP340 tagged hash with tag "secp256k1_ellswift_encode". */ - secp256k1_ellswift_sha256_init_encode(&hash); + secp256k1_ellswift_sha256_init_encode(ctx, &hash); secp256k1_eckey_pubkey_serialize33(&p, p64); secp256k1_sha256_write(&hash, p64, sizeof(p64)); secp256k1_sha256_write(&hash, rnd32, 32); @@ -426,8 +426,8 @@ int secp256k1_ellswift_encode(const secp256k1_context *ctx, unsigned char *ell64 } /** Set hash state to the BIP340 tagged hash midstate for "secp256k1_ellswift_create". */ -static void secp256k1_ellswift_sha256_init_create(secp256k1_sha256* hash) { - secp256k1_sha256_initialize(hash); +static void secp256k1_ellswift_sha256_init_create(const secp256k1_context *ctx, secp256k1_sha256* hash) { + secp256k1_sha256_initialize(hash, ctx->hash_context.fn_sha256_transform); hash->s[0] = 0xd29e1bf5ul; hash->s[1] = 0xf7025f42ul; hash->s[2] = 0x9b024773ul; @@ -463,7 +463,7 @@ int secp256k1_ellswift_create(const secp256k1_context *ctx, unsigned char *ell64 /* Set up hasher state. The used RNG is H(privkey || "\x00"*32 [|| auxrnd32] || cnt++), * using BIP340 tagged hash with tag "secp256k1_ellswift_create". */ - secp256k1_ellswift_sha256_init_create(&hash); + secp256k1_ellswift_sha256_init_create(ctx, &hash); secp256k1_sha256_write(&hash, seckey32, 32); secp256k1_sha256_write(&hash, zero32, sizeof(zero32)); secp256k1_declassify(ctx, &hash, sizeof(hash)); /* private key is hashed now */ @@ -494,10 +494,10 @@ int secp256k1_ellswift_decode(const secp256k1_context *ctx, secp256k1_pubkey *pu return 1; } -static int ellswift_xdh_hash_function_prefix(unsigned char *output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { +static int ellswift_xdh_hash_function_prefix(const secp256k1_context *ctx, unsigned char *output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { secp256k1_sha256 sha; - secp256k1_sha256_initialize(&sha); + secp256k1_sha256_initialize(&sha, ctx->hash_context.fn_sha256_transform); secp256k1_sha256_write(&sha, data, 64); secp256k1_sha256_write(&sha, ell_a64, 64); secp256k1_sha256_write(&sha, ell_b64, 64); @@ -509,8 +509,8 @@ static int ellswift_xdh_hash_function_prefix(unsigned char *output, const unsign } /** Set hash state to the BIP340 tagged hash midstate for "bip324_ellswift_xonly_ecdh". */ -static void secp256k1_ellswift_sha256_init_bip324(secp256k1_sha256* hash) { - secp256k1_sha256_initialize(hash); +static void secp256k1_ellswift_sha256_init_bip324(const secp256k1_context *ctx, secp256k1_sha256* hash) { + secp256k1_sha256_initialize(hash, ctx->hash_context.fn_sha256_transform); hash->s[0] = 0x8c12d730ul; hash->s[1] = 0x827bd392ul; hash->s[2] = 0x9e4fb2eeul; @@ -523,12 +523,12 @@ static void secp256k1_ellswift_sha256_init_bip324(secp256k1_sha256* hash) { hash->bytes = 64; } -static int ellswift_xdh_hash_function_bip324(unsigned char* output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { +static int ellswift_xdh_hash_function_bip324(const secp256k1_context *ctx, unsigned char* output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { secp256k1_sha256 sha; (void)data; - secp256k1_ellswift_sha256_init_bip324(&sha); + secp256k1_ellswift_sha256_init_bip324(ctx, &sha); secp256k1_sha256_write(&sha, ell_a64, 64); secp256k1_sha256_write(&sha, ell_b64, 64); secp256k1_sha256_write(&sha, x32, 32); @@ -573,7 +573,7 @@ int secp256k1_ellswift_xdh(const secp256k1_context *ctx, unsigned char *output, secp256k1_fe_get_b32(sx, &px); /* Invoke hasher */ - ret = hashfp(output, sx, ell_a64, ell_b64, data); + ret = hashfp(ctx, output, sx, ell_a64, ell_b64, data); secp256k1_memclear_explicit(sx, sizeof(sx)); secp256k1_fe_clear(&px); diff --git a/src/modules/ellswift/tests_impl.h b/src/modules/ellswift/tests_impl.h index 63c36e7ff1..4a34357497 100644 --- a/src/modules/ellswift/tests_impl.h +++ b/src/modules/ellswift/tests_impl.h @@ -169,7 +169,8 @@ static const struct ellswift_xdh_test ellswift_xdh_tests_bip324[] = { * exchanged public keys do not affect the shared secret. However, it's used here * in tests to be able to verify the X coordinate through other means. */ -static int ellswift_xdh_hash_x32(unsigned char *output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { +static int ellswift_xdh_hash_x32(const secp256k1_context *ctx, unsigned char *output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { + (void)ctx; (void)ell_a64; (void)ell_b64; (void)data; @@ -407,6 +408,7 @@ void run_ellswift_tests(void) { /* Test hash initializers. */ { secp256k1_sha256 sha_optimized; + const secp256k1_context *ctx = secp256k1_context_static; /* "secp256k1_ellswift_encode" */ static const unsigned char encode_tag[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'e', 'n', 'c', 'o', 'd', 'e'}; /* "secp256k1_ellswift_create" */ @@ -417,20 +419,20 @@ void run_ellswift_tests(void) { /* Check that hash initialized by * secp256k1_ellswift_sha256_init_encode has the expected * state. */ - secp256k1_ellswift_sha256_init_encode(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, encode_tag, sizeof(encode_tag)); + secp256k1_ellswift_sha256_init_encode(ctx, &sha_optimized); + test_sha256_tag_midstate(ctx, &sha_optimized, encode_tag, sizeof(encode_tag)); /* Check that hash initialized by * secp256k1_ellswift_sha256_init_create has the expected * state. */ - secp256k1_ellswift_sha256_init_create(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, create_tag, sizeof(create_tag)); + secp256k1_ellswift_sha256_init_create(ctx, &sha_optimized); + test_sha256_tag_midstate(ctx, &sha_optimized, create_tag, sizeof(create_tag)); /* Check that hash initialized by * secp256k1_ellswift_sha256_init_bip324 has the expected * state. */ - secp256k1_ellswift_sha256_init_bip324(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, bip324_tag, sizeof(bip324_tag)); + secp256k1_ellswift_sha256_init_bip324(ctx, &sha_optimized); + test_sha256_tag_midstate(ctx, &sha_optimized, bip324_tag, sizeof(bip324_tag)); } } diff --git a/src/modules/musig/keyagg.h b/src/modules/musig/keyagg.h index a0b37252f8..8973d16d3a 100644 --- a/src/modules/musig/keyagg.h +++ b/src/modules/musig/keyagg.h @@ -27,6 +27,6 @@ typedef struct { static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_keyagg_cache_internal *cache_i, const secp256k1_musig_keyagg_cache *cache); -static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk); +static void secp256k1_musig_keyaggcoef(const secp256k1_context *ctx, secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk); #endif diff --git a/src/modules/musig/keyagg_impl.h b/src/modules/musig/keyagg_impl.h index 87869a4105..6003db51aa 100644 --- a/src/modules/musig/keyagg_impl.h +++ b/src/modules/musig/keyagg_impl.h @@ -61,8 +61,8 @@ static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_k /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("KeyAgg list")||SHA256("KeyAgg list"). */ -static void secp256k1_musig_keyagglist_sha256(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); +static void secp256k1_musig_keyagglist_sha256(const secp256k1_context *ctx, secp256k1_sha256 *sha) { + secp256k1_sha256_initialize(sha, ctx->hash_context.fn_sha256_transform); sha->s[0] = 0xb399d5e0ul; sha->s[1] = 0xc8fff302ul; @@ -80,7 +80,7 @@ static int secp256k1_musig_compute_pks_hash(const secp256k1_context *ctx, unsign secp256k1_sha256 sha; size_t i; - secp256k1_musig_keyagglist_sha256(&sha); + secp256k1_musig_keyagglist_sha256(ctx, &sha); for (i = 0; i < np; i++) { unsigned char ser[33]; size_t ser_len = sizeof(ser); @@ -96,8 +96,8 @@ static int secp256k1_musig_compute_pks_hash(const secp256k1_context *ctx, unsign /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("KeyAgg coefficient")||SHA256("KeyAgg coefficient"). */ -static void secp256k1_musig_keyaggcoef_sha256(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); +static void secp256k1_musig_keyaggcoef_sha256(const secp256k1_context *ctx, secp256k1_sha256 *sha) { + secp256k1_sha256_initialize(sha, ctx->hash_context.fn_sha256_transform); sha->s[0] = 0x6ef02c5aul; sha->s[1] = 0x06a480deul; @@ -115,7 +115,7 @@ static void secp256k1_musig_keyaggcoef_sha256(secp256k1_sha256 *sha) { * second_pk is the point at infinity in case there is no second_pk. Assumes * that pk is not the point at infinity and that the Y-coordinates of pk and * second_pk are normalized. */ -static void secp256k1_musig_keyaggcoef_internal(secp256k1_scalar *r, const unsigned char *pks_hash, secp256k1_ge *pk, const secp256k1_ge *second_pk) { +static void secp256k1_musig_keyaggcoef_internal(const secp256k1_context *ctx, secp256k1_scalar *r, const unsigned char *pks_hash, secp256k1_ge *pk, const secp256k1_ge *second_pk) { VERIFY_CHECK(!secp256k1_ge_is_infinity(pk)); if (!secp256k1_ge_is_infinity(second_pk) @@ -124,7 +124,7 @@ static void secp256k1_musig_keyaggcoef_internal(secp256k1_scalar *r, const unsig } else { secp256k1_sha256 sha; unsigned char buf[33]; - secp256k1_musig_keyaggcoef_sha256(&sha); + secp256k1_musig_keyaggcoef_sha256(ctx, &sha); secp256k1_sha256_write(&sha, pks_hash, 32); /* Serialization does not fail since the pk is not the point at infinity * (according to this function's precondition). */ @@ -137,8 +137,8 @@ static void secp256k1_musig_keyaggcoef_internal(secp256k1_scalar *r, const unsig /* Assumes that pk is not the point at infinity and that the Y-coordinates of pk * and cache_i->second_pk are normalized. */ -static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk) { - secp256k1_musig_keyaggcoef_internal(r, cache_i->pks_hash, pk, &cache_i->second_pk); +static void secp256k1_musig_keyaggcoef(const secp256k1_context *ctx, secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk) { + secp256k1_musig_keyaggcoef_internal(ctx, r, cache_i->pks_hash, pk, &cache_i->second_pk); } typedef struct { @@ -161,7 +161,7 @@ static int secp256k1_musig_pubkey_agg_callback(secp256k1_scalar *sc, secp256k1_g #else (void) ret; #endif - secp256k1_musig_keyaggcoef_internal(sc, ctx->pks_hash, pt, &ctx->second_pk); + secp256k1_musig_keyaggcoef_internal(ctx->ctx, sc, ctx->pks_hash, pt, &ctx->second_pk); return 1; } diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index 6a80a27b38..ad6b124d3e 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -307,8 +307,8 @@ static void secp256k1_nonce_function_musig_helper(secp256k1_sha256 *sha, unsigne /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("MuSig/aux")||SHA256("MuSig/aux"). */ -static void secp256k1_nonce_function_musig_sha256_tagged_aux(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); +static void secp256k1_nonce_function_musig_sha256_tagged_aux(const secp256k1_context *ctx, secp256k1_sha256 *sha) { + secp256k1_sha256_initialize(sha, ctx->hash_context.fn_sha256_transform); sha->s[0] = 0xa19e884bul; sha->s[1] = 0xf463fe7eul; sha->s[2] = 0x2f18f9a2ul; @@ -322,8 +322,8 @@ static void secp256k1_nonce_function_musig_sha256_tagged_aux(secp256k1_sha256 *s /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("MuSig/nonce")||SHA256("MuSig/nonce"). */ -static void secp256k1_nonce_function_musig_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); +static void secp256k1_nonce_function_musig_sha256_tagged(const secp256k1_context *ctx, secp256k1_sha256 *sha) { + secp256k1_sha256_initialize(sha, ctx->hash_context.fn_sha256_transform); sha->s[0] = 0x07101b64ul; sha->s[1] = 0x18003414ul; sha->s[2] = 0x0391bc43ul; @@ -335,14 +335,14 @@ static void secp256k1_nonce_function_musig_sha256_tagged(secp256k1_sha256 *sha) sha->bytes = 64; } -static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned char *session_secrand, const unsigned char *msg32, const unsigned char *seckey32, const unsigned char *pk33, const unsigned char *agg_pk32, const unsigned char *extra_input32) { +static void secp256k1_nonce_function_musig(const secp256k1_context *ctx, secp256k1_scalar *k, const unsigned char *session_secrand, const unsigned char *msg32, const unsigned char *seckey32, const unsigned char *pk33, const unsigned char *agg_pk32, const unsigned char *extra_input32) { secp256k1_sha256 sha; unsigned char rand[32]; unsigned char i; unsigned char msg_present; if (seckey32 != NULL) { - secp256k1_nonce_function_musig_sha256_tagged_aux(&sha); + secp256k1_nonce_function_musig_sha256_tagged_aux(ctx, &sha); secp256k1_sha256_write(&sha, session_secrand, 32); secp256k1_sha256_finalize(&sha, rand); for (i = 0; i < 32; i++) { @@ -352,7 +352,7 @@ static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned c memcpy(rand, session_secrand, sizeof(rand)); } - secp256k1_nonce_function_musig_sha256_tagged(&sha); + secp256k1_nonce_function_musig_sha256_tagged(ctx, &sha); secp256k1_sha256_write(&sha, rand, sizeof(rand)); secp256k1_nonce_function_musig_helper(&sha, 1, pk33, 33); secp256k1_nonce_function_musig_helper(&sha, 1, agg_pk32, 32); @@ -416,7 +416,7 @@ static int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp /* A pubkey cannot be the point at infinity */ secp256k1_eckey_pubkey_serialize33(&pk, pk_ser); - secp256k1_nonce_function_musig(k, input_nonce, msg32, seckey, pk_ser, aggpk_ser_ptr, extra_input32); + secp256k1_nonce_function_musig(ctx, k, input_nonce, msg32, seckey, pk_ser, aggpk_ser_ptr, extra_input32); VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[0])); VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[1])); secp256k1_musig_secnonce_save(secnonce, k, &pk); @@ -536,8 +536,8 @@ int secp256k1_musig_nonce_agg(const secp256k1_context* ctx, secp256k1_musig_aggn /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("MuSig/noncecoef")||SHA256("MuSig/noncecoef"). */ -static void secp256k1_musig_compute_noncehash_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); +static void secp256k1_musig_compute_noncehash_sha256_tagged(const secp256k1_context *ctx, secp256k1_sha256 *sha) { + secp256k1_sha256_initialize(sha, ctx->hash_context.fn_sha256_transform); sha->s[0] = 0x2c7d5a45ul; sha->s[1] = 0x06bf7e53ul; sha->s[2] = 0x89be68a6ul; @@ -550,12 +550,12 @@ static void secp256k1_musig_compute_noncehash_sha256_tagged(secp256k1_sha256 *sh } /* tagged_hash(aggnonce[0], aggnonce[1], agg_pk, msg) */ -static void secp256k1_musig_compute_noncehash(unsigned char *noncehash, secp256k1_ge *aggnonce, const unsigned char *agg_pk32, const unsigned char *msg) { +static void secp256k1_musig_compute_noncehash(const secp256k1_context *ctx, unsigned char *noncehash, secp256k1_ge *aggnonce, const unsigned char *agg_pk32, const unsigned char *msg) { unsigned char buf[33]; secp256k1_sha256 sha; int i; - secp256k1_musig_compute_noncehash_sha256_tagged(&sha); + secp256k1_musig_compute_noncehash_sha256_tagged(ctx, &sha); for (i = 0; i < 2; i++) { secp256k1_musig_ge_serialize_ext(buf, &aggnonce[i]); secp256k1_sha256_write(&sha, buf, sizeof(buf)); @@ -574,12 +574,12 @@ static void secp256k1_effective_nonce(secp256k1_gej *out_nonce, const secp256k1_ secp256k1_gej_add_ge_var(out_nonce, out_nonce, &nonce_pts[0], NULL); } -static void secp256k1_musig_nonce_process_internal(int *fin_nonce_parity, unsigned char *fin_nonce, secp256k1_scalar *b, secp256k1_ge *aggnonce_pts, const unsigned char *agg_pk32, const unsigned char *msg) { +static void secp256k1_musig_nonce_process_internal(const secp256k1_context *ctx, int *fin_nonce_parity, unsigned char *fin_nonce, secp256k1_scalar *b, secp256k1_ge *aggnonce_pts, const unsigned char *agg_pk32, const unsigned char *msg) { unsigned char noncehash[32]; secp256k1_ge fin_nonce_pt; secp256k1_gej fin_nonce_ptj; - secp256k1_musig_compute_noncehash(noncehash, aggnonce_pts, agg_pk32, msg); + secp256k1_musig_compute_noncehash(ctx, noncehash, aggnonce_pts, agg_pk32, msg); secp256k1_scalar_set_b32(b, noncehash, NULL); /* fin_nonce = aggnonce_pts[0] + b*aggnonce_pts[1] */ secp256k1_effective_nonce(&fin_nonce_ptj, aggnonce_pts, b); @@ -616,8 +616,8 @@ int secp256k1_musig_nonce_process(const secp256k1_context* ctx, secp256k1_musig_ return 0; } - secp256k1_musig_nonce_process_internal(&session_i.fin_nonce_parity, fin_nonce, &session_i.noncecoef, aggnonce_pts, agg_pk32, msg32); - secp256k1_schnorrsig_challenge(&session_i.challenge, fin_nonce, msg32, 32, agg_pk32); + secp256k1_musig_nonce_process_internal(ctx, &session_i.fin_nonce_parity, fin_nonce, &session_i.noncecoef, aggnonce_pts, agg_pk32, msg32); + secp256k1_schnorrsig_challenge(ctx, &session_i.challenge, fin_nonce, msg32, 32, agg_pk32); /* If there is a tweak then set `challenge` times `tweak` to the `s`-part.*/ secp256k1_scalar_set_int(&session_i.s_part, 0); @@ -687,7 +687,7 @@ int secp256k1_musig_partial_sign(const secp256k1_context* ctx, secp256k1_musig_p } /* Multiply KeyAgg coefficient */ - secp256k1_musig_keyaggcoef(&mu, &cache_i, &pk); + secp256k1_musig_keyaggcoef(ctx, &mu, &cache_i, &pk); secp256k1_scalar_mul(&sk, &sk, &mu); if (!secp256k1_musig_session_load(ctx, &session_i, session)) { @@ -747,7 +747,7 @@ int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp2 /* Multiplying the challenge by the KeyAgg coefficient is equivalent * to multiplying the signer's public key by the coefficient, except * much easier to do. */ - secp256k1_musig_keyaggcoef(&mu, &cache_i, &pkp); + secp256k1_musig_keyaggcoef(ctx, &mu, &cache_i, &pkp); secp256k1_scalar_mul(&e, &session_i.challenge, &mu); /* Negate e if secp256k1_fe_is_odd(&cache_i.pk.y)) XOR cache_i.parity_acc. diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h index b4ba185494..d1a1a1c9db 100644 --- a/src/modules/musig/tests_impl.h +++ b/src/modules/musig/tests_impl.h @@ -484,12 +484,12 @@ static void musig_api_tests(void) { CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 2) == 1); } -static void musig_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) { +static void musig_nonce_bitflip(const secp256k1_context *ctx, unsigned char **args, size_t n_flip, size_t n_bytes) { secp256k1_scalar k1[2], k2[2]; - secp256k1_nonce_function_musig(k1, args[0], args[1], args[2], args[3], args[4], args[5]); + secp256k1_nonce_function_musig(ctx, k1, args[0], args[1], args[2], args[3], args[4], args[5]); testrand_flip(args[n_flip], n_bytes); - secp256k1_nonce_function_musig(k2, args[0], args[1], args[2], args[3], args[4], args[5]); + secp256k1_nonce_function_musig(ctx, k2, args[0], args[1], args[2], args[3], args[4], args[5]); CHECK(secp256k1_scalar_eq(&k1[0], &k2[0]) == 0); CHECK(secp256k1_scalar_eq(&k1[1], &k2[1]) == 0); } @@ -505,6 +505,7 @@ static void musig_nonce_test(void) { int i, j; secp256k1_scalar k[6][2]; + const secp256k1_context *ctx = secp256k1_context_static; testrand_bytes_test(session_secrand, sizeof(session_secrand)); testrand_bytes_test(sk, sizeof(sk)); testrand_bytes_test(pk, sizeof(pk)); @@ -520,12 +521,12 @@ static void musig_nonce_test(void) { args[4] = agg_pk; args[5] = extra_input; for (i = 0; i < COUNT; i++) { - musig_nonce_bitflip(args, 0, sizeof(session_secrand)); - musig_nonce_bitflip(args, 1, sizeof(msg)); - musig_nonce_bitflip(args, 2, sizeof(sk)); - musig_nonce_bitflip(args, 3, sizeof(pk)); - musig_nonce_bitflip(args, 4, sizeof(agg_pk)); - musig_nonce_bitflip(args, 5, sizeof(extra_input)); + musig_nonce_bitflip(ctx, args, 0, sizeof(session_secrand)); + musig_nonce_bitflip(ctx, args, 1, sizeof(msg)); + musig_nonce_bitflip(ctx, args, 2, sizeof(sk)); + musig_nonce_bitflip(ctx, args, 3, sizeof(pk)); + musig_nonce_bitflip(ctx, args, 4, sizeof(agg_pk)); + musig_nonce_bitflip(ctx, args, 5, sizeof(extra_input)); } /* Check that if any argument is NULL, a different nonce is produced than if * any other argument is NULL. */ @@ -534,12 +535,12 @@ static void musig_nonce_test(void) { memcpy(pk, session_secrand, sizeof(session_secrand)); memcpy(agg_pk, session_secrand, sizeof(agg_pk)); memcpy(extra_input, session_secrand, sizeof(extra_input)); - secp256k1_nonce_function_musig(k[0], args[0], args[1], args[2], args[3], args[4], args[5]); - secp256k1_nonce_function_musig(k[1], args[0], NULL, args[2], args[3], args[4], args[5]); - secp256k1_nonce_function_musig(k[2], args[0], args[1], NULL, args[3], args[4], args[5]); - secp256k1_nonce_function_musig(k[3], args[0], args[1], args[2], NULL, args[4], args[5]); - secp256k1_nonce_function_musig(k[4], args[0], args[1], args[2], args[3], NULL, args[5]); - secp256k1_nonce_function_musig(k[5], args[0], args[1], args[2], args[3], args[4], NULL); + secp256k1_nonce_function_musig(ctx, k[0], args[0], args[1], args[2], args[3], args[4], args[5]); + secp256k1_nonce_function_musig(ctx, k[1], args[0], NULL, args[2], args[3], args[4], args[5]); + secp256k1_nonce_function_musig(ctx, k[2], args[0], args[1], NULL, args[3], args[4], args[5]); + secp256k1_nonce_function_musig(ctx, k[3], args[0], args[1], args[2], NULL, args[4], args[5]); + secp256k1_nonce_function_musig(ctx, k[4], args[0], args[1], args[2], args[3], NULL, args[5]); + secp256k1_nonce_function_musig(ctx, k[5], args[0], args[1], args[2], args[3], args[4], NULL); for (i = 0; i < 6; i++) { CHECK(!secp256k1_scalar_eq(&k[i][0], &k[i][1])); for (j = i+1; j < 6; j++) { @@ -553,35 +554,36 @@ static void musig_nonce_test(void) { * state. */ static void sha256_tag_test(void) { secp256k1_sha256 sha; + const secp256k1_context *ctx = secp256k1_context_static; { /* "KeyAgg list" */ static const unsigned char tag[] = {'K', 'e', 'y', 'A', 'g', 'g', ' ', 'l', 'i', 's', 't'}; - secp256k1_musig_keyagglist_sha256(&sha); - test_sha256_tag_midstate(&sha, tag, sizeof(tag)); + secp256k1_musig_keyagglist_sha256(ctx, &sha); + test_sha256_tag_midstate(ctx, &sha, tag, sizeof(tag)); } { /* "KeyAgg coefficient" */ static const unsigned char tag[] = {'K', 'e', 'y', 'A', 'g', 'g', ' ', 'c', 'o', 'e', 'f', 'f', 'i', 'c', 'i', 'e', 'n', 't'}; - secp256k1_musig_keyaggcoef_sha256(&sha); - test_sha256_tag_midstate(&sha, tag, sizeof(tag)); + secp256k1_musig_keyaggcoef_sha256(ctx, &sha); + test_sha256_tag_midstate(ctx, &sha, tag, sizeof(tag)); } { /* "MuSig/aux" */ static const unsigned char tag[] = { 'M', 'u', 'S', 'i', 'g', '/', 'a', 'u', 'x' }; - secp256k1_nonce_function_musig_sha256_tagged_aux(&sha); - test_sha256_tag_midstate(&sha, tag, sizeof(tag)); + secp256k1_nonce_function_musig_sha256_tagged_aux(ctx, &sha); + test_sha256_tag_midstate(ctx, &sha, tag, sizeof(tag)); } { /* "MuSig/nonce" */ static const unsigned char tag[] = { 'M', 'u', 'S', 'i', 'g', '/', 'n', 'o', 'n', 'c', 'e' }; - secp256k1_nonce_function_musig_sha256_tagged(&sha); - test_sha256_tag_midstate(&sha, tag, sizeof(tag)); + secp256k1_nonce_function_musig_sha256_tagged(ctx, &sha); + test_sha256_tag_midstate(ctx, &sha, tag, sizeof(tag)); } { /* "MuSig/noncecoef" */ static const unsigned char tag[] = { 'M', 'u', 'S', 'i', 'g', '/', 'n', 'o', 'n', 'c', 'e', 'c', 'o', 'e', 'f' }; - secp256k1_musig_compute_noncehash_sha256_tagged(&sha); - test_sha256_tag_midstate(&sha, tag, sizeof(tag)); + secp256k1_musig_compute_noncehash_sha256_tagged(ctx, &sha); + test_sha256_tag_midstate(ctx, &sha, tag, sizeof(tag)); } } diff --git a/src/modules/recovery/tests_impl.h b/src/modules/recovery/tests_impl.h index 09554a242e..b235bbee7b 100644 --- a/src/modules/recovery/tests_impl.h +++ b/src/modules/recovery/tests_impl.h @@ -9,7 +9,8 @@ #include "../../unit_test.h" -static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { +static int recovery_test_nonce_function(const secp256k1_context *ctx, unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { + (void) ctx; (void) msg32; (void) key32; (void) algo16; diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index b410b19eca..1ddd87bb30 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -13,8 +13,8 @@ /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/nonce")||SHA256("BIP0340/nonce"). */ -static void secp256k1_nonce_function_bip340_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); +static void secp256k1_nonce_function_bip340_sha256_tagged(const secp256k1_context *ctx, secp256k1_sha256 *sha) { + secp256k1_sha256_initialize(sha, ctx->hash_context.fn_sha256_transform); sha->s[0] = 0x46615b35ul; sha->s[1] = 0xf4bfbff7ul; sha->s[2] = 0x9f8dc671ul; @@ -29,8 +29,8 @@ static void secp256k1_nonce_function_bip340_sha256_tagged(secp256k1_sha256 *sha) /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/aux")||SHA256("BIP0340/aux"). */ -static void secp256k1_nonce_function_bip340_sha256_tagged_aux(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); +static void secp256k1_nonce_function_bip340_sha256_tagged_aux(const secp256k1_context *ctx, secp256k1_sha256 *sha) { + secp256k1_sha256_initialize(sha, ctx->hash_context.fn_sha256_transform); sha->s[0] = 0x24dd3219ul; sha->s[1] = 0x4eba7e70ul; sha->s[2] = 0xca0fabb9ul; @@ -49,7 +49,7 @@ static const unsigned char bip340_algo[] = {'B', 'I', 'P', '0', '3', '4', '0', ' static const unsigned char schnorrsig_extraparams_magic[4] = SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC; -static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) { +static int nonce_function_bip340(const secp256k1_context *ctx, unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) { secp256k1_sha256 sha; unsigned char masked_key[32]; int i; @@ -59,7 +59,7 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms } if (data != NULL) { - secp256k1_nonce_function_bip340_sha256_tagged_aux(&sha); + secp256k1_nonce_function_bip340_sha256_tagged_aux(ctx, &sha); secp256k1_sha256_write(&sha, data, 32); secp256k1_sha256_finalize(&sha, masked_key); for (i = 0; i < 32; i++) { @@ -83,9 +83,9 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms * in the spec, an optimized tagging implementation is used. */ if (algolen == sizeof(bip340_algo) && secp256k1_memcmp_var(algo, bip340_algo, algolen) == 0) { - secp256k1_nonce_function_bip340_sha256_tagged(&sha); + secp256k1_nonce_function_bip340_sha256_tagged(ctx, &sha); } else { - secp256k1_sha256_initialize_tagged(&sha, algo, algolen); + secp256k1_sha256_initialize_tagged(&sha, algo, algolen, ctx->hash_context.fn_sha256_transform); } /* Hash masked-key||pk||msg using the tagged hash as per the spec */ @@ -103,8 +103,8 @@ const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340 = nonce_ /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/challenge")||SHA256("BIP0340/challenge"). */ -static void secp256k1_schnorrsig_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); +static void secp256k1_schnorrsig_sha256_tagged(const secp256k1_context *ctx, secp256k1_sha256 *sha) { + secp256k1_sha256_initialize(sha, ctx->hash_context.fn_sha256_transform); sha->s[0] = 0x9cecba11ul; sha->s[1] = 0x23925381ul; sha->s[2] = 0x11679112ul; @@ -116,13 +116,13 @@ static void secp256k1_schnorrsig_sha256_tagged(secp256k1_sha256 *sha) { sha->bytes = 64; } -static void secp256k1_schnorrsig_challenge(secp256k1_scalar* e, const unsigned char *r32, const unsigned char *msg, size_t msglen, const unsigned char *pubkey32) +static void secp256k1_schnorrsig_challenge(const secp256k1_context *ctx, secp256k1_scalar* e, const unsigned char *r32, const unsigned char *msg, size_t msglen, const unsigned char *pubkey32) { unsigned char buf[32]; secp256k1_sha256 sha; /* tagged hash(r.x, pk.x, msg) */ - secp256k1_schnorrsig_sha256_tagged(&sha); + secp256k1_schnorrsig_sha256_tagged(ctx, &sha); secp256k1_sha256_write(&sha, r32, 32); secp256k1_sha256_write(&sha, pubkey32, 32); secp256k1_sha256_write(&sha, msg, msglen); @@ -164,7 +164,7 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi secp256k1_scalar_get_b32(seckey, &sk); secp256k1_fe_get_b32(pk_buf, &pk.x); - ret &= !!noncefp(nonce32, msg, msglen, seckey, pk_buf, bip340_algo, sizeof(bip340_algo), ndata); + ret &= !!noncefp(ctx, nonce32, msg, msglen, seckey, pk_buf, bip340_algo, sizeof(bip340_algo), ndata); secp256k1_scalar_set_b32(&k, nonce32, NULL); ret &= !secp256k1_scalar_is_zero(&k); secp256k1_scalar_cmov(&k, &secp256k1_scalar_one, !ret); @@ -182,7 +182,7 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi secp256k1_fe_normalize_var(&r.x); secp256k1_fe_get_b32(&sig64[0], &r.x); - secp256k1_schnorrsig_challenge(&e, &sig64[0], msg, msglen, pk_buf); + secp256k1_schnorrsig_challenge(ctx, &e, &sig64[0], msg, msglen, pk_buf); secp256k1_scalar_mul(&e, &e, &sk); secp256k1_scalar_add(&e, &e, &k); secp256k1_scalar_get_b32(&sig64[32], &e); @@ -252,7 +252,7 @@ int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned cha /* Compute e. */ secp256k1_fe_get_b32(buf, &pk.x); - secp256k1_schnorrsig_challenge(&e, &sig64[0], msg, msglen, buf); + secp256k1_schnorrsig_challenge(ctx, &e, &sig64[0], msg, msglen, buf); /* Compute rj = s*G + (-e)*pkj */ secp256k1_scalar_negate(&e, &e); diff --git a/src/modules/schnorrsig/tests_exhaustive_impl.h b/src/modules/schnorrsig/tests_exhaustive_impl.h index 601b54975d..df85d1dc7d 100644 --- a/src/modules/schnorrsig/tests_exhaustive_impl.h +++ b/src/modules/schnorrsig/tests_exhaustive_impl.h @@ -58,13 +58,14 @@ static const unsigned char invalid_pubkey_bytes[][32] = { #define NUM_INVALID_KEYS (sizeof(invalid_pubkey_bytes) / sizeof(invalid_pubkey_bytes[0])) -static int secp256k1_hardened_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg, - size_t msglen, +static int secp256k1_hardened_nonce_function_smallint(const secp256k1_context* ctx, unsigned char *nonce32, + const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void* data) { secp256k1_scalar s; int *idata = data; + (void)ctx; (void)msg; (void)msglen; (void)key32; @@ -105,7 +106,7 @@ static void test_exhaustive_schnorrsig_verify(const secp256k1_context *ctx, cons secp256k1_scalar e; unsigned char msg32[32]; testrand256(msg32); - secp256k1_schnorrsig_challenge(&e, sig64, msg32, sizeof(msg32), pk32); + secp256k1_schnorrsig_challenge(ctx, &e, sig64, msg32, sizeof(msg32), pk32); /* Only do work if we hit a challenge we haven't tried before. */ if (!e_done[e]) { /* Iterate over the possible valid last 32 bytes in the signature. @@ -162,7 +163,7 @@ static void test_exhaustive_schnorrsig_sign(const secp256k1_context *ctx, unsign while (e_count_done < EXHAUSTIVE_TEST_ORDER) { secp256k1_scalar e; testrand256(msg32); - secp256k1_schnorrsig_challenge(&e, xonly_pubkey_bytes[k - 1], msg32, sizeof(msg32), xonly_pubkey_bytes[d - 1]); + secp256k1_schnorrsig_challenge(ctx, &e, xonly_pubkey_bytes[k - 1], msg32, sizeof(msg32), xonly_pubkey_bytes[d - 1]); /* Only do work if we hit a challenge we haven't tried before. */ if (!e_done[e]) { secp256k1_scalar expected_s = (actual_k + e * actual_d) % EXHAUSTIVE_TEST_ORDER; diff --git a/src/modules/schnorrsig/tests_impl.h b/src/modules/schnorrsig/tests_impl.h index 9a1b15f0b2..de2a0dcb3f 100644 --- a/src/modules/schnorrsig/tests_impl.h +++ b/src/modules/schnorrsig/tests_impl.h @@ -13,11 +13,11 @@ /* Checks that a bit flip in the n_flip-th argument (that has n_bytes many * bytes) changes the hash function */ -static void nonce_function_bip340_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes, size_t msglen, size_t algolen) { +static void nonce_function_bip340_bitflip(const secp256k1_context* ctx, unsigned char **args, size_t n_flip, size_t n_bytes, size_t msglen, size_t algolen) { unsigned char nonces[2][32]; - CHECK(nonce_function_bip340(nonces[0], args[0], msglen, args[1], args[2], args[3], algolen, args[4]) == 1); + CHECK(nonce_function_bip340(ctx, nonces[0], args[0], msglen, args[1], args[2], args[3], algolen, args[4]) == 1); testrand_flip(args[n_flip], n_bytes); - CHECK(nonce_function_bip340(nonces[1], args[0], msglen, args[1], args[2], args[3], algolen, args[4]) == 1); + CHECK(nonce_function_bip340(ctx, nonces[1], args[0], msglen, args[1], args[2], args[3], algolen, args[4]) == 1); CHECK(secp256k1_memcmp_var(nonces[0], nonces[1], 32) != 0); } @@ -38,18 +38,20 @@ static void run_nonce_function_bip340_tests(void) { unsigned char *args[5]; int i; + const secp256k1_context* ctx = secp256k1_context_static; + /* Check that hash initialized by * secp256k1_nonce_function_bip340_sha256_tagged has the expected * state. */ - secp256k1_nonce_function_bip340_sha256_tagged(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, tag, sizeof(tag)); + secp256k1_nonce_function_bip340_sha256_tagged(ctx, &sha_optimized); + test_sha256_tag_midstate(ctx, &sha_optimized, tag, sizeof(tag)); /* Check that hash initialized by * secp256k1_nonce_function_bip340_sha256_tagged_aux has the expected * state. */ - secp256k1_nonce_function_bip340_sha256_tagged_aux(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, aux_tag, sizeof(aux_tag)); + secp256k1_nonce_function_bip340_sha256_tagged_aux(ctx, &sha_optimized); + test_sha256_tag_midstate(ctx, &sha_optimized, aux_tag, sizeof(aux_tag)); testrand256(msg); testrand256(key); @@ -63,22 +65,22 @@ static void run_nonce_function_bip340_tests(void) { args[3] = algo; args[4] = aux_rand; for (i = 0; i < COUNT; i++) { - nonce_function_bip340_bitflip(args, 0, 32, msglen, algolen); - nonce_function_bip340_bitflip(args, 1, 32, msglen, algolen); - nonce_function_bip340_bitflip(args, 2, 32, msglen, algolen); + nonce_function_bip340_bitflip(ctx, args, 0, 32, msglen, algolen); + nonce_function_bip340_bitflip(ctx, args, 1, 32, msglen, algolen); + nonce_function_bip340_bitflip(ctx, args, 2, 32, msglen, algolen); /* Flip algo special case "BIP0340/nonce" */ - nonce_function_bip340_bitflip(args, 3, algolen, msglen, algolen); + nonce_function_bip340_bitflip(ctx, args, 3, algolen, msglen, algolen); /* Flip algo again */ - nonce_function_bip340_bitflip(args, 3, algolen, msglen, algolen); - nonce_function_bip340_bitflip(args, 4, 32, msglen, algolen); + nonce_function_bip340_bitflip(ctx, args, 3, algolen, msglen, algolen); + nonce_function_bip340_bitflip(ctx, args, 4, 32, msglen, algolen); } /* NULL algo is disallowed */ - CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, NULL, 0, NULL) == 0); - CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1); + CHECK(nonce_function_bip340(ctx, nonce, msg, msglen, key, pk, NULL, 0, NULL) == 0); + CHECK(nonce_function_bip340(ctx, nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1); /* Other algo is fine */ testrand_bytes_test(algo, algolen); - CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1); + CHECK(nonce_function_bip340(ctx, nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1); for (i = 0; i < COUNT; i++) { unsigned char nonce2[32]; @@ -87,20 +89,20 @@ static void run_nonce_function_bip340_tests(void) { size_t algolen_tmp; /* Different msglen gives different nonce */ - CHECK(nonce_function_bip340(nonce2, msg, msglen_tmp, key, pk, algo, algolen, NULL) == 1); + CHECK(nonce_function_bip340(ctx, nonce2, msg, msglen_tmp, key, pk, algo, algolen, NULL) == 1); CHECK(secp256k1_memcmp_var(nonce, nonce2, 32) != 0); /* Different algolen gives different nonce */ offset = testrand_int(algolen - 1); algolen_tmp = (algolen + offset) % algolen; - CHECK(nonce_function_bip340(nonce2, msg, msglen, key, pk, algo, algolen_tmp, NULL) == 1); + CHECK(nonce_function_bip340(ctx, nonce2, msg, msglen, key, pk, algo, algolen_tmp, NULL) == 1); CHECK(secp256k1_memcmp_var(nonce, nonce2, 32) != 0); } /* NULL aux_rand argument is allowed, and identical to passing all zero aux_rand. */ memset(aux_rand, 0, 32); - CHECK(nonce_function_bip340(nonce_z, msg, msglen, key, pk, algo, algolen, &aux_rand) == 1); - CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1); + CHECK(nonce_function_bip340(ctx, nonce_z, msg, msglen, key, pk, algo, algolen, &aux_rand) == 1); + CHECK(nonce_function_bip340(ctx, nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1); CHECK(secp256k1_memcmp_var(nonce_z, nonce, 32) == 0); } @@ -162,9 +164,10 @@ static void test_schnorrsig_sha256_tagged(void) { unsigned char tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'c', 'h', 'a', 'l', 'l', 'e', 'n', 'g', 'e'}; secp256k1_sha256 sha; secp256k1_sha256 sha_optimized; + const secp256k1_context *ctx = secp256k1_context_static; - secp256k1_sha256_initialize_tagged(&sha, (unsigned char *) tag, sizeof(tag)); - secp256k1_schnorrsig_sha256_tagged(&sha_optimized); + secp256k1_sha256_initialize_tagged(&sha, (unsigned char *) tag, sizeof(tag), ctx->hash_context.fn_sha256_transform); + secp256k1_schnorrsig_sha256_tagged(ctx, &sha_optimized); test_sha256_eq(&sha, &sha_optimized); } @@ -763,7 +766,8 @@ static void test_schnorrsig_bip_vectors(void) { } /* Nonce function that returns constant 0 */ -static int nonce_function_failing(unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) { +static int nonce_function_failing(const secp256k1_context* ctx, unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) { + (void) ctx; (void) msg; (void) msglen; (void) key32; @@ -776,7 +780,8 @@ static int nonce_function_failing(unsigned char *nonce32, const unsigned char *m } /* Nonce function that sets nonce to 0 */ -static int nonce_function_0(unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) { +static int nonce_function_0(const secp256k1_context* ctx, unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) { + (void) ctx; (void) msg; (void) msglen; (void) key32; @@ -790,7 +795,8 @@ static int nonce_function_0(unsigned char *nonce32, const unsigned char *msg, si } /* Nonce function that sets nonce to 0xFF...0xFF */ -static int nonce_function_overflowing(unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) { +static int nonce_function_overflowing(const secp256k1_context *ctx, unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) { + (void) ctx; (void) msg; (void) msglen; (void) key32; diff --git a/src/secp256k1.c b/src/secp256k1.c index ec5937cfe4..5de0a19111 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -19,6 +19,7 @@ #include "../include/secp256k1.h" #include "../include/secp256k1_preallocated.h" +#include "../include/secp256k1_sha.h" #include "assumptions.h" #include "checkmem.h" @@ -56,6 +57,10 @@ } \ } while(0) +struct secp256k1_hash_context { + sha256_transform_callback fn_sha256_transform; +}; + /* Note that whenever you change the context struct, you must also change the * context_eq function. */ struct secp256k1_context_struct { @@ -63,13 +68,16 @@ struct secp256k1_context_struct { secp256k1_callback illegal_callback; secp256k1_callback error_callback; int declassify; + + struct secp256k1_hash_context hash_context; }; static const secp256k1_context secp256k1_context_static_ = { { 0 }, { secp256k1_default_illegal_callback_fn, 0 }, { secp256k1_default_error_callback_fn, 0 }, - 0 + 0, + { 0 } }; const secp256k1_context * const secp256k1_context_static = &secp256k1_context_static_; const secp256k1_context * const secp256k1_context_no_precomp = &secp256k1_context_static_; @@ -129,6 +137,7 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne ret = (secp256k1_context*)prealloc; ret->illegal_callback = default_illegal_callback; ret->error_callback = default_error_callback; + ret->hash_context.fn_sha256_transform = secp256k1_sha256_transform; /* Flags have been checked by secp256k1_context_preallocated_size. */ VERIFY_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_CONTEXT); @@ -220,6 +229,18 @@ void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(co ctx->error_callback.data = data; } +void secp256k1_context_set_sha256_transform_callback(secp256k1_context *ctx, void (*sha256_transform_callback_)(uint32_t *state, const unsigned char *block, size_t rounds)) { + VERIFY_CHECK(ctx != NULL); + if (!sha256_transform_callback_) { /* Reset function */ + ctx->hash_context.fn_sha256_transform = secp256k1_sha256_transform; + return; + } + /* Check and set */ + ARG_CHECK_VOID(secp256k1_selftest_sha256(sha256_transform_callback_)); + ARG_CHECK_VOID(secp256k1_sha256_check_transform(sha256_transform_callback_)); + ctx->hash_context.fn_sha256_transform = sha256_transform_callback_; +} + static secp256k1_scratch_space* secp256k1_scratch_space_create(const secp256k1_context* ctx, size_t max_size) { VERIFY_CHECK(ctx != NULL); return secp256k1_scratch_create(&ctx->error_callback, max_size); @@ -472,7 +493,7 @@ static SECP256K1_INLINE void buffer_append(unsigned char *buf, unsigned int *off *offset += len; } -static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { +static int nonce_function_rfc6979(const secp256k1_context *ctx, unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { unsigned char keydata[112]; unsigned int offset = 0; secp256k1_rfc6979_hmac_sha256 rng; @@ -497,9 +518,9 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m if (algo16 != NULL) { buffer_append(keydata, &offset, algo16, 16); } - secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, offset); + secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, offset, ctx->hash_context.fn_sha256_transform); for (i = 0; i <= counter; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32, ctx->hash_context.fn_sha256_transform); } secp256k1_rfc6979_hmac_sha256_finalize(&rng); @@ -533,7 +554,7 @@ static int secp256k1_ecdsa_sign_inner(const secp256k1_context* ctx, secp256k1_sc secp256k1_scalar_set_b32(&msg, msg32, NULL); while (1) { int is_nonce_valid; - ret = !!noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); + ret = !!noncefp(ctx, nonce32, msg32, seckey, NULL, (void*)noncedata, count); if (!ret) { break; } @@ -791,7 +812,7 @@ int secp256k1_tagged_sha256(const secp256k1_context* ctx, unsigned char *hash32, ARG_CHECK(tag != NULL); ARG_CHECK(msg != NULL); - secp256k1_sha256_initialize_tagged(&sha, tag, taglen); + secp256k1_sha256_initialize_tagged(&sha, tag, taglen, ctx->hash_context.fn_sha256_transform); secp256k1_sha256_write(&sha, msg, msglen); secp256k1_sha256_finalize(&sha, hash32); secp256k1_sha256_clear(&sha); diff --git a/src/selftest.h b/src/selftest.h index d083ac9524..09e872d39a 100644 --- a/src/selftest.h +++ b/src/selftest.h @@ -11,7 +11,7 @@ #include -static int secp256k1_selftest_sha256(void) { +static int secp256k1_selftest_sha256(sha256_transform_callback fn_transform) { static const char *input63 = "For this sample, this 63-byte string will be used as input data"; static const unsigned char output32[32] = { 0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, @@ -19,14 +19,15 @@ static int secp256k1_selftest_sha256(void) { }; unsigned char out[32]; secp256k1_sha256 hasher; - secp256k1_sha256_initialize(&hasher); + secp256k1_sha256_initialize(&hasher, fn_transform); secp256k1_sha256_write(&hasher, (const unsigned char*)input63, 63); secp256k1_sha256_finalize(&hasher, out); return secp256k1_memcmp_var(out, output32, 32) == 0; } static int secp256k1_selftest_passes(void) { - return secp256k1_selftest_sha256(); + /* Use default sha256 transform */ + return secp256k1_selftest_sha256(/*fn_transform=*/NULL); } #endif /* SECP256K1_SELFTEST_H */ diff --git a/src/testrand_impl.h b/src/testrand_impl.h index b84f5730a9..f969e6e730 100644 --- a/src/testrand_impl.h +++ b/src/testrand_impl.h @@ -22,9 +22,10 @@ SECP256K1_INLINE static void testrand_seed(const unsigned char *seed16) { unsigned char out32[32]; secp256k1_sha256 hash; int i; + const secp256k1_context *ctx = secp256k1_context_static; /* Use SHA256(PREFIX || seed16) as initial state. */ - secp256k1_sha256_initialize(&hash); + secp256k1_sha256_initialize(&hash, ctx->hash_context.fn_sha256_transform); secp256k1_sha256_write(&hash, PREFIX, sizeof(PREFIX)); secp256k1_sha256_write(&hash, seed16, 16); secp256k1_sha256_finalize(&hash, out32); diff --git a/src/tests.c b/src/tests.c index 4029de5651..2782a39c5b 100644 --- a/src/tests.c +++ b/src/tests.c @@ -432,6 +432,53 @@ static void run_scratch_tests(void) { secp256k1_scratch_space_destroy(CTX, NULL); /* no-op */ } +/* A compression function that does nothing */ +static void invalid_sha256_transform(uint32_t *s, const unsigned char *msg, size_t rounds) { + (void)s; (void)msg; (void)rounds; +} + +static int own_transform_called = 0; +static void good_sha256_transform(uint32_t *s, const unsigned char *msg, size_t rounds) { + own_transform_called = 1; + secp256k1_sha256_transform(s, msg, rounds); +} + +static void run_plug_sha256_transform_tests(void) { + secp256k1_context *ctx, *ctx_cloned; + secp256k1_sha256 sha; + unsigned char sha_out[32]; + /* 1) Verify the context is initialized with the default compression function */ + ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); + CHECK(ctx->hash_context.fn_sha256_transform == secp256k1_sha256_transform); + + /* 2) Verify providing a bad Transform fails during set */ + CHECK_ILLEGAL_VOID(ctx, secp256k1_context_set_sha256_transform_callback(ctx, invalid_sha256_transform)); + CHECK(ctx->hash_context.fn_sha256_transform == secp256k1_sha256_transform); + + /* 3) Provide sha256 to ctx and verify it is called when provided */ + own_transform_called = 0; + secp256k1_context_set_sha256_transform_callback(ctx, good_sha256_transform); + CHECK(own_transform_called); + + /* 4) Verify callback makes it across clone */ + ctx_cloned = secp256k1_context_clone(ctx); + CHECK(ctx_cloned->hash_context.fn_sha256_transform == good_sha256_transform); + + /* 5) A hash operation should invoke the installed callback */ + own_transform_called = 0; + secp256k1_sha256_initialize(&sha, ctx->hash_context.fn_sha256_transform); + secp256k1_sha256_write(&sha, (const unsigned char*)"a", 1); + secp256k1_sha256_finalize(&sha, sha_out); + CHECK(own_transform_called); + + /* 6) Unset sha256 and verify the default one is set again */ + secp256k1_context_set_sha256_transform_callback(ctx, NULL); + CHECK(ctx->hash_context.fn_sha256_transform == secp256k1_sha256_transform); + + secp256k1_context_destroy(ctx); + secp256k1_context_destroy(ctx_cloned); +} + static void run_ctz_tests(void) { static const uint32_t b32[] = {1, 0xffffffff, 0x5e56968f, 0xe0d63129}; static const uint64_t b64[] = {1, 0xffffffffffffffff, 0xbcd02462139b3fc3, 0x98b5f80c769693ef}; @@ -454,6 +501,7 @@ static void run_ctz_tests(void) { /***** HASH TESTS *****/ static void run_sha256_known_output_tests(void) { + const secp256k1_context *ctx = secp256k1_context_static; static const char *inputs[] = { "", "abc", "message digest", "secure hash algorithm", "SHA256 is considered to be safe", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", @@ -487,7 +535,7 @@ static void run_sha256_known_output_tests(void) { unsigned int j; /* 1. Run: simply write the input bytestrings */ j = repeat[i]; - secp256k1_sha256_initialize(&hasher); + secp256k1_sha256_initialize(&hasher, ctx->hash_context.fn_sha256_transform); while (j > 0) { secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); j--; @@ -497,7 +545,7 @@ static void run_sha256_known_output_tests(void) { /* 2. Run: split the input bytestrings randomly before writing */ if (strlen(inputs[i]) > 0) { int split = testrand_int(strlen(inputs[i])); - secp256k1_sha256_initialize(&hasher); + secp256k1_sha256_initialize(&hasher, ctx->hash_context.fn_sha256_transform); j = repeat[i]; while (j > 0) { secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); @@ -558,33 +606,33 @@ static void run_sha256_counter_tests(void) { static const char *input = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"; static const secp256k1_sha256 midstates[] = { {{0xa2b5c8bb, 0x26c88bb3, 0x2abdc3d2, 0x9def99a3, 0xdfd21a6e, 0x41fe585b, 0x7ef2c440, 0x2b79adda}, - {0x00}, 0xfffc0}, + {0x00}, 0xfffc0, NULL}, {{0xa0d29445, 0x9287de66, 0x76aabd71, 0x41acd765, 0x0c7528b4, 0x84e14906, 0x942faec6, 0xcc5a7b26}, - {0x00}, 0x1fffc0}, + {0x00}, 0x1fffc0, NULL}, {{0x50449526, 0xb9f1d657, 0xa0fc13e9, 0x50860f10, 0xa550c431, 0x3fbc97c1, 0x7bbb2d89, 0xdb67bac1}, - {0x00}, 0x3fffc0}, + {0x00}, 0x3fffc0, NULL}, {{0x54a6efdc, 0x46762e7b, 0x88bfe73f, 0xbbd149c7, 0x41620c43, 0x1168da7b, 0x2c5960f9, 0xeccffda6}, - {0x00}, 0x7fffc0}, + {0x00}, 0x7fffc0, NULL}, {{0x2515a8f5, 0x5faa2977, 0x3a850486, 0xac858cad, 0x7b7276ee, 0x235c0385, 0xc53a157c, 0x7cb3e69c}, - {0x00}, 0xffffc0}, + {0x00}, 0xffffc0, NULL}, {{0x34f39828, 0x409fedb7, 0x4bbdd0fb, 0x3b643634, 0x7806bf2e, 0xe0d1b713, 0xca3f2e1e, 0xe38722c2}, - {0x00}, 0x1ffffc0}, + {0x00}, 0x1ffffc0, NULL}, {{0x389ef5c5, 0x38c54167, 0x8f5d56ab, 0x582a75cc, 0x8217caef, 0xf10947dd, 0x6a1998a8, 0x048f0b8c}, - {0x00}, 0x3ffffc0}, + {0x00}, 0x3ffffc0, NULL}, {{0xd6c3f394, 0x0bee43b9, 0x6783f497, 0x29fa9e21, 0x6ce491c1, 0xa81fe45e, 0x2fc3859a, 0x269012d0}, - {0x00}, 0x7ffffc0}, + {0x00}, 0x7ffffc0, NULL}, {{0x6dd3c526, 0x44d88aa0, 0x806a1bae, 0xfbcc0d32, 0x9d6144f3, 0x9d2bd757, 0x9851a957, 0xb50430ad}, - {0x00}, 0xfffffc0}, + {0x00}, 0xfffffc0, NULL}, {{0x2add4021, 0xdfe8a9e6, 0xa56317c6, 0x7a15f5bb, 0x4a48aacd, 0x5d368414, 0x4f00e6f0, 0xd9355023}, - {0x00}, 0x1fffffc0}, + {0x00}, 0x1fffffc0, NULL}, {{0xb66666b4, 0xdbeac32b, 0x0ea351ae, 0xcba9da46, 0x6278b874, 0x8c508e23, 0xe16ca776, 0x8465bac1}, - {0x00}, 0x3fffffc0}, + {0x00}, 0x3fffffc0, NULL}, {{0xb6744789, 0x9cce87aa, 0xc4c478b7, 0xf38404d8, 0x2e38ba62, 0xa3f7019b, 0x50458fe7, 0x3047dbec}, - {0x00}, 0x7fffffc0}, + {0x00}, 0x7fffffc0, NULL}, {{0x8b1297ba, 0xba261a80, 0x2ba1b0dd, 0xfbc67d6d, 0x61072c4e, 0x4b5a2a0f, 0x52872760, 0x2dfeb162}, - {0x00}, 0xffffffc0}, + {0x00}, 0xffffffc0, NULL}, {{0x24f33cf7, 0x41ad6583, 0x41c8ff5d, 0xca7ef35f, 0x50395756, 0x021b743e, 0xd7126cd7, 0xd037473a}, - {0x00}, 0x1ffffffc0}, + {0x00}, 0x1ffffffc0, NULL}, }; static const unsigned char outputs[][32] = { {0x0e, 0x83, 0xe2, 0xc9, 0x4f, 0xb2, 0xb8, 0x2b, 0x89, 0x06, 0x92, 0x78, 0x04, 0x03, 0x48, 0x5c, 0x48, 0x44, 0x67, 0x61, 0x77, 0xa4, 0xc7, 0x90, 0x9e, 0x92, 0x55, 0x10, 0x05, 0xfe, 0x39, 0x15}, @@ -603,9 +651,14 @@ static void run_sha256_counter_tests(void) { {0xec, 0x12, 0x24, 0x9f, 0x35, 0xa4, 0x29, 0x8b, 0x9e, 0x4a, 0x95, 0xf8, 0x61, 0xaf, 0x61, 0xc5, 0x66, 0x55, 0x3e, 0x3f, 0x2a, 0x98, 0xea, 0x71, 0x16, 0x6b, 0x1c, 0xd9, 0xe4, 0x09, 0xd2, 0x8e}, }; unsigned int i; + /* TODO: Use default transform; grabbing it via a dummy state is a temporary hack. */ + secp256k1_sha256 origin; + secp256k1_sha256_initialize(&origin, /*fn_transform=*/NULL); + for (i = 0; i < sizeof(midstates)/sizeof(midstates[0]); i++) { unsigned char out[32]; secp256k1_sha256 hasher = midstates[i]; + hasher.fn_transform = origin.fn_transform; secp256k1_sha256_write(&hasher, (const unsigned char*)input, strlen(input)); secp256k1_sha256_finalize(&hasher, out); CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0); @@ -624,9 +677,9 @@ static void test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_sha256 } /* Convenience function for using test_sha256_eq to verify the correctness of a * tagged hash midstate. This function is used by some module tests. */ -static void test_sha256_tag_midstate(secp256k1_sha256 *sha_tagged, const unsigned char *tag, size_t taglen) { +static void test_sha256_tag_midstate(const secp256k1_context *ctx, secp256k1_sha256 *sha_tagged, const unsigned char *tag, size_t taglen) { secp256k1_sha256 sha; - secp256k1_sha256_initialize_tagged(&sha, tag, taglen); + secp256k1_sha256_initialize_tagged(&sha, tag, taglen, ctx->hash_context.fn_sha256_transform); test_sha256_eq(&sha, sha_tagged); } @@ -656,16 +709,17 @@ static void run_hmac_sha256_tests(void) { {0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2} }; int i; + const secp256k1_context *ctx = secp256k1_context_static; for (i = 0; i < 6; i++) { secp256k1_hmac_sha256 hasher; unsigned char out[32]; - secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); + secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i]), ctx->hash_context.fn_sha256_transform); secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); secp256k1_hmac_sha256_finalize(&hasher, out); CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0); if (strlen(inputs[i]) > 0) { int split = testrand_int(strlen(inputs[i])); - secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); + secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i]), ctx->hash_context.fn_sha256_transform); secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); secp256k1_hmac_sha256_finalize(&hasher, out); @@ -689,27 +743,28 @@ static void run_rfc6979_hmac_sha256_tests(void) { {0x75, 0x97, 0x88, 0x7c, 0xbd, 0x76, 0x32, 0x1f, 0x32, 0xe3, 0x04, 0x40, 0x67, 0x9a, 0x22, 0xcf, 0x7f, 0x8d, 0x9d, 0x2e, 0xac, 0x39, 0x0e, 0x58, 0x1f, 0xea, 0x09, 0x1c, 0xe2, 0x02, 0xba, 0x94} }; + secp256k1_context ctx = secp256k1_context_static_; secp256k1_rfc6979_hmac_sha256 rng; unsigned char out[32]; int i; - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 64); + secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 64, ctx.hash_context.fn_sha256_transform); for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32, ctx.hash_context.fn_sha256_transform); CHECK(secp256k1_memcmp_var(out, out1[i], 32) == 0); } secp256k1_rfc6979_hmac_sha256_finalize(&rng); - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 65); + secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 65, ctx.hash_context.fn_sha256_transform); for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32, ctx.hash_context.fn_sha256_transform); CHECK(secp256k1_memcmp_var(out, out1[i], 32) != 0); } secp256k1_rfc6979_hmac_sha256_finalize(&rng); - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 64); + secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 64, ctx.hash_context.fn_sha256_transform); for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32, ctx.hash_context.fn_sha256_transform); CHECK(secp256k1_memcmp_var(out, out2[i], 32) == 0); } secp256k1_rfc6979_hmac_sha256_finalize(&rng); @@ -5468,6 +5523,7 @@ static void test_ecmult_constants_2bit(void) { secp256k1_sha256 acc; unsigned char b32[32]; int i, j; + secp256k1_context ctx = secp256k1_context_static_; secp256k1_scratch_space *scratch = secp256k1_scratch_space_create(CTX, 65536); /* Expected hash of all the computed points; created with an independent @@ -5478,7 +5534,7 @@ static void test_ecmult_constants_2bit(void) { 0x3a, 0x75, 0x87, 0x60, 0x1a, 0xf9, 0x63, 0x60, 0xd0, 0xcb, 0x1f, 0xaa, 0x85, 0x9a, 0xb7, 0xb4 }; - secp256k1_sha256_initialize(&acc); + secp256k1_sha256_initialize(&acc, ctx.hash_context.fn_sha256_transform); for (i = 0; i <= 36; ++i) { secp256k1_scalar_set_int(&x, i); test_ecmult_accumulate(&acc, &x, scratch); @@ -5512,13 +5568,14 @@ static void test_ecmult_constants_sha(uint32_t prefix, size_t iter, const unsign unsigned char b32[32]; unsigned char inp[6]; size_t i; + secp256k1_context ctx = secp256k1_context_static_; secp256k1_scratch_space *scratch = secp256k1_scratch_space_create(CTX, 65536); inp[0] = prefix & 0xFF; inp[1] = (prefix >> 8) & 0xFF; inp[2] = (prefix >> 16) & 0xFF; inp[3] = (prefix >> 24) & 0xFF; - secp256k1_sha256_initialize(&acc); + secp256k1_sha256_initialize(&acc, ctx.hash_context.fn_sha256_transform); secp256k1_scalar_set_int(&x, 0); test_ecmult_accumulate(&acc, &x, scratch); secp256k1_scalar_set_int(&x, 1); @@ -5530,7 +5587,7 @@ static void test_ecmult_constants_sha(uint32_t prefix, size_t iter, const unsign secp256k1_sha256 gen; inp[4] = i & 0xff; inp[5] = (i >> 8) & 0xff; - secp256k1_sha256_initialize(&gen); + secp256k1_sha256_initialize(&gen, ctx.hash_context.fn_sha256_transform); secp256k1_sha256_write(&gen, inp, sizeof(inp)); secp256k1_sha256_finalize(&gen, b32); secp256k1_scalar_set_b32(&x, b32, NULL); @@ -6330,7 +6387,8 @@ static void run_ecdsa_sign_verify(void) { } /** Dummy nonce generation function that just uses a precomputed nonce, and fails if it is not accepted. Use only for testing. */ -static int precomputed_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { +static int precomputed_nonce_function(const secp256k1_context *ctx, unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { + (void)ctx; (void)msg32; (void)key32; (void)algo16; @@ -6338,15 +6396,15 @@ static int precomputed_nonce_function(unsigned char *nonce32, const unsigned cha return (counter == 0); } -static int nonce_function_test_fail(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { +static int nonce_function_test_fail(const secp256k1_context *ctx, unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { /* Dummy nonce generator that has a fatal error on the first counter value. */ if (counter == 0) { return 0; } - return nonce_function_rfc6979(nonce32, msg32, key32, algo16, data, counter - 1); + return nonce_function_rfc6979(ctx, nonce32, msg32, key32, algo16, data, counter - 1); } -static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { +static int nonce_function_test_retry(const secp256k1_context *ctx, unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { /* Dummy nonce generator that produces unacceptable nonces for the first several counter values. */ if (counter < 3) { memset(nonce32, counter==0 ? 0 : 255, 32); @@ -6367,7 +6425,7 @@ static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char if (counter > 5) { return 0; } - return nonce_function_rfc6979(nonce32, msg32, key32, algo16, data, counter - 5); + return nonce_function_rfc6979(ctx, nonce32, msg32, key32, algo16, data, counter - 5); } static int is_empty_signature(const secp256k1_ecdsa_signature *sig) { @@ -7347,6 +7405,7 @@ static void test_ecdsa_edge_cases(void) { { /* Check that optional nonce arguments do not have equivalent effect. */ + const secp256k1_context* ctx = secp256k1_context_static; const unsigned char zeros[32] = {0}; unsigned char nonce[32]; unsigned char nonce2[32]; @@ -7356,13 +7415,13 @@ static void test_ecdsa_edge_cases(void) { SECP256K1_CHECKMEM_UNDEFINE(nonce2,32); SECP256K1_CHECKMEM_UNDEFINE(nonce3,32); SECP256K1_CHECKMEM_UNDEFINE(nonce4,32); - CHECK(nonce_function_rfc6979(nonce, zeros, zeros, NULL, NULL, 0) == 1); + CHECK(nonce_function_rfc6979(ctx, nonce, zeros, zeros, NULL, NULL, 0) == 1); SECP256K1_CHECKMEM_CHECK(nonce,32); - CHECK(nonce_function_rfc6979(nonce2, zeros, zeros, zeros, NULL, 0) == 1); + CHECK(nonce_function_rfc6979(ctx, nonce2, zeros, zeros, zeros, NULL, 0) == 1); SECP256K1_CHECKMEM_CHECK(nonce2,32); - CHECK(nonce_function_rfc6979(nonce3, zeros, zeros, NULL, (void *)zeros, 0) == 1); + CHECK(nonce_function_rfc6979(ctx, nonce3, zeros, zeros, NULL, (void *)zeros, 0) == 1); SECP256K1_CHECKMEM_CHECK(nonce3,32); - CHECK(nonce_function_rfc6979(nonce4, zeros, zeros, zeros, (void *)zeros, 0) == 1); + CHECK(nonce_function_rfc6979(ctx, nonce4, zeros, zeros, zeros, (void *)zeros, 0) == 1); SECP256K1_CHECKMEM_CHECK(nonce4,32); CHECK(secp256k1_memcmp_var(nonce, nonce2, 32) != 0); CHECK(secp256k1_memcmp_var(nonce, nonce3, 32) != 0); @@ -7396,6 +7455,7 @@ static void test_ecdsa_wycheproof(void) { #include "wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h" int t; + const secp256k1_context* ctx = secp256k1_context_static; for (t = 0; t < SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS; t++) { secp256k1_ecdsa_signature signature; secp256k1_sha256 hasher; @@ -7408,7 +7468,7 @@ static void test_ecdsa_wycheproof(void) { pk = &wycheproof_ecdsa_public_keys[testvectors[t].pk_offset]; CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, pk, 65) == 1); - secp256k1_sha256_initialize(&hasher); + secp256k1_sha256_initialize(&hasher, ctx->hash_context.fn_sha256_transform); msg = &wycheproof_ecdsa_messages[testvectors[t].msg_offset]; secp256k1_sha256_write(&hasher, msg, testvectors[t].msg_len); secp256k1_sha256_finalize(&hasher, out); @@ -7675,6 +7735,7 @@ static const struct tf_test_entry tests_general[] = { CASE(all_static_context_tests), CASE(deprecated_context_flags_test), CASE(scratch_tests), + CASE(plug_sha256_transform_tests), }; static const struct tf_test_entry tests_integer[] = { diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index f8bbcaaf5c..96c0addc99 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -42,11 +42,12 @@ SECP256K1_INLINE static int skip_section(uint64_t* iter) { return ((((uint32_t)*iter ^ (*iter >> 32)) * num_cores) >> 32) != this_core; } -static int secp256k1_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32, - const unsigned char *key32, const unsigned char *algo16, - void *data, unsigned int attempt) { +static int secp256k1_nonce_function_smallint(const secp256k1_context *ctx, unsigned char *nonce32, + const unsigned char *msg32, const unsigned char *key32, + const unsigned char *algo16, void *data, unsigned int attempt) { secp256k1_scalar s; int *idata = data; + (void)ctx; (void)msg32; (void)key32; (void)algo16;