From 986a8046a2b297279569ebd160a5410f8f195185 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 13 Dec 2016 03:20:53 +0100 Subject: siphash: update against upstream submission --- src/crypto/siphash.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++++ src/crypto/siphash.h | 88 +++++++++++++++++++++ src/crypto/siphash24.c | 66 ---------------- src/crypto/siphash24.h | 18 ----- 4 files changed, 292 insertions(+), 84 deletions(-) create mode 100644 src/crypto/siphash.c create mode 100644 src/crypto/siphash.h delete mode 100644 src/crypto/siphash24.c delete mode 100644 src/crypto/siphash24.h (limited to 'src/crypto') diff --git a/src/crypto/siphash.c b/src/crypto/siphash.c new file mode 100644 index 0000000..2bf77c1 --- /dev/null +++ b/src/crypto/siphash.c @@ -0,0 +1,204 @@ +/* Copyright (C) 2015-2016 Jason A. Donenfeld . All Rights Reserved. + * + * SipHash: a fast short-input PRF + * https://131002.net/siphash/ + * + * This implementation is specifically for SipHash2-4. + */ + +#include "siphash.h" +#include + +#if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64 +#include +#include +#endif + +#define SIPROUND \ + do { \ + v0 += v1; v1 = rol64(v1, 13); v1 ^= v0; v0 = rol64(v0, 32); \ + v2 += v3; v3 = rol64(v3, 16); v3 ^= v2; \ + v0 += v3; v3 = rol64(v3, 21); v3 ^= v0; \ + 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); + +u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t key) +{ + const u8 *end = data + len - (len % sizeof(u64)); + const u8 left = len & (sizeof(u64) - 1); + u64 m; + PREAMBLE(len) + for (; data != end; data += sizeof(u64)) { + m = le64_to_cpup(data); + v3 ^= m; + SIPROUND; + SIPROUND; + v0 ^= m; + } +#if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64 + if (left) + b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) & + bytemask_from_count(left))); +#else + switch (left) { + case 7: b |= ((u64)end[6]) << 48; + case 6: b |= ((u64)end[5]) << 40; + case 5: b |= ((u64)end[4]) << 32; + case 4: b |= le32_to_cpup(data); break; + case 3: b |= ((u64)end[2]) << 16; + case 2: b |= le16_to_cpup(data); break; + case 1: b |= end[0]; + } +#endif + POSTAMBLE +} + +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS +u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t key) +{ + const u8 *end = data + len - (len % sizeof(u64)); + const u8 left = len & (sizeof(u64) - 1); + u64 m; + PREAMBLE(len) + for (; data != end; data += sizeof(u64)) { + m = get_unaligned_le64(data); + v3 ^= m; + SIPROUND; + SIPROUND; + v0 ^= m; + } +#if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64 + if (left) + b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) & + bytemask_from_count(left))); +#else + switch (left) { + case 7: b |= ((u64)end[6]) << 48; + case 6: b |= ((u64)end[5]) << 40; + case 5: b |= ((u64)end[4]) << 32; + case 4: b |= get_unaligned_le32(end); break; + case 3: b |= ((u64)end[2]) << 16; + case 2: b |= get_unaligned_le16(end); break; + case 1: b |= end[0]; + } +#endif + POSTAMBLE +} +#endif + +/** + * siphash_1u64 - compute 64-bit siphash PRF value of a u64 + * @first: first u64 + * @key: the siphash key + */ +u64 siphash_1u64(const u64 first, const siphash_key_t key) +{ + PREAMBLE(8) + v3 ^= first; + SIPROUND; + SIPROUND; + v0 ^= first; + POSTAMBLE +} + +/** + * siphash_2u64 - compute 64-bit siphash PRF value of 2 u64 + * @first: first u64 + * @second: second u64 + * @key: the siphash key + */ +u64 siphash_2u64(const u64 first, const u64 second, const siphash_key_t key) +{ + PREAMBLE(16) + v3 ^= first; + SIPROUND; + SIPROUND; + v0 ^= first; + v3 ^= second; + SIPROUND; + SIPROUND; + v0 ^= second; + POSTAMBLE +} + +/** + * siphash_3u64 - compute 64-bit siphash PRF value of 3 u64 + * @first: first u64 + * @second: second u64 + * @third: third u64 + * @key: the siphash key + */ +u64 siphash_3u64(const u64 first, const u64 second, const u64 third, + const siphash_key_t key) +{ + PREAMBLE(24) + v3 ^= first; + SIPROUND; + SIPROUND; + v0 ^= first; + v3 ^= second; + SIPROUND; + SIPROUND; + v0 ^= second; + v3 ^= third; + SIPROUND; + SIPROUND; + v0 ^= third; + POSTAMBLE +} + +/** + * siphash_4u64 - compute 64-bit siphash PRF value of 4 u64 + * @first: first u64 + * @second: second u64 + * @third: third u64 + * @forth: forth u64 + * @key: the siphash key + */ +u64 siphash_4u64(const u64 first, const u64 second, const u64 third, + const u64 forth, const siphash_key_t key) +{ + PREAMBLE(32) + v3 ^= first; + SIPROUND; + SIPROUND; + v0 ^= first; + v3 ^= second; + SIPROUND; + SIPROUND; + v0 ^= second; + v3 ^= third; + SIPROUND; + SIPROUND; + v0 ^= third; + v3 ^= forth; + SIPROUND; + SIPROUND; + v0 ^= forth; + POSTAMBLE +} + +#include "../selftest/siphash.h" diff --git a/src/crypto/siphash.h b/src/crypto/siphash.h new file mode 100644 index 0000000..90777b8 --- /dev/null +++ b/src/crypto/siphash.h @@ -0,0 +1,88 @@ +/* Copyright (C) 2015-2016 Jason A. Donenfeld . All Rights Reserved. + * + * SipHash: a fast short-input PRF + * https://131002.net/siphash/ + * + * This implementation is specifically for SipHash2-4. + */ + +#ifndef SIPHASH_H +#define SIPHASH_H + +#include +#include + +#define SIPHASH_ALIGNMENT 8 +typedef u64 siphash_key_t[2]; + +u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t key); +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS +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_aligned(const u64 *data, size_t len, const siphash_key_t key) +{ + if (__builtin_constant_p(len) && len == 8) + return siphash_1u64(data[0], key); + if (__builtin_constant_p(len) && len == 16) + return siphash_2u64(data[0], data[1], key); + if (__builtin_constant_p(len) && len == 24) + return siphash_3u64(data[0], data[1], data[2], key); + if (__builtin_constant_p(len) && len == 32) + return siphash_4u64(data[0], data[1], data[2], data[3], key); + return __siphash_aligned(data, len, key); +} + +/** + * siphash - compute 64-bit siphash PRF value + * @data: buffer to hash + * @size: size of @data + * @key: the siphash key + */ +static inline u64 siphash(const void *data, size_t len, const siphash_key_t key) +{ +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + if (!IS_ALIGNED((unsigned long)data, SIPHASH_ALIGNMENT)) + return __siphash_unaligned(data, len, key); +#endif + return ___siphash_aligned(data, len, 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); +} + +#ifdef DEBUG +bool siphash_selftest(void); +#endif + +#endif /* SIPHASH_H */ diff --git a/src/crypto/siphash24.c b/src/crypto/siphash24.c deleted file mode 100644 index 727ae4b..0000000 --- a/src/crypto/siphash24.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (C) 2015-2016 Jason A. Donenfeld . All Rights Reserved. */ - -#include "siphash24.h" - -#include - -static inline u64 le64_to_cpuvp(const void *p) -{ - return le64_to_cpup(p); -} - -#define SIPROUND \ - do { \ - v0 += v1; v1 = rol64(v1, 13); v1 ^= v0; v0 = rol64(v0, 32); \ - v2 += v3; v3 = rol64(v3, 16); v3 ^= v2; \ - v0 += v3; v3 = rol64(v3, 21); v3 ^= v0; \ - v2 += v1; v1 = rol64(v1, 17); v1 ^= v2; v2 = rol64(v2, 32); \ - } while(0) - -u64 siphash24(const u8 *data, size_t len, const u8 key[SIPHASH24_KEY_LEN]) -{ - u64 v0 = 0x736f6d6570736575ULL; - u64 v1 = 0x646f72616e646f6dULL; - u64 v2 = 0x6c7967656e657261ULL; - u64 v3 = 0x7465646279746573ULL; - u64 b = ((u64)len) << 56; - u64 k0 = le64_to_cpuvp(key); - u64 k1 = le64_to_cpuvp(key + sizeof(u64)); - u64 m; - const u8 *end = data + len - (len % sizeof(u64)); - const u8 left = len & (sizeof(u64) - 1); - v3 ^= k1; - v2 ^= k0; - v1 ^= k1; - v0 ^= k0; - for (; data != end; data += sizeof(u64)) { - m = le64_to_cpuvp(data); - v3 ^= m; - SIPROUND; - SIPROUND; - v0 ^= m; - } - switch (left) { - case 7: b |= ((u64)data[6]) << 48; - case 6: b |= ((u64)data[5]) << 40; - case 5: b |= ((u64)data[4]) << 32; - case 4: b |= ((u64)data[3]) << 24; - case 3: b |= ((u64)data[2]) << 16; - case 2: b |= ((u64)data[1]) << 8; - case 1: b |= ((u64)data[0]); break; - case 0: break; - } - v3 ^= b; - SIPROUND; - SIPROUND; - v0 ^= b; - v2 ^= 0xff; - SIPROUND; - SIPROUND; - SIPROUND; - SIPROUND; - b = (v0 ^ v1) ^ (v2 ^ v3); - return (__force u64)cpu_to_le64(b); -} - -#include "../selftest/siphash24.h" diff --git a/src/crypto/siphash24.h b/src/crypto/siphash24.h deleted file mode 100644 index 2ac9649..0000000 --- a/src/crypto/siphash24.h +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright (C) 2015-2016 Jason A. Donenfeld . All Rights Reserved. */ - -#ifndef SIPHASH24_H -#define SIPHASH24_H - -#include - -enum siphash24_lengths { - SIPHASH24_KEY_LEN = 16 -}; - -u64 siphash24(const u8 *data, size_t len, const u8 key[SIPHASH24_KEY_LEN]); - -#ifdef DEBUG -bool siphash24_selftest(void); -#endif - -#endif -- cgit v1.2.3-59-g8ed1b