| From d2bba9e964229e9141f4a3428d0981bd407b14bb Mon Sep 17 00:00:00 2001 |
| From: Stephen Hemminger <shemminger@vyatta.com> |
| Date: Wed, 30 Jul 2008 16:29:19 -0700 |
| Subject: random32: seeding improvement |
| Message-Id: <20080805.164907.110850052.davem@davemloft.net> |
| |
| From: Stephen Hemminger <shemminger@vyatta.com> |
| |
| [ Upstream commit 697f8d0348a652593d195a13dd1067d9df911a82 ] |
| |
| The rationale is: |
| * use u32 consistently |
| * no need to do LCG on values from (better) get_random_bytes |
| * use more data from get_random_bytes for secondary seeding |
| * don't reduce state space on srandom32() |
| * enforce state variable initialization restrictions |
| |
| Note: the second paper has a version of random32() with even longer period |
| and a version of random64() if needed. |
| |
| Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Cc: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| lib/random32.c | 48 +++++++++++++++++++++++++++--------------------- |
| 1 file changed, 27 insertions(+), 21 deletions(-) |
| |
| --- a/lib/random32.c |
| +++ b/lib/random32.c |
| @@ -56,23 +56,12 @@ static u32 __random32(struct rnd_state * |
| return (state->s1 ^ state->s2 ^ state->s3); |
| } |
| |
| -static void __set_random32(struct rnd_state *state, unsigned long s) |
| +/* |
| + * Handle minimum values for seeds |
| + */ |
| +static inline u32 __seed(u32 x, u32 m) |
| { |
| - if (s == 0) |
| - s = 1; /* default seed is 1 */ |
| - |
| -#define LCG(n) (69069 * n) |
| - state->s1 = LCG(s); |
| - state->s2 = LCG(state->s1); |
| - state->s3 = LCG(state->s2); |
| - |
| - /* "warm it up" */ |
| - __random32(state); |
| - __random32(state); |
| - __random32(state); |
| - __random32(state); |
| - __random32(state); |
| - __random32(state); |
| + return (x < m) ? x + m : x; |
| } |
| |
| /** |
| @@ -107,7 +96,7 @@ void srandom32(u32 entropy) |
| */ |
| for_each_possible_cpu (i) { |
| struct rnd_state *state = &per_cpu(net_rand_state, i); |
| - __set_random32(state, state->s1 ^ entropy); |
| + state->s1 = __seed(state->s1 ^ entropy, 1); |
| } |
| } |
| EXPORT_SYMBOL(srandom32); |
| @@ -122,7 +111,19 @@ static int __init random32_init(void) |
| |
| for_each_possible_cpu(i) { |
| struct rnd_state *state = &per_cpu(net_rand_state,i); |
| - __set_random32(state, i + jiffies); |
| + |
| +#define LCG(x) ((x) * 69069) /* super-duper LCG */ |
| + state->s1 = __seed(LCG(i + jiffies), 1); |
| + state->s2 = __seed(LCG(state->s1), 7); |
| + state->s3 = __seed(LCG(state->s2), 15); |
| + |
| + /* "warm it up" */ |
| + __random32(state); |
| + __random32(state); |
| + __random32(state); |
| + __random32(state); |
| + __random32(state); |
| + __random32(state); |
| } |
| return 0; |
| } |
| @@ -135,13 +136,18 @@ core_initcall(random32_init); |
| static int __init random32_reseed(void) |
| { |
| int i; |
| - unsigned long seed; |
| |
| for_each_possible_cpu(i) { |
| struct rnd_state *state = &per_cpu(net_rand_state,i); |
| + u32 seeds[3]; |
| + |
| + get_random_bytes(&seeds, sizeof(seeds)); |
| + state->s1 = __seed(seeds[0], 1); |
| + state->s2 = __seed(seeds[1], 7); |
| + state->s3 = __seed(seeds[2], 15); |
| |
| - get_random_bytes(&seed, sizeof(seed)); |
| - __set_random32(state, seed); |
| + /* mix it in */ |
| + __random32(state); |
| } |
| return 0; |
| } |