diff options
| -rw-r--r-- | embassy-stm32/build.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/cryp/mod.rs | 875 | ||||
| -rw-r--r-- | examples/stm32f7/src/bin/cryp.rs | 28 | ||||
| -rw-r--r-- | tests/stm32/src/bin/cryp.rs | 30 | ||||
| -rw-r--r-- | tests/stm32/src/common.rs | 1 |
5 files changed, 758 insertions, 178 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 84e8be25d..70f4515db 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -1121,6 +1121,8 @@ fn main() { | |||
| 1121 | (("dac", "CH2"), quote!(crate::dac::DacDma2)), | 1121 | (("dac", "CH2"), quote!(crate::dac::DacDma2)), |
| 1122 | (("timer", "UP"), quote!(crate::timer::UpDma)), | 1122 | (("timer", "UP"), quote!(crate::timer::UpDma)), |
| 1123 | (("hash", "IN"), quote!(crate::hash::Dma)), | 1123 | (("hash", "IN"), quote!(crate::hash::Dma)), |
| 1124 | (("cryp", "IN"), quote!(crate::cryp::DmaIn)), | ||
| 1125 | (("cryp", "OUT"), quote!(crate::cryp::DmaOut)), | ||
| 1124 | (("timer", "CH1"), quote!(crate::timer::Ch1Dma)), | 1126 | (("timer", "CH1"), quote!(crate::timer::Ch1Dma)), |
| 1125 | (("timer", "CH2"), quote!(crate::timer::Ch2Dma)), | 1127 | (("timer", "CH2"), quote!(crate::timer::Ch2Dma)), |
| 1126 | (("timer", "CH3"), quote!(crate::timer::Ch3Dma)), | 1128 | (("timer", "CH3"), quote!(crate::timer::Ch3Dma)), |
diff --git a/embassy-stm32/src/cryp/mod.rs b/embassy-stm32/src/cryp/mod.rs index 8f259520a..74b095b6f 100644 --- a/embassy-stm32/src/cryp/mod.rs +++ b/embassy-stm32/src/cryp/mod.rs | |||
| @@ -2,14 +2,39 @@ | |||
| 2 | #[cfg(any(cryp_v2, cryp_v3))] | 2 | #[cfg(any(cryp_v2, cryp_v3))] |
| 3 | use core::cmp::min; | 3 | use core::cmp::min; |
| 4 | use core::marker::PhantomData; | 4 | use core::marker::PhantomData; |
| 5 | use core::ptr; | ||
| 5 | 6 | ||
| 6 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 7 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 8 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 7 | 9 | ||
| 10 | use crate::dma::{NoDma, Priority, Transfer, TransferOptions}; | ||
| 11 | use crate::interrupt::typelevel::Interrupt; | ||
| 8 | use crate::{interrupt, pac, peripherals, Peripheral}; | 12 | use crate::{interrupt, pac, peripherals, Peripheral}; |
| 9 | 13 | ||
| 10 | const DES_BLOCK_SIZE: usize = 8; // 64 bits | 14 | const DES_BLOCK_SIZE: usize = 8; // 64 bits |
| 11 | const AES_BLOCK_SIZE: usize = 16; // 128 bits | 15 | const AES_BLOCK_SIZE: usize = 16; // 128 bits |
| 12 | 16 | ||
| 17 | static CRYP_WAKER: AtomicWaker = AtomicWaker::new(); | ||
| 18 | |||
| 19 | /// CRYP interrupt handler. | ||
| 20 | pub struct InterruptHandler<T: Instance> { | ||
| 21 | _phantom: PhantomData<T>, | ||
| 22 | } | ||
| 23 | |||
| 24 | impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { | ||
| 25 | unsafe fn on_interrupt() { | ||
| 26 | let bits = T::regs().misr().read(); | ||
| 27 | if bits.inmis() { | ||
| 28 | T::regs().imscr().modify(|w| w.set_inim(false)); | ||
| 29 | CRYP_WAKER.wake(); | ||
| 30 | } | ||
| 31 | if bits.outmis() { | ||
| 32 | T::regs().imscr().modify(|w| w.set_outim(false)); | ||
| 33 | CRYP_WAKER.wake(); | ||
| 34 | } | ||
| 35 | } | ||
| 36 | } | ||
| 37 | |||
| 13 | /// This trait encapsulates all cipher-specific behavior/ | 38 | /// This trait encapsulates all cipher-specific behavior/ |
| 14 | pub trait Cipher<'c> { | 39 | pub trait Cipher<'c> { |
| 15 | /// Processing block size. Determined by the processor and the algorithm. | 40 | /// Processing block size. Determined by the processor and the algorithm. |
| @@ -32,17 +57,26 @@ pub trait Cipher<'c> { | |||
| 32 | fn prepare_key(&self, _p: &pac::cryp::Cryp) {} | 57 | fn prepare_key(&self, _p: &pac::cryp::Cryp) {} |
| 33 | 58 | ||
| 34 | /// Performs any cipher-specific initialization. | 59 | /// Performs any cipher-specific initialization. |
| 35 | fn init_phase(&self, _p: &pac::cryp::Cryp) {} | 60 | fn init_phase_blocking<T: Instance, DmaIn, DmaOut>(&self, _p: &pac::cryp::Cryp, _cryp: &Cryp<T, DmaIn, DmaOut>) {} |
| 61 | |||
| 62 | /// Performs any cipher-specific initialization. | ||
| 63 | async fn init_phase<T: Instance, DmaIn, DmaOut>(&self, _p: &pac::cryp::Cryp, _cryp: &mut Cryp<'_, T, DmaIn, DmaOut>) | ||
| 64 | where | ||
| 65 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 66 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 67 | { | ||
| 68 | } | ||
| 36 | 69 | ||
| 37 | /// Called prior to processing the last data block for cipher-specific operations. | 70 | /// Called prior to processing the last data block for cipher-specific operations. |
| 38 | fn pre_final_block(&self, _p: &pac::cryp::Cryp, _dir: Direction, _padding_len: usize) -> [u32; 4] { | 71 | fn pre_final(&self, _p: &pac::cryp::Cryp, _dir: Direction, _padding_len: usize) -> [u32; 4] { |
| 39 | return [0; 4]; | 72 | return [0; 4]; |
| 40 | } | 73 | } |
| 41 | 74 | ||
| 42 | /// Called after processing the last data block for cipher-specific operations. | 75 | /// Called after processing the last data block for cipher-specific operations. |
| 43 | fn post_final_block( | 76 | fn post_final_blocking<T: Instance, DmaIn, DmaOut>( |
| 44 | &self, | 77 | &self, |
| 45 | _p: &pac::cryp::Cryp, | 78 | _p: &pac::cryp::Cryp, |
| 79 | _cryp: &Cryp<T, DmaIn, DmaOut>, | ||
| 46 | _dir: Direction, | 80 | _dir: Direction, |
| 47 | _int_data: &mut [u8; AES_BLOCK_SIZE], | 81 | _int_data: &mut [u8; AES_BLOCK_SIZE], |
| 48 | _temp1: [u32; 4], | 82 | _temp1: [u32; 4], |
| @@ -50,7 +84,22 @@ pub trait Cipher<'c> { | |||
| 50 | ) { | 84 | ) { |
| 51 | } | 85 | } |
| 52 | 86 | ||
| 53 | /// Called prior to processing the first associated data block for cipher-specific operations. | 87 | /// Called after processing the last data block for cipher-specific operations. |
| 88 | async fn post_final<T: Instance, DmaIn, DmaOut>( | ||
| 89 | &self, | ||
| 90 | _p: &pac::cryp::Cryp, | ||
| 91 | _cryp: &mut Cryp<'_, T, DmaIn, DmaOut>, | ||
| 92 | _dir: Direction, | ||
| 93 | _int_data: &mut [u8; AES_BLOCK_SIZE], | ||
| 94 | _temp1: [u32; 4], | ||
| 95 | _padding_mask: [u8; 16], | ||
| 96 | ) where | ||
| 97 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 98 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 99 | { | ||
| 100 | } | ||
| 101 | |||
| 102 | /// Returns the AAD header block as required by the cipher. | ||
| 54 | fn get_header_block(&self) -> &[u8] { | 103 | fn get_header_block(&self) -> &[u8] { |
| 55 | return [0; 0].as_slice(); | 104 | return [0; 0].as_slice(); |
| 56 | } | 105 | } |
| @@ -425,14 +474,24 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGcm<'c, KEY_SIZE> { | |||
| 425 | p.cr().modify(|w| w.set_algomode3(true)); | 474 | p.cr().modify(|w| w.set_algomode3(true)); |
| 426 | } | 475 | } |
| 427 | 476 | ||
| 428 | fn init_phase(&self, p: &pac::cryp::Cryp) { | 477 | fn init_phase_blocking<T: Instance, DmaIn, DmaOut>(&self, p: &pac::cryp::Cryp, _cryp: &Cryp<T, DmaIn, DmaOut>) { |
| 478 | p.cr().modify(|w| w.set_gcm_ccmph(0)); | ||
| 479 | p.cr().modify(|w| w.set_crypen(true)); | ||
| 480 | while p.cr().read().crypen() {} | ||
| 481 | } | ||
| 482 | |||
| 483 | async fn init_phase<T: Instance, DmaIn, DmaOut>( | ||
| 484 | &self, | ||
| 485 | p: &pac::cryp::Cryp, | ||
| 486 | _cryp: &mut Cryp<'_, T, DmaIn, DmaOut>, | ||
| 487 | ) { | ||
| 429 | p.cr().modify(|w| w.set_gcm_ccmph(0)); | 488 | p.cr().modify(|w| w.set_gcm_ccmph(0)); |
| 430 | p.cr().modify(|w| w.set_crypen(true)); | 489 | p.cr().modify(|w| w.set_crypen(true)); |
| 431 | while p.cr().read().crypen() {} | 490 | while p.cr().read().crypen() {} |
| 432 | } | 491 | } |
| 433 | 492 | ||
| 434 | #[cfg(cryp_v2)] | 493 | #[cfg(cryp_v2)] |
| 435 | fn pre_final_block(&self, p: &pac::cryp::Cryp, dir: Direction, _padding_len: usize) -> [u32; 4] { | 494 | fn pre_final(&self, p: &pac::cryp::Cryp, dir: Direction, _padding_len: usize) -> [u32; 4] { |
| 436 | //Handle special GCM partial block process. | 495 | //Handle special GCM partial block process. |
| 437 | if dir == Direction::Encrypt { | 496 | if dir == Direction::Encrypt { |
| 438 | p.cr().modify(|w| w.set_crypen(false)); | 497 | p.cr().modify(|w| w.set_crypen(false)); |
| @@ -446,16 +505,17 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGcm<'c, KEY_SIZE> { | |||
| 446 | } | 505 | } |
| 447 | 506 | ||
| 448 | #[cfg(cryp_v3)] | 507 | #[cfg(cryp_v3)] |
| 449 | fn pre_final_block(&self, p: &pac::cryp::Cryp, _dir: Direction, padding_len: usize) -> [u32; 4] { | 508 | fn pre_final(&self, p: &pac::cryp::Cryp, _dir: Direction, padding_len: usize) -> [u32; 4] { |
| 450 | //Handle special GCM partial block process. | 509 | //Handle special GCM partial block process. |
| 451 | p.cr().modify(|w| w.set_npblb(padding_len as u8)); | 510 | p.cr().modify(|w| w.set_npblb(padding_len as u8)); |
| 452 | [0; 4] | 511 | [0; 4] |
| 453 | } | 512 | } |
| 454 | 513 | ||
| 455 | #[cfg(cryp_v2)] | 514 | #[cfg(cryp_v2)] |
| 456 | fn post_final_block( | 515 | fn post_final_blocking<T: Instance, DmaIn, DmaOut>( |
| 457 | &self, | 516 | &self, |
| 458 | p: &pac::cryp::Cryp, | 517 | p: &pac::cryp::Cryp, |
| 518 | cryp: &Cryp<T, DmaIn, DmaOut>, | ||
| 459 | dir: Direction, | 519 | dir: Direction, |
| 460 | int_data: &mut [u8; AES_BLOCK_SIZE], | 520 | int_data: &mut [u8; AES_BLOCK_SIZE], |
| 461 | _temp1: [u32; 4], | 521 | _temp1: [u32; 4], |
| @@ -471,17 +531,44 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGcm<'c, KEY_SIZE> { | |||
| 471 | } | 531 | } |
| 472 | p.cr().modify(|w| w.set_crypen(true)); | 532 | p.cr().modify(|w| w.set_crypen(true)); |
| 473 | p.cr().modify(|w| w.set_gcm_ccmph(3)); | 533 | p.cr().modify(|w| w.set_gcm_ccmph(3)); |
| 474 | let mut index = 0; | 534 | |
| 475 | let end_index = Self::BLOCK_SIZE; | 535 | cryp.write_bytes_blocking(Self::BLOCK_SIZE, int_data); |
| 476 | while index < end_index { | 536 | cryp.read_bytes_blocking(Self::BLOCK_SIZE, int_data); |
| 477 | let mut in_word: [u8; 4] = [0; 4]; | 537 | } |
| 478 | in_word.copy_from_slice(&int_data[index..index + 4]); | 538 | } |
| 479 | p.din().write_value(u32::from_ne_bytes(in_word)); | 539 | |
| 480 | index += 4; | 540 | #[cfg(cryp_v2)] |
| 481 | } | 541 | async fn post_final<T: Instance, DmaIn, DmaOut>( |
| 482 | for _ in 0..4 { | 542 | &self, |
| 483 | p.dout().read(); | 543 | p: &pac::cryp::Cryp, |
| 544 | cryp: &mut Cryp<'_, T, DmaIn, DmaOut>, | ||
| 545 | dir: Direction, | ||
| 546 | int_data: &mut [u8; AES_BLOCK_SIZE], | ||
| 547 | _temp1: [u32; 4], | ||
| 548 | padding_mask: [u8; AES_BLOCK_SIZE], | ||
| 549 | ) where | ||
| 550 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 551 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 552 | { | ||
| 553 | if dir == Direction::Encrypt { | ||
| 554 | // Handle special GCM partial block process. | ||
| 555 | p.cr().modify(|w| w.set_crypen(false)); | ||
| 556 | p.cr().modify(|w| w.set_algomode3(true)); | ||
| 557 | p.cr().modify(|w| w.set_algomode0(0)); | ||
| 558 | for i in 0..AES_BLOCK_SIZE { | ||
| 559 | int_data[i] = int_data[i] & padding_mask[i]; | ||
| 484 | } | 560 | } |
| 561 | p.cr().modify(|w| w.set_crypen(true)); | ||
| 562 | p.cr().modify(|w| w.set_gcm_ccmph(3)); | ||
| 563 | |||
| 564 | let mut out_data: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; | ||
| 565 | |||
| 566 | let read = Cryp::<T, DmaIn, DmaOut>::read_bytes(&mut cryp.outdma, Self::BLOCK_SIZE, &mut out_data); | ||
| 567 | let write = Cryp::<T, DmaIn, DmaOut>::write_bytes(&mut cryp.indma, Self::BLOCK_SIZE, int_data); | ||
| 568 | |||
| 569 | embassy_futures::join::join(read, write).await; | ||
| 570 | |||
| 571 | int_data.copy_from_slice(&out_data); | ||
| 485 | } | 572 | } |
| 486 | } | 573 | } |
| 487 | } | 574 | } |
| @@ -532,14 +619,24 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGmac<'c, KEY_SIZE> { | |||
| 532 | p.cr().modify(|w| w.set_algomode3(true)); | 619 | p.cr().modify(|w| w.set_algomode3(true)); |
| 533 | } | 620 | } |
| 534 | 621 | ||
| 535 | fn init_phase(&self, p: &pac::cryp::Cryp) { | 622 | fn init_phase_blocking<T: Instance, DmaIn, DmaOut>(&self, p: &pac::cryp::Cryp, _cryp: &Cryp<T, DmaIn, DmaOut>) { |
| 623 | p.cr().modify(|w| w.set_gcm_ccmph(0)); | ||
| 624 | p.cr().modify(|w| w.set_crypen(true)); | ||
| 625 | while p.cr().read().crypen() {} | ||
| 626 | } | ||
| 627 | |||
| 628 | async fn init_phase<T: Instance, DmaIn, DmaOut>( | ||
| 629 | &self, | ||
| 630 | p: &pac::cryp::Cryp, | ||
| 631 | _cryp: &mut Cryp<'_, T, DmaIn, DmaOut>, | ||
| 632 | ) { | ||
| 536 | p.cr().modify(|w| w.set_gcm_ccmph(0)); | 633 | p.cr().modify(|w| w.set_gcm_ccmph(0)); |
| 537 | p.cr().modify(|w| w.set_crypen(true)); | 634 | p.cr().modify(|w| w.set_crypen(true)); |
| 538 | while p.cr().read().crypen() {} | 635 | while p.cr().read().crypen() {} |
| 539 | } | 636 | } |
| 540 | 637 | ||
| 541 | #[cfg(cryp_v2)] | 638 | #[cfg(cryp_v2)] |
| 542 | fn pre_final_block(&self, p: &pac::cryp::Cryp, dir: Direction, _padding_len: usize) -> [u32; 4] { | 639 | fn pre_final(&self, p: &pac::cryp::Cryp, dir: Direction, _padding_len: usize) -> [u32; 4] { |
| 543 | //Handle special GCM partial block process. | 640 | //Handle special GCM partial block process. |
| 544 | if dir == Direction::Encrypt { | 641 | if dir == Direction::Encrypt { |
| 545 | p.cr().modify(|w| w.set_crypen(false)); | 642 | p.cr().modify(|w| w.set_crypen(false)); |
| @@ -553,16 +650,17 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGmac<'c, KEY_SIZE> { | |||
| 553 | } | 650 | } |
| 554 | 651 | ||
| 555 | #[cfg(cryp_v3)] | 652 | #[cfg(cryp_v3)] |
| 556 | fn pre_final_block(&self, p: &pac::cryp::Cryp, _dir: Direction, padding_len: usize) -> [u32; 4] { | 653 | fn pre_final(&self, p: &pac::cryp::Cryp, _dir: Direction, padding_len: usize) -> [u32; 4] { |
| 557 | //Handle special GCM partial block process. | 654 | //Handle special GCM partial block process. |
| 558 | p.cr().modify(|w| w.set_npblb(padding_len as u8)); | 655 | p.cr().modify(|w| w.set_npblb(padding_len as u8)); |
| 559 | [0; 4] | 656 | [0; 4] |
| 560 | } | 657 | } |
| 561 | 658 | ||
| 562 | #[cfg(cryp_v2)] | 659 | #[cfg(cryp_v2)] |
| 563 | fn post_final_block( | 660 | fn post_final_blocking<T: Instance, DmaIn, DmaOut>( |
| 564 | &self, | 661 | &self, |
| 565 | p: &pac::cryp::Cryp, | 662 | p: &pac::cryp::Cryp, |
| 663 | cryp: &Cryp<T, DmaIn, DmaOut>, | ||
| 566 | dir: Direction, | 664 | dir: Direction, |
| 567 | int_data: &mut [u8; AES_BLOCK_SIZE], | 665 | int_data: &mut [u8; AES_BLOCK_SIZE], |
| 568 | _temp1: [u32; 4], | 666 | _temp1: [u32; 4], |
| @@ -578,17 +676,42 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGmac<'c, KEY_SIZE> { | |||
| 578 | } | 676 | } |
| 579 | p.cr().modify(|w| w.set_crypen(true)); | 677 | p.cr().modify(|w| w.set_crypen(true)); |
| 580 | p.cr().modify(|w| w.set_gcm_ccmph(3)); | 678 | p.cr().modify(|w| w.set_gcm_ccmph(3)); |
| 581 | let mut index = 0; | 679 | |
| 582 | let end_index = Self::BLOCK_SIZE; | 680 | cryp.write_bytes_blocking(Self::BLOCK_SIZE, int_data); |
| 583 | while index < end_index { | 681 | cryp.read_bytes_blocking(Self::BLOCK_SIZE, int_data); |
| 584 | let mut in_word: [u8; 4] = [0; 4]; | 682 | } |
| 585 | in_word.copy_from_slice(&int_data[index..index + 4]); | 683 | } |
| 586 | p.din().write_value(u32::from_ne_bytes(in_word)); | 684 | |
| 587 | index += 4; | 685 | #[cfg(cryp_v2)] |
| 588 | } | 686 | async fn post_final<T: Instance, DmaIn, DmaOut>( |
| 589 | for _ in 0..4 { | 687 | &self, |
| 590 | p.dout().read(); | 688 | p: &pac::cryp::Cryp, |
| 689 | cryp: &mut Cryp<'_, T, DmaIn, DmaOut>, | ||
| 690 | dir: Direction, | ||
| 691 | int_data: &mut [u8; AES_BLOCK_SIZE], | ||
| 692 | _temp1: [u32; 4], | ||
| 693 | padding_mask: [u8; AES_BLOCK_SIZE], | ||
| 694 | ) where | ||
| 695 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 696 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 697 | { | ||
| 698 | if dir == Direction::Encrypt { | ||
| 699 | // Handle special GCM partial block process. | ||
| 700 | p.cr().modify(|w| w.set_crypen(false)); | ||
| 701 | p.cr().modify(|w| w.set_algomode3(true)); | ||
| 702 | p.cr().modify(|w| w.set_algomode0(0)); | ||
| 703 | for i in 0..AES_BLOCK_SIZE { | ||
| 704 | int_data[i] = int_data[i] & padding_mask[i]; | ||
| 591 | } | 705 | } |
| 706 | p.cr().modify(|w| w.set_crypen(true)); | ||
| 707 | p.cr().modify(|w| w.set_gcm_ccmph(3)); | ||
| 708 | |||
| 709 | let mut out_data: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; | ||
| 710 | |||
| 711 | let read = Cryp::<T, DmaIn, DmaOut>::read_bytes(&mut cryp.outdma, Self::BLOCK_SIZE, &mut out_data); | ||
| 712 | let write = Cryp::<T, DmaIn, DmaOut>::write_bytes(&mut cryp.indma, Self::BLOCK_SIZE, int_data); | ||
| 713 | |||
| 714 | embassy_futures::join::join(read, write).await; | ||
| 592 | } | 715 | } |
| 593 | } | 716 | } |
| 594 | } | 717 | } |
| @@ -697,18 +820,24 @@ impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize, const IV_SIZE: usize> Cip | |||
| 697 | p.cr().modify(|w| w.set_algomode3(true)); | 820 | p.cr().modify(|w| w.set_algomode3(true)); |
| 698 | } | 821 | } |
| 699 | 822 | ||
| 700 | fn init_phase(&self, p: &pac::cryp::Cryp) { | 823 | fn init_phase_blocking<T: Instance, DmaIn, DmaOut>(&self, p: &pac::cryp::Cryp, cryp: &Cryp<T, DmaIn, DmaOut>) { |
| 701 | p.cr().modify(|w| w.set_gcm_ccmph(0)); | 824 | p.cr().modify(|w| w.set_gcm_ccmph(0)); |
| 702 | 825 | ||
| 703 | let mut index = 0; | 826 | cryp.write_bytes_blocking(Self::BLOCK_SIZE, &self.block0); |
| 704 | let end_index = index + Self::BLOCK_SIZE; | 827 | |
| 705 | // Write block in | 828 | p.cr().modify(|w| w.set_crypen(true)); |
| 706 | while index < end_index { | 829 | while p.cr().read().crypen() {} |
| 707 | let mut in_word: [u8; 4] = [0; 4]; | 830 | } |
| 708 | in_word.copy_from_slice(&self.block0[index..index + 4]); | 831 | |
| 709 | p.din().write_value(u32::from_ne_bytes(in_word)); | 832 | async fn init_phase<T: Instance, DmaIn, DmaOut>(&self, p: &pac::cryp::Cryp, cryp: &mut Cryp<'_, T, DmaIn, DmaOut>) |
| 710 | index += 4; | 833 | where |
| 711 | } | 834 | DmaIn: crate::cryp::DmaIn<T>, |
| 835 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 836 | { | ||
| 837 | p.cr().modify(|w| w.set_gcm_ccmph(0)); | ||
| 838 | |||
| 839 | Cryp::<T, DmaIn, DmaOut>::write_bytes(&mut cryp.indma, Self::BLOCK_SIZE, &self.block0).await; | ||
| 840 | |||
| 712 | p.cr().modify(|w| w.set_crypen(true)); | 841 | p.cr().modify(|w| w.set_crypen(true)); |
| 713 | while p.cr().read().crypen() {} | 842 | while p.cr().read().crypen() {} |
| 714 | } | 843 | } |
| @@ -718,7 +847,7 @@ impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize, const IV_SIZE: usize> Cip | |||
| 718 | } | 847 | } |
| 719 | 848 | ||
| 720 | #[cfg(cryp_v2)] | 849 | #[cfg(cryp_v2)] |
| 721 | fn pre_final_block(&self, p: &pac::cryp::Cryp, dir: Direction, _padding_len: usize) -> [u32; 4] { | 850 | fn pre_final(&self, p: &pac::cryp::Cryp, dir: Direction, _padding_len: usize) -> [u32; 4] { |
| 722 | //Handle special CCM partial block process. | 851 | //Handle special CCM partial block process. |
| 723 | let mut temp1 = [0; 4]; | 852 | let mut temp1 = [0; 4]; |
| 724 | if dir == Direction::Decrypt { | 853 | if dir == Direction::Decrypt { |
| @@ -737,16 +866,17 @@ impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize, const IV_SIZE: usize> Cip | |||
| 737 | } | 866 | } |
| 738 | 867 | ||
| 739 | #[cfg(cryp_v3)] | 868 | #[cfg(cryp_v3)] |
| 740 | fn pre_final_block(&self, p: &pac::cryp::Cryp, _dir: Direction, padding_len: usize) -> [u32; 4] { | 869 | fn pre_final(&self, p: &pac::cryp::Cryp, _dir: Direction, padding_len: usize) -> [u32; 4] { |
| 741 | //Handle special GCM partial block process. | 870 | //Handle special GCM partial block process. |
| 742 | p.cr().modify(|w| w.set_npblb(padding_len as u8)); | 871 | p.cr().modify(|w| w.set_npblb(padding_len as u8)); |
| 743 | [0; 4] | 872 | [0; 4] |
| 744 | } | 873 | } |
| 745 | 874 | ||
| 746 | #[cfg(cryp_v2)] | 875 | #[cfg(cryp_v2)] |
| 747 | fn post_final_block( | 876 | fn post_final_blocking<T: Instance, DmaIn, DmaOut>( |
| 748 | &self, | 877 | &self, |
| 749 | p: &pac::cryp::Cryp, | 878 | p: &pac::cryp::Cryp, |
| 879 | cryp: &Cryp<T, DmaIn, DmaOut>, | ||
| 750 | dir: Direction, | 880 | dir: Direction, |
| 751 | int_data: &mut [u8; AES_BLOCK_SIZE], | 881 | int_data: &mut [u8; AES_BLOCK_SIZE], |
| 752 | temp1: [u32; 4], | 882 | temp1: [u32; 4], |
| @@ -774,8 +904,48 @@ impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize, const IV_SIZE: usize> Cip | |||
| 774 | let int_word = u32::from_le_bytes(int_bytes); | 904 | let int_word = u32::from_le_bytes(int_bytes); |
| 775 | in_data[i] = int_word; | 905 | in_data[i] = int_word; |
| 776 | in_data[i] = in_data[i] ^ temp1[i] ^ temp2[i]; | 906 | in_data[i] = in_data[i] ^ temp1[i] ^ temp2[i]; |
| 777 | p.din().write_value(in_data[i]); | ||
| 778 | } | 907 | } |
| 908 | cryp.write_words_blocking(Self::BLOCK_SIZE, &in_data); | ||
| 909 | } | ||
| 910 | } | ||
| 911 | |||
| 912 | #[cfg(cryp_v2)] | ||
| 913 | async fn post_final<T: Instance, DmaIn, DmaOut>( | ||
| 914 | &self, | ||
| 915 | p: &pac::cryp::Cryp, | ||
| 916 | cryp: &mut Cryp<'_, T, DmaIn, DmaOut>, | ||
| 917 | dir: Direction, | ||
| 918 | int_data: &mut [u8; AES_BLOCK_SIZE], | ||
| 919 | temp1: [u32; 4], | ||
| 920 | padding_mask: [u8; 16], | ||
| 921 | ) where | ||
| 922 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 923 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 924 | { | ||
| 925 | if dir == Direction::Decrypt { | ||
| 926 | //Handle special CCM partial block process. | ||
| 927 | let mut temp2 = [0; 4]; | ||
| 928 | temp2[0] = p.csgcmccmr(0).read().swap_bytes(); | ||
| 929 | temp2[1] = p.csgcmccmr(1).read().swap_bytes(); | ||
| 930 | temp2[2] = p.csgcmccmr(2).read().swap_bytes(); | ||
| 931 | temp2[3] = p.csgcmccmr(3).read().swap_bytes(); | ||
| 932 | p.cr().modify(|w| w.set_algomode3(true)); | ||
| 933 | p.cr().modify(|w| w.set_algomode0(1)); | ||
| 934 | p.cr().modify(|w| w.set_gcm_ccmph(3)); | ||
| 935 | // Header phase | ||
| 936 | p.cr().modify(|w| w.set_gcm_ccmph(1)); | ||
| 937 | for i in 0..AES_BLOCK_SIZE { | ||
| 938 | int_data[i] = int_data[i] & padding_mask[i]; | ||
| 939 | } | ||
| 940 | let mut in_data: [u32; 4] = [0; 4]; | ||
| 941 | for i in 0..in_data.len() { | ||
| 942 | let mut int_bytes: [u8; 4] = [0; 4]; | ||
| 943 | int_bytes.copy_from_slice(&int_data[(i * 4)..(i * 4) + 4]); | ||
| 944 | let int_word = u32::from_le_bytes(int_bytes); | ||
| 945 | in_data[i] = int_word; | ||
| 946 | in_data[i] = in_data[i] ^ temp1[i] ^ temp2[i]; | ||
| 947 | } | ||
| 948 | Cryp::<T, DmaIn, DmaOut>::write_words(&mut cryp.indma, Self::BLOCK_SIZE, &in_data).await; | ||
| 779 | } | 949 | } |
| 780 | } | 950 | } |
| 781 | } | 951 | } |
| @@ -845,24 +1015,40 @@ pub enum Direction { | |||
| 845 | } | 1015 | } |
| 846 | 1016 | ||
| 847 | /// Crypto Accelerator Driver | 1017 | /// Crypto Accelerator Driver |
| 848 | pub struct Cryp<'d, T: Instance> { | 1018 | pub struct Cryp<'d, T: Instance, DmaIn = NoDma, DmaOut = NoDma> { |
| 849 | _peripheral: PeripheralRef<'d, T>, | 1019 | _peripheral: PeripheralRef<'d, T>, |
| 1020 | indma: PeripheralRef<'d, DmaIn>, | ||
| 1021 | outdma: PeripheralRef<'d, DmaOut>, | ||
| 850 | } | 1022 | } |
| 851 | 1023 | ||
| 852 | impl<'d, T: Instance> Cryp<'d, T> { | 1024 | impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> { |
| 853 | /// Create a new CRYP driver. | 1025 | /// Create a new CRYP driver. |
| 854 | pub fn new(peri: impl Peripheral<P = T> + 'd) -> Self { | 1026 | pub fn new( |
| 1027 | peri: impl Peripheral<P = T> + 'd, | ||
| 1028 | indma: impl Peripheral<P = DmaIn> + 'd, | ||
| 1029 | outdma: impl Peripheral<P = DmaOut> + 'd, | ||
| 1030 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | ||
| 1031 | ) -> Self { | ||
| 855 | T::enable_and_reset(); | 1032 | T::enable_and_reset(); |
| 856 | into_ref!(peri); | 1033 | into_ref!(peri, indma, outdma); |
| 857 | let instance = Self { _peripheral: peri }; | 1034 | let instance = Self { |
| 1035 | _peripheral: peri, | ||
| 1036 | indma: indma, | ||
| 1037 | outdma: outdma, | ||
| 1038 | }; | ||
| 1039 | |||
| 1040 | T::Interrupt::unpend(); | ||
| 1041 | unsafe { T::Interrupt::enable() }; | ||
| 1042 | |||
| 858 | instance | 1043 | instance |
| 859 | } | 1044 | } |
| 860 | 1045 | ||
| 861 | /// Start a new cipher operation. | 1046 | /// Start a new encrypt or decrypt operation for the given cipher. |
| 862 | /// Key size must be 128, 192, or 256 bits. | 1047 | pub fn start_blocking<'c, C: Cipher<'c> + CipherSized + IVSized>( |
| 863 | /// Initialization vector must only be supplied if necessary. | 1048 | &self, |
| 864 | /// Panics if there is any mismatch in parameters, such as an incorrect IV length or invalid mode. | 1049 | cipher: &'c C, |
| 865 | pub fn start<'c, C: Cipher<'c> + CipherSized + IVSized>(&self, cipher: &'c C, dir: Direction) -> Context<'c, C> { | 1050 | dir: Direction, |
| 1051 | ) -> Context<'c, C> { | ||
| 866 | let mut ctx: Context<'c, C> = Context { | 1052 | let mut ctx: Context<'c, C> = Context { |
| 867 | dir, | 1053 | dir, |
| 868 | last_block_processed: false, | 1054 | last_block_processed: false, |
| @@ -929,7 +1115,90 @@ impl<'d, T: Instance> Cryp<'d, T> { | |||
| 929 | // Flush in/out FIFOs | 1115 | // Flush in/out FIFOs |
| 930 | T::regs().cr().modify(|w| w.fflush()); | 1116 | T::regs().cr().modify(|w| w.fflush()); |
| 931 | 1117 | ||
| 932 | ctx.cipher.init_phase(&T::regs()); | 1118 | ctx.cipher.init_phase_blocking(&T::regs(), self); |
| 1119 | |||
| 1120 | self.store_context(&mut ctx); | ||
| 1121 | |||
| 1122 | ctx | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | /// Start a new encrypt or decrypt operation for the given cipher. | ||
| 1126 | pub async fn start<'c, C: Cipher<'c> + CipherSized + IVSized>( | ||
| 1127 | &mut self, | ||
| 1128 | cipher: &'c C, | ||
| 1129 | dir: Direction, | ||
| 1130 | ) -> Context<'c, C> | ||
| 1131 | where | ||
| 1132 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 1133 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 1134 | { | ||
| 1135 | let mut ctx: Context<'c, C> = Context { | ||
| 1136 | dir, | ||
| 1137 | last_block_processed: false, | ||
| 1138 | cr: 0, | ||
| 1139 | iv: [0; 4], | ||
| 1140 | csgcmccm: [0; 8], | ||
| 1141 | csgcm: [0; 8], | ||
| 1142 | aad_complete: false, | ||
| 1143 | header_len: 0, | ||
| 1144 | payload_len: 0, | ||
| 1145 | cipher: cipher, | ||
| 1146 | phantom_data: PhantomData, | ||
| 1147 | header_processed: false, | ||
| 1148 | aad_buffer: [0; 16], | ||
| 1149 | aad_buffer_len: 0, | ||
| 1150 | }; | ||
| 1151 | |||
| 1152 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1153 | |||
| 1154 | let key = ctx.cipher.key(); | ||
| 1155 | |||
| 1156 | if key.len() == (128 / 8) { | ||
| 1157 | T::regs().cr().modify(|w| w.set_keysize(0)); | ||
| 1158 | } else if key.len() == (192 / 8) { | ||
| 1159 | T::regs().cr().modify(|w| w.set_keysize(1)); | ||
| 1160 | } else if key.len() == (256 / 8) { | ||
| 1161 | T::regs().cr().modify(|w| w.set_keysize(2)); | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | self.load_key(key); | ||
| 1165 | |||
| 1166 | // Set data type to 8-bit. This will match software implementations. | ||
| 1167 | T::regs().cr().modify(|w| w.set_datatype(2)); | ||
| 1168 | |||
| 1169 | ctx.cipher.prepare_key(&T::regs()); | ||
| 1170 | |||
| 1171 | ctx.cipher.set_algomode(&T::regs()); | ||
| 1172 | |||
| 1173 | // Set encrypt/decrypt | ||
| 1174 | if dir == Direction::Encrypt { | ||
| 1175 | T::regs().cr().modify(|w| w.set_algodir(false)); | ||
| 1176 | } else { | ||
| 1177 | T::regs().cr().modify(|w| w.set_algodir(true)); | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | // Load the IV into the registers. | ||
| 1181 | let iv = ctx.cipher.iv(); | ||
| 1182 | let mut full_iv: [u8; 16] = [0; 16]; | ||
| 1183 | full_iv[0..iv.len()].copy_from_slice(iv); | ||
| 1184 | let mut iv_idx = 0; | ||
| 1185 | let mut iv_word: [u8; 4] = [0; 4]; | ||
| 1186 | iv_word.copy_from_slice(&full_iv[iv_idx..iv_idx + 4]); | ||
| 1187 | iv_idx += 4; | ||
| 1188 | T::regs().init(0).ivlr().write_value(u32::from_be_bytes(iv_word)); | ||
| 1189 | iv_word.copy_from_slice(&full_iv[iv_idx..iv_idx + 4]); | ||
| 1190 | iv_idx += 4; | ||
| 1191 | T::regs().init(0).ivrr().write_value(u32::from_be_bytes(iv_word)); | ||
| 1192 | iv_word.copy_from_slice(&full_iv[iv_idx..iv_idx + 4]); | ||
| 1193 | iv_idx += 4; | ||
| 1194 | T::regs().init(1).ivlr().write_value(u32::from_be_bytes(iv_word)); | ||
| 1195 | iv_word.copy_from_slice(&full_iv[iv_idx..iv_idx + 4]); | ||
| 1196 | T::regs().init(1).ivrr().write_value(u32::from_be_bytes(iv_word)); | ||
| 1197 | |||
| 1198 | // Flush in/out FIFOs | ||
| 1199 | T::regs().cr().modify(|w| w.fflush()); | ||
| 1200 | |||
| 1201 | ctx.cipher.init_phase(&T::regs(), self).await; | ||
| 933 | 1202 | ||
| 934 | self.store_context(&mut ctx); | 1203 | self.store_context(&mut ctx); |
| 935 | 1204 | ||
| @@ -938,10 +1207,9 @@ impl<'d, T: Instance> Cryp<'d, T> { | |||
| 938 | 1207 | ||
| 939 | #[cfg(any(cryp_v2, cryp_v3))] | 1208 | #[cfg(any(cryp_v2, cryp_v3))] |
| 940 | /// Controls the header phase of cipher processing. | 1209 | /// Controls the header phase of cipher processing. |
| 941 | /// This function is only valid for GCM, CCM, and GMAC modes. | 1210 | /// This function is only valid for authenticated ciphers including GCM, CCM, and GMAC. |
| 942 | /// It only needs to be called if using one of these modes and there is associated data. | 1211 | /// All additional associated data (AAD) must be supplied to this function prior to starting the payload phase with `payload_blocking`. |
| 943 | /// All AAD must be supplied to this function prior to starting the payload phase with `payload_blocking`. | 1212 | /// The AAD must be supplied in multiples of the block size (128-bits for AES, 64-bits for DES), except when supplying the last block. |
| 944 | /// The AAD must be supplied in multiples of the block size (128 bits), except when supplying the last block. | ||
| 945 | /// When supplying the last block of AAD, `last_aad_block` must be `true`. | 1213 | /// When supplying the last block of AAD, `last_aad_block` must be `true`. |
| 946 | pub fn aad_blocking< | 1214 | pub fn aad_blocking< |
| 947 | 'c, | 1215 | 'c, |
| @@ -985,15 +1253,7 @@ impl<'d, T: Instance> Cryp<'d, T> { | |||
| 985 | if ctx.aad_buffer_len < C::BLOCK_SIZE { | 1253 | if ctx.aad_buffer_len < C::BLOCK_SIZE { |
| 986 | // The buffer isn't full and this is the last buffer, so process it as is (already padded). | 1254 | // The buffer isn't full and this is the last buffer, so process it as is (already padded). |
| 987 | if last_aad_block { | 1255 | if last_aad_block { |
| 988 | let mut index = 0; | 1256 | self.write_bytes_blocking(C::BLOCK_SIZE, &ctx.aad_buffer); |
| 989 | let end_index = C::BLOCK_SIZE; | ||
| 990 | // Write block in | ||
| 991 | while index < end_index { | ||
| 992 | let mut in_word: [u8; 4] = [0; 4]; | ||
| 993 | in_word.copy_from_slice(&ctx.aad_buffer[index..index + 4]); | ||
| 994 | T::regs().din().write_value(u32::from_ne_bytes(in_word)); | ||
| 995 | index += 4; | ||
| 996 | } | ||
| 997 | // Block until input FIFO is empty. | 1257 | // Block until input FIFO is empty. |
| 998 | while !T::regs().sr().read().ifem() {} | 1258 | while !T::regs().sr().read().ifem() {} |
| 999 | 1259 | ||
| @@ -1008,15 +1268,7 @@ impl<'d, T: Instance> Cryp<'d, T> { | |||
| 1008 | } | 1268 | } |
| 1009 | } else { | 1269 | } else { |
| 1010 | // Load the full block from the buffer. | 1270 | // Load the full block from the buffer. |
| 1011 | let mut index = 0; | 1271 | self.write_bytes_blocking(C::BLOCK_SIZE, &ctx.aad_buffer); |
| 1012 | let end_index = C::BLOCK_SIZE; | ||
| 1013 | // Write block in | ||
| 1014 | while index < end_index { | ||
| 1015 | let mut in_word: [u8; 4] = [0; 4]; | ||
| 1016 | in_word.copy_from_slice(&ctx.aad_buffer[index..index + 4]); | ||
| 1017 | T::regs().din().write_value(u32::from_ne_bytes(in_word)); | ||
| 1018 | index += 4; | ||
| 1019 | } | ||
| 1020 | // Block until input FIFO is empty. | 1272 | // Block until input FIFO is empty. |
| 1021 | while !T::regs().sr().read().ifem() {} | 1273 | while !T::regs().sr().read().ifem() {} |
| 1022 | } | 1274 | } |
| @@ -1032,33 +1284,108 @@ impl<'d, T: Instance> Cryp<'d, T> { | |||
| 1032 | 1284 | ||
| 1033 | // Load full data blocks into core. | 1285 | // Load full data blocks into core. |
| 1034 | let num_full_blocks = aad_len_remaining / C::BLOCK_SIZE; | 1286 | let num_full_blocks = aad_len_remaining / C::BLOCK_SIZE; |
| 1035 | for block in 0..num_full_blocks { | 1287 | let start_index = len_to_copy; |
| 1036 | let mut index = len_to_copy + (block * C::BLOCK_SIZE); | 1288 | let end_index = start_index + (C::BLOCK_SIZE * num_full_blocks); |
| 1037 | let end_index = index + C::BLOCK_SIZE; | 1289 | self.write_bytes_blocking(C::BLOCK_SIZE, &aad[start_index..end_index]); |
| 1038 | // Write block in | 1290 | |
| 1039 | while index < end_index { | 1291 | if last_aad_block { |
| 1040 | let mut in_word: [u8; 4] = [0; 4]; | 1292 | if leftovers > 0 { |
| 1041 | in_word.copy_from_slice(&aad[index..index + 4]); | 1293 | self.write_bytes_blocking(C::BLOCK_SIZE, &ctx.aad_buffer); |
| 1042 | T::regs().din().write_value(u32::from_ne_bytes(in_word)); | ||
| 1043 | index += 4; | ||
| 1044 | } | 1294 | } |
| 1045 | // Block until input FIFO is empty. | 1295 | // Switch to payload phase. |
| 1046 | while !T::regs().sr().read().ifem() {} | 1296 | ctx.aad_complete = true; |
| 1297 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1298 | T::regs().cr().modify(|w| w.set_gcm_ccmph(2)); | ||
| 1299 | T::regs().cr().modify(|w| w.fflush()); | ||
| 1300 | } | ||
| 1301 | |||
| 1302 | self.store_context(ctx); | ||
| 1303 | } | ||
| 1304 | |||
| 1305 | #[cfg(any(cryp_v2, cryp_v3))] | ||
| 1306 | /// Controls the header phase of cipher processing. | ||
| 1307 | /// This function is only valid for authenticated ciphers including GCM, CCM, and GMAC. | ||
| 1308 | /// All additional associated data (AAD) must be supplied to this function prior to starting the payload phase with `payload`. | ||
| 1309 | /// The AAD must be supplied in multiples of the block size (128-bits for AES, 64-bits for DES), except when supplying the last block. | ||
| 1310 | /// When supplying the last block of AAD, `last_aad_block` must be `true`. | ||
| 1311 | pub async fn aad<'c, const TAG_SIZE: usize, C: Cipher<'c> + CipherSized + IVSized + CipherAuthenticated<TAG_SIZE>>( | ||
| 1312 | &mut self, | ||
| 1313 | ctx: &mut Context<'c, C>, | ||
| 1314 | aad: &[u8], | ||
| 1315 | last_aad_block: bool, | ||
| 1316 | ) where | ||
| 1317 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 1318 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 1319 | { | ||
| 1320 | self.load_context(ctx); | ||
| 1321 | |||
| 1322 | // Perform checks for correctness. | ||
| 1323 | if ctx.aad_complete { | ||
| 1324 | panic!("Cannot update AAD after starting payload!") | ||
| 1325 | } | ||
| 1326 | |||
| 1327 | ctx.header_len += aad.len() as u64; | ||
| 1328 | |||
| 1329 | // Header phase | ||
| 1330 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1331 | T::regs().cr().modify(|w| w.set_gcm_ccmph(1)); | ||
| 1332 | T::regs().cr().modify(|w| w.set_crypen(true)); | ||
| 1333 | |||
| 1334 | // First write the header B1 block if not yet written. | ||
| 1335 | if !ctx.header_processed { | ||
| 1336 | ctx.header_processed = true; | ||
| 1337 | let header = ctx.cipher.get_header_block(); | ||
| 1338 | ctx.aad_buffer[0..header.len()].copy_from_slice(header); | ||
| 1339 | ctx.aad_buffer_len += header.len(); | ||
| 1340 | } | ||
| 1341 | |||
| 1342 | // Fill the header block to make a full block. | ||
| 1343 | let len_to_copy = min(aad.len(), C::BLOCK_SIZE - ctx.aad_buffer_len); | ||
| 1344 | ctx.aad_buffer[ctx.aad_buffer_len..ctx.aad_buffer_len + len_to_copy].copy_from_slice(&aad[..len_to_copy]); | ||
| 1345 | ctx.aad_buffer_len += len_to_copy; | ||
| 1346 | ctx.aad_buffer[ctx.aad_buffer_len..].fill(0); | ||
| 1347 | let mut aad_len_remaining = aad.len() - len_to_copy; | ||
| 1348 | |||
| 1349 | if ctx.aad_buffer_len < C::BLOCK_SIZE { | ||
| 1350 | // The buffer isn't full and this is the last buffer, so process it as is (already padded). | ||
| 1351 | if last_aad_block { | ||
| 1352 | Self::write_bytes(&mut self.indma, C::BLOCK_SIZE, &ctx.aad_buffer).await; | ||
| 1353 | assert_eq!(T::regs().sr().read().ifem(), true); | ||
| 1354 | |||
| 1355 | // Switch to payload phase. | ||
| 1356 | ctx.aad_complete = true; | ||
| 1357 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1358 | T::regs().cr().modify(|w| w.set_gcm_ccmph(2)); | ||
| 1359 | T::regs().cr().modify(|w| w.fflush()); | ||
| 1360 | } else { | ||
| 1361 | // Just return because we don't yet have a full block to process. | ||
| 1362 | return; | ||
| 1363 | } | ||
| 1364 | } else { | ||
| 1365 | // Load the full block from the buffer. | ||
| 1366 | Self::write_bytes(&mut self.indma, C::BLOCK_SIZE, &ctx.aad_buffer).await; | ||
| 1367 | assert_eq!(T::regs().sr().read().ifem(), true); | ||
| 1047 | } | 1368 | } |
| 1048 | 1369 | ||
| 1370 | // Handle a partial block that is passed in. | ||
| 1371 | ctx.aad_buffer_len = 0; | ||
| 1372 | let leftovers = aad_len_remaining % C::BLOCK_SIZE; | ||
| 1373 | ctx.aad_buffer[..leftovers].copy_from_slice(&aad[aad.len() - leftovers..aad.len()]); | ||
| 1374 | ctx.aad_buffer_len += leftovers; | ||
| 1375 | ctx.aad_buffer[ctx.aad_buffer_len..].fill(0); | ||
| 1376 | aad_len_remaining -= leftovers; | ||
| 1377 | assert_eq!(aad_len_remaining % C::BLOCK_SIZE, 0); | ||
| 1378 | |||
| 1379 | // Load full data blocks into core. | ||
| 1380 | let num_full_blocks = aad_len_remaining / C::BLOCK_SIZE; | ||
| 1381 | let start_index = len_to_copy; | ||
| 1382 | let end_index = start_index + (C::BLOCK_SIZE * num_full_blocks); | ||
| 1383 | Self::write_bytes(&mut self.indma, C::BLOCK_SIZE, &aad[start_index..end_index]).await; | ||
| 1384 | |||
| 1049 | if last_aad_block { | 1385 | if last_aad_block { |
| 1050 | if leftovers > 0 { | 1386 | if leftovers > 0 { |
| 1051 | let mut index = 0; | 1387 | Self::write_bytes(&mut self.indma, C::BLOCK_SIZE, &ctx.aad_buffer).await; |
| 1052 | let end_index = C::BLOCK_SIZE; | 1388 | assert_eq!(T::regs().sr().read().ifem(), true); |
| 1053 | // Write block in | ||
| 1054 | while index < end_index { | ||
| 1055 | let mut in_word: [u8; 4] = [0; 4]; | ||
| 1056 | in_word.copy_from_slice(&ctx.aad_buffer[index..index + 4]); | ||
| 1057 | T::regs().din().write_value(u32::from_ne_bytes(in_word)); | ||
| 1058 | index += 4; | ||
| 1059 | } | ||
| 1060 | // Block until input FIFO is empty. | ||
| 1061 | while !T::regs().sr().read().ifem() {} | ||
| 1062 | } | 1389 | } |
| 1063 | // Switch to payload phase. | 1390 | // Switch to payload phase. |
| 1064 | ctx.aad_complete = true; | 1391 | ctx.aad_complete = true; |
| @@ -1074,7 +1401,7 @@ impl<'d, T: Instance> Cryp<'d, T> { | |||
| 1074 | /// The context determines algorithm, mode, and state of the crypto accelerator. | 1401 | /// The context determines algorithm, mode, and state of the crypto accelerator. |
| 1075 | /// When the last piece of data is supplied, `last_block` should be `true`. | 1402 | /// When the last piece of data is supplied, `last_block` should be `true`. |
| 1076 | /// This function panics under various mismatches of parameters. | 1403 | /// This function panics under various mismatches of parameters. |
| 1077 | /// Input and output buffer lengths must match. | 1404 | /// Output buffer must be at least as long as the input buffer. |
| 1078 | /// Data must be a multiple of block size (128-bits for AES, 64-bits for DES) for CBC and ECB modes. | 1405 | /// Data must be a multiple of block size (128-bits for AES, 64-bits for DES) for CBC and ECB modes. |
| 1079 | /// Padding or ciphertext stealing must be managed by the application for these modes. | 1406 | /// Padding or ciphertext stealing must be managed by the application for these modes. |
| 1080 | /// Data must also be a multiple of block size unless `last_block` is `true`. | 1407 | /// Data must also be a multiple of block size unless `last_block` is `true`. |
| @@ -1125,54 +1452,121 @@ impl<'d, T: Instance> Cryp<'d, T> { | |||
| 1125 | // Load data into core, block by block. | 1452 | // Load data into core, block by block. |
| 1126 | let num_full_blocks = input.len() / C::BLOCK_SIZE; | 1453 | let num_full_blocks = input.len() / C::BLOCK_SIZE; |
| 1127 | for block in 0..num_full_blocks { | 1454 | for block in 0..num_full_blocks { |
| 1128 | let mut index = block * C::BLOCK_SIZE; | 1455 | let index = block * C::BLOCK_SIZE; |
| 1129 | let end_index = index + C::BLOCK_SIZE; | ||
| 1130 | // Write block in | 1456 | // Write block in |
| 1131 | while index < end_index { | 1457 | self.write_bytes_blocking(C::BLOCK_SIZE, &input[index..index + C::BLOCK_SIZE]); |
| 1132 | let mut in_word: [u8; 4] = [0; 4]; | ||
| 1133 | in_word.copy_from_slice(&input[index..index + 4]); | ||
| 1134 | T::regs().din().write_value(u32::from_ne_bytes(in_word)); | ||
| 1135 | index += 4; | ||
| 1136 | } | ||
| 1137 | let mut index = block * C::BLOCK_SIZE; | ||
| 1138 | let end_index = index + C::BLOCK_SIZE; | ||
| 1139 | // Block until there is output to read. | ||
| 1140 | while !T::regs().sr().read().ofne() {} | ||
| 1141 | // Read block out | 1458 | // Read block out |
| 1142 | while index < end_index { | 1459 | self.read_bytes_blocking(C::BLOCK_SIZE, &mut output[index..index + C::BLOCK_SIZE]); |
| 1143 | let out_word: u32 = T::regs().dout().read(); | ||
| 1144 | output[index..index + 4].copy_from_slice(u32::to_ne_bytes(out_word).as_slice()); | ||
| 1145 | index += 4; | ||
| 1146 | } | ||
| 1147 | } | 1460 | } |
| 1148 | 1461 | ||
| 1149 | // Handle the final block, which is incomplete. | 1462 | // Handle the final block, which is incomplete. |
| 1150 | if last_block_remainder > 0 { | 1463 | if last_block_remainder > 0 { |
| 1151 | let padding_len = C::BLOCK_SIZE - last_block_remainder; | 1464 | let padding_len = C::BLOCK_SIZE - last_block_remainder; |
| 1152 | let temp1 = ctx.cipher.pre_final_block(&T::regs(), ctx.dir, padding_len); | 1465 | let temp1 = ctx.cipher.pre_final(&T::regs(), ctx.dir, padding_len); |
| 1153 | 1466 | ||
| 1154 | let mut intermediate_data: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; | 1467 | let mut intermediate_data: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; |
| 1155 | let mut last_block: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; | 1468 | let mut last_block: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; |
| 1156 | last_block[..last_block_remainder].copy_from_slice(&input[input.len() - last_block_remainder..input.len()]); | 1469 | last_block[..last_block_remainder].copy_from_slice(&input[input.len() - last_block_remainder..input.len()]); |
| 1157 | let mut index = 0; | 1470 | self.write_bytes_blocking(C::BLOCK_SIZE, &last_block); |
| 1158 | let end_index = C::BLOCK_SIZE; | 1471 | self.read_bytes_blocking(C::BLOCK_SIZE, &mut intermediate_data); |
| 1159 | // Write block in | 1472 | |
| 1160 | while index < end_index { | 1473 | // Handle the last block depending on mode. |
| 1161 | let mut in_word: [u8; 4] = [0; 4]; | 1474 | let output_len = output.len(); |
| 1162 | in_word.copy_from_slice(&last_block[index..index + 4]); | 1475 | output[output_len - last_block_remainder..output_len] |
| 1163 | T::regs().din().write_value(u32::from_ne_bytes(in_word)); | 1476 | .copy_from_slice(&intermediate_data[0..last_block_remainder]); |
| 1164 | index += 4; | 1477 | |
| 1478 | let mut mask: [u8; 16] = [0; 16]; | ||
| 1479 | mask[..last_block_remainder].fill(0xFF); | ||
| 1480 | ctx.cipher | ||
| 1481 | .post_final_blocking(&T::regs(), self, ctx.dir, &mut intermediate_data, temp1, mask); | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | ctx.payload_len += input.len() as u64; | ||
| 1485 | |||
| 1486 | self.store_context(ctx); | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | /// Performs encryption/decryption on the provided context. | ||
| 1490 | /// The context determines algorithm, mode, and state of the crypto accelerator. | ||
| 1491 | /// When the last piece of data is supplied, `last_block` should be `true`. | ||
| 1492 | /// This function panics under various mismatches of parameters. | ||
| 1493 | /// Output buffer must be at least as long as the input buffer. | ||
| 1494 | /// Data must be a multiple of block size (128-bits for AES, 64-bits for DES) for CBC and ECB modes. | ||
| 1495 | /// Padding or ciphertext stealing must be managed by the application for these modes. | ||
| 1496 | /// Data must also be a multiple of block size unless `last_block` is `true`. | ||
| 1497 | pub async fn payload<'c, C: Cipher<'c> + CipherSized + IVSized>( | ||
| 1498 | &mut self, | ||
| 1499 | ctx: &mut Context<'c, C>, | ||
| 1500 | input: &[u8], | ||
| 1501 | output: &mut [u8], | ||
| 1502 | last_block: bool, | ||
| 1503 | ) where | ||
| 1504 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 1505 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 1506 | { | ||
| 1507 | self.load_context(ctx); | ||
| 1508 | |||
| 1509 | let last_block_remainder = input.len() % C::BLOCK_SIZE; | ||
| 1510 | |||
| 1511 | // Perform checks for correctness. | ||
| 1512 | if !ctx.aad_complete && ctx.header_len > 0 { | ||
| 1513 | panic!("Additional associated data must be processed first!"); | ||
| 1514 | } else if !ctx.aad_complete { | ||
| 1515 | #[cfg(any(cryp_v2, cryp_v3))] | ||
| 1516 | { | ||
| 1517 | ctx.aad_complete = true; | ||
| 1518 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1519 | T::regs().cr().modify(|w| w.set_gcm_ccmph(2)); | ||
| 1520 | T::regs().cr().modify(|w| w.fflush()); | ||
| 1521 | T::regs().cr().modify(|w| w.set_crypen(true)); | ||
| 1165 | } | 1522 | } |
| 1166 | let mut index = 0; | 1523 | } |
| 1167 | let end_index = C::BLOCK_SIZE; | 1524 | if ctx.last_block_processed { |
| 1168 | // Block until there is output to read. | 1525 | panic!("The last block has already been processed!"); |
| 1169 | while !T::regs().sr().read().ofne() {} | 1526 | } |
| 1170 | // Read block out | 1527 | if input.len() > output.len() { |
| 1171 | while index < end_index { | 1528 | panic!("Output buffer length must match input length."); |
| 1172 | let out_word: u32 = T::regs().dout().read(); | 1529 | } |
| 1173 | intermediate_data[index..index + 4].copy_from_slice(u32::to_ne_bytes(out_word).as_slice()); | 1530 | if !last_block { |
| 1174 | index += 4; | 1531 | if last_block_remainder != 0 { |
| 1532 | panic!("Input length must be a multiple of {} bytes.", C::BLOCK_SIZE); | ||
| 1533 | } | ||
| 1534 | } | ||
| 1535 | if C::REQUIRES_PADDING { | ||
| 1536 | if last_block_remainder != 0 { | ||
| 1537 | panic!("Input must be a multiple of {} bytes in ECB and CBC modes. Consider padding or ciphertext stealing.", C::BLOCK_SIZE); | ||
| 1175 | } | 1538 | } |
| 1539 | } | ||
| 1540 | if last_block { | ||
| 1541 | ctx.last_block_processed = true; | ||
| 1542 | } | ||
| 1543 | |||
| 1544 | // Load data into core, block by block. | ||
| 1545 | let num_full_blocks = input.len() / C::BLOCK_SIZE; | ||
| 1546 | for block in 0..num_full_blocks { | ||
| 1547 | let index = block * C::BLOCK_SIZE; | ||
| 1548 | // Read block out | ||
| 1549 | let read = Self::read_bytes( | ||
| 1550 | &mut self.outdma, | ||
| 1551 | C::BLOCK_SIZE, | ||
| 1552 | &mut output[index..index + C::BLOCK_SIZE], | ||
| 1553 | ); | ||
| 1554 | // Write block in | ||
| 1555 | let write = Self::write_bytes(&mut self.indma, C::BLOCK_SIZE, &input[index..index + C::BLOCK_SIZE]); | ||
| 1556 | embassy_futures::join::join(read, write).await; | ||
| 1557 | } | ||
| 1558 | |||
| 1559 | // Handle the final block, which is incomplete. | ||
| 1560 | if last_block_remainder > 0 { | ||
| 1561 | let padding_len = C::BLOCK_SIZE - last_block_remainder; | ||
| 1562 | let temp1 = ctx.cipher.pre_final(&T::regs(), ctx.dir, padding_len); | ||
| 1563 | |||
| 1564 | let mut intermediate_data: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; | ||
| 1565 | let mut last_block: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; | ||
| 1566 | last_block[..last_block_remainder].copy_from_slice(&input[input.len() - last_block_remainder..input.len()]); | ||
| 1567 | let read = Self::read_bytes(&mut self.outdma, C::BLOCK_SIZE, &mut intermediate_data); | ||
| 1568 | let write = Self::write_bytes(&mut self.indma, C::BLOCK_SIZE, &last_block); | ||
| 1569 | embassy_futures::join::join(read, write).await; | ||
| 1176 | 1570 | ||
| 1177 | // Handle the last block depending on mode. | 1571 | // Handle the last block depending on mode. |
| 1178 | let output_len = output.len(); | 1572 | let output_len = output.len(); |
| @@ -1182,7 +1576,8 @@ impl<'d, T: Instance> Cryp<'d, T> { | |||
| 1182 | let mut mask: [u8; 16] = [0; 16]; | 1576 | let mut mask: [u8; 16] = [0; 16]; |
| 1183 | mask[..last_block_remainder].fill(0xFF); | 1577 | mask[..last_block_remainder].fill(0xFF); |
| 1184 | ctx.cipher | 1578 | ctx.cipher |
| 1185 | .post_final_block(&T::regs(), ctx.dir, &mut intermediate_data, temp1, mask); | 1579 | .post_final(&T::regs(), self, ctx.dir, &mut intermediate_data, temp1, mask) |
| 1580 | .await; | ||
| 1186 | } | 1581 | } |
| 1187 | 1582 | ||
| 1188 | ctx.payload_len += input.len() as u64; | 1583 | ctx.payload_len += input.len() as u64; |
| @@ -1191,8 +1586,8 @@ impl<'d, T: Instance> Cryp<'d, T> { | |||
| 1191 | } | 1586 | } |
| 1192 | 1587 | ||
| 1193 | #[cfg(any(cryp_v2, cryp_v3))] | 1588 | #[cfg(any(cryp_v2, cryp_v3))] |
| 1194 | /// This function only needs to be called for GCM, CCM, and GMAC modes to | 1589 | /// Generates an authentication tag for authenticated ciphers including GCM, CCM, and GMAC. |
| 1195 | /// generate an authentication tag. | 1590 | /// Called after the all data has been encrypted/decrypted by `payload`. |
| 1196 | pub fn finish_blocking< | 1591 | pub fn finish_blocking< |
| 1197 | 'c, | 1592 | 'c, |
| 1198 | const TAG_SIZE: usize, | 1593 | const TAG_SIZE: usize, |
| @@ -1213,28 +1608,72 @@ impl<'d, T: Instance> Cryp<'d, T> { | |||
| 1213 | let payloadlen2: u32 = (ctx.payload_len * 8) as u32; | 1608 | let payloadlen2: u32 = (ctx.payload_len * 8) as u32; |
| 1214 | 1609 | ||
| 1215 | #[cfg(cryp_v2)] | 1610 | #[cfg(cryp_v2)] |
| 1216 | { | 1611 | let footer: [u32; 4] = [ |
| 1217 | T::regs().din().write_value(headerlen1.swap_bytes()); | 1612 | headerlen1.swap_bytes(), |
| 1218 | T::regs().din().write_value(headerlen2.swap_bytes()); | 1613 | headerlen2.swap_bytes(), |
| 1219 | T::regs().din().write_value(payloadlen1.swap_bytes()); | 1614 | payloadlen1.swap_bytes(), |
| 1220 | T::regs().din().write_value(payloadlen2.swap_bytes()); | 1615 | payloadlen2.swap_bytes(), |
| 1221 | } | 1616 | ]; |
| 1222 | |||
| 1223 | #[cfg(cryp_v3)] | 1617 | #[cfg(cryp_v3)] |
| 1224 | { | 1618 | let footer: [u32; 4] = [headerlen1, headerlen2, payloadlen1, payloadlen2]; |
| 1225 | T::regs().din().write_value(headerlen1); | 1619 | |
| 1226 | T::regs().din().write_value(headerlen2); | 1620 | self.write_words_blocking(C::BLOCK_SIZE, &footer); |
| 1227 | T::regs().din().write_value(payloadlen1); | ||
| 1228 | T::regs().din().write_value(payloadlen2); | ||
| 1229 | } | ||
| 1230 | 1621 | ||
| 1231 | while !T::regs().sr().read().ofne() {} | 1622 | while !T::regs().sr().read().ofne() {} |
| 1232 | 1623 | ||
| 1233 | let mut full_tag: [u8; 16] = [0; 16]; | 1624 | let mut full_tag: [u8; 16] = [0; 16]; |
| 1234 | full_tag[0..4].copy_from_slice(T::regs().dout().read().to_ne_bytes().as_slice()); | 1625 | self.read_bytes_blocking(C::BLOCK_SIZE, &mut full_tag); |
| 1235 | full_tag[4..8].copy_from_slice(T::regs().dout().read().to_ne_bytes().as_slice()); | 1626 | let mut tag: [u8; TAG_SIZE] = [0; TAG_SIZE]; |
| 1236 | full_tag[8..12].copy_from_slice(T::regs().dout().read().to_ne_bytes().as_slice()); | 1627 | tag.copy_from_slice(&full_tag[0..TAG_SIZE]); |
| 1237 | full_tag[12..16].copy_from_slice(T::regs().dout().read().to_ne_bytes().as_slice()); | 1628 | |
| 1629 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1630 | |||
| 1631 | tag | ||
| 1632 | } | ||
| 1633 | |||
| 1634 | #[cfg(any(cryp_v2, cryp_v3))] | ||
| 1635 | // Generates an authentication tag for authenticated ciphers including GCM, CCM, and GMAC. | ||
| 1636 | /// Called after the all data has been encrypted/decrypted by `payload`. | ||
| 1637 | pub async fn finish< | ||
| 1638 | 'c, | ||
| 1639 | const TAG_SIZE: usize, | ||
| 1640 | C: Cipher<'c> + CipherSized + IVSized + CipherAuthenticated<TAG_SIZE>, | ||
| 1641 | >( | ||
| 1642 | &mut self, | ||
| 1643 | mut ctx: Context<'c, C>, | ||
| 1644 | ) -> [u8; TAG_SIZE] | ||
| 1645 | where | ||
| 1646 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 1647 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 1648 | { | ||
| 1649 | self.load_context(&mut ctx); | ||
| 1650 | |||
| 1651 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1652 | T::regs().cr().modify(|w| w.set_gcm_ccmph(3)); | ||
| 1653 | T::regs().cr().modify(|w| w.set_crypen(true)); | ||
| 1654 | |||
| 1655 | let headerlen1: u32 = ((ctx.header_len * 8) >> 32) as u32; | ||
| 1656 | let headerlen2: u32 = (ctx.header_len * 8) as u32; | ||
| 1657 | let payloadlen1: u32 = ((ctx.payload_len * 8) >> 32) as u32; | ||
| 1658 | let payloadlen2: u32 = (ctx.payload_len * 8) as u32; | ||
| 1659 | |||
| 1660 | #[cfg(cryp_v2)] | ||
| 1661 | let footer: [u32; 4] = [ | ||
| 1662 | headerlen1.swap_bytes(), | ||
| 1663 | headerlen2.swap_bytes(), | ||
| 1664 | payloadlen1.swap_bytes(), | ||
| 1665 | payloadlen2.swap_bytes(), | ||
| 1666 | ]; | ||
| 1667 | #[cfg(cryp_v3)] | ||
| 1668 | let footer: [u32; 4] = [headerlen1, headerlen2, payloadlen1, payloadlen2]; | ||
| 1669 | |||
| 1670 | let write = Self::write_words(&mut self.indma, C::BLOCK_SIZE, &footer); | ||
| 1671 | |||
| 1672 | let mut full_tag: [u8; 16] = [0; 16]; | ||
| 1673 | let read = Self::read_bytes(&mut self.outdma, C::BLOCK_SIZE, &mut full_tag); | ||
| 1674 | |||
| 1675 | embassy_futures::join::join(read, write).await; | ||
| 1676 | |||
| 1238 | let mut tag: [u8; TAG_SIZE] = [0; TAG_SIZE]; | 1677 | let mut tag: [u8; TAG_SIZE] = [0; TAG_SIZE]; |
| 1239 | tag.copy_from_slice(&full_tag[0..TAG_SIZE]); | 1678 | tag.copy_from_slice(&full_tag[0..TAG_SIZE]); |
| 1240 | 1679 | ||
| @@ -1325,6 +1764,125 @@ impl<'d, T: Instance> Cryp<'d, T> { | |||
| 1325 | // Enable crypto processor. | 1764 | // Enable crypto processor. |
| 1326 | T::regs().cr().modify(|w| w.set_crypen(true)); | 1765 | T::regs().cr().modify(|w| w.set_crypen(true)); |
| 1327 | } | 1766 | } |
| 1767 | |||
| 1768 | fn write_bytes_blocking(&self, block_size: usize, blocks: &[u8]) { | ||
| 1769 | // Ensure input is a multiple of block size. | ||
| 1770 | assert_eq!(blocks.len() % block_size, 0); | ||
| 1771 | let mut index = 0; | ||
| 1772 | let end_index = blocks.len(); | ||
| 1773 | while index < end_index { | ||
| 1774 | let mut in_word: [u8; 4] = [0; 4]; | ||
| 1775 | in_word.copy_from_slice(&blocks[index..index + 4]); | ||
| 1776 | T::regs().din().write_value(u32::from_ne_bytes(in_word)); | ||
| 1777 | index += 4; | ||
| 1778 | if index % block_size == 0 { | ||
| 1779 | // Block until input FIFO is empty. | ||
| 1780 | while !T::regs().sr().read().ifem() {} | ||
| 1781 | } | ||
| 1782 | } | ||
| 1783 | } | ||
| 1784 | |||
| 1785 | async fn write_bytes(dma: &mut PeripheralRef<'_, DmaIn>, block_size: usize, blocks: &[u8]) | ||
| 1786 | where | ||
| 1787 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 1788 | { | ||
| 1789 | if blocks.len() == 0 { | ||
| 1790 | return; | ||
| 1791 | } | ||
| 1792 | // Ensure input is a multiple of block size. | ||
| 1793 | assert_eq!(blocks.len() % block_size, 0); | ||
| 1794 | // Configure DMA to transfer input to crypto core. | ||
| 1795 | let dma_request = dma.request(); | ||
| 1796 | let dst_ptr = T::regs().din().as_ptr(); | ||
| 1797 | let num_words = blocks.len() / 4; | ||
| 1798 | let src_ptr = ptr::slice_from_raw_parts(blocks.as_ptr().cast(), num_words); | ||
| 1799 | let options = TransferOptions { | ||
| 1800 | priority: Priority::High, | ||
| 1801 | ..Default::default() | ||
| 1802 | }; | ||
| 1803 | let dma_transfer = unsafe { Transfer::new_write_raw(dma, dma_request, src_ptr, dst_ptr, options) }; | ||
| 1804 | T::regs().dmacr().modify(|w| w.set_dien(true)); | ||
| 1805 | // Wait for the transfer to complete. | ||
| 1806 | dma_transfer.await; | ||
| 1807 | } | ||
| 1808 | |||
| 1809 | #[cfg(any(cryp_v2, cryp_v3))] | ||
| 1810 | fn write_words_blocking(&self, block_size: usize, blocks: &[u32]) { | ||
| 1811 | assert_eq!((blocks.len() * 4) % block_size, 0); | ||
| 1812 | let mut byte_counter: usize = 0; | ||
| 1813 | for word in blocks { | ||
| 1814 | T::regs().din().write_value(*word); | ||
| 1815 | byte_counter += 4; | ||
| 1816 | if byte_counter % block_size == 0 { | ||
| 1817 | // Block until input FIFO is empty. | ||
| 1818 | while !T::regs().sr().read().ifem() {} | ||
| 1819 | } | ||
| 1820 | } | ||
| 1821 | } | ||
| 1822 | |||
| 1823 | #[cfg(any(cryp_v2, cryp_v3))] | ||
| 1824 | async fn write_words(dma: &mut PeripheralRef<'_, DmaIn>, block_size: usize, blocks: &[u32]) | ||
| 1825 | where | ||
| 1826 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 1827 | { | ||
| 1828 | if blocks.len() == 0 { | ||
| 1829 | return; | ||
| 1830 | } | ||
| 1831 | // Ensure input is a multiple of block size. | ||
| 1832 | assert_eq!((blocks.len() * 4) % block_size, 0); | ||
| 1833 | // Configure DMA to transfer input to crypto core. | ||
| 1834 | let dma_request = dma.request(); | ||
| 1835 | let dst_ptr = T::regs().din().as_ptr(); | ||
| 1836 | let num_words = blocks.len(); | ||
| 1837 | let src_ptr = ptr::slice_from_raw_parts(blocks.as_ptr().cast(), num_words); | ||
| 1838 | let options = TransferOptions { | ||
| 1839 | priority: Priority::High, | ||
| 1840 | ..Default::default() | ||
| 1841 | }; | ||
| 1842 | let dma_transfer = unsafe { Transfer::new_write_raw(dma, dma_request, src_ptr, dst_ptr, options) }; | ||
| 1843 | T::regs().dmacr().modify(|w| w.set_dien(true)); | ||
| 1844 | // Wait for the transfer to complete. | ||
| 1845 | dma_transfer.await; | ||
| 1846 | } | ||
| 1847 | |||
| 1848 | fn read_bytes_blocking(&self, block_size: usize, blocks: &mut [u8]) { | ||
| 1849 | // Block until there is output to read. | ||
| 1850 | while !T::regs().sr().read().ofne() {} | ||
| 1851 | // Ensure input is a multiple of block size. | ||
| 1852 | assert_eq!(blocks.len() % block_size, 0); | ||
| 1853 | // Read block out | ||
| 1854 | let mut index = 0; | ||
| 1855 | let end_index = blocks.len(); | ||
| 1856 | while index < end_index { | ||
| 1857 | let out_word: u32 = T::regs().dout().read(); | ||
| 1858 | blocks[index..index + 4].copy_from_slice(u32::to_ne_bytes(out_word).as_slice()); | ||
| 1859 | index += 4; | ||
| 1860 | } | ||
| 1861 | } | ||
| 1862 | |||
| 1863 | async fn read_bytes(dma: &mut PeripheralRef<'_, DmaOut>, block_size: usize, blocks: &mut [u8]) | ||
| 1864 | where | ||
| 1865 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 1866 | { | ||
| 1867 | if blocks.len() == 0 { | ||
| 1868 | return; | ||
| 1869 | } | ||
| 1870 | // Ensure input is a multiple of block size. | ||
| 1871 | assert_eq!(blocks.len() % block_size, 0); | ||
| 1872 | // Configure DMA to get output from crypto core. | ||
| 1873 | let dma_request = dma.request(); | ||
| 1874 | let src_ptr = T::regs().dout().as_ptr(); | ||
| 1875 | let num_words = blocks.len() / 4; | ||
| 1876 | let dst_ptr = ptr::slice_from_raw_parts_mut(blocks.as_mut_ptr().cast(), num_words); | ||
| 1877 | let options = TransferOptions { | ||
| 1878 | priority: Priority::VeryHigh, | ||
| 1879 | ..Default::default() | ||
| 1880 | }; | ||
| 1881 | let dma_transfer = unsafe { Transfer::new_read_raw(dma, dma_request, src_ptr, dst_ptr, options) }; | ||
| 1882 | T::regs().dmacr().modify(|w| w.set_doen(true)); | ||
| 1883 | // Wait for the transfer to complete. | ||
| 1884 | dma_transfer.await; | ||
| 1885 | } | ||
| 1328 | } | 1886 | } |
| 1329 | 1887 | ||
| 1330 | pub(crate) mod sealed { | 1888 | pub(crate) mod sealed { |
| @@ -1354,3 +1912,6 @@ foreach_interrupt!( | |||
| 1354 | } | 1912 | } |
| 1355 | }; | 1913 | }; |
| 1356 | ); | 1914 | ); |
| 1915 | |||
| 1916 | dma_trait!(DmaIn, Instance); | ||
| 1917 | dma_trait!(DmaOut, Instance); | ||
diff --git a/examples/stm32f7/src/bin/cryp.rs b/examples/stm32f7/src/bin/cryp.rs index 04927841a..235853cb9 100644 --- a/examples/stm32f7/src/bin/cryp.rs +++ b/examples/stm32f7/src/bin/cryp.rs | |||
| @@ -6,11 +6,15 @@ use aes_gcm::aead::{AeadInPlace, KeyInit}; | |||
| 6 | use aes_gcm::Aes128Gcm; | 6 | use aes_gcm::Aes128Gcm; |
| 7 | use defmt::info; | 7 | use defmt::info; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::cryp::*; | 9 | use embassy_stm32::cryp::{self, *}; |
| 10 | use embassy_stm32::Config; | 10 | use embassy_stm32::{bind_interrupts, peripherals, Config}; |
| 11 | use embassy_time::Instant; | 11 | use embassy_time::Instant; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| 14 | bind_interrupts!(struct Irqs { | ||
| 15 | CRYP => cryp::InterruptHandler<peripherals::CRYP>; | ||
| 16 | }); | ||
| 17 | |||
| 14 | #[embassy_executor::main] | 18 | #[embassy_executor::main] |
| 15 | async fn main(_spawner: Spawner) -> ! { | 19 | async fn main(_spawner: Spawner) -> ! { |
| 16 | let config = Config::default(); | 20 | let config = Config::default(); |
| @@ -19,7 +23,7 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 19 | let payload: &[u8] = b"hello world"; | 23 | let payload: &[u8] = b"hello world"; |
| 20 | let aad: &[u8] = b"additional data"; | 24 | let aad: &[u8] = b"additional data"; |
| 21 | 25 | ||
| 22 | let hw_cryp = Cryp::new(p.CRYP); | 26 | let mut hw_cryp = Cryp::new(p.CRYP, p.DMA2_CH6, p.DMA2_CH5, Irqs); |
| 23 | let key: [u8; 16] = [0; 16]; | 27 | let key: [u8; 16] = [0; 16]; |
| 24 | let mut ciphertext: [u8; 11] = [0; 11]; | 28 | let mut ciphertext: [u8; 11] = [0; 11]; |
| 25 | let mut plaintext: [u8; 11] = [0; 11]; | 29 | let mut plaintext: [u8; 11] = [0; 11]; |
| @@ -29,16 +33,18 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 29 | 33 | ||
| 30 | // Encrypt in hardware using AES-GCM 128-bit | 34 | // Encrypt in hardware using AES-GCM 128-bit |
| 31 | let aes_gcm = AesGcm::new(&key, &iv); | 35 | let aes_gcm = AesGcm::new(&key, &iv); |
| 32 | let mut gcm_encrypt = hw_cryp.start(&aes_gcm, Direction::Encrypt); | 36 | let mut gcm_encrypt = hw_cryp.start(&aes_gcm, Direction::Encrypt).await; |
| 33 | hw_cryp.aad_blocking(&mut gcm_encrypt, aad, true); | 37 | hw_cryp.aad(&mut gcm_encrypt, aad, true).await; |
| 34 | hw_cryp.payload_blocking(&mut gcm_encrypt, payload, &mut ciphertext, true); | 38 | hw_cryp.payload(&mut gcm_encrypt, payload, &mut ciphertext, true).await; |
| 35 | let encrypt_tag = hw_cryp.finish_blocking(gcm_encrypt); | 39 | let encrypt_tag = hw_cryp.finish(gcm_encrypt).await; |
| 36 | 40 | ||
| 37 | // Decrypt in hardware using AES-GCM 128-bit | 41 | // Decrypt in hardware using AES-GCM 128-bit |
| 38 | let mut gcm_decrypt = hw_cryp.start(&aes_gcm, Direction::Decrypt); | 42 | let mut gcm_decrypt = hw_cryp.start(&aes_gcm, Direction::Decrypt).await; |
| 39 | hw_cryp.aad_blocking(&mut gcm_decrypt, aad, true); | 43 | hw_cryp.aad(&mut gcm_decrypt, aad, true).await; |
| 40 | hw_cryp.payload_blocking(&mut gcm_decrypt, &ciphertext, &mut plaintext, true); | 44 | hw_cryp |
| 41 | let decrypt_tag = hw_cryp.finish_blocking(gcm_decrypt); | 45 | .payload(&mut gcm_decrypt, &ciphertext, &mut plaintext, true) |
| 46 | .await; | ||
| 47 | let decrypt_tag = hw_cryp.finish(gcm_decrypt).await; | ||
| 42 | 48 | ||
| 43 | let hw_end_time = Instant::now(); | 49 | let hw_end_time = Instant::now(); |
| 44 | let hw_execution_time = hw_end_time - hw_start_time; | 50 | let hw_execution_time = hw_end_time - hw_start_time; |
diff --git a/tests/stm32/src/bin/cryp.rs b/tests/stm32/src/bin/cryp.rs index f105abf26..60778bdaa 100644 --- a/tests/stm32/src/bin/cryp.rs +++ b/tests/stm32/src/bin/cryp.rs | |||
| @@ -10,9 +10,14 @@ use aes_gcm::aead::{AeadInPlace, KeyInit}; | |||
| 10 | use aes_gcm::Aes128Gcm; | 10 | use aes_gcm::Aes128Gcm; |
| 11 | use common::*; | 11 | use common::*; |
| 12 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 13 | use embassy_stm32::cryp::*; | 13 | use embassy_stm32::cryp::{self, *}; |
| 14 | use embassy_stm32::{bind_interrupts, peripherals}; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 16 | ||
| 17 | bind_interrupts!(struct Irqs { | ||
| 18 | CRYP => cryp::InterruptHandler<peripherals::CRYP>; | ||
| 19 | }); | ||
| 20 | |||
| 16 | #[embassy_executor::main] | 21 | #[embassy_executor::main] |
| 17 | async fn main(_spawner: Spawner) { | 22 | async fn main(_spawner: Spawner) { |
| 18 | let p: embassy_stm32::Peripherals = embassy_stm32::init(config()); | 23 | let p: embassy_stm32::Peripherals = embassy_stm32::init(config()); |
| @@ -22,27 +27,32 @@ async fn main(_spawner: Spawner) { | |||
| 22 | const AAD1: &[u8] = b"additional data 1 stdargadrhaethaethjatjatjaetjartjstrjsfkk;'jopofyuisrteytweTASTUIKFUKIXTRDTEREharhaeryhaterjartjarthaethjrtjarthaetrhartjatejatrjsrtjartjyt1"; | 27 | const AAD1: &[u8] = b"additional data 1 stdargadrhaethaethjatjatjaetjartjstrjsfkk;'jopofyuisrteytweTASTUIKFUKIXTRDTEREharhaeryhaterjartjarthaethjrtjarthaetrhartjatejatrjsrtjartjyt1"; |
| 23 | const AAD2: &[u8] = b"additional data 2 stdhthsthsthsrthsrthsrtjdykjdukdyuldadfhsdghsdghsdghsadghjk'hioethjrtjarthaetrhartjatecfgjhzdfhgzdfhzdfghzdfhzdfhzfhjatrjsrtjartjytjfytjfyg"; | 28 | const AAD2: &[u8] = b"additional data 2 stdhthsthsthsrthsrthsrtjdykjdukdyuldadfhsdghsdghsdghsadghjk'hioethjrtjarthaetrhartjatecfgjhzdfhgzdfhzdfghzdfhzdfhzfhjatrjsrtjartjytjfytjfyg"; |
| 24 | 29 | ||
| 25 | let hw_cryp = Cryp::new(p.CRYP); | 30 | let in_dma = peri!(p, CRYP_IN_DMA); |
| 31 | let out_dma = peri!(p, CRYP_OUT_DMA); | ||
| 32 | |||
| 33 | let mut hw_cryp = Cryp::new(p.CRYP, in_dma, out_dma, Irqs); | ||
| 26 | let key: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; | 34 | let key: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; |
| 27 | let mut ciphertext: [u8; PAYLOAD1.len() + PAYLOAD2.len()] = [0; PAYLOAD1.len() + PAYLOAD2.len()]; | 35 | let mut ciphertext: [u8; PAYLOAD1.len() + PAYLOAD2.len()] = [0; PAYLOAD1.len() + PAYLOAD2.len()]; |
| 28 | let mut plaintext: [u8; PAYLOAD1.len() + PAYLOAD2.len()] = [0; PAYLOAD1.len() + PAYLOAD2.len()]; | 36 | let mut plaintext: [u8; PAYLOAD1.len() + PAYLOAD2.len()] = [0; PAYLOAD1.len() + PAYLOAD2.len()]; |
| 29 | let iv: [u8; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; | 37 | let iv: [u8; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; |
| 30 | 38 | ||
| 31 | // Encrypt in hardware using AES-GCM 128-bit | 39 | // Encrypt in hardware using AES-GCM 128-bit in blocking mode. |
| 32 | let aes_gcm = AesGcm::new(&key, &iv); | 40 | let aes_gcm = AesGcm::new(&key, &iv); |
| 33 | let mut gcm_encrypt = hw_cryp.start(&aes_gcm, Direction::Encrypt); | 41 | let mut gcm_encrypt = hw_cryp.start_blocking(&aes_gcm, Direction::Encrypt); |
| 34 | hw_cryp.aad_blocking(&mut gcm_encrypt, AAD1, false); | 42 | hw_cryp.aad_blocking(&mut gcm_encrypt, AAD1, false); |
| 35 | hw_cryp.aad_blocking(&mut gcm_encrypt, AAD2, true); | 43 | hw_cryp.aad_blocking(&mut gcm_encrypt, AAD2, true); |
| 36 | hw_cryp.payload_blocking(&mut gcm_encrypt, PAYLOAD1, &mut ciphertext[..PAYLOAD1.len()], false); | 44 | hw_cryp.payload_blocking(&mut gcm_encrypt, PAYLOAD1, &mut ciphertext[..PAYLOAD1.len()], false); |
| 37 | hw_cryp.payload_blocking(&mut gcm_encrypt, PAYLOAD2, &mut ciphertext[PAYLOAD1.len()..], true); | 45 | hw_cryp.payload_blocking(&mut gcm_encrypt, PAYLOAD2, &mut ciphertext[PAYLOAD1.len()..], true); |
| 38 | let encrypt_tag = hw_cryp.finish_blocking(gcm_encrypt); | 46 | let encrypt_tag = hw_cryp.finish_blocking(gcm_encrypt); |
| 39 | 47 | ||
| 40 | // Decrypt in hardware using AES-GCM 128-bit | 48 | // Decrypt in hardware using AES-GCM 128-bit in async (DMA) mode. |
| 41 | let mut gcm_decrypt = hw_cryp.start(&aes_gcm, Direction::Decrypt); | 49 | let mut gcm_decrypt = hw_cryp.start(&aes_gcm, Direction::Decrypt).await; |
| 42 | hw_cryp.aad_blocking(&mut gcm_decrypt, AAD1, false); | 50 | hw_cryp.aad(&mut gcm_decrypt, AAD1, false).await; |
| 43 | hw_cryp.aad_blocking(&mut gcm_decrypt, AAD2, true); | 51 | hw_cryp.aad(&mut gcm_decrypt, AAD2, true).await; |
| 44 | hw_cryp.payload_blocking(&mut gcm_decrypt, &ciphertext, &mut plaintext, true); | 52 | hw_cryp |
| 45 | let decrypt_tag = hw_cryp.finish_blocking(gcm_decrypt); | 53 | .payload(&mut gcm_decrypt, &ciphertext, &mut plaintext, true) |
| 54 | .await; | ||
| 55 | let decrypt_tag = hw_cryp.finish(gcm_decrypt).await; | ||
| 46 | 56 | ||
| 47 | info!("AES-GCM Ciphertext: {:?}", ciphertext); | 57 | info!("AES-GCM Ciphertext: {:?}", ciphertext); |
| 48 | info!("AES-GCM Plaintext: {:?}", plaintext); | 58 | info!("AES-GCM Plaintext: {:?}", plaintext); |
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index 3297ea7e2..c379863a8 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs | |||
| @@ -140,6 +140,7 @@ define_peris!( | |||
| 140 | ); | 140 | ); |
| 141 | #[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi"))] | 141 | #[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi"))] |
| 142 | define_peris!( | 142 | define_peris!( |
| 143 | CRYP_IN_DMA = DMA1_CH0, CRYP_OUT_DMA = DMA1_CH1, | ||
| 143 | UART = USART1, UART_TX = PB6, UART_RX = PB7, UART_TX_DMA = DMA1_CH0, UART_RX_DMA = DMA1_CH1, | 144 | UART = USART1, UART_TX = PB6, UART_RX = PB7, UART_TX_DMA = DMA1_CH0, UART_RX_DMA = DMA1_CH1, |
| 144 | SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PB5, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH0, SPI_RX_DMA = DMA1_CH1, | 145 | SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PB5, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH0, SPI_RX_DMA = DMA1_CH1, |
| 145 | ADC = ADC1, DAC = DAC1, DAC_PIN = PA4, | 146 | ADC = ADC1, DAC = DAC1, DAC_PIN = PA4, |
