| @@ -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(); | |||
| } | |||