http://www.zip.com.au/~dtucker/openntpd/patches/openntpd-prngd.patch This patch adds an interface directly to egd or prngd from OpenNTPD, allowing it to be configure'd --with-builtin-arc4random and work without either a /dev/random device or OpenSSL. Index: openbsd-compat/bsd-arc4random.c =================================================================== RCS file: /usr/local/cvs/openntpd-portable/openbsd-compat/bsd-arc4random.c,v retrieving revision 1.8 diff -u -p -r1.8 bsd-arc4random.c --- openbsd-compat/bsd-arc4random.c 4 Sep 2004 13:23:26 -0000 1.8 +++ openbsd-compat/bsd-arc4random.c 14 Dec 2004 14:32:42 -0000 @@ -28,15 +28,38 @@ # include #else +#include +#include +#include + +enum entropy_dev_type { + none, + dev, /* regular /dev/random type device special */ + egd /* EGD/PRNGD socket */ +}; + +struct entropy_dev_struct { + const char *device; + enum entropy_dev_type type; +} entropy_dev[] = { + { "/dev/urandom", dev }, + { "/dev/arandom", dev }, + { "/dev/random", dev }, + { "/var/run/egd-pool", egd }, + { "/dev/egd-pool", egd }, + { "/etc/egd-pool", egd }, + { NULL, none } +}; + /* * arcfour routines from "nanocrypt" also by Damien Miller, included with * permission under the license above. * Converted to OpenSSL API by Darren Tucker. */ -#define _PATH_DEVURANDOM "/dev/urandom" - static int randfd = -1; +static char *randdev = NULL; +static enum entropy_dev_type randtype = none; typedef struct { unsigned int s[256]; @@ -89,15 +112,63 @@ RC4(RC4_KEY *r, unsigned long len, const static int RAND_status(void) { - if (randfd >= 0) + int i; + size_t len; + struct sockaddr_un sa; + + if (randfd >= 0 && randtype != none) return 1; - randfd = open(_PATH_DEVURANDOM, O_RDONLY); - return (randfd >= 0 ? 1 : 0); + + /* search for an entropy source */ + for (i = 0; entropy_dev[i].device != NULL && randtype == none; i++ ) { + randdev = entropy_dev[i].device; + switch (entropy_dev[i].type) { + case dev: + randfd = open(randdev, O_RDONLY); + if (randfd >= 0) /* success */ + randtype = entropy_dev[i].type; + break; + case egd: + if ((randfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) { + log_warn("socket"); + break; + } + memset((void *)&sa, 0, sizeof(sa)); + sa.sun_family = AF_UNIX; + strlcpy(sa.sun_path, randdev, sizeof(sa.sun_path)); + len = strlen(randdev) + sizeof(sa.sun_family); + if (connect(randfd, &sa, len) == -1) { + close(randfd); + randfd = -1; + } else { + randtype = entropy_dev[i].type; + } + break; + default: + fatal("RAND_status internal error"); + } + } + + if (randfd >= 0 && randtype != none) { + log_info("using entropy source %s type %d", randdev, randtype); + return 1; + } + return(0); } static int RAND_bytes(unsigned char *buf, size_t len) { + if (randtype == egd) { + char egdcmd[2]; + + if (len > 255) + fatal("requested more than 255 bytes from egd"); + egdcmd[0] = 0x02; /* blocking read */ + egdcmd[1] = (unsigned char)len; + if (write(randfd, egdcmd, 2) == -1) + fatal("write to egd socket"); + } if (read(randfd, buf, len) != (ssize_t)len) return 0; return 1;