1 /* Licensed under GPL v2+ - see LICENSE file for details */
3 #include <ccan/endian/endian.h>
9 enum sip_index { A=0, B=2, C=1, D=3, E=4 };
11 #define rol(x,l) (((x) << (l)) | ((x) >> (64-(l))))
13 #define SIP_HALF_ROUND(a,b,c,d,L1,L2) \
16 (b) = (a) ^ rol((b),L1); \
17 (d) = (c) ^ rol((d),L2); \
20 #define SIP_ROUND(W) \
22 SIP_HALF_ROUND((W)[A], (W)[B], (W)[C], (W)[D], 13, 16); \
23 SIP_HALF_ROUND((W)[C], (W)[B], (W)[A], (W)[D], 17, 21); \
27 static inline uint64_t W64(const unsigned char *p, size_t j)
30 memcpy(&x, p + j*sizeof(x), sizeof(x));
31 return le64_to_cpu(x);
34 static void siphash_init(uint64_t v[5], const unsigned char key[16])
36 v[A] = W64(key, 0) ^ UINT64_C(0x736f6d6570736575);
37 v[B] = W64(key, 1) ^ UINT64_C(0x646f72616e646f6d);
38 v[C] = W64(key, 0) ^ UINT64_C(0x6c7967656e657261);
39 v[D] = W64(key, 1) ^ UINT64_C(0x7465646279746573);
40 v[E] = 0; /* message continuation */
43 /* Load the last 0-7 bytes of `in` and put in len & 255 */
44 static void siphash_epilogue(uint64_t *m, const unsigned char *in, size_t len)
46 in += len & ~(size_t)7;
47 *m = (uint64_t)(len & 255) << 56;
49 case 7: *m |= (uint64_t) in[6] << 48;
50 case 6: *m |= (uint64_t) in[5] << 40;
51 case 5: *m |= (uint64_t) in[4] << 32;
52 case 4: *m |= (uint64_t) in[3] << 24;
53 case 3: *m |= (uint64_t) in[2] << 16;
54 case 2: *m |= (uint64_t) in[1] << 8;
55 case 1: *m |= (uint64_t) in[0];
60 uint64_t siphash_2_4(const void *in, size_t len, const unsigned char key[16])
67 for (j = 0; j < len/8; j++) {
74 siphash_epilogue(&v[E], in, len);
88 return v[A]^v[B]^v[C]^v[D];