aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaleb Garrett <[email protected]>2024-02-20 11:54:39 -0500
committerCaleb Garrett <[email protected]>2024-02-25 20:59:07 -0500
commit690b2118c6fdad88bf1e595b6a0c0afdb0583d28 (patch)
tree12cc9250a42c8f5aaab14d0fc776cd2acc167f6e
parentfec26e896052cc0eac6bfa6415a4ebad5352d1d9 (diff)
CCM mode functional.
-rw-r--r--embassy-stm32/src/cryp/mod.rs386
1 files changed, 300 insertions, 86 deletions
diff --git a/embassy-stm32/src/cryp/mod.rs b/embassy-stm32/src/cryp/mod.rs
index 29c1db12e..fe248def1 100644
--- a/embassy-stm32/src/cryp/mod.rs
+++ b/embassy-stm32/src/cryp/mod.rs
@@ -1,6 +1,6 @@
1//! Crypto Accelerator (CRYP) 1//! Crypto Accelerator (CRYP)
2use core::cmp::min;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3
4use embassy_hal_internal::{into_ref, PeripheralRef}; 4use embassy_hal_internal::{into_ref, PeripheralRef};
5 5
6use crate::pac; 6use crate::pac;
@@ -21,7 +21,7 @@ pub trait Cipher<'c> {
21 const REQUIRES_PADDING: bool = false; 21 const REQUIRES_PADDING: bool = false;
22 22
23 /// Returns the symmetric key. 23 /// Returns the symmetric key.
24 fn key(&self) -> &'c [u8]; 24 fn key(&self) -> &[u8];
25 25
26 /// Returns the initialization vector. 26 /// Returns the initialization vector.
27 fn iv(&self) -> &[u8]; 27 fn iv(&self) -> &[u8];
@@ -36,10 +36,25 @@ pub trait Cipher<'c> {
36 fn init_phase(&self, _p: &pac::cryp::Cryp) {} 36 fn init_phase(&self, _p: &pac::cryp::Cryp) {}
37 37
38 /// Called prior to processing the last data block for cipher-specific operations. 38 /// Called prior to processing the last data block for cipher-specific operations.
39 fn pre_final_block(&self, _p: &pac::cryp::Cryp) {} 39 fn pre_final_block(&self, _p: &pac::cryp::Cryp, _dir: Direction) -> [u32; 4] {
40 return [0; 4];
41 }
40 42
41 /// Called after processing the last data block for cipher-specific operations. 43 /// Called after processing the last data block for cipher-specific operations.
42 fn post_final_block(&self, _p: &pac::cryp::Cryp, _dir: Direction, _int_data: &[u8; AES_BLOCK_SIZE]) {} 44 fn post_final_block(
45 &self,
46 _p: &pac::cryp::Cryp,
47 _dir: Direction,
48 _int_data: &[u8; AES_BLOCK_SIZE],
49 _temp1: [u32; 4],
50 _padding_mask: [u8; 16],
51 ) {
52 }
53
54 /// Called prior to processing the first associated data block for cipher-specific operations.
55 fn get_header_block(&self) -> &[u8] {
56 return [0; 0].as_slice();
57 }
43} 58}
44 59
45/// This trait enables restriction of ciphers to specific key sizes. 60/// 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> {
204 while p.cr().read().crypen() {} 219 while p.cr().read().crypen() {}
205 } 220 }
206 221
207 fn pre_final_block(&self, p: &pac::cryp::Cryp) { 222 fn pre_final_block(&self, p: &pac::cryp::Cryp, dir: Direction) -> [u32; 4] {
208 //Handle special GCM partial block process. 223 //Handle special GCM partial block process.
209 p.cr().modify(|w| w.set_crypen(false)); 224 if dir == Direction::Encrypt {
210 p.cr().modify(|w| w.set_algomode3(false)); 225 p.cr().modify(|w| w.set_crypen(false));
211 p.cr().modify(|w| w.set_algomode0(6)); 226 p.cr().modify(|w| w.set_algomode3(false));
212 let iv1r = p.csgcmccmr(7).read() - 1; 227 p.cr().modify(|w| w.set_algomode0(6));
213 p.init(1).ivrr().write_value(iv1r); 228 let iv1r = p.csgcmccmr(7).read() - 1;
214 p.cr().modify(|w| w.set_crypen(true)); 229 p.init(1).ivrr().write_value(iv1r);
230 p.cr().modify(|w| w.set_crypen(true));
231 }
232 [0; 4]
215 } 233 }
216 234
217 fn post_final_block(&self, p: &pac::cryp::Cryp, dir: Direction, int_data: &[u8; AES_BLOCK_SIZE]) { 235 fn post_final_block(
236 &self,
237 p: &pac::cryp::Cryp,
238 dir: Direction,
239 int_data: &[u8; AES_BLOCK_SIZE],
240 _temp1: [u32; 4],
241 _padding_mask: [u8; 16],
242 ) {
218 if dir == Direction::Encrypt { 243 if dir == Direction::Encrypt {
219 //Handle special GCM partial block process. 244 //Handle special GCM partial block process.
220 p.cr().modify(|w| w.set_crypen(false)); 245 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> {
281 while p.cr().read().crypen() {} 306 while p.cr().read().crypen() {}
282 } 307 }
283 308
284 fn pre_final_block(&self, p: &pac::cryp::Cryp) { 309 fn pre_final_block(&self, p: &pac::cryp::Cryp, dir: Direction) -> [u32; 4] {
285 //Handle special GCM partial block process. 310 //Handle special GCM partial block process.
286 p.cr().modify(|w| w.set_crypen(false)); 311 if dir == Direction::Encrypt {
287 p.cr().modify(|w| w.set_algomode3(false)); 312 p.cr().modify(|w| w.set_crypen(false));
288 p.cr().modify(|w| w.set_algomode0(6)); 313 p.cr().modify(|w| w.set_algomode3(false));
289 let iv1r = p.csgcmccmr(7).read() - 1; 314 p.cr().modify(|w| w.set_algomode0(6));
290 p.init(1).ivrr().write_value(iv1r); 315 let iv1r = p.csgcmccmr(7).read() - 1;
291 p.cr().modify(|w| w.set_crypen(true)); 316 p.init(1).ivrr().write_value(iv1r);
317 p.cr().modify(|w| w.set_crypen(true));
318 }
319 [0; 4]
292 } 320 }
293 321
294 fn post_final_block(&self, p: &pac::cryp::Cryp, dir: Direction, int_data: &[u8; AES_BLOCK_SIZE]) { 322 fn post_final_block(
323 &self,
324 p: &pac::cryp::Cryp,
325 dir: Direction,
326 int_data: &[u8; AES_BLOCK_SIZE],
327 _temp1: [u32; 4],
328 _padding_mask: [u8; 16],
329 ) {
295 if dir == Direction::Encrypt { 330 if dir == Direction::Encrypt {
296 //Handle special GCM partial block process. 331 //Handle special GCM partial block process.
297 p.cr().modify(|w| w.set_crypen(false)); 332 p.cr().modify(|w| w.set_crypen(false));
@@ -320,49 +355,180 @@ impl<'c> CipherSized for AesGmac<'c, { 192 / 8 }> {}
320impl<'c> CipherSized for AesGmac<'c, { 256 / 8 }> {} 355impl<'c> CipherSized for AesGmac<'c, { 256 / 8 }> {}
321impl<'c, const KEY_SIZE: usize> CipherAuthenticated for AesGmac<'c, KEY_SIZE> {} 356impl<'c, const KEY_SIZE: usize> CipherAuthenticated for AesGmac<'c, KEY_SIZE> {}
322 357
323// struct AesCcm<'c, const KEY_SIZE: usize> { 358pub struct AesCcm<'c, const KEY_SIZE: usize> {
324// iv: &'c [u8], 359 key: &'c [u8; KEY_SIZE],
325// key: &'c [u8; KEY_SIZE], 360 aad_header: [u8; 6],
326// aad_len: usize, 361 aad_header_len: usize,
327// payload_len: usize, 362 block0: [u8; 16],
328// } 363 ctr: [u8; 16],
329 364}
330// impl<'c, const KEY_SIZE: usize> AesCcm<'c, KEY_SIZE> { 365
331// pub fn new(&self, key: &[u8; KEY_SIZE], iv: &[u8], aad_len: usize, payload_len: usize) { 366impl<'c, const KEY_SIZE: usize> AesCcm<'c, KEY_SIZE> {
332// if iv.len() > 13 { 367 pub fn new(key: &'c [u8; KEY_SIZE], iv: &'c [u8], aad_len: usize, payload_len: usize, tag_len: u8) -> Self {
333// panic!("CCM IV length must be 13 bytes or less."); 368 if (iv.len()) > 13 || (iv.len() < 7) {
334// } 369 panic!("CCM IV length must be 7-13 bytes.");
335// self.key = key; 370 }
336// self.iv = iv; 371 if (tag_len < 4) || (tag_len > 16) {
337// self.aad_len = aad_len; 372 panic!("Tag length must be between 4 and 16 bytes.");
338// self.payload_len = payload_len; 373 }
339// } 374 if tag_len % 2 > 0 {
340// } 375 panic!("Tag length must be a multiple of 2 bytes.");
341 376 }
342// impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesCcm<'c, KEY_SIZE> { 377
343// const BLOCK_SIZE: usize = AES_BLOCK_SIZE; 378 let mut aad_header: [u8; 6] = [0; 6];
344 379 let mut aad_header_len = 0;
345// fn key(&self) -> &'c [u8] { 380 let mut block0: [u8; 16] = [0; 16];
346// self.key 381 if aad_len != 0 {
347// } 382 if aad_len < 65280 {
348 383 aad_header[0] = (aad_len >> 8) as u8 & 0xFF;
349// fn iv(&self) -> &'c [u8] { 384 aad_header[1] = aad_len as u8 & 0xFF;
350// self.iv 385 aad_header_len = 2;
351// } 386 } else {
352 387 aad_header[0] = 0xFF;
353// fn set_algomode(&self, p: &pac::cryp::Cryp) { 388 aad_header[1] = 0xFE;
354// p.cr().modify(|w| w.set_algomode0(1)); 389 let aad_len_bytes: [u8; 4] = aad_len.to_be_bytes();
355// p.cr().modify(|w| w.set_algomode3(true)); 390 aad_header[2] = aad_len_bytes[0];
356// } 391 aad_header[3] = aad_len_bytes[1];
357 392 aad_header[4] = aad_len_bytes[2];
358// fn init_phase(&self, p: &pac::cryp::Cryp) { 393 aad_header[5] = aad_len_bytes[3];
359// todo!(); 394 aad_header_len = 6;
360// } 395 }
361// } 396 }
362 397 let total_aad_len = aad_header_len + aad_len;
363// impl<'c> CipherSized for AesCcm<'c, { 128 / 8 }> {} 398 let mut aad_padding_len = 16 - (total_aad_len % 16);
364// impl<'c> CipherSized for AesCcm<'c, { 192 / 8 }> {} 399 if aad_padding_len == 16 {
365// impl<'c> CipherSized for AesCcm<'c, { 256 / 8 }> {} 400 aad_padding_len = 0;
401 }
402 aad_header_len += aad_padding_len;
403 let total_aad_len_padded = aad_header_len + aad_len;
404 if total_aad_len_padded > 0 {
405 block0[0] = 0x40;
406 }
407 block0[0] |= (((tag_len - 2) >> 1) & 0x07) << 3;
408 block0[0] |= ((15 - (iv.len() as u8)) - 1) & 0x07;
409 block0[1..1 + iv.len()].copy_from_slice(iv);
410 let payload_len_bytes: [u8; 4] = payload_len.to_be_bytes();
411 if iv.len() <= 11 {
412 block0[12] = payload_len_bytes[0];
413 } else if payload_len_bytes[0] > 0 {
414 panic!("Message is too large for given IV size.");
415 }
416 if iv.len() <= 12 {
417 block0[13] = payload_len_bytes[1];
418 } else if payload_len_bytes[1] > 0 {
419 panic!("Message is too large for given IV size.");
420 }
421 block0[14] = payload_len_bytes[2];
422 block0[15] = payload_len_bytes[3];
423 let mut ctr: [u8; 16] = [0; 16];
424 ctr[0] = block0[0] & 0x07;
425 ctr[1..1 + iv.len()].copy_from_slice(&block0[1..1 + iv.len()]);
426 ctr[15] = 0x01;
427
428 return Self {
429 key: key,
430 aad_header: aad_header,
431 aad_header_len: aad_header_len,
432 block0: block0,
433 ctr: ctr,
434 };
435 }
436}
437
438impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesCcm<'c, KEY_SIZE> {
439 const BLOCK_SIZE: usize = AES_BLOCK_SIZE;
440
441 fn key(&self) -> &'c [u8] {
442 self.key
443 }
444
445 fn iv(&self) -> &[u8] {
446 self.ctr.as_slice()
447 }
448
449 fn set_algomode(&self, p: &pac::cryp::Cryp) {
450 p.cr().modify(|w| w.set_algomode0(1));
451 p.cr().modify(|w| w.set_algomode3(true));
452 }
453
454 fn init_phase(&self, p: &pac::cryp::Cryp) {
455 p.cr().modify(|w| w.set_gcm_ccmph(0));
456
457 let mut index = 0;
458 let end_index = index + Self::BLOCK_SIZE;
459 // Write block in
460 while index < end_index {
461 let mut in_word: [u8; 4] = [0; 4];
462 in_word.copy_from_slice(&self.block0[index..index + 4]);
463 p.din().write_value(u32::from_ne_bytes(in_word));
464 index += 4;
465 }
466 p.cr().modify(|w| w.set_crypen(true));
467 while p.cr().read().crypen() {}
468 }
469
470 fn get_header_block(&self) -> &[u8] {
471 return &self.aad_header[0..self.aad_header_len];
472 }
473
474 fn pre_final_block(&self, p: &pac::cryp::Cryp, dir: Direction) -> [u32; 4] {
475 //Handle special CCM partial block process.
476 let mut temp1 = [0; 4];
477 if dir == Direction::Decrypt {
478 p.cr().modify(|w| w.set_crypen(false));
479 let iv1temp = p.init(1).ivrr().read();
480 temp1[0] = p.csgcmccmr(0).read();
481 temp1[1] = p.csgcmccmr(1).read();
482 temp1[2] = p.csgcmccmr(2).read();
483 temp1[3] = p.csgcmccmr(3).read();
484 p.init(1).ivrr().write_value(iv1temp);
485 p.cr().modify(|w| w.set_algomode3(false));
486 p.cr().modify(|w| w.set_algomode0(6));
487 p.cr().modify(|w| w.set_crypen(true));
488 }
489 return temp1;
490 }
491
492 fn post_final_block(
493 &self,
494 p: &pac::cryp::Cryp,
495 dir: Direction,
496 int_data: &[u8; AES_BLOCK_SIZE],
497 temp1: [u32; 4],
498 padding_mask: [u8; 16],
499 ) {
500 if dir == Direction::Decrypt {
501 //Handle special CCM partial block process.
502 let mut intdata_o: [u32; 4] = [0; 4];
503 for i in 0..intdata_o.len() {
504 intdata_o[i] = p.dout().read();
505 }
506 let mut temp2 = [0; 4];
507 temp2[0] = p.csgcmccmr(0).read();
508 temp2[1] = p.csgcmccmr(1).read();
509 temp2[2] = p.csgcmccmr(2).read();
510 temp2[3] = p.csgcmccmr(3).read();
511 p.cr().write(|w| w.set_algomode3(true));
512 p.cr().write(|w| w.set_algomode0(1));
513 p.cr().modify(|w| w.set_gcm_ccmph(3));
514 // Header phase
515 p.cr().modify(|w| w.set_gcm_ccmph(1));
516 let mut in_data: [u32; 4] = [0; 4];
517 for i in 0..in_data.len() {
518 let mut mask_bytes: [u8; 4] = [0; 4];
519 mask_bytes.copy_from_slice(&padding_mask[(i * 4)..(i * 4) + 4]);
520 let mask_word = u32::from_le_bytes(mask_bytes);
521 in_data[i] = intdata_o[i] & mask_word;
522 in_data[i] = in_data[i] ^ temp1[i] ^ temp2[i];
523 }
524 }
525 }
526}
527
528impl<'c> CipherSized for AesCcm<'c, { 128 / 8 }> {}
529impl<'c> CipherSized for AesCcm<'c, { 192 / 8 }> {}
530impl<'c> CipherSized for AesCcm<'c, { 256 / 8 }> {}
531impl<'c, const KEY_SIZE: usize> CipherAuthenticated for AesCcm<'c, KEY_SIZE> {}
366 532
367/// Holds the state information for a cipher operation. 533/// Holds the state information for a cipher operation.
368/// Allows suspending/resuming of cipher operations. 534/// Allows suspending/resuming of cipher operations.
@@ -371,6 +537,7 @@ pub struct Context<'c, C: Cipher<'c> + CipherSized> {
371 cipher: &'c C, 537 cipher: &'c C,
372 dir: Direction, 538 dir: Direction,
373 last_block_processed: bool, 539 last_block_processed: bool,
540 header_processed: bool,
374 aad_complete: bool, 541 aad_complete: bool,
375 cr: u32, 542 cr: u32,
376 iv: [u32; 4], 543 iv: [u32; 4],
@@ -378,6 +545,8 @@ pub struct Context<'c, C: Cipher<'c> + CipherSized> {
378 csgcm: [u32; 8], 545 csgcm: [u32; 8],
379 header_len: u64, 546 header_len: u64,
380 payload_len: u64, 547 payload_len: u64,
548 aad_buffer: [u8; 16],
549 aad_buffer_len: usize,
381} 550}
382 551
383/// Selects whether the crypto processor operates in encryption or decryption mode. 552/// Selects whether the crypto processor operates in encryption or decryption mode.
@@ -420,6 +589,9 @@ impl<'d, T: Instance> Cryp<'d, T> {
420 payload_len: 0, 589 payload_len: 0,
421 cipher: cipher, 590 cipher: cipher,
422 phantom_data: PhantomData, 591 phantom_data: PhantomData,
592 header_processed: false,
593 aad_buffer: [0; 16],
594 aad_buffer_len: 0,
423 }; 595 };
424 596
425 T::regs().cr().modify(|w| w.set_crypen(false)); 597 T::regs().cr().modify(|w| w.set_crypen(false));
@@ -492,16 +664,9 @@ impl<'d, T: Instance> Cryp<'d, T> {
492 ) { 664 ) {
493 self.load_context(ctx); 665 self.load_context(ctx);
494 666
495 let last_block_remainder = aad.len() % C::BLOCK_SIZE;
496
497 // Perform checks for correctness. 667 // Perform checks for correctness.
498 if ctx.aad_complete { 668 if ctx.aad_complete {
499 panic!("Cannot update AAD after calling 'update'!") 669 panic!("Cannot update AAD after starting payload!")
500 }
501 if !last_aad_block {
502 if last_block_remainder != 0 {
503 panic!("Input length must be a multiple of {} bytes.", C::BLOCK_SIZE);
504 }
505 } 670 }
506 671
507 ctx.header_len += aad.len() as u64; 672 ctx.header_len += aad.len() as u64;
@@ -511,11 +676,49 @@ impl<'d, T: Instance> Cryp<'d, T> {
511 T::regs().cr().modify(|w| w.set_gcm_ccmph(1)); 676 T::regs().cr().modify(|w| w.set_gcm_ccmph(1));
512 T::regs().cr().modify(|w| w.set_crypen(true)); 677 T::regs().cr().modify(|w| w.set_crypen(true));
513 678
514 // Load data into core, block by block. 679 // First write the header B1 block if not yet written.
515 let num_full_blocks = aad.len() / C::BLOCK_SIZE; 680 if !ctx.header_processed {
516 for block in 0..num_full_blocks { 681 ctx.header_processed = true;
517 let mut index = block * C::BLOCK_SIZE; 682 let header = ctx.cipher.get_header_block();
518 let end_index = index + C::BLOCK_SIZE; 683 ctx.aad_buffer[0..header.len()].copy_from_slice(header);
684 ctx.aad_buffer_len += header.len();
685 }
686
687 // Fill the header block to make a full block.
688 let len_to_copy = min(aad.len(), C::BLOCK_SIZE - ctx.aad_buffer_len);
689 ctx.aad_buffer[ctx.aad_buffer_len..ctx.aad_buffer_len + len_to_copy].copy_from_slice(&aad[..len_to_copy]);
690 ctx.aad_buffer_len += len_to_copy;
691 ctx.aad_buffer[ctx.aad_buffer_len..].fill(0);
692 let mut aad_len_remaining = aad.len() - len_to_copy;
693
694 if ctx.aad_buffer_len < C::BLOCK_SIZE {
695 // The buffer isn't full and this is the last buffer, so process it as is (already padded).
696 if last_aad_block {
697 let mut index = 0;
698 let end_index = C::BLOCK_SIZE;
699 // Write block in
700 while index < end_index {
701 let mut in_word: [u8; 4] = [0; 4];
702 in_word.copy_from_slice(&aad[index..index + 4]);
703 T::regs().din().write_value(u32::from_ne_bytes(in_word));
704 index += 4;
705 }
706 // Block until input FIFO is empty.
707 while !T::regs().sr().read().ifem() {}
708
709 // Switch to payload phase.
710 ctx.aad_complete = true;
711 T::regs().cr().modify(|w| w.set_crypen(false));
712 T::regs().cr().modify(|w| w.set_gcm_ccmph(2));
713 T::regs().cr().modify(|w| w.fflush());
714 } else {
715 // Just return because we don't yet have a full block to process.
716 return;
717 }
718 } else {
719 // Load the full block from the buffer.
720 let mut index = 0;
721 let end_index = C::BLOCK_SIZE;
519 // Write block in 722 // Write block in
520 while index < end_index { 723 while index < end_index {
521 let mut in_word: [u8; 4] = [0; 4]; 724 let mut in_word: [u8; 4] = [0; 4];
@@ -527,20 +730,26 @@ impl<'d, T: Instance> Cryp<'d, T> {
527 while !T::regs().sr().read().ifem() {} 730 while !T::regs().sr().read().ifem() {}
528 } 731 }
529 732
530 // Handle the final block, which is incomplete. 733 // Handle a partial block that is passed in.
531 if last_block_remainder > 0 { 734 ctx.aad_buffer_len = 0;
532 let mut last_block: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; 735 let leftovers = aad_len_remaining % C::BLOCK_SIZE;
533 last_block[..last_block_remainder].copy_from_slice(&aad[aad.len() - last_block_remainder..aad.len()]); 736 ctx.aad_buffer[..leftovers].copy_from_slice(&aad[aad.len() - leftovers..aad.len()]);
534 let mut index = 0; 737 aad_len_remaining -= leftovers;
535 let end_index = C::BLOCK_SIZE; 738 assert_eq!(aad_len_remaining % C::BLOCK_SIZE, 0);
739
740 // Load full data blocks into core.
741 let num_full_blocks = aad_len_remaining / C::BLOCK_SIZE;
742 for _ in 0..num_full_blocks {
743 let mut index = len_to_copy;
744 let end_index = len_to_copy + C::BLOCK_SIZE;
536 // Write block in 745 // Write block in
537 while index < end_index { 746 while index < end_index {
538 let mut in_word: [u8; 4] = [0; 4]; 747 let mut in_word: [u8; 4] = [0; 4];
539 in_word.copy_from_slice(&last_block[index..index + 4]); 748 in_word.copy_from_slice(&aad[index..index + 4]);
540 T::regs().din().write_value(u32::from_ne_bytes(in_word)); 749 T::regs().din().write_value(u32::from_ne_bytes(in_word));
541 index += 4; 750 index += 4;
542 } 751 }
543 // Block until input FIFO is empty 752 // Block until input FIFO is empty.
544 while !T::regs().sr().read().ifem() {} 753 while !T::regs().sr().read().ifem() {}
545 } 754 }
546 755
@@ -630,7 +839,7 @@ impl<'d, T: Instance> Cryp<'d, T> {
630 839
631 // Handle the final block, which is incomplete. 840 // Handle the final block, which is incomplete.
632 if last_block_remainder > 0 { 841 if last_block_remainder > 0 {
633 ctx.cipher.pre_final_block(&T::regs()); 842 let temp1 = ctx.cipher.pre_final_block(&T::regs(), ctx.dir);
634 843
635 let mut intermediate_data: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; 844 let mut intermediate_data: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE];
636 let mut last_block: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; 845 let mut last_block: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE];
@@ -660,10 +869,15 @@ impl<'d, T: Instance> Cryp<'d, T> {
660 output[output_len - last_block_remainder..output_len] 869 output[output_len - last_block_remainder..output_len]
661 .copy_from_slice(&intermediate_data[0..last_block_remainder]); 870 .copy_from_slice(&intermediate_data[0..last_block_remainder]);
662 871
663 ctx.cipher.post_final_block(&T::regs(), ctx.dir, &intermediate_data); 872 let mut mask: [u8; 16] = [0; 16];
873 mask[..last_block_remainder].fill(0xFF);
874 ctx.cipher
875 .post_final_block(&T::regs(), ctx.dir, &intermediate_data, temp1, mask);
664 } 876 }
665 877
666 ctx.payload_len += input.len() as u64; 878 ctx.payload_len += input.len() as u64;
879
880 self.store_context(ctx);
667 } 881 }
668 882
669 /// This function only needs to be called for GCM, CCM, and GMAC modes to 883 /// This function only needs to be called for GCM, CCM, and GMAC modes to