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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#include <stddef.h>
#include <sys/param.h>
#include "siphash.h"
#include "siphash_internal.h"
struct sipkey *sip_tokey(struct sipkey *key, const void *src) {
key->k[0] = SIP_U8TO64_LE((const unsigned char *)src);
key->k[1] = SIP_U8TO64_LE((const unsigned char *)src + 8);
return key;
} /* sip_tokey() */
void *sip_tobin(void *dst, uint64_t u64) {
SIP_U64TO8_LE((unsigned char *)dst, u64);
return dst;
} /* sip_tobin() */
static inline void sip_round(struct siphash *H, const int rounds) {
int i;
for (i = 0; i < rounds; i++) {
H->v0 += H->v1;
H->v1 = SIP_ROTL(H->v1, 13);
H->v1 ^= H->v0;
H->v0 = SIP_ROTL(H->v0, 32);
H->v2 += H->v3;
H->v3 = SIP_ROTL(H->v3, 16);
H->v3 ^= H->v2;
H->v0 += H->v3;
H->v3 = SIP_ROTL(H->v3, 21);
H->v3 ^= H->v0;
H->v2 += H->v1;
H->v1 = SIP_ROTL(H->v1, 17);
H->v1 ^= H->v2;
H->v2 = SIP_ROTL(H->v2, 32);
}
} /* sip_round() */
struct siphash *sip24_init(struct siphash *H, const struct sipkey *key) {
H->v0 = 0x736f6d6570736575ULL ^ key->k[0];
H->v1 = 0x646f72616e646f6dULL ^ key->k[1];
H->v2 = 0x6c7967656e657261ULL ^ key->k[0];
H->v3 = 0x7465646279746573ULL ^ key->k[1];
H->p = H->b.buf;
H->c = 0;
return H;
} /* sip24_init() */
struct siphash *sip24_update(struct siphash *H, const void *src, size_t len) {
const unsigned char *p = src, *pe = p + len;
uint64_t m;
size_t bufremain = sizeof (H->b.buf) - (H->p - H->b.buf), cpylen;
do {
if (H->p == H->b.buf && len > sizeof (H->b)) {
m = SIP_U8TO64_LE(p);
H->v3 ^= m;
sip_round(H, 2);
H->v0 ^= m;
p += 8;
len -= 8;
H->c += 8;
continue;
}
else {
cpylen = MIN(len, bufremain);
memcpy (H->p, p, cpylen);
H->p += cpylen;
p += cpylen;
len -= cpylen;
}
if (H->p < sip_endof(H->b.buf))
break;
#if BYTE_ORDER == LITTLE_ENDIAN
m = H->b.m;
#else
m = SIP_U8TO64_LE(H->b.buf);
#endif
H->v3 ^= m;
sip_round(H, 2);
H->v0 ^= m;
H->p = H->b.buf;
H->c += 8;
} while (p < pe);
return H;
} /* sip24_update() */
uint64_t sip24_final(struct siphash *H) {
char left = H->p - H->b.buf;
uint64_t b = (H->c + left) << 56;
switch (left) {
case 7: b |= (uint64_t)H->b.buf[6] << 48;
case 6: b |= (uint64_t)H->b.buf[5] << 40;
case 5: b |= (uint64_t)H->b.buf[4] << 32;
case 4: b |= (uint64_t)H->b.buf[3] << 24;
case 3: b |= (uint64_t)H->b.buf[2] << 16;
case 2: b |= (uint64_t)H->b.buf[1] << 8;
case 1: b |= (uint64_t)H->b.buf[0] << 0;
case 0: break;
}
H->v3 ^= b;
sip_round(H, 2);
H->v0 ^= b;
H->v2 ^= 0xff;
sip_round(H, 4);
return H->v0 ^ H->v1 ^ H->v2 ^ H->v3;
} /* sip24_final() */
|