Patch to enable multiple possible sources of entropy

mouring at etoh.eviladmin.org mouring at etoh.eviladmin.org
Mon Jun 11 03:49:18 EST 2001


Hmm.. my only complaints about the patch is that seed_rng and init_rng are
pretty unreadable due to #ifdef/#end, and that I don't know if I like the
idea of ssh/sshd stepping down in entropy quality on a whim.  Which is
what this patch would do if for some odd reason prngd is offline at
startup of sshd/ssh.

- Ben

On Thu, 7 Jun 2001, Dave Dykstra wrote:

> I have a need to have the same OpenSSH binaries run on multiple machines
> which are administered by different people.  That means on Solaris, for
> example, there will be some with /dev/random, some on which I can run prngd
> because they'll be installing my binaries as root, and some which will have
> neither because they will be only installed as non-root.  Below is a patch
> to enable choosing all 3 possible sources at compile time, with the
> available source selected at run time.  If no configure parameters are
> given, it will still determine the entropy source at compile time and only
> the code for the one type, exactly as it does today.  The patch adds a
> configure option called --with-builtin-entropy.
>
> I have tested this in all possible combinations of entropy sources, and on
> 6 different flavors of Unix (linux, solaris, sunos4, hpux, irix, and
> unixware1).  The patch is against 2.9p1 but applies cleanly to the current
> CVS.  Please accept this patch into the openssh code base.  Don't forget to
> run autoheader and autoconf.
>
> - Dave Dykstra
>
> *** entropy.c.O	Fri Jun  1 15:52:20 2001
> --- entropy.c	Tue Jun  5 17:41:47 2001
> ***************
> *** 80,91 ****
>   # define USE_PRNGD
>   #endif
>
> - #if defined(USE_PRNGD) || defined(RANDOM_POOL)
> -
>   #ifdef USE_PRNGD
>   /* Collect entropy from PRNGD/EGD */
>   int
> ! get_random_bytes(unsigned char *buf, int len)
>   {
>   	int fd;
>   	char msg[2];
> --- 80,89 ----
>   # define USE_PRNGD
>   #endif
>
>   #ifdef USE_PRNGD
>   /* Collect entropy from PRNGD/EGD */
>   int
> ! prngd_get_random_bytes(unsigned char *buf, int len)
>   {
>   	int fd;
>   	char msg[2];
> ***************
> *** 100,110 ****
> --- 98,110 ----
>   	memset(&addr, '\0', sizeof(addr));
>
>   #ifdef PRNGD_PORT
> + 	debug2("Opening entropy socket on localhost port %d", PRNGD_PORT);
>   	addr.sin_family = AF_INET;
>   	addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
>   	addr.sin_port = htons(PRNGD_PORT);
>   	addr_len = sizeof(struct sockaddr_in);
>   #else /* use IP socket PRNGD_SOCKET instead */
> + 	debug2("Opening entropy socket at %s", PRNGD_SOCKET);
>   	/* Sanity checks */
>   	if (sizeof(PRNGD_SOCKET) > sizeof(addr.sun_path))
>   		fatal("Random pool path is too long");
> ***************
> *** 179,192 ****
>   		close(fd);
>   	return(rval);
>   }
> ! #else /* !USE_PRNGD */
>   #ifdef RANDOM_POOL
>   /* Collect entropy from /dev/urandom or pipe */
>   int
> ! get_random_bytes(unsigned char *buf, int len)
>   {
>   	int random_pool;
>
>   	random_pool = open(RANDOM_POOL, O_RDONLY);
>   	if (random_pool == -1) {
>   		error("Couldn't open random pool \"%s\": %s",
> --- 179,194 ----
>   		close(fd);
>   	return(rval);
>   }
> ! #endif /* !USE_PRNGD */
> !
>   #ifdef RANDOM_POOL
>   /* Collect entropy from /dev/urandom or pipe */
>   int
> ! pool_get_random_bytes(unsigned char *buf, int len)
>   {
>   	int random_pool;
>
> + 	debug2("Opening random pool at %s", RANDOM_POOL);
>   	random_pool = open(RANDOM_POOL, O_RDONLY);
>   	if (random_pool == -1) {
>   		error("Couldn't open random pool \"%s\": %s",
> ***************
> *** 206,242 ****
>   	return(1);
>   }
>   #endif /* RANDOM_POOL */
> - #endif /* USE_PRNGD */
> -
> - /*
> -  * Seed OpenSSL's random number pool from Kernel random number generator
> -  * or PRNGD/EGD
> -  */
> - void
> - seed_rng(void)
> - {
> - 	unsigned char buf[32];
> -
> - 	debug("Seeding random number generator");
> -
> - 	if (!get_random_bytes(buf, sizeof(buf))) {
> - 		if (!RAND_status())
> - 			fatal("Entropy collection failed and entropy exhausted");
> - 	} else {
> - 		RAND_add(buf, sizeof(buf), sizeof(buf));
> - 	}
> -
> - 	memset(buf, '\0', sizeof(buf));
> - }
> -
> - void
> - init_rng(void)
> - {
> - 	check_openssl_version();
> - }
> -
> - #else /* defined(USE_PRNGD) || defined(RANDOM_POOL) */
>
>   /*
>    * FIXME: proper entropy estimations. All current values are guesses
>    * FIXME: (ATL) do estimates at compile time?
> --- 208,215 ----
>   	return(1);
>   }
>   #endif /* RANDOM_POOL */
>
> + #ifdef USE_BUILTIN_ENTROPY
>   /*
>    * FIXME: proper entropy estimations. All current values are guesses
>    * FIXME: (ATL) do estimates at compile time?
> ***************
> *** 834,840 ****
>    * syscalls and program output
>    */
>   void
> ! seed_rng(void)
>   {
>   	mysig_t old_sigchld_handler;
>
> --- 807,813 ----
>    * syscalls and program output
>    */
>   void
> ! prng_seed_rng(void)
>   {
>   	mysig_t old_sigchld_handler;
>
> ***************
> *** 860,871 ****
>   }
>
>   void
> ! init_rng(void)
>   {
>   	int original_euid;
>
> - 	check_openssl_version();
> -
>   	original_uid = getuid();
>   	original_euid = geteuid();
>
> --- 833,842 ----
>   }
>
>   void
> ! prng_init_rng(void)
>   {
>   	int original_euid;
>
>   	original_uid = getuid();
>   	original_euid = geteuid();
>
> ***************
> *** 912,915 ****
>   	prng_initialised = 1;
>   }
>
> ! #endif /* defined(USE_PRNGD) || defined(RANDOM_POOL) */
> --- 883,979 ----
>   	prng_initialised = 1;
>   }
>
> ! #endif /* USE_BUILTIN_ENTROPY */
> !
> ! #define BUILTIN_SOURCE 1
> ! #define PRNGD_SOURCE 2
> ! #define POOL_SOURCE 3
> !
> ! static int seed_source = 0;
> !
> ! void
> ! init_rng(void)
> ! {
> ! 	check_openssl_version();
> !
> ! #ifdef RANDOM_POOL
> ! #if !defined(USE_PRNGD) && !defined(USE_BUILTIN_ENTROPY)
> ! 	seed_source = POOL_SOURCE;
> ! #else
> ! 	if (access(RANDOM_POOL, R_OK) == 0) {
> ! 		seed_source = POOL_SOURCE;
> ! 		return;
> ! 	}
> ! #endif
> ! #endif /* RANDOM_POOL */
> !
> ! /* it's not trivial to probe for an open port so just make it
> !  *  take priority over the other sources if it is defined
> !  */
> ! #ifdef PRNGD_PORT
> ! 	seed_source = PRNGD_SOURCE;
> ! #else
> !
> ! #ifdef PRNGD_SOCKET
> ! #ifndef USE_BUILTIN_ENTROPY
> ! 	seed_source = PRNGD_SOURCE;
> ! #else
> ! 	if (access(PRNGD_SOCKET, R_OK) == 0) {
> ! 		seed_source = PRNGD_SOURCE;
> ! 		return;
> ! 	}
> ! #endif /* USE_BUILTIN_ENTROPY */
> ! #endif /* PRNGD_SOCKET */
> !
> ! #ifdef USE_BUILTIN_ENTROPY
> ! 	seed_source = BUILTIN_SOURCE;
> ! 	prng_init_rng();
> ! #endif
> !
> ! #endif /* PRNGD_PORT */
> !
> ! 	if (seed_source == 0)
> ! 		fatal("Couldn't find source for random number generator seed");
> ! }
> !
> ! /*
> !  * Seed OpenSSL's random number pool
> !  */
> ! void
> ! seed_rng(void)
> ! {
> ! 	unsigned char buf[32];
> ! 	int ret;
> !
> ! 	debug("Seeding random number generator");
> !
> ! 	switch (seed_source) {
> ! #ifdef USE_BUILTIN_ENTROPY
> ! 	case BUILTIN_SOURCE:
> ! 		prng_seed_rng();
> ! 		return;
> ! #endif
> ! #ifdef USE_PRNGD
> ! 	case PRNGD_SOURCE:
> ! 		ret = prngd_get_random_bytes(buf, sizeof(buf));
> ! 		break;
> ! #endif
> ! #ifdef RANDOM_POOL
> ! 	case POOL_SOURCE:
> ! 		ret = pool_get_random_bytes(buf, sizeof(buf));
> ! 		break;
> ! #endif
> ! 	}
> !
> ! #if defined(USE_PRNGD) || defined(RANDOM_POOL)
> ! 	if (!ret) {
> ! 		if (!RAND_status())
> ! 			fatal("Entropy collection failed and entropy exhausted");
> ! 	} else {
> ! 		RAND_add(buf, sizeof(buf), sizeof(buf));
> ! 	}
> !
> ! 	memset(buf, '\0', sizeof(buf));
> ! #endif
> ! }
> !
> *** configure.in.O	Mon Jun  4 12:25:12 2001
> --- configure.in	Thu Jun  7 13:37:09 2001
> ***************
> *** 1334,1340 ****
>   	]
>   )
>
> ! # Check for PRNGD/EGD pool file
>   AC_ARG_WITH(prngd-port,
>   	[  --with-prngd-port=PORT  read entropy from PRNGD/EGD localhost:PORT],
>   	[
> --- 1334,1340 ----
>   	]
>   )
>
> ! # Check for PRNGD/EGD pool port request
>   AC_ARG_WITH(prngd-port,
>   	[  --with-prngd-port=PORT  read entropy from PRNGD/EGD localhost:PORT],
>   	[
> ***************
> *** 1349,1354 ****
> --- 1349,1357 ----
>   AC_ARG_WITH(prngd-socket,
>   	[  --with-prngd-socket=FILE read entropy from PRNGD/EGD socket FILE (default=/var/run/egd-pool)],
>   	[
> + 		if test ! -z "$PRNGD_PORT" ; then
> + 			AC_MSG_ERROR([*** cannot use both --with-prngd-port and --with-prngd-socket])
> + 		fi
>   		if test "x$withval" != "xno" ; then
>   			PRNGD_SOCKET="$withval"
>   			AC_DEFINE_UNQUOTED(PRNGD_SOCKET, "$PRNGD_SOCKET")
> ***************
> *** 1375,1385 ****
>   	]
>   )
>
>
>   # detect pathnames for entropy gathering commands, if we need them
>   INSTALL_SSH_PRNG_CMDS=""
>   rm -f prng_commands
> ! if (test -z "$RANDOM_POOL" && test -z "$PRNGD") ; then
>   	# Use these commands to collect entropy
>   	OSSH_PATH_ENTROPY_PROG(PROG_LS, ls)
>   	OSSH_PATH_ENTROPY_PROG(PROG_NETSTAT, netstat)
> --- 1378,1406 ----
>   	]
>   )
>
> + # Check for use of builtin entropy collector
> + AC_ARG_WITH(builtin-entropy,
> + 	[  --with-builtin-entropy  use builtin entropy collector if nothing else available],
> + 	[
> + 		if test ! -z "$PRNGD_PORT" ; then
> + 			AC_MSG_ERROR([*** cannot use both --with-prngd-port and --with-builtin-entropy])
> + 		fi
> + 		BUILTIN_RNG=1
> + 	],
> + 	[
> + 		# Only select by default if don't have another method
> + 		if test -z "$RANDOM_POOL" && test -z "$PRNGD" ; then
> + 			BUILTIN_RNG=1
> + 		fi
> + 	]
> + )
>
>   # detect pathnames for entropy gathering commands, if we need them
>   INSTALL_SSH_PRNG_CMDS=""
>   rm -f prng_commands
> ! if test ! -z "$BUILTIN_RNG" ; then
> ! 	AC_DEFINE(USE_BUILTIN_ENTROPY)
> !
>   	# Use these commands to collect entropy
>   	OSSH_PATH_ENTROPY_PROG(PROG_LS, ls)
>   	OSSH_PATH_ENTROPY_PROG(PROG_NETSTAT, netstat)
> ***************
> *** 1885,1901 ****
>
>   # Print summary of options
>
> ! if test ! -z "$RANDOM_POOL" ; then
> ! 	RAND_MSG="Device ($RANDOM_POOL)"
> ! else
> ! 	if test ! -z "$PRNGD_PORT" ; then
> ! 		RAND_MSG="PRNGD/EGD (port localhost:$PRNGD_PORT)"
> ! 	elif test ! -z "$PRNGD_SOCKET" ; then
> ! 		RAND_MSG="PRNGD/EGD (socket $PRNGD_SOCKET)"
>   	else
> ! 		RAND_MSG="Builtin (timeout $entropy_timeout)"
> ! 		BUILTIN_RNG=1
>   	fi
>   fi
>
>   # Someone please show me a better way :)
> --- 1906,1930 ----
>
>   # Print summary of options
>
> ! RAND_MSG=""
> ! randmsg()
> ! {
> ! 	if test -z "$RAND_MSG" ; then
> ! 		RAND_MSG="$1"
>   	else
> ! 		RAND_MSG="$RAND_MSG or $1"
>   	fi
> + }
> + if test ! -z "$RANDOM_POOL" ; then
> + 	randmsg "Device ($RANDOM_POOL)"
> + fi
> + if test ! -z "$PRNGD_PORT" ; then
> + 	randmsg "PRNGD/EGD (port localhost:$PRNGD_PORT)"
> + elif test ! -z "$PRNGD_SOCKET" ; then
> + 	randmsg "PRNGD/EGD (socket $PRNGD_SOCKET)"
> + fi
> + if test ! -z "$BUILTIN_RNG" ; then
> + 	randmsg "Builtin (timeout $entropy_timeout)"
>   fi
>
>   # Someone please show me a better way :)
> *** acconfig.h.O	Mon Jun  4 12:42:09 2001
> --- acconfig.h	Mon Jun  4 13:53:36 2001
> ***************
> *** 95,100 ****
> --- 95,103 ----
>   /* Port number of PRNGD/EGD random number socket */
>   #undef PRNGD_PORT
>
> + /* Use builtin entropy collector if nothing else available */
> + #undef USE_BUILTIN_ENTROPY
> +
>   /* Builtin PRNG command timeout */
>   #undef ENTROPY_TIMEOUT_MSEC
>
>




More information about the openssh-unix-dev mailing list