diff --git a/esp-hal-common/build.rs b/esp-hal-common/build.rs index 422abaaaadd..e658154131b 100644 --- a/esp-hal-common/build.rs +++ b/esp-hal-common/build.rs @@ -42,6 +42,7 @@ fn main() { // - 'uart2' // - 'usb_otg' // - 'usb_serial_jtag' + // - 'aes' // // New symbols can be added as needed, but please be sure to update both this // comment and the required vectors below. @@ -60,6 +61,7 @@ fn main() { "timg0", "timg1", "uart2", + "aes", ] } else if esp32c2 { vec![ @@ -83,6 +85,7 @@ fn main() { "timg0", "timg1", "usb_serial_jtag", + "aes", ] } else if esp32s2 { vec![ @@ -99,6 +102,7 @@ fn main() { "timg0", "timg1", "usb_otg", + "aes", ] } else if esp32s3 { vec![ @@ -117,6 +121,7 @@ fn main() { "uart2", "usb_otg", "usb_serial_jtag", + "aes", ] } else { unreachable!(); // We've already confirmed exactly one chip was selected diff --git a/esp-hal-common/src/aes/esp32.rs b/esp-hal-common/src/aes/esp32.rs new file mode 100644 index 00000000000..52fac57dd1c --- /dev/null +++ b/esp-hal-common/src/aes/esp32.rs @@ -0,0 +1,84 @@ +use crate::{ + aes::{Aes, Aes128, Aes192, Aes256, AesFlavour, Endianness, ALIGN_SIZE}, + system::{Peripheral as PeripheralEnable, PeripheralClockControl}, +}; + +impl<'d> Aes<'d> { + pub(super) fn init(&mut self, peripheral_clock_control: &mut PeripheralClockControl) { + peripheral_clock_control.enable(PeripheralEnable::Aes); + self.write_endianness( + Endianness::BigEndian, + Endianness::BigEndian, + Endianness::BigEndian, + Endianness::BigEndian, + Endianness::BigEndian, + Endianness::BigEndian, + ); + } + + pub(super) fn write_key(&mut self, key: &[u8]) { + debug_assert!(key.len() <= self.aes.key_.len() * ALIGN_SIZE); + debug_assert_eq!(key.len() % ALIGN_SIZE, 0); + Self::write_to_regset(key, self.aes.key_.len(), &mut self.aes.key_[0]); + } + + pub(super) fn write_block(&mut self, block: &[u8]) { + debug_assert_eq!(block.len(), self.aes.text_.len() * ALIGN_SIZE); + Self::write_to_regset(block, self.aes.text_.len(), &mut self.aes.text_[0]); + } + + pub(super) fn write_mode(&mut self, mode: u32) { + Self::write_to_register(&mut self.aes.mode, mode); + } + + /// Configures how the state matrix would be laid out + pub fn write_endianness( + &mut self, + input_text_word_endianess: Endianness, + input_text_byte_endianess: Endianness, + output_text_word_endianess: Endianness, + output_text_byte_endianess: Endianness, + key_word_endianess: Endianness, + key_byte_endianess: Endianness, + ) { + let mut to_write = 0_u32; + to_write |= key_byte_endianess as u32; + to_write |= (key_word_endianess as u32) << 1; + to_write |= (input_text_byte_endianess as u32) << 2; + to_write |= (input_text_word_endianess as u32) << 3; + to_write |= (output_text_byte_endianess as u32) << 4; + to_write |= (output_text_word_endianess as u32) << 5; + Self::write_to_register(&mut self.aes.endian, to_write); + } + + pub(super) fn write_start(&mut self) { + self.aes.start.write(|w| w.start().set_bit()) + } + + pub(super) fn read_idle(&mut self) -> bool { + self.aes.idle.read().idle().bit_is_set() + } + + pub(super) fn read_block(&self, block: &mut [u8]) { + debug_assert_eq!(block.len(), self.aes.text_.len() * ALIGN_SIZE); + Self::read_from_regset(block, self.aes.text_.len(), &self.aes.text_[0]); + } +} + +impl AesFlavour for Aes128 { + type KeyType<'b> = &'b [u8; 16]; + const ENCRYPT_MODE: u32 = 0; + const DECRYPT_MODE: u32 = 4; +} + +impl AesFlavour for Aes192 { + type KeyType<'b> = &'b [u8; 24]; + const ENCRYPT_MODE: u32 = 1; + const DECRYPT_MODE: u32 = 5; +} + +impl AesFlavour for Aes256 { + type KeyType<'b> = &'b [u8; 32]; + const ENCRYPT_MODE: u32 = 2; + const DECRYPT_MODE: u32 = 6; +} diff --git a/esp-hal-common/src/aes/esp32_c3.rs b/esp-hal-common/src/aes/esp32_c3.rs new file mode 100644 index 00000000000..e0bc104a23e --- /dev/null +++ b/esp-hal-common/src/aes/esp32_c3.rs @@ -0,0 +1,58 @@ +use crate::{ + aes::{Aes, Aes128, Aes256, AesFlavour, ALIGN_SIZE}, + system::{Peripheral as PeripheralEnable, PeripheralClockControl}, +}; + +impl<'d> Aes<'d> { + pub(super) fn init(&mut self, peripheral_clock_control: &mut PeripheralClockControl) { + peripheral_clock_control.enable(PeripheralEnable::Aes); + self.write_dma(false); + } + + fn write_dma(&mut self, enable_dma: bool) { + match enable_dma { + true => self.aes.dma_enable.write(|w| w.dma_enable().set_bit()), + false => self.aes.dma_enable.write(|w| w.dma_enable().clear_bit()), + } + } + + pub(super) fn write_key(&mut self, key: &[u8]) { + debug_assert!(key.len() <= 8 * ALIGN_SIZE); + debug_assert_eq!(key.len() % ALIGN_SIZE, 0); + Self::write_to_regset(key, 8, &mut self.aes.key_0); + } + + pub(super) fn write_block(&mut self, block: &[u8]) { + debug_assert_eq!(block.len(), 4 * ALIGN_SIZE); + Self::write_to_regset(block, 4, &mut self.aes.text_in_0); + } + + pub(super) fn write_mode(&mut self, mode: u32) { + Self::write_to_register(&mut self.aes.mode, mode); + } + + pub(super) fn write_start(&mut self) { + self.aes.trigger.write(|w| w.trigger().set_bit()) + } + + pub(super) fn read_idle(&mut self) -> bool { + self.aes.state.read().state().bits() == 0 + } + + pub(super) fn read_block(&self, block: &mut [u8]) { + debug_assert_eq!(block.len(), 4 * ALIGN_SIZE); + Self::read_from_regset(block, 4, &self.aes.text_out_0); + } +} + +impl AesFlavour for Aes128 { + type KeyType<'b> = &'b [u8; 16]; + const ENCRYPT_MODE: u32 = 0; + const DECRYPT_MODE: u32 = 4; +} + +impl AesFlavour for Aes256 { + type KeyType<'b> = &'b [u8; 32]; + const ENCRYPT_MODE: u32 = 2; + const DECRYPT_MODE: u32 = 6; +} diff --git a/esp-hal-common/src/aes/esp32_s2.rs b/esp-hal-common/src/aes/esp32_s2.rs new file mode 100644 index 00000000000..331ed36ff29 --- /dev/null +++ b/esp-hal-common/src/aes/esp32_s2.rs @@ -0,0 +1,92 @@ +use crate::{ + aes::{Aes, Aes128, Aes192, Aes256, AesFlavour, Endianness, ALIGN_SIZE}, + system::{Peripheral as PeripheralEnable, PeripheralClockControl}, +}; + +impl<'d> Aes<'d> { + pub(super) fn init(&mut self, peripheral_clock_control: &mut PeripheralClockControl) { + peripheral_clock_control.enable(PeripheralEnable::Aes); + self.write_dma(false); + self.write_endianness( + Endianness::BigEndian, + Endianness::BigEndian, + Endianness::BigEndian, + Endianness::BigEndian, + Endianness::BigEndian, + Endianness::BigEndian, + ); + } + + fn write_dma(&mut self, enable_dma: bool) { + match enable_dma { + true => self.aes.dma_enable.write(|w| w.dma_enable().set_bit()), + false => self.aes.dma_enable.write(|w| w.dma_enable().clear_bit()), + } + } + + pub(super) fn write_key(&mut self, key: &[u8]) { + debug_assert!(key.len() <= self.aes.key_.len() * ALIGN_SIZE); + debug_assert_eq!(key.len() % ALIGN_SIZE, 0); + Self::write_to_regset(key, self.aes.key_.len(), &mut self.aes.key_[0]); + } + + pub(super) fn write_block(&mut self, block: &[u8]) { + debug_assert_eq!(block.len(), self.aes.text_in_.len() * ALIGN_SIZE); + Self::write_to_regset(block, self.aes.text_in_.len(), &mut self.aes.text_in_[0]); + } + + pub(super) fn write_mode(&mut self, mode: u32) { + Self::write_to_register(&mut self.aes.mode, mode); + } + + /// Configures how the state matrix would be laid out. + pub fn write_endianness( + &mut self, + input_text_word_endianess: Endianness, + input_text_byte_endianess: Endianness, + output_text_word_endianess: Endianness, + output_text_byte_endianess: Endianness, + key_word_endianess: Endianness, + key_byte_endianess: Endianness, + ) { + let mut to_write = 0_u32; + to_write |= key_byte_endianess as u32; + to_write |= (key_word_endianess as u32) << 1; + to_write |= (input_text_byte_endianess as u32) << 2; + to_write |= (input_text_word_endianess as u32) << 3; + to_write |= (output_text_byte_endianess as u32) << 4; + to_write |= (output_text_word_endianess as u32) << 5; + Self::write_to_register(&mut self.aes.endian, to_write); + } + + pub(super) fn write_start(&mut self) { + self.aes.trigger.write(|w| w.trigger().set_bit()) + } + + pub(super) fn read_idle(&mut self) -> bool { + self.aes.state.read().state().bits() == 0 + } + + pub(super) fn read_block(&self, block: &mut [u8]) { + debug_assert_eq!(block.len(), self.aes.text_out_.len() * ALIGN_SIZE); + Self::read_from_regset(block, self.aes.text_out_.len(), &self.aes.text_out_[0]); + } +} + +impl AesFlavour for Aes128 { + type KeyType<'b> = &'b [u8; 16]; + const ENCRYPT_MODE: u32 = 0; + const DECRYPT_MODE: u32 = 4; +} + +impl AesFlavour for Aes192 { + type KeyType<'b> = &'b [u8; 24]; + const ENCRYPT_MODE: u32 = 1; + const DECRYPT_MODE: u32 = 5; +} + +impl AesFlavour for Aes256 { + type KeyType<'b> = &'b [u8; 32]; + const ENCRYPT_MODE: u32 = 2; + const DECRYPT_MODE: u32 = 6; +} diff --git a/esp-hal-common/src/aes/esp32_s3.rs b/esp-hal-common/src/aes/esp32_s3.rs new file mode 100644 index 00000000000..f80ee57466a --- /dev/null +++ b/esp-hal-common/src/aes/esp32_s3.rs @@ -0,0 +1,58 @@ +use crate::{ + aes::{Aes, Aes128, Aes256, AesFlavour, ALIGN_SIZE}, + system::{Peripheral as PeripheralEnable, PeripheralClockControl}, +}; + +impl<'d> Aes<'d> { + pub(super) fn init(&mut self, peripheral_clock_control: &mut PeripheralClockControl) { + peripheral_clock_control.enable(PeripheralEnable::Aes); + self.write_dma(false); + } + + fn write_dma(&mut self, enable_dma: bool) { + match enable_dma { + true => self.aes.dma_enable.write(|w| w.dma_enable().set_bit()), + false => self.aes.dma_enable.write(|w| w.dma_enable().clear_bit()), + } + } + + pub(super) fn write_key(&mut self, key: &[u8]) { + debug_assert!(key.len() <= self.aes.key_.len() * ALIGN_SIZE); + debug_assert_eq!(key.len() % ALIGN_SIZE, 0); + Self::write_to_regset(key, self.aes.key_.len(), &mut self.aes.key_[0]); + } + + pub(super) fn write_block(&mut self, block: &[u8]) { + debug_assert_eq!(block.len(), self.aes.text_in_.len() * ALIGN_SIZE); + Self::write_to_regset(block, self.aes.text_in_.len(), &mut self.aes.text_in_[0]); + } + + pub(super) fn write_mode(&mut self, mode: u32) { + Self::write_to_register(&mut self.aes.mode, mode); + } + + pub(super) fn write_start(&mut self) { + self.aes.trigger.write(|w| w.trigger().set_bit()) + } + + pub(super) fn read_idle(&mut self) -> bool { + self.aes.state.read().state().bits() == 0 + } + + pub(super) fn read_block(&self, block: &mut [u8]) { + debug_assert_eq!(block.len(), self.aes.text_out_.len() * ALIGN_SIZE); + Self::read_from_regset(block, self.aes.text_out_.len(), &self.aes.text_out_[0]); + } +} + +impl AesFlavour for Aes128 { + type KeyType<'b> = &'b [u8; 16]; + const ENCRYPT_MODE: u32 = 0; + const DECRYPT_MODE: u32 = 4; +} + +impl AesFlavour for Aes256 { + type KeyType<'b> = &'b [u8; 32]; + const ENCRYPT_MODE: u32 = 2; + const DECRYPT_MODE: u32 = 6; +} diff --git a/esp-hal-common/src/aes/mod.rs b/esp-hal-common/src/aes/mod.rs new file mode 100644 index 00000000000..240bd174489 --- /dev/null +++ b/esp-hal-common/src/aes/mod.rs @@ -0,0 +1,195 @@ +//! Advanced Encryption Standard (AES) support. +//! +//! This module provides functions and structs for AES encryption and decryption. +//! +//! ### Features +//! The AES peripheral has the following features available on individual chips: +//! +//! | Feature | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 | +//! |------------------|----------|----------|----------|----------| +//! |AES128 |Y |Y |Y |Y | +//! |AES192 |Y |N |Y |N | +//! |AES256 |Y |Y |Y |Y | +//! |Custom endianness |Y |N |Y |N | +//! +//! ### Implementation State +//! * DMA mode is currently not supported. + +use core::marker::PhantomData; + +use crate::{ + peripheral::{Peripheral, PeripheralRef}, + peripherals::{ + generic::{Readable, Reg, RegisterSpec, Resettable, Writable}, + AES, + }, + system::PeripheralClockControl, +}; + +#[cfg_attr(esp32, path = "esp32.rs")] +#[cfg_attr(esp32s3, path = "esp32_s3.rs")] +#[cfg_attr(esp32s2, path = "esp32_s2.rs")] +#[cfg_attr(esp32c3, path = "esp32_c3.rs")] +mod aes_spec_impl; + +const ALIGN_SIZE: usize = core::mem::size_of::(); + +/// AES peripheral container +pub struct Aes<'d> { + aes: PeripheralRef<'d, AES>, +} + +impl<'d> Aes<'d> { + pub fn new( + aes: impl Peripheral

+ 'd, + peripheral_clock_control: &mut PeripheralClockControl, + ) -> Self { + crate::into_ref!(aes); + let mut ret = Self { aes: aes }; + ret.init(peripheral_clock_control); + ret + } + + fn write_to_regset(input: &[u8], n_offset: usize, reg_0: &mut Reg) + where + T: RegisterSpec + Resettable + Writable, + { + let chunks = input.chunks_exact(ALIGN_SIZE); + for (offset, chunk) in (0..n_offset).zip(chunks) { + let to_write = u32::from_ne_bytes(chunk.try_into().unwrap()); + unsafe { + let p = reg_0.as_ptr().add(offset); + p.write_volatile(to_write); + } + } + } + + fn read_from_regset(out_buf: &mut [u8], n_offset: usize, reg_0: &Reg) + where + T: RegisterSpec + Readable, + { + let chunks = out_buf.chunks_exact_mut(ALIGN_SIZE); + for (offset, chunk) in (0..n_offset).zip(chunks) { + unsafe { + let p = reg_0.as_ptr().add(offset); + let read_val: [u8; ALIGN_SIZE] = p.read_volatile().to_ne_bytes(); + chunk.copy_from_slice(&read_val); + } + } + } + + fn write_to_register(reg: &mut Reg, data: u32) + where + T: RegisterSpec + Resettable + Writable, + { + reg.write(|w| unsafe { w.bits(data) }); + } +} + +mod sealed { + /// Specifications for AES flavours + pub trait AesFlavour { + type KeyType<'b>; + const ENCRYPT_MODE: u32; + const DECRYPT_MODE: u32; + } +} + +use sealed::AesFlavour; + +/// Marker type for AES-128 +pub struct Aes128; + +/// Marker type for AES-192 +#[cfg(any(esp32, esp32s2))] +pub struct Aes192; + +/// Marker type for AES-256 +pub struct Aes256; + +/// Block cipher +pub struct Cipher<'a, 'd, T: AesFlavour> { + aes: &'a mut Aes<'d>, + phantom: PhantomData, +} + +impl<'a, 'd, T: AesFlavour> Cipher<'a, 'd, T> { + /// Creates and returns a new cipher + pub fn new(aes: &'a mut Aes<'d>, key: &Key) -> Self { + aes.write_key(key.key); + Self { + aes, + phantom: PhantomData, + } + } + /// Encrypts the given buffer + pub fn encrypt_block(&mut self, block: &mut [u8; 16]) { + self.set_mode(T::ENCRYPT_MODE); + self.set_block(block); + self.start(); + while !(self.is_idle()) {} + self.get_block(block); + } + + /// Decrypts the given buffer + pub fn decrypt_block(&mut self, block: &mut [u8; 16]) { + self.set_mode(T::DECRYPT_MODE); + self.set_block(block); + self.start(); + while !(self.is_idle()) {} + self.get_block(block); + } + + fn set_mode(&mut self, mode: u32) { + self.aes.write_mode(mode); + } + + fn is_idle(&mut self) -> bool { + self.aes.read_idle() + } + + fn set_block(&mut self, block: &[u8; 16]) { + self.aes.write_block(block); + } + + fn get_block(&self, block: &mut [u8; 16]) { + self.aes.read_block(block); + } + + fn start(&mut self) { + self.aes.write_start(); + } +} + +/// Aes cipher key +/// +/// A `Key` can be initialized from an array of appropriate length: +/// +/// ``` plain +/// let key = Key::::from(&[0_u8;16]); +/// let key = Key::::from(&[0_u8;24]); +/// let key = Key::::from(&[0_u8;32]); +/// ``` +/// +pub struct Key<'b, T: AesFlavour> { + key: &'b [u8], + phantom: PhantomData, +} + +impl<'b, T, const N: usize> From<&'b [u8; N]> for Key<'b, T> +where + T: AesFlavour = &'b [u8; N]>, +{ + fn from(value: T::KeyType<'b>) -> Self { + Key { + key: value, + phantom: PhantomData, + } + } +} +/// State matrix endianness +#[cfg(any(esp32, esp32s2))] +pub enum Endianness { + BigEndian = 1, + LittleEndian = 0, +} diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index f5a2f812121..a7f6cc55090 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -45,6 +45,8 @@ pub use self::{ uart::Uart, }; +#[cfg(aes)] +pub mod aes; pub mod analog; pub mod clock; pub mod delay; diff --git a/esp-hal-common/src/system.rs b/esp-hal-common/src/system.rs index fb2f70e4b65..8bb46d40aff 100644 --- a/esp-hal-common/src/system.rs +++ b/esp-hal-common/src/system.rs @@ -44,6 +44,8 @@ pub enum Peripheral { Usb, #[cfg(any(esp32s3, esp32c3))] Twai, + #[cfg(aes)] + Aes, } /// Controls the enablement of peripheral clocks. @@ -59,9 +61,16 @@ impl PeripheralClockControl { #[cfg(not(esp32))] let (perip_clk_en0, perip_rst_en0) = { (&system.perip_clk_en0, &system.perip_rst_en0) }; #[cfg(esp32)] - let (perip_clk_en0, perip_rst_en0) = { (&system.perip_clk_en, &system.perip_rst_en) }; + let (perip_clk_en0, perip_rst_en0, peri_clk_en, peri_rst_en) = { + ( + &system.perip_clk_en, + &system.perip_rst_en, + &system.peri_clk_en, + &system.peri_rst_en, + ) + }; - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32s2, esp32s3))] let (perip_clk_en1, perip_rst_en1) = { (&system.perip_clk_en1, &system.perip_rst_en1) }; match peripheral { @@ -156,6 +165,16 @@ impl PeripheralClockControl { perip_clk_en0.modify(|_, w| w.twai_clk_en().set_bit()); perip_rst_en0.modify(|_, w| w.twai_rst().clear_bit()); } + #[cfg(esp32)] + Peripheral::Aes => { + peri_clk_en.modify(|r, w| unsafe { w.bits(r.bits() | 1) }); + peri_rst_en.modify(|r, w| unsafe { w.bits(r.bits() & (!1)) }); + } + #[cfg(any(esp32c3, esp32s2, esp32s3))] + Peripheral::Aes => { + perip_clk_en1.modify(|_, w| w.crypto_aes_clk_en().set_bit()); + perip_rst_en1.modify(|_, w| w.crypto_aes_rst().clear_bit()); + } } } } diff --git a/esp32-hal/Cargo.toml b/esp32-hal/Cargo.toml index f6134673532..706ce2a85fc 100644 --- a/esp32-hal/Cargo.toml +++ b/esp32-hal/Cargo.toml @@ -44,6 +44,7 @@ sha2 = { version = "0.10.6", default-features = false} smart-leds = "0.3.0" ssd1306 = "0.7.1" static_cell = "1.0.0" +aes = "0.8.2" [features] default = ["rt", "vectored"] diff --git a/esp32-hal/examples/aes.rs b/esp32-hal/examples/aes.rs new file mode 100644 index 00000000000..877b84394f7 --- /dev/null +++ b/esp32-hal/examples/aes.rs @@ -0,0 +1,97 @@ +#![no_std] +#![no_main] +use aes::{ + cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit}, + Aes128 as Aes128SW, +}; +use esp32_hal::{ + aes::{Aes, Aes128, Cipher, Key}, + clock::ClockControl, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Rtc, +}; +use esp_backtrace as _; +use esp_println::println; + +#[xtensa_lx_rt::entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.DPORT.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the RTC and TIMG watchdog timers + let mut rtc = Rtc::new(peripherals.RTC_CNTL); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let mut wdt1 = timer_group1.wdt; + + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); + + let mut aes = Aes::new(peripherals.AES, &mut system.peripheral_clock_control); + + let keytext = "SUp4SeCp@sSw0rd".as_bytes(); + let plaintext = "message".as_bytes(); + + // create an array with aes128 key size + let mut keybuf = [0_u8; 16]; + keybuf[..keytext.len()].copy_from_slice(keytext); + + // create an array with aes block size + let mut block_buf = [0_u8; 16]; + block_buf[..plaintext.len()].copy_from_slice(plaintext); + + let key = Key::::from(&keybuf); + let mut cipher = Cipher::new(&mut aes, &key); + let mut block = block_buf.clone(); + let pre_hw_encrypt = xtensa_lx::timer::get_cycle_count(); + cipher.encrypt_block(&mut block); + let post_hw_encrypt = xtensa_lx::timer::get_cycle_count(); + println!( + "it took {} cycles for hw encrypt", + post_hw_encrypt - pre_hw_encrypt + ); + let hw_encrypted = block.clone(); + let pre_hw_decrypt = xtensa_lx::timer::get_cycle_count(); + cipher.decrypt_block(&mut block); + let post_hw_decrypt = xtensa_lx::timer::get_cycle_count(); + println!( + "it took {} cycles for hw decrypt", + post_hw_decrypt - pre_hw_decrypt + ); + let hw_decrypted = block; + + let key = GenericArray::from(keybuf); + let mut block = GenericArray::from(block_buf); + let cipher = Aes128SW::new(&key); + let pre_sw_encrypt = xtensa_lx::timer::get_cycle_count(); + cipher.encrypt_block(&mut block); + let post_sw_encrypt = xtensa_lx::timer::get_cycle_count(); + println!( + "it took {} cycles for sw encrypt", + post_sw_encrypt - pre_sw_encrypt + ); + let sw_encrypted = block.clone(); + let pre_sw_decrypt = xtensa_lx::timer::get_cycle_count(); + cipher.decrypt_block(&mut block); + let post_sw_decrypt = xtensa_lx::timer::get_cycle_count(); + println!( + "it took {} cycles for sw decrypt", + post_sw_decrypt - pre_sw_decrypt + ); + let sw_decrypted = block; + + assert!(eq(&sw_encrypted.into(), &hw_encrypted)); + assert!(eq(&sw_decrypted.into(), &hw_decrypted)); + + println!("done"); + + loop {} +} +fn eq(slice1: &[u8; 16], slice2: &[u8; 16]) -> bool { + slice1.iter().zip(slice2.iter()).all(|(a, b)| a == b) +} diff --git a/esp32-hal/src/lib.rs b/esp32-hal/src/lib.rs index a213b5a1813..dbc748e76af 100644 --- a/esp32-hal/src/lib.rs +++ b/esp32-hal/src/lib.rs @@ -5,6 +5,7 @@ pub use embedded_hal as ehal; pub use esp_hal_common::embassy; #[doc(inline)] pub use esp_hal_common::{ + aes, analog::adc::implementation as adc, analog::dac::implementation as dac, clock, diff --git a/esp32c3-hal/Cargo.toml b/esp32c3-hal/Cargo.toml index 7df9a8f5cd8..b496111afdb 100644 --- a/esp32c3-hal/Cargo.toml +++ b/esp32c3-hal/Cargo.toml @@ -47,6 +47,7 @@ sha2 = { version = "0.10.6", default-features = false} smart-leds = "0.3.0" ssd1306 = "0.7.1" static_cell = "1.0.0" +aes = "0.8.2" [features] default = ["rt", "vectored"] diff --git a/esp32c3-hal/examples/aes.rs b/esp32c3-hal/examples/aes.rs new file mode 100644 index 00000000000..9eeec47d004 --- /dev/null +++ b/esp32c3-hal/examples/aes.rs @@ -0,0 +1,74 @@ +#![no_std] +#![no_main] +use aes::{ + cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit}, + Aes128 as Aes128SW, +}; +use esp32c3_hal::{ + aes::{Aes, Aes128, Cipher, Key}, + clock::ClockControl, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Rtc, +}; +use esp_backtrace as _; +use esp_println::println; +use riscv_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.SYSTEM.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the RTC and TIMG watchdog timers + let mut rtc = Rtc::new(peripherals.RTC_CNTL); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let mut wdt1 = timer_group1.wdt; + + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); + + let mut aes = Aes::new(peripherals.AES, &mut system.peripheral_clock_control); + + let keytext = "SUp4SeCp@sSw0rd".as_bytes(); + let plaintext = "message".as_bytes(); + + // create an array with aes128 key size + let mut keybuf = [0_u8; 16]; + keybuf[..keytext.len()].copy_from_slice(keytext); + + // create an array with aes block size + let mut block_buf = [0_u8; 16]; + block_buf[..plaintext.len()].copy_from_slice(plaintext); + + let key = Key::::from(&keybuf); + let mut cipher = Cipher::new(&mut aes, &key); + let mut block = block_buf.clone(); + cipher.encrypt_block(&mut block); + let hw_encrypted = block.clone(); + cipher.decrypt_block(&mut block); + let hw_decrypted = block; + + let key = GenericArray::from(keybuf); + let mut block = GenericArray::from(block_buf); + let cipher = Aes128SW::new(&key); + cipher.encrypt_block(&mut block); + let sw_encrypted = block.clone(); + cipher.decrypt_block(&mut block); + let sw_decrypted = block; + + assert!(eq(&sw_encrypted.into(), &hw_encrypted)); + assert!(eq(&sw_decrypted.into(), &hw_decrypted)); + + println!("done"); + + loop {} +} +fn eq(slice1: &[u8; 16], slice2: &[u8; 16]) -> bool { + slice1.iter().zip(slice2.iter()).all(|(a, b)| a == b) +} diff --git a/esp32c3-hal/src/lib.rs b/esp32c3-hal/src/lib.rs index 90a94c7df93..789db4a8c00 100644 --- a/esp32c3-hal/src/lib.rs +++ b/esp32c3-hal/src/lib.rs @@ -9,6 +9,7 @@ pub use embedded_hal as ehal; pub use esp_hal_common::embassy; #[doc(inline)] pub use esp_hal_common::{ + aes, analog::adc::implementation as adc, clock, dma, diff --git a/esp32s2-hal/Cargo.toml b/esp32s2-hal/Cargo.toml index bd59c30bbc3..1fb5d19ec04 100644 --- a/esp32s2-hal/Cargo.toml +++ b/esp32s2-hal/Cargo.toml @@ -47,6 +47,7 @@ ssd1306 = "0.7.1" usb-device = { version = "0.2.9" } usbd-serial = "0.1.1" static_cell = "1.0.0" +aes = "0.8.2" [features] default = ["rt", "vectored"] diff --git a/esp32s2-hal/examples/aes.rs b/esp32s2-hal/examples/aes.rs new file mode 100644 index 00000000000..1035a1f25ea --- /dev/null +++ b/esp32s2-hal/examples/aes.rs @@ -0,0 +1,97 @@ +#![no_std] +#![no_main] +use aes::{ + cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit}, + Aes128 as Aes128SW, +}; +use esp32s2_hal::{ + aes::{Aes, Aes128, Cipher, Key}, + clock::ClockControl, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Rtc, +}; +use esp_backtrace as _; +use esp_println::println; + +#[xtensa_lx_rt::entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.SYSTEM.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the RTC and TIMG watchdog timers + let mut rtc = Rtc::new(peripherals.RTC_CNTL); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let mut wdt1 = timer_group1.wdt; + + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); + + let mut aes = Aes::new(peripherals.AES, &mut system.peripheral_clock_control); + + let keytext = "SUp4SeCp@sSw0rd".as_bytes(); + let plaintext = "message".as_bytes(); + + // create an array with aes128 key size + let mut keybuf = [0_u8; 16]; + keybuf[..keytext.len()].copy_from_slice(keytext); + + // create an array with aes block size + let mut block_buf = [0_u8; 16]; + block_buf[..plaintext.len()].copy_from_slice(plaintext); + + let key = Key::::from(&keybuf); + let mut cipher = Cipher::new(&mut aes, &key); + let mut block = block_buf.clone(); + let pre_hw_encrypt = xtensa_lx::timer::get_cycle_count(); + cipher.encrypt_block(&mut block); + let post_hw_encrypt = xtensa_lx::timer::get_cycle_count(); + println!( + "it took {} cycles for hw encrypt", + post_hw_encrypt - pre_hw_encrypt + ); + let hw_encrypted = block.clone(); + let pre_hw_decrypt = xtensa_lx::timer::get_cycle_count(); + cipher.decrypt_block(&mut block); + let post_hw_decrypt = xtensa_lx::timer::get_cycle_count(); + println!( + "it took {} cycles for hw decrypt", + post_hw_decrypt - pre_hw_decrypt + ); + let hw_decrypted = block; + + let key = GenericArray::from(keybuf); + let mut block = GenericArray::from(block_buf); + let cipher = Aes128SW::new(&key); + let pre_sw_encrypt = xtensa_lx::timer::get_cycle_count(); + cipher.encrypt_block(&mut block); + let post_sw_encrypt = xtensa_lx::timer::get_cycle_count(); + println!( + "it took {} cycles for sw encrypt", + post_sw_encrypt - pre_sw_encrypt + ); + let sw_encrypted = block.clone(); + let pre_sw_decrypt = xtensa_lx::timer::get_cycle_count(); + cipher.decrypt_block(&mut block); + let post_sw_decrypt = xtensa_lx::timer::get_cycle_count(); + println!( + "it took {} cycles for sw decrypt", + post_sw_decrypt - pre_sw_decrypt + ); + let sw_decrypted = block; + + assert!(eq(&sw_encrypted.into(), &hw_encrypted)); + assert!(eq(&sw_decrypted.into(), &hw_decrypted)); + + println!("done"); + + loop {} +} +fn eq(slice1: &[u8; 16], slice2: &[u8; 16]) -> bool { + slice1.iter().zip(slice2.iter()).all(|(a, b)| a == b) +} diff --git a/esp32s2-hal/src/lib.rs b/esp32s2-hal/src/lib.rs index 1c9f481fb53..ca2bdf8410e 100644 --- a/esp32s2-hal/src/lib.rs +++ b/esp32s2-hal/src/lib.rs @@ -5,6 +5,7 @@ pub use embedded_hal as ehal; pub use esp_hal_common::embassy; #[doc(inline)] pub use esp_hal_common::{ + aes, analog::adc::implementation as adc, analog::dac::implementation as dac, clock, diff --git a/esp32s3-hal/Cargo.toml b/esp32s3-hal/Cargo.toml index 67a3e1ce654..6615cdcb4fe 100644 --- a/esp32s3-hal/Cargo.toml +++ b/esp32s3-hal/Cargo.toml @@ -49,6 +49,7 @@ ssd1306 = "0.7.1" usb-device = { version = "0.2.9" } usbd-serial = "0.1.1" static_cell = "1.0.0" +aes = "0.8.2" [features] default = ["rt", "vectored"] diff --git a/esp32s3-hal/examples/aes.rs b/esp32s3-hal/examples/aes.rs new file mode 100644 index 00000000000..a7d46927f81 --- /dev/null +++ b/esp32s3-hal/examples/aes.rs @@ -0,0 +1,97 @@ +#![no_std] +#![no_main] +use aes::{ + cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit}, + Aes128 as Aes128SW, +}; +use esp32s3_hal::{ + aes::{Aes, Aes128, Cipher, Key}, + clock::ClockControl, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Rtc, +}; +use esp_backtrace as _; +use esp_println::println; + +#[xtensa_lx_rt::entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.SYSTEM.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the RTC and TIMG watchdog timers + let mut rtc = Rtc::new(peripherals.RTC_CNTL); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let mut wdt1 = timer_group1.wdt; + + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); + + let mut aes = Aes::new(peripherals.AES, &mut system.peripheral_clock_control); + + let keytext = "SUp4SeCp@sSw0rd".as_bytes(); + let plaintext = "message".as_bytes(); + + // create an array with aes128 key size + let mut keybuf = [0_u8; 16]; + keybuf[..keytext.len()].copy_from_slice(keytext); + + // create an array with aes block size + let mut block_buf = [0_u8; 16]; + block_buf[..plaintext.len()].copy_from_slice(plaintext); + + let key = Key::::from(&keybuf); + let mut cipher = Cipher::new(&mut aes, &key); + let mut block = block_buf.clone(); + let pre_hw_encrypt = xtensa_lx::timer::get_cycle_count(); + cipher.encrypt_block(&mut block); + let post_hw_encrypt = xtensa_lx::timer::get_cycle_count(); + println!( + "it took {} cycles for hw encrypt", + post_hw_encrypt - pre_hw_encrypt + ); + let hw_encrypted = block.clone(); + let pre_hw_decrypt = xtensa_lx::timer::get_cycle_count(); + cipher.decrypt_block(&mut block); + let post_hw_decrypt = xtensa_lx::timer::get_cycle_count(); + println!( + "it took {} cycles for hw decrypt", + post_hw_decrypt - pre_hw_decrypt + ); + let hw_decrypted = block; + + let key = GenericArray::from(keybuf); + let mut block = GenericArray::from(block_buf); + let cipher = Aes128SW::new(&key); + let pre_sw_encrypt = xtensa_lx::timer::get_cycle_count(); + cipher.encrypt_block(&mut block); + let post_sw_encrypt = xtensa_lx::timer::get_cycle_count(); + println!( + "it took {} cycles for sw encrypt", + post_sw_encrypt - pre_sw_encrypt + ); + let sw_encrypted = block.clone(); + let pre_sw_decrypt = xtensa_lx::timer::get_cycle_count(); + cipher.decrypt_block(&mut block); + let post_sw_decrypt = xtensa_lx::timer::get_cycle_count(); + println!( + "it took {} cycles for sw decrypt", + post_sw_decrypt - pre_sw_decrypt + ); + let sw_decrypted = block; + + assert!(eq(&sw_encrypted.into(), &hw_encrypted)); + assert!(eq(&sw_decrypted.into(), &hw_decrypted)); + + println!("done"); + + loop {} +} +fn eq(slice1: &[u8; 16], slice2: &[u8; 16]) -> bool { + slice1.iter().zip(slice2.iter()).all(|(a, b)| a == b) +} diff --git a/esp32s3-hal/src/lib.rs b/esp32s3-hal/src/lib.rs index 870ada55901..bcf459e2311 100644 --- a/esp32s3-hal/src/lib.rs +++ b/esp32s3-hal/src/lib.rs @@ -7,6 +7,7 @@ pub use embedded_hal as ehal; pub use esp_hal_common::embassy; #[doc(inline)] pub use esp_hal_common::{ + aes, analog::adc::implementation as adc, clock, cpu_control::CpuControl,