Skip to content

Commit a83077c

Browse files
committed
aes esp32
1 parent 4d036c3 commit a83077c

File tree

7 files changed

+309
-1
lines changed

7 files changed

+309
-1
lines changed

esp-hal-common/build.rs

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ fn main() {
6060
"timg0",
6161
"timg1",
6262
"uart2",
63+
"aes",
6364
]
6465
} else if esp32c2 {
6566
vec![

esp-hal-common/src/aes.rs

+194
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
use core::marker::PhantomData;
2+
3+
use crate::{
4+
peripheral::{Peripheral, PeripheralRef},
5+
peripherals::{
6+
generic::{Readable, Reg, RegisterSpec, Resettable, Writable},
7+
AES,
8+
},
9+
system::{Peripheral as PeripheralEnable, PeripheralClockControl},
10+
};
11+
12+
const ALIGN_SIZE: usize = core::mem::size_of::<u32>();
13+
14+
pub struct Aes<'d> {
15+
aes: PeripheralRef<'d, AES>,
16+
}
17+
18+
impl<'d> Aes<'d> {
19+
pub fn new(
20+
aes: impl Peripheral<P = AES> + 'd,
21+
peripheral_clock_control: &mut PeripheralClockControl,
22+
) -> Self {
23+
crate::into_ref!(aes);
24+
peripheral_clock_control.enable(PeripheralEnable::Aes);
25+
Self { aes: aes }
26+
}
27+
28+
fn write_key(&mut self, key: &[u8]) {
29+
debug_assert!(key.len() <= self.aes.key_.len() * ALIGN_SIZE);
30+
debug_assert_eq!(key.len() % ALIGN_SIZE, 0);
31+
Self::write_to_regset(key, &mut self.aes.key_);
32+
}
33+
34+
fn write_block(&mut self, block: &[u8]) {
35+
debug_assert_eq!(block.len(), self.aes.text_.len() * ALIGN_SIZE);
36+
Self::write_to_regset(block, &mut self.aes.text_);
37+
}
38+
39+
fn write_mode(&mut self, mode: u32) {
40+
Self::write_to_register(&mut self.aes.mode, mode);
41+
}
42+
43+
fn write_endianness(&mut self, val: u32) {
44+
Self::write_to_register(&mut self.aes.endian, val)
45+
}
46+
47+
fn write_start(&mut self) {
48+
self.aes.start.write(|w| w.start().set_bit())
49+
}
50+
51+
fn read_idle(&mut self) -> bool {
52+
self.aes.idle.read().idle().bit_is_set()
53+
}
54+
55+
fn read_block(&self, block: &mut [u8]) {
56+
debug_assert_eq!(block.len(), self.aes.text_.len() * ALIGN_SIZE);
57+
Self::read_from_regset(block, &self.aes.text_);
58+
}
59+
60+
fn write_to_regset<T>(input: &[u8], reg_set: &mut [Reg<T>])
61+
where
62+
T: RegisterSpec<Ux = u32> + Resettable + Writable,
63+
{
64+
let chunks = input.chunks_exact(ALIGN_SIZE);
65+
for (reg, chunk) in reg_set.iter_mut().zip(chunks) {
66+
let to_write = u32::from_ne_bytes(chunk.try_into().unwrap());
67+
Self::write_to_register(reg, to_write);
68+
}
69+
}
70+
71+
fn read_from_regset<T>(out_buf: &mut [u8], reg_set: &[Reg<T>])
72+
where
73+
T: RegisterSpec<Ux = u32> + Readable,
74+
{
75+
let chunks = out_buf.chunks_exact_mut(ALIGN_SIZE);
76+
for (reg, chunk) in reg_set.iter().zip(chunks) {
77+
let read_val: [u8; 4] = Self::read_from_register(reg).to_ne_bytes();
78+
chunk.copy_from_slice(&read_val);
79+
}
80+
}
81+
82+
fn write_to_register<T>(reg: &mut Reg<T>, data: u32)
83+
where
84+
T: RegisterSpec<Ux = u32> + Resettable + Writable,
85+
{
86+
reg.write(|w| unsafe { w.bits(data) });
87+
}
88+
89+
fn read_from_register<T>(reg: &Reg<T>) -> u32
90+
where
91+
T: RegisterSpec<Ux = u32> + Readable,
92+
{
93+
reg.read().bits()
94+
}
95+
}
96+
97+
pub trait AesFlavour {
98+
type KeyType<'b>;
99+
const ENCRYPT_MODE: u32;
100+
const DECRYPT_MODE: u32;
101+
}
102+
103+
pub struct Aes128;
104+
105+
impl AesFlavour for Aes128 {
106+
type KeyType<'b> = &'b [u8; 16];
107+
const ENCRYPT_MODE: u32 = 0;
108+
const DECRYPT_MODE: u32 = 4;
109+
}
110+
111+
pub struct Aes192;
112+
113+
impl AesFlavour for Aes192 {
114+
type KeyType<'b> = &'b [u8; 24];
115+
const ENCRYPT_MODE: u32 = 1;
116+
const DECRYPT_MODE: u32 = 5;
117+
}
118+
119+
pub struct Aes256;
120+
121+
impl AesFlavour for Aes256 {
122+
type KeyType<'b> = &'b [u8; 32];
123+
const ENCRYPT_MODE: u32 = 2;
124+
const DECRYPT_MODE: u32 = 6;
125+
}
126+
127+
pub struct Cipher<'a, T: AesFlavour> {
128+
aes: &'a mut Aes<'a>,
129+
phantom: PhantomData<T>,
130+
}
131+
132+
impl<'a, T: AesFlavour> Cipher<'a, T> {
133+
pub fn new(aes: &'a mut Aes<'a>, key: &Key<T>) -> Self {
134+
aes.write_endianness(63);
135+
aes.write_key(key.key);
136+
Self {
137+
aes,
138+
phantom: PhantomData,
139+
}
140+
}
141+
142+
pub fn encrypt_block(&mut self, block: &mut [u8; 16]) {
143+
self.set_mode(T::ENCRYPT_MODE);
144+
self.set_block(block);
145+
self.start();
146+
while !(self.is_idle()) {}
147+
self.get_block(block);
148+
}
149+
150+
pub fn decrypt_block(&mut self, block: &mut [u8; 16]) {
151+
self.set_mode(T::DECRYPT_MODE);
152+
self.set_block(block);
153+
self.start();
154+
while !(self.is_idle()) {}
155+
self.get_block(block);
156+
}
157+
158+
fn set_mode(&mut self, mode: u32) {
159+
self.aes.write_mode(mode);
160+
}
161+
162+
fn is_idle(&mut self) -> bool {
163+
self.aes.read_idle()
164+
}
165+
166+
fn set_block(&mut self, block: &[u8; 16]) {
167+
self.aes.write_block(block);
168+
}
169+
170+
fn get_block(&self, block: &mut [u8; 16]) {
171+
self.aes.read_block(block);
172+
}
173+
174+
fn start(&mut self) {
175+
self.aes.write_start();
176+
}
177+
}
178+
179+
pub struct Key<'b, T: AesFlavour> {
180+
key: &'b [u8],
181+
phantom: PhantomData<T>,
182+
}
183+
184+
impl<'b, T, const N: usize> From<&'b [u8; N]> for Key<'b, T>
185+
where
186+
T: AesFlavour<KeyType<'b> = &'b [u8; N]>,
187+
{
188+
fn from(value: T::KeyType<'b>) -> Self {
189+
Key {
190+
key: value,
191+
phantom: PhantomData,
192+
}
193+
}
194+
}

esp-hal-common/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ pub use self::{
4545
uart::Uart,
4646
};
4747

48+
#[cfg(aes)]
49+
pub mod aes;
4850
pub mod analog;
4951
pub mod clock;
5052
pub mod delay;

esp-hal-common/src/system.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ pub enum Peripheral {
4444
Usb,
4545
#[cfg(any(esp32s3, esp32c3))]
4646
Twai,
47+
#[cfg(aes)]
48+
Aes,
4749
}
4850

4951
/// Controls the enablement of peripheral clocks.
@@ -59,7 +61,13 @@ impl PeripheralClockControl {
5961
#[cfg(not(esp32))]
6062
let (perip_clk_en0, perip_rst_en0) = { (&system.perip_clk_en0, &system.perip_rst_en0) };
6163
#[cfg(esp32)]
62-
let (perip_clk_en0, perip_rst_en0) = { (&system.perip_clk_en, &system.perip_rst_en) };
64+
let (perip_clk_en0, perip_rst_en0, peri_clk_en) = {
65+
(
66+
&system.perip_clk_en,
67+
&system.perip_rst_en,
68+
&system.peri_clk_en,
69+
)
70+
};
6371

6472
#[cfg(any(esp32c2, esp32c3, esp32s3))]
6573
let (perip_clk_en1, perip_rst_en1) = { (&system.perip_clk_en1, &system.perip_rst_en1) };
@@ -156,6 +164,10 @@ impl PeripheralClockControl {
156164
perip_clk_en0.modify(|_, w| w.twai_clk_en().set_bit());
157165
perip_rst_en0.modify(|_, w| w.twai_rst().clear_bit());
158166
}
167+
#[cfg(esp32)]
168+
Peripheral::Aes => {
169+
peri_clk_en.modify(|r, w| unsafe { w.bits(r.bits() | 1) });
170+
}
159171
}
160172
}
161173
}

esp32-hal/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ sha2 = { version = "0.10.6", default-features = false}
4444
smart-leds = "0.3.0"
4545
ssd1306 = "0.7.1"
4646
static_cell = "1.0.0"
47+
aes = "0.8.2"
4748

4849
[features]
4950
default = ["rt", "vectored"]

esp32-hal/examples/aes.rs

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#![no_std]
2+
#![no_main]
3+
use aes::{
4+
cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit},
5+
Aes128 as Aes128SW,
6+
};
7+
use esp32_hal::{
8+
aes::{Aes, Aes128, Cipher, Key},
9+
clock::ClockControl,
10+
peripherals::Peripherals,
11+
prelude::*,
12+
timer::TimerGroup,
13+
Rtc,
14+
};
15+
use esp_backtrace as _;
16+
use esp_println::println;
17+
18+
#[xtensa_lx_rt::entry]
19+
fn main() -> ! {
20+
let peripherals = Peripherals::take();
21+
let mut system = peripherals.DPORT.split();
22+
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
23+
24+
// Disable the RTC and TIMG watchdog timers
25+
let mut rtc = Rtc::new(peripherals.RTC_CNTL);
26+
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
27+
let mut wdt0 = timer_group0.wdt;
28+
let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks);
29+
let mut wdt1 = timer_group1.wdt;
30+
31+
rtc.rwdt.disable();
32+
wdt0.disable();
33+
wdt1.disable();
34+
35+
let mut aes = Aes::new(peripherals.AES, &mut system.peripheral_clock_control);
36+
37+
let keytext = "SUp4SeCp@sSw0rd".as_bytes();
38+
let plaintext = "message".as_bytes();
39+
40+
// create an array with aes128 key size
41+
let mut keybuf = [0_u8; 16];
42+
keybuf[..keytext.len()].copy_from_slice(keytext);
43+
44+
// create an array with aes block size
45+
let mut block_buf = [0_u8; 16];
46+
block_buf[..plaintext.len()].copy_from_slice(plaintext);
47+
48+
let key = Key::<Aes128>::from(&keybuf);
49+
let mut cipher = Cipher::new(&mut aes, &key);
50+
let mut block = block_buf.clone();
51+
let pre_hw_encrypt = xtensa_lx::timer::get_cycle_count();
52+
cipher.encrypt_block(&mut block);
53+
let post_hw_encrypt = xtensa_lx::timer::get_cycle_count();
54+
println!(
55+
"it took {} cycles for hw encrypt",
56+
post_hw_encrypt - pre_hw_encrypt
57+
);
58+
let hw_encrypted = block.clone();
59+
let pre_hw_decrypt = xtensa_lx::timer::get_cycle_count();
60+
cipher.decrypt_block(&mut block);
61+
let post_hw_decrypt = xtensa_lx::timer::get_cycle_count();
62+
println!(
63+
"it took {} cycles for hw decrypt",
64+
post_hw_decrypt - pre_hw_decrypt
65+
);
66+
let hw_decrypted = block;
67+
68+
let key = GenericArray::from(keybuf);
69+
let mut block = GenericArray::from(block_buf);
70+
let cipher = Aes128SW::new(&key);
71+
let pre_sw_encrypt = xtensa_lx::timer::get_cycle_count();
72+
cipher.encrypt_block(&mut block);
73+
let post_sw_encrypt = xtensa_lx::timer::get_cycle_count();
74+
println!(
75+
"it took {} cycles for sw encrypt",
76+
post_sw_encrypt - pre_sw_encrypt
77+
);
78+
let sw_encrypted = block.clone();
79+
let pre_sw_decrypt = xtensa_lx::timer::get_cycle_count();
80+
cipher.decrypt_block(&mut block);
81+
let post_sw_decrypt = xtensa_lx::timer::get_cycle_count();
82+
println!(
83+
"it took {} cycles for sw decrypt",
84+
post_sw_decrypt - pre_sw_decrypt
85+
);
86+
let sw_decrypted = block;
87+
88+
assert!(eq(&sw_encrypted.into(), &hw_encrypted));
89+
assert!(eq(&sw_decrypted.into(), &hw_decrypted));
90+
91+
println!("done");
92+
93+
loop {}
94+
}
95+
fn eq(slice1: &[u8; 16], slice2: &[u8; 16]) -> bool {
96+
slice1.iter().zip(slice2.iter()).all(|(a, b)| a == b)
97+
}

esp32-hal/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub use embedded_hal as ehal;
55
pub use esp_hal_common::embassy;
66
#[doc(inline)]
77
pub use esp_hal_common::{
8+
aes,
89
analog::adc::implementation as adc,
910
analog::dac::implementation as dac,
1011
clock,

0 commit comments

Comments
 (0)