From patchwork Thu Dec 15 20:30:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Jason A. Donenfeld" X-Patchwork-Id: 9476861 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 274206047D for ; Thu, 15 Dec 2016 20:30:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 194CF28848 for ; Thu, 15 Dec 2016 20:30:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0DA5728850; Thu, 15 Dec 2016 20:30:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id CEE2328848 for ; Thu, 15 Dec 2016 20:30:47 +0000 (UTC) Received: (qmail 5871 invoked by uid 550); 15 Dec 2016 20:30:40 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Reply-To: kernel-hardening@lists.openwall.com Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 5369 invoked from network); 15 Dec 2016 20:30:35 -0000 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=zx2c4.com; h=from:to:cc :subject:date:message-id:in-reply-to:references; s=mail; bh=kn/Z qyha4fTSueycodf1ioS39i8=; b=Hesx+wLxLX1Jvq3DNoOP625ssJ0yMH3YgtUh 5Ijkfnhcsz1UBWMmCFPxgc+4g+p6HOk4e8oscEDrDnuV1GTxFK1nwWwJdnOVvcEP ueFYu0J05TNOzoP92sIB5ZiHcnViuCpc3g/sQEzm+j2z09+sfnmwM2Yj3M0ZrycM sCZa6ggMSahP4LKsCAbIgxCUY5vYLrtRd+gwzdXoHQz+YB+k2N3pot2ufK4/07CI Y8p0s0z3VRQixkrdQwcWBz/FWotMePg1zCWut3/Bs/rFDZn3SjdRjhUePSWpoDgG WV04+FZVnSV9YTWyoODrVzVile//aFpBpZbG4jS/STAtozNm7A== From: "Jason A. Donenfeld" To: Netdev , kernel-hardening@lists.openwall.com, LKML , linux-crypto@vger.kernel.org, David Laight , Ted Tso , Hannes Frederic Sowa , Linus Torvalds , Eric Biggers , Tom Herbert , George Spelvin , Vegard Nossum , ak@linux.intel.com, davem@davemloft.net, luto@amacapital.net Cc: "Jason A. Donenfeld" Date: Thu, 15 Dec 2016 21:30:01 +0100 Message-Id: <20161215203003.31989-3-Jason@zx2c4.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20161215203003.31989-1-Jason@zx2c4.com> References: <20161215203003.31989-1-Jason@zx2c4.com> Subject: [kernel-hardening] [PATCH v5 2/4] siphash: add Nu{32,64} helpers X-Virus-Scanned: ClamAV using ClamSMTP 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 + +/** + * 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 +} +EXPORT_SYMBOL(siphash_1u64); + +/** + * 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 ^= b; - v2 ^= 0xff; + v0 ^= first; + v3 ^= second; SIPROUND; SIPROUND; + v0 ^= second; + POSTAMBLE +} +EXPORT_SYMBOL(siphash_2u64); + +/** + * 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; - return (v0 ^ v1) ^ (v2 ^ v3); + v0 ^= first; + v3 ^= second; + SIPROUND; + SIPROUND; + v0 ^= second; + v3 ^= third; + SIPROUND; + SIPROUND; + v0 ^= third; + POSTAMBLE } -EXPORT_SYMBOL(siphash_unaligned); -#endif +EXPORT_SYMBOL(siphash_3u64); + +/** + * 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 +} +EXPORT_SYMBOL(siphash_4u64); diff --git a/lib/test_siphash.c b/lib/test_siphash.c index 93549e4e22c5..1635189c171f 100644 --- a/lib/test_siphash.c +++ b/lib/test_siphash.c @@ -67,6 +67,24 @@ static int __init siphash_test_init(void) ret = -EINVAL; } } + if (siphash_1u64(0x0706050403020100ULL, test_key) != test_vectors[8]) { + pr_info("self-test 1u64: FAIL\n"); + ret = -EINVAL; + } + if (siphash_2u64(0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL, test_key) != test_vectors[16]) { + pr_info("self-test 2u64: FAIL\n"); + ret = -EINVAL; + } + if (siphash_3u64(0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL, + 0x1716151413121110ULL, test_key) != test_vectors[24]) { + pr_info("self-test 3u64: FAIL\n"); + ret = -EINVAL; + } + if (siphash_4u64(0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL, + 0x1716151413121110ULL, 0x1f1e1d1c1b1a1918ULL, test_key) != test_vectors[32]) { + pr_info("self-test 4u64: FAIL\n"); + ret = -EINVAL; + } if (!ret) pr_info("self-tests: pass\n"); return ret;