diff --git a/configure b/configure index d10cf33..7be160e 100755 --- a/configure +++ b/configure @@ -633,6 +633,11 @@ if test_code 'arc4random_buf()' 'stdlib.h' '' '' 'arc4random_buf(NULL, 0);'; the add_def HAVE_ARC4RANDOM fi +if test_code 'getrandom()' 'stdlib.h sys/random.h' '' '' \ + 'getrandom(NULL, 256, 0);'; then + add_def HAVE_GETRANDOM +fi + RECVMMSG_CODE=' struct mmsghdr hdr; return !recvmmsg(0, &hdr, 1, MSG_DONTWAIT, 0);' diff --git a/sysincl.h b/sysincl.h index 1caf586..0e1c65a 100644 --- a/sysincl.h +++ b/sysincl.h @@ -76,4 +76,8 @@ #include #endif +#ifdef HAVE_GETRANDOM +#include +#endif + #endif /* GOT_SYSINCL_H */ diff --git a/util.c b/util.c index c336e36..ae530c9 100644 --- a/util.c +++ b/util.c @@ -1195,11 +1195,44 @@ UTI_GetRandomBytesUrandom(void *buf, unsigned int len) /* ================================================== */ +#ifdef HAVE_GETRANDOM +static void +get_random_bytes_getrandom(char *buf, unsigned int len) +{ + static char rand_buf[256]; + static unsigned int available = 0, disabled = 0; + unsigned int i; + + for (i = 0; i < len; i++) { + if (!available) { + if (disabled) + break; + + if (getrandom(rand_buf, sizeof (rand_buf), 0) != sizeof (rand_buf)) { + disabled = 1; + break; + } + + available = sizeof (rand_buf); + } + + buf[i] = rand_buf[--available]; + } + + if (i < len) + UTI_GetRandomBytesUrandom(buf, len); +} +#endif + +/* ================================================== */ + void UTI_GetRandomBytes(void *buf, unsigned int len) { #ifdef HAVE_ARC4RANDOM arc4random_buf(buf, len); +#elif defined(HAVE_GETRANDOM) + get_random_bytes_getrandom(buf, len); #else UTI_GetRandomBytesUrandom(buf, len); #endif