Improve RDRAND implementation (#24)
* Move sgx.rs to rdrand.rs * Improve RDRAND implementation
This commit is contained in:
parent
50212bd5ed
commit
9e6408260f
@ -105,6 +105,7 @@ 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
|
||||
@ -112,6 +113,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
|
||||
# also test minimum dependency versions are usable
|
||||
- cargo generate-lockfile -Z minimal-versions
|
||||
- cargo build --target=x86_64-sun-solaris --all-features
|
||||
@ -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
|
||||
|
@ -189,7 +189,7 @@ mod_use!(cfg(target_os = "openbsd"), openbsd_bitrig);
|
||||
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"), sgx);
|
||||
mod_use!(cfg(target_env = "sgx"), rdrand);
|
||||
mod_use!(cfg(target_os = "wasi"), wasi);
|
||||
|
||||
mod_use!(
|
||||
|
55
src/rdrand.rs
Normal file
55
src/rdrand.rs
Normal file
@ -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 SGX using RDRAND instruction
|
||||
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!");
|
||||
|
||||
// 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> {
|
||||
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());
|
||||
}
|
||||
};
|
||||
}
|
||||
error!("RDRAND failed, CPU issue likely");
|
||||
Err(Error::UNKNOWN)
|
||||
}
|
||||
|
||||
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 tail = chunks.into_remainder();
|
||||
let n = tail.len();
|
||||
if n > 0 {
|
||||
tail.copy_from_slice(&rdrand()?[..n]);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
51
src/sgx.rs
51
src/sgx.rs
@ -1,51 +0,0 @@
|
||||
// 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 SGX using RDRAND instruction
|
||||
use crate::Error;
|
||||
use core::{mem, ptr};
|
||||
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;
|
||||
|
||||
fn get_rand_u64() -> Result<u64, Error> {
|
||||
for _ in 0..RETRY_LIMIT {
|
||||
unsafe {
|
||||
let mut el = mem::uninitialized();
|
||||
if _rdrand64_step(&mut el) == 1 {
|
||||
return Ok(el);
|
||||
}
|
||||
};
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
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]);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
Loading…
x
Reference in New Issue
Block a user