aboutsummaryrefslogtreecommitdiffstats
path: root/lib/random32.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/random32.c')
-rw-r--r--lib/random32.c86
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
42static void __init prandom_state_selftest(void); 43static void __init prandom_state_selftest(void);
44#else
45static inline void prandom_state_selftest(void)
46{
47}
43#endif 48#endif
44 49
45static DEFINE_PER_CPU(struct rnd_state, net_rand_state); 50static 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 */
54u32 prandom_u32_state(struct rnd_state *state) 59u32 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 */
96void prandom_bytes_state(struct rnd_state *state, void *buf, int bytes) 100void 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}
119EXPORT_SYMBOL(prandom_bytes_state); 119EXPORT_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 */
126void prandom_bytes(void *buf, int bytes) 126void 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
135static void prandom_warmup(struct rnd_state *state) 135static 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
150static void prandom_seed_very_weak(struct rnd_state *state, u32 seed) 150static 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 */ 160static 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)
210core_initcall(prandom_init); 213core_initcall(prandom_init);
211 214
212static void __prandom_timer(unsigned long dontcare); 215static void __prandom_timer(unsigned long dontcare);
216
213static DEFINE_TIMER(seed_timer, __prandom_timer, 0, 0); 217static DEFINE_TIMER(seed_timer, __prandom_timer, 0, 0);
214 218
215static void __prandom_timer(unsigned long dontcare) 219static 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++)