use crypto_common::generic_array::{ArrayLength, GenericArray};
use crate::{Error, Support};
#[derive(Copy, Clone)]
pub struct AeadSupport {
pub no_copy: bool,
pub in_place_no_copy: bool,
}
impl From<AeadSupport> for bool {
fn from(value: AeadSupport) -> Self {
value.no_copy || value.in_place_no_copy
}
}
pub trait Api<Key, Iv>: Support<AeadSupport> + Send
where
Key: ArrayLength<u8>,
Iv: ArrayLength<u8>,
{
type Tag: ArrayLength<u8>;
fn encrypt(
key: &Array<Key>, iv: &Array<Iv>, aad: &[u8], clear: Option<&[u8]>, cipher: &mut [u8],
tag: &mut Array<Self::Tag>,
) -> Result<(), Error>;
fn decrypt(
key: &Array<Key>, iv: &Array<Iv>, aad: &[u8], cipher: Option<&[u8]>,
tag: &Array<Self::Tag>, clear: &mut [u8],
) -> Result<(), Error>;
}
pub type Array<N> = GenericArray<u8, N>;
#[cfg(feature = "internal-software-crypto-aead")]
mod software {
use aead::{AeadCore, AeadInPlace};
use crypto_common::{KeyInit, KeySizeUser};
use super::*;
impl<T: AeadInPlace> Support<AeadSupport> for T {
const SUPPORT: AeadSupport = AeadSupport { no_copy: false, in_place_no_copy: true };
}
impl<Key, Iv, T> Api<Key, Iv> for T
where
T: Send + KeyInit + AeadInPlace,
T: KeySizeUser<KeySize = Key>,
T: AeadCore<NonceSize = Iv>,
Key: ArrayLength<u8>,
Iv: ArrayLength<u8>,
{
type Tag = T::TagSize;
fn encrypt(
key: &Array<Key>, iv: &Array<Iv>, aad: &[u8], clear: Option<&[u8]>, cipher: &mut [u8],
tag: &mut Array<Self::Tag>,
) -> Result<(), Error> {
let aead = T::new(key);
if let Some(clear) = clear {
cipher.copy_from_slice(clear);
}
tag.copy_from_slice(
&aead.encrypt_in_place_detached(iv, aad, cipher).map_err(|_| Error::world(0))?,
);
Ok(())
}
fn decrypt(
key: &Array<Key>, iv: &Array<Iv>, aad: &[u8], cipher: Option<&[u8]>,
tag: &Array<Self::Tag>, clear: &mut [u8],
) -> Result<(), Error> {
let aead = T::new(key);
if let Some(cipher) = cipher {
clear.copy_from_slice(cipher);
}
aead.decrypt_in_place_detached(iv, aad, clear, tag).map_err(|_| Error::world(0))
}
}
}