net: Compute protocol sequence numbers and fragment IDs using MD5, CVE-2011-3188
[linux-flexiantxendom0-natty.git] / drivers / char / random.c
index 3823cb2..99924b4 100644 (file)
 #include <linux/fs.h>
 #include <linux/genhd.h>
 #include <linux/interrupt.h>
+#include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <linux/percpu.h>
 #include <linux/cryptohash.h>
+#include <linux/fips.h>
+
+#ifdef CONFIG_GENERIC_HARDIRQS
+# include <linux/irq.h>
+#endif
 
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #define INPUT_POOL_WORDS 128
 #define OUTPUT_POOL_WORDS 32
 #define SEC_XFER_SIZE 512
+#define EXTRACT_SIZE 10
 
 /*
  * The minimum number of bits of entropy before we wake up a read on
@@ -370,6 +377,7 @@ static struct poolinfo {
  */
 static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
 static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
+static struct fasync_struct *fasync;
 
 #if 0
 static int debug;
@@ -399,14 +407,15 @@ struct entropy_store {
        struct poolinfo *poolinfo;
        __u32 *pool;
        const char *name;
-       int limit;
        struct entropy_store *pull;
+       int limit;
 
        /* read-write data: */
        spinlock_t lock;
        unsigned add_ptr;
        int entropy_count;
        int input_rotate;
+       __u8 last_data[EXTRACT_SIZE];
 };
 
 static __u32 input_pool_data[INPUT_POOL_WORDS];
@@ -439,25 +448,26 @@ static struct entropy_store nonblocking_pool = {
 };
 
 /*
- * This function adds a byte into the entropy "pool".  It does not
+ * This function adds bytes into the entropy "pool".  It does not
  * update the entropy estimate.  The caller should call
- * credit_entropy_store if this is appropriate.
+ * credit_entropy_bits if this is appropriate.
  *
  * The pool is stirred with a primitive polynomial of the appropriate
  * degree, and then twisted.  We twist by three bits at a time because
  * it's cheap to do so and helps slightly in the expected case where
  * the entropy is concentrated in the low-order bits.
  */
-static void __add_entropy_words(struct entropy_store *r, const __u32 *in,
-                               int nwords, __u32 out[16])
+static void mix_pool_bytes_extract(struct entropy_store *r, const void *in,
+                                  int nbytes, __u8 out[64])
 {
        static __u32 const twist_table[8] = {
                0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
                0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
-       unsigned long i, add_ptr, tap1, tap2, tap3, tap4, tap5;
+       unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
        int input_rotate;
        int wordmask = r->poolinfo->poolwords - 1;
-       __u32 w, next_w;
+       const char *bytes = in;
+       __u32 w;
        unsigned long flags;
 
        /* Taps are constant, so we can load them without holding r->lock.  */
@@ -466,26 +476,25 @@ static void __add_entropy_words(struct entropy_store *r, const __u32 *in,
        tap3 = r->poolinfo->tap3;
        tap4 = r->poolinfo->tap4;
        tap5 = r->poolinfo->tap5;
-       next_w = *in++;
 
        spin_lock_irqsave(&r->lock, flags);
-       prefetch_range(r->pool, wordmask);
        input_rotate = r->input_rotate;
-       add_ptr = r->add_ptr;
+       i = r->add_ptr;
 
-       while (nwords--) {
-               w = rol32(next_w, input_rotate & 31);
-               if (nwords > 0)
-                       next_w = *in++;
-               i = add_ptr = (add_ptr - 1) & wordmask;
+       /* mix one byte at a time to simplify size handling and churn faster */
+       while (nbytes--) {
+               w = rol32(*bytes++, input_rotate & 31);
+               i = (i - 1) & wordmask;
 
                /* XOR in the various taps */
+               w ^= r->pool[i];
                w ^= r->pool[(i + tap1) & wordmask];
                w ^= r->pool[(i + tap2) & wordmask];
                w ^= r->pool[(i + tap3) & wordmask];
                w ^= r->pool[(i + tap4) & wordmask];
                w ^= r->pool[(i + tap5) & wordmask];
-               w ^= r->pool[i];
+
+               /* Mix the result back in with a twist */
                r->pool[i] = (w >> 3) ^ twist_table[w & 7];
 
                /*
@@ -498,50 +507,48 @@ static void __add_entropy_words(struct entropy_store *r, const __u32 *in,
        }
 
        r->input_rotate = input_rotate;
-       r->add_ptr = add_ptr;
+       r->add_ptr = i;
 
-       if (out) {
-               for (i = 0; i < 16; i++) {
-                       out[i] = r->pool[add_ptr];
-                       add_ptr = (add_ptr - 1) & wordmask;
-               }
-       }
+       if (out)
+               for (j = 0; j < 16; j++)
+                       ((__u32 *)out)[j] = r->pool[(i - j) & wordmask];
 
        spin_unlock_irqrestore(&r->lock, flags);
 }
 
-static inline void add_entropy_words(struct entropy_store *r, const __u32 *in,
-                                    int nwords)
+static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes)
 {
-       __add_entropy_words(r, in, nwords, NULL);
+       mix_pool_bytes_extract(r, in, bytes, NULL);
 }
 
 /*
  * Credit (or debit) the entropy store with n bits of entropy
  */
-static void credit_entropy_store(struct entropy_store *r, int nbits)
+static void credit_entropy_bits(struct entropy_store *r, int nbits)
 {
        unsigned long flags;
+       int entropy_count;
+
+       if (!nbits)
+               return;
 
        spin_lock_irqsave(&r->lock, flags);
 
-       if (r->entropy_count + nbits < 0) {
-               DEBUG_ENT("negative entropy/overflow (%d+%d)\n",
-                         r->entropy_count, nbits);
-               r->entropy_count = 0;
-       } else if (r->entropy_count + nbits > r->poolinfo->POOLBITS) {
-               r->entropy_count = r->poolinfo->POOLBITS;
-       } else {
-               r->entropy_count += nbits;
-               if (nbits)
-                       DEBUG_ENT("added %d entropy credits to %s\n",
-                                 nbits, r->name);
-       }
+       DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
+       entropy_count = r->entropy_count;
+       entropy_count += nbits;
+       if (entropy_count < 0) {
+               DEBUG_ENT("negative entropy/overflow\n");
+               entropy_count = 0;
+       } else if (entropy_count > r->poolinfo->POOLBITS)
+               entropy_count = r->poolinfo->POOLBITS;
+       r->entropy_count = entropy_count;
 
        /* should we wake readers? */
-       if (r == &input_pool && r->entropy_count >= random_read_wakeup_thresh)
+       if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) {
                wake_up_interruptible(&random_read_wait);
-
+               kill_fasync(&fasync, SIGIO, POLL_IN);
+       }
        spin_unlock_irqrestore(&r->lock, flags);
 }
 
@@ -558,9 +565,45 @@ struct timer_rand_state {
        unsigned dont_count_entropy:1;
 };
 
-static struct timer_rand_state input_timer_state;
+#ifndef CONFIG_GENERIC_HARDIRQS
+
 static struct timer_rand_state *irq_timer_state[NR_IRQS];
 
+static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
+{
+       return irq_timer_state[irq];
+}
+
+static void set_timer_rand_state(unsigned int irq,
+                                struct timer_rand_state *state)
+{
+       irq_timer_state[irq] = state;
+}
+
+#else
+
+static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
+{
+       struct irq_desc *desc;
+
+       desc = irq_to_desc(irq);
+
+       return desc->timer_rand_state;
+}
+
+static void set_timer_rand_state(unsigned int irq,
+                                struct timer_rand_state *state)
+{
+       struct irq_desc *desc;
+
+       desc = irq_to_desc(irq);
+
+       desc->timer_rand_state = state;
+}
+#endif
+
+static struct timer_rand_state input_timer_state;
+
 /*
  * This function adds entropy to the entropy "pool" by using timing
  * delays.  It uses the timer_rand_state structure to make an estimate
@@ -583,13 +626,13 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
        preempt_disable();
        /* if over the trickle threshold, use only 1 in 4096 samples */
        if (input_pool.entropy_count > trickle_thresh &&
-           (__get_cpu_var(trickle_count)++ & 0xfff))
+           ((__this_cpu_inc_return(trickle_count) - 1) & 0xfff))
                goto out;
 
        sample.jiffies = jiffies;
        sample.cycles = get_cycles();
        sample.num = num;
-       add_entropy_words(&input_pool, (u32 *)&sample, sizeof(sample)/4);
+       mix_pool_bytes(&input_pool, &sample, sizeof(sample));
 
        /*
         * Calculate number of bits of randomness we probably added.
@@ -623,8 +666,8 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
                 * Round down by 1 bit on general principles,
                 * and limit entropy entimate to 12 bits.
                 */
-               credit_entropy_store(&input_pool,
-                                    min_t(int, fls(delta>>1), 11));
+               credit_entropy_bits(&input_pool,
+                                   min_t(int, fls(delta>>1), 11));
        }
 out:
        preempt_enable();
@@ -648,11 +691,15 @@ EXPORT_SYMBOL_GPL(add_input_randomness);
 
 void add_interrupt_randomness(int irq)
 {
-       if (irq >= NR_IRQS || irq_timer_state[irq] == NULL)
+       struct timer_rand_state *state;
+
+       state = get_timer_rand_state(irq);
+
+       if (state == NULL)
                return;
 
        DEBUG_ENT("irq event %d\n", irq);
-       add_timer_randomness(irq_timer_state[irq], 0x100 + irq);
+       add_timer_randomness(state, 0x100 + irq);
 }
 
 #ifdef CONFIG_BLOCK
@@ -661,15 +708,13 @@ void add_disk_randomness(struct gendisk *disk)
        if (!disk || !disk->random)
                return;
        /* first major is 1, so we get >= 0x200 here */
-       DEBUG_ENT("disk event %d:%d\n", disk->major, disk->first_minor);
+       DEBUG_ENT("disk event %d:%d\n",
+                 MAJOR(disk_devt(disk)), MINOR(disk_devt(disk)));
 
-       add_timer_randomness(disk->random,
-                            0x100 + MKDEV(disk->major, disk->first_minor));
+       add_timer_randomness(disk->random, 0x100 + disk_devt(disk));
 }
 #endif
 
-#define EXTRACT_SIZE 10
-
 /*********************************************************************
  *
  * Entropy extraction routines
@@ -705,8 +750,8 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
 
                bytes = extract_entropy(r->pull, tmp, bytes,
                                        random_read_wakeup_thresh / 8, rsvd);
-               add_entropy_words(r, tmp, (bytes + 3) / 4);
-               credit_entropy_store(r, bytes*8);
+               mix_pool_bytes(r, tmp, bytes);
+               credit_entropy_bits(r, bytes*8);
        }
 }
 
@@ -727,11 +772,10 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
 {
        unsigned long flags;
 
-       BUG_ON(r->entropy_count > r->poolinfo->POOLBITS);
-
        /* Hold lock while accounting */
        spin_lock_irqsave(&r->lock, flags);
 
+       BUG_ON(r->entropy_count > r->poolinfo->POOLBITS);
        DEBUG_ENT("trying to extract %d bits from %s\n",
                  nbytes * 8, r->name);
 
@@ -748,8 +792,10 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
                else
                        r->entropy_count = reserved;
 
-               if (r->entropy_count < random_write_wakeup_thresh)
+               if (r->entropy_count < random_write_wakeup_thresh) {
                        wake_up_interruptible(&random_write_wait);
+                       kill_fasync(&fasync, SIGIO, POLL_OUT);
+               }
        }
 
        DEBUG_ENT("debiting %d entropy credits from %s%s\n",
@@ -763,7 +809,8 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
 static void extract_buf(struct entropy_store *r, __u8 *out)
 {
        int i;
-       __u32 extract[16], hash[5], workspace[SHA_WORKSPACE_WORDS];
+       __u32 hash[5], workspace[SHA_WORKSPACE_WORDS];
+       __u8 extract[64];
 
        /* Generate a hash across the pool, 16 words (512 bits) at a time */
        sha_init(hash);
@@ -779,13 +826,13 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
         * brute-forcing the feedback as hard as brute-forcing the
         * hash.
         */
-       __add_entropy_words(r, hash, 5, extract);
+       mix_pool_bytes_extract(r, hash, sizeof(hash), extract);
 
        /*
         * To avoid duplicates, we atomically extract a portion of the
         * pool while mixing, and hash one final time.
         */
-       sha_transform(hash, (__u8 *)extract, workspace);
+       sha_transform(hash, extract, workspace);
        memset(extract, 0, sizeof(extract));
        memset(workspace, 0, sizeof(workspace));
 
@@ -806,12 +853,21 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
 {
        ssize_t ret = 0, i;
        __u8 tmp[EXTRACT_SIZE];
+       unsigned long flags;
 
        xfer_secondary_pool(r, nbytes);
        nbytes = account(r, nbytes, min, reserved);
 
        while (nbytes) {
                extract_buf(r, tmp);
+
+               if (fips_enabled) {
+                       spin_lock_irqsave(&r->lock, flags);
+                       if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
+                               panic("Hardware RNG duplicated output!\n");
+                       memcpy(r->last_data, tmp, EXTRACT_SIZE);
+                       spin_unlock_irqrestore(&r->lock, flags);
+               }
                i = min_t(int, nbytes, EXTRACT_SIZE);
                memcpy(buf, tmp, i);
                nbytes -= i;
@@ -892,9 +948,8 @@ static void init_std_data(struct entropy_store *r)
        spin_unlock_irqrestore(&r->lock, flags);
 
        now = ktime_get_real();
-       add_entropy_words(r, (__u32 *)&now, sizeof(now)/4);
-       add_entropy_words(r, (__u32 *)utsname(),
-                         sizeof(*(utsname()))/4);
+       mix_pool_bytes(r, &now, sizeof(now));
+       mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
 }
 
 static int rand_initialize(void)
@@ -910,7 +965,9 @@ void rand_initialize_irq(int irq)
 {
        struct timer_rand_state *state;
 
-       if (irq >= NR_IRQS || irq_timer_state[irq])
+       state = get_timer_rand_state(irq);
+
+       if (state)
                return;
 
        /*
@@ -919,7 +976,7 @@ void rand_initialize_irq(int irq)
         */
        state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL);
        if (state)
-               irq_timer_state[irq] = state;
+               set_timer_rand_state(irq, state);
 }
 
 #ifdef CONFIG_BLOCK
@@ -990,12 +1047,6 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
                                /* like a named pipe */
        }
 
-       /*
-        * If we gave the user some bytes, update the access time.
-        */
-       if (count)
-               file_accessed(file);
-
        return (count ? count : retval);
 }
 
@@ -1035,7 +1086,7 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
                count -= bytes;
                p += bytes;
 
-               add_entropy_words(r, buf, (bytes + 3) / 4);
+               mix_pool_bytes(r, buf, bytes);
                cond_resched();
        }
 
@@ -1046,7 +1097,6 @@ static ssize_t random_write(struct file *file, const char __user *buffer,
                            size_t count, loff_t *ppos)
 {
        size_t ret;
-       struct inode *inode = file->f_path.dentry->d_inode;
 
        ret = write_pool(&blocking_pool, buffer, count);
        if (ret)
@@ -1055,8 +1105,6 @@ static ssize_t random_write(struct file *file, const char __user *buffer,
        if (ret)
                return ret;
 
-       inode->i_mtime = current_fs_time(inode->i_sb);
-       mark_inode_dirty(inode);
        return (ssize_t)count;
 }
 
@@ -1077,7 +1125,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
                        return -EPERM;
                if (get_user(ent_count, p))
                        return -EFAULT;
-               credit_entropy_store(&input_pool, ent_count);
+               credit_entropy_bits(&input_pool, ent_count);
                return 0;
        case RNDADDENTROPY:
                if (!capable(CAP_SYS_ADMIN))
@@ -1092,7 +1140,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
                                    size);
                if (retval < 0)
                        return retval;
-               credit_entropy_store(&input_pool, ent_count);
+               credit_entropy_bits(&input_pool, ent_count);
                return 0;
        case RNDZAPENTCNT:
        case RNDCLEARPOOL:
@@ -1106,17 +1154,26 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
        }
 }
 
+static int random_fasync(int fd, struct file *filp, int on)
+{
+       return fasync_helper(fd, filp, on, &fasync);
+}
+
 const struct file_operations random_fops = {
        .read  = random_read,
        .write = random_write,
        .poll  = random_poll,
        .unlocked_ioctl = random_ioctl,
+       .fasync = random_fasync,
+       .llseek = noop_llseek,
 };
 
 const struct file_operations urandom_fops = {
        .read  = urandom_read,
        .write = random_write,
        .unlocked_ioctl = random_ioctl,
+       .fasync = random_fasync,
+       .llseek = noop_llseek,
 };
 
 /***************************************************************
@@ -1132,7 +1189,7 @@ const struct file_operations urandom_fops = {
 void generate_random_uuid(unsigned char uuid_out[16])
 {
        get_random_bytes(uuid_out, 16);
-       /* Set UUID version to 4 --- truely random generation */
+       /* Set UUID version to 4 --- truly random generation */
        uuid_out[6] = (uuid_out[6] & 0x0F) | 0x40;
        /* Set the UUID variant to DCE */
        uuid_out[8] = (uuid_out[8] & 0x3F) | 0x80;
@@ -1163,7 +1220,7 @@ static char sysctl_bootid[16];
  * as an ASCII string in the standard UUID format.  If accesses via the
  * sysctl system call, it is returned as 16 bytes of binary data.
  */
-static int proc_do_uuid(ctl_table *table, int write, struct file *filp,
+static int proc_do_uuid(ctl_table *table, int write,
                        void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        ctl_table fake_table;
@@ -1177,431 +1234,73 @@ static int proc_do_uuid(ctl_table *table, int write, struct file *filp,
        if (uuid[8] == 0)
                generate_random_uuid(uuid);
 
-       sprintf(buf, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
-               "%02x%02x%02x%02x%02x%02x",
-               uuid[0],  uuid[1],  uuid[2],  uuid[3],
-               uuid[4],  uuid[5],  uuid[6],  uuid[7],
-               uuid[8],  uuid[9],  uuid[10], uuid[11],
-               uuid[12], uuid[13], uuid[14], uuid[15]);
+       sprintf(buf, "%pU", uuid);
+
        fake_table.data = buf;
        fake_table.maxlen = sizeof(buf);
 
-       return proc_dostring(&fake_table, write, filp, buffer, lenp, ppos);
-}
-
-static int uuid_strategy(ctl_table *table, int __user *name, int nlen,
-                        void __user *oldval, size_t __user *oldlenp,
-                        void __user *newval, size_t newlen)
-{
-       unsigned char tmp_uuid[16], *uuid;
-       unsigned int len;
-
-       if (!oldval || !oldlenp)
-               return 1;
-
-       uuid = table->data;
-       if (!uuid) {
-               uuid = tmp_uuid;
-               uuid[8] = 0;
-       }
-       if (uuid[8] == 0)
-               generate_random_uuid(uuid);
-
-       if (get_user(len, oldlenp))
-               return -EFAULT;
-       if (len) {
-               if (len > 16)
-                       len = 16;
-               if (copy_to_user(oldval, uuid, len) ||
-                   put_user(len, oldlenp))
-                       return -EFAULT;
-       }
-       return 1;
+       return proc_dostring(&fake_table, write, buffer, lenp, ppos);
 }
 
 static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
 ctl_table random_table[] = {
        {
-               .ctl_name       = RANDOM_POOLSIZE,
                .procname       = "poolsize",
                .data           = &sysctl_poolsize,
                .maxlen         = sizeof(int),
                .mode           = 0444,
-               .proc_handler   = &proc_dointvec,
+               .proc_handler   = proc_dointvec,
        },
        {
-               .ctl_name       = RANDOM_ENTROPY_COUNT,
                .procname       = "entropy_avail",
                .maxlen         = sizeof(int),
                .mode           = 0444,
-               .proc_handler   = &proc_dointvec,
+               .proc_handler   = proc_dointvec,
                .data           = &input_pool.entropy_count,
        },
        {
-               .ctl_name       = RANDOM_READ_THRESH,
                .procname       = "read_wakeup_threshold",
                .data           = &random_read_wakeup_thresh,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = &proc_dointvec_minmax,
-               .strategy       = &sysctl_intvec,
+               .proc_handler   = proc_dointvec_minmax,
                .extra1         = &min_read_thresh,
                .extra2         = &max_read_thresh,
        },
        {
-               .ctl_name       = RANDOM_WRITE_THRESH,
                .procname       = "write_wakeup_threshold",
                .data           = &random_write_wakeup_thresh,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = &proc_dointvec_minmax,
-               .strategy       = &sysctl_intvec,
+               .proc_handler   = proc_dointvec_minmax,
                .extra1         = &min_write_thresh,
                .extra2         = &max_write_thresh,
        },
        {
-               .ctl_name       = RANDOM_BOOT_ID,
                .procname       = "boot_id",
                .data           = &sysctl_bootid,
                .maxlen         = 16,
                .mode           = 0444,
-               .proc_handler   = &proc_do_uuid,
-               .strategy       = &uuid_strategy,
+               .proc_handler   = proc_do_uuid,
        },
        {
-               .ctl_name       = RANDOM_UUID,
                .procname       = "uuid",
                .maxlen         = 16,
                .mode           = 0444,
-               .proc_handler   = &proc_do_uuid,
-               .strategy       = &uuid_strategy,
+               .proc_handler   = proc_do_uuid,
        },
-       { .ctl_name = 0 }
+       { }
 };
 #endif         /* CONFIG_SYSCTL */
 
-/********************************************************************
- *
- * Random funtions for networking
- *
- ********************************************************************/
-
-/*
- * TCP initial sequence number picking.  This uses the random number
- * generator to pick an initial secret value.  This value is hashed
- * along with the TCP endpoint information to provide a unique
- * starting point for each pair of TCP endpoints.  This defeats
- * attacks which rely on guessing the initial TCP sequence number.
- * This algorithm was suggested by Steve Bellovin.
- *
- * Using a very strong hash was taking an appreciable amount of the total
- * TCP connection establishment time, so this is a weaker hash,
- * compensated for by changing the secret periodically.
- */
-
-/* F, G and H are basic MD4 functions: selection, majority, parity */
-#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-
-/*
- * The generic round function.  The application is so specific that
- * we don't bother protecting all the arguments with parens, as is generally
- * good macro practice, in favor of extra legibility.
- * Rotation is separate from addition to prevent recomputation
- */
-#define ROUND(f, a, b, c, d, x, s)     \
-       (a += f(b, c, d) + x, a = (a << s) | (a >> (32 - s)))
-#define K1 0
-#define K2 013240474631UL
-#define K3 015666365641UL
+static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned;
 
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-
-static __u32 twothirdsMD4Transform(__u32 const buf[4], __u32 const in[12])
-{
-       __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
-
-       /* Round 1 */
-       ROUND(F, a, b, c, d, in[ 0] + K1,  3);
-       ROUND(F, d, a, b, c, in[ 1] + K1,  7);
-       ROUND(F, c, d, a, b, in[ 2] + K1, 11);
-       ROUND(F, b, c, d, a, in[ 3] + K1, 19);
-       ROUND(F, a, b, c, d, in[ 4] + K1,  3);
-       ROUND(F, d, a, b, c, in[ 5] + K1,  7);
-       ROUND(F, c, d, a, b, in[ 6] + K1, 11);
-       ROUND(F, b, c, d, a, in[ 7] + K1, 19);
-       ROUND(F, a, b, c, d, in[ 8] + K1,  3);
-       ROUND(F, d, a, b, c, in[ 9] + K1,  7);
-       ROUND(F, c, d, a, b, in[10] + K1, 11);
-       ROUND(F, b, c, d, a, in[11] + K1, 19);
-
-       /* Round 2 */
-       ROUND(G, a, b, c, d, in[ 1] + K2,  3);
-       ROUND(G, d, a, b, c, in[ 3] + K2,  5);
-       ROUND(G, c, d, a, b, in[ 5] + K2,  9);
-       ROUND(G, b, c, d, a, in[ 7] + K2, 13);
-       ROUND(G, a, b, c, d, in[ 9] + K2,  3);
-       ROUND(G, d, a, b, c, in[11] + K2,  5);
-       ROUND(G, c, d, a, b, in[ 0] + K2,  9);
-       ROUND(G, b, c, d, a, in[ 2] + K2, 13);
-       ROUND(G, a, b, c, d, in[ 4] + K2,  3);
-       ROUND(G, d, a, b, c, in[ 6] + K2,  5);
-       ROUND(G, c, d, a, b, in[ 8] + K2,  9);
-       ROUND(G, b, c, d, a, in[10] + K2, 13);
-
-       /* Round 3 */
-       ROUND(H, a, b, c, d, in[ 3] + K3,  3);
-       ROUND(H, d, a, b, c, in[ 7] + K3,  9);
-       ROUND(H, c, d, a, b, in[11] + K3, 11);
-       ROUND(H, b, c, d, a, in[ 2] + K3, 15);
-       ROUND(H, a, b, c, d, in[ 6] + K3,  3);
-       ROUND(H, d, a, b, c, in[10] + K3,  9);
-       ROUND(H, c, d, a, b, in[ 1] + K3, 11);
-       ROUND(H, b, c, d, a, in[ 5] + K3, 15);
-       ROUND(H, a, b, c, d, in[ 9] + K3,  3);
-       ROUND(H, d, a, b, c, in[ 0] + K3,  9);
-       ROUND(H, c, d, a, b, in[ 4] + K3, 11);
-       ROUND(H, b, c, d, a, in[ 8] + K3, 15);
-
-       return buf[1] + b; /* "most hashed" word */
-       /* Alternative: return sum of all words? */
-}
-#endif
-
-#undef ROUND
-#undef F
-#undef G
-#undef H
-#undef K1
-#undef K2
-#undef K3
-
-/* This should not be decreased so low that ISNs wrap too fast. */
-#define REKEY_INTERVAL (300 * HZ)
-/*
- * Bit layout of the tcp sequence numbers (before adding current time):
- * bit 24-31: increased after every key exchange
- * bit 0-23: hash(source,dest)
- *
- * The implementation is similar to the algorithm described
- * in the Appendix of RFC 1185, except that
- * - it uses a 1 MHz clock instead of a 250 kHz clock
- * - it performs a rekey every 5 minutes, which is equivalent
- *     to a (source,dest) tulple dependent forward jump of the
- *     clock by 0..2^(HASH_BITS+1)
- *
- * Thus the average ISN wraparound time is 68 minutes instead of
- * 4.55 hours.
- *
- * SMP cleanup and lock avoidance with poor man's RCU.
- *                     Manfred Spraul <manfred@colorfullife.com>
- *
- */
-#define COUNT_BITS 8
-#define COUNT_MASK ((1 << COUNT_BITS) - 1)
-#define HASH_BITS 24
-#define HASH_MASK ((1 << HASH_BITS) - 1)
-
-static struct keydata {
-       __u32 count; /* already shifted to the final position */
-       __u32 secret[12];
-} ____cacheline_aligned ip_keydata[2];
-
-static unsigned int ip_cnt;
-
-static void rekey_seq_generator(struct work_struct *work);
-
-static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator);
-
-/*
- * Lock avoidance:
- * The ISN generation runs lockless - it's just a hash over random data.
- * State changes happen every 5 minutes when the random key is replaced.
- * Synchronization is performed by having two copies of the hash function
- * state and rekey_seq_generator always updates the inactive copy.
- * The copy is then activated by updating ip_cnt.
- * The implementation breaks down if someone blocks the thread
- * that processes SYN requests for more than 5 minutes. Should never
- * happen, and even if that happens only a not perfectly compliant
- * ISN is generated, nothing fatal.
- */
-static void rekey_seq_generator(struct work_struct *work)
-{
-       struct keydata *keyptr = &ip_keydata[1 ^ (ip_cnt & 1)];
-
-       get_random_bytes(keyptr->secret, sizeof(keyptr->secret));
-       keyptr->count = (ip_cnt & COUNT_MASK) << HASH_BITS;
-       smp_wmb();
-       ip_cnt++;
-       schedule_delayed_work(&rekey_work, REKEY_INTERVAL);
-}
-
-static inline struct keydata *get_keyptr(void)
-{
-       struct keydata *keyptr = &ip_keydata[ip_cnt & 1];
-
-       smp_rmb();
-
-       return keyptr;
-}
-
-static __init int seqgen_init(void)
+static int __init random_int_secret_init(void)
 {
-       rekey_seq_generator(NULL);
+       get_random_bytes(random_int_secret, sizeof(random_int_secret));
        return 0;
 }
-late_initcall(seqgen_init);
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-__u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
-                                  __be16 sport, __be16 dport)
-{
-       __u32 seq;
-       __u32 hash[12];
-       struct keydata *keyptr = get_keyptr();
-
-       /* The procedure is the same as for IPv4, but addresses are longer.
-        * Thus we must use twothirdsMD4Transform.
-        */
-
-       memcpy(hash, saddr, 16);
-       hash[4] = ((__force u16)sport << 16) + (__force u16)dport;
-       memcpy(&hash[5], keyptr->secret, sizeof(__u32) * 7);
-
-       seq = twothirdsMD4Transform((const __u32 *)daddr, hash) & HASH_MASK;
-       seq += keyptr->count;
-
-       seq += ktime_to_ns(ktime_get_real());
-
-       return seq;
-}
-EXPORT_SYMBOL(secure_tcpv6_sequence_number);
-#endif
-
-/*  The code below is shamelessly stolen from secure_tcp_sequence_number().
- *  All blames to Andrey V. Savochkin <saw@msu.ru>.
- */
-__u32 secure_ip_id(__be32 daddr)
-{
-       struct keydata *keyptr;
-       __u32 hash[4];
-
-       keyptr = get_keyptr();
-
-       /*
-        *  Pick a unique starting offset for each IP destination.
-        *  The dest ip address is placed in the starting vector,
-        *  which is then hashed with random data.
-        */
-       hash[0] = (__force __u32)daddr;
-       hash[1] = keyptr->secret[9];
-       hash[2] = keyptr->secret[10];
-       hash[3] = keyptr->secret[11];
-
-       return half_md4_transform(hash, keyptr->secret);
-}
-
-#ifdef CONFIG_INET
-
-__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
-                                __be16 sport, __be16 dport)
-{
-       __u32 seq;
-       __u32 hash[4];
-       struct keydata *keyptr = get_keyptr();
-
-       /*
-        *  Pick a unique starting offset for each TCP connection endpoints
-        *  (saddr, daddr, sport, dport).
-        *  Note that the words are placed into the starting vector, which is
-        *  then mixed with a partial MD4 over random data.
-        */
-       hash[0] = (__force u32)saddr;
-       hash[1] = (__force u32)daddr;
-       hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
-       hash[3] = keyptr->secret[11];
-
-       seq = half_md4_transform(hash, keyptr->secret) & HASH_MASK;
-       seq += keyptr->count;
-       /*
-        *      As close as possible to RFC 793, which
-        *      suggests using a 250 kHz clock.
-        *      Further reading shows this assumes 2 Mb/s networks.
-        *      For 10 Mb/s Ethernet, a 1 MHz clock is appropriate.
-        *      For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but
-        *      we also need to limit the resolution so that the u32 seq
-        *      overlaps less than one time per MSL (2 minutes).
-        *      Choosing a clock of 64 ns period is OK. (period of 274 s)
-        */
-       seq += ktime_to_ns(ktime_get_real()) >> 6;
-
-       return seq;
-}
-
-/* Generate secure starting point for ephemeral IPV4 transport port search */
-u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
-{
-       struct keydata *keyptr = get_keyptr();
-       u32 hash[4];
-
-       /*
-        *  Pick a unique starting offset for each ephemeral port search
-        *  (saddr, daddr, dport) and 48bits of random data.
-        */
-       hash[0] = (__force u32)saddr;
-       hash[1] = (__force u32)daddr;
-       hash[2] = (__force u32)dport ^ keyptr->secret[10];
-       hash[3] = keyptr->secret[11];
-
-       return half_md4_transform(hash, keyptr->secret);
-}
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
-                              __be16 dport)
-{
-       struct keydata *keyptr = get_keyptr();
-       u32 hash[12];
-
-       memcpy(hash, saddr, 16);
-       hash[4] = (__force u32)dport;
-       memcpy(&hash[5], keyptr->secret, sizeof(__u32) * 7);
-
-       return twothirdsMD4Transform((const __u32 *)daddr, hash);
-}
-#endif
-
-#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
-/* Similar to secure_tcp_sequence_number but generate a 48 bit value
- * bit's 32-47 increase every key exchange
- *       0-31  hash(source, dest)
- */
-u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
-                               __be16 sport, __be16 dport)
-{
-       u64 seq;
-       __u32 hash[4];
-       struct keydata *keyptr = get_keyptr();
-
-       hash[0] = (__force u32)saddr;
-       hash[1] = (__force u32)daddr;
-       hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
-       hash[3] = keyptr->secret[11];
-
-       seq = half_md4_transform(hash, keyptr->secret);
-       seq |= ((u64)keyptr->count) << (32 - HASH_BITS);
-
-       seq += ktime_to_ns(ktime_get_real());
-       seq &= (1ull << 48) - 1;
-
-       return seq;
-}
-EXPORT_SYMBOL(secure_dccp_sequence_number);
-#endif
-
-#endif /* CONFIG_INET */
-
+late_initcall(random_int_secret_init);
 
 /*
  * Get a random word for internal kernel use only. Similar to urandom but
@@ -1609,15 +1308,18 @@ EXPORT_SYMBOL(secure_dccp_sequence_number);
  * value is not cryptographically secure but for several uses the cost of
  * depleting entropy is too high
  */
+DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
 unsigned int get_random_int(void)
 {
-       /*
-        * Use IP's RNG. It suits our purpose perfectly: it re-keys itself
-        * every second, from the entropy pool (and thus creates a limited
-        * drain on it), and uses halfMD4Transform within the second. We
-        * also mix it with jiffies and the PID:
-        */
-       return secure_ip_id((__force __be32)(current->pid + jiffies));
+       __u32 *hash = get_cpu_var(get_random_int_hash);
+       unsigned int ret;
+
+       hash[0] += current->pid + jiffies + get_cycles();
+       md5_transform(hash, random_int_secret);
+       ret = hash[0];
+       put_cpu_var(get_random_int_hash);
+
+       return ret;
 }
 
 /*