use core::{
convert::TryInto,
ops::{Deref, DerefMut},
pin::Pin,
};
use as_slice::{AsMutSlice, AsSlice};
use nb::block;
use void::Void;
use crate::{
dma,
pac::{
self,
aes::{self, cr},
},
rcc::{Enable, Rcc, Reset},
};
pub struct AES {
aes: pac::AES,
}
impl AES {
pub fn new(aes: pac::AES, rcc: &mut Rcc) -> Self {
pac::AES::enable(rcc);
pac::AES::reset(rcc);
aes.cr.write(|w| {
w.dmaouten().set_bit();
w.dmainen().set_bit();
w.errie().clear_bit();
w.ccfie().clear_bit()
});
Self { aes }
}
pub fn enable<M>(self, mode: M, key: [u32; 4]) -> Stream
where
M: Mode,
{
self.aes.keyr0.write(|w| w.bits(key[0]));
self.aes.keyr1.write(|w| w.bits(key[1]));
self.aes.keyr2.write(|w| w.bits(key[2]));
self.aes.keyr3.write(|w| w.bits(key[3]));
mode.prepare(&self.aes);
self.aes.cr.modify(|_, w| {
mode.select(w);
w.datatype().bits(0b10);
w.en().set_bit()
});
Stream {
aes: self,
rx: Rx(()),
tx: Tx(()),
}
}
}
pub struct Stream {
aes: AES,
pub tx: Tx,
pub rx: Rx,
}
impl Stream {
pub fn process(&mut self, input: &Block) -> Result<Block, Error> {
self.tx.write(input)?;
let output = block!(self.rx.read()).unwrap();
Ok(output)
}
pub fn disable(self) -> AES {
self.aes.aes.cr.modify(|_, w| w.en().clear_bit());
self.aes
}
}
pub struct Tx(());
impl Tx {
pub fn write(&mut self, block: &Block) -> Result<(), Error> {
let (dinr, sr) = unsafe {
let aes = &*pac::AES::ptr();
(&aes.dinr, &aes.sr)
};
for i in (0..4).rev() {
dinr.write(|w| {
let i = i * 4;
let word = &block[i..i + 4];
let word = word.try_into().unwrap();
let word = u32::from_le_bytes(word);
w.bits(word)
});
}
if sr.read().wrerr().bit_is_set() {
return Err(Error::Busy);
}
Ok(())
}
pub fn write_all<Buffer, Channel>(
self,
dma: &mut dma::Handle,
buffer: Pin<Buffer>,
channel: Channel,
) -> Transfer<Self, Channel, Buffer, dma::Ready>
where
Self: dma::Target<Channel>,
Buffer: Deref + 'static,
Buffer::Target: AsSlice<Element = u8>,
Channel: dma::Channel,
{
assert!(buffer.as_slice().len() % 16 == 0);
let address = &unsafe { &*pac::AES::ptr() }.dinr as *const _ as u32;
unsafe {
Transfer::new(
dma,
self,
channel,
buffer,
address,
dma::Priority::high(),
dma::Direction::memory_to_peripheral(),
)
}
}
}
pub struct Rx(());
impl Rx {
pub fn read(&mut self) -> nb::Result<Block, Void> {
let (sr, doutr, cr) = unsafe {
let aes = &*pac::AES::ptr();
(&aes.sr, &aes.doutr, &aes.cr)
};
if sr.read().ccf().bit_is_clear() {
return Err(nb::Error::WouldBlock);
}
let mut block = [0; 16];
for i in (0..4).rev() {
let i = i * 4;
let word = doutr.read().bits();
let word = word.to_le_bytes();
(&mut block[i..i + 4]).copy_from_slice(&word);
}
cr.modify(|_, w| w.ccfc().set_bit());
Ok(block)
}
pub fn read_all<Buffer, Channel>(
self,
dma: &mut dma::Handle,
buffer: Pin<Buffer>,
channel: Channel,
) -> Transfer<Self, Channel, Buffer, dma::Ready>
where
Self: dma::Target<Channel>,
Buffer: DerefMut + 'static,
Buffer::Target: AsMutSlice<Element = u8>,
Channel: dma::Channel,
{
assert!(buffer.as_slice().len() % 16 == 0);
let address = &unsafe { &*pac::AES::ptr() }.doutr as *const _ as u32;
unsafe {
Transfer::new(
dma,
self,
channel,
buffer,
address,
dma::Priority::very_high(),
dma::Direction::peripheral_to_memory(),
)
}
}
}
pub trait Mode {
fn prepare(&self, _: &aes::RegisterBlock);
fn select(&self, _: &mut cr::W);
}
impl dyn Mode {
pub fn ecb_encrypt() -> ECB<Encrypt> {
ECB(Encrypt)
}
pub fn ecb_decrypt() -> ECB<Decrypt> {
ECB(Decrypt)
}
pub fn cbc_encrypt(init_vector: [u32; 4]) -> CBC<Encrypt> {
CBC {
_mode: Encrypt,
init_vector,
}
}
pub fn cbc_decrypt(init_vector: [u32; 4]) -> CBC<Decrypt> {
CBC {
_mode: Decrypt,
init_vector,
}
}
pub fn ctr(init_vector: [u32; 3]) -> CTR {
CTR { init_vector }
}
}
pub struct ECB<Mode>(Mode);
impl Mode for ECB<Encrypt> {
fn prepare(&self, _: &aes::RegisterBlock) {
}
fn select(&self, w: &mut cr::W) {
unsafe {
w.chmod().bits(0b00);
w.mode().bits(0b00);
}
}
}
impl Mode for ECB<Decrypt> {
fn prepare(&self, aes: &aes::RegisterBlock) {
derive_key(aes)
}
fn select(&self, w: &mut cr::W) {
unsafe {
w.chmod().bits(0b00);
w.mode().bits(0b10);
}
}
}
pub struct CBC<Mode> {
_mode: Mode,
init_vector: [u32; 4],
}
impl Mode for CBC<Encrypt> {
fn prepare(&self, aes: &aes::RegisterBlock) {
aes.ivr3.write(|w| w.bits(self.init_vector[0]));
aes.ivr2.write(|w| w.bits(self.init_vector[1]));
aes.ivr1.write(|w| w.bits(self.init_vector[2]));
aes.ivr0.write(|w| w.bits(self.init_vector[3]));
}
fn select(&self, w: &mut cr::W) {
unsafe {
w.chmod().bits(0b01);
w.mode().bits(0b00);
}
}
}
impl Mode for CBC<Decrypt> {
fn prepare(&self, aes: &aes::RegisterBlock) {
derive_key(aes);
aes.ivr3.write(|w| w.bits(self.init_vector[0]));
aes.ivr2.write(|w| w.bits(self.init_vector[1]));
aes.ivr1.write(|w| w.bits(self.init_vector[2]));
aes.ivr0.write(|w| w.bits(self.init_vector[3]));
}
fn select(&self, w: &mut cr::W) {
unsafe {
w.chmod().bits(0b01);
w.mode().bits(0b10);
}
}
}
pub struct CTR {
init_vector: [u32; 3],
}
impl Mode for CTR {
fn prepare(&self, aes: &aes::RegisterBlock) {
aes.ivr3.write(|w| w.bits(self.init_vector[0]));
aes.ivr2.write(|w| w.bits(self.init_vector[1]));
aes.ivr1.write(|w| w.bits(self.init_vector[2]));
aes.ivr0.write(|w| w.bits(0x0001)); }
fn select(&self, w: &mut cr::W) {
unsafe {
w.chmod().bits(0b10);
w.mode().bits(0b00);
}
}
}
fn derive_key(aes: &aes::RegisterBlock) {
aes.cr.modify(|_, w| w.mode().bits(0b01));
aes.cr.modify(|_, w| w.en().set_bit());
while aes.sr.read().ccf().bit_is_clear() {}
}
pub struct Encrypt;
pub struct Decrypt;
pub type Block = [u8; 16];
#[derive(Debug)]
pub enum Error {
Busy,
}
pub struct Transfer<Target, Channel, Buffer, State> {
buffer: Pin<Buffer>,
inner: dma::Transfer<Target, Channel, dma::PtrBuffer<u32>, State>,
}
impl<Target, Channel, Buffer> Transfer<Target, Channel, Buffer, dma::Ready>
where
Target: dma::Target<Channel>,
Channel: dma::Channel,
Buffer: Deref + 'static,
Buffer::Target: AsSlice<Element = u8>,
{
unsafe fn new(
dma: &mut dma::Handle,
target: Target,
channel: Channel,
buffer: Pin<Buffer>,
address: u32,
priority: dma::Priority,
dir: dma::Direction,
) -> Self {
let num_words = buffer.as_slice().len() / 4;
let transfer = dma::Transfer::new(
dma,
target,
channel,
Pin::new(dma::PtrBuffer {
ptr: buffer.as_slice().as_ptr() as *const u32,
len: num_words,
}),
num_words,
address,
priority,
dir,
false,
);
Self {
buffer,
inner: transfer,
}
}
pub fn enable_interrupts(&mut self, interrupts: dma::Interrupts) {
self.inner.enable_interrupts(interrupts)
}
pub fn start(self) -> Transfer<Target, Channel, Buffer, dma::Started> {
Transfer {
buffer: self.buffer,
inner: self.inner.start(),
}
}
}
impl<Target, Channel, Buffer> Transfer<Target, Channel, Buffer, dma::Started>
where
Channel: dma::Channel,
{
pub fn is_active(&self) -> bool {
self.inner.is_active()
}
pub fn wait(self) -> dma::TransferResourcesResult<Target, Channel, Buffer> {
let (res, err) = match self.inner.wait() {
Ok(res) => (res, None),
Err((res, err)) => (res, Some(err)),
};
let res = dma::TransferResources {
target: res.target,
channel: res.channel,
buffer: self.buffer,
};
match err {
None => Ok(res),
Some(err) => Err((res, err)),
}
}
}