From patchwork Wed Dec 14 00:16:56 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: 9473495 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 C1CBB6021C for ; Wed, 14 Dec 2016 00:17:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B3089286C9 for ; Wed, 14 Dec 2016 00:17:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A7899286CC; Wed, 14 Dec 2016 00:17:33 +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 75900286C9 for ; Wed, 14 Dec 2016 00:17:32 +0000 (UTC) Received: (qmail 19672 invoked by uid 550); 14 Dec 2016 00:17:27 -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 18009 invoked from network); 14 Dec 2016 00:17:20 -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=jfFX aRRSpy6upYofJVeFkk1pIEM=; b=EdwQfBdi7nK0DcOo5HzqwsJi90LE/XzrhZdY 0Y0/cLqJ7+6KuLQTH1ValGnvHeIIA0RN45vO5NP4UGYDwulXWNWpXypG8ZCPtyvz l6bc8BqMTIjdU9cCos2e/L3DAFLUlf2dZrrNHoMtQ5wnJnsg0c5hhCPnyGXJEvEI ACMpe8V/OEExkthNDy4NBUtPX2DQDBgmGS2YBlh5mMtpVTV+lpS+uxVHVYdlz8nN /a92rxkb0AmUJnt33VJlG/gaCXelgmi0Qpho6YNJ9VQCT2sX5tB3izAG0xN0s3ke v0PPvkCarwnZHPG1M0gkqPHfHGNKjpFZmtgzIA0+5bU/Jz3HBg== From: "Jason A. Donenfeld" To: Netdev , David Miller , Linus Torvalds , "kernel-hardening@lists.openwall.com" , LKML , George Spelvin , Scott Bauer , Andi Kleen , Andy Lutomirski , Greg KH , Eric Biggers Cc: "Jason A. Donenfeld" Date: Wed, 14 Dec 2016 01:16:56 +0100 Message-Id: <20161214001656.19388-3-Jason@zx2c4.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20161214001656.19388-1-Jason@zx2c4.com> References: <20161214001656.19388-1-Jason@zx2c4.com> Subject: [kernel-hardening] [PATCH 3/3] secure_seq: use fast&secure siphash instead of slow&insecure md5 X-Virus-Scanned: ClamAV using ClamSMTP This gives a clear speed and security improvement. Rather than manually filling MD5 buffers, we simply create a layout by a simple anonymous struct, for which gcc generates rather efficient code. Signed-off-by: Jason A. Donenfeld --- net/core/secure_seq.c | 153 ++++++++++++++++++++++++-------------------------- 1 file changed, 73 insertions(+), 80 deletions(-) diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c index fd3ce461fbe6..dcee974f2fb1 100644 --- a/net/core/secure_seq.c +++ b/net/core/secure_seq.c @@ -1,3 +1,5 @@ +/* Copyright (C) 2016 Jason A. Donenfeld . All Rights Reserved. */ + #include #include #include @@ -8,13 +10,12 @@ #include #include #include - +#include +#include #include #if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET) -#define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4) - -static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned; +static u8 net_secret[SIPHASH24_KEY_LEN]; static __always_inline void net_secret_init(void) { @@ -43,43 +44,36 @@ static u32 seq_scale(u32 seq) __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr, __be16 sport, __be16 dport) { - u32 secret[MD5_MESSAGE_BYTES / 4]; - u32 hash[MD5_DIGEST_WORDS]; - u32 i; - + const struct { + struct in6_addr saddr; + struct in6_addr daddr; + __be16 sport; + __be16 dport; + } __packed combined = { + .saddr = *(struct in6_addr *)saddr, + .daddr = *(struct in6_addr *)daddr, + .sport = sport, + .dport = dport + }; net_secret_init(); - memcpy(hash, saddr, 16); - for (i = 0; i < 4; i++) - secret[i] = net_secret[i] + (__force u32)daddr[i]; - secret[4] = net_secret[4] + - (((__force u16)sport << 16) + (__force u16)dport); - for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++) - secret[i] = net_secret[i]; - - md5_transform(hash, secret); - - return seq_scale(hash[0]); + return seq_scale(siphash24((const u8 *)&combined, sizeof(combined), net_secret)); } EXPORT_SYMBOL(secure_tcpv6_sequence_number); u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, __be16 dport) { - u32 secret[MD5_MESSAGE_BYTES / 4]; - u32 hash[MD5_DIGEST_WORDS]; - u32 i; - + const struct { + struct in6_addr saddr; + struct in6_addr daddr; + __be16 dport; + } __packed combined = { + .saddr = *(struct in6_addr *)saddr, + .daddr = *(struct in6_addr *)daddr, + .dport = dport + }; net_secret_init(); - memcpy(hash, saddr, 16); - for (i = 0; i < 4; i++) - secret[i] = net_secret[i] + (__force u32) daddr[i]; - secret[4] = net_secret[4] + (__force u32)dport; - for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++) - secret[i] = net_secret[i]; - - md5_transform(hash, secret); - - return hash[0]; + return siphash24((const u8 *)&combined, sizeof(combined), net_secret); } EXPORT_SYMBOL(secure_ipv6_port_ephemeral); #endif @@ -89,32 +83,34 @@ EXPORT_SYMBOL(secure_ipv6_port_ephemeral); __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport) { - u32 hash[MD5_DIGEST_WORDS]; - + const struct { + __be32 saddr; + __be32 daddr; + __be16 sport; + __be16 dport; + } __packed combined = { + .saddr = saddr, + .daddr = daddr, + .sport = sport, + .dport = dport + }; net_secret_init(); - hash[0] = (__force u32)saddr; - hash[1] = (__force u32)daddr; - hash[2] = ((__force u16)sport << 16) + (__force u16)dport; - hash[3] = net_secret[15]; - - md5_transform(hash, net_secret); - - return seq_scale(hash[0]); + return seq_scale(siphash24((const u8 *)&combined, sizeof(combined), net_secret)); } u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport) { - u32 hash[MD5_DIGEST_WORDS]; - + const struct { + __be32 saddr; + __be32 daddr; + __be16 dport; + } __packed combined = { + .saddr = saddr, + .daddr = daddr, + .dport = dport + }; net_secret_init(); - hash[0] = (__force u32)saddr; - hash[1] = (__force u32)daddr; - hash[2] = (__force u32)dport ^ net_secret[14]; - hash[3] = net_secret[15]; - - md5_transform(hash, net_secret); - - return hash[0]; + return seq_scale(siphash24((const u8 *)&combined, sizeof(combined), net_secret)); } EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral); #endif @@ -123,21 +119,22 @@ EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral); u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport) { - u32 hash[MD5_DIGEST_WORDS]; + const struct { + __be32 saddr; + __be32 daddr; + __be16 sport; + __be16 dport; + } __packed combined = { + .saddr = saddr, + .daddr = daddr, + .sport = sport, + .dport = dport + }; u64 seq; - net_secret_init(); - hash[0] = (__force u32)saddr; - hash[1] = (__force u32)daddr; - hash[2] = ((__force u16)sport << 16) + (__force u16)dport; - hash[3] = net_secret[15]; - - md5_transform(hash, net_secret); - - seq = hash[0] | (((u64)hash[1]) << 32); + seq = siphash24((const u8 *)&combined, sizeof(combined), net_secret); seq += ktime_get_real_ns(); seq &= (1ull << 48) - 1; - return seq; } EXPORT_SYMBOL(secure_dccp_sequence_number); @@ -146,26 +143,22 @@ EXPORT_SYMBOL(secure_dccp_sequence_number); u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, __be16 sport, __be16 dport) { - u32 secret[MD5_MESSAGE_BYTES / 4]; - u32 hash[MD5_DIGEST_WORDS]; + const struct { + struct in6_addr saddr; + struct in6_addr daddr; + __be16 sport; + __be16 dport; + } __packed combined = { + .saddr = *(struct in6_addr *)saddr, + .daddr = *(struct in6_addr *)daddr, + .sport = sport, + .dport = dport + }; u64 seq; - u32 i; - net_secret_init(); - memcpy(hash, saddr, 16); - for (i = 0; i < 4; i++) - secret[i] = net_secret[i] + (__force u32)daddr[i]; - secret[4] = net_secret[4] + - (((__force u16)sport << 16) + (__force u16)dport); - for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++) - secret[i] = net_secret[i]; - - md5_transform(hash, secret); - - seq = hash[0] | (((u64)hash[1]) << 32); + seq = siphash24((const u8 *)&combined, sizeof(combined), net_secret); seq += ktime_get_real_ns(); seq &= (1ull << 48) - 1; - return seq; } EXPORT_SYMBOL(secure_dccpv6_sequence_number);