#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
)]
#![cfg_attr(feature = "getrandom", doc = "```")]
#![cfg_attr(not(feature = "getrandom"), doc = "```ignore")]
#![cfg_attr(all(feature = "getrandom", feature = "arrayvec"), doc = "```")]
#![cfg_attr(
not(all(feature = "getrandom", feature = "arrayvec")),
doc = "```ignore"
)]
#[cfg(feature = "alloc")]
extern crate alloc;
pub mod siv;
pub use aead::{self, AeadCore, AeadInOut, Error, Key, KeyInit, KeySizeUser};
use crate::siv::Siv;
use aead::{
TagPosition,
array::Array,
consts::{U1, U16, U32, U64},
inout::InOutBuf,
};
use aes::{Aes128, Aes256};
use cipher::{BlockCipherEncrypt, BlockSizeUser, array::ArraySize, typenum::IsGreaterOrEqual};
use cmac::Cmac;
use core::{fmt, marker::PhantomData, ops::Add};
use digest::{FixedOutputReset, Mac};
#[cfg(feature = "pmac")]
use pmac::Pmac;
pub type Nonce<NonceSize = U16> = Array<u8, NonceSize>;
pub type Tag = Array<u8, U16>;
pub struct SivAead<C, M, NonceSize = U16>
where
Self: KeySizeUser,
C: BlockSizeUser<BlockSize = U16> + BlockCipherEncrypt + KeyInit + KeySizeUser,
M: Mac<OutputSize = U16> + FixedOutputReset + KeyInit,
<C as KeySizeUser>::KeySize: Add,
NonceSize: ArraySize + IsGreaterOrEqual<U1>,
{
key: Array<u8, <Self as KeySizeUser>::KeySize>,
mac: PhantomData<M>, }
pub type CmacSivAead<BlockCipher> = SivAead<BlockCipher, Cmac<BlockCipher>>;
#[cfg(feature = "pmac")]
#[cfg_attr(docsrs, doc(cfg(feature = "pmac")))]
pub type PmacSivAead<BlockCipher> = SivAead<BlockCipher, Pmac<BlockCipher>>;
pub type Aes128SivAead = CmacSivAead<Aes128>;
pub type Aes256SivAead = CmacSivAead<Aes256>;
#[cfg(feature = "pmac")]
#[cfg_attr(docsrs, doc(cfg(feature = "pmac")))]
pub type Aes128PmacSivAead = PmacSivAead<Aes128>;
#[cfg(feature = "pmac")]
#[cfg_attr(docsrs, doc(cfg(feature = "pmac")))]
pub type Aes256PmacSivAead = PmacSivAead<Aes256>;
impl<M, NonceSize> KeySizeUser for SivAead<Aes128, M, NonceSize>
where
M: Mac<OutputSize = U16> + FixedOutputReset + KeyInit,
NonceSize: ArraySize + IsGreaterOrEqual<U1>,
{
type KeySize = U32;
}
impl<M, NonceSize> KeySizeUser for SivAead<Aes256, M, NonceSize>
where
M: Mac<OutputSize = U16> + FixedOutputReset + KeyInit,
NonceSize: ArraySize + IsGreaterOrEqual<U1>,
{
type KeySize = U64;
}
impl<M, NonceSize> KeyInit for SivAead<Aes128, M, NonceSize>
where
M: Mac<OutputSize = U16> + FixedOutputReset + KeyInit,
NonceSize: ArraySize + IsGreaterOrEqual<U1>,
{
fn new(key: &Array<u8, Self::KeySize>) -> Self {
Self {
key: *key,
mac: PhantomData,
}
}
}
impl<M, NonceSize> KeyInit for SivAead<Aes256, M, NonceSize>
where
M: Mac<OutputSize = U16> + FixedOutputReset + KeyInit,
NonceSize: ArraySize + IsGreaterOrEqual<U1>,
{
fn new(key: &Array<u8, Self::KeySize>) -> Self {
Self {
key: *key,
mac: PhantomData,
}
}
}
impl<C, M, NonceSize> AeadCore for SivAead<C, M, NonceSize>
where
Self: KeySizeUser,
C: BlockSizeUser<BlockSize = U16> + BlockCipherEncrypt + KeyInit + KeySizeUser,
M: Mac<OutputSize = U16> + FixedOutputReset + KeyInit,
<C as KeySizeUser>::KeySize: Add,
NonceSize: ArraySize + IsGreaterOrEqual<U1>,
{
type NonceSize = NonceSize;
type TagSize = U16;
const TAG_POSITION: TagPosition = TagPosition::Prefix;
}
impl<C, M, NonceSize> AeadInOut for SivAead<C, M, NonceSize>
where
Self: KeySizeUser,
Siv<C, M>: KeyInit + KeySizeUser<KeySize = <Self as KeySizeUser>::KeySize>,
C: BlockSizeUser<BlockSize = U16> + BlockCipherEncrypt + KeyInit + KeySizeUser,
M: Mac<OutputSize = U16> + FixedOutputReset + KeyInit,
<C as KeySizeUser>::KeySize: Add,
NonceSize: ArraySize + IsGreaterOrEqual<U1>,
{
fn encrypt_inout_detached(
&self,
nonce: &Array<u8, Self::NonceSize>,
associated_data: &[u8],
buffer: InOutBuf<'_, '_, u8>,
) -> Result<Array<u8, Self::TagSize>, Error> {
Siv::<C, M>::new(&self.key)
.encrypt_inout_detached([associated_data, nonce.as_slice()], buffer)
}
fn decrypt_inout_detached(
&self,
nonce: &Array<u8, Self::NonceSize>,
associated_data: &[u8],
buffer: InOutBuf<'_, '_, u8>,
tag: &Array<u8, Self::TagSize>,
) -> Result<(), Error> {
Siv::<C, M>::new(&self.key).decrypt_inout_detached(
[associated_data, nonce.as_slice()],
buffer,
tag,
)
}
}
impl<C, M, NonceSize> fmt::Debug for SivAead<C, M, NonceSize>
where
Self: KeySizeUser,
C: BlockSizeUser<BlockSize = U16> + BlockCipherEncrypt + KeyInit + KeySizeUser,
M: Mac<OutputSize = U16> + FixedOutputReset + KeyInit,
<C as KeySizeUser>::KeySize: Add,
NonceSize: ArraySize + IsGreaterOrEqual<U1>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("SivAead").finish_non_exhaustive()
}
}