-
Notifications
You must be signed in to change notification settings - Fork 256
Add Windows UWP support #69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
e050963
f871486
6f147a1
8ff7697
0d51ab5
6b113ff
cdb2033
bd5af6d
1af5963
b403d6e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| #![deny(warnings)] | ||
|
|
||
| use std::env; | ||
|
|
||
| fn main() { | ||
| let target = env::var("TARGET").expect("TARGET was not set"); | ||
| if target.contains("uwp") { | ||
| // 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"); | ||
|
newpavlov marked this conversation as resolved.
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -126,6 +126,14 @@ cfg_if! { | |
| macro_rules! error { | ||
| ($($x:tt)*) => {}; | ||
| } | ||
| #[allow(unused)] | ||
| macro_rules! warn { | ||
| ($($x:tt)*) => {}; | ||
| } | ||
| #[allow(unused)] | ||
| macro_rules! info { | ||
| ($($x:tt)*) => {}; | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -216,6 +224,15 @@ cfg_if! { | |
| #[path = "solaris_illumos.rs"] mod imp; | ||
| } else if #[cfg(target_os = "wasi")] { | ||
| #[path = "wasi.rs"] mod imp; | ||
| } else if #[cfg(any( | ||
| // target_vendor was stabilized only in Rust 1.33 | ||
| target = "i686-uwp-windows-gnu", | ||
| target = "x86_64-uwp-windows-gnu", | ||
| target = "aarch64-uwp-windows-msvc", | ||
| target = "x86_64-uwp-windows-msvc", | ||
| target = "i686-uwp-windows-msvc", | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like this will not work, see rust-lang/rust#63217. :/ So our options are:
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should bump the MSRV to 1.33 (and release 0.1.8), Rust 1.38 is coming out in a few days (Aug 12 I think), so bumping to 1.33 then seems reasonable. Users still on 1.32 can still use
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Personally until something like rust-lang/rfcs#2495 lands I prefer a conservative position stating that MSRV bump should be considered a breaking change. I think we also could move UWP check to the Windows branch, so MSRV bump will affect only Windows users, but I would prefer to drop support for Windows XP and Vista instead, but I guess it would require writing an RFC if we want @dhardy
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After looking at #75 and rust-lang/rfcs#2495, I think you're right. Incrementing the minimum supported version should be considered a breaking change. However, we can support UWP without bumping the MSRV, adding a feature, or dropping support for XP/Vista. We can just check in the build script.
So we would do the following: // build.rs
...
if target.contains("uwp") {
println!("cargo:rustc-cfg=getrandom_uwp");
// for BCryptGenRandom
println!("cargo:rustc-link-lib=bcrypt");
...// src/lib.rs
...
} else if #[cfg(all(windows, getrandom_uwp))] {
#[path = "windows_uwp.rs"] mod imp;
} else if #[cfg(windows)] {
#[path = "windows.rs"] mod imp;
}
...This prevents exposing any of the details in
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good workaround!
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using a build.rs file seems appropriate in this case. |
||
| ))] { | ||
| #[path = "windows_uwp.rs"] mod imp; | ||
| } else if #[cfg(windows)] { | ||
| #[path = "windows.rs"] mod imp; | ||
| } else if #[cfg(all(target_arch = "x86_64", any( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| // Copyright 2018 Developers of the Rand project. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
| // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
| // <LICENSE-MIT or https://opensource.org/licenses/MIT>, 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 superseed the `RtlGenRandom`-based implementation. | ||
| use crate::Error; | ||
| use core::{ffi::c_void, num::NonZeroU32, ptr, u32}; | ||
|
newpavlov marked this conversation as resolved.
Outdated
|
||
|
|
||
| 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 two highest bits for severity codes | ||
| match ret >> 30 { | ||
| 0b01 => info!("BCryptGenRandom: information code 0x{:08X}", ret), | ||
| 0b10 => warn!("BCryptGenRandom: warning code 0x{:08X}", ret), | ||
| 0b11 => { | ||
| error!("BCryptGenRandom: failed with 0x{:08X}", ret); | ||
| // We zeroize the highest bit, so the error code will reside | ||
| // inside the range designated for OS codes. | ||
| let code = ret & (u32::MAX >> 1); | ||
|
newpavlov marked this conversation as resolved.
Outdated
|
||
| // SAFETY: the second highest bit is always equal to one, | ||
| // so it's impossible to get zero. Unfortunately compiler | ||
| // is not smart enough to figure out it yet. | ||
| let code = unsafe { NonZeroU32::new_unchecked(code) }; | ||
| return Err(Error::from(code)); | ||
| } | ||
| _ => (), | ||
| } | ||
| } | ||
| Ok(()) | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.