18f76bb7dSCy Schubert /*
28f76bb7dSCy Schubert SipHash reference C implementation
38f76bb7dSCy Schubert
48f76bb7dSCy Schubert Copyright (c) 2012-2016 Jean-Philippe Aumasson
58f76bb7dSCy Schubert <jeanphilippe.aumasson@gmail.com>
68f76bb7dSCy Schubert Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
78f76bb7dSCy Schubert
88f76bb7dSCy Schubert To the extent possible under law, the author(s) have dedicated all copyright
98f76bb7dSCy Schubert and related and neighboring rights to this software to the public domain
108f76bb7dSCy Schubert worldwide. This software is distributed without any warranty.
118f76bb7dSCy Schubert
128f76bb7dSCy Schubert You should have received a copy of the CC0 Public Domain Dedication along
138f76bb7dSCy Schubert with
148f76bb7dSCy Schubert this software. If not, see
158f76bb7dSCy Schubert <http://creativecommons.org/publicdomain/zero/1.0/>.
168f76bb7dSCy Schubert */
178f76bb7dSCy Schubert /**
188f76bb7dSCy Schubert * Edited slightly for integration in Unbound. Edits are noted with 'EDIT'.
198f76bb7dSCy Schubert */
208f76bb7dSCy Schubert /** EDIT
218f76bb7dSCy Schubert * \#include <assert.h>
228f76bb7dSCy Schubert * \#include <stdint.h>
238f76bb7dSCy Schubert * \#include <stdio.h>
248f76bb7dSCy Schubert * \#include <string.h>
258f76bb7dSCy Schubert * Replaced the above includes with Unbound's config.h
268f76bb7dSCy Schubert */
278f76bb7dSCy Schubert #include "config.h"
288f76bb7dSCy Schubert
29103ba509SCy Schubert /** EDIT
30103ba509SCy Schubert * prevent warning from -Wmissing-prototypes
31103ba509SCy Schubert */
32103ba509SCy Schubert #include "util/siphash.h"
33103ba509SCy Schubert
348f76bb7dSCy Schubert /* default: SipHash-2-4 */
358f76bb7dSCy Schubert #define cROUNDS 2
368f76bb7dSCy Schubert #define dROUNDS 4
378f76bb7dSCy Schubert
388f76bb7dSCy Schubert #define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
398f76bb7dSCy Schubert
408f76bb7dSCy Schubert #define U32TO8_LE(p, v) \
418f76bb7dSCy Schubert (p)[0] = (uint8_t)((v)); \
428f76bb7dSCy Schubert (p)[1] = (uint8_t)((v) >> 8); \
438f76bb7dSCy Schubert (p)[2] = (uint8_t)((v) >> 16); \
448f76bb7dSCy Schubert (p)[3] = (uint8_t)((v) >> 24);
458f76bb7dSCy Schubert
468f76bb7dSCy Schubert #define U64TO8_LE(p, v) \
478f76bb7dSCy Schubert U32TO8_LE((p), (uint32_t)((v))); \
488f76bb7dSCy Schubert U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
498f76bb7dSCy Schubert
508f76bb7dSCy Schubert #define U8TO64_LE(p) \
518f76bb7dSCy Schubert (((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \
528f76bb7dSCy Schubert ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \
538f76bb7dSCy Schubert ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \
548f76bb7dSCy Schubert ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
558f76bb7dSCy Schubert
568f76bb7dSCy Schubert #define SIPROUND \
578f76bb7dSCy Schubert do { \
588f76bb7dSCy Schubert v0 += v1; \
598f76bb7dSCy Schubert v1 = ROTL(v1, 13); \
608f76bb7dSCy Schubert v1 ^= v0; \
618f76bb7dSCy Schubert v0 = ROTL(v0, 32); \
628f76bb7dSCy Schubert v2 += v3; \
638f76bb7dSCy Schubert v3 = ROTL(v3, 16); \
648f76bb7dSCy Schubert v3 ^= v2; \
658f76bb7dSCy Schubert v0 += v3; \
668f76bb7dSCy Schubert v3 = ROTL(v3, 21); \
678f76bb7dSCy Schubert v3 ^= v0; \
688f76bb7dSCy Schubert v2 += v1; \
698f76bb7dSCy Schubert v1 = ROTL(v1, 17); \
708f76bb7dSCy Schubert v1 ^= v2; \
718f76bb7dSCy Schubert v2 = ROTL(v2, 32); \
728f76bb7dSCy Schubert } while (0)
738f76bb7dSCy Schubert
748f76bb7dSCy Schubert #ifdef DEBUG
758f76bb7dSCy Schubert #define TRACE \
768f76bb7dSCy Schubert do { \
778f76bb7dSCy Schubert printf("(%3d) v0 %08x %08x\n", (int)inlen, (uint32_t)(v0 >> 32), \
788f76bb7dSCy Schubert (uint32_t)v0); \
798f76bb7dSCy Schubert printf("(%3d) v1 %08x %08x\n", (int)inlen, (uint32_t)(v1 >> 32), \
808f76bb7dSCy Schubert (uint32_t)v1); \
818f76bb7dSCy Schubert printf("(%3d) v2 %08x %08x\n", (int)inlen, (uint32_t)(v2 >> 32), \
828f76bb7dSCy Schubert (uint32_t)v2); \
838f76bb7dSCy Schubert printf("(%3d) v3 %08x %08x\n", (int)inlen, (uint32_t)(v3 >> 32), \
848f76bb7dSCy Schubert (uint32_t)v3); \
858f76bb7dSCy Schubert } while (0)
868f76bb7dSCy Schubert #else
878f76bb7dSCy Schubert #define TRACE
888f76bb7dSCy Schubert #endif
898f76bb7dSCy Schubert
siphash(const uint8_t * in,const size_t inlen,const uint8_t * k,uint8_t * out,const size_t outlen)908f76bb7dSCy Schubert int siphash(const uint8_t *in, const size_t inlen, const uint8_t *k,
918f76bb7dSCy Schubert uint8_t *out, const size_t outlen) {
928f76bb7dSCy Schubert
938f76bb7dSCy Schubert uint64_t v0 = 0x736f6d6570736575ULL;
948f76bb7dSCy Schubert uint64_t v1 = 0x646f72616e646f6dULL;
958f76bb7dSCy Schubert uint64_t v2 = 0x6c7967656e657261ULL;
968f76bb7dSCy Schubert uint64_t v3 = 0x7465646279746573ULL;
978f76bb7dSCy Schubert uint64_t k0 = U8TO64_LE(k);
988f76bb7dSCy Schubert uint64_t k1 = U8TO64_LE(k + 8);
998f76bb7dSCy Schubert uint64_t m;
1008f76bb7dSCy Schubert int i;
1018f76bb7dSCy Schubert const uint8_t *end = in + inlen - (inlen % sizeof(uint64_t));
1028f76bb7dSCy Schubert const int left = inlen & 7;
1038f76bb7dSCy Schubert uint64_t b = ((uint64_t)inlen) << 56;
1048f76bb7dSCy Schubert /** EDIT
1058f76bb7dSCy Schubert * The following assert moved here from the top for C90 compliance.
1068f76bb7dSCy Schubert */
1078f76bb7dSCy Schubert assert((outlen == 8) || (outlen == 16));
1088f76bb7dSCy Schubert v3 ^= k1;
1098f76bb7dSCy Schubert v2 ^= k0;
1108f76bb7dSCy Schubert v1 ^= k1;
1118f76bb7dSCy Schubert v0 ^= k0;
1128f76bb7dSCy Schubert
1138f76bb7dSCy Schubert if (outlen == 16)
1148f76bb7dSCy Schubert v1 ^= 0xee;
1158f76bb7dSCy Schubert
1168f76bb7dSCy Schubert for (; in != end; in += 8) {
1178f76bb7dSCy Schubert m = U8TO64_LE(in);
1188f76bb7dSCy Schubert v3 ^= m;
1198f76bb7dSCy Schubert
1208f76bb7dSCy Schubert TRACE;
1218f76bb7dSCy Schubert for (i = 0; i < cROUNDS; ++i)
1228f76bb7dSCy Schubert SIPROUND;
1238f76bb7dSCy Schubert
1248f76bb7dSCy Schubert v0 ^= m;
1258f76bb7dSCy Schubert }
1268f76bb7dSCy Schubert
1278f76bb7dSCy Schubert switch (left) {
1288f76bb7dSCy Schubert case 7:
1298f76bb7dSCy Schubert b |= ((uint64_t)in[6]) << 48;
1308f76bb7dSCy Schubert /** EDIT annotate case statement fallthrough for gcc */
131*56850988SCy Schubert ATTR_FALLTHROUGH
1328f76bb7dSCy Schubert /* fallthrough */
1338f76bb7dSCy Schubert case 6:
1348f76bb7dSCy Schubert b |= ((uint64_t)in[5]) << 40;
1358f76bb7dSCy Schubert /** EDIT annotate case statement fallthrough for gcc */
136*56850988SCy Schubert ATTR_FALLTHROUGH
1378f76bb7dSCy Schubert /* fallthrough */
1388f76bb7dSCy Schubert case 5:
1398f76bb7dSCy Schubert b |= ((uint64_t)in[4]) << 32;
1408f76bb7dSCy Schubert /** EDIT annotate case statement fallthrough for gcc */
141*56850988SCy Schubert ATTR_FALLTHROUGH
1428f76bb7dSCy Schubert /* fallthrough */
1438f76bb7dSCy Schubert case 4:
1448f76bb7dSCy Schubert b |= ((uint64_t)in[3]) << 24;
1458f76bb7dSCy Schubert /** EDIT annotate case statement fallthrough for gcc */
146*56850988SCy Schubert ATTR_FALLTHROUGH
1478f76bb7dSCy Schubert /* fallthrough */
1488f76bb7dSCy Schubert case 3:
1498f76bb7dSCy Schubert b |= ((uint64_t)in[2]) << 16;
1508f76bb7dSCy Schubert /** EDIT annotate case statement fallthrough for gcc */
151*56850988SCy Schubert ATTR_FALLTHROUGH
1528f76bb7dSCy Schubert /* fallthrough */
1538f76bb7dSCy Schubert case 2:
1548f76bb7dSCy Schubert b |= ((uint64_t)in[1]) << 8;
1558f76bb7dSCy Schubert /** EDIT annotate case statement fallthrough for gcc */
156*56850988SCy Schubert ATTR_FALLTHROUGH
1578f76bb7dSCy Schubert /* fallthrough */
1588f76bb7dSCy Schubert case 1:
1598f76bb7dSCy Schubert b |= ((uint64_t)in[0]);
1608f76bb7dSCy Schubert break;
1618f76bb7dSCy Schubert case 0:
1628f76bb7dSCy Schubert break;
1638f76bb7dSCy Schubert }
1648f76bb7dSCy Schubert
1658f76bb7dSCy Schubert v3 ^= b;
1668f76bb7dSCy Schubert
1678f76bb7dSCy Schubert TRACE;
1688f76bb7dSCy Schubert for (i = 0; i < cROUNDS; ++i)
1698f76bb7dSCy Schubert SIPROUND;
1708f76bb7dSCy Schubert
1718f76bb7dSCy Schubert v0 ^= b;
1728f76bb7dSCy Schubert
1738f76bb7dSCy Schubert if (outlen == 16)
1748f76bb7dSCy Schubert v2 ^= 0xee;
1758f76bb7dSCy Schubert else
1768f76bb7dSCy Schubert v2 ^= 0xff;
1778f76bb7dSCy Schubert
1788f76bb7dSCy Schubert TRACE;
1798f76bb7dSCy Schubert for (i = 0; i < dROUNDS; ++i)
1808f76bb7dSCy Schubert SIPROUND;
1818f76bb7dSCy Schubert
1828f76bb7dSCy Schubert b = v0 ^ v1 ^ v2 ^ v3;
1838f76bb7dSCy Schubert U64TO8_LE(out, b);
1848f76bb7dSCy Schubert
1858f76bb7dSCy Schubert if (outlen == 8)
1868f76bb7dSCy Schubert return 0;
1878f76bb7dSCy Schubert
1888f76bb7dSCy Schubert v1 ^= 0xdd;
1898f76bb7dSCy Schubert
1908f76bb7dSCy Schubert TRACE;
1918f76bb7dSCy Schubert for (i = 0; i < dROUNDS; ++i)
1928f76bb7dSCy Schubert SIPROUND;
1938f76bb7dSCy Schubert
1948f76bb7dSCy Schubert b = v0 ^ v1 ^ v2 ^ v3;
1958f76bb7dSCy Schubert U64TO8_LE(out + 8, b);
1968f76bb7dSCy Schubert
1978f76bb7dSCy Schubert return 0;
1988f76bb7dSCy Schubert }
199