use crate::Result;
pub trait Algorithm {
const ID: &'static str;
const NAME: &'static str;
}
pub trait Digest: Algorithm + Clone + Default {
type Output: AsRef<[u8]> + AsMut<[u8]> + Copy;
const OUTPUT_LEN: usize;
const BLOCK_LEN: usize;
fn new() -> Self;
fn update(&mut self, data: &[u8]);
fn finalize(self) -> Result<Self::Output>;
fn digest(data: &[u8]) -> Result<Self::Output> {
let mut h = Self::new();
h.update(data);
h.finalize()
}
}
pub trait Xof: Algorithm + Clone + Default {
const BLOCK_LEN: usize;
fn update(&mut self, data: &[u8]);
fn finalize_xof(self, out: &mut [u8]) -> Result<()>;
}
impl<T: internal::Digest> Digest for T {
type Output = <T as internal::Digest>::Output;
const OUTPUT_LEN: usize = <T as internal::Digest>::OUTPUT_LEN;
const BLOCK_LEN: usize = <T as internal::Digest>::BLOCK_LEN;
fn new() -> Self {
<T as internal::Digest>::new()
}
fn update(&mut self, data: &[u8]) {
<T as internal::Digest>::update(self, data)
}
fn finalize(self) -> Result<Self::Output> {
crate::module::operational()?;
Ok(<T as internal::Digest>::finalize(self))
}
}
impl<T: internal::Xof> Xof for T {
const BLOCK_LEN: usize = <T as internal::Xof>::BLOCK_LEN;
fn update(&mut self, data: &[u8]) {
<T as internal::Xof>::update(self, data)
}
fn finalize_xof(self, out: &mut [u8]) -> Result<()> {
crate::module::operational()?;
<T as internal::Xof>::finalize_xof(self, out);
Ok(())
}
}
#[doc(hidden)]
pub mod internal {
use super::Algorithm;
pub trait Digest: Algorithm + Clone + Default {
type Output: AsRef<[u8]> + AsMut<[u8]> + Copy;
const OUTPUT_LEN: usize;
const BLOCK_LEN: usize;
fn new() -> Self {
Self::default()
}
fn update(&mut self, data: &[u8]);
fn finalize(self) -> Self::Output;
fn digest(data: &[u8]) -> Self::Output {
let mut h = Self::new();
h.update(data);
h.finalize()
}
}
pub trait Mac: Algorithm + Clone {
type Tag: AsRef<[u8]> + AsMut<[u8]> + Copy;
const TAG_LEN: usize;
fn new(key: &[u8]) -> crate::Result<Self>
where
Self: Sized;
fn update(&mut self, data: &[u8]);
fn finalize(self) -> Self::Tag;
fn mac(key: &[u8], data: &[u8]) -> crate::Result<Self::Tag>
where
Self: Sized,
{
let mut m = Self::new(key)?;
m.update(data);
Ok(m.finalize())
}
}
pub trait Xof: Algorithm + Clone + Default {
const BLOCK_LEN: usize;
fn update(&mut self, data: &[u8]);
fn finalize_xof(self, out: &mut [u8]);
}
}
pub trait Mac: Algorithm + Clone {
type Tag: AsRef<[u8]> + AsMut<[u8]> + Copy;
const TAG_LEN: usize;
fn new(key: &[u8]) -> Result<Self>
where
Self: Sized;
fn update(&mut self, data: &[u8]);
fn finalize(self) -> Result<Self::Tag>;
fn mac(key: &[u8], data: &[u8]) -> Result<Self::Tag>
where
Self: Sized,
{
let mut m = Self::new(key)?;
m.update(data);
m.finalize()
}
fn verify(key: &[u8], data: &[u8], tag: &[u8]) -> Result<()>
where
Self: Sized,
{
let expected = Self::mac(key, data)?;
if crate::ct::verify(expected.as_ref(), tag) {
Ok(())
} else {
Err(crate::err!(AuthenticationFailed, "mac tag"))
}
}
}
impl<T: internal::Mac> Mac for T {
type Tag = <T as internal::Mac>::Tag;
const TAG_LEN: usize = <T as internal::Mac>::TAG_LEN;
fn new(key: &[u8]) -> Result<Self> {
<T as internal::Mac>::new(key)
}
fn update(&mut self, data: &[u8]) {
<T as internal::Mac>::update(self, data)
}
fn finalize(self) -> Result<Self::Tag> {
crate::module::operational()?;
Ok(<T as internal::Mac>::finalize(self))
}
}
pub trait BlockCipher: Algorithm {
const BLOCK_LEN: usize;
const KEY_LEN: usize;
fn new(key: &[u8]) -> Result<Self>
where
Self: Sized;
fn encrypt_block(&self, block: &mut [u8]) -> Result<()>;
fn decrypt_block(&self, block: &mut [u8]) -> Result<()>;
fn encrypt_blocks(&self, data: &mut [u8]) -> Result<()> {
if !data.len().is_multiple_of(Self::BLOCK_LEN) {
return Err(crate::err!(InvalidLength, "batch must be block-aligned"));
}
for block in data.chunks_mut(Self::BLOCK_LEN) {
self.encrypt_block(block)?;
}
Ok(())
}
}
pub trait Aead: Algorithm {
const KEY_LEN: usize;
const NONCE_LEN: usize;
const TAG_LEN: usize;
fn new(key: &[u8]) -> Result<Self>
where
Self: Sized;
fn seal_detached(
&self,
nonce: &[u8],
aad: &[u8],
in_out: &mut [u8],
tag: &mut [u8],
) -> Result<()>;
fn open_detached(&self, nonce: &[u8], aad: &[u8], in_out: &mut [u8], tag: &[u8]) -> Result<()>;
}
pub trait Kdf: Algorithm {
fn derive(secret: &[u8], salt: &[u8], info: &[u8], out: &mut [u8]) -> Result<()>;
}
pub trait Drbg: Algorithm {
fn instantiate(entropy: &[u8], nonce: &[u8], personalization: &[u8]) -> Result<Self>
where
Self: Sized;
fn reseed(&mut self, entropy: &[u8], additional: &[u8]) -> Result<()>;
fn generate(&mut self, additional: &[u8], out: &mut [u8]) -> Result<()>;
}
pub trait RandomSource {
fn fill(&mut self, out: &mut [u8]) -> Result<()>;
}
pub trait KeyAgreement: Algorithm {
const PRIVATE_KEY_LEN: usize;
const PUBLIC_KEY_LEN: usize;
const SHARED_SECRET_LEN: usize;
fn public_key(private_key: &[u8], out: &mut [u8]) -> Result<()>;
fn agree(private_key: &[u8], peer_public_key: &[u8], out: &mut [u8]) -> Result<()>;
}
pub trait SignatureScheme: Algorithm {
const PRIVATE_KEY_LEN: usize;
const PUBLIC_KEY_LEN: usize;
const SIGNATURE_LEN: usize;
fn public_key(private_key: &[u8], out: &mut [u8]) -> Result<()>;
fn sign(private_key: &[u8], message: &[u8], signature: &mut [u8]) -> Result<()>;
fn verify(public_key: &[u8], message: &[u8], signature: &[u8]) -> Result<()>;
}
pub trait SelfTest {
fn self_test() -> Result<()>;
}