LCOV - code coverage report
Current view: top level - ballet/sha512 - fd_sha512.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 234 240 97.5 %
Date: 2026-09-17 04:28:31 Functions: 13 13 100.0 %

          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

Generated by: LCOV version 1.14