35 #include "ext/siphash.h"
38 #include "ext/byteorder.h"
40 #define ROTATE(x, b) (uint64_t)( ((x) << (b)) | ( (x) >> (64 - (b))) )
42 #define HALF_ROUND(a,b,c,d,s,t) \
44 b = ROTATE(b, s) ^ a; \
45 d = ROTATE(d, t) ^ c; \
48 #define DOUBLE_ROUND(v0,v1,v2,v3) \
49 HALF_ROUND(v0,v1,v2,v3,13,16); \
50 HALF_ROUND(v2,v1,v0,v3,17,21); \
51 HALF_ROUND(v0,v1,v2,v3,13,16); \
52 HALF_ROUND(v2,v1,v0,v3,17,21);
58 #if (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
59 defined(__x86_64) || defined(__x86_64__) || \
60 defined(_M_AMD64) || defined(_M_X64) || defined(__INTEL__))
61 # define UNALIGNED_OK 1
65 uint64_t siphash24(
const void *src,
unsigned long src_sz,
const struct sipkey *key) {
66 const uint8_t *m = src;
67 uint64_t k0 = key->k0;
68 uint64_t k1 = key->k1;
69 uint64_t last7 = (uint64_t)(src_sz & 0xff) << 56;
72 uint64_t v0 = k0 ^ 0x736f6d6570736575ULL;
73 uint64_t v1 = k1 ^ 0x646f72616e646f6dULL;
74 uint64_t v2 = k0 ^ 0x6c7967656e657261ULL;
75 uint64_t v3 = k1 ^ 0x7465646279746573ULL;
77 for (i = 0, blocks = (src_sz & ~7); i < blocks; i+= 8) {
79 uint64_t mi = _le64toh(*(m + i));
82 memcpy(&mi, m + i, 8);
86 DOUBLE_ROUND(v0,v1,v2,v3);
93 memcpy(&mi, m+i, (src_sz-blocks));
94 last7 = _le64toh(mi) | (uint64_t)(src_sz & 0xff) << 56;
97 switch (src_sz - blocks) {
98 case 7: last7 |= (uint64_t)m[i + 6] << 48; FALLTHROUGH;
99 case 6: last7 |= (uint64_t)m[i + 5] << 40; FALLTHROUGH;
100 case 5: last7 |= (uint64_t)m[i + 4] << 32; FALLTHROUGH;
101 case 4: last7 |= (uint64_t)m[i + 3] << 24; FALLTHROUGH;
102 case 3: last7 |= (uint64_t)m[i + 2] << 16; FALLTHROUGH;
103 case 2: last7 |= (uint64_t)m[i + 1] << 8; FALLTHROUGH;
104 case 1: last7 |= (uint64_t)m[i + 0] ; FALLTHROUGH;
110 DOUBLE_ROUND(v0,v1,v2,v3);
113 DOUBLE_ROUND(v0,v1,v2,v3);
114 DOUBLE_ROUND(v0,v1,v2,v3);
115 return v0 ^ v1 ^ v2 ^ v3;
119 static int the_siphash_key_is_set = 0;
120 static struct sipkey the_siphash_key;
122 uint64_t siphash24g(
const void *src,
unsigned long src_sz) {
123 raw_assert(the_siphash_key_is_set);
124 return siphash24(src, src_sz, &the_siphash_key);
127 void siphash_set_global_key(
const struct sipkey *key)
129 raw_assert(! the_siphash_key_is_set);
130 the_siphash_key.k0 = key->k0;
131 the_siphash_key.k1 = key->k1;
132 the_siphash_key_is_set = 1;
135 void siphash_unset_global_key(
void)
137 the_siphash_key_is_set = 0;
138 memset(&the_siphash_key, 0,
sizeof(the_siphash_key));
Integer definitions used throughout Tor.