LCOV - code coverage report
Current view: top level - ballet/siphash13 - fd_siphash13.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 113 113 100.0 %
Date: 2024-11-13 11:58:15 Functions: 6 6 100.0 %

          Line data    Source code
       1             : #include "fd_siphash13.h"
       2             : 
       3             : /* This code is a modified version of https://github.com/antirez/siphash
       4             :    For further license info see NOTICE in the root of this repo.
       5             : 
       6             :    Copyright (c) 2012-2016 Jean-Philippe Aumasson
       7             :    <jeanphilippe.aumasson@gmail.com>
       8             :    Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
       9             :    Copyright (c) 2017 Salvatore Sanfilippo <antirez@gmail.com>
      10             :    Modified 2023 by Firedancer Contributors */
      11             : 
      12             : static const ulong __attribute__((aligned(64UL)))
      13             : fd_siphash13_initial[4] = {
      14             :   0x736f6d6570736575UL,
      15             :   0x646f72616e646f6dUL,
      16             :   0x6c7967656e657261UL,
      17             :   0x7465646279746573UL,
      18             : };
      19             : 
      20             : fd_siphash13_t *
      21             : fd_siphash13_init( fd_siphash13_t * sip,
      22             :                    ulong            k0,
      23           9 :                    ulong            k1 ) {
      24             : 
      25           9 :   memset( sip, 0, sizeof(fd_siphash13_t) );
      26             : 
      27           9 :   ulong * v = sip->v;
      28             : 
      29           9 :   v[ 0 ] = fd_siphash13_initial[ 0 ];
      30           9 :   v[ 1 ] = fd_siphash13_initial[ 1 ];
      31           9 :   v[ 2 ] = fd_siphash13_initial[ 2 ];
      32           9 :   v[ 3 ] = fd_siphash13_initial[ 3 ];
      33           9 :   v[ 3 ] ^= k1;
      34           9 :   v[ 2 ] ^= k0;
      35           9 :   v[ 1 ] ^= k1;
      36           9 :   v[ 0 ] ^= k0;
      37             : 
      38           9 :   return sip;
      39           9 : }
      40             : 
      41             : static void
      42             : fd_siphash1N_core( ulong         v[ static 4 ],
      43             :                    uchar const * buf,
      44   120120216 :                    ulong         n ) {
      45   120120216 :   ulong m;
      46   420420432 :   for( ulong i=0UL; i<n; i++ ) {
      47   300300216 :     m = ((ulong const *)buf)[ i ];
      48   300300216 :     v[ 3 ] ^= m;
      49   300300216 :     FD_SIPHASH_ROUND( v );
      50   300300216 :     v[ 0 ] ^= m;
      51   300300216 :   }
      52   120120216 : }
      53             : 
      54             : fd_siphash13_t *
      55             : fd_siphash13_append( fd_siphash13_t * sip,
      56             :                      uchar const *    data,
      57    30030192 :                      ulong            sz ) {
      58             : 
      59    30030192 :   ulong * v        = sip->v;
      60    30030192 :   uchar * buf      = sip->buf;
      61    30030192 :   ulong   buf_used = sip->n & 7UL;
      62             : 
      63    30030192 :   sip->n += sz;
      64             : 
      65    30030192 :   if( FD_UNLIKELY( buf_used ) ) { /* optimized for well aligned use of append */
      66             : 
      67             :     /* If the append isn't large enough to complete the current block,
      68             :        buffer these bytes too and return */
      69             : 
      70         168 :     ulong buf_rem = 8UL - buf_used;
      71         168 :     if( FD_UNLIKELY( sz < buf_rem ) ) {
      72         144 :       fd_memcpy( buf + buf_used, data, sz );
      73         144 :       return sip;
      74         144 :     }
      75             : 
      76             :     /* Otherwise, buffer enough leading bytes of data complete the
      77             :        block, update the hash and then continue processing any remaining
      78             :        bytes of data. */
      79             : 
      80          24 :     fd_memcpy( buf + buf_used, data, buf_rem );
      81          24 :     data += buf_rem;
      82          24 :     sz   -= buf_rem;
      83             : 
      84          24 :     fd_siphash1N_core( v, buf, 1UL );
      85          24 :   }
      86             : 
      87             :   /* Append the bulk of the data */
      88             : 
      89    30030048 :   ulong block_cnt = sz >> 3;
      90    30030048 :   if( FD_LIKELY( block_cnt ) ) fd_siphash1N_core( v, data, block_cnt );
      91             : 
      92             :   /* Buffer any leftover bytes */
      93             : 
      94    30030048 :   buf_used = sz & 7UL;
      95    30030048 :   if( FD_UNLIKELY( buf_used ) )
      96          24 :     fd_memcpy( buf, data + (sz - buf_used), buf_used );
      97             : 
      98    30030048 :   return sip;
      99    30030192 : }
     100             : 
     101             : fd_siphash13_t *
     102             : fd_siphash13_append_fast( fd_siphash13_t * sip,
     103             :                           uchar const *    data,
     104    30030000 :                           ulong            sz ) {
     105             :   /* TODO debug assertions */
     106    30030000 :   sip->n += sz;
     107    30030000 :   fd_siphash1N_core( sip->v, data, sz >> 3 );
     108    30030000 :   return sip;
     109    30030000 : }
     110             : 
     111             : ulong
     112    60060192 : fd_siphash13_fini( fd_siphash13_t * sip ) {
     113             : 
     114             :   /* Unpack inputs */
     115             : 
     116    60060192 :   ulong * v        = sip->v;
     117    60060192 :   uchar * buf      = sip->buf;
     118    60060192 :   ulong   n        = sip->n;
     119    60060192 :   ulong   buf_used = sip->n & 7UL;
     120             : 
     121             :   /* Hash last block */
     122             : 
     123    60060192 :   ulong b = n<<56UL;
     124    60060192 :   switch( buf_used ) {
     125          24 :     case 7: b |= ((ulong)buf[6]) << 48; __attribute__((fallthrough));
     126          48 :     case 6: b |= ((ulong)buf[5]) << 40; __attribute__((fallthrough));
     127          72 :     case 5: b |= ((ulong)buf[4]) << 32; __attribute__((fallthrough));
     128          96 :     case 4: b |= ((ulong)buf[3]) << 24; __attribute__((fallthrough));
     129         120 :     case 3: b |= ((ulong)buf[2]) << 16; __attribute__((fallthrough));
     130         144 :     case 2: b |= ((ulong)buf[1]) <<  8; __attribute__((fallthrough));
     131         168 :     case 1: b |= ((ulong)buf[0]); break;
     132    60060024 :     case 0: break;
     133    60060192 :   }
     134    60060192 :   fd_siphash1N_core( v, (uchar const *)&b, 1UL );
     135             : 
     136             :   /* Finalize */
     137             : 
     138    60060192 :   v[ 2 ] ^= 0xff;
     139    60060192 :   FD_SIPHASH_ROUND( v );
     140    60060192 :   FD_SIPHASH_ROUND( v );
     141    60060192 :   FD_SIPHASH_ROUND( v );
     142    60060192 :   b = v[ 0 ] ^ v[ 1 ] ^ v[ 2 ] ^ v[ 3 ];
     143    60060192 :   return b;
     144    60060192 : }
     145             : 
     146             : FD_FN_PURE ulong
     147             : fd_siphash13_hash( void const * data,
     148             :                    ulong        data_sz,
     149             :                    ulong        k0,
     150      330192 :                    ulong        k1 ) {
     151             : 
     152             :   /* Initialize */
     153             : 
     154      330192 :   ulong v[ 4 ];
     155      330192 :   memcpy( v, fd_siphash13_initial, 32UL );
     156             : 
     157      330192 :   v[ 3 ] ^= k1;
     158      330192 :   v[ 2 ] ^= k0;
     159      330192 :   v[ 1 ] ^= k1;
     160      330192 :   v[ 0 ] ^= k0;
     161             : 
     162             :   /* Hash blocks */
     163             : 
     164      330192 :   ulong m;
     165      330192 :   ulong const * in    = (ulong const *)data;
     166      330192 :   ulong const * end   = in + data_sz/8UL;
     167     1650864 :   for( ; in!=end; in++ ) {
     168     1320672 :     m = *in;
     169     1320672 :     v[ 3 ] ^= m;
     170     1320672 :     FD_SIPHASH_ROUND( v );
     171     1320672 :     v[ 0 ] ^= m;
     172     1320672 :   }
     173             : 
     174             :   /* Hash last block */
     175             : 
     176      330192 :   int const     left = data_sz & 7;
     177      330192 :   ulong         b    = ((ulong)data_sz) << 56;
     178      330192 :   uchar const * rem  = (uchar const *)in;
     179      330192 :   switch( left ) {
     180          24 :     case 7: b |= ((ulong)rem[6]) << 48; __attribute__((fallthrough));
     181          48 :     case 6: b |= ((ulong)rem[5]) << 40; __attribute__((fallthrough));
     182          72 :     case 5: b |= ((ulong)rem[4]) << 32; __attribute__((fallthrough));
     183          96 :     case 4: b |= ((ulong)rem[3]) << 24; __attribute__((fallthrough));
     184         120 :     case 3: b |= ((ulong)rem[2]) << 16; __attribute__((fallthrough));
     185         144 :     case 2: b |= ((ulong)rem[1]) <<  8; __attribute__((fallthrough));
     186         168 :     case 1: b |= ((ulong)rem[0]); break;
     187      330024 :     case 0: break;
     188      330192 :   }
     189             : 
     190      330192 :   v[ 3 ] ^= b;
     191      330192 :   FD_SIPHASH_ROUND( v );
     192      330192 :   v[ 0 ] ^= b;
     193             : 
     194             :   /* Finalize */
     195             : 
     196      330192 :   v[ 2 ] ^= 0xff;
     197      330192 :   FD_SIPHASH_ROUND( v );
     198      330192 :   FD_SIPHASH_ROUND( v );
     199      330192 :   FD_SIPHASH_ROUND( v );
     200      330192 :   b = v[ 0 ] ^ v[ 1 ] ^ v[ 2 ] ^ v[ 3 ];
     201             : 
     202      330192 :   return b;
     203      330192 : }

Generated by: LCOV version 1.14