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.c75
1 files changed, 43 insertions, 32 deletions
diff --git a/util/libreboot-utils/lib/rand.c b/util/libreboot-utils/lib/rand.c
index 392ec2ba..c36b4b74 100644
--- a/util/libreboot-utils/lib/rand.c
+++ b/util/libreboot-utils/lib/rand.c
@@ -20,6 +20,9 @@
#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>
@@ -69,48 +72,53 @@
* or your program dies.
*/
-#define ELOTTERY ECANCELED
+#ifndef BUFSIZ
+#define BUFSIZ 8192 /* reasonably on modern 64-bit systems */
+#elif (BUFSIZ <= 0)
+#error defined buffer size BUFSIZ below or equal to zero
+#endif
int
-win_lottery(void)
+win_lottery(void) /* are u lucky? */
{
- int saved_errno = errno;
- size_t size1;
- char *s1 = NULL;
- size_t size2;
- char *s2 = NULL;
- size_t pool = BUFSIZ;
+ size_t size = 0;
+ size_t size2 = 0;
int rval;
- rset(&size1, sizeof(size1));
- rset(&size2, sizeof(size2));
+ char *s1 = rmalloc(&size);
+ char *s2 = rmalloc(&size2);
- size1 %= pool, size2 %= pool;
- s1 = mkrstr(size1), s2 = mkrstr(size2);
+ if (size2 > size)
+ size = size2;
- if (scmp(s1, s2, BUFSIZ + 2, &rval) < 0)
- goto err;
- if (rval == 0)
- goto win;
+ if (scmp(s1, s2, size + 1, &rval) >= 0 &&
+ rval == 0)
+ rval = 1; /* winner! */
+ else
+ rval = 0;
+
+ free_if_null(&s1);
+ free_if_null(&s2);
+
+ return rval;
+}
+
+void *
+rmalloc(size_t *rval)
+{
+ size_t size = 16777216;
- free_if_null(&s1), free_if_null(&s2);
+ /* clamp rand to prevent modulo bias */
+ size_t limit = SIZE_MAX - (SIZE_MAX % size);
- fprintf(stderr, "Sorry, you lose! Try again.\n");
- return 0;
-win:
- free_if_null(&s1), free_if_null(&s2);
+ if (if_err(rval == NULL, EFAULT))
+ return NULL;
- err_no_cleanup(0, ELOTTERY,
- "Congratulations! you won the errno lottery");
+ do {
+ rset(rval, sizeof(*rval));
+ } while (*rval >= limit || *rval == 0);
- exit(1);
- return -1;
-err:
- /* the lottery won you */
- free_if_null(&s1), free_if_null(&s2);
- err_no_cleanup(0, EFAULT, "lottery won you");
- exit(1);
- return -1;
+ return mkrstr(*rval %= size);
}
char *
@@ -122,7 +130,7 @@ mkrstr(size_t n) /* emulates spkmodem-decode */
if (n == 0)
err_no_cleanup(0, EPERM, "mkrbuf: zero-byte request");
- if (n == SIZE_MAX)
+ if (n >= SIZE_MAX - 1)
err_no_cleanup(0, EOVERFLOW, "mkrbuf: overflow");
if (if_err((s = mkrbuf(n + 1)) == NULL, EFAULT))
@@ -145,6 +153,9 @@ mkrbuf(size_t n)
if (n == 0)
err_no_cleanup(0, EPERM, "mkrbuf: zero-byte request");
+ if (n >= SIZE_MAX - 1)
+ err_no_cleanup(0, EOVERFLOW, "integer overflow in mkrbuf");
+
if ((buf = malloc(n)) == NULL)
err_no_cleanup(0, ENOMEM, "mkrbuf: malloc");