diff options
Diffstat (limited to 'openpgp/src')
-rw-r--r-- | openpgp/src/crypto/backend/cng/symmetric.rs | 65 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/nettle/symmetric.rs | 239 | ||||
-rw-r--r-- | openpgp/src/crypto/ecdh.rs | 16 | ||||
-rw-r--r-- | openpgp/src/crypto/symmetric.rs | 61 | ||||
-rw-r--r-- | openpgp/src/packet/skesk.rs | 12 |
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 |