Skip to content

Commit 6766018

Browse files
committed
Add Window7-specific implementation
1 parent 1390386 commit 6766018

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,8 @@ cfg_if! {
323323
#[path = "solid.rs"] mod imp;
324324
} else if #[cfg(target_os = "espidf")] {
325325
#[path = "espidf.rs"] mod imp;
326+
} else if #[cfg(all(windows, target_vendor = "win7"))] {
327+
#[path = "windows7.rs"] mod imp;
326328
} else if #[cfg(windows)] {
327329
#[path = "windows.rs"] mod imp;
328330
} else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] {

src/windows7.rs

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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

Comments
 (0)