Hi,

Attached you can find a split up patch ported from grSecurity [1], as
Linus commented that he wouldn't get a whole-sale patch, I was working
on it and also studying what features of grSecurity can be implemented
without a development or maintenance overhead, aka less-invasive
implementations.

It adds support for advanced networking-related randomization, in
concrete it adds support for TCP ISNs randomization, RPC XIDs
randomization, IP IDs randomization and finally a sub-key under the
Cryptographic options menu for Linux PRNG [2] enhancements (useful now
and also for future patch submissions), which currently has an only-one
option for poll sizes increasing (x2).

As it's impact is minimal (in performance and development/maintenance
terms), I recommend to merge it, as it gives a basic prevention for the
so-called system fingerprinting (which is used most by "kids" to know
how old and insecure could be a target system, many time used as the
first, even only-one, data to decide if attack or not the target host)
among other things.

There's only a missing feature that is present on grSecurity, the
sources ports randomization which seems achieved now by some changes
that can be checked out in the Linux BKBits repository:
http://linux.bkbits.net:8080/linux-2.6/diffs/net/ipv4/[EMAIL 
PROTECTED]|src/|src/net|src/net/ipv4|hist/net/ipv4/tcp_ipv4.c
(net/ipv4/[EMAIL PROTECTED])

I'm not sure of the effectiveness of that changes, but I just prefer to
keep it as most simple as possible.If there are thoughts on reverting to
the old schema, and using obsd_rand.c code instead, just drop me a line
and I will modify the patch.

I've uploaded the patches and obsd_rand.c source to:
http://cvs.tuxedo-es.org/cgi-bin/viewcvs.cgi/obsd-netrand/

References:     
 [1]: http://www.grsecurity.net
 [2]: http://en.wikipedia.org/wiki/Pseudorandom_number_generator

Cheers,
-- 
Lorenzo Hernández García-Hierro <[EMAIL PROTECTED]> 
[1024D/6F2B2DEC] & [2048g/9AE91A22][http://tuxedo-es.org]
diff -Nur linux-2.6.11-rc2/crypto/Kconfig linux-2.6.11-rc2.tx1/crypto/Kconfig
--- linux-2.6.11-rc2/crypto/Kconfig	2005-01-26 19:54:06.000000000 +0100
+++ linux-2.6.11-rc2.tx1/crypto/Kconfig	2005-01-28 17:05:39.000000000 +0100
@@ -4,6 +4,26 @@
 
 menu "Cryptographic options"
 
+config RANDOM
+	bool "Random Numbers Generator enhancements"
+	help
+	  By enabling this option, you will be able to select
+	  a few enhancements for the Linux Random Numbers Generator
+	  (./drivers/char/random.{h,c}).
+	  
+	  If unsure: say Y.
+	  
+config RANDOM_INCREASED_POOLSIZES
+	bool "Larger entropy pools"
+	depends on RANDOM
+	help
+	  If you say Y here, the entropy pools used for many features of Linux
+          will be doubled in size. It is recommended that you say Y
+          here.  Saying Y here has a similar effect as modifying
+          /proc/sys/kernel/random/poolsize.
+	  
+	  If unsure: say Y.
+
 config CRYPTO
 	bool "Cryptographic API"
 	help
diff -Nur linux-2.6.11-rc2/drivers/char/random.c linux-2.6.11-rc2.tx1/drivers/char/random.c
--- linux-2.6.11-rc2/drivers/char/random.c	2005-01-26 19:54:07.000000000 +0100
+++ linux-2.6.11-rc2.tx1/drivers/char/random.c	2005-01-28 17:03:02.000000000 +0100
@@ -255,10 +255,20 @@
 
 /*
  * Configuration information
+ * If "increased pool sizes" option is enabled,
+ * then poll size default values get increased x2. 
  */
+ 
+#ifdef CONFIG_RANDOM_INCREASED_POOLSIZES
+#define DEFAULT_POOL_SIZE 1024
+#define SECONDARY_POOL_SIZE 256
+#define BATCH_ENTROPY_SIZE 512
+#else
 #define DEFAULT_POOL_SIZE 512
 #define SECONDARY_POOL_SIZE 128
 #define BATCH_ENTROPY_SIZE 256
+#endif
+
 #define USE_SHA
 
 /*
diff -Nur linux-2.6.11-rc2/include/linux/random.h linux-2.6.11-rc2.tx1/include/linux/random.h
--- linux-2.6.11-rc2/include/linux/random.h	2005-01-26 19:54:17.000000000 +0100
+++ linux-2.6.11-rc2.tx1/include/linux/random.h	2005-01-27 23:45:34.000000000 +0100
@@ -42,6 +42,12 @@
 
 #ifdef __KERNEL__
 
+#ifdef CONFIG_NET_SECURITY
+extern unsigned long obsd_get_random_long(void);
+extern __u16 ip_randomid(void);
+extern __u32 ip_randomisn(void);
+#endif
+
 extern void rand_initialize_irq(int irq);
 
 extern void add_input_randomness(unsigned int type, unsigned int code,
diff -Nur linux-2.6.11-rc2/net/ipv4/tcp_ipv4.c linux-2.6.11-rc2.tx1/net/ipv4/tcp_ipv4.c
--- linux-2.6.11-rc2/net/ipv4/tcp_ipv4.c	2005-01-26 19:54:19.000000000 +0100
+++ linux-2.6.11-rc2.tx1/net/ipv4/tcp_ipv4.c	2005-01-28 17:16:09.000000000 +0100
@@ -539,10 +539,14 @@
 
 static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb)
 {
+#ifdef CONFIG_NET_RANDISN
+		return ip_randomisn();
+#else
 	return secure_tcp_sequence_number(skb->nh.iph->daddr,
 					  skb->nh.iph->saddr,
 					  skb->h.th->dest,
 					  skb->h.th->source);
+#endif
 }
 
 /* called with local bh disabled */
@@ -833,14 +837,21 @@
 	tcp_v4_setup_caps(sk, &rt->u.dst);
 	tp->ext2_header_len = rt->u.dst.header_len;
 
-	if (!tp->write_seq)
+	if (!tp->write_seq) {
+#ifdef CONFIG_NET_RANDISN
+			tp->write_seq = ip_randomisn();
+#else
 		tp->write_seq = secure_tcp_sequence_number(inet->saddr,
 							   inet->daddr,
 							   inet->sport,
 							   usin->sin_port);
-
+#endif
+	}
+#ifdef CONFIG_NET_RANDID
+		inet->id = htons(ip_randomid());
+#else
 	inet->id = tp->write_seq ^ jiffies;
-
+#endif
 	err = tcp_connect(sk);
 	rt = NULL;
 	if (err)
@@ -1579,8 +1590,11 @@
 	if (newinet->opt)
 		newtp->ext_header_len = newinet->opt->optlen;
 	newtp->ext2_header_len = dst->header_len;
+#ifdef CONFIG_NET_RANDID
+	newinet->id = htons(ip_randomid());
+#else
 	newinet->id = newtp->write_seq ^ jiffies;
-
+#endif
 	tcp_sync_mss(newsk, dst_pmtu(dst));
 	newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
 	tcp_initialize_rcv_mss(newsk);
diff -Nur linux-2.6.11-rc2/net/ipv4/udp.c linux-2.6.11-rc2.tx1/net/ipv4/udp.c
--- linux-2.6.11-rc2/net/ipv4/udp.c	2005-01-26 19:54:19.000000000 +0100
+++ linux-2.6.11-rc2.tx1/net/ipv4/udp.c	2005-01-27 23:02:32.000000000 +0100
@@ -94,6 +94,7 @@
 #include <linux/inet.h>
 #include <linux/ipv6.h>
 #include <linux/netdevice.h>
+#include <linux/random.h>
 #include <net/snmp.h>
 #include <net/tcp.h>
 #include <net/protocol.h>
diff -Nur linux-2.6.11-rc2/net/Kconfig linux-2.6.11-rc2.tx1/net/Kconfig
--- linux-2.6.11-rc2/net/Kconfig	2005-01-26 19:54:17.000000000 +0100
+++ linux-2.6.11-rc2.tx1/net/Kconfig	2005-01-28 17:04:30.608652680 +0100
@@ -81,6 +81,59 @@
 
 	  Say Y unless you know what you are doing.
 
+config NET_SECURITY
+	bool "Network Protections"
+	depends on NET
+	select INET
+	help
+	 By enabling this option, you will be able to choose a few options
+	 that will enhance the TCP/IP stack and network-related randomization.
+	 An example of results of this, is that the system will be a difficult
+	 subject of (remote) fingerprinting.
+	 
+	 These protections come from the grSecurity project by Brad Spengler,
+	 and based on OpenBSD extended networking security features.
+	 
+	 Ported to vanilla sources by Lorenzo Hernández García-Hierro
+	 <[EMAIL PROTECTED]>.
+	 Information at http://tuxedo-es.org and http://grsecurity.net.
+	 
+	 Short answer: say Y.
+
+config NET_RANDISN
+        bool "Truly random TCP ISN selection"
+        depends on NET_SECURITY
+        help
+          If you say Y here, Linux's default selection of TCP Initial Sequence
+          Numbers (ISNs) will be replaced with that of OpenBSD.  Linux uses
+          an MD4 hash based on the connection plus a time value to create the
+          ISN, while OpenBSD's selection is random.  If the sysctl option is
+          enabled, a sysctl option with name "rand_isns" is created.
+
+config NET_RANDID
+        bool "Randomized IP IDs"
+        depends on NET_SECURITY
+        help
+          If you say Y here, all the id field on all outgoing packets
+          will be randomized.  This hinders os fingerprinters and
+          keeps your machine from being used as a bounce for an untraceable
+          portscan.  Ids are used for fragmented packets, fragments belonging
+          to the same packet have the same id.  By default linux only
+          increments the id value on each packet sent to an individual host.
+          We use a port of the OpenBSD random ip id code to achieve the
+          randomness, while keeping the possibility of id duplicates to
+          near none.
+          
+config NET_RANDRPC
+        bool "Randomized RPC XIDs"
+        depends on NET_SECURITY
+        help
+          If you say Y here, the method of determining XIDs for RPC requests will
+          be randomized, instead of using linux's default behavior of simply
+          incrementing the XID.  If you want your RPC connections to be more
+          secure, say Y here.
+
+
 config INET
 	bool "TCP/IP networking"
 	---help---
diff -Nur linux-2.6.11-rc2/net/Makefile linux-2.6.11-rc2.tx1/net/Makefile
--- linux-2.6.11-rc2/net/Makefile	2005-01-26 19:50:49.000000000 +0100
+++ linux-2.6.11-rc2.tx1/net/Makefile	2005-01-27 23:04:02.000000000 +0100
@@ -11,6 +11,7 @@
 
 tmp-$(CONFIG_COMPAT) 		:= compat.o
 obj-$(CONFIG_NET)		+= $(tmp-y)
+obj-$(CONFIG_NET_SECURITY)	+= obsd_rand.o
 
 # LLC has to be linked before the files in net/802/
 obj-$(CONFIG_LLC)		+= llc/
diff -Nur linux-2.6.11-rc2/net/obsd_rand.c linux-2.6.11-rc2.tx1/net/obsd_rand.c
--- linux-2.6.11-rc2/net/obsd_rand.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.11-rc2.tx1/net/obsd_rand.c	2005-01-28 17:43:50.452901824 +0100
@@ -0,0 +1,269 @@
+/* $Id: openbsd-netrand-2.6.11-rc2.patch,v 1.2 2005/01/28 16:51:02 lorenzo Exp $
+ * Copyright (c) 2005 Lorenzo Hernandez Garcia-Hierro <[EMAIL PROTECTED]>.
+ * All rights reserved.
+ *
+ * Added some macros and stolen code from random.c, for individual and less
+ * "invasive" implementation.Also removed the get_random_long() macro definition,
+ * which is not good if we can simply call back obsd_get_random_long().
+ *
+ * Copyright (c) 1996, 1997, 2000-2002 Michael Shalayeff.
+ * 
+ * Version 1.90, last modified 28-Jan-05
+ *    
+ * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999.
+ * All rights reserved.
+ *
+ * Copyright 1998 Niels Provos <[EMAIL PROTECTED]>
+ * All rights reserved.
+ * Theo de Raadt <[EMAIL PROTECTED]> came up with the idea of using
+ * such a mathematical system to generate more random (yet non-repeating)
+ * ids to solve the resolver/named problem.  But Niels designed the
+ * actual system based on the constraints.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/timer.h>
+#include <linux/smp_lock.h>
+#include <linux/random.h>
+
+#define RU_OUT 180
+#define RU_MAX 30000
+#define RU_GEN 2
+#define RU_N 32749
+#define RU_AGEN 7
+#define RU_M 31104
+#define PFAC_N 3
+
+/*
+ * Stolen from ./drivers/char/random.c
+ */
+
+/* FOO, GEEK and HECK are basic geekish MD4 functions: foo selection, geek majority, heck parity */
+#define FOO(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define GEEK(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
+#define HECK(x, y, z) ((x) ^ (y) ^ (z))
+#define OBROUND(f, a, b, c, d, x, s)	\
+	(a += f(b, c, d) + x, a = (a << s) | (a >> (32 - s)))
+#define obK1 0
+#define obK2 013240474631UL
+#define obK3 015666365641UL
+#define OB_REKEY_INTERVAL (300 * HZ)
+
+
+const static __u16 pfacts[PFAC_N] = { 2, 3, 2729 };
+
+static __u16 ru_x;
+static __u16 ru_seed, ru_seed2;
+static __u16 ru_a, ru_b;
+static __u16 ru_g;
+static __u16 ru_counter = 0;
+static __u16 ru_msb = 0;
+static unsigned long ru_reseed = 0;
+static __u32 tmp;
+
+#define TCP_RNDISS_ROUNDS	15
+#define TCP_RNDISS_OUT		7200
+#define TCP_RNDISS_MAX		30000
+
+static __u8 tcp_rndiss_sbox[128];
+static __u16 tcp_rndiss_msb;
+static __u16 tcp_rndiss_cnt;
+static unsigned long tcp_rndiss_reseed;
+
+static __u16 pmod(__u16, __u16, __u16);
+static void ip_initid(void);
+__u16 ip_randomid(void);
+
+/*
+ * Basic cut-down MD4 transform.  Returns only 32 bits of result.
+ */
+static __u32 half_md4_transform (__u32 const buf[4], __u32 const in[8])
+{
+	__u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+	/* Round 1 */
+	OBROUND(FOO, a, b, c, d, in[0] + obK1,  3);
+	OBROUND(FOO, d, a, b, c, in[1] + obK1,  7);
+	OBROUND(FOO, c, d, a, b, in[2] + obK1, 11);
+	OBROUND(FOO, b, c, d, a, in[3] + obK1, 19);
+	OBROUND(FOO, a, b, c, d, in[4] + obK1,  3);
+	OBROUND(FOO, d, a, b, c, in[5] + obK1,  7);
+	OBROUND(FOO, c, d, a, b, in[6] + obK1, 11);
+	OBROUND(FOO, b, c, d, a, in[7] + obK1, 19);
+
+	/* Round 2 */
+	OBROUND(GEEK, a, b, c, d, in[1] + obK2,  3);
+	OBROUND(GEEK, d, a, b, c, in[3] + obK2,  5);
+	OBROUND(GEEK, c, d, a, b, in[5] + obK2,  9);
+	OBROUND(GEEK, b, c, d, a, in[7] + obK2, 13);
+	OBROUND(GEEK, a, b, c, d, in[0] + obK2,  3);
+	OBROUND(GEEK, d, a, b, c, in[2] + obK2,  5);
+	OBROUND(GEEK, c, d, a, b, in[4] + obK2,  9);
+	OBROUND(GEEK, b, c, d, a, in[6] + obK2, 13);
+
+	/* Round 3 */
+	OBROUND(HECK, a, b, c, d, in[3] + obK3,  3);
+	OBROUND(HECK, d, a, b, c, in[7] + obK3,  9);
+	OBROUND(HECK, c, d, a, b, in[2] + obK3, 11);
+	OBROUND(HECK, b, c, d, a, in[6] + obK3, 15);
+	OBROUND(HECK, a, b, c, d, in[1] + obK3,  3);
+	OBROUND(HECK, d, a, b, c, in[5] + obK3,  9);
+	OBROUND(HECK, c, d, a, b, in[0] + obK3, 11);
+	OBROUND(HECK, b, c, d, a, in[4] + obK3, 15);
+
+	return buf[1] + b;	/* "most hashed" word */
+	/* Alternative: return sum of all words? */
+}
+
+unsigned long obsd_get_random_long(void)
+{
+	static time_t   rekey_time;
+	static __u32    secret[12];
+	time_t          t;
+
+	/*
+	 * Pick a random secret every OB_REKEY_INTERVAL seconds.
+	 */
+	t = get_seconds();
+	if (!rekey_time || (t - rekey_time) > OB_REKEY_INTERVAL) {
+		rekey_time = t;
+		get_random_bytes(secret, sizeof(secret));
+	}
+
+	secret[1] = half_md4_transform(secret+8, secret);
+	secret[0] = half_md4_transform(secret+8, secret);
+	return *(unsigned long *)secret;
+}
+
+static __u16
+pmod(__u16 gen, __u16 exp, __u16 mod)
+{
+	__u16 s, t, u;
+
+	s = 1;
+	t = gen;
+	u = exp;
+
+	while (u) {
+		if (u & 1)
+			s = (s * t) % mod;
+		u >>= 1;
+		t = (t * t) % mod;
+	}
+	return (s);
+}
+
+static void
+ip_initid(void)
+{
+	__u16 j, i;
+	int noprime = 1;
+
+	ru_x = ((tmp = obsd_get_random_long()) & 0xFFFF) % RU_M;
+
+	ru_seed = (tmp >> 16) & 0x7FFF;
+	ru_seed2 = obsd_get_random_long() & 0x7FFF;
+
+	ru_b = ((tmp = obsd_get_random_long()) & 0xfffe) | 1;
+	ru_a = pmod(RU_AGEN, (tmp >> 16) & 0xfffe, RU_M);
+	while (ru_b % 3 == 0)
+		ru_b += 2;
+
+	j = (tmp = obsd_get_random_long()) % RU_N;
+	tmp = tmp >> 16;
+
+	while (noprime) {
+		for (i = 0; i < PFAC_N; i++)
+			if (j % pfacts[i] == 0)
+				break;
+
+		if (i >= PFAC_N)
+			noprime = 0;
+		else
+			j = (j + 1) % RU_N;
+	}
+
+	ru_g = pmod(RU_GEN, j, RU_N);
+	ru_counter = 0;
+
+	ru_reseed = xtime.tv_sec + RU_OUT;
+	ru_msb = ru_msb == 0x8000 ? 0 : 0x8000;
+}
+
+__u16
+ip_randomid(void)
+{
+	int i, n;
+
+	if (ru_counter >= RU_MAX || time_after(get_seconds(), ru_reseed))
+		ip_initid();
+
+	if (!tmp)
+		tmp = obsd_get_random_long();
+
+	n = tmp & 0x3;
+	tmp = tmp >> 2;
+	if (ru_counter + n >= RU_MAX)
+		ip_initid();
+	for (i = 0; i <= n; i++)
+		ru_x = (ru_a * ru_x + ru_b) % RU_M;
+	ru_counter += i;
+
+	return ((ru_seed ^ pmod(ru_g, ru_seed2 ^ ru_x, RU_N)) | ru_msb);
+}
+
+static __u16
+tcp_rndiss_encrypt(__u16 val)
+{
+	__u16 sum = 0, i;
+
+	for (i = 0; i < TCP_RNDISS_ROUNDS; i++) {
+		sum += 0x79b9;
+		val ^= ((__u16) tcp_rndiss_sbox[(val ^ sum) & 0x7f]) << 7;
+		val = ((val & 0xff) << 7) | (val >> 8);
+	}
+
+	return val;
+}
+
+static void
+tcp_rndiss_init(void)
+{
+	get_random_bytes(tcp_rndiss_sbox, sizeof (tcp_rndiss_sbox));
+	tcp_rndiss_reseed = get_seconds() + TCP_RNDISS_OUT;
+	tcp_rndiss_msb = tcp_rndiss_msb == 0x8000 ? 0 : 0x8000;
+	tcp_rndiss_cnt = 0;
+}
+
+__u32
+ip_randomisn(void)
+{
+	if (tcp_rndiss_cnt >= TCP_RNDISS_MAX ||
+	    time_after(get_seconds(), tcp_rndiss_reseed))
+		tcp_rndiss_init();
+
+	return (((tcp_rndiss_encrypt(tcp_rndiss_cnt++) |
+		  tcp_rndiss_msb) << 16) | (obsd_get_random_long() & 0x7fff));
+}
diff -Nur linux-2.6.11-rc2/net/sunrpc/xprt.c linux-2.6.11-rc2.tx1/net/sunrpc/xprt.c
--- linux-2.6.11-rc2/net/sunrpc/xprt.c	2005-01-26 19:54:20.000000000 +0100
+++ linux-2.6.11-rc2.tx1/net/sunrpc/xprt.c	2005-01-28 00:07:18.000000000 +0100
@@ -1342,7 +1342,11 @@
  */
 static inline u32 xprt_alloc_xid(struct rpc_xprt *xprt)
 {
+#ifdef CONFIG_NET_RANDRPC
+		return (u32) obsd_get_random_long();
+#else
 	return xprt->xid++;
+#endif
 }
 
 static inline void xprt_init_xid(struct rpc_xprt *xprt)

Attachment: signature.asc
Description: Esta parte del mensaje =?ISO-8859-1?Q?est=E1?= firmada digitalmente

Reply via email to