-
Notifications
You must be signed in to change notification settings - Fork 241
Support x86_64-unknown-uefi #30
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 all commits
0381ee0
94440e1
fc8ab62
5c6294a
25bd5a5
8053d7e
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 |
|---|---|---|
|
|
@@ -9,33 +9,61 @@ | |
| //! 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; | ||
|
|
||
| #[cfg(not(target_feature = "rdrand"))] | ||
| compile_error!("enable rdrand target feature!"); | ||
| 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 | ||
| // Software Developer’s Manual" - Volume 1 - Section 7.3.17.1. | ||
| const RETRY_LIMIT: usize = 10; | ||
| const WORD_SIZE: usize = mem::size_of::<u64>(); | ||
|
|
||
| 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(); | ||
|
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. A bit late to the party here, but I was curious why this uses Zeroing seems relatively lightweight compared to RDRAND itself, would make RNG failures more obvious, and eliminates the potential risk of using attacker-controlled values which appear plausibly random at first glance as e.g. cryptographic keys.
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. Yeah,
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. Fixed in the latest commit.
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. @tarcieri good catch! It also gets rid of a deprecation warning on the latest nightly. |
||
| if _rdrand64_step(&mut el) == 1 { | ||
| return Ok(el.to_ne_bytes()); | ||
| } | ||
| } | ||
| error!("RDRAND failed, CPU issue likely"); | ||
| 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 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 | ||
| fn is_rdrand_supported() -> bool { | ||
| if cfg!(target_feature = "rdrand") { | ||
| true | ||
| } 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_rdrand_supported() { | ||
| 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); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.