From 17c86a908b9e3cf132f86a3ad47c515b8fbf9fee Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Wed, 12 Jun 2024 16:53:14 -0400 Subject: [PATCH 1/9] Add support for using GCM in PBES2 Fixes #1432 --- pkcs5/Cargo.toml | 3 +- pkcs5/src/pbes2.rs | 72 ++++++++++++++ pkcs5/src/pbes2/encryption.rs | 90 ++++++++++++++++++ pkcs8/tests/encrypted_private_key.rs | 80 ++++++++++++++++ .../ed25519-encpriv-aes128-gcm-scrypt.der | Bin 0 -> 150 bytes .../ed25519-encpriv-aes256-gcm-scrypt.der | Bin 0 -> 151 bytes 6 files changed, 244 insertions(+), 1 deletion(-) create mode 100644 pkcs8/tests/examples/ed25519-encpriv-aes128-gcm-scrypt.der create mode 100644 pkcs8/tests/examples/ed25519-encpriv-aes256-gcm-scrypt.der diff --git a/pkcs5/Cargo.toml b/pkcs5/Cargo.toml index 94fb4d9fc..a0dc69c9e 100644 --- a/pkcs5/Cargo.toml +++ b/pkcs5/Cargo.toml @@ -22,6 +22,7 @@ spki = { version = "=0.8.0-pre.0" } # optional dependencies cbc = { version = "=0.2.0-pre", optional = true } aes = { version = "=0.9.0-pre", optional = true, default-features = false } +aes-gcm = { version = "0.10", optional = true, default-features = false, features = ["aes"] } des = { version = "=0.9.0-pre.0", optional = true, default-features = false } pbkdf2 = { version = "=0.13.0-pre.0", optional = true, default-features = false, features = ["hmac"] } rand_core = { version = "0.6.4", optional = true, default-features = false } @@ -37,7 +38,7 @@ alloc = [] 3des = ["dep:des", "pbes2"] des-insecure = ["dep:des", "pbes2"] getrandom = ["rand_core/getrandom"] -pbes2 = ["dep:aes", "dep:cbc", "dep:pbkdf2", "dep:scrypt", "dep:sha2"] +pbes2 = ["dep:aes", "dep:cbc", "dep:pbkdf2", "dep:scrypt", "dep:sha2", "dep:aes-gcm"] sha1-insecure = ["dep:sha1", "pbes2"] [package.metadata.docs.rs] diff --git a/pkcs5/src/pbes2.rs b/pkcs5/src/pbes2.rs index d7b63b8f4..def3eec09 100644 --- a/pkcs5/src/pbes2.rs +++ b/pkcs5/src/pbes2.rs @@ -39,6 +39,14 @@ pub const AES_192_CBC_OID: ObjectIdentifier = pub const AES_256_CBC_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.1.42"); +/// 128-bit Advanced Encryption Standard (AES) algorithm with Galois Counter Mode +pub const AES_128_GCM_OID: ObjectIdentifier = + ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.1.6"); + +/// 256-bit Advanced Encryption Standard (AES) algorithm with Galois Counter Mode +pub const AES_256_GCM_OID: ObjectIdentifier = + ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.1.46"); + /// DES operating in CBC mode #[cfg(feature = "des-insecure")] pub const DES_CBC_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.14.3.2.7"); @@ -55,6 +63,12 @@ pub const PBES2_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.11 /// AES cipher block size const AES_BLOCK_SIZE: usize = 16; +/// GCM nonce size +/// +/// We could use any value here but GCM is most efficient +/// with 96 bit nonces +const GCM_NONCE_SIZE: usize = 12; + /// DES / Triple DES block size #[cfg(any(feature = "3des", feature = "des-insecure"))] const DES_BLOCK_SIZE: usize = 8; @@ -205,6 +219,40 @@ impl Parameters { Ok(Self { kdf, encryption }) } + /// Initialize PBES2 parameters using scrypt as the password-based + /// key derivation function and AES-128-GCM as the symmetric cipher. + /// + /// For more information on scrypt parameters, see documentation for the + /// [`scrypt::Params`] struct. + // TODO(tarcieri): encapsulate `scrypt::Params`? + #[cfg(feature = "pbes2")] + pub fn scrypt_aes128gcm( + params: scrypt::Params, + salt: &[u8], + gcm_nonce: [u8; GCM_NONCE_SIZE], + ) -> Result { + let kdf = ScryptParams::from_params_and_salt(params, salt)?.into(); + let encryption = EncryptionScheme::Aes128Gcm { iv: gcm_nonce }; + Ok(Self { kdf, encryption }) + } + + /// Initialize PBES2 parameters using scrypt as the password-based + /// key derivation function and AES-256-GCM as the symmetric cipher. + /// + /// For more information on scrypt parameters, see documentation for the + /// [`scrypt::Params`] struct. + // TODO(tarcieri): encapsulate `scrypt::Params`? + #[cfg(feature = "pbes2")] + pub fn scrypt_aes256gcm( + params: scrypt::Params, + salt: &[u8], + gcm_nonce: [u8; GCM_NONCE_SIZE], + ) -> Result { + let kdf = ScryptParams::from_params_and_salt(params, salt)?.into(); + let encryption = EncryptionScheme::Aes256Gcm { iv: gcm_nonce }; + Ok(Self { kdf, encryption }) + } + /// Attempt to decrypt the given ciphertext, allocating and returning a /// byte vector containing the plaintext. #[cfg(all(feature = "alloc", feature = "pbes2"))] @@ -321,6 +369,18 @@ pub enum EncryptionScheme { iv: [u8; AES_BLOCK_SIZE], }, + /// AES-128 in CBC mode + Aes128Gcm { + /// GCM nonce + iv: [u8; GCM_NONCE_SIZE], + }, + + /// AES-256 in GCM mode + Aes256Gcm { + /// GCM nonce + iv: [u8; GCM_NONCE_SIZE], + }, + /// 3-Key Triple DES in CBC mode #[cfg(feature = "3des")] DesEde3Cbc { @@ -343,6 +403,8 @@ impl EncryptionScheme { Self::Aes128Cbc { .. } => 16, Self::Aes192Cbc { .. } => 24, Self::Aes256Cbc { .. } => 32, + Self::Aes128Gcm { .. } => 16, + Self::Aes256Gcm { .. } => 32, #[cfg(feature = "des-insecure")] Self::DesCbc { .. } => 8, #[cfg(feature = "3des")] @@ -356,6 +418,8 @@ impl EncryptionScheme { Self::Aes128Cbc { .. } => AES_128_CBC_OID, Self::Aes192Cbc { .. } => AES_192_CBC_OID, Self::Aes256Cbc { .. } => AES_256_CBC_OID, + Self::Aes128Gcm { .. } => AES_128_GCM_OID, + Self::Aes256Gcm { .. } => AES_256_GCM_OID, #[cfg(feature = "des-insecure")] Self::DesCbc { .. } => DES_CBC_OID, #[cfg(feature = "3des")] @@ -399,6 +463,12 @@ impl TryFrom> for EncryptionScheme { AES_256_CBC_OID => Ok(Self::Aes256Cbc { iv: iv.try_into().map_err(|_| Tag::OctetString.value_error())?, }), + AES_128_GCM_OID => Ok(Self::Aes128Gcm { + iv: iv.try_into().map_err(|_| Tag::OctetString.value_error())?, + }), + AES_256_GCM_OID => Ok(Self::Aes256Gcm { + iv: iv.try_into().map_err(|_| Tag::OctetString.value_error())?, + }), #[cfg(feature = "des-insecure")] DES_CBC_OID => Ok(Self::DesCbc { iv: iv[0..DES_BLOCK_SIZE] @@ -424,6 +494,8 @@ impl<'a> TryFrom<&'a EncryptionScheme> for AlgorithmIdentifierRef<'a> { EncryptionScheme::Aes128Cbc { iv } => iv.as_slice(), EncryptionScheme::Aes192Cbc { iv } => iv.as_slice(), EncryptionScheme::Aes256Cbc { iv } => iv.as_slice(), + EncryptionScheme::Aes128Gcm { iv } => iv.as_slice(), + EncryptionScheme::Aes256Gcm { iv } => iv.as_slice(), #[cfg(feature = "des-insecure")] EncryptionScheme::DesCbc { iv } => iv.as_slice(), #[cfg(feature = "3des")] diff --git a/pkcs5/src/pbes2/encryption.rs b/pkcs5/src/pbes2/encryption.rs index 4cf4924cb..83b36d931 100644 --- a/pkcs5/src/pbes2/encryption.rs +++ b/pkcs5/src/pbes2/encryption.rs @@ -2,6 +2,7 @@ use super::{EncryptionScheme, Kdf, Parameters, Pbkdf2Params, Pbkdf2Prf, ScryptParams}; use crate::{Error, Result}; +use aes_gcm::{Aes256Gcm, Aes128Gcm, KeyInit as GcmKeyInit, AeadInPlace, Nonce, Tag}; use cbc::cipher::{ block_padding::Pkcs7, BlockCipher, BlockCipherDecrypt, BlockCipherEncrypt, BlockModeDecrypt, BlockModeEncrypt, KeyInit, KeyIvInit, @@ -48,6 +49,91 @@ fn cbc_decrypt<'a, C: BlockCipherDecrypt + BlockCipher + KeyInit>( .map_err(|_| Error::EncryptFailed) } +fn aes_128_gcm_encrypt<'a>( + es: EncryptionScheme, + key: EncryptionKey, + iv: &[u8], + buffer: &'a mut [u8], + pos: usize, +) -> Result<&'a [u8]> { + if buffer.len() < 16 + pos { + return Err(Error::EncryptFailed); + } + let gcm = Aes128Gcm::new_from_slice(key.as_slice()).map_err(|_| es.to_alg_params_invalid())?; + let nonce : [u8; 12] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; + let nonce = Nonce::from(nonce); + let tag = gcm.encrypt_in_place_detached(&nonce, &[], &mut buffer[..pos]).map_err(|_| Error::EncryptFailed)?; + buffer[pos..].copy_from_slice(tag.as_ref()); + Ok(&buffer[0..pos+16]) +} + +fn aes_128_gcm_decrypt<'a>( + es: EncryptionScheme, + key: EncryptionKey, + iv: &[u8], + buffer: &'a mut [u8], +) -> Result<&'a [u8]> { + let msg_len = if buffer.len() < 16 { + return Err(Error::DecryptFailed); + } else { + buffer.len() - 16 + }; + + let gcm = Aes128Gcm::new_from_slice(key.as_slice()).map_err(|_| es.to_alg_params_invalid())?; + let nonce : [u8; 12] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; + let nonce = Nonce::from(nonce); + let tag: [u8; 16] = buffer[msg_len..].try_into().map_err(|_| Error::DecryptFailed)?; + let tag = Tag::from(tag); + if !gcm.decrypt_in_place_detached(&nonce, &[], &mut buffer[..msg_len], &tag).is_ok() { + return Err(Error::DecryptFailed); + } + + Ok(&buffer[..msg_len]) +} + +fn aes_256_gcm_encrypt<'a>( + es: EncryptionScheme, + key: EncryptionKey, + iv: &[u8], + buffer: &'a mut [u8], + pos: usize, +) -> Result<&'a [u8]> { + if buffer.len() < 16 + pos { + return Err(Error::EncryptFailed); + } + let gcm = Aes256Gcm::new_from_slice(key.as_slice()).map_err(|_| es.to_alg_params_invalid())?; + let nonce : [u8; 12] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; + let nonce = Nonce::from(nonce); + let tag = gcm.encrypt_in_place_detached(&nonce, &[], &mut buffer[..pos]).map_err(|_| Error::EncryptFailed)?; + buffer[pos..].copy_from_slice(tag.as_ref()); + Ok(&buffer[0..pos+16]) +} + +fn aes_256_gcm_decrypt<'a>( + es: EncryptionScheme, + key: EncryptionKey, + iv: &[u8], + buffer: &'a mut [u8], +) -> Result<&'a [u8]> { + let msg_len = if buffer.len() < 16 { + return Err(Error::DecryptFailed); + } else { + buffer.len() - 16 + }; + + let gcm = Aes256Gcm::new_from_slice(key.as_slice()).map_err(|_| es.to_alg_params_invalid())?; + let nonce : [u8; 12] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; + let nonce = Nonce::from(nonce); + let tag: [u8; 16] = buffer[msg_len..].try_into().map_err(|_| Error::DecryptFailed)?; + let tag = Tag::from(tag); + if !gcm.decrypt_in_place_detached(&nonce, &[], &mut buffer[..msg_len], &tag).is_ok() { + return Err(Error::DecryptFailed); + } + + Ok(&buffer[..msg_len]) +} + + pub fn encrypt_in_place<'b>( params: &Parameters, password: impl AsRef<[u8]>, @@ -65,6 +151,8 @@ pub fn encrypt_in_place<'b>( EncryptionScheme::Aes128Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), EncryptionScheme::Aes192Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), EncryptionScheme::Aes256Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), + EncryptionScheme::Aes128Gcm { iv } => aes_128_gcm_encrypt(es, key, &iv, buf, pos), + EncryptionScheme::Aes256Gcm { iv } => aes_256_gcm_encrypt(es, key, &iv, buf, pos), #[cfg(feature = "3des")] EncryptionScheme::DesEde3Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), #[cfg(feature = "des-insecure")] @@ -87,6 +175,8 @@ pub fn decrypt_in_place<'a>( EncryptionScheme::Aes128Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), EncryptionScheme::Aes192Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), EncryptionScheme::Aes256Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), + EncryptionScheme::Aes128Gcm { iv } => aes_128_gcm_decrypt(es, key, &iv, buf), + EncryptionScheme::Aes256Gcm { iv } => aes_256_gcm_decrypt(es, key, &iv, buf), #[cfg(feature = "3des")] EncryptionScheme::DesEde3Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), #[cfg(feature = "des-insecure")] diff --git a/pkcs8/tests/encrypted_private_key.rs b/pkcs8/tests/encrypted_private_key.rs index 9d601c749..cd7ad6b0a 100644 --- a/pkcs8/tests/encrypted_private_key.rs +++ b/pkcs8/tests/encrypted_private_key.rs @@ -46,6 +46,28 @@ const ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE: &[u8] = const ED25519_DER_AES256_SCRYPT_EXAMPLE: &[u8] = include_bytes!("examples/ed25519-encpriv-aes256-scrypt.der"); +/// Ed25519 PKCS#8 encrypted private key (PBES2 + AES-128-GCM + scrypt) encoded as ASN.1 DER. +/// +/// Generated using: +/// +/// ``` +/// $ botan pkcs8 ed25519-priv-pkcs8v1.der --der-out '--pbe=PBES2(AES-128/GCM,Scrypt)' --pass-out=hunter42 +/// ``` +#[cfg(feature = "encryption")] +const ED25519_DER_AES128_GCM_SCRYPT_EXAMPLE: &[u8] = + include_bytes!("examples/ed25519-encpriv-aes128-gcm-scrypt.der"); + +/// Ed25519 PKCS#8 encrypted private key (PBES2 + AES-256-GCM + scrypt) encoded as ASN.1 DER. +/// +/// Generated using: +/// +/// ``` +/// $ botan pkcs8 ed25519-priv-pkcs8v1.der --der-out '--pbe=PBES2(AES-256/GCM,Scrypt)' --pass-out=hunter42 +/// ``` +#[cfg(feature = "encryption")] +const ED25519_DER_AES256_GCM_SCRYPT_EXAMPLE: &[u8] = + include_bytes!("examples/ed25519-encpriv-aes256-gcm-scrypt.der"); + /// Ed25519 PKCS#8 encrypted private key encoded as PEM #[cfg(feature = "pem")] const ED25519_PEM_AES256_PBKDF2_SHA256_EXAMPLE: &str = @@ -158,6 +180,64 @@ fn decrypt_ed25519_der_encpriv_aes256_scrypt() { assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE); } +#[cfg(feature = "encryption")] +#[test] +fn decrypt_ed25519_der_encpriv_aes128_gcm_scrypt() { + let enc_pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES128_GCM_SCRYPT_EXAMPLE).unwrap(); + let pk = enc_pk.decrypt(PASSWORD).unwrap(); + assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE); +} + +#[cfg(feature = "encryption")] +#[test] +fn encrypt_ed25519_der_encpriv_aes128_gcm_scrypt() { + let scrypt_params = pkcs5::pbes2::Parameters::scrypt_aes128gcm( + pkcs5::scrypt::Params::new(14, 8, 1, 16).unwrap(), + &hex!("05BE17663E551D120F81308E"), + hex!("D7E967A5DF6189471BCC1F49"), + ) + .unwrap(); + + let pk_plaintext = PrivateKeyInfo::try_from(ED25519_DER_PLAINTEXT_EXAMPLE).unwrap(); + let pk_encrypted = pk_plaintext + .encrypt_with_params(scrypt_params, PASSWORD) + .unwrap(); + + assert_eq!( + pk_encrypted.as_bytes(), + ED25519_DER_AES128_GCM_SCRYPT_EXAMPLE + ); +} + +#[cfg(feature = "encryption")] +#[test] +fn decrypt_ed25519_der_encpriv_aes256_gcm_scrypt() { + let enc_pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_GCM_SCRYPT_EXAMPLE).unwrap(); + let pk = enc_pk.decrypt(PASSWORD).unwrap(); + assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE); +} + +#[cfg(feature = "encryption")] +#[test] +fn encrypt_ed25519_der_encpriv_aes256_gcm_scrypt() { + let scrypt_params = pkcs5::pbes2::Parameters::scrypt_aes256gcm( + pkcs5::scrypt::Params::new(15, 8, 1, 32).unwrap(), + &hex!("F67F4005A8393BD41F5B4981"), + hex!("98B118A950D39E2ECB5B125C"), + ) + .unwrap(); + + let pk_plaintext = PrivateKeyInfo::try_from(ED25519_DER_PLAINTEXT_EXAMPLE).unwrap(); + let pk_encrypted = pk_plaintext + .encrypt_with_params(scrypt_params, PASSWORD) + .unwrap(); + + assert_eq!( + pk_encrypted.as_bytes(), + ED25519_DER_AES256_GCM_SCRYPT_EXAMPLE + ); +} + #[cfg(feature = "encryption")] #[test] fn encrypt_ed25519_der_encpriv_aes256_pbkdf2_sha256() { diff --git a/pkcs8/tests/examples/ed25519-encpriv-aes128-gcm-scrypt.der b/pkcs8/tests/examples/ed25519-encpriv-aes128-gcm-scrypt.der new file mode 100644 index 0000000000000000000000000000000000000000..6d76fb7647a344418797efe42595618fb47d9d61 GIT binary patch literal 150 zcmV;H0BQd)fs-_>&LNQU1UhwsC7RWRs}^=ROXhrF!A E#qf|c+5i9m literal 0 HcmV?d00001 diff --git a/pkcs8/tests/examples/ed25519-encpriv-aes256-gcm-scrypt.der b/pkcs8/tests/examples/ed25519-encpriv-aes256-gcm-scrypt.der new file mode 100644 index 0000000000000000000000000000000000000000..c95e45c71cb4dd1ddc072f7d6677ebe4648150e1 GIT binary patch literal 151 zcmV;I0BHX(fs`;%1_>&LNQU)Car12}*WX8%Ynudb}lLOJQ~;U8>$yZr`Dhu3k(G+{E literal 0 HcmV?d00001 From e95bb017a7ef2cbe437bd413cf4233cafa5c8026 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Thu, 13 Jun 2024 08:35:35 -0400 Subject: [PATCH 2/9] Fix fmt and cargo lints --- pkcs5/src/pbes2/encryption.rs | 41 +++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/pkcs5/src/pbes2/encryption.rs b/pkcs5/src/pbes2/encryption.rs index 83b36d931..e6b1d1721 100644 --- a/pkcs5/src/pbes2/encryption.rs +++ b/pkcs5/src/pbes2/encryption.rs @@ -2,7 +2,7 @@ use super::{EncryptionScheme, Kdf, Parameters, Pbkdf2Params, Pbkdf2Prf, ScryptParams}; use crate::{Error, Result}; -use aes_gcm::{Aes256Gcm, Aes128Gcm, KeyInit as GcmKeyInit, AeadInPlace, Nonce, Tag}; +use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, KeyInit as GcmKeyInit, Nonce, Tag}; use cbc::cipher::{ block_padding::Pkcs7, BlockCipher, BlockCipherDecrypt, BlockCipherEncrypt, BlockModeDecrypt, BlockModeEncrypt, KeyInit, KeyIvInit, @@ -60,11 +60,13 @@ fn aes_128_gcm_encrypt<'a>( return Err(Error::EncryptFailed); } let gcm = Aes128Gcm::new_from_slice(key.as_slice()).map_err(|_| es.to_alg_params_invalid())?; - let nonce : [u8; 12] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; + let nonce: [u8; 12] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; let nonce = Nonce::from(nonce); - let tag = gcm.encrypt_in_place_detached(&nonce, &[], &mut buffer[..pos]).map_err(|_| Error::EncryptFailed)?; + let tag = gcm + .encrypt_in_place_detached(&nonce, &[], &mut buffer[..pos]) + .map_err(|_| Error::EncryptFailed)?; buffer[pos..].copy_from_slice(tag.as_ref()); - Ok(&buffer[0..pos+16]) + Ok(&buffer[0..pos + 16]) } fn aes_128_gcm_decrypt<'a>( @@ -80,11 +82,16 @@ fn aes_128_gcm_decrypt<'a>( }; let gcm = Aes128Gcm::new_from_slice(key.as_slice()).map_err(|_| es.to_alg_params_invalid())?; - let nonce : [u8; 12] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; + let nonce: [u8; 12] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; let nonce = Nonce::from(nonce); - let tag: [u8; 16] = buffer[msg_len..].try_into().map_err(|_| Error::DecryptFailed)?; + let tag: [u8; 16] = buffer[msg_len..] + .try_into() + .map_err(|_| Error::DecryptFailed)?; let tag = Tag::from(tag); - if !gcm.decrypt_in_place_detached(&nonce, &[], &mut buffer[..msg_len], &tag).is_ok() { + if gcm + .decrypt_in_place_detached(&nonce, &[], &mut buffer[..msg_len], &tag) + .is_err() + { return Err(Error::DecryptFailed); } @@ -102,11 +109,13 @@ fn aes_256_gcm_encrypt<'a>( return Err(Error::EncryptFailed); } let gcm = Aes256Gcm::new_from_slice(key.as_slice()).map_err(|_| es.to_alg_params_invalid())?; - let nonce : [u8; 12] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; + let nonce: [u8; 12] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; let nonce = Nonce::from(nonce); - let tag = gcm.encrypt_in_place_detached(&nonce, &[], &mut buffer[..pos]).map_err(|_| Error::EncryptFailed)?; + let tag = gcm + .encrypt_in_place_detached(&nonce, &[], &mut buffer[..pos]) + .map_err(|_| Error::EncryptFailed)?; buffer[pos..].copy_from_slice(tag.as_ref()); - Ok(&buffer[0..pos+16]) + Ok(&buffer[0..pos + 16]) } fn aes_256_gcm_decrypt<'a>( @@ -122,18 +131,22 @@ fn aes_256_gcm_decrypt<'a>( }; let gcm = Aes256Gcm::new_from_slice(key.as_slice()).map_err(|_| es.to_alg_params_invalid())?; - let nonce : [u8; 12] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; + let nonce: [u8; 12] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; let nonce = Nonce::from(nonce); - let tag: [u8; 16] = buffer[msg_len..].try_into().map_err(|_| Error::DecryptFailed)?; + let tag: [u8; 16] = buffer[msg_len..] + .try_into() + .map_err(|_| Error::DecryptFailed)?; let tag = Tag::from(tag); - if !gcm.decrypt_in_place_detached(&nonce, &[], &mut buffer[..msg_len], &tag).is_ok() { + if gcm + .decrypt_in_place_detached(&nonce, &[], &mut buffer[..msg_len], &tag) + .is_err() + { return Err(Error::DecryptFailed); } Ok(&buffer[..msg_len]) } - pub fn encrypt_in_place<'b>( params: &Parameters, password: impl AsRef<[u8]>, From 6a26b049254c6d0632766b71ce99c8df68b1f489 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Thu, 13 Jun 2024 14:34:10 -0400 Subject: [PATCH 3/9] Rename GCM param from iv to nonce --- pkcs5/src/pbes2.rs | 16 ++++++++-------- pkcs5/src/pbes2/encryption.rs | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pkcs5/src/pbes2.rs b/pkcs5/src/pbes2.rs index def3eec09..80f7485e5 100644 --- a/pkcs5/src/pbes2.rs +++ b/pkcs5/src/pbes2.rs @@ -232,7 +232,7 @@ impl Parameters { gcm_nonce: [u8; GCM_NONCE_SIZE], ) -> Result { let kdf = ScryptParams::from_params_and_salt(params, salt)?.into(); - let encryption = EncryptionScheme::Aes128Gcm { iv: gcm_nonce }; + let encryption = EncryptionScheme::Aes128Gcm { nonce: gcm_nonce }; Ok(Self { kdf, encryption }) } @@ -249,7 +249,7 @@ impl Parameters { gcm_nonce: [u8; GCM_NONCE_SIZE], ) -> Result { let kdf = ScryptParams::from_params_and_salt(params, salt)?.into(); - let encryption = EncryptionScheme::Aes256Gcm { iv: gcm_nonce }; + let encryption = EncryptionScheme::Aes256Gcm { nonce: gcm_nonce }; Ok(Self { kdf, encryption }) } @@ -372,13 +372,13 @@ pub enum EncryptionScheme { /// AES-128 in CBC mode Aes128Gcm { /// GCM nonce - iv: [u8; GCM_NONCE_SIZE], + nonce: [u8; GCM_NONCE_SIZE], }, /// AES-256 in GCM mode Aes256Gcm { /// GCM nonce - iv: [u8; GCM_NONCE_SIZE], + nonce: [u8; GCM_NONCE_SIZE], }, /// 3-Key Triple DES in CBC mode @@ -464,10 +464,10 @@ impl TryFrom> for EncryptionScheme { iv: iv.try_into().map_err(|_| Tag::OctetString.value_error())?, }), AES_128_GCM_OID => Ok(Self::Aes128Gcm { - iv: iv.try_into().map_err(|_| Tag::OctetString.value_error())?, + nonce: iv.try_into().map_err(|_| Tag::OctetString.value_error())?, }), AES_256_GCM_OID => Ok(Self::Aes256Gcm { - iv: iv.try_into().map_err(|_| Tag::OctetString.value_error())?, + nonce: iv.try_into().map_err(|_| Tag::OctetString.value_error())?, }), #[cfg(feature = "des-insecure")] DES_CBC_OID => Ok(Self::DesCbc { @@ -494,8 +494,8 @@ impl<'a> TryFrom<&'a EncryptionScheme> for AlgorithmIdentifierRef<'a> { EncryptionScheme::Aes128Cbc { iv } => iv.as_slice(), EncryptionScheme::Aes192Cbc { iv } => iv.as_slice(), EncryptionScheme::Aes256Cbc { iv } => iv.as_slice(), - EncryptionScheme::Aes128Gcm { iv } => iv.as_slice(), - EncryptionScheme::Aes256Gcm { iv } => iv.as_slice(), + EncryptionScheme::Aes128Gcm { nonce } => nonce.as_slice(), + EncryptionScheme::Aes256Gcm { nonce } => nonce.as_slice(), #[cfg(feature = "des-insecure")] EncryptionScheme::DesCbc { iv } => iv.as_slice(), #[cfg(feature = "3des")] diff --git a/pkcs5/src/pbes2/encryption.rs b/pkcs5/src/pbes2/encryption.rs index e6b1d1721..735454b71 100644 --- a/pkcs5/src/pbes2/encryption.rs +++ b/pkcs5/src/pbes2/encryption.rs @@ -164,8 +164,8 @@ pub fn encrypt_in_place<'b>( EncryptionScheme::Aes128Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), EncryptionScheme::Aes192Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), EncryptionScheme::Aes256Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), - EncryptionScheme::Aes128Gcm { iv } => aes_128_gcm_encrypt(es, key, &iv, buf, pos), - EncryptionScheme::Aes256Gcm { iv } => aes_256_gcm_encrypt(es, key, &iv, buf, pos), + EncryptionScheme::Aes128Gcm { nonce } => aes_128_gcm_encrypt(es, key, &nonce, buf, pos), + EncryptionScheme::Aes256Gcm { nonce } => aes_256_gcm_encrypt(es, key, &nonce, buf, pos), #[cfg(feature = "3des")] EncryptionScheme::DesEde3Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), #[cfg(feature = "des-insecure")] @@ -188,8 +188,8 @@ pub fn decrypt_in_place<'a>( EncryptionScheme::Aes128Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), EncryptionScheme::Aes192Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), EncryptionScheme::Aes256Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), - EncryptionScheme::Aes128Gcm { iv } => aes_128_gcm_decrypt(es, key, &iv, buf), - EncryptionScheme::Aes256Gcm { iv } => aes_256_gcm_decrypt(es, key, &iv, buf), + EncryptionScheme::Aes128Gcm { nonce } => aes_128_gcm_decrypt(es, key, &nonce, buf), + EncryptionScheme::Aes256Gcm { nonce } => aes_256_gcm_decrypt(es, key, &nonce, buf), #[cfg(feature = "3des")] EncryptionScheme::DesEde3Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), #[cfg(feature = "des-insecure")] From c5280f31cb2597a5944a9d2573659751e3aa7765 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Fri, 14 Jun 2024 11:24:58 -0400 Subject: [PATCH 4/9] Make GCM encryption/decryption generic over the cipher --- Cargo.toml | 4 ++ pkcs5/Cargo.toml | 2 +- pkcs5/src/pbes2/encryption.rs | 109 +++++++++++++--------------------- 3 files changed, 47 insertions(+), 68 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1bc56ca67..f8879bd7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,6 +68,10 @@ whirlpool = { git = "https://github.com/RustCrypto/hashes.git" } cbc = { git = "https://github.com/RustCrypto/block-modes.git" } # Pending a release of 0.11.0-pre salsa20 = { git = "https://github.com/RustCrypto/stream-ciphers.git" } +# Pending a release of 0.11.0-pre +aes-gcm = { git = "https://github.com/RustCrypto/AEADs.git" } +aead = { git = "https://github.com/RustCrypto/traits.git" } +ctr = { git = "https://github.com/RustCrypto/block-modes.git" } # https://github.com/RustCrypto/formats/pull/1055 # https://github.com/RustCrypto/signatures/pull/809 diff --git a/pkcs5/Cargo.toml b/pkcs5/Cargo.toml index a0dc69c9e..7d988f334 100644 --- a/pkcs5/Cargo.toml +++ b/pkcs5/Cargo.toml @@ -22,7 +22,7 @@ spki = { version = "=0.8.0-pre.0" } # optional dependencies cbc = { version = "=0.2.0-pre", optional = true } aes = { version = "=0.9.0-pre", optional = true, default-features = false } -aes-gcm = { version = "0.10", optional = true, default-features = false, features = ["aes"] } +aes-gcm = { version = "=0.11.0-pre", optional = true, default-features = false, features = ["aes"] } des = { version = "=0.9.0-pre.0", optional = true, default-features = false } pbkdf2 = { version = "=0.13.0-pre.0", optional = true, default-features = false, features = ["hmac"] } rand_core = { version = "0.6.4", optional = true, default-features = false } diff --git a/pkcs5/src/pbes2/encryption.rs b/pkcs5/src/pbes2/encryption.rs index 735454b71..d15b51f30 100644 --- a/pkcs5/src/pbes2/encryption.rs +++ b/pkcs5/src/pbes2/encryption.rs @@ -2,7 +2,7 @@ use super::{EncryptionScheme, Kdf, Parameters, Pbkdf2Params, Pbkdf2Prf, ScryptParams}; use crate::{Error, Result}; -use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, KeyInit as GcmKeyInit, Nonce, Tag}; +use aes_gcm::{AeadInPlace, KeyInit as GcmKeyInit, Nonce, Tag}; use cbc::cipher::{ block_padding::Pkcs7, BlockCipher, BlockCipherDecrypt, BlockCipherEncrypt, BlockModeDecrypt, BlockModeEncrypt, KeyInit, KeyIvInit, @@ -12,7 +12,7 @@ use pbkdf2::{ digest::{ block_buffer::Eager, core_api::{BlockSizeUser, BufferKindUser, FixedOutputCore, UpdateCore}, - typenum::{IsLess, Le, NonZero, U256}, + typenum::{IsLess, Le, NonZero, UInt, UTerm, B0, B1, U12, U16, U256}, HashMarker, }, EagerHash, @@ -49,91 +49,58 @@ fn cbc_decrypt<'a, C: BlockCipherDecrypt + BlockCipher + KeyInit>( .map_err(|_| Error::EncryptFailed) } -fn aes_128_gcm_encrypt<'a>( +fn gcm_encrypt<'a, C>( es: EncryptionScheme, key: EncryptionKey, iv: &[u8], buffer: &'a mut [u8], pos: usize, -) -> Result<&'a [u8]> { - if buffer.len() < 16 + pos { - return Err(Error::EncryptFailed); - } - let gcm = Aes128Gcm::new_from_slice(key.as_slice()).map_err(|_| es.to_alg_params_invalid())?; - let nonce: [u8; 12] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; - let nonce = Nonce::from(nonce); - let tag = gcm - .encrypt_in_place_detached(&nonce, &[], &mut buffer[..pos]) - .map_err(|_| Error::EncryptFailed)?; - buffer[pos..].copy_from_slice(tag.as_ref()); - Ok(&buffer[0..pos + 16]) -} - -fn aes_128_gcm_decrypt<'a>( - es: EncryptionScheme, - key: EncryptionKey, - iv: &[u8], - buffer: &'a mut [u8], -) -> Result<&'a [u8]> { - let msg_len = if buffer.len() < 16 { - return Err(Error::DecryptFailed); - } else { - buffer.len() - 16 - }; - - let gcm = Aes128Gcm::new_from_slice(key.as_slice()).map_err(|_| es.to_alg_params_invalid())?; - let nonce: [u8; 12] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; - let nonce = Nonce::from(nonce); - let tag: [u8; 16] = buffer[msg_len..] - .try_into() - .map_err(|_| Error::DecryptFailed)?; - let tag = Tag::from(tag); - if gcm - .decrypt_in_place_detached(&nonce, &[], &mut buffer[..msg_len], &tag) - .is_err() - { - return Err(Error::DecryptFailed); - } +) -> Result<&'a [u8]> +where + C: BlockCipher + BlockSizeUser + GcmKeyInit + BlockCipherEncrypt, + aes_gcm::AesGcm, B1>, B0>, B0>>: GcmKeyInit, +{ + const TAG_SIZE: usize = 16; + const NONCE_SIZE: usize = 12; - Ok(&buffer[..msg_len]) -} - -fn aes_256_gcm_encrypt<'a>( - es: EncryptionScheme, - key: EncryptionKey, - iv: &[u8], - buffer: &'a mut [u8], - pos: usize, -) -> Result<&'a [u8]> { - if buffer.len() < 16 + pos { + if buffer.len() < TAG_SIZE + pos { return Err(Error::EncryptFailed); } - let gcm = Aes256Gcm::new_from_slice(key.as_slice()).map_err(|_| es.to_alg_params_invalid())?; - let nonce: [u8; 12] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; + let gcm = as GcmKeyInit>::new_from_slice(key.as_slice()) + .map_err(|_| es.to_alg_params_invalid())?; + let nonce: [u8; NONCE_SIZE] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; let nonce = Nonce::from(nonce); let tag = gcm .encrypt_in_place_detached(&nonce, &[], &mut buffer[..pos]) .map_err(|_| Error::EncryptFailed)?; buffer[pos..].copy_from_slice(tag.as_ref()); - Ok(&buffer[0..pos + 16]) + Ok(&buffer[0..pos + TAG_SIZE]) } -fn aes_256_gcm_decrypt<'a>( +fn gcm_decrypt<'a, C>( es: EncryptionScheme, key: EncryptionKey, iv: &[u8], buffer: &'a mut [u8], -) -> Result<&'a [u8]> { - let msg_len = if buffer.len() < 16 { +) -> Result<&'a [u8]> +where + C: BlockCipher + BlockSizeUser + GcmKeyInit + BlockCipherEncrypt, + aes_gcm::AesGcm, B1>, B0>, B0>>: GcmKeyInit, +{ + const TAG_SIZE: usize = 16; + const NONCE_SIZE: usize = 12; + + let msg_len = if buffer.len() < TAG_SIZE { return Err(Error::DecryptFailed); } else { - buffer.len() - 16 + buffer.len() - TAG_SIZE }; - let gcm = Aes256Gcm::new_from_slice(key.as_slice()).map_err(|_| es.to_alg_params_invalid())?; - let nonce: [u8; 12] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; + let gcm = as GcmKeyInit>::new_from_slice(key.as_slice()) + .map_err(|_| es.to_alg_params_invalid())?; + let nonce: [u8; NONCE_SIZE] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; let nonce = Nonce::from(nonce); - let tag: [u8; 16] = buffer[msg_len..] + let tag: [u8; TAG_SIZE] = buffer[msg_len..] .try_into() .map_err(|_| Error::DecryptFailed)?; let tag = Tag::from(tag); @@ -164,8 +131,12 @@ pub fn encrypt_in_place<'b>( EncryptionScheme::Aes128Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), EncryptionScheme::Aes192Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), EncryptionScheme::Aes256Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), - EncryptionScheme::Aes128Gcm { nonce } => aes_128_gcm_encrypt(es, key, &nonce, buf, pos), - EncryptionScheme::Aes256Gcm { nonce } => aes_256_gcm_encrypt(es, key, &nonce, buf, pos), + EncryptionScheme::Aes128Gcm { nonce } => { + gcm_encrypt::(es, key, &nonce, buf, pos) + } + EncryptionScheme::Aes256Gcm { nonce } => { + gcm_encrypt::(es, key, &nonce, buf, pos) + } #[cfg(feature = "3des")] EncryptionScheme::DesEde3Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), #[cfg(feature = "des-insecure")] @@ -188,8 +159,12 @@ pub fn decrypt_in_place<'a>( EncryptionScheme::Aes128Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), EncryptionScheme::Aes192Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), EncryptionScheme::Aes256Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), - EncryptionScheme::Aes128Gcm { nonce } => aes_128_gcm_decrypt(es, key, &nonce, buf), - EncryptionScheme::Aes256Gcm { nonce } => aes_256_gcm_decrypt(es, key, &nonce, buf), + EncryptionScheme::Aes128Gcm { nonce } => { + gcm_decrypt::(es, key, &nonce, buf) + } + EncryptionScheme::Aes256Gcm { nonce } => { + gcm_decrypt::(es, key, &nonce, buf) + } #[cfg(feature = "3des")] EncryptionScheme::DesEde3Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), #[cfg(feature = "des-insecure")] From 3222d462bed88df1394af1d99d9bc6274159571d Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Fri, 14 Jun 2024 11:28:33 -0400 Subject: [PATCH 5/9] Use U12 for where clause --- pkcs5/src/pbes2/encryption.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkcs5/src/pbes2/encryption.rs b/pkcs5/src/pbes2/encryption.rs index d15b51f30..f5925a67f 100644 --- a/pkcs5/src/pbes2/encryption.rs +++ b/pkcs5/src/pbes2/encryption.rs @@ -12,7 +12,7 @@ use pbkdf2::{ digest::{ block_buffer::Eager, core_api::{BlockSizeUser, BufferKindUser, FixedOutputCore, UpdateCore}, - typenum::{IsLess, Le, NonZero, UInt, UTerm, B0, B1, U12, U16, U256}, + typenum::{IsLess, Le, NonZero, U12, U16, U256}, HashMarker, }, EagerHash, @@ -58,7 +58,7 @@ fn gcm_encrypt<'a, C>( ) -> Result<&'a [u8]> where C: BlockCipher + BlockSizeUser + GcmKeyInit + BlockCipherEncrypt, - aes_gcm::AesGcm, B1>, B0>, B0>>: GcmKeyInit, + aes_gcm::AesGcm: GcmKeyInit, { const TAG_SIZE: usize = 16; const NONCE_SIZE: usize = 12; @@ -85,7 +85,7 @@ fn gcm_decrypt<'a, C>( ) -> Result<&'a [u8]> where C: BlockCipher + BlockSizeUser + GcmKeyInit + BlockCipherEncrypt, - aes_gcm::AesGcm, B1>, B0>, B0>>: GcmKeyInit, + aes_gcm::AesGcm: GcmKeyInit, { const TAG_SIZE: usize = 16; const NONCE_SIZE: usize = 12; From 603bbb4238b6e5ff320de2099193c761c270999b Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Fri, 14 Jun 2024 14:40:50 -0400 Subject: [PATCH 6/9] Apply suggestion from review --- pkcs5/src/pbes2/encryption.rs | 54 ++++++++++++++++------------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/pkcs5/src/pbes2/encryption.rs b/pkcs5/src/pbes2/encryption.rs index f5925a67f..26483d96d 100644 --- a/pkcs5/src/pbes2/encryption.rs +++ b/pkcs5/src/pbes2/encryption.rs @@ -49,61 +49,55 @@ fn cbc_decrypt<'a, C: BlockCipherDecrypt + BlockCipher + KeyInit>( .map_err(|_| Error::EncryptFailed) } -fn gcm_encrypt<'a, C>( +fn gcm_encrypt<'a, C, NonceSize, TagSize>( es: EncryptionScheme, key: EncryptionKey, - iv: &[u8], + nonce: Nonce, buffer: &'a mut [u8], pos: usize, ) -> Result<&'a [u8]> where C: BlockCipher + BlockSizeUser + GcmKeyInit + BlockCipherEncrypt, - aes_gcm::AesGcm: GcmKeyInit, + aes_gcm::AesGcm: GcmKeyInit, + TagSize: aes_gcm::TagSize, + NonceSize: aes::cipher::ArraySize, { - const TAG_SIZE: usize = 16; - const NONCE_SIZE: usize = 12; - - if buffer.len() < TAG_SIZE + pos { + if buffer.len() < TagSize::USIZE + pos { return Err(Error::EncryptFailed); } - let gcm = as GcmKeyInit>::new_from_slice(key.as_slice()) - .map_err(|_| es.to_alg_params_invalid())?; - let nonce: [u8; NONCE_SIZE] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; - let nonce = Nonce::from(nonce); + let gcm = + as GcmKeyInit>::new_from_slice(key.as_slice()) + .map_err(|_| es.to_alg_params_invalid())?; let tag = gcm .encrypt_in_place_detached(&nonce, &[], &mut buffer[..pos]) .map_err(|_| Error::EncryptFailed)?; buffer[pos..].copy_from_slice(tag.as_ref()); - Ok(&buffer[0..pos + TAG_SIZE]) + Ok(&buffer[0..pos + TagSize::USIZE]) } -fn gcm_decrypt<'a, C>( +fn gcm_decrypt<'a, C, NonceSize, TagSize>( es: EncryptionScheme, key: EncryptionKey, - iv: &[u8], + nonce: Nonce, buffer: &'a mut [u8], ) -> Result<&'a [u8]> where C: BlockCipher + BlockSizeUser + GcmKeyInit + BlockCipherEncrypt, aes_gcm::AesGcm: GcmKeyInit, + TagSize: aes_gcm::TagSize, + NonceSize: aes::cipher::ArraySize, { - const TAG_SIZE: usize = 16; - const NONCE_SIZE: usize = 12; - - let msg_len = if buffer.len() < TAG_SIZE { + let msg_len = if buffer.len() < TagSize::USIZE { return Err(Error::DecryptFailed); } else { - buffer.len() - TAG_SIZE + buffer.len() - TagSize::USIZE }; - let gcm = as GcmKeyInit>::new_from_slice(key.as_slice()) + let gcm = as GcmKeyInit>::new_from_slice(key.as_slice()) .map_err(|_| es.to_alg_params_invalid())?; - let nonce: [u8; NONCE_SIZE] = iv.try_into().map_err(|_| es.to_alg_params_invalid())?; - let nonce = Nonce::from(nonce); - let tag: [u8; TAG_SIZE] = buffer[msg_len..] - .try_into() - .map_err(|_| Error::DecryptFailed)?; - let tag = Tag::from(tag); + + let tag = Tag::try_from(&buffer[msg_len..]).map_err(|_| Error::DecryptFailed)?; + if gcm .decrypt_in_place_detached(&nonce, &[], &mut buffer[..msg_len], &tag) .is_err() @@ -132,10 +126,10 @@ pub fn encrypt_in_place<'b>( EncryptionScheme::Aes192Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), EncryptionScheme::Aes256Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), EncryptionScheme::Aes128Gcm { nonce } => { - gcm_encrypt::(es, key, &nonce, buf, pos) + gcm_encrypt::(es, key, Nonce::from(nonce), buf, pos) } EncryptionScheme::Aes256Gcm { nonce } => { - gcm_encrypt::(es, key, &nonce, buf, pos) + gcm_encrypt::(es, key, Nonce::from(nonce), buf, pos) } #[cfg(feature = "3des")] EncryptionScheme::DesEde3Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), @@ -160,10 +154,10 @@ pub fn decrypt_in_place<'a>( EncryptionScheme::Aes192Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), EncryptionScheme::Aes256Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), EncryptionScheme::Aes128Gcm { nonce } => { - gcm_decrypt::(es, key, &nonce, buf) + gcm_decrypt::(es, key, Nonce::from(nonce), buf) } EncryptionScheme::Aes256Gcm { nonce } => { - gcm_decrypt::(es, key, &nonce, buf) + gcm_decrypt::(es, key, Nonce::from(nonce), buf) } #[cfg(feature = "3des")] EncryptionScheme::DesEde3Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), From fc5ee24293e0ce59beeea1f629ec7a3544cfa379 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Fri, 14 Jun 2024 15:07:11 -0400 Subject: [PATCH 7/9] Fix a clippy --- pkcs5/src/pbes2/encryption.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkcs5/src/pbes2/encryption.rs b/pkcs5/src/pbes2/encryption.rs index 26483d96d..7b3fda668 100644 --- a/pkcs5/src/pbes2/encryption.rs +++ b/pkcs5/src/pbes2/encryption.rs @@ -49,13 +49,13 @@ fn cbc_decrypt<'a, C: BlockCipherDecrypt + BlockCipher + KeyInit>( .map_err(|_| Error::EncryptFailed) } -fn gcm_encrypt<'a, C, NonceSize, TagSize>( +fn gcm_encrypt( es: EncryptionScheme, key: EncryptionKey, nonce: Nonce, - buffer: &'a mut [u8], + buffer: &mut [u8], pos: usize, -) -> Result<&'a [u8]> +) -> Result<&[u8]> where C: BlockCipher + BlockSizeUser + GcmKeyInit + BlockCipherEncrypt, aes_gcm::AesGcm: GcmKeyInit, @@ -75,12 +75,12 @@ where Ok(&buffer[0..pos + TagSize::USIZE]) } -fn gcm_decrypt<'a, C, NonceSize, TagSize>( +fn gcm_decrypt( es: EncryptionScheme, key: EncryptionKey, nonce: Nonce, - buffer: &'a mut [u8], -) -> Result<&'a [u8]> + buffer: &mut [u8], +) -> Result<&[u8]> where C: BlockCipher + BlockSizeUser + GcmKeyInit + BlockCipherEncrypt, aes_gcm::AesGcm: GcmKeyInit, From 67ebe39c80968dfecdedf13222600628fbda0eec Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Fri, 14 Jun 2024 15:22:00 -0400 Subject: [PATCH 8/9] Apply suggestions from code review Co-authored-by: Arthur Gautier --- pkcs5/src/pbes2/encryption.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/pkcs5/src/pbes2/encryption.rs b/pkcs5/src/pbes2/encryption.rs index 7b3fda668..936c903c0 100644 --- a/pkcs5/src/pbes2/encryption.rs +++ b/pkcs5/src/pbes2/encryption.rs @@ -83,17 +83,13 @@ fn gcm_decrypt( ) -> Result<&[u8]> where C: BlockCipher + BlockSizeUser + GcmKeyInit + BlockCipherEncrypt, - aes_gcm::AesGcm: GcmKeyInit, + aes_gcm::AesGcm: GcmKeyInit, TagSize: aes_gcm::TagSize, NonceSize: aes::cipher::ArraySize, { - let msg_len = if buffer.len() < TagSize::USIZE { - return Err(Error::DecryptFailed); - } else { - buffer.len() - TagSize::USIZE - }; + let msg_len = buffer.len().checked_sub(TagSize::USIZE).ok_or{Error::DecryptFailed)?; - let gcm = as GcmKeyInit>::new_from_slice(key.as_slice()) + let gcm = as GcmKeyInit>::new_from_slice(key.as_slice()) .map_err(|_| es.to_alg_params_invalid())?; let tag = Tag::try_from(&buffer[msg_len..]).map_err(|_| Error::DecryptFailed)?; From f4109145589822cd685d87ea54d17c212a592ab5 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Fri, 14 Jun 2024 15:23:09 -0400 Subject: [PATCH 9/9] Fix typo, and fmt --- pkcs5/src/pbes2/encryption.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pkcs5/src/pbes2/encryption.rs b/pkcs5/src/pbes2/encryption.rs index 936c903c0..7a749158a 100644 --- a/pkcs5/src/pbes2/encryption.rs +++ b/pkcs5/src/pbes2/encryption.rs @@ -87,10 +87,14 @@ where TagSize: aes_gcm::TagSize, NonceSize: aes::cipher::ArraySize, { - let msg_len = buffer.len().checked_sub(TagSize::USIZE).ok_or{Error::DecryptFailed)?; + let msg_len = buffer + .len() + .checked_sub(TagSize::USIZE) + .ok_or(Error::DecryptFailed)?; - let gcm = as GcmKeyInit>::new_from_slice(key.as_slice()) - .map_err(|_| es.to_alg_params_invalid())?; + let gcm = + as GcmKeyInit>::new_from_slice(key.as_slice()) + .map_err(|_| es.to_alg_params_invalid())?; let tag = Tag::try_from(&buffer[msg_len..]).map_err(|_| Error::DecryptFailed)?;