Skip to content

Commit

Permalink
More panic info on failure of Windows rand
Browse files Browse the repository at this point in the history
Add the error messages of both `BCryptGenRandom` and `RtlGenRandom` in the (unlikely) event they both fail.

Also use an `isize` for the algorithm handle instead of a pointer. This matches the windows-sys crate.
  • Loading branch information
ChrisDenton committed Sep 5, 2022
1 parent 8521a8c commit 884f945
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 17 deletions.
5 changes: 3 additions & 2 deletions library/std/src/sys/windows/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub type LPSYSTEM_INFO = *mut SYSTEM_INFO;
pub type LPWSABUF = *mut WSABUF;
pub type LPWSAOVERLAPPED = *mut c_void;
pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = *mut c_void;
pub type BCRYPT_ALG_HANDLE = isize;

pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE;
pub type PLARGE_INTEGER = *mut c_longlong;
Expand Down Expand Up @@ -285,7 +286,7 @@ pub fn nt_success(status: NTSTATUS) -> bool {
status >= 0
}

pub const BCRYPT_RNG_ALG_HANDLE: usize = 0x81;
pub const BCRYPT_RNG_ALG_HANDLE: BCRYPT_ALG_HANDLE = 0x81;

#[repr(C)]
pub struct UNICODE_STRING {
Expand Down Expand Up @@ -1229,7 +1230,7 @@ extern "system" {
// >= Vista / Server 2008
// https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
pub fn BCryptGenRandom(
hAlgorithm: LPVOID,
hAlgorithm: BCRYPT_ALG_HANDLE,
pBuffer: *mut u8,
cbBuffer: ULONG,
dwFlags: ULONG,
Expand Down
35 changes: 20 additions & 15 deletions library/std/src/sys/windows/rand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
//! [`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;
Expand All @@ -34,35 +33,41 @@ use crate::sys::c;
/// [`HashMap`]: crate::collections::HashMap
/// [`RandomState`]: crate::collections::hash_map::RandomState
pub fn hashmap_random_keys() -> (u64, u64) {
// 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
gen_random_keys(c::BCRYPT_RNG_ALG_HANDLE).unwrap_or_else(fallback_rng)
}

fn gen_random_keys(algorithm: c::BCRYPT_ALG_HANDLE) -> Result<(u64, u64), c::NTSTATUS> {
let mut v = (0, 0);
let ret = unsafe {
let status = unsafe {
let size = mem::size_of_val(&v).try_into().unwrap();
c::BCryptGenRandom(
// 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,
)
c::BCryptGenRandom(algorithm, ptr::addr_of_mut!(v).cast(), size, 0)
};
if ret != 0 { fallback_rng() } else { v }
if c::nt_success(status) { Ok(v) } else { Err(status) }
}

/// Generate random numbers using the fallback RNG function (RtlGenRandom)
#[cfg(not(target_vendor = "uwp"))]
#[inline(never)]
fn fallback_rng() -> (u64, u64) {
fn fallback_rng(rng_status: c::NTSTATUS) -> (u64, u64) {
let mut v = (0, 0);
let ret =
unsafe { c::RtlGenRandom(&mut v as *mut _ as *mut u8, mem::size_of_val(&v) as c::ULONG) };

if ret != 0 { v } else { panic!("fallback RNG broken: {}", io::Error::last_os_error()) }
if ret != 0 {
v
} else {
panic!(
"RNG broken: {rng_status:#x}, fallback RNG broken: {}",
crate::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");
fn fallback_rng(rng_status: c::NTSTATUS) -> (u64, u64) {
panic!("RMG broken: {rng_status:#x} fallback RNG broken: RtlGenRandom() not supported on UWP");
}

0 comments on commit 884f945

Please sign in to comment.