mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-26 20:00:32 +00:00
Midterm AES rework (#3882)
* Midterm AES rework * Update esp-hal/src/aes/mod.rs Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com> * Update esp-hal/MIGRATING-1.0.0-rc.0.md Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com> * Panic on wrong size --------- Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>
This commit is contained in:
parent
e1917abf9f
commit
406056ab9c
@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- The `rng` module has been rewritten (#3829)
|
||||
- Update `embassy-usb` to v0.5.0 (#3848)
|
||||
- `aes::Key` variants have been renamed from bytes to bits (e.g. `Key16 -> Key128`) (#3845)
|
||||
- `aes::Mode` has been replaced by `Operation`. The key length is now solely determined by the key. (#3882)
|
||||
- `Aes::process` has been split into `Aes::encrypt` and `Aes::decrypt` (#3882)
|
||||
|
||||
### Fixed
|
||||
|
||||
@ -27,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Removed
|
||||
|
||||
- `Trng::new` (replaced by `Trng::try_new`) (#3829)
|
||||
- `AesDma::write_block` has been removed. (#3882)
|
||||
|
||||
## [v1.0.0-rc.0] - 2025-07-16
|
||||
|
||||
|
@ -24,3 +24,19 @@ The previous way to obtain RNG object has changed like so:
|
||||
+// As long as `trng_source` is alive:
|
||||
+let trng = Tnrg::try_new().unrwap();
|
||||
```
|
||||
|
||||
## AES changes
|
||||
|
||||
The `esp_hal::aes::Aes` driver has been slightly reworked:
|
||||
|
||||
- `Mode` has been replaced by `Operation`. Operation has `Encrypt` and `Decrypt` variants, but the key length is no longer part of the enum. The key length is specified by the key. AesDma now takes this `Operation`.
|
||||
- `Aes::process` has been split into `encrypt` and `decrypt`. These functions no longer take a mode parameter.
|
||||
- `AesDma::write_block` has been removed.
|
||||
|
||||
```diff
|
||||
-aes.process(block, Mode::Encrypt128, key);
|
||||
+aes.encrypt(block, key_16_bytes);
|
||||
|
||||
-aes.process(block, Mode::Decrypt256, key);
|
||||
+aes.decrypt(block, key_32_bytes);
|
||||
```
|
||||
|
@ -1,68 +0,0 @@
|
||||
use crate::aes::{ALIGN_SIZE, Aes, Endianness, Mode};
|
||||
|
||||
impl Aes<'_> {
|
||||
pub(super) fn init(&mut self) {
|
||||
self.write_endianness(
|
||||
Endianness::BigEndian,
|
||||
Endianness::BigEndian,
|
||||
Endianness::BigEndian,
|
||||
Endianness::BigEndian,
|
||||
Endianness::BigEndian,
|
||||
Endianness::BigEndian,
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn write_key(&mut self, key: &[u8]) {
|
||||
let key_len = self.regs().key_iter().count();
|
||||
debug_assert!(key.len() <= key_len * ALIGN_SIZE);
|
||||
debug_assert_eq!(key.len() % ALIGN_SIZE, 0);
|
||||
self.alignment_helper
|
||||
.volatile_write_regset(self.regs().key(0).as_ptr(), key, key_len);
|
||||
}
|
||||
|
||||
pub(super) fn write_block(&mut self, block: &[u8]) {
|
||||
let text_len = self.regs().text_iter().count();
|
||||
debug_assert_eq!(block.len(), text_len * ALIGN_SIZE);
|
||||
self.alignment_helper
|
||||
.volatile_write_regset(self.regs().text(0).as_ptr(), block, text_len);
|
||||
}
|
||||
|
||||
pub(super) fn write_mode(&self, mode: Mode) {
|
||||
self.regs().mode().write(|w| unsafe { w.bits(mode as _) });
|
||||
}
|
||||
|
||||
/// 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.regs().endian().write(|w| unsafe { w.bits(to_write) });
|
||||
}
|
||||
|
||||
pub(super) fn write_start(&self) {
|
||||
self.regs().start().write(|w| w.start().set_bit());
|
||||
}
|
||||
|
||||
pub(super) fn read_idle(&mut self) -> bool {
|
||||
self.regs().idle().read().idle().bit_is_set()
|
||||
}
|
||||
|
||||
pub(super) fn read_block(&self, block: &mut [u8]) {
|
||||
let text_len = self.regs().text_iter().count();
|
||||
debug_assert_eq!(block.len(), text_len * ALIGN_SIZE);
|
||||
self.alignment_helper
|
||||
.volatile_read_regset(self.regs().text(0).as_ptr(), block, text_len);
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
use crate::aes::{ALIGN_SIZE, Aes, Mode};
|
||||
|
||||
impl Aes<'_> {
|
||||
pub(super) fn init(&mut self) {
|
||||
self.write_dma(false);
|
||||
}
|
||||
|
||||
fn write_dma(&mut self, enable_dma: bool) {
|
||||
self.regs()
|
||||
.dma_enable()
|
||||
.write(|w| w.dma_enable().bit(enable_dma));
|
||||
}
|
||||
|
||||
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.alignment_helper
|
||||
.volatile_write_regset(self.regs().key(0).as_ptr(), key, 8);
|
||||
}
|
||||
|
||||
pub(super) fn write_block(&mut self, block: &[u8]) {
|
||||
debug_assert_eq!(block.len(), 4 * ALIGN_SIZE);
|
||||
self.alignment_helper
|
||||
.volatile_write_regset(self.regs().text_in(0).as_ptr(), block, 4);
|
||||
}
|
||||
|
||||
pub(super) fn write_mode(&self, mode: Mode) {
|
||||
self.regs().mode().write(|w| unsafe { w.bits(mode as _) });
|
||||
}
|
||||
|
||||
pub(super) fn write_start(&self) {
|
||||
self.regs().trigger().write(|w| w.trigger().set_bit());
|
||||
}
|
||||
|
||||
pub(super) fn read_idle(&mut self) -> bool {
|
||||
self.regs().state().read().state().bits() == 0
|
||||
}
|
||||
|
||||
pub(super) fn read_block(&self, block: &mut [u8]) {
|
||||
debug_assert_eq!(block.len(), 4 * ALIGN_SIZE);
|
||||
self.alignment_helper
|
||||
.volatile_read_regset(self.regs().text_out(0).as_ptr(), block, 4);
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
use crate::aes::{ALIGN_SIZE, Aes, Endianness, Mode};
|
||||
|
||||
impl Aes<'_> {
|
||||
pub(super) fn init(&mut self) {
|
||||
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) {
|
||||
self.regs()
|
||||
.dma_enable()
|
||||
.write(|w| w.dma_enable().bit(enable_dma));
|
||||
}
|
||||
|
||||
pub(super) fn write_key(&mut self, key: &[u8]) {
|
||||
let key_len = self.regs().key_iter().count();
|
||||
debug_assert!(key.len() <= key_len * ALIGN_SIZE);
|
||||
debug_assert_eq!(key.len() % ALIGN_SIZE, 0);
|
||||
self.alignment_helper
|
||||
.volatile_write_regset(self.regs().key(0).as_ptr(), key, key_len);
|
||||
}
|
||||
|
||||
pub(super) fn write_block(&mut self, block: &[u8]) {
|
||||
let text_in_len = self.regs().text_in_iter().count();
|
||||
debug_assert_eq!(block.len(), text_in_len * ALIGN_SIZE);
|
||||
self.alignment_helper.volatile_write_regset(
|
||||
self.regs().text_in(0).as_ptr(),
|
||||
block,
|
||||
text_in_len,
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn write_mode(&self, mode: Mode) {
|
||||
self.regs().mode().write(|w| unsafe { w.bits(mode as _) });
|
||||
}
|
||||
|
||||
/// 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.regs().endian().write(|w| unsafe { w.bits(to_write) });
|
||||
}
|
||||
|
||||
pub(super) fn write_start(&self) {
|
||||
self.regs().trigger().write(|w| w.trigger().set_bit());
|
||||
}
|
||||
|
||||
pub(super) fn read_idle(&mut self) -> bool {
|
||||
self.regs().state().read().state().bits() == 0
|
||||
}
|
||||
|
||||
pub(super) fn read_block(&self, block: &mut [u8]) {
|
||||
let text_out_len = self.regs().text_out_iter().count();
|
||||
debug_assert_eq!(block.len(), text_out_len * ALIGN_SIZE);
|
||||
self.alignment_helper.volatile_read_regset(
|
||||
self.regs().text_out(0).as_ptr(),
|
||||
block,
|
||||
text_out_len,
|
||||
);
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
use crate::aes::{ALIGN_SIZE, Aes, Mode};
|
||||
|
||||
impl Aes<'_> {
|
||||
pub(super) fn init(&mut self) {
|
||||
self.write_dma(false);
|
||||
}
|
||||
|
||||
fn write_dma(&mut self, enable_dma: bool) {
|
||||
self.regs()
|
||||
.dma_enable()
|
||||
.write(|w| w.dma_enable().bit(enable_dma));
|
||||
}
|
||||
|
||||
pub(super) fn write_key(&mut self, key: &[u8]) {
|
||||
let key_len = self.regs().key_iter().count();
|
||||
debug_assert!(key.len() <= key_len * ALIGN_SIZE);
|
||||
debug_assert_eq!(key.len() % ALIGN_SIZE, 0);
|
||||
self.alignment_helper
|
||||
.volatile_write_regset(self.regs().key(0).as_ptr(), key, key_len);
|
||||
}
|
||||
|
||||
pub(super) fn write_block(&mut self, block: &[u8]) {
|
||||
let text_in_len = self.regs().text_in_iter().count();
|
||||
debug_assert_eq!(block.len(), text_in_len * ALIGN_SIZE);
|
||||
self.alignment_helper.volatile_write_regset(
|
||||
self.regs().text_in(0).as_ptr(),
|
||||
block,
|
||||
text_in_len,
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn write_mode(&self, mode: Mode) {
|
||||
self.regs().mode().write(|w| unsafe { w.bits(mode as _) });
|
||||
}
|
||||
|
||||
pub(super) fn write_start(&self) {
|
||||
self.regs().trigger().write(|w| w.trigger().set_bit());
|
||||
}
|
||||
|
||||
pub(super) fn read_idle(&mut self) -> bool {
|
||||
self.regs().state().read().state().bits() == 0
|
||||
}
|
||||
|
||||
pub(super) fn read_block(&self, block: &mut [u8]) {
|
||||
let text_out_len = self.regs().text_out_iter().count();
|
||||
debug_assert_eq!(block.len(), text_out_len * ALIGN_SIZE);
|
||||
self.alignment_helper.volatile_read_regset(
|
||||
self.regs().text_out(0).as_ptr(),
|
||||
block,
|
||||
text_out_len,
|
||||
);
|
||||
}
|
||||
}
|
@ -24,7 +24,7 @@
|
||||
//!
|
||||
//! ```rust, no_run
|
||||
//! # {before_snippet}
|
||||
//! # use esp_hal::aes::{Aes, Mode};
|
||||
//! # use esp_hal::aes::{Aes, Operation};
|
||||
//! # let keytext = b"SUp4SeCp@sSw0rd";
|
||||
//! # let plaintext = b"message";
|
||||
//! # let mut keybuf = [0_u8; 16];
|
||||
@ -34,11 +34,11 @@
|
||||
//! block[..plaintext.len()].copy_from_slice(plaintext);
|
||||
//!
|
||||
//! let mut aes = Aes::new(peripherals.AES);
|
||||
//! aes.process(&mut block, Mode::Encryption128, keybuf);
|
||||
//! aes.encrypt(&mut block, keybuf);
|
||||
//!
|
||||
//! // The encryption happens in-place, so the ciphertext is in `block`
|
||||
//!
|
||||
//! aes.process(&mut block, Mode::Decryption128, keybuf);
|
||||
//! aes.decrypt(&mut block, keybuf);
|
||||
//!
|
||||
//! // The decryption happens in-place, so the plaintext is in `block`
|
||||
//! # {after_snippet}
|
||||
@ -50,28 +50,8 @@
|
||||
//! mode.
|
||||
//!
|
||||
//! [AES-DMA]: https://github.com/esp-rs/esp-hal/blob/main/hil-test/tests/aes_dma.rs
|
||||
//!
|
||||
//! ## Implementation State
|
||||
//!
|
||||
//! * AES-DMA mode is currently not supported on ESP32
|
||||
//! * AES-DMA Initialization Vector (IV) is currently not supported
|
||||
|
||||
use crate::{
|
||||
pac,
|
||||
peripherals::AES,
|
||||
reg_access::{AlignmentHelper, NativeEndianess},
|
||||
system::GenericPeripheralGuard,
|
||||
};
|
||||
|
||||
#[cfg_attr(esp32, path = "esp32.rs")]
|
||||
#[cfg_attr(esp32s3, path = "esp32s3.rs")]
|
||||
#[cfg_attr(esp32s2, path = "esp32s2.rs")]
|
||||
#[cfg_attr(esp32c3, path = "esp32cX.rs")]
|
||||
#[cfg_attr(esp32c6, path = "esp32cX.rs")]
|
||||
#[cfg_attr(esp32h2, path = "esp32cX.rs")]
|
||||
mod aes_spec_impl;
|
||||
|
||||
const ALIGN_SIZE: usize = core::mem::size_of::<u32>();
|
||||
use crate::{pac, peripherals::AES, system::GenericPeripheralGuard};
|
||||
|
||||
for_each_aes_key_length! {
|
||||
($len:literal) => {
|
||||
@ -122,23 +102,45 @@ for_each_aes_key_length! {
|
||||
paste::paste! {
|
||||
/// Defines the operating modes for AES encryption and decryption.
|
||||
#[repr(C)]
|
||||
pub enum Mode {
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
enum Mode {
|
||||
$(
|
||||
#[doc= concat!("Encryption mode with ", stringify!($len), "-bit key")]
|
||||
[<Encryption $bits>] = $encrypt,
|
||||
|
||||
#[doc= concat!("Decryption mode with ", stringify!($len), "-bit key")]
|
||||
[<Decryption $bits>] = $decrypt,
|
||||
)*
|
||||
}
|
||||
|
||||
impl Key {
|
||||
fn encrypt_mode(&self) -> Mode {
|
||||
match self {
|
||||
$(Self::[<Key $bits>](_) => Mode::[<Encryption $bits>],)*
|
||||
}
|
||||
}
|
||||
|
||||
fn decrypt_mode(&self) -> Mode {
|
||||
match self {
|
||||
$(Self::[<Key $bits>](_) => Mode::[<Decryption $bits>],)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Defines the operating modes for AES encryption and decryption.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Operation {
|
||||
/// Produce ciphertext from plaintext
|
||||
Encrypt,
|
||||
|
||||
/// Produce plaintext from ciphertext
|
||||
Decrypt,
|
||||
}
|
||||
|
||||
/// AES peripheral container
|
||||
pub struct Aes<'d> {
|
||||
aes: AES<'d>,
|
||||
alignment_helper: AlignmentHelper<NativeEndianess>,
|
||||
_guard: GenericPeripheralGuard<{ crate::system::Peripheral::Aes as u8 }>,
|
||||
}
|
||||
|
||||
@ -147,48 +149,120 @@ impl<'d> Aes<'d> {
|
||||
pub fn new(aes: AES<'d>) -> Self {
|
||||
let guard = GenericPeripheralGuard::new();
|
||||
|
||||
let mut ret = Self {
|
||||
aes,
|
||||
alignment_helper: AlignmentHelper::native_endianess(),
|
||||
_guard: guard,
|
||||
};
|
||||
ret.init();
|
||||
#[cfg_attr(not(aes_dma), expect(unused_mut))]
|
||||
let mut this = Self { aes, _guard: guard };
|
||||
|
||||
ret
|
||||
#[cfg(aes_dma)]
|
||||
this.write_dma(false);
|
||||
|
||||
this
|
||||
}
|
||||
|
||||
fn regs(&self) -> &pac::aes::RegisterBlock {
|
||||
self.aes.register_block()
|
||||
}
|
||||
|
||||
/// Encrypts/Decrypts the given buffer based on `mode` parameter
|
||||
pub fn process<K>(&mut self, block: &mut [u8; 16], mode: Mode, key: K)
|
||||
where
|
||||
K: Into<Key>,
|
||||
{
|
||||
// Convert from into Key enum
|
||||
self.write_key(key.into().as_slice());
|
||||
self.write_mode(mode);
|
||||
self.set_block(block);
|
||||
self.start();
|
||||
while !(self.is_idle()) {}
|
||||
self.block(block);
|
||||
/// Configures how the state matrix would be laid out
|
||||
#[cfg(aes_endianness_configurable)]
|
||||
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.regs().endian().write(|w| unsafe { w.bits(to_write) });
|
||||
}
|
||||
|
||||
fn start(&self) {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(esp32)] {
|
||||
self.regs().start().write(|w| w.start().set_bit());
|
||||
} else {
|
||||
self.regs().trigger().write(|w| w.trigger().set_bit());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_idle(&mut self) -> bool {
|
||||
self.read_idle()
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(esp32)] {
|
||||
self.regs().idle().read().idle().bit_is_set()
|
||||
} else {
|
||||
self.regs().state().read().state().bits() == 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_block(&mut self, block: &[u8; 16]) {
|
||||
fn write_key(&mut self, input: &[u8]) {
|
||||
for (i, word) in read_words(input).enumerate() {
|
||||
self.regs().key(i).write(|w| unsafe { w.bits(word) });
|
||||
}
|
||||
}
|
||||
|
||||
fn write_block(&mut self, block: &[u8]) {
|
||||
for (i, word) in read_words(block).enumerate() {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(aes_has_split_text_registers)] {
|
||||
self.regs().text_in(i).write(|w| unsafe { w.bits(word) });
|
||||
} else {
|
||||
self.regs().text(i).write(|w| unsafe { w.bits(word) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_block(&self, block: &mut [u8]) {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(aes_has_split_text_registers)] {
|
||||
write_words(block, |i| self.regs().text_out(i).read().bits());
|
||||
} else {
|
||||
write_words(block, |i| self.regs().text(i).read().bits());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_mode(&self, mode: Mode) {
|
||||
self.regs().mode().write(|w| unsafe { w.bits(mode as _) });
|
||||
}
|
||||
|
||||
#[cfg(aes_dma)]
|
||||
fn write_dma(&mut self, enable_dma: bool) {
|
||||
self.regs()
|
||||
.dma_enable()
|
||||
.write(|w| w.dma_enable().bit(enable_dma));
|
||||
}
|
||||
|
||||
fn process(&mut self, block: &mut [u8; 16], mode: Mode, key: Key) {
|
||||
self.write_key(key.as_slice());
|
||||
self.write_mode(mode);
|
||||
self.write_block(block);
|
||||
}
|
||||
|
||||
fn block(&self, block: &mut [u8; 16]) {
|
||||
self.start();
|
||||
while !(self.is_idle()) {}
|
||||
self.read_block(block);
|
||||
}
|
||||
|
||||
fn start(&mut self) {
|
||||
self.write_start();
|
||||
/// Encrypts the given buffer with the given key.
|
||||
pub fn encrypt(&mut self, block: &mut [u8; 16], key: impl Into<Key>) {
|
||||
let key = key.into();
|
||||
let mode = key.encrypt_mode();
|
||||
self.process(block, mode, key)
|
||||
}
|
||||
|
||||
/// Decrypts the given buffer with the given key.
|
||||
pub fn decrypt(&mut self, block: &mut [u8; 16], key: impl Into<Key>) {
|
||||
let key = key.into();
|
||||
let mode = key.decrypt_mode();
|
||||
self.process(block, mode, key)
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,7 +296,7 @@ pub mod dma {
|
||||
|
||||
use crate::{
|
||||
Blocking,
|
||||
aes::{Key, Mode},
|
||||
aes::{Key, Operation},
|
||||
dma::{
|
||||
Channel,
|
||||
DmaChannelFor,
|
||||
@ -287,21 +361,12 @@ pub mod dma {
|
||||
impl<'d> AesDma<'d> {
|
||||
/// Writes the encryption key to the AES hardware, checking that its
|
||||
/// length matches expected constraints.
|
||||
pub fn write_key<K>(&mut self, key: K)
|
||||
where
|
||||
K: Into<Key>,
|
||||
{
|
||||
pub fn write_key(&mut self, key: impl Into<Key>) {
|
||||
let key = key.into(); // Convert into Key enum
|
||||
debug_assert!(key.as_slice().len() <= 8 * ALIGN_SIZE);
|
||||
debug_assert_eq!(key.as_slice().len() % ALIGN_SIZE, 0);
|
||||
self.aes.write_key(key.as_slice());
|
||||
}
|
||||
|
||||
/// Writes a block of data to the AES hardware, ensuring the block's
|
||||
/// length is properly aligned.
|
||||
pub fn write_block(&mut self, block: &[u8]) {
|
||||
debug_assert_eq!(block.len(), 4 * ALIGN_SIZE);
|
||||
self.aes.write_key(block);
|
||||
let key = key.as_slice();
|
||||
debug_assert!(key.len() <= 8 * ALIGN_SIZE);
|
||||
debug_assert_eq!(key.len() % ALIGN_SIZE, 0);
|
||||
self.aes.write_key(key);
|
||||
}
|
||||
|
||||
/// Perform a DMA transfer.
|
||||
@ -313,7 +378,7 @@ pub mod dma {
|
||||
number_of_blocks: usize,
|
||||
mut output: RXBUF,
|
||||
mut input: TXBUF,
|
||||
mode: Mode,
|
||||
mode: Operation,
|
||||
cipher_mode: CipherMode,
|
||||
key: K,
|
||||
) -> Result<AesTransfer<'d, RXBUF, TXBUF>, (crate::dma::DmaError, Self, RXBUF, TXBUF)>
|
||||
@ -347,11 +412,16 @@ pub mod dma {
|
||||
return Err((err, self, output, input));
|
||||
}
|
||||
|
||||
let key = key.into();
|
||||
self.enable_dma(true);
|
||||
self.enable_interrupt();
|
||||
self.aes.write_mode(mode);
|
||||
self.aes.write_mode(if mode == Operation::Encrypt {
|
||||
key.encrypt_mode()
|
||||
} else {
|
||||
key.decrypt_mode()
|
||||
});
|
||||
self.set_cipher_mode(cipher_mode);
|
||||
self.write_key(key.into());
|
||||
self.write_key(key);
|
||||
|
||||
self.set_num_block(number_of_blocks as u32);
|
||||
|
||||
@ -398,7 +468,7 @@ pub mod dma {
|
||||
}
|
||||
|
||||
fn start_transform(&self) {
|
||||
self.aes.write_start();
|
||||
self.aes.start();
|
||||
}
|
||||
|
||||
fn finish_transform(&self) {
|
||||
@ -479,7 +549,7 @@ pub mod dma {
|
||||
self.aes_dma.channel.rx.stop_transfer();
|
||||
self.aes_dma.channel.tx.stop_transfer();
|
||||
|
||||
// SAFETY: This is Drop, we know that self.i8080 and self.buf_view
|
||||
// SAFETY: This is Drop, we know that self.aes_dma and self.buf_view
|
||||
// won't be touched again.
|
||||
unsafe {
|
||||
ManuallyDrop::drop(&mut self.aes_dma);
|
||||
@ -491,3 +561,24 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Utilities
|
||||
|
||||
fn read_words(slice: &[u8]) -> impl Iterator<Item = u32> {
|
||||
fn bytes<const N: usize>(slice: &[u8]) -> impl Iterator<Item = [u8; N]> {
|
||||
slice.chunks(N).map(|c| {
|
||||
let mut bytes = [0; N];
|
||||
bytes[0..c.len()].copy_from_slice(c);
|
||||
bytes
|
||||
})
|
||||
}
|
||||
|
||||
bytes::<4>(slice).map(u32::from_le_bytes)
|
||||
}
|
||||
|
||||
fn write_words(slice: &mut [u8], next: impl Fn(usize) -> u32) {
|
||||
for (i, chunk) in slice.chunks_mut(4).enumerate() {
|
||||
let bytes = next(i).to_le_bytes();
|
||||
chunk.copy_from_slice(&bytes[0..chunk.len()]);
|
||||
}
|
||||
}
|
||||
|
@ -79,18 +79,6 @@ impl AlignmentHelper<SocDependentEndianess> {
|
||||
}
|
||||
}
|
||||
|
||||
// only used by AES
|
||||
#[cfg(aes)]
|
||||
impl AlignmentHelper<NativeEndianess> {
|
||||
pub fn native_endianess() -> AlignmentHelper<NativeEndianess> {
|
||||
AlignmentHelper {
|
||||
buf: [0u8; U32_ALIGN_SIZE],
|
||||
buf_fill: 0,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EndianessConverter> AlignmentHelper<E> {
|
||||
pub fn reset(&mut self) {
|
||||
self.buf_fill = 0;
|
||||
|
@ -266,6 +266,7 @@ impl Chip {
|
||||
"soc_ref_tick_hz_is_set",
|
||||
"soc_rc_fast_clk_default=\"8000000\"",
|
||||
"soc_rc_fast_clk_default_is_set",
|
||||
"aes_endianness_configurable",
|
||||
"gpio_has_bank_1",
|
||||
"gpio_gpio_function=\"2\"",
|
||||
"gpio_constant_0_input=\"48\"",
|
||||
@ -419,6 +420,7 @@ impl Chip {
|
||||
"cargo:rustc-cfg=soc_ref_tick_hz_is_set",
|
||||
"cargo:rustc-cfg=soc_rc_fast_clk_default=\"8000000\"",
|
||||
"cargo:rustc-cfg=soc_rc_fast_clk_default_is_set",
|
||||
"cargo:rustc-cfg=aes_endianness_configurable",
|
||||
"cargo:rustc-cfg=gpio_has_bank_1",
|
||||
"cargo:rustc-cfg=gpio_gpio_function=\"2\"",
|
||||
"cargo:rustc-cfg=gpio_constant_0_input=\"48\"",
|
||||
@ -792,6 +794,7 @@ impl Chip {
|
||||
"aes_dma_mode_ctr",
|
||||
"aes_dma_mode_cfb8",
|
||||
"aes_dma_mode_cfb128",
|
||||
"aes_has_split_text_registers",
|
||||
"assist_debug_has_sp_monitor",
|
||||
"assist_debug_has_region_monitor",
|
||||
"gpio_gpio_function=\"1\"",
|
||||
@ -934,6 +937,7 @@ impl Chip {
|
||||
"cargo:rustc-cfg=aes_dma_mode_ctr",
|
||||
"cargo:rustc-cfg=aes_dma_mode_cfb8",
|
||||
"cargo:rustc-cfg=aes_dma_mode_cfb128",
|
||||
"cargo:rustc-cfg=aes_has_split_text_registers",
|
||||
"cargo:rustc-cfg=assist_debug_has_sp_monitor",
|
||||
"cargo:rustc-cfg=assist_debug_has_region_monitor",
|
||||
"cargo:rustc-cfg=gpio_gpio_function=\"1\"",
|
||||
@ -1131,6 +1135,7 @@ impl Chip {
|
||||
"aes_dma_mode_ctr",
|
||||
"aes_dma_mode_cfb8",
|
||||
"aes_dma_mode_cfb128",
|
||||
"aes_has_split_text_registers",
|
||||
"assist_debug_has_sp_monitor",
|
||||
"assist_debug_has_region_monitor",
|
||||
"gpio_gpio_function=\"1\"",
|
||||
@ -1329,6 +1334,7 @@ impl Chip {
|
||||
"cargo:rustc-cfg=aes_dma_mode_ctr",
|
||||
"cargo:rustc-cfg=aes_dma_mode_cfb8",
|
||||
"cargo:rustc-cfg=aes_dma_mode_cfb128",
|
||||
"cargo:rustc-cfg=aes_has_split_text_registers",
|
||||
"cargo:rustc-cfg=assist_debug_has_sp_monitor",
|
||||
"cargo:rustc-cfg=assist_debug_has_region_monitor",
|
||||
"cargo:rustc-cfg=gpio_gpio_function=\"1\"",
|
||||
@ -1508,6 +1514,7 @@ impl Chip {
|
||||
"aes_dma_mode_ctr",
|
||||
"aes_dma_mode_cfb8",
|
||||
"aes_dma_mode_cfb128",
|
||||
"aes_has_split_text_registers",
|
||||
"assist_debug_has_sp_monitor",
|
||||
"assist_debug_has_region_monitor",
|
||||
"gpio_gpio_function=\"1\"",
|
||||
@ -1680,6 +1687,7 @@ impl Chip {
|
||||
"cargo:rustc-cfg=aes_dma_mode_ctr",
|
||||
"cargo:rustc-cfg=aes_dma_mode_cfb8",
|
||||
"cargo:rustc-cfg=aes_dma_mode_cfb128",
|
||||
"cargo:rustc-cfg=aes_has_split_text_registers",
|
||||
"cargo:rustc-cfg=assist_debug_has_sp_monitor",
|
||||
"cargo:rustc-cfg=assist_debug_has_region_monitor",
|
||||
"cargo:rustc-cfg=gpio_gpio_function=\"1\"",
|
||||
@ -1853,6 +1861,8 @@ impl Chip {
|
||||
"aes_dma_mode_cfb8",
|
||||
"aes_dma_mode_cfb128",
|
||||
"aes_dma_mode_gcm",
|
||||
"aes_has_split_text_registers",
|
||||
"aes_endianness_configurable",
|
||||
"gpio_has_bank_1",
|
||||
"gpio_gpio_function=\"1\"",
|
||||
"gpio_constant_0_input=\"60\"",
|
||||
@ -2021,6 +2031,8 @@ impl Chip {
|
||||
"cargo:rustc-cfg=aes_dma_mode_cfb8",
|
||||
"cargo:rustc-cfg=aes_dma_mode_cfb128",
|
||||
"cargo:rustc-cfg=aes_dma_mode_gcm",
|
||||
"cargo:rustc-cfg=aes_has_split_text_registers",
|
||||
"cargo:rustc-cfg=aes_endianness_configurable",
|
||||
"cargo:rustc-cfg=gpio_has_bank_1",
|
||||
"cargo:rustc-cfg=gpio_gpio_function=\"1\"",
|
||||
"cargo:rustc-cfg=gpio_constant_0_input=\"60\"",
|
||||
@ -2205,6 +2217,7 @@ impl Chip {
|
||||
"aes_dma_mode_ctr",
|
||||
"aes_dma_mode_cfb8",
|
||||
"aes_dma_mode_cfb128",
|
||||
"aes_has_split_text_registers",
|
||||
"assist_debug_has_region_monitor",
|
||||
"gpio_has_bank_1",
|
||||
"gpio_gpio_function=\"1\"",
|
||||
@ -2389,6 +2402,7 @@ impl Chip {
|
||||
"cargo:rustc-cfg=aes_dma_mode_ctr",
|
||||
"cargo:rustc-cfg=aes_dma_mode_cfb8",
|
||||
"cargo:rustc-cfg=aes_dma_mode_cfb128",
|
||||
"cargo:rustc-cfg=aes_has_split_text_registers",
|
||||
"cargo:rustc-cfg=assist_debug_has_region_monitor",
|
||||
"cargo:rustc-cfg=gpio_has_bank_1",
|
||||
"cargo:rustc-cfg=gpio_gpio_function=\"1\"",
|
||||
@ -2563,6 +2577,7 @@ impl Config {
|
||||
println!("cargo:rustc-check-cfg=cfg(uart_uart2)");
|
||||
println!("cargo:rustc-check-cfg=cfg(soc_ref_tick_hz_is_set)");
|
||||
println!("cargo:rustc-check-cfg=cfg(soc_rc_fast_clk_default_is_set)");
|
||||
println!("cargo:rustc-check-cfg=cfg(aes_endianness_configurable)");
|
||||
println!("cargo:rustc-check-cfg=cfg(gpio_has_bank_1)");
|
||||
println!("cargo:rustc-check-cfg=cfg(gpio_remap_iomux_pin_registers)");
|
||||
println!("cargo:rustc-check-cfg=cfg(i2c_master_separate_filter_config_registers)");
|
||||
@ -2635,6 +2650,7 @@ impl Config {
|
||||
println!("cargo:rustc-check-cfg=cfg(aes_dma_mode_ctr)");
|
||||
println!("cargo:rustc-check-cfg=cfg(aes_dma_mode_cfb8)");
|
||||
println!("cargo:rustc-check-cfg=cfg(aes_dma_mode_cfb128)");
|
||||
println!("cargo:rustc-check-cfg=cfg(aes_has_split_text_registers)");
|
||||
println!("cargo:rustc-check-cfg=cfg(assist_debug_has_region_monitor)");
|
||||
println!("cargo:rustc-check-cfg=cfg(esp32c6)");
|
||||
println!("cargo:rustc-check-cfg=cfg(soc_has_atomic)");
|
||||
|
@ -57,6 +57,12 @@ macro_rules! property {
|
||||
("aes.dma") => {
|
||||
false
|
||||
};
|
||||
("aes.has_split_text_registers") => {
|
||||
false
|
||||
};
|
||||
("aes.endianness_configurable") => {
|
||||
true
|
||||
};
|
||||
("gpio.has_bank_1") => {
|
||||
true
|
||||
};
|
||||
|
@ -51,6 +51,12 @@ macro_rules! property {
|
||||
("aes.dma") => {
|
||||
true
|
||||
};
|
||||
("aes.has_split_text_registers") => {
|
||||
true
|
||||
};
|
||||
("aes.endianness_configurable") => {
|
||||
false
|
||||
};
|
||||
("assist_debug.has_sp_monitor") => {
|
||||
true
|
||||
};
|
||||
|
@ -51,6 +51,12 @@ macro_rules! property {
|
||||
("aes.dma") => {
|
||||
true
|
||||
};
|
||||
("aes.has_split_text_registers") => {
|
||||
true
|
||||
};
|
||||
("aes.endianness_configurable") => {
|
||||
false
|
||||
};
|
||||
("assist_debug.has_sp_monitor") => {
|
||||
true
|
||||
};
|
||||
|
@ -51,6 +51,12 @@ macro_rules! property {
|
||||
("aes.dma") => {
|
||||
true
|
||||
};
|
||||
("aes.has_split_text_registers") => {
|
||||
true
|
||||
};
|
||||
("aes.endianness_configurable") => {
|
||||
false
|
||||
};
|
||||
("assist_debug.has_sp_monitor") => {
|
||||
true
|
||||
};
|
||||
|
@ -57,6 +57,12 @@ macro_rules! property {
|
||||
("aes.dma") => {
|
||||
true
|
||||
};
|
||||
("aes.has_split_text_registers") => {
|
||||
true
|
||||
};
|
||||
("aes.endianness_configurable") => {
|
||||
true
|
||||
};
|
||||
("gpio.has_bank_1") => {
|
||||
true
|
||||
};
|
||||
|
@ -51,6 +51,12 @@ macro_rules! property {
|
||||
("aes.dma") => {
|
||||
true
|
||||
};
|
||||
("aes.has_split_text_registers") => {
|
||||
true
|
||||
};
|
||||
("aes.endianness_configurable") => {
|
||||
false
|
||||
};
|
||||
("assist_debug.has_sp_monitor") => {
|
||||
false
|
||||
};
|
||||
|
@ -112,6 +112,8 @@ instances = [
|
||||
|
||||
[device.aes]
|
||||
support_status = "partial"
|
||||
has_split_text_registers = false
|
||||
endianness_configurable = true
|
||||
key_length = { options = [
|
||||
{ bits = 128, encrypt_mode = 0, decrypt_mode = 4 },
|
||||
{ bits = 192, encrypt_mode = 1, decrypt_mode = 5 },
|
||||
|
@ -99,6 +99,8 @@ instances = [
|
||||
|
||||
[device.aes]
|
||||
support_status = "partial"
|
||||
has_split_text_registers = true
|
||||
endianness_configurable = false
|
||||
dma = true
|
||||
dma_mode = ["ECB", "CBC", "OFB", "CTR", "CFB8", "CFB128"]
|
||||
key_length = { options = [
|
||||
|
@ -140,6 +140,8 @@ instances = [
|
||||
|
||||
[device.aes]
|
||||
support_status = "partial"
|
||||
has_split_text_registers = true
|
||||
endianness_configurable = false
|
||||
dma = true
|
||||
dma_mode = ["ECB", "CBC", "OFB", "CTR", "CFB8", "CFB128"]
|
||||
key_length = { options = [
|
||||
|
@ -119,6 +119,8 @@ instances = [
|
||||
|
||||
[device.aes]
|
||||
support_status = "partial"
|
||||
has_split_text_registers = true
|
||||
endianness_configurable = false
|
||||
dma = true
|
||||
dma_mode = ["ECB", "CBC", "OFB", "CTR", "CFB8", "CFB128"]
|
||||
key_length = { options = [
|
||||
|
@ -114,6 +114,8 @@ instances = [
|
||||
|
||||
[device.aes]
|
||||
support_status = "partial"
|
||||
has_split_text_registers = true
|
||||
endianness_configurable = true
|
||||
dma = true
|
||||
dma_mode = ["ECB", "CBC", "OFB", "CTR", "CFB8", "CFB128", "GCM"]
|
||||
key_length = { options = [
|
||||
|
@ -123,6 +123,8 @@ instances = [
|
||||
|
||||
[device.aes]
|
||||
support_status = "partial"
|
||||
has_split_text_registers = true
|
||||
endianness_configurable = false
|
||||
dma = true
|
||||
dma_mode = ["ECB", "CBC", "OFB", "CTR", "CFB8", "CFB128"]
|
||||
key_length = { options = [
|
||||
|
@ -293,6 +293,8 @@ driver_configs![
|
||||
dma: bool,
|
||||
#[serde(default)]
|
||||
dma_mode: Vec<String>,
|
||||
has_split_text_registers: bool,
|
||||
endianness_configurable: bool,
|
||||
}
|
||||
},
|
||||
AssistDebugProperties {
|
||||
|
@ -6,142 +6,80 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp_hal::{
|
||||
aes::{Aes, Mode},
|
||||
clock::CpuClock,
|
||||
};
|
||||
use hil_test as _;
|
||||
|
||||
esp_bootloader_esp_idf::esp_app_desc!();
|
||||
|
||||
struct Context<'a> {
|
||||
aes: Aes<'a>,
|
||||
const fn pad_to<const K: usize>(input: &[u8]) -> [u8; K] {
|
||||
let mut out = [0; K];
|
||||
|
||||
let in_bytes = input.len();
|
||||
assert!(in_bytes <= K);
|
||||
|
||||
let mut i = 0;
|
||||
while i < in_bytes {
|
||||
out[i] = input[i];
|
||||
i += 1;
|
||||
}
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(default_timeout = 3)]
|
||||
mod tests {
|
||||
use esp_hal::{
|
||||
Config,
|
||||
aes::{Aes, Key},
|
||||
clock::CpuClock,
|
||||
};
|
||||
use hil_test as _;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[init]
|
||||
fn init() -> Context<'static> {
|
||||
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
|
||||
let peripherals = esp_hal::init(config);
|
||||
let aes = Aes::new(peripherals.AES);
|
||||
const KEY: &[u8] = b"SUp4SeCp@sSw0rd";
|
||||
|
||||
Context { aes }
|
||||
}
|
||||
const PLAINTEXT: &[u8] = b"message";
|
||||
const PLAINTEXT_BUF: [u8; 16] = pad_to::<16>(PLAINTEXT);
|
||||
|
||||
const CIPHERTEXT_ECB_128: [u8; 16] = [
|
||||
0xb3, 0xc8, 0xd2, 0x3b, 0xa7, 0x36, 0x5f, 0x18, 0x61, 0x70, 0x0, 0x3e, 0xd9, 0x3a, 0x31,
|
||||
0x96,
|
||||
];
|
||||
#[cfg(any(esp32, esp32s2))]
|
||||
const CIPHERTEXT_ECB_192: [u8; 16] = [
|
||||
0x79, 0x88, 0x3f, 0x9d, 0x67, 0x27, 0xf4, 0x18, 0x3, 0xe3, 0xc6, 0x6a, 0x2e, 0x76, 0xb6,
|
||||
0xf7,
|
||||
];
|
||||
const CIPHERTEXT_ECB_256: [u8; 16] = [
|
||||
0x0, 0x63, 0x3f, 0x02, 0xa4, 0x53, 0x09, 0x72, 0x20, 0x6d, 0xc9, 0x08, 0x7c, 0xe5, 0xfd,
|
||||
0xc,
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn test_aes_128_encryption(mut ctx: Context<'static>) {
|
||||
let keytext = b"SUp4SeCp@sSw0rd";
|
||||
let plaintext = b"message";
|
||||
let encrypted_message = [
|
||||
0xb3, 0xc8, 0xd2, 0x3b, 0xa7, 0x36, 0x5f, 0x18, 0x61, 0x70, 0x0, 0x3e, 0xd9, 0x3a,
|
||||
0x31, 0x96,
|
||||
];
|
||||
fn test_aes_block_operation() {
|
||||
fn test_aes_block<const K: usize>(
|
||||
aes: &mut Aes<'_>,
|
||||
plaintext: [u8; 16],
|
||||
ciphertext: [u8; 16],
|
||||
) where
|
||||
Key: From<[u8; K]>,
|
||||
{
|
||||
let mut block_buf = plaintext;
|
||||
aes.encrypt(&mut block_buf, pad_to::<K>(KEY));
|
||||
assert_eq!(&block_buf[..ciphertext.len()], ciphertext);
|
||||
|
||||
let mut keybuf = [0_u8; 16];
|
||||
keybuf[..keytext.len()].copy_from_slice(keytext);
|
||||
let mut block_buf = ciphertext;
|
||||
aes.decrypt(&mut block_buf, pad_to::<K>(KEY));
|
||||
assert_eq!(&block_buf[..plaintext.len()], plaintext);
|
||||
}
|
||||
|
||||
let mut block_buf = [0_u8; 16];
|
||||
block_buf[..plaintext.len()].copy_from_slice(plaintext);
|
||||
let p = esp_hal::init(Config::default().with_cpu_clock(CpuClock::max()));
|
||||
let mut aes = Aes::new(p.AES);
|
||||
|
||||
let mut block = block_buf.clone();
|
||||
ctx.aes.process(&mut block, Mode::Encryption128, keybuf);
|
||||
assert_eq!(block, encrypted_message);
|
||||
}
|
||||
test_aes_block::<16>(&mut aes, PLAINTEXT_BUF, CIPHERTEXT_ECB_128);
|
||||
|
||||
#[test]
|
||||
fn test_aes_128_decryption(mut ctx: Context<'static>) {
|
||||
let keytext = b"SUp4SeCp@sSw0rd";
|
||||
let plaintext = b"message";
|
||||
let mut encrypted_message = [
|
||||
0xb3, 0xc8, 0xd2, 0x3b, 0xa7, 0x36, 0x5f, 0x18, 0x61, 0x70, 0x0, 0x3e, 0xd9, 0x3a,
|
||||
0x31, 0x96,
|
||||
];
|
||||
#[cfg(any(esp32, esp32s2))]
|
||||
test_aes_block::<24>(&mut aes, PLAINTEXT_BUF, CIPHERTEXT_ECB_192);
|
||||
|
||||
let mut keybuf = [0_u8; 16];
|
||||
keybuf[..keytext.len()].copy_from_slice(keytext);
|
||||
|
||||
ctx.aes
|
||||
.process(&mut encrypted_message, Mode::Decryption128, keybuf);
|
||||
assert_eq!(&encrypted_message[..plaintext.len()], plaintext);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "esp32", feature = "esp32s2"))]
|
||||
fn test_aes_192_encryption(mut ctx: Context<'static>) {
|
||||
let keytext = b"SUp4SeCp@sSw0rd";
|
||||
let plaintext = b"message";
|
||||
let encrypted_message = [
|
||||
0x79, 0x88, 0x3f, 0x9d, 0x67, 0x27, 0xf4, 0x18, 0x3, 0xe3, 0xc6, 0x6a, 0x2e, 0x76,
|
||||
0xb6, 0xf7,
|
||||
];
|
||||
|
||||
let mut keybuf = [0_u8; 16];
|
||||
keybuf[..keytext.len()].copy_from_slice(keytext);
|
||||
|
||||
let mut block_buf = [0_u8; 16];
|
||||
block_buf[..plaintext.len()].copy_from_slice(plaintext);
|
||||
|
||||
let mut block = block_buf.clone();
|
||||
ctx.aes.process(&mut block, Mode::Encryption192, keybuf);
|
||||
assert_eq!(block, encrypted_message);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "esp32", feature = "esp32s2"))]
|
||||
fn test_aes_192_decryption(mut ctx: Context<'static>) {
|
||||
let keytext = b"SUp4SeCp@sSw0rd";
|
||||
let plaintext = b"message";
|
||||
let mut encrypted_message = [
|
||||
0x79, 0x88, 0x3f, 0x9d, 0x67, 0x27, 0xf4, 0x18, 0x3, 0xe3, 0xc6, 0x6a, 0x2e, 0x76,
|
||||
0xb6, 0xf7,
|
||||
];
|
||||
|
||||
let mut keybuf = [0_u8; 16];
|
||||
keybuf[..keytext.len()].copy_from_slice(keytext);
|
||||
|
||||
ctx.aes
|
||||
.process(&mut encrypted_message, Mode::Decryption192, keybuf);
|
||||
assert_eq!(&encrypted_message[..plaintext.len()], plaintext);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_aes_256_encryption(mut ctx: Context<'static>) {
|
||||
let keytext = b"SUp4SeCp@sSw0rd";
|
||||
let plaintext = b"message";
|
||||
let encrypted_message = [
|
||||
0x0, 0x63, 0x3f, 0x2, 0xa4, 0x53, 0x9, 0x72, 0x20, 0x6d, 0xc9, 0x8, 0x7c, 0xe5, 0xfd,
|
||||
0xc,
|
||||
];
|
||||
|
||||
let mut keybuf = [0_u8; 16];
|
||||
keybuf[..keytext.len()].copy_from_slice(keytext);
|
||||
|
||||
let mut block_buf = [0_u8; 16];
|
||||
block_buf[..plaintext.len()].copy_from_slice(plaintext);
|
||||
|
||||
let mut block = block_buf.clone();
|
||||
ctx.aes.process(&mut block, Mode::Encryption256, keybuf);
|
||||
assert_eq!(block, encrypted_message);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_aes_256_decryption(mut ctx: Context<'static>) {
|
||||
let keytext = b"SUp4SeCp@sSw0rd";
|
||||
let plaintext = b"message";
|
||||
let mut encrypted_message = [
|
||||
0x0, 0x63, 0x3f, 0x2, 0xa4, 0x53, 0x9, 0x72, 0x20, 0x6d, 0xc9, 0x8, 0x7c, 0xe5, 0xfd,
|
||||
0xc,
|
||||
];
|
||||
|
||||
let mut keybuf = [0_u8; 16];
|
||||
keybuf[..keytext.len()].copy_from_slice(keytext);
|
||||
|
||||
ctx.aes
|
||||
.process(&mut encrypted_message, Mode::Decryption256, keybuf);
|
||||
assert_eq!(&encrypted_message[..plaintext.len()], plaintext);
|
||||
test_aes_block::<32>(&mut aes, PLAINTEXT_BUF, CIPHERTEXT_ECB_256);
|
||||
}
|
||||
}
|
||||
|
@ -7,30 +7,103 @@
|
||||
#![no_main]
|
||||
|
||||
use esp_hal::{
|
||||
aes::{Aes, Mode, dma::CipherMode},
|
||||
aes::{Aes, Key, Operation, dma::CipherMode},
|
||||
clock::CpuClock,
|
||||
dma::{DmaRxBuf, DmaTxBuf},
|
||||
dma_buffers,
|
||||
peripherals::Peripherals,
|
||||
};
|
||||
use hil_test as _;
|
||||
|
||||
esp_bootloader_esp_idf::esp_app_desc!();
|
||||
|
||||
const fn pad_to<const K: usize>(input: &[u8]) -> [u8; K] {
|
||||
let mut out = [0; K];
|
||||
|
||||
let in_bytes = input.len();
|
||||
assert!(in_bytes <= K);
|
||||
|
||||
let mut i = 0;
|
||||
while i < in_bytes {
|
||||
out[i] = input[i];
|
||||
i += 1;
|
||||
}
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
const DMA_BUFFER_SIZE: usize = 16;
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(default_timeout = 3)]
|
||||
mod tests {
|
||||
use esp_hal::dma::{DmaRxBuf, DmaTxBuf};
|
||||
use esp_hal::aes::dma::AesDma;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[init]
|
||||
fn init() -> Peripherals {
|
||||
esp_hal::init(esp_hal::Config::default())
|
||||
}
|
||||
const KEY: &[u8] = b"SUp4SeCp@sSw0rd";
|
||||
|
||||
const PLAINTEXT: &[u8] = b"message";
|
||||
const PLAINTEXT_BUF: [u8; 16] = pad_to::<16>(PLAINTEXT);
|
||||
|
||||
const CIPHERTEXT_ECB_128: [u8; 16] = [
|
||||
0xb3, 0xc8, 0xd2, 0x3b, 0xa7, 0x36, 0x5f, 0x18, 0x61, 0x70, 0x0, 0x3e, 0xd9, 0x3a, 0x31,
|
||||
0x96,
|
||||
];
|
||||
const CIPHERTEXT_ECB_256: [u8; 16] = [
|
||||
0x0, 0x63, 0x3f, 0x02, 0xa4, 0x53, 0x09, 0x72, 0x20, 0x6d, 0xc9, 0x08, 0x7c, 0xe5, 0xfd,
|
||||
0xc,
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn test_aes_128_dma_encryption(peripherals: Peripherals) {
|
||||
fn test_aes_dma_ecb() {
|
||||
fn test_aes_ecb<const K: usize>(
|
||||
mut aes: AesDma<'_>,
|
||||
plaintext: [u8; 16],
|
||||
ciphertext: [u8; 16],
|
||||
) -> AesDma<'_>
|
||||
where
|
||||
Key: From<[u8; K]>,
|
||||
{
|
||||
let (output, rx_descriptors, input, tx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE);
|
||||
let mut output = DmaRxBuf::new(rx_descriptors, output).unwrap();
|
||||
let mut input = DmaTxBuf::new(tx_descriptors, input).unwrap();
|
||||
|
||||
// Encrypt
|
||||
input.as_mut_slice().copy_from_slice(&plaintext);
|
||||
let transfer = aes
|
||||
.process(
|
||||
1,
|
||||
output,
|
||||
input,
|
||||
Operation::Encrypt,
|
||||
CipherMode::Ecb,
|
||||
pad_to::<K>(KEY),
|
||||
)
|
||||
.map_err(|e| e.0)
|
||||
.unwrap();
|
||||
(aes, output, input) = transfer.wait();
|
||||
assert_eq!(output.as_slice(), ciphertext);
|
||||
|
||||
// Decrypt
|
||||
input.as_mut_slice().copy_from_slice(&ciphertext);
|
||||
let transfer = aes
|
||||
.process(
|
||||
1,
|
||||
output,
|
||||
input,
|
||||
Operation::Decrypt,
|
||||
CipherMode::Ecb,
|
||||
pad_to::<K>(KEY),
|
||||
)
|
||||
.map_err(|e| e.0)
|
||||
.unwrap();
|
||||
(aes, output, _) = transfer.wait();
|
||||
assert_eq!(output.as_slice(), plaintext);
|
||||
|
||||
aes
|
||||
}
|
||||
let peripherals = esp_hal::init(esp_hal::Config::default().with_cpu_clock(CpuClock::max()));
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(esp32s2)] {
|
||||
let dma_channel = peripherals.DMA_CRYPTO;
|
||||
@ -39,179 +112,9 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
let (output, rx_descriptors, input, tx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE);
|
||||
let mut output = DmaRxBuf::new(rx_descriptors, output).unwrap();
|
||||
let mut input = DmaTxBuf::new(tx_descriptors, input).unwrap();
|
||||
|
||||
let aes = Aes::new(peripherals.AES).with_dma(dma_channel);
|
||||
|
||||
let keytext = b"SUp4SeCp@sSw0rd";
|
||||
let mut keybuf = [0_u8; 16];
|
||||
keybuf[..keytext.len()].copy_from_slice(keytext);
|
||||
|
||||
let plaintext = b"message";
|
||||
input.as_mut_slice()[..plaintext.len()].copy_from_slice(plaintext);
|
||||
|
||||
let encrypted_message = [
|
||||
0xb3, 0xc8, 0xd2, 0x3b, 0xa7, 0x36, 0x5f, 0x18, 0x61, 0x70, 0x0, 0x3e, 0xd9, 0x3a,
|
||||
0x31, 0x96,
|
||||
];
|
||||
|
||||
let transfer = aes
|
||||
.process(
|
||||
1,
|
||||
output,
|
||||
input,
|
||||
Mode::Encryption128,
|
||||
CipherMode::Ecb,
|
||||
keybuf,
|
||||
)
|
||||
.map_err(|e| e.0)
|
||||
.unwrap();
|
||||
(_, output, _) = transfer.wait();
|
||||
|
||||
let mut encrypted_output = [0u8; 16];
|
||||
(&mut encrypted_output[..]).copy_from_slice(output.as_slice());
|
||||
|
||||
assert_eq!(encrypted_output, encrypted_message);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_aes_128_dma_decryption(peripherals: Peripherals) {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(esp32s2)] {
|
||||
let dma_channel = peripherals.DMA_CRYPTO;
|
||||
} else {
|
||||
let dma_channel = peripherals.DMA_CH0;
|
||||
}
|
||||
}
|
||||
|
||||
let (output, rx_descriptors, input, tx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE);
|
||||
let mut output = DmaRxBuf::new(rx_descriptors, output).unwrap();
|
||||
let mut input = DmaTxBuf::new(tx_descriptors, input).unwrap();
|
||||
|
||||
let aes = Aes::new(peripherals.AES).with_dma(dma_channel);
|
||||
|
||||
let keytext = b"SUp4SeCp@sSw0rd";
|
||||
let mut keybuf = [0_u8; 16];
|
||||
keybuf[..keytext.len()].copy_from_slice(keytext);
|
||||
|
||||
let plaintext = b"message";
|
||||
let encrypted_message = [
|
||||
0xb3, 0xc8, 0xd2, 0x3b, 0xa7, 0x36, 0x5f, 0x18, 0x61, 0x70, 0x0, 0x3e, 0xd9, 0x3a,
|
||||
0x31, 0x96,
|
||||
];
|
||||
input.as_mut_slice().copy_from_slice(&encrypted_message);
|
||||
|
||||
let transfer = aes
|
||||
.process(
|
||||
1,
|
||||
output,
|
||||
input,
|
||||
Mode::Decryption128,
|
||||
CipherMode::Ecb,
|
||||
keybuf,
|
||||
)
|
||||
.map_err(|e| e.0)
|
||||
.unwrap();
|
||||
(_, output, _) = transfer.wait();
|
||||
|
||||
let mut decrypted_output = [0u8; 16];
|
||||
(&mut decrypted_output[..]).copy_from_slice(output.as_slice());
|
||||
|
||||
assert_eq!(&decrypted_output[..plaintext.len()], plaintext);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_aes_256_dma_encryption(peripherals: Peripherals) {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(esp32s2)] {
|
||||
let dma_channel = peripherals.DMA_CRYPTO;
|
||||
} else {
|
||||
let dma_channel = peripherals.DMA_CH0;
|
||||
}
|
||||
}
|
||||
|
||||
let (output, rx_descriptors, input, tx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE);
|
||||
let mut output = DmaRxBuf::new(rx_descriptors, output).unwrap();
|
||||
let mut input = DmaTxBuf::new(tx_descriptors, input).unwrap();
|
||||
|
||||
let aes = Aes::new(peripherals.AES).with_dma(dma_channel);
|
||||
|
||||
let keytext = b"SUp4SeCp@sSw0rd";
|
||||
let mut keybuf = [0_u8; 16];
|
||||
keybuf[..keytext.len()].copy_from_slice(keytext);
|
||||
|
||||
let plaintext = b"message";
|
||||
input.as_mut_slice()[..plaintext.len()].copy_from_slice(plaintext);
|
||||
|
||||
let encrypted_message = [
|
||||
0x0, 0x63, 0x3f, 0x2, 0xa4, 0x53, 0x9, 0x72, 0x20, 0x6d, 0xc9, 0x8, 0x7c, 0xe5, 0xfd,
|
||||
0xc,
|
||||
];
|
||||
|
||||
let transfer = aes
|
||||
.process(
|
||||
1,
|
||||
output,
|
||||
input,
|
||||
Mode::Encryption256,
|
||||
CipherMode::Ecb,
|
||||
keybuf,
|
||||
)
|
||||
.map_err(|e| e.0)
|
||||
.unwrap();
|
||||
(_, output, _) = transfer.wait();
|
||||
|
||||
let mut encrypted_output = [0u8; 16];
|
||||
(&mut encrypted_output[..]).copy_from_slice(output.as_slice());
|
||||
|
||||
assert_eq!(encrypted_output, encrypted_message);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_aes_256_dma_decryption(peripherals: Peripherals) {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(esp32s2)] {
|
||||
let dma_channel = peripherals.DMA_CRYPTO;
|
||||
} else {
|
||||
let dma_channel = peripherals.DMA_CH0;
|
||||
}
|
||||
}
|
||||
|
||||
let (output, rx_descriptors, input, tx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE);
|
||||
let mut output = DmaRxBuf::new(rx_descriptors, output).unwrap();
|
||||
let mut input = DmaTxBuf::new(tx_descriptors, input).unwrap();
|
||||
|
||||
let aes = Aes::new(peripherals.AES).with_dma(dma_channel);
|
||||
|
||||
let keytext = b"SUp4SeCp@sSw0rd";
|
||||
let mut keybuf = [0_u8; 16];
|
||||
keybuf[..keytext.len()].copy_from_slice(keytext);
|
||||
|
||||
let plaintext = b"message";
|
||||
let encrypted_message = [
|
||||
0x0, 0x63, 0x3f, 0x2, 0xa4, 0x53, 0x9, 0x72, 0x20, 0x6d, 0xc9, 0x8, 0x7c, 0xe5, 0xfd,
|
||||
0xc,
|
||||
];
|
||||
input.as_mut_slice().copy_from_slice(&encrypted_message);
|
||||
|
||||
let transfer = aes
|
||||
.process(
|
||||
1,
|
||||
output,
|
||||
input,
|
||||
Mode::Decryption256,
|
||||
CipherMode::Ecb,
|
||||
keybuf,
|
||||
)
|
||||
.map_err(|e| e.0)
|
||||
.unwrap();
|
||||
(_, output, _) = transfer.wait();
|
||||
|
||||
let mut decrypted_output = [0u8; 16];
|
||||
(&mut decrypted_output[..]).copy_from_slice(output.as_slice());
|
||||
|
||||
assert_eq!(&decrypted_output[..plaintext.len()], plaintext);
|
||||
let aes = test_aes_ecb::<16>(aes, PLAINTEXT_BUF, CIPHERTEXT_ECB_128);
|
||||
let _ = test_aes_ecb::<32>(aes, PLAINTEXT_BUF, CIPHERTEXT_ECB_256);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user