summary refs log tree commit diff
path: root/library/std/src/sys
diff options
context:
space:
mode:
authorChris Denton <christophersdenton@gmail.com>2022-09-02 13:23:52 +0100
committerChris Denton <christophersdenton@gmail.com>2022-09-02 14:30:16 +0100
commitbc793c9fb2ae45b1e93cdd6ad1cd4ffe30587674 (patch)
treece2842a38b9889cb1072de87c5151b7a46f5f6b2 /library/std/src/sys
parente4f049312c8547a493e618d00db7a346d35a2c98 (diff)
downloadrust-bc793c9fb2ae45b1e93cdd6ad1cd4ffe30587674.tar.gz
rust-bc793c9fb2ae45b1e93cdd6ad1cd4ffe30587674.zip
Use `BCRYPT_RNG_ALG_HANDLE` by default
Also briefly document the history of `sys/windows/rand.rs` as they may be relevant to any future changes.
Diffstat (limited to 'library/std/src/sys')
-rw-r--r--library/std/src/sys/windows/c.rs2
-rw-r--r--library/std/src/sys/windows/rand.rs41
2 files changed, 38 insertions, 5 deletions
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index c99c8efe436..270294d13df 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -285,7 +285,7 @@ pub fn nt_success(status: NTSTATUS) -> bool {
     status >= 0
 }
 
-pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002;
+pub const BCRYPT_RNG_ALG_HANDLE: usize = 0x81;
 
 #[repr(C)]
 pub struct UNICODE_STRING {
diff --git a/library/std/src/sys/windows/rand.rs b/library/std/src/sys/windows/rand.rs
index f8fd93a7398..8b969788436 100644
--- a/library/std/src/sys/windows/rand.rs
+++ b/library/std/src/sys/windows/rand.rs
@@ -1,16 +1,49 @@
+//! # Random key generation
+//!
+//! This module wraps the RNG provided by the OS. There are a few different
+//! ways to interface with the OS RNG so it's worth exploring each of the options.
+//! Note that at the time of writing these all go through the (undocumented)
+//! `bcryptPrimitives.dll` but they use different route to get there.
+//!
+//! Originally we were using [`RtlGenRandom`], however that function is
+//! deprecated and warns it "may be altered or unavailable in subsequent versions".
+//!
+//! So we switched to [`BCryptGenRandom`] with the `BCRYPT_USE_SYSTEM_PREFERRED_RNG`
+//! flag to query and find the system configured RNG. However, this change caused a small
+//! but significant number of users to experience panics caused by a failure of
+//! this function. See [#94098].
+//!
+//! The current version changes this to use the `BCRYPT_RNG_ALG_HANDLE`
+//! [Pseudo-handle], which gets the default RNG algorithm without querying the
+//! system preference thus hopefully avoiding the previous issue.
+//! This is only supported on Windows 10+ so a fallback is used for older versions.
+//!
+//! [#94098]: https://github.com/rust-lang/rust/issues/94098
+//! [`RtlGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
+//! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
+//! [Pseudo-handle]: https://docs.microsoft.com/en-us/windows/win32/seccng/cng-algorithm-pseudo-handles
 use crate::io;
 use crate::mem;
 use crate::ptr;
 use crate::sys::c;
 
+/// Generates high quality secure random keys for use by [`HashMap`].
+///
+/// This is used to seed the default [`RandomState`].
+///
+/// [`HashMap`]: crate::collections::HashMap
+/// [`RandomState`]: crate::collections::hash_map::RandomState
 pub fn hashmap_random_keys() -> (u64, u64) {
     let mut v = (0, 0);
     let ret = unsafe {
+        let size = mem::size_of_val(&v).try_into().unwrap();
         c::BCryptGenRandom(
-            ptr::null_mut(),
-            &mut v as *mut _ as *mut u8,
-            mem::size_of_val(&v) as c::ULONG,
-            c::BCRYPT_USE_SYSTEM_PREFERRED_RNG,
+            // BCRYPT_RNG_ALG_HANDLE is only supported in Windows 10+.
+            // So for Windows 8.1 and Windows 7 we'll need a fallback when this fails.
+            ptr::invalid_mut(c::BCRYPT_RNG_ALG_HANDLE),
+            ptr::addr_of_mut!(v).cast(),
+            size,
+            0,
         )
     };
     if ret != 0 { fallback_rng() } else { v }