Skip to content

Commit

Permalink
Add rng::bytes() as a safer version of rng::fill_bytes()
Browse files Browse the repository at this point in the history
  • Loading branch information
ia0 committed Jan 3, 2025
1 parent 3a6a8b5 commit 43eb5e1
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 21 deletions.
2 changes: 1 addition & 1 deletion book/src/applet/prelude/usb.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ We then wait until the player presses Enter. We can read a single byte from the
{{#include usb.rs:ready}}
```

To generate the next question, we use `rng::fill_bytes()` which fills a buffer with random bytes. We
To generate the next question, we use `rng::bytes()` which returns a slice of random bytes. We
provide a buffer with the length of the current level. For the string to be printable we truncate
the entropy of each byte from 8 to 5 bits and convert it to a `base32` symbol.

Expand Down
7 changes: 3 additions & 4 deletions book/src/applet/prelude/usb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
#![no_std]
wasefire::applet!();

use alloc::format;
use alloc::rc::Rc;
use alloc::string::String;
use alloc::{format, vec};
use core::cell::Cell;
use core::time::Duration;

Expand All @@ -49,13 +49,12 @@ fn main() {

//{ ANCHOR: generate
// Generate a question for this level.
let mut question = vec![0; level];
rng::fill_bytes(&mut question).unwrap();
let mut question = rng::bytes(level).unwrap();
for byte in &mut question {
const BASE32: [u8; 32] = *b"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
*byte = BASE32[(*byte & 0x1f) as usize];
}
let mut question = String::from_utf8(question).unwrap();
let mut question = String::from_utf8(question.into()).unwrap();
//} ANCHOR_END: generate

//{ ANCHOR: question
Expand Down
1 change: 1 addition & 0 deletions crates/prelude/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Minor

- Add `rng::bytes{,_array}()` as safer alternatives to `rng::fill_bytes()`
- Use Rust edition 2024

### Patch
Expand Down
2 changes: 2 additions & 0 deletions crates/prelude/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#![feature(alloc_error_handler)]
#![feature(doc_auto_cfg)]
#![feature(macro_metavar_expr)]
#![feature(maybe_uninit_array_assume_init)]
#![feature(maybe_uninit_uninit_array)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(vec_into_raw_parts)]
Expand Down
31 changes: 30 additions & 1 deletion crates/prelude/src/rng.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,41 @@

//! Provides API for random number generation.
use alloc::boxed::Box;
use core::mem::MaybeUninit;

use wasefire_applet_api::rng as api;

use crate::{Error, convert_unit};

/// Returns a slice of random bytes.
pub fn bytes(len: usize) -> Result<Box<[u8]>, Error> {
let mut buf = Box::new_uninit_slice(len);
fill_uninit_bytes(&mut buf)?;
// SAFETY: `fill_uninit_bytes()` only succeeds if all bytes are initialized.
Ok(unsafe { buf.assume_init() })
}

/// Returns an array of random bytes.
pub fn bytes_array<const N: usize>() -> Result<[u8; N], Error> {
let mut buf = MaybeUninit::uninit_array();
fill_uninit_bytes(&mut buf)?;
// SAFETY: `fill_uninit_bytes()` only succeeds if all bytes are initialized.
Ok(unsafe { MaybeUninit::array_assume_init(buf) })
}

/// Fills a slice with random bytes.
///
/// Prefer [`bytes()`] if you don't already have an allocation.
pub fn fill_bytes(buf: &mut [u8]) -> Result<(), Error> {
let params = api::fill_bytes::Params { ptr: buf.as_mut_ptr(), len: buf.len() };
// SAFETY: `fill_uninit_bytes()` only writes initialized bytes.
let buf = unsafe {
core::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut MaybeUninit<u8>, buf.len())
};
fill_uninit_bytes(buf)
}

fn fill_uninit_bytes(buf: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
let params = api::fill_bytes::Params { ptr: buf.as_mut_ptr() as *mut u8, len: buf.len() };
convert_unit(unsafe { api::fill_bytes(params) })
}
3 changes: 1 addition & 2 deletions examples/rust/ec_test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,7 @@ fn test_ecdsa_random<C: Curve>(name: &str) {
let mut rs = Vec::new();
for _ in 0 .. 5 {
let d = EcdsaPrivate::<C>::random().unwrap();
let mut m = vec![0; 257];
rng::fill_bytes(&mut m).unwrap();
let mut m = rng::bytes(257).unwrap().into_vec();
m.truncate(m[256] as usize);
let s = d.sign(&m).unwrap();
debug!("- {:02x?}{:02x?} ({} bytes message)", &s.r()[.. 4], &s.s()[.. 4], m.len());
Expand Down
3 changes: 1 addition & 2 deletions examples/rust/hsm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ fn main() {
fn process(request: Request) -> Result<Response, Error> {
match request {
Request::GenerateKey { key } => {
let mut secret = [0; 16];
rng::fill_bytes(&mut secret).map_err(|_| Error::RngError)?;
let secret = rng::bytes_array::<16>().map_err(|_| Error::RngError)?;
store::insert(key, &secret).map_err(|_| Error::StoreError)?;
Ok(Response::GenerateKey)
}
Expand Down
7 changes: 3 additions & 4 deletions examples/rust/memory_game/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
#![no_std]
wasefire::applet!();

use alloc::format;
use alloc::rc::Rc;
use alloc::string::String;
use alloc::{format, vec};
use core::cell::Cell;
use core::time::Duration;

Expand All @@ -43,13 +43,12 @@ fn main() {
while serial::read_byte(&UsbSerial).unwrap() != 0x0d {}

// Generate a question for this level.
let mut question = vec![0; level];
rng::fill_bytes(&mut question).unwrap();
let mut question = rng::bytes(level).unwrap();
for byte in &mut question {
const BASE32: [u8; 32] = *b"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
*byte = BASE32[(*byte & 0x1f) as usize];
}
let mut question = String::from_utf8(question).unwrap();
let mut question = String::from_utf8(question.into()).unwrap();

// Display the question.
process(3, "Memorize this", &mut question, |_, x| x == 0x0d);
Expand Down
5 changes: 1 addition & 4 deletions examples/rust/oom/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@
#![no_std]
wasefire::applet!();

use alloc::vec;

fn main() {
let mut data = vec![0; 100000];
rng::fill_bytes(&mut data).unwrap();
let data = rng::bytes(100000).unwrap();
store::insert(0, &data).unwrap();
}
5 changes: 2 additions & 3 deletions examples/rust/rand/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#![no_std]
wasefire::applet!();

use alloc::{format, vec};
use alloc::format;

use wasefire::usb::serial::UsbSerial;

Expand All @@ -32,8 +32,7 @@ fn main() {
b'0' => 10,
_ => continue,
};
let mut buf = vec![0; len as usize];
rng::fill_bytes(&mut buf).unwrap();
let buf = rng::bytes(len as usize).unwrap();
serial::write_all(&UsbSerial, format!("{buf:02x?}\r\n").as_bytes()).unwrap();
}
}

0 comments on commit 43eb5e1

Please sign in to comment.