Re: [Mingw-w64-public] [PATCH v3 09/10] RFC: crt: Try using BCrypt and RtlGenRandom before rand_s for initializing __stack_chk_guard

2022-09-30 Thread Martin Storsjö

On Fri, 30 Sep 2022, Alvin Wong wrote:


On 30/9/2022 5:25, Martin Storsjö wrote:

+  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);

Should this also check the status result of pBCryptGenRandom(...)?


Thanks - yeah I guess it should, updating the patch locally with that 
change.


Then again, I'm not at all convinced (but I'm open for discussion) that we 
should include this patch at all - I included it mostly for reference and 
discussion here.


// Martin

___
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public


Re: [Mingw-w64-public] [PATCH v3 09/10] RFC: crt: Try using BCrypt and RtlGenRandom before rand_s for initializing __stack_chk_guard

2022-09-30 Thread Alvin Wong via Mingw-w64-public
On 30/9/2022 5:25, Martin Storsjö wrote:
> +  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);
Should this also check the status result of pBCryptGenRandom(...)?
> +pBCryptCloseAlgorithmProvider(alg, 0);
> +FreeLibrary(bcrypt);
> +return;
> +  }
> +}
> +FreeLibrary(bcrypt);
> +  }
>


___
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public


[Mingw-w64-public] [PATCH v3 09/10] RFC: crt: Try using BCrypt and RtlGenRandom before rand_s for initializing __stack_chk_guard

2022-09-29 Thread Martin Storsjö
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