Add cryp configuration.
This commit is contained in:
parent
fd5058875a
commit
79e5e8b052
2 changed files with 229 additions and 0 deletions
227
embassy-stm32/src/cryp/mod.rs
Normal file
227
embassy-stm32/src/cryp/mod.rs
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||||
|
use pac::cryp::Init;
|
||||||
|
|
||||||
|
use crate::pac;
|
||||||
|
use crate::peripherals::CRYP;
|
||||||
|
use crate::rcc::sealed::RccPeripheral;
|
||||||
|
use crate::{interrupt, peripherals, Peripheral};
|
||||||
|
|
||||||
|
pub struct Context<'c> {
|
||||||
|
key: &'c [u8],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
pub enum Algorithm {
|
||||||
|
AES,
|
||||||
|
DES,
|
||||||
|
TDES,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
pub enum Mode {
|
||||||
|
ECB,
|
||||||
|
CBC,
|
||||||
|
CTR,
|
||||||
|
GCM,
|
||||||
|
GMAC,
|
||||||
|
CCM,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
pub enum Direction {
|
||||||
|
Encrypt,
|
||||||
|
Decrypt,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Crypto Accelerator Driver
|
||||||
|
pub struct Cryp<'d, T: Instance, In, Out> {
|
||||||
|
_peripheral: PeripheralRef<'d, T>,
|
||||||
|
indma: PeripheralRef<'d, In>,
|
||||||
|
outdma: PeripheralRef<'d, Out>,
|
||||||
|
}
|
||||||
|
|
||||||
|
type InitVector<'v> = Option<&'v [u8]>;
|
||||||
|
|
||||||
|
impl<'d, T: Instance, In, Out> Cryp<'d, T, In, Out> {
|
||||||
|
/// Create a new CRYP driver.
|
||||||
|
pub fn new(
|
||||||
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
|
indma: impl Peripheral<P = In> + 'd,
|
||||||
|
outdma: impl Peripheral<P = Out> + 'd,
|
||||||
|
) -> Self {
|
||||||
|
CRYP::enable_and_reset();
|
||||||
|
into_ref!(peri, indma, outdma);
|
||||||
|
let instance = Self {
|
||||||
|
_peripheral: peri,
|
||||||
|
indma: indma,
|
||||||
|
outdma: outdma,
|
||||||
|
};
|
||||||
|
instance
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start a new cipher operation.
|
||||||
|
/// Key size must be 128, 192, or 256 bits.
|
||||||
|
pub fn start(key: &[u8], iv: InitVector, algo: Algorithm, mode: Mode, dir: Direction) -> Context {
|
||||||
|
T::regs().cr().modify(|w| w.set_crypen(false));
|
||||||
|
|
||||||
|
let keylen = key.len() * 8;
|
||||||
|
let ivlen;
|
||||||
|
if let Some(iv) = iv {
|
||||||
|
ivlen = iv.len() * 8;
|
||||||
|
} else {
|
||||||
|
ivlen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks for correctness
|
||||||
|
if algo == Algorithm::AES {
|
||||||
|
match keylen {
|
||||||
|
128 => T::regs().cr().write(|w| w.set_keysize(0)),
|
||||||
|
192 => T::regs().cr().write(|w| w.set_keysize(1)),
|
||||||
|
256 => T::regs().cr().write(|w| w.set_keysize(2)),
|
||||||
|
_ => panic!("Key length must be 128, 192, or 256 bits."),
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == Mode::GCM) && (ivlen != 96) {
|
||||||
|
panic!("IV length must be 96 bits for GCM.");
|
||||||
|
} else if (mode == Mode::CBC) && (ivlen != 128) {
|
||||||
|
panic!("IV length must be 128 bits for CBC.");
|
||||||
|
} else if (mode == Mode::CCM) && (ivlen != 128) {
|
||||||
|
panic!("IV length must be 128 bits for CCM.");
|
||||||
|
} else if (mode == Mode::CTR) && (ivlen != 64) {
|
||||||
|
panic!("IV length must be 64 bits for CTR.");
|
||||||
|
} else if (mode == Mode::GCM) && (ivlen != 96) {
|
||||||
|
panic!("IV length must be 96 bits for GCM.");
|
||||||
|
} else if (mode == Mode::GMAC) && (ivlen != 96) {
|
||||||
|
panic!("IV length must be 96 bits for GMAC.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the key into the registers.
|
||||||
|
let mut keyidx = 0;
|
||||||
|
let mut keyword: [u8; 4] = [0; 4];
|
||||||
|
if keylen > 192 {
|
||||||
|
keyword.copy_from_slice(&key[keyidx..keyidx + 4]);
|
||||||
|
keyidx += 4;
|
||||||
|
T::regs().key(0).klr().write_value(u32::from_be_bytes(keyword));
|
||||||
|
keyword.copy_from_slice(&key[keyidx..keyidx + 4]);
|
||||||
|
keyidx += 4;
|
||||||
|
T::regs().key(0).krr().write_value(u32::from_be_bytes(keyword));
|
||||||
|
}
|
||||||
|
if keylen > 128 {
|
||||||
|
keyword.copy_from_slice(&key[keyidx..keyidx + 4]);
|
||||||
|
keyidx += 4;
|
||||||
|
T::regs().key(1).klr().write_value(u32::from_be_bytes(keyword));
|
||||||
|
keyword.copy_from_slice(&key[keyidx..keyidx + 4]);
|
||||||
|
keyidx += 4;
|
||||||
|
T::regs().key(1).krr().write_value(u32::from_be_bytes(keyword));
|
||||||
|
}
|
||||||
|
if keylen > 64 {
|
||||||
|
keyword.copy_from_slice(&key[keyidx..keyidx + 4]);
|
||||||
|
keyidx += 4;
|
||||||
|
T::regs().key(2).klr().write_value(u32::from_be_bytes(keyword));
|
||||||
|
keyword.copy_from_slice(&key[keyidx..keyidx + 4]);
|
||||||
|
keyidx += 4;
|
||||||
|
T::regs().key(2).krr().write_value(u32::from_be_bytes(keyword));
|
||||||
|
}
|
||||||
|
keyword.copy_from_slice(&key[keyidx..keyidx + 4]);
|
||||||
|
keyidx += 4;
|
||||||
|
T::regs().key(3).klr().write_value(u32::from_be_bytes(keyword));
|
||||||
|
keyword.copy_from_slice(&key[keyidx..keyidx + 4]);
|
||||||
|
T::regs().key(3).krr().write_value(u32::from_be_bytes(keyword));
|
||||||
|
|
||||||
|
// Set data type to 8-bit. This will match software implementations.
|
||||||
|
T::regs().cr().modify(|w| w.set_datatype(2));
|
||||||
|
|
||||||
|
if algo == Algorithm::AES {
|
||||||
|
if (mode == Mode::ECB) || (mode == Mode::CBC) {
|
||||||
|
T::regs().cr().modify(|w| w.set_algomode0(7));
|
||||||
|
T::regs().cr().modify(|w| w.set_crypen(true));
|
||||||
|
while T::regs().sr().read().busy() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match mode {
|
||||||
|
Mode::ECB => T::regs().cr().modify(|w| w.set_algomode0(4)),
|
||||||
|
Mode::CBC => T::regs().cr().modify(|w| w.set_algomode0(5)),
|
||||||
|
Mode::CTR => T::regs().cr().modify(|w| w.set_algomode0(6)),
|
||||||
|
Mode::GCM => T::regs().cr().modify(|w| w.set_algomode0(8)),
|
||||||
|
Mode::GMAC => T::regs().cr().modify(|w| w.set_algomode0(8)),
|
||||||
|
Mode::CCM => T::regs().cr().modify(|w| w.set_algomode0(9)),
|
||||||
|
}
|
||||||
|
} else if algo == Algorithm::DES {
|
||||||
|
match mode {
|
||||||
|
Mode::ECB => T::regs().cr().modify(|w| w.set_algomode0(2)),
|
||||||
|
Mode::CBC => T::regs().cr().modify(|w| w.set_algomode0(3)),
|
||||||
|
_ => panic!("Only ECB and CBC modes are valid for DES."),
|
||||||
|
}
|
||||||
|
} else if algo == Algorithm::TDES {
|
||||||
|
match mode {
|
||||||
|
Mode::ECB => T::regs().cr().modify(|w| w.set_algomode0(0)),
|
||||||
|
Mode::CBC => T::regs().cr().modify(|w| w.set_algomode0(1)),
|
||||||
|
_ => panic!("Only ECB and CBC modes are valid for TDES."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set encrypt/decrypt
|
||||||
|
if dir == Direction::Encrypt {
|
||||||
|
T::regs().cr().modify(|w| w.set_algodir(false));
|
||||||
|
} else {
|
||||||
|
T::regs().cr().modify(|w| w.set_algodir(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the IV into the registers.
|
||||||
|
if let Some(iv) = iv {
|
||||||
|
let mut iv_idx = 0;
|
||||||
|
let mut iv_word: [u8; 4] = [0; 4];
|
||||||
|
iv_word.copy_from_slice(&iv[iv_idx..iv_idx + 4]);
|
||||||
|
iv_idx += 4;
|
||||||
|
T::regs().init(0).ivlr().write_value(u32::from_be_bytes(iv_word));
|
||||||
|
iv_word.copy_from_slice(&iv[iv_idx..iv_idx + 4]);
|
||||||
|
iv_idx += 4;
|
||||||
|
if iv.len() >= 12 {
|
||||||
|
T::regs().init(0).ivrr().write_value(u32::from_be_bytes(iv_word));
|
||||||
|
iv_word.copy_from_slice(&iv[iv_idx..iv_idx + 4]);
|
||||||
|
iv_idx += 4;
|
||||||
|
}
|
||||||
|
if iv.len() >= 16 {
|
||||||
|
T::regs().init(1).ivlr().write_value(u32::from_be_bytes(iv_word));
|
||||||
|
iv_word.copy_from_slice(&iv[iv_idx..iv_idx + 4]);
|
||||||
|
T::regs().init(1).ivrr().write_value(u32::from_be_bytes(iv_word));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush in/out FIFOs
|
||||||
|
T::regs().cr().modify(|w| w.fflush());
|
||||||
|
|
||||||
|
let ctx = Context { key: key };
|
||||||
|
|
||||||
|
ctx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) mod sealed {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub trait Instance {
|
||||||
|
fn regs() -> pac::cryp::Cryp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// RNG instance trait.
|
||||||
|
pub trait Instance: sealed::Instance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send {
|
||||||
|
/// Interrupt for this RNG instance.
|
||||||
|
type Interrupt: interrupt::typelevel::Interrupt;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach_interrupt!(
|
||||||
|
($inst:ident, rng, CRYP, GLOBAL, $irq:ident) => {
|
||||||
|
impl Instance for peripherals::$inst {
|
||||||
|
type Interrupt = crate::interrupt::typelevel::$irq;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl sealed::Instance for peripherals::$inst {
|
||||||
|
fn regs() -> crate::pac::cryp::Cryp {
|
||||||
|
crate::pac::$inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
);
|
|
@ -34,6 +34,8 @@ pub mod adc;
|
||||||
pub mod can;
|
pub mod can;
|
||||||
#[cfg(crc)]
|
#[cfg(crc)]
|
||||||
pub mod crc;
|
pub mod crc;
|
||||||
|
#[cfg(cryp)]
|
||||||
|
pub mod cryp;
|
||||||
#[cfg(dac)]
|
#[cfg(dac)]
|
||||||
pub mod dac;
|
pub mod dac;
|
||||||
#[cfg(dcmi)]
|
#[cfg(dcmi)]
|
||||||
|
|
Loading…
Add table
Reference in a new issue