Re: [PATCH] OpenBSD Networking-related randomization port

From: Lorenzo Hernández García-Hierro
Date: Fri Jan 28 2005 - 17:14:46 EST


El vie, 28-01-2005 a las 21:47 +0100, Arjan van de Ven escribió:
> as for obsd_get_random_long().. would it be possible to use the
> get_random_int() function from the patches I posted the other day? They
> use the existing random.c infrastructure instead of making a copy...

As seen at
http://www.kernel.org/pub/linux/kernel/people/arjan/execshield/00-randomize-A0 you can suppose that there's no point to use that, we can easily maintain the functions at obsd_rand.c so we wouldn't need to add more maintenance overhead, I hope you can understand why I want it like that and not depending on random.c in more than the function exports (which make it even more independent as we don't need to use our proper header and add each proper include entry in the modified files, as most of them use or have already random.h included).

Attached you can find the new patch with the indentation fixes.

The tests on the patch are the following ones:
http://www.osdl.org/plm-cgi/plm?module=patch_info&patch_id=4136
(above one shows that there are no SMP-related issues)
http://khack.osdl.org/stp/300417
http://khack.osdl.org/stp/300420

Cheers and thanks for the information,
--
Lorenzo Hernández García-Hierro <lorenzo@xxxxxxx>
[1024D/6F2B2DEC] & [2048g/9AE91A22][http://tuxedo-es.org]
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-28 19:45:31.359923392 +0100
@@ -42,6 +42,12 @@

#ifdef __KERNEL__

+/* OpenBSD Networking-related randomization functions - lorenzo@xxxxxxx */
+extern unsigned long obsd_get_random_long(void);
+extern __u16 ip_randomid(void);
+extern __u32 ip_randomisn(void);
+
+
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 22:28:24.991105608 +0100
@@ -539,10 +539,7 @@

static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb)
{
- return secure_tcp_sequence_number(skb->nh.iph->daddr,
- skb->nh.iph->saddr,
- skb->h.th->dest,
- skb->h.th->source);
+ return ip_randomisn();
}

/* called with local bh disabled */
@@ -834,13 +830,9 @@
tp->ext2_header_len = rt->u.dst.header_len;

if (!tp->write_seq)
- tp->write_seq = secure_tcp_sequence_number(inet->saddr,
- inet->daddr,
- inet->sport,
- usin->sin_port);
-
- inet->id = tp->write_seq ^ jiffies;
+ tp->write_seq = ip_randomisn();

+ inet->id = htons(ip_randomid());
err = tcp_connect(sk);
rt = NULL;
if (err)
@@ -1566,20 +1555,20 @@
newsk->sk_dst_cache = dst;
tcp_v4_setup_caps(newsk, dst);

- newtp = tcp_sk(newsk);
- newinet = inet_sk(newsk);
- newinet->daddr = req->af.v4_req.rmt_addr;
- newinet->rcv_saddr = req->af.v4_req.loc_addr;
- newinet->saddr = req->af.v4_req.loc_addr;
- newinet->opt = req->af.v4_req.opt;
- req->af.v4_req.opt = NULL;
- newinet->mc_index = tcp_v4_iif(skb);
- newinet->mc_ttl = skb->nh.iph->ttl;
+ newtp = tcp_sk(newsk);
+ newinet = inet_sk(newsk);
+ newinet->daddr = req->af.v4_req.rmt_addr;
+ newinet->rcv_saddr = req->af.v4_req.loc_addr;
+ newinet->saddr = req->af.v4_req.loc_addr;
+ newinet->opt = req->af.v4_req.opt;
+ req->af.v4_req.opt = NULL;
+ newinet->mc_index = tcp_v4_iif(skb);
+ newinet->mc_ttl = skb->nh.iph->ttl;
newtp->ext_header_len = 0;
if (newinet->opt)
newtp->ext_header_len = newinet->opt->optlen;
newtp->ext2_header_len = dst->header_len;
- newinet->id = newtp->write_seq ^ jiffies;
+ newinet->id = htons(ip_randomid());

tcp_sync_mss(newsk, dst_pmtu(dst));
newtp->advmss = dst_metric(dst, RTAX_ADVMSS);

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-28 21:01:21.870140688 +0100
@@ -11,6 +11,7 @@

tmp-$(CONFIG_COMPAT) := compat.o
obj-$(CONFIG_NET) += $(tmp-y)
+obj-y += 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.000000000 +0100
@@ -0,0 +1,269 @@
+/* $Id: openbsd-netrand-2.6.11-rc2.patch,v 1.6 2005/01/28 22:10:30 lorenzo Exp $
+ * Copyright (c) 2005 Lorenzo Hernandez Garcia-Hierro <lorenzo@xxxxxxx>.
+ * 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 <provos@xxxxxxxxxxxxxx>
+ * All rights reserved.
+ * Theo de Raadt <deraadt@xxxxxxxxxxx> 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 22:27:18.644191872 +0100
@@ -1342,7 +1342,7 @@
*/
static inline u32 xprt_alloc_xid(struct rpc_xprt *xprt)
{
- return xprt->xid++;
+ return (u32) obsd_get_random_long();
}

static inline void xprt_init_xid(struct rpc_xprt *xprt)

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