diff options
Diffstat (limited to 'util/libreboot-utils/lib/rand.c')
| -rw-r--r-- | util/libreboot-utils/lib/rand.c | 80 |
1 files changed, 43 insertions, 37 deletions
diff --git a/util/libreboot-utils/lib/rand.c b/util/libreboot-utils/lib/rand.c index adfad3d7..bf090b43 100644 --- a/util/libreboot-utils/lib/rand.c +++ b/util/libreboot-utils/lib/rand.c @@ -4,27 +4,30 @@ * Random number generation */ -#ifndef RAND_H -#define RAND_H +#if defined(USE_ARC4) && \ + ((USE_ARC4) > 0) +#define _DEFAULT_SOURCE 1 /* for arc4random on *linux* */ + /* (not needed on bsd - on bsd, + it is used automatically unless + overridden with USE_URANDOM */ +#elif defined(USE_URANDOM) && \ + ((USE_URANDOM) > 0) +#include <fcntl.h> /* if not arc4random: /dev/urandom */ +#elif defined(__linux__) && \ + !(defined(USE_ARC4) && ((USE_ARC4) > 0)) +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif +#include <sys/syscall.h> +#include <sys/random.h> +#endif #ifdef __OpenBSD__ #include <sys/param.h> #endif #include <sys/types.h> -#ifndef USE_URANDOM -#define USE_URANDOM 0 -#endif - #include <errno.h> -#if defined(USE_URANDOM) && \ - ((USE_URANDOM) > 0) -#include <fcntl.h> /* if not arc4random: /dev/urandom */ -#elif defined(__linux__) -#include <sys/random.h> -#include <sys/syscall.h> -#endif - #include <fcntl.h> #include <limits.h> #include <stddef.h> @@ -107,7 +110,7 @@ rsize(size_t n) { size_t rval = SIZE_MAX; if (!n) - err_exit(EFAULT, "rsize: division by zero"); + exitf("rsize: division by zero"); /* rejection sampling (clamp rand to eliminate modulo bias) */ for (; rval >= SIZE_MAX - (SIZE_MAX % n); rset(&rval, sizeof(rval))); @@ -133,62 +136,65 @@ rset(void *buf, size_t n) goto err; if (n == 0) - err_exit(EPERM, "rset: zero-byte request"); + exitf("rset: zero-byte request"); -#if (defined(__OpenBSD__) || defined(__FreeBSD__) || \ +/* on linux, getrandom is recommended, + but you can pass -DUSE_ARC4=1 to use arc4random. + useful for portability testing from linux. + */ +#if (defined(USE_ARC4) && ((USE_ARC4) > 0)) || \ + ((defined(__OpenBSD__) || defined(__FreeBSD__) || \ defined(__NetBSD__) || defined(__APPLE__) || \ defined(__DragonFly__)) && !(defined(USE_URANDOM) && \ - ((USE_URANDOM) > 0)) + ((USE_URANDOM) > 0))) arc4random_buf(buf, n); #else size_t off = 0; -retry_rand: +retry_rand: { #if defined(USE_URANDOM) && \ ((USE_URANDOM) > 0) - ssize_t rc; + ssize_t rval; int fd = -1; open_file_on_eintr("/dev/urandom", &fd, O_RDONLY, 0400, NULL); while (rw_retry(saved_errno, - rc = read_on_eintr(fd, - (unsigned char *)buf + off, n - off, 0))); + rval = rw(fd, (unsigned char *)buf + off, n - off, 0, IO_READ))); #elif defined(__linux__) - long rc; + long rval; while (sys_retry(saved_errno, - rc = syscall(SYS_getrandom, + rval = syscall(SYS_getrandom, (unsigned char *)buf + off, n - off, 0))); #else #error Unsupported operating system (possibly unsecure randomisation) #endif - if (rc < 0) - goto err; /* syscall fehler */ - - if (rc == 0) - goto err; /* prevent infinite loop on fatal err */ + if (rval < 0 || /* syscall fehler */ + rval == 0) { /* prevent infinite loop on fatal err */ +#if defined(USE_URANDOM) && \ + ((USE_URANDOM) > 0) + xclose(&fd); +#endif + goto err; + } - if ((off += (size_t)rc) < n) + if ((off += (size_t)rval) < n) goto retry_rand; #if defined(USE_URANDOM) && \ ((USE_URANDOM) > 0) - close_on_eintr(&fd); + xclose(&fd); #endif +} #endif reset_caller_errno(0); return; err: -#if defined(USE_URANDOM) && \ - ((USE_URANDOM) > 0) - close_on_eintr(&fd); -#endif (void) with_fallback_errno(ECANCELED); - err_exit(errno, "Randomisierungsfehler"); + exitf("Randomisierungsfehler"); exit(EXIT_FAILURE); } -#endif |
