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