These are the APIs that generally would be recommended to use. For
RtlGenRandom, there's also the alternative that we could try to
load it with LoadLibrary+GetProcAddress. (If we link directly against
it here, we need the winstorecompat replacement for the function
too.)
Signed-off-by: Martin Storsjö
---
I'm not really sure if this is worthwhile doing though; we already
have the one fallback function that always works for us here, while
these other ones just add more code for little reason.
---
mingw-w64-crt/ssp/stack_chk_guard.c | 56 +
1 file changed, 49 insertions(+), 7 deletions(-)
diff --git a/mingw-w64-crt/ssp/stack_chk_guard.c
b/mingw-w64-crt/ssp/stack_chk_guard.c
index 3ff22e020..ffc59e1a6 100644
--- a/mingw-w64-crt/ssp/stack_chk_guard.c
+++ b/mingw-w64-crt/ssp/stack_chk_guard.c
@@ -6,22 +6,64 @@
#define _CRT_RAND_S
#include
+#include
+#include
#include
+#include
void *__stack_chk_guard;
static void __cdecl __attribute__((__constructor__)) init(void)
{
+ HMODULE bcrypt;
unsigned int ui;
if (__stack_chk_guard != 0)
return;
- // Call rand_s from the CRT; this uses a high quality random source
- // RtlGenRandom internally. This function is available since XP, and is
- // callable in WinStore mode too (since it's from the CRT).
- // In the case of msvcrt.dll, our import library provides a small wrapper
- // which tries to load the function dynamically, and falls back on
- // using RtlRandomGen if not available.
+ // First try to generate the random number using BCrypt. This is the
+ // preferred approach. However, BCrypt is only available since Vista
+ // and we still support XP, so this has to be fetched and tested at
+ // runtime. (For WinStore apps, BCrypt is available only since Windows 10.
+ // But in WinStore builds, LoadLibrary isn't allowed, and libwinstorecompat
+ // and libwindowsappcompat would override LoadLibrary with a stub that
+ // returns NULL.)
+ //
+ // Also, if we'd link directly against this API, the compiler driver
+ // would need to add -lbcrypt to the linking command line by default.
+ //
+ // Since this is fetched with LoadLibrary/GetProcAddress, we can't
+ // provide/override it for builds with winstorecompat.
+ bcrypt = LoadLibraryW(L"bcrypt.dll");
+ if (bcrypt) {
+NTSTATUS (WINAPI *pBCryptOpenAlgorithmProvider)(BCRYPT_ALG_HANDLE *,
LPCWSTR, LPCWSTR, ULONG);
+NTSTATUS (WINAPI *pBCryptGenRandom)(BCRYPT_ALG_HANDLE, PUCHAR, ULONG,
ULONG);
+NTSTATUS (WINAPI *pBCryptCloseAlgorithmProvider)(BCRYPT_ALG_HANDLE, ULONG);
+pBCryptOpenAlgorithmProvider = (void*)GetProcAddress(bcrypt,
"BCryptOpenAlgorithmProvider");
+pBCryptGenRandom = (void*)GetProcAddress(bcrypt, "BCryptGenRandom");
+pBCryptCloseAlgorithmProvider = (void*)GetProcAddress(bcrypt,
"BCryptCloseAlgorithmProvider");
+
+if (pBCryptOpenAlgorithmProvider && pBCryptGenRandom &&
pBCryptCloseAlgorithmProvider) {
+ BCRYPT_ALG_HANDLE alg;
+ if (BCRYPT_SUCCESS(pBCryptOpenAlgorithmProvider(,
BCRYPT_RNG_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0))) {
+pBCryptGenRandom(alg, (void*)&__stack_chk_guard,
sizeof(__stack_chk_guard), 0);
+pBCryptCloseAlgorithmProvider(alg, 0);
+FreeLibrary(bcrypt);
+return;
+ }
+}
+FreeLibrary(bcrypt);
+ }
+
+ // If BCrypt wasn't found, try to use RtlGenRandom. This is available
+ // since XP. For winstorecompat, this call is intercepted and emulated.
+ if (RtlGenRandom(&__stack_chk_guard, sizeof(__stack_chk_guard))) {
+return;
+ }
+
+ // If RtlGenRandom failed, call rand_s from the CRT. This uses the same
+ // random source as RtlGenRandom above. In the case of msvcrt.dll, the
+ // rand_s function ends up loaded dynamically, and if not found, it tries
+ // to dynamically load RtlGenRandom instead.
if (rand_s() == 0) {
__stack_chk_guard = (void*)(intptr_t)ui;
#if __SIZEOF_POINTER__ > 4
@@ -31,7 +73,7 @@ static void __cdecl __attribute__((__constructor__))
init(void)
return;
}
- // If rand_s failed (it shouldn't), hardcode a nonzero default stack guard.
+ // If everything else failed, hardcode a nonzero default stack guard.
#if __SIZEOF_POINTER__ > 4
__stack_chk_guard = (void*)0xdeadbeefdeadbeefULL;
#else
--
2.25.1
___
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public