diff options
Diffstat (limited to 'lib/rand.c')
-rw-r--r-- | lib/rand.c | 77 |
1 files changed, 73 insertions, 4 deletions
@@ -18,6 +18,8 @@ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * + * SPDX-License-Identifier: curl + * ***************************************************************************/ #include "curl_setup.h" @@ -36,6 +38,64 @@ #include "curl_memory.h" #include "memdebug.h" +#ifdef WIN32 + +#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) +# define HAVE_MINGW_ORIGINAL +#endif + +#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 && \ + !defined(HAVE_MINGW_ORIGINAL) +# define HAVE_WIN_BCRYPTGENRANDOM +# include <bcrypt.h> +# ifdef _MSC_VER +# pragma comment(lib, "bcrypt.lib") +# endif +# ifndef BCRYPT_USE_SYSTEM_PREFERRED_RNG +# define BCRYPT_USE_SYSTEM_PREFERRED_RNG 0x00000002 +# endif +# ifndef STATUS_SUCCESS +# define STATUS_SUCCESS ((NTSTATUS)0x00000000L) +# endif +#elif defined(USE_WIN32_CRYPTO) +# include <wincrypt.h> +# ifdef _MSC_VER +# pragma comment(lib, "advapi32.lib") +# endif +#endif + +CURLcode Curl_win32_random(unsigned char *entropy, size_t length) +{ + memset(entropy, 0, length); + +#if defined(HAVE_WIN_BCRYPTGENRANDOM) + if(BCryptGenRandom(NULL, entropy, (ULONG)length, + BCRYPT_USE_SYSTEM_PREFERRED_RNG) != STATUS_SUCCESS) + return CURLE_FAILED_INIT; + + return CURLE_OK; +#elif defined(USE_WIN32_CRYPTO) + { + HCRYPTPROV hCryptProv = 0; + + if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) + return CURLE_FAILED_INIT; + + if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) { + CryptReleaseContext(hCryptProv, 0UL); + return CURLE_FAILED_INIT; + } + + CryptReleaseContext(hCryptProv, 0UL); + } + return CURLE_OK; +#else + return CURLE_NOT_BUILT_IN; +#endif +} +#endif + static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) { unsigned int r; @@ -71,7 +131,15 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) /* ---- non-cryptographic version following ---- */ -#ifdef RANDOM_FILE +#ifdef WIN32 + if(!seeded) { + result = Curl_win32_random((unsigned char *)rnd, sizeof(*rnd)); + if(result != CURLE_NOT_BUILT_IN) + return result; + } +#endif + +#if defined(RANDOM_FILE) && !defined(WIN32) if(!seeded) { /* if there's a random file to read a seed from, use it */ int fd = open(RANDOM_FILE, O_RDONLY); @@ -106,7 +174,8 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) * 'rndptr' points to. * * If libcurl is built without TLS support or with a TLS backend that lacks a - * proper random API (Gskit or mbedTLS), this function will use "weak" random. + * proper random API (rustls, Gskit or mbedTLS), this function will use "weak" + * random. * * When built *with* TLS support and a backend that offers strong random, it * will return error if it cannot provide strong random values. @@ -143,7 +212,7 @@ CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num) /* * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random - * hexadecimal digits PLUS a zero terminating byte. It must be an odd number + * hexadecimal digits PLUS a null-terminating byte. It must be an odd number * size. */ @@ -166,7 +235,7 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, /* make sure it fits in the local buffer and that it is an odd number! */ return CURLE_BAD_FUNCTION_ARGUMENT; - num--; /* save one for zero termination */ + num--; /* save one for null-termination */ result = Curl_rand(data, buffer, num/2); if(result) |