summaryrefslogtreecommitdiff
path: root/util/nvmutil/lib/num.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/nvmutil/lib/num.c')
-rw-r--r--util/nvmutil/lib/num.c444
1 files changed, 0 insertions, 444 deletions
diff --git a/util/nvmutil/lib/num.c b/util/nvmutil/lib/num.c
deleted file mode 100644
index 343350b0..00000000
--- a/util/nvmutil/lib/num.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/* SPDX-License-Identifier: MIT
- * Copyright (c) 2026 Leah Rowe <leah@libreboot.org>
- *
- * Numerical functions.
- */
-
-/*
-TODO: properly handle errno in this file
- */
-
-#ifdef __OpenBSD__
-#include <sys/param.h>
-#endif
-#include <sys/types.h>
-#if defined(FALLBACK_RAND_1989) && \
- (FALLBACK_RAND_1989) > 0
-#include <sys/time.h>
-#endif
-
-#include <errno.h>
-#if !((defined(__OpenBSD__) && (OpenBSD) >= 201) || \
- defined(__FreeBSD__) || \
- defined(__NetBSD__) || defined(__APPLE__))
-#include <fcntl.h> /* if not arc4random: /dev/urandom */
-#endif
-#include <limits.h>
-#include <stddef.h>
-#include <string.h>
-#if defined(FALLBACK_RAND_1989) && \
- (FALLBACK_RAND_1989) > 0
-#include <time.h>
-#endif
-#include <unistd.h>
-
-#include "../include/common.h"
-
-/* TODO:
- * make this and errno handling more
- * flexible
-
- in particular:
- hextonum could be modified to
- write into a buffer instead,
- with the converted numbers,
- of an arbitrary length
- */
-unsigned short
-hextonum(char ch_s)
-{
- int saved_errno = errno;
-
- /* rlong() can return error,
- but preserves errno if no
- error. we need to detect
- this because it handles
- /dev/urandom sometimes
-
- therefore, if it's zero
- at start, we know if there
- was an err at the end, by
- return value zero, if errno
- was set; this is technically
- valid, since zero is also
- a valid random number!
-
- it's an edge case that i had
- to fix. i'll rewrite the code
- better later. for now, it
- should be ok.
- */
- errno = 0;
-
- unsigned char ch;
- size_t rval;
-
- ch = (unsigned char)ch_s;
-
- if ((unsigned int)(ch - '0') <= 9) {
-
- rval = ch - '0';
- goto hextonum_success;
- }
-
- ch |= 0x20;
-
- if ((unsigned int)(ch - 'a') <= 5) {
-
- rval = ch - 'a' + 10;
- goto hextonum_success;
- }
-
- if (ch == '?' || ch == 'x') {
-
- rval = rlong();
- if (errno > 0)
- goto err_hextonum;
-
- goto hextonum_success;
- }
-
- goto err_hextonum;
-
-hextonum_success:
-
- errno = saved_errno;
- return (unsigned short)rval & 0xf;
-
-err_hextonum:
-
- if (errno == saved_errno)
- errno = EINVAL;
- else
- return 17; /* 17 indicates getrandom/urandom fail */
-
- return 16; /* invalid character */
-
- /* caller just checks >15. */
-}
-
-/* Random numbers
- */
-
-/* when calling this: save errno
- * first, then set errno to zero.
- * on error, this function will
- * set errno and possibly return
- *
- * rlong also preserves errno
- * and leaves it unchanged on
- * success, so if you do it
- * right, you can detect error.
- * this is because it uses
- * /dev/urandom which can err.
- * ditto getrandom (EINTR),
- * theoretically.
- */
-
-size_t
-rlong(void)
-{
-#if !(defined(FALLBACK_RAND_1989) && \
- ((FALLBACK_RAND_1989) > 0))
-#if (defined(__OpenBSD__) && (OpenBSD) >= 201) || \
- defined(__FreeBSD__) || \
- defined(__NetBSD__) || defined(__APPLE__)
-
- int saved_errno = errno;
- size_t rval;
-
- arc4random_buf(&rval, sizeof(size_t));
-
- errno = saved_errno;
- return rval;
-#else
- static int fd = -1;
- static ssize_t nr = -1;
- static size_t off = 0;
-#if defined (BUFSIZ)
- static char rbuf[BUFSIZ];
-#else
-#ifndef PORTABLE
- static char rbuf[4096];
-#elif ((PORTABLE) > 0)
- static char rbuf[256]; /* scarce memory on old systems */
-#else
- static char rbuf[4096]; /* typical 32-bit BUFSIZ */
-#endif
-#endif
- size_t rval;
- ssize_t new_nr;
-
- int retries = 0;
- int max_retries = 100;
-
- int saved_errno = errno;
-
-#if defined(__linux__)
-#if defined(HAVE_GETRANDOM) || \
- defined(HAVE_GETRANDOM_SYSCALL)
-
- /* linux getrandom()
- *
- * we *can* use arc4random on
- * modern linux, but not on
- * every libc. better use the
- * official linux function
- */
-
- if (fallback_rand_getrandom(&rval, sizeof(rval)) == 0) {
- errno = saved_errno;
- return rval;
- }
-
- /*
- * now fall back to urandom if getrandom failed:
- */
-#endif
-#endif
-
- /* reading from urandom is inherently
- * unreliable on old systems, even if
- * newer systems make it more reliable
- *
- * modern linux/bsd make it safe, but
- * we have to assume that someone is
- * compiling this on linux from 1999
- *
- * this logic therefore applies various
- * tricks to mitigate possible os bugs
- */
-
-retry_urandom_read:
-
- if (++retries > max_retries)
- goto err_rlong;
-
- if (nr < 0 || nr < (ssize_t)sizeof(size_t)) {
-
- if (fd < 0) {
-
- fd = open("/dev/urandom",
- O_RDONLY | O_BINARY | O_NOFOLLOW |
- O_CLOEXEC | O_NOCTTY);
-
-#ifdef USE_OLD_DEV_RANDOM
-#if (USE_OLD_DEV_RANDOM) > 0
- /* WARNING:
- * /dev/random may block
- * forever and does **NOT**
- * guarantee better entropy
- * on old systems
- *
- * only use it if needed
- */
-
- if (fd < 0)
- fd = open("/dev/random",
- O_RDONLY | O_BINARY | O_NOFOLLOW |
- O_CLOEXEC | O_NOCTTY);
-#endif
-#endif
-
- if (fd < 0)
- goto retry_urandom_read;
-
- retries = 0;
- }
-
- new_nr = rw_file_exact(fd, (unsigned char *)rbuf,
- sizeof(rbuf), 0, IO_READ, LOOP_EAGAIN,
- LOOP_EINTR, MAX_ZERO_RW_RETRY, OFF_ERR);
-
- if (new_nr < 0 || new_nr < (ssize_t)sizeof(rbuf))
- goto retry_urandom_read;
-
- /* only reset buffer after successful refill */
- nr = new_nr;
- off = 0;
-
- /* to mitigate file descriptor
- * injection, we do not re-use
- * the same descriptor each time
- */
- (void) close_on_eintr(fd);
- fd = -1;
- }
-
- fd = -1;
- retries = 0;
-
- memcpy(&rval, rbuf + off, sizeof(size_t));
-
- nr -= (ssize_t)sizeof(size_t);
- off += sizeof(size_t);
-
- errno = saved_errno;
-
- return rval;
-
-err_rlong:
-
- if (errno == saved_errno)
- errno = EIO;
-
- return 0;
-
-#endif
-#else /* FALLBACK_RAND_1989 */
- /* your computer is from a museum
- */
- size_t mix = 0;
- int nr = 0;
- int saved_errno = errno;
-
- /* 100 times, for entropy
- */
- for (nr = 0; nr < 100; nr++)
- mix ^= fallback_rand_1989();
-
- errno = saved_errno;
- return mix;
-#endif
-}
-
-#if !(defined(FALLBACK_RAND_1989) && \
- ((FALLBACK_RAND_1989) > 0))
-#if defined(__linux__)
-#if defined(HAVE_GETRANDOM) || \
- defined(HAVE_GETRANDOM_SYSCALL)
-int /* yes, linux is a fallback */
-fallback_rand_getrandom(void *buf, size_t len)
-{
- size_t off = 0;
- ssize_t rval = -1;
- int saved_errno = errno;
-
- if (!len) {
- errno = EINVAL;
- return -1;
- }
-
- if (buf == NULL) {
- errno = EFAULT;
- return -1;
- }
-
-#if defined(HAVE_GETRANDOM) || \
- defined(HAVE_GETRANDOM_SYSCALL)
-
- while (off < len) {
-
-#if defined(HAVE_GETRANDOM)
- rval = (ssize_t)getrandom((char *)buf + off, len - off, 0);
-#elif defined(HAVE_GETRANDOM_SYSCALL)
- rval = (ssize_t)syscall(SYS_getrandom,
- (char *)buf + off, len - off, 0);
-#endif
-
- if (rval < 0) {
- if (errno == EINTR || errno == EAGAIN)
- continue;
-
- errno = EIO;
- return -1; /* unsupported by kernel */
- }
-
- if (rval == 0) {
- errno = EIO;
- return -1;
- }
-
- off += (size_t)rval;
- }
-
- errno = saved_errno;
- return 0;
-
-#else
- (void)buf;
- (void)len;
-
- errno = EIO;
- return -1;
-#endif
-}
-#endif
-#endif
-#else
-size_t
-fallback_rand_1989(void)
-{
- static size_t mix = 0;
- static size_t counter = 0;
-
- struct timeval tv;
-
- /* nobody should use this
- * (not crypto-safe)
- */
-
- gettimeofday(&tv, NULL);
-
- mix ^= (size_t)tv.tv_sec
- ^ (size_t)tv.tv_usec
- ^ (size_t)getpid()
- ^ (size_t)&mix
- ^ counter++
- ^ entropy_jitter();
-
- /*
- * Stack addresses can vary between
- * calls, thus increasing entropy.
- */
- mix ^= (size_t)&mix;
- mix ^= (size_t)&tv;
- mix ^= (size_t)&counter;
-
- return mix;
-}
-
-size_t
-entropy_jitter(void)
-{
- size_t mix;
-
- struct timeval a, b;
- ssize_t mix_diff;
-
- int c;
-
- mix = 0;
-
- gettimeofday(&a, NULL);
-
- for (c = 0; c < 32; c++) {
-
- getpid();
- gettimeofday(&b, NULL);
-
- /*
- * prevent negative numbers to prevent overflow,
- * which would bias rand to large numbers
- */
- mix_diff = (ssize_t)(b.tv_usec - a.tv_usec);
- if (mix_diff < 0)
- mix_diff = -mix_diff;
-
- mix ^= (size_t)(mix_diff);
-
- mix ^= (size_t)&mix;
-
- }
-
- return mix;
-}
-#endif
-
-void
-check_bin(size_t a, const char *a_name)
-{
- if (a > 1)
- err(EINVAL, "%s must be 0 or 1, but is %lu",
- a_name, (size_t)a);
-}