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.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/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/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 4341917773..14d1072e36 100644 --- a/src/hash_impl.h +++ b/src/hash_impl.h @@ -10,25 +10,13 @@ #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) { +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; @@ -38,89 +26,7 @@ static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) { hash->s[6] = 0x1f83d9abul; hash->s[7] = 0x5be0cd19ul; 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; + 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) { @@ -133,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); + hash->fn_transform(hash->s, hash->buf, 1); bufsize = 0; } if (len) { @@ -158,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); } @@ -175,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)) { @@ -183,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; } @@ -219,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}; @@ -228,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); } @@ -266,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) { @@ -288,12 +235,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/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/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..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); @@ -821,3 +842,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 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;