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