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;
}