diff options
| author | Caleb Garrett <[email protected]> | 2024-02-14 20:24:52 -0500 |
|---|---|---|
| committer | Caleb Garrett <[email protected]> | 2024-02-25 20:59:07 -0500 |
| commit | a0a8a4ec864763948d4a965ccf8ec11ca91cb15f (patch) | |
| tree | 57fde5d557ddb6dd9446b1b33e3b5d70bf5d0066 | |
| parent | 79e5e8b052b56f8c6fc07d8407fcfc3aaf39bab3 (diff) | |
Support CBC, ECB, CTR modes.
| -rw-r--r-- | embassy-stm32/src/cryp/mod.rs | 350 |
1 files changed, 282 insertions, 68 deletions
diff --git a/embassy-stm32/src/cryp/mod.rs b/embassy-stm32/src/cryp/mod.rs index dedc6ddc5..f266313c1 100644 --- a/embassy-stm32/src/cryp/mod.rs +++ b/embassy-stm32/src/cryp/mod.rs | |||
| @@ -1,23 +1,34 @@ | |||
| 1 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 1 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 2 | use pac::cryp::Init; | ||
| 3 | 2 | ||
| 4 | use crate::pac; | 3 | use crate::pac; |
| 5 | use crate::peripherals::CRYP; | 4 | use crate::peripherals::CRYP; |
| 6 | use crate::rcc::sealed::RccPeripheral; | 5 | use crate::rcc::sealed::RccPeripheral; |
| 7 | use crate::{interrupt, peripherals, Peripheral}; | 6 | use crate::{interrupt, Peripheral}; |
| 7 | |||
| 8 | const DES_BLOCK_SIZE: usize = 8; // 64 bits | ||
| 9 | const AES_BLOCK_SIZE: usize = 16; // 128 bits | ||
| 8 | 10 | ||
| 9 | pub struct Context<'c> { | 11 | pub struct Context<'c> { |
| 12 | algo: Algorithm, | ||
| 13 | mode: Mode, | ||
| 14 | dir: Direction, | ||
| 15 | last_block_processed: bool, | ||
| 16 | aad_complete: bool, | ||
| 17 | cr: u32, | ||
| 18 | iv: [u32; 4], | ||
| 10 | key: &'c [u8], | 19 | key: &'c [u8], |
| 20 | csgcmccm: [u32; 8], | ||
| 21 | csgcm: [u32; 8], | ||
| 11 | } | 22 | } |
| 12 | 23 | ||
| 13 | #[derive(PartialEq)] | 24 | #[derive(PartialEq, Clone, Copy)] |
| 14 | pub enum Algorithm { | 25 | pub enum Algorithm { |
| 15 | AES, | 26 | AES, |
| 16 | DES, | 27 | DES, |
| 17 | TDES, | 28 | TDES, |
| 18 | } | 29 | } |
| 19 | 30 | ||
| 20 | #[derive(PartialEq)] | 31 | #[derive(PartialEq, Clone, Copy)] |
| 21 | pub enum Mode { | 32 | pub enum Mode { |
| 22 | ECB, | 33 | ECB, |
| 23 | CBC, | 34 | CBC, |
| @@ -27,53 +38,55 @@ pub enum Mode { | |||
| 27 | CCM, | 38 | CCM, |
| 28 | } | 39 | } |
| 29 | 40 | ||
| 30 | #[derive(PartialEq)] | 41 | #[derive(PartialEq, Clone, Copy)] |
| 31 | pub enum Direction { | 42 | pub enum Direction { |
| 32 | Encrypt, | 43 | Encrypt, |
| 33 | Decrypt, | 44 | Decrypt, |
| 34 | } | 45 | } |
| 35 | 46 | ||
| 36 | /// Crypto Accelerator Driver | 47 | /// Crypto Accelerator Driver |
| 37 | pub struct Cryp<'d, T: Instance, In, Out> { | 48 | pub struct Cryp<'d, T: Instance> { |
| 38 | _peripheral: PeripheralRef<'d, T>, | 49 | _peripheral: PeripheralRef<'d, T>, |
| 39 | indma: PeripheralRef<'d, In>, | ||
| 40 | outdma: PeripheralRef<'d, Out>, | ||
| 41 | } | 50 | } |
| 42 | 51 | ||
| 43 | type InitVector<'v> = Option<&'v [u8]>; | 52 | type InitVector<'v> = Option<&'v [u8]>; |
| 44 | 53 | ||
| 45 | impl<'d, T: Instance, In, Out> Cryp<'d, T, In, Out> { | 54 | impl<'d, T: Instance> Cryp<'d, T> { |
| 46 | /// Create a new CRYP driver. | 55 | /// Create a new CRYP driver. |
| 47 | pub fn new( | 56 | pub fn new(peri: impl Peripheral<P = T> + 'd) -> Self { |
| 48 | peri: impl Peripheral<P = T> + 'd, | ||
| 49 | indma: impl Peripheral<P = In> + 'd, | ||
| 50 | outdma: impl Peripheral<P = Out> + 'd, | ||
| 51 | ) -> Self { | ||
| 52 | CRYP::enable_and_reset(); | 57 | CRYP::enable_and_reset(); |
| 53 | into_ref!(peri, indma, outdma); | 58 | into_ref!(peri); |
| 54 | let instance = Self { | 59 | let instance = Self { _peripheral: peri }; |
| 55 | _peripheral: peri, | ||
| 56 | indma: indma, | ||
| 57 | outdma: outdma, | ||
| 58 | }; | ||
| 59 | instance | 60 | instance |
| 60 | } | 61 | } |
| 61 | 62 | ||
| 62 | /// Start a new cipher operation. | 63 | /// Start a new cipher operation. |
| 63 | /// Key size must be 128, 192, or 256 bits. | 64 | /// Key size must be 128, 192, or 256 bits. |
| 64 | pub fn start(key: &[u8], iv: InitVector, algo: Algorithm, mode: Mode, dir: Direction) -> Context { | 65 | pub fn start<'c>(&self, key: &'c [u8], iv: InitVector, algo: Algorithm, mode: Mode, dir: Direction) -> Context<'c> { |
| 65 | T::regs().cr().modify(|w| w.set_crypen(false)); | 66 | let mut ctx = Context { |
| 67 | algo, | ||
| 68 | mode, | ||
| 69 | dir, | ||
| 70 | last_block_processed: false, | ||
| 71 | cr: 0, | ||
| 72 | iv: [0; 4], | ||
| 73 | key, | ||
| 74 | csgcmccm: [0; 8], | ||
| 75 | csgcm: [0; 8], | ||
| 76 | aad_complete: false, | ||
| 77 | }; | ||
| 66 | 78 | ||
| 67 | let keylen = key.len() * 8; | 79 | T::regs().cr().modify(|w| w.set_crypen(false)); |
| 68 | let ivlen; | ||
| 69 | if let Some(iv) = iv { | ||
| 70 | ivlen = iv.len() * 8; | ||
| 71 | } else { | ||
| 72 | ivlen = 0; | ||
| 73 | } | ||
| 74 | 80 | ||
| 75 | // Checks for correctness | 81 | // Checks for correctness |
| 76 | if algo == Algorithm::AES { | 82 | if algo == Algorithm::AES { |
| 83 | let keylen = key.len() * 8; | ||
| 84 | let ivlen; | ||
| 85 | if let Some(iv) = iv { | ||
| 86 | ivlen = iv.len() * 8; | ||
| 87 | } else { | ||
| 88 | ivlen = 0; | ||
| 89 | } | ||
| 77 | match keylen { | 90 | match keylen { |
| 78 | 128 => T::regs().cr().write(|w| w.set_keysize(0)), | 91 | 128 => T::regs().cr().write(|w| w.set_keysize(0)), |
| 79 | 192 => T::regs().cr().write(|w| w.set_keysize(1)), | 92 | 192 => T::regs().cr().write(|w| w.set_keysize(1)), |
| @@ -96,49 +109,14 @@ impl<'d, T: Instance, In, Out> Cryp<'d, T, In, Out> { | |||
| 96 | } | 109 | } |
| 97 | } | 110 | } |
| 98 | 111 | ||
| 99 | // Load the key into the registers. | 112 | self.load_key(key); |
| 100 | let mut keyidx = 0; | ||
| 101 | let mut keyword: [u8; 4] = [0; 4]; | ||
| 102 | if keylen > 192 { | ||
| 103 | keyword.copy_from_slice(&key[keyidx..keyidx + 4]); | ||
| 104 | keyidx += 4; | ||
| 105 | T::regs().key(0).klr().write_value(u32::from_be_bytes(keyword)); | ||
| 106 | keyword.copy_from_slice(&key[keyidx..keyidx + 4]); | ||
| 107 | keyidx += 4; | ||
| 108 | T::regs().key(0).krr().write_value(u32::from_be_bytes(keyword)); | ||
| 109 | } | ||
| 110 | if keylen > 128 { | ||
| 111 | keyword.copy_from_slice(&key[keyidx..keyidx + 4]); | ||
| 112 | keyidx += 4; | ||
| 113 | T::regs().key(1).klr().write_value(u32::from_be_bytes(keyword)); | ||
| 114 | keyword.copy_from_slice(&key[keyidx..keyidx + 4]); | ||
| 115 | keyidx += 4; | ||
| 116 | T::regs().key(1).krr().write_value(u32::from_be_bytes(keyword)); | ||
| 117 | } | ||
| 118 | if keylen > 64 { | ||
| 119 | keyword.copy_from_slice(&key[keyidx..keyidx + 4]); | ||
| 120 | keyidx += 4; | ||
| 121 | T::regs().key(2).klr().write_value(u32::from_be_bytes(keyword)); | ||
| 122 | keyword.copy_from_slice(&key[keyidx..keyidx + 4]); | ||
| 123 | keyidx += 4; | ||
| 124 | T::regs().key(2).krr().write_value(u32::from_be_bytes(keyword)); | ||
| 125 | } | ||
| 126 | keyword.copy_from_slice(&key[keyidx..keyidx + 4]); | ||
| 127 | keyidx += 4; | ||
| 128 | T::regs().key(3).klr().write_value(u32::from_be_bytes(keyword)); | ||
| 129 | keyword.copy_from_slice(&key[keyidx..keyidx + 4]); | ||
| 130 | T::regs().key(3).krr().write_value(u32::from_be_bytes(keyword)); | ||
| 131 | 113 | ||
| 132 | // Set data type to 8-bit. This will match software implementations. | 114 | // Set data type to 8-bit. This will match software implementations. |
| 133 | T::regs().cr().modify(|w| w.set_datatype(2)); | 115 | T::regs().cr().modify(|w| w.set_datatype(2)); |
| 134 | 116 | ||
| 135 | if algo == Algorithm::AES { | 117 | self.prepare_key(&ctx); |
| 136 | if (mode == Mode::ECB) || (mode == Mode::CBC) { | ||
| 137 | T::regs().cr().modify(|w| w.set_algomode0(7)); | ||
| 138 | T::regs().cr().modify(|w| w.set_crypen(true)); | ||
| 139 | while T::regs().sr().read().busy() {} | ||
| 140 | } | ||
| 141 | 118 | ||
| 119 | if algo == Algorithm::AES { | ||
| 142 | match mode { | 120 | match mode { |
| 143 | Mode::ECB => T::regs().cr().modify(|w| w.set_algomode0(4)), | 121 | Mode::ECB => T::regs().cr().modify(|w| w.set_algomode0(4)), |
| 144 | Mode::CBC => T::regs().cr().modify(|w| w.set_algomode0(5)), | 122 | Mode::CBC => T::regs().cr().modify(|w| w.set_algomode0(5)), |
| @@ -192,10 +170,246 @@ impl<'d, T: Instance, In, Out> Cryp<'d, T, In, Out> { | |||
| 192 | // Flush in/out FIFOs | 170 | // Flush in/out FIFOs |
| 193 | T::regs().cr().modify(|w| w.fflush()); | 171 | T::regs().cr().modify(|w| w.fflush()); |
| 194 | 172 | ||
| 195 | let ctx = Context { key: key }; | 173 | if mode == Mode::GCM { |
| 174 | // GCM init phase | ||
| 175 | T::regs().cr().modify(|w| w.set_gcm_ccmph(0)); | ||
| 176 | T::regs().cr().modify(|w| w.set_crypen(true)); | ||
| 177 | while T::regs().cr().read().crypen() {} | ||
| 178 | } | ||
| 179 | |||
| 180 | self.store_context(&mut ctx); | ||
| 196 | 181 | ||
| 197 | ctx | 182 | ctx |
| 198 | } | 183 | } |
| 184 | |||
| 185 | // pub fn aad_blocking(&self, ctx: &mut Context, aad: &[u8]) { | ||
| 186 | // if ctx.aad_complete { | ||
| 187 | // panic!("Cannot update AAD after calling 'update'!") | ||
| 188 | // } | ||
| 189 | // if (ctx.mode != Mode::GCM) && (ctx.mode != Mode::GMAC) && (ctx.mode != Mode::CCM) { | ||
| 190 | // panic!("Associated data only valid for GCM, GMAC, and CCM modes.") | ||
| 191 | // } | ||
| 192 | |||
| 193 | // let mut header_size = 0; | ||
| 194 | // let mut header: [u8;] | ||
| 195 | |||
| 196 | // if aad.len() < 65280 { | ||
| 197 | |||
| 198 | // } | ||
| 199 | |||
| 200 | // // GCM header phase | ||
| 201 | // T::regs().cr().modify(|w| w.set_gcm_ccmph(1)); | ||
| 202 | // T::regs().cr().modify(|w| w.set_crypen(true)); | ||
| 203 | // } | ||
| 204 | |||
| 205 | pub fn update_blocking(&self, ctx: &mut Context, input: &[u8], output: &mut [u8], last_block: bool) { | ||
| 206 | self.load_context(ctx); | ||
| 207 | |||
| 208 | ctx.aad_complete = true; | ||
| 209 | if last_block { | ||
| 210 | ctx.last_block_processed = true; | ||
| 211 | } | ||
| 212 | |||
| 213 | let block_size; | ||
| 214 | if ctx.algo == Algorithm::DES { | ||
| 215 | block_size = 8; | ||
| 216 | } else { | ||
| 217 | block_size = 16; | ||
| 218 | } | ||
| 219 | let last_block_remainder = input.len() % block_size; | ||
| 220 | |||
| 221 | // Perform checks for correctness. | ||
| 222 | |||
| 223 | if ctx.mode == Mode::GMAC { | ||
| 224 | panic!("GMAC works on header data only. Do not call this function for GMAC."); | ||
| 225 | } | ||
| 226 | if ctx.last_block_processed { | ||
| 227 | panic!("The last block has already been processed!"); | ||
| 228 | } | ||
| 229 | if input.len() != output.len() { | ||
| 230 | panic!("Output buffer length must match input length."); | ||
| 231 | } | ||
| 232 | if !last_block { | ||
| 233 | if last_block_remainder != 0 { | ||
| 234 | panic!("Input length must be a multiple of {block_size} bytes."); | ||
| 235 | } | ||
| 236 | } | ||
| 237 | if (ctx.mode == Mode::ECB) || (ctx.mode == Mode::CBC) { | ||
| 238 | if last_block_remainder != 0 { | ||
| 239 | panic!("Input must be a multiple of {block_size} bytes in ECB and CBC modes. Consider padding or ciphertext stealing."); | ||
| 240 | } | ||
| 241 | } | ||
| 242 | |||
| 243 | // Load data into core, block by block. | ||
| 244 | let num_full_blocks = input.len() / block_size; | ||
| 245 | for block in 0..num_full_blocks { | ||
| 246 | let mut index = block * block_size; | ||
| 247 | let end_index = index + block_size; | ||
| 248 | // Write block in | ||
| 249 | while index < end_index { | ||
| 250 | let mut in_word: [u8; 4] = [0; 4]; | ||
| 251 | in_word.copy_from_slice(&input[index..index + 4]); | ||
| 252 | T::regs().din().write_value(u32::from_ne_bytes(in_word)); | ||
| 253 | index += 4; | ||
| 254 | } | ||
| 255 | let mut index = block * block_size; | ||
| 256 | let end_index = index + block_size; | ||
| 257 | // Block until there is output to read. | ||
| 258 | while !T::regs().sr().read().ofne() {} | ||
| 259 | // Read block out | ||
| 260 | while index < end_index { | ||
| 261 | let out_word: u32 = T::regs().dout().read(); | ||
| 262 | output[index..index + 4].copy_from_slice(u32::to_ne_bytes(out_word).as_slice()); | ||
| 263 | index += 4; | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | // Handle the final block, which is incomplete. | ||
| 268 | if last_block_remainder > 0 { | ||
| 269 | if ctx.mode == Mode::GCM && ctx.dir == Direction::Encrypt { | ||
| 270 | //Handle special GCM partial block process. | ||
| 271 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 272 | T::regs().cr().write(|w| w.set_algomode0(6)); | ||
| 273 | let iv1r = T::regs().csgcmccmr(7).read() - 1; | ||
| 274 | T::regs().init(1).ivrr().write_value(iv1r); | ||
| 275 | T::regs().cr().modify(|w| w.set_crypen(true)); | ||
| 276 | } | ||
| 277 | |||
| 278 | let mut intermediate_data: [u8; 16] = [0; 16]; | ||
| 279 | let mut last_block: [u8; 16] = [0; 16]; | ||
| 280 | last_block.copy_from_slice(&input[input.len() - last_block_remainder..input.len()]); | ||
| 281 | let mut index = 0; | ||
| 282 | let end_index = block_size; | ||
| 283 | // Write block in | ||
| 284 | while index < end_index { | ||
| 285 | let mut in_word: [u8; 4] = [0; 4]; | ||
| 286 | in_word.copy_from_slice(&last_block[index..index + 4]); | ||
| 287 | T::regs().din().write_value(u32::from_ne_bytes(in_word)); | ||
| 288 | index += 4; | ||
| 289 | } | ||
| 290 | let mut index = 0; | ||
| 291 | let end_index = block_size; | ||
| 292 | // Block until there is output to read. | ||
| 293 | while !T::regs().sr().read().ofne() {} | ||
| 294 | // Read block out | ||
| 295 | while index < end_index { | ||
| 296 | let out_word: u32 = T::regs().dout().read(); | ||
| 297 | intermediate_data[index..index + 4].copy_from_slice(u32::to_ne_bytes(out_word).as_slice()); | ||
| 298 | index += 4; | ||
| 299 | } | ||
| 300 | |||
| 301 | // Handle the last block depending on mode. | ||
| 302 | output[output.len() - last_block_remainder..output.len()] | ||
| 303 | .copy_from_slice(&intermediate_data[0..last_block_remainder]); | ||
| 304 | |||
| 305 | if ctx.mode == Mode::GCM && ctx.dir == Direction::Encrypt { | ||
| 306 | //Handle special GCM partial block process. | ||
| 307 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 308 | T::regs().cr().write(|w| w.set_algomode0(8)); | ||
| 309 | T::regs().init(1).ivrr().write_value(2); | ||
| 310 | T::regs().cr().modify(|w| w.set_crypen(true)); | ||
| 311 | T::regs().cr().modify(|w| w.set_gcm_ccmph(3)); | ||
| 312 | let mut index = 0; | ||
| 313 | let end_index = block_size; | ||
| 314 | while index < end_index { | ||
| 315 | let mut in_word: [u8; 4] = [0; 4]; | ||
| 316 | in_word.copy_from_slice(&intermediate_data[index..index + 4]); | ||
| 317 | T::regs().din().write_value(u32::from_ne_bytes(in_word)); | ||
| 318 | index += 4; | ||
| 319 | } | ||
| 320 | for _ in 0..4 { | ||
| 321 | T::regs().dout().read(); | ||
| 322 | } | ||
| 323 | } | ||
| 324 | } | ||
| 325 | } | ||
| 326 | |||
| 327 | fn prepare_key(&self, ctx: &Context) { | ||
| 328 | if ctx.algo == Algorithm::AES { | ||
| 329 | if (ctx.mode == Mode::ECB) || (ctx.mode == Mode::CBC) { | ||
| 330 | T::regs().cr().modify(|w| w.set_algomode0(7)); | ||
| 331 | T::regs().cr().modify(|w| w.set_crypen(true)); | ||
| 332 | while T::regs().sr().read().busy() {} | ||
| 333 | } | ||
| 334 | } | ||
| 335 | } | ||
| 336 | |||
| 337 | fn load_key(&self, key: &[u8]) { | ||
| 338 | // Load the key into the registers. | ||
| 339 | let mut keyidx = 0; | ||
| 340 | let mut keyword: [u8; 4] = [0; 4]; | ||
| 341 | let keylen = key.len() * 8; | ||
| 342 | if keylen > 192 { | ||
| 343 | keyword.copy_from_slice(&key[keyidx..keyidx + 4]); | ||
| 344 | keyidx += 4; | ||
| 345 | T::regs().key(0).klr().write_value(u32::from_be_bytes(keyword)); | ||
| 346 | keyword.copy_from_slice(&key[keyidx..keyidx + 4]); | ||
| 347 | keyidx += 4; | ||
| 348 | T::regs().key(0).krr().write_value(u32::from_be_bytes(keyword)); | ||
| 349 | } | ||
| 350 | if keylen > 128 { | ||
| 351 | keyword.copy_from_slice(&key[keyidx..keyidx + 4]); | ||
| 352 | keyidx += 4; | ||
| 353 | T::regs().key(1).klr().write_value(u32::from_be_bytes(keyword)); | ||
| 354 | keyword.copy_from_slice(&key[keyidx..keyidx + 4]); | ||
| 355 | keyidx += 4; | ||
| 356 | T::regs().key(1).krr().write_value(u32::from_be_bytes(keyword)); | ||
| 357 | } | ||
| 358 | if keylen > 64 { | ||
| 359 | keyword.copy_from_slice(&key[keyidx..keyidx + 4]); | ||
| 360 | keyidx += 4; | ||
| 361 | T::regs().key(2).klr().write_value(u32::from_be_bytes(keyword)); | ||
| 362 | keyword.copy_from_slice(&key[keyidx..keyidx + 4]); | ||
| 363 | keyidx += 4; | ||
| 364 | T::regs().key(2).krr().write_value(u32::from_be_bytes(keyword)); | ||
| 365 | } | ||
| 366 | keyword.copy_from_slice(&key[keyidx..keyidx + 4]); | ||
| 367 | keyidx += 4; | ||
| 368 | T::regs().key(3).klr().write_value(u32::from_be_bytes(keyword)); | ||
| 369 | keyword.copy_from_slice(&key[keyidx..keyidx + 4]); | ||
| 370 | T::regs().key(3).krr().write_value(u32::from_be_bytes(keyword)); | ||
| 371 | } | ||
| 372 | |||
| 373 | fn store_context(&self, ctx: &mut Context) { | ||
| 374 | // Wait for data block processing to finish. | ||
| 375 | while !T::regs().sr().read().ifem() {} | ||
| 376 | while T::regs().sr().read().ofne() {} | ||
| 377 | while T::regs().sr().read().busy() {} | ||
| 378 | |||
| 379 | // Disable crypto processor. | ||
| 380 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 381 | |||
| 382 | // Save the peripheral state. | ||
| 383 | ctx.cr = T::regs().cr().read().0; | ||
| 384 | ctx.iv[0] = T::regs().init(0).ivlr().read(); | ||
| 385 | ctx.iv[1] = T::regs().init(0).ivrr().read(); | ||
| 386 | ctx.iv[2] = T::regs().init(1).ivlr().read(); | ||
| 387 | ctx.iv[3] = T::regs().init(1).ivrr().read(); | ||
| 388 | for i in 0..8 { | ||
| 389 | ctx.csgcmccm[i] = T::regs().csgcmccmr(i).read(); | ||
| 390 | ctx.csgcm[i] = T::regs().csgcmr(i).read(); | ||
| 391 | } | ||
| 392 | } | ||
| 393 | |||
| 394 | fn load_context(&self, ctx: &Context) { | ||
| 395 | // Reload state registers. | ||
| 396 | T::regs().cr().write(|w| w.0 = ctx.cr); | ||
| 397 | T::regs().init(0).ivlr().write_value(ctx.iv[0]); | ||
| 398 | T::regs().init(0).ivrr().write_value(ctx.iv[1]); | ||
| 399 | T::regs().init(1).ivlr().write_value(ctx.iv[2]); | ||
| 400 | T::regs().init(1).ivrr().write_value(ctx.iv[3]); | ||
| 401 | for i in 0..8 { | ||
| 402 | T::regs().csgcmccmr(i).write_value(ctx.csgcmccm[i]); | ||
| 403 | T::regs().csgcmr(i).write_value(ctx.csgcm[i]); | ||
| 404 | } | ||
| 405 | self.load_key(ctx.key); | ||
| 406 | |||
| 407 | // Prepare key if applicable. | ||
| 408 | self.prepare_key(ctx); | ||
| 409 | |||
| 410 | // Enable crypto processor. | ||
| 411 | T::regs().cr().modify(|w| w.set_crypen(true)); | ||
| 412 | } | ||
| 199 | } | 413 | } |
| 200 | 414 | ||
| 201 | pub(crate) mod sealed { | 415 | pub(crate) mod sealed { |
