Line data Source code
1 : /* 2 : SipHash reference C implementation 3 : Copyright (c) 2012-2021 Jean-Philippe Aumasson 4 : <jeanphilippe.aumasson@gmail.com> 5 : Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to> 6 : To the extent possible under law, the author(s) have dedicated all copyright 7 : and related and neighboring rights to this software to the public domain 8 : worldwide. This software is distributed without any warranty. 9 : You should have received a copy of the CC0 Public Domain Dedication along 10 : with 11 : this software. If not, see 12 : <http://creativecommons.org/publicdomain/zero/1.0/>. 13 : */ 14 : 15 : #include "passgen/util/siphash.h" 16 : #include <assert.h> 17 : #include <stdint.h> 18 : #include <stdio.h> 19 : 20 : /* default: SipHash-2-4 */ 21 : #ifndef cROUNDS 22 : #define cROUNDS 2 23 : #endif 24 : #ifndef dROUNDS 25 : #define dROUNDS 4 26 : #endif 27 : 28 : #define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b)))) 29 : 30 : #define U32TO8_LE(p, v) \ 31 : (p)[0] = (uint8_t) ((v)); \ 32 : (p)[1] = (uint8_t) ((v) >> 8); \ 33 : (p)[2] = (uint8_t) ((v) >> 16); \ 34 : (p)[3] = (uint8_t) ((v) >> 24); 35 : 36 : #define U64TO8_LE(p, v) \ 37 : U32TO8_LE((p), (uint32_t) ((v))); \ 38 : U32TO8_LE((p) + 4, (uint32_t) ((v) >> 32)); 39 : 40 : #define U8TO64_LE(p) \ 41 : (((uint64_t) ((p)[0])) | ((uint64_t) ((p)[1]) << 8) | \ 42 : ((uint64_t) ((p)[2]) << 16) | ((uint64_t) ((p)[3]) << 24) | \ 43 : ((uint64_t) ((p)[4]) << 32) | ((uint64_t) ((p)[5]) << 40) | \ 44 : ((uint64_t) ((p)[6]) << 48) | ((uint64_t) ((p)[7]) << 56)) 45 : 46 : #define SIPROUND \ 47 : do { \ 48 : v0 += v1; \ 49 : v1 = ROTL(v1, 13); \ 50 : v1 ^= v0; \ 51 : v0 = ROTL(v0, 32); \ 52 : v2 += v3; \ 53 : v3 = ROTL(v3, 16); \ 54 : v3 ^= v2; \ 55 : v0 += v3; \ 56 : v3 = ROTL(v3, 21); \ 57 : v3 ^= v0; \ 58 : v2 += v1; \ 59 : v1 = ROTL(v1, 17); \ 60 : v1 ^= v2; \ 61 : v2 = ROTL(v2, 32); \ 62 : } while(0) 63 : 64 : #ifdef DEBUG 65 : #define TRACE \ 66 : do { \ 67 : printf("(%3zu) v0 %016" PRIx64 "\n", inlen, v0); \ 68 : printf("(%3zu) v1 %016" PRIx64 "\n", inlen, v1); \ 69 : printf("(%3zu) v2 %016" PRIx64 "\n", inlen, v2); \ 70 : printf("(%3zu) v3 %016" PRIx64 "\n", inlen, v3); \ 71 : } while(0) 72 : #else 73 : #define TRACE 74 : #endif 75 : 76 38675 : int passgen_siphash( 77 : const void *in, 78 : const size_t inlen, 79 : const void *k, 80 : uint8_t *out, 81 : const size_t outlen) { 82 38675 : const unsigned char *ni = (const unsigned char *) in; 83 38675 : const unsigned char *kk = (const unsigned char *) k; 84 : 85 38675 : assert((outlen == 8) || (outlen == 16)); 86 38675 : uint64_t v0 = UINT64_C(0x736f6d6570736575); 87 38675 : uint64_t v1 = UINT64_C(0x646f72616e646f6d); 88 38675 : uint64_t v2 = UINT64_C(0x6c7967656e657261); 89 38675 : uint64_t v3 = UINT64_C(0x7465646279746573); 90 38675 : uint64_t k0 = U8TO64_LE(kk); 91 38675 : uint64_t k1 = U8TO64_LE(kk + 8); 92 : uint64_t m; 93 : int i; 94 38675 : const unsigned char *end = ni + inlen - (inlen % sizeof(uint64_t)); 95 38675 : const int left = inlen & 7; 96 38675 : uint64_t b = ((uint64_t) inlen) << 56; 97 38675 : v3 ^= k1; 98 38675 : v2 ^= k0; 99 38675 : v1 ^= k1; 100 38675 : v0 ^= k0; 101 : 102 38675 : if(outlen == 16) v1 ^= 0xee; 103 : 104 38677 : for(; ni != end; ni += 8) { 105 2 : m = U8TO64_LE(ni); 106 2 : v3 ^= m; 107 : 108 : TRACE; 109 6 : for(i = 0; i < cROUNDS; ++i) SIPROUND; 110 : 111 2 : v0 ^= m; 112 : } 113 : 114 38675 : switch(left) { 115 5 : case 7: 116 5 : b |= ((uint64_t) ni[6]) << 48; 117 : // fall through 118 5 : case 6: 119 5 : b |= ((uint64_t) ni[5]) << 40; 120 : // fall through 121 57 : case 5: 122 57 : b |= ((uint64_t) ni[4]) << 32; 123 : // fall through 124 29284 : case 4: 125 29284 : b |= ((uint64_t) ni[3]) << 24; 126 : // fall through 127 37085 : case 3: 128 37085 : b |= ((uint64_t) ni[2]) << 16; 129 : // fall through 130 38430 : case 2: 131 38430 : b |= ((uint64_t) ni[1]) << 8; 132 : // fall through 133 38673 : case 1: 134 38673 : b |= ((uint64_t) ni[0]); 135 38673 : break; 136 2 : case 0: 137 2 : break; 138 : } 139 : 140 38675 : v3 ^= b; 141 : 142 : TRACE; 143 116025 : for(i = 0; i < cROUNDS; ++i) SIPROUND; 144 : 145 38675 : v0 ^= b; 146 : 147 38675 : if(outlen == 16) 148 8 : v2 ^= 0xee; 149 : else 150 38667 : v2 ^= 0xff; 151 : 152 : TRACE; 153 193375 : for(i = 0; i < dROUNDS; ++i) SIPROUND; 154 : 155 38675 : b = v0 ^ v1 ^ v2 ^ v3; 156 38675 : U64TO8_LE(out, b); 157 : 158 38675 : if(outlen == 8) return 0; 159 : 160 8 : v1 ^= 0xdd; 161 : 162 : TRACE; 163 40 : for(i = 0; i < dROUNDS; ++i) SIPROUND; 164 : 165 8 : b = v0 ^ v1 ^ v2 ^ v3; 166 8 : U64TO8_LE(out + 8, b); 167 : 168 8 : return 0; 169 : }