diff options
| author | Caleb Garrett <[email protected]> | 2024-02-20 11:54:39 -0500 |
|---|---|---|
| committer | Caleb Garrett <[email protected]> | 2024-02-25 20:59:07 -0500 |
| commit | 690b2118c6fdad88bf1e595b6a0c0afdb0583d28 (patch) | |
| tree | 12cc9250a42c8f5aaab14d0fc776cd2acc167f6e | |
| parent | fec26e896052cc0eac6bfa6415a4ebad5352d1d9 (diff) | |
CCM mode functional.
| -rw-r--r-- | embassy-stm32/src/cryp/mod.rs | 386 |
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) |
| 2 | use core::cmp::min; | ||
| 2 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 3 | |||
| 4 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 4 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 5 | 5 | ||
| 6 | use crate::pac; | 6 | use 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 }> {} | |||
| 320 | impl<'c> CipherSized for AesGmac<'c, { 256 / 8 }> {} | 355 | impl<'c> CipherSized for AesGmac<'c, { 256 / 8 }> {} |
| 321 | impl<'c, const KEY_SIZE: usize> CipherAuthenticated for AesGmac<'c, KEY_SIZE> {} | 356 | impl<'c, const KEY_SIZE: usize> CipherAuthenticated for AesGmac<'c, KEY_SIZE> {} |
| 322 | 357 | ||
| 323 | // struct AesCcm<'c, const KEY_SIZE: usize> { | 358 | pub 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) { | 366 | impl<'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 | |||
| 438 | impl<'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 | |||
| 528 | impl<'c> CipherSized for AesCcm<'c, { 128 / 8 }> {} | ||
| 529 | impl<'c> CipherSized for AesCcm<'c, { 192 / 8 }> {} | ||
| 530 | impl<'c> CipherSized for AesCcm<'c, { 256 / 8 }> {} | ||
| 531 | impl<'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 |
