summaryrefslogtreecommitdiff
path: root/random_seed.c
diff options
context:
space:
mode:
Diffstat (limited to 'random_seed.c')
-rw-r--r--random_seed.c106
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 */
}