diff options
Diffstat (limited to 'random_seed.c')
-rw-r--r-- | random_seed.c | 106 |
1 files changed, 62 insertions, 44 deletions
diff --git a/random_seed.c b/random_seed.c index 17727c6..f474e39 100644 --- a/random_seed.c +++ b/random_seed.c @@ -13,9 +13,23 @@ #include "config.h" #include "strerror_override.h" #include <stdio.h> +#include <stdlib.h> +#ifdef HAVE_BSD_STDLIB_H +#include <bsd/stdlib.h> +#endif #define DEBUG_SEED(s) +#if defined(__APPLE__) || defined(__unix__) || defined(__linux__) +#define HAVE_DEV_RANDOM 1 +#endif + +#ifdef HAVE_ARC4RANDOM +#undef HAVE_GETRANDOM +#undef HAVE_DEV_RANDOM +#undef HAVE_CRYPTGENRANDOM +#endif + #if defined ENABLE_RDRAND /* cpuid */ @@ -162,36 +176,38 @@ retry: #include <sys/random.h> #endif -static int get_getrandom_seed(void) +static int get_getrandom_seed(int *seed) { - DEBUG_SEED("get_dev_random_seed"); + DEBUG_SEED("get_getrandom_seed"); - int r; ssize_t ret; - do { - ret = getrandom(&r, sizeof(r), 0); + do + { + ret = getrandom(seed, sizeof(*seed), GRND_NONBLOCK); } while ((ret == -1) && (errno == EINTR)); if (ret == -1) { if (errno == ENOSYS) /* syscall not available in kernel */ return -1; + if (errno == EAGAIN) /* entropy not yet initialized */ + return -1; fprintf(stderr, "error from getrandom(): %s", strerror(errno)); - exit(1); + return -1; } - if (ret != sizeof(r)) + if (ret != sizeof(*seed)) return -1; - return r; + return 0; } #endif /* defined HAVE_GETRANDOM */ -/* has_dev_urandom */ +/* get_dev_random_seed */ -#if defined(__APPLE__) || defined(__unix__) || defined(__linux__) +#ifdef HAVE_DEV_RANDOM #include <fcntl.h> #include <string.h> @@ -201,43 +217,34 @@ static int get_getrandom_seed(void) #include <stdlib.h> #include <sys/stat.h> -#define HAVE_DEV_RANDOM 1 - static const char *dev_random_file = "/dev/urandom"; -static int has_dev_urandom(void) +static int get_dev_random_seed(int *seed) { + DEBUG_SEED("get_dev_random_seed"); + struct stat buf; if (stat(dev_random_file, &buf)) - { - return 0; - } - return ((buf.st_mode & S_IFCHR) != 0); -} - -/* get_dev_random_seed */ - -static int get_dev_random_seed(void) -{ - DEBUG_SEED("get_dev_random_seed"); + return -1; + if ((buf.st_mode & S_IFCHR) == 0) + return -1; int fd = open(dev_random_file, O_RDONLY); if (fd < 0) { fprintf(stderr, "error opening %s: %s", dev_random_file, strerror(errno)); - exit(1); + return -1; } - int r; - ssize_t nread = read(fd, &r, sizeof(r)); - if (nread != sizeof(r)) + ssize_t nread = read(fd, seed, sizeof(*seed)); + if (nread != sizeof(*seed)) { fprintf(stderr, "error short read %s: %s", dev_random_file, strerror(errno)); - exit(1); + return -1; } close(fd); - return r; + return 0; } #endif @@ -260,13 +267,10 @@ static int get_dev_random_seed(void) #pragma comment(lib, "advapi32.lib") #endif -static int get_time_seed(void); - -static int get_cryptgenrandom_seed(void) +static int get_cryptgenrandom_seed(int *seed) { HCRYPTPROV hProvider = 0; DWORD dwFlags = CRYPT_VERIFYCONTEXT; - int r; DEBUG_SEED("get_cryptgenrandom_seed"); @@ -277,34 +281,36 @@ static int get_cryptgenrandom_seed(void) if (!CryptAcquireContextA(&hProvider, 0, 0, PROV_RSA_FULL, dwFlags)) { fprintf(stderr, "error CryptAcquireContextA 0x%08lx", GetLastError()); - r = get_time_seed(); + return -1; } else { - BOOL ret = CryptGenRandom(hProvider, sizeof(r), (BYTE*)&r); + BOOL ret = CryptGenRandom(hProvider, sizeof(*seed), (BYTE *)seed); CryptReleaseContext(hProvider, 0); if (!ret) { fprintf(stderr, "error CryptGenRandom 0x%08lx", GetLastError()); - r = get_time_seed(); + return -1; } } - return r; + return 0; } #endif /* get_time_seed */ +#ifndef HAVE_ARC4RANDOM #include <time.h> static int get_time_seed(void) { DEBUG_SEED("get_time_seed"); - return (int)time(NULL) * 433494437; + return (unsigned)time(NULL) * 433494437; } +#endif /* json_c_get_random_seed */ @@ -317,19 +323,31 @@ int json_c_get_random_seed(void) if (has_rdrand()) return get_rdrand_seed(); #endif +#ifdef HAVE_ARC4RANDOM + /* arc4random never fails, so use it if it's available */ + return arc4random(); +#else #ifdef HAVE_GETRANDOM { - int seed = get_getrandom_seed(); - if (seed != -1) + int seed; + if (get_getrandom_seed(&seed) == 0) return seed; } #endif #if defined HAVE_DEV_RANDOM && HAVE_DEV_RANDOM - if (has_dev_urandom()) - return get_dev_random_seed(); + { + int seed; + if (get_dev_random_seed(&seed) == 0) + return seed; + } #endif #if defined HAVE_CRYPTGENRANDOM && HAVE_CRYPTGENRANDOM - return get_cryptgenrandom_seed(); + { + int seed; + if (get_cryptgenrandom_seed(&seed) == 0) + return seed; + } #endif return get_time_seed(); +#endif /* !HAVE_ARC4RANDOM */ } |