diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index 6b12d7db8b03..ad8e01bfa9b0 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -321,6 +321,21 @@ pub unsafe fn NtWriteFile( } } +// Use raw-dylib to import ProcessPrng as we can't rely on there being an import library. +cfg_if::cfg_if! { +if #[cfg(not(target_vendor = "win7"))] { + #[cfg(target_arch = "x86")] + #[link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated")] + extern "system" { + pub fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL; + } + #[cfg(not(target_arch = "x86"))] + #[link(name = "bcryptprimitives", kind = "raw-dylib")] + extern "system" { + pub fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL; + } +}} + // Functions that aren't available on every version of Windows that we support, // but we still use them and just provide some form of a fallback implementation. compat_fn_with_fallback! { diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt index 726f1c3df829..ab2a8caf5dfd 100644 --- a/library/std/src/sys/pal/windows/c/bindings.txt +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -2180,10 +2180,6 @@ Windows.Win32.Networking.WinSock.WSATRY_AGAIN Windows.Win32.Networking.WinSock.WSATYPE_NOT_FOUND Windows.Win32.Networking.WinSock.WSAVERNOTSUPPORTED Windows.Win32.Security.Authentication.Identity.RtlGenRandom -Windows.Win32.Security.Cryptography.BCRYPT_ALG_HANDLE -Windows.Win32.Security.Cryptography.BCRYPT_USE_SYSTEM_PREFERRED_RNG -Windows.Win32.Security.Cryptography.BCryptGenRandom -Windows.Win32.Security.Cryptography.BCRYPTGENRANDOM_FLAGS Windows.Win32.Security.SECURITY_ATTRIBUTES Windows.Win32.Security.TOKEN_ACCESS_MASK Windows.Win32.Security.TOKEN_ACCESS_PSEUDO_HANDLE diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index c386b66a722d..8eb779373f7e 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -15,15 +15,6 @@ extern "system" { pub fn RtlGenRandom(randombuffer: *mut ::core::ffi::c_void, randombufferlength: u32) -> BOOLEAN; } -#[link(name = "bcrypt")] -extern "system" { - pub fn BCryptGenRandom( - halgorithm: BCRYPT_ALG_HANDLE, - pbbuffer: *mut u8, - cbbuffer: u32, - dwflags: BCRYPTGENRANDOM_FLAGS, - ) -> NTSTATUS; -} #[link(name = "kernel32")] extern "system" { pub fn AcquireSRWLockExclusive(srwlock: *mut SRWLOCK) -> (); @@ -889,9 +880,6 @@ impl ::core::clone::Clone for ARM64_NT_NEON128_0 { *self } } -pub type BCRYPTGENRANDOM_FLAGS = u32; -pub type BCRYPT_ALG_HANDLE = *mut ::core::ffi::c_void; -pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: BCRYPTGENRANDOM_FLAGS = 2u32; pub const BELOW_NORMAL_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 16384u32; pub type BOOL = i32; pub type BOOLEAN = u8; diff --git a/library/std/src/sys/pal/windows/rand.rs b/library/std/src/sys/pal/windows/rand.rs index bd1ae6b06076..e427546222ae 100644 --- a/library/std/src/sys/pal/windows/rand.rs +++ b/library/std/src/sys/pal/windows/rand.rs @@ -1,42 +1,27 @@ -use crate::mem; -use crate::ptr; use crate::sys::c; +use core::mem; +use core::ptr; +#[cfg(not(target_vendor = "win7"))] +#[inline] pub fn hashmap_random_keys() -> (u64, u64) { let mut v = (0, 0); - let ret = unsafe { - c::BCryptGenRandom( - ptr::null_mut(), - core::ptr::addr_of_mut!(v) as *mut u8, - mem::size_of_val(&v) as c::ULONG, - c::BCRYPT_USE_SYSTEM_PREFERRED_RNG, - ) - }; - if c::nt_success(ret) { v } else { fallback_rng() } + let ret = unsafe { c::ProcessPrng(ptr::addr_of_mut!(v).cast::(), mem::size_of_val(&v)) }; + // ProcessPrng is documented as always returning `TRUE`. + // https://learn.microsoft.com/en-us/windows/win32/seccng/processprng#return-value + debug_assert_eq!(ret, c::TRUE); + v } -/// Generate random numbers using the fallback RNG function (RtlGenRandom) -/// -/// This is necessary because of a failure to load the SysWOW64 variant of the -/// bcryptprimitives.dll library from code that lives in bcrypt.dll -/// See -#[cfg(not(target_vendor = "uwp"))] -#[inline(never)] -fn fallback_rng() -> (u64, u64) { +#[cfg(target_vendor = "win7")] +pub fn hashmap_random_keys() -> (u64, u64) { use crate::ffi::c_void; use crate::io; let mut v = (0, 0); let ret = unsafe { - c::RtlGenRandom(core::ptr::addr_of_mut!(v) as *mut c_void, mem::size_of_val(&v) as c::ULONG) + c::RtlGenRandom(ptr::addr_of_mut!(v).cast::(), mem::size_of_val(&v) as c::ULONG) }; - if ret != 0 { v } else { panic!("fallback RNG broken: {}", io::Error::last_os_error()) } -} - -/// We can't use RtlGenRandom with UWP, so there is no fallback -#[cfg(target_vendor = "uwp")] -#[inline(never)] -fn fallback_rng() -> (u64, u64) { - panic!("fallback RNG broken: RtlGenRandom() not supported on UWP"); + if ret != 0 { v } else { panic!("RNG broken: {}", io::Error::last_os_error()) } }