summaryrefslogtreecommitdiff
path: root/util/libreboot-utils/lib/rand.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/libreboot-utils/lib/rand.c')
-rw-r--r--util/libreboot-utils/lib/rand.c80
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