aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2016-01-17 12:12:08 -0800
committerPaul Eggert2016-01-17 12:13:49 -0800
commit05e8148a24ebe51fbe758dd16265e8fb81f85953 (patch)
tree447c9fa28f9b8b3e8380f4f1c039b6cf76ce5750 /src
parenta0d5b7ae3bb014bb0b1c205d123c597df0e76411 (diff)
downloademacs-05e8148a24ebe51fbe758dd16265e8fb81f85953.tar.gz
emacs-05e8148a24ebe51fbe758dd16265e8fb81f85953.zip
Prefer GnuTLS when acquiring random seed
This attempts to improve on the fix for Bug#22202. * configure.ac (HAVE_DEV_URANDOM): Remove. Check /dev/urandom existence at run time, not at build time, since the device could exist in the former but not the latter. * src/sysdep.c [HAVE_GNUTLS]: Include gnutls/gnutls.h. (gnutls_rnd) [GNUTLS_VERSION_NUMBER < 0x020c00]: New fallback macro. (random_seed): New typedef. (set_random_seed): New static function. (seed_random): Use them. (init_random): Use random_seed instead of uintmax_t, so as to not consume more entropy than needed. Prefer gnutls_rnd if it works; this avoids a redundant open of /dev/urandom on GNU/Linux with modern GnuTLS.
Diffstat (limited to 'src')
-rw-r--r--src/sysdep.c85
1 files changed, 43 insertions, 42 deletions
diff --git a/src/sysdep.c b/src/sysdep.c
index 1fa422947ed..635443cfe66 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -99,6 +99,15 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
99#include "process.h" 99#include "process.h"
100#include "cm.h" 100#include "cm.h"
101 101
102#ifdef HAVE_GNUTLS
103# include <gnutls/gnutls.h>
104#endif
105#if 0x020c00 <= GNUTLS_VERSION_NUMBER
106# include <gnutls/crypto.h>
107#else
108# define gnutls_rnd(level, data, len) (-1)
109#endif
110
102#ifdef WINDOWSNT 111#ifdef WINDOWSNT
103#include <direct.h> 112#include <direct.h>
104/* In process.h which conflicts with the local copy. */ 113/* In process.h which conflicts with the local copy. */
@@ -2068,63 +2077,55 @@ init_signals (bool dumping)
2068# endif /* !HAVE_RANDOM */ 2077# endif /* !HAVE_RANDOM */
2069#endif /* !RAND_BITS */ 2078#endif /* !RAND_BITS */
2070 2079
2080#ifdef HAVE_RANDOM
2081typedef unsigned int random_seed;
2082static void set_random_seed (random_seed arg) { srandom (arg); }
2083#elif defined HAVE_LRAND48
2084/* Although srand48 uses a long seed, this is unsigned long to avoid
2085 undefined behavior on signed integer overflow in init_random. */
2086typedef unsigned long int random_seed;
2087static void set_random_seed (random_seed arg) { srand48 (arg); }
2088#else
2089typedef unsigned int random_seed;
2090static void set_random_seed (random_seed arg) { srand (arg); }
2091#endif
2092
2071void 2093void
2072seed_random (void *seed, ptrdiff_t seed_size) 2094seed_random (void *seed, ptrdiff_t seed_size)
2073{ 2095{
2074#if defined HAVE_RANDOM || ! defined HAVE_LRAND48 2096 random_seed arg = 0;
2075 unsigned int arg = 0;
2076#else
2077 long int arg = 0;
2078#endif
2079 unsigned char *argp = (unsigned char *) &arg; 2097 unsigned char *argp = (unsigned char *) &arg;
2080 unsigned char *seedp = seed; 2098 unsigned char *seedp = seed;
2081 ptrdiff_t i; 2099 for (ptrdiff_t i = 0; i < seed_size; i++)
2082 for (i = 0; i < seed_size; i++)
2083 argp[i % sizeof arg] ^= seedp[i]; 2100 argp[i % sizeof arg] ^= seedp[i];
2084#ifdef HAVE_RANDOM 2101 set_random_seed (arg);
2085 srandom (arg);
2086#else
2087# ifdef HAVE_LRAND48
2088 srand48 (arg);
2089# else
2090 srand (arg);
2091# endif
2092#endif
2093} 2102}
2094 2103
2095void 2104void
2096init_random (void) 2105init_random (void)
2097{ 2106{
2098 uintmax_t v; 2107 random_seed v;
2099 struct timespec t; 2108 if (gnutls_rnd (GNUTLS_RND_NONCE, &v, sizeof v) != 0)
2100 bool success = false;
2101
2102#if HAVE_DEV_URANDOM
2103 FILE *fp = fopen ("/dev/urandom", "rb");
2104
2105 if (fp)
2106 { 2109 {
2107 int i; 2110 bool success = false;
2108 2111#ifndef WINDOWSNT
2109 for (i = 0, v = 0; i < sizeof (uintmax_t); i++) 2112 int fd = emacs_open ("/dev/urandom", O_RDONLY | O_BINARY, 0);
2113 if (0 <= fd)
2110 { 2114 {
2111 v <<= 8; 2115 success = emacs_read (fd, &v, sizeof v) == sizeof v;
2112 v |= fgetc (fp); 2116 emacs_close (fd);
2117 }
2118#else
2119 success = w32_init_random (&v, sizeof v) == 0;
2120#endif
2121 if (! success)
2122 {
2123 /* Fall back to current time value + PID. */
2124 struct timespec t = current_timespec ();
2125 v = getpid () ^ t.tv_sec ^ t.tv_nsec;
2113 } 2126 }
2114 fclose (fp);
2115 success = true;
2116 }
2117#elif defined WINDOWSNT
2118 if (w32_init_random (&v, sizeof v) == 0)
2119 success = true;
2120#endif /* HAVE_DEV_URANDOM || WINDOWSNT */
2121 if (!success)
2122 {
2123 /* Fall back to current time value + PID. */
2124 t = current_timespec ();
2125 v = getpid () ^ t.tv_sec ^ t.tv_nsec;
2126 } 2127 }
2127 seed_random (&v, sizeof v); 2128 set_random_seed (v);
2128} 2129}
2129 2130
2130/* 2131/*