From d8807e6ceadafc1b175845cd0283f71f39c7318b Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Wed, 2 Nov 2022 14:29:53 +0100 Subject: [PATCH] kernel: Move rand driver to platform module. Signed-off-by: Jean-Pierre De Jesus DIAZ --- kernel/src/arch/riscv/mod.rs | 2 - kernel/src/arch/riscv/rand.rs | 69 ------------------- kernel/src/main.rs | 4 +- kernel/src/platform/mod.rs | 2 + kernel/src/platform/precursor/mod.rs | 2 + kernel/src/platform/precursor/rand.rs | 98 +++++++++++++++++++++++++++ kernel/src/platform/precursor/uart.rs | 6 +- kernel/src/platform/rand.rs | 11 +++ kernel/src/services.rs | 9 +-- 9 files changed, 123 insertions(+), 80 deletions(-) delete mode 100644 kernel/src/arch/riscv/rand.rs create mode 100644 kernel/src/platform/precursor/rand.rs create mode 100644 kernel/src/platform/rand.rs diff --git a/kernel/src/arch/riscv/mod.rs b/kernel/src/arch/riscv/mod.rs index ac1d1fb99..eb2d5f784 100644 --- a/kernel/src/arch/riscv/mod.rs +++ b/kernel/src/arch/riscv/mod.rs @@ -7,7 +7,6 @@ pub mod exception; pub mod irq; pub mod mem; pub mod process; -pub mod rand; pub mod syscall; pub use process::Thread; @@ -49,7 +48,6 @@ pub fn init() { sie::set_ssoft(); sie::set_sext(); } - rand::init(); } /// Put the core to sleep until an interrupt hits. Returns `true` diff --git a/kernel/src/arch/riscv/rand.rs b/kernel/src/arch/riscv/rand.rs deleted file mode 100644 index c742af7f9..000000000 --- a/kernel/src/arch/riscv/rand.rs +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-FileCopyrightText: 2020 Sean Cross -// SPDX-License-Identifier: Apache-2.0 - -use crate::mem::MemoryManager; -use utralib::generated::*; -use xous_kernel::{MemoryFlags, MemoryType, PID}; - -pub const TRNG_KERNEL: Trng = Trng { - // the HW device mapping is done in xous-rs/src/lib.rs/init() - // the manually chosen virtual address has to be in the top 4MiB as it is the only page shared among all processes - base: 0xffce_0000 as *mut usize, // see https://github.com/betrusted-io/xous-core/blob/master/docs/memory.md -}; - -pub struct Trng { - pub base: *mut usize, -} - -pub fn init() { - // Map the TRNG so that we can allocate names - // hardware guarantees that: - // - TRNG will automatically power on - // - Both TRNGs are enabled, with conservative defaults - // - Kernel FIFO will fill with TRNGs such that at least the next 512 calls to get_u32() will succeed without delay - // - The kernel will start a TRNG server - // - All further security decisions and policies are 100% delegated to this new server. - MemoryManager::with_mut(|memory_manager| { - memory_manager - .map_range( - utra::trng_kernel::HW_TRNG_KERNEL_BASE as *mut u8, - ((TRNG_KERNEL.base as u32) & !4095) as *mut u8, - 4096, - PID::new(1).unwrap(), - MemoryFlags::R | MemoryFlags::W, - MemoryType::Default, - ) - .expect("unable to map TRNG") - }); - - let trng_kernel_csr = CSR::new(TRNG_KERNEL.base as *mut u32); - if false { // raw random path - left in for debugging urandom, can strip out later - while trng_kernel_csr.rf(utra::trng_kernel::STATUS_AVAIL) == 0 {} - // discard the first entry, as it is always 0x0000_0000 - // this is because the read register is a pipeline stage behind the FIFO - // once the pipeline has been filled, there is no need to prime it again. - trng_kernel_csr.rf(utra::trng_kernel::DATA_DATA); - } else { // urandom path (recommended) - // simulations show this isn't strictly necessary, but I prefer to have it - // just in case a subtle bug in the reset logic leaves something deterministic - // in the connecting logic: the simulation coverage stops at the edge of the TRNG block. - for _ in 0..4 { - // wait until the urandom port is initialized - while trng_kernel_csr.rf(utra::trng_kernel::URANDOM_VALID_URANDOM_VALID) == 0 {} - // pull a dummy piece of data - trng_kernel_csr.rf(utra::trng_kernel::URANDOM_URANDOM); - } - } - -} - -pub fn get_u32() -> u32 { - let trng_kernel_csr = CSR::new(TRNG_KERNEL.base as *mut u32); - if false { // raw random path - while trng_kernel_csr.rf(utra::trng_kernel::STATUS_AVAIL) == 0 {} - trng_kernel_csr.rf(utra::trng_kernel::DATA_DATA) - } else { // urandom path (recommended) - while trng_kernel_csr.rf(utra::trng_kernel::URANDOM_VALID_URANDOM_VALID) == 0 {} - trng_kernel_csr.rf(utra::trng_kernel::URANDOM_URANDOM) - } -} diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 0cb7c3ef0..cefd0191d 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -69,8 +69,8 @@ pub unsafe extern "C" fn init(arg_offset: *const u32, init_offset: *const u32, r println!("KMAIN (clean boot): Supervisor mode started..."); // rand::init() already clears the initial pipe, but pump the TRNG a little more out of no other reason than sheer paranoia - arch::rand::get_u32(); - arch::rand::get_u32(); + platform::rand::get_u32(); + platform::rand::get_u32(); } /// Loop through the SystemServices list to determine the next PID to be run. diff --git a/kernel/src/platform/mod.rs b/kernel/src/platform/mod.rs index 66e742e3d..850735f37 100644 --- a/kernel/src/platform/mod.rs +++ b/kernel/src/platform/mod.rs @@ -4,6 +4,8 @@ #[cfg(any(feature="precursor", feature="renode"))] pub mod precursor; +pub mod rand; + /// Platform specific initialization. #[cfg(not(any(unix, windows)))] pub fn init() { diff --git a/kernel/src/platform/precursor/mod.rs b/kernel/src/platform/precursor/mod.rs index f02ec11ff..40ffd80a0 100644 --- a/kernel/src/platform/precursor/mod.rs +++ b/kernel/src/platform/precursor/mod.rs @@ -3,9 +3,11 @@ #[cfg(any(feature = "debug-print", feature = "print-panics"))] pub mod uart; +pub mod rand; /// Precursor specific initialization. pub fn init() { + self::rand::init(); #[cfg(any(feature = "debug-print", feature = "print-panics"))] self::uart::init(); } \ No newline at end of file diff --git a/kernel/src/platform/precursor/rand.rs b/kernel/src/platform/precursor/rand.rs new file mode 100644 index 000000000..227dd370f --- /dev/null +++ b/kernel/src/platform/precursor/rand.rs @@ -0,0 +1,98 @@ +// SPDX-FileCopyrightText: 2020 Sean Cross +// SPDX-FileCopyrightText: 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use crate::mem::MemoryManager; +use utralib::generated::*; +use xous_kernel::{MemoryFlags, MemoryType, PID}; + +/// The manually chosen virtual address has to be in the top 4MiB as it is the +/// only page shared among all processes. +/// +/// See https://github.com/betrusted-io/xous-core/blob/master/docs/memory.md +pub const TRNG_KERNEL_ADDR: usize = 0xffce_0000; +pub static mut TRNG_KERNEL: Option = None; + +pub struct TrngKernel { + pub trng_kernel_csr: CSR, +} + +impl TrngKernel { + pub fn new(addr: usize) -> TrngKernel { + TrngKernel { + trng_kernel_csr: CSR::new(addr as *mut u32), + } + } + + pub fn init(&mut self) { + if false { // raw random path - left in for debugging urandom, can strip out later + while self.trng_kernel_csr.rf(utra::trng_kernel::STATUS_AVAIL) == 0 {} + // discard the first entry, as it is always 0x0000_0000 + // this is because the read register is a pipeline stage behind the FIFO + // once the pipeline has been filled, there is no need to prime it again. + self.trng_kernel_csr.rf(utra::trng_kernel::DATA_DATA); + } else { // urandom path (recommended) + // simulations show this isn't strictly necessary, but I prefer to have it + // just in case a subtle bug in the reset logic leaves something deterministic + // in the connecting logic: the simulation coverage stops at the edge of the TRNG block. + for _ in 0..4 { + // wait until the urandom port is initialized + while self.trng_kernel_csr.rf(utra::trng_kernel::URANDOM_VALID_URANDOM_VALID) == 0 {} + // pull a dummy piece of data + self.trng_kernel_csr.rf(utra::trng_kernel::URANDOM_URANDOM); + } + } + } + + pub fn get_u32(&mut self) -> u32 { + if false { // raw random path + while self.trng_kernel_csr.rf(utra::trng_kernel::STATUS_AVAIL) == 0 {} + self.trng_kernel_csr.rf(utra::trng_kernel::DATA_DATA) + } else { // urandom path (recommended) + while self.trng_kernel_csr.rf(utra::trng_kernel::URANDOM_VALID_URANDOM_VALID) == 0 {} + self.trng_kernel_csr.rf(utra::trng_kernel::URANDOM_URANDOM) + } + } +} + +/// Initialize TRNG driver. +/// +/// Needed so that the kernel can allocate names. +pub fn init() { + // Map the TRNG so that we can allocate names + // hardware guarantees that: + // - TRNG will automatically power on + // - Both TRNGs are enabled, with conservative defaults + // - Kernel FIFO will fill with TRNGs such that at least the next 512 calls to get_u32() will succeed without delay + // - The kernel will start a TRNG server + // - All further security decisions and policies are 100% delegated to this new server. + MemoryManager::with_mut(|memory_manager| { + memory_manager + .map_range( + utra::trng_kernel::HW_TRNG_KERNEL_BASE as *mut u8, + (TRNG_KERNEL_ADDR & !4095) as *mut u8, + 4096, + PID::new(1).unwrap(), + MemoryFlags::R | MemoryFlags::W, + MemoryType::Default, + ) + .expect("unable to map TRNG_KERNEL") + }); + + let mut trng_kernel = TrngKernel::new(TRNG_KERNEL_ADDR); + trng_kernel.init(); + + unsafe { + TRNG_KERNEL = Some(trng_kernel); + } +} + +/// Retrieve random `u32`. +pub fn get_u32() -> u32 { + unsafe { + TRNG_KERNEL + .as_mut() + .expect("TRNG_KERNEL driver not initialized") + .get_u32() + } +} diff --git a/kernel/src/platform/precursor/uart.rs b/kernel/src/platform/precursor/uart.rs index 0001bbddb..0aa42c855 100644 --- a/kernel/src/platform/precursor/uart.rs +++ b/kernel/src/platform/precursor/uart.rs @@ -85,10 +85,10 @@ pub fn init() { .expect("unable to map serial port") }); - unsafe { - let mut uart = Uart::new(UART_ADDR, process_characters); - uart.init(); + let mut uart = Uart::new(UART_ADDR, process_characters); + uart.init(); + unsafe { UART = Some(uart); crate::debug::shell::init(UART.as_mut().unwrap()); diff --git a/kernel/src/platform/rand.rs b/kernel/src/platform/rand.rs new file mode 100644 index 000000000..22c5027c1 --- /dev/null +++ b/kernel/src/platform/rand.rs @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: Apache-2.0 + +pub fn get_u32() -> u32 { + // hosted rand code is coupled with arch code. + #[cfg(any(windows, unix))] + let rand = crate::arch::rand::get_u32(); + #[cfg(any(feature="precursor", feature="renode"))] + let rand = crate::platform::precursor::rand::get_u32(); + rand +} \ No newline at end of file diff --git a/kernel/src/services.rs b/kernel/src/services.rs index cbfd0d5c3..1f4b7a24b 100644 --- a/kernel/src/services.rs +++ b/kernel/src/services.rs @@ -5,6 +5,7 @@ use crate::arch; use crate::arch::mem::MemoryMapping; pub use crate::arch::process::Process as ArchProcess; pub use crate::arch::process::Thread; +use crate::platform; use xous_kernel::arch::ProcessStartup; use xous_kernel::MemoryRange; @@ -1742,10 +1743,10 @@ impl SystemServices { /// any processes. pub fn create_server_id(&mut self) -> Result { let sid = SID::from_u32( - arch::rand::get_u32(), - arch::rand::get_u32(), - arch::rand::get_u32(), - arch::rand::get_u32(), + platform::rand::get_u32(), + platform::rand::get_u32(), + platform::rand::get_u32(), + platform::rand::get_u32(), ); Ok(sid) }