- 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
if(USE_WIN32_CRYPTO OR USE_SCHANNEL)
list(APPEND CURL_LIBS "advapi32" "crypt32")
endif()
+
+ list(APPEND CURL_LIBS "bcrypt")
endif()
if(MSVC)
;;
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 **********************************************************************
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)
curl_LDADD += -L"$(LIBSSH2_PATH)/win32" -lssh2
ifdef SCHANNEL
ifndef DYN
- curl_LDADD += -lbcrypt -lcrypt32
+ curl_LDADD += -lcrypt32
endif
endif
endif
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
DLL_LIBS += -L"$(LIBSSH2_PATH)/win32" -lssh2
ifdef SCHANNEL
ifndef DYN
- DLL_LIBS += -lbcrypt -lcrypt32
+ DLL_LIBS += -lcrypt32
endif
endif
endif
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
#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;
/* ---- 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 */
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 */
#include "curl_printf.h"
#include "multiif.h"
#include "version_win32.h"
+#include "rand.h"
/* The last #include file should be: */
#include "curl_memory.h"
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,
curl_LDADD += -L"$(LIBSSH2_PATH)/win32" -lssh2
ifdef SCHANNEL
ifndef DYN
- curl_LDADD += -lbcrypt -lcrypt32
+ curl_LDADD += -lcrypt32
endif
endif
endif
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