Skip to content

Commit

Permalink
aes esp32
Browse files Browse the repository at this point in the history
  • Loading branch information
matrixhead committed Jan 15, 2023
1 parent 4d036c3 commit 0b76fca
Show file tree
Hide file tree
Showing 6 changed files with 308 additions and 1 deletion.
1 change: 1 addition & 0 deletions esp-hal-common/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ fn main() {
"timg0",
"timg1",
"uart2",
"aes"
]
} else if esp32c2 {
vec![
Expand Down
194 changes: 194 additions & 0 deletions esp-hal-common/src/aes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
use core::marker::PhantomData;

use crate::{
peripheral::{Peripheral, PeripheralRef},
peripherals::{
generic::{Readable, Reg, RegisterSpec, Resettable, Writable},
AES,
},
system::{Peripheral as PeripheralEnable, PeripheralClockControl},
};

const ALIGN_SIZE: usize = core::mem::size_of::<u32>();

pub struct Aes<'d> {
aes: PeripheralRef<'d, AES>,
}

impl<'d> Aes<'d> {
pub fn new(
aes: impl Peripheral<P = AES> + 'd,
peripheral_clock_control: &mut PeripheralClockControl,
) -> Self {
crate::into_ref!(aes);
peripheral_clock_control.enable(PeripheralEnable::Aes);
Self { aes: aes }
}

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, &mut self.aes.key_);
}

fn write_block(&mut self, block: &[u8]) {
debug_assert_eq!(block.len(), self.aes.text_.len() * ALIGN_SIZE);
Self::write_to_regset(block, &mut self.aes.text_);
}

fn write_mode(&mut self, mode: u32) {
Self::write_to_register(&mut self.aes.mode, mode);
}

fn write_endianness(&mut self, val: u32) {
Self::write_to_register(&mut self.aes.endian, val)
}

fn write_start(&mut self) {
self.aes.start.write(|w| w.start().set_bit())
}

fn read_idle(&mut self) -> bool {
self.aes.idle.read().idle().bit_is_set()
}

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_);
}

fn write_to_regset<T>(input: &[u8], reg_set: &mut [Reg<T>])
where
T: RegisterSpec<Ux = u32> + Resettable + Writable,
{
let chunks = input.chunks_exact(ALIGN_SIZE);
for (reg, chunk) in reg_set.iter_mut().zip(chunks) {
let to_write = u32::from_ne_bytes(chunk.try_into().unwrap());
Self::write_to_register(reg, to_write);
}
}

fn read_from_regset<T>(out_buf: &mut [u8], reg_set: &[Reg<T>])
where
T: RegisterSpec<Ux = u32> + Readable,
{
let chunks = out_buf.chunks_exact_mut(ALIGN_SIZE);
for (reg, chunk) in reg_set.iter().zip(chunks) {
let read_val: [u8; 4] = Self::read_from_register(reg).to_ne_bytes();
chunk.copy_from_slice(&read_val);
}
}

fn write_to_register<T>(reg: &mut Reg<T>, data: u32)
where
T: RegisterSpec<Ux = u32> + Resettable + Writable,
{
reg.write(|w| unsafe { w.bits(data) });
}

fn read_from_register<T>(reg: &Reg<T>) -> u32
where
T: RegisterSpec<Ux = u32> + Readable,
{
reg.read().bits()
}
}

pub trait AesFlavour {
type KeyType<'b>;
const ENCRYPT_MODE: u32;
const DECRYPT_MODE: u32;
}

pub struct Aes128;

impl AesFlavour for Aes128 {
type KeyType<'b> = &'b [u8; 16];
const ENCRYPT_MODE: u32 = 0;
const DECRYPT_MODE: u32 = 4;
}

pub struct Aes192;

impl AesFlavour for Aes192 {
type KeyType<'b> = &'b [u8; 24];
const ENCRYPT_MODE: u32 = 1;
const DECRYPT_MODE: u32 = 5;
}

pub struct Aes256;

impl AesFlavour for Aes256 {
type KeyType<'b> = &'b [u8; 32];
const ENCRYPT_MODE: u32 = 2;
const DECRYPT_MODE: u32 = 6;
}

pub struct Cipher<'a, T: AesFlavour> {
aes: &'a mut Aes<'a>,
phantom: PhantomData<T>,
}

impl<'a, T: AesFlavour> Cipher<'a, T> {
pub fn new(aes: &'a mut Aes<'a>, key: &Key<T>) -> Self {
aes.write_endianness(63);
aes.write_key(key.key);
Self {
aes,
phantom: PhantomData,
}
}

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);
}

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();
}
}

pub struct Key<'b, T: AesFlavour> {
key: &'b [u8],
phantom: PhantomData<T>,
}

impl<'b, T, const N: usize> From<&'b [u8; N]> for Key<'b, T>
where
T: AesFlavour<KeyType<'b> = &'b [u8; N]>,
{
fn from(value: T::KeyType<'b>) -> Self {
Key {
key: value,
phantom: PhantomData,
}
}
}
2 changes: 2 additions & 0 deletions esp-hal-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ pub use self::{
uart::Uart,
};

#[cfg(aes)]
pub mod aes;
pub mod analog;
pub mod clock;
pub mod delay;
Expand Down
14 changes: 13 additions & 1 deletion esp-hal-common/src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pub enum Peripheral {
Usb,
#[cfg(any(esp32s3, esp32c3))]
Twai,
#[cfg(aes)]
Aes,
}

/// Controls the enablement of peripheral clocks.
Expand All @@ -59,7 +61,13 @@ 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) = {
(
&system.perip_clk_en,
&system.perip_rst_en,
&system.peri_clk_en,
)
};

#[cfg(any(esp32c2, esp32c3, esp32s3))]
let (perip_clk_en1, perip_rst_en1) = { (&system.perip_clk_en1, &system.perip_rst_en1) };
Expand Down Expand Up @@ -156,6 +164,10 @@ 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) });
}
}
}
}
Expand Down
97 changes: 97 additions & 0 deletions esp32-hal/examples/aes.rs
Original file line number Diff line number Diff line change
@@ -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::<Aes128>::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)
}
1 change: 1 addition & 0 deletions esp32-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 0b76fca

Please sign in to comment.