diff options
Diffstat (limited to 'openpgp/src/crypto/backend')
-rw-r--r-- | openpgp/src/crypto/backend/cng/aead.rs | 23 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/nettle/aead.rs | 22 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/rust/aead.rs | 24 |
3 files changed, 61 insertions, 8 deletions
diff --git a/openpgp/src/crypto/backend/cng/aead.rs b/openpgp/src/crypto/backend/cng/aead.rs index a7b87613..fb95b150 100644 --- a/openpgp/src/crypto/backend/cng/aead.rs +++ b/openpgp/src/crypto/backend/cng/aead.rs @@ -1,7 +1,9 @@ //! Implementation of AEAD using Windows CNG API. +use std::cmp::Ordering; use crate::{Error, Result}; use crate::crypto::aead::{Aead, CipherOp}; +use crate::crypto::mem::secure_cmp; use crate::seal; use crate::types::{AEADAlgorithm, SymmetricAlgorithm}; @@ -10,6 +12,12 @@ use win_crypto_ng::symmetric::{BlockCipherKey, Aes}; use win_crypto_ng::symmetric::block_cipher::generic_array::{GenericArray, ArrayLength}; use win_crypto_ng::symmetric::block_cipher::generic_array::typenum::{U128, U192, U256}; +/// Disables authentication checks. +/// +/// This is DANGEROUS, and is only useful for debugging problems with +/// malformed AEAD-encrypted messages. +const DANGER_DISABLE_AUTHENTICATION: bool = false; + trait GenericArrayExt<T, N: ArrayLength<T>> { const LEN: usize; @@ -94,7 +102,7 @@ macro_rules! impl_aead { dst[..len].copy_from_slice(&src[..len]); EaxOnline::<$type, Encrypt>::encrypt(self, &mut dst[..len]) } - fn decrypt(&mut self, _dst: &mut [u8], _src: &[u8]) { + fn decrypt_verify(&mut self, _dst: &mut [u8], _src: &[u8], _digest: &[u8]) -> Result<()> { panic!("AEAD decryption called in the encryption context") } } @@ -113,10 +121,19 @@ macro_rules! impl_aead { fn encrypt(&mut self, _dst: &mut [u8], _src: &[u8]) { panic!("AEAD encryption called in the decryption context") } - fn decrypt(&mut self, dst: &mut [u8], src: &[u8]) { + fn decrypt_verify(&mut self, dst: &mut [u8], src: &[u8], digest: &[u8]) -> Result<()> { let len = core::cmp::min(dst.len(), src.len()); dst[..len].copy_from_slice(&src[..len]); - self.decrypt_unauthenticated_hazmat(&mut dst[..len]) + self.decrypt_unauthenticated_hazmat(&mut dst[..len]); + let mut chunk_digest = vec![0u8; self.digest_size()]; + + self.digest(&mut chunk_digest)?; + if secure_cmp(&chunk_digest[..], digest) + != Ordering::Equal && ! DANGER_DISABLE_AUTHENTICATION + { + return Err(Error::ManipulatedMessage.into()); + } + Ok(()) } } impl seal::Sealed for EaxOnline<$type, Decrypt> {} diff --git a/openpgp/src/crypto/backend/nettle/aead.rs b/openpgp/src/crypto/backend/nettle/aead.rs index e7ae9d85..000d3156 100644 --- a/openpgp/src/crypto/backend/nettle/aead.rs +++ b/openpgp/src/crypto/backend/nettle/aead.rs @@ -1,12 +1,21 @@ //! Implementation of AEAD using Nettle cryptographic library. +use std::cmp::Ordering; + use nettle::{aead, cipher}; use crate::{Error, Result}; use crate::crypto::aead::{Aead, CipherOp}; +use crate::crypto::mem::secure_cmp; use crate::seal; use crate::types::{AEADAlgorithm, SymmetricAlgorithm}; +/// Disables authentication checks. +/// +/// This is DANGEROUS, and is only useful for debugging problems with +/// malformed AEAD-encrypted messages. +const DANGER_DISABLE_AUTHENTICATION: bool = false; + impl<T: nettle::aead::Aead> seal::Sealed for T {} impl<T: nettle::aead::Aead> Aead for T { fn update(&mut self, ad: &[u8]) { @@ -15,8 +24,17 @@ impl<T: nettle::aead::Aead> Aead for T { fn encrypt(&mut self, dst: &mut [u8], src: &[u8]) { self.encrypt(dst, src) } - fn decrypt(&mut self, dst: &mut [u8], src: &[u8]) { - self.decrypt(dst, src) + fn decrypt_verify(&mut self, dst: &mut [u8], src: &[u8], digest: &[u8]) -> Result<()> { + self.decrypt(dst, src); + let mut chunk_digest = vec![0u8; self.digest_size()]; + + self.digest(&mut chunk_digest); + if secure_cmp(&chunk_digest[..], digest) + != Ordering::Equal && ! DANGER_DISABLE_AUTHENTICATION + { + return Err(Error::ManipulatedMessage.into()); + } + Ok(()) } fn digest(&mut self, digest: &mut [u8]) { self.digest(digest) diff --git a/openpgp/src/crypto/backend/rust/aead.rs b/openpgp/src/crypto/backend/rust/aead.rs index e5fcdb0b..f4dbc198 100644 --- a/openpgp/src/crypto/backend/rust/aead.rs +++ b/openpgp/src/crypto/backend/rust/aead.rs @@ -1,6 +1,7 @@ //! Implementation of AEAD using pure Rust cryptographic libraries. use std::cmp; +use std::cmp::Ordering; use cipher::{BlockCipher, NewBlockCipher}; use cipher::block::Block; @@ -10,9 +11,16 @@ use generic_array::{ArrayLength, GenericArray}; use crate::{Error, Result}; use crate::crypto::aead::{Aead, CipherOp}; +use crate::crypto::mem::secure_cmp; use crate::seal; use crate::types::{AEADAlgorithm, SymmetricAlgorithm}; +/// Disables authentication checks. +/// +/// This is DANGEROUS, and is only useful for debugging problems with +/// malformed AEAD-encrypted messages. +const DANGER_DISABLE_AUTHENTICATION: bool = false; + trait GenericArrayExt<T, N: ArrayLength<T>> { const LEN: usize; @@ -56,7 +64,7 @@ where Self::encrypt(self, &mut dst[..len]) } - fn decrypt(&mut self, _dst: &mut [u8], _src: &[u8]) { + fn decrypt_verify(&mut self, _dst: &mut [u8], _src: &[u8], _digest: &[u8]) -> Result<()> { panic!("AEAD decryption called in the encryption context") } } @@ -83,10 +91,20 @@ where panic!("AEAD encryption called in the decryption context") } - fn decrypt(&mut self, dst: &mut [u8], src: &[u8]) { + fn decrypt_verify(&mut self, dst: &mut [u8], src: &[u8], digest: &[u8]) -> Result<()> { let len = core::cmp::min(dst.len(), src.len()); dst[..len].copy_from_slice(&src[..len]); - self.decrypt_unauthenticated_hazmat(&mut dst[..len]) + self.decrypt_unauthenticated_hazmat(&mut dst[..len]); + + let mut chunk_digest = vec![0u8; self.digest_size()]; + + self.digest(&mut chunk_digest)?; + if secure_cmp(&chunk_digest[..], digest) + != Ordering::Equal && ! DANGER_DISABLE_AUTHENTICATION + { + return Err(Error::ManipulatedMessage.into()); + } + Ok(()) } } |