#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::{
_rdrand16_step, _rdrand32_step, _rdrand64_step, _rdseed16_step, _rdseed32_step, _rdseed64_step,
};
#[cfg(target_arch = "x86")]
use core::arch::x86::{_rdrand16_step, _rdrand32_step, _rdseed16_step, _rdseed32_step};
#[inline(always)]
pub unsafe fn rdrand16(e: &mut u16) -> bool {
_rdrand16_step(e) == 1
}
#[inline(always)]
pub unsafe fn rdrand32(e: &mut u32) -> bool {
_rdrand32_step(e) == 1
}
#[cfg(target_arch = "x86_64")]
#[inline(always)]
pub unsafe fn rdrand64(e: &mut u64) -> bool {
_rdrand64_step(e) == 1
}
pub trait RdRand {
unsafe fn fill_random(&mut self) -> bool;
}
impl RdRand for u8 {
unsafe fn fill_random(&mut self) -> bool {
let mut r: u16 = 0;
let ret = rdrand16(&mut r);
*self = r as u8;
ret
}
}
impl RdRand for u16 {
unsafe fn fill_random(&mut self) -> bool {
rdrand16(self)
}
}
impl RdRand for u32 {
unsafe fn fill_random(&mut self) -> bool {
rdrand32(self)
}
}
#[cfg(target_arch = "x86_64")]
impl RdRand for u64 {
unsafe fn fill_random(&mut self) -> bool {
rdrand64(self)
}
}
pub unsafe fn rdrand_slice<T: RdRand>(buffer: &mut [T]) -> bool {
let mut worked = true;
for element in buffer {
worked &= element.fill_random();
}
worked
}
#[inline(always)]
pub unsafe fn rdseed16(e: &mut u16) -> bool {
_rdseed16_step(e) == 1
}
#[inline(always)]
pub unsafe fn rdseed32(e: &mut u32) -> bool {
_rdseed32_step(e) == 1
}
#[cfg(target_arch = "x86_64")]
#[inline(always)]
pub unsafe fn rdseed64(e: &mut u64) -> bool {
_rdseed64_step(e) == 1
}
pub trait RdSeed {
unsafe fn fill_random(&mut self) -> bool;
}
impl RdSeed for u8 {
unsafe fn fill_random(&mut self) -> bool {
let mut r: u16 = 0;
let ret = rdseed16(&mut r);
*self = r as u8;
ret
}
}
impl RdSeed for u16 {
unsafe fn fill_random(&mut self) -> bool {
rdseed16(self)
}
}
impl RdSeed for u32 {
unsafe fn fill_random(&mut self) -> bool {
rdseed32(self)
}
}
#[cfg(target_arch = "x86_64")]
impl RdSeed for u64 {
unsafe fn fill_random(&mut self) -> bool {
rdseed64(self)
}
}
pub unsafe fn rdseed_slice<T: RdSeed>(buffer: &mut [T]) -> bool {
let mut worked = true;
for element in buffer {
worked &= element.fill_random();
}
worked
}
#[cfg(all(test, feature = "utest"))]
mod test {
use super::*;
#[test]
fn rdrand_u64() {
let has_rdrand = crate::cpuid::CpuId::new()
.get_feature_info()
.map_or(false, |finfo| finfo.has_rdrand());
if !has_rdrand {
return;
}
unsafe {
let mut buf: [u64; 4] = [0, 0, 0, 0];
rdrand_slice(&mut buf);
assert_ne!(buf[0], 0);
assert_ne!(buf[1], 0);
assert_ne!(buf[2], 0);
assert_ne!(buf[3], 0);
}
}
#[test]
fn rdrand_u32() {
let has_rdrand = crate::cpuid::CpuId::new()
.get_feature_info()
.map_or(false, |finfo| finfo.has_rdrand());
if !has_rdrand {
return;
}
unsafe {
let mut buf: [u32; 4] = [0, 0, 0, 0];
rdrand_slice(&mut buf);
assert_ne!(buf[0], 0);
assert_ne!(buf[1], 0);
assert_ne!(buf[2], 0);
assert_ne!(buf[3], 0);
}
}
#[test]
fn rdrand_u16() {
let has_rdrand = crate::cpuid::CpuId::new()
.get_feature_info()
.map_or(false, |finfo| finfo.has_rdrand());
if !has_rdrand {
return;
}
unsafe {
let mut buf: [u16; 4] = [0, 0, 0, 0];
rdrand_slice(&mut buf);
assert_ne!(buf[0], 0);
assert_ne!(buf[1], 0);
assert_ne!(buf[2], 0);
assert_ne!(buf[3], 0);
}
}
#[test]
fn rdseed_u64() {
let has_rdseed = crate::cpuid::CpuId::new()
.get_extended_feature_info()
.map_or(false, |efinfo| efinfo.has_rdseed());
if !has_rdseed {
return;
}
unsafe {
let mut buf: [u64; 4] = [0, 0, 0, 0];
rdseed_slice(&mut buf);
assert_ne!(buf[0], 0);
assert_ne!(buf[1], 0);
assert_ne!(buf[2], 0);
assert_ne!(buf[3], 0);
}
}
#[test]
fn rdseed_u32() {
let has_rdseed = crate::cpuid::CpuId::new()
.get_extended_feature_info()
.map_or(false, |efinfo| efinfo.has_rdseed());
if !has_rdseed {
return;
}
unsafe {
let mut buf: [u32; 4] = [0, 0, 0, 0];
rdseed_slice(&mut buf);
assert_ne!(buf[0], 0);
assert_ne!(buf[1], 0);
assert_ne!(buf[2], 0);
assert_ne!(buf[3], 0);
}
}
#[test]
fn rdseed_u16() {
let has_rdseed = crate::cpuid::CpuId::new()
.get_extended_feature_info()
.map_or(false, |efinfo| efinfo.has_rdseed());
if !has_rdseed {
return;
}
unsafe {
let mut buf: [u16; 4] = [0, 0, 0, 0];
rdseed_slice(&mut buf);
assert!(buf[0] > 0 || buf[1] > 0 || buf[2] > 0 || buf[3] > 0);
}
}
#[test]
fn rdrand_u8() {
let has_rdseed = crate::cpuid::CpuId::new()
.get_extended_feature_info()
.map_or(false, |efinfo| efinfo.has_rdseed());
if !has_rdseed {
return;
}
unsafe {
let mut buf: [u8; 4] = [0, 0, 0, 0];
rdrand_slice(&mut buf);
assert!(buf[0] > 0 || buf[1] > 0 || buf[2] > 0 || buf[3] > 0);
}
}
#[test]
fn rdseed_u8() {
let has_rdseed = crate::cpuid::CpuId::new()
.get_extended_feature_info()
.map_or(false, |efinfo| efinfo.has_rdseed());
if !has_rdseed {
return;
}
unsafe {
let mut buf: [u8; 4] = [0, 0, 0, 0];
rdseed_slice(&mut buf);
assert!(buf[0] > 0 || buf[1] > 0 || buf[2] > 0 || buf[3] > 0);
}
}
}