Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 49 additions & 37 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions pkcs5/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ der = { version = "=0.6.0-pre.1", features = ["oid"], path = "../der" }
spki = { version = "=0.6.0-pre.0", path = "../spki" }

# optional dependencies
aes = { version = "0.7", optional = true }
block-modes = { version = "0.8", optional = true, default-features = false }
cbc = { version = "0.1", optional = true }
aes = { version = "0.8", optional = true, default-features = false }
des = { version = "0.8", optional = true, default-features = false }
hmac = { version = "0.12", optional = true, default-features = false }
pbkdf2 = { version = "0.10", optional = true, default-features = false }
scrypt = { version = "0.8", optional = true, default-features = false }
sha-1 = { version = "0.10", optional = true, default-features = false }
sha2 = { version = "0.10", optional = true, default-features = false }
des = { version = "0.7", optional = true, default-features = false }

[dev-dependencies]
hex-literal = "0.3"
Expand All @@ -35,7 +35,7 @@ hex-literal = "0.3"
alloc = []
3des = ["pbes2", "des"]
des-insecure = ["pbes2", "des"]
pbes2 = ["aes", "block-modes", "hmac", "pbkdf2", "scrypt", "sha2"]
pbes2 = ["aes", "cbc", "hmac", "pbkdf2", "scrypt", "sha2"]
sha1 = ["pbes2", "sha-1"]

[package.metadata.docs.rs]
Expand Down
110 changes: 41 additions & 69 deletions pkcs5/src/pbes2/encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

use super::{EncryptionScheme, Kdf, Parameters, Pbkdf2Params, Pbkdf2Prf, ScryptParams};
use crate::{Error, Result};
use block_modes::{block_padding::Pkcs7, BlockMode, Cbc};
use cbc::cipher::{
block_padding::Pkcs7, BlockCipher, BlockDecryptMut, BlockEncryptMut, KeyInit, KeyIvInit,
};
use hmac::{
digest::{
block_buffer::Eager,
Expand All @@ -15,62 +17,53 @@ use hmac::{
use pbkdf2::pbkdf2;
use scrypt::scrypt;

type Aes128Cbc = Cbc<aes::Aes128, Pkcs7>;
type Aes192Cbc = Cbc<aes::Aes192, Pkcs7>;
type Aes256Cbc = Cbc<aes::Aes256, Pkcs7>;

#[cfg(feature = "des-insecure")]
type DesCbc = Cbc<des::Des, Pkcs7>;
#[cfg(feature = "3des")]
type DesEde3Cbc = Cbc<des::TdesEde3, Pkcs7>;

/// Maximum size of a derived encryption key
const MAX_KEY_LEN: usize = 32;

fn cbc_encrypt<'a, C: BlockEncryptMut + BlockCipher + KeyInit>(
es: EncryptionScheme<'_>,
key: EncryptionKey,
iv: &[u8],
buffer: &'a mut [u8],
pos: usize,
) -> Result<&'a [u8]> {
cbc::Encryptor::<C>::new_from_slices(key.as_slice(), iv)
.map_err(|_| es.to_alg_params_invalid())?
.encrypt_padded_mut::<Pkcs7>(buffer, pos)
.map_err(|_| Error::EncryptFailed)
}

fn cbc_decrypt<'a, C: BlockDecryptMut + BlockCipher + KeyInit>(
es: EncryptionScheme<'_>,
key: EncryptionKey,
iv: &[u8],
buffer: &'a mut [u8],
) -> Result<&'a [u8]> {
cbc::Decryptor::<C>::new_from_slices(key.as_slice(), iv)
.map_err(|_| es.to_alg_params_invalid())?
.decrypt_padded_mut::<Pkcs7>(buffer)
.map_err(|_| Error::EncryptFailed)
}

pub fn encrypt_in_place<'b>(
params: &Parameters<'_>,
password: impl AsRef<[u8]>,
buffer: &'b mut [u8],
buf: &'b mut [u8],
pos: usize,
) -> Result<&'b [u8]> {
let es = params.encryption;
let key_size = es.key_size();
if key_size > MAX_KEY_LEN {
return Err(es.to_alg_params_invalid());
}
let encryption_key =
EncryptionKey::derive_from_password(password.as_ref(), &params.kdf, key_size)?;
let key = EncryptionKey::derive_from_password(password.as_ref(), &params.kdf, key_size)?;

match es {
EncryptionScheme::Aes128Cbc { iv } => {
let cipher = Aes128Cbc::new_from_slices(encryption_key.as_slice(), iv)
.map_err(|_| es.to_alg_params_invalid())?;
cipher
.encrypt(buffer, pos)
.map_err(|_| Error::EncryptFailed)
}
EncryptionScheme::Aes192Cbc { iv } => {
let cipher = Aes192Cbc::new_from_slices(encryption_key.as_slice(), iv)
.map_err(|_| es.to_alg_params_invalid())?;
cipher
.encrypt(buffer, pos)
.map_err(|_| Error::EncryptFailed)
}
EncryptionScheme::Aes256Cbc { iv } => {
let cipher = Aes256Cbc::new_from_slices(encryption_key.as_slice(), iv)
.map_err(|_| es.to_alg_params_invalid())?;
cipher
.encrypt(buffer, pos)
.map_err(|_| Error::EncryptFailed)
}
EncryptionScheme::Aes128Cbc { iv } => cbc_encrypt::<aes::Aes128Enc>(es, key, iv, buf, pos),
EncryptionScheme::Aes192Cbc { iv } => cbc_encrypt::<aes::Aes192Enc>(es, key, iv, buf, pos),
EncryptionScheme::Aes256Cbc { iv } => cbc_encrypt::<aes::Aes256Enc>(es, key, iv, buf, pos),
#[cfg(feature = "3des")]
EncryptionScheme::DesEde3Cbc { iv } => {
let cipher = DesEde3Cbc::new_from_slices(encryption_key.as_slice(), iv)
.map_err(|_| es.to_alg_params_invalid())?;
cipher
.encrypt(buffer, pos)
.map_err(|_| Error::EncryptFailed)
}
EncryptionScheme::DesEde3Cbc { iv } => cbc_encrypt::<des::TdesEde3>(es, key, iv, buf, pos),
#[cfg(feature = "des-insecure")]
EncryptionScheme::DesCbc { .. } => Err(Error::UnsupportedAlgorithm {
oid: super::DES_CBC_OID,
Expand All @@ -82,40 +75,19 @@ pub fn encrypt_in_place<'b>(
pub fn decrypt_in_place<'a>(
params: &Parameters<'_>,
password: impl AsRef<[u8]>,
buffer: &'a mut [u8],
buf: &'a mut [u8],
) -> Result<&'a [u8]> {
let es = params.encryption;
let encryption_key =
EncryptionKey::derive_from_password(password.as_ref(), &params.kdf, es.key_size())?;
let key = EncryptionKey::derive_from_password(password.as_ref(), &params.kdf, es.key_size())?;

match es {
EncryptionScheme::Aes128Cbc { iv } => {
let cipher = Aes128Cbc::new_from_slices(encryption_key.as_slice(), iv)
.map_err(|_| es.to_alg_params_invalid())?;
cipher.decrypt(buffer).map_err(|_| Error::DecryptFailed)
}
EncryptionScheme::Aes192Cbc { iv } => {
let cipher = Aes192Cbc::new_from_slices(encryption_key.as_slice(), iv)
.map_err(|_| es.to_alg_params_invalid())?;
cipher.decrypt(buffer).map_err(|_| Error::DecryptFailed)
}
EncryptionScheme::Aes256Cbc { iv } => {
let cipher = Aes256Cbc::new_from_slices(encryption_key.as_slice(), iv)
.map_err(|_| es.to_alg_params_invalid())?;
cipher.decrypt(buffer).map_err(|_| Error::DecryptFailed)
}
EncryptionScheme::Aes128Cbc { iv } => cbc_decrypt::<aes::Aes128Dec>(es, key, iv, buf),
EncryptionScheme::Aes192Cbc { iv } => cbc_decrypt::<aes::Aes192Dec>(es, key, iv, buf),
EncryptionScheme::Aes256Cbc { iv } => cbc_decrypt::<aes::Aes256Dec>(es, key, iv, buf),
#[cfg(feature = "3des")]
EncryptionScheme::DesEde3Cbc { iv } => {
let cipher = DesEde3Cbc::new_from_slices(encryption_key.as_slice(), iv)
.map_err(|_| es.to_alg_params_invalid())?;
cipher.decrypt(buffer).map_err(|_| Error::DecryptFailed)
}
EncryptionScheme::DesEde3Cbc { iv } => cbc_decrypt::<des::TdesEde3>(es, key, iv, buf),
#[cfg(feature = "des-insecure")]
EncryptionScheme::DesCbc { iv } => {
let cipher = DesCbc::new_from_slices(encryption_key.as_slice(), iv)
.map_err(|_| es.to_alg_params_invalid())?;
cipher.decrypt(buffer).map_err(|_| Error::DecryptFailed)
}
EncryptionScheme::DesCbc { iv } => cbc_decrypt::<des::Des>(es, key, iv, buf),
}
}

Expand Down