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