diff options
-rw-r--r-- | sys/dev/rnd.c | 180 | ||||
-rw-r--r-- | sys/dev/rndvar.h | 4 |
2 files changed, 115 insertions, 69 deletions
diff --git a/sys/dev/rnd.c b/sys/dev/rnd.c index 2d94279e9be..d55cd8c8324 100644 --- a/sys/dev/rnd.c +++ b/sys/dev/rnd.c @@ -1,44 +1,13 @@ -/* $OpenBSD: rnd.c,v 1.7 1996/08/29 09:26:36 deraadt Exp $ */ +/* $OpenBSD: rnd.c,v 1.8 1996/09/06 08:36:13 mickey Exp $ */ /* - * Copyright (c) 1996 Michael Shalayeff. - * - * This software derived from one contributed by Theodore Ts'o. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Theodore Ts'o. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * * random.c -- A strong random number generator * - * Version 0.96, last modified 29-Dec-95 + * Copyright (c) 1996 Michael Shalayeff. + * + * Version 1.00, last modified 26-May-96 * - * Copyright Theodore Ts'o, 1994, 1995. All rights reserved. + * Copyright Theodore Ts'o, 1994, 1995, 1996. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -79,14 +48,14 @@ * and returns good random numbers, suitable for cryptographic use. * Besides the obvious cryptographic uses, these numbers are also good * for seeding TCP sequence numbers, and other places where it is - * desireable to have numbers which are not only random, but hard to + * desirable to have numbers which are not only random, but hard to * predict by an attacker. * * Theory of operation * =================== * * Computers are very predictable devices. Hence it is extremely hard - * to produce truely random numbers on a computer --- as opposed to + * to produce truly random numbers on a computer --- as opposed to * pseudo-random numbers, which can easily generated by using a * algorithm. Unfortunately, it is very easy for attackers to guess * the sequence of pseudo-random number generators, and for some @@ -124,7 +93,7 @@ * random numbers; however, an attacker may (at least in theory) be * able to infer the future output of the generator from prior * outputs. This requires successful cryptanalysis of MD5, which is - * not believed to be feasible, but there is a remote possiblility. + * not believed to be feasible, but there is a remote possibility. * Nonetheless, these numbers should be useful for the vast majority * of purposes. * @@ -158,10 +127,10 @@ * The current exported interfaces for gathering environmental noise * from the devices are: * - * void add_keyboard_randomness(u_char scancode); * void add_mouse_randomness(u_int32_t mouse_data); - * void add_interrupt_randomness(int irq); - * void add_blkdev_randomness(dev_t dev); + * void add_net_randomness(int isr); + * void add_tty_randomness(dev_t dev, int c); + * void add_blkdev_randomness(int irq); * * add_keyboard_randomness() uses the inter-keypress timing, as well as the * scancode as random inputs into the "entropy pool". @@ -183,6 +152,58 @@ * particular randomness source. They do this by keeping track of the * first and second order deltas of the event timings. * + * Ensuring unpredictability at system startup + * ============================================ + * + * When any operating system starts up, it will go through a sequence + * of actions that are fairly predictable by an adversary, especially + * if the start-up does not involve interaction with a human operator. + * This reduces the actual number of bits of unpredictability in the + * entropy pool below the value in entropy_count. In order to + * counteract this effect, it helps to carry information in the + * entropy pool across shut-downs and start-ups. To do this, put the + * following lines an appropriate script which is run during the boot + * sequence: + * + * echo "Initializing random number generator..." + * # Carry a random seed from start-up to start-up + * # Load and then save 512 bytes, which is the size of the entropy pool + * if [ -f /etc/random-seed ]; then + * cat /etc/random-seed >/dev/urandom + * fi + * dd if=/dev/urandom of=/etc/random-seed count=1 + * + * and the following lines in an appropriate script which is run as + * the system is shutdown: + * + * # Carry a random seed from shut-down to start-up + * # Save 512 bytes, which is the size of the entropy pool + * echo "Saving random seed..." + * dd if=/dev/urandom of=/etc/random-seed count=1 + * + * For example, on many Linux systems, the appropriate scripts are + * usually /etc/rc.d/rc.local and /etc/rc.d/rc.0, respectively. + * + * Effectively, these commands cause the contents of the entropy pool + * to be saved at shut-down time and reloaded into the entropy pool at + * start-up. (The 'dd' in the addition to the bootup script is to + * make sure that /etc/random-seed is different for every start-up, + * even if the system crashes without executing rc.0.) Even with + * complete knowledge of the start-up activities, predicting the state + * of the entropy pool requires knowledge of the previous history of + * the system. + * + * Configuring the /dev/random driver under Linux + * ============================================== + * + * The /dev/random driver under Linux uses minor numbers 8 and 9 of + * the /dev/mem major number (#1). So if your system does not have + * /dev/random and /dev/urandom created already, they can be created + * by using the commands: + * + * mknod /dev/random c 1 8 + * mknod /dev/urandom c 1 9 + * * Acknowledgements: * ================= * @@ -193,10 +214,20 @@ * entropy pool, taken from PGP 3.0 (under development). It has since * been modified by myself to provide better mixing in the case where * the input values to add_entropy_word() are mostly small numbers. + * Dale Worley has also contributed many useful ideas and suggestions + * to improve this driver. * * Any flaws in the design are solely my responsibility, and should * not be attributed to the Phil, Colin, or any of authors of PGP. * + * The code for MD5 transform was taken from Colin Plumb's + * implementation, which has been placed in the public domain. The + * MD5 cryptographic checksum was devised by Ronald Rivest, and is + * documented in RFC 1321, "The MD5 Message Digest Algorithm". + * + * Further background information on this topic may be obtained from + * RFC 1750, "Randomness Recommendations for Security", by Donald + * Eastlake, Steve Crocker, and Jeff Schiller. */ #include "random.h" @@ -226,6 +257,17 @@ int rnd_debug = 0x0000; #define RD_WAIT 0x0100 /* sleep/wakeup for good data */ #endif +#ifdef RND_USE_SHA +#define HASH_BUFFER_SIZE 5 +#define HASH_TRANSFORM SHATransform +#else /* RND_USE_MD5 */ +#ifndef RND_USE_MD5 +#define RND_USE_MD5 +#endif +#define HASH_BUFFER_SIZE 4 +#define HASH_TRANSFORM MD5Transform +#endif + /* * The pool is stirred with a primitive polynomial of degree 128 * over GF(2), namely x^128 + x^99 + x^59 + x^31 + x^9 + x^7 + 1. @@ -274,9 +316,6 @@ struct arc4_stream { #define ENT_BLKDEV 0x200 #define ENT_TTY 0x300 -/* device functions prototypes: XXX move em to dev_conf.h */ -cdev_decl(random); - static struct random_bucket random_state; struct arc4_stream arc4random_state; static u_int32_t random_pool[POOLWORDS]; @@ -322,7 +361,7 @@ arc4_getbyte (struct arc4_stream *as) return (as->s[(si + sj) & 0xff]); } -u_long +u_int32_t arc4random (void) { return ((arc4_getbyte (&arc4random_state) << 24) @@ -330,7 +369,7 @@ arc4random (void) | (arc4_getbyte (&arc4random_state) << 8) | arc4_getbyte (&arc4random_state)); } - + void randomattach(num) int num; @@ -443,7 +482,7 @@ add_timer_randomness(r, state, num) { int delta, delta2; u_int nbits; - u_int32_t time; + u_long time; { struct timeval tv; @@ -492,17 +531,6 @@ add_timer_randomness(r, state, num) } void -add_keyboard_randomness(scancode) - u_char scancode; -{ -#ifdef DEBUG - if (rnd_debug & RD_INPUT) - printf("rnd: adding %02x from kbd\n", scancode); -#endif - add_timer_randomness(&random_state, &keyboard_timer_state, scancode); -} - -void add_mouse_randomness(mouse_data) u_int32_t mouse_data; { @@ -559,16 +587,13 @@ extract_entropy(r, buf, nbytes) int nbytes; { int ret, i; - u_int32_t tmp[4]; + u_int32_t tmp[HASH_BUFFER_SIZE]; add_timer_randomness(r, &extract_timer_state, nbytes); /* Redundant, but just in case... */ if (r->entropy_count > POOLBITS) r->entropy_count = POOLBITS; - /* Why is this here? Left in from Ted Ts'o. Perhaps to limit time. */ - if (nbytes > 32768) - nbytes = 32768; ret = nbytes; if (r->entropy_count / 8 >= nbytes) @@ -578,26 +603,46 @@ extract_entropy(r, buf, nbytes) while (nbytes) { /* Hash the pool to get the output */ +#ifdef RND_USE_MD5 MD5Init(tmp); +#endif for (i = 0; i < POOLWORDS; i += 16) - MD5Transform(tmp, r->pool+i); + HASH_TRANSFORM(tmp, r->pool+i); /* Modify pool so next hash will produce different results */ add_entropy_word(r, tmp[0]); add_entropy_word(r, tmp[1]); add_entropy_word(r, tmp[2]); add_entropy_word(r, tmp[3]); +#ifdef RND_USE_SHA + add_entropy_word(r, tmp[5]); +#endif /* * Run the MD5 Transform one more time, since we want * to add at least minimal obscuring of the inputs to * add_entropy_word(). --- TYT */ - MD5Transform(tmp, r->pool); - + HASH_TRANSFORM(tmp, r->pool); + + /* + * In case the hash function has some recognizable + * output pattern, we fold it in half. + */ + { + register u_int8_t *cp, *dp; + cp = (u_int8_t *) tmp; + dp = cp + (HASH_BUFFER_SIZE*sizeof(tmp[0])) - 1; + for (i=0; i < HASH_BUFFER_SIZE*sizeof(tmp[0])/2; i++) { + *cp ^= *dp; + cp++; dp--; + } + } + /* Copy data to destination buffer */ - i = MIN(nbytes, 16); + i = MIN(nbytes, HASH_BUFFER_SIZE*sizeof(tmp[0])); bcopy((caddr_t)tmp, buf, i); nbytes -= i; buf += i; + add_timer_randomness(r, &extract_timer_state, nbytes); } /* Wipe data from memory */ @@ -638,6 +683,7 @@ randomread(dev, uio, ioflag) s = splhigh(); switch(minor(dev)) { case RND_RND: + ret = EIO; /* no chip -- error */ break; case RND_SRND: if (random_state.entropy_count < 8) { diff --git a/sys/dev/rndvar.h b/sys/dev/rndvar.h index 34297e6922e..013ffe38fac 100644 --- a/sys/dev/rndvar.h +++ b/sys/dev/rndvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rndvar.h,v 1.3 1996/08/11 07:31:32 dm Exp $ */ +/* $OpenBSD: rndvar.h,v 1.4 1996/09/06 08:36:14 mickey Exp $ */ /* * Copyright (c) 1996 Michael Shalayeff. @@ -54,7 +54,7 @@ extern void add_blkdev_randomness __P((dev_t)); extern void add_tty_randomness __P((dev_t, int)); extern void get_random_bytes __P((void *, size_t)); -extern unsigned long arc4random __P((void)); +extern u_int32_t arc4random __P((void)); #endif /* _KERNEL */ |