1 /* Licensed under GPL v2+ - see LICENSE file for details */
3 #include <ccan/endian/endian.h>
11 enum sip_index { A=0, B=2, C=1, D=3, E=4 };
13 #define rol(x,l) (((x) << (l)) | ((x) >> (64-(l))))
15 #define SIP_HALF_ROUND(a,b,c,d,L1,L2) \
18 (b) = (a) ^ rol((b),L1); \
19 (d) = (c) ^ rol((d),L2); \
22 #define SIP_ROUND(W) \
24 SIP_HALF_ROUND((W)[A], (W)[B], (W)[C], (W)[D], 13, 16); \
25 SIP_HALF_ROUND((W)[C], (W)[B], (W)[A], (W)[D], 17, 21); \
29 static inline u64 W64(const void *p, size_t I)
32 memcpy(&x, (char *)p + I*sizeof(x), sizeof(x));
33 return le64_to_cpu(x);
36 static void siphash_init(u64 v[5], const unsigned char key[16])
38 v[A] = W64(key, 0) ^ UINT64_C(0x736f6d6570736575);
39 v[B] = W64(key, 1) ^ UINT64_C(0x646f72616e646f6d);
40 v[C] = W64(key, 0) ^ UINT64_C(0x6c7967656e657261);
41 v[D] = W64(key, 1) ^ UINT64_C(0x7465646279746573);
42 v[E] = 0; /* message continuation */
45 /* Load the last 0-7 bytes of `in` and put in len & 255 */
46 static void siphash_epilogue(u64 *m, const unsigned char *in, size_t len)
49 *m = (u64)(len & 255) << 56;
51 case 7: *m |= (u64) in[6] << 48;
52 case 6: *m |= (u64) in[5] << 40;
53 case 5: *m |= (u64) in[4] << 32;
54 case 4: *m |= (u64) in[3] << 24;
55 case 3: *m |= (u64) in[2] << 16;
56 case 2: *m |= (u64) in[1] << 8;
57 case 1: *m |= (u64) in[0];
62 u64 siphash_2_4(const void *in, size_t len, const unsigned char key[16])
69 for (j = 0; j < len/8; j++) {
76 siphash_epilogue(&v[E], in, len);
90 return v[A]^v[B]^v[C]^v[D];