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