diff --git a/hal/src/aes.rs b/hal/src/aes.rs index c1c019f69f..241ba20e96 100644 --- a/hal/src/aes.rs +++ b/hal/src/aes.rs @@ -777,6 +777,92 @@ impl Aes { Ok(()) } + /// Encrypt using the Cipher block chaining (CBC) algorithm. + /// + /// # Panics + /// + /// * Key is not 128-bits long `[u32; 4]` or 256-bits long `[u32; 8]`. + /// + /// # Example + /// + /// ```no_run + /// use stm32wlxx_hal::{aes::Aes, pac}; + /// + /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap(); + /// let mut aes: Aes = Aes::new(dp.AES, &mut dp.RCC); + /// + /// const KEY: [u32; 4] = [0; 4]; + /// const IV: [u32; 4] = [0; 4]; //currently not used + /// + /// let plaintext: [u32; 4] = [0xf34481ec, 0x3cc627ba, 0xcd5dc3fb, 0x08f273e6]; + /// let mut ciphertext: [u32; 4] = [0; 4]; + /// aes.encrypt_cbc(&KEY, &IV, &plaintext, &mut ciphertext)?; + /// # Ok::<(), stm32wlxx_hal::aes::Error>(()) + /// ``` + pub fn encrypt_cbc( + &mut self, + key: &[u32], + _iv: &[u32; 4], + plaintext: &[u32], + ciphertext: &mut [u32], + ) -> Result<(), Error> { + const ALGO: Algorithm = Algorithm::Cbc; + const CHMOD2: bool = ALGO.chmod2(); + const CHMOD10: u8 = ALGO.chmod10(); + const MODE: u8 = Mode::Encryption.bits(); + + let keysize: KeySize = self.set_key(key); + + self.aes.cr.write(|w| { + w.en().enabled(); + w.datatype().variant(self.swap_mode); + w.mode().bits(MODE); + w.chmod2().bit(CHMOD2); + w.chmod().bits(CHMOD10); + w.ccfc().clear(); + w.errc().clear(); + w.ccfie().disabled(); + w.errie().disabled(); + w.dmainen().disabled(); + w.dmaouten().disabled(); + w.gcmph().bits(0); // do not care for CBC + w.keysize().variant(keysize); + w.npblb().bits(0) // no padding + }); + + if plaintext.len() != ciphertext.len() { + panic!("Plaintext and Ciphertext fields need to have the same length!") + } + + //Would be nice to have automatic padding here + if plaintext.len() % 4 != 0 { + panic!("Plaintext has to be a multiple of 128 bits!") + } + + let mut i = 0; + while i < plaintext.len() { + let mut part: [u32; 4] = [0; 4]; + part[0] = plaintext[i]; + part[1] = plaintext[i + 1]; + part[2] = plaintext[i + 2]; + part[3] = plaintext[i + 3]; + + self.set_din(&part); + self.poll_completion()?; + + let mut cipher_out: [u32; 4] = [0; 4]; + self.dout(&mut cipher_out); + ciphertext[i] = cipher_out[0]; + ciphertext[i + 1] = cipher_out[1]; + ciphertext[i + 2] = cipher_out[2]; + ciphertext[i + 3] = cipher_out[3]; + + i = i + 4; + } + + Ok(()) + } + /// Encrypt using the Galois counter mode (GCM) algorithm in-place. /// /// # Panics