lkml.org 
[lkml]   [2005]   [Jan]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH] OpenBSD Networking-related randomization port
    From
    Date
    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/tcp_ipv4.c@1.105?nav=index.html|src/|src/net|src/net/ipv4|hist/net/ipv4/tcp_ipv4.c
    (net/ipv4/tcp_ipv4.c@1.105)

    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 <lorenzo@gnu.org>
    [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
    + <lorenzo@gnu.org>.
    + 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 <lorenzo@gnu.org>.
    + * 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@citi.umich.edu>
    + * All rights reserved.
    + * Theo de Raadt <deraadt@openbsd.org> 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)[unhandled content-type:application/pgp-signature]
    \
     
     \ /
      Last update: 2005-03-22 14:09    [W:0.050 / U:0.560 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site