-
Notifications
You must be signed in to change notification settings - Fork 215
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4d036c3
commit 0b76fca
Showing
6 changed files
with
308 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,6 +60,7 @@ fn main() { | |
"timg0", | ||
"timg1", | ||
"uart2", | ||
"aes" | ||
] | ||
} else if esp32c2 { | ||
vec![ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters