use std::cmp;
use std::convert::TryInto;
use std::fmt;
use std::io;
use buffered_reader::BufferedReader;
use crate::types::{
AEADAlgorithm,
SymmetricAlgorithm,
};
use crate::utils::{
write_be_u64,
};
use crate::Error;
use crate::Result;
use crate::crypto::SessionKey;
use crate::crypto::mem::secure_cmp;
use crate::seal;
use crate::parse::Cookie;
/// Minimum AEAD chunk size.
///
/// Implementations MUST support chunk sizes down to 64B.
const MIN_CHUNK_SIZE: usize = 1 << 6; // 64B
/// Maximum AEAD chunk size.
///
/// Implementations MUST support chunk sizes up to 4MiB.
const MAX_CHUNK_SIZE: usize = 1 << 22; // 4MiB
/// Disables authentication checks.
///
/// This is DANGEROUS, and is only useful for debugging problems with
/// malformed AEAD-encrypted messages.
const DANGER_DISABLE_AUTHENTICATION: bool = false;
/// Converts a chunk size to a usize.
pub(crate) fn chunk_size_usize(chunk_size: u64) -> Result<usize> {
chunk_size.try_into()
.map_err(|_| Error::InvalidOperation(
format!("AEAD chunk size exceeds size of \
virtual memory: {}", chunk_size)).into())
}
/// An AEAD mode of operation.
///
/// # Sealed trait
///
/// This trait is [sealed] and cannot be implemented for types outside this crate.
/// Therefore it can be extended in a non-breaking way.
/// If you want to implement the trait inside the crate
/// you also need to implement the `seal::Sealed` marker trait.
///
/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
pub trait Aead : seal::Sealed {
/// Adds associated data `ad`.
fn update(&mut self, ad: &[u8]);
/// Encrypts one block `src` to `dst`.
fn encrypt(&mut self, dst: &mut [u8], src: &[u8]);
/// Decrypts one block `src` to `dst`.
fn decrypt(&mut self, dst: &mut [u8], src: &[u8]);
/// Produce the digest.
fn digest(&mut self, digest: &mut [u8]);
/// Length of the digest in bytes.
fn digest_size(&self) -> usize;
}
/// Whether AEAD cipher is used for data encryption or decryption.
pub(crate) enum CipherOp {
/// Cipher is used for data encryption.
Encrypt,
/// Cipher is used for data decryption.
Decrypt,
}
impl AEADAlgorithm {
/// Returns the digest size of the AEAD algorithm.
pub fn digest_size(&self) -> Result<usize> {
use self::AEADAlgorithm::*;
match self {
// According to RFC4880bis, Section 5.16.1.
EAX => Ok(16),
// According to RFC4880bis, Section 5.16.2.
OCB => Ok(16),
_ => Err(Error::UnsupportedAEADAlgorithm(*self).into()),
}
}
/// Returns the initialization vector size of the AEAD algorithm.
pub fn iv_size(&self) -> Result<usize> {
use self::AEADAlgorithm::*;
match self {
// According to RFC4880bis, Section 5.16.1.
EAX => Ok(16),
// According to RFC4880bis, Section 5.16.2, the IV is "at
// least 15 octets long". GnuPG hardcodes 15 in
// openpgp_aead_algo_info.
OCB => Ok(15),
_ => Err(Error::UnsupportedAEADAlgorithm(*self).into()),
}
}
}
const AD_PREFIX_LEN: usize = 5;
/// A `Read`er for decrypting AEAD-encrypted data.
pub struct Decryptor<'a> {
// The encrypted data.
source: