forked from haskell-unordered-containers/hashable
-
Notifications
You must be signed in to change notification settings - Fork 0
/
siphash.c
74 lines (65 loc) · 1.5 KB
/
siphash.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/* Almost a verbatim copy of the reference implementation. */
#include <stddef.h>
#include <stdint.h>
typedef uint64_t u64;
typedef uint8_t u8;
#define ROTL(x,b) (u64)(((x) << (b)) | ((x) >> (64 - (b))))
#define SIPROUND \
do { \
v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
v2 += v3; v3=ROTL(v3,16); v3 ^= v2; \
v0 += v3; v3=ROTL(v3,21); v3 ^= v0; \
v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
} while(0)
u64 siphash(int c, int d, u64 k0, u64 k1, const u8 *str, size_t len)
{
u64 v0 = 0x736f6d6570736575ull ^ k0;
u64 v1 = 0x646f72616e646f6dull ^ k1;
u64 v2 = 0x6c7967656e657261ull ^ k0;
u64 v3 = 0x7465646279746573ull ^ k1;
u64 b = ((u64) len) << 56;
const u8 *end, *p;
int i;
for (p = str, end = str + (len & ~7); p < end; p += 8) {
u64 m = *(u64 *) p;
v3 ^= m;
if (c == 2) {
SIPROUND;
SIPROUND;
} else {
for (i = 0; i < c; i++)
SIPROUND;
}
v0 ^= m;
}
switch (len & 7) {
case 7: b |= ((u64)p[6]) << 48;
case 6: b |= ((u64)p[5]) << 40;
case 5: b |= ((u64)p[4]) << 32;
case 4: b |= ((u64)p[3]) << 24;
case 3: b |= ((u64)p[2]) << 16;
case 2: b |= ((u64)p[1]) << 8;
case 1: b |= ((u64)p[0]);
}
v3 ^= b;
if (c == 2) {
SIPROUND;
SIPROUND;
} else {
for (i = 0; i < c; i++)
SIPROUND;
}
v0 ^= b;
v2 ^= 0xff;
if (d == 4) {
SIPROUND;
SIPROUND;
SIPROUND;
SIPROUND;
} else {
for (i = 0; i < d; i++)
SIPROUND;
}
b = v0 ^ v1 ^ v2 ^ v3;
return b;
}