1 /*
2 * random_machdep.c -- A strong random number generator
3 *
4 * $FreeBSD$
5 *
6 * Version 0.95, last modified 18-Oct-95
7 *
8 * Copyright Theodore Ts'o, 1994, 1995. All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, and the entire permission notice in its entirety,
15 * including the disclaimer of warranties.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote
20 * products derived from this software without specific prior
21 * written permission.
22 *
23 * ALTERNATIVELY, this product may be distributed under the terms of
24 * the GNU Public License, in which case the provisions of the GPL are
25 * required INSTEAD OF the above restrictions. (This clause is
26 * necessary due to a potential bad interaction between the GPL and
27 * the restrictions contained in a BSD-style copyright.)
28 *
29 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
30 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
31 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
32 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/select.h>
46 #include <sys/poll.h>
47 #include <sys/md5.h>
48
49 #include <machine/random.h>
50
51 #include <i386/isa/icu.h>
52 #include <i386/isa/intr_machdep.h>
53
54 #define MAX_BLKDEV 4
55
56 /*
57 * The pool is stirred with a primitive polynomial of degree 128
58 * over GF(2), namely x^128 + x^99 + x^59 + x^31 + x^9 + x^7 + 1.
59 * For a pool of size 64, try x^64+x^62+x^38+x^10+x^6+x+1.
60 */
61 #define POOLWORDS 128 /* Power of 2 - note that this is 32-bit words */
62 #define POOLBITS (POOLWORDS*32)
63
64 #if POOLWORDS == 128
65 #define TAP1 99 /* The polynomial taps */
66 #define TAP2 59
67 #define TAP3 31
68 #define TAP4 9
69 #define TAP5 7
70 #elif POOLWORDS == 64
71 #define TAP1 62 /* The polynomial taps */
72 #define TAP2 38
73 #define TAP3 10
74 #define TAP4 6
75 #define TAP5 1
76 #else
77 #error No primitive polynomial available for chosen POOLWORDS
78 #endif
79
80 #define WRITEBUFFER 512 /* size in bytes */
81
82 /* There is actually only one of these, globally. */
83 struct random_bucket {
84 u_int add_ptr;
85 u_int entropy_count;
86 int input_rotate;
87 u_int32_t *pool;
88 struct selinfo rsel;
89 };
90
91 /* There is one of these per entropy source */
92 struct timer_rand_state {
93 u_long last_time;
94 int last_delta;
95 int nbits;
96 };
97
98 static struct random_bucket random_state;
99 static u_int32_t random_pool[POOLWORDS];
100 static struct timer_rand_state keyboard_timer_state;
101 static struct timer_rand_state extract_timer_state;
102 static struct timer_rand_state irq_timer_state[ICU_LEN];
103 #ifdef notyet
104 static struct timer_rand_state blkdev_timer_state[MAX_BLKDEV];
105 #endif
106 static struct wait_queue *random_wait;
107
108 #ifndef MIN
109 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
110 #endif
111
112 void
113 rand_initialize(void)
114 {
115 random_state.add_ptr = 0;
116 random_state.entropy_count = 0;
117 random_state.pool = random_pool;
118 random_wait = NULL;
119 random_state.rsel.si_flags = 0;
120 random_state.rsel.si_pid = 0;
121 }
122
123 /*
124 * This function adds an int into the entropy "pool". It does not
125 * update the entropy estimate. The caller must do this if appropriate.
126 *
127 * The pool is stirred with a primitive polynomial of degree 128
128 * over GF(2), namely x^128 + x^99 + x^59 + x^31 + x^9 + x^7 + 1.
129 * For a pool of size 64, try x^64+x^62+x^38+x^10+x^6+x+1.
130 *
131 * We rotate the input word by a changing number of bits, to help
132 * assure that all bits in the entropy get toggled. Otherwise, if we
133 * consistently feed the entropy pool small numbers (like ticks and
134 * scancodes, for example), the upper bits of the entropy pool don't
135 * get affected. --- TYT, 10/11/95
136 */
137 static __inline void
138 add_entropy_word(struct random_bucket *r, const u_int32_t input)
139 {
140 u_int i;
141 u_int32_t w;
142
143 w = (input << r->input_rotate) | (input >> (32 - r->input_rotate));
144 i = r->add_ptr = (r->add_ptr - 1) & (POOLWORDS-1);
145 if (i)
146 r->input_rotate = (r->input_rotate + 7) & 31;
147 else
148 /*
149 * At the beginning of the pool, add an extra 7 bits
150 * rotation, so that successive passes spread the
151 * input bits across the pool evenly.
152 */
153 r->input_rotate = (r->input_rotate + 14) & 31;
154
155 /* XOR in the various taps */
156 w ^= r->pool[(i+TAP1)&(POOLWORDS-1)];
157 w ^= r->pool[(i+TAP2)&(POOLWORDS-1)];
158 w ^= r->pool[(i+TAP3)&(POOLWORDS-1)];
159 w ^= r->pool[(i+TAP4)&(POOLWORDS-1)];
160 w ^= r->pool[(i+TAP5)&(POOLWORDS-1)];
161 w ^= r->pool[i];
162 /* Rotate w left 1 bit (stolen from SHA) and store */
163 r->pool[i] = (w << 1) | (w >> 31);
164 }
165
166 /*
167 * This function adds entropy to the entropy "pool" by using timing
168 * delays. It uses the timer_rand_state structure to make an estimate
169 * of how any bits of entropy this call has added to the pool.
170 *
171 * The number "num" is also added to the pool - it should somehow describe
172 * the type of event which just happened. This is currently 0-255 for
173 * keyboard scan codes, and 256 upwards for interrupts.
174 * On the i386, this is assumed to be at most 16 bits, and the high bits
175 * are used for a high-resolution timer.
176 */
177 static void
178 add_timer_randomness(struct random_bucket *r, struct timer_rand_state *state,
179 u_int num)
180 {
181 int delta, delta2;
182 u_int nbits;
183 u_int32_t time;
184
185 num ^= timecounter->tc_get_timecount(timecounter) << 16;
186 r->entropy_count += 2;
187
188 time = ticks;
189
190 add_entropy_word(r, (u_int32_t) num);
191 add_entropy_word(r, time);
192
193 /*
194 * Calculate number of bits of randomness we probably
195 * added. We take into account the first and second order
196 * deltas in order to make our estimate.
197 */
198 delta = time - state->last_time;
199 state->last_time = time;
200
201 delta2 = delta - state->last_delta;
202 state->last_delta = delta;
203
204 if (delta < 0) delta = -delta;
205 if (delta2 < 0) delta2 = -delta2;
206 delta = MIN(delta, delta2) >> 1;
207 for (nbits = 0; delta; nbits++)
208 delta >>= 1;
209
210 r->entropy_count += nbits;
211
212 /* Prevent overflow */
213 if (r->entropy_count > POOLBITS)
214 r->entropy_count = POOLBITS;
215
216 if (r->entropy_count >= 8)
217 selwakeup(&random_state.rsel);
218 }
219
220 void
221 add_keyboard_randomness(u_char scancode)
222 {
223 add_timer_randomness(&random_state, &keyboard_timer_state, scancode);
224 }
225
226 void
227 add_interrupt_randomness(void *vsc)
228 {
229 int intr;
230 struct random_softc *sc = vsc;
231
232 (sc->sc_handler)(sc->sc_arg);
233 intr = sc->sc_intr;
234 add_timer_randomness(&random_state, &irq_timer_state[intr], intr);
235 }
236
237 #ifdef notused
238 void
239 add_blkdev_randomness(int major)
240 {
241 if (major >= MAX_BLKDEV)
242 return;
243
244 add_timer_randomness(&random_state, &blkdev_timer_state[major],
245 0x200+major);
246 }
247 #endif /* notused */
248
249 #if POOLWORDS % 16
250 #error extract_entropy() assumes that POOLWORDS is a multiple of 16 words.
251 #endif
252 /*
253 * This function extracts randomness from the "entropy pool", and
254 * returns it in a buffer. This function computes how many remaining
255 * bits of entropy are left in the pool, but it does not restrict the
256 * number of bytes that are actually obtained.
257 */
258 static __inline int
259 extract_entropy(struct random_bucket *r, char *buf, int nbytes)
260 {
261 int ret, i;
262 u_int32_t tmp[4];
263
264 add_timer_randomness(r, &extract_timer_state, nbytes);
265
266 /* Redundant, but just in case... */
267 if (r->entropy_count > POOLBITS)
268 r->entropy_count = POOLBITS;
269 /* Why is this here? Left in from Ted Ts'o. Perhaps to limit time. */
270 if (nbytes > 32768)
271 nbytes = 32768;
272
273 ret = nbytes;
274 if (r->entropy_count / 8 >= nbytes)
275 r->entropy_count -= nbytes*8;
276 else
277 r->entropy_count = 0;
278
279 while (nbytes) {
280 /* Hash the pool to get the output */
281 tmp[0] = 0x67452301;
282 tmp[1] = 0xefcdab89;
283 tmp[2] = 0x98badcfe;
284 tmp[3] = 0x10325476;
285 for (i = 0; i < POOLWORDS; i += 16)
286 MD5Transform(tmp, (char *)(r->pool+i));
287 /* Modify pool so next hash will produce different results */
288 add_entropy_word(r, tmp[0]);
289 add_entropy_word(r, tmp[1]);
290 add_entropy_word(r, tmp[2]);
291 add_entropy_word(r, tmp[3]);
292 /*
293 * Run the MD5 Transform one more time, since we want
294 * to add at least minimal obscuring of the inputs to
295 * add_entropy_word(). --- TYT
296 */
297 MD5Transform(tmp, (char *)(r->pool));
298
299 /* Copy data to destination buffer */
300 i = MIN(nbytes, 16);
301 bcopy(tmp, buf, i);
302 nbytes -= i;
303 buf += i;
304 }
305
306 /* Wipe data from memory */
307 bzero(tmp, sizeof(tmp));
308
309 return ret;
310 }
311
312 #ifdef notused /* XXX NOT the exported kernel interface */
313 /*
314 * This function is the exported kernel interface. It returns some
315 * number of good random numbers, suitable for seeding TCP sequence
316 * numbers, etc.
317 */
318 void
319 get_random_bytes(void *buf, u_int nbytes)
320 {
321 extract_entropy(&random_state, (char *) buf, nbytes);
322 }
323 #endif /* notused */
324
325 u_int
326 read_random(void *buf, u_int nbytes)
327 {
328 if ((nbytes * 8) > random_state.entropy_count)
329 nbytes = random_state.entropy_count / 8;
330
331 return extract_entropy(&random_state, (char *)buf, nbytes);
332 }
333
334 u_int
335 read_random_unlimited(void *buf, u_int nbytes)
336 {
337 return extract_entropy(&random_state, (char *)buf, nbytes);
338 }
339
340 #ifdef notused
341 u_int
342 write_random(const char *buf, u_int nbytes)
343 {
344 u_int i;
345 u_int32_t word, *p;
346
347 for (i = nbytes, p = (u_int32_t *)buf;
348 i >= sizeof(u_int32_t);
349 i-= sizeof(u_int32_t), p++)
350 add_entropy_word(&random_state, *p);
351 if (i) {
352 word = 0;
353 bcopy(p, &word, i);
354 add_entropy_word(&random_state, word);
355 }
356 return nbytes;
357 }
358 #endif /* notused */
359
360 int
361 random_poll(dev_t dev, int events, struct proc *p)
362 {
363 int s;
364 int revents = 0;
365
366 s = splhigh();
367 if (events & (POLLIN | POLLRDNORM))
368 if (random_state.entropy_count >= 8)
369 revents |= events & (POLLIN | POLLRDNORM);
370 else
371 selrecord(p, &random_state.rsel);
372
373 splx(s);
374 if (events & (POLLOUT | POLLWRNORM))
375 revents |= events & (POLLOUT | POLLWRNORM); /* heh */
376
377 return (revents);
378 }
379
Cache object: 4476bf866ceab091d36064b58539d2f4
|