wasmtime_wasi/
random.rs

1use cap_rand::{Rng as _, RngCore, SeedableRng as _};
2use wasmtime::component::HasData;
3
4pub(crate) struct WasiRandom;
5
6impl HasData for WasiRandom {
7    type Data<'a> = &'a mut WasiRandomCtx;
8}
9
10pub struct WasiRandomCtx {
11    pub random: Box<dyn RngCore + Send>,
12    pub insecure_random: Box<dyn RngCore + Send>,
13    pub insecure_random_seed: u128,
14}
15
16impl Default for WasiRandomCtx {
17    fn default() -> Self {
18        // For the insecure random API, use `SmallRng`, which is fast. It's
19        // also insecure, but that's the deal here.
20        let insecure_random = Box::new(
21            cap_rand::rngs::SmallRng::from_rng(cap_rand::thread_rng(cap_rand::ambient_authority()))
22                .unwrap(),
23        );
24        // For the insecure random seed, use a `u128` generated from
25        // `thread_rng()`, so that it's not guessable from the insecure_random
26        // API.
27        let insecure_random_seed =
28            cap_rand::thread_rng(cap_rand::ambient_authority()).r#gen::<u128>();
29        Self {
30            random: thread_rng(),
31            insecure_random,
32            insecure_random_seed,
33        }
34    }
35}
36
37pub trait WasiRandomView: Send {
38    fn random(&mut self) -> &mut WasiRandomCtx;
39}
40
41impl WasiRandomView for WasiRandomCtx {
42    fn random(&mut self) -> &mut WasiRandomCtx {
43        self
44    }
45}
46
47/// Implement `insecure-random` using a deterministic cycle of bytes.
48pub struct Deterministic {
49    cycle: std::iter::Cycle<std::vec::IntoIter<u8>>,
50}
51
52impl Deterministic {
53    pub fn new(bytes: Vec<u8>) -> Self {
54        Deterministic {
55            cycle: bytes.into_iter().cycle(),
56        }
57    }
58}
59
60impl RngCore for Deterministic {
61    fn next_u32(&mut self) -> u32 {
62        let b0 = self.cycle.next().expect("infinite sequence");
63        let b1 = self.cycle.next().expect("infinite sequence");
64        let b2 = self.cycle.next().expect("infinite sequence");
65        let b3 = self.cycle.next().expect("infinite sequence");
66        ((b0 as u32) << 24) + ((b1 as u32) << 16) + ((b2 as u32) << 8) + (b3 as u32)
67    }
68    fn next_u64(&mut self) -> u64 {
69        let w0 = self.next_u32();
70        let w1 = self.next_u32();
71        ((w0 as u64) << 32) + (w1 as u64)
72    }
73    fn fill_bytes(&mut self, buf: &mut [u8]) {
74        for b in buf.iter_mut() {
75            *b = self.cycle.next().expect("infinite sequence");
76        }
77    }
78    fn try_fill_bytes(&mut self, buf: &mut [u8]) -> Result<(), cap_rand::Error> {
79        self.fill_bytes(buf);
80        Ok(())
81    }
82}
83
84#[cfg(test)]
85mod test {
86    use super::*;
87    #[test]
88    fn deterministic() {
89        let mut det = Deterministic::new(vec![1, 2, 3, 4]);
90        let mut buf = vec![0; 1024];
91        det.try_fill_bytes(&mut buf).expect("get randomness");
92        for (ix, b) in buf.iter().enumerate() {
93            assert_eq!(*b, (ix % 4) as u8 + 1)
94        }
95    }
96}
97
98pub fn thread_rng() -> Box<dyn RngCore + Send> {
99    use cap_rand::{Rng, SeedableRng};
100    let mut rng = cap_rand::thread_rng(cap_rand::ambient_authority());
101    Box::new(cap_rand::rngs::StdRng::from_seed(rng.r#gen()))
102}