From b073ac69bb2851b59b1980ad92e790af84cb890f Mon Sep 17 00:00:00 2001 From: silverstillisntgold Date: Fri, 3 Jan 2025 03:51:28 -0500 Subject: [PATCH 1/2] Remove error branch of ProcessPrng associated cleanup and documentation --- src/backends/windows.rs | 32 ++++++++++++++++---------------- src/error.rs | 2 -- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/backends/windows.rs b/src/backends/windows.rs index 76435943..9818f085 100644 --- a/src/backends/windows.rs +++ b/src/backends/windows.rs @@ -1,7 +1,7 @@ //! Implementation for Windows 10 and later //! //! On Windows 10 and later, ProcessPrng "is the primary interface to the -//! user-mode per-processer PRNGs" and only requires bcryptprimitives.dll, +//! user-mode per-processor PRNGs" and only requires bcryptprimitives.dll, //! making it a better option than the other Windows RNG APIs: //! - BCryptGenRandom: https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom //! - Requires bcrypt.dll (which loads bcryptprimitives.dll anyway) @@ -27,21 +27,21 @@ pub use crate::util::{inner_u32, inner_u64}; // Binding to the Windows.Win32.Security.Cryptography.ProcessPrng API. As // bcryptprimitives.dll lacks an import library, we use the windows-targets -// crate to link to it. -windows_targets::link!("bcryptprimitives.dll" "system" fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL); -#[allow(clippy::upper_case_acronyms)] -pub type BOOL = i32; -pub const TRUE: BOOL = 1i32; - -pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { - // ProcessPrng should always return TRUE, but we check just in case. - match unsafe { ProcessPrng(dest.as_mut_ptr().cast::(), dest.len()) } { - TRUE => Ok(()), - _ => Err(Error::WINDOWS_PROCESS_PRNG), - } +// crate to link to it. The link! macro always declares external functions +// as pub, so we wrap it in a private module to keep it local. +// +// TODO(MSRV 1.71): Migrate to linking as raw-dylib directly. +// https://github.com/joboet/rust/blob/5c1c72572479afe98734d5f78fa862abe662c41a/library/std/src/sys/pal/windows/c.rs#L119 +// https://github.com/microsoft/windows-rs/blob/0.60.0/crates/libs/targets/src/lib.rs +mod internal { + windows_targets::link!("bcryptprimitives.dll" "system" fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> i32); } -impl Error { - /// Calling Windows ProcessPrng failed. - pub(crate) const WINDOWS_PROCESS_PRNG: Error = Self::new_internal(10); +pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + // Since Windows 10, calls to the user-mode RNG are guaranteed + // to never fail during runtime (rare windows W). + // See the bottom of page 6 of the aforementioned Windows RNG + // whitepaper for more information. + unsafe { internal::ProcessPrng(dest.as_mut_ptr().cast::(), dest.len()) }; + Ok(()) } diff --git a/src/error.rs b/src/error.rs index 4004af57..e82b5e3a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -114,8 +114,6 @@ impl Error { target_os = "tvos", ))] Error::IOS_RANDOM_GEN => "SecRandomCopyBytes: iOS Security framework failure", - #[cfg(all(windows, not(target_vendor = "win7")))] - Error::WINDOWS_PROCESS_PRNG => "ProcessPrng: Windows system function failure", #[cfg(all(windows, target_vendor = "win7"))] Error::WINDOWS_RTL_GEN_RANDOM => "RtlGenRandom: Windows system function failure", #[cfg(getrandom_backend = "wasm_js")] From c01dc2125c49df450313d2e6dcdd0b93da23140f Mon Sep 17 00:00:00 2001 From: silverstillisntgold Date: Sun, 12 Jan 2025 03:48:33 -0500 Subject: [PATCH 2/2] check for success on debug builds; remove internal mod --- src/backends/windows.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/backends/windows.rs b/src/backends/windows.rs index 9818f085..e6e12e18 100644 --- a/src/backends/windows.rs +++ b/src/backends/windows.rs @@ -27,21 +27,20 @@ pub use crate::util::{inner_u32, inner_u64}; // Binding to the Windows.Win32.Security.Cryptography.ProcessPrng API. As // bcryptprimitives.dll lacks an import library, we use the windows-targets -// crate to link to it. The link! macro always declares external functions -// as pub, so we wrap it in a private module to keep it local. +// crate to link to it. // // TODO(MSRV 1.71): Migrate to linking as raw-dylib directly. // https://github.com/joboet/rust/blob/5c1c72572479afe98734d5f78fa862abe662c41a/library/std/src/sys/pal/windows/c.rs#L119 // https://github.com/microsoft/windows-rs/blob/0.60.0/crates/libs/targets/src/lib.rs -mod internal { - windows_targets::link!("bcryptprimitives.dll" "system" fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> i32); -} +windows_targets::link!("bcryptprimitives.dll" "system" fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> i32); pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { - // Since Windows 10, calls to the user-mode RNG are guaranteed - // to never fail during runtime (rare windows W). + let result = unsafe { ProcessPrng(dest.as_mut_ptr().cast::(), dest.len()) }; + // Since Windows 10, calls to the user-mode RNG are guaranteed to never + // fail during runtime (rare windows W); `ProcessPrng` will only ever + // return 1 (which is how windows represents TRUE). // See the bottom of page 6 of the aforementioned Windows RNG // whitepaper for more information. - unsafe { internal::ProcessPrng(dest.as_mut_ptr().cast::(), dest.len()) }; + debug_assert!(result == 1); Ok(()) }