summaryrefslogtreecommitdiffstats
path: root/vendor/hmac/src/simple.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/hmac/src/simple.rs')
-rw-r--r--vendor/hmac/src/simple.rs106
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);
+ }
+}