From 66093853a6a61412bf57213de0367460063141c5 Mon Sep 17 00:00:00 2001 From: Chris H-C Date: Thu, 16 Feb 2023 15:10:04 -0500 Subject: [PATCH 1/3] Add in a RtlGenRandom fallback for non-UWP Windows In some instances BCryptRandom will fail when RtlGenRandom will work. On UWP, we might be unable to actually use RtlGenRandom. Thread the needle and use RtlGenRandom when we have to, when we're able. See also rust-lang/rust#108060 Fixes #314 --- src/windows.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/windows.rs b/src/windows.rs index e5a626c0..be4cb60f 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -21,6 +21,14 @@ extern "system" { ) -> u32; } +// Forbidden when targetting UWP +#[cfg(not(target_vendor = "uwp"))] +#[link(name = "advapi32")] +extern "system" { + #[link_name = "SystemFunction036"] + fn RtlGenRandom(RandomBuffer: *mut c_void, RandomBufferLength: u32) -> u8; +} + pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { // Prevent overflow of u32 for chunk in dest.chunks_mut(u32::max_value() as usize) { @@ -35,6 +43,15 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { }; // NTSTATUS codes use the two highest bits for severity status. if ret >> 30 == 0b11 { + // Failed. Try RtlGenRandom as a fallback. + #[cfg(not(target_vendor = "uwp"))] + { + if unsafe { RtlGenRandom(chunk.as_mut_ptr() as *mut c_void, chunk.len() as u32) } + != 0 + { + continue; + } + } // We zeroize the highest bit, so the error code will reside // inside the range designated for OS codes. let code = ret ^ (1 << 31); From 8060d8ea387c15a25415394224fd87376a8aef53 Mon Sep 17 00:00:00 2001 From: Chris H-C Date: Wed, 22 Feb 2023 14:09:28 -0500 Subject: [PATCH 2/3] style suggestion Co-authored-by: Artyom Pavlov --- src/windows.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/windows.rs b/src/windows.rs index be4cb60f..2c03676e 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -46,9 +46,8 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { // Failed. Try RtlGenRandom as a fallback. #[cfg(not(target_vendor = "uwp"))] { - if unsafe { RtlGenRandom(chunk.as_mut_ptr() as *mut c_void, chunk.len() as u32) } - != 0 - { + let ret = unsafe { RtlGenRandom(chunk.as_mut_ptr() as *mut c_void, chunk.len() as u32) }; + if ret != 0 { continue; } } From baf37d952aa035fe233b7dd84a1f6879cb592405 Mon Sep 17 00:00:00 2001 From: Chris H-C Date: Wed, 22 Feb 2023 15:06:06 -0500 Subject: [PATCH 3/3] appease clippy --- src/windows.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/windows.rs b/src/windows.rs index 2c03676e..92d70429 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -46,7 +46,8 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { // Failed. Try RtlGenRandom as a fallback. #[cfg(not(target_vendor = "uwp"))] { - let ret = unsafe { RtlGenRandom(chunk.as_mut_ptr() as *mut c_void, chunk.len() as u32) }; + let ret = + unsafe { RtlGenRandom(chunk.as_mut_ptr() as *mut c_void, chunk.len() as u32) }; if ret != 0 { continue; }