From b062f0f7e4344fe4216a20264d7d2ed864ac057b Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Tue, 12 Nov 2024 19:36:31 +0000 Subject: [PATCH 1/3] Support for AES CFB (128-bit) mode --- aws-lc-rs/src/cipher.rs | 228 ++++++++++++++++++++++++++++-- aws-lc-rs/src/cipher/streaming.rs | 148 +++++++++++++++++++ 2 files changed, 363 insertions(+), 13 deletions(-) diff --git a/aws-lc-rs/src/cipher.rs b/aws-lc-rs/src/cipher.rs index 31d85865b27..ce416c067a3 100644 --- a/aws-lc-rs/src/cipher.rs +++ b/aws-lc-rs/src/cipher.rs @@ -11,10 +11,10 @@ //! The modes provided here only provide confidentiality, but **do not** //! provide integrity or authentication verification of ciphertext. //! -//! These algorithms are provided solely for applications requring them -//! in order to maintain backwards compatability in legacy applications. +//! These algorithms are provided solely for applications requiring them +//! in order to maintain backwards compatibility in legacy applications. //! -//! If you are developing new applications requring data encryption see +//! If you are developing new applications requiring data encryption see //! the algorithms provided in [`aead`](crate::aead). //! //! # Examples @@ -134,6 +134,35 @@ //! # Ok(()) //! # } //! ``` +//! +//! ### AES-128 CFB 128-bit mode +//! +//! ```rust +//! # use std::error::Error; +//! # +//! # fn main() -> Result<(), Box> { +//! use aws_lc_rs::cipher::{DecryptingKey, EncryptingKey, UnboundCipherKey, AES_128}; +//! +//! let original_message = "This is a secret message!".as_bytes(); +//! let mut in_out_buffer = Vec::from(original_message); +//! +//! let key_bytes: &[u8] = &[ +//! 0xff, 0x0b, 0xe5, 0x84, 0x64, 0x0b, 0x00, 0xc8, 0x90, 0x7a, 0x4b, 0xbf, 0x82, 0x7c, 0xb6, +//! 0xd1, +//! ]; +//! +//! let key = UnboundCipherKey::new(&AES_128, key_bytes)?; +//! let mut encrypting_key = EncryptingKey::cfb128(key)?; +//! let context = encrypting_key.encrypt(&mut in_out_buffer)?; +//! +//! let key = UnboundCipherKey::new(&AES_128, key_bytes)?; +//! let mut decrypting_key = DecryptingKey::cfb128(key)?; +//! let plaintext = decrypting_key.decrypt(&mut in_out_buffer, context)?; +//! assert_eq!(original_message, plaintext); +//! # +//! # Ok(()) +//! # } +//! ``` //! //! ## Constructing a `DecryptionContext` for decryption. //! @@ -207,11 +236,11 @@ use crate::hkdf::KeyType; use crate::iv::{FixedLength, IV_LEN_128_BIT}; use crate::ptr::ConstPointer; use aws_lc::{ - AES_cbc_encrypt, AES_ctr128_encrypt, EVP_aes_128_cbc, EVP_aes_128_ctr, EVP_aes_256_cbc, - EVP_aes_256_ctr, AES_DECRYPT, AES_ENCRYPT, AES_KEY, EVP_CIPHER, + AES_cbc_encrypt, AES_cfb128_encrypt, AES_ctr128_encrypt, EVP_aes_128_cbc, EVP_aes_128_cfb128, + EVP_aes_128_ctr, EVP_aes_256_cbc, EVP_aes_256_cfb128, EVP_aes_256_ctr, AES_DECRYPT, + AES_ENCRYPT, AES_KEY, EVP_CIPHER, }; use core::fmt::Debug; -use core::mem::MaybeUninit; use key::SymmetricCipherKey; use zeroize::Zeroize; @@ -228,6 +257,10 @@ pub const AES_CBC_IV_LEN: usize = 16; /// The number of bytes for an AES-CTR initialization vector (IV) pub const AES_CTR_IV_LEN: usize = 16; + +/// The number of bytes for an AES-CFB initialization vector (IV) +pub const AES_CFB_IV_LEN: usize = 16; + const AES_BLOCK_LEN: usize = 16; const MAX_CIPHER_BLOCK_LEN: usize = AES_BLOCK_LEN; @@ -241,6 +274,9 @@ pub enum OperatingMode { /// Counter (CTR) mode. CTR, + + /// CFB 128-bit mode. + CFB128, } impl OperatingMode { @@ -249,8 +285,10 @@ impl OperatingMode { ConstPointer::new(match (self, algorithm.id) { (OperatingMode::CBC, AlgorithmId::Aes128) => unsafe { EVP_aes_128_cbc() }, (OperatingMode::CTR, AlgorithmId::Aes128) => unsafe { EVP_aes_128_ctr() }, + (OperatingMode::CFB128, AlgorithmId::Aes128) => unsafe { EVP_aes_128_cfb128() }, (OperatingMode::CBC, AlgorithmId::Aes256) => unsafe { EVP_aes_256_cbc() }, (OperatingMode::CTR, AlgorithmId::Aes256) => unsafe { EVP_aes_256_ctr() }, + (OperatingMode::CFB128, AlgorithmId::Aes256) => unsafe { EVP_aes_256_cfb128() }, }) .unwrap() } @@ -345,8 +383,9 @@ impl Algorithm { mode: OperatingMode, ) -> Result { match self.id { + // TODO: Hopefully support CFB1, and CFB8 AlgorithmId::Aes128 | AlgorithmId::Aes256 => match mode { - OperatingMode::CBC | OperatingMode::CTR => { + OperatingMode::CBC | OperatingMode::CTR | OperatingMode::CFB128 => { Ok(EncryptionContext::Iv128(FixedLength::new()?)) } }, @@ -355,8 +394,9 @@ impl Algorithm { fn is_valid_encryption_context(&self, mode: OperatingMode, input: &EncryptionContext) -> bool { match self.id { + // TODO: Hopefully support CFB1, and CFB8 AlgorithmId::Aes128 | AlgorithmId::Aes256 => match mode { - OperatingMode::CBC | OperatingMode::CTR => { + OperatingMode::CBC | OperatingMode::CTR | OperatingMode::CFB128 => { matches!(input, EncryptionContext::Iv128(_)) } }, @@ -364,9 +404,10 @@ impl Algorithm { } fn is_valid_decryption_context(&self, mode: OperatingMode, input: &DecryptionContext) -> bool { + // TODO: Hopefully support CFB1, and CFB8 match self.id { AlgorithmId::Aes128 | AlgorithmId::Aes256 => match mode { - OperatingMode::CBC | OperatingMode::CTR => { + OperatingMode::CBC | OperatingMode::CTR | OperatingMode::CFB128 => { matches!(input, DecryptionContext::Iv128(_)) } }, @@ -459,6 +500,19 @@ impl EncryptingKey { EncryptingKey::new(key, OperatingMode::CTR) } + /// Constructs an `EncryptingKey` operating in cipher feedback 128-bit mode (CFB128) using the provided key. + /// + // # FIPS + // Use this function with an `UnboundCipherKey` constructed with one of the following algorithms: + // * `AES_128` + // * `AES_256` + // + /// # Errors + /// * [`Unspecified`]: Returned if there is an error constructing the `EncryptingKey`. + pub fn cfb128(key: UnboundCipherKey) -> Result { + EncryptingKey::new(key, OperatingMode::CFB128) + } + #[allow(clippy::unnecessary_wraps)] fn new(key: UnboundCipherKey, mode: OperatingMode) -> Result { let algorithm = key.algorithm(); @@ -547,6 +601,19 @@ impl DecryptingKey { DecryptingKey::new(key, OperatingMode::CTR) } + /// Constructs a cipher decrypting key operating in cipher feedback 128-bit mode (CFB128) using the provided key and context. + /// + // # FIPS + // Use this function with an `UnboundCipherKey` constructed with one of the following algorithms: + // * `AES_128` + // * `AES_256` + // + /// # Errors + /// * [`Unspecified`]: Returned if there is an error during decryption. + pub fn cfb128(key: UnboundCipherKey) -> Result { + DecryptingKey::new(key, OperatingMode::CFB128) + } + #[allow(clippy::unnecessary_wraps)] fn new(key: UnboundCipherKey, mode: OperatingMode) -> Result { let algorithm = key.algorithm(); @@ -604,7 +671,8 @@ fn encrypt( let block_len = algorithm.block_len(); match mode { - OperatingMode::CTR => {} + // TODO: Hopefully support CFB1, and CFB8 + OperatingMode::CTR | OperatingMode::CFB128 => {} _ => { if (in_out.len() % block_len) != 0 { return Err(Unspecified); @@ -619,6 +687,12 @@ fn encrypt( OperatingMode::CTR => match algorithm.id() { AlgorithmId::Aes128 | AlgorithmId::Aes256 => encrypt_aes_ctr_mode(key, context, in_out), }, + // TODO: Hopefully support CFB1, and CFB8 + OperatingMode::CFB128 => match algorithm.id() { + AlgorithmId::Aes128 | AlgorithmId::Aes256 => { + encrypt_aes_cfb_mode(key, mode, context, in_out) + } + }, } } @@ -632,7 +706,8 @@ fn decrypt<'in_out>( let block_len = algorithm.block_len(); match mode { - OperatingMode::CTR => {} + // TODO: Hopefully support CFB1, and CFB8 + OperatingMode::CTR | OperatingMode::CFB128 => {} _ => { if (in_out.len() % block_len) != 0 { return Err(Unspecified); @@ -647,6 +722,12 @@ fn decrypt<'in_out>( OperatingMode::CTR => match algorithm.id() { AlgorithmId::Aes128 | AlgorithmId::Aes256 => decrypt_aes_ctr_mode(key, context, in_out), }, + // TODO: Hopefully support CFB1, and CFB8 + OperatingMode::CFB128 => match algorithm.id() { + AlgorithmId::Aes128 | AlgorithmId::Aes256 => { + decrypt_aes_cfb_mode(key, mode, context, in_out) + } + }, } } @@ -737,8 +818,79 @@ fn decrypt_aes_cbc_mode<'in_out>( Ok(in_out) } +fn encrypt_aes_cfb_mode( + key: &SymmetricCipherKey, + mode: OperatingMode, + context: EncryptionContext, + in_out: &mut [u8], +) -> Result { + #[allow(clippy::match_wildcard_for_single_variants)] + let key = match &key { + SymmetricCipherKey::Aes128 { enc_key, .. } | SymmetricCipherKey::Aes256 { enc_key, .. } => { + enc_key + } + _ => return Err(Unspecified), + }; + + let mut iv = { + let mut iv = [0u8; AES_CFB_IV_LEN]; + iv.copy_from_slice((&context).try_into()?); + iv + }; + + let cfb_encrypt: fn(&AES_KEY, &mut [u8], &mut [u8]) = match mode { + // TODO: Hopefully support CFB1, and CFB8 + OperatingMode::CFB128 => aes_cfb128_encrypt, + _ => { + // this indicates a programming error and shouldn't happen + return Err(Unspecified); + } + }; + + cfb_encrypt(key, &mut iv, in_out); + iv.zeroize(); + + Ok(context.into()) +} + +fn decrypt_aes_cfb_mode<'in_out>( + key: &SymmetricCipherKey, + mode: OperatingMode, + context: DecryptionContext, + in_out: &'in_out mut [u8], +) -> Result<&'in_out mut [u8], Unspecified> { + #[allow(clippy::match_wildcard_for_single_variants)] + let key = match &key { + SymmetricCipherKey::Aes128 { enc_key, .. } | SymmetricCipherKey::Aes256 { enc_key, .. } => { + enc_key + } + _ => return Err(Unspecified), + }; + + let mut iv = { + let mut iv = [0u8; AES_CFB_IV_LEN]; + iv.copy_from_slice((&context).try_into()?); + iv + }; + + let cfb_decrypt: fn(&AES_KEY, &mut [u8], &mut [u8]) = match mode { + // TODO: Hopefully support CFB1, and CFB8 + OperatingMode::CFB128 => aes_cfb128_decrypt, + _ => { + // this indicates a programming error and shouldn't happen + return Err(Unspecified); + } + }; + + cfb_decrypt(key, &mut iv, in_out); + + iv.zeroize(); + + Ok(in_out) +} + fn aes_ctr128_encrypt(key: &AES_KEY, iv: &mut [u8], block_buffer: &mut [u8], in_out: &mut [u8]) { - let mut num = MaybeUninit::::new(0); + let mut num: u32 = 0; indicator_check!(unsafe { AES_ctr128_encrypt( @@ -748,7 +900,7 @@ fn aes_ctr128_encrypt(key: &AES_KEY, iv: &mut [u8], block_buffer: &mut [u8], in_ key, iv.as_mut_ptr(), block_buffer.as_mut_ptr(), - num.as_mut_ptr(), + &mut num, ); }); @@ -781,6 +933,36 @@ fn aes_cbc_decrypt(key: &AES_KEY, iv: &mut [u8], in_out: &mut [u8]) { }); } +fn aes_cfb128_encrypt(key: &AES_KEY, iv: &mut [u8], in_out: &mut [u8]) { + let mut num: i32 = 0; + indicator_check!(unsafe { + AES_cfb128_encrypt( + in_out.as_ptr(), + in_out.as_mut_ptr(), + in_out.len(), + key, + iv.as_mut_ptr(), + &mut num, + AES_ENCRYPT, + ); + }); +} + +fn aes_cfb128_decrypt(key: &AES_KEY, iv: &mut [u8], in_out: &mut [u8]) { + let mut num: i32 = 0; + indicator_check!(unsafe { + AES_cfb128_encrypt( + in_out.as_ptr(), + in_out.as_mut_ptr(), + in_out.len(), + key, + iv.as_mut_ptr(), + &mut num, + AES_DECRYPT, + ); + }); +} + #[cfg(test)] mod tests { use super::*; @@ -963,4 +1145,24 @@ mod tests { "eca7285d19f3c20e295378460e8729", "b5098e5e788de6ac2f2098eb2fc6f8" ); + + cipher_kat!( + test_sp800_38a_cfb128_aes128, + &AES_128, + OperatingMode::CFB128, + "2b7e151628aed2a6abf7158809cf4f3c", + "000102030405060708090a0b0c0d0e0f", + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", + "3b3fd92eb72dad20333449f8e83cfb4ac8a64537a0b3a93fcde3cdad9f1ce58b26751f67a3cbb140b1808cf187a4f4dfc04b05357c5d1c0eeac4c66f9ff7f2e6" + ); + + cipher_kat!( + test_sp800_38a_cfb128_aes256, + &AES_256, + OperatingMode::CFB128, + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", + "000102030405060708090a0b0c0d0e0f", + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", + "dc7e84bfda79164b7ecd8486985d386039ffed143b28b1c832113c6331e5407bdf10132415e54b92a13ed0a8267ae2f975a385741ab9cef82031623d55b1e471" + ); } diff --git a/aws-lc-rs/src/cipher/streaming.rs b/aws-lc-rs/src/cipher/streaming.rs index b12029abeff..1adc2f10fc1 100644 --- a/aws-lc-rs/src/cipher/streaming.rs +++ b/aws-lc-rs/src/cipher/streaming.rs @@ -217,6 +217,33 @@ impl StreamingEncryptingKey { Self::less_safe_cbc_pkcs7(key, context) } + /// Constructs a `StreamingEncryptingKey` for encrypting data using the CFB128 cipher mode. + /// The resulting ciphertext will be the same length as the plaintext. + /// + /// # Errors + /// Returns and error on an internal failure. + pub fn cfb128(key: UnboundCipherKey) -> Result { + let context = key + .algorithm() + .new_encryption_context(OperatingMode::CFB128)?; + Self::less_safe_cfb128(key, context) + } + + /// Constructs a `StreamingEncryptingKey` for encrypting data using the CFB128 cipher mode. + /// The resulting ciphertext will be the same length as the plaintext. + /// + /// This is considered less safe because the caller could potentially construct + /// an `EncryptionContext` from a previously used initialization vector (IV). + /// + /// # Errors + /// Returns an error on an internal failure. + pub fn less_safe_cfb128( + key: UnboundCipherKey, + context: EncryptionContext, + ) -> Result { + Self::new(key, OperatingMode::CFB128, context) + } + /// Constructs a `StreamingEncryptingKey` for encrypting data using the CBC cipher mode /// with pkcs7 padding. /// The resulting ciphertext will be longer than the plaintext; padding is added @@ -380,6 +407,15 @@ impl StreamingDecryptingKey { ) -> Result { Self::new(key, OperatingMode::CBC, context) } + + // Constructs a `StreamingDecryptingKey` for decrypting using the CFB128 cipher mode. + /// The resulting plaintext will be the same length as the ciphertext. + /// + /// # Errors + /// Returns an error on an internal failure. + pub fn cfb128(key: UnboundCipherKey, context: DecryptionContext) -> Result { + Self::new(key, OperatingMode::CFB128, context) + } } #[cfg(test)] @@ -437,6 +473,10 @@ mod tests { OperatingMode::CTR => { assert_eq!(ciphertext.len(), plaintext.len()); } + // TODO: Hopefully support CFB1, and CFB8 + OperatingMode::CFB128 => { + assert_eq!(ciphertext.len(), plaintext.len()); + } } (ciphertext.into_boxed_slice(), decrypt_iv) @@ -486,6 +526,10 @@ mod tests { OperatingMode::CTR => { assert_eq!(ciphertext.len(), plaintext.len()); } + // TODO: Hopefully support CFB1, and CFB8 + OperatingMode::CFB128 => { + assert_eq!(ciphertext.len(), plaintext.len()); + } } plaintext.into_boxed_slice() } @@ -519,6 +563,7 @@ mod tests { helper_stream_step_encrypt_test!(cbc_pkcs7); helper_stream_step_encrypt_test!(ctr); + helper_stream_step_encrypt_test!(cfb128); #[test] fn test_step_cbc() { @@ -631,6 +676,61 @@ mod tests { } } + #[test] + fn test_step_cfb128() { + let random = SystemRandom::new(); + let mut key = [0u8; AES_256_KEY_LEN]; + random.fill(&mut key).unwrap(); + + let encrypting_key_creator = || { + let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); + StreamingEncryptingKey::cfb128(key).unwrap() + }; + let decrypting_key_creator = |decryption_ctx: DecryptionContext| { + let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); + StreamingDecryptingKey::cfb128(key, decryption_ctx).unwrap() + }; + + for i in 13..=21 { + for j in 124..=131 { + helper_test_cfb128_stream_encrypt_step_n_bytes( + encrypting_key_creator, + decrypting_key_creator, + j, + i, + ); + } + for j in 124..=131 { + helper_test_cfb128_stream_encrypt_step_n_bytes( + encrypting_key_creator, + decrypting_key_creator, + j, + j - i, + ); + } + } + for j in 124..=131 { + helper_test_cfb128_stream_encrypt_step_n_bytes( + encrypting_key_creator, + decrypting_key_creator, + j, + j, + ); + helper_test_cfb128_stream_encrypt_step_n_bytes( + encrypting_key_creator, + decrypting_key_creator, + j, + 256, + ); + helper_test_cfb128_stream_encrypt_step_n_bytes( + encrypting_key_creator, + decrypting_key_creator, + j, + 1, + ); + } + } + macro_rules! streaming_cipher_kat { ($name:ident, $alg:expr, $mode:expr, $key:literal, $iv: literal, $plaintext:literal, $ciphertext:literal, $from_step:literal, $to_step:literal) => { #[test] @@ -783,4 +883,52 @@ mod tests { 2, 9 ); + + streaming_cipher_kat!( + test_openssl_aes_128_cfb128_16_bytes, + &AES_128, + OperatingMode::CFB128, + "5c353f739429bbd48b7e3f9a76facf4d", + "7b2c7ce17a9b6a59a9e64253b98c8cd1", + "add1bcebeaabe9423d4e916400e877c5", + "8440ec442e4135a613ddb2ce26107e10", + 2, + 9 + ); + + streaming_cipher_kat!( + test_openssl_aes_128_cfb128_15_bytes, + &AES_128, + OperatingMode::CFB128, + "e1f39d70ad378efc1ac318aa8ac4489f", + "ec78c3d54fff2fe09678c7883024ddce", + "b8c905004b2a92a323769f1b8dc1b2", + "964c3e9bf8bf2a3cca02d8e2e75608", + 2, + 9 + ); + + streaming_cipher_kat!( + test_openssl_aes_256_cfb128_16_bytes, + &AES_256, + OperatingMode::CFB128, + "0e8117d0984d6acb957a5d6ca526a12fa612ce5de2daadebd42c14d28a0a192e", + "09147a153b230a40cd7bf4197ad0e825", + "13f4540a4e06394148ade31a6f678787", + "250e590e47b7613b7d0a53f684e970d6", + 2, + 9 + ); + + streaming_cipher_kat!( + test_openssl_aes_256_cfb128_15_bytes, + &AES_256, + OperatingMode::CFB128, + "5cb17d8d5b9dbd81e4f1e0a2c82ebf36cf61156388fb7abf99d4526622858225", + "13c77415ec24f3e2f784f228478a85be", + "3efa583df4405aab61e18155aa7e0d", + "c1f2ffe8aa5064199e8f4f1b388303", + 2, + 9 + ); } From 6f3a0e81e83d9ad662368b369125e24142d8675a Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Wed, 13 Nov 2024 18:35:08 +0000 Subject: [PATCH 2/3] Address feedback --- aws-lc-rs/src/cipher.rs | 32 ++++++++++++------------------- aws-lc-rs/src/cipher/streaming.rs | 12 ++---------- 2 files changed, 14 insertions(+), 30 deletions(-) diff --git a/aws-lc-rs/src/cipher.rs b/aws-lc-rs/src/cipher.rs index ce416c067a3..a332796b4fa 100644 --- a/aws-lc-rs/src/cipher.rs +++ b/aws-lc-rs/src/cipher.rs @@ -134,7 +134,7 @@ //! # Ok(()) //! # } //! ``` -//! +//! //! ### AES-128 CFB 128-bit mode //! //! ```rust @@ -671,13 +671,12 @@ fn encrypt( let block_len = algorithm.block_len(); match mode { - // TODO: Hopefully support CFB1, and CFB8 - OperatingMode::CTR | OperatingMode::CFB128 => {} - _ => { + OperatingMode::CBC => { if (in_out.len() % block_len) != 0 { return Err(Unspecified); } } + _ => {} } match mode { @@ -706,13 +705,12 @@ fn decrypt<'in_out>( let block_len = algorithm.block_len(); match mode { - // TODO: Hopefully support CFB1, and CFB8 - OperatingMode::CTR | OperatingMode::CFB128 => {} - _ => { + OperatingMode::CBC => { if (in_out.len() % block_len) != 0 { return Err(Unspecified); } } + _ => {} } match mode { @@ -741,7 +739,7 @@ fn encrypt_aes_ctr_mode( SymmetricCipherKey::Aes128 { enc_key, .. } | SymmetricCipherKey::Aes256 { enc_key, .. } => { enc_key } - _ => return Err(Unspecified), + _ => unreachable!(), }; let mut iv = { @@ -777,7 +775,7 @@ fn encrypt_aes_cbc_mode( SymmetricCipherKey::Aes128 { enc_key, .. } | SymmetricCipherKey::Aes256 { enc_key, .. } => { enc_key } - _ => return Err(Unspecified), + _ => unreachable!(), }; let mut iv = { @@ -803,7 +801,7 @@ fn decrypt_aes_cbc_mode<'in_out>( SymmetricCipherKey::Aes128 { dec_key, .. } | SymmetricCipherKey::Aes256 { dec_key, .. } => { dec_key } - _ => return Err(Unspecified), + _ => unreachable!(), }; let mut iv = { @@ -829,7 +827,7 @@ fn encrypt_aes_cfb_mode( SymmetricCipherKey::Aes128 { enc_key, .. } | SymmetricCipherKey::Aes256 { enc_key, .. } => { enc_key } - _ => return Err(Unspecified), + _ => unreachable!(), }; let mut iv = { @@ -841,10 +839,7 @@ fn encrypt_aes_cfb_mode( let cfb_encrypt: fn(&AES_KEY, &mut [u8], &mut [u8]) = match mode { // TODO: Hopefully support CFB1, and CFB8 OperatingMode::CFB128 => aes_cfb128_encrypt, - _ => { - // this indicates a programming error and shouldn't happen - return Err(Unspecified); - } + _ => unreachable!(), }; cfb_encrypt(key, &mut iv, in_out); @@ -864,7 +859,7 @@ fn decrypt_aes_cfb_mode<'in_out>( SymmetricCipherKey::Aes128 { enc_key, .. } | SymmetricCipherKey::Aes256 { enc_key, .. } => { enc_key } - _ => return Err(Unspecified), + _ => unreachable!(), }; let mut iv = { @@ -876,10 +871,7 @@ fn decrypt_aes_cfb_mode<'in_out>( let cfb_decrypt: fn(&AES_KEY, &mut [u8], &mut [u8]) = match mode { // TODO: Hopefully support CFB1, and CFB8 OperatingMode::CFB128 => aes_cfb128_decrypt, - _ => { - // this indicates a programming error and shouldn't happen - return Err(Unspecified); - } + _ => unreachable!(), }; cfb_decrypt(key, &mut iv, in_out); diff --git a/aws-lc-rs/src/cipher/streaming.rs b/aws-lc-rs/src/cipher/streaming.rs index 1adc2f10fc1..e990678bc07 100644 --- a/aws-lc-rs/src/cipher/streaming.rs +++ b/aws-lc-rs/src/cipher/streaming.rs @@ -470,11 +470,7 @@ mod tests { assert!(ciphertext.len() > plaintext.len()); assert!(ciphertext.len() <= plaintext.len() + alg.block_len()); } - OperatingMode::CTR => { - assert_eq!(ciphertext.len(), plaintext.len()); - } - // TODO: Hopefully support CFB1, and CFB8 - OperatingMode::CFB128 => { + _ => { assert_eq!(ciphertext.len(), plaintext.len()); } } @@ -523,11 +519,7 @@ mod tests { assert!(ciphertext.len() > plaintext.len()); assert!(ciphertext.len() <= plaintext.len() + alg.block_len()); } - OperatingMode::CTR => { - assert_eq!(ciphertext.len(), plaintext.len()); - } - // TODO: Hopefully support CFB1, and CFB8 - OperatingMode::CFB128 => { + _ => { assert_eq!(ciphertext.len(), plaintext.len()); } } From 113cfffcf85df75d521c1a55db360c466f3aca46 Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Wed, 13 Nov 2024 18:47:30 +0000 Subject: [PATCH 3/3] =?UTF-8?q?a=CC=B8l=CC=B4l=CC=B8=20=CC=B6h=CC=B7a?= =?UTF-8?q?=CC=B4i=CC=B4l=CC=B6=20=CC=B8c=CC=B4l=CC=B5i=CC=B6p=CC=B4p?= =?UTF-8?q?=CC=B8y=CC=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aws-lc-rs-testing/benches/kem_benchmark.rs | 1 + aws-lc-rs/src/cipher.rs | 20 ++++++-------------- aws-lc-rs/src/test.rs | 2 +- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/aws-lc-rs-testing/benches/kem_benchmark.rs b/aws-lc-rs-testing/benches/kem_benchmark.rs index e906b3d2723..afe708156a2 100644 --- a/aws-lc-rs-testing/benches/kem_benchmark.rs +++ b/aws-lc-rs-testing/benches/kem_benchmark.rs @@ -7,6 +7,7 @@ use aws_lc_rs::{ }; use criterion::{criterion_group, criterion_main, Criterion}; +#[allow(deprecated)] const UNSTABLE_ALGORITHMS: &[Option<&aws_lc_rs::kem::Algorithm>] = &[ get_algorithm(AlgorithmId::Kyber512_R3), get_algorithm(AlgorithmId::Kyber768_R3), diff --git a/aws-lc-rs/src/cipher.rs b/aws-lc-rs/src/cipher.rs index a332796b4fa..e5c8608dc42 100644 --- a/aws-lc-rs/src/cipher.rs +++ b/aws-lc-rs/src/cipher.rs @@ -670,13 +670,8 @@ fn encrypt( ) -> Result { let block_len = algorithm.block_len(); - match mode { - OperatingMode::CBC => { - if (in_out.len() % block_len) != 0 { - return Err(Unspecified); - } - } - _ => {} + if mode == OperatingMode::CBC && (in_out.len() % block_len) != 0 { + return Err(Unspecified); } match mode { @@ -704,13 +699,8 @@ fn decrypt<'in_out>( ) -> Result<&'in_out mut [u8], Unspecified> { let block_len = algorithm.block_len(); - match mode { - OperatingMode::CBC => { - if (in_out.len() % block_len) != 0 { - return Err(Unspecified); - } - } - _ => {} + if mode == OperatingMode::CBC && (in_out.len() % block_len) != 0 { + return Err(Unspecified); } match mode { @@ -816,6 +806,7 @@ fn decrypt_aes_cbc_mode<'in_out>( Ok(in_out) } +#[allow(clippy::needless_pass_by_value)] fn encrypt_aes_cfb_mode( key: &SymmetricCipherKey, mode: OperatingMode, @@ -848,6 +839,7 @@ fn encrypt_aes_cfb_mode( Ok(context.into()) } +#[allow(clippy::needless_pass_by_value)] fn decrypt_aes_cfb_mode<'in_out>( key: &SymmetricCipherKey, mode: OperatingMode, diff --git a/aws-lc-rs/src/test.rs b/aws-lc-rs/src/test.rs index a88716252fb..ccc2f6675fd 100644 --- a/aws-lc-rs/src/test.rs +++ b/aws-lc-rs/src/test.rs @@ -202,7 +202,7 @@ impl TestCase { let result = if s.starts_with('\"') { // The value is a quoted UTF-8 string. - let mut bytes = Vec::with_capacity(s.as_bytes().len()); + let mut bytes = Vec::with_capacity(s.len()); let mut s = s.as_bytes().iter().skip(1); loop { let b = match s.next() {