kernel: Move rand driver to platform module.

Signed-off-by: Jean-Pierre De Jesus DIAZ <me@jeandudey.tech>
This commit is contained in:
Jean-Pierre De Jesus DIAZ 2022-11-02 14:29:53 +01:00
parent b334e5bc31
commit d8807e6cea
No known key found for this signature in database
GPG key ID: 6279AEC20A9524EC
9 changed files with 123 additions and 80 deletions

View file

@ -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`

View file

@ -1,69 +0,0 @@
// SPDX-FileCopyrightText: 2020 Sean Cross <sean@xobs.io>
// 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)
}
}

View file

@ -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.

View file

@ -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() {

View file

@ -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();
}

View file

@ -0,0 +1,98 @@
// SPDX-FileCopyrightText: 2020 Sean Cross <sean@xobs.io>
// SPDX-FileCopyrightText: 2022 Foundation Devices, Inc. <hello@foundationdevices.com>
// 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<TrngKernel> = None;
pub struct TrngKernel {
pub trng_kernel_csr: CSR<u32>,
}
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()
}
}

View file

@ -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());

View file

@ -0,0 +1,11 @@
// SPDX-FileCopyrightText: 2022 Foundation Devices, Inc. <hello@foundationdevices.com>
// 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
}

View file

@ -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<SID, xous_kernel::Error> {
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)
}