18c2ecf20Sopenharmony_ci/* Copyright (C) 2016 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
28c2ecf20Sopenharmony_ci *
38c2ecf20Sopenharmony_ci * This file is provided under a dual BSD/GPLv2 license.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * SipHash: a fast short-input PRF
68c2ecf20Sopenharmony_ci * https://131002.net/siphash/
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * This implementation is specifically for SipHash2-4 for a secure PRF
98c2ecf20Sopenharmony_ci * and HalfSipHash1-3/SipHash1-3 for an insecure PRF only suitable for
108c2ecf20Sopenharmony_ci * hashtables.
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/siphash.h>
148c2ecf20Sopenharmony_ci#include <asm/unaligned.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
178c2ecf20Sopenharmony_ci#include <linux/dcache.h>
188c2ecf20Sopenharmony_ci#include <asm/word-at-a-time.h>
198c2ecf20Sopenharmony_ci#endif
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#define SIPROUND SIPHASH_PERMUTATION(v0, v1, v2, v3)
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#define PREAMBLE(len) \
248c2ecf20Sopenharmony_ci	u64 v0 = SIPHASH_CONST_0; \
258c2ecf20Sopenharmony_ci	u64 v1 = SIPHASH_CONST_1; \
268c2ecf20Sopenharmony_ci	u64 v2 = SIPHASH_CONST_2; \
278c2ecf20Sopenharmony_ci	u64 v3 = SIPHASH_CONST_3; \
288c2ecf20Sopenharmony_ci	u64 b = ((u64)(len)) << 56; \
298c2ecf20Sopenharmony_ci	v3 ^= key->key[1]; \
308c2ecf20Sopenharmony_ci	v2 ^= key->key[0]; \
318c2ecf20Sopenharmony_ci	v1 ^= key->key[1]; \
328c2ecf20Sopenharmony_ci	v0 ^= key->key[0];
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#define POSTAMBLE \
358c2ecf20Sopenharmony_ci	v3 ^= b; \
368c2ecf20Sopenharmony_ci	SIPROUND; \
378c2ecf20Sopenharmony_ci	SIPROUND; \
388c2ecf20Sopenharmony_ci	v0 ^= b; \
398c2ecf20Sopenharmony_ci	v2 ^= 0xff; \
408c2ecf20Sopenharmony_ci	SIPROUND; \
418c2ecf20Sopenharmony_ci	SIPROUND; \
428c2ecf20Sopenharmony_ci	SIPROUND; \
438c2ecf20Sopenharmony_ci	SIPROUND; \
448c2ecf20Sopenharmony_ci	return (v0 ^ v1) ^ (v2 ^ v3);
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
478c2ecf20Sopenharmony_ciu64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	const u8 *end = data + len - (len % sizeof(u64));
508c2ecf20Sopenharmony_ci	const u8 left = len & (sizeof(u64) - 1);
518c2ecf20Sopenharmony_ci	u64 m;
528c2ecf20Sopenharmony_ci	PREAMBLE(len)
538c2ecf20Sopenharmony_ci	for (; data != end; data += sizeof(u64)) {
548c2ecf20Sopenharmony_ci		m = le64_to_cpup(data);
558c2ecf20Sopenharmony_ci		v3 ^= m;
568c2ecf20Sopenharmony_ci		SIPROUND;
578c2ecf20Sopenharmony_ci		SIPROUND;
588c2ecf20Sopenharmony_ci		v0 ^= m;
598c2ecf20Sopenharmony_ci	}
608c2ecf20Sopenharmony_ci#if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
618c2ecf20Sopenharmony_ci	if (left)
628c2ecf20Sopenharmony_ci		b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) &
638c2ecf20Sopenharmony_ci						  bytemask_from_count(left)));
648c2ecf20Sopenharmony_ci#else
658c2ecf20Sopenharmony_ci	switch (left) {
668c2ecf20Sopenharmony_ci	case 7: b |= ((u64)end[6]) << 48; /* fall through */
678c2ecf20Sopenharmony_ci	case 6: b |= ((u64)end[5]) << 40; /* fall through */
688c2ecf20Sopenharmony_ci	case 5: b |= ((u64)end[4]) << 32; /* fall through */
698c2ecf20Sopenharmony_ci	case 4: b |= le32_to_cpup(data); break;
708c2ecf20Sopenharmony_ci	case 3: b |= ((u64)end[2]) << 16; /* fall through */
718c2ecf20Sopenharmony_ci	case 2: b |= le16_to_cpup(data); break;
728c2ecf20Sopenharmony_ci	case 1: b |= end[0];
738c2ecf20Sopenharmony_ci	}
748c2ecf20Sopenharmony_ci#endif
758c2ecf20Sopenharmony_ci	POSTAMBLE
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__siphash_aligned);
788c2ecf20Sopenharmony_ci#endif
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ciu64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key)
818c2ecf20Sopenharmony_ci{
828c2ecf20Sopenharmony_ci	const u8 *end = data + len - (len % sizeof(u64));
838c2ecf20Sopenharmony_ci	const u8 left = len & (sizeof(u64) - 1);
848c2ecf20Sopenharmony_ci	u64 m;
858c2ecf20Sopenharmony_ci	PREAMBLE(len)
868c2ecf20Sopenharmony_ci	for (; data != end; data += sizeof(u64)) {
878c2ecf20Sopenharmony_ci		m = get_unaligned_le64(data);
888c2ecf20Sopenharmony_ci		v3 ^= m;
898c2ecf20Sopenharmony_ci		SIPROUND;
908c2ecf20Sopenharmony_ci		SIPROUND;
918c2ecf20Sopenharmony_ci		v0 ^= m;
928c2ecf20Sopenharmony_ci	}
938c2ecf20Sopenharmony_ci#if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
948c2ecf20Sopenharmony_ci	if (left)
958c2ecf20Sopenharmony_ci		b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) &
968c2ecf20Sopenharmony_ci						  bytemask_from_count(left)));
978c2ecf20Sopenharmony_ci#else
988c2ecf20Sopenharmony_ci	switch (left) {
998c2ecf20Sopenharmony_ci	case 7: b |= ((u64)end[6]) << 48; /* fall through */
1008c2ecf20Sopenharmony_ci	case 6: b |= ((u64)end[5]) << 40; /* fall through */
1018c2ecf20Sopenharmony_ci	case 5: b |= ((u64)end[4]) << 32; /* fall through */
1028c2ecf20Sopenharmony_ci	case 4: b |= get_unaligned_le32(end); break;
1038c2ecf20Sopenharmony_ci	case 3: b |= ((u64)end[2]) << 16; /* fall through */
1048c2ecf20Sopenharmony_ci	case 2: b |= get_unaligned_le16(end); break;
1058c2ecf20Sopenharmony_ci	case 1: b |= end[0];
1068c2ecf20Sopenharmony_ci	}
1078c2ecf20Sopenharmony_ci#endif
1088c2ecf20Sopenharmony_ci	POSTAMBLE
1098c2ecf20Sopenharmony_ci}
1108c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__siphash_unaligned);
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci/**
1138c2ecf20Sopenharmony_ci * siphash_1u64 - compute 64-bit siphash PRF value of a u64
1148c2ecf20Sopenharmony_ci * @first: first u64
1158c2ecf20Sopenharmony_ci * @key: the siphash key
1168c2ecf20Sopenharmony_ci */
1178c2ecf20Sopenharmony_ciu64 siphash_1u64(const u64 first, const siphash_key_t *key)
1188c2ecf20Sopenharmony_ci{
1198c2ecf20Sopenharmony_ci	PREAMBLE(8)
1208c2ecf20Sopenharmony_ci	v3 ^= first;
1218c2ecf20Sopenharmony_ci	SIPROUND;
1228c2ecf20Sopenharmony_ci	SIPROUND;
1238c2ecf20Sopenharmony_ci	v0 ^= first;
1248c2ecf20Sopenharmony_ci	POSTAMBLE
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ciEXPORT_SYMBOL(siphash_1u64);
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci/**
1298c2ecf20Sopenharmony_ci * siphash_2u64 - compute 64-bit siphash PRF value of 2 u64
1308c2ecf20Sopenharmony_ci * @first: first u64
1318c2ecf20Sopenharmony_ci * @second: second u64
1328c2ecf20Sopenharmony_ci * @key: the siphash key
1338c2ecf20Sopenharmony_ci */
1348c2ecf20Sopenharmony_ciu64 siphash_2u64(const u64 first, const u64 second, const siphash_key_t *key)
1358c2ecf20Sopenharmony_ci{
1368c2ecf20Sopenharmony_ci	PREAMBLE(16)
1378c2ecf20Sopenharmony_ci	v3 ^= first;
1388c2ecf20Sopenharmony_ci	SIPROUND;
1398c2ecf20Sopenharmony_ci	SIPROUND;
1408c2ecf20Sopenharmony_ci	v0 ^= first;
1418c2ecf20Sopenharmony_ci	v3 ^= second;
1428c2ecf20Sopenharmony_ci	SIPROUND;
1438c2ecf20Sopenharmony_ci	SIPROUND;
1448c2ecf20Sopenharmony_ci	v0 ^= second;
1458c2ecf20Sopenharmony_ci	POSTAMBLE
1468c2ecf20Sopenharmony_ci}
1478c2ecf20Sopenharmony_ciEXPORT_SYMBOL(siphash_2u64);
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci/**
1508c2ecf20Sopenharmony_ci * siphash_3u64 - compute 64-bit siphash PRF value of 3 u64
1518c2ecf20Sopenharmony_ci * @first: first u64
1528c2ecf20Sopenharmony_ci * @second: second u64
1538c2ecf20Sopenharmony_ci * @third: third u64
1548c2ecf20Sopenharmony_ci * @key: the siphash key
1558c2ecf20Sopenharmony_ci */
1568c2ecf20Sopenharmony_ciu64 siphash_3u64(const u64 first, const u64 second, const u64 third,
1578c2ecf20Sopenharmony_ci		 const siphash_key_t *key)
1588c2ecf20Sopenharmony_ci{
1598c2ecf20Sopenharmony_ci	PREAMBLE(24)
1608c2ecf20Sopenharmony_ci	v3 ^= first;
1618c2ecf20Sopenharmony_ci	SIPROUND;
1628c2ecf20Sopenharmony_ci	SIPROUND;
1638c2ecf20Sopenharmony_ci	v0 ^= first;
1648c2ecf20Sopenharmony_ci	v3 ^= second;
1658c2ecf20Sopenharmony_ci	SIPROUND;
1668c2ecf20Sopenharmony_ci	SIPROUND;
1678c2ecf20Sopenharmony_ci	v0 ^= second;
1688c2ecf20Sopenharmony_ci	v3 ^= third;
1698c2ecf20Sopenharmony_ci	SIPROUND;
1708c2ecf20Sopenharmony_ci	SIPROUND;
1718c2ecf20Sopenharmony_ci	v0 ^= third;
1728c2ecf20Sopenharmony_ci	POSTAMBLE
1738c2ecf20Sopenharmony_ci}
1748c2ecf20Sopenharmony_ciEXPORT_SYMBOL(siphash_3u64);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci/**
1778c2ecf20Sopenharmony_ci * siphash_4u64 - compute 64-bit siphash PRF value of 4 u64
1788c2ecf20Sopenharmony_ci * @first: first u64
1798c2ecf20Sopenharmony_ci * @second: second u64
1808c2ecf20Sopenharmony_ci * @third: third u64
1818c2ecf20Sopenharmony_ci * @forth: forth u64
1828c2ecf20Sopenharmony_ci * @key: the siphash key
1838c2ecf20Sopenharmony_ci */
1848c2ecf20Sopenharmony_ciu64 siphash_4u64(const u64 first, const u64 second, const u64 third,
1858c2ecf20Sopenharmony_ci		 const u64 forth, const siphash_key_t *key)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	PREAMBLE(32)
1888c2ecf20Sopenharmony_ci	v3 ^= first;
1898c2ecf20Sopenharmony_ci	SIPROUND;
1908c2ecf20Sopenharmony_ci	SIPROUND;
1918c2ecf20Sopenharmony_ci	v0 ^= first;
1928c2ecf20Sopenharmony_ci	v3 ^= second;
1938c2ecf20Sopenharmony_ci	SIPROUND;
1948c2ecf20Sopenharmony_ci	SIPROUND;
1958c2ecf20Sopenharmony_ci	v0 ^= second;
1968c2ecf20Sopenharmony_ci	v3 ^= third;
1978c2ecf20Sopenharmony_ci	SIPROUND;
1988c2ecf20Sopenharmony_ci	SIPROUND;
1998c2ecf20Sopenharmony_ci	v0 ^= third;
2008c2ecf20Sopenharmony_ci	v3 ^= forth;
2018c2ecf20Sopenharmony_ci	SIPROUND;
2028c2ecf20Sopenharmony_ci	SIPROUND;
2038c2ecf20Sopenharmony_ci	v0 ^= forth;
2048c2ecf20Sopenharmony_ci	POSTAMBLE
2058c2ecf20Sopenharmony_ci}
2068c2ecf20Sopenharmony_ciEXPORT_SYMBOL(siphash_4u64);
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ciu64 siphash_1u32(const u32 first, const siphash_key_t *key)
2098c2ecf20Sopenharmony_ci{
2108c2ecf20Sopenharmony_ci	PREAMBLE(4)
2118c2ecf20Sopenharmony_ci	b |= first;
2128c2ecf20Sopenharmony_ci	POSTAMBLE
2138c2ecf20Sopenharmony_ci}
2148c2ecf20Sopenharmony_ciEXPORT_SYMBOL(siphash_1u32);
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ciu64 siphash_3u32(const u32 first, const u32 second, const u32 third,
2178c2ecf20Sopenharmony_ci		 const siphash_key_t *key)
2188c2ecf20Sopenharmony_ci{
2198c2ecf20Sopenharmony_ci	u64 combined = (u64)second << 32 | first;
2208c2ecf20Sopenharmony_ci	PREAMBLE(12)
2218c2ecf20Sopenharmony_ci	v3 ^= combined;
2228c2ecf20Sopenharmony_ci	SIPROUND;
2238c2ecf20Sopenharmony_ci	SIPROUND;
2248c2ecf20Sopenharmony_ci	v0 ^= combined;
2258c2ecf20Sopenharmony_ci	b |= third;
2268c2ecf20Sopenharmony_ci	POSTAMBLE
2278c2ecf20Sopenharmony_ci}
2288c2ecf20Sopenharmony_ciEXPORT_SYMBOL(siphash_3u32);
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci#if BITS_PER_LONG == 64
2318c2ecf20Sopenharmony_ci/* Note that on 64-bit, we make HalfSipHash1-3 actually be SipHash1-3, for
2328c2ecf20Sopenharmony_ci * performance reasons. On 32-bit, below, we actually implement HalfSipHash1-3.
2338c2ecf20Sopenharmony_ci */
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci#define HSIPROUND SIPROUND
2368c2ecf20Sopenharmony_ci#define HPREAMBLE(len) PREAMBLE(len)
2378c2ecf20Sopenharmony_ci#define HPOSTAMBLE \
2388c2ecf20Sopenharmony_ci	v3 ^= b; \
2398c2ecf20Sopenharmony_ci	HSIPROUND; \
2408c2ecf20Sopenharmony_ci	v0 ^= b; \
2418c2ecf20Sopenharmony_ci	v2 ^= 0xff; \
2428c2ecf20Sopenharmony_ci	HSIPROUND; \
2438c2ecf20Sopenharmony_ci	HSIPROUND; \
2448c2ecf20Sopenharmony_ci	HSIPROUND; \
2458c2ecf20Sopenharmony_ci	return (v0 ^ v1) ^ (v2 ^ v3);
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
2488c2ecf20Sopenharmony_ciu32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key)
2498c2ecf20Sopenharmony_ci{
2508c2ecf20Sopenharmony_ci	const u8 *end = data + len - (len % sizeof(u64));
2518c2ecf20Sopenharmony_ci	const u8 left = len & (sizeof(u64) - 1);
2528c2ecf20Sopenharmony_ci	u64 m;
2538c2ecf20Sopenharmony_ci	HPREAMBLE(len)
2548c2ecf20Sopenharmony_ci	for (; data != end; data += sizeof(u64)) {
2558c2ecf20Sopenharmony_ci		m = le64_to_cpup(data);
2568c2ecf20Sopenharmony_ci		v3 ^= m;
2578c2ecf20Sopenharmony_ci		HSIPROUND;
2588c2ecf20Sopenharmony_ci		v0 ^= m;
2598c2ecf20Sopenharmony_ci	}
2608c2ecf20Sopenharmony_ci#if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
2618c2ecf20Sopenharmony_ci	if (left)
2628c2ecf20Sopenharmony_ci		b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) &
2638c2ecf20Sopenharmony_ci						  bytemask_from_count(left)));
2648c2ecf20Sopenharmony_ci#else
2658c2ecf20Sopenharmony_ci	switch (left) {
2668c2ecf20Sopenharmony_ci	case 7: b |= ((u64)end[6]) << 48; /* fall through */
2678c2ecf20Sopenharmony_ci	case 6: b |= ((u64)end[5]) << 40; /* fall through */
2688c2ecf20Sopenharmony_ci	case 5: b |= ((u64)end[4]) << 32; /* fall through */
2698c2ecf20Sopenharmony_ci	case 4: b |= le32_to_cpup(data); break;
2708c2ecf20Sopenharmony_ci	case 3: b |= ((u64)end[2]) << 16; /* fall through */
2718c2ecf20Sopenharmony_ci	case 2: b |= le16_to_cpup(data); break;
2728c2ecf20Sopenharmony_ci	case 1: b |= end[0];
2738c2ecf20Sopenharmony_ci	}
2748c2ecf20Sopenharmony_ci#endif
2758c2ecf20Sopenharmony_ci	HPOSTAMBLE
2768c2ecf20Sopenharmony_ci}
2778c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__hsiphash_aligned);
2788c2ecf20Sopenharmony_ci#endif
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ciu32 __hsiphash_unaligned(const void *data, size_t len,
2818c2ecf20Sopenharmony_ci			 const hsiphash_key_t *key)
2828c2ecf20Sopenharmony_ci{
2838c2ecf20Sopenharmony_ci	const u8 *end = data + len - (len % sizeof(u64));
2848c2ecf20Sopenharmony_ci	const u8 left = len & (sizeof(u64) - 1);
2858c2ecf20Sopenharmony_ci	u64 m;
2868c2ecf20Sopenharmony_ci	HPREAMBLE(len)
2878c2ecf20Sopenharmony_ci	for (; data != end; data += sizeof(u64)) {
2888c2ecf20Sopenharmony_ci		m = get_unaligned_le64(data);
2898c2ecf20Sopenharmony_ci		v3 ^= m;
2908c2ecf20Sopenharmony_ci		HSIPROUND;
2918c2ecf20Sopenharmony_ci		v0 ^= m;
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci#if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
2948c2ecf20Sopenharmony_ci	if (left)
2958c2ecf20Sopenharmony_ci		b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) &
2968c2ecf20Sopenharmony_ci						  bytemask_from_count(left)));
2978c2ecf20Sopenharmony_ci#else
2988c2ecf20Sopenharmony_ci	switch (left) {
2998c2ecf20Sopenharmony_ci	case 7: b |= ((u64)end[6]) << 48; /* fall through */
3008c2ecf20Sopenharmony_ci	case 6: b |= ((u64)end[5]) << 40; /* fall through */
3018c2ecf20Sopenharmony_ci	case 5: b |= ((u64)end[4]) << 32; /* fall through */
3028c2ecf20Sopenharmony_ci	case 4: b |= get_unaligned_le32(end); break;
3038c2ecf20Sopenharmony_ci	case 3: b |= ((u64)end[2]) << 16; /* fall through */
3048c2ecf20Sopenharmony_ci	case 2: b |= get_unaligned_le16(end); break;
3058c2ecf20Sopenharmony_ci	case 1: b |= end[0];
3068c2ecf20Sopenharmony_ci	}
3078c2ecf20Sopenharmony_ci#endif
3088c2ecf20Sopenharmony_ci	HPOSTAMBLE
3098c2ecf20Sopenharmony_ci}
3108c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__hsiphash_unaligned);
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci/**
3138c2ecf20Sopenharmony_ci * hsiphash_1u32 - compute 64-bit hsiphash PRF value of a u32
3148c2ecf20Sopenharmony_ci * @first: first u32
3158c2ecf20Sopenharmony_ci * @key: the hsiphash key
3168c2ecf20Sopenharmony_ci */
3178c2ecf20Sopenharmony_ciu32 hsiphash_1u32(const u32 first, const hsiphash_key_t *key)
3188c2ecf20Sopenharmony_ci{
3198c2ecf20Sopenharmony_ci	HPREAMBLE(4)
3208c2ecf20Sopenharmony_ci	b |= first;
3218c2ecf20Sopenharmony_ci	HPOSTAMBLE
3228c2ecf20Sopenharmony_ci}
3238c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hsiphash_1u32);
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci/**
3268c2ecf20Sopenharmony_ci * hsiphash_2u32 - compute 32-bit hsiphash PRF value of 2 u32
3278c2ecf20Sopenharmony_ci * @first: first u32
3288c2ecf20Sopenharmony_ci * @second: second u32
3298c2ecf20Sopenharmony_ci * @key: the hsiphash key
3308c2ecf20Sopenharmony_ci */
3318c2ecf20Sopenharmony_ciu32 hsiphash_2u32(const u32 first, const u32 second, const hsiphash_key_t *key)
3328c2ecf20Sopenharmony_ci{
3338c2ecf20Sopenharmony_ci	u64 combined = (u64)second << 32 | first;
3348c2ecf20Sopenharmony_ci	HPREAMBLE(8)
3358c2ecf20Sopenharmony_ci	v3 ^= combined;
3368c2ecf20Sopenharmony_ci	HSIPROUND;
3378c2ecf20Sopenharmony_ci	v0 ^= combined;
3388c2ecf20Sopenharmony_ci	HPOSTAMBLE
3398c2ecf20Sopenharmony_ci}
3408c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hsiphash_2u32);
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci/**
3438c2ecf20Sopenharmony_ci * hsiphash_3u32 - compute 32-bit hsiphash PRF value of 3 u32
3448c2ecf20Sopenharmony_ci * @first: first u32
3458c2ecf20Sopenharmony_ci * @second: second u32
3468c2ecf20Sopenharmony_ci * @third: third u32
3478c2ecf20Sopenharmony_ci * @key: the hsiphash key
3488c2ecf20Sopenharmony_ci */
3498c2ecf20Sopenharmony_ciu32 hsiphash_3u32(const u32 first, const u32 second, const u32 third,
3508c2ecf20Sopenharmony_ci		  const hsiphash_key_t *key)
3518c2ecf20Sopenharmony_ci{
3528c2ecf20Sopenharmony_ci	u64 combined = (u64)second << 32 | first;
3538c2ecf20Sopenharmony_ci	HPREAMBLE(12)
3548c2ecf20Sopenharmony_ci	v3 ^= combined;
3558c2ecf20Sopenharmony_ci	HSIPROUND;
3568c2ecf20Sopenharmony_ci	v0 ^= combined;
3578c2ecf20Sopenharmony_ci	b |= third;
3588c2ecf20Sopenharmony_ci	HPOSTAMBLE
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hsiphash_3u32);
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci/**
3638c2ecf20Sopenharmony_ci * hsiphash_4u32 - compute 32-bit hsiphash PRF value of 4 u32
3648c2ecf20Sopenharmony_ci * @first: first u32
3658c2ecf20Sopenharmony_ci * @second: second u32
3668c2ecf20Sopenharmony_ci * @third: third u32
3678c2ecf20Sopenharmony_ci * @forth: forth u32
3688c2ecf20Sopenharmony_ci * @key: the hsiphash key
3698c2ecf20Sopenharmony_ci */
3708c2ecf20Sopenharmony_ciu32 hsiphash_4u32(const u32 first, const u32 second, const u32 third,
3718c2ecf20Sopenharmony_ci		  const u32 forth, const hsiphash_key_t *key)
3728c2ecf20Sopenharmony_ci{
3738c2ecf20Sopenharmony_ci	u64 combined = (u64)second << 32 | first;
3748c2ecf20Sopenharmony_ci	HPREAMBLE(16)
3758c2ecf20Sopenharmony_ci	v3 ^= combined;
3768c2ecf20Sopenharmony_ci	HSIPROUND;
3778c2ecf20Sopenharmony_ci	v0 ^= combined;
3788c2ecf20Sopenharmony_ci	combined = (u64)forth << 32 | third;
3798c2ecf20Sopenharmony_ci	v3 ^= combined;
3808c2ecf20Sopenharmony_ci	HSIPROUND;
3818c2ecf20Sopenharmony_ci	v0 ^= combined;
3828c2ecf20Sopenharmony_ci	HPOSTAMBLE
3838c2ecf20Sopenharmony_ci}
3848c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hsiphash_4u32);
3858c2ecf20Sopenharmony_ci#else
3868c2ecf20Sopenharmony_ci#define HSIPROUND HSIPHASH_PERMUTATION(v0, v1, v2, v3)
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci#define HPREAMBLE(len) \
3898c2ecf20Sopenharmony_ci	u32 v0 = HSIPHASH_CONST_0; \
3908c2ecf20Sopenharmony_ci	u32 v1 = HSIPHASH_CONST_1; \
3918c2ecf20Sopenharmony_ci	u32 v2 = HSIPHASH_CONST_2; \
3928c2ecf20Sopenharmony_ci	u32 v3 = HSIPHASH_CONST_3; \
3938c2ecf20Sopenharmony_ci	u32 b = ((u32)(len)) << 24; \
3948c2ecf20Sopenharmony_ci	v3 ^= key->key[1]; \
3958c2ecf20Sopenharmony_ci	v2 ^= key->key[0]; \
3968c2ecf20Sopenharmony_ci	v1 ^= key->key[1]; \
3978c2ecf20Sopenharmony_ci	v0 ^= key->key[0];
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci#define HPOSTAMBLE \
4008c2ecf20Sopenharmony_ci	v3 ^= b; \
4018c2ecf20Sopenharmony_ci	HSIPROUND; \
4028c2ecf20Sopenharmony_ci	v0 ^= b; \
4038c2ecf20Sopenharmony_ci	v2 ^= 0xff; \
4048c2ecf20Sopenharmony_ci	HSIPROUND; \
4058c2ecf20Sopenharmony_ci	HSIPROUND; \
4068c2ecf20Sopenharmony_ci	HSIPROUND; \
4078c2ecf20Sopenharmony_ci	return v1 ^ v3;
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
4108c2ecf20Sopenharmony_ciu32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key)
4118c2ecf20Sopenharmony_ci{
4128c2ecf20Sopenharmony_ci	const u8 *end = data + len - (len % sizeof(u32));
4138c2ecf20Sopenharmony_ci	const u8 left = len & (sizeof(u32) - 1);
4148c2ecf20Sopenharmony_ci	u32 m;
4158c2ecf20Sopenharmony_ci	HPREAMBLE(len)
4168c2ecf20Sopenharmony_ci	for (; data != end; data += sizeof(u32)) {
4178c2ecf20Sopenharmony_ci		m = le32_to_cpup(data);
4188c2ecf20Sopenharmony_ci		v3 ^= m;
4198c2ecf20Sopenharmony_ci		HSIPROUND;
4208c2ecf20Sopenharmony_ci		v0 ^= m;
4218c2ecf20Sopenharmony_ci	}
4228c2ecf20Sopenharmony_ci	switch (left) {
4238c2ecf20Sopenharmony_ci	case 3: b |= ((u32)end[2]) << 16; /* fall through */
4248c2ecf20Sopenharmony_ci	case 2: b |= le16_to_cpup(data); break;
4258c2ecf20Sopenharmony_ci	case 1: b |= end[0];
4268c2ecf20Sopenharmony_ci	}
4278c2ecf20Sopenharmony_ci	HPOSTAMBLE
4288c2ecf20Sopenharmony_ci}
4298c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__hsiphash_aligned);
4308c2ecf20Sopenharmony_ci#endif
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ciu32 __hsiphash_unaligned(const void *data, size_t len,
4338c2ecf20Sopenharmony_ci			 const hsiphash_key_t *key)
4348c2ecf20Sopenharmony_ci{
4358c2ecf20Sopenharmony_ci	const u8 *end = data + len - (len % sizeof(u32));
4368c2ecf20Sopenharmony_ci	const u8 left = len & (sizeof(u32) - 1);
4378c2ecf20Sopenharmony_ci	u32 m;
4388c2ecf20Sopenharmony_ci	HPREAMBLE(len)
4398c2ecf20Sopenharmony_ci	for (; data != end; data += sizeof(u32)) {
4408c2ecf20Sopenharmony_ci		m = get_unaligned_le32(data);
4418c2ecf20Sopenharmony_ci		v3 ^= m;
4428c2ecf20Sopenharmony_ci		HSIPROUND;
4438c2ecf20Sopenharmony_ci		v0 ^= m;
4448c2ecf20Sopenharmony_ci	}
4458c2ecf20Sopenharmony_ci	switch (left) {
4468c2ecf20Sopenharmony_ci	case 3: b |= ((u32)end[2]) << 16; /* fall through */
4478c2ecf20Sopenharmony_ci	case 2: b |= get_unaligned_le16(end); break;
4488c2ecf20Sopenharmony_ci	case 1: b |= end[0];
4498c2ecf20Sopenharmony_ci	}
4508c2ecf20Sopenharmony_ci	HPOSTAMBLE
4518c2ecf20Sopenharmony_ci}
4528c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__hsiphash_unaligned);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci/**
4558c2ecf20Sopenharmony_ci * hsiphash_1u32 - compute 32-bit hsiphash PRF value of a u32
4568c2ecf20Sopenharmony_ci * @first: first u32
4578c2ecf20Sopenharmony_ci * @key: the hsiphash key
4588c2ecf20Sopenharmony_ci */
4598c2ecf20Sopenharmony_ciu32 hsiphash_1u32(const u32 first, const hsiphash_key_t *key)
4608c2ecf20Sopenharmony_ci{
4618c2ecf20Sopenharmony_ci	HPREAMBLE(4)
4628c2ecf20Sopenharmony_ci	v3 ^= first;
4638c2ecf20Sopenharmony_ci	HSIPROUND;
4648c2ecf20Sopenharmony_ci	v0 ^= first;
4658c2ecf20Sopenharmony_ci	HPOSTAMBLE
4668c2ecf20Sopenharmony_ci}
4678c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hsiphash_1u32);
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci/**
4708c2ecf20Sopenharmony_ci * hsiphash_2u32 - compute 32-bit hsiphash PRF value of 2 u32
4718c2ecf20Sopenharmony_ci * @first: first u32
4728c2ecf20Sopenharmony_ci * @second: second u32
4738c2ecf20Sopenharmony_ci * @key: the hsiphash key
4748c2ecf20Sopenharmony_ci */
4758c2ecf20Sopenharmony_ciu32 hsiphash_2u32(const u32 first, const u32 second, const hsiphash_key_t *key)
4768c2ecf20Sopenharmony_ci{
4778c2ecf20Sopenharmony_ci	HPREAMBLE(8)
4788c2ecf20Sopenharmony_ci	v3 ^= first;
4798c2ecf20Sopenharmony_ci	HSIPROUND;
4808c2ecf20Sopenharmony_ci	v0 ^= first;
4818c2ecf20Sopenharmony_ci	v3 ^= second;
4828c2ecf20Sopenharmony_ci	HSIPROUND;
4838c2ecf20Sopenharmony_ci	v0 ^= second;
4848c2ecf20Sopenharmony_ci	HPOSTAMBLE
4858c2ecf20Sopenharmony_ci}
4868c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hsiphash_2u32);
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci/**
4898c2ecf20Sopenharmony_ci * hsiphash_3u32 - compute 32-bit hsiphash PRF value of 3 u32
4908c2ecf20Sopenharmony_ci * @first: first u32
4918c2ecf20Sopenharmony_ci * @second: second u32
4928c2ecf20Sopenharmony_ci * @third: third u32
4938c2ecf20Sopenharmony_ci * @key: the hsiphash key
4948c2ecf20Sopenharmony_ci */
4958c2ecf20Sopenharmony_ciu32 hsiphash_3u32(const u32 first, const u32 second, const u32 third,
4968c2ecf20Sopenharmony_ci		  const hsiphash_key_t *key)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	HPREAMBLE(12)
4998c2ecf20Sopenharmony_ci	v3 ^= first;
5008c2ecf20Sopenharmony_ci	HSIPROUND;
5018c2ecf20Sopenharmony_ci	v0 ^= first;
5028c2ecf20Sopenharmony_ci	v3 ^= second;
5038c2ecf20Sopenharmony_ci	HSIPROUND;
5048c2ecf20Sopenharmony_ci	v0 ^= second;
5058c2ecf20Sopenharmony_ci	v3 ^= third;
5068c2ecf20Sopenharmony_ci	HSIPROUND;
5078c2ecf20Sopenharmony_ci	v0 ^= third;
5088c2ecf20Sopenharmony_ci	HPOSTAMBLE
5098c2ecf20Sopenharmony_ci}
5108c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hsiphash_3u32);
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci/**
5138c2ecf20Sopenharmony_ci * hsiphash_4u32 - compute 32-bit hsiphash PRF value of 4 u32
5148c2ecf20Sopenharmony_ci * @first: first u32
5158c2ecf20Sopenharmony_ci * @second: second u32
5168c2ecf20Sopenharmony_ci * @third: third u32
5178c2ecf20Sopenharmony_ci * @forth: forth u32
5188c2ecf20Sopenharmony_ci * @key: the hsiphash key
5198c2ecf20Sopenharmony_ci */
5208c2ecf20Sopenharmony_ciu32 hsiphash_4u32(const u32 first, const u32 second, const u32 third,
5218c2ecf20Sopenharmony_ci		  const u32 forth, const hsiphash_key_t *key)
5228c2ecf20Sopenharmony_ci{
5238c2ecf20Sopenharmony_ci	HPREAMBLE(16)
5248c2ecf20Sopenharmony_ci	v3 ^= first;
5258c2ecf20Sopenharmony_ci	HSIPROUND;
5268c2ecf20Sopenharmony_ci	v0 ^= first;
5278c2ecf20Sopenharmony_ci	v3 ^= second;
5288c2ecf20Sopenharmony_ci	HSIPROUND;
5298c2ecf20Sopenharmony_ci	v0 ^= second;
5308c2ecf20Sopenharmony_ci	v3 ^= third;
5318c2ecf20Sopenharmony_ci	HSIPROUND;
5328c2ecf20Sopenharmony_ci	v0 ^= third;
5338c2ecf20Sopenharmony_ci	v3 ^= forth;
5348c2ecf20Sopenharmony_ci	HSIPROUND;
5358c2ecf20Sopenharmony_ci	v0 ^= forth;
5368c2ecf20Sopenharmony_ci	HPOSTAMBLE
5378c2ecf20Sopenharmony_ci}
5388c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hsiphash_4u32);
5398c2ecf20Sopenharmony_ci#endif
540