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, &mut peripherals.ADC1);
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//! ```
92use core::marker::PhantomData;
93
94use crate::{
95 peripheral::{Peripheral, PeripheralRef},
96 peripherals::{ADC1, RNG},
97 private::Sealed,
98};
99
100/// Random number generator driver
101#[derive(Clone, Copy)]
102pub struct Rng {
103 _phantom: PhantomData<RNG>,
104}
105
106impl Rng {
107 /// Create a new random number generator instance
108 pub fn new(_rng: impl Peripheral<P = RNG>) -> Self {
109 Self {
110 _phantom: PhantomData,
111 }
112 }
113
114 #[inline]
115 /// Reads currently available `u32` integer from `RNG`
116 pub fn random(&mut self) -> u32 {
117 // SAFETY: read-only register access
118 RNG::regs().data().read().bits()
119 }
120
121 #[inline]
122 /// Reads enough bytes from hardware random number generator to fill
123 /// `buffer`.
124 ///
125 /// If any error is encountered then this function immediately returns. The
126 /// contents of buf are unspecified in this case.
127 ///
128 /// If this function returns an error, it is unspecified how many bytes it
129 /// has read, but it will never read more than would be necessary to
130 /// completely fill the buffer.
131 pub fn read(&mut self, buffer: &mut [u8]) {
132 for chunk in buffer.chunks_mut(4) {
133 let bytes = self.random().to_le_bytes();
134 chunk.copy_from_slice(&bytes[..chunk.len()]);
135 }
136 }
137}
138
139impl Sealed for Rng {}
140
141impl Peripheral for Rng {
142 type P = Self;
143
144 #[inline]
145 unsafe fn clone_unchecked(&self) -> Self::P {
146 *self
147 }
148}
149
150impl rand_core::RngCore for Rng {
151 fn next_u32(&mut self) -> u32 {
152 self.random()
153 }
154
155 fn next_u64(&mut self) -> u64 {
156 let upper = self.random() as u64;
157 let lower = self.random() as u64;
158
159 (upper << 32) | lower
160 }
161
162 fn fill_bytes(&mut self, dest: &mut [u8]) {
163 self.read(dest);
164 }
165
166 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
167 self.read(dest);
168 Ok(())
169 }
170}
171
172/// True Random Number Generator (TRNG) driver
173///
174/// The `Trng` struct represents a true random number generator that combines
175/// the randomness from the hardware RNG and an ADC. This struct provides
176/// methods to generate random numbers and fill buffers with random bytes.
177/// Due to pulling the entropy source from the ADC, it uses the associated
178/// registers, so to use TRNG we need to "occupy" the ADC peripheral.
179pub struct Trng<'d> {
180 /// The hardware random number generator instance.
181 pub rng: Rng,
182 /// A mutable reference to the ADC1 instance.
183 _adc: PeripheralRef<'d, ADC1>,
184}
185
186impl<'d> Trng<'d> {
187 /// Creates a new True Random Number Generator (TRNG) instance.
188 ///
189 /// # Arguments
190 ///
191 /// * `rng` - A peripheral instance implementing the `RNG` trait.
192 /// * `adc` - A mutable reference to an `Adc` instance.
193 ///
194 /// # Returns
195 ///
196 /// Returns a new `Trng` instance.
197 pub fn new(rng: impl Peripheral<P = RNG>, adc: impl Peripheral<P = ADC1> + 'd) -> Self {
198 crate::into_ref!(adc);
199
200 let gen = Rng::new(rng);
201 crate::soc::trng::ensure_randomness();
202 Self {
203 rng: gen,
204 _adc: adc,
205 }
206 }
207
208 /// Reads currently available `u32` integer from `TRNG`
209 pub fn random(&mut self) -> u32 {
210 self.rng.random()
211 }
212
213 /// Fills the provided buffer with random bytes.
214 pub fn read(&mut self, buffer: &mut [u8]) {
215 self.rng.read(buffer);
216 }
217
218 /// Downgrades the `Trng` instance to a `Rng` instance and releases the
219 /// ADC1.
220 pub fn downgrade(self) -> Rng {
221 self.rng
222 }
223}
224
225impl Drop for Trng<'_> {
226 fn drop(&mut self) {
227 crate::soc::trng::revert_trng();
228 }
229}
230
231/// Implementing RngCore trait from rand_core for `Trng` structure
232impl rand_core::RngCore for Trng<'_> {
233 fn next_u32(&mut self) -> u32 {
234 self.rng.next_u32()
235 }
236
237 fn next_u64(&mut self) -> u64 {
238 self.rng.next_u64()
239 }
240
241 fn fill_bytes(&mut self, dest: &mut [u8]) {
242 self.rng.fill_bytes(dest)
243 }
244
245 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
246 self.rng.try_fill_bytes(dest)
247 }
248}
249
250/// Implementing a CryptoRng marker trait that indicates that the generator is
251/// cryptographically secure.
252impl rand_core::CryptoRng for Trng<'_> {}
253
254impl Sealed for Trng<'_> {}
255
256impl Peripheral for Trng<'_> {
257 type P = Self;
258
259 #[inline]
260 unsafe fn clone_unchecked(&self) -> Self::P {
261 Self {
262 rng: self.rng.clone_unchecked(),
263 _adc: self._adc.clone_unchecked(),
264 }
265 }
266}