281 lines
7.5 KiB
Rust
281 lines
7.5 KiB
Rust
use super::{get_der_key, IPAD, OPAD};
|
|
use core::{fmt, slice};
|
|
#[cfg(feature = "reset")]
|
|
use digest::Reset;
|
|
use digest::{
|
|
block_buffer::Eager,
|
|
core_api::{
|
|
AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreProxy, CoreWrapper,
|
|
FixedOutputCore, OutputSizeUser, UpdateCore,
|
|
},
|
|
crypto_common::{Key, KeySizeUser},
|
|
generic_array::typenum::{IsLess, Le, NonZero, U256},
|
|
HashMarker, InvalidLength, KeyInit, MacMarker, Output,
|
|
};
|
|
|
|
/// 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
|
|
+ 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,
|
|
}
|
|
|
|
impl<D> Clone 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,
|
|
{
|
|
fn clone(&self) -> Self {
|
|
Self {
|
|
digest: self.digest.clone(),
|
|
opad_digest: self.opad_digest.clone(),
|
|
#[cfg(feature = "reset")]
|
|
ipad_digest: self.ipad_digest.clone(),
|
|
}
|
|
}
|
|
}
|
|
|
|
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> 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,
|
|
{
|
|
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> 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> 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> 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,
|
|
{
|
|
#[inline(always)]
|
|
fn new(key: &Key<Self>) -> Self {
|
|
Self::new_from_slice(key.as_slice()).unwrap()
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
|
|
let mut buf = get_der_key::<CoreWrapper<D::Core>>(key);
|
|
for b in buf.iter_mut() {
|
|
*b ^= IPAD;
|
|
}
|
|
let mut digest = D::Core::default();
|
|
digest.update_blocks(slice::from_ref(&buf));
|
|
|
|
for b in buf.iter_mut() {
|
|
*b ^= IPAD ^ OPAD;
|
|
}
|
|
|
|
let mut opad_digest = D::Core::default();
|
|
opad_digest.update_blocks(slice::from_ref(&buf));
|
|
|
|
Ok(Self {
|
|
#[cfg(feature = "reset")]
|
|
ipad_digest: digest.clone(),
|
|
opad_digest,
|
|
digest,
|
|
})
|
|
}
|
|
}
|
|
|
|
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,
|
|
{
|
|
#[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,
|
|
{
|
|
#[inline(always)]
|
|
fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
|
|
let mut hash = Output::<D::Core>::default();
|
|
self.digest.finalize_fixed_core(buffer, &mut hash);
|
|
// finalize_fixed_core should reset the buffer as well, but
|
|
// to be extra safe we reset it explicitly again.
|
|
buffer.reset();
|
|
#[cfg(not(feature = "reset"))]
|
|
let h = &mut self.opad_digest;
|
|
#[cfg(feature = "reset")]
|
|
let mut h = self.opad_digest.clone();
|
|
buffer.digest_blocks(&hash, |b| h.update_blocks(b));
|
|
h.finalize_fixed_core(buffer, out);
|
|
}
|
|
}
|
|
|
|
#[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,
|
|
{
|
|
#[inline(always)]
|
|
fn reset(&mut self) {
|
|
self.digest = self.ipad_digest.clone();
|
|
}
|
|
}
|
|
|
|
impl<D> 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,
|
|
{
|
|
fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
f.write_str("Hmac<")?;
|
|
<D::Core as AlgorithmName>::write_alg_name(f)?;
|
|
f.write_str(">")
|
|
}
|
|
}
|
|
|
|
impl<D> 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,
|
|
{
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
f.write_str("HmacCore<")?;
|
|
<D::Core as AlgorithmName>::write_alg_name(f)?;
|
|
f.write_str("> { ... }")
|
|
}
|
|
}
|