From 25f654a73af995e32f18e334cb4ebb09ac158fd5 Mon Sep 17 00:00:00 2001 From: mdw Date: Sat, 17 Jun 2000 12:57:47 +0000 Subject: [PATCH] New free counter noise generator, for use if /dev/random is unavailable. --- acconfig.h | 10 ++++- configure.in | 28 ++++++++++--- noise.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++------------- noise.h | 32 +++++++++++++- 4 files changed, 167 insertions(+), 36 deletions(-) diff --git a/acconfig.h b/acconfig.h index 8de2795..a9f3737 100644 --- a/acconfig.h +++ b/acconfig.h @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: acconfig.h,v 1.2 1999/12/10 23:30:08 mdw Exp $ + * $Id: acconfig.h,v 1.3 2000/06/17 12:57:46 mdw Exp $ * * Configuration header for Catacomb * @@ -30,6 +30,10 @@ /*----- Revision history --------------------------------------------------* * * $Log: acconfig.h,v $ + * Revision 1.3 2000/06/17 12:57:46 mdw + * New free counter noise generator, for use if /dev/random is + * unavailable. + * * Revision 1.2 1999/12/10 23:30:08 mdw * Change header file guard names. * @@ -60,6 +64,10 @@ * representing time. (Probably `long'.) */ #undef time_t +/* Define if you have working `setitimer' and `sigsetjmp' functions. This + * sill enable the free counter noise generator. */ +#define USE_FREEWHEEL + @BOTTOM@ /*----- That's all, folks -------------------------------------------------*/ diff --git a/configure.in b/configure.in index 13c0c22..bef9b1b 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ dnl -*-fundamental-*- dnl -dnl $Id: configure.in,v 1.11 2000/06/17 10:51:23 mdw Exp $ +dnl $Id: configure.in,v 1.12 2000/06/17 12:57:47 mdw Exp $ dnl dnl Autoconfiguration for Catacomb dnl @@ -29,6 +29,10 @@ dnl MA 02111-1307, USA. dnl ----- Revision history -------------------------------------------------- dnl dnl $Log: configure.in,v $ +dnl Revision 1.12 2000/06/17 12:57:47 mdw +dnl New free counter noise generator, for use if /dev/random is +dnl unavailable. +dnl dnl Revision 1.11 2000/06/17 10:51:23 mdw dnl Version number changes. Find maths library for Maurer's test. dnl @@ -62,7 +66,7 @@ dnl dnl --- Boring boilerplate --- AC_INIT(blkc.h) -AM_INIT_AUTOMAKE(catacomb, 2.0.0) +AM_INIT_AUTOMAKE(catacomb, 2.0.0pre1) AM_CONFIG_HEADER(config.h) dnl --- Make sure I can compile and build libraries --- @@ -91,12 +95,26 @@ dnl --- The maths library, for Maurer's test --- mdw_CHECK_MANYLIBS(log, m,,, [#include ], [2]) mdw_CHECK_MANYLIBS(sqrt, m,,, [#include ], [2]) -dnl --- Can I call `initgroups'? --- -dnl -dnl This is used in noise-gathering. +dnl --- Functions used for noise-gathering --- AC_CHECK_FUNCS(setgroups) +AC_CACHE_CHECK([whether the freewheel noise generator will work], +[catacomb_cv_freewheel], +[AC_TRY_LINK([ +#include +#include +], +[struct itimerval itv = { { 0, 0 }, { 0, 5000 } }; +jmp_buf j; +setitimer(ITIMER_REAL, &itv, 0); +sigsetjmp(j, 1);], +[catacomb_cv_freewheel=yes], +[catacomb_cv_freewheel=no])]) +if test "$catacomb_cv_freewheel" = "yes"; then + AC_DEFINE([USE_FREEWHEEL]) +fi + dnl --- Support for the passphrase pixie --- mdw_CHECK_MANYLIBS(socket, socket) diff --git a/noise.c b/noise.c index ed2d83c..a4648f8 100644 --- a/noise.c +++ b/noise.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: noise.c,v 1.5 1999/12/22 15:57:55 mdw Exp $ + * $Id: noise.c,v 1.6 2000/06/17 12:57:47 mdw Exp $ * * Acquisition of environmental noise (Unix-specific) * @@ -30,6 +30,10 @@ /*----- Revision history --------------------------------------------------* * * $Log: noise.c,v $ + * Revision 1.6 2000/06/17 12:57:47 mdw + * New free counter noise generator, for use if /dev/random is + * unavailable. + * * Revision 1.5 1999/12/22 15:57:55 mdw * Label system-specific parts more clearly. * @@ -51,6 +55,7 @@ #include "config.h" +#include #include #include #include @@ -120,7 +125,7 @@ static int bitcount(unsigned long x) * Arguments: @rand_pool *r@ = pointer to randomness pool * @struct timeval *tv@ = pointer to time block * - * Returns: Nonzer if some randomness was contributed. + * Returns: Nonzero if some randomness was contributed. * * Use: Low-level timer contributor. */ @@ -187,7 +192,9 @@ int noise_devrandom(rand_pool *r) * needs to get some more entropy from somewhere. */ - if ((fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) >= 0) { + if ((fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK)) >= 0 || + (fd = open("/dev/arandom", O_RDONLY | O_NONBLOCK)) >= 0 || + (fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) >= 0) { if ((len = read(fd, buf, sizeof(buf))) > 0) { rand_add(r, buf, len, len * 8); BURN(buf); @@ -364,6 +371,94 @@ int noise_filter(rand_pool *r, int good, const char *c) return (ret); } +/* --- @noise_freewheel@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: Nonzero if some randomness was contributed. + * + * Use: Runs a free counter for a short while as a desparate attempt + * to get randomness from somewhere. This is actually quite + * effective. + */ + +#ifdef USE_FREEWHEEL + +static jmp_buf fwjmp; + +static void fwalarm(int sig) +{ + siglongjmp(fwjmp, 1); +} + +int noise_freewheel(rand_pool *r) +{ + void (*sigal)(int) = 0; + struct itimerval oitv, itv = { { 0, 0 }, { 0, 5000 } }; + int rc = 0; + volatile uint32 fwcount = 0; + + if (!sigsetjmp(fwjmp, 1)) { + if ((sigal = signal(SIGALRM, fwalarm)) == SIG_ERR) + return (0); + if (setitimer(ITIMER_REAL, &itv, &oitv)) + goto done; + for (;;) + fwcount++; + } else { + octet buf[4]; + STORE32(buf, fwcount); + rand_add(r, buf, sizeof(buf), 16); + rc = 1; + } + +done: + signal(SIGALRM, sigal); + TV_SUB(&oitv.it_value, &oitv.it_value, &itv.it_value); + setitimer(ITIMER_REAL, &oitv, 0); + return (rc); +} + +#else + +int noise_freewheel(rand_pool *r) +{ + return (0); +} + +#endif + +/* --- @noise_enquire@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: Nonzero if some randomness was contributed. + * + * Use: Runs some shell commands to enquire about the prevailing + * environment. This can gather quite a lot of low-quality + * entropy. + */ + +int noise_enquire(rand_pool *r) +{ + struct tab { + const char *cmd; + unsigned rate; + } tab[] = { + { "ps alxww || ps -elf", 16 }, + { "netstat -n", 6 }, + { "df", 20 }, + { "w", 6 }, + { "ls -align /tmp/.", 10 }, + { 0, 0 } + }; + int i; + + for (i = 0; tab[i].cmd; i++) + noise_filter(r, tab[i].rate, tab[i].cmd); + return (1); +} + /* --- @noise_acquire@ --- * * * Arguments: @rand_pool *r@ = pointer to a randomness pool @@ -375,33 +470,13 @@ int noise_filter(rand_pool *r, int good, const char *c) void noise_acquire(rand_pool *r) { + unsigned i; + for (i = 0; i < 8; i++) + noise_freewheel(r); if (!noise_devrandom(r)) { - - /* --- Output of `ps' --- * - * - * This is a hopefully cheap way of getting a bit of noise. I'm guessing - * the good bit ratio based on about 90 bytes per line of output, and - * each line containing maybe 12 bits worth of interesting data. (Some - * quick experiments with gzip seem to bear this idea out.) So, 12 good - * bits per 90 bytes of output gives slightly more than 17 good bits per - * 1024 bits of output. So I'll be a pessimist and say 16 bits. - */ - - (void) - (noise_filter(r, 16, "ps alxww") || - noise_filter(r, 16, "ps -elf")); - - /* --- Output of `netstat' --- * - * - * Another possibly cheap way of getting noise. My output has about - * 72 bytes per line of output. My wild guesses are telling me that - * there are probably only about four good bits per line (gzip tells - * me there's six, but I want to underestimate). Four bits per 72 bytes - * is 7 good bits per 1024 bits of output. Pessimist that I am, I'll - * call it six. - */ - - noise_filter(r, 6, "netstat -n"); + noise_enquire(r); + for (i = 0; i < 8; i++) + noise_freewheel(r); } } diff --git a/noise.h b/noise.h index b8a0050..3777a6f 100644 --- a/noise.h +++ b/noise.h @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: noise.h,v 1.3 1999/12/22 15:57:55 mdw Exp $ + * $Id: noise.h,v 1.4 2000/06/17 12:57:47 mdw Exp $ * * Acquisition of environmental noise (Unix-specific) * @@ -30,6 +30,10 @@ /*----- Revision history --------------------------------------------------* * * $Log: noise.h,v $ + * Revision 1.4 2000/06/17 12:57:47 mdw + * New free counter noise generator, for use if /dev/random is + * unavailable. + * * Revision 1.3 1999/12/22 15:57:55 mdw * Label system-specific parts more clearly. * @@ -133,6 +137,32 @@ extern void noise_setid(uid_t /*uid*/, gid_t /*gid*/); extern int noise_filter(rand_pool */*r*/, int /*good*/, const char */*c*/); +/* --- @noise_freewheel@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: Nonzero if some randomness was contributed. + * + * Use: Runs a free counter for a short while as a desparate attempt + * to get randomness from somewhere. This is actually quite + * effective. + */ + +int noise_freewheel(rand_pool */*r*/); + +/* --- @noise_enquire@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * + * Returns: Nonzero if some randomness was contributed. + * + * Use: Runs some shell commands to enquire about the prevailing + * environment. This can gather quite a lot of low-quality + * entropy. + */ + +extern int noise_enquire(rand_pool */*r*/); + /* --- @noise_acquire@ --- * * * Arguments: @rand_pool *r@ = pointer to a randomness pool -- 2.11.0