|
|
@@ -9,14 +9,13 @@ |
|
|
|
* |
|
|
|
*/ |
|
|
|
|
|
|
|
#include "random_seed.h" |
|
|
|
#include "config.h" |
|
|
|
#include "strerror_override.h" |
|
|
|
#include <stdio.h> |
|
|
|
#include "config.h" |
|
|
|
#include "random_seed.h" |
|
|
|
|
|
|
|
#define DEBUG_SEED(s) |
|
|
|
|
|
|
|
|
|
|
|
#if defined ENABLE_RDRAND |
|
|
|
|
|
|
|
/* cpuid */ |
|
|
@@ -26,6 +25,7 @@ |
|
|
|
|
|
|
|
static void do_cpuid(int regs[], int h) |
|
|
|
{ |
|
|
|
/* clang-format off */ |
|
|
|
__asm__ __volatile__( |
|
|
|
#if defined __x86_64__ |
|
|
|
"pushq %%rbx;\n" |
|
|
@@ -40,6 +40,7 @@ static void do_cpuid(int regs[], int h) |
|
|
|
#endif |
|
|
|
: "=a"(regs[0]), [ebx] "=r"(regs[1]), "=c"(regs[2]), "=d"(regs[3]) |
|
|
|
: "a"(h)); |
|
|
|
/* clang-format on */ |
|
|
|
} |
|
|
|
|
|
|
|
#elif defined _MSC_VER |
|
|
@@ -55,10 +56,10 @@ static void do_cpuid(int regs[], int h) |
|
|
|
|
|
|
|
static int has_rdrand(void) |
|
|
|
{ |
|
|
|
// CPUID.01H:ECX.RDRAND[bit 30] == 1 |
|
|
|
int regs[4]; |
|
|
|
do_cpuid(regs, 1); |
|
|
|
return (regs[2] & (1 << 30)) != 0; |
|
|
|
// CPUID.01H:ECX.RDRAND[bit 30] == 1 |
|
|
|
int regs[4]; |
|
|
|
do_cpuid(regs, 1); |
|
|
|
return (regs[2] & (1 << 30)) != 0; |
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
@@ -71,15 +72,17 @@ static int has_rdrand(void) |
|
|
|
|
|
|
|
static int get_rdrand_seed(void) |
|
|
|
{ |
|
|
|
DEBUG_SEED("get_rdrand_seed"); |
|
|
|
int _eax; |
|
|
|
// rdrand eax |
|
|
|
__asm__ __volatile__("1: .byte 0x0F\n" |
|
|
|
" .byte 0xC7\n" |
|
|
|
" .byte 0xF0\n" |
|
|
|
" jnc 1b;\n" |
|
|
|
: "=a" (_eax)); |
|
|
|
return _eax; |
|
|
|
DEBUG_SEED("get_rdrand_seed"); |
|
|
|
int _eax; |
|
|
|
// rdrand eax |
|
|
|
/* clang-format off */ |
|
|
|
__asm__ __volatile__("1: .byte 0x0F\n" |
|
|
|
" .byte 0xC7\n" |
|
|
|
" .byte 0xF0\n" |
|
|
|
" jnc 1b;\n" |
|
|
|
: "=a" (_eax)); |
|
|
|
/* clang-format on */ |
|
|
|
return _eax; |
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
@@ -93,10 +96,11 @@ static int get_rdrand_seed(void) |
|
|
|
|
|
|
|
static int get_rdrand_seed(void) |
|
|
|
{ |
|
|
|
DEBUG_SEED("get_rdrand_seed"); |
|
|
|
int r; |
|
|
|
while (_rdrand32_step(&r) == 0); |
|
|
|
return r; |
|
|
|
DEBUG_SEED("get_rdrand_seed"); |
|
|
|
int r; |
|
|
|
while (_rdrand32_step(&r) == 0) |
|
|
|
; |
|
|
|
return r; |
|
|
|
} |
|
|
|
|
|
|
|
#elif defined _M_IX86 |
|
|
@@ -104,6 +108,7 @@ static int get_rdrand_seed(void) |
|
|
|
|
|
|
|
/* get_rdrand_seed - Visual Studio 2010 and below - x86 only */ |
|
|
|
|
|
|
|
/* clang-format off */ |
|
|
|
static int get_rdrand_seed(void) |
|
|
|
{ |
|
|
|
DEBUG_SEED("get_rdrand_seed"); |
|
|
@@ -115,21 +120,21 @@ retry: |
|
|
|
__asm mov _eax, eax |
|
|
|
return _eax; |
|
|
|
} |
|
|
|
/* clang-format on */ |
|
|
|
|
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
#endif /* defined ENABLE_RDRAND */ |
|
|
|
|
|
|
|
|
|
|
|
/* has_dev_urandom */ |
|
|
|
|
|
|
|
#if defined (__APPLE__) || defined(__unix__) || defined(__linux__) |
|
|
|
#if defined(__APPLE__) || defined(__unix__) || defined(__linux__) |
|
|
|
|
|
|
|
#include <string.h> |
|
|
|
#include <fcntl.h> |
|
|
|
#include <string.h> |
|
|
|
#if HAVE_UNISTD_H |
|
|
|
# include <unistd.h> |
|
|
|
#include <unistd.h> |
|
|
|
#endif /* HAVE_UNISTD_H */ |
|
|
|
#include <stdlib.h> |
|
|
|
#include <sys/stat.h> |
|
|
@@ -140,101 +145,105 @@ static const char *dev_random_file = "/dev/urandom"; |
|
|
|
|
|
|
|
static int has_dev_urandom(void) |
|
|
|
{ |
|
|
|
struct stat buf; |
|
|
|
if (stat(dev_random_file, &buf)) { |
|
|
|
return 0; |
|
|
|
} |
|
|
|
return ((buf.st_mode & S_IFCHR) != 0); |
|
|
|
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"); |
|
|
|
|
|
|
|
int fd = open(dev_random_file, O_RDONLY); |
|
|
|
if (fd < 0) { |
|
|
|
fprintf(stderr, "error opening %s: %s", dev_random_file, strerror(errno)); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
|
|
|
|
int r; |
|
|
|
ssize_t nread = read(fd, &r, sizeof(r)); |
|
|
|
if (nread != sizeof(r)) { |
|
|
|
fprintf(stderr, "error short read %s: %s", dev_random_file, strerror(errno)); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
|
|
|
|
close(fd); |
|
|
|
return r; |
|
|
|
DEBUG_SEED("get_dev_random_seed"); |
|
|
|
|
|
|
|
int fd = open(dev_random_file, O_RDONLY); |
|
|
|
if (fd < 0) |
|
|
|
{ |
|
|
|
fprintf(stderr, "error opening %s: %s", dev_random_file, strerror(errno)); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
|
|
|
|
int r; |
|
|
|
ssize_t nread = read(fd, &r, sizeof(r)); |
|
|
|
if (nread != sizeof(r)) |
|
|
|
{ |
|
|
|
fprintf(stderr, "error short read %s: %s", dev_random_file, strerror(errno)); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
|
|
|
|
close(fd); |
|
|
|
return r; |
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
/* get_cryptgenrandom_seed */ |
|
|
|
|
|
|
|
#ifdef WIN32 |
|
|
|
|
|
|
|
#define HAVE_CRYPTGENRANDOM 1 |
|
|
|
|
|
|
|
#include <windows.h> |
|
|
|
#include <wincrypt.h> |
|
|
|
#include <windows.h> |
|
|
|
#ifndef __GNUC__ |
|
|
|
#pragma comment(lib, "advapi32.lib") |
|
|
|
#endif |
|
|
|
|
|
|
|
static int get_cryptgenrandom_seed(void) |
|
|
|
{ |
|
|
|
HCRYPTPROV hProvider = 0; |
|
|
|
int r; |
|
|
|
HCRYPTPROV hProvider = 0; |
|
|
|
int r; |
|
|
|
|
|
|
|
DEBUG_SEED("get_cryptgenrandom_seed"); |
|
|
|
DEBUG_SEED("get_cryptgenrandom_seed"); |
|
|
|
|
|
|
|
if (!CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { |
|
|
|
fprintf(stderr, "error CryptAcquireContextW"); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
if (!CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, |
|
|
|
CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) |
|
|
|
{ |
|
|
|
fprintf(stderr, "error CryptAcquireContextW"); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
|
|
|
|
if (!CryptGenRandom(hProvider, sizeof(r), (BYTE*)&r)) { |
|
|
|
fprintf(stderr, "error CryptGenRandom"); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
if (!CryptGenRandom(hProvider, sizeof(r), (BYTE *)&r)) |
|
|
|
{ |
|
|
|
fprintf(stderr, "error CryptGenRandom"); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
|
|
|
|
CryptReleaseContext(hProvider, 0); |
|
|
|
CryptReleaseContext(hProvider, 0); |
|
|
|
|
|
|
|
return r; |
|
|
|
return r; |
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
/* get_time_seed */ |
|
|
|
|
|
|
|
#include <time.h> |
|
|
|
|
|
|
|
static int get_time_seed(void) |
|
|
|
{ |
|
|
|
DEBUG_SEED("get_time_seed"); |
|
|
|
DEBUG_SEED("get_time_seed"); |
|
|
|
|
|
|
|
return (int)time(NULL) * 433494437; |
|
|
|
return (int)time(NULL) * 433494437; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* json_c_get_random_seed */ |
|
|
|
|
|
|
|
int json_c_get_random_seed(void) |
|
|
|
{ |
|
|
|
#if defined HAVE_RDRAND && HAVE_RDRAND |
|
|
|
if (has_rdrand()) return get_rdrand_seed(); |
|
|
|
if (has_rdrand()) |
|
|
|
return get_rdrand_seed(); |
|
|
|
#endif |
|
|
|
#if defined HAVE_DEV_RANDOM && HAVE_DEV_RANDOM |
|
|
|
if (has_dev_urandom()) return get_dev_random_seed(); |
|
|
|
if (has_dev_urandom()) |
|
|
|
return get_dev_random_seed(); |
|
|
|
#endif |
|
|
|
#if defined HAVE_CRYPTGENRANDOM && HAVE_CRYPTGENRANDOM |
|
|
|
return get_cryptgenrandom_seed(); |
|
|
|
return get_cryptgenrandom_seed(); |
|
|
|
#endif |
|
|
|
return get_time_seed(); |
|
|
|
return get_time_seed(); |
|
|
|
} |