2006-10-17 11:09:42 +04:00
|
|
|
/*
|
|
|
|
This is a maximally equidistributed combined Tausworthe generator
|
|
|
|
based on code from GNU Scientific Library 1.5 (30 Jun 2004)
|
|
|
|
|
|
|
|
x_n = (s1_n ^ s2_n ^ s3_n)
|
|
|
|
|
|
|
|
s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
|
|
|
|
s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
|
|
|
|
s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
|
|
|
|
|
|
|
|
The period of this generator is about 2^88.
|
|
|
|
|
|
|
|
From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe
|
|
|
|
Generators", Mathematics of Computation, 65, 213 (1996), 203--213.
|
|
|
|
|
|
|
|
This is available on the net from L'Ecuyer's home page,
|
|
|
|
|
|
|
|
http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
|
|
|
|
ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps
|
|
|
|
|
|
|
|
There is an erratum in the paper "Tables of Maximally
|
|
|
|
Equidistributed Combined LFSR Generators", Mathematics of
|
|
|
|
Computation, 68, 225 (1999), 261--269:
|
|
|
|
http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
|
|
|
|
|
|
|
|
... the k_j most significant bits of z_j must be non-
|
|
|
|
zero, for each j. (Note: this restriction also applies to the
|
|
|
|
computer code given in [4], but was mistakenly not mentioned in
|
|
|
|
that paper.)
|
|
|
|
|
|
|
|
This affects the seeding procedure by imposing the requirement
|
|
|
|
s1 > 1, s2 > 7, s3 > 15.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/types.h>
|
|
|
|
#include <linux/percpu.h>
|
2011-11-17 06:29:17 +04:00
|
|
|
#include <linux/export.h>
|
2006-10-18 09:47:25 +04:00
|
|
|
#include <linux/jiffies.h>
|
2006-10-17 11:09:42 +04:00
|
|
|
#include <linux/random.h>
|
|
|
|
|
|
|
|
static DEFINE_PER_CPU(struct rnd_state, net_rand_state);
|
|
|
|
|
2010-05-27 01:44:13 +04:00
|
|
|
/**
|
2012-12-18 04:04:23 +04:00
|
|
|
* prandom_u32_state - seeded pseudo-random number generator.
|
2010-05-27 01:44:13 +04:00
|
|
|
* @state: pointer to state structure holding seeded state.
|
|
|
|
*
|
|
|
|
* This is used for pseudo-randomness with no outside seeding.
|
2012-12-18 04:04:23 +04:00
|
|
|
* For more random results, use prandom_u32().
|
2010-05-27 01:44:13 +04:00
|
|
|
*/
|
2012-12-18 04:04:23 +04:00
|
|
|
u32 prandom_u32_state(struct rnd_state *state)
|
2006-10-17 11:09:42 +04:00
|
|
|
{
|
|
|
|
#define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b)
|
|
|
|
|
|
|
|
state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12);
|
|
|
|
state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4);
|
|
|
|
state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17);
|
|
|
|
|
|
|
|
return (state->s1 ^ state->s2 ^ state->s3);
|
|
|
|
}
|
2012-12-18 04:04:23 +04:00
|
|
|
EXPORT_SYMBOL(prandom_u32_state);
|
2006-10-17 11:09:42 +04:00
|
|
|
|
|
|
|
/**
|
2012-12-18 04:04:23 +04:00
|
|
|
* prandom_u32 - pseudo random number generator
|
2006-10-17 11:09:42 +04:00
|
|
|
*
|
|
|
|
* A 32 bit pseudo-random number is generated using a fast
|
|
|
|
* algorithm suitable for simulation. This algorithm is NOT
|
|
|
|
* considered safe for cryptographic use.
|
|
|
|
*/
|
2012-12-18 04:04:23 +04:00
|
|
|
u32 prandom_u32(void)
|
2006-10-17 11:09:42 +04:00
|
|
|
{
|
|
|
|
unsigned long r;
|
|
|
|
struct rnd_state *state = &get_cpu_var(net_rand_state);
|
2012-12-18 04:04:23 +04:00
|
|
|
r = prandom_u32_state(state);
|
2006-10-17 11:09:42 +04:00
|
|
|
put_cpu_var(state);
|
|
|
|
return r;
|
|
|
|
}
|
2012-12-18 04:04:23 +04:00
|
|
|
EXPORT_SYMBOL(prandom_u32);
|
2006-10-17 11:09:42 +04:00
|
|
|
|
2012-12-18 04:04:25 +04:00
|
|
|
/*
|
|
|
|
* prandom_bytes_state - get the requested number of pseudo-random bytes
|
|
|
|
*
|
|
|
|
* @state: pointer to state structure holding seeded state.
|
|
|
|
* @buf: where to copy the pseudo-random bytes to
|
|
|
|
* @bytes: the requested number of bytes
|
|
|
|
*
|
|
|
|
* This is used for pseudo-randomness with no outside seeding.
|
|
|
|
* For more random results, use prandom_bytes().
|
|
|
|
*/
|
|
|
|
void prandom_bytes_state(struct rnd_state *state, void *buf, int bytes)
|
|
|
|
{
|
|
|
|
unsigned char *p = buf;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < round_down(bytes, sizeof(u32)); i += sizeof(u32)) {
|
|
|
|
u32 random = prandom_u32_state(state);
|
|
|
|
int j;
|
|
|
|
|
|
|
|
for (j = 0; j < sizeof(u32); j++) {
|
|
|
|
p[i + j] = random;
|
|
|
|
random >>= BITS_PER_BYTE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i < bytes) {
|
|
|
|
u32 random = prandom_u32_state(state);
|
|
|
|
|
|
|
|
for (; i < bytes; i++) {
|
|
|
|
p[i] = random;
|
|
|
|
random >>= BITS_PER_BYTE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(prandom_bytes_state);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* prandom_bytes - get the requested number of pseudo-random bytes
|
|
|
|
* @buf: where to copy the pseudo-random bytes to
|
|
|
|
* @bytes: the requested number of bytes
|
|
|
|
*/
|
|
|
|
void prandom_bytes(void *buf, int bytes)
|
|
|
|
{
|
|
|
|
struct rnd_state *state = &get_cpu_var(net_rand_state);
|
|
|
|
|
|
|
|
prandom_bytes_state(state, buf, bytes);
|
|
|
|
put_cpu_var(state);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(prandom_bytes);
|
|
|
|
|
2006-10-17 11:09:42 +04:00
|
|
|
/**
|
2012-12-18 04:04:23 +04:00
|
|
|
* prandom_seed - add entropy to pseudo random number generator
|
2006-10-17 11:09:42 +04:00
|
|
|
* @seed: seed value
|
|
|
|
*
|
2012-12-18 04:04:23 +04:00
|
|
|
* Add some additional seeding to the prandom pool.
|
2006-10-17 11:09:42 +04:00
|
|
|
*/
|
2012-12-18 04:04:23 +04:00
|
|
|
void prandom_seed(u32 entropy)
|
2006-10-17 11:09:42 +04:00
|
|
|
{
|
2008-04-04 01:07:02 +04:00
|
|
|
int i;
|
|
|
|
/*
|
|
|
|
* No locking on the CPUs, but then somewhat random results are, well,
|
|
|
|
* expected.
|
|
|
|
*/
|
|
|
|
for_each_possible_cpu (i) {
|
|
|
|
struct rnd_state *state = &per_cpu(net_rand_state, i);
|
random32: fix off-by-one in seeding requirement
For properly initialising the Tausworthe generator [1], we have
a strict seeding requirement, that is, s1 > 1, s2 > 7, s3 > 15.
Commit 697f8d0348 ("random32: seeding improvement") introduced
a __seed() function that imposes boundary checks proposed by the
errata paper [2] to properly ensure above conditions.
However, we're off by one, as the function is implemented as:
"return (x < m) ? x + m : x;", and called with __seed(X, 1),
__seed(X, 7), __seed(X, 15). Thus, an unwanted seed of 1, 7, 15
would be possible, whereas the lower boundary should actually
be of at least 2, 8, 16, just as GSL does. Fix this, as otherwise
an initialization with an unwanted seed could have the effect
that Tausworthe's PRNG properties cannot not be ensured.
Note that this PRNG is *not* used for cryptography in the kernel.
[1] http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
[2] http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
Joint work with Hannes Frederic Sowa.
Fixes: 697f8d0348a6 ("random32: seeding improvement")
Cc: Stephen Hemminger <stephen@networkplumber.org>
Cc: Florian Weimer <fweimer@redhat.com>
Cc: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2013-11-11 15:20:32 +04:00
|
|
|
state->s1 = __seed(state->s1 ^ entropy, 2);
|
2013-11-11 15:20:33 +04:00
|
|
|
prandom_u32_state(state);
|
2008-04-04 01:07:02 +04:00
|
|
|
}
|
2006-10-17 11:09:42 +04:00
|
|
|
}
|
2012-12-18 04:04:23 +04:00
|
|
|
EXPORT_SYMBOL(prandom_seed);
|
2006-10-17 11:09:42 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Generate some initially weak seeding values to allow
|
2012-12-18 04:04:23 +04:00
|
|
|
* to start the prandom_u32() engine.
|
2006-10-17 11:09:42 +04:00
|
|
|
*/
|
2012-12-18 04:04:23 +04:00
|
|
|
static int __init prandom_init(void)
|
2006-10-17 11:09:42 +04:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for_each_possible_cpu(i) {
|
|
|
|
struct rnd_state *state = &per_cpu(net_rand_state,i);
|
2008-07-31 03:29:19 +04:00
|
|
|
|
|
|
|
#define LCG(x) ((x) * 69069) /* super-duper LCG */
|
random32: fix off-by-one in seeding requirement
For properly initialising the Tausworthe generator [1], we have
a strict seeding requirement, that is, s1 > 1, s2 > 7, s3 > 15.
Commit 697f8d0348 ("random32: seeding improvement") introduced
a __seed() function that imposes boundary checks proposed by the
errata paper [2] to properly ensure above conditions.
However, we're off by one, as the function is implemented as:
"return (x < m) ? x + m : x;", and called with __seed(X, 1),
__seed(X, 7), __seed(X, 15). Thus, an unwanted seed of 1, 7, 15
would be possible, whereas the lower boundary should actually
be of at least 2, 8, 16, just as GSL does. Fix this, as otherwise
an initialization with an unwanted seed could have the effect
that Tausworthe's PRNG properties cannot not be ensured.
Note that this PRNG is *not* used for cryptography in the kernel.
[1] http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
[2] http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
Joint work with Hannes Frederic Sowa.
Fixes: 697f8d0348a6 ("random32: seeding improvement")
Cc: Stephen Hemminger <stephen@networkplumber.org>
Cc: Florian Weimer <fweimer@redhat.com>
Cc: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2013-11-11 15:20:32 +04:00
|
|
|
state->s1 = __seed(LCG(i + jiffies), 2);
|
|
|
|
state->s2 = __seed(LCG(state->s1), 8);
|
|
|
|
state->s3 = __seed(LCG(state->s2), 16);
|
2008-07-31 03:29:19 +04:00
|
|
|
|
|
|
|
/* "warm it up" */
|
2012-12-18 04:04:23 +04:00
|
|
|
prandom_u32_state(state);
|
|
|
|
prandom_u32_state(state);
|
|
|
|
prandom_u32_state(state);
|
|
|
|
prandom_u32_state(state);
|
|
|
|
prandom_u32_state(state);
|
|
|
|
prandom_u32_state(state);
|
2006-10-17 11:09:42 +04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2012-12-18 04:04:23 +04:00
|
|
|
core_initcall(prandom_init);
|
2006-10-17 11:09:42 +04:00
|
|
|
|
2013-11-11 15:20:33 +04:00
|
|
|
static void __prandom_timer(unsigned long dontcare);
|
|
|
|
static DEFINE_TIMER(seed_timer, __prandom_timer, 0, 0);
|
|
|
|
|
|
|
|
static void __prandom_timer(unsigned long dontcare)
|
|
|
|
{
|
|
|
|
u32 entropy;
|
|
|
|
|
|
|
|
get_random_bytes(&entropy, sizeof(entropy));
|
|
|
|
prandom_seed(entropy);
|
|
|
|
/* reseed every ~60 seconds, in [40 .. 80) interval with slack */
|
|
|
|
seed_timer.expires = jiffies + (40 * HZ + (prandom_u32() % (40 * HZ)));
|
|
|
|
add_timer(&seed_timer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void prandom_start_seed_timer(void)
|
|
|
|
{
|
|
|
|
set_timer_slack(&seed_timer, HZ);
|
|
|
|
seed_timer.expires = jiffies + 40 * HZ;
|
|
|
|
add_timer(&seed_timer);
|
|
|
|
}
|
|
|
|
|
2006-10-17 11:09:42 +04:00
|
|
|
/*
|
|
|
|
* Generate better values after random number generator
|
2010-06-11 14:17:00 +04:00
|
|
|
* is fully initialized.
|
2006-10-17 11:09:42 +04:00
|
|
|
*/
|
2012-12-18 04:04:23 +04:00
|
|
|
static int __init prandom_reseed(void)
|
2006-10-17 11:09:42 +04:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for_each_possible_cpu(i) {
|
|
|
|
struct rnd_state *state = &per_cpu(net_rand_state,i);
|
2008-07-31 03:29:19 +04:00
|
|
|
u32 seeds[3];
|
|
|
|
|
|
|
|
get_random_bytes(&seeds, sizeof(seeds));
|
random32: fix off-by-one in seeding requirement
For properly initialising the Tausworthe generator [1], we have
a strict seeding requirement, that is, s1 > 1, s2 > 7, s3 > 15.
Commit 697f8d0348 ("random32: seeding improvement") introduced
a __seed() function that imposes boundary checks proposed by the
errata paper [2] to properly ensure above conditions.
However, we're off by one, as the function is implemented as:
"return (x < m) ? x + m : x;", and called with __seed(X, 1),
__seed(X, 7), __seed(X, 15). Thus, an unwanted seed of 1, 7, 15
would be possible, whereas the lower boundary should actually
be of at least 2, 8, 16, just as GSL does. Fix this, as otherwise
an initialization with an unwanted seed could have the effect
that Tausworthe's PRNG properties cannot not be ensured.
Note that this PRNG is *not* used for cryptography in the kernel.
[1] http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
[2] http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
Joint work with Hannes Frederic Sowa.
Fixes: 697f8d0348a6 ("random32: seeding improvement")
Cc: Stephen Hemminger <stephen@networkplumber.org>
Cc: Florian Weimer <fweimer@redhat.com>
Cc: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2013-11-11 15:20:32 +04:00
|
|
|
state->s1 = __seed(seeds[0], 2);
|
|
|
|
state->s2 = __seed(seeds[1], 8);
|
|
|
|
state->s3 = __seed(seeds[2], 16);
|
2006-10-17 11:09:42 +04:00
|
|
|
|
2008-07-31 03:29:19 +04:00
|
|
|
/* mix it in */
|
2012-12-18 04:04:23 +04:00
|
|
|
prandom_u32_state(state);
|
2006-10-17 11:09:42 +04:00
|
|
|
}
|
2013-11-11 15:20:33 +04:00
|
|
|
prandom_start_seed_timer();
|
2006-10-17 11:09:42 +04:00
|
|
|
return 0;
|
|
|
|
}
|
2012-12-18 04:04:23 +04:00
|
|
|
late_initcall(prandom_reseed);
|