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::parse::Cookie;
/// 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.
pub trait Aead {
/// 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;
}
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.clone()).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.clone()).into()),
}
}
}
const AD_PREFIX_LEN: usize = 5;
/// A `Read`er for decrypting AEAD-encrypted data.
pub struct Decryptor<'a> {
// The encrypted data.
source: Box<dyn BufferedReader<Cookie> + 'a>,
sym_algo: SymmetricAlgorithm,
aead: AEADAlgorithm,
key: SessionKey,
iv: Box<[u8]>,
ad: [u8; AD_PREFIX_LEN + 8 + 8],
digest_size: usize,
chunk_size: usize,
chunk_index: u64,
bytes_decrypted: u64,
// Up to a chunk of unread data.
buffer: Vec<u8>,
}
impl<'a> Decryptor<'a> {
/// Instantiate a new AEAD decryptor.
///
/// `source` is the source to wrap.
pub fn new<R: io::Read>(version: u8, sym_algo: SymmetricAlgorithm,
aead: AEADAlgorithm, chunk_size: usize,
iv: &[u8], key: &SessionKey, source: R)
-> Result<Self>
where R<