|
| 1 | +//! Implementation for Windows 7 and 8 |
| 2 | +//! |
| 3 | +//! For targets where we cannot use ProcessPrng (added in Windows 10), we use |
| 4 | +//! RtlGenRandom. See windows.rs for a more detailed discussion of the Windows |
| 5 | +//! RNG APIs (and why we don't use BCryptGenRandom). On versions prior to |
| 6 | +//! Windows 10, this implementation works, while on Windows 10 and later, this |
| 7 | +//! is a thin wrapper around ProcessPrng. |
| 8 | +//! |
| 9 | +//! This implementation will not work on UWP targets, but those targets require |
| 10 | +//! Windows 10 regardless, so can use the ProcessPrng implementation. |
| 11 | +use crate::Error; |
| 12 | +use core::{ffi::c_void, mem::MaybeUninit}; |
| 13 | + |
| 14 | +// This code is based on that produced by windows-bindgen with the APIs: |
| 15 | +// Windows.Win32.Foundation.TRUE |
| 16 | +// Windows.Win32.Security.Authentication.Identity.RtlGenRandom |
| 17 | +// but we avoid using windows-targets as it doesn't support older Windows. |
| 18 | +#[link(name = "advapi32")] |
| 19 | +extern "system" { |
| 20 | + #[link_name = "SystemFunction036"] |
| 21 | + fn RtlGenRandom(randombuffer: *mut c_void, randombufferlength: u32) -> BOOLEAN; |
| 22 | +} |
| 23 | +#[repr(transparent)] |
| 24 | +#[derive(PartialEq, Eq)] |
| 25 | +pub struct BOOLEAN(pub u8); |
| 26 | +pub const TRUE: BOOLEAN = BOOLEAN(1u8); |
| 27 | + |
| 28 | +pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> { |
| 29 | + // Prevent overflow of u32 |
| 30 | + for chunk in dest.chunks_mut(u32::max_value() as usize) { |
| 31 | + let ret = unsafe { RtlGenRandom(chunk.as_mut_ptr().cast::<c_void>(), chunk.len() as u32) }; |
| 32 | + if ret != TRUE { |
| 33 | + return Err(Error::WINDOWS_RTL_GEN_RANDOM); |
| 34 | + } |
| 35 | + } |
| 36 | + Ok(()) |
| 37 | +} |
0 commit comments