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 <sys/stat.h>
|
||||||
#include <limits.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]))
|
#define items(x) (sizeof((x)) / sizeof((x)[0]))
|
||||||
|
|
||||||
/* system prototypes
|
/* 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 long mac_byte_pos, unsigned long mac_nib_pos);
|
||||||
unsigned short hextonum(char ch_s);
|
unsigned short hextonum(char ch_s);
|
||||||
unsigned long rlong(void);
|
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);
|
void write_mac_part(unsigned long partnum);
|
||||||
|
|
||||||
/* Helper functions for command: dump
|
/* Helper functions for command: dump
|
||||||
|
|||||||
@@ -75,6 +75,37 @@ rlong(void)
|
|||||||
unsigned long rval;
|
unsigned long rval;
|
||||||
long new_nr;
|
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
|
/* reading from urandom is inherently
|
||||||
* unreliable on old systems, even if
|
* unreliable on old systems, even if
|
||||||
* newer systems make it more reliable
|
* newer systems make it more reliable
|
||||||
@@ -87,9 +118,6 @@ rlong(void)
|
|||||||
* tricks to mitigate possible os bugs
|
* tricks to mitigate possible os bugs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int retries = 0;
|
|
||||||
int max_retries = 100;
|
|
||||||
|
|
||||||
retry_urandom_read:
|
retry_urandom_read:
|
||||||
|
|
||||||
if (++retries > max_retries)
|
if (++retries > max_retries)
|
||||||
@@ -104,6 +132,10 @@ retry_urandom_read:
|
|||||||
O_CLOEXEC);
|
O_CLOEXEC);
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
|
/* TODO: dead code
|
||||||
|
openbsd 2.1 had arc4random.
|
||||||
|
arandam was introduced **later**
|
||||||
|
*/
|
||||||
if (fd < 0) /* old openbsd */
|
if (fd < 0) /* old openbsd */
|
||||||
fd = open("/dev/arandom",
|
fd = open("/dev/arandom",
|
||||||
O_RDONLY | O_BINARY | O_NOFOLLOW |
|
O_RDONLY | O_BINARY | O_NOFOLLOW |
|
||||||
@@ -178,6 +210,51 @@ rlong_next:
|
|||||||
#endif
|
#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
|
void
|
||||||
check_bin(unsigned long a, const char *a_name)
|
check_bin(unsigned long a, const char *a_name)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user