use crate::Result;
use derivative::Derivative;
pub use self::aes_gcm::{AES128_GCM, AES256_GCM};
pub use self::block::{AES128_CBC, AES192_CBC, AES256_CBC};
#[cfg(feature = "insecure-crypto")]
pub use self::block::TDES_CBC;
pub use self::chacha_poly::CHACHA20_POLY1305;
pub use self::none::NONE;
pub use self::stream::{AES128_CTR, AES192_CTR, AES256_CTR};
pub(crate) use self::none::Identity;
use crate::mac::{Mac, MacVerified};
mod aes_gcm;
mod block;
mod chacha_poly;
mod none;
mod stream;
static ALGOS: &[&CipherAlgo] = &[
&AES128_GCM, &AES256_GCM,
&AES128_CBC, &AES192_CBC, &AES256_CBC,
&CHACHA20_POLY1305,
&NONE,
&AES128_CTR, &AES192_CTR, &AES256_CTR,
#[cfg(feature = "insecure-crypto")]
&TDES_CBC,
];
#[derive(Debug)]
pub struct CipherAlgo {
pub name: &'static str,
pub(crate) block_len: usize,
pub(crate) key_len: usize,
pub(crate) iv_len: usize,
pub(crate) variant: CipherAlgoVariant,
}
#[derive(Debug)]
pub(crate) enum CipherAlgoVariant {
Standard(StandardCipherAlgo),
Aead(AeadCipherAlgo),
}
#[derive(Derivative)]
#[derivative(Debug)]
pub(crate) struct StandardCipherAlgo {
#[derivative(Debug = "ignore")]
pub(crate) make_encrypt: fn(key: &[u8], iv: &[u8]) -> Box<dyn Encrypt + Send>,
#[derivative(Debug = "ignore")]
pub(crate) make_decrypt: fn(key: &[u8], iv: &[u8]) -> Box<dyn Decrypt + Send>,
}
#[derive(Derivative)]
#[derivative(Debug)]
pub(crate) struct AeadCipherAlgo {
pub(crate) tag_len: usize,
#[derivative(Debug = "ignore")]
pub(crate) make_encrypt: fn(key: &[u8], iv: &[u8]) -> Box<dyn AeadEncrypt + Send>,
#[derivative(Debug = "ignore")]
pub(crate) make_decrypt: fn(key: &[u8], iv: &[u8]) -> Box<dyn AeadDecrypt + Send>,
}
pub(crate) enum PacketEncrypt {
EncryptAndMac(Box<dyn Encrypt + Send>, Box<dyn Mac + Send>),
EncryptThenMac(Box<dyn Encrypt + Send>, Box<dyn Mac + Send>),
Aead(Box<dyn AeadEncrypt + Send>),
}
pub(crate) enum PacketDecrypt {
EncryptAndMac(Box<dyn Decrypt + Send>, Box<dyn Mac + Send>),
EncryptThenMac(Box<dyn Decrypt + Send>, Box<dyn Mac + Send>),
Aead(Box<dyn AeadDecrypt + Send>),
}
pub(crate) trait Encrypt {
fn encrypt(&mut self, data: &mut [u8]);
}
pub(crate) trait Decrypt {
fn decrypt(&mut self, data: &mut [u8]);
}
pub(crate) trait AeadEncrypt {
fn encrypt_and_sign(&mut self, packet_seq: u64, packet: &mut [u8], tag: &mut [u8]);
}
pub(crate) trait AeadDecrypt {
fn decrypt_packet_len(&mut self, packet_seq: u64, ciphertext: &[u8], plaintext: &mut [u8]);
fn decrypt_and_verify(&mut self, packet_seq: u64, packet: &mut [u8], tag: &[u8]) -> Result<MacVerified>;
}
impl CipherAlgoVariant {
pub fn is_aead(&self) -> bool {
matches!(self, CipherAlgoVariant::Aead(_))
}
}
pub(crate) fn algo_by_name(name: &str) -> Option<&'static CipherAlgo> {
ALGOS.iter().copied().find(|algo| algo.name == name)
}