mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Auto merge of #121337 - ChrisDenton:ProcessPrng, r=Mark-Simulacrum
Windows: Use ProcessPrng for random keys Windows 10 introduced [`ProcessPrng`](https://learn.microsoft.com/en-us/windows/win32/seccng/processprng) for random number generation. This allows us to replace the overly complicated (and prone to failure) `BCryptGenRandom` with a documented function. For the tier 3 Windows 7 target, we simply use the older `RtlGenRandom`, which is undocumented. It should be fine even on modern systems (for comparability reasons) as it's just a wrapper for `ProcessPrng`. However, it does require loading an extra intermediary DLL which we can avoid when we know we have Windows 10+.
This commit is contained in:
commit
34aab623dd
@ -0,0 +1,47 @@
|
||||
From 9f65e742ba3e41474e6126c6c4469c48eaa6ca7e Mon Sep 17 00:00:00 2001
|
||||
From: Chris Denton <chris@chrisdenton.dev>
|
||||
Date: Tue, 20 Feb 2024 16:01:40 -0300
|
||||
Subject: [PATCH] Don't use raw-dylib in std
|
||||
|
||||
---
|
||||
library/std/src/sys/pal/windows/c.rs | 2 +-
|
||||
library/std/src/sys/pal/windows/rand.rs | 3 +--
|
||||
2 files changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs
|
||||
index ad8e01bfa9b..9ca8e4c16ce 100644
|
||||
--- a/library/std/src/sys/pal/windows/c.rs
|
||||
+++ b/library/std/src/sys/pal/windows/c.rs
|
||||
@@ -323,7 +323,7 @@ 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"))] {
|
||||
+if #[cfg(any())] {
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated")]
|
||||
extern "system" {
|
||||
diff --git a/library/std/src/sys/pal/windows/rand.rs b/library/std/src/sys/pal/windows/rand.rs
|
||||
index e427546222a..f2fe42a4d51 100644
|
||||
--- a/library/std/src/sys/pal/windows/rand.rs
|
||||
+++ b/library/std/src/sys/pal/windows/rand.rs
|
||||
@@ -2,7 +2,7 @@
|
||||
use core::mem;
|
||||
use core::ptr;
|
||||
|
||||
-#[cfg(not(target_vendor = "win7"))]
|
||||
+#[cfg(any())]
|
||||
#[inline]
|
||||
pub fn hashmap_random_keys() -> (u64, u64) {
|
||||
let mut v = (0, 0);
|
||||
@@ -13,7 +13,6 @@ pub fn hashmap_random_keys() -> (u64, u64) {
|
||||
v
|
||||
}
|
||||
|
||||
-#[cfg(target_vendor = "win7")]
|
||||
pub fn hashmap_random_keys() -> (u64, u64) {
|
||||
use crate::ffi::c_void;
|
||||
use crate::io;
|
||||
--
|
||||
2.42.0.windows.2
|
||||
|
@ -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! {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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::<u8>(), 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 <https://bugzilla.mozilla.org/show_bug.cgi?id=1788004#c9>
|
||||
#[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::<c_void>(), 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()) }
|
||||
}
|
||||
|
@ -427,6 +427,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
this.gen_random(ptr, len.into())?;
|
||||
this.write_scalar(Scalar::from_bool(true), dest)?;
|
||||
}
|
||||
"ProcessPrng" => {
|
||||
let [ptr, len] =
|
||||
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
let len = this.read_target_usize(len)?;
|
||||
this.gen_random(ptr, len.into())?;
|
||||
this.write_scalar(Scalar::from_i32(1), dest)?;
|
||||
}
|
||||
"BCryptGenRandom" => {
|
||||
let [algorithm, ptr, len, flags] =
|
||||
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
|
||||
|
Loading…
Reference in New Issue
Block a user