Module rng

Module rng 

Source
Available on crate feature unstable only.
Expand description

§Random Number Generator (RNG)

§Overview

The Random Number Generator (RNG) module provides an interface to generate random numbers using the RNG peripheral on ESP chips. This driver allows you to generate random numbers that can be used for various cryptographic, security, or general-purpose applications.

There are certain pre-conditions which must be met in order for the RNG to produce true random numbers. The hardware RNG produces true random numbers under any of the following conditions:

  • RF subsystem is enabled (i.e. Wi-Fi or Bluetooth are enabled).
  • An ADC is used to generate entropy.
  • An internal entropy source has been enabled by calling bootloader_random_enable() and not yet disabled by calling bootloader_random_disable(). As the default bootloader calls bootloader_random_disable() automatically, this option requires a custom bootloader build.

When any of these conditions are true, samples of physical noise are continuously mixed into the internal hardware RNG state to provide entropy. If none of the above conditions are true, the output of the RNG should be considered pseudo-random only.

Note that, when the Wi-Fi module is enabled, the value read from the high-speed ADC can be saturated in some extreme cases, which lowers the entropy. Thus, it is advisable to also enable the SAR ADC as the noise source for the random number generator for such cases.

For more information, please refer to the ESP-IDF documentation

§Configuration

To generate pseudo-random numbers, you can create Rng at any time. To generate true random numbers, you need to create an instance of TrngSource. Once you’ve done that, you can create Trng instances at any time, as long as the TrngSource is alive.

§Compatibility with rand_core

The Rng and Trng drivers implement the relevant traits from versions 0.6 and 0.9 of the rand_core crate.

§Compatibility with getrandom

The driver can be used to implement a custom backend for getrandom.

§Example

The following example demonstrates how to set up a custom backend using getrandom v0.3.3:

use getrandom::Error;

#[no_mangle]
unsafe extern "Rust" fn __getrandom_v03_custom(
    dest: *mut u8,
    len: usize,
) -> Result<(), Error> {
    unsafe { esp_hal::rng:Rng::new().read_into_raw() };
    Ok(())
}

§Examples

§Basic RNG operation


let rng = Rng::new();

// Generate a random word (u32):
let rand_word = rng.random();

// Fill a buffer with random bytes:
let mut buf = [0u8; 16];
rng.read(&mut buf);

loop {}

§TRNG operation

use esp_hal::rng::{Trng, TrngSource};

let mut buf = [0u8; 16];

// ADC is not available from now
let trng_source = TrngSource::new(peripherals.RNG, peripherals.ADC1.reborrow());

let trng = Trng::try_new().unwrap(); // Unwrap is safe as we have enabled TrngSource.

// Generate true random numbers
trng.read(&mut buf);
let true_random_number = trng.random();

// Downgrade to Rng to allow disabling the TrngSource
let rng = trng.downgrade();

// Drop the true random number source. ADC is available now.
core::mem::drop(trng_source);

let analog_pin = peripherals.GPIO3;

let mut adc1_config = AdcConfig::new();
let mut adc1_pin = adc1_config.enable_pin(analog_pin, Attenuation::_11dB);
let mut adc1 = Adc::<ADC1, Blocking>::new(peripherals.ADC1, adc1_config);
let pin_value: u16 = nb::block!(adc1.read_oneshot(&mut adc1_pin))?;

// Now we can only generate pseudo-random numbers...
rng.read(&mut buf);
let pseudo_random_number = rng.random();

// ... but the ADC is available for use.
let pin_value: u16 = nb::block!(adc1.read_oneshot(&mut adc1_pin))?;

Structs§

Rng
(Pseudo-)Random Number Generator
Trng
True Random Number Generator (TRNG)
TrngSource
Ensures random numbers are cryptographically secure.

Enums§

TrngError
Errors returned when constructing a Trng.