Skip to content

Commit

Permalink
hmac: add EagerHash (#151)
Browse files Browse the repository at this point in the history
Provides a trait for hash functions which expose their block-level core
which can be used in an optimized implementation of HMAC without
polluting the bounds of code which uses HMAC generically over hash
functions.

Originally from #123.
  • Loading branch information
tarcieri authored Jan 9, 2024
1 parent e435a12 commit a37e152
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 158 deletions.
2 changes: 1 addition & 1 deletion hmac/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ use digest::{
mod optim;
mod simple;

pub use optim::{Hmac, HmacCore};
pub use optim::{EagerHash, Hmac, HmacCore};
pub use simple::SimpleHmac;

const IPAD: u8 = 0x36;
Expand Down
194 changes: 37 additions & 157 deletions hmac/src/optim.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
use super::{get_der_key, IPAD, OPAD};
use core::{fmt, slice};
#[cfg(feature = "reset")]
use digest::Reset;
use digest::{
array::typenum::{IsLess, Le, NonZero, U256},
block_buffer::Eager,
core_api::{
AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreProxy, CoreWrapper,
FixedOutputCore, OutputSizeUser, UpdateCore,
AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore,
OutputSizeUser, UpdateCore,
},
crypto_common::{Key, KeySizeUser},
HashMarker, InvalidLength, KeyInit, MacMarker, Output,
Expand All @@ -16,37 +13,38 @@ use digest::{
/// Generic HMAC instance.
pub type Hmac<D> = CoreWrapper<HmacCore<D>>;

/// Generic core HMAC instance, which operates over blocks.
pub struct HmacCore<D>
where
D: CoreProxy,
D::Core: HashMarker
/// Trait implemented by eager hashes which expose their block-level core.
pub trait EagerHash {
/// Block-level core type of the hash.
type Core: HashMarker
+ UpdateCore
+ FixedOutputCore
+ BufferKindUser<BufferKind = Eager>
+ Default
+ Clone,
<D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
digest: D::Core,
opad_digest: D::Core,
#[cfg(feature = "reset")]
ipad_digest: D::Core,
+ Clone;
}

impl<D> Clone for HmacCore<D>
impl<C> EagerHash for CoreWrapper<C>
where
D: CoreProxy,
D::Core: HashMarker
C: HashMarker
+ UpdateCore
+ FixedOutputCore
+ BufferKindUser<BufferKind = Eager>
+ Default
+ Clone,
<D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
type Core = C;
}

/// Generic core HMAC instance, which operates over blocks.
pub struct HmacCore<D: EagerHash> {
digest: D::Core,
opad_digest: D::Core,
#[cfg(feature = "reset")]
ipad_digest: D::Core,
}

impl<D: EagerHash> Clone for HmacCore<D> {
fn clone(&self) -> Self {
Self {
digest: self.digest.clone(),
Expand All @@ -57,92 +55,25 @@ where
}
}

impl<D> MacMarker for HmacCore<D>
where
D: CoreProxy,
D::Core: HashMarker
+ UpdateCore
+ FixedOutputCore
+ BufferKindUser<BufferKind = Eager>
+ Default
+ Clone,
<D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
}
impl<D: EagerHash> MacMarker for HmacCore<D> {}

impl<D> BufferKindUser for HmacCore<D>
where
D: CoreProxy,
D::Core: HashMarker
+ UpdateCore
+ FixedOutputCore
+ BufferKindUser<BufferKind = Eager>
+ Default
+ Clone,
<D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
impl<D: EagerHash> BufferKindUser for HmacCore<D> {
type BufferKind = Eager;
}

impl<D> KeySizeUser for HmacCore<D>
where
D: CoreProxy,
D::Core: HashMarker
+ UpdateCore
+ FixedOutputCore
+ BufferKindUser<BufferKind = Eager>
+ Default
+ Clone,
<D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
type KeySize = <<D as CoreProxy>::Core as BlockSizeUser>::BlockSize;
impl<D: EagerHash> KeySizeUser for HmacCore<D> {
type KeySize = <<D as EagerHash>::Core as BlockSizeUser>::BlockSize;
}

impl<D> BlockSizeUser for HmacCore<D>
where
D: CoreProxy,
D::Core: HashMarker
+ UpdateCore
+ FixedOutputCore
+ BufferKindUser<BufferKind = Eager>
+ Default
+ Clone,
<D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
type BlockSize = <<D as CoreProxy>::Core as BlockSizeUser>::BlockSize;
impl<D: EagerHash> BlockSizeUser for HmacCore<D> {
type BlockSize = <<D as EagerHash>::Core as BlockSizeUser>::BlockSize;
}

impl<D> OutputSizeUser for HmacCore<D>
where
D: CoreProxy,
D::Core: HashMarker
+ UpdateCore
+ FixedOutputCore
+ BufferKindUser<BufferKind = Eager>
+ Default
+ Clone,
<D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
type OutputSize = <<D as CoreProxy>::Core as OutputSizeUser>::OutputSize;
impl<D: EagerHash> OutputSizeUser for HmacCore<D> {
type OutputSize = <<D as EagerHash>::Core as OutputSizeUser>::OutputSize;
}

impl<D> KeyInit for HmacCore<D>
where
D: CoreProxy,
D::Core: HashMarker
+ UpdateCore
+ FixedOutputCore
+ BufferKindUser<BufferKind = Eager>
+ Default
+ Clone,
<D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
impl<D: EagerHash> KeyInit for HmacCore<D> {
#[inline(always)]
fn new(key: &Key<Self>) -> Self {
Self::new_from_slice(key.as_slice()).unwrap()
Expand Down Expand Up @@ -173,36 +104,14 @@ where
}
}

impl<D> UpdateCore for HmacCore<D>
where
D: CoreProxy,
D::Core: HashMarker
+ UpdateCore
+ FixedOutputCore
+ BufferKindUser<BufferKind = Eager>
+ Default
+ Clone,
<D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
impl<D: EagerHash> UpdateCore for HmacCore<D> {
#[inline(always)]
fn update_blocks(&mut self, blocks: &[Block<Self>]) {
self.digest.update_blocks(blocks);
}
}

impl<D> FixedOutputCore for HmacCore<D>
where
D: CoreProxy,
D::Core: HashMarker
+ UpdateCore
+ FixedOutputCore
+ BufferKindUser<BufferKind = Eager>
+ Default
+ Clone,
<D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
impl<D: EagerHash> FixedOutputCore for HmacCore<D> {
#[inline(always)]
fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
let mut hash = Output::<D::Core>::default();
Expand All @@ -221,36 +130,16 @@ where

#[cfg(feature = "reset")]
#[cfg_attr(docsrs, doc(cfg(feature = "reset")))]
impl<D> Reset for HmacCore<D>
where
D: CoreProxy,
D::Core: HashMarker
+ UpdateCore
+ FixedOutputCore
+ BufferKindUser<BufferKind = Eager>
+ Default
+ Clone,
<D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
impl<D: EagerHash> digest::Reset for HmacCore<D> {
#[inline(always)]
fn reset(&mut self) {
self.digest = self.ipad_digest.clone();
}
}

impl<D> AlgorithmName for HmacCore<D>
impl<D: EagerHash> AlgorithmName for HmacCore<D>
where
D: CoreProxy,
D::Core: HashMarker
+ AlgorithmName
+ UpdateCore
+ FixedOutputCore
+ BufferKindUser<BufferKind = Eager>
+ Default
+ Clone,
<D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
D::Core: AlgorithmName,
{
fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Hmac<")?;
Expand All @@ -259,18 +148,9 @@ where
}
}

impl<D> fmt::Debug for HmacCore<D>
impl<D: EagerHash> fmt::Debug for HmacCore<D>
where
D: CoreProxy,
D::Core: HashMarker
+ AlgorithmName
+ UpdateCore
+ FixedOutputCore
+ BufferKindUser<BufferKind = Eager>
+ Default
+ Clone,
<D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
D::Core: AlgorithmName,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("HmacCore<")?;
Expand Down

0 comments on commit a37e152

Please sign in to comment.