diff --git a/build.rs b/build.rs index ff2c5a85..95f4b90b 100644 --- a/build.rs +++ b/build.rs @@ -4,12 +4,9 @@ use std::env; fn main() { let target = env::var("TARGET").expect("TARGET was not set"); - if target.contains("-uwp-windows-") { + if target.contains("windows") { // for BCryptGenRandom println!("cargo:rustc-link-lib=bcrypt"); - } else if target.contains("windows") { - // for RtlGenRandom (aka SystemFunction036) - println!("cargo:rustc-link-lib=advapi32"); } else if target.contains("apple-ios") { // for SecRandomCopyBytes and kSecRandomDefault println!("cargo:rustc-link-lib=framework=Security"); diff --git a/src/lib.rs b/src/lib.rs index aed78ad5..940113a7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,8 +13,7 @@ //! | Target | Target Triple | Implementation //! | ----------------- | ------------------ | -------------- //! | Linux, Android | `*‑linux‑*` | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random` | -//! | Windows | `*‑pc‑windows‑*` | [`RtlGenRandom`][3] | -//! | [Windows UWP][22] | `*‑uwp‑windows‑*` | [`BCryptGenRandom`][23] | +//! | Windows | `*‑windows‑*` | [`BCryptGenRandom`][3] | //! | macOS | `*‑apple‑darwin` | [`getentropy()`][19] if available, otherwise [`/dev/random`][20] (identical to `/dev/urandom`) //! | iOS | `*‑apple‑ios` | [`SecRandomCopyBytes`][4] //! | FreeBSD | `*‑freebsd` | [`getrandom()`][21] if available, otherwise [`kern.arandom`][5] @@ -121,7 +120,7 @@ //! //! [1]: http://man7.org/linux/man-pages/man2/getrandom.2.html //! [2]: http://man7.org/linux/man-pages/man4/urandom.4.html -//! [3]: https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-rtlgenrandom +//! [3]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom //! [4]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc //! [5]: https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4 //! [6]: https://man.openbsd.org/getentropy.2 @@ -139,8 +138,6 @@ //! [19]: https://www.unix.com/man-page/mojave/2/getentropy/ //! [20]: https://www.unix.com/man-page/mojave/4/random/ //! [21]: https://www.freebsd.org/cgi/man.cgi?query=getrandom&manpath=FreeBSD+12.0-stable -//! [22]: https://docs.microsoft.com/en-us/windows/uwp/ -//! [23]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", @@ -201,8 +198,6 @@ cfg_if! { } else if #[cfg(target_os = "vxworks")] { mod util_libc; #[path = "vxworks.rs"] mod imp; - } else if #[cfg(all(windows, target_vendor = "uwp"))] { - #[path = "windows_uwp.rs"] mod imp; } else if #[cfg(windows)] { #[path = "windows.rs"] mod imp; } else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] { diff --git a/src/windows.rs b/src/windows.rs index a5b05659..56b3d07e 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -6,20 +6,41 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Implementation for Windows use crate::Error; +use core::{ffi::c_void, num::NonZeroU32, ptr}; + +const BCRYPT_USE_SYSTEM_PREFERRED_RNG: u32 = 0x00000002; extern "system" { - #[link_name = "SystemFunction036"] - fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: u32) -> u8; + fn BCryptGenRandom( + hAlgorithm: *mut c_void, + pBuffer: *mut u8, + cbBuffer: u32, + dwFlags: u32, + ) -> u32; } pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { // Prevent overflow of u32 for chunk in dest.chunks_mut(u32::max_value() as usize) { - let ret = unsafe { RtlGenRandom(chunk.as_mut_ptr(), chunk.len() as u32) }; - if ret == 0 { - return Err(Error::WINDOWS_RTL_GEN_RANDOM); + let ret = unsafe { + BCryptGenRandom( + ptr::null_mut(), + chunk.as_mut_ptr(), + chunk.len() as u32, + BCRYPT_USE_SYSTEM_PREFERRED_RNG, + ) + }; + // NTSTATUS codes use the two highest bits for severity status. + if ret >> 30 == 0b11 { + // We zeroize the highest bit, so the error code will reside + // inside the range designated for OS codes. + let code = ret ^ (1 << 31); + // SAFETY: the second highest bit is always equal to one, + // so it's impossible to get zero. Unfortunately the type + // system does not have a way to express this yet. + let code = unsafe { NonZeroU32::new_unchecked(code) }; + return Err(Error::from(code)); } } Ok(()) diff --git a/src/windows_uwp.rs b/src/windows_uwp.rs deleted file mode 100644 index 6ba3a5e0..00000000 --- a/src/windows_uwp.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2018 Developers of the Rand project. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Implementation for Windows UWP targets. After deprecation of Windows XP -//! and Vista, this can supersede the `RtlGenRandom`-based implementation. -use crate::Error; -use core::{ffi::c_void, num::NonZeroU32, ptr}; - -const BCRYPT_USE_SYSTEM_PREFERRED_RNG: u32 = 0x00000002; - -extern "system" { - fn BCryptGenRandom( - hAlgorithm: *mut c_void, - pBuffer: *mut u8, - cbBuffer: u32, - dwFlags: u32, - ) -> u32; -} - -pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { - // Prevent overflow of u32 - for chunk in dest.chunks_mut(u32::max_value() as usize) { - let ret = unsafe { - BCryptGenRandom( - ptr::null_mut(), - chunk.as_mut_ptr(), - chunk.len() as u32, - BCRYPT_USE_SYSTEM_PREFERRED_RNG, - ) - }; - // NTSTATUS codes use the two highest bits for severity status. - if ret >> 30 == 0b11 { - // We zeroize the highest bit, so the error code will reside - // inside the range designated for OS codes. - let code = ret ^ (1 << 31); - // SAFETY: the second highest bit is always equal to one, - // so it's impossible to get zero. Unfortunately the type - // system does not have a way to express this yet. - let code = unsafe { NonZeroU32::new_unchecked(code) }; - return Err(Error::from(code)); - } - } - Ok(()) -}