On 2017/10/17 22:12, Christian Weisgerber wrote:
> The /dev/arandom device was a detour that we are trying to get rid
> of.  Nothing should use it any longer.  Code should preferably use
> the arc4random() family of functions to get random numbers.  If
> that isn't an option, e.g. in shell, use /dev/urandom.
> 
> I extracted all packages from an amd64 snapshot and ran fgrep -a
> /dev/arandom over all files.  It turned up these matches:

A common method is to try various /dev/*random nodes in order to find
one which works. In some cases this is done at configure time, in others
at runtime.

To pick one example, nmap:

------------
void nrand_init(nrand_h *r) {
  u8 seed[256]; /* Starts out with "random" stack data */
  int i;

  /* Gather seed entropy with best the OS has to offer */
#ifdef WIN32
  HCRYPTPROV hcrypt = 0;

  CryptAcquireContext(&hcrypt, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
  CryptGenRandom(hcrypt, sizeof(seed), seed);
  CryptReleaseContext(hcrypt, 0);
#else
  struct timeval *tv = (struct timeval *)seed;
  int *pid = (int *)(seed + sizeof(*tv));
  int fd;

  gettimeofday(tv, NULL); /* fill lowest seed[] with time */
  *pid = getpid();        /* fill next lowest seed[] with pid */

  /* Try to fill the rest of the state with OS provided entropy */
  if ((fd = open("/dev/urandom", O_RDONLY)) != -1 ||
      (fd = open("/dev/arandom", O_RDONLY)) != -1) {
    ssize_t n;
    do {
      errno = 0;
      n = read(fd, seed + sizeof(*tv) + sizeof(*pid),
               sizeof(seed) - sizeof(*tv) - sizeof(*pid));
    } while (n < 0 && errno == EINTR);
    close(fd);
  }
#endif

  /* Fill up our handle with starter values */
  for (i = 0; i < 256; i++) { r->s[i] = i; };
  r->i = r->j = 0;

  nrand_addrandom(r, seed, 128); /* lower half of seed data for entropy */
  nrand_addrandom(r, seed + 128, 128); /* Now use upper half */
  r->tmp = NULL;
  r->tmplen = 0;

  /* This stream will start biased.  Get rid of 1K of the stream */
  nrand_get(r, seed, 256); nrand_get(r, seed, 256);
  nrand_get(r, seed, 256); nrand_get(r, seed, 256);
}

int get_random_bytes(void *buf, int numbytes) {
  static nrand_h state;
  static int state_init = 0;

  /* Initialize if we need to */
  if (!state_init) {
    nrand_init(&state);
    state_init = 1;
  }

  /* Now fill our buffer */
  nrand_get(&state, buf, numbytes);

  return 0;
}
------------

In this case, I'd consider converting get_random_bytes() to use
arc4random_buf, and get rid of nrand_init which is only called from
get_random_bytes. The other get_random_* are implemented in terms of
get_random_bytes and should get_random_probably just be left alone
(especially the LCG in get_random_unique_u32).

That list of files is shorter than I would have guessed :)

Reply via email to