diff options
| author | Paul Eggert | 2020-06-27 13:02:24 -0700 |
|---|---|---|
| committer | Paul Eggert | 2020-06-27 13:03:49 -0700 |
| commit | 5ce5cf643840cd6efd25d987bc5b6f12478c50a6 (patch) | |
| tree | 48a0f14e8162ee889475f54a21227356885cd330 /src | |
| parent | 118c07e02e939c9f52688091509d4bff2a897032 (diff) | |
| download | emacs-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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/fns.c | 15 | ||||
| -rw-r--r-- | src/sysdep.c | 32 |
2 files changed, 16 insertions, 31 deletions
| @@ -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) | |||
| 2278 | typedef unsigned int random_seed; | 2269 | typedef unsigned int random_seed; |
| 2279 | static void set_random_seed (random_seed arg) { srandom (arg); } | 2270 | static 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 | 2272 | typedef long int random_seed; |
| 2282 | undefined behavior on signed integer overflow in init_random. */ | ||
| 2283 | typedef unsigned long int random_seed; | ||
| 2284 | static void set_random_seed (random_seed arg) { srand48 (arg); } | 2273 | static void set_random_seed (random_seed arg) { srand48 (arg); } |
| 2285 | #else | 2274 | #else |
| 2286 | typedef unsigned int random_seed; | 2275 | typedef 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 | { |