components/
rng.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Component for random number generator.
6//!
7//! `RngComponent`
8//! --------------
9//!
10//! `RngComponent` implements a userspace syscall interface to the RNG
11//! peripheral (TRNG) using `Entropy32ToRandom`.
12//!
13//! ### Usage
14//! ```rust
15//! let rng = components::rng::RngComponent::new(board_kernel, capsules_core::rng::DRIVER_NUM, rng)
16//!     .finalize(rng_component_static!(nrf52840::trng::Trng));
17//! ```
18//!
19//! `RngRandomComponent`
20//! --------------------
21//!
22//! `RngRandomComponent` implements a userspace syscall interface to an RNG.
23//!
24//! ### Usage
25//! ```rust
26//! let rng = components::rng::RngRandomComponent::new(board_kernel, capsules_core::rng::DRIVER_NUM, rng)
27//!     .finalize(rng_random_component_static!(qemu_rv32_virt_chip::virtio::devices::virtio_rng::VirtIORng));
28//! ```
29
30// Author: Hudson Ayers <hayers@cs.stanford.edu>
31// Last modified: 07/12/2019
32
33use capsules_core::rng;
34use core::mem::MaybeUninit;
35use kernel::capabilities;
36use kernel::component::Component;
37use kernel::create_capability;
38use kernel::hil::entropy::Entropy32;
39use kernel::hil::rng::Rng;
40
41#[macro_export]
42macro_rules! rng_component_static {
43    ($E: ty $(,)?) => {{
44        let etr = kernel::static_buf!(capsules_core::rng::Entropy32ToRandom<'static, $E>);
45        let rng = kernel::static_buf!(
46            capsules_core::rng::RngDriver<
47                'static,
48                capsules_core::rng::Entropy32ToRandom<'static, $E>,
49            >
50        );
51
52        (etr, rng)
53    };};
54}
55
56pub type RngComponentType<E> =
57    rng::RngDriver<'static, capsules_core::rng::Entropy32ToRandom<'static, E>>;
58
59pub struct RngComponent<E: Entropy32<'static> + 'static> {
60    board_kernel: &'static kernel::Kernel,
61    driver_num: usize,
62    trng: &'static E,
63}
64
65impl<E: Entropy32<'static>> RngComponent<E> {
66    pub fn new(board_kernel: &'static kernel::Kernel, driver_num: usize, trng: &'static E) -> Self {
67        Self {
68            board_kernel,
69            driver_num,
70            trng,
71        }
72    }
73}
74
75impl<E: Entropy32<'static>> Component for RngComponent<E> {
76    type StaticInput = (
77        &'static mut MaybeUninit<capsules_core::rng::Entropy32ToRandom<'static, E>>,
78        &'static mut MaybeUninit<
79            capsules_core::rng::RngDriver<
80                'static,
81                capsules_core::rng::Entropy32ToRandom<'static, E>,
82            >,
83        >,
84    );
85    type Output =
86        &'static rng::RngDriver<'static, capsules_core::rng::Entropy32ToRandom<'static, E>>;
87
88    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
89        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
90
91        let entropy_to_random = static_buffer
92            .0
93            .write(rng::Entropy32ToRandom::new(self.trng));
94        let rng = static_buffer.1.write(rng::RngDriver::new(
95            entropy_to_random,
96            self.board_kernel.create_grant(self.driver_num, &grant_cap),
97        ));
98        self.trng.set_client(entropy_to_random);
99        entropy_to_random.set_client(rng);
100
101        rng
102    }
103}
104
105#[macro_export]
106macro_rules! rng_random_component_static {
107    ($R: ty $(,)?) => {{
108        let rng = kernel::static_buf!(capsules_core::rng::RngDriver<'static, $R>);
109
110        rng
111    };};
112}
113
114pub type RngRandomComponentType<R> = rng::RngDriver<'static, R>;
115
116pub struct RngRandomComponent<R: Rng<'static> + 'static> {
117    board_kernel: &'static kernel::Kernel,
118    driver_num: usize,
119    rng: &'static R,
120}
121
122impl<R: Rng<'static>> RngRandomComponent<R> {
123    pub fn new(board_kernel: &'static kernel::Kernel, driver_num: usize, rng: &'static R) -> Self {
124        Self {
125            board_kernel,
126            driver_num,
127            rng,
128        }
129    }
130}
131
132impl<R: Rng<'static>> Component for RngRandomComponent<R> {
133    type StaticInput = &'static mut MaybeUninit<capsules_core::rng::RngDriver<'static, R>>;
134    type Output = &'static rng::RngDriver<'static, R>;
135
136    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
137        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
138
139        let rng_driver = static_buffer.write(rng::RngDriver::new(
140            self.rng,
141            self.board_kernel.create_grant(self.driver_num, &grant_cap),
142        ));
143        self.rng.set_client(rng_driver);
144
145        rng_driver
146    }
147}