xref: /openbsd-src/usr.sbin/unbound/util/siphash.c (revision a43524d9cc222a049058246319ec6a29f2d9ca78)
1437d2860Ssthen /*
2437d2860Ssthen    SipHash reference C implementation
3437d2860Ssthen 
4437d2860Ssthen    Copyright (c) 2012-2016 Jean-Philippe Aumasson
5437d2860Ssthen    <jeanphilippe.aumasson@gmail.com>
6437d2860Ssthen    Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
7437d2860Ssthen 
8437d2860Ssthen    To the extent possible under law, the author(s) have dedicated all copyright
9437d2860Ssthen    and related and neighboring rights to this software to the public domain
10437d2860Ssthen    worldwide. This software is distributed without any warranty.
11437d2860Ssthen 
12437d2860Ssthen    You should have received a copy of the CC0 Public Domain Dedication along
13437d2860Ssthen    with
14437d2860Ssthen    this software. If not, see
15437d2860Ssthen    <http://creativecommons.org/publicdomain/zero/1.0/>.
16437d2860Ssthen  */
17437d2860Ssthen /**
18437d2860Ssthen  * Edited slightly for integration in Unbound. Edits are noted with 'EDIT'.
19437d2860Ssthen  */
20437d2860Ssthen /** EDIT
21437d2860Ssthen  * \#include <assert.h>
22437d2860Ssthen  * \#include <stdint.h>
23437d2860Ssthen  * \#include <stdio.h>
24437d2860Ssthen  * \#include <string.h>
25437d2860Ssthen  * Replaced the above includes with Unbound's config.h
26437d2860Ssthen  */
27437d2860Ssthen #include "config.h"
28437d2860Ssthen 
299c7f0a49Ssthen /** EDIT
309c7f0a49Ssthen   * prevent warning from -Wmissing-prototypes
319c7f0a49Ssthen   */
329c7f0a49Ssthen #include "util/siphash.h"
339c7f0a49Ssthen 
34437d2860Ssthen /* default: SipHash-2-4 */
35437d2860Ssthen #define cROUNDS 2
36437d2860Ssthen #define dROUNDS 4
37437d2860Ssthen 
38437d2860Ssthen #define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
39437d2860Ssthen 
40437d2860Ssthen #define U32TO8_LE(p, v)                                                        \
41437d2860Ssthen     (p)[0] = (uint8_t)((v));                                                   \
42437d2860Ssthen     (p)[1] = (uint8_t)((v) >> 8);                                              \
43437d2860Ssthen     (p)[2] = (uint8_t)((v) >> 16);                                             \
44437d2860Ssthen     (p)[3] = (uint8_t)((v) >> 24);
45437d2860Ssthen 
46437d2860Ssthen #define U64TO8_LE(p, v)                                                        \
47437d2860Ssthen     U32TO8_LE((p), (uint32_t)((v)));                                           \
48437d2860Ssthen     U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
49437d2860Ssthen 
50437d2860Ssthen #define U8TO64_LE(p)                                                           \
51437d2860Ssthen     (((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) |                        \
52437d2860Ssthen      ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) |                 \
53437d2860Ssthen      ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) |                 \
54437d2860Ssthen      ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
55437d2860Ssthen 
56437d2860Ssthen #define SIPROUND                                                               \
57437d2860Ssthen     do {                                                                       \
58437d2860Ssthen         v0 += v1;                                                              \
59437d2860Ssthen         v1 = ROTL(v1, 13);                                                     \
60437d2860Ssthen         v1 ^= v0;                                                              \
61437d2860Ssthen         v0 = ROTL(v0, 32);                                                     \
62437d2860Ssthen         v2 += v3;                                                              \
63437d2860Ssthen         v3 = ROTL(v3, 16);                                                     \
64437d2860Ssthen         v3 ^= v2;                                                              \
65437d2860Ssthen         v0 += v3;                                                              \
66437d2860Ssthen         v3 = ROTL(v3, 21);                                                     \
67437d2860Ssthen         v3 ^= v0;                                                              \
68437d2860Ssthen         v2 += v1;                                                              \
69437d2860Ssthen         v1 = ROTL(v1, 17);                                                     \
70437d2860Ssthen         v1 ^= v2;                                                              \
71437d2860Ssthen         v2 = ROTL(v2, 32);                                                     \
72437d2860Ssthen     } while (0)
73437d2860Ssthen 
74437d2860Ssthen #ifdef DEBUG
75437d2860Ssthen #define TRACE                                                                  \
76437d2860Ssthen     do {                                                                       \
77437d2860Ssthen         printf("(%3d) v0 %08x %08x\n", (int)inlen, (uint32_t)(v0 >> 32),       \
78437d2860Ssthen                (uint32_t)v0);                                                  \
79437d2860Ssthen         printf("(%3d) v1 %08x %08x\n", (int)inlen, (uint32_t)(v1 >> 32),       \
80437d2860Ssthen                (uint32_t)v1);                                                  \
81437d2860Ssthen         printf("(%3d) v2 %08x %08x\n", (int)inlen, (uint32_t)(v2 >> 32),       \
82437d2860Ssthen                (uint32_t)v2);                                                  \
83437d2860Ssthen         printf("(%3d) v3 %08x %08x\n", (int)inlen, (uint32_t)(v3 >> 32),       \
84437d2860Ssthen                (uint32_t)v3);                                                  \
85437d2860Ssthen     } while (0)
86437d2860Ssthen #else
87437d2860Ssthen #define TRACE
88437d2860Ssthen #endif
89437d2860Ssthen 
90437d2860Ssthen int siphash(const uint8_t *in, const size_t inlen, const uint8_t *k,
91437d2860Ssthen             uint8_t *out, const size_t outlen) {
92437d2860Ssthen 
93437d2860Ssthen     uint64_t v0 = 0x736f6d6570736575ULL;
94437d2860Ssthen     uint64_t v1 = 0x646f72616e646f6dULL;
95437d2860Ssthen     uint64_t v2 = 0x6c7967656e657261ULL;
96437d2860Ssthen     uint64_t v3 = 0x7465646279746573ULL;
97437d2860Ssthen     uint64_t k0 = U8TO64_LE(k);
98437d2860Ssthen     uint64_t k1 = U8TO64_LE(k + 8);
99437d2860Ssthen     uint64_t m;
100437d2860Ssthen     int i;
101437d2860Ssthen     const uint8_t *end = in + inlen - (inlen % sizeof(uint64_t));
102437d2860Ssthen     const int left = inlen & 7;
103437d2860Ssthen     uint64_t b = ((uint64_t)inlen) << 56;
104437d2860Ssthen     /** EDIT
105437d2860Ssthen      * The following assert moved here from the top for C90 compliance.
106437d2860Ssthen      */
107437d2860Ssthen     assert((outlen == 8) || (outlen == 16));
108437d2860Ssthen     v3 ^= k1;
109437d2860Ssthen     v2 ^= k0;
110437d2860Ssthen     v1 ^= k1;
111437d2860Ssthen     v0 ^= k0;
112437d2860Ssthen 
113437d2860Ssthen     if (outlen == 16)
114437d2860Ssthen         v1 ^= 0xee;
115437d2860Ssthen 
116437d2860Ssthen     for (; in != end; in += 8) {
117437d2860Ssthen         m = U8TO64_LE(in);
118437d2860Ssthen         v3 ^= m;
119437d2860Ssthen 
120437d2860Ssthen         TRACE;
121437d2860Ssthen         for (i = 0; i < cROUNDS; ++i)
122437d2860Ssthen             SIPROUND;
123437d2860Ssthen 
124437d2860Ssthen         v0 ^= m;
125437d2860Ssthen     }
126437d2860Ssthen 
127437d2860Ssthen     switch (left) {
128437d2860Ssthen     case 7:
129437d2860Ssthen         b |= ((uint64_t)in[6]) << 48;
130437d2860Ssthen         /** EDIT annotate case statement fallthrough for gcc */
131*a43524d9Ssthen 	ATTR_FALLTHROUGH
132437d2860Ssthen         /* fallthrough */
133437d2860Ssthen     case 6:
134437d2860Ssthen         b |= ((uint64_t)in[5]) << 40;
135437d2860Ssthen         /** EDIT annotate case statement fallthrough for gcc */
136*a43524d9Ssthen 	ATTR_FALLTHROUGH
137437d2860Ssthen         /* fallthrough */
138437d2860Ssthen     case 5:
139437d2860Ssthen         b |= ((uint64_t)in[4]) << 32;
140437d2860Ssthen         /** EDIT annotate case statement fallthrough for gcc */
141*a43524d9Ssthen 	ATTR_FALLTHROUGH
142437d2860Ssthen         /* fallthrough */
143437d2860Ssthen     case 4:
144437d2860Ssthen         b |= ((uint64_t)in[3]) << 24;
145437d2860Ssthen         /** EDIT annotate case statement fallthrough for gcc */
146*a43524d9Ssthen 	ATTR_FALLTHROUGH
147437d2860Ssthen         /* fallthrough */
148437d2860Ssthen     case 3:
149437d2860Ssthen         b |= ((uint64_t)in[2]) << 16;
150437d2860Ssthen         /** EDIT annotate case statement fallthrough for gcc */
151*a43524d9Ssthen 	ATTR_FALLTHROUGH
152437d2860Ssthen         /* fallthrough */
153437d2860Ssthen     case 2:
154437d2860Ssthen         b |= ((uint64_t)in[1]) << 8;
155437d2860Ssthen         /** EDIT annotate case statement fallthrough for gcc */
156*a43524d9Ssthen 	ATTR_FALLTHROUGH
157437d2860Ssthen         /* fallthrough */
158437d2860Ssthen     case 1:
159437d2860Ssthen         b |= ((uint64_t)in[0]);
160437d2860Ssthen         break;
161437d2860Ssthen     case 0:
162437d2860Ssthen         break;
163437d2860Ssthen     }
164437d2860Ssthen 
165437d2860Ssthen     v3 ^= b;
166437d2860Ssthen 
167437d2860Ssthen     TRACE;
168437d2860Ssthen     for (i = 0; i < cROUNDS; ++i)
169437d2860Ssthen         SIPROUND;
170437d2860Ssthen 
171437d2860Ssthen     v0 ^= b;
172437d2860Ssthen 
173437d2860Ssthen     if (outlen == 16)
174437d2860Ssthen         v2 ^= 0xee;
175437d2860Ssthen     else
176437d2860Ssthen         v2 ^= 0xff;
177437d2860Ssthen 
178437d2860Ssthen     TRACE;
179437d2860Ssthen     for (i = 0; i < dROUNDS; ++i)
180437d2860Ssthen         SIPROUND;
181437d2860Ssthen 
182437d2860Ssthen     b = v0 ^ v1 ^ v2 ^ v3;
183437d2860Ssthen     U64TO8_LE(out, b);
184437d2860Ssthen 
185437d2860Ssthen     if (outlen == 8)
186437d2860Ssthen         return 0;
187437d2860Ssthen 
188437d2860Ssthen     v1 ^= 0xdd;
189437d2860Ssthen 
190437d2860Ssthen     TRACE;
191437d2860Ssthen     for (i = 0; i < dROUNDS; ++i)
192437d2860Ssthen         SIPROUND;
193437d2860Ssthen 
194437d2860Ssthen     b = v0 ^ v1 ^ v2 ^ v3;
195437d2860Ssthen     U64TO8_LE(out + 8, b);
196437d2860Ssthen 
197437d2860Ssthen     return 0;
198437d2860Ssthen }
199