Patch to enable multiple possible sources of entropy

Dave Dykstra dwd at bell-labs.com
Fri Jun 8 03:50:14 EST 2001


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