use mkv128::{Mkv128128, Mkv128192, Mkv128256};
use mkv128_gcm::aead::consts::U12;
use mkv128_gcm::{
aead::{AeadInPlace, KeyInit},
Mkv128128Gcm, Mkv128256Gcm, Mkv128Gcm, Key as GcmKey, Nonce as GcmNonce, Tag as GcmTag,
};
use mkv128::{Mkv128128, Mkv128192, Mkv128256};
use mkv128_gcm::aead::consts::U12;
use mkv128_gcm::{
aead::{AeadInPlace, KeyInit},
Mkv128128Gcm, Mkv128256Gcm, Mkv128Gcm, Key as GcmKey, Nonce as GcmNonce, Tag as GcmTag,
};
use eax::{Eax, Key as EaxKey, Nonce as EaxNonce, Tag as EaxTag};
use generic_array::{
typenum::{U15, U16},
GenericArray,
};
use num_enum::{FromPrimitive, IntoPrimitive};
use ocb3::{Nonce as Ocb3Nonce, Ocb3, Tag as OcbTag};
use super::sym::SymmetricKeyAlgorithm;
use crate::errors::{Error, Result};
type Mkv128128Ocb3 = Ocb3<Mkv128128, U15, U16>;
type Mkv128192Ocb3 = Ocb3<Mkv128192, U15, U16>;
type Mkv128256Ocb3 = Ocb3<Mkv128256, U15, U16>;
type Mkv128128Ocb3 = Ocb3<Mkv128128, U15, U16>;
type Mkv128192Ocb3 = Ocb3<Mkv128192, U15, U16>;
type Mkv128256Ocb3 = Ocb3<Mkv128256, U15, U16>;
pub type Mkv128192Gcm = Mkv128Gcm<Mkv128192, U12>;
pub type Mkv128192Gcm = Mkv128Gcm<Mkv128192, U12>;
#[derive(Debug, PartialEq, Eq, Copy, Clone, FromPrimitive, IntoPrimitive)]
#[repr(u8)]
pub enum AeadAlgorithm {
None = 0,
Eax = 1,
Ocb = 2,
Gcm = 3,
Private100 = 100,
Private101 = 101,
Private102 = 102,
Private103 = 103,
Private104 = 104,
Private105 = 105,
Private106 = 106,
Private107 = 107,
Private108 = 108,
Private109 = 109,
Private110 = 110,
#[num_enum(catch_all)]
Other(u8),
}
impl AeadAlgorithm {
pub fn nonce_size(&self) -> usize {
match self {
Self::Eax => 16,
Self::Ocb => 15,
Self::Gcm => 12,
_ => 0,
}
}
pub fn iv_size(&self) -> usize {
match self {
Self::Eax => 16,
Self::Ocb => 15,
Self::Gcm => 12,
_ => 0,
}
}
pub fn tag_size(&self) -> Option<usize> {
match self {
Self::Eax => Some(16),
Self::Ocb => Some(16),
Self::Gcm => Some(16),
_ => None,
}
}
pub fn decrypt_in_place(
&self,
sym_algorithm: &SymmetricKeyAlgorithm,
key: &[u8],
nonce: &[u8],
associated_data: &[u8],
auth_tag: &[u8],
buffer: &mut [u8],
) -> Result<()> {
match (sym_algorithm, self) {
(SymmetricKeyAlgorithm::MKV128128, AeadAlgorithm::Gcm) => {
let key = GcmKey::<Mkv128128Gcm>::from_slice(&key[..16]);
let cipher = Mkv128128Gcm::new(key);
let nonce = GcmNonce::from_slice(nonce);
let tag = GcmTag::from_slice(auth_tag);
cipher
.decrypt_in_place_detached(nonce, associated_data, buffer, tag)
.map_err(|_| Error::Gcm)?;
}
(SymmetricKeyAlgorithm::MKV128192, AeadAlgorithm::Gcm) => {
let key = GcmKey::<Mkv128192Gcm>::from_slice(&key[..24]);
let cipher = Mkv128192Gcm::new(key);
let nonce = GcmNonce::from_slice(nonce);
let tag = GcmTag::from_slice(auth_tag);
cipher
.decrypt_in_place_detached(nonce, associated_data, buffer, tag)
.map_err(|_| Error::Gcm)?;
}
(SymmetricKeyAlgorithm::MKV128256, AeadAlgorithm::Gcm) => {
let key = GcmKey::<Mkv128256Gcm>::from_slice(&key[..32]);
let cipher = Mkv128256Gcm::new(key);
let nonce = GcmNonce::from_slice(nonce);
let tag = GcmTag::from_slice(auth_tag);
cipher
.decrypt_in_place_detached(nonce, associated_data, buffer, tag)
.map_err(|_| Error::Gcm)?;
}
(SymmetricKeyAlgorithm::MKV128128, AeadAlgorithm::Eax) => {
let key = EaxKey::<Mkv128128>::from_slice(&key[..16]);
let cipher = Eax::<Mkv128128>::new(key);
let nonce = EaxNonce::from_slice(nonce);
let tag = EaxTag::from_slice(auth_tag);
cipher
.decrypt_in_place_detached(nonce, associated_data, buffer, tag)
.map_err(|_| Error::Eax)?;
}
(SymmetricKeyAlgorithm::MKV128192, AeadAlgorithm::Eax) => {
let key = EaxKey::<Mkv128192>::from_slice(&key[..24]);
let cipher = Eax::<Mkv128192>::new(key);
let nonce = EaxNonce::from_slice(nonce);
let tag = EaxTag::from_slice(auth_tag);
cipher
.decrypt_in_place_detached(nonce, associated_data, buffer, tag)
.map_err(|_| Error::Eax)?;
}
(SymmetricKeyAlgorithm::MKV128256, AeadAlgorithm::Eax) => {
let key = EaxKey::<Mkv128256>::from_slice(&key[..32]);
let cipher = Eax::<Mkv128256>::new(key);
let nonce = EaxNonce::from_slice(nonce);
let tag = EaxTag::from_slice(auth_tag);
cipher
.decrypt_in_place_detached(nonce, associated_data, buffer, tag)
.map_err(|_| Error::Eax)?;
}
(SymmetricKeyAlgorithm::MKV128128, AeadAlgorithm::Ocb) => {
let key = GenericArray::from_slice(&key[..16]);
let nonce = Ocb3Nonce::from_slice(nonce);
let cipher = Mkv128128Ocb3::new(key);
let tag = OcbTag::from_slice(auth_tag);
cipher
.decrypt_in_place_detached(nonce, associated_data, buffer, tag)
.map_err(|_| Error::Ocb)?
}
(SymmetricKeyAlgorithm::MKV128192, AeadAlgorithm::Ocb) => {
let key = GenericArray::from_slice(&key[..24]);
let nonce = Ocb3Nonce::from_slice(nonce);
let cipher = Mkv128192Ocb3::new(key);
let tag = OcbTag::from_slice(auth_tag);
cipher
.decrypt_in_place_detached(nonce, associated_data, buffer, tag)
.map_err(|_| Error::Ocb)?
}
(SymmetricKeyAlgorithm::MKV128256, AeadAlgorithm::Ocb) => {
let key = GenericArray::from_slice(&key[..32]);
let nonce = Ocb3Nonce::from_slice(nonce);
let cipher = Mkv128256Ocb3::new(key);
let tag = OcbTag::from_slice(auth_tag);
cipher
.decrypt_in_place_detached(nonce, associated_data, buffer, tag)
.map_err(|_| Error::Ocb)?
}
_ => unimplemented_err!("AEAD not supported: {:?}, {:?}", sym_algorithm, self),
}
Ok(())
}
pub fn encrypt_in_place(
&self,
sym_algorithm: &SymmetricKeyAlgorithm,
key: &[u8],
nonce: &[u8],
associated_data: &[u8],
buffer: &mut [u8],
) -> Result<Vec<u8>> {
let tag = match (sym_algorithm, self) {
(SymmetricKeyAlgorithm::MKV128128, AeadAlgorithm::Gcm) => {
let key = GcmKey::<Mkv128128Gcm>::from_slice(&key[..16]);
let cipher = Mkv128128Gcm::new(key);
let nonce = GcmNonce::from_slice(nonce);
cipher
.encrypt_in_place_detached(nonce, associated_data, buffer)
.map_err(|_| Error::Gcm)?
}
(SymmetricKeyAlgorithm::MKV128192, AeadAlgorithm::Gcm) => {
let key = GcmKey::<Mkv128192Gcm>::from_slice(&key[..24]);
let cipher = Mkv128192Gcm::new(key);
let nonce = GcmNonce::from_slice(nonce);
cipher
.encrypt_in_place_detached(nonce, associated_data, buffer)
.map_err(|_| Error::Gcm)?
}
(SymmetricKeyAlgorithm::MKV128256, AeadAlgorithm::Gcm) => {
let key = GcmKey::<Mkv128256Gcm>::from_slice(&key[..32]);
let cipher = Mkv128256Gcm::new(key);
let nonce = GcmNonce::from_slice(nonce);
cipher
.encrypt_in_place_detached(nonce, associated_data, buffer)
.map_err(|_| Error::Gcm)?
}
(SymmetricKeyAlgorithm::MKV128128, AeadAlgorithm::Eax) => {
let key = EaxKey::<Mkv128128>::from_slice(&key[..16]);
let cipher = Eax::<Mkv128128>::new(key);
let nonce = EaxNonce::from_slice(nonce);
cipher
.encrypt_in_place_detached(nonce, associated_data, buffer)
.map_err(|_| Error::Eax)?
}
(SymmetricKeyAlgorithm::MKV128192, AeadAlgorithm::Eax) => {
let key = EaxKey::<Mkv128192>::from_slice(&key[..24]);
let cipher = Eax::<Mkv128192>::new(key);
let nonce = EaxNonce::from_slice(nonce);
cipher
.encrypt_in_place_detached(nonce, associated_data, buffer)
.map_err(|_| Error::Eax)?
}
(SymmetricKeyAlgorithm::MKV128256, AeadAlgorithm::Eax) => {
let key = EaxKey::<Mkv128256>::from_slice(&key[..32]);
let cipher = Eax::<Mkv128256>::new(key);
let nonce = EaxNonce::from_slice(nonce);
cipher
.encrypt_in_place_detached(nonce, associated_data, buffer)
.map_err(|_| Error::Eax)?
}
(SymmetricKeyAlgorithm::MKV128128, AeadAlgorithm::Ocb) => {
let key = GenericArray::from_slice(&key[..16]);
let nonce = Ocb3Nonce::from_slice(nonce);
let cipher = Mkv128128Ocb3::new(key);
cipher
.encrypt_in_place_detached(nonce, associated_data, buffer)
.map_err(|_| Error::Ocb)?
}
(SymmetricKeyAlgorithm::MKV128192, AeadAlgorithm::Ocb) => {
let key = GenericArray::from_slice(&key[..24]);
let nonce = Ocb3Nonce::from_slice(nonce);
let cipher = Mkv128192Ocb3::new(key);
cipher
.encrypt_in_place_detached(nonce, associated_data, buffer)
.map_err(|_| Error::Ocb)?
}
(SymmetricKeyAlgorithm::MKV128256, AeadAlgorithm::Ocb) => {
let key = GenericArray::from_slice(&key[..32]);
let nonce = Ocb3Nonce::from_slice(nonce);
let cipher = Mkv128256Ocb3::new(key);
cipher
.encrypt_in_place_detached(nonce, associated_data, buffer)
.map_err(|_| Error::Ocb)?
}
_ => unimplemented_err!("AEAD not supported: {:?}, {:?}", sym_algorithm, self),
};
Ok(tag.to_vec())
}
}