blob: ca977381e28735b39e37018c1c3118d7837fc78d [file] [log] [blame]
use super::{
AlgorithmName, Buffer, BufferKindUser, ExtendableOutputCore, FixedOutputCore, OutputSizeUser,
Reset, UpdateCore, XofReaderCoreWrapper,
};
use crate::{
ExtendableOutput, ExtendableOutputReset, FixedOutput, FixedOutputReset, HashMarker, Update,
};
use block_buffer::BlockBuffer;
use core::fmt;
use crypto_common::{
typenum::{IsLess, Le, NonZero, U256},
BlockSizeUser, InvalidLength, Key, KeyInit, KeySizeUser, Output,
};
#[cfg(feature = "mac")]
use crate::MacMarker;
#[cfg(feature = "oid")]
use const_oid::{AssociatedOid, ObjectIdentifier};
/// Wrapper around [`BufferKindUser`].
///
/// It handles data buffering and implements the slice-based traits.
#[derive(Clone, Default)]
pub struct CoreWrapper<T>
where
T: BufferKindUser,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
core: T,
buffer: BlockBuffer<T::BlockSize, T::BufferKind>,
}
impl<T> HashMarker for CoreWrapper<T>
where
T: BufferKindUser + HashMarker,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
}
#[cfg(feature = "mac")]
#[cfg_attr(docsrs, doc(cfg(feature = "mac")))]
impl<T> MacMarker for CoreWrapper<T>
where
T: BufferKindUser + MacMarker,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
}
// this blanket impl is needed for HMAC
impl<T> BlockSizeUser for CoreWrapper<T>
where
T: BufferKindUser + HashMarker,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
type BlockSize = T::BlockSize;
}
impl<T> CoreWrapper<T>
where
T: BufferKindUser,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
/// Create new wrapper from `core`.
#[inline]
pub fn from_core(core: T) -> Self {
let buffer = Default::default();
Self { core, buffer }
}
/// Decompose wrapper into inner parts.
#[inline]
pub fn decompose(self) -> (T, Buffer<T>) {
let Self { core, buffer } = self;
(core, buffer)
}
}
impl<T> KeySizeUser for CoreWrapper<T>
where
T: BufferKindUser + KeySizeUser,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
type KeySize = T::KeySize;
}
impl<T> KeyInit for CoreWrapper<T>
where
T: BufferKindUser + KeyInit,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
#[inline]
fn new(key: &Key<Self>) -> Self {
Self {
core: T::new(key),
buffer: Default::default(),
}
}
#[inline]
fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
Ok(Self {
core: T::new_from_slice(key)?,
buffer: Default::default(),
})
}
}
impl<T> fmt::Debug for CoreWrapper<T>
where
T: BufferKindUser + AlgorithmName,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
T::write_alg_name(f)?;
f.write_str(" { .. }")
}
}
impl<T> Reset for CoreWrapper<T>
where
T: BufferKindUser + Reset,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
#[inline]
fn reset(&mut self) {
self.core.reset();
self.buffer.reset();
}
}
impl<T> Update for CoreWrapper<T>
where
T: BufferKindUser + UpdateCore,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
#[inline]
fn update(&mut self, input: &[u8]) {
let Self { core, buffer } = self;
buffer.digest_blocks(input, |blocks| core.update_blocks(blocks));
}
}
impl<T> OutputSizeUser for CoreWrapper<T>
where
T: BufferKindUser + OutputSizeUser,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
type OutputSize = T::OutputSize;
}
impl<T> FixedOutput for CoreWrapper<T>
where
T: FixedOutputCore,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
#[inline]
fn finalize_into(mut self, out: &mut Output<Self>) {
let Self { core, buffer } = &mut self;
core.finalize_fixed_core(buffer, out);
}
}
impl<T> FixedOutputReset for CoreWrapper<T>
where
T: FixedOutputCore + Reset,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
#[inline]
fn finalize_into_reset(&mut self, out: &mut Output<Self>) {
let Self { core, buffer } = self;
core.finalize_fixed_core(buffer, out);
core.reset();
buffer.reset();
}
}
impl<T> ExtendableOutput for CoreWrapper<T>
where
T: ExtendableOutputCore,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
<T::ReaderCore as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<T::ReaderCore as BlockSizeUser>::BlockSize, U256>: NonZero,
{
type Reader = XofReaderCoreWrapper<T::ReaderCore>;
#[inline]
fn finalize_xof(self) -> Self::Reader {
let (mut core, mut buffer) = self.decompose();
let core = core.finalize_xof_core(&mut buffer);
let buffer = Default::default();
Self::Reader { core, buffer }
}
}
impl<T> ExtendableOutputReset for CoreWrapper<T>
where
T: ExtendableOutputCore + Reset,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
<T::ReaderCore as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<T::ReaderCore as BlockSizeUser>::BlockSize, U256>: NonZero,
{
#[inline]
fn finalize_xof_reset(&mut self) -> Self::Reader {
let Self { core, buffer } = self;
let reader_core = core.finalize_xof_core(buffer);
core.reset();
buffer.reset();
let buffer = Default::default();
Self::Reader {
core: reader_core,
buffer,
}
}
}
#[cfg(feature = "oid")]
#[cfg_attr(docsrs, doc(cfg(feature = "oid")))]
impl<T> AssociatedOid for CoreWrapper<T>
where
T: BufferKindUser + AssociatedOid,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
const OID: ObjectIdentifier = T::OID;
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<T> std::io::Write for CoreWrapper<T>
where
T: BufferKindUser + UpdateCore,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
Update::update(self, buf);
Ok(buf.len())
}
#[inline]
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
/// A proxy trait to a core type implemented by [`CoreWrapper`]
// TODO: replace with an inherent associated type on stabilization:
// https://github.com/rust-lang/rust/issues/8995
pub trait CoreProxy: sealed::Sealed {
/// Type wrapped by [`CoreWrapper`].
type Core;
}
mod sealed {
pub trait Sealed {}
}
impl<T> sealed::Sealed for CoreWrapper<T>
where
T: BufferKindUser,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
}
impl<T> CoreProxy for CoreWrapper<T>
where
T: BufferKindUser,
T::BlockSize: IsLess<U256>,
Le<T::BlockSize, U256>: NonZero,
{
type Core = T;
}