From e9ca69fd4bb45b71d70e5c45032f848f3d8ddc8f 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: Thu, 11 Feb 2021 03:16:05 +0300 Subject: [PATCH 01/22] Add crypto-common crate --- .github/workflows/crypto-common.yml | 57 ++++++++ Cargo.lock | 9 ++ Cargo.toml | 1 + crypto-common/Cargo.toml | 22 +++ crypto-common/LICENSE-APACHE | 201 ++++++++++++++++++++++++++++ crypto-common/LICENSE-MIT | 25 ++++ crypto-common/README.md | 53 ++++++++ crypto-common/src/core_api.rs | 117 ++++++++++++++++ crypto-common/src/lib.rs | 169 +++++++++++++++++++++++ 9 files changed, 654 insertions(+) create mode 100644 .github/workflows/crypto-common.yml create mode 100644 crypto-common/Cargo.toml create mode 100644 crypto-common/LICENSE-APACHE create mode 100644 crypto-common/LICENSE-MIT create mode 100644 crypto-common/README.md create mode 100644 crypto-common/src/core_api.rs create mode 100644 crypto-common/src/lib.rs diff --git a/.github/workflows/crypto-common.yml b/.github/workflows/crypto-common.yml new file mode 100644 index 000000000..3a91ff660 --- /dev/null +++ b/.github/workflows/crypto-common.yml @@ -0,0 +1,57 @@ +name: crypto-common + +on: + pull_request: + paths: + - "crypto-common/**" + - "Cargo.*" + push: + branches: master + +defaults: + run: + working-directory: crypto-common + +env: + CARGO_INCREMENTAL: 0 + RUSTFLAGS: "-Dwarnings" + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - 1.41.0 # MSRV + - stable + target: + - thumbv7em-none-eabi + - wasm32-unknown-unknown + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + target: ${{ matrix.target }} + override: true + - run: cargo build --no-default-features --release --target ${{ matrix.target }} + test: + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - 1.41.0 # MSRV + - stable + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + - run: cargo check --all-features + - run: cargo test + - run: cargo test --features core-api + - run: cargo test --features rand_core + - run: cargo test --features std + - run: cargo test --all-features diff --git a/Cargo.lock b/Cargo.lock index 8a11576d1..2e45e13e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,6 +140,15 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "crypto-common" +version = "0.1.0" +dependencies = [ + "block-buffer 0.10.0-pre.1", + "generic-array 0.14.4", + "rand_core", +] + [[package]] name = "crypto-mac" version = "0.11.0-pre" diff --git a/Cargo.toml b/Cargo.toml index 9db9bf636..ebf9e0985 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ "aead", "cipher", + "crypto-common", "crypto-mac", "crypto", "digest", diff --git a/crypto-common/Cargo.toml b/crypto-common/Cargo.toml new file mode 100644 index 000000000..7e494e85b --- /dev/null +++ b/crypto-common/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "crypto-common" +description = "Common cryptographic traits" +version = "0.1.0" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" +edition = "2018" +documentation = "https://docs.rs/crypto-common" +repository = "https://github.com/RustCrypto/traits" +keywords = ["crypto", "traits"] +categories = ["cryptography", "no-std"] + +[dependencies] +generic-array = "0.14" +rand_core = { version = "0.6", optional = true } +block-buffer = { version = "0.10.0-pre.1", optional = true } + +[features] +default = ["rand_core", "std", "core-api"] +core-api = ["block-buffer"] +std = [] diff --git a/crypto-common/LICENSE-APACHE b/crypto-common/LICENSE-APACHE new file mode 100644 index 000000000..78173fa2e --- /dev/null +++ b/crypto-common/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/crypto-common/LICENSE-MIT b/crypto-common/LICENSE-MIT new file mode 100644 index 000000000..efb0b5f8b --- /dev/null +++ b/crypto-common/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2021 RustCrypto Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/crypto-common/README.md b/crypto-common/README.md new file mode 100644 index 000000000..70ca758cd --- /dev/null +++ b/crypto-common/README.md @@ -0,0 +1,53 @@ +# RustCrypto: Common Cryptographic Traits + +[![crate][crate-image]][crate-link] +[![Docs][docs-image]][docs-link] +![Apache2/MIT licensed][license-image] +![Rust Version][rustc-image] +[![Project Chat][chat-image]][chat-link] +[![Build Status][build-image]][build-link] + +Common traits used by cryptographic algorithms. Users should generally use +higher-level trait crates instead of this one. + +[Documentation][docs-link] + +## Minimum Supported Rust Version + +Rust **1.41** or higher. + +Minimum supported Rust version can be changed in the future, but it will be +done with a minor version bump. + +## SemVer Policy + +- All on-by-default features of this library are covered by SemVer +- MSRV is considered exempt from SemVer as noted above + +## License + +Licensed under either of: + + * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) + * [MIT license](http://opensource.org/licenses/MIT) + +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, shall be +dual licensed as above, without any additional terms or conditions. + +[//]: # (badges) + +[crate-image]: https://img.shields.io/crates/v/crypto-common.svg +[crate-link]: https://crates.io/crates/crypto-common +[docs-image]: https://docs.rs/crypto-common/badge.svg +[docs-link]: https://docs.rs/crypto-common/ +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +[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/260041-hashes +[build-image]: https://github.com/RustCrypto/traits/workflows/crypto-common/badge.svg?branch=master&event=push +[build-link]: https://github.com/RustCrypto/traits/actions?query=workflow%3Acrypto-common diff --git a/crypto-common/src/core_api.rs b/crypto-common/src/core_api.rs new file mode 100644 index 000000000..95e8d3fe3 --- /dev/null +++ b/crypto-common/src/core_api.rs @@ -0,0 +1,117 @@ +//! Low-level core API traits. +use super::{FinalizeFixed, FinalizeFixedReset, Reset, Update}; +use block_buffer::BlockBuffer; +use core::fmt; +use generic_array::{ArrayLength, GenericArray}; + +/// Trait for types which consume data in blocks. +#[cfg(feature = "core-api")] +#[cfg_attr(docsrs, doc(cfg(feature = "core-api")))] +pub trait UpdateCore { + /// Block size in bytes. + type BlockSize: ArrayLength; + + /// Update state using the provided data blocks. + fn update_blocks(&mut self, blocks: &[GenericArray]); +} + +/// Core trait for hash functions with fixed output size. +#[cfg(feature = "core-api")] +#[cfg_attr(docsrs, doc(cfg(feature = "core-api")))] +pub trait FinalizeFixedCore: UpdateCore { + /// Size of result in bytes. + type OutputSize: ArrayLength; + + /// Finalize state using remaining data stored in the provided block buffer, + /// write result into provided array using and leave value in a dirty state. + fn finalize_fixed_core( + &mut self, + buffer: &mut block_buffer::BlockBuffer, + out: &mut GenericArray, + ); +} + +/// Trait which stores algorithm name constant, used in `Debug` implementations. +pub trait AlgorithmName { + /// Write algorithm name into `f`. + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result; +} + +/// Wrapper around [`UpdateCore`] implementations. +/// +/// It handles data buffering and implements the slice-based traits. +#[derive(Clone, Default)] +pub struct CoreWrapper { + core: T, + buffer: BlockBuffer, +} + +impl CoreWrapper { + /// Create new wrapper from `core`. + #[inline] + pub fn from_core(core: T) -> Self { + let buffer = Default::default(); + Self { core, buffer } + } + + /// Decompose wrapper into inner parts. + #[inline] + pub fn decompose(self) -> (T, BlockBuffer) { + let Self { core, buffer } = self; + (core, buffer) + } +} + +impl CoreWrapper { + /// Apply function to core and buffer, return its result, and reset core and buffer. + pub fn apply_reset( + &mut self, + mut f: impl FnMut(&mut T, &mut BlockBuffer) -> V, + ) -> V { + let Self { core, buffer } = self; + let res = f(core, buffer); + core.reset(); + buffer.reset(); + res + } +} + +impl fmt::Debug for CoreWrapper { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + T::write_alg_name(f)?; + f.write_str(" { .. }") + } +} + +impl Reset for CoreWrapper { + #[inline] + fn reset(&mut self) { + self.core.reset(); + self.buffer.reset(); + } +} + +impl Update for CoreWrapper { + #[inline] + fn update(&mut self, input: &[u8]) { + let Self { core, buffer } = self; + buffer.digest_blocks(input, |blocks| core.update_blocks(blocks)); + } +} + +impl FinalizeFixed for CoreWrapper { + type OutputSize = D::OutputSize; + + #[inline] + fn finalize_into(mut self, out: &mut GenericArray) { + let Self { core, buffer } = &mut self; + core.finalize_fixed_core(buffer, out); + } +} + +impl FinalizeFixedReset for CoreWrapper { + #[inline] + fn finalize_into_reset(&mut self, out: &mut GenericArray) { + self.apply_reset(|core, buffer| core.finalize_fixed_core(buffer, out)); + } +} diff --git a/crypto-common/src/lib.rs b/crypto-common/src/lib.rs new file mode 100644 index 000000000..bc3fb96fc --- /dev/null +++ b/crypto-common/src/lib.rs @@ -0,0 +1,169 @@ +//! Common cryptographic traits. + +#![no_std] +#![cfg_attr(docsrs, feature(doc_cfg))] +#![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" +)] +#![forbid(unsafe_code)] +#![warn(missing_docs, rust_2018_idioms)] + +use core::fmt; +use generic_array::{typenum::Unsigned, ArrayLength, GenericArray}; +#[cfg(feature = "rand_core")] +use rand_core::{CryptoRng, RngCore}; +#[cfg(feature = "std")] +extern crate std; + +#[cfg(feature = "core-api")] +#[cfg_attr(docsrs, doc(cfg(feature = "core-api")))] +pub mod core_api; + +/// Trait for types which can be created from key and nonce. +pub trait FromKeyNonce: Sized { + /// Key size in bytes. + type KeySize: ArrayLength; + + /// Nonce size in bytes. + type NonceSize: ArrayLength; + + /// Create new value from fixed length key and nonce. + fn new( + key: &GenericArray, + nonce: &GenericArray, + ) -> Self; + + /// Create new value from variable length key and nonce. + #[inline] + fn new_from_slices(key: &[u8], nonce: &[u8]) -> Result { + let kl = Self::KeySize::to_usize(); + let nl = Self::NonceSize::to_usize(); + if key.len() != kl || nonce.len() != nl { + Err(InvalidLength) + } else { + let key = GenericArray::from_slice(key); + let nonce = GenericArray::from_slice(nonce); + Ok(Self::new(key, nonce)) + } + } + + /// Generate a random key using the provided [`CryptoRng`]. + #[cfg(feature = "rand_core")] + #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] + #[inline] + fn generate_key(mut rng: impl CryptoRng + RngCore) -> GenericArray { + let mut key = GenericArray::::default(); + rng.fill_bytes(&mut key); + key + } + + /// Generate a random nonce using the provided [`CryptoRng`]. + #[cfg(feature = "rand_core")] + #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] + #[inline] + fn generate_nonce(mut rng: impl CryptoRng + RngCore) -> GenericArray { + let mut nonce = GenericArray::::default(); + rng.fill_bytes(&mut nonce); + nonce + } + + /// Generate random key and nonce using the provided [`CryptoRng`]. + #[cfg(feature = "rand_core")] + #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] + #[inline] + fn generate_key_nonce( + mut rng: impl CryptoRng + RngCore, + ) -> ( + GenericArray, + GenericArray, + ) { + (Self::generate_key(&mut rng), Self::generate_nonce(&mut rng)) + } +} + +/// Trait for types which can be created from key. +pub trait FromKey: Sized { + /// Key size in bytes. + type KeySize: ArrayLength; + + /// Create new value from fixed size key. + fn new(key: &GenericArray) -> Self; + + /// Create new value from variable size key. + fn new_from_slice(key: &[u8]) -> Result { + if key.len() != Self::KeySize::to_usize() { + Err(InvalidLength) + } else { + Ok(Self::new(GenericArray::from_slice(key))) + } + } + + /// Generate a random key using the provided [`CryptoRng`]. + #[cfg(feature = "rand_core")] + #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] + #[inline] + fn generate_key(mut rng: impl CryptoRng + RngCore) -> GenericArray { + let mut key = GenericArray::::default(); + rng.fill_bytes(&mut key); + key + } +} + +/// Trait for types which consume data. +pub trait Update { + /// Update state using the provided data. + fn update(&mut self, data: &[u8]); +} + +/// Trait for types which return fixed-sized result after finalization. +pub trait FinalizeFixed: Sized { + /// Size of result in bytes. + type OutputSize: ArrayLength; + + /// Consume value and write result into provided array. + fn finalize_into(self, out: &mut GenericArray); + + /// Retrieve result and consume the hasher instance. + #[inline] + fn finalize_fixed(self) -> GenericArray { + let mut out = Default::default(); + self.finalize_into(&mut out); + out + } +} + +/// Trait for types which return fixed-sized result after finalization and reset +/// values into its initial state. +pub trait FinalizeFixedReset: FinalizeFixed + Reset { + /// Write result into provided array and reset value to its initial state. + fn finalize_into_reset(&mut self, out: &mut GenericArray); + + /// Retrieve result and reset the hasher instance. + #[inline] + fn finalize_fixed_reset(&mut self) -> GenericArray { + let mut out = Default::default(); + self.finalize_into_reset(&mut out); + out + } +} + +/// Trait for resetting values to initial state. +pub trait Reset { + /// Reset value to its initial state. + fn reset(&mut self); +} + +/// The error type returned when key and/or nonce used in [`FromKey`] +/// or [`FromKeyNonce`] slice-based methods had an invalid length. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub struct InvalidLength; + +impl fmt::Display for InvalidLength { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.write_str("Invalid Length") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidLength {} From a05b621a03a6b1a2601b59114efcf400911d6648 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: Thu, 11 Feb 2021 03:58:38 +0300 Subject: [PATCH 02/22] migrate digest --- Cargo.lock | 2 +- crypto-common/Cargo.toml | 2 +- crypto-common/src/core_api.rs | 23 +++++-- crypto-common/src/lib.rs | 13 ++-- digest/Cargo.toml | 8 +-- digest/src/core_api.rs | 60 ++++++++----------- digest/src/core_api/ct_variable.rs | 2 +- digest/src/core_api/rt_variable.rs | 2 +- digest/src/core_api/update.rs | 96 ------------------------------ digest/src/core_api/xof_reader.rs | 2 +- digest/src/digest.rs | 47 ++++++++++----- digest/src/lib.rs | 53 +---------------- 12 files changed, 97 insertions(+), 213 deletions(-) delete mode 100644 digest/src/core_api/update.rs diff --git a/Cargo.lock b/Cargo.lock index 2e45e13e8..622f8c2cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -183,7 +183,7 @@ name = "digest" version = "0.10.0-pre.3" dependencies = [ "blobby", - "block-buffer 0.10.0-pre.1", + "crypto-common", "generic-array 0.14.4", ] diff --git a/crypto-common/Cargo.toml b/crypto-common/Cargo.toml index 7e494e85b..3e2043c2c 100644 --- a/crypto-common/Cargo.toml +++ b/crypto-common/Cargo.toml @@ -17,6 +17,6 @@ rand_core = { version = "0.6", optional = true } block-buffer = { version = "0.10.0-pre.1", optional = true } [features] -default = ["rand_core", "std", "core-api"] +block-padding = ["block-buffer/block-padding"] core-api = ["block-buffer"] std = [] diff --git a/crypto-common/src/core_api.rs b/crypto-common/src/core_api.rs index 95e8d3fe3..edb93755b 100644 --- a/crypto-common/src/core_api.rs +++ b/crypto-common/src/core_api.rs @@ -1,5 +1,5 @@ //! Low-level core API traits. -use super::{FinalizeFixed, FinalizeFixedReset, Reset, Update}; +use super::{FixedOutput, FixedOutputReset, Reset, Update}; use block_buffer::BlockBuffer; use core::fmt; use generic_array::{ArrayLength, GenericArray}; @@ -18,7 +18,7 @@ pub trait UpdateCore { /// Core trait for hash functions with fixed output size. #[cfg(feature = "core-api")] #[cfg_attr(docsrs, doc(cfg(feature = "core-api")))] -pub trait FinalizeFixedCore: UpdateCore { +pub trait FixedOutputCore: UpdateCore { /// Size of result in bytes. type OutputSize: ArrayLength; @@ -99,7 +99,7 @@ impl Update for CoreWrapper { } } -impl FinalizeFixed for CoreWrapper { +impl FixedOutput for CoreWrapper { type OutputSize = D::OutputSize; #[inline] @@ -109,9 +109,24 @@ impl FinalizeFixed for CoreWrapper { } } -impl FinalizeFixedReset for CoreWrapper { +impl FixedOutputReset for CoreWrapper { #[inline] fn finalize_into_reset(&mut self, out: &mut GenericArray) { self.apply_reset(|core, buffer| core.finalize_fixed_core(buffer, out)); } } + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::io::Write for CoreWrapper { + #[inline] + fn write(&mut self, buf: &[u8]) -> std::io::Result { + Update::update(self, buf); + Ok(buf.len()) + } + + #[inline] + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} diff --git a/crypto-common/src/lib.rs b/crypto-common/src/lib.rs index bc3fb96fc..0189872cc 100644 --- a/crypto-common/src/lib.rs +++ b/crypto-common/src/lib.rs @@ -9,12 +9,17 @@ #![forbid(unsafe_code)] #![warn(missing_docs, rust_2018_idioms)] +#[cfg(feature = "std")] +extern crate std; + use core::fmt; use generic_array::{typenum::Unsigned, ArrayLength, GenericArray}; #[cfg(feature = "rand_core")] use rand_core::{CryptoRng, RngCore}; -#[cfg(feature = "std")] -extern crate std; + +#[cfg(feature = "core-api")] +#[cfg_attr(docsrs, doc(cfg(feature = "core-api")))] +pub use block_buffer; #[cfg(feature = "core-api")] #[cfg_attr(docsrs, doc(cfg(feature = "core-api")))] @@ -117,7 +122,7 @@ pub trait Update { } /// Trait for types which return fixed-sized result after finalization. -pub trait FinalizeFixed: Sized { +pub trait FixedOutput: Sized { /// Size of result in bytes. type OutputSize: ArrayLength; @@ -135,7 +140,7 @@ pub trait FinalizeFixed: Sized { /// Trait for types which return fixed-sized result after finalization and reset /// values into its initial state. -pub trait FinalizeFixedReset: FinalizeFixed + Reset { +pub trait FixedOutputReset: FixedOutput + Reset { /// Write result into provided array and reset value to its initial state. fn finalize_into_reset(&mut self, out: &mut GenericArray); diff --git a/digest/Cargo.toml b/digest/Cargo.toml index 90c050642..7f7dd8286 100644 --- a/digest/Cargo.toml +++ b/digest/Cargo.toml @@ -14,14 +14,14 @@ categories = ["cryptography", "no-std"] [dependencies] generic-array = "0.14" blobby = { version = "0.3", optional = true } -block-buffer = { version = "0.10.0-pre.1", optional = true } +crypto-common = { version = "0.1", path = "../crypto-common/" } [features] alloc = [] -std = ["alloc"] +std = ["alloc", "crypto-common/std"] dev = ["blobby"] -core-api = ["block-buffer"] -block-padding = ["block-buffer/block-padding"] +core-api = ["crypto-common/core-api"] +block-padding = ["crypto-common/block-padding"] [package.metadata.docs.rs] all-features = true diff --git a/digest/src/core_api.rs b/digest/src/core_api.rs index e08a131a5..a1895bacd 100644 --- a/digest/src/core_api.rs +++ b/digest/src/core_api.rs @@ -4,42 +4,20 @@ //! core algorithm wrapped by the wrapper types, which implement the //! higher-level traits. use crate::InvalidOutputSize; -use core::fmt; +use crate::{ExtendableOutput, Reset}; +use crypto_common::block_buffer::BlockBuffer; use generic_array::{ArrayLength, GenericArray}; +pub use crypto_common::core_api::{AlgorithmName, CoreWrapper, FixedOutputCore, UpdateCore}; + mod ct_variable; mod rt_variable; -mod update; mod xof_reader; pub use ct_variable::CtVariableCoreWrapper; pub use rt_variable::RtVariableCoreWrapper; -pub use update::UpdateCoreWrapper; pub use xof_reader::XofReaderCoreWrapper; -/// Trait for updating hasher state with input data divided into blocks. -pub trait UpdateCore { - /// Block size in bytes. - type BlockSize: ArrayLength; - - /// Update the hasher state using the provided data. - fn update_blocks(&mut self, blocks: &[GenericArray]); -} - -/// Core trait for hash functions with fixed output size. -pub trait FixedOutputCore: UpdateCore { - /// Digest output size in bytes. - type OutputSize: ArrayLength; - - /// Retrieve result into provided buffer using remaining data stored - /// in the block buffer and leave hasher in a dirty state. - fn finalize_fixed_core( - &mut self, - buffer: &mut block_buffer::BlockBuffer, - out: &mut GenericArray, - ); -} - /// Core trait for hash functions with extendable (XOF) output size. pub trait ExtendableOutputCore: UpdateCore { /// XOF reader core state. @@ -47,10 +25,7 @@ pub trait ExtendableOutputCore: UpdateCore { /// Retrieve XOF reader using remaining data stored in the block buffer /// and leave hasher in a dirty state. - fn finalize_xof_core( - &mut self, - buffer: &mut block_buffer::BlockBuffer, - ) -> Self::ReaderCore; + fn finalize_xof_core(&mut self, buffer: &mut BlockBuffer) -> Self::ReaderCore; } /// Core reader trait for extendable-output function (XOF) result. @@ -78,14 +53,29 @@ pub trait VariableOutputCore: UpdateCore + Sized { /// `output_size` must be equal to `output_size` used during construction. fn finalize_variable_core( &mut self, - buffer: &mut block_buffer::BlockBuffer, + buffer: &mut BlockBuffer, output_size: usize, f: impl FnOnce(&[u8]), ); } -/// Trait which stores algorithm name constant, used in `Debug` implementations. -pub trait AlgorithmName { - /// Write algorithm name into `f`. - fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result; +impl ExtendableOutput for CoreWrapper { + type Reader = XofReaderCoreWrapper; + + #[inline] + fn finalize_xof(self) -> Self::Reader { + let (core, mut buffer) = self.decompose(); + let core = core.finalize_xof_core(&mut buffer); + buffer.reset(); + Self::Reader { core, buffer } + } + + #[inline] + fn finalize_xof_reset(&mut self) -> Self::Reader { + self.apply_reset(|core, buffer| { + let core = core.finalize_xof_core(buffer); + let buffer = BlockBuffer::::default(); + Self::Reader { core, buffer } + }) + } } diff --git a/digest/src/core_api/ct_variable.rs b/digest/src/core_api/ct_variable.rs index e4e154bfa..5ebdec114 100644 --- a/digest/src/core_api/ct_variable.rs +++ b/digest/src/core_api/ct_variable.rs @@ -1,6 +1,6 @@ use super::{AlgorithmName, FixedOutputCore, UpdateCore, VariableOutputCore}; -use block_buffer::BlockBuffer; use core::{fmt, marker::PhantomData}; +use crypto_common::block_buffer::BlockBuffer; use generic_array::{ typenum::{IsLessOrEqual, LeEq, NonZero}, ArrayLength, GenericArray, diff --git a/digest/src/core_api/rt_variable.rs b/digest/src/core_api/rt_variable.rs index 5e7ceb3e0..6941e7e9a 100644 --- a/digest/src/core_api/rt_variable.rs +++ b/digest/src/core_api/rt_variable.rs @@ -1,7 +1,7 @@ use super::{AlgorithmName, UpdateCore, VariableOutputCore}; use crate::{InvalidOutputSize, Reset, Update, VariableOutput}; -use block_buffer::BlockBuffer; use core::fmt; +use crypto_common::block_buffer::BlockBuffer; use generic_array::typenum::Unsigned; /// Wrapper around [`VariableOutputCore`] which selects output size diff --git a/digest/src/core_api/update.rs b/digest/src/core_api/update.rs deleted file mode 100644 index 67a8ffc49..000000000 --- a/digest/src/core_api/update.rs +++ /dev/null @@ -1,96 +0,0 @@ -use super::{ - AlgorithmName, ExtendableOutputCore, FixedOutputCore, UpdateCore, XofReaderCoreWrapper, -}; -use crate::{ExtendableOutput, FixedOutput, Reset, Update}; -use block_buffer::BlockBuffer; -use core::fmt; -use generic_array::GenericArray; - -/// Wrapper around [`UpdateCore`] implementations. -/// -/// It handles data buffering and implements the mid-level traits. -#[derive(Clone, Default)] -pub struct UpdateCoreWrapper { - core: T, - buffer: BlockBuffer, -} - -impl fmt::Debug for UpdateCoreWrapper { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - T::write_alg_name(f)?; - f.write_str(" { .. }") - } -} - -impl Reset for UpdateCoreWrapper { - #[inline] - fn reset(&mut self) { - self.core = Default::default(); - self.buffer.reset(); - } -} - -impl Update for UpdateCoreWrapper { - #[inline] - fn update(&mut self, input: &[u8]) { - let Self { core, buffer } = self; - buffer.digest_blocks(input, |blocks| core.update_blocks(blocks)); - } -} - -impl FixedOutput for UpdateCoreWrapper { - type OutputSize = D::OutputSize; - - #[inline] - fn finalize_into(mut self, out: &mut GenericArray) { - let Self { core, buffer } = &mut self; - core.finalize_fixed_core(buffer, out); - } - - #[inline] - fn finalize_into_reset(&mut self, out: &mut GenericArray) { - let Self { core, buffer } = self; - core.finalize_fixed_core(buffer, out); - self.reset(); - } -} - -impl ExtendableOutput for UpdateCoreWrapper { - type Reader = XofReaderCoreWrapper; - - #[inline] - fn finalize_xof(mut self) -> Self::Reader { - let Self { core, buffer } = &mut self; - let reader_core = core.finalize_xof_core(buffer); - XofReaderCoreWrapper { - core: reader_core, - buffer: Default::default(), - } - } - - #[inline] - fn finalize_xof_reset(&mut self) -> Self::Reader { - let Self { core, buffer } = self; - let reader_core = core.finalize_xof_core(buffer); - self.reset(); - XofReaderCoreWrapper { - core: reader_core, - buffer: Default::default(), - } - } -} - -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl std::io::Write for UpdateCoreWrapper { - #[inline] - fn write(&mut self, buf: &[u8]) -> std::io::Result { - Update::update(self, buf); - Ok(buf.len()) - } - - #[inline] - fn flush(&mut self) -> std::io::Result<()> { - Ok(()) - } -} diff --git a/digest/src/core_api/xof_reader.rs b/digest/src/core_api/xof_reader.rs index 2942e0627..5d7b83520 100644 --- a/digest/src/core_api/xof_reader.rs +++ b/digest/src/core_api/xof_reader.rs @@ -1,7 +1,7 @@ use super::{AlgorithmName, XofReaderCore}; use crate::XofReader; -use block_buffer::BlockBuffer; use core::fmt; +use crypto_common::block_buffer::BlockBuffer; /// Wrapper around [`XofReaderCore`] implementations. /// diff --git a/digest/src/digest.rs b/digest/src/digest.rs index 5af6958c8..851faa03a 100644 --- a/digest/src/digest.rs +++ b/digest/src/digest.rs @@ -1,4 +1,4 @@ -use super::{FixedOutput, Reset, Update}; +use super::{FixedOutput, FixedOutputReset, Reset, Update}; use generic_array::typenum::Unsigned; use generic_array::{ArrayLength, GenericArray}; @@ -22,17 +22,23 @@ pub trait Digest { /// Retrieve result and consume hasher instance. fn finalize(self) -> Output; - /// Retrieve result and reset hasher instance. - fn finalize_reset(&mut self) -> Output; - /// Write result into provided array and consume the hasher instance. fn finalize_into(self, out: &mut Output); + /// Retrieve result and reset hasher instance. + fn finalize_reset(&mut self) -> Output + where + Self: FixedOutputReset; + /// Write result into provided array and reset the hasher instance. - fn finalize_into_reset(&mut self, out: &mut Output); + fn finalize_into_reset(&mut self, out: &mut Output) + where + Self: FixedOutputReset; /// Reset hasher instance to its initial state. - fn reset(&mut self); + fn reset(&mut self) + where + Self: Reset; /// Get output size of the hasher fn output_size() -> usize; @@ -41,7 +47,7 @@ pub trait Digest { fn digest(data: impl AsRef<[u8]>) -> Output; } -impl Digest for D { +impl Digest for D { type OutputSize = ::OutputSize; #[inline] @@ -66,22 +72,31 @@ impl Digest for D { } #[inline] - fn finalize_reset(&mut self) -> Output { - FixedOutput::finalize_fixed_reset(self) + fn finalize_into(self, out: &mut Output) { + FixedOutput::finalize_into(self, out); } #[inline] - fn finalize_into(self, out: &mut Output) { - FixedOutput::finalize_into(self, out); + fn finalize_reset(&mut self) -> Output + where + Self: FixedOutputReset, + { + FixedOutputReset::finalize_fixed_reset(self) } #[inline] - fn finalize_into_reset(&mut self, out: &mut Output) { - FixedOutput::finalize_into_reset(self, out); + fn finalize_into_reset(&mut self, out: &mut Output) + where + Self: FixedOutputReset, + { + FixedOutputReset::finalize_into_reset(self, out); } #[inline] - fn reset(&mut self) { + fn reset(&mut self) + where + Self: Reset, + { Reset::reset(self) } @@ -92,7 +107,9 @@ impl Digest for D { #[inline] fn digest(data: impl AsRef<[u8]>) -> Output { - Self::digest_fixed(data) + let mut hasher = Self::default(); + hasher.update(data.as_ref()); + hasher.finalize() } } diff --git a/digest/src/lib.rs b/digest/src/lib.rs index 814687dce..0be4efc19 100644 --- a/digest/src/lib.rs +++ b/digest/src/lib.rs @@ -54,62 +54,15 @@ mod digest; mod dyn_digest; pub use crate::digest::{Digest, Output}; +use core::fmt; #[cfg(feature = "core-api")] #[cfg_attr(docsrs, doc(cfg(feature = "core-api")))] -pub use block_buffer; -use core::fmt; +pub use crypto_common::block_buffer; #[cfg(feature = "alloc")] pub use dyn_digest::{DynDigest, InvalidBufferLength}; -use generic_array::ArrayLength; pub use generic_array::{self, typenum::consts, GenericArray}; -/// Trait for updating hasher state with input data. -pub trait Update { - /// Update the hasher state using the provided data. - fn update(&mut self, data: &[u8]); -} - -/// Trait for resetting hasher instances -pub trait Reset { - /// Reset hasher instance to its initial state. - fn reset(&mut self); -} - -/// Trait for returning digest result with the fixed size -pub trait FixedOutput: Sized + Update + Default + Reset { - /// Output size for fixed output digest - type OutputSize: ArrayLength; - - /// Write result into provided array and consume the hasher instance. - fn finalize_into(self, out: &mut GenericArray); - - /// Write result into provided array and reset the hasher instance. - fn finalize_into_reset(&mut self, out: &mut GenericArray); - - /// Retrieve result and consume the hasher instance. - #[inline] - fn finalize_fixed(self) -> GenericArray { - let mut out = Default::default(); - self.finalize_into(&mut out); - out - } - - /// Retrieve result and reset the hasher instance. - #[inline] - fn finalize_fixed_reset(&mut self) -> GenericArray { - let mut out = Default::default(); - self.finalize_into_reset(&mut out); - out - } - - /// Compute hash of `data`. - #[inline] - fn digest_fixed(data: impl AsRef<[u8]>) -> GenericArray { - let mut hasher = Self::default(); - hasher.update(data.as_ref()); - hasher.finalize_fixed() - } -} +pub use crypto_common::{FixedOutput, FixedOutputReset, Reset, Update}; /// Trait for describing readers which are used to extract extendable output /// from XOF (extendable-output function) result. From 5b4e595a327378a9171b070abfc7d65c93ac5ae9 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: Thu, 11 Feb 2021 04:10:53 +0300 Subject: [PATCH 03/22] fix digest bugs --- digest/src/core_api.rs | 6 +++--- digest/src/dev.rs | 4 ++-- digest/src/digest.rs | 15 +-------------- digest/src/dyn_digest.rs | 4 ++-- 4 files changed, 8 insertions(+), 21 deletions(-) diff --git a/digest/src/core_api.rs b/digest/src/core_api.rs index a1895bacd..cc91508e1 100644 --- a/digest/src/core_api.rs +++ b/digest/src/core_api.rs @@ -64,9 +64,9 @@ impl ExtendableOutput for CoreWrapper #[inline] fn finalize_xof(self) -> Self::Reader { - let (core, mut buffer) = self.decompose(); + let (mut core, mut buffer) = self.decompose(); let core = core.finalize_xof_core(&mut buffer); - buffer.reset(); + let buffer = Default::default(); Self::Reader { core, buffer } } @@ -74,7 +74,7 @@ impl ExtendableOutput for CoreWrapper fn finalize_xof_reset(&mut self) -> Self::Reader { self.apply_reset(|core, buffer| { let core = core.finalize_xof_core(buffer); - let buffer = BlockBuffer::::default(); + let buffer = Default::default(); Self::Reader { core, buffer } }) } diff --git a/digest/src/dev.rs b/digest/src/dev.rs index 6799fea90..b53e796a1 100644 --- a/digest/src/dev.rs +++ b/digest/src/dev.rs @@ -33,13 +33,13 @@ macro_rules! new_test { /// Module to separate Digest from other traits mod foo { - use super::super::Digest; + use super::super::{Digest, Reset}; use core::fmt::Debug; /// Digest test pub fn digest_test(input: &[u8], output: &[u8]) -> Option<&'static str> where - D: Digest + Debug + Clone, + D: Digest + Reset + Debug + Clone, { let mut hasher = D::new(); // Test that it works when accepting the message all at once diff --git a/digest/src/digest.rs b/digest/src/digest.rs index 851faa03a..283245c33 100644 --- a/digest/src/digest.rs +++ b/digest/src/digest.rs @@ -1,4 +1,4 @@ -use super::{FixedOutput, FixedOutputReset, Reset, Update}; +use super::{FixedOutput, FixedOutputReset, Update}; use generic_array::typenum::Unsigned; use generic_array::{ArrayLength, GenericArray}; @@ -35,11 +35,6 @@ pub trait Digest { where Self: FixedOutputReset; - /// Reset hasher instance to its initial state. - fn reset(&mut self) - where - Self: Reset; - /// Get output size of the hasher fn output_size() -> usize; @@ -92,14 +87,6 @@ impl Digest for D { FixedOutputReset::finalize_into_reset(self, out); } - #[inline] - fn reset(&mut self) - where - Self: Reset, - { - Reset::reset(self) - } - #[inline] fn output_size() -> usize { Self::OutputSize::to_usize() diff --git a/digest/src/dyn_digest.rs b/digest/src/dyn_digest.rs index f6936badd..09408db59 100644 --- a/digest/src/dyn_digest.rs +++ b/digest/src/dyn_digest.rs @@ -1,7 +1,7 @@ use alloc::boxed::Box; use core::fmt; -use super::{FixedOutput, Reset, Update}; +use super::{FixedOutput, FixedOutputReset, Reset, Update}; use generic_array::{typenum::Unsigned, GenericArray}; /// The `DynDigest` trait is a modification of `Digest` trait suitable @@ -39,7 +39,7 @@ pub trait DynDigest { fn box_clone(&self) -> Box; } -impl DynDigest for D { +impl DynDigest for D { fn update(&mut self, data: &[u8]) { Update::update(self, data); } From 06b804622d388f779bc78fe23d2ffd5a40b7974a 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: Thu, 11 Feb 2021 04:41:43 +0300 Subject: [PATCH 04/22] bump block-buffer to pre.2 --- Cargo.lock | 6 +++--- crypto-common/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 622f8c2cf..d63fd97b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -76,9 +76,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.0-pre.1" +version = "0.10.0-pre.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae646bb58db3c82677a9ebece843b3577e1e2e134067c3e69681ebe1e4c75f02" +checksum = "9bda843099271fe07dc9638389268bf732e981d8a71d7a1472f79eb54cc5a827" dependencies = [ "block-padding", "generic-array 0.14.4", @@ -144,7 +144,7 @@ dependencies = [ name = "crypto-common" version = "0.1.0" dependencies = [ - "block-buffer 0.10.0-pre.1", + "block-buffer 0.10.0-pre.2", "generic-array 0.14.4", "rand_core", ] diff --git a/crypto-common/Cargo.toml b/crypto-common/Cargo.toml index 3e2043c2c..460aa92b6 100644 --- a/crypto-common/Cargo.toml +++ b/crypto-common/Cargo.toml @@ -14,7 +14,7 @@ categories = ["cryptography", "no-std"] [dependencies] generic-array = "0.14" rand_core = { version = "0.6", optional = true } -block-buffer = { version = "0.10.0-pre.1", optional = true } +block-buffer = { version = "0.10.0-pre.2", optional = true } [features] block-padding = ["block-buffer/block-padding"] From c0a2e0185592b1c4c8fe30c007fd3a2a862a3b9b 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: Thu, 11 Feb 2021 04:59:45 +0300 Subject: [PATCH 05/22] impl Reset for CtVariableCoreWrapper --- digest/src/core_api/ct_variable.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/digest/src/core_api/ct_variable.rs b/digest/src/core_api/ct_variable.rs index 5ebdec114..083eae770 100644 --- a/digest/src/core_api/ct_variable.rs +++ b/digest/src/core_api/ct_variable.rs @@ -67,6 +67,18 @@ where } } +impl Default for CtVariableCoreWrapper +where + T: VariableOutputCore, + OutSize: ArrayLength + IsLessOrEqual, + LeEq: NonZero, +{ + #[inline] + fn reset(&mut self) { + *self = Default::default(); + } +} + impl AlgorithmName for CtVariableCoreWrapper where T: VariableOutputCore + AlgorithmName, From 2d14a756752f86173fe1cbd7d242d4905644e0c1 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: Thu, 11 Feb 2021 05:01:22 +0300 Subject: [PATCH 06/22] fix typo --- digest/src/core_api/ct_variable.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/digest/src/core_api/ct_variable.rs b/digest/src/core_api/ct_variable.rs index 083eae770..0b629093f 100644 --- a/digest/src/core_api/ct_variable.rs +++ b/digest/src/core_api/ct_variable.rs @@ -1,4 +1,4 @@ -use super::{AlgorithmName, FixedOutputCore, UpdateCore, VariableOutputCore}; +use super::{AlgorithmName, FixedOutputCore, UpdateCore, VariableOutputCore, Reset}; use core::{fmt, marker::PhantomData}; use crypto_common::block_buffer::BlockBuffer; use generic_array::{ @@ -67,7 +67,7 @@ where } } -impl Default for CtVariableCoreWrapper +impl Reset for CtVariableCoreWrapper where T: VariableOutputCore, OutSize: ArrayLength + IsLessOrEqual, From 124ce52511bdbb30c7dfb62e9021db40cc4ef1e8 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: Thu, 11 Feb 2021 05:03:38 +0300 Subject: [PATCH 07/22] fmt --- digest/src/core_api/ct_variable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/digest/src/core_api/ct_variable.rs b/digest/src/core_api/ct_variable.rs index 0b629093f..b15379a35 100644 --- a/digest/src/core_api/ct_variable.rs +++ b/digest/src/core_api/ct_variable.rs @@ -1,4 +1,4 @@ -use super::{AlgorithmName, FixedOutputCore, UpdateCore, VariableOutputCore, Reset}; +use super::{AlgorithmName, FixedOutputCore, Reset, UpdateCore, VariableOutputCore}; use core::{fmt, marker::PhantomData}; use crypto_common::block_buffer::BlockBuffer; use generic_array::{ From 3087b5ad73f1fb591c1fc9adf435e71ffdb7b400 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: Thu, 11 Feb 2021 06:07:26 +0300 Subject: [PATCH 08/22] migrate cipher --- Cargo.lock | 1 + cipher/Cargo.toml | 3 +- cipher/src/block.rs | 100 +++++++++++++++++++++++++++---------------- cipher/src/common.rs | 94 ---------------------------------------- cipher/src/errors.rs | 16 +------ cipher/src/lib.rs | 4 +- digest/Cargo.toml | 3 +- 7 files changed, 73 insertions(+), 148 deletions(-) delete mode 100644 cipher/src/common.rs diff --git a/Cargo.lock b/Cargo.lock index d63fd97b8..6ddb349ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,6 +110,7 @@ name = "cipher" version = "0.3.0-pre.4" dependencies = [ "blobby", + "crypto-common", "generic-array 0.14.4", "rand_core", ] diff --git a/cipher/Cargo.toml b/cipher/Cargo.toml index b13ee47f4..5ca5e8736 100644 --- a/cipher/Cargo.toml +++ b/cipher/Cargo.toml @@ -13,12 +13,13 @@ categories = ["cryptography", "no-std"] [dependencies] generic-array = "0.14" +crypto-common = { version = "0.1", path = "../crypto-common/" } blobby = { version = "0.3", optional = true } rand_core = { version = "0.6", optional = true } [features] -std = [] +std = ["crypto-common/std"] dev = ["blobby"] [package.metadata.docs.rs] diff --git a/cipher/src/block.rs b/cipher/src/block.rs index 0e39ff90f..257678159 100644 --- a/cipher/src/block.rs +++ b/cipher/src/block.rs @@ -9,15 +9,12 @@ //! [1]: https://en.wikipedia.org/wiki/Block_cipher //! [2]: https://en.wikipedia.org/wiki/Symmetric-key_algorithm -use crate::errors::InvalidLength; use core::convert::TryInto; +use crypto_common::FromKey; use generic_array::{typenum::Unsigned, ArrayLength, GenericArray}; -#[cfg(feature = "rand_core")] -use rand_core::{CryptoRng, RngCore}; - -/// Key for an algorithm that implements [`NewBlockCipher`]. -pub type BlockCipherKey = GenericArray::KeySize>; +/// Key for an algorithm that implements [`FromKey`]. +pub type BlockCipherKey = GenericArray::KeySize>; /// Block on which a [`BlockCipher`] operates. pub type Block = GenericArray::BlockSize>; @@ -25,36 +22,6 @@ pub type Block = GenericArray::BlockSize>; /// Block on which a [`BlockCipher`] operates in parallel. pub type ParBlocks = GenericArray, ::ParBlocks>; -/// Instantiate a [`BlockCipher`] algorithm. -pub trait NewBlockCipher: Sized { - /// Key size in bytes with which cipher guaranteed to be initialized. - type KeySize: ArrayLength; - - /// Create new block cipher instance from key with fixed size. - fn new(key: &BlockCipherKey) -> Self; - - /// Create new block cipher instance from key with variable size. - /// - /// Default implementation will accept only keys with length equal to - /// `KeySize`, but some ciphers can accept range of key lengths. - fn new_from_slice(key: &[u8]) -> Result { - if key.len() != Self::KeySize::to_usize() { - Err(InvalidLength) - } else { - Ok(Self::new(GenericArray::from_slice(key))) - } - } - - /// Generate a random key for this block cipher using the provided [`CryptoRng`]. - #[cfg(feature = "rand_core")] - #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] - fn generate_key(mut rng: impl CryptoRng + RngCore) -> BlockCipherKey { - let mut key = BlockCipherKey::::default(); - rng.fill_bytes(&mut key); - key - } -} - /// Trait which marks a type as being a block cipher. pub trait BlockCipher { /// Size of the block in bytes @@ -209,3 +176,64 @@ impl BlockDecrypt for &Alg { Alg::decrypt_blocks(self, blocks); } } + +/// Trait for types which can be initialized from a block cipher. +pub trait FromBlockCipher { + /// Block cipher + type BlockCipher: BlockCipher; + + /// Instantiate a stream cipher from a block cipher + fn from_block_cipher(cipher: Self::BlockCipher) -> Self; +} + +/// Trait for types which can be initialized from a block cipher and nonce. +pub trait FromBlockCipherNonce { + /// Block cipher + type BlockCipher: BlockCipher; + /// Nonce size in bytes + type NonceSize: ArrayLength; + + /// Instantiate a stream cipher from a block cipher + fn from_block_cipher_nonce( + cipher: Self::BlockCipher, + nonce: &GenericArray, + ) -> Self; +} + +/// Implement [`FromKeyNonce`][crate::FromKeyNonce] for a type which implements [`FromBlockCipherNonce`]. +#[macro_export] +macro_rules! impl_from_key_nonce { + ($name:ty) => { + impl cipher::FromKeyNonce for $name + where + C: FromKey + BlockCipher, + { + type KeySize = C::KeySize; + type NonceSize = ::NonceSize; + + fn new( + key: &GenericArray, + nonce: &GenericArray, + ) -> Self { + Self::from_block_cipher_nonce(C::new(key), nonce) + } + + fn new_from_slices( + key: &[u8], + nonce: &[u8], + ) -> Result { + use cipher::errors::InvalidLength; + if nonce.len() != Self::NonceSize::USIZE { + Err(InvalidLength) + } else { + C::new_from_slice(key) + .map_err(|_| InvalidLength) + .map(|cipher| { + let nonce = GenericArray::from_slice(nonce); + Self::from_block_cipher_nonce(cipher, nonce) + }) + } + } + } + }; +} diff --git a/cipher/src/common.rs b/cipher/src/common.rs deleted file mode 100644 index 849cd95be..000000000 --- a/cipher/src/common.rs +++ /dev/null @@ -1,94 +0,0 @@ -//! Functionality common to block ciphers and stream ciphers - -use crate::{errors::InvalidLength, BlockCipher, NewBlockCipher}; -use generic_array::{typenum::Unsigned, ArrayLength, GenericArray}; - -#[cfg(feature = "rand_core")] -use rand_core::{CryptoRng, RngCore}; - -/// Key for an algorithm that implements [`NewCipher`]. -pub type CipherKey = GenericArray::KeySize>; - -/// Nonce for an algorithm that implements [`NewCipher`]. -pub type Nonce = GenericArray::NonceSize>; - -/// Cipher creation trait. -/// -/// It can be used for creation of block modes, synchronous and asynchronous stream ciphers. -pub trait NewCipher: Sized { - /// Key size in bytes - type KeySize: ArrayLength; - - /// Nonce size in bytes - type NonceSize: ArrayLength; - - /// Create new stream cipher instance from key and nonce arrays. - fn new(key: &CipherKey, nonce: &Nonce) -> Self; - - /// Create new stream cipher instance from variable length key and nonce - /// given as byte slices. - #[inline] - fn new_from_slices(key: &[u8], nonce: &[u8]) -> Result { - let kl = Self::KeySize::to_usize(); - let nl = Self::NonceSize::to_usize(); - if key.len() != kl || nonce.len() != nl { - Err(InvalidLength) - } else { - let key = GenericArray::from_slice(key); - let nonce = GenericArray::from_slice(nonce); - Ok(Self::new(key, nonce)) - } - } - - /// Generate a random key for this cipher using the provided [`CryptoRng`]. - #[cfg(feature = "rand_core")] - #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] - fn generate_key(mut rng: impl CryptoRng + RngCore) -> CipherKey { - let mut key = CipherKey::::default(); - rng.fill_bytes(&mut key); - key - } -} - -/// Trait for types which can be initialized from a block cipher and nonce. -pub trait FromBlockCipher { - /// Block cipher - type BlockCipher: BlockCipher; - /// Nonce size in bytes - type NonceSize: ArrayLength; - - /// Instantiate a stream cipher from a block cipher - fn from_block_cipher( - cipher: Self::BlockCipher, - nonce: &GenericArray, - ) -> Self; -} - -impl NewCipher for C -where - C: FromBlockCipher, - C::BlockCipher: NewBlockCipher, -{ - type KeySize = <::BlockCipher as NewBlockCipher>::KeySize; - type NonceSize = ::NonceSize; - - fn new(key: &CipherKey, nonce: &Nonce) -> C { - C::from_block_cipher( - <::BlockCipher as NewBlockCipher>::new(key), - nonce, - ) - } - - fn new_from_slices(key: &[u8], nonce: &[u8]) -> Result { - if nonce.len() != Self::NonceSize::USIZE { - Err(InvalidLength) - } else { - C::BlockCipher::new_from_slice(key) - .map_err(|_| InvalidLength) - .map(|cipher| { - let nonce = GenericArray::from_slice(nonce); - Self::from_block_cipher(cipher, nonce) - }) - } - } -} diff --git a/cipher/src/errors.rs b/cipher/src/errors.rs index 69235fceb..6dbb5eb25 100644 --- a/cipher/src/errors.rs +++ b/cipher/src/errors.rs @@ -2,6 +2,8 @@ use core::fmt; +pub use crypto_common::InvalidLength; + /// The error type returned when stream cipher has reached the end of a keystream. #[derive(Copy, Clone, Debug)] pub struct LoopError; @@ -15,20 +17,6 @@ impl fmt::Display for LoopError { #[cfg(feature = "std")] impl std::error::Error for LoopError {} -/// The error type returned when key and/or nonce used in stream cipher -/// initialization had an invalid length. -#[derive(Copy, Clone, Debug)] -pub struct InvalidLength; - -impl fmt::Display for InvalidLength { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - f.write_str("Invalid Length") - } -} - -#[cfg(feature = "std")] -impl std::error::Error for InvalidLength {} - /// The error type returned when a cipher position can not be represented /// by the requested type. #[derive(Copy, Clone, Debug)] diff --git a/cipher/src/lib.rs b/cipher/src/lib.rs index d0766d8de..677166666 100644 --- a/cipher/src/lib.rs +++ b/cipher/src/lib.rs @@ -20,11 +20,11 @@ extern crate std; pub use blobby; mod block; -mod common; #[cfg(feature = "dev")] mod dev; pub mod errors; mod stream; -pub use crate::{block::*, common::*, stream::*}; +pub use crate::{block::*, stream::*}; +pub use crypto_common::{FromKey, FromKeyNonce}; pub use generic_array::{self, typenum::consts}; diff --git a/digest/Cargo.toml b/digest/Cargo.toml index 7f7dd8286..d1a884dee 100644 --- a/digest/Cargo.toml +++ b/digest/Cargo.toml @@ -13,9 +13,10 @@ categories = ["cryptography", "no-std"] [dependencies] generic-array = "0.14" -blobby = { version = "0.3", optional = true } crypto-common = { version = "0.1", path = "../crypto-common/" } +blobby = { version = "0.3", optional = true } + [features] alloc = [] std = ["alloc", "crypto-common/std"] From c530bb0c2d304500ff28bacb62100910cbcb8d82 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: Thu, 11 Feb 2021 06:15:58 +0300 Subject: [PATCH 09/22] add impl_from_key macro --- cipher/src/block.rs | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/cipher/src/block.rs b/cipher/src/block.rs index 257678159..c25ddfc1d 100644 --- a/cipher/src/block.rs +++ b/cipher/src/block.rs @@ -204,10 +204,7 @@ pub trait FromBlockCipherNonce { #[macro_export] macro_rules! impl_from_key_nonce { ($name:ty) => { - impl cipher::FromKeyNonce for $name - where - C: FromKey + BlockCipher, - { + impl cipher::FromKeyNonce for $name { type KeySize = C::KeySize; type NonceSize = ::NonceSize; @@ -237,3 +234,23 @@ macro_rules! impl_from_key_nonce { } }; } + +/// Implement [`FromKey`] for a type which implements [`FromBlockCipher`]. +#[macro_export] +macro_rules! impl_from_key { + ($name:ty) => { + impl cipher::FromKey for $name { + type KeySize = C::KeySize; + + fn new(key: &GenericArray) -> Self { + Self::from_block_cipher(C::new(key)) + } + + fn new_from_slices(key: &[u8]) -> Result { + C::new_from_slice(key) + .map_err(|_| cipher::errors::InvalidLength) + .map(|cipher| Self::from_block_cipher(cipher, nonce)) + } + } + }; +} From 9500247904b3b1723f3662ceff2c0d544ce03b39 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: Thu, 11 Feb 2021 06:29:18 +0300 Subject: [PATCH 10/22] migrate crypto-mac --- Cargo.lock | 2 +- crypto-mac/Cargo.toml | 5 +- crypto-mac/src/errors.rs | 27 ---------- crypto-mac/src/lib.rs | 107 ++++++++++----------------------------- 4 files changed, 30 insertions(+), 111 deletions(-) delete mode 100644 crypto-mac/src/errors.rs diff --git a/Cargo.lock b/Cargo.lock index 6ddb349ef..34c837b3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -155,7 +155,7 @@ name = "crypto-mac" version = "0.11.0-pre" dependencies = [ "blobby", - "cipher", + "crypto-common", "generic-array 0.14.4", "rand_core", "subtle", diff --git a/crypto-mac/Cargo.toml b/crypto-mac/Cargo.toml index 12a2036aa..8168c2bdc 100644 --- a/crypto-mac/Cargo.toml +++ b/crypto-mac/Cargo.toml @@ -13,15 +13,16 @@ categories = ["cryptography", "no-std"] [dependencies] generic-array = "0.14" +crypto-common = { version = "0.1", path = "../crypto-common/" } subtle = { version = "2", default-features = false } blobby = { version = "0.3", optional = true } -cipher = { version = "=0.3.0-pre.4", optional = true, path = "../cipher" } rand_core = { version = "0.6", optional = true } [features] dev = ["blobby"] -std = [] +core-api = ["crypto-common/core-api"] +std = ["crypto-common/std"] [package.metadata.docs.rs] all-features = true diff --git a/crypto-mac/src/errors.rs b/crypto-mac/src/errors.rs deleted file mode 100644 index 7bcb0fd34..000000000 --- a/crypto-mac/src/errors.rs +++ /dev/null @@ -1,27 +0,0 @@ -use core::fmt; - -/// Error type for signaling failed MAC verification -#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] -pub struct MacError; - -/// Error type for signaling invalid key length for MAC initialization -#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] -pub struct InvalidKeyLength; - -impl fmt::Display for MacError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("failed MAC verification") - } -} - -impl fmt::Display for InvalidKeyLength { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("invalid key length") - } -} - -#[cfg(feature = "std")] -impl std::error::Error for MacError {} - -#[cfg(feature = "std")] -impl std::error::Error for InvalidKeyLength {} diff --git a/crypto-mac/src/lib.rs b/crypto-mac/src/lib.rs index 60e89112e..a9e85973d 100644 --- a/crypto-mac/src/lib.rs +++ b/crypto-mac/src/lib.rs @@ -21,72 +21,34 @@ use cipher::{BlockCipher, NewBlockCipher}; #[cfg_attr(docsrs, doc(cfg(feature = "dev")))] pub mod dev; -mod errors; - -pub use crate::errors::{InvalidKeyLength, MacError}; +pub use crypto_common::{FixedOutput, FixedOutputReset, FromKey, InvalidLength, Reset, Update}; pub use generic_array::{self, typenum::consts}; -use generic_array::typenum::Unsigned; -use generic_array::{ArrayLength, GenericArray}; +use core::fmt; +use generic_array::GenericArray; use subtle::{Choice, ConstantTimeEq}; #[cfg(feature = "rand_core")] use rand_core::{CryptoRng, RngCore}; -/// Key for an algorithm that implements [`NewMac`]. -pub type Key = GenericArray::KeySize>; - -/// Instantiate a [`Mac`] algorithm. -pub trait NewMac: Sized { - /// Key size in bytes with which cipher guaranteed to be initialized. - type KeySize: ArrayLength; - - /// Initialize new MAC instance from key with fixed size. - fn new(key: &Key) -> Self; - - /// Initialize new MAC instance from key with variable size. - /// - /// Default implementation will accept only keys with length equal to - /// `KeySize`, but some MACs can accept range of key lengths. - fn new_from_slice(key: &[u8]) -> Result { - if key.len() != Self::KeySize::to_usize() { - Err(InvalidKeyLength) - } else { - Ok(Self::new(GenericArray::from_slice(key))) - } - } - - /// Generate a random key for this MAC using the provided [`CryptoRng`]. - #[cfg(feature = "rand_core")] - #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] - fn generate_key(mut rng: impl CryptoRng + RngCore) -> Key { - let mut key = Key::::default(); - rng.fill_bytes(&mut key); - key - } -} - -/// The [`Mac`] trait defines methods for a Message Authentication algorithm. -pub trait Mac: Clone { - /// Output size of the [[`Mac`]] - type OutputSize: ArrayLength; - - /// Update MAC state with the given data. - fn update(&mut self, data: &[u8]); - - /// Reset [`Mac`] instance. - fn reset(&mut self); +/// Key for an algorithm that implements [`FromKey`]. +pub type Key = GenericArray::KeySize>; +/// Convinience super-trait covering functionality of Message Authentication algorithms. +pub trait Mac: FromKey + Update + FixedOutput { /// Obtain the result of a [`Mac`] computation as a [`Output`] and consume /// [`Mac`] instance. - fn finalize(self) -> Output; + fn finalize(self) -> Output { + Output::new(self.finalize_fixed()) + } /// Obtain the result of a [`Mac`] computation as a [`Output`] and reset /// [`Mac`] instance. - fn finalize_reset(&mut self) -> Output { - let res = self.clone().finalize(); - self.reset(); - res + fn finalize_reset(&mut self) -> Output + where + Self: FixedOutputReset, + { + Output::new(self.finalize_fixed_reset()) } /// Check if tag/code value is correct for the processed input. @@ -101,6 +63,8 @@ pub trait Mac: Clone { } } +impl Mac for T {} + /// [`Output`] is a thin wrapper around bytes array which provides a safe `Eq` /// implementation that runs in a fixed time. #[derive(Clone)] @@ -138,34 +102,15 @@ impl PartialEq for Output { impl Eq for Output {} -#[cfg(feature = "cipher")] -#[cfg_attr(docsrs, doc(cfg(feature = "cipher")))] -/// Trait for MAC functions which can be created from block cipher. -pub trait FromBlockCipher { - /// Block cipher type - type Cipher: BlockCipher; - - /// Create new MAC isntance from provided block cipher. - fn from_cipher(cipher: Self::Cipher) -> Self; -} +/// Error type for signaling failed MAC verification +#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] +pub struct MacError; -#[cfg(feature = "cipher")] -#[cfg_attr(docsrs, doc(cfg(feature = "cipher")))] -impl NewMac for T -where - T: FromBlockCipher, - T::Cipher: NewBlockCipher, -{ - type KeySize = <::Cipher as NewBlockCipher>::KeySize; - - fn new(key: &Key) -> Self { - let cipher = ::Cipher::new(key); - Self::from_cipher(cipher) - } - - fn new_from_slice(key: &[u8]) -> Result { - ::Cipher::new_from_slice(key) - .map_err(|_| InvalidKeyLength) - .map(Self::from_cipher) +impl fmt::Display for MacError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("failed MAC verification") } } + +#[cfg(feature = "std")] +impl std::error::Error for MacError {} From 448f61ba46f0d606043acc8df31439733c05ec7a 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: Thu, 11 Feb 2021 06:31:24 +0300 Subject: [PATCH 11/22] remove unused import --- crypto-mac/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/crypto-mac/src/lib.rs b/crypto-mac/src/lib.rs index a9e85973d..0de690951 100644 --- a/crypto-mac/src/lib.rs +++ b/crypto-mac/src/lib.rs @@ -28,9 +28,6 @@ use core::fmt; use generic_array::GenericArray; use subtle::{Choice, ConstantTimeEq}; -#[cfg(feature = "rand_core")] -use rand_core::{CryptoRng, RngCore}; - /// Key for an algorithm that implements [`FromKey`]. pub type Key = GenericArray::KeySize>; From 5b18648972a53383a81b62fc8e64030d089b6a01 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: Thu, 11 Feb 2021 06:36:22 +0300 Subject: [PATCH 12/22] fix crypto-mac workflow --- .github/workflows/crypto-mac.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/crypto-mac.yml b/.github/workflows/crypto-mac.yml index 5336c0319..15caa59ed 100644 --- a/.github/workflows/crypto-mac.yml +++ b/.github/workflows/crypto-mac.yml @@ -52,8 +52,8 @@ jobs: profile: minimal toolchain: ${{ matrix.rust }} - run: cargo check --all-features - - run: cargo test --release - - run: cargo test --features cipher --release - - run: cargo test --features dev --release - - run: cargo test --features std --release - - run: cargo test --all-features --release + - run: cargo test + - run: cargo test --features core-api + - run: cargo test --features dev + - run: cargo test --features std + - run: cargo test --all-features From 472da7db362c0664e28d3ee4def81cb279f85121 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: Thu, 11 Feb 2021 06:47:40 +0300 Subject: [PATCH 13/22] remove FromBlockCipher --- cipher/src/block.rs | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/cipher/src/block.rs b/cipher/src/block.rs index c25ddfc1d..123b600b6 100644 --- a/cipher/src/block.rs +++ b/cipher/src/block.rs @@ -177,15 +177,6 @@ impl BlockDecrypt for &Alg { } } -/// Trait for types which can be initialized from a block cipher. -pub trait FromBlockCipher { - /// Block cipher - type BlockCipher: BlockCipher; - - /// Instantiate a stream cipher from a block cipher - fn from_block_cipher(cipher: Self::BlockCipher) -> Self; -} - /// Trait for types which can be initialized from a block cipher and nonce. pub trait FromBlockCipherNonce { /// Block cipher @@ -204,7 +195,7 @@ pub trait FromBlockCipherNonce { #[macro_export] macro_rules! impl_from_key_nonce { ($name:ty) => { - impl cipher::FromKeyNonce for $name { + impl cipher::FromKeyNonce for $name { type KeySize = C::KeySize; type NonceSize = ::NonceSize; @@ -235,21 +226,24 @@ macro_rules! impl_from_key_nonce { }; } -/// Implement [`FromKey`] for a type which implements [`FromBlockCipher`]. +/// Implement [`FromKey`] for a type which implements [`From`][From], +/// where `C` implements [`FromKey`]. #[macro_export] macro_rules! impl_from_key { ($name:ty) => { - impl cipher::FromKey for $name { + impl cipher::FromKey for $name + where Self: From, + { type KeySize = C::KeySize; fn new(key: &GenericArray) -> Self { - Self::from_block_cipher(C::new(key)) + C::new(key).into() } - fn new_from_slices(key: &[u8]) -> Result { + fn new_from_slice(key: &[u8]) -> Result { C::new_from_slice(key) .map_err(|_| cipher::errors::InvalidLength) - .map(|cipher| Self::from_block_cipher(cipher, nonce)) + .map(|cipher| cipher.into()) } } }; From f333076b4ec7982df2537f6d60672fbf02b756bf 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: Thu, 11 Feb 2021 06:49:32 +0300 Subject: [PATCH 14/22] fmt --- cipher/src/block.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cipher/src/block.rs b/cipher/src/block.rs index 123b600b6..cb0ac09be 100644 --- a/cipher/src/block.rs +++ b/cipher/src/block.rs @@ -232,7 +232,8 @@ macro_rules! impl_from_key_nonce { macro_rules! impl_from_key { ($name:ty) => { impl cipher::FromKey for $name - where Self: From, + where + Self: From, { type KeySize = C::KeySize; From 8c5110ba0cc8f8315e96a3a6f69dbd83abd913bb 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: Thu, 11 Feb 2021 07:01:53 +0300 Subject: [PATCH 15/22] fix impl_from_key_nonce --- cipher/src/block.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/cipher/src/block.rs b/cipher/src/block.rs index cb0ac09be..30076ba16 100644 --- a/cipher/src/block.rs +++ b/cipher/src/block.rs @@ -195,26 +195,31 @@ pub trait FromBlockCipherNonce { #[macro_export] macro_rules! impl_from_key_nonce { ($name:ty) => { - impl cipher::FromKeyNonce for $name { - type KeySize = C::KeySize; + impl crate::FromKeyNonce for $name + where + Self: FromBlockCipherNonce, + ::BlockCipher: FromKey, + { + type KeySize = <::BlockCipher as FromKey>::KeySize; type NonceSize = ::NonceSize; fn new( key: &GenericArray, nonce: &GenericArray, ) -> Self { - Self::from_block_cipher_nonce(C::new(key), nonce) + let cipher = ::BlockCipher::new(key); + Self::from_block_cipher_nonce(cipher, nonce) } fn new_from_slices( key: &[u8], nonce: &[u8], - ) -> Result { - use cipher::errors::InvalidLength; + ) -> Result { + use crate::errors::InvalidLength; if nonce.len() != Self::NonceSize::USIZE { Err(InvalidLength) } else { - C::new_from_slice(key) + ::BlockCipher::new_from_slice(key) .map_err(|_| InvalidLength) .map(|cipher| { let nonce = GenericArray::from_slice(nonce); From 4c647462f36d0b52bd0a2eb88b7ee2c3d2521f45 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: Thu, 11 Feb 2021 07:08:17 +0300 Subject: [PATCH 16/22] add core-api to crypto-mac --- crypto-mac/src/core_api.rs | 2 ++ crypto-mac/src/lib.rs | 4 ++++ 2 files changed, 6 insertions(+) create mode 100644 crypto-mac/src/core_api.rs diff --git a/crypto-mac/src/core_api.rs b/crypto-mac/src/core_api.rs new file mode 100644 index 000000000..ed6dfb6b4 --- /dev/null +++ b/crypto-mac/src/core_api.rs @@ -0,0 +1,2 @@ +//! Low-level core API traits. +pub use crypto_common::core_api::{AlgorithmName, CoreWrapper, FixedOutputCore, UpdateCore}; \ No newline at end of file diff --git a/crypto-mac/src/lib.rs b/crypto-mac/src/lib.rs index 0de690951..2cebf8277 100644 --- a/crypto-mac/src/lib.rs +++ b/crypto-mac/src/lib.rs @@ -21,6 +21,10 @@ use cipher::{BlockCipher, NewBlockCipher}; #[cfg_attr(docsrs, doc(cfg(feature = "dev")))] pub mod dev; +#[cfg(feature = "core-api")] +#[cfg_attr(docsrs, doc(cfg(feature = "core-api")))] +pub mod core_api; + pub use crypto_common::{FixedOutput, FixedOutputReset, FromKey, InvalidLength, Reset, Update}; pub use generic_array::{self, typenum::consts}; From 7f48e7764d457c6fefcbe9ea89b6e331342b6648 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: Thu, 11 Feb 2021 07:10:33 +0300 Subject: [PATCH 17/22] fmt --- crypto-mac/src/core_api.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto-mac/src/core_api.rs b/crypto-mac/src/core_api.rs index ed6dfb6b4..7f7e6a6ec 100644 --- a/crypto-mac/src/core_api.rs +++ b/crypto-mac/src/core_api.rs @@ -1,2 +1,2 @@ //! Low-level core API traits. -pub use crypto_common::core_api::{AlgorithmName, CoreWrapper, FixedOutputCore, UpdateCore}; \ No newline at end of file +pub use crypto_common::core_api::{AlgorithmName, CoreWrapper, FixedOutputCore, UpdateCore}; From 82b0c9c1aeac188c58fa4fe49ace48a79706421e 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: Fri, 12 Feb 2021 02:24:47 +0300 Subject: [PATCH 18/22] generalize over block buffer type --- Cargo.lock | 6 ++---- Cargo.toml | 3 +++ crypto-common/src/core_api.rs | 15 +++++++++------ crypto-mac/Cargo.toml | 1 + digest/src/core_api.rs | 5 ++--- digest/src/core_api/ct_variable.rs | 4 ++-- digest/src/core_api/rt_variable.rs | 4 ++-- 7 files changed, 21 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34c837b3f..4bc1afbab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,8 +77,7 @@ dependencies = [ [[package]] name = "block-buffer" version = "0.10.0-pre.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bda843099271fe07dc9638389268bf732e981d8a71d7a1472f79eb54cc5a827" +source = "git+https://github.com/RustCrypto/utils?branch=lazy#5730141d1970a047242cfb1e5b65d06db1486d90" dependencies = [ "block-padding", "generic-array 0.14.4", @@ -87,8 +86,7 @@ dependencies = [ [[package]] name = "block-padding" version = "0.3.0-pre" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3992d179d1dd2fa87869057217d43cf88ad31d4e44738d159a5a6caafdf63ae6" +source = "git+https://github.com/RustCrypto/utils?branch=lazy#5730141d1970a047242cfb1e5b65d06db1486d90" dependencies = [ "generic-array 0.14.4", ] diff --git a/Cargo.toml b/Cargo.toml index ebf9e0985..35d2ecc26 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,6 @@ members = [ "signature/async", "universal-hash", ] + +[patch.crates-io] +block-buffer = { git = "https://github.com/RustCrypto/utils", branch = "lazy" } diff --git a/crypto-common/src/core_api.rs b/crypto-common/src/core_api.rs index edb93755b..95f7283e3 100644 --- a/crypto-common/src/core_api.rs +++ b/crypto-common/src/core_api.rs @@ -1,6 +1,6 @@ //! Low-level core API traits. use super::{FixedOutput, FixedOutputReset, Reset, Update}; -use block_buffer::BlockBuffer; +use block_buffer::DigestBuffer; use core::fmt; use generic_array::{ArrayLength, GenericArray}; @@ -10,6 +10,8 @@ use generic_array::{ArrayLength, GenericArray}; pub trait UpdateCore { /// Block size in bytes. type BlockSize: ArrayLength; + /// Block buffer type over which value operates. + type Buffer: DigestBuffer; /// Update state using the provided data blocks. fn update_blocks(&mut self, blocks: &[GenericArray]); @@ -26,7 +28,7 @@ pub trait FixedOutputCore: UpdateCore { /// write result into provided array using and leave value in a dirty state. fn finalize_fixed_core( &mut self, - buffer: &mut block_buffer::BlockBuffer, + buffer: &mut Self::Buffer, out: &mut GenericArray, ); } @@ -43,7 +45,7 @@ pub trait AlgorithmName { #[derive(Clone, Default)] pub struct CoreWrapper { core: T, - buffer: BlockBuffer, + buffer: T::Buffer, } impl CoreWrapper { @@ -56,17 +58,18 @@ impl CoreWrapper { /// Decompose wrapper into inner parts. #[inline] - pub fn decompose(self) -> (T, BlockBuffer) { + pub fn decompose(self) -> (T, T::Buffer) { let Self { core, buffer } = self; (core, buffer) } } impl CoreWrapper { - /// Apply function to core and buffer, return its result, and reset core and buffer. + /// Apply function to core and buffer, return its result, + /// and reset core and buffer. pub fn apply_reset( &mut self, - mut f: impl FnMut(&mut T, &mut BlockBuffer) -> V, + mut f: impl FnMut(&mut T, &mut T::Buffer) -> V, ) -> V { let Self { core, buffer } = self; let res = f(core, buffer); diff --git a/crypto-mac/Cargo.toml b/crypto-mac/Cargo.toml index 8168c2bdc..b9df0ac53 100644 --- a/crypto-mac/Cargo.toml +++ b/crypto-mac/Cargo.toml @@ -20,6 +20,7 @@ blobby = { version = "0.3", optional = true } rand_core = { version = "0.6", optional = true } [features] +default = ["core-api"] dev = ["blobby"] core-api = ["crypto-common/core-api"] std = ["crypto-common/std"] diff --git a/digest/src/core_api.rs b/digest/src/core_api.rs index cc91508e1..63e573d33 100644 --- a/digest/src/core_api.rs +++ b/digest/src/core_api.rs @@ -5,7 +5,6 @@ //! higher-level traits. use crate::InvalidOutputSize; use crate::{ExtendableOutput, Reset}; -use crypto_common::block_buffer::BlockBuffer; use generic_array::{ArrayLength, GenericArray}; pub use crypto_common::core_api::{AlgorithmName, CoreWrapper, FixedOutputCore, UpdateCore}; @@ -25,7 +24,7 @@ pub trait ExtendableOutputCore: UpdateCore { /// Retrieve XOF reader using remaining data stored in the block buffer /// and leave hasher in a dirty state. - fn finalize_xof_core(&mut self, buffer: &mut BlockBuffer) -> Self::ReaderCore; + fn finalize_xof_core(&mut self, buffer: &mut Self::Buffer) -> Self::ReaderCore; } /// Core reader trait for extendable-output function (XOF) result. @@ -53,7 +52,7 @@ pub trait VariableOutputCore: UpdateCore + Sized { /// `output_size` must be equal to `output_size` used during construction. fn finalize_variable_core( &mut self, - buffer: &mut BlockBuffer, + buffer: &mut Self::Buffer, output_size: usize, f: impl FnOnce(&[u8]), ); diff --git a/digest/src/core_api/ct_variable.rs b/digest/src/core_api/ct_variable.rs index b15379a35..11474326f 100644 --- a/digest/src/core_api/ct_variable.rs +++ b/digest/src/core_api/ct_variable.rs @@ -1,6 +1,5 @@ use super::{AlgorithmName, FixedOutputCore, Reset, UpdateCore, VariableOutputCore}; use core::{fmt, marker::PhantomData}; -use crypto_common::block_buffer::BlockBuffer; use generic_array::{ typenum::{IsLessOrEqual, LeEq, NonZero}, ArrayLength, GenericArray, @@ -26,6 +25,7 @@ where LeEq: NonZero, { type BlockSize = T::BlockSize; + type Buffer = T::Buffer; #[inline] fn update_blocks(&mut self, blocks: &[GenericArray]) { @@ -44,7 +44,7 @@ where #[inline] fn finalize_fixed_core( &mut self, - buffer: &mut BlockBuffer, + buffer: &mut Self::Buffer, out: &mut GenericArray, ) { self.inner diff --git a/digest/src/core_api/rt_variable.rs b/digest/src/core_api/rt_variable.rs index 6941e7e9a..c9af06ae3 100644 --- a/digest/src/core_api/rt_variable.rs +++ b/digest/src/core_api/rt_variable.rs @@ -1,7 +1,7 @@ use super::{AlgorithmName, UpdateCore, VariableOutputCore}; use crate::{InvalidOutputSize, Reset, Update, VariableOutput}; use core::fmt; -use crypto_common::block_buffer::BlockBuffer; +use crypto_common::block_buffer::DigestBuffer; use generic_array::typenum::Unsigned; /// Wrapper around [`VariableOutputCore`] which selects output size @@ -12,7 +12,7 @@ where T: VariableOutputCore + UpdateCore, { core: T, - buffer: BlockBuffer, + buffer: T::Buffer, output_size: usize, } From 1fa8f220daefab164caeedcbc10bfca0310a6a31 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: Fri, 12 Feb 2021 02:25:40 +0300 Subject: [PATCH 19/22] remove default features --- crypto-mac/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/crypto-mac/Cargo.toml b/crypto-mac/Cargo.toml index b9df0ac53..8168c2bdc 100644 --- a/crypto-mac/Cargo.toml +++ b/crypto-mac/Cargo.toml @@ -20,7 +20,6 @@ blobby = { version = "0.3", optional = true } rand_core = { version = "0.6", optional = true } [features] -default = ["core-api"] dev = ["blobby"] core-api = ["crypto-common/core-api"] std = ["crypto-common/std"] From 7a99773503e6dcc76a118373b2eb234ed4d48e05 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: Fri, 12 Feb 2021 02:36:55 +0300 Subject: [PATCH 20/22] fmt --- crypto-common/src/core_api.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crypto-common/src/core_api.rs b/crypto-common/src/core_api.rs index 95f7283e3..7def7a076 100644 --- a/crypto-common/src/core_api.rs +++ b/crypto-common/src/core_api.rs @@ -67,10 +67,7 @@ impl CoreWrapper { impl CoreWrapper { /// Apply function to core and buffer, return its result, /// and reset core and buffer. - pub fn apply_reset( - &mut self, - mut f: impl FnMut(&mut T, &mut T::Buffer) -> V, - ) -> V { + pub fn apply_reset(&mut self, mut f: impl FnMut(&mut T, &mut T::Buffer) -> V) -> V { let Self { core, buffer } = self; let res = f(core, buffer); core.reset(); From cacb281b9a5fcf64b925802e0dbdcd50b595fc06 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: Fri, 12 Feb 2021 13:36:28 +0300 Subject: [PATCH 21/22] revert removal of variable_test --- digest/src/dev.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/digest/src/dev.rs b/digest/src/dev.rs index b53e796a1..926ebbd53 100644 --- a/digest/src/dev.rs +++ b/digest/src/dev.rs @@ -2,7 +2,7 @@ pub use blobby; -use super::{ExtendableOutput, Reset, Update, XofReader}; +use super::{ExtendableOutput, Reset, Update, VariableOutput, XofReader}; use core::fmt::Debug; /// Define test @@ -164,6 +164,56 @@ where None } +/// Variable-output digest test +pub fn variable_test(input: &[u8], output: &[u8]) -> Option<&'static str> +where + D: Update + VariableOutput + Reset + Debug + Clone, +{ + let mut hasher = D::new(output.len()).unwrap(); + let mut buf = [0u8; 128]; + let buf = &mut buf[..output.len()]; + // Test that it works when accepting the message all at once + hasher.update(input); + let mut hasher2 = hasher.clone(); + hasher.finalize_variable(|res| buf.copy_from_slice(res)); + if buf != output { + return Some("whole message"); + } + + // Test if reset works correctly + hasher2.reset(); + hasher2.update(input); + hasher2.finalize_variable(|res| buf.copy_from_slice(res)); + if buf != output { + return Some("whole message after reset"); + } + + // Test that it works when accepting the message in pieces + let mut hasher = D::new(output.len()).unwrap(); + let len = input.len(); + let mut left = len; + while left > 0 { + let take = (left + 1) / 2; + hasher.update(&input[len - left..take + len - left]); + left -= take; + } + hasher.finalize_variable(|res| buf.copy_from_slice(res)); + if buf != output { + return Some("message in pieces"); + } + + // Test processing byte-by-byte + let mut hasher = D::new(output.len()).unwrap(); + for chunk in input.chunks(1) { + hasher.update(chunk) + } + hasher.finalize_variable(|res| buf.copy_from_slice(res)); + if buf != output { + return Some("message byte-by-byte"); + } + None +} + /// Define benchmark #[macro_export] #[cfg_attr(docsrs, doc(cfg(feature = "dev")))] From f5d4a866e9faf80c933cab099e426e7185e5f423 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?= Date: Fri, 26 Feb 2021 15:42:53 +0300 Subject: [PATCH 22/22] use utils' master branch --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cea9a1579..3ca909455 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,7 +77,7 @@ dependencies = [ [[package]] name = "block-buffer" version = "0.10.0-pre.2" -source = "git+https://github.com/RustCrypto/utils?branch=lazy#5730141d1970a047242cfb1e5b65d06db1486d90" +source = "git+https://github.com/RustCrypto/utils?branch=master#47b80c33dd1d83d02426152f681ab2c3acd7e40e" dependencies = [ "block-padding", "generic-array 0.14.4", @@ -86,7 +86,7 @@ dependencies = [ [[package]] name = "block-padding" version = "0.3.0-pre" -source = "git+https://github.com/RustCrypto/utils?branch=lazy#5730141d1970a047242cfb1e5b65d06db1486d90" +source = "git+https://github.com/RustCrypto/utils?branch=master#47b80c33dd1d83d02426152f681ab2c3acd7e40e" dependencies = [ "generic-array 0.14.4", ] diff --git a/Cargo.toml b/Cargo.toml index 35d2ecc26..95aa71a0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,4 +14,4 @@ members = [ ] [patch.crates-io] -block-buffer = { git = "https://github.com/RustCrypto/utils", branch = "lazy" } +block-buffer = { git = "https://github.com/RustCrypto/utils", branch = "master" }