From 49c543bac0eb3f6454018b5097bb8b918343d609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Tue, 7 Dec 2021 23:08:55 +0300 Subject: [PATCH] update hmac to digest v0.10 --- .github/workflows/hmac.yml | 1 + Cargo.lock | 84 ++++---- README.md | 35 +++- hmac/CHANGELOG.md | 10 + hmac/Cargo.toml | 18 +- hmac/README.md | 3 - hmac/src/lib.rs | 230 +++++++-------------- hmac/src/optim.rs | 280 ++++++++++++++++++++++++++ hmac/src/simple.rs | 106 ++++++++++ hmac/tests/data/wycheproof-sha1.blb | Bin 0 -> 4875 bytes hmac/tests/data/wycheproof-sha256.blb | Bin 0 -> 6153 bytes hmac/tests/data/wycheproof-sha384.blb | Bin 0 -> 7857 bytes hmac/tests/data/wycheproof-sha512.blb | Bin 0 -> 9648 bytes hmac/tests/lib.rs | 18 -- hmac/tests/optim.rs | 49 +++++ hmac/tests/simple.rs | 57 ++++++ 16 files changed, 660 insertions(+), 231 deletions(-) create mode 100644 hmac/src/optim.rs create mode 100644 hmac/src/simple.rs create mode 100644 hmac/tests/data/wycheproof-sha1.blb create mode 100644 hmac/tests/data/wycheproof-sha256.blb create mode 100644 hmac/tests/data/wycheproof-sha384.blb create mode 100644 hmac/tests/data/wycheproof-sha512.blb delete mode 100644 hmac/tests/lib.rs create mode 100644 hmac/tests/optim.rs create mode 100644 hmac/tests/simple.rs diff --git a/.github/workflows/hmac.yml b/.github/workflows/hmac.yml index 9a2dc56..d058bef 100644 --- a/.github/workflows/hmac.yml +++ b/.github/workflows/hmac.yml @@ -53,4 +53,5 @@ jobs: toolchain: ${{ matrix.rust }} override: true - run: cargo test --release --no-default-features + - run: cargo test --release --features reset - run: cargo test --release diff --git a/Cargo.lock b/Cargo.lock index 88497db..a86ec70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "aes" version = "0.7.5" @@ -14,26 +16,19 @@ dependencies = [ [[package]] name = "blobby" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc52553543ecb104069b0ff9e0fcc5c739ad16202935528a112d974e8f1a4ee8" +checksum = "847495c209977a90e8aad588b959d0ca9f5dc228096d29a6bd3defd53f35eaec" [[package]] name = "block-buffer" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95" dependencies = [ - "block-padding", "generic-array", ] -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - [[package]] name = "byteorder" version = "1.4.3" @@ -69,13 +64,22 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cc47dfc37fe9455a291c6aef98ac51376b771fa9779aa7a2f9a86f0700a7a20" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" dependencies = [ "libc", ] +[[package]] +name = "crypto-common" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567569e659735adb39ff2d4c20600f7cd78be5471f8c58ab162bce3c03fdbc5f" +dependencies = [ + "generic-array", +] + [[package]] name = "crypto-mac" version = "0.11.1" @@ -118,11 +122,15 @@ dependencies = [ [[package]] name = "digest" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "8549e6bfdecd113b7e221fe60b433087f6957387a20f8118ebca9b12af19143d" dependencies = [ + "blobby", + "block-buffer", + "crypto-common", "generic-array", + "subtle", ] [[package]] @@ -156,11 +164,12 @@ dependencies = [ [[package]] name = "hmac" -version = "0.11.0" +version = "0.12.0" dependencies = [ - "crypto-mac", "digest", + "hex-literal", "md-5", + "sha-1", "sha2", "streebog", ] @@ -176,9 +185,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.101" +version = "0.2.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" +checksum = "f98a04dce437184842841303488f70d0188c5f51437d2a834dc097eafa909a01" [[package]] name = "magma" @@ -192,13 +201,11 @@ dependencies = [ [[package]] name = "md-5" -version = "0.9.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" +checksum = "e6a38fc55c8bbc10058782919516f88826e70320db6d206aebc49611d24216ae" dependencies = [ - "block-buffer", "digest", - "opaque-debug", ] [[package]] @@ -222,41 +229,48 @@ version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" +[[package]] +name = "sha-1" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha2" -version = "0.9.8" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" +checksum = "900d964dd36bb15bcf2f2b35694c072feab74969a54f2bbeec7a2d725d2bdcb6" dependencies = [ - "block-buffer", "cfg-if", "cpufeatures", "digest", - "opaque-debug", ] [[package]] name = "streebog" -version = "0.9.2" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9a21c1a3920381f27c666a81ad2481abc005900ac871a80b479e1869d54e753" +checksum = "5f2a93b52a311873ee038192d8a95dc3bad1d638ac926c2afee0ea9887ecfaf0" dependencies = [ - "block-buffer", "digest", - "opaque-debug", ] [[package]] name = "subtle" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "typenum" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" [[package]] name = "version_check" diff --git a/README.md b/README.md index d5ef9bd..5e0d9e9 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,21 @@ -# RustCrypto: Message Authentication Codes ![Rust Version][rustc-image] [![Project Chat][chat-image]][chat-link] [![dependency status][deps-image]][deps-link] +# RustCrypto: Message Authentication Codes + +[![Project Chat][chat-image]][chat-link] [![dependency status][deps-image]][deps-link] ![Apache2/MIT licensed][license-image] Collection of [Message Authentication Code][1] (MAC) algorithms written in pure Rust. -## Crates +## Supported Algorithms + +| Algorithm | Crate | Crates.io | Documentation | MSRV | +|-----------|----------|:-------------:|:-------------:|:----:| +| [CMAC] | [`cmac`] | [![crates.io](https://img.shields.io/crates/v/cmac.svg)](https://crates.io/crates/cmac) | [![Documentation](https://docs.rs/cmac/badge.svg)](https://docs.rs/cmac) | ![MSRV 1.41][msrv-1.41] | +| [DAA] | [`daa`] | [![crates.io](https://img.shields.io/crates/v/daa.svg)](https://crates.io/crates/daa) | [![Documentation](https://docs.rs/daa/badge.svg)](https://docs.rs/daa) | ![MSRV 1.41][msrv-1.41] | +| [HMAC] | [`hmac`] | [![crates.io](https://img.shields.io/crates/v/hmac.svg)](https://crates.io/crates/hmac) | [![Documentation](https://docs.rs/hmac/badge.svg)](https://docs.rs/hmac) | ![MSRV 1.41][msrv-1.41] | +| [PMAC] | [`pmac`] | [![crates.io](https://img.shields.io/crates/v/pmac.svg)](https://crates.io/crates/pmac) | [![Documentation](https://docs.rs/pmac/badge.svg)](https://docs.rs/pmac) | ![MSRV 1.41][msrv-1.41] | + +### Minimum Supported Rust Version (MSRV) Policy -| Name | Algorithm | Crates.io | Documentation | Build Status | -|--------|-----------|---------------|---------------|--------------| -| `cmac` | [CMAC] | [![crates.io](https://img.shields.io/crates/v/cmac.svg)](https://crates.io/crates/cmac) | [![Documentation](https://docs.rs/cmac/badge.svg)](https://docs.rs/cmac) | [![Build](https://github.com/RustCrypto/MACs/workflows/cmac/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/MACs/actions?query=workflow:cmac+branch:master) -| `daa` | [DAA] | [![crates.io](https://img.shields.io/crates/v/daa.svg)](https://crates.io/crates/daa) | [![Documentation](https://docs.rs/daa/badge.svg)](https://docs.rs/daa) | [![Build](https://github.com/RustCrypto/MACs/workflows/daa/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/MACs/actions?query=workflow:daa+branch:master) -| `hmac` | [HMAC] | [![crates.io](https://img.shields.io/crates/v/hmac.svg)](https://crates.io/crates/hmac) | [![Documentation](https://docs.rs/hmac/badge.svg)](https://docs.rs/hmac) | [![Build](https://github.com/RustCrypto/MACs/workflows/hmac/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/MACs/actions?query=workflow:hmac+branch:master) -| `pmac` | [PMAC] | [![crates.io](https://img.shields.io/crates/v/pmac.svg)](https://crates.io/crates/pmac) | [![Documentation](https://docs.rs/pmac/badge.svg)](https://docs.rs/pmac) | [![Build](https://github.com/RustCrypto/MACs/workflows/pmac/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/MACs/actions?query=workflow:pmac+branch:master) +MSRV bumps are considered breaking changes and will be performed only with minor version bump. ## License @@ -22,16 +28,23 @@ at your option. ### Contribution -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in the work by you, as defined in the Apache-2.0 license +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. [//]: # (badges) -[rustc-image]: https://img.shields.io/badge/rustc-1.41+-blue.svg [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260044-MACs +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg [deps-image]: https://deps.rs/repo/github/RustCrypto/MACs/status.svg [deps-link]: https://deps.rs/repo/github/RustCrypto/MACs +[msrv-1.41]: https://img.shields.io/badge/rustc-1.41.0+-blue.svg + +[//]: # (crates) + +[`cmac`]: ./cmac +[`daa`]: ./daa +[`hmac`]: ./hmac +[`pmac`]: ./pmac [//]: # (footnotes) diff --git a/hmac/CHANGELOG.md b/hmac/CHANGELOG.md index 77a2f7b..1bcf688 100644 --- a/hmac/CHANGELOG.md +++ b/hmac/CHANGELOG.md @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.12.0 (2021-12-07) +### Changed +- Bump `digest` crate dependency to v0.10 and remove `crypto-mac` ([#97]) +- Use a more efficient state representation by using block-level hash API ([#97]) + +### Added +- `SimpleHmac` as a less constrained alternative to `Hmac` ([#97]) + +[#97]: https://github.com/RustCrypto/MACs/pull/97 + ## 0.11.0 (2021-04-29) ### Changed - Bump `crypto-mac` crate dependency to v0.11 ([#73]) diff --git a/hmac/Cargo.toml b/hmac/Cargo.toml index 23544f6..d285310 100644 --- a/hmac/Cargo.toml +++ b/hmac/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hmac" -version = "0.11.0" +version = "0.12.0" # Also update html_root_url in lib.rs when bumping this description = "Generic implementation of Hash-based Message Authentication Code (HMAC)" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -12,14 +12,16 @@ readme = "README.md" edition = "2018" [dependencies] -crypto-mac = "0.11" -digest = "0.9" +digest = { version = "0.10", features = ["mac"] } [dev-dependencies] -crypto-mac = { version = "0.11", features = ["dev"] } -md-5 = { version = "0.9", default-features = false } -sha2 = { version = "0.9", default-features = false } -streebog = { version = "0.9", default-features = false } +digest = { version = "0.10", features = ["dev"] } +md-5 = { version = "0.10", default-features = false } +sha-1 = { version = "0.10", default-features = false } +sha2 = { version = "0.10", default-features = false } +streebog = { version = "0.10", default-features = false } +hex-literal = "0.2" [features] -std = ["crypto-mac/std"] +std = ["digest/std"] +reset = [] # Enable ability to reset HMAC instances diff --git a/hmac/README.md b/hmac/README.md index ab50b2c..52d4ef9 100644 --- a/hmac/README.md +++ b/hmac/README.md @@ -5,7 +5,6 @@ ![Apache2/MIT licensed][license-image] ![Rust Version][rustc-image] [![Project Chat][chat-image]][chat-link] -[![Build Status][build-image]][build-link] Pure Rust implementation of the [Hash-based Message Authentication Code (HMAC)][1]. @@ -48,8 +47,6 @@ dual licensed as above, without any additional terms or conditions. [rustc-image]: https://img.shields.io/badge/rustc-1.41+-blue.svg [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260044-MACs -[build-image]: https://github.com/RustCrypto/MACs/workflows/hmac/badge.svg?branch=master&event=push -[build-link]: https://github.com/RustCrypto/MACs/actions?query=workflow%3Ahmac [//]: # (general links) diff --git a/hmac/src/lib.rs b/hmac/src/lib.rs index b3f3666..303c7c5 100644 --- a/hmac/src/lib.rs +++ b/hmac/src/lib.rs @@ -1,213 +1,131 @@ //! Generic implementation of Hash-based Message Authentication Code (HMAC). //! -//! To use it you'll need a cryptographic hash function implementation from -//! RustCrypto project. You can either import specific crate (e.g. `sha2`), or -//! meta-crate `crypto-hashes` which reexport all related crates. +//! 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. //! //! # Usage -//! Let us demonstrate how to use HMAC using SHA256 as an example. +//! Let us demonstrate how to use HMAC using the SHA-256 hash function. +//! +//! In the following examples [`Hmac`] is interchangeable with [`SimpleHmac`]. //! -//! To get the authentication code: +//! To get authentication code: //! //! ```rust //! use sha2::Sha256; -//! use hmac::{Hmac, Mac, NewMac}; +//! use hmac::{Hmac, Mac}; +//! use hex_literal::hex; //! //! // Create alias for HMAC-SHA256 //! type HmacSha256 = Hmac; //! -//! // Create HMAC-SHA256 instance which implements `Mac` trait //! 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 `Output` which is a thin wrapper around array of +//! // `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` method, but be careful, since -//! // incorrect use of the code value may permit timing attacks which defeat -//! // the security provided by the `Output` +//! // 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, NewMac}; +//! # use hmac::{Hmac, Mac}; +//! # use hex_literal::hex; //! # type HmacSha256 = Hmac; //! 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 = mac.clone().finalize().into_bytes(); -//! // `verify` will return `Ok(())` if code is correct, `Err(MacError)` otherwise -//! mac.verify(&code_bytes).unwrap(); +//! 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 scenario. This is done by truncating hash output -//! to the hash block size if needed. +//! 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/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/hmac/0.12.0" )] +#![cfg_attr(docsrs, feature(doc_cfg))] #![forbid(unsafe_code)] #![warn(missing_docs, rust_2018_idioms)] #[cfg(feature = "std")] extern crate std; -pub use crypto_mac::{self, Mac, NewMac}; pub use digest; +pub use digest::Mac; -use core::{cmp::min, fmt}; -use crypto_mac::{ - generic_array::{sequence::GenericSequence, ArrayLength, GenericArray}, - InvalidKeyLength, Output, +use digest::{ + core_api::{Block, BlockSizeUser}, + Digest, }; -use digest::{BlockInput, FixedOutput, Reset, Update}; - -const IPAD: u8 = 0x36; -const OPAD: u8 = 0x5C; - -/// The `Hmac` struct represents an HMAC using a given hash function `D`. -pub struct Hmac -where - D: Update + BlockInput + FixedOutput + Reset + Default + Clone, - D::BlockSize: ArrayLength, -{ - digest: D, - i_key_pad: GenericArray, - opad_digest: D, -} - -impl Clone for Hmac -where - D: Update + BlockInput + FixedOutput + Reset + Default + Clone, - D::BlockSize: ArrayLength, -{ - fn clone(&self) -> Hmac { - Hmac { - digest: self.digest.clone(), - i_key_pad: self.i_key_pad.clone(), - opad_digest: self.opad_digest.clone(), - } - } -} -impl fmt::Debug for Hmac -where - D: Update + BlockInput + FixedOutput + Reset + Default + Clone + fmt::Debug, - D::BlockSize: ArrayLength, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Hmac") - .field("digest", &self.digest) - .field("i_key_pad", &self.i_key_pad) - .field("opad_digest", &self.opad_digest) - .finish() - } -} +mod optim; +mod simple; -impl NewMac for Hmac -where - D: Update + BlockInput + FixedOutput + Reset + Default + Clone, - D::BlockSize: ArrayLength, - D::OutputSize: ArrayLength, -{ - type KeySize = D::BlockSize; +pub use optim::{Hmac, HmacCore}; +pub use simple::SimpleHmac; - fn new(key: &GenericArray) -> Self { - Self::new_from_slice(key.as_slice()).unwrap() - } - - #[inline] - fn new_from_slice(key: &[u8]) -> Result { - let mut hmac = Self { - digest: Default::default(), - i_key_pad: GenericArray::generate(|_| IPAD), - opad_digest: Default::default(), - }; - - let mut opad = GenericArray::::generate(|_| OPAD); - debug_assert!(hmac.i_key_pad.len() == opad.len()); +const IPAD: u8 = 0x36; +const OPAD: u8 = 0x5C; - // The key that Hmac processes must be the same as the block size of the - // underlying Digest. 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() <= hmac.i_key_pad.len() { - for (k_idx, k_itm) in key.iter().enumerate() { - hmac.i_key_pad[k_idx] ^= *k_itm; - opad[k_idx] ^= *k_itm; - } +fn get_der_key(key: &[u8]) -> Block { + let mut der_key = Block::::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 mut digest = D::default(); - digest.update(key); - let output = digest.finalize_fixed(); - // `n` is calculated at compile time and will equal - // D::OutputSize. This is used to ensure panic-free code - let n = min(output.len(), hmac.i_key_pad.len()); - for idx in 0..n { - hmac.i_key_pad[idx] ^= output[idx]; - opad[idx] ^= output[idx]; - } + let n = der_key.len(); + der_key.copy_from_slice(&hash[..n]); } - - hmac.digest.update(&hmac.i_key_pad); - hmac.opad_digest.update(&opad); - - Ok(hmac) - } -} - -impl Mac for Hmac -where - D: Update + BlockInput + FixedOutput + Reset + Default + Clone, - D::BlockSize: ArrayLength, - D::OutputSize: ArrayLength, -{ - type OutputSize = D::OutputSize; - - #[inline] - fn update(&mut self, data: &[u8]) { - self.digest.update(data); - } - - #[inline] - fn finalize(self) -> Output { - let mut opad_digest = self.opad_digest.clone(); - let hash = self.digest.finalize_fixed(); - opad_digest.update(&hash); - Output::new(opad_digest.finalize_fixed()) - } - - #[inline] - fn reset(&mut self) { - self.digest.reset(); - self.digest.update(&self.i_key_pad); - } -} - -#[cfg(feature = "std")] -impl std::io::Write for Hmac -where - D: Update + BlockInput + FixedOutput + Reset + Default + Clone, - D::BlockSize: ArrayLength, - D::OutputSize: ArrayLength, -{ - fn write(&mut self, buf: &[u8]) -> std::io::Result { - Mac::update(self, buf); - Ok(buf.len()) - } - - fn flush(&mut self) -> std::io::Result<()> { - Ok(()) } + der_key } diff --git a/hmac/src/optim.rs b/hmac/src/optim.rs new file mode 100644 index 0000000..32d6277 --- /dev/null +++ b/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 = CoreWrapper>; + +/// Generic core HMAC instance, which operates over blocks. +pub struct HmacCore +where + D: CoreProxy, + D::Core: HashMarker + + UpdateCore + + FixedOutputCore + + BufferKindUser + + Default + + Clone, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + digest: D::Core, + opad_digest: D::Core, + #[cfg(feature = "reset")] + ipad_digest: D::Core, +} + +impl Clone for HmacCore +where + D: CoreProxy, + D::Core: HashMarker + + UpdateCore + + FixedOutputCore + + BufferKindUser + + Default + + Clone, + ::BlockSize: IsLess, + Le<::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 MacMarker for HmacCore +where + D: CoreProxy, + D::Core: HashMarker + + UpdateCore + + FixedOutputCore + + BufferKindUser + + Default + + Clone, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ +} + +impl BufferKindUser for HmacCore +where + D: CoreProxy, + D::Core: HashMarker + + UpdateCore + + FixedOutputCore + + BufferKindUser + + Default + + Clone, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + type BufferKind = Eager; +} + +impl KeySizeUser for HmacCore +where + D: CoreProxy, + D::Core: HashMarker + + UpdateCore + + FixedOutputCore + + BufferKindUser + + Default + + Clone, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + type KeySize = <::Core as BlockSizeUser>::BlockSize; +} + +impl BlockSizeUser for HmacCore +where + D: CoreProxy, + D::Core: HashMarker + + UpdateCore + + FixedOutputCore + + BufferKindUser + + Default + + Clone, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + type BlockSize = <::Core as BlockSizeUser>::BlockSize; +} + +impl OutputSizeUser for HmacCore +where + D: CoreProxy, + D::Core: HashMarker + + UpdateCore + + FixedOutputCore + + BufferKindUser + + Default + + Clone, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + type OutputSize = <::Core as OutputSizeUser>::OutputSize; +} + +impl KeyInit for HmacCore +where + D: CoreProxy, + D::Core: HashMarker + + UpdateCore + + FixedOutputCore + + BufferKindUser + + Default + + Clone, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + #[inline(always)] + fn new(key: &Key) -> Self { + Self::new_from_slice(key.as_slice()).unwrap() + } + + #[inline(always)] + fn new_from_slice(key: &[u8]) -> Result { + let mut buf = get_der_key::>(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 UpdateCore for HmacCore +where + D: CoreProxy, + D::Core: HashMarker + + UpdateCore + + FixedOutputCore + + BufferKindUser + + Default + + Clone, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + #[inline(always)] + fn update_blocks(&mut self, blocks: &[Block]) { + self.digest.update_blocks(blocks); + } +} + +impl FixedOutputCore for HmacCore +where + D: CoreProxy, + D::Core: HashMarker + + UpdateCore + + FixedOutputCore + + BufferKindUser + + Default + + Clone, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + #[inline(always)] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let mut hash = Output::::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 Reset for HmacCore +where + D: CoreProxy, + D::Core: HashMarker + + UpdateCore + + FixedOutputCore + + BufferKindUser + + Default + + Clone, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + #[inline(always)] + fn reset(&mut self) { + self.digest = self.ipad_digest.clone(); + } +} + +impl AlgorithmName for HmacCore +where + D: CoreProxy, + D::Core: HashMarker + + AlgorithmName + + UpdateCore + + FixedOutputCore + + BufferKindUser + + Default + + Clone, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Hmac<")?; + ::write_alg_name(f)?; + f.write_str(">") + } +} + +impl fmt::Debug for HmacCore +where + D: CoreProxy, + D::Core: HashMarker + + AlgorithmName + + UpdateCore + + FixedOutputCore + + BufferKindUser + + Default + + Clone, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("HmacCore<")?; + ::write_alg_name(f)?; + f.write_str("> { ... }") + } +} diff --git a/hmac/src/simple.rs b/hmac/src/simple.rs new file mode 100644 index 0000000..e28c4c3 --- /dev/null +++ b/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 { + digest: D, + opad_key: Block, + #[cfg(feature = "reset")] + ipad_key: Block, +} + +impl KeySizeUser for SimpleHmac { + type KeySize = D::BlockSize; +} + +impl MacMarker for SimpleHmac {} + +impl KeyInit for SimpleHmac { + fn new(key: &Key) -> Self { + Self::new_from_slice(key.as_slice()).unwrap() + } + + #[inline] + fn new_from_slice(key: &[u8]) -> Result { + let der_key = get_der_key::(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 Update for SimpleHmac { + #[inline(always)] + fn update(&mut self, data: &[u8]) { + self.digest.update(data); + } +} + +impl OutputSizeUser for SimpleHmac { + type OutputSize = D::OutputSize; +} + +impl FixedOutput for SimpleHmac { + fn finalize_into(self, out: &mut Output) { + let mut h = D::new(); + h.update(&self.opad_key); + h.update(&self.digest.finalize()); + h.finalize_into(out); + } +} + +impl fmt::Debug for SimpleHmac { + 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 Reset for SimpleHmac { + 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 FixedOutputReset for SimpleHmac { + fn finalize_into_reset(&mut self, out: &mut Output) { + 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); + } +} diff --git a/hmac/tests/data/wycheproof-sha1.blb b/hmac/tests/data/wycheproof-sha1.blb new file mode 100644 index 0000000000000000000000000000000000000000..a4f8f43632d11124cbf16144fd039242070185f0 GIT binary patch literal 4875 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 literal 0 HcmV?d00001 diff --git a/hmac/tests/data/wycheproof-sha256.blb b/hmac/tests/data/wycheproof-sha256.blb new file mode 100644 index 0000000000000000000000000000000000000000..62f1d3570d4f3ae76580e79070534a08575f8275 GIT binary patch literal 6153 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 b8$-NO;f|OfFYNwB*ONKLecifft2FiT1!u{8 literal 0 HcmV?d00001 diff --git a/hmac/tests/data/wycheproof-sha384.blb b/hmac/tests/data/wycheproof-sha384.blb new file mode 100644 index 0000000000000000000000000000000000000000..69a787437553300cf439bce35bc32175172fd0d1 GIT binary patch literal 7857 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 P4}u4Sjq{2(aC&1f8tN<= literal 0 HcmV?d00001 diff --git a/hmac/tests/data/wycheproof-sha512.blb b/hmac/tests/data/wycheproof-sha512.blb new file mode 100644 index 0000000000000000000000000000000000000000..e061fd554b2d1498f59912cfbe7b86b16af051d1 GIT binary patch literal 9648 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%0AMDm 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 -new_test!(hmac_sha224, "sha224", Hmac); -new_test!(hmac_sha256, "sha256", Hmac); -new_test!(hmac_sha384, "sha384", Hmac); -new_test!(hmac_sha512, "sha512", Hmac); -// Test vectors from R 50.1.113-2016: -// https://tc26.ru/standard/rs/Р 50.1.113-2016.pdf -new_test!(hmac_streebog256, "streebog256", Hmac); -new_test!(hmac_streebog512, "streebog512", Hmac); diff --git a/hmac/tests/optim.rs b/hmac/tests/optim.rs new file mode 100644 index 0000000..02e28c7 --- /dev/null +++ b/hmac/tests/optim.rs @@ -0,0 +1,49 @@ +#[cfg(not(feature = "reset"))] +use digest::new_mac_test as new_test; +#[cfg(feature = "reset")] +use digest::new_resettable_mac_test as new_test; +use hmac::Hmac; +use sha1::Sha1; +use sha2::{Sha224, Sha256, Sha384, Sha512}; +use streebog::{Streebog256, Streebog512}; + +// Test vectors from RFC 2104, plus wiki test +new_test!(rfc2104_hmac_md5, "md5", Hmac); + +// Test vectors from RFC 4231 +new_test!(rfc4231_hmac_sha224, "sha224", Hmac); +new_test!(rfc4231_hmac_sha256, "sha256", Hmac); +new_test!(rfc4231_hmac_sha384, "sha384", Hmac); +new_test!(rfc4231_hmac_sha512, "sha512", Hmac); + +// Tests from Project Wycheproof: +// https://github.com/google/wycheproof +new_test!( + wycheproof_hmac_sha1, + "wycheproof-sha1", + Hmac, + trunc_left, +); +new_test!( + wycheproof_hmac_sha256, + "wycheproof-sha256", + Hmac, + trunc_left, +); +new_test!( + wycheproof_hmac_sha384, + "wycheproof-sha384", + Hmac, + trunc_left, +); +new_test!( + wycheproof_hmac_sha512, + "wycheproof-sha512", + Hmac, + trunc_left, +); + +// Test vectors from R 50.1.113-2016: +// https://tc26.ru/standard/rs/Р 50.1.113-2016.pdf +new_test!(hmac_streebog256, "streebog256", Hmac); +new_test!(hmac_streebog512, "streebog512", Hmac); diff --git a/hmac/tests/simple.rs b/hmac/tests/simple.rs new file mode 100644 index 0000000..f75bea7 --- /dev/null +++ b/hmac/tests/simple.rs @@ -0,0 +1,57 @@ +#[cfg(not(feature = "reset"))] +use digest::new_mac_test as new_test; +#[cfg(feature = "reset")] +use digest::new_resettable_mac_test as new_test; +use hmac::SimpleHmac; +use sha1::Sha1; +use sha2::{Sha224, Sha256, Sha384, Sha512}; +use streebog::{Streebog256, Streebog512}; + +// Test vectors from RFC 2104, plus wiki test +new_test!(rfc2104_simple_hmac_md5, "md5", SimpleHmac); + +// Test vectors from RFC 4231 +new_test!(rfc4231_simple_hmac_sha224, "sha224", SimpleHmac); +new_test!(rfc4231_simple_hmac_sha256, "sha256", SimpleHmac); +new_test!(rfc4231_simple_hmac_sha384, "sha384", SimpleHmac); +new_test!(rfc4231_simple_hmac_sha512, "sha512", SimpleHmac); + +// Tests from Project Wycheproof: +// https://github.com/google/wycheproof +new_test!( + wycheproof_simple_hmac_sha1, + "wycheproof-sha1", + SimpleHmac, + trunc_left, +); +new_test!( + wycheproof_simple_hmac_sha256, + "wycheproof-sha256", + SimpleHmac, + trunc_left, +); +new_test!( + wycheproof_simple_hmac_sha384, + "wycheproof-sha384", + SimpleHmac, + trunc_left, +); +new_test!( + wycheproof_simple_hmac_sha512, + "wycheproof-sha512", + SimpleHmac, + trunc_left, +); + +// Test vectors from R 50.1.113-2016: +// https://tc26.ru/standard/rs/Р 50.1.113-2016.pdf +new_test!( + simple_hmac_streebog256, + "streebog256", + SimpleHmac +); +new_test!( + simple_hmac_streebog512, + "streebog512", + SimpleHmac +);