Hi,

On 2022-09-26 23:33, Martin Storsjö wrote:
On Mon, 26 Sep 2022, Alvin Wong wrote:

On 22/9/2022 0:01, Martin Storsjö wrote:
+static void __cdecl __attribute__((__constructor__)) init(void)
+{
+  HCRYPTPROV crypt = 0;
+  if (__stack_chk_guard != 0)
+    return;
+
+  if (CryptAcquireContext(&crypt, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { +    if (CryptGenRandom(crypt, sizeof(__stack_chk_guard), (BYTE*) &__stack_chk_guard) && __stack_chk_guard != 0) {
+      CryptReleaseContext(crypt, 0);
+      return;
+    }
+    CryptReleaseContext(crypt, 0);
+  }

I guess this is just following whatever libssp does, but I did just stumble across some talks about RNG functions elsewhere, mainly an old comment on Mozilla's bugzilla <https://bugzilla.mozilla.org/show_bug.cgi?id=504270#c5> recommending `RtlGenRandom` over `CryptGenRandom` and a discussion in rust-random <https://github.com/rust-random/getrandom/issues/65> advocating for `BCryptGenRandom` over `RtlGenRandom` and its references. Firefox, Chrome, Rust and Go all prefer to use `RtlGenRandom` instead of `CryptGenRandom`. The documentation of CryptGenRandom <https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom> says the API is deprecated and may be removed in the future (though I doubt they will really remove it) which may be a good reason to avoid using `CryptGenRandom`.

FWIW, CryptGenRandom is not available in UWP mode at all, which is why libwinstorecompat has got a reimplementation of it. It is reimplemented on top of the Windows.Security.Cryptography.CryptographicBuffer API. I'm CCing Hugo and Steve who have been involved in winstorecompat, in case they have anything to add about why they chose to implement it on top of that instead of on top of BCrypt.

IIRC at the time BCrypt was probably not allowed in UWP (Win8+). Now BCrypt would be a better choice.

Now whether to use `RtlGenRandom` or `BCryptGenRandom` as the replacement: For UWP, `BCryptGenRandom` is the only choice. For desktop, a comment in a BoringSSL issue <https://bugs.chromium.org/p/boringssl/issues/detail?id=307#c9> claims that they both use "the same internal RNG infrastructure".

It seems we'd be better off replacing this use of `CryptGenRandom` with `RtlGenRandom` for desktop and `BCryptGenRandom` for UWP. Do you think this make sense?

I would suggest the other way around. Use BCrypt everywhere except for XP (if it's that the issue for having 2 different code path). If anyone builds for Vista and above the code would only use BCrypt. And if one day XP is dropped, it's easier to spot this code running only on XP.

Hmm, this does sound reasonable - however it doesn't seem entirely easy.

Using separate codepaths for UWP is done by linking the libwinstorecompat static library (or libwindowsappcompat) before linking kernel32 or similar, so that unavailable functions are resolved from there instead of being imported.

Now for RtlGenRandom, this isn't available as one single function that can be linked from somewhere, but you're expected to use LoadLibrary and GetProcAddress to fetch it. (We could of course add it to our import libraries, but the docs for it says we shouldn't do it that way.) And we can't really replace the calls to LoadLibrary/GetProcAddress specifically for this case only.

We could use rand_s, which is a simple single function, and is kinda documented to be implemented on top of RtlGenRandom. That single function would be simple to handle in winstorecompat, but as far as I know, we wouldn't even need to, as it's part of the public bits of the CRT (which we should be free to use).

// Martin


_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to