Skip to content

Commit

Permalink
Improve RDRAND implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
josephlr committed Jun 12, 2019
1 parent 5302a81 commit 0558adf
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 17 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,15 @@ matrix:
#- rustup target add x86_64-unknown-fuchsia
- rustup target add x86_64-unknown-netbsd
- rustup target add x86_64-unknown-redox
- rustup target add x86_64-fortanix-unknown-sgx
script:
- cargo build --target=x86_64-sun-solaris --all-features
- cargo build --target=x86_64-unknown-cloudabi --all-features
- cargo build --target=x86_64-unknown-freebsd --all-features
#- cargo build --target=x86_64-unknown-fuchsia --all-features
- 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
# also test minimum dependency versions are usable
- cargo generate-lockfile -Z minimal-versions
- cargo build --target=x86_64-sun-solaris --all-features
Expand All @@ -120,6 +122,7 @@ matrix:
#- cargo build --target=x86_64-unknown-fuchsia --all-features
- 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

# Trust cross-built/emulated targets. We must repeat all non-default values.
- rust: stable
Expand Down
38 changes: 21 additions & 17 deletions src/rdrand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,45 @@

//! Implementation for SGX using RDRAND instruction
use crate::Error;
use core::{mem, ptr};
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!");

const RETRY_LIMIT: usize = 32;
// 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 get_rand_u64() -> Result<u64, Error> {
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);
return Ok(el.to_ne_bytes());
}
};
}
error!("RDRAND failed, CPU issue likely");
Err(Error::UNKNOWN)
}

pub fn getrandom_inner(mut dest: &mut [u8]) -> Result<(), Error> {
while dest.len() >= 8 {
let (chunk, left) = {dest}.split_at_mut(8);
dest = left;
let r = get_rand_u64()?;
unsafe {
ptr::write_unaligned(chunk.as_mut_ptr() as *mut u64, r)
}
pub fn getrandom_inner(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);
for chunk in chunks.by_ref() {
chunk.copy_from_slice(&rdrand()?);
}
let n = dest.len();
if n != 0 {
let r = get_rand_u64()?;
let r: [u8; 8] = unsafe { mem::transmute(r) };
dest.copy_from_slice(&r[..n]);

let tail = chunks.into_remainder();
let n = tail.len();
if n > 0 {
tail.copy_from_slice(&rdrand()?[..n]);
}
Ok(())
}
Expand Down

0 comments on commit 0558adf

Please sign in to comment.