Line data Source code
1 : #include "fd_sha256.h"
2 : #include "fd_sha256_constants.h"
3 :
4 : #if FD_HAS_SHANI
5 : #include "../../util/simd/fd_sse.h"
6 : #endif
7 :
8 : ulong
9 23502 : fd_sha256_align( void ) {
10 23502 : return FD_SHA256_ALIGN;
11 23502 : }
12 :
13 : ulong
14 11758 : fd_sha256_footprint( void ) {
15 11758 : return FD_SHA256_FOOTPRINT;
16 11758 : }
17 :
18 : void *
19 11757 : fd_sha256_new( void * shmem ) {
20 11757 : fd_sha256_t * sha = (fd_sha256_t *)shmem;
21 :
22 11757 : if( FD_UNLIKELY( !shmem ) ) {
23 0 : FD_LOG_WARNING(( "NULL shmem" ));
24 0 : return NULL;
25 0 : }
26 :
27 11757 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_sha256_align() ) ) ) {
28 0 : FD_LOG_WARNING(( "misaligned shmem" ));
29 0 : return NULL;
30 0 : }
31 :
32 11757 : ulong footprint = fd_sha256_footprint();
33 :
34 11757 : fd_memset( sha, 0, footprint );
35 :
36 11757 : FD_COMPILER_MFENCE();
37 11757 : FD_VOLATILE( sha->magic ) = FD_SHA256_MAGIC;
38 11757 : FD_COMPILER_MFENCE();
39 :
40 11757 : return (void *)sha;
41 11757 : }
42 :
43 : fd_sha256_t *
44 11753 : fd_sha256_join( void * shsha ) {
45 :
46 11753 : if( FD_UNLIKELY( !shsha ) ) {
47 0 : FD_LOG_WARNING(( "NULL shsha" ));
48 0 : return NULL;
49 0 : }
50 :
51 11753 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shsha, fd_sha256_align() ) ) ) {
52 0 : FD_LOG_WARNING(( "misaligned shsha" ));
53 0 : return NULL;
54 0 : }
55 :
56 11753 : fd_sha256_t * sha = (fd_sha256_t *)shsha;
57 :
58 11753 : if( FD_UNLIKELY( sha->magic!=FD_SHA256_MAGIC ) ) {
59 0 : FD_LOG_WARNING(( "bad magic" ));
60 0 : return NULL;
61 0 : }
62 :
63 11753 : return sha;
64 11753 : }
65 :
66 : void *
67 0 : fd_sha256_leave( fd_sha256_t * sha ) {
68 :
69 0 : if( FD_UNLIKELY( !sha ) ) {
70 0 : FD_LOG_WARNING(( "NULL sha" ));
71 0 : return NULL;
72 0 : }
73 :
74 0 : return (void *)sha;
75 0 : }
76 :
77 : void *
78 0 : fd_sha256_delete( void * shsha ) {
79 :
80 0 : if( FD_UNLIKELY( !shsha ) ) {
81 0 : FD_LOG_WARNING(( "NULL shsha" ));
82 0 : return NULL;
83 0 : }
84 :
85 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shsha, fd_sha256_align() ) ) ) {
86 0 : FD_LOG_WARNING(( "misaligned shsha" ));
87 0 : return NULL;
88 0 : }
89 :
90 0 : fd_sha256_t * sha = (fd_sha256_t *)shsha;
91 :
92 0 : if( FD_UNLIKELY( sha->magic!=FD_SHA256_MAGIC ) ) {
93 0 : FD_LOG_WARNING(( "bad magic" ));
94 0 : return NULL;
95 0 : }
96 :
97 0 : FD_COMPILER_MFENCE();
98 0 : FD_VOLATILE( sha->magic ) = 0UL;
99 0 : FD_COMPILER_MFENCE();
100 :
101 0 : return (void *)sha;
102 0 : }
103 :
104 : #ifndef FD_SHA256_CORE_IMPL
105 : #if FD_HAS_ARM_SHA256
106 : #define FD_SHA256_CORE_IMPL 2
107 : #elif FD_HAS_SHANI
108 : #define FD_SHA256_CORE_IMPL 1
109 : #elif FD_HAS_RISCV_SHA256
110 : #define FD_SHA256_CORE_IMPL 3
111 : #else
112 : #define FD_SHA256_CORE_IMPL 0
113 : #endif
114 : #endif
115 :
116 : #if FD_SHA256_CORE_IMPL==0
117 :
118 : /* The implementation below was derived from OpenSSL's SHA-256
119 : implementation (Apache-2.0 licensed). See in particular:
120 :
121 : https://github.com/openssl/openssl/blob/master/crypto/sha/sha256.c
122 :
123 : (link valid circa 2022-Dec). It has been made more strict with more
124 : extensive implementation documentation, has been simplified and has
125 : been streamlined specifically for use inside Firedancer base machine
126 : model (no machine specific capabilities required).
127 :
128 : In particular, fd_sha256_core_ref is based on OpenSSL's
129 : OPENSSL_SMALL_FOOTPRINT SHA-256 implementation (Apache licensed).
130 : This should work anywhere but it is not the highest performance
131 : implementation possible.
132 :
133 : It is also straightforward to replace these implementations with HPC
134 : implementations that target specific machine capabilities without
135 : requiring any changes to caller code. */
136 :
137 : static void
138 : fd_sha256_core_ref( uint * state,
139 : uchar const * block,
140 : ulong block_cnt ) {
141 :
142 :
143 : # define ROTATE fd_uint_rotate_left
144 : # define Sigma0(x) (ROTATE((x),30) ^ ROTATE((x),19) ^ ROTATE((x),10))
145 : # define Sigma1(x) (ROTATE((x),26) ^ ROTATE((x),21) ^ ROTATE((x),7))
146 : # define sigma0(x) (ROTATE((x),25) ^ ROTATE((x),14) ^ ((x)>>3))
147 : # define sigma1(x) (ROTATE((x),15) ^ ROTATE((x),13) ^ ((x)>>10))
148 : # define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
149 : # define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
150 :
151 : uchar const * W = block;
152 : do {
153 : uint a = state[0];
154 : uint b = state[1];
155 : uint c = state[2];
156 : uint d = state[3];
157 : uint e = state[4];
158 : uint f = state[5];
159 : uint g = state[6];
160 : uint h = state[7];
161 :
162 : uint X[16];
163 :
164 : ulong i;
165 : for( i=0UL; i<16UL; i++ ) {
166 : X[i] = fd_uint_bswap( FD_LOAD( uint, W + i*sizeof(uint) ) );
167 : uint T1 = X[i] + h + Sigma1(e) + Ch(e, f, g) + fd_sha256_K[i];
168 : uint T2 = Sigma0(a) + Maj(a, b, c);
169 : h = g;
170 : g = f;
171 : f = e;
172 : e = d + T1;
173 : d = c;
174 : c = b;
175 : b = a;
176 : a = T1 + T2;
177 : }
178 : for( ; i<64UL; i++ ) {
179 : uint s0 = X[(i + 1UL) & 0x0fUL];
180 : uint s1 = X[(i + 14UL) & 0x0fUL];
181 : s0 = sigma0(s0);
182 : s1 = sigma1(s1);
183 : X[i & 0xfUL] += s0 + s1 + X[(i + 9UL) & 0xfUL];
184 : uint T1 = X[i & 0xfUL ] + h + Sigma1(e) + Ch(e, f, g) + fd_sha256_K[i];
185 : uint T2 = Sigma0(a) + Maj(a, b, c);
186 : h = g;
187 : g = f;
188 : f = e;
189 : e = d + T1;
190 : d = c;
191 : c = b;
192 : b = a;
193 : a = T1 + T2;
194 : }
195 :
196 : state[0] += a;
197 : state[1] += b;
198 : state[2] += c;
199 : state[3] += d;
200 : state[4] += e;
201 : state[5] += f;
202 : state[6] += g;
203 : state[7] += h;
204 :
205 : W += 16UL*sizeof(uint);
206 : } while( --block_cnt );
207 :
208 : # undef ROTATE
209 : # undef Sigma0
210 : # undef Sigma1
211 : # undef sigma0
212 : # undef sigma1
213 : # undef Ch
214 : # undef Maj
215 :
216 : }
217 :
218 : #define fd_sha256_core fd_sha256_core_ref
219 :
220 : #elif FD_SHA256_CORE_IMPL==1
221 :
222 : /* _mm_sha256rnds2_epu32 does two rounds, one from the first uint in
223 : wk and one from the second. Since wk stores four rounds worth of
224 : message schedule values, it makes sense for the macro to do four
225 : rounds at a time. We need to permute wk in between so that the
226 : second call to the intrinsic will use the other values. */
227 47909040 : #define FOUR_ROUNDS( wk ) do { \
228 47909040 : vu_t __wk = (wk); \
229 47909040 : vu_t temp_state = stateFEBA; \
230 47909040 : stateFEBA = _mm_sha256rnds2_epu32( stateHGDC, stateFEBA, __wk ); \
231 47909040 : stateHGDC = temp_state; \
232 47909040 : \
233 47909040 : temp_state = stateFEBA; \
234 47909040 : stateFEBA = _mm_sha256rnds2_epu32( stateHGDC, stateFEBA, vu_permute( __wk, 2,3,0,1 ) );\
235 47909040 : stateHGDC = temp_state; \
236 47909040 : } while( 0 )
237 :
238 :
239 : /* For completeness, here's the documentation for _mm_sha256msg1_epu32
240 : and _mm_sha256msg2_epu32 in a slightly reformatted way, where all
241 : values are uints, and "-" indicates a don't-care value:
242 :
243 : _mm_sha256msg1_epu32( (w[j ], w[j+1], w[j+1], w[j+3]),
244 : (w[j+4], -, -, - ) )
245 : = ( w[j ]+s0( w[j+1] ), w[j+1]+s0( w[j+2] ),
246 : w[j+2]+s0( w[j+3] ), w[j+3]+s0( w[j+4] ) ).
247 :
248 :
249 : _mm_sha256msg2_epu32( (v[j ], v[j+1], v[j+1], v[j+3]),
250 : (-, -, w[j-2], w[j-1]) )
251 : sets w[j ] = v[j ] + s1( w[j-2] ) and
252 : w[j+1] = v[j+1] + s1( w[j-1] ), and then returns
253 :
254 : ( v[j ]+s1( w[j-2] ), v[j+1]+s1( w[j-1] ),
255 : v[j+2]+s1( w[j ] ), v[j+3]+s1( w[j+1] ) ) */
256 :
257 :
258 : /* w[i] for i>= 16 is w[i-16] + s0(w[i-15]) + w[i-7] + s1(w[i-2])
259 : Since our vector size is 4 uints, it's only s1 that is a little
260 : problematic, because it references items in the same vector.
261 : Thankfully, the msg2 intrinsic takes care of the complexity, but we
262 : need to execute it last.
263 :
264 : We get w[i-16] and s0(s[i-15]) using the msg1 intrinsic, setting j =
265 : i-16. For example, to compute w1013, we pass in w0003 and w0407.
266 : Then we can get w[i-7] by using the alignr instruction on
267 : (w[i-8], w[i-7], w[i-6], w[i-5]) and (w[i-4], w[i-3], w[i-2], w[i-1])
268 : to concatenate them and shift by one uint. Continuing with the
269 : example of w1013, we need w080b and w0c0f. We then put
270 : v[i] = w[i-16] + s0(w[i-15]) + w[i-7],
271 : and invoke the msg2 intrinsic with j=i, which gives w[i], as desired.
272 : Each invocation of NEXT_W computes 4 values of w. */
273 :
274 35931780 : #define NEXT_W( w_minus_16, w_minus_12, w_minus_8, w_minus_4 ) (__extension__({ \
275 35931780 : vu_t __w_i_16_s0_i_15 = _mm_sha256msg1_epu32( w_minus_16, w_minus_12 ); \
276 35931780 : vu_t __w_i_7 = _mm_alignr_epi8( w_minus_4, w_minus_8, 4 ); \
277 35931780 : _mm_sha256msg2_epu32( vu_add( __w_i_7, __w_i_16_s0_i_15 ), w_minus_4 ); \
278 35931780 : }))
279 :
280 : /* Zen 5's sha256rnds2 has an RTP of 2, while Zen 4's has an RTP of 1. We can
281 : win some performance by moving the schedule updates earlier in the loop. */
282 : #ifdef __znver5__
283 : #define FULL_ROUNDS() do { \
284 : vu_t w1013 = NEXT_W( w0003, w0407, w080b, w0c0f ); FOUR_ROUNDS( vu_add( w0003, vu_ld( fd_sha256_K+ 0UL ) ) ); \
285 : vu_t w1417 = NEXT_W( w0407, w080b, w0c0f, w1013 ); FOUR_ROUNDS( vu_add( w0407, vu_ld( fd_sha256_K+ 4UL ) ) ); \
286 : vu_t w181b = NEXT_W( w080b, w0c0f, w1013, w1417 ); FOUR_ROUNDS( vu_add( w080b, vu_ld( fd_sha256_K+ 8UL ) ) ); \
287 : vu_t w1c1f = NEXT_W( w0c0f, w1013, w1417, w181b ); FOUR_ROUNDS( vu_add( w0c0f, vu_ld( fd_sha256_K+12UL ) ) ); \
288 : vu_t w2023 = NEXT_W( w1013, w1417, w181b, w1c1f ); FOUR_ROUNDS( vu_add( w1013, vu_ld( fd_sha256_K+16UL ) ) ); \
289 : vu_t w2427 = NEXT_W( w1417, w181b, w1c1f, w2023 ); FOUR_ROUNDS( vu_add( w1417, vu_ld( fd_sha256_K+20UL ) ) ); \
290 : vu_t w282b = NEXT_W( w181b, w1c1f, w2023, w2427 ); FOUR_ROUNDS( vu_add( w181b, vu_ld( fd_sha256_K+24UL ) ) ); \
291 : vu_t w2c2f = NEXT_W( w1c1f, w2023, w2427, w282b ); FOUR_ROUNDS( vu_add( w1c1f, vu_ld( fd_sha256_K+28UL ) ) ); \
292 : vu_t w3033 = NEXT_W( w2023, w2427, w282b, w2c2f ); FOUR_ROUNDS( vu_add( w2023, vu_ld( fd_sha256_K+32UL ) ) ); \
293 : vu_t w3437 = NEXT_W( w2427, w282b, w2c2f, w3033 ); FOUR_ROUNDS( vu_add( w2427, vu_ld( fd_sha256_K+36UL ) ) ); \
294 : vu_t w383b = NEXT_W( w282b, w2c2f, w3033, w3437 ); FOUR_ROUNDS( vu_add( w282b, vu_ld( fd_sha256_K+40UL ) ) ); \
295 : vu_t w3c3f = NEXT_W( w2c2f, w3033, w3437, w383b ); FOUR_ROUNDS( vu_add( w2c2f, vu_ld( fd_sha256_K+44UL ) ) ); \
296 : /* */ FOUR_ROUNDS( vu_add( w3033, vu_ld( fd_sha256_K+48UL ) ) ); \
297 : /* */ FOUR_ROUNDS( vu_add( w3437, vu_ld( fd_sha256_K+52UL ) ) ); \
298 : /* */ FOUR_ROUNDS( vu_add( w383b, vu_ld( fd_sha256_K+56UL ) ) ); \
299 : /* */ FOUR_ROUNDS( vu_add( w3c3f, vu_ld( fd_sha256_K+60UL ) ) ); \
300 : } while ( 0 )
301 : #else
302 2994315 : #define FULL_ROUNDS() do { \
303 2994315 : /* */ FOUR_ROUNDS( vu_add( w0003, vu_ld( fd_sha256_K+ 0UL ) ) ); \
304 2994315 : /* */ FOUR_ROUNDS( vu_add( w0407, vu_ld( fd_sha256_K+ 4UL ) ) ); \
305 2994315 : /* */ FOUR_ROUNDS( vu_add( w080b, vu_ld( fd_sha256_K+ 8UL ) ) ); \
306 2994315 : /* */ FOUR_ROUNDS( vu_add( w0c0f, vu_ld( fd_sha256_K+12UL ) ) ); \
307 2994315 : vu_t w1013 = NEXT_W( w0003, w0407, w080b, w0c0f ); FOUR_ROUNDS( vu_add( w1013, vu_ld( fd_sha256_K+16UL ) ) ); \
308 2994315 : vu_t w1417 = NEXT_W( w0407, w080b, w0c0f, w1013 ); FOUR_ROUNDS( vu_add( w1417, vu_ld( fd_sha256_K+20UL ) ) ); \
309 2994315 : vu_t w181b = NEXT_W( w080b, w0c0f, w1013, w1417 ); FOUR_ROUNDS( vu_add( w181b, vu_ld( fd_sha256_K+24UL ) ) ); \
310 2994315 : vu_t w1c1f = NEXT_W( w0c0f, w1013, w1417, w181b ); FOUR_ROUNDS( vu_add( w1c1f, vu_ld( fd_sha256_K+28UL ) ) ); \
311 2994315 : vu_t w2023 = NEXT_W( w1013, w1417, w181b, w1c1f ); FOUR_ROUNDS( vu_add( w2023, vu_ld( fd_sha256_K+32UL ) ) ); \
312 2994315 : vu_t w2427 = NEXT_W( w1417, w181b, w1c1f, w2023 ); FOUR_ROUNDS( vu_add( w2427, vu_ld( fd_sha256_K+36UL ) ) ); \
313 2994315 : vu_t w282b = NEXT_W( w181b, w1c1f, w2023, w2427 ); FOUR_ROUNDS( vu_add( w282b, vu_ld( fd_sha256_K+40UL ) ) ); \
314 2994315 : vu_t w2c2f = NEXT_W( w1c1f, w2023, w2427, w282b ); FOUR_ROUNDS( vu_add( w2c2f, vu_ld( fd_sha256_K+44UL ) ) ); \
315 2994315 : vu_t w3033 = NEXT_W( w2023, w2427, w282b, w2c2f ); FOUR_ROUNDS( vu_add( w3033, vu_ld( fd_sha256_K+48UL ) ) ); \
316 2994315 : vu_t w3437 = NEXT_W( w2427, w282b, w2c2f, w3033 ); FOUR_ROUNDS( vu_add( w3437, vu_ld( fd_sha256_K+52UL ) ) ); \
317 2994315 : vu_t w383b = NEXT_W( w282b, w2c2f, w3033, w3437 ); FOUR_ROUNDS( vu_add( w383b, vu_ld( fd_sha256_K+56UL ) ) ); \
318 2994315 : vu_t w3c3f = NEXT_W( w2c2f, w3033, w3437, w383b ); FOUR_ROUNDS( vu_add( w3c3f, vu_ld( fd_sha256_K+60UL ) ) ); \
319 2994315 : } while ( 0 )
320 : #endif
321 :
322 :
323 : void
324 : fd_sha256_core_shaext( uint * state, /* 64-byte aligned, 8 entries */
325 : uchar const * block, /* ideally 128-byte aligned (but not required), 64*block_cnt in size */
326 863528 : ulong block_cnt ) {/* positive */
327 863528 : vu_t stateABCD = vu_ld( state );
328 863528 : vu_t stateEFGH = vu_ld( state+4UL );
329 :
330 863528 : vu_t baseFEBA = vu_permute2( stateEFGH, stateABCD, 1, 0, 1, 0 );
331 863528 : vu_t baseHGDC = vu_permute2( stateEFGH, stateABCD, 3, 2, 3, 2 );
332 :
333 3857843 : for( ulong b=0UL; b<block_cnt; b++ ) {
334 2994315 : vu_t stateFEBA = baseFEBA;
335 2994315 : vu_t stateHGDC = baseHGDC;
336 :
337 2994315 : vu_t w0003 = vu_bswap( vu_ldu( block+64UL*b ) );
338 2994315 : vu_t w0407 = vu_bswap( vu_ldu( block+64UL*b+16UL ) );
339 2994315 : vu_t w080b = vu_bswap( vu_ldu( block+64UL*b+32UL ) );
340 2994315 : vu_t w0c0f = vu_bswap( vu_ldu( block+64UL*b+48UL ) );
341 :
342 2994315 : FULL_ROUNDS();
343 :
344 2994315 : baseFEBA = vu_add( baseFEBA, stateFEBA );
345 2994315 : baseHGDC = vu_add( baseHGDC, stateHGDC );
346 :
347 2994315 : }
348 :
349 863528 : stateABCD = vu_permute2( baseFEBA, baseHGDC, 3, 2, 3, 2 );
350 863528 : stateEFGH = vu_permute2( baseFEBA, baseHGDC, 1, 0, 1, 0 );
351 863528 : vu_st( state, stateABCD );
352 863528 : vu_st( state+4UL, stateEFGH );
353 863528 : }
354 :
355 : #undef FULL_ROUNDS
356 : #undef NEXT_W
357 : #undef FOUR_ROUNDS
358 :
359 863996 : #define fd_sha256_core fd_sha256_core_shaext
360 :
361 : #elif FD_SHA256_CORE_IMPL==2
362 :
363 : void
364 : fd_sha256_core_arm( uint * state,
365 : uchar const * block,
366 : ulong block_cnt );
367 :
368 : #define fd_sha256_core fd_sha256_core_arm
369 :
370 : #elif FD_SHA256_CORE_IMPL==3
371 :
372 : void
373 : fd_sha256_core_riscv( uint * state,
374 : uchar const * block,
375 : ulong block_cnt );
376 :
377 : #define fd_sha256_core fd_sha256_core_riscv
378 :
379 : #else
380 : #error "Unsupported FD_SHA256_CORE_IMPL"
381 : #endif
382 :
383 : fd_sha256_t *
384 292371 : fd_sha256_init( fd_sha256_t * sha ) {
385 292371 : sha->state[0] = FD_SHA256_INITIAL_A;
386 292371 : sha->state[1] = FD_SHA256_INITIAL_B;
387 292371 : sha->state[2] = FD_SHA256_INITIAL_C;
388 292371 : sha->state[3] = FD_SHA256_INITIAL_D;
389 292371 : sha->state[4] = FD_SHA256_INITIAL_E;
390 292371 : sha->state[5] = FD_SHA256_INITIAL_F;
391 292371 : sha->state[6] = FD_SHA256_INITIAL_G;
392 292371 : sha->state[7] = FD_SHA256_INITIAL_H;
393 292371 : sha->buf_used = 0UL;
394 292371 : sha->bit_cnt = 0UL;
395 292371 : return sha;
396 292371 : }
397 :
398 : fd_sha256_t *
399 : fd_sha256_append( fd_sha256_t * sha,
400 : void const * _data,
401 844788 : ulong sz ) {
402 :
403 : /* If no data to append, we are done */
404 :
405 844788 : if( FD_UNLIKELY( !sz ) ) return sha; /* optimize for non-trivial append */
406 :
407 : /* Unpack inputs */
408 :
409 844673 : uint * state = sha->state;
410 844673 : uchar * buf = sha->buf;
411 844673 : ulong buf_used = sha->buf_used;
412 844673 : ulong bit_cnt = sha->bit_cnt;
413 :
414 844673 : uchar const * data = (uchar const *)_data;
415 :
416 : /* Update bit_cnt */
417 : /* FIXME: could accumulate bytes here and do bit conversion in append */
418 : /* FIXME: Overflow handling if more than 2^64 bits (unlikely) */
419 :
420 844673 : sha->bit_cnt = bit_cnt + (sz<<3);
421 :
422 : /* Handle buffered bytes from previous appends */
423 :
424 844673 : if( FD_UNLIKELY( buf_used ) ) { /* optimized for well aligned use of append */
425 :
426 : /* If the append isn't large enough to complete the current block,
427 : buffer these bytes too and return */
428 :
429 552650 : ulong buf_rem = FD_SHA256_PRIVATE_BUF_MAX - buf_used; /* In (0,FD_SHA256_PRIVATE_BUF_MAX) */
430 552650 : if( FD_UNLIKELY( sz < buf_rem ) ) { /* optimize for large append */
431 266259 : fd_memcpy( buf + buf_used, data, sz );
432 266259 : sha->buf_used = buf_used + sz;
433 266259 : return sha;
434 266259 : }
435 :
436 : /* Otherwise, buffer enough leading bytes of data to complete the
437 : block, update the hash and then continue processing any remaining
438 : bytes of data. */
439 :
440 286391 : fd_memcpy( buf + buf_used, data, buf_rem );
441 286391 : data += buf_rem;
442 286391 : sz -= buf_rem;
443 :
444 286391 : fd_sha256_core( state, buf, 1UL );
445 286391 : sha->buf_used = 0UL;
446 286391 : }
447 :
448 : /* Append the bulk of the data */
449 :
450 578414 : ulong block_cnt = sz >> FD_SHA256_PRIVATE_LG_BUF_MAX;
451 578414 : if( FD_LIKELY( block_cnt ) ) fd_sha256_core( state, data, block_cnt ); /* optimized for large append */
452 :
453 : /* Buffer any leftover bytes */
454 :
455 578414 : buf_used = sz & (FD_SHA256_PRIVATE_BUF_MAX-1UL); /* In [0,FD_SHA256_PRIVATE_BUF_MAX) */
456 578414 : if( FD_UNLIKELY( buf_used ) ) { /* optimized for well aligned use of append */
457 578244 : fd_memcpy( buf, data + (block_cnt << FD_SHA256_PRIVATE_LG_BUF_MAX), buf_used );
458 578244 : sha->buf_used = buf_used; /* In (0,FD_SHA256_PRIVATE_BUF_MAX) */
459 578244 : }
460 :
461 578414 : return sha;
462 844673 : }
463 :
464 : void *
465 : fd_sha256_fini( fd_sha256_t * sha,
466 292118 : void * _hash ) {
467 :
468 : /* Unpack inputs */
469 :
470 292118 : uint * state = sha->state;
471 292118 : uchar * buf = sha->buf;
472 292118 : ulong buf_used = sha->buf_used; /* In [0,FD_SHA256_PRIVATE_BUF_MAX) */
473 292118 : ulong bit_cnt = sha->bit_cnt;
474 :
475 : /* Append the terminating message byte */
476 :
477 292118 : buf[ buf_used ] = (uchar)0x80;
478 292118 : buf_used++;
479 :
480 : /* If there isn't enough room to save the message length in bits at
481 : the end of the in progress block, clear the rest of the in progress
482 : block, update the hash and start a new block. */
483 :
484 292118 : if( FD_UNLIKELY( buf_used > (FD_SHA256_PRIVATE_BUF_MAX-8UL) ) ) { /* optimize for well aligned use of append */
485 422 : fd_memset( buf + buf_used, 0, FD_SHA256_PRIVATE_BUF_MAX-buf_used );
486 422 : fd_sha256_core( state, buf, 1UL );
487 422 : buf_used = 0UL;
488 422 : }
489 :
490 : /* Clear in progress block up to last 64-bits, append the message
491 : size in bytes in the last 64-bits of the in progress block and
492 : update the hash to finalize it. */
493 :
494 292118 : fd_memset( buf + buf_used, 0, FD_SHA256_PRIVATE_BUF_MAX-8UL-buf_used );
495 292118 : FD_STORE( ulong, buf+FD_SHA256_PRIVATE_BUF_MAX-8UL, fd_ulong_bswap( bit_cnt ) );
496 292118 : fd_sha256_core( state, buf, 1UL );
497 :
498 : /* Unpack the result into md (annoying bswaps here) */
499 :
500 292118 : state[0] = fd_uint_bswap( state[0] );
501 292118 : state[1] = fd_uint_bswap( state[1] );
502 292118 : state[2] = fd_uint_bswap( state[2] );
503 292118 : state[3] = fd_uint_bswap( state[3] );
504 292118 : state[4] = fd_uint_bswap( state[4] );
505 292118 : state[5] = fd_uint_bswap( state[5] );
506 292118 : state[6] = fd_uint_bswap( state[6] );
507 292118 : state[7] = fd_uint_bswap( state[7] );
508 292118 : return memcpy( _hash, state, 32 );
509 292118 : }
510 :
511 : void *
512 : fd_sha256_hash( void const * _data,
513 : ulong sz,
514 68896 : void * _hash ) {
515 68896 : uchar const * data = (uchar const *)_data;
516 :
517 : /* This is just the above streamlined to eliminate all the overheads
518 : to support incremental hashing. */
519 :
520 68896 : uchar buf[ FD_SHA256_PRIVATE_BUF_MAX ] __attribute__((aligned(128)));
521 68896 : uint state[8] __attribute__((aligned(32)));
522 :
523 68896 : state[0] = FD_SHA256_INITIAL_A;
524 68896 : state[1] = FD_SHA256_INITIAL_B;
525 68896 : state[2] = FD_SHA256_INITIAL_C;
526 68896 : state[3] = FD_SHA256_INITIAL_D;
527 68896 : state[4] = FD_SHA256_INITIAL_E;
528 68896 : state[5] = FD_SHA256_INITIAL_F;
529 68896 : state[6] = FD_SHA256_INITIAL_G;
530 68896 : state[7] = FD_SHA256_INITIAL_H;
531 :
532 68896 : ulong block_cnt = sz >> FD_SHA256_PRIVATE_LG_BUF_MAX;
533 68896 : if( FD_LIKELY( block_cnt ) ) fd_sha256_core( state, data, block_cnt );
534 :
535 68896 : ulong buf_used = sz & (FD_SHA256_PRIVATE_BUF_MAX-1UL);
536 68896 : if( FD_UNLIKELY( buf_used ) ) fd_memcpy( buf, data + (block_cnt << FD_SHA256_PRIVATE_LG_BUF_MAX), buf_used );
537 68896 : buf[ buf_used ] = (uchar)0x80;
538 68896 : buf_used++;
539 :
540 68896 : if( FD_UNLIKELY( buf_used > (FD_SHA256_PRIVATE_BUF_MAX-8UL) ) ) {
541 0 : fd_memset( buf + buf_used, 0, FD_SHA256_PRIVATE_BUF_MAX-buf_used );
542 0 : fd_sha256_core( state, buf, 1UL );
543 0 : buf_used = 0UL;
544 0 : }
545 :
546 68896 : ulong bit_cnt = sz << 3;
547 68896 : fd_memset( buf + buf_used, 0, FD_SHA256_PRIVATE_BUF_MAX-8UL-buf_used );
548 68896 : FD_STORE( ulong, buf+FD_SHA256_PRIVATE_BUF_MAX-8UL, fd_ulong_bswap( bit_cnt ) );
549 68896 : fd_sha256_core( state, buf, 1UL );
550 :
551 68896 : state[0] = fd_uint_bswap( state[0] );
552 68896 : state[1] = fd_uint_bswap( state[1] );
553 68896 : state[2] = fd_uint_bswap( state[2] );
554 68896 : state[3] = fd_uint_bswap( state[3] );
555 68896 : state[4] = fd_uint_bswap( state[4] );
556 68896 : state[5] = fd_uint_bswap( state[5] );
557 68896 : state[6] = fd_uint_bswap( state[6] );
558 68896 : state[7] = fd_uint_bswap( state[7] );
559 68896 : return memcpy( _hash, state, 32 );
560 68896 : }
561 :
562 : #undef fd_sha256_core
|