diff options
Diffstat (limited to 'lib/random32.c')
-rw-r--r-- | lib/random32.c | 86 |
1 files changed, 45 insertions, 41 deletions
diff --git a/lib/random32.c b/lib/random32.c index fa5da61ce7ad..0bee183fa18f 100644 --- a/lib/random32.c +++ b/lib/random32.c | |||
@@ -37,9 +37,14 @@ | |||
37 | #include <linux/jiffies.h> | 37 | #include <linux/jiffies.h> |
38 | #include <linux/random.h> | 38 | #include <linux/random.h> |
39 | #include <linux/sched.h> | 39 | #include <linux/sched.h> |
40 | #include <asm/unaligned.h> | ||
40 | 41 | ||
41 | #ifdef CONFIG_RANDOM32_SELFTEST | 42 | #ifdef CONFIG_RANDOM32_SELFTEST |
42 | static void __init prandom_state_selftest(void); | 43 | static void __init prandom_state_selftest(void); |
44 | #else | ||
45 | static inline void prandom_state_selftest(void) | ||
46 | { | ||
47 | } | ||
43 | #endif | 48 | #endif |
44 | 49 | ||
45 | static DEFINE_PER_CPU(struct rnd_state, net_rand_state); | 50 | static DEFINE_PER_CPU(struct rnd_state, net_rand_state); |
@@ -53,8 +58,7 @@ static DEFINE_PER_CPU(struct rnd_state, net_rand_state); | |||
53 | */ | 58 | */ |
54 | u32 prandom_u32_state(struct rnd_state *state) | 59 | u32 prandom_u32_state(struct rnd_state *state) |
55 | { | 60 | { |
56 | #define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b) | 61 | #define TAUSWORTHE(s, a, b, c, d) ((s & c) << d) ^ (((s << a) ^ s) >> b) |
57 | |||
58 | state->s1 = TAUSWORTHE(state->s1, 6U, 13U, 4294967294U, 18U); | 62 | state->s1 = TAUSWORTHE(state->s1, 6U, 13U, 4294967294U, 18U); |
59 | state->s2 = TAUSWORTHE(state->s2, 2U, 27U, 4294967288U, 2U); | 63 | state->s2 = TAUSWORTHE(state->s2, 2U, 27U, 4294967288U, 2U); |
60 | state->s3 = TAUSWORTHE(state->s3, 13U, 21U, 4294967280U, 7U); | 64 | state->s3 = TAUSWORTHE(state->s3, 13U, 21U, 4294967280U, 7U); |
@@ -93,27 +97,23 @@ EXPORT_SYMBOL(prandom_u32); | |||
93 | * This is used for pseudo-randomness with no outside seeding. | 97 | * This is used for pseudo-randomness with no outside seeding. |
94 | * For more random results, use prandom_bytes(). | 98 | * For more random results, use prandom_bytes(). |
95 | */ | 99 | */ |
96 | void prandom_bytes_state(struct rnd_state *state, void *buf, int bytes) | 100 | void prandom_bytes_state(struct rnd_state *state, void *buf, size_t bytes) |
97 | { | 101 | { |
98 | unsigned char *p = buf; | 102 | u8 *ptr = buf; |
99 | int i; | ||
100 | 103 | ||
101 | for (i = 0; i < round_down(bytes, sizeof(u32)); i += sizeof(u32)) { | 104 | while (bytes >= sizeof(u32)) { |
102 | u32 random = prandom_u32_state(state); | 105 | put_unaligned(prandom_u32_state(state), (u32 *) ptr); |
103 | int j; | 106 | ptr += sizeof(u32); |
104 | 107 | bytes -= sizeof(u32); | |
105 | for (j = 0; j < sizeof(u32); j++) { | ||
106 | p[i + j] = random; | ||
107 | random >>= BITS_PER_BYTE; | ||
108 | } | ||
109 | } | 108 | } |
110 | if (i < bytes) { | ||
111 | u32 random = prandom_u32_state(state); | ||
112 | 109 | ||
113 | for (; i < bytes; i++) { | 110 | if (bytes > 0) { |
114 | p[i] = random; | 111 | u32 rem = prandom_u32_state(state); |
115 | random >>= BITS_PER_BYTE; | 112 | do { |
116 | } | 113 | *ptr++ = (u8) rem; |
114 | bytes--; | ||
115 | rem >>= BITS_PER_BYTE; | ||
116 | } while (bytes > 0); | ||
117 | } | 117 | } |
118 | } | 118 | } |
119 | EXPORT_SYMBOL(prandom_bytes_state); | 119 | EXPORT_SYMBOL(prandom_bytes_state); |
@@ -123,7 +123,7 @@ EXPORT_SYMBOL(prandom_bytes_state); | |||
123 | * @buf: where to copy the pseudo-random bytes to | 123 | * @buf: where to copy the pseudo-random bytes to |
124 | * @bytes: the requested number of bytes | 124 | * @bytes: the requested number of bytes |
125 | */ | 125 | */ |
126 | void prandom_bytes(void *buf, int bytes) | 126 | void prandom_bytes(void *buf, size_t bytes) |
127 | { | 127 | { |
128 | struct rnd_state *state = &get_cpu_var(net_rand_state); | 128 | struct rnd_state *state = &get_cpu_var(net_rand_state); |
129 | 129 | ||
@@ -134,7 +134,7 @@ EXPORT_SYMBOL(prandom_bytes); | |||
134 | 134 | ||
135 | static void prandom_warmup(struct rnd_state *state) | 135 | static void prandom_warmup(struct rnd_state *state) |
136 | { | 136 | { |
137 | /* Calling RNG ten times to satify recurrence condition */ | 137 | /* Calling RNG ten times to satisfy recurrence condition */ |
138 | prandom_u32_state(state); | 138 | prandom_u32_state(state); |
139 | prandom_u32_state(state); | 139 | prandom_u32_state(state); |
140 | prandom_u32_state(state); | 140 | prandom_u32_state(state); |
@@ -147,21 +147,25 @@ static void prandom_warmup(struct rnd_state *state) | |||
147 | prandom_u32_state(state); | 147 | prandom_u32_state(state); |
148 | } | 148 | } |
149 | 149 | ||
150 | static void prandom_seed_very_weak(struct rnd_state *state, u32 seed) | 150 | static u32 __extract_hwseed(void) |
151 | { | 151 | { |
152 | /* Note: This sort of seeding is ONLY used in test cases and | 152 | unsigned int val = 0; |
153 | * during boot at the time from core_initcall until late_initcall | 153 | |
154 | * as we don't have a stronger entropy source available yet. | 154 | (void)(arch_get_random_seed_int(&val) || |
155 | * After late_initcall, we reseed entire state, we have to (!), | 155 | arch_get_random_int(&val)); |
156 | * otherwise an attacker just needs to search 32 bit space to | 156 | |
157 | * probe for our internal 128 bit state if he knows a couple | 157 | return val; |
158 | * of prandom32 outputs! | 158 | } |
159 | */ | 159 | |
160 | #define LCG(x) ((x) * 69069U) /* super-duper LCG */ | 160 | static void prandom_seed_early(struct rnd_state *state, u32 seed, |
161 | state->s1 = __seed(LCG(seed), 2U); | 161 | bool mix_with_hwseed) |
162 | state->s2 = __seed(LCG(state->s1), 8U); | 162 | { |
163 | state->s3 = __seed(LCG(state->s2), 16U); | 163 | #define LCG(x) ((x) * 69069U) /* super-duper LCG */ |
164 | state->s4 = __seed(LCG(state->s3), 128U); | 164 | #define HWSEED() (mix_with_hwseed ? __extract_hwseed() : 0) |
165 | state->s1 = __seed(HWSEED() ^ LCG(seed), 2U); | ||
166 | state->s2 = __seed(HWSEED() ^ LCG(state->s1), 8U); | ||
167 | state->s3 = __seed(HWSEED() ^ LCG(state->s2), 16U); | ||
168 | state->s4 = __seed(HWSEED() ^ LCG(state->s3), 128U); | ||
165 | } | 169 | } |
166 | 170 | ||
167 | /** | 171 | /** |
@@ -194,14 +198,13 @@ static int __init prandom_init(void) | |||
194 | { | 198 | { |
195 | int i; | 199 | int i; |
196 | 200 | ||
197 | #ifdef CONFIG_RANDOM32_SELFTEST | ||
198 | prandom_state_selftest(); | 201 | prandom_state_selftest(); |
199 | #endif | ||
200 | 202 | ||
201 | for_each_possible_cpu(i) { | 203 | for_each_possible_cpu(i) { |
202 | struct rnd_state *state = &per_cpu(net_rand_state,i); | 204 | struct rnd_state *state = &per_cpu(net_rand_state,i); |
205 | u32 weak_seed = (i + jiffies) ^ random_get_entropy(); | ||
203 | 206 | ||
204 | prandom_seed_very_weak(state, (i + jiffies) ^ random_get_entropy()); | 207 | prandom_seed_early(state, weak_seed, true); |
205 | prandom_warmup(state); | 208 | prandom_warmup(state); |
206 | } | 209 | } |
207 | 210 | ||
@@ -210,6 +213,7 @@ static int __init prandom_init(void) | |||
210 | core_initcall(prandom_init); | 213 | core_initcall(prandom_init); |
211 | 214 | ||
212 | static void __prandom_timer(unsigned long dontcare); | 215 | static void __prandom_timer(unsigned long dontcare); |
216 | |||
213 | static DEFINE_TIMER(seed_timer, __prandom_timer, 0, 0); | 217 | static DEFINE_TIMER(seed_timer, __prandom_timer, 0, 0); |
214 | 218 | ||
215 | static void __prandom_timer(unsigned long dontcare) | 219 | static void __prandom_timer(unsigned long dontcare) |
@@ -221,7 +225,7 @@ static void __prandom_timer(unsigned long dontcare) | |||
221 | prandom_seed(entropy); | 225 | prandom_seed(entropy); |
222 | 226 | ||
223 | /* reseed every ~60 seconds, in [40 .. 80) interval with slack */ | 227 | /* reseed every ~60 seconds, in [40 .. 80) interval with slack */ |
224 | expires = 40 + (prandom_u32() % 40); | 228 | expires = 40 + prandom_u32_max(40); |
225 | seed_timer.expires = jiffies + msecs_to_jiffies(expires * MSEC_PER_SEC); | 229 | seed_timer.expires = jiffies + msecs_to_jiffies(expires * MSEC_PER_SEC); |
226 | 230 | ||
227 | add_timer(&seed_timer); | 231 | add_timer(&seed_timer); |
@@ -419,7 +423,7 @@ static void __init prandom_state_selftest(void) | |||
419 | for (i = 0; i < ARRAY_SIZE(test1); i++) { | 423 | for (i = 0; i < ARRAY_SIZE(test1); i++) { |
420 | struct rnd_state state; | 424 | struct rnd_state state; |
421 | 425 | ||
422 | prandom_seed_very_weak(&state, test1[i].seed); | 426 | prandom_seed_early(&state, test1[i].seed, false); |
423 | prandom_warmup(&state); | 427 | prandom_warmup(&state); |
424 | 428 | ||
425 | if (test1[i].result != prandom_u32_state(&state)) | 429 | if (test1[i].result != prandom_u32_state(&state)) |
@@ -434,7 +438,7 @@ static void __init prandom_state_selftest(void) | |||
434 | for (i = 0; i < ARRAY_SIZE(test2); i++) { | 438 | for (i = 0; i < ARRAY_SIZE(test2); i++) { |
435 | struct rnd_state state; | 439 | struct rnd_state state; |
436 | 440 | ||
437 | prandom_seed_very_weak(&state, test2[i].seed); | 441 | prandom_seed_early(&state, test2[i].seed, false); |
438 | prandom_warmup(&state); | 442 | prandom_warmup(&state); |
439 | 443 | ||
440 | for (j = 0; j < test2[i].iteration - 1; j++) | 444 | for (j = 0; j < test2[i].iteration - 1; j++) |