Re: [PATCH] arc4random: simplify design for better safety

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



If you're just following along on the mailing list, without actively
trying to apply this to a glibc tree, that diff might be hard to read.
The meat of it is the below function implementation. Notably this is
basically the same as systemd's crypto_random_bytes() (which I recently
rewrote there).

void
__arc4random_buf (void *p, size_t n)
{
  static bool have_getrandom = true, seen_initialized = false;
  int fd;

  if (n == 0)
    return;

  for (;;)
    {
      ssize_t l;

      if (!have_getrandom)
        break;

      l = __getrandom_nocancel (p, n, 0);
      if (l > 0)
        {
          if ((size_t) l == n)
              return; /* Done reading, success. */
          p = (uint8_t *) p + l;
          n -= l;
          continue; /* Interrupted by a signal; keep going. */
        }
      else if (l == 0)
        arc4random_getrandom_failure (); /* Weird, should never happen. */
      else if (errno == ENOSYS)
        {
          have_getrandom = false;
          break; /* No syscall, so fallback to /dev/urandom. */
        }
      arc4random_getrandom_failure (); /* Unknown other error, should never happen. */
    }

  if (!seen_initialized)
    {
      struct pollfd pfd = { .events = POLLIN };
      pfd.fd = TEMP_FAILURE_RETRY (__open64_nocancel ("/dev/random", O_RDONLY | O_CLOEXEC | O_NOCTTY));
      if (pfd.fd < 0)
        arc4random_getrandom_failure ();
      if (__poll(&pfd, 1, -1) < 0)
        arc4random_getrandom_failure ();
      if (__close_nocancel(pfd.fd) < 0)
        arc4random_getrandom_failure ();
      seen_initialized = true;
    }

  fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOCTTY);
  if (fd < 0)
    arc4random_getrandom_failure ();
  while (n)
    {
      ssize_t l = TEMP_FAILURE_RETRY (__read_nocancel (fd, p, n));
      if (l <= 0)
        arc4random_getrandom_failure ();
      p = (uint8_t *) p + l;
      n -= l;
    }
  if (__close_nocancel (fd) < 0)
    arc4random_getrandom_failure ();
}
libc_hidden_def (__arc4random_buf)
weak_alias (__arc4random_buf, arc4random_buf)



[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]
  Powered by Linux