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 : }