tfhe_csprng/seeders/implem/
rdseed.rs1use crate::seeders::{Seed, Seeder};
2
3pub struct RdseedSeeder(());
8
9impl RdseedSeeder {
10 pub fn new() -> Self {
11 if Self::is_available() {
12 Self(())
13 } else {
14 panic!("Tried to use RdSeedSeeder but rdseed instruction is not enabled on the current machine");
15 }
16 }
17}
18
19impl Default for RdseedSeeder {
20 fn default() -> Self {
21 Self::new()
22 }
23}
24
25impl Seeder for RdseedSeeder {
26 fn seed(&mut self) -> Seed {
27 Seed(unsafe { rdseed_random_m128() })
28 }
29
30 fn is_available() -> bool {
31 is_x86_feature_detected!("rdseed")
32 }
33}
34
35#[target_feature(enable = "rdseed")]
37unsafe fn rdseed_random_m128() -> u128 {
38 let mut rand1: u64 = 0;
39 let mut rand2: u64 = 0;
40 let mut output_bytes = [0u8; 16];
41
42 loop {
43 if core::arch::x86_64::_rdseed64_step(&mut rand1) == 1 {
44 break;
45 }
46 }
47 loop {
48 if core::arch::x86_64::_rdseed64_step(&mut rand2) == 1 {
49 break;
50 }
51 }
52
53 output_bytes[0..8].copy_from_slice(&rand1.to_ne_bytes());
54 output_bytes[8..16].copy_from_slice(&rand2.to_ne_bytes());
55 u128::from_ne_bytes(output_bytes)
56}
57
58#[cfg(test)]
59mod test {
60 use super::*;
61 use crate::seeders::generic_tests::check_seeder_fixed_sequences_different;
62
63 #[test]
64 fn check_bounded_sequence_difference() {
65 check_seeder_fixed_sequences_different(|_| RdseedSeeder::new());
66 }
67}