diff --git a/Cargo.lock b/Cargo.lock index aea88db8c..f41e9f121 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -171,7 +171,6 @@ dependencies = [ "controlled", "core2", "cpio-decoder", - "getrandom", "getset", "hashbrown 0.14.3", "id-alloc", diff --git a/kernel/aster-nix/Cargo.toml b/kernel/aster-nix/Cargo.toml index 9457fcda6..407a0570d 100644 --- a/kernel/aster-nix/Cargo.toml +++ b/kernel/aster-nix/Cargo.toml @@ -61,7 +61,7 @@ lru = "0.12.3" log = "0.4" bitvec = { version = "1.0", default-features = false, features = ["alloc"] } hashbrown = "0.14" -rand = { version = "0.8.5", default-features = false, features = ["getrandom", "small_rng", "std_rng"] } +rand = { version = "0.8.5", default-features = false, features = ["small_rng", "std_rng"] } static_assertions = "1.1.0" inherit-methods-macro = { git = "https://github.com/asterinas/inherit-methods-macro", rev = "98f7e3e" } getset = "0.1.2" @@ -71,11 +71,6 @@ bytemuck_derive = "1.5.0" takeable = "0.2.2" cfg-if = "1.0" -[target.x86_64-unknown-none.dependencies] -getrandom = { version = "0.2.10", default-features = false, features = [ - "rdrand", -] } - [dependencies.lazy_static] version = "1.0" features = ["spin_no_std"] diff --git a/kernel/aster-nix/src/util/random.rs b/kernel/aster-nix/src/util/random.rs index a31b5e835..973005829 100644 --- a/kernel/aster-nix/src/util/random.rs +++ b/kernel/aster-nix/src/util/random.rs @@ -22,8 +22,22 @@ pub fn init() { cfg_if::cfg_if! { if #[cfg(target_arch = "x86_64")] { use rand::SeedableRng; + use ostd::arch::read_random; - RNG.call_once(|| SpinLock::new(StdRng::from_entropy())); + let mut seed = ::Seed::default(); + let mut chunks = seed.as_mut().chunks_exact_mut(size_of::()); + for chunk in chunks.by_ref() { + let src = read_random().expect("read_random failed multiple times").to_ne_bytes(); + chunk.copy_from_slice(&src); + } + let tail = chunks.into_remainder(); + let n = tail.len(); + if n > 0 { + let src = read_random().expect("read_random failed multiple times").to_ne_bytes(); + tail.copy_from_slice(&src[..n]); + } + + RNG.call_once(|| SpinLock::new(StdRng::from_seed(seed))); } else { compile_error!("unsupported target"); } diff --git a/ostd/src/arch/x86/mod.rs b/ostd/src/arch/x86/mod.rs index 4161c33bf..bcb42c417 100644 --- a/ostd/src/arch/x86/mod.rs +++ b/ostd/src/arch/x86/mod.rs @@ -19,7 +19,10 @@ pub(crate) mod tdx_guest; pub mod timer; pub mod trap; -use core::{arch::x86_64::_rdtsc, sync::atomic::Ordering}; +use core::{ + arch::x86_64::{_rdrand64_step, _rdtsc}, + sync::atomic::Ordering, +}; #[cfg(feature = "intel_tdx")] use ::tdx_guest::tdx_is_enabled; @@ -79,6 +82,25 @@ pub fn read_tsc() -> u64 { unsafe { _rdtsc() } } +/// Reads a hardware generated 64-bit random value. +/// +/// Returns None if no random value was generated. +pub fn read_random() -> Option { + // 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; + + for _ in 0..RETRY_LIMIT { + let mut val = 0; + let generated = unsafe { _rdrand64_step(&mut val) }; + if generated == 1 { + return Some(val); + } + } + None +} + fn enable_common_cpu_features() { use x86_64::registers::{control::Cr4Flags, model_specific::EferFlags, xcontrol::XCr0Flags}; let mut cr4 = x86_64::registers::control::Cr4::read();