1*53c83d6dSJason A. Donenfeld // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2*53c83d6dSJason A. Donenfeld /* Copyright (C) 2016-2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
32c956a60SJason A. Donenfeld *
42c956a60SJason A. Donenfeld * SipHash: a fast short-input PRF
52c956a60SJason A. Donenfeld * https://131002.net/siphash/
62c956a60SJason A. Donenfeld *
71ae2324fSJason A. Donenfeld * This implementation is specifically for SipHash2-4 for a secure PRF
81ae2324fSJason A. Donenfeld * and HalfSipHash1-3/SipHash1-3 for an insecure PRF only suitable for
91ae2324fSJason A. Donenfeld * hashtables.
102c956a60SJason A. Donenfeld */
112c956a60SJason A. Donenfeld
122c956a60SJason A. Donenfeld #include <linux/siphash.h>
132c956a60SJason A. Donenfeld #include <asm/unaligned.h>
142c956a60SJason A. Donenfeld
152c956a60SJason A. Donenfeld #if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
162c956a60SJason A. Donenfeld #include <linux/dcache.h>
172c956a60SJason A. Donenfeld #include <asm/word-at-a-time.h>
182c956a60SJason A. Donenfeld #endif
192c956a60SJason A. Donenfeld
20e73aaae2SJason A. Donenfeld #define SIPROUND SIPHASH_PERMUTATION(v0, v1, v2, v3)
212c956a60SJason A. Donenfeld
222c956a60SJason A. Donenfeld #define PREAMBLE(len) \
23e73aaae2SJason A. Donenfeld u64 v0 = SIPHASH_CONST_0; \
24e73aaae2SJason A. Donenfeld u64 v1 = SIPHASH_CONST_1; \
25e73aaae2SJason A. Donenfeld u64 v2 = SIPHASH_CONST_2; \
26e73aaae2SJason A. Donenfeld u64 v3 = SIPHASH_CONST_3; \
272c956a60SJason A. Donenfeld u64 b = ((u64)(len)) << 56; \
282c956a60SJason A. Donenfeld v3 ^= key->key[1]; \
292c956a60SJason A. Donenfeld v2 ^= key->key[0]; \
302c956a60SJason A. Donenfeld v1 ^= key->key[1]; \
312c956a60SJason A. Donenfeld v0 ^= key->key[0];
322c956a60SJason A. Donenfeld
332c956a60SJason A. Donenfeld #define POSTAMBLE \
342c956a60SJason A. Donenfeld v3 ^= b; \
352c956a60SJason A. Donenfeld SIPROUND; \
362c956a60SJason A. Donenfeld SIPROUND; \
372c956a60SJason A. Donenfeld v0 ^= b; \
382c956a60SJason A. Donenfeld v2 ^= 0xff; \
392c956a60SJason A. Donenfeld SIPROUND; \
402c956a60SJason A. Donenfeld SIPROUND; \
412c956a60SJason A. Donenfeld SIPROUND; \
422c956a60SJason A. Donenfeld SIPROUND; \
432c956a60SJason A. Donenfeld return (v0 ^ v1) ^ (v2 ^ v3);
442c956a60SJason A. Donenfeld
45f7e5b9bfSArnd Bergmann #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
__siphash_aligned(const void * data,size_t len,const siphash_key_t * key)462c956a60SJason A. Donenfeld u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key)
472c956a60SJason A. Donenfeld {
482c956a60SJason A. Donenfeld const u8 *end = data + len - (len % sizeof(u64));
492c956a60SJason A. Donenfeld const u8 left = len & (sizeof(u64) - 1);
502c956a60SJason A. Donenfeld u64 m;
512c956a60SJason A. Donenfeld PREAMBLE(len)
522c956a60SJason A. Donenfeld for (; data != end; data += sizeof(u64)) {
532c956a60SJason A. Donenfeld m = le64_to_cpup(data);
542c956a60SJason A. Donenfeld v3 ^= m;
552c956a60SJason A. Donenfeld SIPROUND;
562c956a60SJason A. Donenfeld SIPROUND;
572c956a60SJason A. Donenfeld v0 ^= m;
582c956a60SJason A. Donenfeld }
592c956a60SJason A. Donenfeld #if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
602c956a60SJason A. Donenfeld if (left)
612c956a60SJason A. Donenfeld b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) &
622c956a60SJason A. Donenfeld bytemask_from_count(left)));
632c956a60SJason A. Donenfeld #else
642c956a60SJason A. Donenfeld switch (left) {
654c1ca831SNick Desaulniers case 7: b |= ((u64)end[6]) << 48; fallthrough;
664c1ca831SNick Desaulniers case 6: b |= ((u64)end[5]) << 40; fallthrough;
674c1ca831SNick Desaulniers case 5: b |= ((u64)end[4]) << 32; fallthrough;
682c956a60SJason A. Donenfeld case 4: b |= le32_to_cpup(data); break;
694c1ca831SNick Desaulniers case 3: b |= ((u64)end[2]) << 16; fallthrough;
702c956a60SJason A. Donenfeld case 2: b |= le16_to_cpup(data); break;
712c956a60SJason A. Donenfeld case 1: b |= end[0];
722c956a60SJason A. Donenfeld }
732c956a60SJason A. Donenfeld #endif
742c956a60SJason A. Donenfeld POSTAMBLE
752c956a60SJason A. Donenfeld }
762c956a60SJason A. Donenfeld EXPORT_SYMBOL(__siphash_aligned);
77f7e5b9bfSArnd Bergmann #endif
782c956a60SJason A. Donenfeld
__siphash_unaligned(const void * data,size_t len,const siphash_key_t * key)792c956a60SJason A. Donenfeld u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key)
802c956a60SJason A. Donenfeld {
812c956a60SJason A. Donenfeld const u8 *end = data + len - (len % sizeof(u64));
822c956a60SJason A. Donenfeld const u8 left = len & (sizeof(u64) - 1);
832c956a60SJason A. Donenfeld u64 m;
842c956a60SJason A. Donenfeld PREAMBLE(len)
852c956a60SJason A. Donenfeld for (; data != end; data += sizeof(u64)) {
862c956a60SJason A. Donenfeld m = get_unaligned_le64(data);
872c956a60SJason A. Donenfeld v3 ^= m;
882c956a60SJason A. Donenfeld SIPROUND;
892c956a60SJason A. Donenfeld SIPROUND;
902c956a60SJason A. Donenfeld v0 ^= m;
912c956a60SJason A. Donenfeld }
922c956a60SJason A. Donenfeld #if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
932c956a60SJason A. Donenfeld if (left)
942c956a60SJason A. Donenfeld b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) &
952c956a60SJason A. Donenfeld bytemask_from_count(left)));
962c956a60SJason A. Donenfeld #else
972c956a60SJason A. Donenfeld switch (left) {
984c1ca831SNick Desaulniers case 7: b |= ((u64)end[6]) << 48; fallthrough;
994c1ca831SNick Desaulniers case 6: b |= ((u64)end[5]) << 40; fallthrough;
1004c1ca831SNick Desaulniers case 5: b |= ((u64)end[4]) << 32; fallthrough;
1012c956a60SJason A. Donenfeld case 4: b |= get_unaligned_le32(end); break;
1024c1ca831SNick Desaulniers case 3: b |= ((u64)end[2]) << 16; fallthrough;
1032c956a60SJason A. Donenfeld case 2: b |= get_unaligned_le16(end); break;
1042c956a60SJason A. Donenfeld case 1: b |= end[0];
1052c956a60SJason A. Donenfeld }
1062c956a60SJason A. Donenfeld #endif
1072c956a60SJason A. Donenfeld POSTAMBLE
1082c956a60SJason A. Donenfeld }
1092c956a60SJason A. Donenfeld EXPORT_SYMBOL(__siphash_unaligned);
1102c956a60SJason A. Donenfeld
1112c956a60SJason A. Donenfeld /**
1122c956a60SJason A. Donenfeld * siphash_1u64 - compute 64-bit siphash PRF value of a u64
1132c956a60SJason A. Donenfeld * @first: first u64
1142c956a60SJason A. Donenfeld * @key: the siphash key
1152c956a60SJason A. Donenfeld */
siphash_1u64(const u64 first,const siphash_key_t * key)1162c956a60SJason A. Donenfeld u64 siphash_1u64(const u64 first, const siphash_key_t *key)
1172c956a60SJason A. Donenfeld {
1182c956a60SJason A. Donenfeld PREAMBLE(8)
1192c956a60SJason A. Donenfeld v3 ^= first;
1202c956a60SJason A. Donenfeld SIPROUND;
1212c956a60SJason A. Donenfeld SIPROUND;
1222c956a60SJason A. Donenfeld v0 ^= first;
1232c956a60SJason A. Donenfeld POSTAMBLE
1242c956a60SJason A. Donenfeld }
1252c956a60SJason A. Donenfeld EXPORT_SYMBOL(siphash_1u64);
1262c956a60SJason A. Donenfeld
1272c956a60SJason A. Donenfeld /**
1282c956a60SJason A. Donenfeld * siphash_2u64 - compute 64-bit siphash PRF value of 2 u64
1292c956a60SJason A. Donenfeld * @first: first u64
1302c956a60SJason A. Donenfeld * @second: second u64
1312c956a60SJason A. Donenfeld * @key: the siphash key
1322c956a60SJason A. Donenfeld */
siphash_2u64(const u64 first,const u64 second,const siphash_key_t * key)1332c956a60SJason A. Donenfeld u64 siphash_2u64(const u64 first, const u64 second, const siphash_key_t *key)
1342c956a60SJason A. Donenfeld {
1352c956a60SJason A. Donenfeld PREAMBLE(16)
1362c956a60SJason A. Donenfeld v3 ^= first;
1372c956a60SJason A. Donenfeld SIPROUND;
1382c956a60SJason A. Donenfeld SIPROUND;
1392c956a60SJason A. Donenfeld v0 ^= first;
1402c956a60SJason A. Donenfeld v3 ^= second;
1412c956a60SJason A. Donenfeld SIPROUND;
1422c956a60SJason A. Donenfeld SIPROUND;
1432c956a60SJason A. Donenfeld v0 ^= second;
1442c956a60SJason A. Donenfeld POSTAMBLE
1452c956a60SJason A. Donenfeld }
1462c956a60SJason A. Donenfeld EXPORT_SYMBOL(siphash_2u64);
1472c956a60SJason A. Donenfeld
1482c956a60SJason A. Donenfeld /**
1492c956a60SJason A. Donenfeld * siphash_3u64 - compute 64-bit siphash PRF value of 3 u64
1502c956a60SJason A. Donenfeld * @first: first u64
1512c956a60SJason A. Donenfeld * @second: second u64
1522c956a60SJason A. Donenfeld * @third: third u64
1532c956a60SJason A. Donenfeld * @key: the siphash key
1542c956a60SJason A. Donenfeld */
siphash_3u64(const u64 first,const u64 second,const u64 third,const siphash_key_t * key)1552c956a60SJason A. Donenfeld u64 siphash_3u64(const u64 first, const u64 second, const u64 third,
1562c956a60SJason A. Donenfeld const siphash_key_t *key)
1572c956a60SJason A. Donenfeld {
1582c956a60SJason A. Donenfeld PREAMBLE(24)
1592c956a60SJason A. Donenfeld v3 ^= first;
1602c956a60SJason A. Donenfeld SIPROUND;
1612c956a60SJason A. Donenfeld SIPROUND;
1622c956a60SJason A. Donenfeld v0 ^= first;
1632c956a60SJason A. Donenfeld v3 ^= second;
1642c956a60SJason A. Donenfeld SIPROUND;
1652c956a60SJason A. Donenfeld SIPROUND;
1662c956a60SJason A. Donenfeld v0 ^= second;
1672c956a60SJason A. Donenfeld v3 ^= third;
1682c956a60SJason A. Donenfeld SIPROUND;
1692c956a60SJason A. Donenfeld SIPROUND;
1702c956a60SJason A. Donenfeld v0 ^= third;
1712c956a60SJason A. Donenfeld POSTAMBLE
1722c956a60SJason A. Donenfeld }
1732c956a60SJason A. Donenfeld EXPORT_SYMBOL(siphash_3u64);
1742c956a60SJason A. Donenfeld
1752c956a60SJason A. Donenfeld /**
1762c956a60SJason A. Donenfeld * siphash_4u64 - compute 64-bit siphash PRF value of 4 u64
1772c956a60SJason A. Donenfeld * @first: first u64
1782c956a60SJason A. Donenfeld * @second: second u64
1792c956a60SJason A. Donenfeld * @third: third u64
1802c956a60SJason A. Donenfeld * @forth: forth u64
1812c956a60SJason A. Donenfeld * @key: the siphash key
1822c956a60SJason A. Donenfeld */
siphash_4u64(const u64 first,const u64 second,const u64 third,const u64 forth,const siphash_key_t * key)1832c956a60SJason A. Donenfeld u64 siphash_4u64(const u64 first, const u64 second, const u64 third,
1842c956a60SJason A. Donenfeld const u64 forth, const siphash_key_t *key)
1852c956a60SJason A. Donenfeld {
1862c956a60SJason A. Donenfeld PREAMBLE(32)
1872c956a60SJason A. Donenfeld v3 ^= first;
1882c956a60SJason A. Donenfeld SIPROUND;
1892c956a60SJason A. Donenfeld SIPROUND;
1902c956a60SJason A. Donenfeld v0 ^= first;
1912c956a60SJason A. Donenfeld v3 ^= second;
1922c956a60SJason A. Donenfeld SIPROUND;
1932c956a60SJason A. Donenfeld SIPROUND;
1942c956a60SJason A. Donenfeld v0 ^= second;
1952c956a60SJason A. Donenfeld v3 ^= third;
1962c956a60SJason A. Donenfeld SIPROUND;
1972c956a60SJason A. Donenfeld SIPROUND;
1982c956a60SJason A. Donenfeld v0 ^= third;
1992c956a60SJason A. Donenfeld v3 ^= forth;
2002c956a60SJason A. Donenfeld SIPROUND;
2012c956a60SJason A. Donenfeld SIPROUND;
2022c956a60SJason A. Donenfeld v0 ^= forth;
2032c956a60SJason A. Donenfeld POSTAMBLE
2042c956a60SJason A. Donenfeld }
2052c956a60SJason A. Donenfeld EXPORT_SYMBOL(siphash_4u64);
2062c956a60SJason A. Donenfeld
siphash_1u32(const u32 first,const siphash_key_t * key)2072c956a60SJason A. Donenfeld u64 siphash_1u32(const u32 first, const siphash_key_t *key)
2082c956a60SJason A. Donenfeld {
2092c956a60SJason A. Donenfeld PREAMBLE(4)
2102c956a60SJason A. Donenfeld b |= first;
2112c956a60SJason A. Donenfeld POSTAMBLE
2122c956a60SJason A. Donenfeld }
2132c956a60SJason A. Donenfeld EXPORT_SYMBOL(siphash_1u32);
2142c956a60SJason A. Donenfeld
siphash_3u32(const u32 first,const u32 second,const u32 third,const siphash_key_t * key)2152c956a60SJason A. Donenfeld u64 siphash_3u32(const u32 first, const u32 second, const u32 third,
2162c956a60SJason A. Donenfeld const siphash_key_t *key)
2172c956a60SJason A. Donenfeld {
2182c956a60SJason A. Donenfeld u64 combined = (u64)second << 32 | first;
2192c956a60SJason A. Donenfeld PREAMBLE(12)
2202c956a60SJason A. Donenfeld v3 ^= combined;
2212c956a60SJason A. Donenfeld SIPROUND;
2222c956a60SJason A. Donenfeld SIPROUND;
2232c956a60SJason A. Donenfeld v0 ^= combined;
2242c956a60SJason A. Donenfeld b |= third;
2252c956a60SJason A. Donenfeld POSTAMBLE
2262c956a60SJason A. Donenfeld }
2272c956a60SJason A. Donenfeld EXPORT_SYMBOL(siphash_3u32);
2281ae2324fSJason A. Donenfeld
2291ae2324fSJason A. Donenfeld #if BITS_PER_LONG == 64
2301ae2324fSJason A. Donenfeld /* Note that on 64-bit, we make HalfSipHash1-3 actually be SipHash1-3, for
2311ae2324fSJason A. Donenfeld * performance reasons. On 32-bit, below, we actually implement HalfSipHash1-3.
2321ae2324fSJason A. Donenfeld */
2331ae2324fSJason A. Donenfeld
2341ae2324fSJason A. Donenfeld #define HSIPROUND SIPROUND
2351ae2324fSJason A. Donenfeld #define HPREAMBLE(len) PREAMBLE(len)
2361ae2324fSJason A. Donenfeld #define HPOSTAMBLE \
2371ae2324fSJason A. Donenfeld v3 ^= b; \
2381ae2324fSJason A. Donenfeld HSIPROUND; \
2391ae2324fSJason A. Donenfeld v0 ^= b; \
2401ae2324fSJason A. Donenfeld v2 ^= 0xff; \
2411ae2324fSJason A. Donenfeld HSIPROUND; \
2421ae2324fSJason A. Donenfeld HSIPROUND; \
2431ae2324fSJason A. Donenfeld HSIPROUND; \
2441ae2324fSJason A. Donenfeld return (v0 ^ v1) ^ (v2 ^ v3);
2451ae2324fSJason A. Donenfeld
246f7e5b9bfSArnd Bergmann #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
__hsiphash_aligned(const void * data,size_t len,const hsiphash_key_t * key)2471ae2324fSJason A. Donenfeld u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key)
2481ae2324fSJason A. Donenfeld {
2491ae2324fSJason A. Donenfeld const u8 *end = data + len - (len % sizeof(u64));
2501ae2324fSJason A. Donenfeld const u8 left = len & (sizeof(u64) - 1);
2511ae2324fSJason A. Donenfeld u64 m;
2521ae2324fSJason A. Donenfeld HPREAMBLE(len)
2531ae2324fSJason A. Donenfeld for (; data != end; data += sizeof(u64)) {
2541ae2324fSJason A. Donenfeld m = le64_to_cpup(data);
2551ae2324fSJason A. Donenfeld v3 ^= m;
2561ae2324fSJason A. Donenfeld HSIPROUND;
2571ae2324fSJason A. Donenfeld v0 ^= m;
2581ae2324fSJason A. Donenfeld }
2591ae2324fSJason A. Donenfeld #if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
2601ae2324fSJason A. Donenfeld if (left)
2611ae2324fSJason A. Donenfeld b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) &
2621ae2324fSJason A. Donenfeld bytemask_from_count(left)));
2631ae2324fSJason A. Donenfeld #else
2641ae2324fSJason A. Donenfeld switch (left) {
2654c1ca831SNick Desaulniers case 7: b |= ((u64)end[6]) << 48; fallthrough;
2664c1ca831SNick Desaulniers case 6: b |= ((u64)end[5]) << 40; fallthrough;
2674c1ca831SNick Desaulniers case 5: b |= ((u64)end[4]) << 32; fallthrough;
2681ae2324fSJason A. Donenfeld case 4: b |= le32_to_cpup(data); break;
2694c1ca831SNick Desaulniers case 3: b |= ((u64)end[2]) << 16; fallthrough;
2701ae2324fSJason A. Donenfeld case 2: b |= le16_to_cpup(data); break;
2711ae2324fSJason A. Donenfeld case 1: b |= end[0];
2721ae2324fSJason A. Donenfeld }
2731ae2324fSJason A. Donenfeld #endif
2741ae2324fSJason A. Donenfeld HPOSTAMBLE
2751ae2324fSJason A. Donenfeld }
2761ae2324fSJason A. Donenfeld EXPORT_SYMBOL(__hsiphash_aligned);
277f7e5b9bfSArnd Bergmann #endif
2781ae2324fSJason A. Donenfeld
__hsiphash_unaligned(const void * data,size_t len,const hsiphash_key_t * key)2791ae2324fSJason A. Donenfeld u32 __hsiphash_unaligned(const void *data, size_t len,
2801ae2324fSJason A. Donenfeld const hsiphash_key_t *key)
2811ae2324fSJason A. Donenfeld {
2821ae2324fSJason A. Donenfeld const u8 *end = data + len - (len % sizeof(u64));
2831ae2324fSJason A. Donenfeld const u8 left = len & (sizeof(u64) - 1);
2841ae2324fSJason A. Donenfeld u64 m;
2851ae2324fSJason A. Donenfeld HPREAMBLE(len)
2861ae2324fSJason A. Donenfeld for (; data != end; data += sizeof(u64)) {
2871ae2324fSJason A. Donenfeld m = get_unaligned_le64(data);
2881ae2324fSJason A. Donenfeld v3 ^= m;
2891ae2324fSJason A. Donenfeld HSIPROUND;
2901ae2324fSJason A. Donenfeld v0 ^= m;
2911ae2324fSJason A. Donenfeld }
2921ae2324fSJason A. Donenfeld #if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
2931ae2324fSJason A. Donenfeld if (left)
2941ae2324fSJason A. Donenfeld b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) &
2951ae2324fSJason A. Donenfeld bytemask_from_count(left)));
2961ae2324fSJason A. Donenfeld #else
2971ae2324fSJason A. Donenfeld switch (left) {
2984c1ca831SNick Desaulniers case 7: b |= ((u64)end[6]) << 48; fallthrough;
2994c1ca831SNick Desaulniers case 6: b |= ((u64)end[5]) << 40; fallthrough;
3004c1ca831SNick Desaulniers case 5: b |= ((u64)end[4]) << 32; fallthrough;
3011ae2324fSJason A. Donenfeld case 4: b |= get_unaligned_le32(end); break;
3024c1ca831SNick Desaulniers case 3: b |= ((u64)end[2]) << 16; fallthrough;
3031ae2324fSJason A. Donenfeld case 2: b |= get_unaligned_le16(end); break;
3041ae2324fSJason A. Donenfeld case 1: b |= end[0];
3051ae2324fSJason A. Donenfeld }
3061ae2324fSJason A. Donenfeld #endif
3071ae2324fSJason A. Donenfeld HPOSTAMBLE
3081ae2324fSJason A. Donenfeld }
3091ae2324fSJason A. Donenfeld EXPORT_SYMBOL(__hsiphash_unaligned);
3101ae2324fSJason A. Donenfeld
3111ae2324fSJason A. Donenfeld /**
3121ae2324fSJason A. Donenfeld * hsiphash_1u32 - compute 64-bit hsiphash PRF value of a u32
3131ae2324fSJason A. Donenfeld * @first: first u32
3141ae2324fSJason A. Donenfeld * @key: the hsiphash key
3151ae2324fSJason A. Donenfeld */
hsiphash_1u32(const u32 first,const hsiphash_key_t * key)3161ae2324fSJason A. Donenfeld u32 hsiphash_1u32(const u32 first, const hsiphash_key_t *key)
3171ae2324fSJason A. Donenfeld {
3181ae2324fSJason A. Donenfeld HPREAMBLE(4)
3191ae2324fSJason A. Donenfeld b |= first;
3201ae2324fSJason A. Donenfeld HPOSTAMBLE
3211ae2324fSJason A. Donenfeld }
3221ae2324fSJason A. Donenfeld EXPORT_SYMBOL(hsiphash_1u32);
3231ae2324fSJason A. Donenfeld
3241ae2324fSJason A. Donenfeld /**
3251ae2324fSJason A. Donenfeld * hsiphash_2u32 - compute 32-bit hsiphash PRF value of 2 u32
3261ae2324fSJason A. Donenfeld * @first: first u32
3271ae2324fSJason A. Donenfeld * @second: second u32
3281ae2324fSJason A. Donenfeld * @key: the hsiphash key
3291ae2324fSJason A. Donenfeld */
hsiphash_2u32(const u32 first,const u32 second,const hsiphash_key_t * key)3301ae2324fSJason A. Donenfeld u32 hsiphash_2u32(const u32 first, const u32 second, const hsiphash_key_t *key)
3311ae2324fSJason A. Donenfeld {
3321ae2324fSJason A. Donenfeld u64 combined = (u64)second << 32 | first;
3331ae2324fSJason A. Donenfeld HPREAMBLE(8)
3341ae2324fSJason A. Donenfeld v3 ^= combined;
3351ae2324fSJason A. Donenfeld HSIPROUND;
3361ae2324fSJason A. Donenfeld v0 ^= combined;
3371ae2324fSJason A. Donenfeld HPOSTAMBLE
3381ae2324fSJason A. Donenfeld }
3391ae2324fSJason A. Donenfeld EXPORT_SYMBOL(hsiphash_2u32);
3401ae2324fSJason A. Donenfeld
3411ae2324fSJason A. Donenfeld /**
3421ae2324fSJason A. Donenfeld * hsiphash_3u32 - compute 32-bit hsiphash PRF value of 3 u32
3431ae2324fSJason A. Donenfeld * @first: first u32
3441ae2324fSJason A. Donenfeld * @second: second u32
3451ae2324fSJason A. Donenfeld * @third: third u32
3461ae2324fSJason A. Donenfeld * @key: the hsiphash key
3471ae2324fSJason A. Donenfeld */
hsiphash_3u32(const u32 first,const u32 second,const u32 third,const hsiphash_key_t * key)3481ae2324fSJason A. Donenfeld u32 hsiphash_3u32(const u32 first, const u32 second, const u32 third,
3491ae2324fSJason A. Donenfeld const hsiphash_key_t *key)
3501ae2324fSJason A. Donenfeld {
3511ae2324fSJason A. Donenfeld u64 combined = (u64)second << 32 | first;
3521ae2324fSJason A. Donenfeld HPREAMBLE(12)
3531ae2324fSJason A. Donenfeld v3 ^= combined;
3541ae2324fSJason A. Donenfeld HSIPROUND;
3551ae2324fSJason A. Donenfeld v0 ^= combined;
3561ae2324fSJason A. Donenfeld b |= third;
3571ae2324fSJason A. Donenfeld HPOSTAMBLE
3581ae2324fSJason A. Donenfeld }
3591ae2324fSJason A. Donenfeld EXPORT_SYMBOL(hsiphash_3u32);
3601ae2324fSJason A. Donenfeld
3611ae2324fSJason A. Donenfeld /**
3621ae2324fSJason A. Donenfeld * hsiphash_4u32 - compute 32-bit hsiphash PRF value of 4 u32
3631ae2324fSJason A. Donenfeld * @first: first u32
3641ae2324fSJason A. Donenfeld * @second: second u32
3651ae2324fSJason A. Donenfeld * @third: third u32
3661ae2324fSJason A. Donenfeld * @forth: forth u32
3671ae2324fSJason A. Donenfeld * @key: the hsiphash key
3681ae2324fSJason A. Donenfeld */
hsiphash_4u32(const u32 first,const u32 second,const u32 third,const u32 forth,const hsiphash_key_t * key)3691ae2324fSJason A. Donenfeld u32 hsiphash_4u32(const u32 first, const u32 second, const u32 third,
3701ae2324fSJason A. Donenfeld const u32 forth, const hsiphash_key_t *key)
3711ae2324fSJason A. Donenfeld {
3721ae2324fSJason A. Donenfeld u64 combined = (u64)second << 32 | first;
3731ae2324fSJason A. Donenfeld HPREAMBLE(16)
3741ae2324fSJason A. Donenfeld v3 ^= combined;
3751ae2324fSJason A. Donenfeld HSIPROUND;
3761ae2324fSJason A. Donenfeld v0 ^= combined;
3771ae2324fSJason A. Donenfeld combined = (u64)forth << 32 | third;
3781ae2324fSJason A. Donenfeld v3 ^= combined;
3791ae2324fSJason A. Donenfeld HSIPROUND;
3801ae2324fSJason A. Donenfeld v0 ^= combined;
3811ae2324fSJason A. Donenfeld HPOSTAMBLE
3821ae2324fSJason A. Donenfeld }
3831ae2324fSJason A. Donenfeld EXPORT_SYMBOL(hsiphash_4u32);
3841ae2324fSJason A. Donenfeld #else
385e73aaae2SJason A. Donenfeld #define HSIPROUND HSIPHASH_PERMUTATION(v0, v1, v2, v3)
3861ae2324fSJason A. Donenfeld
3871ae2324fSJason A. Donenfeld #define HPREAMBLE(len) \
388e73aaae2SJason A. Donenfeld u32 v0 = HSIPHASH_CONST_0; \
389e73aaae2SJason A. Donenfeld u32 v1 = HSIPHASH_CONST_1; \
390e73aaae2SJason A. Donenfeld u32 v2 = HSIPHASH_CONST_2; \
391e73aaae2SJason A. Donenfeld u32 v3 = HSIPHASH_CONST_3; \
3921ae2324fSJason A. Donenfeld u32 b = ((u32)(len)) << 24; \
3931ae2324fSJason A. Donenfeld v3 ^= key->key[1]; \
3941ae2324fSJason A. Donenfeld v2 ^= key->key[0]; \
3951ae2324fSJason A. Donenfeld v1 ^= key->key[1]; \
3961ae2324fSJason A. Donenfeld v0 ^= key->key[0];
3971ae2324fSJason A. Donenfeld
3981ae2324fSJason A. Donenfeld #define HPOSTAMBLE \
3991ae2324fSJason A. Donenfeld v3 ^= b; \
4001ae2324fSJason A. Donenfeld HSIPROUND; \
4011ae2324fSJason A. Donenfeld v0 ^= b; \
4021ae2324fSJason A. Donenfeld v2 ^= 0xff; \
4031ae2324fSJason A. Donenfeld HSIPROUND; \
4041ae2324fSJason A. Donenfeld HSIPROUND; \
4051ae2324fSJason A. Donenfeld HSIPROUND; \
4061ae2324fSJason A. Donenfeld return v1 ^ v3;
4071ae2324fSJason A. Donenfeld
408f7e5b9bfSArnd Bergmann #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
__hsiphash_aligned(const void * data,size_t len,const hsiphash_key_t * key)4091ae2324fSJason A. Donenfeld u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key)
4101ae2324fSJason A. Donenfeld {
4111ae2324fSJason A. Donenfeld const u8 *end = data + len - (len % sizeof(u32));
4121ae2324fSJason A. Donenfeld const u8 left = len & (sizeof(u32) - 1);
4131ae2324fSJason A. Donenfeld u32 m;
4141ae2324fSJason A. Donenfeld HPREAMBLE(len)
4151ae2324fSJason A. Donenfeld for (; data != end; data += sizeof(u32)) {
4161ae2324fSJason A. Donenfeld m = le32_to_cpup(data);
4171ae2324fSJason A. Donenfeld v3 ^= m;
4181ae2324fSJason A. Donenfeld HSIPROUND;
4191ae2324fSJason A. Donenfeld v0 ^= m;
4201ae2324fSJason A. Donenfeld }
4211ae2324fSJason A. Donenfeld switch (left) {
4224c1ca831SNick Desaulniers case 3: b |= ((u32)end[2]) << 16; fallthrough;
4231ae2324fSJason A. Donenfeld case 2: b |= le16_to_cpup(data); break;
4241ae2324fSJason A. Donenfeld case 1: b |= end[0];
4251ae2324fSJason A. Donenfeld }
4261ae2324fSJason A. Donenfeld HPOSTAMBLE
4271ae2324fSJason A. Donenfeld }
4281ae2324fSJason A. Donenfeld EXPORT_SYMBOL(__hsiphash_aligned);
429f7e5b9bfSArnd Bergmann #endif
4301ae2324fSJason A. Donenfeld
__hsiphash_unaligned(const void * data,size_t len,const hsiphash_key_t * key)4311ae2324fSJason A. Donenfeld u32 __hsiphash_unaligned(const void *data, size_t len,
4321ae2324fSJason A. Donenfeld const hsiphash_key_t *key)
4331ae2324fSJason A. Donenfeld {
4341ae2324fSJason A. Donenfeld const u8 *end = data + len - (len % sizeof(u32));
4351ae2324fSJason A. Donenfeld const u8 left = len & (sizeof(u32) - 1);
4361ae2324fSJason A. Donenfeld u32 m;
4371ae2324fSJason A. Donenfeld HPREAMBLE(len)
4381ae2324fSJason A. Donenfeld for (; data != end; data += sizeof(u32)) {
4391ae2324fSJason A. Donenfeld m = get_unaligned_le32(data);
4401ae2324fSJason A. Donenfeld v3 ^= m;
4411ae2324fSJason A. Donenfeld HSIPROUND;
4421ae2324fSJason A. Donenfeld v0 ^= m;
4431ae2324fSJason A. Donenfeld }
4441ae2324fSJason A. Donenfeld switch (left) {
4454c1ca831SNick Desaulniers case 3: b |= ((u32)end[2]) << 16; fallthrough;
4461ae2324fSJason A. Donenfeld case 2: b |= get_unaligned_le16(end); break;
4471ae2324fSJason A. Donenfeld case 1: b |= end[0];
4481ae2324fSJason A. Donenfeld }
4491ae2324fSJason A. Donenfeld HPOSTAMBLE
4501ae2324fSJason A. Donenfeld }
4511ae2324fSJason A. Donenfeld EXPORT_SYMBOL(__hsiphash_unaligned);
4521ae2324fSJason A. Donenfeld
4531ae2324fSJason A. Donenfeld /**
4541ae2324fSJason A. Donenfeld * hsiphash_1u32 - compute 32-bit hsiphash PRF value of a u32
4551ae2324fSJason A. Donenfeld * @first: first u32
4561ae2324fSJason A. Donenfeld * @key: the hsiphash key
4571ae2324fSJason A. Donenfeld */
hsiphash_1u32(const u32 first,const hsiphash_key_t * key)4581ae2324fSJason A. Donenfeld u32 hsiphash_1u32(const u32 first, const hsiphash_key_t *key)
4591ae2324fSJason A. Donenfeld {
4601ae2324fSJason A. Donenfeld HPREAMBLE(4)
4611ae2324fSJason A. Donenfeld v3 ^= first;
4621ae2324fSJason A. Donenfeld HSIPROUND;
4631ae2324fSJason A. Donenfeld v0 ^= first;
4641ae2324fSJason A. Donenfeld HPOSTAMBLE
4651ae2324fSJason A. Donenfeld }
4661ae2324fSJason A. Donenfeld EXPORT_SYMBOL(hsiphash_1u32);
4671ae2324fSJason A. Donenfeld
4681ae2324fSJason A. Donenfeld /**
4691ae2324fSJason A. Donenfeld * hsiphash_2u32 - compute 32-bit hsiphash PRF value of 2 u32
4701ae2324fSJason A. Donenfeld * @first: first u32
4711ae2324fSJason A. Donenfeld * @second: second u32
4721ae2324fSJason A. Donenfeld * @key: the hsiphash key
4731ae2324fSJason A. Donenfeld */
hsiphash_2u32(const u32 first,const u32 second,const hsiphash_key_t * key)4741ae2324fSJason A. Donenfeld u32 hsiphash_2u32(const u32 first, const u32 second, const hsiphash_key_t *key)
4751ae2324fSJason A. Donenfeld {
4761ae2324fSJason A. Donenfeld HPREAMBLE(8)
4771ae2324fSJason A. Donenfeld v3 ^= first;
4781ae2324fSJason A. Donenfeld HSIPROUND;
4791ae2324fSJason A. Donenfeld v0 ^= first;
4801ae2324fSJason A. Donenfeld v3 ^= second;
4811ae2324fSJason A. Donenfeld HSIPROUND;
4821ae2324fSJason A. Donenfeld v0 ^= second;
4831ae2324fSJason A. Donenfeld HPOSTAMBLE
4841ae2324fSJason A. Donenfeld }
4851ae2324fSJason A. Donenfeld EXPORT_SYMBOL(hsiphash_2u32);
4861ae2324fSJason A. Donenfeld
4871ae2324fSJason A. Donenfeld /**
4881ae2324fSJason A. Donenfeld * hsiphash_3u32 - compute 32-bit hsiphash PRF value of 3 u32
4891ae2324fSJason A. Donenfeld * @first: first u32
4901ae2324fSJason A. Donenfeld * @second: second u32
4911ae2324fSJason A. Donenfeld * @third: third u32
4921ae2324fSJason A. Donenfeld * @key: the hsiphash key
4931ae2324fSJason A. Donenfeld */
hsiphash_3u32(const u32 first,const u32 second,const u32 third,const hsiphash_key_t * key)4941ae2324fSJason A. Donenfeld u32 hsiphash_3u32(const u32 first, const u32 second, const u32 third,
4951ae2324fSJason A. Donenfeld const hsiphash_key_t *key)
4961ae2324fSJason A. Donenfeld {
4971ae2324fSJason A. Donenfeld HPREAMBLE(12)
4981ae2324fSJason A. Donenfeld v3 ^= first;
4991ae2324fSJason A. Donenfeld HSIPROUND;
5001ae2324fSJason A. Donenfeld v0 ^= first;
5011ae2324fSJason A. Donenfeld v3 ^= second;
5021ae2324fSJason A. Donenfeld HSIPROUND;
5031ae2324fSJason A. Donenfeld v0 ^= second;
5041ae2324fSJason A. Donenfeld v3 ^= third;
5051ae2324fSJason A. Donenfeld HSIPROUND;
5061ae2324fSJason A. Donenfeld v0 ^= third;
5071ae2324fSJason A. Donenfeld HPOSTAMBLE
5081ae2324fSJason A. Donenfeld }
5091ae2324fSJason A. Donenfeld EXPORT_SYMBOL(hsiphash_3u32);
5101ae2324fSJason A. Donenfeld
5111ae2324fSJason A. Donenfeld /**
5121ae2324fSJason A. Donenfeld * hsiphash_4u32 - compute 32-bit hsiphash PRF value of 4 u32
5131ae2324fSJason A. Donenfeld * @first: first u32
5141ae2324fSJason A. Donenfeld * @second: second u32
5151ae2324fSJason A. Donenfeld * @third: third u32
5161ae2324fSJason A. Donenfeld * @forth: forth u32
5171ae2324fSJason A. Donenfeld * @key: the hsiphash key
5181ae2324fSJason A. Donenfeld */
hsiphash_4u32(const u32 first,const u32 second,const u32 third,const u32 forth,const hsiphash_key_t * key)5191ae2324fSJason A. Donenfeld u32 hsiphash_4u32(const u32 first, const u32 second, const u32 third,
5201ae2324fSJason A. Donenfeld const u32 forth, const hsiphash_key_t *key)
5211ae2324fSJason A. Donenfeld {
5221ae2324fSJason A. Donenfeld HPREAMBLE(16)
5231ae2324fSJason A. Donenfeld v3 ^= first;
5241ae2324fSJason A. Donenfeld HSIPROUND;
5251ae2324fSJason A. Donenfeld v0 ^= first;
5261ae2324fSJason A. Donenfeld v3 ^= second;
5271ae2324fSJason A. Donenfeld HSIPROUND;
5281ae2324fSJason A. Donenfeld v0 ^= second;
5291ae2324fSJason A. Donenfeld v3 ^= third;
5301ae2324fSJason A. Donenfeld HSIPROUND;
5311ae2324fSJason A. Donenfeld v0 ^= third;
5321ae2324fSJason A. Donenfeld v3 ^= forth;
5331ae2324fSJason A. Donenfeld HSIPROUND;
5341ae2324fSJason A. Donenfeld v0 ^= forth;
5351ae2324fSJason A. Donenfeld HPOSTAMBLE
5361ae2324fSJason A. Donenfeld }
5371ae2324fSJason A. Donenfeld EXPORT_SYMBOL(hsiphash_4u32);
5381ae2324fSJason A. Donenfeld #endif
539