-
Notifications
You must be signed in to change notification settings - Fork 109
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #524 from CosminGGeorgescu/rng_api
Rng API
- Loading branch information
Showing
6 changed files
with
212 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
[package] | ||
name = "libtock_rng" | ||
version = "0.1.0" | ||
authors = [ | ||
"Tock Project Developers <[email protected]>", | ||
"Cosmin Gabriel Georgescu <[email protected]>", | ||
] | ||
license = "Apache-2.0 OR MIT" | ||
edition = "2021" | ||
repository = "https://www.github.com/tock/libtock-rs" | ||
rust-version.workspace = true | ||
description = "libtock rng driver" | ||
|
||
[dependencies] | ||
libtock_platform = { path = "../../platform" } | ||
|
||
[dev-dependencies] | ||
libtock_unittest = { path = "../../unittest" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
#![no_std] | ||
|
||
use core::cell::Cell; | ||
use libtock_platform::{ | ||
share, subscribe::OneId, AllowRw, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall, | ||
}; | ||
|
||
pub struct Rng<S: Syscalls>(S); | ||
|
||
impl<S: Syscalls> Rng<S> { | ||
/// Check if the RNG kernel driver exists | ||
pub fn exists() -> Result<(), ErrorCode> { | ||
S::command(DRIVER_NUM, EXISTS, 0, 0).to_result() | ||
} | ||
|
||
/// Request `n` bytes of randomness in an asynchronous way. | ||
/// Users must first share a buffer slice with the kernel and register an Rng listener | ||
pub fn get_bytes_async(n: u32) -> Result<(), ErrorCode> { | ||
S::command(DRIVER_NUM, GET_BYTES, n, 0).to_result() | ||
} | ||
|
||
/// Share a buffer slice with the kernel. | ||
/// Must be used in conjunction with the `share::scope` function | ||
pub fn allow_buffer<'share>( | ||
buf: &'share mut [u8], | ||
allow_rw: share::Handle<AllowRw<'share, S, DRIVER_NUM, 0>>, | ||
) -> Result<(), ErrorCode> { | ||
S::allow_rw::<DefaultConfig, DRIVER_NUM, 0>(allow_rw, buf) | ||
} | ||
|
||
pub fn unallow_buffer() { | ||
S::unallow_rw(DRIVER_NUM, 0) | ||
} | ||
|
||
/// Register an Rng listener to be called when an upcall is serviced | ||
/// Must be used in conjunction with the `share::scope` function | ||
pub fn register_listener<'share, F: Fn(u32)>( | ||
listener: &'share RngListener<F>, | ||
subscribe: share::Handle<Subscribe<'share, S, DRIVER_NUM, 0>>, | ||
) -> Result<(), ErrorCode> { | ||
S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener) | ||
} | ||
|
||
pub fn unregister_listener() { | ||
S::unsubscribe(DRIVER_NUM, 0) | ||
} | ||
|
||
/// Ask to fill the provided `buf` with `n` random bytes. | ||
/// If `n > buf.len()`, it will simply fill the whole buffer. | ||
pub fn get_bytes_sync(buf: &mut [u8], n: u32) -> Result<(), ErrorCode> { | ||
let called = Cell::new(false); | ||
share::scope::<(AllowRw<S, DRIVER_NUM, 0>, Subscribe<S, DRIVER_NUM, 0>), _, _>(|handle| { | ||
let (allow_rw, subscribe) = handle.split(); | ||
|
||
// Share the provided buffer with the kernel | ||
S::allow_rw::<DefaultConfig, DRIVER_NUM, 0>(allow_rw, buf)?; | ||
|
||
// Subscribe for an upcall with the kernel | ||
S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &called)?; | ||
|
||
// Send the command to the kernel driver to fill the allowed_readwrite buffer | ||
S::command(DRIVER_NUM, GET_BYTES, n, 0).to_result()?; | ||
|
||
// Wait for a callback to happen | ||
while !called.get() { | ||
S::yield_wait(); | ||
} | ||
|
||
Ok(()) | ||
}) | ||
} | ||
} | ||
|
||
/// The provided listener to be called. | ||
/// Interior function operates on the number of random bytes filled into the buffer | ||
pub struct RngListener<F: Fn(u32)>(pub F); | ||
|
||
impl<F: Fn(u32)> Upcall<OneId<DRIVER_NUM, 0>> for RngListener<F> { | ||
fn upcall(&self, _: u32, arg1: u32, _: u32) { | ||
(self.0)(arg1) | ||
} | ||
} | ||
|
||
// ------------- | ||
// DRIVER NUMBER | ||
// ------------- | ||
const DRIVER_NUM: u32 = 0x40001; | ||
|
||
// --------------- | ||
// COMMAND NUMBERS | ||
// --------------- | ||
const EXISTS: u32 = 0; | ||
const GET_BYTES: u32 = 1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#![no_std] | ||
#![no_main] | ||
|
||
use core::fmt::Write; | ||
use libtock::alarm::{Alarm, Milliseconds}; | ||
use libtock::console::Console; | ||
use libtock::rng::Rng; | ||
use libtock::runtime::{set_main, stack_size}; | ||
|
||
stack_size! {0x300} | ||
set_main! {main} | ||
|
||
struct Randomness<'a, const N: usize>(&'a [u8; N]); | ||
|
||
impl<'a, const N: usize> core::fmt::Display for Randomness<'a, N> { | ||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { | ||
let mut bytes = self.0.iter(); | ||
while let Some(&byte) = bytes.next() { | ||
write!(f, "{byte:02x}")?; | ||
} | ||
Ok(()) | ||
} | ||
} | ||
|
||
fn main() { | ||
if let Err(e) = Rng::exists() { | ||
writeln!(Console::writer(), "RNG DRIVER ERROR: {e:?}").unwrap(); | ||
return; | ||
} | ||
|
||
let mut console_writer = Console::writer(); | ||
let mut buffer: [u8; 32] = Default::default(); | ||
let n: u32 = 32; | ||
|
||
loop { | ||
match Rng::get_bytes_sync(&mut buffer, n) { | ||
Ok(()) => { | ||
let _ = writeln!(console_writer, "Randomness: {}", Randomness(&buffer)); | ||
} | ||
Err(e) => { | ||
let _ = writeln!(console_writer, "Error while getting bytes {e:?}"); | ||
} | ||
} | ||
let _ = Alarm::sleep_for(Milliseconds(2000)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#![no_std] | ||
#![no_main] | ||
|
||
use core::fmt::Write; | ||
use libtock::alarm::{Alarm, Milliseconds}; | ||
use libtock::rng::RngListener; | ||
use libtock::{console::Console, rng::Rng}; | ||
use libtock_platform::{share, Syscalls}; | ||
use libtock_runtime::{set_main, stack_size, TockSyscalls}; | ||
|
||
stack_size! {0x300} | ||
set_main! {main} | ||
|
||
fn main() { | ||
if let Err(e) = Rng::exists() { | ||
writeln!(Console::writer(), "RNG DRIVER ERROR: {e:?}").unwrap(); | ||
return; | ||
} | ||
|
||
let mut console_writer = Console::writer(); | ||
let rng_listener = RngListener(|_| write!(Console::writer(), "Randomness: ").unwrap()); | ||
let mut buffer: [u8; 32] = Default::default(); | ||
let n: u32 = 32; | ||
|
||
loop { | ||
share::scope(|allow_rw| { | ||
Rng::allow_buffer(&mut buffer, allow_rw).unwrap(); | ||
|
||
share::scope(|subscribe| { | ||
Rng::register_listener(&rng_listener, subscribe).unwrap(); | ||
|
||
Rng::get_bytes_async(n).unwrap(); | ||
TockSyscalls::yield_wait(); | ||
}); | ||
}); | ||
|
||
buffer.iter().for_each(|&byte| { | ||
let _ = write!(console_writer, "{byte:02x}"); | ||
}); | ||
let _ = writeln!(console_writer, ""); | ||
|
||
let _ = Alarm::sleep_for(Milliseconds(2000)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters