File:  [DVB] / dietlibc / lib / arc4random.c
Revision 1.5: download - view: text, annotated - select for diffs
Thu Feb 23 16:54:14 2017 UTC (7 years, 3 months ago) by leitner
Branches: MAIN
CVS tags: HEAD
change include file for getrandom

#define _LINUX_SOURCE
#include <unistd.h>
#include <sys/random.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>

static uint32_t buf[256];
static unsigned int n;

/* These come from OpenBSD: */
uint32_t arc4random(void) {
  if (n==0) arc4random_stir();
  uint32_t r=buf[n];
  if (++n > sizeof(buf)/sizeof(buf[0])) n=0;
  return r;
}

void arc4random_buf(void* Buf, size_t N) {
  int r;
  if ((size_t)(r=getrandom(Buf,N,GRND_NONBLOCK)) != N) {
    if (r==-1 && errno==ENOSYS) {
      int fd=open("/dev/urandom",O_RDONLY);
      if (fd==-1) abort();
      r=read(fd,Buf,N);
      close(fd);
    }
    if ((size_t)r != N)
      abort();
  }
}

uint32_t arc4random_uniform(uint32_t upper_bound) {
  uint32_t r, min;

  if (upper_bound < 2)
    return 0;

  /* 2**32 % x == (2**32 - x) % x */
  min = -upper_bound % upper_bound;

  /*
    * This could theoretically loop forever but each retry has
    * p > 0.5 (worst case, usually far better) of selecting a
    * number inside the range we need, so it should rarely need
    * to re-roll.
    */
  for (;;) {
    r = arc4random();
    if (r >= min)
      break;
  }

  return r % upper_bound;
}

void arc4random_stir(void) {
  n=0;
  arc4random_buf(buf,sizeof(buf));
}

void arc4random_addrandom(unsigned char* dat,size_t datlen) {
}


LinuxTV legacy CVS <linuxtv.org/cvs>