Skip to content

Commit 884f945

Browse files
committed
More panic info on failure of Windows rand
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.
1 parent 8521a8c commit 884f945

File tree

2 files changed

+23
-17
lines changed

2 files changed

+23
-17
lines changed

library/std/src/sys/windows/c.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ pub type LPSYSTEM_INFO = *mut SYSTEM_INFO;
6666
pub type LPWSABUF = *mut WSABUF;
6767
pub type LPWSAOVERLAPPED = *mut c_void;
6868
pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = *mut c_void;
69+
pub type BCRYPT_ALG_HANDLE = isize;
6970

7071
pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE;
7172
pub type PLARGE_INTEGER = *mut c_longlong;
@@ -285,7 +286,7 @@ pub fn nt_success(status: NTSTATUS) -> bool {
285286
status >= 0
286287
}
287288

288-
pub const BCRYPT_RNG_ALG_HANDLE: usize = 0x81;
289+
pub const BCRYPT_RNG_ALG_HANDLE: BCRYPT_ALG_HANDLE = 0x81;
289290

290291
#[repr(C)]
291292
pub struct UNICODE_STRING {
@@ -1229,7 +1230,7 @@ extern "system" {
12291230
// >= Vista / Server 2008
12301231
// https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
12311232
pub fn BCryptGenRandom(
1232-
hAlgorithm: LPVOID,
1233+
hAlgorithm: BCRYPT_ALG_HANDLE,
12331234
pBuffer: *mut u8,
12341235
cbBuffer: ULONG,
12351236
dwFlags: ULONG,

library/std/src/sys/windows/rand.rs

+20-15
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
//! [`RtlGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
2323
//! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
2424
//! [Pseudo-handle]: https://docs.microsoft.com/en-us/windows/win32/seccng/cng-algorithm-pseudo-handles
25-
use crate::io;
2625
use crate::mem;
2726
use crate::ptr;
2827
use crate::sys::c;
@@ -34,35 +33,41 @@ use crate::sys::c;
3433
/// [`HashMap`]: crate::collections::HashMap
3534
/// [`RandomState`]: crate::collections::hash_map::RandomState
3635
pub fn hashmap_random_keys() -> (u64, u64) {
36+
// BCRYPT_RNG_ALG_HANDLE is only supported in Windows 10+.
37+
// So for Windows 8.1 and Windows 7 we'll need a fallback when this fails
38+
gen_random_keys(c::BCRYPT_RNG_ALG_HANDLE).unwrap_or_else(fallback_rng)
39+
}
40+
41+
fn gen_random_keys(algorithm: c::BCRYPT_ALG_HANDLE) -> Result<(u64, u64), c::NTSTATUS> {
3742
let mut v = (0, 0);
38-
let ret = unsafe {
43+
let status = unsafe {
3944
let size = mem::size_of_val(&v).try_into().unwrap();
40-
c::BCryptGenRandom(
41-
// BCRYPT_RNG_ALG_HANDLE is only supported in Windows 10+.
42-
// So for Windows 8.1 and Windows 7 we'll need a fallback when this fails.
43-
ptr::invalid_mut(c::BCRYPT_RNG_ALG_HANDLE),
44-
ptr::addr_of_mut!(v).cast(),
45-
size,
46-
0,
47-
)
45+
c::BCryptGenRandom(algorithm, ptr::addr_of_mut!(v).cast(), size, 0)
4846
};
49-
if ret != 0 { fallback_rng() } else { v }
47+
if c::nt_success(status) { Ok(v) } else { Err(status) }
5048
}
5149

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

60-
if ret != 0 { v } else { panic!("fallback RNG broken: {}", io::Error::last_os_error()) }
58+
if ret != 0 {
59+
v
60+
} else {
61+
panic!(
62+
"RNG broken: {rng_status:#x}, fallback RNG broken: {}",
63+
crate::io::Error::last_os_error()
64+
)
65+
}
6166
}
6267

6368
/// We can't use RtlGenRandom with UWP, so there is no fallback
6469
#[cfg(target_vendor = "uwp")]
6570
#[inline(never)]
66-
fn fallback_rng() -> (u64, u64) {
67-
panic!("fallback RNG broken: RtlGenRandom() not supported on UWP");
71+
fn fallback_rng(rng_status: c::NTSTATUS) -> (u64, u64) {
72+
panic!("RMG broken: {rng_status:#x} fallback RNG broken: RtlGenRandom() not supported on UWP");
6873
}

0 commit comments

Comments
 (0)