#include #include #include #include #include "impl.h" static const int cROUNDS = 2; static const int dROUNDS = 4; static inline uint64_t ROTL(uint64_t x, uint64_t b) { return (x << b) | (x >> (64 - b)); } static inline void U32TO8_LE(u8 *p, uint32_t v) { p[0] = (u8)(v >> 0); p[1] = (u8)(v >> 8); p[2] = (u8)(v >> 16); p[3] = (u8)(v >> 24); } static inline void U64TO8_LE(u8 *p, uint64_t v) { U32TO8_LE(p + 0, (uint32_t)(v >> 0)); U32TO8_LE(p + 4, (uint32_t)(v >> 32)); } static inline uint64_t U8TO64_LE(const u8 *p) { return (((uint64_t)p[0]) << 0) | (((uint64_t)p[1]) << 8) | (((uint64_t)p[2]) << 16) | (((uint64_t)p[3]) << 24) | (((uint64_t)p[4]) << 32) | (((uint64_t)p[5]) << 40) | (((uint64_t)p[6]) << 48) | (((uint64_t)p[7]) << 56); } static inline void SIPROUND(uint64_t *v0, uint64_t *v1, uint64_t *v2, uint64_t *v3) { *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); } /** Computes a SipHash value: - *in: pointer to input data (read-only) - inlen: input data length in bytes (any size_t value) - *key: pointer to the key data (read-only), must be 16 bytes - *out: pointer to output data (write-only), outlen bytes must be allocated - outlen: length of the output in bytes, must be 8 or 16 */ int siphash_impl( const void *const restrict in, const size_t inlen, const void *const restrict key, u8 out[16U], const size_t outlen ) { const unsigned char *ni = (const unsigned char *)in; const unsigned char *kk = (const unsigned char *)key; #line 95 assert((outlen == 8) || (outlen == 16)); #line 89 uint64_t v0 = UINT64_C(0x736f6d6570736575); uint64_t v1 = UINT64_C(0x646f72616e646f6d); uint64_t v2 = UINT64_C(0x6c7967656e657261); uint64_t v3 = UINT64_C(0x7465646279746573); const uint64_t k0 = U8TO64_LE(kk); const uint64_t k1 = U8TO64_LE(kk + 8); const unsigned char *end = ni + inlen - (inlen % sizeof(uint64_t)); const int left = inlen & 7; uint64_t b = ((uint64_t)inlen) << 56; v3 ^= k1; v2 ^= k0; v1 ^= k1; v0 ^= k0; if (outlen == 16) { v1 ^= 0xee; } while (ni != end) { uint64_t m = U8TO64_LE(ni); v3 ^= m; for (int i = 0; i < cROUNDS; i++) { SIPROUND(&v0, &v1, &v2, &v3); } v0 ^= m; ni += 8; } switch (left) { case 7: b |= ((uint64_t)ni[6]) << 48; // fallthrough case 6: b |= ((uint64_t)ni[5]) << 40; // fallthrough case 5: b |= ((uint64_t)ni[4]) << 32; // fallthrough case 4: b |= ((uint64_t)ni[3]) << 24; // fallthrough case 3: b |= ((uint64_t)ni[2]) << 16; // fallthrough case 2: b |= ((uint64_t)ni[1]) << 8; // fallthrough case 1: b |= ((uint64_t)ni[0]); break; case 0: break; } v3 ^= b; for (int i = 0; i < cROUNDS; i++) { SIPROUND(&v0, &v1, &v2, &v3); } v0 ^= b; if (outlen == 16) { v2 ^= 0xee; } else { v2 ^= 0xff; } for (int i = 0; i < dROUNDS; i++) { SIPROUND(&v0, &v1, &v2, &v3); } b = v0 ^ v1 ^ v2 ^ v3; U64TO8_LE(out, b); if (outlen == 8) { return 0; } v1 ^= 0xdd; for (int i = 0; i < dROUNDS; i++) { SIPROUND(&v0, &v1, &v2, &v3); } b = v0 ^ v1 ^ v2 ^ v3; U64TO8_LE(out + 8, b); return 0; }