Skip to content

Commit

Permalink
rdrand: Avoid assuming usize is the native word size. (#442)
Browse files Browse the repository at this point in the history
`x86_64-unknown-linux-gnux32` has target_pointer_width = "32", so usize
is 32-bits. In this case, we were throwing away half of each RDRAND
result and doing twice as many RDRAND invocations as necessary. This
wasn't noticed because `as` silently does a lossy conversion.
  • Loading branch information
briansmith authored May 31, 2024
1 parent f8899bd commit b2bca0f
Showing 1 changed file with 5 additions and 3 deletions.
8 changes: 5 additions & 3 deletions src/rdrand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ cfg_if! {
if #[cfg(target_arch = "x86_64")] {
use core::arch::x86_64 as arch;
use arch::_rdrand64_step as rdrand_step;
type Word = u64;
} else if #[cfg(target_arch = "x86")] {
use core::arch::x86 as arch;
use arch::_rdrand32_step as rdrand_step;
type Word = u32;
}
}

Expand All @@ -18,11 +20,11 @@ cfg_if! {
const RETRY_LIMIT: usize = 10;

#[target_feature(enable = "rdrand")]
unsafe fn rdrand() -> Option<usize> {
unsafe fn rdrand() -> Option<Word> {
for _ in 0..RETRY_LIMIT {
let mut val = 0;
if rdrand_step(&mut val) == 1 {
return Some(val as usize);
return Some(val);
}
}
None
Expand Down Expand Up @@ -105,7 +107,7 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
unsafe fn rdrand_exact(dest: &mut [MaybeUninit<u8>]) -> Option<()> {
// 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(size_of::<usize>());
let mut chunks = dest.chunks_exact_mut(size_of::<Word>());
for chunk in chunks.by_ref() {
let src = rdrand()?.to_ne_bytes();
chunk.copy_from_slice(slice_as_uninit(&src));
Expand Down

0 comments on commit b2bca0f

Please sign in to comment.