pub use aead::{AeadCore, AeadInPlace, Buffer, Error, KeyInit, KeySizeUser};
#[cfg(feature = "alloc")]
pub use aead::{Aead, Payload};
use aead::{
consts::{U0, U12, U16, U32},
generic_array::GenericArray,
};
use ring::aead::{
Aad, LessSafeKey as Key, Nonce, UnboundKey, AES_128_GCM, AES_256_GCM, CHACHA20_POLY1305,
};
pub type Tag = GenericArray<u8, U16>;
pub struct Aes128Gcm(Cipher);
pub struct Aes256Gcm(Cipher);
pub struct ChaCha20Poly1305(Cipher);
macro_rules! impl_aead {
($cipher:ty, $algorithm:expr, $key_size:ty) => {
impl KeySizeUser for $cipher {
type KeySize = $key_size;
}
impl KeyInit for $cipher {
fn new(key: &GenericArray<u8, Self::KeySize>) -> Self {
let key = UnboundKey::new(&$algorithm, key.as_slice()).unwrap();
Self(Cipher::new(key))
}
}
impl AeadCore for $cipher {
type NonceSize = U12;
type TagSize = U16;
type CiphertextOverhead = U0;
}
impl AeadInPlace for $cipher {
fn encrypt_in_place_detached(
&self,
nonce: &GenericArray<u8, Self::NonceSize>,
associated_data: &[u8],
buffer: &mut [u8],
) -> Result<Tag, Error> {
self.0
.encrypt_in_place_detached(nonce.as_slice(), associated_data, buffer)
}
fn decrypt_in_place(
&self,
nonce: &GenericArray<u8, Self::NonceSize>,
associated_data: &[u8],
buffer: &mut dyn Buffer,
) -> Result<(), Error> {
self.0
.decrypt_in_place(nonce.as_slice(), associated_data, buffer)
}
fn decrypt_in_place_detached(
&self,
_nonce: &GenericArray<u8, Self::NonceSize>,
_associated_data: &[u8],
_buffer: &mut [u8],
_tag: &Tag,
) -> Result<(), Error> {
unimplemented!(); }
}
};
}
impl_aead!(Aes128Gcm, AES_128_GCM, U16);
impl_aead!(Aes256Gcm, AES_256_GCM, U32);
impl_aead!(ChaCha20Poly1305, CHACHA20_POLY1305, U32);
pub(crate) struct Cipher(Key);
impl Cipher {
pub fn new(key: UnboundKey) -> Self {
Cipher(Key::new(key))
}
fn encrypt_in_place_detached(
&self,
nonce: &[u8],
associated_data: &[u8],
buffer: &mut [u8],
) -> Result<Tag, Error> {
self.0
.seal_in_place_separate_tag(
Nonce::try_assume_unique_for_key(nonce).map_err(|_| Error)?,
Aad::from(associated_data),
buffer,
)
.map(|tag| Tag::clone_from_slice(tag.as_ref()))
.map_err(|_| Error)
}
fn decrypt_in_place(
&self,
nonce: &[u8],
associated_data: &[u8],
buffer: &mut dyn Buffer,
) -> Result<(), Error> {
let pt_len = self
.0
.open_in_place(
Nonce::try_assume_unique_for_key(nonce).map_err(|_| Error)?,
Aad::from(associated_data),
buffer.as_mut(),
)
.map_err(|_| Error)?
.len();
buffer.truncate(pt_len);
Ok(())
}
}