1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

//! Interfaces for accessing a random number generator.
//!
//! A random number generator produces a stream of random numbers,
//! either from hardware or based on an initial seed. The
//! [RNG](trait.RNG.html) trait provides a simple, implementation
//! agnostic interface for getting new random values.
//!
//! _Randomness_: Random numbers generated by this trait MUST pass
//! standard randomness tests, such as A. Rukhin, J. Soto,
//! J. Nechvatal, M. Smid, E. Barker, S. Leigh, M. Levenson,
//! M. Vangel, D. Banks, A. Heckert, J. Dray, and S. Vo. A statistical
//! test suite for random and pseudorandom number generators for
//! cryptographic applications. Technical report, NIST, 2010. It is
//! acceptable for implementations to rely on prior verification of
//! the algorithm being used. For example, if the implementation
//! chooses to use a Fishman and Moore Linear Congruence Generator
//! (LCG) with the parameters specified in the NIST report above, it
//! does not need to re-run the tests.
//!
//! Entropy: This trait does not promise high-entropy random numbers,
//! although it MAY generate them. Implementations of this interface
//! MAY generate random numbers using techniques other than true
//! random number generation (through entropy) or cryptographically
//! secure pseudorandom number generation. Other traits, described
//! elsewhere, provide random numbers with entropy guarantees. This
//! trait MUST NOT be used for randomness needed for security or
//! cryptography. If high-entropy randomness is needed, the `Entropy`
//! trait should be used instead.
//!
//! The Rng trait is designed to work well with random number
//! generators that may not have values ready immediately. This is
//! important when generating numbers from a low-bandwidth hardware
//! random number generator or when the RNG is virtualized among many
//! consumers.  Random numbers are yielded to the
//! [Client](trait.Client.html) as an `Iterator` which only terminates
//! when no more numbers are currently available. Clients can request
//! more randomness if needed and will be called again when more is
//! available.
//!
//! The Random trait is synchronous, so designed to work
//! with arithmetically simple random number generators that can
//! return a result quickly.
//!
//!
//! # Example
//!
//! The following example is a simple capsule that prints out a random number
//! once a second using the `Alarm` and `RNG` traits.
//!
//! ```
//! use kernel::hil;
//! use kernel::hil::time::ConvertTicks;
//! use kernel::hil::time::Frequency;
//! use kernel::hil::time::Time;
//! use kernel::ErrorCode;
//!
//! struct RngTest<'a, A: 'a + hil::time::Alarm<'a>> {
//!     rng: &'a dyn hil::rng::Rng<'a>,
//!     alarm: &'a A
//! }
//!
//! impl<'a, A: hil::time::Alarm<'a>> RngTest<'a, A> {
//!     pub fn initialize(&self) {
//!         let now = self.alarm.now();
//!         let dt = self.alarm.ticks_from_seconds(1);
//!         self.alarm.set_alarm(now, dt);
//!     }
//! }
//!
//! impl<'a, A: hil::time::Alarm<'a>> hil::time::AlarmClient for RngTest<'a, A> {
//!     fn alarm(&self) {
//!         self.rng.get();
//!     }
//! }
//!
//! impl<'a, A: hil::time::Alarm<'a>> hil::rng::Client for RngTest<'a, A> {
//!     fn randomness_available(&self,
//!                             randomness: &mut dyn Iterator<Item = u32>,
//!                             error: Result<(), ErrorCode>) -> hil::rng::Continue {
//!         match randomness.next() {
//!             Some(random) => {
//!                 println!("Rand {}", random);
//!                 let now = self.alarm.now();
//!                 let dt = self.alarm.ticks_from_seconds(1);
//!
//!                 self.alarm.set_alarm(now, dt);
//!                 hil::rng::Continue::Done
//!             },
//!             None => hil::rng::Continue::More
//!         }
//!     }
//! }
//! ```

use crate::ErrorCode;

/// Denotes whether the [Client](trait.Client.html) wants to be notified when
/// `More` randomness is available or if they are `Done`
#[derive(Debug, Eq, PartialEq)]
pub enum Continue {
    /// More randomness is required.
    More,
    /// No more randomness required.
    Done,
}

/// Generic interface for a 32-bit random number generator.
///
/// Implementors should assume the client implements the
/// [Client](trait.Client.html) trait.
pub trait Rng<'a> {
    /// Initiate the aquisition of new random number generation.
    ///
    /// There are three valid return values:
    ///   - Ok(()): a `randomness_available` callback will be called in
    ///     the future when randomness is available.
    ///   - FAIL: a `randomness_available` callback will not be called in
    ///     the future, because random numbers cannot be generated. This
    ///     is a general failure condition.
    ///   - OFF: a `randomness_available` callback will not be called in
    ///     the future, because the random number generator is off/not
    ///     powered.
    fn get(&self) -> Result<(), ErrorCode>;

    /// Cancel acquisition of random numbers.
    ///
    /// There are two valid return values:
    ///   - Ok(()): an outstanding request from `get` has been cancelled,
    ///     or there was no oustanding request. No `randomness_available`
    ///     callback will be issued.
    ///   - FAIL: There will be a randomness_available callback, which
    ///     may or may not return an error code.
    fn cancel(&self) -> Result<(), ErrorCode>;
    fn set_client(&'a self, _: &'a dyn Client);
}

/// An [Rng](trait.Rng.html) client
///
/// Clients of an [Rng](trait.Rng.html) must implement this trait.
pub trait Client {
    /// Called by the (RNG)[trait.RNG.html] when there are one or more random
    /// numbers available
    ///
    /// `randomness` in an `Iterator` of available random numbers. The amount of
    /// randomness available may increase if `randomness` is not consumed
    /// quickly so clients should not rely on iterator termination to finish
    /// consuming random numbers.
    ///
    /// The client returns either `Continue::More` if the iterator did not have
    /// enough random values and the client would like to be called again when
    /// more is available, or `Continue::Done`.
    ///
    /// If randoness_available is triggered after a call to cancel()
    /// then error MUST be CANCEL and randomness MAY contain
    /// random bits.
    fn randomness_available(
        &self,
        randomness: &mut dyn Iterator<Item = u32>,
        error: Result<(), ErrorCode>,
    ) -> Continue;
}

/// Generic interface for a synchronous 32-bit random number
/// generator.

pub trait Random<'a> {
    /// Initialize/reseed the random number generator from an
    /// internal source. This initialization MAY be deterministic
    /// (e.g., based on an EUI-64) or MAY be random (e.g., based on an
    /// underlying hardware entropy source); an implementation SHOULD
    /// make reseeding random.
    fn initialize(&'a self);

    /// Reseed the random number generator with a specific
    /// seed. Useful for deterministic tests.
    fn reseed(&self, seed: u32);

    /// Generate a 32-bit random number.
    fn random(&self) -> u32;
}