X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/028b34c6d70fddf2e8af47e5e05e19074140c2a2..42ca150ce7fa024a8fd6a4c9433b613175270eb4:/noise.c diff --git a/noise.c b/noise.c index a78a790..e339317 100644 --- a/noise.c +++ b/noise.c @@ -1,13 +1,13 @@ /* -*-c-*- * - * $Id: noise.c,v 1.3 1999/12/10 23:24:11 mdw Exp $ + * $Id$ * - * Acquisition of environmental noise (Unix specific) + * Acquisition of environmental noise (Unix-specific) * * (c) 1998 Straylight/Edgeware */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of Catacomb. * @@ -15,36 +15,23 @@ * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * Catacomb is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with Catacomb; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* - * - * $Log: noise.c,v $ - * Revision 1.3 1999/12/10 23:24:11 mdw - * Bug fix: flush buffers before forking. - * - * Revision 1.2 1999/11/11 00:59:08 mdw - * A bit of reformatting. Initialize the uid and gid correctly. - * - * Revision 1.1 1999/09/03 08:41:12 mdw - * Initial import. - * - */ - /*----- Header files ------------------------------------------------------*/ #include "config.h" +#include #include #include #include @@ -74,7 +61,7 @@ /*----- Noise source definition -------------------------------------------*/ -rand_source noise_source = { noise_acquire, noise_timer }; +const rand_source noise_source = { noise_acquire, noise_timer }; /*----- Static variables --------------------------------------------------*/ @@ -114,7 +101,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. */ @@ -124,7 +111,7 @@ static int timer(rand_pool *r, struct timeval *tv) unsigned long x, d, dd; int de, dde; int ret; - + x = tv->tv_usec + MILLION * tv->tv_sec; d = x ^ noise_last; dd = d ^ noise_diff; @@ -181,7 +168,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); @@ -203,7 +192,7 @@ int noise_devrandom(rand_pool *r) * Use: Sets the user and group ids to be used by @noise_filter@ * when running child processes. This is useful to avoid * giving shell commands (even carefully written ones) undue - * privileges. + * privileges. This interface is Unix-specific */ void noise_setid(uid_t uid, gid_t gid) @@ -231,6 +220,8 @@ void noise_setid(uid_t uid, gid_t gid) * fails to complete within a short time period, it is killed. * Paranoid use of close-on-exec flags for file descriptors is * recommended. + * + * This interface is Unix-specific. */ int noise_filter(rand_pool *r, int good, const char *c) @@ -267,7 +258,6 @@ int noise_filter(rand_pool *r, int good, const char *c) /* --- Handle the child end of the deal --- */ - fflush(0); if (kid == 0) { int f; @@ -357,6 +347,96 @@ 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); + if (oitv.it_value.tv_sec || oitv.it_value.tv_usec) + 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 }, + { "ifconfig -a", 8 }, + { "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 @@ -368,33 +448,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); } }