/* -*-c-*-
*
- * $Id: noise.c,v 1.2 1999/11/11 00:59:08 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.
*
* 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.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 <setjmp.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
/*----- Noise source definition -------------------------------------------*/
-rand_source noise_source = { noise_acquire, noise_timer };
+const rand_source noise_source = { noise_acquire, noise_timer };
/*----- Static variables --------------------------------------------------*/
* 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.
*/
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;
* 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);
* 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)
* 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)
/* --- Fork a child off --- */
+ fflush(0);
kid = fork();
if (kid < 0) {
close(fd[0]);
/* --- Handle the child end of the deal --- */
- fflush(0);
if (kid == 0) {
int f;
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
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);
}
}