From 0381ee0ce0685248744cdbec9d24a8f0bfc5d36f Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Wed, 12 Jun 2019 04:47:31 -0700 Subject: [PATCH 1/6] Support x86_64-unknown-uefi --- .travis.yml | 5 +++++ Cargo.toml | 3 +++ src/lib.rs | 2 ++ src/rdrand.rs | 29 ++++++++++++++++++----------- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0ea94751..3b634285 100644 --- a/.travis.yml +++ b/.travis.yml @@ -106,6 +106,9 @@ matrix: - rustup target add x86_64-unknown-netbsd - rustup target add x86_64-unknown-redox - rustup target add x86_64-fortanix-unknown-sgx + # For no_std targets + - rustup component add rust-src + - cargo install cargo-xbuild || true script: - cargo build --target=x86_64-sun-solaris --all-features - cargo build --target=x86_64-unknown-cloudabi --all-features @@ -114,6 +117,7 @@ matrix: - cargo build --target=x86_64-unknown-netbsd --all-features - cargo build --target=x86_64-unknown-redox --all-features - cargo build --target=x86_64-fortanix-unknown-sgx --all-features + - cargo xbuild --target=x86_64-unknown-uefi # also test minimum dependency versions are usable - cargo generate-lockfile -Z minimal-versions - cargo build --target=x86_64-sun-solaris --all-features @@ -123,6 +127,7 @@ matrix: - cargo build --target=x86_64-unknown-netbsd --all-features - cargo build --target=x86_64-unknown-redox --all-features - cargo build --target=x86_64-fortanix-unknown-sgx --all-features + - cargo xbuild --target=x86_64-unknown-uefi # Trust cross-built/emulated targets. We must repeat all non-default values. - rust: stable diff --git a/Cargo.toml b/Cargo.toml index abb2d7c2..1cfcd581 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,5 +39,8 @@ stdweb = { version = "0.4.9", optional = true } [target.wasm32-wasi.dependencies] libc = "0.2.54" +[target.'cfg(any(target_env = "sgx", target_os = "uefi"))'.dependencies] +std_detect = { version = "0.1.5", default-features = false } + [features] std = [] diff --git a/src/lib.rs b/src/lib.rs index f2189651..e64b29a1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -190,6 +190,7 @@ mod_use!(cfg(target_os = "redox"), use_file); mod_use!(cfg(target_os = "solaris"), solaris_illumos); mod_use!(cfg(windows), windows); mod_use!(cfg(target_env = "sgx"), rdrand); +mod_use!(cfg(target_os = "uefi"), rdrand); mod_use!(cfg(target_os = "wasi"), wasi); mod_use!( @@ -231,6 +232,7 @@ mod_use!( target_os = "openbsd", target_os = "redox", target_os = "solaris", + target_os = "uefi", target_env = "sgx", windows, all( diff --git a/src/rdrand.rs b/src/rdrand.rs index 0c45f48b..1b900e9f 100644 --- a/src/rdrand.rs +++ b/src/rdrand.rs @@ -11,9 +11,7 @@ use crate::Error; use core::mem; use core::arch::x86_64::_rdrand64_step; use core::num::NonZeroU32; - -#[cfg(not(target_feature = "rdrand"))] -compile_error!("enable rdrand target feature!"); +use std_detect::is_x86_feature_detected; // Recommendation from "Intel® Digital Random Number Generator (DRNG) Software // Implementation Guide" - Section 5.2.1 and "Intel® 64 and IA-32 Architectures @@ -21,21 +19,30 @@ compile_error!("enable rdrand target feature!"); const RETRY_LIMIT: usize = 10; const WORD_SIZE: usize = mem::size_of::(); -fn rdrand() -> Result<[u8; WORD_SIZE], Error> { +#[target_feature(enable = "rdrand")] +unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> { for _ in 0..RETRY_LIMIT { - unsafe { - // SAFETY: we've checked RDRAND support, and u64 can have any value. - let mut el = mem::uninitialized(); - if _rdrand64_step(&mut el) == 1 { - return Ok(el.to_ne_bytes()); - } - }; + let mut el = mem::uninitialized(); + if _rdrand64_step(&mut el) == 1 { + return Ok(el.to_ne_bytes()); + } } error!("RDRAND failed, CPU issue likely"); Err(Error::UNKNOWN) } pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { + if !is_x86_feature_detected!("rdrand") { + return Err(Error::UNAVAILABLE); + } + + // SAFETY: After this point, rdrand is supported, so calling the rdrand + // functions is not undefined behavior. + unsafe { rdrand_exact(dest) } +} + +#[target_feature(enable = "rdrand")] +unsafe fn rdrand_exact(dest: &mut [u8]) -> Result<(), Error> { // We use chunks_exact_mut instead of chunks_mut as it allows almost all // calls to memcpy to be elided by the compiler. let mut chunks = dest.chunks_exact_mut(WORD_SIZE); From 94440e117bcb3a2a714ad1ab9cb63142d8927e50 Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Thu, 13 Jun 2019 13:11:41 -0700 Subject: [PATCH 2/6] Use custom implementation of is_rdrand_supported --- Cargo.toml | 2 +- src/rdrand.rs | 23 ++++++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1cfcd581..7cb539da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ stdweb = { version = "0.4.9", optional = true } libc = "0.2.54" [target.'cfg(any(target_env = "sgx", target_os = "uefi"))'.dependencies] -std_detect = { version = "0.1.5", default-features = false } +lazy_static = { version = "1.3.0", features = ["spin_no_std"] } [features] std = [] diff --git a/src/rdrand.rs b/src/rdrand.rs index 1b900e9f..7dcdd339 100644 --- a/src/rdrand.rs +++ b/src/rdrand.rs @@ -9,9 +9,9 @@ //! Implementation for SGX using RDRAND instruction use crate::Error; use core::mem; -use core::arch::x86_64::_rdrand64_step; +use core::arch::x86_64::{__cpuid, _rdrand64_step}; use core::num::NonZeroU32; -use std_detect::is_x86_feature_detected; +use lazy_static::lazy_static; // Recommendation from "Intel® Digital Random Number Generator (DRNG) Software // Implementation Guide" - Section 5.2.1 and "Intel® 64 and IA-32 Architectures @@ -31,8 +31,25 @@ unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> { Err(Error::UNKNOWN) } +// TODO use is_x86_feature_detected!("rdrand") when that works in core. See: +// https://github.com/rust-lang-nursery/stdsimd/issues/464 +fn is_rdrand_supported() -> bool { + if cfg!(target_feature = "rdrand") { + true + } else if cfg!(target_env = "sgx") { + false // No CPUID in SGX enclaves + } else { + // SAFETY: All x86_64 CPUs support CPUID leaf 1 + const FLAG: u32 = 1 << 30; + lazy_static! { + static ref HAS_RDRAND: bool = unsafe { __cpuid(1).ecx & FLAG != 0 }; + } + *HAS_RDRAND + } +} + pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { - if !is_x86_feature_detected!("rdrand") { + if is_rdrand_supported() { return Err(Error::UNAVAILABLE); } From fc8ab62f590c15f25f70f8ccdc9fb3736c676b27 Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Fri, 14 Jun 2019 02:10:51 -0700 Subject: [PATCH 3/6] Add missing not --- src/rdrand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rdrand.rs b/src/rdrand.rs index 7dcdd339..6c607967 100644 --- a/src/rdrand.rs +++ b/src/rdrand.rs @@ -49,7 +49,7 @@ fn is_rdrand_supported() -> bool { } pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { - if is_rdrand_supported() { + if !is_rdrand_supported() { return Err(Error::UNAVAILABLE); } From 5c6294ae7bf10ca9fac33afde649a8aee1b97572 Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Fri, 14 Jun 2019 03:47:37 -0700 Subject: [PATCH 4/6] Add error for sgx && !rdrand --- src/rdrand.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/rdrand.rs b/src/rdrand.rs index 6c607967..4753507b 100644 --- a/src/rdrand.rs +++ b/src/rdrand.rs @@ -31,13 +31,14 @@ unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> { Err(Error::UNKNOWN) } +#[cfg(and(target_env = "sgx", not(target_feature = "rdrand")))] +compile_error!("SGX targets must enable RDRAND to get randomness"); + // TODO use is_x86_feature_detected!("rdrand") when that works in core. See: // https://github.com/rust-lang-nursery/stdsimd/issues/464 fn is_rdrand_supported() -> bool { if cfg!(target_feature = "rdrand") { true - } else if cfg!(target_env = "sgx") { - false // No CPUID in SGX enclaves } else { // SAFETY: All x86_64 CPUs support CPUID leaf 1 const FLAG: u32 = 1 << 30; From 25bd5a558b97f39aeff3acc60bd3bdb6b285c3cf Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Fri, 14 Jun 2019 12:42:25 -0700 Subject: [PATCH 5/6] Fix cfg guards --- src/lib.rs | 4 ++-- src/rdrand.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e64b29a1..32ccfdf2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -190,7 +190,7 @@ mod_use!(cfg(target_os = "redox"), use_file); mod_use!(cfg(target_os = "solaris"), solaris_illumos); mod_use!(cfg(windows), windows); mod_use!(cfg(target_env = "sgx"), rdrand); -mod_use!(cfg(target_os = "uefi"), rdrand); +mod_use!(cfg(all(target_arch = "x86_64", target_os = "uefi")), rdrand); mod_use!(cfg(target_os = "wasi"), wasi); mod_use!( @@ -232,7 +232,7 @@ mod_use!( target_os = "openbsd", target_os = "redox", target_os = "solaris", - target_os = "uefi", + all(target_arch = "x86_64", target_os = "uefi"), target_env = "sgx", windows, all( diff --git a/src/rdrand.rs b/src/rdrand.rs index 4753507b..587979e6 100644 --- a/src/rdrand.rs +++ b/src/rdrand.rs @@ -31,7 +31,7 @@ unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> { Err(Error::UNKNOWN) } -#[cfg(and(target_env = "sgx", not(target_feature = "rdrand")))] +#[cfg(all(target_env = "sgx", not(target_feature = "rdrand")))] compile_error!("SGX targets must enable RDRAND to get randomness"); // TODO use is_x86_feature_detected!("rdrand") when that works in core. See: From 8053d7ec3b3a34a5064ff41112a57060dcf31ada Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Sat, 15 Jun 2019 21:43:28 -0700 Subject: [PATCH 6/6] Improve compile_error! message --- src/rdrand.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rdrand.rs b/src/rdrand.rs index 587979e6..8bd7a1de 100644 --- a/src/rdrand.rs +++ b/src/rdrand.rs @@ -31,8 +31,11 @@ unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> { Err(Error::UNKNOWN) } +// "rdrand" target feature requires "+rdrnd" flag, see https://github.com/rust-lang/rust/issues/49653. #[cfg(all(target_env = "sgx", not(target_feature = "rdrand")))] -compile_error!("SGX targets must enable RDRAND to get randomness"); +compile_error!( + "SGX targets require 'rdrand' target feature. Enable by using -C target-feature=+rdrnd." +); // TODO use is_x86_feature_detected!("rdrand") when that works in core. See: // https://github.com/rust-lang-nursery/stdsimd/issues/464