These restore parity with the jhash interface by providing high
performance helpers for common input sizes.
Signed-off-by: Jason A. Donenfeld
Cc: Tom Herbert
---
include/linux/siphash.h | 33 ++
lib/siphash.c | 157 +---
lib/test_siphash.c | 18 ++
3 files changed, 172 insertions(+), 36 deletions(-)
diff --git a/include/linux/siphash.h b/include/linux/siphash.h
index 145cf5667078..6f5a08a0fc7e 100644
--- a/include/linux/siphash.h
+++ b/include/linux/siphash.h
@@ -29,4 +29,37 @@ static inline u64 siphash_unaligned(const void *data, size_t
len,
u64 siphash_unaligned(const void *data, size_t len, const siphash_key_t key);
#endif
+u64 siphash_1u64(const u64 a, const siphash_key_t key);
+u64 siphash_2u64(const u64 a, const u64 b, const siphash_key_t key);
+u64 siphash_3u64(const u64 a, const u64 b, const u64 c,
+const siphash_key_t key);
+u64 siphash_4u64(const u64 a, const u64 b, const u64 c, const u64 d,
+const siphash_key_t key);
+
+static inline u64 siphash_2u32(const u32 a, const u32 b, const siphash_key_t
key)
+{
+ return siphash_1u64((u64)b << 32 | a, key);
+}
+
+static inline u64 siphash_4u32(const u32 a, const u32 b, const u32 c, const
u32 d,
+ const siphash_key_t key)
+{
+ return siphash_2u64((u64)b << 32 | a, (u64)d << 32 | c, key);
+}
+
+static inline u64 siphash_6u32(const u32 a, const u32 b, const u32 c, const
u32 d,
+ const u32 e, const u32 f, const siphash_key_t
key)
+{
+ return siphash_3u64((u64)b << 32 | a, (u64)d << 32 | c, (u64)f << 32 |
e,
+ key);
+}
+
+static inline u64 siphash_8u32(const u32 a, const u32 b, const u32 c, const
u32 d,
+ const u32 e, const u32 f, const u32 g, const u32
h,
+ const siphash_key_t key)
+{
+ return siphash_4u64((u64)b << 32 | a, (u64)d << 32 | c, (u64)f << 32 |
e,
+ (u64)h << 32 | g, key);
+}
+
#endif /* _LINUX_SIPHASH_H */
diff --git a/lib/siphash.c b/lib/siphash.c
index afc13cbb1b78..970c083ab06a 100644
--- a/lib/siphash.c
+++ b/lib/siphash.c
@@ -25,6 +25,29 @@
v2 += v1; v1 = rol64(v1, 17); v1 ^= v2; v2 = rol64(v2, 32); \
} while(0)
+#define PREAMBLE(len) \
+ u64 v0 = 0x736f6d6570736575ULL; \
+ u64 v1 = 0x646f72616e646f6dULL; \
+ u64 v2 = 0x6c7967656e657261ULL; \
+ u64 v3 = 0x7465646279746573ULL; \
+ u64 b = ((u64)len) << 56; \
+ v3 ^= key[1]; \
+ v2 ^= key[0]; \
+ v1 ^= key[1]; \
+ v0 ^= key[0];
+
+#define POSTAMBLE \
+ v3 ^= b; \
+ SIPROUND; \
+ SIPROUND; \
+ v0 ^= b; \
+ v2 ^= 0xff; \
+ SIPROUND; \
+ SIPROUND; \
+ SIPROUND; \
+ SIPROUND; \
+ return (v0 ^ v1) ^ (v2 ^ v3);
+
/**
* siphash - compute 64-bit siphash PRF value
* @data: buffer to hash, must be aligned to SIPHASH_ALIGNMENT
@@ -33,18 +56,10 @@
*/
u64 siphash(const void *data, size_t len, const siphash_key_t key)
{
- u64 v0 = 0x736f6d6570736575ULL;
- u64 v1 = 0x646f72616e646f6dULL;
- u64 v2 = 0x6c7967656e657261ULL;
- u64 v3 = 0x7465646279746573ULL;
- u64 b = ((u64)len) << 56;
- u64 m;
const u8 *end = data + len - (len % sizeof(u64));
const u8 left = len & (sizeof(u64) - 1);
- v3 ^= key[1];
- v2 ^= key[0];
- v1 ^= key[1];
- v0 ^= key[0];
+ u64 m;
+ PREAMBLE(len)
for (; data != end; data += sizeof(u64)) {
m = le64_to_cpup(data);
v3 ^= m;
@@ -67,16 +82,7 @@ u64 siphash(const void *data, size_t len, const
siphash_key_t key)
case 1: b |= end[0];
}
#endif
- v3 ^= b;
- SIPROUND;
- SIPROUND;
- v0 ^= b;
- v2 ^= 0xff;
- SIPROUND;
- SIPROUND;
- SIPROUND;
- SIPROUND;
- return (v0 ^ v1) ^ (v2 ^ v3);
+ POSTAMBLE
}
EXPORT_SYMBOL(siphash);
@@ -89,18 +95,10 @@ EXPORT_SYMBOL(siphash);
*/
u64 siphash_unaligned(const void *data, size_t len, const siphash_key_t key)
{
- u64 v0 = 0x736f6d6570736575ULL;
- u64 v1 = 0x646f72616e646f6dULL;
- u64 v2 = 0x6c7967656e657261ULL;
- u64 v3 = 0x7465646279746573ULL;
- u64 b = ((u64)len) << 56;
- u64 m;
const u8 *end = data + len - (len % sizeof(u64));
const u8 left = len & (sizeof(u64) - 1);
- v3 ^= key[1];
- v2 ^= key[0];
- v1 ^= key[1];
- v0 ^= key[0];
+ u64 m;
+ PREAMBLE(len)
for (; data != end; data += sizeof(u64)) {
m = get_unaligned_le64(data);
v3 ^= m;
@@ -123,16 +121,103 @@ u64 siphash_unaligned(const void *data, size_t len,
const siphash_key_t key)
case 1: b |= bytes[0];
}
#endif
- v3 ^= b;
+ POSTAMBLE
+}
+EXPORT_SYMBOL(siphash_unaligned);
+#endif
+
+/**
+ *