Commit 5ce5cf64 authored by Paul Eggert's avatar Paul Eggert

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.
parent 118c07e0
Pipeline #5953 failed with stage
in 15 seconds
......@@ -35,7 +35,7 @@ GNULIB_MODULES='
environ execinfo explicit_bzero faccessat
fchmodat fcntl fcntl-h fdopendir
filemode filename filevercmp flexmember fpieee fstatat fsusage fsync futimens
getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog
getloadavg getopt-gnu getrandom gettime gettimeofday gitlog-to-changelog
ieee754-h ignore-value intprops largefile lstat
manywarnings memmem-simple mempcpy memrchr minmax mkostemp mktime nstrftime
pathmax pipe2 pselect pthread_sigmask
......
......@@ -4813,11 +4813,9 @@ When @var{noerror} is non-@code{nil}, this function silently uses
@code{raw-text} coding instead.
@item (@code{iv-auto} @var{length})
This will generate an IV (Initialization Vector) of the specified
length using the GnuTLS @code{GNUTLS_RND_NONCE} generator and pass it
to the function. This ensures that the IV is unpredictable and
unlikely to be reused in the same session. The actual value of the IV
is returned by the function as described below.
This generates a random IV (Initialization Vector) of the specified
length and passes it to the function. This ensures that the IV is
unpredictable and unlikely to be reused in the same session.
@end table
......
......@@ -21,6 +21,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdlib.h>
#include <sys/random.h>
#include <unistd.h>
#include <filevercmp.h>
#include <intprops.h>
......@@ -5267,7 +5268,6 @@ extract_data_from_object (Lisp_Object spec,
}
else if (EQ (object, Qiv_auto))
{
#ifdef HAVE_GNUTLS3
/* Format: (iv-auto REQUIRED-LENGTH). */
if (! FIXNATP (start))
......@@ -5276,14 +5276,19 @@ extract_data_from_object (Lisp_Object spec,
{
EMACS_INT start_hold = XFIXNAT (start);
object = make_uninit_string (start_hold);
gnutls_rnd (GNUTLS_RND_NONCE, SSDATA (object), start_hold);
char *lim = SSDATA (object) + start_hold;
for (char *p = SSDATA (object); p < lim; p++)
{
ssize_t gotten = getrandom (p, lim - p, 0);
if (0 <= gotten)
p += gotten;
else if (errno != EINTR)
report_file_error ("Getting random data", Qnil);
}
*start_byte = 0;
*end_byte = start_hold;
}
#else
error ("GnuTLS is not available, so `iv-auto' can't be used");
#endif
}
if (!STRINGP (object))
......
......@@ -27,6 +27,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#endif /* HAVE_PWD_H */
#include <limits.h>
#include <stdlib.h>
#include <sys/random.h>
#include <unistd.h>
#include <c-ctype.h>
......@@ -115,16 +116,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "process.h"
#include "cm.h"
#include "gnutls.h"
/* MS-Windows loads GnuTLS at run time, if available; we don't want to
do that during startup just to call gnutls_rnd. */
#if defined HAVE_GNUTLS && !defined WINDOWSNT
# include <gnutls/crypto.h>
#else
# define emacs_gnutls_global_init() Qnil
# define gnutls_rnd(level, data, len) (-1)
#endif
#ifdef WINDOWSNT
# include <direct.h>
/* In process.h which conflicts with the local copy. */
......@@ -2278,9 +2269,7 @@ init_signals (void)
typedef unsigned int random_seed;
static void set_random_seed (random_seed arg) { srandom (arg); }
#elif defined HAVE_LRAND48
/* Although srand48 uses a long seed, this is unsigned long to avoid
undefined behavior on signed integer overflow in init_random. */
typedef unsigned long int random_seed;
typedef long int random_seed;
static void set_random_seed (random_seed arg) { srand48 (arg); }
#else
typedef unsigned int random_seed;
......@@ -2307,23 +2296,14 @@ init_random (void)
/* First, try seeding the PRNG from the operating system's entropy
source. This approach is both fast and secure. */
#ifdef WINDOWSNT
/* FIXME: Perhaps getrandom can be used here too? */
success = w32_init_random (&v, sizeof v) == 0;
#else
int fd = emacs_open ("/dev/urandom", O_RDONLY, 0);
if (0 <= fd)
{
success = emacs_read (fd, &v, sizeof v) == sizeof v;
close (fd);
}
verify (sizeof v <= 256);
success = getrandom (&v, sizeof v, 0) == sizeof v;
#endif
/* If that didn't work, try using GnuTLS, which is secure, but on
some systems, can be somewhat slow. */
if (!success)
success = EQ (emacs_gnutls_global_init (), Qt)
&& gnutls_rnd (GNUTLS_RND_NONCE, &v, sizeof v) == 0;
/* If _that_ didn't work, just use the current time value and PID.
/* If that didn't work, just use the current time value and PID.
It's at least better than XKCD 221. */
if (!success)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment