CCM mode functional.
This commit is contained in:
parent
fec26e8960
commit
690b2118c6
1 changed files with 293 additions and 79 deletions
|
@ -1,6 +1,6 @@
|
||||||
//! Crypto Accelerator (CRYP)
|
//! Crypto Accelerator (CRYP)
|
||||||
|
use core::cmp::min;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||||
|
|
||||||
use crate::pac;
|
use crate::pac;
|
||||||
|
@ -21,7 +21,7 @@ pub trait Cipher<'c> {
|
||||||
const REQUIRES_PADDING: bool = false;
|
const REQUIRES_PADDING: bool = false;
|
||||||
|
|
||||||
/// Returns the symmetric key.
|
/// Returns the symmetric key.
|
||||||
fn key(&self) -> &'c [u8];
|
fn key(&self) -> &[u8];
|
||||||
|
|
||||||
/// Returns the initialization vector.
|
/// Returns the initialization vector.
|
||||||
fn iv(&self) -> &[u8];
|
fn iv(&self) -> &[u8];
|
||||||
|
@ -36,10 +36,25 @@ pub trait Cipher<'c> {
|
||||||
fn init_phase(&self, _p: &pac::cryp::Cryp) {}
|
fn init_phase(&self, _p: &pac::cryp::Cryp) {}
|
||||||
|
|
||||||
/// Called prior to processing the last data block for cipher-specific operations.
|
/// Called prior to processing the last data block for cipher-specific operations.
|
||||||
fn pre_final_block(&self, _p: &pac::cryp::Cryp) {}
|
fn pre_final_block(&self, _p: &pac::cryp::Cryp, _dir: Direction) -> [u32; 4] {
|
||||||
|
return [0; 4];
|
||||||
|
}
|
||||||
|
|
||||||
/// Called after processing the last data block for cipher-specific operations.
|
/// Called after processing the last data block for cipher-specific operations.
|
||||||
fn post_final_block(&self, _p: &pac::cryp::Cryp, _dir: Direction, _int_data: &[u8; AES_BLOCK_SIZE]) {}
|
fn post_final_block(
|
||||||
|
&self,
|
||||||
|
_p: &pac::cryp::Cryp,
|
||||||
|
_dir: Direction,
|
||||||
|
_int_data: &[u8; AES_BLOCK_SIZE],
|
||||||
|
_temp1: [u32; 4],
|
||||||
|
_padding_mask: [u8; 16],
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Called prior to processing the first associated data block for cipher-specific operations.
|
||||||
|
fn get_header_block(&self) -> &[u8] {
|
||||||
|
return [0; 0].as_slice();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This trait enables restriction of ciphers to specific key sizes.
|
/// This trait enables restriction of ciphers to specific key sizes.
|
||||||
|
@ -204,17 +219,27 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGcm<'c, KEY_SIZE> {
|
||||||
while p.cr().read().crypen() {}
|
while p.cr().read().crypen() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pre_final_block(&self, p: &pac::cryp::Cryp) {
|
fn pre_final_block(&self, p: &pac::cryp::Cryp, dir: Direction) -> [u32; 4] {
|
||||||
//Handle special GCM partial block process.
|
//Handle special GCM partial block process.
|
||||||
p.cr().modify(|w| w.set_crypen(false));
|
if dir == Direction::Encrypt {
|
||||||
p.cr().modify(|w| w.set_algomode3(false));
|
p.cr().modify(|w| w.set_crypen(false));
|
||||||
p.cr().modify(|w| w.set_algomode0(6));
|
p.cr().modify(|w| w.set_algomode3(false));
|
||||||
let iv1r = p.csgcmccmr(7).read() - 1;
|
p.cr().modify(|w| w.set_algomode0(6));
|
||||||
p.init(1).ivrr().write_value(iv1r);
|
let iv1r = p.csgcmccmr(7).read() - 1;
|
||||||
p.cr().modify(|w| w.set_crypen(true));
|
p.init(1).ivrr().write_value(iv1r);
|
||||||
|
p.cr().modify(|w| w.set_crypen(true));
|
||||||
|
}
|
||||||
|
[0; 4]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_final_block(&self, p: &pac::cryp::Cryp, dir: Direction, int_data: &[u8; AES_BLOCK_SIZE]) {
|
fn post_final_block(
|
||||||
|
&self,
|
||||||
|
p: &pac::cryp::Cryp,
|
||||||
|
dir: Direction,
|
||||||
|
int_data: &[u8; AES_BLOCK_SIZE],
|
||||||
|
_temp1: [u32; 4],
|
||||||
|
_padding_mask: [u8; 16],
|
||||||
|
) {
|
||||||
if dir == Direction::Encrypt {
|
if dir == Direction::Encrypt {
|
||||||
//Handle special GCM partial block process.
|
//Handle special GCM partial block process.
|
||||||
p.cr().modify(|w| w.set_crypen(false));
|
p.cr().modify(|w| w.set_crypen(false));
|
||||||
|
@ -281,17 +306,27 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGmac<'c, KEY_SIZE> {
|
||||||
while p.cr().read().crypen() {}
|
while p.cr().read().crypen() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pre_final_block(&self, p: &pac::cryp::Cryp) {
|
fn pre_final_block(&self, p: &pac::cryp::Cryp, dir: Direction) -> [u32; 4] {
|
||||||
//Handle special GCM partial block process.
|
//Handle special GCM partial block process.
|
||||||
p.cr().modify(|w| w.set_crypen(false));
|
if dir == Direction::Encrypt {
|
||||||
p.cr().modify(|w| w.set_algomode3(false));
|
p.cr().modify(|w| w.set_crypen(false));
|
||||||
p.cr().modify(|w| w.set_algomode0(6));
|
p.cr().modify(|w| w.set_algomode3(false));
|
||||||
let iv1r = p.csgcmccmr(7).read() - 1;
|
p.cr().modify(|w| w.set_algomode0(6));
|
||||||
p.init(1).ivrr().write_value(iv1r);
|
let iv1r = p.csgcmccmr(7).read() - 1;
|
||||||
p.cr().modify(|w| w.set_crypen(true));
|
p.init(1).ivrr().write_value(iv1r);
|
||||||
|
p.cr().modify(|w| w.set_crypen(true));
|
||||||
|
}
|
||||||
|
[0; 4]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_final_block(&self, p: &pac::cryp::Cryp, dir: Direction, int_data: &[u8; AES_BLOCK_SIZE]) {
|
fn post_final_block(
|
||||||
|
&self,
|
||||||
|
p: &pac::cryp::Cryp,
|
||||||
|
dir: Direction,
|
||||||
|
int_data: &[u8; AES_BLOCK_SIZE],
|
||||||
|
_temp1: [u32; 4],
|
||||||
|
_padding_mask: [u8; 16],
|
||||||
|
) {
|
||||||
if dir == Direction::Encrypt {
|
if dir == Direction::Encrypt {
|
||||||
//Handle special GCM partial block process.
|
//Handle special GCM partial block process.
|
||||||
p.cr().modify(|w| w.set_crypen(false));
|
p.cr().modify(|w| w.set_crypen(false));
|
||||||
|
@ -320,49 +355,180 @@ impl<'c> CipherSized for AesGmac<'c, { 192 / 8 }> {}
|
||||||
impl<'c> CipherSized for AesGmac<'c, { 256 / 8 }> {}
|
impl<'c> CipherSized for AesGmac<'c, { 256 / 8 }> {}
|
||||||
impl<'c, const KEY_SIZE: usize> CipherAuthenticated for AesGmac<'c, KEY_SIZE> {}
|
impl<'c, const KEY_SIZE: usize> CipherAuthenticated for AesGmac<'c, KEY_SIZE> {}
|
||||||
|
|
||||||
// struct AesCcm<'c, const KEY_SIZE: usize> {
|
pub struct AesCcm<'c, const KEY_SIZE: usize> {
|
||||||
// iv: &'c [u8],
|
key: &'c [u8; KEY_SIZE],
|
||||||
// key: &'c [u8; KEY_SIZE],
|
aad_header: [u8; 6],
|
||||||
// aad_len: usize,
|
aad_header_len: usize,
|
||||||
// payload_len: usize,
|
block0: [u8; 16],
|
||||||
// }
|
ctr: [u8; 16],
|
||||||
|
}
|
||||||
|
|
||||||
// impl<'c, const KEY_SIZE: usize> AesCcm<'c, KEY_SIZE> {
|
impl<'c, const KEY_SIZE: usize> AesCcm<'c, KEY_SIZE> {
|
||||||
// pub fn new(&self, key: &[u8; KEY_SIZE], iv: &[u8], aad_len: usize, payload_len: usize) {
|
pub fn new(key: &'c [u8; KEY_SIZE], iv: &'c [u8], aad_len: usize, payload_len: usize, tag_len: u8) -> Self {
|
||||||
// if iv.len() > 13 {
|
if (iv.len()) > 13 || (iv.len() < 7) {
|
||||||
// panic!("CCM IV length must be 13 bytes or less.");
|
panic!("CCM IV length must be 7-13 bytes.");
|
||||||
// }
|
}
|
||||||
// self.key = key;
|
if (tag_len < 4) || (tag_len > 16) {
|
||||||
// self.iv = iv;
|
panic!("Tag length must be between 4 and 16 bytes.");
|
||||||
// self.aad_len = aad_len;
|
}
|
||||||
// self.payload_len = payload_len;
|
if tag_len % 2 > 0 {
|
||||||
// }
|
panic!("Tag length must be a multiple of 2 bytes.");
|
||||||
// }
|
}
|
||||||
|
|
||||||
// impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesCcm<'c, KEY_SIZE> {
|
let mut aad_header: [u8; 6] = [0; 6];
|
||||||
// const BLOCK_SIZE: usize = AES_BLOCK_SIZE;
|
let mut aad_header_len = 0;
|
||||||
|
let mut block0: [u8; 16] = [0; 16];
|
||||||
|
if aad_len != 0 {
|
||||||
|
if aad_len < 65280 {
|
||||||
|
aad_header[0] = (aad_len >> 8) as u8 & 0xFF;
|
||||||
|
aad_header[1] = aad_len as u8 & 0xFF;
|
||||||
|
aad_header_len = 2;
|
||||||
|
} else {
|
||||||
|
aad_header[0] = 0xFF;
|
||||||
|
aad_header[1] = 0xFE;
|
||||||
|
let aad_len_bytes: [u8; 4] = aad_len.to_be_bytes();
|
||||||
|
aad_header[2] = aad_len_bytes[0];
|
||||||
|
aad_header[3] = aad_len_bytes[1];
|
||||||
|
aad_header[4] = aad_len_bytes[2];
|
||||||
|
aad_header[5] = aad_len_bytes[3];
|
||||||
|
aad_header_len = 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let total_aad_len = aad_header_len + aad_len;
|
||||||
|
let mut aad_padding_len = 16 - (total_aad_len % 16);
|
||||||
|
if aad_padding_len == 16 {
|
||||||
|
aad_padding_len = 0;
|
||||||
|
}
|
||||||
|
aad_header_len += aad_padding_len;
|
||||||
|
let total_aad_len_padded = aad_header_len + aad_len;
|
||||||
|
if total_aad_len_padded > 0 {
|
||||||
|
block0[0] = 0x40;
|
||||||
|
}
|
||||||
|
block0[0] |= (((tag_len - 2) >> 1) & 0x07) << 3;
|
||||||
|
block0[0] |= ((15 - (iv.len() as u8)) - 1) & 0x07;
|
||||||
|
block0[1..1 + iv.len()].copy_from_slice(iv);
|
||||||
|
let payload_len_bytes: [u8; 4] = payload_len.to_be_bytes();
|
||||||
|
if iv.len() <= 11 {
|
||||||
|
block0[12] = payload_len_bytes[0];
|
||||||
|
} else if payload_len_bytes[0] > 0 {
|
||||||
|
panic!("Message is too large for given IV size.");
|
||||||
|
}
|
||||||
|
if iv.len() <= 12 {
|
||||||
|
block0[13] = payload_len_bytes[1];
|
||||||
|
} else if payload_len_bytes[1] > 0 {
|
||||||
|
panic!("Message is too large for given IV size.");
|
||||||
|
}
|
||||||
|
block0[14] = payload_len_bytes[2];
|
||||||
|
block0[15] = payload_len_bytes[3];
|
||||||
|
let mut ctr: [u8; 16] = [0; 16];
|
||||||
|
ctr[0] = block0[0] & 0x07;
|
||||||
|
ctr[1..1 + iv.len()].copy_from_slice(&block0[1..1 + iv.len()]);
|
||||||
|
ctr[15] = 0x01;
|
||||||
|
|
||||||
// fn key(&self) -> &'c [u8] {
|
return Self {
|
||||||
// self.key
|
key: key,
|
||||||
// }
|
aad_header: aad_header,
|
||||||
|
aad_header_len: aad_header_len,
|
||||||
|
block0: block0,
|
||||||
|
ctr: ctr,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// fn iv(&self) -> &'c [u8] {
|
impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesCcm<'c, KEY_SIZE> {
|
||||||
// self.iv
|
const BLOCK_SIZE: usize = AES_BLOCK_SIZE;
|
||||||
// }
|
|
||||||
|
|
||||||
// fn set_algomode(&self, p: &pac::cryp::Cryp) {
|
fn key(&self) -> &'c [u8] {
|
||||||
// p.cr().modify(|w| w.set_algomode0(1));
|
self.key
|
||||||
// p.cr().modify(|w| w.set_algomode3(true));
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// fn init_phase(&self, p: &pac::cryp::Cryp) {
|
fn iv(&self) -> &[u8] {
|
||||||
// todo!();
|
self.ctr.as_slice()
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// impl<'c> CipherSized for AesCcm<'c, { 128 / 8 }> {}
|
fn set_algomode(&self, p: &pac::cryp::Cryp) {
|
||||||
// impl<'c> CipherSized for AesCcm<'c, { 192 / 8 }> {}
|
p.cr().modify(|w| w.set_algomode0(1));
|
||||||
// impl<'c> CipherSized for AesCcm<'c, { 256 / 8 }> {}
|
p.cr().modify(|w| w.set_algomode3(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_phase(&self, p: &pac::cryp::Cryp) {
|
||||||
|
p.cr().modify(|w| w.set_gcm_ccmph(0));
|
||||||
|
|
||||||
|
let mut index = 0;
|
||||||
|
let end_index = index + Self::BLOCK_SIZE;
|
||||||
|
// Write block in
|
||||||
|
while index < end_index {
|
||||||
|
let mut in_word: [u8; 4] = [0; 4];
|
||||||
|
in_word.copy_from_slice(&self.block0[index..index + 4]);
|
||||||
|
p.din().write_value(u32::from_ne_bytes(in_word));
|
||||||
|
index += 4;
|
||||||
|
}
|
||||||
|
p.cr().modify(|w| w.set_crypen(true));
|
||||||
|
while p.cr().read().crypen() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_header_block(&self) -> &[u8] {
|
||||||
|
return &self.aad_header[0..self.aad_header_len];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pre_final_block(&self, p: &pac::cryp::Cryp, dir: Direction) -> [u32; 4] {
|
||||||
|
//Handle special CCM partial block process.
|
||||||
|
let mut temp1 = [0; 4];
|
||||||
|
if dir == Direction::Decrypt {
|
||||||
|
p.cr().modify(|w| w.set_crypen(false));
|
||||||
|
let iv1temp = p.init(1).ivrr().read();
|
||||||
|
temp1[0] = p.csgcmccmr(0).read();
|
||||||
|
temp1[1] = p.csgcmccmr(1).read();
|
||||||
|
temp1[2] = p.csgcmccmr(2).read();
|
||||||
|
temp1[3] = p.csgcmccmr(3).read();
|
||||||
|
p.init(1).ivrr().write_value(iv1temp);
|
||||||
|
p.cr().modify(|w| w.set_algomode3(false));
|
||||||
|
p.cr().modify(|w| w.set_algomode0(6));
|
||||||
|
p.cr().modify(|w| w.set_crypen(true));
|
||||||
|
}
|
||||||
|
return temp1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn post_final_block(
|
||||||
|
&self,
|
||||||
|
p: &pac::cryp::Cryp,
|
||||||
|
dir: Direction,
|
||||||
|
int_data: &[u8; AES_BLOCK_SIZE],
|
||||||
|
temp1: [u32; 4],
|
||||||
|
padding_mask: [u8; 16],
|
||||||
|
) {
|
||||||
|
if dir == Direction::Decrypt {
|
||||||
|
//Handle special CCM partial block process.
|
||||||
|
let mut intdata_o: [u32; 4] = [0; 4];
|
||||||
|
for i in 0..intdata_o.len() {
|
||||||
|
intdata_o[i] = p.dout().read();
|
||||||
|
}
|
||||||
|
let mut temp2 = [0; 4];
|
||||||
|
temp2[0] = p.csgcmccmr(0).read();
|
||||||
|
temp2[1] = p.csgcmccmr(1).read();
|
||||||
|
temp2[2] = p.csgcmccmr(2).read();
|
||||||
|
temp2[3] = p.csgcmccmr(3).read();
|
||||||
|
p.cr().write(|w| w.set_algomode3(true));
|
||||||
|
p.cr().write(|w| w.set_algomode0(1));
|
||||||
|
p.cr().modify(|w| w.set_gcm_ccmph(3));
|
||||||
|
// Header phase
|
||||||
|
p.cr().modify(|w| w.set_gcm_ccmph(1));
|
||||||
|
let mut in_data: [u32; 4] = [0; 4];
|
||||||
|
for i in 0..in_data.len() {
|
||||||
|
let mut mask_bytes: [u8; 4] = [0; 4];
|
||||||
|
mask_bytes.copy_from_slice(&padding_mask[(i * 4)..(i * 4) + 4]);
|
||||||
|
let mask_word = u32::from_le_bytes(mask_bytes);
|
||||||
|
in_data[i] = intdata_o[i] & mask_word;
|
||||||
|
in_data[i] = in_data[i] ^ temp1[i] ^ temp2[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'c> CipherSized for AesCcm<'c, { 128 / 8 }> {}
|
||||||
|
impl<'c> CipherSized for AesCcm<'c, { 192 / 8 }> {}
|
||||||
|
impl<'c> CipherSized for AesCcm<'c, { 256 / 8 }> {}
|
||||||
|
impl<'c, const KEY_SIZE: usize> CipherAuthenticated for AesCcm<'c, KEY_SIZE> {}
|
||||||
|
|
||||||
/// Holds the state information for a cipher operation.
|
/// Holds the state information for a cipher operation.
|
||||||
/// Allows suspending/resuming of cipher operations.
|
/// Allows suspending/resuming of cipher operations.
|
||||||
|
@ -371,6 +537,7 @@ pub struct Context<'c, C: Cipher<'c> + CipherSized> {
|
||||||
cipher: &'c C,
|
cipher: &'c C,
|
||||||
dir: Direction,
|
dir: Direction,
|
||||||
last_block_processed: bool,
|
last_block_processed: bool,
|
||||||
|
header_processed: bool,
|
||||||
aad_complete: bool,
|
aad_complete: bool,
|
||||||
cr: u32,
|
cr: u32,
|
||||||
iv: [u32; 4],
|
iv: [u32; 4],
|
||||||
|
@ -378,6 +545,8 @@ pub struct Context<'c, C: Cipher<'c> + CipherSized> {
|
||||||
csgcm: [u32; 8],
|
csgcm: [u32; 8],
|
||||||
header_len: u64,
|
header_len: u64,
|
||||||
payload_len: u64,
|
payload_len: u64,
|
||||||
|
aad_buffer: [u8; 16],
|
||||||
|
aad_buffer_len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Selects whether the crypto processor operates in encryption or decryption mode.
|
/// Selects whether the crypto processor operates in encryption or decryption mode.
|
||||||
|
@ -420,6 +589,9 @@ impl<'d, T: Instance> Cryp<'d, T> {
|
||||||
payload_len: 0,
|
payload_len: 0,
|
||||||
cipher: cipher,
|
cipher: cipher,
|
||||||
phantom_data: PhantomData,
|
phantom_data: PhantomData,
|
||||||
|
header_processed: false,
|
||||||
|
aad_buffer: [0; 16],
|
||||||
|
aad_buffer_len: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
T::regs().cr().modify(|w| w.set_crypen(false));
|
T::regs().cr().modify(|w| w.set_crypen(false));
|
||||||
|
@ -492,16 +664,9 @@ impl<'d, T: Instance> Cryp<'d, T> {
|
||||||
) {
|
) {
|
||||||
self.load_context(ctx);
|
self.load_context(ctx);
|
||||||
|
|
||||||
let last_block_remainder = aad.len() % C::BLOCK_SIZE;
|
|
||||||
|
|
||||||
// Perform checks for correctness.
|
// Perform checks for correctness.
|
||||||
if ctx.aad_complete {
|
if ctx.aad_complete {
|
||||||
panic!("Cannot update AAD after calling 'update'!")
|
panic!("Cannot update AAD after starting payload!")
|
||||||
}
|
|
||||||
if !last_aad_block {
|
|
||||||
if last_block_remainder != 0 {
|
|
||||||
panic!("Input length must be a multiple of {} bytes.", C::BLOCK_SIZE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.header_len += aad.len() as u64;
|
ctx.header_len += aad.len() as u64;
|
||||||
|
@ -511,11 +676,49 @@ impl<'d, T: Instance> Cryp<'d, T> {
|
||||||
T::regs().cr().modify(|w| w.set_gcm_ccmph(1));
|
T::regs().cr().modify(|w| w.set_gcm_ccmph(1));
|
||||||
T::regs().cr().modify(|w| w.set_crypen(true));
|
T::regs().cr().modify(|w| w.set_crypen(true));
|
||||||
|
|
||||||
// Load data into core, block by block.
|
// First write the header B1 block if not yet written.
|
||||||
let num_full_blocks = aad.len() / C::BLOCK_SIZE;
|
if !ctx.header_processed {
|
||||||
for block in 0..num_full_blocks {
|
ctx.header_processed = true;
|
||||||
let mut index = block * C::BLOCK_SIZE;
|
let header = ctx.cipher.get_header_block();
|
||||||
let end_index = index + C::BLOCK_SIZE;
|
ctx.aad_buffer[0..header.len()].copy_from_slice(header);
|
||||||
|
ctx.aad_buffer_len += header.len();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the header block to make a full block.
|
||||||
|
let len_to_copy = min(aad.len(), C::BLOCK_SIZE - ctx.aad_buffer_len);
|
||||||
|
ctx.aad_buffer[ctx.aad_buffer_len..ctx.aad_buffer_len + len_to_copy].copy_from_slice(&aad[..len_to_copy]);
|
||||||
|
ctx.aad_buffer_len += len_to_copy;
|
||||||
|
ctx.aad_buffer[ctx.aad_buffer_len..].fill(0);
|
||||||
|
let mut aad_len_remaining = aad.len() - len_to_copy;
|
||||||
|
|
||||||
|
if ctx.aad_buffer_len < C::BLOCK_SIZE {
|
||||||
|
// The buffer isn't full and this is the last buffer, so process it as is (already padded).
|
||||||
|
if last_aad_block {
|
||||||
|
let mut index = 0;
|
||||||
|
let end_index = C::BLOCK_SIZE;
|
||||||
|
// Write block in
|
||||||
|
while index < end_index {
|
||||||
|
let mut in_word: [u8; 4] = [0; 4];
|
||||||
|
in_word.copy_from_slice(&aad[index..index + 4]);
|
||||||
|
T::regs().din().write_value(u32::from_ne_bytes(in_word));
|
||||||
|
index += 4;
|
||||||
|
}
|
||||||
|
// Block until input FIFO is empty.
|
||||||
|
while !T::regs().sr().read().ifem() {}
|
||||||
|
|
||||||
|
// Switch to payload phase.
|
||||||
|
ctx.aad_complete = true;
|
||||||
|
T::regs().cr().modify(|w| w.set_crypen(false));
|
||||||
|
T::regs().cr().modify(|w| w.set_gcm_ccmph(2));
|
||||||
|
T::regs().cr().modify(|w| w.fflush());
|
||||||
|
} else {
|
||||||
|
// Just return because we don't yet have a full block to process.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Load the full block from the buffer.
|
||||||
|
let mut index = 0;
|
||||||
|
let end_index = C::BLOCK_SIZE;
|
||||||
// Write block in
|
// Write block in
|
||||||
while index < end_index {
|
while index < end_index {
|
||||||
let mut in_word: [u8; 4] = [0; 4];
|
let mut in_word: [u8; 4] = [0; 4];
|
||||||
|
@ -527,20 +730,26 @@ impl<'d, T: Instance> Cryp<'d, T> {
|
||||||
while !T::regs().sr().read().ifem() {}
|
while !T::regs().sr().read().ifem() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the final block, which is incomplete.
|
// Handle a partial block that is passed in.
|
||||||
if last_block_remainder > 0 {
|
ctx.aad_buffer_len = 0;
|
||||||
let mut last_block: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE];
|
let leftovers = aad_len_remaining % C::BLOCK_SIZE;
|
||||||
last_block[..last_block_remainder].copy_from_slice(&aad[aad.len() - last_block_remainder..aad.len()]);
|
ctx.aad_buffer[..leftovers].copy_from_slice(&aad[aad.len() - leftovers..aad.len()]);
|
||||||
let mut index = 0;
|
aad_len_remaining -= leftovers;
|
||||||
let end_index = C::BLOCK_SIZE;
|
assert_eq!(aad_len_remaining % C::BLOCK_SIZE, 0);
|
||||||
|
|
||||||
|
// Load full data blocks into core.
|
||||||
|
let num_full_blocks = aad_len_remaining / C::BLOCK_SIZE;
|
||||||
|
for _ in 0..num_full_blocks {
|
||||||
|
let mut index = len_to_copy;
|
||||||
|
let end_index = len_to_copy + C::BLOCK_SIZE;
|
||||||
// Write block in
|
// Write block in
|
||||||
while index < end_index {
|
while index < end_index {
|
||||||
let mut in_word: [u8; 4] = [0; 4];
|
let mut in_word: [u8; 4] = [0; 4];
|
||||||
in_word.copy_from_slice(&last_block[index..index + 4]);
|
in_word.copy_from_slice(&aad[index..index + 4]);
|
||||||
T::regs().din().write_value(u32::from_ne_bytes(in_word));
|
T::regs().din().write_value(u32::from_ne_bytes(in_word));
|
||||||
index += 4;
|
index += 4;
|
||||||
}
|
}
|
||||||
// Block until input FIFO is empty
|
// Block until input FIFO is empty.
|
||||||
while !T::regs().sr().read().ifem() {}
|
while !T::regs().sr().read().ifem() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,7 +839,7 @@ impl<'d, T: Instance> Cryp<'d, T> {
|
||||||
|
|
||||||
// Handle the final block, which is incomplete.
|
// Handle the final block, which is incomplete.
|
||||||
if last_block_remainder > 0 {
|
if last_block_remainder > 0 {
|
||||||
ctx.cipher.pre_final_block(&T::regs());
|
let temp1 = ctx.cipher.pre_final_block(&T::regs(), ctx.dir);
|
||||||
|
|
||||||
let mut intermediate_data: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE];
|
let mut intermediate_data: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE];
|
||||||
let mut last_block: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE];
|
let mut last_block: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE];
|
||||||
|
@ -660,10 +869,15 @@ impl<'d, T: Instance> Cryp<'d, T> {
|
||||||
output[output_len - last_block_remainder..output_len]
|
output[output_len - last_block_remainder..output_len]
|
||||||
.copy_from_slice(&intermediate_data[0..last_block_remainder]);
|
.copy_from_slice(&intermediate_data[0..last_block_remainder]);
|
||||||
|
|
||||||
ctx.cipher.post_final_block(&T::regs(), ctx.dir, &intermediate_data);
|
let mut mask: [u8; 16] = [0; 16];
|
||||||
|
mask[..last_block_remainder].fill(0xFF);
|
||||||
|
ctx.cipher
|
||||||
|
.post_final_block(&T::regs(), ctx.dir, &intermediate_data, temp1, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.payload_len += input.len() as u64;
|
ctx.payload_len += input.len() as u64;
|
||||||
|
|
||||||
|
self.store_context(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function only needs to be called for GCM, CCM, and GMAC modes to
|
/// This function only needs to be called for GCM, CCM, and GMAC modes to
|
||||||
|
|
Loading…
Add table
Reference in a new issue