Skip to content

Commit

Permalink
syncookies: use SipHash in place of SHA1
Browse files Browse the repository at this point in the history
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: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: David Miller <davem@davemloft.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jason A. Donenfeld authored and David S. Miller committed Jan 9, 2017
1 parent 7cd23e5 commit fe62d05
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 38 deletions.
21 changes: 5 additions & 16 deletions net/ipv4/syncookies.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
#include <linux/tcp.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/cryptohash.h>
#include <linux/siphash.h>
#include <linux/kernel.h>
#include <linux/export.h>
#include <net/tcp.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 COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
Expand Down Expand Up @@ -48,24 +48,13 @@ static u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS] __read_mostly;
#define TSBITS 6
#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,
u32 count, int c)
{
__u32 *tmp;

net_get_random_once(syncookie_secret, sizeof(syncookie_secret));

tmp = this_cpu_ptr(ipv4_cookie_scratch);
memcpy(tmp + 4, syncookie_secret[c], sizeof(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];
return siphash_4u32((__force u32)saddr, (__force u32)daddr,
(__force u32)sport << 16 | (__force u32)dport,
count, &syncookie_secret[c]);
}


Expand Down
41 changes: 19 additions & 22 deletions net/ipv6/syncookies.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@

#include <linux/tcp.h>
#include <linux/random.h>
#include <linux/cryptohash.h>
#include <linux/siphash.h>
#include <linux/kernel.h>
#include <net/ipv6.h>
#include <net/tcp.h>

#define COOKIEBITS 24 /* Upper bits store count */
#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:
* [ipv6 tcp] MSS must be computed as the maximum packet size minus 60 [..]
Expand All @@ -41,30 +41,27 @@ static __u16 const msstab[] = {
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)
{
__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));

tmp = this_cpu_ptr(ipv6_cookie_scratch);

/*
* 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];
return siphash(&combined, offsetofend(typeof(combined), dport),
&syncookie6_secret[c]);
}

static __u32 secure_tcp_syn_cookie(const struct in6_addr *saddr,
Expand Down

0 comments on commit fe62d05

Please sign in to comment.