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::soc::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, &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}