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