diff options
-rw-r--r-- | sbin/sysctl/sysctl.8 | 9 | ||||
-rw-r--r-- | sbin/sysctl/sysctl.c | 26 | ||||
-rw-r--r-- | sys/dev/rnd.c | 161 | ||||
-rw-r--r-- | sys/dev/rndioctl.h | 6 | ||||
-rw-r--r-- | sys/dev/rndvar.h | 21 | ||||
-rw-r--r-- | sys/kern/kern_sysctl.c | 6 | ||||
-rw-r--r-- | sys/sys/sysctl.h | 6 | ||||
-rw-r--r-- | usr.sbin/sysctl/sysctl.8 | 9 | ||||
-rw-r--r-- | usr.sbin/sysctl/sysctl.c | 26 |
9 files changed, 220 insertions, 50 deletions
diff --git a/sbin/sysctl/sysctl.8 b/sbin/sysctl/sysctl.8 index 2a9e6fdbeb7..fa0511b8646 100644 --- a/sbin/sysctl/sysctl.8 +++ b/sbin/sysctl/sysctl.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sysctl.8,v 1.8 1997/06/13 13:50:59 mickey Exp $ +.\" $OpenBSD: sysctl.8,v 1.9 1997/06/14 21:37:11 mickey Exp $ .\" $NetBSD: sysctl.8,v 1.4 1995/09/30 07:12:49 thorpej Exp $ .\" .\" Copyright (c) 1993 @@ -136,8 +136,9 @@ privilege can change the value. .It kern.somaxconn integer yes .It kern.sominconn integer yes .It kern.usermount integer yes +.It kern.random struct no .It vm.loadavg struct no -.It vm.psstrings struct _ps_strings no +.It vm.psstrings struct no .It fs.posix.setuid integer yes .It net.inet.ip.forwarding integer yes .It net.inet.ip.redirect integer yes @@ -226,6 +227,10 @@ sysctl vm.loadavg .It Pa <sys/sysctl.h> definitions for top level identifiers, second level kernel and hardware identifiers, and user level identifiers +.It Pa <dev/rndvar.h> +definitions for +.Xr random 4 +device's statistics structure .It Pa <sys/socket.h> definitions for second level network identifiers .It Pa <sys/gmon.h> diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c index a4867ee0deb..196026e9414 100644 --- a/sbin/sysctl/sysctl.c +++ b/sbin/sysctl/sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sysctl.c,v 1.7 1997/04/06 20:19:22 millert Exp $ */ +/* $OpenBSD: sysctl.c,v 1.8 1997/06/14 21:37:12 mickey Exp $ */ /* $NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $ */ /* @@ -44,7 +44,7 @@ static char copyright[] = #if 0 static char sccsid[] = "@(#)sysctl.c 8.1 (Berkeley) 6/6/93"; #else -static char *rcsid = "$OpenBSD: sysctl.c,v 1.7 1997/04/06 20:19:22 millert Exp $"; +static char *rcsid = "$OpenBSD: sysctl.c,v 1.8 1997/06/14 21:37:12 mickey Exp $"; #endif #endif /* not lint */ @@ -72,6 +72,7 @@ static char *rcsid = "$OpenBSD: sysctl.c,v 1.7 1997/04/06 20:19:22 millert Exp $ #include <netipx/ipx_var.h> #include <netipx/spx_var.h> #include <ddb/db_var.h> +#include <dev/rndvar.h> #include <errno.h> #include <stdio.h> @@ -123,6 +124,7 @@ int Aflag, aflag, nflag, wflag; #define CLOCK 0x00000001 #define BOOTTIME 0x00000002 #define CONSDEV 0x00000004 +#define RNDSTATS 0x00000008 /* prototypes */ void usage(); @@ -272,7 +274,7 @@ parse(string, flags) return; if (!nflag) fprintf(stdout, "%s: ", string); - fprintf(stderr, + fprintf(stdout, "kernel is not compiled for profiling\n"); return; } @@ -305,6 +307,9 @@ parse(string, flags) case KERN_BOOTTIME: special |= BOOTTIME; break; + case KERN_RND: + special |= RNDSTATS; + break; } break; @@ -453,6 +458,21 @@ parse(string, flags) fprintf(stdout, "0x%x\n", dev); return; } + if (special & RNDSTATS) { + struct rndstats *rndstats = (struct rndstats *)buf; + if (!nflag) + fprintf(stdout, "%s: ", string); + fprintf(stdout, + "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n", + rndstats->rnd_total, rndstats->rnd_used, + rndstats->arc4_reads, rndstats->rnd_timer, + rndstats->rnd_mouse, rndstats->rnd_tty, + rndstats->rnd_disk, rndstats->rnd_net, + rndstats->rnd_reads, rndstats->rnd_waits, + rndstats->rnd_enqs, rndstats->rnd_deqs, + rndstats->rnd_drops); + return; + } switch (type) { case CTLTYPE_INT: if (newsize == 0) { diff --git a/sys/dev/rnd.c b/sys/dev/rnd.c index 11e03042228..640006ee3c2 100644 --- a/sys/dev/rnd.c +++ b/sys/dev/rnd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rnd.c,v 1.22 1997/06/12 02:18:39 mickey Exp $ */ +/* $OpenBSD: rnd.c,v 1.23 1997/06/14 21:37:08 mickey Exp $ */ /* * random.c -- A strong random number generator @@ -239,6 +239,7 @@ #include <sys/fcntl.h> #include <sys/vnode.h> #include <sys/md5k.h> +#include <sys/sysctl.h> #include <net/netisr.h> @@ -274,6 +275,10 @@ int rnd_debug = 0x0000; #error No primitive polynomial available for chosen POOLWORDS #endif +#define QEVLEN 32 +#define QEVSLOW 16 +#define QEVSBITS 4 + /* There is actually only one of these, globally. */ struct random_bucket { u_int add_ptr; @@ -295,11 +300,20 @@ struct arc4_stream { u_char s[256]; }; +struct rand_event { + struct rand_event *re_next; + struct timer_rand_state *re_state; + u_char re_nbits; + u_long re_time; + u_int re_val; +}; + /* tags for different random sources */ #define ENT_NET 0x100 #define ENT_DISK 0x200 #define ENT_TTY 0x300 +struct rndstats rndstats; static struct random_bucket random_state; static int arc4random_uninitialized = 2; static struct arc4_stream arc4random_state; @@ -308,15 +322,20 @@ static struct timer_rand_state extract_timer_state; static struct timer_rand_state disk_timer_state; static struct timer_rand_state net_timer_state; static struct timer_rand_state tty_timer_state; +static struct rand_event event_space[QEVLEN]; static int rnd_sleep = 0; static int rnd_attached = 0; +static int rnd_enqueued = 0; +static struct rand_event *event_q = NULL; +static struct rand_event *event_free; #ifndef MIN #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #endif static __inline void add_entropy_word __P((const u_int32_t)); -void add_timer_randomness __P((struct timer_rand_state *, u_int)); +static void enqueue_randomness __P((register struct timer_rand_state*, u_int)); +void dequeue_randomness __P((void *)); static __inline int extract_entropy __P((register char *, int)); void arc4_init __P((struct arc4_stream *, u_char *, int)); static __inline void arc4_stir (register struct arc4_stream *); @@ -361,6 +380,7 @@ arc4_getbyte (register struct arc4_stream *as) { register u_char si, sj; + rndstats.arc4_reads++; as->i = (as->i + 1) & 0xff; si = as->s[as->i]; as->j = (as->j + si) & 0xff; @@ -370,7 +390,7 @@ arc4_getbyte (register struct arc4_stream *as) return (as->s[(si + sj) & 0xff]); } -static inline void +static __inline void arc4maybeinit (void) { if (arc4random_uninitialized) { @@ -385,11 +405,11 @@ arc4maybeinit (void) u_int32_t arc4random (void) { - arc4maybeinit (); - return ((arc4_getbyte (&arc4random_state) << 24) - | (arc4_getbyte (&arc4random_state) << 16) - | (arc4_getbyte (&arc4random_state) << 8) - | arc4_getbyte (&arc4random_state)); + arc4maybeinit (); + return ((arc4_getbyte (&arc4random_state) << 24) + | (arc4_getbyte (&arc4random_state) << 16) + | (arc4_getbyte (&arc4random_state) << 8) + | arc4_getbyte (&arc4random_state)); } void @@ -397,11 +417,18 @@ randomattach(void) { int i; struct timeval tv; + struct rand_event *rep; random_state.add_ptr = 0; random_state.entropy_count = 0; extract_timer_state.dont_count_entropy = 1; + bzero(&rndstats, sizeof(rndstats)); + + bzero(&event_space, sizeof(event_space)); + event_free = event_space; + for (rep = event_space; rep < &event_space[QEVLEN]; rep++) + rep->re_next = rep + 1; for (i = 0; i < 256; i++) arc4random_state.s[i] = i; microtime (&tv); @@ -488,22 +515,22 @@ add_entropy_word(input) * are used for a high-resolution timer. * */ -void -add_timer_randomness(state, num) - struct timer_rand_state *state; - u_int num; +static void +enqueue_randomness(state, val) + register struct timer_rand_state *state; + u_int val; { int delta, delta2; u_int nbits; - u_long time; struct timeval tv; + register struct rand_event *rep; + int s; + u_long time; + + rndstats.rnd_enqs++; microtime(&tv); time = tv.tv_usec ^ tv.tv_sec; - - add_entropy_word((u_int32_t)num); - add_entropy_word(time); - /* * Calculate number of bits of randomness we probably * added. We take into account the first and second order @@ -522,22 +549,83 @@ add_timer_randomness(state, num) for (nbits = 0; delta; nbits++) delta >>= 1; - random_state.entropy_count += nbits; - + if (rnd_enqueued > QEVSLOW && nbits < QEVSBITS) { + rndstats.rnd_drops++; + return; + } + } + + s = splhigh(); + if ((rep = event_free) == NULL) { + splx(s); + rndstats.rnd_drops++; + return; + } + event_free = rep->re_next; + + rep->re_state = state; + rep->re_nbits = nbits; + rep->re_time = time; + rep->re_val = val; + + rep->re_next = event_q; + event_q = rep; + rep = rep->re_next; + splx(s); + rndstats.rnd_timer++; + rnd_enqueued++; + + if (rep == NULL) + timeout(dequeue_randomness, NULL, 1); + +} + +void +dequeue_randomness(v) + void *v; +{ + register struct rand_event *rep; + int s; + + rndstats.rnd_deqs++; + + do { + s = splhigh(); + if (event_q == NULL) { + splx(s); + return; + } + rep = event_q; + event_q = rep->re_next; + splx(s); + + add_entropy_word((u_int32_t)rep->re_val); + add_entropy_word(rep->re_time); + + random_state.entropy_count += rep->re_nbits; + rndstats.rnd_total += rep->re_nbits; + /* Prevent overflow */ if (random_state.entropy_count > POOLBITS) random_state.entropy_count = POOLBITS; - } - if (random_state.entropy_count > 8 && rnd_sleep != 0) { - rnd_sleep--; + s = splhigh(); + rep->re_next = event_free; + event_free = rep; + splx(s); + rnd_enqueued--; + + if (random_state.entropy_count > 8 && rnd_sleep != 0) { + rnd_sleep--; #ifdef DEBUG - if (rnd_debug & RD_WAIT) - printf("rnd: wakeup[%d]{%u}\n", - rnd_sleep, random_state.entropy_count); + if (rnd_debug & RD_WAIT) + printf("rnd: wakeup[%d]{%u}\n", + rnd_sleep, random_state.entropy_count); #endif - wakeup(&rnd_sleep); - } + wakeup(&rnd_sleep); + } + } while(1); + } void @@ -548,7 +636,8 @@ add_mouse_randomness(mouse_data) if (!rnd_attached) return; - add_timer_randomness(&mouse_timer_state, mouse_data); + rndstats.rnd_mouse++; + enqueue_randomness(&mouse_timer_state, mouse_data); } void @@ -559,7 +648,8 @@ add_net_randomness(isr) if (!rnd_attached) return; - add_timer_randomness(&net_timer_state, ENT_NET + isr); + rndstats.rnd_net++; + enqueue_randomness(&net_timer_state, ENT_NET + isr); } void @@ -572,6 +662,7 @@ add_disk_randomness(n) if (!rnd_attached) return; + rndstats.rnd_disk++; c = n & 0xff; n >>= 8; c ^= n & 0xff; @@ -579,7 +670,7 @@ add_disk_randomness(n) c ^= n & 0xff; n >>= 8; c ^= n & 0xff; - add_timer_randomness(&disk_timer_state, ENT_DISK + c); + enqueue_randomness(&disk_timer_state, ENT_DISK + c); } void @@ -590,7 +681,8 @@ add_tty_randomness(c) if (!rnd_attached) return; - add_timer_randomness(&tty_timer_state, ENT_TTY + c); + rndstats.rnd_tty++; + enqueue_randomness(&tty_timer_state, ENT_TTY + c); } #if POOLWORDS % 16 @@ -610,7 +702,7 @@ extract_entropy(buf, nbytes) int ret, i; MD5_CTX tmp; - add_timer_randomness(&extract_timer_state, nbytes); + enqueue_randomness(&extract_timer_state, nbytes); /* Redundant, but just in case... */ if (random_state.entropy_count > POOLBITS) @@ -656,7 +748,7 @@ extract_entropy(buf, nbytes) bcopy((caddr_t)&tmp.buffer, buf, i); nbytes -= i; buf += i; - add_timer_randomness(&extract_timer_state, nbytes); + enqueue_randomness(&extract_timer_state, nbytes); } /* Wipe data from memory */ @@ -676,6 +768,7 @@ get_random_bytes(buf, nbytes) size_t nbytes; { extract_entropy((char *) buf, nbytes); + rndstats.rnd_used += nbytes * 8; } int @@ -711,6 +804,7 @@ randomread(dev, uio, ioflag) rnd_sleep); #endif rnd_sleep++; + rndstats.rnd_waits++; ret = tsleep(&rnd_sleep, PWAIT | PCATCH, "rndrd", 0); #ifdef DEBUG @@ -721,6 +815,7 @@ randomread(dev, uio, ioflag) break; } n = min(n, random_state.entropy_count / 8); + rndstats.rnd_reads++; #ifdef DEBUG if (rnd_debug & RD_OUTPUT) printf("rnd: %u possible output\n", n); diff --git a/sys/dev/rndioctl.h b/sys/dev/rndioctl.h index 7a13f6103b1..e198087b734 100644 --- a/sys/dev/rndioctl.h +++ b/sys/dev/rndioctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rndioctl.h,v 1.2 1996/08/11 07:31:32 dm Exp $ */ +/* $OpenBSD: rndioctl.h,v 1.3 1997/06/14 21:37:08 mickey Exp $ */ /* * Copyright (c) 1996 Michael Shalayeff. @@ -38,14 +38,14 @@ #ifndef __RNDIOCTL_H__ #define __RNDIOCTL_H__ +/* ioctl()'s for the random number generator */ + struct rnd_pool_info { size_t entropy_count; size_t buf_size; u_int32_t *buf; }; -/* ioctl()'s for the random number generator */ - #define RNDGETENTCNT _IOR('R', 0, sizeof(u_int)) #define RNDADDTOENTCNT _IOW('R', 1, sizeof(u_int)) #define RNDGETPOOL _IOWR('R', 2, sizeof(struct rnd_pool_info)) diff --git a/sys/dev/rndvar.h b/sys/dev/rndvar.h index 2a9ffaf87b4..0014dfcffa4 100644 --- a/sys/dev/rndvar.h +++ b/sys/dev/rndvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rndvar.h,v 1.5 1997/01/05 11:08:59 niklas Exp $ */ +/* $OpenBSD: rndvar.h,v 1.6 1997/06/14 21:37:09 mickey Exp $ */ /* * Copyright (c) 1996 Michael Shalayeff. @@ -46,7 +46,26 @@ #define RND_ARND 4 /* aRC4 based random number generator */ #define RND_NODEV 5 /* First invalid minor device number */ +struct rndstats { + u_long rnd_total; /* total bits of entropy generated */ + u_long rnd_used; /* strong data bits read so far */ + u_long arc4_reads;/* aRC4 data bytes read so far */ + + u_long rnd_timer; /* timer calls */ + u_long rnd_mouse; /* mouse calls */ + u_long rnd_tty; /* tty calls */ + u_long rnd_disk; /* block devices calls */ + u_long rnd_net; /* net calls */ + + u_long rnd_reads; /* strong read calls */ + u_long rnd_waits; /* sleep for data */ + u_long rnd_enqs; /* enqueue calls */ + u_long rnd_deqs; /* dequeue calls */ + u_long rnd_drops; /* queue-full drops */ +}; + #ifdef _KERNEL +extern struct rndstats rndstats; extern void add_mouse_randomness __P((u_int32_t)); extern void add_net_randomness __P((int)); diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index f9d638bf1ce..604564a0aef 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sysctl.c,v 1.15 1997/03/27 04:39:35 millert Exp $ */ +/* $OpenBSD: kern_sysctl.c,v 1.16 1997/06/14 21:37:10 mickey Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- @@ -60,6 +60,7 @@ #include <sys/mount.h> #include <sys/syscallargs.h> +#include <dev/rndvar.h> #ifdef DDB #include <ddb/db_var.h> @@ -297,6 +298,9 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) return (sysctl_int(oldp, oldlenp, newp, newlen, &sominconn)); case KERN_USERMOUNT: return (sysctl_int(oldp, oldlenp, newp, newlen, &usermount)); + case KERN_RND: + return (sysctl_rdstruct(oldp, oldlenp, newp, &rndstats, + sizeof(rndstats))); default: return (EOPNOTSUPP); } diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index 1377c5eef71..7712a632634 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sysctl.h,v 1.11 1996/10/04 01:26:45 deraadt Exp $ */ +/* $OpenBSD: sysctl.h,v 1.12 1997/06/14 21:37:10 mickey Exp $ */ /* $NetBSD: sysctl.h,v 1.16 1996/04/09 20:55:36 cgd Exp $ */ /* @@ -141,7 +141,8 @@ struct ctlname { #define KERN_SOMAXCONN 28 /* int: listen queue maximum */ #define KERN_SOMINCONN 29 /* int: half-open controllable param */ #define KERN_USERMOUNT 30 /* int: users may mount filesystems */ -#define KERN_MAXID 31 /* number of valid kern ids */ +#define KERN_RND 31 /* struct: rnd(4) statistics */ +#define KERN_MAXID 32 /* number of valid kern ids */ #define CTL_KERN_NAMES { \ { 0, 0 }, \ @@ -175,6 +176,7 @@ struct ctlname { { "somaxconn", CTLTYPE_INT }, \ { "sominconn", CTLTYPE_INT }, \ { "usermount", CTLTYPE_INT }, \ + { "random", CTLTYPE_STRUCT }, \ } /* diff --git a/usr.sbin/sysctl/sysctl.8 b/usr.sbin/sysctl/sysctl.8 index 2a9e6fdbeb7..fa0511b8646 100644 --- a/usr.sbin/sysctl/sysctl.8 +++ b/usr.sbin/sysctl/sysctl.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sysctl.8,v 1.8 1997/06/13 13:50:59 mickey Exp $ +.\" $OpenBSD: sysctl.8,v 1.9 1997/06/14 21:37:11 mickey Exp $ .\" $NetBSD: sysctl.8,v 1.4 1995/09/30 07:12:49 thorpej Exp $ .\" .\" Copyright (c) 1993 @@ -136,8 +136,9 @@ privilege can change the value. .It kern.somaxconn integer yes .It kern.sominconn integer yes .It kern.usermount integer yes +.It kern.random struct no .It vm.loadavg struct no -.It vm.psstrings struct _ps_strings no +.It vm.psstrings struct no .It fs.posix.setuid integer yes .It net.inet.ip.forwarding integer yes .It net.inet.ip.redirect integer yes @@ -226,6 +227,10 @@ sysctl vm.loadavg .It Pa <sys/sysctl.h> definitions for top level identifiers, second level kernel and hardware identifiers, and user level identifiers +.It Pa <dev/rndvar.h> +definitions for +.Xr random 4 +device's statistics structure .It Pa <sys/socket.h> definitions for second level network identifiers .It Pa <sys/gmon.h> diff --git a/usr.sbin/sysctl/sysctl.c b/usr.sbin/sysctl/sysctl.c index a4867ee0deb..196026e9414 100644 --- a/usr.sbin/sysctl/sysctl.c +++ b/usr.sbin/sysctl/sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sysctl.c,v 1.7 1997/04/06 20:19:22 millert Exp $ */ +/* $OpenBSD: sysctl.c,v 1.8 1997/06/14 21:37:12 mickey Exp $ */ /* $NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $ */ /* @@ -44,7 +44,7 @@ static char copyright[] = #if 0 static char sccsid[] = "@(#)sysctl.c 8.1 (Berkeley) 6/6/93"; #else -static char *rcsid = "$OpenBSD: sysctl.c,v 1.7 1997/04/06 20:19:22 millert Exp $"; +static char *rcsid = "$OpenBSD: sysctl.c,v 1.8 1997/06/14 21:37:12 mickey Exp $"; #endif #endif /* not lint */ @@ -72,6 +72,7 @@ static char *rcsid = "$OpenBSD: sysctl.c,v 1.7 1997/04/06 20:19:22 millert Exp $ #include <netipx/ipx_var.h> #include <netipx/spx_var.h> #include <ddb/db_var.h> +#include <dev/rndvar.h> #include <errno.h> #include <stdio.h> @@ -123,6 +124,7 @@ int Aflag, aflag, nflag, wflag; #define CLOCK 0x00000001 #define BOOTTIME 0x00000002 #define CONSDEV 0x00000004 +#define RNDSTATS 0x00000008 /* prototypes */ void usage(); @@ -272,7 +274,7 @@ parse(string, flags) return; if (!nflag) fprintf(stdout, "%s: ", string); - fprintf(stderr, + fprintf(stdout, "kernel is not compiled for profiling\n"); return; } @@ -305,6 +307,9 @@ parse(string, flags) case KERN_BOOTTIME: special |= BOOTTIME; break; + case KERN_RND: + special |= RNDSTATS; + break; } break; @@ -453,6 +458,21 @@ parse(string, flags) fprintf(stdout, "0x%x\n", dev); return; } + if (special & RNDSTATS) { + struct rndstats *rndstats = (struct rndstats *)buf; + if (!nflag) + fprintf(stdout, "%s: ", string); + fprintf(stdout, + "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n", + rndstats->rnd_total, rndstats->rnd_used, + rndstats->arc4_reads, rndstats->rnd_timer, + rndstats->rnd_mouse, rndstats->rnd_tty, + rndstats->rnd_disk, rndstats->rnd_net, + rndstats->rnd_reads, rndstats->rnd_waits, + rndstats->rnd_enqs, rndstats->rnd_deqs, + rndstats->rnd_drops); + return; + } switch (type) { case CTLTYPE_INT: if (newsize == 0) { |