Patch: Stop using /dev/random

Andrey Jivsov crypto at brainhub.org
Thu Nov 3 21:33:47 CET 2016


Can you please provide references to the statement that Linux makes sure
that its pool is seeded before the first read from /dev/urandom? Thank you.

On 11/03/2016 10:39 AM, Scott Arciszewski wrote:
> I'd like to propose this patch (or something similar) be applied to libgcrypt.
> 
> What libgcrypt does currently:
> 
> - Reads from /dev/random which blocks on Linux.
> 
> What the patch does instead:
> 
> - Polls /dev/random until it's available, then
> - Reads from /dev/urandom (the non-blocking interface) instead.
> 
> Because the Linux kernel (which has the offending /dev/random
> interface) will make sure /dev/urandom is seeded first, we can rely on
> the availability of /dev/random signaling that /dev/urandom has been
> seeded. This means we don't have to worry about racing against the
> init process and generating insecure random numbers.
> 
> This gives us usability and performance (no more waiting for "entropy"
> to gather) without sacrificing security.
> 
> Most of the code in this patch was lifted from libsodium, which
> already does this. Libsodium is ISC Licensed (by Frank Denis).
> 
> Thank you for your time,
> 
> Scott Arciszewski
> Chief Development Officer
> Paragon Initiative Enterprises <https://paragonie.com>
> 
> The patch follows:
> 
> diff --git a/random/rndlinux.c b/random/rndlinux.c
> index 2b563bf..59e7fc9 100644
> --- a/random/rndlinux.c
> +++ b/random/rndlinux.c
> @@ -36,6 +36,7 @@
>  # include <sys/syscall.h>
>  #endif
> 
> +#include <poll.h>
>  #include "types.h"
>  #include "g10lib.h"
>  #include "rand-internal.h"
> @@ -66,6 +67,7 @@ static int
>  open_device (const char *name, int retry)
>  {
>    int fd;
> +  _gcry_block_on_dev_random();
> 
>    if (retry)
>      _gcry_random_progress ("open_dev_random", 'X', 1, 0);
> @@ -102,6 +104,32 @@ open_device (const char *name, int retry)
>    return fd;
>  }
> 
> +/* Block until /dev/random is available. This means that /dev/urandom
> +   has already been seeded. */
> +static int
> +_gcry_block_on_dev_random(void)
> +{
> +    struct pollfd pfd;
> +    int           fd;
> +    int           pret;
> +
> +    fd = open("/dev/random", O_RDONLY);
> +    if (fd == -1) {
> +        return 0;
> +    }
> +    pfd.fd = fd;
> +    pfd.events = POLLIN;
> +    pfd.revents = 0;
> +    do {
> +        pret = poll(&pfd, 1, -1);
> +    } while (pret < 0 && (errno == EINTR || errno == EAGAIN));
> +    if (pret != 1) {
> +        (void) close(fd);
> +        errno = EIO;
> +        return -1;
> +    }
> +    return close(fd);
> +}
> 
>  /* Note that the caller needs to make sure that this function is only
>     called by one thread at a time.  The function returns 0 on success
> @@ -114,7 +142,6 @@ _gcry_rndlinux_gather_random (void (*add)(const
> void*, size_t,
>                                size_t length, int level )
>  {
>    static int fd_urandom = -1;
> -  static int fd_random = -1;
>    static unsigned char ever_opened;
>    int fd;
>    int n;
> @@ -128,11 +155,6 @@ _gcry_rndlinux_gather_random (void (*add)(const
> void*, size_t,
>    if (!add)
>      {
>        /* Special mode to close the descriptors.  */
> -      if (fd_random != -1)
> -        {
> -          close (fd_random);
> -          fd_random = -1;
> -        }
>        if (fd_urandom != -1)
>          {
>            close (fd_urandom);
> @@ -165,24 +187,12 @@ _gcry_rndlinux_gather_random (void (*add)(const
> void*, size_t,
>       that we always require the device to be existent but want a more
>       graceful behaviour if the rarely needed close operation has been
>       used and the device needs to be re-opened later. */
> -  if (level >= 2)
> -    {
> -      if (fd_random == -1)
> -        {
> -          fd_random = open_device (NAME_OF_DEV_RANDOM, (ever_opened & 1));
> -          ever_opened |= 1;
> -        }
> -      fd = fd_random;
> -    }
> -  else
> -    {
>        if (fd_urandom == -1)
>          {
>            fd_urandom = open_device (NAME_OF_DEV_URANDOM, (ever_opened & 2));
>            ever_opened |= 2;
>          }
>        fd = fd_urandom;
> -    }
> 
>    /* Enter the read loop.  */
>    delay = 0;  /* Start with 0 seconds so that we do no block on the
> 
> _______________________________________________
> Gcrypt-devel mailing list
> Gcrypt-devel at gnupg.org
> http://lists.gnupg.org/mailman/listinfo/gcrypt-devel
> 




More information about the Gcrypt-devel mailing list