summaryrefslogtreecommitdiffstats
path: root/openpgp/src
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp/src')
-rw-r--r--openpgp/src/crypto/backend/cng/symmetric.rs65
-rw-r--r--openpgp/src/crypto/backend/nettle/symmetric.rs239
-rw-r--r--openpgp/src/crypto/ecdh.rs16
-rw-r--r--openpgp/src/crypto/symmetric.rs61
-rw-r--r--openpgp/src/packet/skesk.rs12
5 files changed, 194 insertions, 199 deletions
diff --git a/openpgp/src/crypto/backend/cng/symmetric.rs b/openpgp/src/crypto/backend/cng/symmetric.rs
index d3215eec..27694f52 100644
--- a/openpgp/src/crypto/backend/cng/symmetric.rs
+++ b/openpgp/src/crypto/backend/cng/symmetric.rs
@@ -3,21 +3,34 @@ use std::sync::Mutex;
use win_crypto_ng::symmetric as cng;
+use crate::crypto::mem::Protected;
use crate::crypto::symmetric::Mode;
use crate::{Error, Result};
use crate::types::SymmetricAlgorithm;
+struct KeyWrapper {
+ key: Mutex<cng::SymmetricAlgorithmKey>,
+ iv: Option<Protected>,
+}
+
+impl KeyWrapper {
+ fn new(key: cng::SymmetricAlgorithmKey, iv: Option<Vec<u8>>) -> KeyWrapper {
+ KeyWrapper {
+ key: Mutex::new(key),
+ iv: iv.map(|iv| iv.into()),
+ }
+ }
+}
-impl Mode for Mutex<cng::SymmetricAlgorithmKey> {
+impl Mode for KeyWrapper {
fn block_size(&self) -> usize {
- self.lock().expect("Mutex not to be poisoned")
+ self.key.lock().expect("Mutex not to be poisoned")
.block_size().expect("CNG not to fail internally")
}
fn encrypt(
&mut self,
- iv: &mut [u8],
dst: &mut [u8],
src: &[u8],
) -> Result<()> {
@@ -36,16 +49,14 @@ impl Mode for Mutex<cng::SymmetricAlgorithmKey> {
};
let len = std::cmp::min(src.len(), dst.len());
- // NOTE: `None` IV is required for ECB mode but we don't ever use it.
let buffer = cng::SymmetricAlgorithmKey::encrypt(
- &*self.lock().expect("Mutex not to be poisoned"),
- Some(iv), src, None)?;
+ &*self.key.lock().expect("Mutex not to be poisoned"),
+ self.iv.as_deref_mut(), src, None)?;
Ok(dst[..len].copy_from_slice(&buffer.as_slice()[..len]))
}
fn decrypt(
&mut self,
- iv: &mut [u8],
dst: &mut [u8],
src: &[u8],
) -> Result<()> {
@@ -64,10 +75,9 @@ impl Mode for Mutex<cng::SymmetricAlgorithmKey> {
};
let len = std::cmp::min(src.len(), dst.len());
- // NOTE: `None` IV is required for ECB mode but we don't ever use it.
let buffer = cng::SymmetricAlgorithmKey::decrypt(
- &*self.lock().expect("Mutex not to be poisoned"),
- Some(iv), src, None)?;
+ &*self.key.lock().expect("Mutex not to be poisoned"),
+ self.iv.as_deref_mut(), src, None)?;
dst[..len].copy_from_slice(&buffer.as_slice()[..len]);
Ok(())
@@ -149,7 +159,7 @@ impl SymmetricAlgorithm {
}
/// Creates a symmetric cipher context for encrypting in CFB mode.
- pub(crate) fn make_encrypt_cfb(self, key: &[u8]) -> Result<Box<dyn Mode>> {
+ pub(crate) fn make_encrypt_cfb(self, key: &[u8], iv: Vec<u8>) -> Result<Box<dyn Mode>> {
let (algo, _) = TryFrom::try_from(self)?;
let algo = cng::SymmetricAlgorithm::open(algo, cng::ChainingMode::Cfb)?;
@@ -158,37 +168,26 @@ impl SymmetricAlgorithm {
// set to 8-bit CFB)
key.set_msg_block_len(key.block_size()?)?;
- Ok(Box::new(Mutex::new(key)))
+ Ok(Box::new(KeyWrapper::new(key, Some(iv))))
}
/// Creates a symmetric cipher context for decrypting in CFB mode.
- pub(crate) fn make_decrypt_cfb(self, key: &[u8]) -> Result<Box<dyn Mode>> {
- Self::make_encrypt_cfb(self, key)
+ pub(crate) fn make_decrypt_cfb(self, key: &[u8], iv: Vec<u8>) -> Result<Box<dyn Mode>> {
+ Self::make_encrypt_cfb(self, key, iv)
}
- /// Creates a Nettle context for encrypting in CBC mode.
- pub(crate) fn make_encrypt_cbc(self, key: &[u8]) -> Result<Box<dyn Mode>> {
+ /// Creates a symmetric cipher context for encrypting in ECB mode.
+ pub(crate) fn make_encrypt_ecb(self, key: &[u8]) -> Result<Box<dyn Mode>> {
let (algo, _) = TryFrom::try_from(self)?;
- let algo = cng::SymmetricAlgorithm::open(algo, cng::ChainingMode::Cbc)?;
+ let algo = cng::SymmetricAlgorithm::open(algo, cng::ChainingMode::Ecb)?;
+ let key = algo.new_key(key)?;
- Ok(Box::new(Mutex::new(
- algo.new_key(key).expect(
- "CNG to successfully create a symmetric key for valid/supported algorithm"
- )
- )))
+ Ok(Box::new(KeyWrapper::new(key, None)))
}
- /// Creates a Nettle context for decrypting in CBC mode.
- pub(crate) fn make_decrypt_cbc(self, key: &[u8]) -> Result<Box<dyn Mode>> {
- let (algo, _) = TryFrom::try_from(self)?;
-
- let algo = cng::SymmetricAlgorithm::open(algo, cng::ChainingMode::Cbc)?;
-
- Ok(Box::new(Mutex::new(
- algo.new_key(key).expect(
- "CNG to successfully create a symmetric key for valid/supported algorithm"
- )
- )))
+ /// Creates a symmetric cipher context for decrypting in ECB mode.
+ pub(crate) fn make_decrypt_ecb(self, key: &[u8]) -> Result<Box<dyn Mode>> {
+ Self::make_encrypt_ecb(self, key)
}
}
diff --git a/openpgp/src/crypto/backend/nettle/symmetric.rs b/openpgp/src/crypto/backend/nettle/symmetric.rs
index 8ce4cdc6..72acae58 100644
--- a/openpgp/src/crypto/backend/nettle/symmetric.rs
+++ b/openpgp/src/crypto/backend/nettle/symmetric.rs
@@ -1,34 +1,81 @@
use nettle::cipher::{self, Cipher};
use nettle::mode::{self};
+use crate::crypto::mem::Protected;
use crate::crypto::symmetric::Mode;
use crate::{Error, Result};
use crate::types::SymmetricAlgorithm;
-impl<T: nettle::mode::Mode + Send + Sync> Mode for T {
+struct ModeWrapper<M>
+{
+ mode: M,
+ iv: Protected,
+}
+
+impl<M> ModeWrapper<M>
+where
+ M: nettle::mode::Mode + Send + Sync + 'static,
+{
+ fn new(mode: M, iv: Vec<u8>) -> Box<dyn Mode> {
+ Box::new(ModeWrapper {
+ mode,
+ iv: iv.into(),
+ })
+ }
+}
+
+impl<M> Mode for ModeWrapper<M>
+where
+ M: nettle::mode::Mode + Send + Sync,
+{
+ fn block_size(&self) -> usize {
+ self.mode.block_size()
+ }
+
+ fn encrypt(
+ &mut self,
+ dst: &mut [u8],
+ src: &[u8],
+ ) -> Result<()> {
+ self.mode.encrypt(&mut self.iv, dst, src)?;
+ Ok(())
+ }
+
+ fn decrypt(
+ &mut self,
+ dst: &mut [u8],
+ src: &[u8],
+ ) -> Result<()> {
+ self.mode.decrypt(&mut self.iv, dst, src)?;
+ Ok(())
+ }
+}
+
+impl<C> Mode for C
+where
+ C: Cipher + Send + Sync,
+{
fn block_size(&self) -> usize {
- self.block_size()
+ C::BLOCK_SIZE
}
fn encrypt(
&mut self,
- iv: &mut [u8],
dst: &mut [u8],
src: &[u8],
) -> Result<()> {
- self.encrypt(iv, dst, src)
- .map_err(Into::into)
+ self.encrypt(dst, src);
+ Ok(())
}
fn decrypt(
&mut self,
- iv: &mut [u8],
dst: &mut [u8],
src: &[u8],
) -> Result<()> {
- self.decrypt(iv, dst, src)
- .map_err(Into::into)
+ self.decrypt(dst, src);
+ Ok(())
}
}
@@ -99,150 +146,110 @@ impl SymmetricAlgorithm {
}
/// Creates a Nettle context for encrypting in CFB mode.
- pub(crate) fn make_encrypt_cfb(self, key: &[u8]) -> Result<Box<dyn Mode>> {
+ pub(crate) fn make_encrypt_cfb(self, key: &[u8], iv: Vec<u8>) -> Result<Box<dyn Mode>> {
match self {
SymmetricAlgorithm::TripleDES =>
- Ok(Box::new(
- mode::Cfb::<cipher::Des3>::with_encrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Des3>::with_encrypt_key(key)?, iv)),
SymmetricAlgorithm::CAST5 =>
- Ok(Box::new(
- mode::Cfb::<cipher::Cast128>::with_encrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Cast128>::with_encrypt_key(key)?, iv)),
SymmetricAlgorithm::Blowfish =>
- Ok(Box::new(
- mode::Cfb::<cipher::Blowfish>::with_encrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Blowfish>::with_encrypt_key(key)?, iv)),
SymmetricAlgorithm::AES128 =>
- Ok(Box::new(
- mode::Cfb::<cipher::Aes128>::with_encrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Aes128>::with_encrypt_key(key)?, iv)),
SymmetricAlgorithm::AES192 =>
- Ok(Box::new(
- mode::Cfb::<cipher::Aes192>::with_encrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Aes192>::with_encrypt_key(key)?, iv)),
SymmetricAlgorithm::AES256 =>
- Ok(Box::new(
- mode::Cfb::<cipher::Aes256>::with_encrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Aes256>::with_encrypt_key(key)?, iv)),
SymmetricAlgorithm::Twofish =>
- Ok(Box::new(
- mode::Cfb::<cipher::Twofish>::with_encrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Twofish>::with_encrypt_key(key)?, iv)),
SymmetricAlgorithm::Camellia128 =>
- Ok(Box::new(
- mode::Cfb::<cipher::Camellia128>::with_encrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Camellia128>::with_encrypt_key(key)?, iv)),
SymmetricAlgorithm::Camellia192 =>
- Ok(Box::new(
- mode::Cfb::<cipher::Camellia192>::with_encrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Camellia192>::with_encrypt_key(key)?, iv)),
SymmetricAlgorithm::Camellia256 =>
- Ok(Box::new(
- mode::Cfb::<cipher::Camellia256>::with_encrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Camellia256>::with_encrypt_key(key)?, iv)),
_ => Err(Error::UnsupportedSymmetricAlgorithm(self).into()),
}
}
/// Creates a Nettle context for decrypting in CFB mode.
- pub(crate) fn make_decrypt_cfb(self, key: &[u8]) -> Result<Box<dyn Mode>> {
+ pub(crate) fn make_decrypt_cfb(self, key: &[u8], iv: Vec<u8>) -> Result<Box<dyn Mode>> {
match self {
SymmetricAlgorithm::TripleDES =>
- Ok(Box::new(
- mode::Cfb::<cipher::Des3>::with_decrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Des3>::with_decrypt_key(key)?, iv)),
SymmetricAlgorithm::CAST5 =>
- Ok(Box::new(
- mode::Cfb::<cipher::Cast128>::with_decrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Cast128>::with_decrypt_key(key)?, iv)),
SymmetricAlgorithm::Blowfish =>
- Ok(Box::new(
- mode::Cfb::<cipher::Blowfish>::with_decrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Blowfish>::with_decrypt_key(key)?, iv)),
SymmetricAlgorithm::AES128 =>
- Ok(Box::new(
- mode::Cfb::<cipher::Aes128>::with_decrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Aes128>::with_decrypt_key(key)?, iv)),
SymmetricAlgorithm::AES192 =>
- Ok(Box::new(
- mode::Cfb::<cipher::Aes192>::with_decrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Aes192>::with_decrypt_key(key)?, iv)),
SymmetricAlgorithm::AES256 =>
- Ok(Box::new(
- mode::Cfb::<cipher::Aes256>::with_decrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Aes256>::with_decrypt_key(key)?, iv)),
SymmetricAlgorithm::Twofish =>
- Ok(Box::new(
- mode::Cfb::<cipher::Twofish>::with_decrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Twofish>::with_decrypt_key(key)?, iv)),
SymmetricAlgorithm::Camellia128 =>
- Ok(Box::new(
- mode::Cfb::<cipher::Camellia128>::with_decrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Camellia128>::with_decrypt_key(key)?, iv)),
SymmetricAlgorithm::Camellia192 =>
- Ok(Box::new(
- mode::Cfb::<cipher::Camellia192>::with_decrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Camellia192>::with_decrypt_key(key)?, iv)),
SymmetricAlgorithm::Camellia256 =>
- Ok(Box::new(
- mode::Cfb::<cipher::Camellia256>::with_decrypt_key(&key[..])?)),
+ Ok(ModeWrapper::new(
+ mode::Cfb::<cipher::Camellia256>::with_decrypt_key(key)?, iv)),
_ => Err(Error::UnsupportedSymmetricAlgorithm(self).into())
}
}
- /// Creates a Nettle context for encrypting in CBC mode.
- pub(crate) fn make_encrypt_cbc(self, key: &[u8]) -> Result<Box<dyn Mode>> {
+ /// Creates a Nettle context for encrypting in ECB mode.
+ pub(crate) fn make_encrypt_ecb(self, key: &[u8]) -> Result<Box<dyn Mode>> {
match self {
- SymmetricAlgorithm::TripleDES =>
- Ok(Box::new(
- mode::Cbc::<cipher::Des3>::with_encrypt_key(&key[..])?)),
- SymmetricAlgorithm::CAST5 =>
- Ok(Box::new(
- mode::Cbc::<cipher::Cast128>::with_encrypt_key(&key[..])?)),
- SymmetricAlgorithm::Blowfish =>
- Ok(Box::new(
- mode::Cbc::<cipher::Blowfish>::with_encrypt_key(&key[..])?)),
- SymmetricAlgorithm::AES128 =>
- Ok(Box::new(
- mode::Cbc::<cipher::Aes128>::with_encrypt_key(&key[..])?)),
- SymmetricAlgorithm::AES192 =>
- Ok(Box::new(
- mode::Cbc::<cipher::Aes192>::with_encrypt_key(&key[..])?)),
- SymmetricAlgorithm::AES256 =>
- Ok(Box::new(
- mode::Cbc::<cipher::Aes256>::with_encrypt_key(&key[..])?)),
- SymmetricAlgorithm::Twofish =>
- Ok(Box::new(
- mode::Cbc::<cipher::Twofish>::with_encrypt_key(&key[..])?)),
- SymmetricAlgorithm::Camellia128 =>
- Ok(Box::new(
- mode::Cbc::<cipher::Camellia128>::with_encrypt_key(&key[..])?)),
- SymmetricAlgorithm::Camellia192 =>
- Ok(Box::new(
- mode::Cbc::<cipher::Camellia192>::with_encrypt_key(&key[..])?)),
- SymmetricAlgorithm::Camellia256 =>
- Ok(Box::new(
- mode::Cbc::<cipher::Camellia256>::with_encrypt_key(&key[..])?)),
- _ => Err(Error::UnsupportedSymmetricAlgorithm(self).into()),
+ SymmetricAlgorithm::TripleDES => Ok(Box::new(cipher::Des3::with_encrypt_key(key)?)),
+ SymmetricAlgorithm::CAST5 => Ok(Box::new(cipher::Cast128::with_encrypt_key(key)?)),
+ SymmetricAlgorithm::Blowfish => Ok(Box::new(cipher::Blowfish::with_encrypt_key(key)?)),
+ SymmetricAlgorithm::AES128 => Ok(Box::new(cipher::Aes128::with_encrypt_key(key)?)),
+ SymmetricAlgorithm::AES192 => Ok(Box::new(cipher::Aes192::with_encrypt_key(key)?)),
+ SymmetricAlgorithm::AES256 => Ok(Box::new(cipher::Aes256::with_encrypt_key(key)?)),
+ SymmetricAlgorithm::Twofish => Ok(Box::new(cipher::Twofish::with_encrypt_key(key)?)),
+ SymmetricAlgorithm::Camellia128 => Ok(Box::new(cipher::Camellia128::with_encrypt_key(key)?)),
+ SymmetricAlgorithm::Camellia192 => Ok(Box::new(cipher::Camellia192::with_encrypt_key(key)?)),
+ SymmetricAlgorithm::Camellia256 => Ok(Box::new(cipher::Camellia256::with_encrypt_key(key)?)),
+ _ => Err(Error::UnsupportedSymmetricAlgorithm(self).into())
}
}
- /// Creates a Nettle context for decrypting in CBC mode.
- pub(crate) fn make_decrypt_cbc(self, key: &[u8]) -> Result<Box<dyn Mode>> {
+ /// Creates a Nettle context for decrypting in ECB mode.
+ pub(crate) fn make_decrypt_ecb(self, key: &[u8]) -> Result<Box<dyn Mode>> {
match self {
- SymmetricAlgorithm::TripleDES =>
- Ok(Box::new(
- mode::Cbc::<cipher::Des3>::with_decrypt_key(&key[..])?)),
- SymmetricAlgorithm::CAST5 =>
- Ok(Box::new(
- mode::Cbc::<cipher::Cast128>::with_decrypt_key(&key[..])?)),
- SymmetricAlgorithm::Blowfish =>
- Ok(Box::new(
- mode::Cbc::<cipher::Blowfish>::with_decrypt_key(&key[..])?)),
- SymmetricAlgorithm::AES128 =>
- Ok(Box::new(
- mode::Cbc::<cipher::Aes128>::with_decrypt_key(&key[..])?)),
- SymmetricAlgorithm::AES192 =>
- Ok(Box::new(
- mode::Cbc::<cipher::Aes192>::with_decrypt_key(&key[..])?)),
- SymmetricAlgorithm::AES256 =>
- Ok(Box::new(
- mode::Cbc::<cipher::Aes256>::with_decrypt_key(&key[..])?)),
- SymmetricAlgorithm::Twofish =>
- Ok(Box::new(
- mode::Cbc::<cipher::Twofish>::with_decrypt_key(&key[..])?)),
- SymmetricAlgorithm::Camellia128 =>
- Ok(Box::new(
- mode::Cbc::<cipher::Camellia128>::with_decrypt_key(&key[..])?)),
- SymmetricAlgorithm::Camellia192 =>
- Ok(Box::new(
- mode::Cbc::<cipher::Camellia192>::with_decrypt_key(&key[..])?)),
- SymmetricAlgorithm::Camellia256 =>
- Ok(Box::new(
- mode::Cbc::<cipher::Camellia256>::with_decrypt_key(&key[..])?)),
- _ => Err(Error::UnsupportedSymmetricAlgorithm(self).into()),
+ SymmetricAlgorithm::TripleDES => Ok(Box::new(cipher::Des3::with_decrypt_key(key)?)),
+ SymmetricAlgorithm::CAST5 => Ok(Box::new(cipher::Cast128::with_decrypt_key(key)?)),
+ SymmetricAlgorithm::Blowfish => Ok(Box::new(cipher::Blowfish::with_decrypt_key(key)?)),
+ SymmetricAlgorithm::AES128 => Ok(Box::new(cipher::Aes128::with_decrypt_key(key)?)),
+ SymmetricAlgorithm::AES192 => Ok(Box::new(cipher::Aes192::with_decrypt_key(key)?)),
+ SymmetricAlgorithm::AES256 => Ok(Box::new(cipher::Aes256::with_decrypt_key(key)?)),
+ SymmetricAlgorithm::Twofish => Ok(Box::new(cipher::Twofish::with_decrypt_key(key)?)),
+ SymmetricAlgorithm::Camellia128 => Ok(Box::new(cipher::Camellia128::with_decrypt_key(key)?)),
+ SymmetricAlgorithm::Camellia192 => Ok(Box::new(cipher::Camellia192::with_decrypt_key(key)?)),
+ SymmetricAlgorithm::Camellia256 => Ok(Box::new(cipher::Camellia256::with_decrypt_key(key)?)),
+ _ => Err(Error::UnsupportedSymmetricAlgorithm(self).into())
}
}
}
diff --git a/openpgp/src/crypto/ecdh.rs b/openpgp/src/crypto/ecdh.rs
index 84b8660e..5ed7c203 100644
--- a/openpgp/src/crypto/ecdh.rs
+++ b/openpgp/src/crypto/ecdh.rs
@@ -209,10 +209,8 @@ fn aes_key_wrap(algo: SymmetricAlgorithm, key: &Protected,
return Err(Error::InvalidArgument("Bad key size".into()).into());
}
- // We need ECB for the algorithm. However, there is no nettle::Mode:ECB,
- // so to work around this, we use CBC, and always use an all-zero IV.
let mut cipher = match algo {
- AES128 | AES192 | AES256 => algo.make_encrypt_cbc(key)?,
+ AES128 | AES192 | AES256 => algo.make_encrypt_ecb(key)?,
_ => return Err(Error::UnsupportedSymmetricAlgorithm(algo).into()),
};
@@ -235,7 +233,6 @@ fn aes_key_wrap(algo: SymmetricAlgorithm, key: &Protected,
let mut b = [0; 16];
let mut tmp = [0; 16];
- let mut iv: Protected = vec![0; cipher.block_size()].into();
// 2) Calculate intermediate values.
@@ -246,8 +243,7 @@ fn aes_key_wrap(algo: SymmetricAlgorithm, key: &Protected,
// B = AES(K, A | R[i])
write_be_u64(&mut tmp[..8], a);
&mut tmp[8..].copy_from_slice(&r[8 * i..8 * (i + 1)]);
- iv.iter_mut().for_each(|p| *p = 0); // Turn CBC into ECB.
- cipher.encrypt(&mut iv, &mut b, &tmp)?;
+ cipher.encrypt(&mut b, &tmp)?;
// A = MSB(64, B) ^ t where t = (n*j)+i
a = read_be_u64(&b[..8]) ^ ((n * j) + i + 1) as u64;
@@ -288,10 +284,8 @@ fn aes_key_unwrap(algo: SymmetricAlgorithm, key: &Protected,
return Err(Error::InvalidArgument("Bad key size".into()).into());
}
- // We need ECB for the algorithm. However, there is no nettle::Mode:ECB,
- // so to work around this, we use CBC, and always use an all-zero IV.
let mut cipher = match algo {
- AES128 | AES192 | AES256 => algo.make_decrypt_cbc(key)?,
+ AES128 | AES192 | AES256 => algo.make_decrypt_ecb(key)?,
_ => return Err(Error::UnsupportedSymmetricAlgorithm(algo).into()),
};
@@ -316,7 +310,6 @@ fn aes_key_unwrap(algo: SymmetricAlgorithm, key: &Protected,
let mut b = [0; 16];
let mut tmp = [0; 16];
- let mut iv: Protected = vec![0; cipher.block_size()].into();
// For j = 5 to 0
for j in (0..=5).rev() {
@@ -327,8 +320,7 @@ fn aes_key_unwrap(algo: SymmetricAlgorithm, key: &Protected,
&mut tmp[8..].copy_from_slice(&r[8 * i..8 * (i + 1)]);
// (Note that our i runs from n-1 to 0 instead of n to
// 1, hence the index shift.
- iv.iter_mut().for_each(|p| *p = 0); // Turn CBC into ECB.
- cipher.decrypt(&mut iv, &mut b, &tmp)?;
+ cipher.decrypt(&mut b, &tmp)?;
// A = MSB(64, B)
a = read_be_u64(&b[..8]);
diff --git a/openpgp/src/crypto/symmetric.rs b/openpgp/src/crypto/symmetric.rs
index 381cbe95..2c2ccab3 100644
--- a/openpgp/src/crypto/symmetric.rs
+++ b/openpgp/src/crypto/symmetric.rs
@@ -17,24 +17,20 @@ pub(crate) trait Mode: Send + Sync {
/// Block size of the underlying cipher in bytes.
fn block_size(&self) -> usize;
- /// Encrypt a single block `src` using the initialization vector `iv` to
- /// a ciphertext block `dst`. Both `iv` and dst` are updated.
- /// The buffer `iv`, `dst` and `src` are expected to be at least as large as
+ /// Encrypt a single block `src` to a ciphertext block `dst`.
+ /// The `dst` and `src` buffers are expected to be at least as large as
/// the block size of the underlying cipher.
fn encrypt(
&mut self,
- iv: &mut [u8],
dst: &mut [u8],
src: &[u8],
) -> Result<()>;
- /// Decrypt a single ciphertext block `src` using the initialization vector
- /// `iv` to a plaintext block `dst`. Both `iv` and dst` are updated.
- /// The buffer `iv`, `dst` and `src` are expected to be at least as large as
+ /// Decrypt a single ciphertext block `src` to a plaintext block `dst`.
+ /// The `dst` and `src` buffers are expected to be at least as large as
/// the block size of the underlying cipher.
fn decrypt(
&mut self,
- iv: &mut [u8],
dst: &mut [u8],
src: &[u8],
) -> Result<()>;
@@ -47,7 +43,6 @@ pub struct Decryptor<R: io::Read> {
dec: Box<dyn Mode>,
block_size: usize,
- iv: Vec<u8>,
// Up to a block of unread data.
buffer: Vec<u8>,
}
@@ -57,14 +52,14 @@ impl<R: io::Read> Decryptor<R> {
/// Instantiate a new symmetric decryptor. `reader` is the source
/// to wrap.
pub fn new(algo: SymmetricAlgorithm, key: &[u8], source: R) -> Result<Self> {
- let dec = algo.make_decrypt_cfb(key)?;
let block_size = algo.block_size()?;
+ let iv = vec![0; block_size];
+ let dec = algo.make_decrypt_cfb(key, iv)?;
Ok(Decryptor {
source,
dec,
block_size,
- iv: vec![0u8; block_size],
buffer: Vec::with_capacity(block_size),
})
}
@@ -140,8 +135,7 @@ impl<R: io::Read> io::Read for Decryptor<R> {
Err(e) => return Err(e),
}
- self.dec.decrypt(&mut self.iv,
- &mut plaintext[pos..pos + to_copy],
+ self.dec.decrypt(&mut plaintext[pos..pos + to_copy],
&ciphertext[..])
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput,
format!("{}", e)))?;
@@ -179,7 +173,7 @@ impl<R: io::Read> io::Read for Decryptor<R> {
}
vec_truncate(&mut self.buffer, ciphertext.len());
- self.dec.decrypt(&mut self.iv, &mut self.buffer, &ciphertext[..])
+ self.dec.decrypt(&mut self.buffer, &ciphertext[..])
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput,
format!("{}", e)))?;
@@ -312,7 +306,6 @@ pub struct Encryptor<W: io::Write> {
cipher: Box<dyn Mode>,
block_size: usize,
- iv: Vec<u8>,
// Up to a block of unencrypted data.
buffer: Vec<u8>,
// A place to write encrypted data into.
@@ -323,8 +316,9 @@ assert_send_and_sync!(Encryptor<W> where W: io::Write);
impl<W: io::Write> Encryptor<W> {
/// Instantiate a new symmetric encryptor.
pub fn new(algo: SymmetricAlgorithm, key: &[u8], sink: W) -> Result<Self> {
- let cipher = algo.make_encrypt_cfb(key)?;
let block_size = algo.block_size()?;
+ let iv = vec![0; block_size];
+ let cipher = algo.make_encrypt_cfb(key, iv)?;
let mut scratch = Vec::with_capacity(block_size);
unsafe { scratch.set_len(block_size); }
@@ -332,7 +326,6 @@ impl<W: io::Write> Encryptor<W> {
inner: Some(sink),
cipher,
block_size,
- iv: vec![0u8; block_size],
buffer: Vec::with_capacity(block_size),
scratch,
})
@@ -343,7 +336,7 @@ impl<W: io::Write> Encryptor<W> {
if let Some(mut inner) = self.inner.take() {
if self.buffer.len() > 0 {
unsafe { self.scratch.set_len(self.buffer.len()) }
- self.cipher.encrypt(&mut self.iv, &mut self.scratch, &self.buffer)?;
+ self.cipher.encrypt(&mut self.scratch, &self.buffer)?;
crate::vec_truncate(&mut self.buffer, 0);
inner.write_all(&self.scratch)?;
}
@@ -384,7 +377,7 @@ impl<W: io::Write> io::Write for Encryptor<W> {
// And possibly encrypt the block.
if self.buffer.len() == self.block_size {
- self.cipher.encrypt(&mut self.iv, &mut self.scratch, &self.buffer)
+ self.cipher.encrypt(&mut self.scratch, &self.buffer)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput,
format!("{}", e)))?;
crate::vec_truncate(&mut self.buffer, 0);
@@ -397,7 +390,7 @@ impl<W: io::Write> io::Write for Encryptor<W> {
for block in buf.chunks(self.block_size) {
if block.len() == self.block_size {
// Complete block.
- self.cipher.encrypt(&mut self.iv, &mut self.scratch, block)
+ self.cipher.encrypt(&mut self.scratch, block)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput,
format!("{}", e)))?;
inner.write_all(&self.scratch)?;
@@ -445,37 +438,41 @@ mod tests {
let algo = SymmetricAlgorithm::AES128;
let key = &hex::decode("2b7e151628aed2a6abf7158809cf4f3c").unwrap();
assert_eq!(key.len(), 16);
- // Ensure we use CFB128 by default
- let mut cfb = algo.make_encrypt_cfb(&key).unwrap();
- let mut iv = hex::decode("000102030405060708090A0B0C0D0E0F").unwrap();
+ // Ensure we use CFB128 by default
+ let iv = hex::decode("000102030405060708090A0B0C0D0E0F").unwrap();
+ let mut cfb = algo.make_encrypt_cfb(&key, iv).unwrap();
let msg = hex::decode("6bc1bee22e409f96e93d7e117393172a").unwrap();
let mut dst = vec![0; msg.len()];
-
- cfb.encrypt(&mut iv, &mut dst, &*msg).unwrap();
- assert_eq!(&iv, &hex::decode("3b3fd92eb72dad20333449f8e83cfb4a").unwrap());
+ cfb.encrypt(&mut dst, &*msg).unwrap();
assert_eq!(&dst[..16], &*hex::decode("3b3fd92eb72dad20333449f8e83cfb4a").unwrap());
+
// 32-byte long message
- let mut iv = hex::decode("000102030405060708090A0B0C0D0E0F").unwrap();
+ let iv = hex::decode("000102030405060708090A0B0C0D0E0F").unwrap();
+ let mut cfb = algo.make_encrypt_cfb(&key, iv).unwrap();
let msg = b"This is a very important message";
let mut dst = vec![0; msg.len()];
- cfb.encrypt