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#![doc = concat!("[ESP-IDF documentation](https://docs.espressif.com/projects/esp-idf/en/latest/", crate::chip!(), "/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<'_> {}