esp_hal/rng.rs
1//! # Random Number Generator (RNG)
2//!
3//! ## Overview
4//! The Random Number Generator (RNG) module provides an interface to generate
5//! random numbers using the RNG peripheral on ESP chips. This driver allows you
6//! to generate random numbers that can be used for various cryptographic,
7//! security, or general-purpose applications.
8//!
9//! There are certain pre-conditions which must be met in order for the RNG to
10//! produce *true* random numbers. The hardware RNG produces true random numbers
11//! under any of the following conditions:
12//!
13//! - RF subsystem is enabled (i.e. Wi-Fi or Bluetooth are enabled).
14//! - An internal entropy source has been enabled by calling
15//! `bootloader_random_enable()` and not yet disabled by calling
16//! `bootloader_random_disable()`.
17//! - While the ESP-IDF Second stage bootloader is running. This is because the
18//! default ESP-IDF bootloader implementation calls
19//! `bootloader_random_enable()` when the bootloader starts, and
20//! `bootloader_random_disable()` before executing the app.
21//!
22//! When any of these conditions are true, samples of physical noise are
23//! continuously mixed into the internal hardware RNG state to provide entropy.
24//! If none of the above conditions are true, the output of the RNG should be
25//! considered pseudo-random only.
26//!
27//! For more information, please refer to the
28#, "/api-reference/system/random.html)")]
29//! ## Configuration
30//! To use the [Rng] Driver, you need to initialize it with the RNG peripheral.
31//! Once initialized, you can generate random numbers by calling the `random`
32//! method, which returns a 32-bit unsigned integer.
33//!
34//! ## Usage
35//! The driver implements the traits from the [`rand_core`] crate.
36//!
37//! [`rand_core`]: https://crates.io/crates/rand_core
38//!
39//! ## Examples
40//!
41//! ### Basic RNG operation
42//!
43//! ```rust, no_run
44#![doc = crate::before_snippet!()]
45//! # use esp_hal::rng::Rng;
46//!
47//! let mut rng = Rng::new(peripherals.RNG);
48//!
49//! // Generate a random word (u32):
50//! let rand_word = rng.random();
51//!
52//! // Fill a buffer with random bytes:
53//! let mut buf = [0u8; 16];
54//! rng.read(&mut buf);
55//!
56//! loop {}
57//! # }
58//! ```
59//!
60//! ### TRNG operation
61//! ```rust, no_run
62#![doc = crate::before_snippet!()]
63//! # use esp_hal::Blocking;
64//! # use esp_hal::rng::Trng;
65//! # use esp_hal::peripherals::Peripherals;
66//! # use esp_hal::peripherals::ADC1;
67//! # use esp_hal::analog::adc::{AdcConfig, Attenuation, Adc};
68//!
69//! let mut buf = [0u8; 16];
70//!
71//! // ADC is not available from now
72//! let mut trng = Trng::new(peripherals.RNG, peripherals.ADC1.reborrow());
73//! trng.read(&mut buf);
74//! let mut true_rand = trng.random();
75//! let mut rng = trng.downgrade();
76//! // ADC is available now
77#![cfg_attr(esp32, doc = "let analog_pin = peripherals.GPIO32;")]
78#![cfg_attr(not(esp32), doc = "let analog_pin = peripherals.GPIO3;")]
79//! let mut adc1_config = AdcConfig::new();
80//! let mut adc1_pin = adc1_config.enable_pin(
81//! analog_pin,
82//! Attenuation::_11dB
83//! );
84//! let mut adc1 = Adc::<ADC1, Blocking>::new(peripherals.ADC1, adc1_config);
85//! let pin_value: u16 = nb::block!(adc1.read_oneshot(&mut adc1_pin))?;
86//! rng.read(&mut buf);
87//! true_rand = rng.random();
88//! let pin_value: u16 = nb::block!(adc1.read_oneshot(&mut adc1_pin))?;
89//! # Ok(())
90//! # }
91//! ```
92
93use crate::{
94 peripherals::{ADC1, RNG},
95 private::Sealed,
96};
97
98/// Random number generator driver
99#[derive(Clone, Copy)]
100#[non_exhaustive]
101pub struct Rng;
102
103impl Rng {
104 /// Create a new random number generator instance
105 pub fn new(_rng: RNG<'_>) -> Self {
106 Self
107 }
108
109 #[inline]
110 /// Reads currently available `u32` integer from `RNG`
111 pub fn random(&mut self) -> u32 {
112 // SAFETY: read-only register access
113 RNG::regs().data().read().bits()
114 }
115
116 #[inline]
117 /// Reads enough bytes from hardware random number generator to fill
118 /// `buffer`.
119 ///
120 /// If any error is encountered then this function immediately returns. The
121 /// contents of buf are unspecified in this case.
122 ///
123 /// If this function returns an error, it is unspecified how many bytes it
124 /// has read, but it will never read more than would be necessary to
125 /// completely fill the buffer.
126 pub fn read(&mut self, buffer: &mut [u8]) {
127 for chunk in buffer.chunks_mut(4) {
128 let bytes = self.random().to_le_bytes();
129 chunk.copy_from_slice(&bytes[..chunk.len()]);
130 }
131 }
132}
133
134impl Sealed for Rng {}
135
136#[instability::unstable]
137impl rand_core_06::RngCore for Rng {
138 fn next_u32(&mut self) -> u32 {
139 self.random()
140 }
141
142 fn next_u64(&mut self) -> u64 {
143 let upper = self.random() as u64;
144 let lower = self.random() as u64;
145
146 (upper << 32) | lower
147 }
148
149 fn fill_bytes(&mut self, dest: &mut [u8]) {
150 self.read(dest);
151 }
152
153 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> {
154 self.read(dest);
155 Ok(())
156 }
157}
158
159#[instability::unstable]
160impl rand_core_09::RngCore for Rng {
161 fn next_u32(&mut self) -> u32 {
162 self.random()
163 }
164 fn next_u64(&mut self) -> u64 {
165 let upper = self.random() as u64;
166 let lower = self.random() as u64;
167
168 (upper << 32) | lower
169 }
170 fn fill_bytes(&mut self, dest: &mut [u8]) {
171 self.read(dest);
172 }
173}
174
175/// True Random Number Generator (TRNG) driver
176///
177/// The `Trng` struct represents a true random number generator that combines
178/// the randomness from the hardware RNG and an ADC. This struct provides
179/// methods to generate random numbers and fill buffers with random bytes.
180/// Due to pulling the entropy source from the ADC, it uses the associated
181/// registers, so to use TRNG we need to "occupy" the ADC peripheral.
182pub struct Trng<'d> {
183 /// The hardware random number generator instance.
184 pub rng: Rng,
185 /// A mutable reference to the ADC1 instance.
186 _adc: ADC1<'d>,
187}
188
189impl<'d> Trng<'d> {
190 /// Creates a new True Random Number Generator (TRNG) instance.
191 ///
192 /// # Arguments
193 ///
194 /// * `rng` - A peripheral instance implementing the `RNG` trait.
195 /// * `adc` - A mutable reference to an `Adc` instance.
196 ///
197 /// # Returns
198 ///
199 /// Returns a new `Trng` instance.
200 pub fn new(rng: RNG<'_>, adc: ADC1<'d>) -> Self {
201 let r#gen = Rng::new(rng);
202 crate::soc::trng::ensure_randomness();
203 Self {
204 rng: r#gen,
205 _adc: adc,
206 }
207 }
208
209 /// Reads currently available `u32` integer from `TRNG`
210 pub fn random(&mut self) -> u32 {
211 self.rng.random()
212 }
213
214 /// Fills the provided buffer with random bytes.
215 pub fn read(&mut self, buffer: &mut [u8]) {
216 self.rng.read(buffer);
217 }
218
219 /// Downgrades the `Trng` instance to a `Rng` instance and releases the
220 /// ADC1.
221 pub fn downgrade(self) -> Rng {
222 self.rng
223 }
224}
225
226impl Drop for Trng<'_> {
227 fn drop(&mut self) {
228 crate::soc::trng::revert_trng();
229 }
230}
231
232/// Implementing RngCore trait from rand_core for `Trng` structure
233#[instability::unstable]
234impl rand_core_06::RngCore for Trng<'_> {
235 fn next_u32(&mut self) -> u32 {
236 self.rng.next_u32()
237 }
238
239 fn next_u64(&mut self) -> u64 {
240 self.rng.next_u64()
241 }
242
243 fn fill_bytes(&mut self, dest: &mut [u8]) {
244 self.rng.fill_bytes(dest)
245 }
246
247 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> {
248 self.rng.try_fill_bytes(dest)
249 }
250}
251
252#[instability::unstable]
253impl rand_core_09::RngCore for Trng<'_> {
254 fn next_u32(&mut self) -> u32 {
255 self.rng.next_u32()
256 }
257 fn next_u64(&mut self) -> u64 {
258 self.rng.next_u64()
259 }
260 fn fill_bytes(&mut self, dest: &mut [u8]) {
261 self.rng.fill_bytes(dest)
262 }
263}
264
265/// Implementing a CryptoRng marker trait that indicates that the generator is
266/// cryptographically secure.
267#[instability::unstable]
268impl rand_core_06::CryptoRng for Trng<'_> {}
269#[instability::unstable]
270impl rand_core_09::CryptoRng for Trng<'_> {}
271
272impl Sealed for Trng<'_> {}