mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-10-02 14:44:42 +00:00

* No longer publicly expose the `PeripheralClockControl` struct * Update examples as needed to get things building again * Update CHANGELOG.md * Address review feedback, fix a warning * Use a critical section for all devices other than the ESP32-C6/H2, as they modify multiple registers * Rebase and update `etm` driver to fix build errors
122 lines
4.5 KiB
Rust
122 lines
4.5 KiB
Rust
//! Demonstrates the use of the HMAC peripheral and compares the speed of
|
|
//! hardware-accelerated and pure software hashing.
|
|
//!
|
|
//! # Writing key
|
|
//! Before using the HMAC accelerator in upstream mode, you first need to
|
|
//! prepare a secret 256-bit HMAC key and burn the key to an empty eFuse block.
|
|
//!
|
|
//! ## ⚠️ Before writing ⚠️
|
|
//! - From the factory, the eFuse keyblocks are programmed to be 32-byte 0x00.
|
|
//! - This example is programmed to use this value so you can skip this step if
|
|
//! you don't want to burn an eFuse key.
|
|
//! - If you skip the skip burning a custom key, you still need to [burn the
|
|
//! purpose](#burn-key-purpose).
|
|
//! - [Read more about eFuses](https://docs.espressif.com/projects/esptool/en/latest/esp32s3/espefuse/index.html)
|
|
//!
|
|
//! ## Burn key purpose
|
|
//! You first need to burn the efuse key purpose for the specified key below
|
|
//! (Default Key0). Purposes:
|
|
//!
|
|
//! | Purpose | Mode | Value | Description |
|
|
//! |--------------------------------|------------|-------|-----------------------------------------------|
|
|
//! | JTAG Re-enable | Downstream | 6 | EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG |
|
|
//! | DS Key Derivation | Downstream | 7 | EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE |
|
|
//! | HMAC Calculation | Upstream | 8 | EFUSE_KEY_PURPOSE_HMAC_UP |
|
|
//! | Both JTAG Re-enable and DS KDF | Downstream | 5 | EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL |
|
|
//!
|
|
//! To burn the efuse key purpose `HMAC_UP` to `Key0`:
|
|
//! ```sh
|
|
//! espefuse.py burn_efuse KEY_PURPOSE_0 8
|
|
//! ```
|
|
//!
|
|
//! ## Use a custom key
|
|
//! You can generate a custom key file from a string using the following command
|
|
//! ```sh
|
|
//! echo -n "<Your custom key>" | openssl dgst -sha256 -binary > key.bin
|
|
//! ```
|
|
//!
|
|
//! You can then write your key using the following command
|
|
//! - `BLOCK_KEY0` The keyblock to program the key to. By default this example
|
|
//! uses key0.
|
|
//! - `HMAC_UP` The purpose for the key. Use HMAC_UP for upstream.
|
|
//! - `--no-read-protect` Allow to read the key from software, after writing it.
|
|
//! ```sh
|
|
//! espefuse.py burn_key BLOCK_KEY0 key.bin HMAC_UP --no-read-protect
|
|
//! ```
|
|
//! To see the key in bytes, you can do the following:
|
|
//! ```sh
|
|
//! echo -n "<Your custom key>" | openssl dgst -sha256 -binary | xxd -p
|
|
//! ```
|
|
//! or from the binary file
|
|
//! ```sh
|
|
//! xxd -p key.bin
|
|
//! ```
|
|
|
|
#![no_std]
|
|
#![no_main]
|
|
|
|
use esp32s3_hal::{
|
|
clock::ClockControl,
|
|
hmac::{Hmac, HmacPurpose, KeyId},
|
|
peripherals::Peripherals,
|
|
prelude::*,
|
|
systimer::SystemTimer,
|
|
Rng,
|
|
};
|
|
use esp_backtrace as _;
|
|
use esp_println::println;
|
|
use hmac::{Hmac as HmacSw, Mac};
|
|
use nb::block;
|
|
use sha2::Sha256;
|
|
|
|
type HmacSha256 = HmacSw<Sha256>;
|
|
|
|
#[entry]
|
|
fn main() -> ! {
|
|
let peripherals = Peripherals::take();
|
|
let system = peripherals.SYSTEM.split();
|
|
let _clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
|
|
|
let mut rng = Rng::new(peripherals.RNG);
|
|
|
|
// Set sw key
|
|
let key = [0_u8; 32].as_ref();
|
|
|
|
let mut hw_hmac = Hmac::new(peripherals.HMAC);
|
|
|
|
let mut src = [0_u8; 1024];
|
|
rng.read(src.as_mut_slice()).unwrap();
|
|
// println!("HMAC input {:02X?}", src);
|
|
|
|
let mut output = [0u8; 32];
|
|
|
|
println!("Beginning stress tests...");
|
|
println!("Testing length from 0 to {:?} bytes for HMAC...", src.len());
|
|
for i in 0..src.len() + 1 {
|
|
let (nsrc, _) = src.split_at(i);
|
|
let mut remaining = nsrc;
|
|
hw_hmac.init();
|
|
block!(hw_hmac.configure(HmacPurpose::ToUser, KeyId::Key0)).expect("Key purpose mismatch");
|
|
let pre_hw_hmac = SystemTimer::now();
|
|
while remaining.len() > 0 {
|
|
remaining = block!(hw_hmac.update(remaining)).unwrap();
|
|
}
|
|
block!(hw_hmac.finalize(output.as_mut_slice())).unwrap();
|
|
let post_hw_hmac = SystemTimer::now();
|
|
let hw_time = post_hw_hmac - pre_hw_hmac;
|
|
let mut sw_hmac = HmacSha256::new_from_slice(key).expect("HMAC can take key of any size");
|
|
let pre_sw_hash = SystemTimer::now();
|
|
sw_hmac.update(nsrc);
|
|
let soft_result = sw_hmac.finalize().into_bytes();
|
|
let post_sw_hash = SystemTimer::now();
|
|
let soft_time = post_sw_hash - pre_sw_hash;
|
|
for (a, b) in output.iter().zip(soft_result) {
|
|
assert_eq!(*a, b);
|
|
}
|
|
println!("Testing for length: {:>4} | HW: {:>6} cycles, SW: {:>7} cycles (HW HMAC is {:>2}x faster)", i, hw_time, soft_time, soft_time / hw_time);
|
|
}
|
|
println!("Finished stress tests!");
|
|
|
|
loop {}
|
|
}
|