summaryrefslogtreecommitdiff
path: root/lib/random32.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2008-07-31 03:29:19 +0400
committerDavid S. Miller <davem@davemloft.net>2008-07-31 03:29:19 +0400
commit697f8d0348a652593d195a13dd1067d9df911a82 (patch)
tree025da07dad72399662f10d87dbf4d711dd55e766 /lib/random32.c
parent4adf0af6818f3ea52421dc0bae836cfaf20ef72a (diff)
downloadlinux-697f8d0348a652593d195a13dd1067d9df911a82.tar.xz
random32: seeding improvement
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>
Diffstat (limited to 'lib/random32.c')
-rw-r--r--lib/random32.c48
1 files changed, 27 insertions, 21 deletions
diff --git a/lib/random32.c b/lib/random32.c
index ca87d86992bd..217d5c4b666d 100644
--- a/lib/random32.c
+++ b/lib/random32.c
@@ -56,23 +56,12 @@ static u32 __random32(struct rnd_state *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;
}