From: damien Date: Mon, 3 Apr 2000 04:50:43 +0000 (+0000) Subject: - Wrote entropy collection routines for systems that lack /dev/random X-Git-Tag: V_1_2_3_TEST1~1 X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/commitdiff_plain/bfc9a61014eca85876c2861cbfe79042fccec9bf - Wrote entropy collection routines for systems that lack /dev/random and EGD --- diff --git a/ChangeLog b/ChangeLog index 585686e2..978c4082 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +20000403 + - Wrote entropy collection routines for systems that lack /dev/random + and EGD + 20000401 - Big OpenBSD CVS update (mainly beginnings of SSH2 infrastructure) - [auth.c session.c sshd.c auth.h] diff --git a/Makefile.in b/Makefile.in index 43870d5f..89b40848 100644 --- a/Makefile.in +++ b/Makefile.in @@ -31,7 +31,7 @@ LDFLAGS=-L. @LDFLAGS@ TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS) -LIBOBJS= atomicio.o authfd.o authfile.o bsd-bindresvport.o bsd-daemon.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o fake-getaddrinfo.o fake-getnameinfo.o fingerprint.o hostfile.o key.o log.o match.o mpaux.o nchan.o packet.o radix.o random.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o xmalloc.o +LIBOBJS= atomicio.o authfd.o authfile.o bsd-bindresvport.o bsd-daemon.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o fake-getaddrinfo.o fake-getnameinfo.o fingerprint.o hostfile.o key.o log.o match.o mpaux.o nchan.o packet.o radix.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o xmalloc.o SSHOBJS= ssh.o sshconnect.o log-client.o readconf.o clientloop.o diff --git a/README b/README index ecd82c4d..450d81c5 100644 --- a/README +++ b/README @@ -32,11 +32,6 @@ The PAM support is now more functional than the popular packages of commercial ssh-1.2.x. It checks "account" and "session" modules for all logins, not just when using password authentication. -All new code is released under a XFree style license, which is very -liberal. Please refer to the source files for details. The code in -bsd-*.[ch] is from the OpenBSD project and has its own license (again, -see the source files for details). - OpenSSH depends on Zlib[2], OpenSSL[3] and optionally PAM[4] and Dante[6]. To build the GNOME[5] pass-phrase requester (--with-gnome-askpass), you will need the GNOME libraries installed. @@ -64,10 +59,6 @@ This version of SSH is based upon code retrieved from the OpenBSD CVS repository which in turn was based on the last free version of SSH released by Tatu Ylonen. -Code in bsd-misc.[ch] and gnome-ssh-askpass.c is Copyright 1999 Damien -Miller & Internet Business Solutions and is released under a X11-style -license (see source files for details). - References - [1] http://www.lothar.com/tech/crypto/ diff --git a/acconfig.h b/acconfig.h index 32764f09..cbb3a97c 100644 --- a/acconfig.h +++ b/acconfig.h @@ -24,17 +24,8 @@ /* Location of random number pool */ #undef RANDOM_POOL -/* Are we using the Entropy gathering daemon */ -#undef HAVE_EGD - -/* Define if using the Dante SOCKS library. */ -#undef HAVE_DANTE - -/* Define if using the Socks4 SOCKS library. */ -#undef HAVE_SOCKS4 - -/* Define if using the Socks5 SOCKS library. */ -#undef HAVE_SOCKS5 +/* Location of EGD random number socket */ +#undef EGD_SOCKET /* Define if you want to install preformatted manpages.*/ #undef MANTYPE @@ -159,6 +150,23 @@ /* Detect IPv4 in IPv6 mapped addresses and treat as IPv4 */ #undef IPV4_IN_IPV6 +/* Programs used in entropy collection */ +#undef PROG_LS +#undef PROG_NETSTAT +#undef PROG_ARP +#undef PROG_IFCONFIG +#undef PROG_PS +#undef PROG_W +#undef PROG_WHO +#undef PROG_LAST +#undef PROG_LASTLOG +#undef PROG_DF +#undef PROG_VMSTAT +#undef PROG_UPTIME +#undef PROG_IPCS +#undef PROG_TAIL + + @BOTTOM@ /* ******************* Shouldn't need to edit below this line ************** */ diff --git a/bsd-misc.c b/bsd-misc.c index dd1f6a47..3186c86d 100644 --- a/bsd-misc.c +++ b/bsd-misc.c @@ -1,38 +1,31 @@ /* -** -** OpenBSD replacement routines -** -** Damien Miller -** -** Copyright 1999 Damien Miller -** Copyright 1999 Internet Business Solutions -** -** Permission is hereby granted, free of charge, to any person -** obtaining a copy of this software and associated documentation -** files (the "Software"), to deal in the Software without -** restriction, including without limitation the rights to use, copy, -** modify, merge, publish, distribute, sublicense, and/or sell copies -** of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -** KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -** WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -** AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER OR INTERNET -** BUSINESS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -** OR OTHER DEALINGS IN THE SOFTWARE. -** -** Except as contained in this notice, the name of Internet Business -** Solutions shall not be used in advertising or otherwise to promote -** the sale, use or other dealings in this Software without prior -** written authorization from Internet Business Solutions. -** -*/ + * Copyright (c) 1999-2000 Damien Miller. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Markus Friedl. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "config.h" @@ -52,7 +45,7 @@ #include "xmalloc.h" #include "ssh.h" #include "bsd-misc.h" -#include "random.h" +#include "entropy.h" #ifndef HAVE_ARC4RANDOM @@ -125,8 +118,11 @@ void arc4random_stir(void) if (rc4 == NULL) rc4 = xmalloc(sizeof(*rc4)); + + seed_rng(); + RAND_bytes(rand_buf, sizeof(rand_buf)); + seed_rng(); - get_random_bytes(rand_buf, sizeof(rand_buf)); rc4_key(rc4, rand_buf, sizeof(rand_buf)); memset(rand_buf, 0, sizeof(rand_buf)); } diff --git a/bsd-misc.h b/bsd-misc.h index 9d499c80..cdf8e2b6 100644 --- a/bsd-misc.h +++ b/bsd-misc.h @@ -1,38 +1,31 @@ /* -** -** OpenBSD replacement routines -** -** Damien Miller -** -** Copyright 1999 Damien Miller -** Copyright 1999 Internet Business Solutions -** -** Permission is hereby granted, free of charge, to any person -** obtaining a copy of this software and associated documentation -** files (the "Software"), to deal in the Software without -** restriction, including without limitation the rights to use, copy, -** modify, merge, publish, distribute, sublicense, and/or sell copies -** of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -** KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -** WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -** AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER OR INTERNET -** BUSINESS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -** OR OTHER DEALINGS IN THE SOFTWARE. -** -** Except as contained in this notice, the name of Internet Business -** Solutions shall not be used in advertising or otherwise to promote -** the sale, use or other dealings in this Software without prior -** written authorization from Internet Business Solutions. -** -*/ + * Copyright (c) 1999-2000 Damien Miller. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Markus Friedl. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef _BSD_MISC_H #define _BSD_MISC_H diff --git a/configure.in b/configure.in index 2d2fbe1a..6c9ea312 100644 --- a/configure.in +++ b/configure.in @@ -12,6 +12,36 @@ AC_CHECK_PROG(AR, ar, ar) AC_PATH_PROG(PERL, perl) AC_SUBST(PERL) +# We may need these for entropy collection +AC_PATH_PROG(PROG_LS, ls) +AC_DEFINE_UNQUOTED(PROG_LS, "$PROG_LS") +AC_PATH_PROG(PROG_NETSTAT, netstat) +AC_DEFINE_UNQUOTED(PROG_NETSTAT, "$PROG_NETSTAT") +AC_PATH_PROG(PROG_ARP, arp) +AC_DEFINE_UNQUOTED(PROG_ARP, "$PROG_ARP") +AC_PATH_PROG(PROG_IFCONFIG, ifconfig) +AC_DEFINE_UNQUOTED(PROG_IFCONFIG, "$PROG_IFCONFIG") +AC_PATH_PROG(PROG_PS, ps) +AC_DEFINE_UNQUOTED(PROG_PS, "$PROG_PS") +AC_PATH_PROG(PROG_W, w) +AC_DEFINE_UNQUOTED(PROG_W, "$PROG_W") +AC_PATH_PROG(PROG_WHO, who) +AC_DEFINE_UNQUOTED(PROG_WHO, "$PROG_WHO") +AC_PATH_PROG(PROG_LAST, last) +AC_DEFINE_UNQUOTED(PROG_LAST, "$PROG_LAST") +AC_PATH_PROG(PROG_LASTLOG, lastlog) +AC_DEFINE_UNQUOTED(PROG_LASTLOG, "$PROG_LASTLOG") +AC_PATH_PROG(PROG_DF, df) +AC_DEFINE_UNQUOTED(PROG_DF, "$PROG_DF") +AC_PATH_PROG(PROG_VMSTAT, vmstat) +AC_DEFINE_UNQUOTED(PROG_VMSTAT, "$PROG_VMSTAT") +AC_PATH_PROG(PROG_UPTIME, uptime) +AC_DEFINE_UNQUOTED(PROG_UPTIME, "$PROG_UPTIME") +AC_PATH_PROG(PROG_IPCS, ipcs) +AC_DEFINE_UNQUOTED(PROG_UPTIME, "$PROG_UPTIME") +AC_PATH_PROG(PROG_TAIL, tail) +AC_DEFINE_UNQUOTED(PROG_TAIL, "$PROG_TAIL") + if test -z "$LD" ; then LD=$CC fi @@ -110,7 +140,7 @@ fi AC_CHECK_HEADERS(bstring.h endian.h lastlog.h login.h maillock.h netdb.h netgroup.h paths.h poll.h pty.h shadow.h security/pam_appl.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h sys/poll.h sys/select.h sys/stropts.h sys/sysmacros.h sys/time.h sys/ttcompat.h stddef.h util.h utmp.h utmpx.h) # Checks for library functions. -AC_CHECK_FUNCS(arc4random bindresvport_af freeaddrinfo gai_strerror getaddrinfo getnameinfo innetgr md5_crypt mkdtemp openpty rresvport_af setenv seteuid setlogin setproctitle setreuid snprintf strlcat strlcpy updwtmpx vsnprintf _getpty) +AC_CHECK_FUNCS(arc4random bindresvport_af clock freeaddrinfo gai_strerror getaddrinfo getnameinfo getrusage innetgr md5_crypt mkdtemp openpty rresvport_af setenv seteuid setlogin setproctitle setreuid snprintf strlcat strlcpy updwtmpx vsnprintf _getpty) AC_CHECK_FUNC(login, [AC_DEFINE(HAVE_LOGIN)], @@ -604,8 +634,10 @@ AC_CHECK_FILE("/dev/ptc", AC_ARG_WITH(random, [ --with-random=FILE read randomness from FILE (default=/dev/urandom)], [ - RANDOM_POOL="$withval"; - AC_DEFINE_UNQUOTED(RANDOM_POOL, "$RANDOM_POOL") + if test "x$withval" != "xno" ; then + RANDOM_POOL="$withval"; + AC_DEFINE_UNQUOTED(RANDOM_POOL, "$RANDOM_POOL") + fi ], [ # Check for random device @@ -623,18 +655,13 @@ AC_ARG_WITH(random, AC_ARG_WITH(egd-pool, [ --with-egd-pool=FILE read randomness from EGD pool FILE (default none)], [ - RANDOM_POOL="$withval"; - AC_DEFINE(HAVE_EGD) - AC_SUBST(RANDOM_POOL) - AC_DEFINE_UNQUOTED(RANDOM_POOL, "$RANDOM_POOL") + if test "x$withval" != "xno" ; then + EGD_SOCKET="$withval"; + AC_DEFINE_UNQUOTED(EGD_SOCKET, "$EGD_SOCKET") + fi ] ) -# Make sure we have some random number support -if test -z "$RANDOM_POOL" -a -z "$EGD_POOL"; then - AC_MSG_ERROR([No random device found, and no EGD random pool specified]) -fi - AC_ARG_WITH(catman, [ --with-catman=man|cat Install preformatted manpages[no]], [ diff --git a/entropy.c b/entropy.c new file mode 100644 index 00000000..a1fe80cd --- /dev/null +++ b/entropy.c @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2000 Damien Miller. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Markus Friedl. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#include "ssh.h" +#include "xmalloc.h" + +#ifdef HAVE_OPENSSL +# include +# include +#endif +#ifdef HAVE_SSL +# include +# include +#endif + +RCSID("$Id$"); + +#ifdef EGD_SOCKET +#ifndef offsetof +# define offsetof(type, member) ((size_t) &((type *)0)->member) +#endif +/* Collect entropy from EGD */ +void get_random_bytes(unsigned char *buf, int len) +{ + static int egd_socket = -1; + int c; + char egd_message[2] = { 0x02, 0x00 }; + struct sockaddr_un addr; + int addr_len; + + memset(&addr, '\0', sizeof(addr)); + addr.sun_family = AF_UNIX; + + /* FIXME: compile time check? */ + if (sizeof(EGD_SOCKET) > sizeof(addr.sun_path)) + fatal("Random pool path is too long"); + + strcpy(addr.sun_path, EGD_SOCKET); + + addr_len = offsetof(struct sockaddr_un, sun_path) + sizeof(EGD_SOCKET); + + if (egd_socket == -1) { + egd_socket = socket(AF_UNIX, SOCK_STREAM, 0); + if (egd_socket == -1) + fatal("Couldn't create AF_UNIX socket: %s", strerror(errno)); + if (connect(egd_socket, (struct sockaddr*)&addr, addr_len) == -1) + fatal("Couldn't connect to EGD socket \"%s\": %s", addr.sun_path, strerror(errno)); + } + + if (len > 255) + fatal("Too many bytes to read from EGD"); + + /* Send blocking read request to EGD */ + egd_message[1] = len; + + c = atomicio(write, egd_socket, egd_message, sizeof(egd_message)); + if (c == -1) + fatal("Couldn't write to EGD socket \"%s\": %s", EGD_SOCKET, strerror(errno)); + + c = atomicio(read, egd_socket, buf, len); + if (c <= 0) + fatal("Couldn't read from EGD socket \"%s\": %s", EGD_SOCKET, strerror(errno)); + + close(EGD_SOCKET); +} +#else /* !EGD_SOCKET */ +#ifdef RANDOM_POOL +/* Collect entropy from /dev/urandom or pipe */ +void get_random_bytes(unsigned char *buf, int len) +{ + static int random_pool = -1; + int c; + + if (random_pool == -1) { + random_pool = open(RANDOM_POOL, O_RDONLY); + if (random_pool == -1) + fatal("Couldn't open random pool \"%s\": %s", RANDOM_POOL, strerror(errno)); + } + + verbose("randfd: %i", random_pool); + + c = atomicio(read, random_pool, buf, len); + if (c <= 0) + fatal("Couldn't read from random pool \"%s\": %s", RANDOM_POOL, strerror(errno)); +} +#endif /* RANDOM_POOL */ +#endif /* EGD_SOCKET */ + +#if !defined(EGD_SOCKET) && !defined(RANDOM_POOL) +/* + * FIXME: proper entropy estimations. All current values are guesses + * FIXME: Need timeout for slow moving programs + * FIXME: More entropy sources + */ + +double stir_from_system(void); +double stir_from_programs(void); +double stir_gettimeofday(double entropy_estimate); +double stir_clock(double entropy_estimate); +double stir_rusage(int who, double entropy_estimate); +double hash_output_from_command(const char *path, const char **args, char *hash); + +typedef struct +{ + /* Proportion of data that is entropy */ + double rate; + /* Path to executable */ + const char *path; + /* argv to pass to executable */ + const char *args[5]; +} entropy_source_t; + +entropy_source_t entropy_sources[] = { +#ifdef PROG_LS + { 0.002, PROG_LS, { "ls", "-alni", "/var/log", NULL } }, + { 0.002, PROG_LS, { "ls", "-alni", "/var/adm", NULL } }, + { 0.002, PROG_LS, { "ls", "-alni", "/var/mail", NULL } }, + { 0.002, PROG_LS, { "ls", "-alni", "/var/spool/mail", NULL } }, + { 0.002, PROG_LS, { "ls", "-alni", "/proc", NULL } }, + { 0.002, PROG_LS, { "ls", "-alni", "/tmp", NULL } }, +#endif +#ifdef PROG_NETSTAT + { 0.005, PROG_NETSTAT, { "netstat","-an", NULL, NULL } }, + { 0.010, PROG_NETSTAT, { "netstat","-in", NULL, NULL } }, + { 0.002, PROG_NETSTAT, { "netstat","-rn", NULL, NULL } }, + { 0.002, PROG_NETSTAT, { "netstat","-s", NULL, NULL } }, +#endif +#ifdef PROG_ARP + { 0.002, PROG_ARP, { "arp","-a","-n", NULL } }, +#endif +#ifdef PROG_IFCONFIG + { 0.002, PROG_IFCONFIG, { "ifconfig", "-a", NULL, NULL } }, +#endif +#ifdef PROG_PS + { 0.003, PROG_PS, { "ps", "laxww", NULL, NULL } }, + { 0.003, PROG_PS, { "ps", "-al", NULL, NULL } }, + { 0.003, PROG_PS, { "ps", "-efl", NULL, NULL } }, +#endif +#ifdef PROG_W + { 0.005, PROG_W, { "w", NULL, NULL, NULL } }, +#endif +#ifdef PROG_WHO + { 0.001, PROG_WHO, { "who","-i", NULL, NULL } }, +#endif +#ifdef PROG_LAST + { 0.001, PROG_LAST, { "last", NULL, NULL, NULL } }, +#endif +#ifdef PROG_LASTLOG + { 0.001, PROG_LASTLOG, { "lastlog", NULL, NULL, NULL } }, +#endif +#ifdef PROG_DF + { 0.010, PROG_DF, { "df", NULL, NULL, NULL } }, + { 0.010, PROG_DF, { "df", "-i", NULL, NULL } }, +#endif +#ifdef PROG_VMSTAT + { 0.010, PROG_VMSTAT, { "vmstat", NULL, NULL, NULL } }, +#endif +#ifdef PROG_UPTIME + { 0.001, PROG_UPTIME, { "uptime", NULL, NULL, NULL } }, +#endif +#ifdef PROG_IPCS + { 0.001, PROG_IPCS, { "-a", NULL, NULL, NULL } }, +#endif +#ifdef PROG_TAIL + { 0.001, PROG_TAIL, { "tail", "-200", "/var/log/messages", NULL, NULL } }, + { 0.001, PROG_TAIL, { "tail", "-200", "/var/log/syslog", NULL, NULL } }, + { 0.001, PROG_TAIL, { "tail", "-200", "/var/adm/messages", NULL, NULL } }, + { 0.001, PROG_TAIL, { "tail", "-200", "/var/adm/syslog", NULL, NULL } }, + { 0.001, PROG_TAIL, { "tail", "-200", "/var/log/maillog", NULL, NULL } }, + { 0.001, PROG_TAIL, { "tail", "-200", "/var/adm/maillog", NULL, NULL } }, +#endif + { 0.000, NULL, { NULL, NULL, NULL, NULL, NULL } }, +}; + + +double +stir_from_system(void) +{ + double total_entropy_estimate; + long int i; + + total_entropy_estimate = 0; + + i = getpid(); + RAND_add(&i, sizeof(i), 0.1); + total_entropy_estimate += 0.1; + + i = getppid(); + RAND_add(&i, sizeof(i), 0.1); + total_entropy_estimate += 0.1; + + i = getuid(); + RAND_add(&i, sizeof(i), 0.0); + i = getgid(); + RAND_add(&i, sizeof(i), 0.0); + + total_entropy_estimate += stir_gettimeofday(1.0); + total_entropy_estimate += stir_clock(0.2); + total_entropy_estimate += stir_rusage(RUSAGE_SELF, 2.0); + + return(total_entropy_estimate); +} + +double +stir_from_programs(void) +{ + int i; + int c; + double entropy_estimate; + double total_entropy_estimate; + char hash[SHA_DIGEST_LENGTH]; + + /* + * Run through list of programs twice to catch differences + */ + total_entropy_estimate = 0; + for(i = 0; i < 2; i++) { + c = 0; + while (entropy_sources[c].path != NULL) { + /* Hash output from command */ + entropy_estimate = hash_output_from_command(entropy_sources[c].path, + entropy_sources[c].args, hash); + + /* Scale back entropy estimate according to command's rate */ + entropy_estimate *= entropy_sources[c].rate; + + /* Upper bound of entropy estimate is SHA_DIGEST_LENGTH */ + if (entropy_estimate > SHA_DIGEST_LENGTH) + entropy_estimate = SHA_DIGEST_LENGTH; + + /* * Scale back estimates for subsequent passes through list */ + entropy_estimate /= 10.0 * (i + 1.0); + + /* Stir it in */ + RAND_add(hash, sizeof(hash), entropy_estimate); + +/* FIXME: turn this off later */ +#if 1 + debug("Got %0.2f bytes of entropy from %s", entropy_estimate, + entropy_sources[c].path); +#endif + + total_entropy_estimate += entropy_estimate; + + /* Execution times should be a little unpredictable */ + total_entropy_estimate += stir_gettimeofday(0.05); + total_entropy_estimate += stir_clock(0.05); + total_entropy_estimate += stir_rusage(RUSAGE_SELF, 0.1); + total_entropy_estimate += stir_rusage(RUSAGE_CHILDREN, 0.1); + + c++; + } + } + + return(total_entropy_estimate); +} + +double +stir_gettimeofday(double entropy_estimate) +{ + struct timeval tv; + + if (gettimeofday(&tv, NULL) == -1) + fatal("Couldn't gettimeofday: %s", strerror(errno)); + + RAND_add(&tv, sizeof(tv), entropy_estimate); + + return(entropy_estimate); +} + +double +stir_clock(double entropy_estimate) +{ +#ifdef HAVE_CLOCK + clock_t c; + + c = clock(); + RAND_add(&c, sizeof(c), entropy_estimate); + + return(entropy_estimate); +#else /* _HAVE_CLOCK */ + return(0); +#endif /* _HAVE_CLOCK */ +} + +double +stir_rusage(int who, double entropy_estimate) +{ +#ifdef HAVE_GETRUSAGE + struct rusage ru; + + if (getrusage(who, &ru) == -1) + fatal("Couldn't getrusage: %s", strerror(errno)); + + RAND_add(&ru, sizeof(ru), 0.1); + + return(entropy_estimate); +#else /* _HAVE_GETRUSAGE */ + return(0); +#endif /* _HAVE_GETRUSAGE */ +} + +double +hash_output_from_command(const char *path, const char **args, char *hash) +{ + static int devnull = -1; + int p[2]; + pid_t pid; + int status; + char buf[2048]; + int bytes_read; + int total_bytes_read; + SHA_CTX sha; + + if (devnull == -1) { + devnull = open("/dev/null", O_RDWR); + if (devnull == -1) + fatal("Couldn't open /dev/null: %s", strerror(errno)); + } + + if (pipe(p) == -1) + fatal("Couldn't open pipe: %s", strerror(errno)); + + switch (pid = fork()) { + case -1: /* Error */ + close(p[0]); + close(p[1]); + fatal("Couldn't fork: %s", strerror(errno)); + /* NOTREACHED */ + case 0: /* Child */ + close(0); + close(1); + close(2); + dup2(devnull, 0); + dup2(p[1], 1); + dup2(p[1], 2); + close(p[0]); + close(p[1]); + close(devnull); + + execv(path, (char**)args); + debug("(child) Couldn't exec '%s': %s", path, strerror(errno)); + _exit(-1); + default: /* Parent */ + break; + } + + RAND_add(&pid, sizeof(&pid), 0.0); + + close(p[1]); + + /* Hash output from child */ + SHA1_Init(&sha); + total_bytes_read = 0; + while ((bytes_read = read(p[0], buf, sizeof(buf))) > 0) { + SHA1_Update(&sha, buf, bytes_read); + total_bytes_read += bytes_read; + RAND_add(&bytes_read, sizeof(&bytes_read), 0.0); + } + SHA1_Final(hash, &sha); + + close(p[0]); + + if (waitpid(pid, &status, 0) == -1) { + error("Couldn't wait for child '%s' completion: %s", path, + strerror(errno)); + return(-1); + } + + RAND_add(&status, sizeof(&status), 0.0); + + if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) + return(0.0); + else + return(total_bytes_read); +} +#endif /* defined(EGD_SOCKET) || defined(RANDOM_POOL) */ + +#if defined(EGD_SOCKET) || defined(RANDOM_POOL) +/* + * Seed OpenSSL's random number pool from Kernel random number generator + * or EGD + */ +void +seed_rng(void) +{ + char buf[32]; + + debug("Seeding random number generator"); + get_random_bytes(buf, sizeof(buf)); + RAND_add(buf, sizeof(buf), sizeof(buf)); + memset(buf, '\0', sizeof(buf)); +} +#else /* defined(EGD_SOCKET) || defined(RANDOM_POOL) */ +/* + * Conditionally Seed OpenSSL's random number pool syscalls and program output + */ +void +seed_rng(void) +{ + if (!RAND_status()) { + debug("Seeding random number generator."); + debug("%i bytes from system calls", (int)stir_from_system()); + debug("%i bytes from programs", (int)stir_from_programs()); + debug("OpenSSL random status is now %i\n", RAND_status()); + } +} +#endif /* defined(EGD_SOCKET) || defined(RANDOM_POOL) */ diff --git a/entropy.h b/entropy.h new file mode 100644 index 00000000..ec425a0c --- /dev/null +++ b/entropy.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 1999-2000 Damien Miller. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Markus Friedl. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RANDOMS_H +#define _RANDOMS_H + +void seed_rng(void); + +#endif /* _RANDOMS_H */ diff --git a/random.c b/random.c deleted file mode 100644 index 06c8d2b3..00000000 --- a/random.c +++ /dev/null @@ -1,124 +0,0 @@ -/* -** -** Random number collection -** -** Damien Miller -** -** Copyright 1999 Damien Miller -** -** Permission is hereby granted, free of charge, to any person -** obtaining a copy of this software and associated documentation -** files (the "Software"), to deal in the Software without -** restriction, including without limitation the rights to use, copy, -** modify, merge, publish, distribute, sublicense, and/or sell copies -** of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -** KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -** WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -** AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER OR INTERNET -** BUSINESS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -** OR OTHER DEALINGS IN THE SOFTWARE. -** -** Except as contained in this notice, the name of Internet Business -** Solutions shall not be used in advertising or otherwise to promote -** the sale, use or other dealings in this Software without prior -** written authorization from Internet Business Solutions. -** -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#ifdef HAVE_STDDEF_H -#include -#endif - -#include "ssh.h" -#include "xmalloc.h" -#include "random.h" - -#ifndef offsetof -# define offsetof(type, member) ((size_t) &((type *)0)->member) -#endif - -#ifdef HAVE_EGD - -/* Collect entropy from EGD */ -void get_random_bytes(unsigned char *buf, int len) -{ - static int random_pool; - int c; - char egd_message[2] = { 0x02, 0x00 }; - struct sockaddr_un addr; - int addr_len; - - memset(&addr, '\0', sizeof(addr)); - addr.sun_family = AF_UNIX; - - /* FIXME: compile time check? */ - if (sizeof(RANDOM_POOL) > sizeof(addr.sun_path)) - fatal("Random pool path is too long"); - - strcpy(addr.sun_path, RANDOM_POOL); - - addr_len = offsetof(struct sockaddr_un, sun_path) + sizeof(RANDOM_POOL); - - random_pool = socket(AF_UNIX, SOCK_STREAM, 0); - - if (random_pool == -1) - fatal("Couldn't create AF_UNIX socket: %s", strerror(errno)); - - if (connect(random_pool, (struct sockaddr*)&addr, addr_len) == -1) - fatal("Couldn't connect to EGD socket \"%s\": %s", addr.sun_path, strerror(errno)); - - if (len > 255) - fatal("Too many bytes to read from EGD"); - - /* Send blocking read request to EGD */ - egd_message[1] = len; - - c = atomicio(write, random_pool, egd_message, sizeof(egd_message)); - if (c == -1) - fatal("Couldn't write to EGD socket \"%s\": %s", RANDOM_POOL, strerror(errno)); - - c = atomicio(read, random_pool, buf, len); - if (c <= 0) - fatal("Couldn't read from random pool \"%s\": %s", RANDOM_POOL, strerror(errno)); - - close(random_pool); -} -#else /* HAVE_EGD */ - -/* Collect entropy from /dev/urandom or pipe */ -void get_random_bytes(unsigned char *buf, int len) -{ - static int random_pool; - int c; - - random_pool = open(RANDOM_POOL, O_RDONLY); - if (random_pool == -1) - fatal("Couldn't open random pool \"%s\": %s", RANDOM_POOL, strerror(errno)); - - c = atomicio(read, random_pool, buf, len); - if (c <= 0) - fatal("Couldn't read from random pool \"%s\": %s", RANDOM_POOL, strerror(errno)); - - close(random_pool); -} - -#endif /* HAVE_EGD */ diff --git a/random.h b/random.h deleted file mode 100644 index 6eb9f3a9..00000000 --- a/random.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -** -** Random number collection -** -** Damien Miller -** -** Copyright 1999 Damien Miller -** -** Permission is hereby granted, free of charge, to any person -** obtaining a copy of this software and associated documentation -** files (the "Software"), to deal in the Software without -** restriction, including without limitation the rights to use, copy, -** modify, merge, publish, distribute, sublicense, and/or sell copies -** of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -** KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -** WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -** AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER OR INTERNET -** BUSINESS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -** OR OTHER DEALINGS IN THE SOFTWARE. -** -** Except as contained in this notice, the name of Internet Business -** Solutions shall not be used in advertising or otherwise to promote -** the sale, use or other dealings in this Software without prior -** written authorization from Internet Business Solutions. -** -*/ - -#ifndef _RANDOM_H -#define _RANDOM_H - -void get_random_bytes(unsigned char *buf, int len); - -#endif /* _RANDOM_H */ diff --git a/rsa.c b/rsa.c index 5cc987df..4d52251c 100644 --- a/rsa.c +++ b/rsa.c @@ -40,23 +40,10 @@ RCSID("$Id$"); #include "rsa.h" #include "ssh.h" #include "xmalloc.h" -#include "random.h" +#include "entropy.h" int rsa_verbose = 1; -/* - * Seed OpenSSL's random number generator - */ -void -seed_rng() -{ - char buf[64]; - - get_random_bytes(buf, sizeof(buf)); - RAND_seed(buf, sizeof(buf)); - memset(buf, 0, sizeof(buf)); -} - int rsa_alive() { @@ -109,6 +96,8 @@ rsa_generate_key(RSA *prv, RSA *pub, unsigned int bits) if (key == NULL) fatal("rsa_generate_key: key generation failed."); + seed_rng(); + /* Copy public key parameters */ pub->n = BN_new(); BN_copy(pub->n, key->n);