Skip to content

Commit c4f7f45

Browse files
committed
rdrand: Remove check for 0 and !0 values
Also makes rdrand() return an integer instead of an array of bytes. This will make the self-test implementation easier. As we can just return a `usize` we no longer need the `WORD_SIZE` constant. Signed-off-by: Joe Richey <[email protected]>
1 parent a56faa8 commit c4f7f45

File tree

1 file changed

+20
-26
lines changed

1 file changed

+20
-26
lines changed

src/rdrand.rs

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
// except according to those terms.
88

99
//! Implementation for SGX using RDRAND instruction
10-
use crate::{util::slice_as_uninit, Error};
11-
use core::mem::{self, MaybeUninit};
10+
use crate::{
11+
util::{slice_as_uninit, LazyBool},
12+
Error,
13+
};
14+
use core::mem::{size_of, MaybeUninit};
1215

1316
cfg_if! {
1417
if #[cfg(target_arch = "x86_64")] {
@@ -24,25 +27,16 @@ cfg_if! {
2427
// Implementation Guide" - Section 5.2.1 and "Intel® 64 and IA-32 Architectures
2528
// Software Developer’s Manual" - Volume 1 - Section 7.3.17.1.
2629
const RETRY_LIMIT: usize = 10;
27-
const WORD_SIZE: usize = mem::size_of::<usize>();
2830

2931
#[target_feature(enable = "rdrand")]
30-
unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> {
32+
unsafe fn rdrand() -> Option<usize> {
3133
for _ in 0..RETRY_LIMIT {
32-
let mut el = mem::zeroed();
33-
if rdrand_step(&mut el) == 1 {
34-
// AMD CPUs from families 14h to 16h (pre Ryzen) sometimes fail to
35-
// set CF on bogus random data, so we check these values explicitly.
36-
// See https://github.com/systemd/systemd/issues/11810#issuecomment-489727505
37-
// We perform this check regardless of target to guard against
38-
// any implementation that incorrectly fails to set CF.
39-
if el != 0 && el != !0 {
40-
return Ok(el.to_ne_bytes());
41-
}
42-
// Keep looping in case this was a false positive.
34+
let mut val = 0;
35+
if rdrand_step(&mut val) == 1 {
36+
return Some(val as usize);
4337
}
4438
}
45-
Err(Error::FAILED_RDRAND)
39+
None
4640
}
4741

4842
// "rdrand" target feature requires "+rdrand" flag, see https://github.com/rust-lang/rust/issues/49653.
@@ -73,25 +67,25 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
7367
if !is_rdrand_supported() {
7468
return Err(Error::NO_RDRAND);
7569
}
76-
77-
// SAFETY: After this point, rdrand is supported, so calling the rdrand
78-
// functions is not undefined behavior.
79-
unsafe { rdrand_exact(dest) }
70+
rdrand_exact(dest).ok_or(Error::FAILED_RDRAND)
8071
}
8172

82-
#[target_feature(enable = "rdrand")]
83-
unsafe fn rdrand_exact(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
73+
fn rdrand_exact(dest: &mut [MaybeUninit<u8>]) -> Option<()> {
8474
// We use chunks_exact_mut instead of chunks_mut as it allows almost all
8575
// calls to memcpy to be elided by the compiler.
86-
let mut chunks = dest.chunks_exact_mut(WORD_SIZE);
76+
let mut chunks = dest.chunks_exact_mut(size_of::<usize>());
8777
for chunk in chunks.by_ref() {
88-
chunk.copy_from_slice(slice_as_uninit(&rdrand()?));
78+
// SAFETY: After this point, we know rdrand is supported, so calling
79+
// rdrand is not undefined behavior.
80+
let src = unsafe { rdrand() }?.to_ne_bytes();
81+
chunk.copy_from_slice(slice_as_uninit(&src));
8982
}
9083

9184
let tail = chunks.into_remainder();
9285
let n = tail.len();
9386
if n > 0 {
94-
tail.copy_from_slice(slice_as_uninit(&rdrand()?[..n]));
87+
let src = unsafe { rdrand() }?.to_ne_bytes();
88+
tail.copy_from_slice(slice_as_uninit(&src[..n]));
9589
}
96-
Ok(())
90+
Some(())
9791
}

0 commit comments

Comments
 (0)