Windows: Use ProcessPrng for random keys

This commit is contained in:
Chris Denton 2023-12-20 11:57:19 +00:00
parent 43fdd4916d
commit 08caefbb10
No known key found for this signature in database
GPG Key ID: 713472F2F45627DE
4 changed files with 28 additions and 44 deletions

View File

@ -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! {

View File

@ -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

View File

@ -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;

View File

@ -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()) }
}