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