summaryrefslogtreecommitdiffstats
path: root/vendor/hmac/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/hmac/src')
-rw-r--r--vendor/hmac/src/lib.rs131
-rw-r--r--vendor/hmac/src/optim.rs280
-rw-r--r--vendor/hmac/src/simple.rs106
3 files changed, 517 insertions, 0 deletions
diff --git a/vendor/hmac/src/lib.rs b/vendor/hmac/src/lib.rs
new file mode 100644
index 0000000..e79c068
--- /dev/null
+++ b/vendor/hmac/src/lib.rs
@@ -0,0 +1,131 @@
+//! Generic implementation of Hash-based Message Authentication Code (HMAC).
+//!
+//! To use it you will need a cryptographic hash function implementation which
+//! implements the [`digest`] crate traits. You can find compatible crates
+//! (e.g. [`sha2`]) in the [`RustCrypto/hashes`] repository.
+//!
+//! This crate provides two HMAC implementation [`Hmac`] and [`SimpleHmac`].
+//! The first one is a buffered wrapper around block-level [`HmacCore`].
+//! Internally it uses efficient state representation, but works only with
+//! hash functions which expose block-level API and consume blocks eagerly
+//! (e.g. it will not work with the BLAKE2 family of hash functions).
+//! On the other hand, [`SimpleHmac`] is a bit less efficient memory-wise,
+//! but works with all hash functions which implement the [`Digest`] trait.
+//!
+//! # Examples
+//! Let us demonstrate how to use HMAC using the SHA-256 hash function.
+//!
+//! In the following examples [`Hmac`] is interchangeable with [`SimpleHmac`].
+//!
+//! To get authentication code:
+//!
+//! ```rust
+//! use sha2::Sha256;
+//! use hmac::{Hmac, Mac};
+//! use hex_literal::hex;
+//!
+//! // Create alias for HMAC-SHA256
+//! type HmacSha256 = Hmac<Sha256>;
+//!
+//! let mut mac = HmacSha256::new_from_slice(b"my secret and secure key")
+//! .expect("HMAC can take key of any size");
+//! mac.update(b"input message");
+//!
+//! // `result` has type `CtOutput` which is a thin wrapper around array of
+//! // bytes for providing constant time equality check
+//! let result = mac.finalize();
+//! // To get underlying array use `into_bytes`, but be careful, since
+//! // incorrect use of the code value may permit timing attacks which defeats
+//! // the security provided by the `CtOutput`
+//! let code_bytes = result.into_bytes();
+//! let expected = hex!("
+//! 97d2a569059bbcd8ead4444ff99071f4
+//! c01d005bcefe0d3567e1be628e5fdcd9
+//! ");
+//! assert_eq!(code_bytes[..], expected[..]);
+//! ```
+//!
+//! To verify the message:
+//!
+//! ```rust
+//! # use sha2::Sha256;
+//! # use hmac::{Hmac, Mac};
+//! # use hex_literal::hex;
+//! # type HmacSha256 = Hmac<Sha256>;
+//! let mut mac = HmacSha256::new_from_slice(b"my secret and secure key")
+//! .expect("HMAC can take key of any size");
+//!
+//! mac.update(b"input message");
+//!
+//! let code_bytes = hex!("
+//! 97d2a569059bbcd8ead4444ff99071f4
+//! c01d005bcefe0d3567e1be628e5fdcd9
+//! ");
+//! // `verify_slice` will return `Ok(())` if code is correct, `Err(MacError)` otherwise
+//! mac.verify_slice(&code_bytes[..]).unwrap();
+//! ```
+//!
+//! # Block and input sizes
+//! Usually it is assumed that block size is larger than output size. Due to the
+//! generic nature of the implementation, this edge case must be handled as well
+//! to remove potential panic. This is done by truncating hash output to the hash
+//! block size if needed.
+//!
+//! [`digest`]: https://docs.rs/digest
+//! [`sha2`]: https://docs.rs/sha2
+//! [`RustCrypto/hashes`]: https://github.com/RustCrypto/hashes
+
+#![no_std]
+#![doc(
+ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg",
+ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg",
+ html_root_url = "https://docs.rs/hmac/0.12.1"
+)]
+#![forbid(unsafe_code)]
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![warn(missing_docs, rust_2018_idioms)]
+
+#[cfg(feature = "std")]
+extern crate std;
+
+pub use digest;
+pub use digest::Mac;
+
+use digest::{
+ core_api::{Block, BlockSizeUser},
+ Digest,
+};
+
+mod optim;
+mod simple;
+
+pub use optim::{Hmac, HmacCore};
+pub use simple::SimpleHmac;
+
+const IPAD: u8 = 0x36;
+const OPAD: u8 = 0x5C;
+
+fn get_der_key<D: Digest + BlockSizeUser>(key: &[u8]) -> Block<D> {
+ let mut der_key = Block::<D>::default();
+ // The key that HMAC processes must be the same as the block size of the
+ // underlying hash function. If the provided key is smaller than that,
+ // we just pad it with zeros. If its larger, we hash it and then pad it
+ // with zeros.
+ if key.len() <= der_key.len() {
+ der_key[..key.len()].copy_from_slice(key);
+ } else {
+ let hash = D::digest(key);
+ // All commonly used hash functions have block size bigger
+ // than output hash size, but to be extra rigorous we
+ // handle the potential uncommon cases as well.
+ // The condition is calcualted at compile time, so this
+ // branch gets removed from the final binary.
+ if hash.len() <= der_key.len() {
+ der_key[..hash.len()].copy_from_slice(&hash);
+ } else {
+ let n = der_key.len();
+ der_key.copy_from_slice(&hash[..n]);
+ }
+ }
+ der_key
+}
diff --git a/vendor/hmac/src/optim.rs b/vendor/hmac/src/optim.rs
new file mode 100644
index 0000000..32d6277
--- /dev/null
+++ b/vendor/hmac/src/optim.rs
@@ -0,0 +1,280 @@
+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("> { ... }")
+ }
+}
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);
+ }
+}