aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2020-06-27 13:02:24 -0700
committerPaul Eggert2020-06-27 13:03:49 -0700
commit5ce5cf643840cd6efd25d987bc5b6f12478c50a6 (patch)
tree48a0f14e8162ee889475f54a21227356885cd330
parent118c07e02e939c9f52688091509d4bff2a897032 (diff)
downloademacs-5ce5cf643840cd6efd25d987bc5b6f12478c50a6.tar.gz
emacs-5ce5cf643840cd6efd25d987bc5b6f12478c50a6.zip
Use getrandom syscall for nonces
* admin/merge-gnulib (GNULIB_MODULES): Add getrandom. * doc/lispref/text.texi (Format of GnuTLS Cryptography Inputs): Don’t say that iv-auto uses GNUTLS_RND_NONCE. Also, don’t say that it returns the IV’s actual value, as it never has done that. * src/fns.c, src/sysdep.c: Include sys/random.h, for getrandom. * src/fns.c (Fsecure_hash_algorithms): Use getrandom so that this function does not depend on HAVE_GNUTLS3. * src/sysdep.c: Do not include <gnutls/crypto.h>. (random_seed) [HAVE_LRAND48]: Can be long int now. (init_random) [!WINDOWSNT]: Use getrandom syscall instead of opening /dev/urandom, as this works even on GNU/Linux hosts that lack /dev/urandom. Don’t bother with gnutls_rnd as it’s not needed now that we have getrandom.
-rwxr-xr-xadmin/merge-gnulib2
-rw-r--r--doc/lispref/text.texi8
-rw-r--r--src/fns.c15
-rw-r--r--src/sysdep.c32
4 files changed, 20 insertions, 37 deletions
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index 99469e47aa7..5a78b052b24 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -35,7 +35,7 @@ GNULIB_MODULES='
35 environ execinfo explicit_bzero faccessat 35 environ execinfo explicit_bzero faccessat
36 fchmodat fcntl fcntl-h fdopendir 36 fchmodat fcntl fcntl-h fdopendir
37 filemode filename filevercmp flexmember fpieee fstatat fsusage fsync futimens 37 filemode filename filevercmp flexmember fpieee fstatat fsusage fsync futimens
38 getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog 38 getloadavg getopt-gnu getrandom gettime gettimeofday gitlog-to-changelog
39 ieee754-h ignore-value intprops largefile lstat 39 ieee754-h ignore-value intprops largefile lstat
40 manywarnings memmem-simple mempcpy memrchr minmax mkostemp mktime nstrftime 40 manywarnings memmem-simple mempcpy memrchr minmax mkostemp mktime nstrftime
41 pathmax pipe2 pselect pthread_sigmask 41 pathmax pipe2 pselect pthread_sigmask
diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index 10e8246a5fa..0c3813ff1d0 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -4813,11 +4813,9 @@ When @var{noerror} is non-@code{nil}, this function silently uses
4813@code{raw-text} coding instead. 4813@code{raw-text} coding instead.
4814 4814
4815@item (@code{iv-auto} @var{length}) 4815@item (@code{iv-auto} @var{length})
4816This will generate an IV (Initialization Vector) of the specified 4816This generates a random IV (Initialization Vector) of the specified
4817length using the GnuTLS @code{GNUTLS_RND_NONCE} generator and pass it 4817length and passes it to the function. This ensures that the IV is
4818to the function. This ensures that the IV is unpredictable and 4818unpredictable and unlikely to be reused in the same session.
4819unlikely to be reused in the same session. The actual value of the IV
4820is returned by the function as described below.
4821 4819
4822@end table 4820@end table
4823 4821
diff --git a/src/fns.c b/src/fns.c
index b2f84b202de..c1465f7fe3c 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -21,6 +21,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
21#include <config.h> 21#include <config.h>
22 22
23#include <stdlib.h> 23#include <stdlib.h>
24#include <sys/random.h>
24#include <unistd.h> 25#include <unistd.h>
25#include <filevercmp.h> 26#include <filevercmp.h>
26#include <intprops.h> 27#include <intprops.h>
@@ -5267,7 +5268,6 @@ extract_data_from_object (Lisp_Object spec,
5267 } 5268 }
5268 else if (EQ (object, Qiv_auto)) 5269 else if (EQ (object, Qiv_auto))
5269 { 5270 {
5270#ifdef HAVE_GNUTLS3
5271 /* Format: (iv-auto REQUIRED-LENGTH). */ 5271 /* Format: (iv-auto REQUIRED-LENGTH). */
5272 5272
5273 if (! FIXNATP (start)) 5273 if (! FIXNATP (start))
@@ -5276,14 +5276,19 @@ extract_data_from_object (Lisp_Object spec,
5276 { 5276 {
5277 EMACS_INT start_hold = XFIXNAT (start); 5277 EMACS_INT start_hold = XFIXNAT (start);
5278 object = make_uninit_string (start_hold); 5278 object = make_uninit_string (start_hold);
5279 gnutls_rnd (GNUTLS_RND_NONCE, SSDATA (object), start_hold); 5279 char *lim = SSDATA (object) + start_hold;
5280 for (char *p = SSDATA (object); p < lim; p++)
5281 {
5282 ssize_t gotten = getrandom (p, lim - p, 0);
5283 if (0 <= gotten)
5284 p += gotten;
5285 else if (errno != EINTR)
5286 report_file_error ("Getting random data", Qnil);
5287 }
5280 5288
5281 *start_byte = 0; 5289 *start_byte = 0;
5282 *end_byte = start_hold; 5290 *end_byte = start_hold;
5283 } 5291 }
5284#else
5285 error ("GnuTLS is not available, so `iv-auto' can't be used");
5286#endif
5287 } 5292 }
5288 5293
5289 if (!STRINGP (object)) 5294 if (!STRINGP (object))
diff --git a/src/sysdep.c b/src/sysdep.c
index cbd306a6b67..6b54ed3b6ec 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -27,6 +27,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
27#endif /* HAVE_PWD_H */ 27#endif /* HAVE_PWD_H */
28#include <limits.h> 28#include <limits.h>
29#include <stdlib.h> 29#include <stdlib.h>
30#include <sys/random.h>
30#include <unistd.h> 31#include <unistd.h>
31 32
32#include <c-ctype.h> 33#include <c-ctype.h>
@@ -115,16 +116,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
115#include "process.h" 116#include "process.h"
116#include "cm.h" 117#include "cm.h"
117 118
118#include "gnutls.h"
119/* MS-Windows loads GnuTLS at run time, if available; we don't want to
120 do that during startup just to call gnutls_rnd. */
121#if defined HAVE_GNUTLS && !defined WINDOWSNT
122# include <gnutls/crypto.h>
123#else
124# define emacs_gnutls_global_init() Qnil
125# define gnutls_rnd(level, data, len) (-1)
126#endif
127
128#ifdef WINDOWSNT 119#ifdef WINDOWSNT
129# include <direct.h> 120# include <direct.h>
130/* In process.h which conflicts with the local copy. */ 121/* In process.h which conflicts with the local copy. */
@@ -2278,9 +2269,7 @@ init_signals (void)
2278typedef unsigned int random_seed; 2269typedef unsigned int random_seed;
2279static void set_random_seed (random_seed arg) { srandom (arg); } 2270static void set_random_seed (random_seed arg) { srandom (arg); }
2280#elif defined HAVE_LRAND48 2271#elif defined HAVE_LRAND48
2281/* Although srand48 uses a long seed, this is unsigned long to avoid 2272typedef long int random_seed;
2282 undefined behavior on signed integer overflow in init_random. */
2283typedef unsigned long int random_seed;
2284static void set_random_seed (random_seed arg) { srand48 (arg); } 2273static void set_random_seed (random_seed arg) { srand48 (arg); }
2285#else 2274#else
2286typedef unsigned int random_seed; 2275typedef unsigned int random_seed;
@@ -2307,23 +2296,14 @@ init_random (void)
2307 /* First, try seeding the PRNG from the operating system's entropy 2296 /* First, try seeding the PRNG from the operating system's entropy
2308 source. This approach is both fast and secure. */ 2297 source. This approach is both fast and secure. */
2309#ifdef WINDOWSNT 2298#ifdef WINDOWSNT
2299 /* FIXME: Perhaps getrandom can be used here too? */
2310 success = w32_init_random (&v, sizeof v) == 0; 2300 success = w32_init_random (&v, sizeof v) == 0;
2311#else 2301#else
2312 int fd = emacs_open ("/dev/urandom", O_RDONLY, 0); 2302 verify (sizeof v <= 256);
2313 if (0 <= fd) 2303 success = getrandom (&v, sizeof v, 0) == sizeof v;
2314 {
2315 success = emacs_read (fd, &v, sizeof v) == sizeof v;
2316 close (fd);
2317 }
2318#endif 2304#endif
2319 2305
2320 /* If that didn't work, try using GnuTLS, which is secure, but on 2306 /* If that didn't work, just use the current time value and PID.
2321 some systems, can be somewhat slow. */
2322 if (!success)
2323 success = EQ (emacs_gnutls_global_init (), Qt)
2324 && gnutls_rnd (GNUTLS_RND_NONCE, &v, sizeof v) == 0;
2325
2326 /* If _that_ didn't work, just use the current time value and PID.
2327 It's at least better than XKCD 221. */ 2307 It's at least better than XKCD 221. */
2328 if (!success) 2308 if (!success)
2329 { 2309 {