diff --git a/CMakeLists.txt b/CMakeLists.txt index c334316..2333d08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -144,6 +144,7 @@ check_include_file(stdint.h HAVE_STDINT_H) check_include_file(stdlib.h HAVE_STDLIB_H) check_include_file(sys/cdefs.h HAVE_SYS_CDEFS_H) check_include_file(sys/param.h HAVE_SYS_PARAM_H) +check_include_file(sys/random.h HAVE_SYS_RANDOM_H) check_include_file(sys/stat.h HAVE_SYS_STAT_H) check_include_file(xlocale.h HAVE_XLOCALE_H) @@ -190,6 +191,9 @@ endif() if (HAVE_SYSLOG_H) check_symbol_exists(vsyslog "syslog.h" HAVE_VSYSLOG) endif() +if (HAVE_SYS_RANDOM_H) + check_symbol_exists(getrandom "sys/random.h" HAVE_GETRANDOM) +endif() if (HAVE_SYS_RESOURCE_H) check_symbol_exists(getrusage "sys/resource.h" HAVE_GETRUSAGE) endif() diff --git a/cmake/config.h.in b/cmake/config.h.in index 547a585..9e097cb 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in @@ -56,6 +56,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_PARAM_H @HAVE_SYS_PARAM_H@ +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_RANDOM_H + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_RESOURCE_H @@ -140,6 +143,9 @@ /* Define to 1 if you have the `vsyslog' function. */ #cmakedefine HAVE_VSYSLOG @HAVE_VSYSLOG@ +/* Define if you have the `getrandom' function. */ +#cmakedefine HAVE_GETRANDOM + /* Define if you have the `getrusage' function. */ #cmakedefine HAVE_GETRUSAGE diff --git a/random_seed.c b/random_seed.c index 1a15350..17727c6 100644 --- a/random_seed.c +++ b/random_seed.c @@ -155,6 +155,40 @@ retry: #endif /* defined ENABLE_RDRAND */ +#ifdef HAVE_GETRANDOM + +#include +#ifdef HAVE_SYS_RANDOM_H +#include +#endif + +static int get_getrandom_seed(void) +{ + DEBUG_SEED("get_dev_random_seed"); + + int r; + ssize_t ret; + + do { + ret = getrandom(&r, sizeof(r), 0); + } while ((ret == -1) && (errno == EINTR)); + + if (ret == -1) + { + if (errno == ENOSYS) /* syscall not available in kernel */ + return -1; + + fprintf(stderr, "error from getrandom(): %s", strerror(errno)); + exit(1); + } + + if (ret != sizeof(r)) + return -1; + + return r; +} +#endif /* defined HAVE_GETRANDOM */ + /* has_dev_urandom */ #if defined(__APPLE__) || defined(__unix__) || defined(__linux__) @@ -283,6 +317,13 @@ int json_c_get_random_seed(void) if (has_rdrand()) return get_rdrand_seed(); #endif +#ifdef HAVE_GETRANDOM + { + int seed = get_getrandom_seed(); + if (seed != -1) + return seed; + } +#endif #if defined HAVE_DEV_RANDOM && HAVE_DEV_RANDOM if (has_dev_urandom()) return get_dev_random_seed();