4#ifndef SIP_HASH_STREAMING
5 #define SIP_HASH_STREAMING 1
8#if defined(__MINGW32__)
12 #define __LITTLE_ENDIAN LITTLE_ENDIAN
13 #define __BIG_ENDIAN BIG_ENDIAN
15 #define BYTE_ORDER __LITTLE_ENDIAN
16#elif !defined(BYTE_ORDER)
21#define LITTLE_ENDIAN __LITTLE_ENDIAN
24#define BIG_ENDIAN __BIG_ENDIAN
27#if BYTE_ORDER == LITTLE_ENDIAN
30#elif BYTE_ORDER == BIG_ENDIAN
34 #error "Only strictly little or big endian supported"
38#ifndef UNALIGNED_WORD_ACCESS
39# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
40 defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \
41 defined(__powerpc64__) || defined(__POWERPC__) || defined(__aarch64__) || \
43# define UNALIGNED_WORD_ACCESS 1
46#ifndef UNALIGNED_WORD_ACCESS
47# define UNALIGNED_WORD_ACCESS 0
51 (((uint32_t)((p)[0]) ) | ((uint32_t)((p)[1]) << 8) | \
52 ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24)) \
54#define U32TO8_LE(p, v) \
56 (p)[0] = (uint8_t)((v) ); \
57 (p)[1] = (uint8_t)((v) >> 8); \
58 (p)[2] = (uint8_t)((v) >> 16); \
59 (p)[3] = (uint8_t)((v) >> 24); \
64 ((uint64_t)U8TO32_LE(p) | ((uint64_t)U8TO32_LE((p) + 4)) << 32 )
66#define U64TO8_LE(p, v) \
68 U32TO8_LE((p), (uint32_t)((v) )); \
69 U32TO8_LE((p) + 4, (uint32_t)((v) >> 32)); \
73 ((v) << (s)) | ((v) >> (64 - (s)))
75#define ROTL64_TO(v, s) ((v) = ROTL64((v), (s)))
77#define ADD64_TO(v, s) ((v) += (s))
78#define XOR64_TO(v, s) ((v) ^= (s))
79#define XOR64_INT(v, x) ((v) ^= (x))
81#define U8TO64_LE(p) u8to64_le(p)
83u8to64_le(
const uint8_t *p)
86 ret.lo = U8TO32_LE(p);
87 ret.hi = U8TO32_LE(p + 4);
91#define U64TO8_LE(p, v) u64to8_le(p, v)
93u64to8_le(uint8_t *p, uint64_t v)
96 U32TO8_LE(p + 4, v.hi);
99#define ROTL64_TO(v, s) ((s) > 32 ? rotl64_swap(rotl64_to(&(v), (s) - 32)) : \
100 (s) == 32 ? rotl64_swap(&(v)) : rotl64_to(&(v), (s)))
101static inline uint64_t *
102rotl64_to(uint64_t *v,
unsigned int s)
104 uint32_t uhi = (v->hi << s) | (v->lo >> (32 - s));
105 uint32_t ulo = (v->lo << s) | (v->hi >> (32 - s));
111static inline uint64_t *
112rotl64_swap(uint64_t *v)
120#define ADD64_TO(v, s) add64_to(&(v), (s))
121static inline uint64_t *
122add64_to(uint64_t *v,
const uint64_t s)
126 if (v->lo < s.lo) v->hi++;
130#define XOR64_TO(v, s) xor64_to(&(v), (s))
131static inline uint64_t *
132xor64_to(uint64_t *v,
const uint64_t s)
139#define XOR64_INT(v, x) ((v).lo ^= (x))
143#if defined(__has_attribute) && __has_attribute(nonstring)
148} sip_init_state_bin = {
"uespemos""modnarod""arenegyl""setybdet"};
149#define sip_init_state sip_init_state_bin.u64
151#if SIP_HASH_STREAMING
152struct sip_interface_st {
153 void (*init)(
sip_state *s,
const uint8_t *key);
154 void (*update)(
sip_state *s,
const uint8_t *data,
size_t len);
155 void (*
final)(
sip_state *s, uint64_t *digest);
158static void int_sip_init(
sip_state *state,
const uint8_t *key);
159static void int_sip_update(
sip_state *state,
const uint8_t *data,
size_t len);
160static void int_sip_final(
sip_state *state, uint64_t *digest);
162static const sip_interface sip_methods = {
169#define SIP_COMPRESS(v0, v1, v2, v3) \
171 ADD64_TO((v0), (v1)); \
172 ADD64_TO((v2), (v3)); \
173 ROTL64_TO((v1), 13); \
174 ROTL64_TO((v3), 16); \
175 XOR64_TO((v1), (v0)); \
176 XOR64_TO((v3), (v2)); \
177 ROTL64_TO((v0), 32); \
178 ADD64_TO((v2), (v1)); \
179 ADD64_TO((v0), (v3)); \
180 ROTL64_TO((v1), 17); \
181 ROTL64_TO((v3), 21); \
182 XOR64_TO((v1), (v2)); \
183 XOR64_TO((v3), (v0)); \
184 ROTL64_TO((v2), 32); \
187#if SIP_HASH_STREAMING
193 for (v = 0; v < 4; v++) {
195 printf(
"v%d: %" PRIx64
"\n", v, state->v[v]);
197 printf(
"v%d: %" PRIx32
"%.8" PRIx32
"\n", v, state->v[v].hi, state->v[v].lo);
203int_sip_init(
sip_state *state,
const uint8_t key[16])
208 k1 = U8TO64_LE(key +
sizeof(uint64_t));
210 state->v[0] = k0; XOR64_TO(state->v[0], sip_init_state[0]);
211 state->v[1] = k1; XOR64_TO(state->v[1], sip_init_state[1]);
212 state->v[2] = k0; XOR64_TO(state->v[2], sip_init_state[2]);
213 state->v[3] = k1; XOR64_TO(state->v[3], sip_init_state[3]);
221 for (i = 0; i < n; i++) {
222 SIP_COMPRESS(state->v[0], state->v[1], state->v[2], state->v[3]);
227int_sip_update_block(
sip_state *state, uint64_t m)
229 XOR64_TO(state->v[3], m);
230 int_sip_round(state, state->c);
231 XOR64_TO(state->v[0], m);
235int_sip_pre_update(
sip_state *state,
const uint8_t **pdata,
size_t *plen)
240 if (!state->buflen)
return;
242 to_read =
sizeof(uint64_t) - state->buflen;
243 memcpy(state->buf + state->buflen, *pdata, to_read);
244 m = U8TO64_LE(state->buf);
245 int_sip_update_block(state, m);
252int_sip_post_update(
sip_state *state,
const uint8_t *data,
size_t len)
254 uint8_t r =
len %
sizeof(uint64_t);
256 memcpy(state->buf, data +
len - r, r);
262int_sip_update(
sip_state *state,
const uint8_t *data,
size_t len)
267 state->msglen_byte = state->msglen_byte + (
len % 256);
268 data64 = (uint64_t *) data;
270 int_sip_pre_update(state, &data, &
len);
272 end = data64 + (
len /
sizeof(uint64_t));
274#if BYTE_ORDER == LITTLE_ENDIAN
275 while (data64 != end) {
276 int_sip_update_block(state, *data64++);
278#elif BYTE_ORDER == BIG_ENDIAN
281 uint8_t *data8 = data;
282 for (; data8 != (uint8_t *) end; data8 +=
sizeof(uint64_t)) {
283 m = U8TO64_LE(data8);
284 int_sip_update_block(state, m);
289 int_sip_post_update(state, data,
len);
297 for (i = state->buflen; i <
sizeof(uint64_t); i++) {
298 state->buf[i] = 0x00;
300 state->buf[
sizeof(uint64_t) - 1] = state->msglen_byte;
304int_sip_final(
sip_state *state, uint64_t *digest)
308 int_sip_pad_final_block(state);
310 m = U8TO64_LE(state->buf);
311 int_sip_update_block(state, m);
313 XOR64_INT(state->v[2], 0xff);
315 int_sip_round(state, state->d);
317 *digest = state->v[0];
318 XOR64_TO(*digest, state->v[1]);
319 XOR64_TO(*digest, state->v[2]);
320 XOR64_TO(*digest, state->v[3]);
324sip_hash_new(
const uint8_t key[16],
int c,
int d)
329 return sip_hash_init(h, key, c, d);
333sip_hash_init(
sip_hash *h,
const uint8_t key[16],
int c,
int d)
337 h->state->buflen = 0;
338 h->state->msglen_byte = 0;
339 h->methods = &sip_methods;
340 h->methods->init(h->state, key);
345sip_hash_update(
sip_hash *h,
const uint8_t *msg,
size_t len)
347 h->methods->update(h->state, msg,
len);
352sip_hash_final(
sip_hash *h, uint8_t **digest,
size_t*
len)
357 h->methods->final(h->state, &digest64);
358 if (!(ret = (uint8_t *)malloc(
sizeof(uint64_t))))
return 0;
359 U64TO8_LE(ret, digest64);
360 *
len =
sizeof(uint64_t);
367sip_hash_final_integer(
sip_hash *h, uint64_t *digest)
369 h->methods->final(h->state, digest);
374sip_hash_digest(
sip_hash *h,
const uint8_t *data,
size_t data_len, uint8_t **digest,
size_t *digest_len)
376 if (!sip_hash_update(h, data, data_len))
return 0;
377 return sip_hash_final(h, digest, digest_len);
381sip_hash_digest_integer(
sip_hash *h,
const uint8_t *data,
size_t data_len, uint64_t *digest)
383 if (!sip_hash_update(h, data, data_len))
return 0;
384 return sip_hash_final_integer(h, digest);
396 int_sip_dump(h->state);
400#define SIP_ROUND(m, v0, v1, v2, v3) \
402 XOR64_TO((v3), (m)); \
403 SIP_COMPRESS(v0, v1, v2, v3); \
404 XOR64_TO((v0), (m)); \
408sip_hash13(
const uint8_t key[16],
const uint8_t *data,
size_t len)
411 uint64_t v0, v1, v2, v3;
413 const uint8_t *end = data +
len - (
len %
sizeof(uint64_t));
416 k1 = U8TO64_LE(key +
sizeof(uint64_t));
418 v0 = k0; XOR64_TO(v0, sip_init_state[0]);
419 v1 = k1; XOR64_TO(v1, sip_init_state[1]);
420 v2 = k0; XOR64_TO(v2, sip_init_state[2]);
421 v3 = k1; XOR64_TO(v3, sip_init_state[3]);
423#if BYTE_ORDER == LITTLE_ENDIAN && UNALIGNED_WORD_ACCESS
425 uint64_t *data64 = (uint64_t *)data;
426 while (data64 != (uint64_t *) end) {
428 SIP_ROUND(m, v0, v1, v2, v3);
432 for (; data != end; data +=
sizeof(uint64_t)) {
434 SIP_ROUND(m, v0, v1, v2, v3);
439 last = (uint64_t)
len << 56;
440#define OR_BYTE(n) (last |= ((uint64_t) end[n]) << ((n) * 8))
444#define OR_BYTE(n) do { \
446 last.hi |= ((uint32_t) end[n]) << ((n) >= 4 ? (n) * 8 - 32 : 0); \
448 last.lo |= ((uint32_t) end[n]) << ((n) >= 4 ? 0 : (n) * 8); \
452 switch (
len %
sizeof(uint64_t)) {
460#if BYTE_ORDER == LITTLE_ENDIAN && UNALIGNED_WORD_ACCESS
462 last |= (uint64_t) ((uint32_t *) end)[0];
464 last.lo |= ((uint32_t *) end)[0];
481 SIP_ROUND(last, v0, v1, v2, v3);
485 SIP_COMPRESS(v0, v1, v2, v3);
486 SIP_COMPRESS(v0, v1, v2, v3);
487 SIP_COMPRESS(v0, v1, v2, v3);
int len
Length of the buffer.