kernel/hil/entropy.rs
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 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
// 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 an entropy source.
//!
//! An entropy source produces random bits that are computationally
//! intractable to guess, even if the complete history of generated
//! bits and state of the device can be observed. Entropy sources must
//! generate bits from an underlying physical random process, such as
//! thermal noise, radiation, avalanche noise, or circuit
//! instability. These bits of entropy can be used to seed
//! cryptographically strong random number generators. Because high-quality
//! entropy is critical for security and these APIs provide entropy,
//! it is important to understand all of these requirements before
//! implementing these traits. Otherwise you may subvert the security
//! of the operating system.
//!
//! _Entropy_: Entropy bits generated by this trait MUST have very high
//! entropy, i.e. 1 bit of entropy per generated bit. If the underlying
//! source generates <1 bit of entropy per bit, these low-entropy bits
//! SHOULD be mixed and combined with a cryptographic hash function.
//! A good, short reference on the difference between entropy and
//! randomness as well as guidelines for high-entropy sources is
//! Recommendations for Randomness in the Operating System: How to
//! Keep Evil Children Out of Your Pool and Other Random Facts,
//! Corrigan-Gibbs et al., HotOS 2015.
//!
//! The interface is designed to work well with entropy generators
//! that may not have values ready immediately. This is important when
//! generating numbers from a low-bandwidth hardware entropy source
//! generator or when virtualized among many consumers.
//!
//! Entropy is yielded to a Client as an `Iterator` which only
//! terminates when no more entropy is currently available. Clients
//! can request more entropy if needed and will be called again when
//! more is available.
//!
//! # Example
//!
//! The following example is a simple capsule that prints out entropy
//! once a second using the `Alarm` and `Entropy` traits.
//!
//! ```
//! use kernel::hil;
//! use kernel::hil::entropy::Entropy32;
//! use kernel::hil::entropy::Client32;
//! use kernel::hil::time::Alarm;
//! use kernel::hil::time::ConvertTicks;
//! use kernel::hil::time::Frequency;
//! use kernel::hil::time::AlarmClient;
//! use kernel::ErrorCode;
//!
//! struct EntropyTest<'a, A: 'a + Alarm<'a>> {
//! entropy: &'a dyn Entropy32 <'a>,
//! alarm: &'a A
//! }
//!
//! impl<'a, A: Alarm<'a>> EntropyTest<'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: Alarm<'a>> AlarmClient for EntropyTest<'a, A> {
//! fn alarm(&self) {
//! self.entropy.get();
//! }
//! }
//!
//! impl<'a, A: Alarm<'a>> Client32 for EntropyTest<'a, A> {
//! fn entropy_available(&self,
//! entropy: &mut dyn Iterator<Item = u32>,
//! error: Result<(), ErrorCode>) -> hil::entropy::Continue {
//! match entropy.next() {
//! Some(val) => {
//! println!("Entropy {}", val);
//! let now = self.alarm.now();
//! let dt = self.alarm.ticks_from_seconds(1);
//! self.alarm.set_alarm(now, dt);
//! hil::entropy::Continue::Done
//! },
//! None => hil::entropy::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 entropy source.
///
/// Implementors should assume the client implements the
/// [Client](trait.Client32.html) trait.
pub trait Entropy32<'a> {
/// Initiate the acquisition of entropy.
///
/// There are three valid return values:
/// - Ok(()): a `entropy_available` callback will be called in
/// the future when entropy is available.
/// - FAIL: a `entropy_available` callback will not be called in
/// the future, because entropy cannot be generated. This
/// is a general failure condition.
/// - OFF: a `entropy_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 entropy.
///
/// There are three valid return values:
/// - Ok(()): an outstanding request from `get` has been cancelled,
/// or there was no outstanding request. No `entropy_available`
/// callback will be issued.
/// - FAIL: There will be a `entropy_available` callback, which
/// may or may not return an error code.
fn cancel(&self) -> Result<(), ErrorCode>;
/// Set the client to receive `entropy_available` callbacks.
fn set_client(&'a self, _: &'a dyn Client32);
}
/// An [Entropy32](trait.Entropy32.html) client
///
/// Clients of an [Entropy32](trait.Entropy32.html) must implement this trait.
pub trait Client32 {
/// Called by the (Entropy)[trait.Entropy32.html] when there is entropy
/// available.
///
/// `entropy` in an `Iterator` of available entropy. The amount of
/// entropy available may increase if `entropy` is not consumed
/// quickly so clients should not rely on iterator termination to
/// finish consuming entropy.
///
/// The client returns either `Continue::More` if the iterator did
/// not have enough entropy (indicating another
/// `entropy_available` callback is requested) and the client
/// would like to be called again when more is available, or
/// `Continue::Done`, which indicates `entropy_available` should
/// not be called again until `get()` is called.
///
/// If `entropy_available` is triggered after a call to `cancel()`
/// then error MUST be CANCEL and `entropy` MAY contain bits of
/// entropy.
fn entropy_available(
&self,
entropy: &mut dyn Iterator<Item = u32>,
error: Result<(), ErrorCode>,
) -> Continue;
}
/// An 8-bit entropy generator.
///
/// Implementors should assume the client implements the
/// [Client8](trait.Client8.html) trait.
pub trait Entropy8<'a> {
/// Initiate the acquisition of new entropy.
///
/// There are three valid return values:
/// - Ok(()): a `entropy_available` callback will be called in
/// the future when entropy is available.
/// - FAIL: a `entropy_available` callback will not be called in
/// the future, because entropy cannot be generated. This
/// is a general failure condition.
/// - OFF: a `entropy_available` callback will not be called in
/// the future, because the entropy generator is off/not
/// powered.
fn get(&self) -> Result<(), ErrorCode>;
/// Cancel acquisition of entropy.
///
/// There are three valid return values:
/// - Ok(()): an outstanding request from `get` has been cancelled,
/// or there was no outstanding request. No `entropy_available`
/// callback will be issued.
/// - FAIL:: There will be a `entropy_available` callback, which
/// may or may not return an error code.
fn cancel(&self) -> Result<(), ErrorCode>;
/// Set the client to receive `entropy_available` callbacks.
fn set_client(&'a self, _: &'a dyn Client8);
}
/// An [Entropy8](trait.Entropy8.html) client
///
/// Clients of an [Entropy8](trait.Entropy8.html) must implement this trait.
pub trait Client8 {
/// Called by the (Entropy)[trait.Entropy8.html] when there are
/// one or more bytes of entropy available.
///
/// `entropy` in an `Iterator` of available entropy. The amount of
/// entropy available may increase if `entropy` is not consumed
/// quickly so clients should not rely on iterator termination to
/// finish consuming entropy.
///
/// The client returns either `Continue::More` if the iterator did
/// not have enough entropy (indicating another
/// `entropy_available` callback is requested) and the client
/// would like to be called again when more is available, or
/// `Continue::Done`, which indicates `entropy_available` should
/// not be called again until `get()` is called.
///
/// If `entropy_available` is triggered after a call to `cancel()`
/// then error MUST be CANCEL and `entropy` MAY contain bits of
/// entropy.
fn entropy_available(
&self,
entropy: &mut dyn Iterator<Item = u8>,
error: Result<(), ErrorCode>,
) -> Continue;
}