From: Matt Mackall Move syncookie code off to networking land. Signed-off-by: Matt Mackall Signed-off-by: Andrew Morton --- 25-akpm/drivers/char/random.c | 81 ----------------------------------------- 25-akpm/include/linux/random.h | 8 ---- 25-akpm/net/ipv4/syncookies.c | 77 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 89 deletions(-) diff -puN drivers/char/random.c~random-pt4-move-syncookies-to-net drivers/char/random.c --- 25/drivers/char/random.c~random-pt4-move-syncookies-to-net 2005-02-22 18:17:10.000000000 -0800 +++ 25-akpm/drivers/char/random.c 2005-02-22 18:17:10.000000000 -0800 @@ -366,10 +366,6 @@ static struct poolinfo { * hash; hash collisions will occur no more often than chance. */ -#ifdef CONFIG_SYN_COOKIES -static __u32 syncookie_secret[2][16-3+SHA_WORKSPACE_WORDS]; -#endif - /* * Static global variables */ @@ -901,9 +897,6 @@ static int __init rand_initialize(void) init_std_data(&input_pool); init_std_data(&blocking_pool); init_std_data(&nonblocking_pool); -#ifdef CONFIG_SYN_COOKIES - get_random_bytes(syncookie_secret, sizeof(syncookie_secret)); -#endif return 0; } module_init(rand_initialize); @@ -1581,80 +1574,6 @@ u32 secure_tcp_port_ephemeral(__u32 sadd return half_md4_transform(hash, keyptr->secret); } -#ifdef CONFIG_SYN_COOKIES -/* - * Secure SYN cookie computation. This is the algorithm worked out by - * Dan Bernstein and Eric Schenk. - * - * For linux I implement the 1 minute counter by looking at the jiffies clock. - * The count is passed in as a parameter, so this code doesn't much care. - */ - -#define COOKIEBITS 24 /* Upper bits store count */ -#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) - -static u32 cookie_hash(u32 saddr, u32 daddr, u32 sport, u32 dport, - u32 count, int c) -{ - __u32 tmp[16 + 5 + SHA_WORKSPACE_WORDS]; - - memcpy(tmp + 3, syncookie_secret[c], sizeof(syncookie_secret[c])); - tmp[0] = saddr; - tmp[1] = daddr; - tmp[2] = (sport << 16) + dport; - tmp[3] = count; - sha_transform(tmp + 16, tmp); - - return tmp[17]; -} - -__u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport, - __u16 dport, __u32 sseq, __u32 count, __u32 data) -{ - /* - * Compute the secure sequence number. - * The output should be: - * HASH(sec1,saddr,sport,daddr,dport,sec1) + sseq + (count * 2^24) - * + (HASH(sec2,saddr,sport,daddr,dport,count,sec2) % 2^24). - * Where sseq is their sequence number and count increases every - * minute by 1. - * As an extra hack, we add a small "data" value that encodes the - * MSS into the second hash value. - */ - - return (cookie_hash(saddr, daddr, sport, dport, 0, 0) + - sseq + (count << COOKIEBITS) + - ((cookie_hash(saddr, daddr, sport, dport, count, 1) + data) - & COOKIEMASK)); -} - -/* - * This retrieves the small "data" value from the syncookie. - * If the syncookie is bad, the data returned will be out of - * range. This must be checked by the caller. - * - * The count value used to generate the cookie must be within - * "maxdiff" if the current (passed-in) "count". The return value - * is (__u32)-1 if this test fails. - */ -__u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, __u16 sport, - __u16 dport, __u32 sseq, __u32 count, __u32 maxdiff) -{ - __u32 diff; - - /* Strip away the layers from the cookie */ - cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq; - - /* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */ - diff = (count - (cookie >> COOKIEBITS)) & ((__u32)-1 >> COOKIEBITS); - if (diff >= maxdiff) - return (__u32)-1; - - return (cookie - - cookie_hash(saddr, daddr, sport, dport, count - diff, 1)) - & COOKIEMASK; /* Leaving the data behind */ -} -#endif #endif /* CONFIG_INET */ diff -puN include/linux/random.h~random-pt4-move-syncookies-to-net include/linux/random.h --- 25/include/linux/random.h~random-pt4-move-syncookies-to-net 2005-02-22 18:17:10.000000000 -0800 +++ 25-akpm/include/linux/random.h 2005-02-22 18:17:10.000000000 -0800 @@ -55,14 +55,6 @@ extern __u32 secure_ip_id(__u32 daddr); extern u32 secure_tcp_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport); extern __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport); -extern __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, - __u16 sport, __u16 dport, - __u32 sseq, __u32 count, - __u32 data); -extern __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, - __u32 daddr, __u16 sport, - __u16 dport, __u32 sseq, - __u32 count, __u32 maxdiff); extern __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr, __u16 sport, __u16 dport); diff -puN net/ipv4/syncookies.c~random-pt4-move-syncookies-to-net net/ipv4/syncookies.c --- 25/net/ipv4/syncookies.c~random-pt4-move-syncookies-to-net 2005-02-22 18:17:10.000000000 -0800 +++ 25-akpm/net/ipv4/syncookies.c 2005-02-22 18:17:10.000000000 -0800 @@ -17,11 +17,88 @@ #include #include #include +#include #include #include extern int sysctl_tcp_syncookies; +static __u32 syncookie_secret[2][16-3+SHA_DIGEST_WORDS]; + +static __init int init_syncookies(void) +{ + get_random_bytes(syncookie_secret, sizeof(syncookie_secret)); + return 0; +} +module_init(init_syncookies); + +#define COOKIEBITS 24 /* Upper bits store count */ +#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) + +static u32 cookie_hash(u32 saddr, u32 daddr, u32 sport, u32 dport, + u32 count, int c) +{ + __u32 tmp[16 + 5 + SHA_WORKSPACE_WORDS]; + + memcpy(tmp + 3, syncookie_secret[c], sizeof(syncookie_secret[c])); + tmp[0] = saddr; + tmp[1] = daddr; + tmp[2] = (sport << 16) + dport; + tmp[3] = count; + sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5); + + return tmp[17]; +} + +static __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport, + __u16 dport, __u32 sseq, __u32 count, + __u32 data) +{ + /* + * Compute the secure sequence number. + * The output should be: + * HASH(sec1,saddr,sport,daddr,dport,sec1) + sseq + (count * 2^24) + * + (HASH(sec2,saddr,sport,daddr,dport,count,sec2) % 2^24). + * Where sseq is their sequence number and count increases every + * minute by 1. + * As an extra hack, we add a small "data" value that encodes the + * MSS into the second hash value. + */ + + return (cookie_hash(saddr, daddr, sport, dport, 0, 0) + + sseq + (count << COOKIEBITS) + + ((cookie_hash(saddr, daddr, sport, dport, count, 1) + data) + & COOKIEMASK)); +} + +/* + * This retrieves the small "data" value from the syncookie. + * If the syncookie is bad, the data returned will be out of + * range. This must be checked by the caller. + * + * The count value used to generate the cookie must be within + * "maxdiff" if the current (passed-in) "count". The return value + * is (__u32)-1 if this test fails. + */ +static __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, + __u16 sport, __u16 dport, __u32 sseq, + __u32 count, __u32 maxdiff) +{ + __u32 diff; + + /* Strip away the layers from the cookie */ + cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq; + + /* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */ + diff = (count - (cookie >> COOKIEBITS)) & ((__u32) - 1 >> COOKIEBITS); + if (diff >= maxdiff) + return (__u32)-1; + + return (cookie - + cookie_hash(saddr, daddr, sport, dport, count - diff, 1)) + & COOKIEMASK; /* Leaving the data behind */ +} + /* * This table has to be sorted and terminated with (__u16)-1. * XXX generate a better table. _