| @@ -9,14 +9,13 @@ | |||||
| * | * | ||||
| */ | */ | ||||
| #include "random_seed.h" | |||||
| #include "config.h" | |||||
| #include "strerror_override.h" | #include "strerror_override.h" | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include "config.h" | |||||
| #include "random_seed.h" | |||||
| #define DEBUG_SEED(s) | #define DEBUG_SEED(s) | ||||
| #if defined ENABLE_RDRAND | #if defined ENABLE_RDRAND | ||||
| /* cpuid */ | /* cpuid */ | ||||
| @@ -26,6 +25,7 @@ | |||||
| static void do_cpuid(int regs[], int h) | static void do_cpuid(int regs[], int h) | ||||
| { | { | ||||
| /* clang-format off */ | |||||
| __asm__ __volatile__( | __asm__ __volatile__( | ||||
| #if defined __x86_64__ | #if defined __x86_64__ | ||||
| "pushq %%rbx;\n" | "pushq %%rbx;\n" | ||||
| @@ -40,6 +40,7 @@ static void do_cpuid(int regs[], int h) | |||||
| #endif | #endif | ||||
| : "=a"(regs[0]), [ebx] "=r"(regs[1]), "=c"(regs[2]), "=d"(regs[3]) | : "=a"(regs[0]), [ebx] "=r"(regs[1]), "=c"(regs[2]), "=d"(regs[3]) | ||||
| : "a"(h)); | : "a"(h)); | ||||
| /* clang-format on */ | |||||
| } | } | ||||
| #elif defined _MSC_VER | #elif defined _MSC_VER | ||||
| @@ -55,10 +56,10 @@ static void do_cpuid(int regs[], int h) | |||||
| static int has_rdrand(void) | 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 | #endif | ||||
| @@ -71,15 +72,17 @@ static int has_rdrand(void) | |||||
| static int get_rdrand_seed(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 | #endif | ||||
| @@ -93,10 +96,11 @@ static int get_rdrand_seed(void) | |||||
| 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 | #elif defined _M_IX86 | ||||
| @@ -104,6 +108,7 @@ static int get_rdrand_seed(void) | |||||
| /* get_rdrand_seed - Visual Studio 2010 and below - x86 only */ | /* get_rdrand_seed - Visual Studio 2010 and below - x86 only */ | ||||
| /* clang-format off */ | |||||
| static int get_rdrand_seed(void) | static int get_rdrand_seed(void) | ||||
| { | { | ||||
| DEBUG_SEED("get_rdrand_seed"); | DEBUG_SEED("get_rdrand_seed"); | ||||
| @@ -115,21 +120,21 @@ retry: | |||||
| __asm mov _eax, eax | __asm mov _eax, eax | ||||
| return _eax; | return _eax; | ||||
| } | } | ||||
| /* clang-format on */ | |||||
| #endif | #endif | ||||
| #endif | #endif | ||||
| #endif /* defined ENABLE_RDRAND */ | #endif /* defined ENABLE_RDRAND */ | ||||
| /* has_dev_urandom */ | /* has_dev_urandom */ | ||||
| #if defined (__APPLE__) || defined(__unix__) || defined(__linux__) | |||||
| #if defined(__APPLE__) || defined(__unix__) || defined(__linux__) | |||||
| #include <string.h> | |||||
| #include <fcntl.h> | #include <fcntl.h> | ||||
| #include <string.h> | |||||
| #if HAVE_UNISTD_H | #if HAVE_UNISTD_H | ||||
| # include <unistd.h> | |||||
| #include <unistd.h> | |||||
| #endif /* HAVE_UNISTD_H */ | #endif /* HAVE_UNISTD_H */ | ||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||
| @@ -140,101 +145,105 @@ static const char *dev_random_file = "/dev/urandom"; | |||||
| static int has_dev_urandom(void) | 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 */ | /* get_dev_random_seed */ | ||||
| static int get_dev_random_seed(void) | 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 | #endif | ||||
| /* get_cryptgenrandom_seed */ | /* get_cryptgenrandom_seed */ | ||||
| #ifdef WIN32 | #ifdef WIN32 | ||||
| #define HAVE_CRYPTGENRANDOM 1 | #define HAVE_CRYPTGENRANDOM 1 | ||||
| #include <windows.h> | |||||
| #include <wincrypt.h> | #include <wincrypt.h> | ||||
| #include <windows.h> | |||||
| #ifndef __GNUC__ | #ifndef __GNUC__ | ||||
| #pragma comment(lib, "advapi32.lib") | #pragma comment(lib, "advapi32.lib") | ||||
| #endif | #endif | ||||
| static int get_cryptgenrandom_seed(void) | 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 | #endif | ||||
| /* get_time_seed */ | /* get_time_seed */ | ||||
| #include <time.h> | #include <time.h> | ||||
| static int get_time_seed(void) | 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 */ | /* json_c_get_random_seed */ | ||||
| int json_c_get_random_seed(void) | int json_c_get_random_seed(void) | ||||
| { | { | ||||
| #if defined HAVE_RDRAND && HAVE_RDRAND | #if defined HAVE_RDRAND && HAVE_RDRAND | ||||
| if (has_rdrand()) return get_rdrand_seed(); | |||||
| if (has_rdrand()) | |||||
| return get_rdrand_seed(); | |||||
| #endif | #endif | ||||
| #if defined HAVE_DEV_RANDOM && HAVE_DEV_RANDOM | #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 | #endif | ||||
| #if defined HAVE_CRYPTGENRANDOM && HAVE_CRYPTGENRANDOM | #if defined HAVE_CRYPTGENRANDOM && HAVE_CRYPTGENRANDOM | ||||
| return get_cryptgenrandom_seed(); | |||||
| return get_cryptgenrandom_seed(); | |||||
| #endif | #endif | ||||
| return get_time_seed(); | |||||
| return get_time_seed(); | |||||
| } | } | ||||