mirror of
https://codeberg.org/libreboot/lbmk.git
synced 2026-03-25 13:29:03 +02:00
util/nvmutil: rand: use getrandom on newer linux
we still fall back to the old /dev/urandom read on older linux, via runtime detection (ENOSYS). getrandom is better, because it guarantees entropy via blocking, and works even when /dev/urandom is unavailable. it has the same practical benefit as arc4random, which i use on bsd. linux can have arc4random, but not every linux libc has it, so it's better to use getrandom on linux. older linux will fall back to /dev/urandom Signed-off-by: Leah Rowe <leah@libreboot.org>
This commit is contained in:
@@ -9,6 +9,25 @@
|
||||
#include <sys/stat.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* for linux getrandom
|
||||
*/
|
||||
#if defined(__linux__)
|
||||
#include <errno.h>
|
||||
#if defined(__has_include)
|
||||
#if __has_include(<sys/random.h>)
|
||||
#include <sys/random.h>
|
||||
#define HAVE_GETRANDOM 1
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(HAVE_GETRANDOM)
|
||||
#include <sys/syscall.h>
|
||||
#if defined(SYS_getrandom)
|
||||
#define HAVE_GETRANDOM_SYSCALL 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define items(x) (sizeof((x)) / sizeof((x)[0]))
|
||||
|
||||
/* system prototypes
|
||||
@@ -318,6 +337,12 @@ void set_mac_nib(unsigned long mac_str_pos,
|
||||
unsigned long mac_byte_pos, unsigned long mac_nib_pos);
|
||||
unsigned short hextonum(char ch_s);
|
||||
unsigned long rlong(void);
|
||||
#if defined(__linux__)
|
||||
#if defined(HAVE_GETRANDOM) || \
|
||||
defined(HAVE_GETRANDOM_SYSCALL)
|
||||
int fallback_rand_getrandom(void *buf, size_t len);
|
||||
#endif
|
||||
#endif
|
||||
void write_mac_part(unsigned long partnum);
|
||||
|
||||
/* Helper functions for command: dump
|
||||
|
||||
@@ -75,6 +75,37 @@ rlong(void)
|
||||
unsigned long rval;
|
||||
long new_nr;
|
||||
|
||||
int retries = 0;
|
||||
int max_retries = 100;
|
||||
|
||||
#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
|
||||
*
|
||||
* similar benefits to arc4random
|
||||
* e.g. works in chroot, blocks
|
||||
* until it has enough entropy,
|
||||
* and works even when /dev/urandom
|
||||
* is available (doesn't use it);
|
||||
* it's generally more reliable
|
||||
*/
|
||||
|
||||
if (fallback_rand_getrandom(&rval, sizeof(rval)) == 0)
|
||||
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
|
||||
@@ -87,9 +118,6 @@ rlong(void)
|
||||
* tricks to mitigate possible os bugs
|
||||
*/
|
||||
|
||||
int retries = 0;
|
||||
int max_retries = 100;
|
||||
|
||||
retry_urandom_read:
|
||||
|
||||
if (++retries > max_retries)
|
||||
@@ -104,6 +132,10 @@ retry_urandom_read:
|
||||
O_CLOEXEC);
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
/* TODO: dead code
|
||||
openbsd 2.1 had arc4random.
|
||||
arandam was introduced **later**
|
||||
*/
|
||||
if (fd < 0) /* old openbsd */
|
||||
fd = open("/dev/arandom",
|
||||
O_RDONLY | O_BINARY | O_NOFOLLOW |
|
||||
@@ -178,6 +210,51 @@ rlong_next:
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__linux__)
|
||||
#if defined(HAVE_GETRANDOM) || \
|
||||
defined(HAVE_GETRANDOM_SYSCALL)
|
||||
int
|
||||
fallback_rand_getrandom(void *buf, size_t len)
|
||||
{
|
||||
ssize_t rval = -1;
|
||||
|
||||
/* keep strict compiler
|
||||
* happy if unused
|
||||
*/
|
||||
(void)rval;
|
||||
(void)buf;
|
||||
(void)len;
|
||||
|
||||
#if defined(HAVE_GETRANDOM)
|
||||
do {
|
||||
rval = getrandom(buf, len, 0);
|
||||
} while (rval < 0 && errno == EINTR);
|
||||
|
||||
#elif defined(HAVE_GETRANDOM_SYSCALL)
|
||||
do {
|
||||
rval = syscall(SYS_getrandom, buf, len, 0);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GETRANDOM) || \
|
||||
defined(HAVE_GETRANDOM_SYSCALL)
|
||||
|
||||
if (rval == (ssize_t)len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rval < 0 && errno == ENOSYS)
|
||||
return -1; /* not supported by kernel */
|
||||
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void
|
||||
check_bin(unsigned long a, const char *a_name)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user