diff options
author | Stephen Hemminger <shemminger@vyatta.com> | 2008-07-30 19:29:19 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-30 19:29:19 -0400 |
commit | 697f8d0348a652593d195a13dd1067d9df911a82 (patch) | |
tree | 025da07dad72399662f10d87dbf4d711dd55e766 /lib/random32.c | |
parent | 4adf0af6818f3ea52421dc0bae836cfaf20ef72a (diff) |
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.c | 48 |
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) | |||
56 | return (state->s1 ^ state->s2 ^ state->s3); | 56 | return (state->s1 ^ state->s2 ^ state->s3); |
57 | } | 57 | } |
58 | 58 | ||
59 | static void __set_random32(struct rnd_state *state, unsigned long s) | 59 | /* |
60 | * Handle minimum values for seeds | ||
61 | */ | ||
62 | static inline u32 __seed(u32 x, u32 m) | ||
60 | { | 63 | { |
61 | if (s == 0) | 64 | return (x < m) ? x + m : x; |
62 | s = 1; /* default seed is 1 */ | ||
63 | |||
64 | #define LCG(n) (69069 * n) | ||
65 | state->s1 = LCG(s); | ||
66 | state->s2 = LCG(state->s1); | ||
67 | state->s3 = LCG(state->s2); | ||
68 | |||
69 | /* "warm it up" */ | ||
70 | __random32(state); | ||
71 | __random32(state); | ||
72 | __random32(state); | ||
73 | __random32(state); | ||
74 | __random32(state); | ||
75 | __random32(state); | ||
76 | } | 65 | } |
77 | 66 | ||
78 | /** | 67 | /** |
@@ -107,7 +96,7 @@ void srandom32(u32 entropy) | |||
107 | */ | 96 | */ |
108 | for_each_possible_cpu (i) { | 97 | for_each_possible_cpu (i) { |
109 | struct rnd_state *state = &per_cpu(net_rand_state, i); | 98 | struct rnd_state *state = &per_cpu(net_rand_state, i); |
110 | __set_random32(state, state->s1 ^ entropy); | 99 | state->s1 = __seed(state->s1 ^ entropy, 1); |
111 | } | 100 | } |
112 | } | 101 | } |
113 | EXPORT_SYMBOL(srandom32); | 102 | EXPORT_SYMBOL(srandom32); |
@@ -122,7 +111,19 @@ static int __init random32_init(void) | |||
122 | 111 | ||
123 | for_each_possible_cpu(i) { | 112 | for_each_possible_cpu(i) { |
124 | struct rnd_state *state = &per_cpu(net_rand_state,i); | 113 | struct rnd_state *state = &per_cpu(net_rand_state,i); |
125 | __set_random32(state, i + jiffies); | 114 | |
115 | #define LCG(x) ((x) * 69069) /* super-duper LCG */ | ||
116 | state->s1 = __seed(LCG(i + jiffies), 1); | ||
117 | state->s2 = __seed(LCG(state->s1), 7); | ||
118 | state->s3 = __seed(LCG(state->s2), 15); | ||
119 | |||
120 | /* "warm it up" */ | ||
121 | __random32(state); | ||
122 | __random32(state); | ||
123 | __random32(state); | ||
124 | __random32(state); | ||
125 | __random32(state); | ||
126 | __random32(state); | ||
126 | } | 127 | } |
127 | return 0; | 128 | return 0; |
128 | } | 129 | } |
@@ -135,13 +136,18 @@ core_initcall(random32_init); | |||
135 | static int __init random32_reseed(void) | 136 | static int __init random32_reseed(void) |
136 | { | 137 | { |
137 | int i; | 138 | int i; |
138 | unsigned long seed; | ||
139 | 139 | ||
140 | for_each_possible_cpu(i) { | 140 | for_each_possible_cpu(i) { |
141 | struct rnd_state *state = &per_cpu(net_rand_state,i); | 141 | struct rnd_state *state = &per_cpu(net_rand_state,i); |
142 | u32 seeds[3]; | ||
143 | |||
144 | get_random_bytes(&seeds, sizeof(seeds)); | ||
145 | state->s1 = __seed(seeds[0], 1); | ||
146 | state->s2 = __seed(seeds[1], 7); | ||
147 | state->s3 = __seed(seeds[2], 15); | ||
142 | 148 | ||
143 | get_random_bytes(&seed, sizeof(seed)); | 149 | /* mix it in */ |
144 | __set_random32(state, seed); | 150 | __random32(state); |
145 | } | 151 | } |
146 | return 0; | 152 | return 0; |
147 | } | 153 | } |