Commit fe62d05b authored by Jason A. Donenfeld's avatar Jason A. Donenfeld Committed by David S. Miller

syncookies: use SipHash in place of SHA1

SHA1 is slower and less secure than SipHash, and so replacing syncookie
generation with SipHash makes natural sense. Some BSDs have been doing
this for several years in fact.

The speedup should be similar -- and even more impressive -- to the
speedup from the sequence number fix in this series.
Signed-off-by: default avatarJason A. Donenfeld <Jason@zx2c4.com>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: David Miller <davem@davemloft.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7cd23e53
...@@ -13,13 +13,13 @@ ...@@ -13,13 +13,13 @@
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/cryptohash.h> #include <linux/siphash.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/export.h> #include <linux/export.h>
#include <net/tcp.h> #include <net/tcp.h>
#include <net/route.h> #include <net/route.h>
static u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS] __read_mostly; static siphash_key_t syncookie_secret[2] __read_mostly;
#define COOKIEBITS 24 /* Upper bits store count */ #define COOKIEBITS 24 /* Upper bits store count */
#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
...@@ -48,24 +48,13 @@ static u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS] __read_mostly; ...@@ -48,24 +48,13 @@ static u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS] __read_mostly;
#define TSBITS 6 #define TSBITS 6
#define TSMASK (((__u32)1 << TSBITS) - 1) #define TSMASK (((__u32)1 << TSBITS) - 1)
static DEFINE_PER_CPU(__u32 [16 + 5 + SHA_WORKSPACE_WORDS], ipv4_cookie_scratch);
static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport, static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport,
u32 count, int c) u32 count, int c)
{ {
__u32 *tmp;
net_get_random_once(syncookie_secret, sizeof(syncookie_secret)); net_get_random_once(syncookie_secret, sizeof(syncookie_secret));
return siphash_4u32((__force u32)saddr, (__force u32)daddr,
tmp = this_cpu_ptr(ipv4_cookie_scratch); (__force u32)sport << 16 | (__force u32)dport,
memcpy(tmp + 4, syncookie_secret[c], sizeof(syncookie_secret[c])); count, &syncookie_secret[c]);
tmp[0] = (__force u32)saddr;
tmp[1] = (__force u32)daddr;
tmp[2] = ((__force u32)sport << 16) + (__force u32)dport;
tmp[3] = count;
sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5);
return tmp[17];
} }
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/cryptohash.h> #include <linux/siphash.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <net/ipv6.h> #include <net/ipv6.h>
#include <net/tcp.h> #include <net/tcp.h>
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#define COOKIEBITS 24 /* Upper bits store count */ #define COOKIEBITS 24 /* Upper bits store count */
#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
static u32 syncookie6_secret[2][16-4+SHA_DIGEST_WORDS] __read_mostly; static siphash_key_t syncookie6_secret[2] __read_mostly;
/* RFC 2460, Section 8.3: /* RFC 2460, Section 8.3:
* [ipv6 tcp] MSS must be computed as the maximum packet size minus 60 [..] * [ipv6 tcp] MSS must be computed as the maximum packet size minus 60 [..]
...@@ -41,30 +41,27 @@ static __u16 const msstab[] = { ...@@ -41,30 +41,27 @@ static __u16 const msstab[] = {
9000 - 60, 9000 - 60,
}; };
static DEFINE_PER_CPU(__u32 [16 + 5 + SHA_WORKSPACE_WORDS], ipv6_cookie_scratch); static u32 cookie_hash(const struct in6_addr *saddr,
const struct in6_addr *daddr,
static u32 cookie_hash(const struct in6_addr *saddr, const struct in6_addr *daddr,
__be16 sport, __be16 dport, u32 count, int c) __be16 sport, __be16 dport, u32 count, int c)
{ {
__u32 *tmp; const struct {
struct in6_addr saddr;
struct in6_addr daddr;
u32 count;
__be16 sport;
__be16 dport;
} __aligned(SIPHASH_ALIGNMENT) combined = {
.saddr = *saddr,
.daddr = *daddr,
.count = count,
.sport = sport,
.dport = dport
};
net_get_random_once(syncookie6_secret, sizeof(syncookie6_secret)); net_get_random_once(syncookie6_secret, sizeof(syncookie6_secret));
return siphash(&combined, offsetofend(typeof(combined), dport),
tmp = this_cpu_ptr(ipv6_cookie_scratch); &syncookie6_secret[c]);
/*
* we have 320 bits of information to hash, copy in the remaining
* 192 bits required for sha_transform, from the syncookie6_secret
* and overwrite the digest with the secret
*/
memcpy(tmp + 10, syncookie6_secret[c], 44);
memcpy(tmp, saddr, 16);
memcpy(tmp + 4, daddr, 16);
tmp[8] = ((__force u32)sport << 16) + (__force u32)dport;
tmp[9] = count;
sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5);
return tmp[17];
} }
static __u32 secure_tcp_syn_cookie(const struct in6_addr *saddr, static __u32 secure_tcp_syn_cookie(const struct in6_addr *saddr,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment