diff --git a/CMakeLists.txt b/CMakeLists.txt index db6053ce8..2d052c3b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -533,6 +533,7 @@ if (WIN32) list(APPEND SYMBOLS_TO_CHECK _gmtime64 _gmtime64_s + BCryptGenRandom ) else() list(APPEND SYMBOLS_TO_CHECK diff --git a/arc4random.c b/arc4random.c index 10f3c586f..3ff683404 100644 --- a/arc4random.c +++ b/arc4random.c @@ -52,7 +52,11 @@ #ifndef ARC4RANDOM_NO_INCLUDES #include "evconfig-private.h" #ifdef _WIN32 +#ifndef EVENT__HAVE_BCRYPTGENRANDOM +#include +#else #include +#endif #include #include #else @@ -153,9 +157,25 @@ static int arc4_seed_win32(void) { unsigned char buf[ADD_ENTROPY]; +#ifndef EVENT__HAVE_BCRYPTGENRANDOM + /* This is adapted from Tor's crypto_seed_rng() */ + static int provider_set = 0; + static HCRYPTPROV provider; + + if (!provider_set) { + if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) { + if (GetLastError() != (DWORD)NTE_BAD_KEYSET) + return -1; + } + provider_set = 1; + } + if (!CryptGenRandom(provider, sizeof(buf), buf)) +#else if (BCryptGenRandom(NULL, buf, sizeof(buf), BCRYPT_USE_SYSTEM_PREFERRED_RNG)) +#endif return -1; arc4_addrandom(buf, sizeof(buf)); evutil_memclear_(buf, sizeof(buf)); diff --git a/event-config.h.cmake b/event-config.h.cmake index 68c9cc723..db9a379d2 100644 --- a/event-config.h.cmake +++ b/event-config.h.cmake @@ -285,6 +285,9 @@ /* Define to 1 if you have the `_gmtime64' function. */ #cmakedefine EVENT__HAVE__GMTIME64 1 +/* Define to 1 if you have the `BCryptGenRandom' function. */ +#cmakedefine EVENT__HAVE_BCRYPTGENRANDOM 1 + /* Define to 1 if the system has the type `struct addrinfo'. */ #cmakedefine EVENT__HAVE_STRUCT_ADDRINFO 1