mirror of
https://github.com/curl/curl.git
synced 2025-09-17 01:22:41 +03:00
windows: improve random source
- Use the Windows API to seed the fallback random generator. This ensures to always have a random seed, even when libcurl is built with a vtls backend lacking a random generator API, such as rustls (experimental), GSKit and certain mbedTLS builds, or, when libcurl is built without a TLS backend. We reuse the Windows-specific random function from the Schannel backend. - Implement support for `BCryptGenRandom()` [1] on Windows, as a replacement for the deprecated `CryptGenRandom()` [2] function. It is used as the secure random generator for Schannel, and also to provide entropy for libcurl's fallback random generator. The new function is supported on Vista and newer via its `bcrypt.dll`. It is used automatically when building for supported versions. It also works in UWP apps (the old function did not). - Clear entropy buffer before calling the Windows random generator. This avoids using arbitrary application memory as entropy (with `CryptGenRandom()`) and makes sure to return in a predictable state when an API call fails. [1] https://docs.microsoft.com/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom [2] https://docs.microsoft.com/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom Closes #9027
This commit is contained in:
parent
e6f8445ede
commit
76172511e7
|
@ -1327,6 +1327,8 @@ if(WIN32)
|
|||
if(USE_WIN32_CRYPTO OR USE_SCHANNEL)
|
||||
list(APPEND CURL_LIBS "advapi32" "crypt32")
|
||||
endif()
|
||||
|
||||
list(APPEND CURL_LIBS "bcrypt")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
|
|
28
configure.ac
28
configure.ac
|
@ -500,6 +500,28 @@ case $host in
|
|||
;;
|
||||
esac
|
||||
|
||||
# Detect original MinGW (not MinGW-w64)
|
||||
curl_mingw_original=no
|
||||
case $host in
|
||||
*-*-mingw32*)
|
||||
AC_MSG_CHECKING([using original MinGW (not MinGW-w64)])
|
||||
AC_COMPILE_IFELSE([
|
||||
AC_LANG_PROGRAM([[
|
||||
#include <_mingw.h>
|
||||
]],[[
|
||||
#if defined(__MINGW64_VERSION_MAJOR)
|
||||
#error
|
||||
#endif
|
||||
]])
|
||||
],[
|
||||
curl_mingw_original=yes
|
||||
AC_MSG_RESULT([yes])
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
;;
|
||||
esac
|
||||
|
||||
dnl **********************************************************************
|
||||
dnl Compilation based checks should not be done before this point.
|
||||
dnl **********************************************************************
|
||||
|
@ -1917,6 +1939,12 @@ if test "x$USE_WIN32_CRYPTO" = "x1" -o "x$USE_SCHANNEL" = "x1"; then
|
|||
LIBS="-ladvapi32 -lcrypt32 $LIBS"
|
||||
fi
|
||||
|
||||
dnl link bcrypt for BCryptGenRandom() (used when building for Vista or newer)
|
||||
if test "x$curl_cv_native_windows" = "xyes" &&
|
||||
test "x$curl_mingw_original" = "xno"; then
|
||||
LIBS="-lbcrypt $LIBS"
|
||||
fi
|
||||
|
||||
case "x$OPENSSL_ENABLED$GNUTLS_ENABLED$NSS_ENABLED$MBEDTLS_ENABLED$WOLFSSL_ENABLED$SCHANNEL_ENABLED$SECURETRANSPORT_ENABLED$BEARSSL_ENABLED$AMISSL_ENABLED$RUSTLS_ENABLED"
|
||||
in
|
||||
x)
|
||||
|
|
|
@ -266,7 +266,7 @@ ifdef SSH2
|
|||
curl_LDADD += -L"$(LIBSSH2_PATH)/win32" -lssh2
|
||||
ifdef SCHANNEL
|
||||
ifndef DYN
|
||||
curl_LDADD += -lbcrypt -lcrypt32
|
||||
curl_LDADD += -lcrypt32
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
@ -374,7 +374,7 @@ ifndef USE_LDAP_OPENLDAP
|
|||
curl_LDADD += -lwldap32
|
||||
endif
|
||||
endif
|
||||
curl_LDADD += -lws2_32
|
||||
curl_LDADD += -lws2_32 -lbcrypt
|
||||
|
||||
# Makefile.inc provides the check_PROGRAMS and COMPLICATED_EXAMPLES defines
|
||||
include Makefile.inc
|
||||
|
|
|
@ -279,7 +279,7 @@ ifdef SSH2
|
|||
DLL_LIBS += -L"$(LIBSSH2_PATH)/win32" -lssh2
|
||||
ifdef SCHANNEL
|
||||
ifndef DYN
|
||||
DLL_LIBS += -lbcrypt -lcrypt32
|
||||
DLL_LIBS += -lcrypt32
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
@ -400,7 +400,7 @@ ifndef USE_LDAP_OPENLDAP
|
|||
DLL_LIBS += -lwldap32
|
||||
endif
|
||||
endif
|
||||
DLL_LIBS += -lws2_32
|
||||
DLL_LIBS += -lws2_32 -lbcrypt
|
||||
|
||||
# Makefile.inc provides the CSOURCES and HHEADERS defines
|
||||
include Makefile.inc
|
||||
|
|
66
lib/rand.c
66
lib/rand.c
|
@ -38,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;
|
||||
|
@ -73,6 +131,14 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
|
|||
|
||||
/* ---- non-cryptographic version following ---- */
|
||||
|
||||
#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 */
|
||||
|
|
|
@ -48,4 +48,10 @@ CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num);
|
|||
CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
|
||||
size_t num);
|
||||
|
||||
#ifdef WIN32
|
||||
/* Random generator shared between the Schannel vtls and Curl_rand*()
|
||||
functions */
|
||||
CURLcode Curl_win32_random(unsigned char *entropy, size_t length);
|
||||
#endif
|
||||
|
||||
#endif /* HEADER_CURL_RAND_H */
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "curl_printf.h"
|
||||
#include "multiif.h"
|
||||
#include "version_win32.h"
|
||||
#include "rand.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "curl_memory.h"
|
||||
|
@ -2298,21 +2299,9 @@ static size_t schannel_version(char *buffer, size_t size)
|
|||
static CURLcode schannel_random(struct Curl_easy *data UNUSED_PARAM,
|
||||
unsigned char *entropy, size_t length)
|
||||
{
|
||||
HCRYPTPROV hCryptProv = 0;
|
||||
|
||||
(void)data;
|
||||
|
||||
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;
|
||||
return Curl_win32_random(entropy, length);
|
||||
}
|
||||
|
||||
static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
|
||||
|
|
|
@ -291,7 +291,7 @@ ifdef SSH2
|
|||
curl_LDADD += -L"$(LIBSSH2_PATH)/win32" -lssh2
|
||||
ifdef SCHANNEL
|
||||
ifndef DYN
|
||||
curl_LDADD += -lbcrypt -lcrypt32
|
||||
curl_LDADD += -lcrypt32
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
@ -399,7 +399,7 @@ ifndef USE_LDAP_OPENLDAP
|
|||
curl_LDADD += -lwldap32
|
||||
endif
|
||||
endif
|
||||
curl_LDADD += -lws2_32
|
||||
curl_LDADD += -lws2_32 -lbcrypt
|
||||
|
||||
# Makefile.inc provides the CSOURCES and HHEADERS defines
|
||||
include Makefile.inc
|
||||
|
|
Loading…
Reference in New Issue
Block a user