Line data Source code
1 : #include "fd_sha512.h"
2 :
3 : #if FD_HAS_ARM_SHA512
4 : #include <arm_neon.h>
5 : #endif
6 :
7 : ulong
8 9450 : fd_sha512_align( void ) {
9 9450 : return FD_SHA512_ALIGN;
10 9450 : }
11 :
12 : ulong
13 4767 : fd_sha512_footprint( void ) {
14 4767 : return FD_SHA512_FOOTPRINT;
15 4767 : }
16 :
17 : void *
18 4464 : fd_sha512_new( void * shmem ) {
19 4464 : fd_sha512_t * sha = (fd_sha512_t *)shmem;
20 :
21 4464 : if( FD_UNLIKELY( !shmem ) ) {
22 3 : FD_LOG_WARNING(( "NULL shmem" ));
23 3 : return NULL;
24 3 : }
25 :
26 4461 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_sha512_align() ) ) ) {
27 3 : FD_LOG_WARNING(( "misaligned shmem" ));
28 3 : return NULL;
29 3 : }
30 :
31 4458 : ulong footprint = fd_sha512_footprint();
32 :
33 4458 : fd_memset( sha, 0, footprint );
34 :
35 4458 : FD_COMPILER_MFENCE();
36 4458 : FD_VOLATILE( sha->magic ) = FD_SHA512_MAGIC;
37 4458 : FD_COMPILER_MFENCE();
38 :
39 4458 : return (void *)sha;
40 4461 : }
41 :
42 : fd_sha512_t *
43 4422 : fd_sha512_join( void * shsha ) {
44 :
45 4422 : if( FD_UNLIKELY( !shsha ) ) {
46 3 : FD_LOG_WARNING(( "NULL shsha" ));
47 3 : return NULL;
48 3 : }
49 :
50 4419 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shsha, fd_sha512_align() ) ) ) {
51 3 : FD_LOG_WARNING(( "misaligned shsha" ));
52 3 : return NULL;
53 3 : }
54 :
55 4416 : fd_sha512_t * sha = (fd_sha512_t *)shsha;
56 :
57 4416 : if( FD_UNLIKELY( sha->magic!=FD_SHA512_MAGIC ) ) {
58 0 : FD_LOG_WARNING(( "bad magic" ));
59 0 : return NULL;
60 0 : }
61 :
62 4416 : return sha;
63 4416 : }
64 :
65 : void *
66 33 : fd_sha512_leave( fd_sha512_t * sha ) {
67 :
68 33 : if( FD_UNLIKELY( !sha ) ) {
69 3 : FD_LOG_WARNING(( "NULL sha" ));
70 3 : return NULL;
71 3 : }
72 :
73 30 : return (void *)sha;
74 33 : }
75 :
76 : void *
77 36 : fd_sha512_delete( void * shsha ) {
78 :
79 36 : if( FD_UNLIKELY( !shsha ) ) {
80 3 : FD_LOG_WARNING(( "NULL shsha" ));
81 3 : return NULL;
82 3 : }
83 :
84 33 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shsha, fd_sha512_align() ) ) ) {
85 3 : FD_LOG_WARNING(( "misaligned shsha" ));
86 3 : return NULL;
87 3 : }
88 :
89 30 : fd_sha512_t * sha = (fd_sha512_t *)shsha;
90 :
91 30 : if( FD_UNLIKELY( sha->magic!=FD_SHA512_MAGIC ) ) {
92 0 : FD_LOG_WARNING(( "bad magic" ));
93 0 : return NULL;
94 0 : }
95 :
96 30 : FD_COMPILER_MFENCE();
97 30 : FD_VOLATILE( sha->magic ) = 0UL;
98 30 : FD_COMPILER_MFENCE();
99 :
100 30 : return (void *)sha;
101 30 : }
102 :
103 : #ifndef FD_SHA512_CORE_IMPL
104 : #if FD_HAS_ARM_SHA512
105 : #define FD_SHA512_CORE_IMPL 2
106 : #elif FD_HAS_AVX
107 : #define FD_SHA512_CORE_IMPL 1
108 : #else
109 : #define FD_SHA512_CORE_IMPL 0
110 : #endif
111 : #endif
112 :
113 : #if FD_SHA512_CORE_IMPL==0
114 :
115 : /* The implementation below was derived from OpenSSL's sha512
116 : implementation (Apache 2 licensed). See in particular:
117 :
118 : https://github.com/openssl/openssl/blob/master/crypto/sha/sha512.c
119 :
120 : (link valid circa 2022-Oct). It has been made more strict with more
121 : extensive implementation documentation, has been simplified and has
122 : been streamlined specifically for use inside Firedancer base machine
123 : model (no machine specific capabilities required).
124 :
125 : In particular, fd_sha512_core_ref is based on OpenSSL's
126 : OPENSSL_SMALL_FOOTPRINT SHA-512 implementation (Apache licensed).
127 : This should work anywhere but it is not the highest performance
128 : implementation possible.
129 :
130 : It is also straightforward to replace these implementations with HPC
131 : implementations that target specific machine capabilities without
132 : requiring any changes to caller code. */
133 :
134 : static void
135 : fd_sha512_core_ref( ulong * state, /* 64-byte aligned, 8 entries */
136 : uchar const * block, /* ideally 128-byte aligned (but not required), 128*block_cnt in size */
137 : ulong block_cnt ) { /* positive */
138 :
139 : static ulong const K[80] = {
140 : 0x428a2f98d728ae22UL, 0x7137449123ef65cdUL, 0xb5c0fbcfec4d3b2fUL, 0xe9b5dba58189dbbcUL,
141 : 0x3956c25bf348b538UL, 0x59f111f1b605d019UL, 0x923f82a4af194f9bUL, 0xab1c5ed5da6d8118UL,
142 : 0xd807aa98a3030242UL, 0x12835b0145706fbeUL, 0x243185be4ee4b28cUL, 0x550c7dc3d5ffb4e2UL,
143 : 0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL, 0x9bdc06a725c71235UL, 0xc19bf174cf692694UL,
144 : 0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL, 0x0fc19dc68b8cd5b5UL, 0x240ca1cc77ac9c65UL,
145 : 0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL, 0x5cb0a9dcbd41fbd4UL, 0x76f988da831153b5UL,
146 : 0x983e5152ee66dfabUL, 0xa831c66d2db43210UL, 0xb00327c898fb213fUL, 0xbf597fc7beef0ee4UL,
147 : 0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL, 0x06ca6351e003826fUL, 0x142929670a0e6e70UL,
148 : 0x27b70a8546d22ffcUL, 0x2e1b21385c26c926UL, 0x4d2c6dfc5ac42aedUL, 0x53380d139d95b3dfUL,
149 : 0x650a73548baf63deUL, 0x766a0abb3c77b2a8UL, 0x81c2c92e47edaee6UL, 0x92722c851482353bUL,
150 : 0xa2bfe8a14cf10364UL, 0xa81a664bbc423001UL, 0xc24b8b70d0f89791UL, 0xc76c51a30654be30UL,
151 : 0xd192e819d6ef5218UL, 0xd69906245565a910UL, 0xf40e35855771202aUL, 0x106aa07032bbd1b8UL,
152 : 0x19a4c116b8d2d0c8UL, 0x1e376c085141ab53UL, 0x2748774cdf8eeb99UL, 0x34b0bcb5e19b48a8UL,
153 : 0x391c0cb3c5c95a63UL, 0x4ed8aa4ae3418acbUL, 0x5b9cca4f7763e373UL, 0x682e6ff3d6b2b8a3UL,
154 : 0x748f82ee5defb2fcUL, 0x78a5636f43172f60UL, 0x84c87814a1f0ab72UL, 0x8cc702081a6439ecUL,
155 : 0x90befffa23631e28UL, 0xa4506cebde82bde9UL, 0xbef9a3f7b2c67915UL, 0xc67178f2e372532bUL,
156 : 0xca273eceea26619cUL, 0xd186b8c721c0c207UL, 0xeada7dd6cde0eb1eUL, 0xf57d4f7fee6ed178UL,
157 : 0x06f067aa72176fbaUL, 0x0a637dc5a2c898a6UL, 0x113f9804bef90daeUL, 0x1b710b35131c471bUL,
158 : 0x28db77f523047d84UL, 0x32caab7b40c72493UL, 0x3c9ebe0a15c9bebcUL, 0x431d67c49c100d4cUL,
159 : 0x4cc5d4becb3e42b6UL, 0x597f299cfc657e2aUL, 0x5fcb6fab3ad6faecUL, 0x6c44198c4a475817UL
160 : };
161 :
162 : # define ROTR fd_ulong_rotate_right
163 : # define Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39))
164 : # define Sigma1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41))
165 : # define sigma0(x) (ROTR((x), 1) ^ ROTR((x), 8) ^ ((x)>>7))
166 : # define sigma1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6))
167 : # define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
168 : # define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
169 :
170 : uchar const * W = block;
171 : do {
172 : ulong a = state[0];
173 : ulong b = state[1];
174 : ulong c = state[2];
175 : ulong d = state[3];
176 : ulong e = state[4];
177 : ulong f = state[5];
178 : ulong g = state[6];
179 : ulong h = state[7];
180 :
181 : ulong X[16];
182 :
183 : ulong i;
184 : for( i=0UL; i<16UL; i++ ) {
185 : X[i] = fd_ulong_bswap( FD_LOAD( ulong, W + i*sizeof(ulong) ) );
186 : ulong T1 = X[i] + h + Sigma1(e) + Ch(e, f, g) + K[i];
187 : ulong T2 = Sigma0(a) + Maj(a, b, c);
188 : h = g;
189 : g = f;
190 : f = e;
191 : e = d + T1;
192 : d = c;
193 : c = b;
194 : b = a;
195 : a = T1 + T2;
196 : }
197 : for( ; i<80UL; i++ ) {
198 : ulong s0 = X[(i + 1UL) & 0x0fUL];
199 : ulong s1 = X[(i + 14UL) & 0x0fUL];
200 : s0 = sigma0(s0);
201 : s1 = sigma1(s1);
202 : X[i & 0xfUL] += s0 + s1 + X[(i + 9UL) & 0xfUL];
203 : ulong T1 = X[i & 0xfUL ] + h + Sigma1(e) + Ch(e, f, g) + K[i];
204 : ulong T2 = Sigma0(a) + Maj(a, b, c);
205 : h = g;
206 : g = f;
207 : f = e;
208 : e = d + T1;
209 : d = c;
210 : c = b;
211 : b = a;
212 : a = T1 + T2;
213 : }
214 :
215 : state[0] += a;
216 : state[1] += b;
217 : state[2] += c;
218 : state[3] += d;
219 : state[4] += e;
220 : state[5] += f;
221 : state[6] += g;
222 : state[7] += h;
223 :
224 : W += 16UL*sizeof(ulong);
225 : } while( --block_cnt );
226 :
227 : # undef ROTR
228 : # undef Sigma0
229 : # undef Sigma1
230 : # undef sigma0
231 : # undef sigma1
232 : # undef Ch
233 : # undef Maj
234 :
235 : }
236 :
237 : #define fd_sha512_core fd_sha512_core_ref
238 :
239 : #elif FD_SHA512_CORE_IMPL==1
240 :
241 : __attribute__((sysv_abi))
242 : void
243 : fd_sha512_core_avx2( ulong * state, /* 64-byte aligned, 8 entries */
244 : uchar const * block, /* ideally 128-byte aligned (but not required), 128*block_cnt in size */
245 : ulong block_cnt ); /* positive */
246 :
247 8716573 : #define fd_sha512_core fd_sha512_core_avx2
248 :
249 : #elif FD_SHA512_CORE_IMPL==2
250 :
251 : static void
252 : fd_sha512_core_arm( ulong * state,
253 : uchar const * block,
254 : ulong block_cnt ) {
255 :
256 : static ulong const K[80] = {
257 : 0x428a2f98d728ae22UL, 0x7137449123ef65cdUL, 0xb5c0fbcfec4d3b2fUL, 0xe9b5dba58189dbbcUL,
258 : 0x3956c25bf348b538UL, 0x59f111f1b605d019UL, 0x923f82a4af194f9bUL, 0xab1c5ed5da6d8118UL,
259 : 0xd807aa98a3030242UL, 0x12835b0145706fbeUL, 0x243185be4ee4b28cUL, 0x550c7dc3d5ffb4e2UL,
260 : 0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL, 0x9bdc06a725c71235UL, 0xc19bf174cf692694UL,
261 : 0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL, 0x0fc19dc68b8cd5b5UL, 0x240ca1cc77ac9c65UL,
262 : 0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL, 0x5cb0a9dcbd41fbd4UL, 0x76f988da831153b5UL,
263 : 0x983e5152ee66dfabUL, 0xa831c66d2db43210UL, 0xb00327c898fb213fUL, 0xbf597fc7beef0ee4UL,
264 : 0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL, 0x06ca6351e003826fUL, 0x142929670a0e6e70UL,
265 : 0x27b70a8546d22ffcUL, 0x2e1b21385c26c926UL, 0x4d2c6dfc5ac42aedUL, 0x53380d139d95b3dfUL,
266 : 0x650a73548baf63deUL, 0x766a0abb3c77b2a8UL, 0x81c2c92e47edaee6UL, 0x92722c851482353bUL,
267 : 0xa2bfe8a14cf10364UL, 0xa81a664bbc423001UL, 0xc24b8b70d0f89791UL, 0xc76c51a30654be30UL,
268 : 0xd192e819d6ef5218UL, 0xd69906245565a910UL, 0xf40e35855771202aUL, 0x106aa07032bbd1b8UL,
269 : 0x19a4c116b8d2d0c8UL, 0x1e376c085141ab53UL, 0x2748774cdf8eeb99UL, 0x34b0bcb5e19b48a8UL,
270 : 0x391c0cb3c5c95a63UL, 0x4ed8aa4ae3418acbUL, 0x5b9cca4f7763e373UL, 0x682e6ff3d6b2b8a3UL,
271 : 0x748f82ee5defb2fcUL, 0x78a5636f43172f60UL, 0x84c87814a1f0ab72UL, 0x8cc702081a6439ecUL,
272 : 0x90befffa23631e28UL, 0xa4506cebde82bde9UL, 0xbef9a3f7b2c67915UL, 0xc67178f2e372532bUL,
273 : 0xca273eceea26619cUL, 0xd186b8c721c0c207UL, 0xeada7dd6cde0eb1eUL, 0xf57d4f7fee6ed178UL,
274 : 0x06f067aa72176fbaUL, 0x0a637dc5a2c898a6UL, 0x113f9804bef90daeUL, 0x1b710b35131c471bUL,
275 : 0x28db77f523047d84UL, 0x32caab7b40c72493UL, 0x3c9ebe0a15c9bebcUL, 0x431d67c49c100d4cUL,
276 : 0x4cc5d4becb3e42b6UL, 0x597f299cfc657e2aUL, 0x5fcb6fab3ad6faecUL, 0x6c44198c4a475817UL
277 : };
278 :
279 : #define SHA512_ROUNDS( MSG, KIDX ) do { \
280 : uint64x2_t ab_prev = ab; \
281 : uint64x2_t ef_prev = ef; \
282 : uint64x2_t wk = vaddq_u64( (MSG), vld1q_u64( K + (KIDX) ) ); \
283 : wk = vextq_u64( wk, wk, 1 ); \
284 : uint64x2_t fg = vextq_u64( ef, gh, 1 ); \
285 : uint64x2_t de = vextq_u64( cd, ef, 1 ); \
286 : gh = vaddq_u64( gh, wk ); \
287 : gh = vsha512hq_u64( gh, fg, de ); \
288 : uint64x2_t new_ef = vaddq_u64( cd, gh ); \
289 : gh = vsha512h2q_u64( gh, cd, ab ); \
290 : ab = gh; \
291 : cd = ab_prev; \
292 : ef = new_ef; \
293 : gh = ef_prev; \
294 : } while( 0 )
295 :
296 : #define SHA512_SCHEDULE( MSG0, MSG1, MSG4, MSG5, MSG7 ) do { \
297 : (MSG0) = vsha512su0q_u64( (MSG0), (MSG1) ); \
298 : uint64x2_t w9_10 = vextq_u64( (MSG4), (MSG5), 1 ); \
299 : (MSG0) = vsha512su1q_u64( (MSG0), (MSG7), w9_10 ); \
300 : } while( 0 )
301 :
302 : do {
303 : uint64x2_t ab = vld1q_u64( state );
304 : uint64x2_t cd = vld1q_u64( state+2 );
305 : uint64x2_t ef = vld1q_u64( state+4 );
306 : uint64x2_t gh = vld1q_u64( state+6 );
307 : uint64x2_t ab_init = ab;
308 : uint64x2_t cd_init = cd;
309 : uint64x2_t ef_init = ef;
310 : uint64x2_t gh_init = gh;
311 :
312 : uint64x2_t msg0 = vreinterpretq_u64_u8( vrev64q_u8( vld1q_u8( block ) ) );
313 : uint64x2_t msg1 = vreinterpretq_u64_u8( vrev64q_u8( vld1q_u8( block+ 16UL ) ) );
314 : uint64x2_t msg2 = vreinterpretq_u64_u8( vrev64q_u8( vld1q_u8( block+ 32UL ) ) );
315 : uint64x2_t msg3 = vreinterpretq_u64_u8( vrev64q_u8( vld1q_u8( block+ 48UL ) ) );
316 : uint64x2_t msg4 = vreinterpretq_u64_u8( vrev64q_u8( vld1q_u8( block+ 64UL ) ) );
317 : uint64x2_t msg5 = vreinterpretq_u64_u8( vrev64q_u8( vld1q_u8( block+ 80UL ) ) );
318 : uint64x2_t msg6 = vreinterpretq_u64_u8( vrev64q_u8( vld1q_u8( block+ 96UL ) ) );
319 : uint64x2_t msg7 = vreinterpretq_u64_u8( vrev64q_u8( vld1q_u8( block+112UL ) ) );
320 :
321 : SHA512_ROUNDS( msg0, 0 ); SHA512_SCHEDULE( msg0, msg1, msg4, msg5, msg7 );
322 : SHA512_ROUNDS( msg1, 2 ); SHA512_SCHEDULE( msg1, msg2, msg5, msg6, msg0 );
323 : SHA512_ROUNDS( msg2, 4 ); SHA512_SCHEDULE( msg2, msg3, msg6, msg7, msg1 );
324 : SHA512_ROUNDS( msg3, 6 ); SHA512_SCHEDULE( msg3, msg4, msg7, msg0, msg2 );
325 : SHA512_ROUNDS( msg4, 8 ); SHA512_SCHEDULE( msg4, msg5, msg0, msg1, msg3 );
326 : SHA512_ROUNDS( msg5, 10 ); SHA512_SCHEDULE( msg5, msg6, msg1, msg2, msg4 );
327 : SHA512_ROUNDS( msg6, 12 ); SHA512_SCHEDULE( msg6, msg7, msg2, msg3, msg5 );
328 : SHA512_ROUNDS( msg7, 14 ); SHA512_SCHEDULE( msg7, msg0, msg3, msg4, msg6 );
329 : SHA512_ROUNDS( msg0, 16 ); SHA512_SCHEDULE( msg0, msg1, msg4, msg5, msg7 );
330 : SHA512_ROUNDS( msg1, 18 ); SHA512_SCHEDULE( msg1, msg2, msg5, msg6, msg0 );
331 : SHA512_ROUNDS( msg2, 20 ); SHA512_SCHEDULE( msg2, msg3, msg6, msg7, msg1 );
332 : SHA512_ROUNDS( msg3, 22 ); SHA512_SCHEDULE( msg3, msg4, msg7, msg0, msg2 );
333 : SHA512_ROUNDS( msg4, 24 ); SHA512_SCHEDULE( msg4, msg5, msg0, msg1, msg3 );
334 : SHA512_ROUNDS( msg5, 26 ); SHA512_SCHEDULE( msg5, msg6, msg1, msg2, msg4 );
335 : SHA512_ROUNDS( msg6, 28 ); SHA512_SCHEDULE( msg6, msg7, msg2, msg3, msg5 );
336 : SHA512_ROUNDS( msg7, 30 ); SHA512_SCHEDULE( msg7, msg0, msg3, msg4, msg6 );
337 : SHA512_ROUNDS( msg0, 32 ); SHA512_SCHEDULE( msg0, msg1, msg4, msg5, msg7 );
338 : SHA512_ROUNDS( msg1, 34 ); SHA512_SCHEDULE( msg1, msg2, msg5, msg6, msg0 );
339 : SHA512_ROUNDS( msg2, 36 ); SHA512_SCHEDULE( msg2, msg3, msg6, msg7, msg1 );
340 : SHA512_ROUNDS( msg3, 38 ); SHA512_SCHEDULE( msg3, msg4, msg7, msg0, msg2 );
341 : SHA512_ROUNDS( msg4, 40 ); SHA512_SCHEDULE( msg4, msg5, msg0, msg1, msg3 );
342 : SHA512_ROUNDS( msg5, 42 ); SHA512_SCHEDULE( msg5, msg6, msg1, msg2, msg4 );
343 : SHA512_ROUNDS( msg6, 44 ); SHA512_SCHEDULE( msg6, msg7, msg2, msg3, msg5 );
344 : SHA512_ROUNDS( msg7, 46 ); SHA512_SCHEDULE( msg7, msg0, msg3, msg4, msg6 );
345 : SHA512_ROUNDS( msg0, 48 ); SHA512_SCHEDULE( msg0, msg1, msg4, msg5, msg7 );
346 : SHA512_ROUNDS( msg1, 50 ); SHA512_SCHEDULE( msg1, msg2, msg5, msg6, msg0 );
347 : SHA512_ROUNDS( msg2, 52 ); SHA512_SCHEDULE( msg2, msg3, msg6, msg7, msg1 );
348 : SHA512_ROUNDS( msg3, 54 ); SHA512_SCHEDULE( msg3, msg4, msg7, msg0, msg2 );
349 : SHA512_ROUNDS( msg4, 56 ); SHA512_SCHEDULE( msg4, msg5, msg0, msg1, msg3 );
350 : SHA512_ROUNDS( msg5, 58 ); SHA512_SCHEDULE( msg5, msg6, msg1, msg2, msg4 );
351 : SHA512_ROUNDS( msg6, 60 ); SHA512_SCHEDULE( msg6, msg7, msg2, msg3, msg5 );
352 : SHA512_ROUNDS( msg7, 62 ); SHA512_SCHEDULE( msg7, msg0, msg3, msg4, msg6 );
353 : SHA512_ROUNDS( msg0, 64 );
354 : SHA512_ROUNDS( msg1, 66 );
355 : SHA512_ROUNDS( msg2, 68 );
356 : SHA512_ROUNDS( msg3, 70 );
357 : SHA512_ROUNDS( msg4, 72 );
358 : SHA512_ROUNDS( msg5, 74 );
359 : SHA512_ROUNDS( msg6, 76 );
360 : SHA512_ROUNDS( msg7, 78 );
361 :
362 : vst1q_u64( state, vaddq_u64( ab, ab_init ) );
363 : vst1q_u64( state+2, vaddq_u64( cd, cd_init ) );
364 : vst1q_u64( state+4, vaddq_u64( ef, ef_init ) );
365 : vst1q_u64( state+6, vaddq_u64( gh, gh_init ) );
366 : block += FD_SHA512_BLOCK_SZ;
367 : } while( --block_cnt );
368 :
369 : #undef SHA512_SCHEDULE
370 : #undef SHA512_ROUNDS
371 : }
372 :
373 : #define fd_sha512_core fd_sha512_core_arm
374 :
375 : #else
376 : #error "Unsupported FD_SHA512_CORE_IMPL"
377 : #endif
378 :
379 : fd_sha512_t *
380 2118 : fd_sha384_init( fd_sha512_t * sha ) {
381 : /* sha->buf d/c */
382 2118 : sha->state[0] = 0xcbbb9d5dc1059ed8UL;
383 2118 : sha->state[1] = 0x629a292a367cd507UL;
384 2118 : sha->state[2] = 0x9159015a3070dd17UL;
385 2118 : sha->state[3] = 0x152fecd8f70e5939UL;
386 2118 : sha->state[4] = 0x67332667ffc00b31UL;
387 2118 : sha->state[5] = 0x8eb44a8768581511UL;
388 2118 : sha->state[6] = 0xdb0c2e0d64f98fa7UL;
389 2118 : sha->state[7] = 0x47b5481dbefa4fa4UL;
390 2118 : sha->buf_used = 0U;
391 2118 : sha->bit_cnt_lo = 0UL;
392 2118 : sha->bit_cnt_hi = 0UL;
393 2118 : return sha;
394 2118 : }
395 :
396 : fd_sha512_t *
397 846828 : fd_sha512_init( fd_sha512_t * sha ) {
398 : /* sha->buf d/c */
399 846828 : sha->state[0] = 0x6a09e667f3bcc908UL;
400 846828 : sha->state[1] = 0xbb67ae8584caa73bUL;
401 846828 : sha->state[2] = 0x3c6ef372fe94f82bUL;
402 846828 : sha->state[3] = 0xa54ff53a5f1d36f1UL;
403 846828 : sha->state[4] = 0x510e527fade682d1UL;
404 846828 : sha->state[5] = 0x9b05688c2b3e6c1fUL;
405 846828 : sha->state[6] = 0x1f83d9abfb41bd6bUL;
406 846828 : sha->state[7] = 0x5be0cd19137e2179UL;
407 846828 : sha->buf_used = 0U;
408 846828 : sha->bit_cnt_lo = 0UL;
409 846828 : sha->bit_cnt_hi = 0UL;
410 846828 : return sha;
411 846828 : }
412 :
413 : fd_sha512_t *
414 : fd_sha512_append( fd_sha512_t * sha,
415 : void const * _data,
416 4443267 : ulong sz ) {
417 :
418 : /* If no data to append, we are done */
419 :
420 4443267 : if( FD_UNLIKELY( !sz ) ) return sha; /* optimize for non-trivial append */
421 :
422 : /* Unpack inputs */
423 :
424 4442505 : ulong * state = sha->state;
425 4442505 : uchar * buf = sha->buf;
426 4442505 : ulong buf_used = sha->buf_used;
427 4442505 : ulong bit_cnt_lo = sha->bit_cnt_lo;
428 4442505 : ulong bit_cnt_hi = sha->bit_cnt_hi;
429 :
430 4442505 : uchar const * data = (uchar const *)_data;
431 :
432 : /* Update bit_cnt */
433 : /* FIXME: could accumulate bytes here and do bit conversion in append */
434 :
435 4442505 : ulong new_bit_cnt_lo = bit_cnt_lo + (sz<< 3);
436 4442505 : ulong new_bit_cnt_hi = bit_cnt_hi + (sz>>61) + (ulong)(new_bit_cnt_lo<bit_cnt_lo);
437 :
438 4442505 : sha->bit_cnt_lo = new_bit_cnt_lo;
439 4442505 : sha->bit_cnt_hi = new_bit_cnt_hi;
440 :
441 : /* Handle buffered bytes from previous appends */
442 :
443 4442505 : if( FD_UNLIKELY( buf_used ) ) { /* optimized for well aligned use of append */
444 :
445 : /* If the append isn't large enough to complete the current block,
446 : buffer these bytes too and return */
447 :
448 655896 : ulong buf_rem = FD_SHA512_PRIVATE_BUF_MAX - buf_used; /* In (0,FD_SHA512_PRIVATE_BUF_MAX) */
449 655896 : if( FD_UNLIKELY( sz < buf_rem ) ) { /* optimize for large append */
450 610041 : fd_memcpy( buf + buf_used, data, sz );
451 610041 : sha->buf_used = buf_used + sz;
452 610041 : return sha;
453 610041 : }
454 :
455 : /* Otherwise, buffer enough leading bytes of data to complete the
456 : block, update the hash and then continue processing any remaining
457 : bytes of data. */
458 :
459 45855 : fd_memcpy( buf + buf_used, data, buf_rem );
460 45855 : data += buf_rem;
461 45855 : sz -= buf_rem;
462 :
463 45855 : fd_sha512_core( state, buf, 1UL );
464 45855 : sha->buf_used = 0UL;
465 45855 : }
466 :
467 : /* Append the bulk of the data */
468 :
469 3832464 : ulong block_cnt = sz >> FD_SHA512_PRIVATE_LG_BUF_MAX;
470 3832464 : if( FD_LIKELY( block_cnt ) ) fd_sha512_core( state, data, block_cnt ); /* optimized for large append */
471 :
472 : /* Buffer any leftover bytes */
473 :
474 3832464 : buf_used = sz & (FD_SHA512_PRIVATE_BUF_MAX-1UL); /* In [0,FD_SHA512_PRIVATE_BUF_MAX) */
475 3832464 : if( FD_UNLIKELY( buf_used ) ) { /* optimized for well aligned use of append */
476 685504 : fd_memcpy( buf, data + (block_cnt << FD_SHA512_PRIVATE_LG_BUF_MAX), buf_used );
477 685504 : sha->buf_used = buf_used; /* In (0,FD_SHA512_PRIVATE_BUF_MAX) */
478 685504 : }
479 :
480 3832464 : return sha;
481 4442505 : }
482 :
483 : void *
484 : fd_sha512_fini( fd_sha512_t * sha,
485 641238 : void * _hash ) {
486 :
487 : /* Unpack inputs */
488 :
489 641238 : ulong * state = sha->state;
490 641238 : uchar * buf = sha->buf;
491 641238 : ulong buf_used = sha->buf_used; /* In [0,FD_SHA512_PRIVATE_BUF_MAX) */
492 641238 : ulong bit_cnt_lo = sha->bit_cnt_lo;
493 641238 : ulong bit_cnt_hi = sha->bit_cnt_hi;
494 :
495 : /* Append the terminating message byte */
496 :
497 641238 : buf[ buf_used ] = (uchar)0x80;
498 641238 : buf_used++;
499 :
500 : /* If there isn't enough room to save the message length in bits at
501 : the end of the in progress block, clear the rest of the in progress
502 : block, update the hash and start a new block. */
503 :
504 641238 : if( FD_UNLIKELY( buf_used > FD_SHA512_PRIVATE_BUF_MAX-16UL ) ) { /* optimize for well aligned use of append */
505 1045 : fd_memset( buf + buf_used, 0, FD_SHA512_PRIVATE_BUF_MAX-buf_used );
506 1045 : fd_sha512_core( state, buf, 1UL );
507 1045 : buf_used = 0UL;
508 1045 : }
509 :
510 : /* Clear in progress block up to last 128-bits, append the message
511 : size in bytes in the last 128-bits of the in progress block and
512 : update the hash to finalize it. */
513 :
514 641238 : fd_memset( buf + buf_used, 0, FD_SHA512_PRIVATE_BUF_MAX-16UL-buf_used );
515 641238 : *((ulong *)(buf+FD_SHA512_PRIVATE_BUF_MAX-16UL)) = fd_ulong_bswap( bit_cnt_hi );
516 641238 : *((ulong *)(buf+FD_SHA512_PRIVATE_BUF_MAX- 8UL)) = fd_ulong_bswap( bit_cnt_lo );
517 641238 : fd_sha512_core( state, buf, 1UL );
518 :
519 : /* Unpack the result into md (annoying bswaps here) */
520 :
521 641238 : uchar * hash = (uchar *)_hash;
522 641238 : FD_STORE( ulong, hash, fd_ulong_bswap( state[0] ) );
523 641238 : FD_STORE( ulong, hash+ 8UL, fd_ulong_bswap( state[1] ) );
524 641238 : FD_STORE( ulong, hash+16UL, fd_ulong_bswap( state[2] ) );
525 641238 : FD_STORE( ulong, hash+24UL, fd_ulong_bswap( state[3] ) );
526 641238 : FD_STORE( ulong, hash+32UL, fd_ulong_bswap( state[4] ) );
527 641238 : FD_STORE( ulong, hash+40UL, fd_ulong_bswap( state[5] ) );
528 641238 : FD_STORE( ulong, hash+48UL, fd_ulong_bswap( state[6] ) );
529 641238 : FD_STORE( ulong, hash+56UL, fd_ulong_bswap( state[7] ) );
530 641238 : return _hash;
531 641238 : }
532 :
533 : void *
534 : fd_sha384_fini( fd_sha512_t * sha,
535 2118 : void * _hash ) {
536 2118 : uchar hash[ FD_SHA512_HASH_SZ ] __attribute__((aligned(64)));
537 2118 : fd_sha512_fini( sha, hash );
538 2118 : memcpy( _hash, hash, FD_SHA384_HASH_SZ );
539 2118 : return _hash;
540 2118 : }
541 :
542 : void *
543 : fd_sha512_hash( void const * _data,
544 : ulong sz,
545 2933100 : void * _hash ) {
546 2933100 : uchar const * data = (uchar const *)_data;
547 :
548 : /* This is just the above streamlined to eliminate all the overheads
549 : to support incremental hashing. */
550 :
551 2933100 : uchar buf[ FD_SHA512_PRIVATE_BUF_MAX ] __attribute__((aligned(128)));
552 2933100 : ulong state[8] __attribute__((aligned(64)));
553 :
554 2933100 : state[0] = 0x6a09e667f3bcc908UL;
555 2933100 : state[1] = 0xbb67ae8584caa73bUL;
556 2933100 : state[2] = 0x3c6ef372fe94f82bUL;
557 2933100 : state[3] = 0xa54ff53a5f1d36f1UL;
558 2933100 : state[4] = 0x510e527fade682d1UL;
559 2933100 : state[5] = 0x9b05688c2b3e6c1fUL;
560 2933100 : state[6] = 0x1f83d9abfb41bd6bUL;
561 2933100 : state[7] = 0x5be0cd19137e2179UL;
562 :
563 2933100 : ulong block_cnt = sz >> FD_SHA512_PRIVATE_LG_BUF_MAX;
564 2933100 : if( FD_LIKELY( block_cnt ) ) fd_sha512_core( state, data, block_cnt );
565 :
566 2933100 : ulong buf_used = sz & (FD_SHA512_PRIVATE_BUF_MAX-1UL);
567 2933100 : if( FD_UNLIKELY( buf_used ) ) fd_memcpy( buf, data + (block_cnt << FD_SHA512_PRIVATE_LG_BUF_MAX), buf_used );
568 2933100 : buf[ buf_used ] = (uchar)0x80;
569 2933100 : buf_used++;
570 :
571 2933100 : if( FD_UNLIKELY( buf_used > (FD_SHA512_PRIVATE_BUF_MAX-16UL) ) ) {
572 287975 : fd_memset( buf + buf_used, 0, FD_SHA512_PRIVATE_BUF_MAX-buf_used );
573 287975 : fd_sha512_core( state, buf, 1UL );
574 287975 : buf_used = 0UL;
575 287975 : }
576 :
577 2933100 : ulong bit_cnt_lo = sz<< 3;
578 2933100 : ulong bit_cnt_hi = sz>>61;
579 2933100 : fd_memset( buf + buf_used, 0, FD_SHA512_PRIVATE_BUF_MAX-16UL-buf_used );
580 2933100 : *((ulong *)(buf+FD_SHA512_PRIVATE_BUF_MAX-16UL)) = fd_ulong_bswap( bit_cnt_hi );
581 2933100 : *((ulong *)(buf+FD_SHA512_PRIVATE_BUF_MAX- 8UL)) = fd_ulong_bswap( bit_cnt_lo );
582 2933100 : fd_sha512_core( state, buf, 1UL );
583 :
584 2933100 : uchar * hash = (uchar *)_hash;
585 2933100 : FD_STORE( ulong, hash, fd_ulong_bswap( state[0] ) );
586 2933100 : FD_STORE( ulong, hash+ 8UL, fd_ulong_bswap( state[1] ) );
587 2933100 : FD_STORE( ulong, hash+16UL, fd_ulong_bswap( state[2] ) );
588 2933100 : FD_STORE( ulong, hash+24UL, fd_ulong_bswap( state[3] ) );
589 2933100 : FD_STORE( ulong, hash+32UL, fd_ulong_bswap( state[4] ) );
590 2933100 : FD_STORE( ulong, hash+40UL, fd_ulong_bswap( state[5] ) );
591 2933100 : FD_STORE( ulong, hash+48UL, fd_ulong_bswap( state[6] ) );
592 2933100 : FD_STORE( ulong, hash+56UL, fd_ulong_bswap( state[7] ) );
593 2933100 : return _hash;
594 2933100 : }
595 :
596 : void *
597 : fd_sha384_hash( void const * _data,
598 : ulong sz,
599 2937 : void * _hash ) {
600 2937 : uchar const * data = (uchar const *)_data;
601 :
602 : /* This is just the above streamlined to eliminate all the overheads
603 : to support incremental hashing. */
604 :
605 2937 : uchar buf[ FD_SHA512_PRIVATE_BUF_MAX ] __attribute__((aligned(128)));
606 2937 : ulong state[8] __attribute__((aligned(64)));
607 :
608 2937 : state[0] = 0xcbbb9d5dc1059ed8UL;
609 2937 : state[1] = 0x629a292a367cd507UL;
610 2937 : state[2] = 0x9159015a3070dd17UL;
611 2937 : state[3] = 0x152fecd8f70e5939UL;
612 2937 : state[4] = 0x67332667ffc00b31UL;
613 2937 : state[5] = 0x8eb44a8768581511UL;
614 2937 : state[6] = 0xdb0c2e0d64f98fa7UL;
615 2937 : state[7] = 0x47b5481dbefa4fa4UL;
616 :
617 2937 : ulong block_cnt = sz >> FD_SHA512_PRIVATE_LG_BUF_MAX;
618 2937 : if( FD_LIKELY( block_cnt ) ) fd_sha512_core( state, data, block_cnt );
619 :
620 2937 : ulong buf_used = sz & (FD_SHA512_PRIVATE_BUF_MAX-1UL);
621 2937 : if( FD_UNLIKELY( buf_used ) ) fd_memcpy( buf, data + (block_cnt << FD_SHA512_PRIVATE_LG_BUF_MAX), buf_used );
622 2937 : buf[ buf_used ] = (uchar)0x80;
623 2937 : buf_used++;
624 :
625 2937 : if( FD_UNLIKELY( buf_used > (FD_SHA512_PRIVATE_BUF_MAX-16UL) ) ) {
626 195 : fd_memset( buf + buf_used, 0, FD_SHA512_PRIVATE_BUF_MAX-buf_used );
627 195 : fd_sha512_core( state, buf, 1UL );
628 195 : buf_used = 0UL;
629 195 : }
630 :
631 2937 : ulong bit_cnt_lo = sz<< 3;
632 2937 : ulong bit_cnt_hi = sz>>61;
633 2937 : fd_memset( buf + buf_used, 0, FD_SHA512_PRIVATE_BUF_MAX-16UL-buf_used );
634 2937 : *((ulong *)(buf+FD_SHA512_PRIVATE_BUF_MAX-16UL)) = fd_ulong_bswap( bit_cnt_hi );
635 2937 : *((ulong *)(buf+FD_SHA512_PRIVATE_BUF_MAX- 8UL)) = fd_ulong_bswap( bit_cnt_lo );
636 2937 : fd_sha512_core( state, buf, 1UL );
637 :
638 2937 : uchar * hash = (uchar *)_hash;
639 2937 : FD_STORE( ulong, hash, fd_ulong_bswap( state[0] ) );
640 2937 : FD_STORE( ulong, hash+ 8UL, fd_ulong_bswap( state[1] ) );
641 2937 : FD_STORE( ulong, hash+16UL, fd_ulong_bswap( state[2] ) );
642 2937 : FD_STORE( ulong, hash+24UL, fd_ulong_bswap( state[3] ) );
643 2937 : FD_STORE( ulong, hash+32UL, fd_ulong_bswap( state[4] ) );
644 2937 : FD_STORE( ulong, hash+40UL, fd_ulong_bswap( state[5] ) );
645 2937 : return _hash;
646 2937 : }
647 :
648 : #undef fd_sha512_core
|