diff options
Diffstat (limited to 'vendor/hmac/src/simple.rs')
-rw-r--r-- | vendor/hmac/src/simple.rs | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/vendor/hmac/src/simple.rs b/vendor/hmac/src/simple.rs new file mode 100644 index 0000000..e28c4c3 --- /dev/null +++ b/vendor/hmac/src/simple.rs @@ -0,0 +1,106 @@ +use super::{get_der_key, IPAD, OPAD}; +use core::fmt; +use digest::{ + crypto_common::{Block, BlockSizeUser, InvalidLength, Key, KeySizeUser}, + Digest, FixedOutput, KeyInit, MacMarker, Output, OutputSizeUser, Update, +}; +#[cfg(feature = "reset")] +use digest::{FixedOutputReset, Reset}; + +/// Simplified HMAC instance able to operate over hash functions +/// which do not expose block-level API and hash functions which +/// process blocks lazily (e.g. BLAKE2). +#[derive(Clone)] +pub struct SimpleHmac<D: Digest + BlockSizeUser> { + digest: D, + opad_key: Block<D>, + #[cfg(feature = "reset")] + ipad_key: Block<D>, +} + +impl<D: Digest + BlockSizeUser> KeySizeUser for SimpleHmac<D> { + type KeySize = D::BlockSize; +} + +impl<D: Digest + BlockSizeUser> MacMarker for SimpleHmac<D> {} + +impl<D: Digest + BlockSizeUser> KeyInit for SimpleHmac<D> { + fn new(key: &Key<Self>) -> Self { + Self::new_from_slice(key.as_slice()).unwrap() + } + + #[inline] + fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> { + let der_key = get_der_key::<D>(key); + let mut ipad_key = der_key.clone(); + for b in ipad_key.iter_mut() { + *b ^= IPAD; + } + let mut digest = D::new(); + digest.update(&ipad_key); + + let mut opad_key = der_key; + for b in opad_key.iter_mut() { + *b ^= OPAD; + } + + Ok(Self { + digest, + opad_key, + #[cfg(feature = "reset")] + ipad_key, + }) + } +} + +impl<D: Digest + BlockSizeUser> Update for SimpleHmac<D> { + #[inline(always)] + fn update(&mut self, data: &[u8]) { + self.digest.update(data); + } +} + +impl<D: Digest + BlockSizeUser> OutputSizeUser for SimpleHmac<D> { + type OutputSize = D::OutputSize; +} + +impl<D: Digest + BlockSizeUser> FixedOutput for SimpleHmac<D> { + fn finalize_into(self, out: &mut Output<Self>) { + let mut h = D::new(); + h.update(&self.opad_key); + h.update(&self.digest.finalize()); + h.finalize_into(out); + } +} + +impl<D: Digest + BlockSizeUser + fmt::Debug> fmt::Debug for SimpleHmac<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SimpleHmac") + .field("digest", &self.digest) + // TODO: replace with `finish_non_exhaustive` on MSRV + // bump to 1.53 + .field("..", &"..") + .finish() + } +} + +#[cfg(feature = "reset")] +#[cfg_attr(docsrs, doc(cfg(feature = "reset")))] +impl<D: Digest + BlockSizeUser + Reset> Reset for SimpleHmac<D> { + fn reset(&mut self) { + Reset::reset(&mut self.digest); + self.digest.update(&self.ipad_key); + } +} + +#[cfg(feature = "reset")] +#[cfg_attr(docsrs, doc(cfg(feature = "reset")))] +impl<D: Digest + BlockSizeUser + FixedOutputReset> FixedOutputReset for SimpleHmac<D> { + fn finalize_into_reset(&mut self, out: &mut Output<Self>) { + let mut h = D::new(); + Update::update(&mut h, &self.opad_key); + Update::update(&mut h, &self.digest.finalize_reset()); + Update::update(&mut self.digest, &self.ipad_key); + Digest::finalize_into(h, out); + } +} |