Skip to content

Commit

Permalink
Add in a RtlGenRandom fallback for non-UWP Windows (#337)
Browse files Browse the repository at this point in the history
* 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

* style suggestion

Co-authored-by: Artyom Pavlov <newpavlov@gmail.com>

* appease clippy

---------

Co-authored-by: Artyom Pavlov <newpavlov@gmail.com>
  • Loading branch information
chutten and newpavlov authored Feb 22, 2023
1 parent 7c83ea0 commit c526c89
Showing 1 changed file with 17 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u8>]) -> Result<(), Error> {
// Prevent overflow of u32
for chunk in dest.chunks_mut(u32::max_value() as usize) {
Expand All @@ -35,6 +43,15 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> 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"))]
{
let ret =
unsafe { RtlGenRandom(chunk.as_mut_ptr() as *mut c_void, chunk.len() as u32) };
if ret != 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);
Expand Down

0 comments on commit c526c89

Please sign in to comment.