Skip to content

Commit 97fb41e

Browse files
committed
Add ability to provide SHA256 compression at compile-time
Introduces a new `sha` module that exposes the SHA256 compression function and allows users to provide their own implementation. This moves the built-in transform logic out of `hash_impl.h` into a dedicated module (`src/modules/sha`), adds the corresponding public header (`secp256k1_sha.h`), and wires the module through Autotools and CMake via: `--with-external-sha256` / SECP256K1_EXTERNAL_SHA256_PATH. Existing behavior is unchanged; the library compiles and links the default transform function by default.
1 parent e7f7083 commit 97fb41e

File tree

9 files changed

+206
-106
lines changed

9 files changed

+206
-106
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ message(" extrakeys ........................... ${SECP256K1_ENABLE_MODULE_EXTRA
285285
message(" schnorrsig .......................... ${SECP256K1_ENABLE_MODULE_SCHNORRSIG}")
286286
message(" musig ............................... ${SECP256K1_ENABLE_MODULE_MUSIG}")
287287
message(" ElligatorSwift ...................... ${SECP256K1_ENABLE_MODULE_ELLSWIFT}")
288+
message(" External SHA256 ..................... ${SECP256K1_EXTERNAL_SHA256_PATH-NONE}")
288289
message("Parameters:")
289290
message(" ecmult window size .................. ${SECP256K1_ECMULT_WINDOW_SIZE}")
290291
message(" ecmult gen table size ............... ${SECP256K1_ECMULT_GEN_KB} KiB")

Makefile.am

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ noinst_HEADERS += src/scratch_impl.h
6262
noinst_HEADERS += src/selftest.h
6363
noinst_HEADERS += src/testrand.h
6464
noinst_HEADERS += src/testrand_impl.h
65+
if !SECP256K1_EXTERNAL_SHA256
66+
noinst_HEADERS += src/modules/sha/main_impl.h
67+
endif
6568
noinst_HEADERS += src/hash.h
6669
noinst_HEADERS += src/hash_impl.h
6770
noinst_HEADERS += src/field.h
@@ -314,3 +317,6 @@ endif
314317
if ENABLE_MODULE_ELLSWIFT
315318
include src/modules/ellswift/Makefile.am.include
316319
endif
320+
321+
# Always include SHA module files, but they conditionally compile
322+
include src/modules/sha/Makefile.am.include

configure.ac

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,12 @@ SECP_TRY_APPEND_DEFAULT_CFLAGS(SECP_CFLAGS)
134134
### Define config arguments
135135
###
136136

137+
AC_ARG_WITH([external-sha256],
138+
AS_HELP_STRING([--with-external-sha256=PATH], [use external SHA256 compression implementation]),
139+
[external_sha256_path="$withval"],
140+
[external_sha256_path=""]
141+
)
142+
137143
# In dev mode, we enable all binaries and modules by default but individual options can still be overridden explicitly.
138144
# Check for dev mode first because SECP_SET_DEFAULT needs enable_dev_mode set.
139145
AC_ARG_ENABLE(dev_mode, [], [],
@@ -397,6 +403,12 @@ SECP_CFLAGS="$SECP_CFLAGS $WERROR_CFLAGS"
397403

398404
# Processing must be done in a reverse topological sorting of the dependency graph
399405
# (dependent module first).
406+
407+
if test "x$external_sha256_path" != "x"; then
408+
SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DSECP256K1_EXTERNAL_SHA256=1"
409+
SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DSECP256K1_EXTERNAL_SHA256_HEADER='\"$external_sha256_path\"'"
410+
fi
411+
400412
if test x"$enable_module_ellswift" = x"yes"; then
401413
SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_ELLSWIFT=1"
402414
fi
@@ -470,6 +482,7 @@ AM_CONDITIONAL([ENABLE_MODULE_EXTRAKEYS], [test x"$enable_module_extrakeys" = x"
470482
AM_CONDITIONAL([ENABLE_MODULE_SCHNORRSIG], [test x"$enable_module_schnorrsig" = x"yes"])
471483
AM_CONDITIONAL([ENABLE_MODULE_MUSIG], [test x"$enable_module_musig" = x"yes"])
472484
AM_CONDITIONAL([ENABLE_MODULE_ELLSWIFT], [test x"$enable_module_ellswift" = x"yes"])
485+
AM_CONDITIONAL([SECP256K1_EXTERNAL_SHA256], [test "x$SHA256_EXTERNAL_SRC" != "x"])
473486
AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$enable_external_asm" = x"yes"])
474487
AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm32"])
475488
AM_CONDITIONAL([BUILD_WINDOWS], [test "$build_windows" = "yes"])
@@ -494,6 +507,7 @@ echo " module extrakeys = $enable_module_extrakeys"
494507
echo " module schnorrsig = $enable_module_schnorrsig"
495508
echo " module musig = $enable_module_musig"
496509
echo " module ellswift = $enable_module_ellswift"
510+
echo " external sha256 = ${external_sha256_path:-none}"
497511
echo
498512
echo " asm = $set_asm"
499513
echo " ecmult window size = $set_ecmult_window"

include/secp256k1_sha.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#ifndef SECP256K1_SHA_H
2+
#define SECP256K1_SHA_H
3+
4+
#include "secp256k1.h"
5+
6+
#include <stdint.h>
7+
8+
/**
9+
* SHA-256 block compression function.
10+
*
11+
* Performs the SHA-256 transform step on a single 64-byte message block,
12+
* updating the 8-word `state` in place. This is the raw block-level primitive:
13+
* no padding, no message scheduling across blocks, and no length encoding.
14+
* Only the compression function is applied.
15+
*
16+
* If `rounds` is greater than 1, the same 64-byte block is re-compressed
17+
* repeatedly onto the updated state.
18+
*
19+
* The caller must supply a fully-formed, 64-byte, block-aligned message block.
20+
*
21+
* @param state Current hash state (8 x 32-bit words), updated in place.
22+
* @param block Pointer to a 64-byte message block.
23+
* @param rounds Number of times to apply the compression to this block.
24+
*/
25+
SECP256K1_API void secp256k1_sha256_transform(
26+
uint32_t *state,
27+
const unsigned char *block,
28+
size_t rounds
29+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
30+
31+
#endif /* SECP256K1_SHA_H */

src/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,26 @@ add_library(secp256k1)
33
set_property(TARGET secp256k1 PROPERTY PUBLIC_HEADER
44
${PROJECT_SOURCE_DIR}/include/secp256k1.h
55
${PROJECT_SOURCE_DIR}/include/secp256k1_preallocated.h
6+
${PROJECT_SOURCE_DIR}/include/secp256k1_sha.h
67
)
78

89
# Processing must be done in a topological sorting of the dependency graph
910
# (dependent module first).
11+
12+
if(SECP256K1_EXTERNAL_SHA256_PATH)
13+
if(EXISTS "${SECP256K1_EXTERNAL_SHA256_PATH}")
14+
add_compile_definitions(SECP256K1_EXTERNAL_SHA256=1)
15+
add_compile_definitions(SECP256K1_EXTERNAL_SHA256_HEADER="${SECP256K1_EXTERNAL_SHA256_PATH}")
16+
else()
17+
message(FATAL_ERROR "SECP256K1_EXTERNAL_SHA256_PATH does not exist: ${SECP256K1_EXTERNAL_SHA256_PATH}")
18+
endif()
19+
else()
20+
# No external override. Compile internal implementation
21+
target_sources(secp256k1 PRIVATE
22+
${PROJECT_SOURCE_DIR}/src/modules/sha/main_impl.h
23+
)
24+
endif()
25+
1026
if(SECP256K1_ENABLE_MODULE_ELLSWIFT)
1127
add_compile_definitions(ENABLE_MODULE_ELLSWIFT=1)
1228
set_property(TARGET secp256k1 APPEND PROPERTY PUBLIC_HEADER ${PROJECT_SOURCE_DIR}/include/secp256k1_ellswift.h)

src/hash_impl.h

Lines changed: 3 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,12 @@
1010
#include "hash.h"
1111
#include "util.h"
1212

13+
#include "../include/secp256k1_sha.h"
14+
1315
#include <stdlib.h>
1416
#include <stdint.h>
1517
#include <string.h>
1618

17-
#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
18-
#define Maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
19-
#define Sigma0(x) (((x) >> 2 | (x) << 30) ^ ((x) >> 13 | (x) << 19) ^ ((x) >> 22 | (x) << 10))
20-
#define Sigma1(x) (((x) >> 6 | (x) << 26) ^ ((x) >> 11 | (x) << 21) ^ ((x) >> 25 | (x) << 7))
21-
#define sigma0(x) (((x) >> 7 | (x) << 25) ^ ((x) >> 18 | (x) << 14) ^ ((x) >> 3))
22-
#define sigma1(x) (((x) >> 17 | (x) << 15) ^ ((x) >> 19 | (x) << 13) ^ ((x) >> 10))
23-
24-
#define Round(a,b,c,d,e,f,g,h,k,w) do { \
25-
uint32_t t1 = (h) + Sigma1(e) + Ch((e), (f), (g)) + (k) + (w); \
26-
uint32_t t2 = Sigma0(a) + Maj((a), (b), (c)); \
27-
(d) += t1; \
28-
(h) = t1 + t2; \
29-
} while(0)
30-
3119
static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) {
3220
hash->s[0] = 0x6a09e667ul;
3321
hash->s[1] = 0xbb67ae85ul;
@@ -40,89 +28,6 @@ static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) {
4028
hash->bytes = 0;
4129
}
4230

43-
/** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */
44-
static void secp256k1_sha256_transform(uint32_t* s, const unsigned char* buf) {
45-
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];
46-
uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
47-
48-
Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = secp256k1_read_be32(&buf[0]));
49-
Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = secp256k1_read_be32(&buf[4]));
50-
Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = secp256k1_read_be32(&buf[8]));
51-
Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = secp256k1_read_be32(&buf[12]));
52-
Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = secp256k1_read_be32(&buf[16]));
53-
Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = secp256k1_read_be32(&buf[20]));
54-
Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = secp256k1_read_be32(&buf[24]));
55-
Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = secp256k1_read_be32(&buf[28]));
56-
Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = secp256k1_read_be32(&buf[32]));
57-
Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = secp256k1_read_be32(&buf[36]));
58-
Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = secp256k1_read_be32(&buf[40]));
59-
Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = secp256k1_read_be32(&buf[44]));
60-
Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = secp256k1_read_be32(&buf[48]));
61-
Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = secp256k1_read_be32(&buf[52]));
62-
Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = secp256k1_read_be32(&buf[56]));
63-
Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = secp256k1_read_be32(&buf[60]));
64-
65-
Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1));
66-
Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2));
67-
Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3));
68-
Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4));
69-
Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5));
70-
Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6));
71-
Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7));
72-
Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8));
73-
Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9));
74-
Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10));
75-
Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11));
76-
Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12));
77-
Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13));
78-
Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14));
79-
Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15));
80-
Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0));
81-
82-
Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1));
83-
Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2));
84-
Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3));
85-
Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4));
86-
Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5));
87-
Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6));
88-
Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7));
89-
Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8));
90-
Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9));
91-
Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10));
92-
Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11));
93-
Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12));
94-
Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13));
95-
Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14));
96-
Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15));
97-
Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0));
98-
99-
Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1));
100-
Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2));
101-
Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3));
102-
Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4));
103-
Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5));
104-
Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6));
105-
Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7));
106-
Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8));
107-
Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9));
108-
Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10));
109-
Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11));
110-
Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12));
111-
Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13));
112-
Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14));
113-
Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15));
114-
Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0));
115-
116-
s[0] += a;
117-
s[1] += b;
118-
s[2] += c;
119-
s[3] += d;
120-
s[4] += e;
121-
s[5] += f;
122-
s[6] += g;
123-
s[7] += h;
124-
}
125-
12631
static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t len) {
12732
size_t bufsize = hash->bytes & 0x3F;
12833
hash->bytes += len;
@@ -133,7 +38,7 @@ static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *
13338
memcpy(hash->buf + bufsize, data, chunk_len);
13439
data += chunk_len;
13540
len -= chunk_len;
136-
secp256k1_sha256_transform(hash->s, hash->buf);
41+
secp256k1_sha256_transform(hash->s, hash->buf, 1);
13742
bufsize = 0;
13843
}
13944
if (len) {
@@ -288,12 +193,4 @@ static void secp256k1_rfc6979_hmac_sha256_clear(secp256k1_rfc6979_hmac_sha256 *r
288193
secp256k1_memclear_explicit(rng, sizeof(*rng));
289194
}
290195

291-
#undef Round
292-
#undef sigma1
293-
#undef sigma0
294-
#undef Sigma1
295-
#undef Sigma0
296-
#undef Maj
297-
#undef Ch
298-
299196
#endif /* SECP256K1_HASH_IMPL_H */
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
include_HEADERS += include/secp256k1_sha.h
2+
noinst_HEADERS += src/modules/sha/main_impl.h

0 commit comments

Comments
 (0)