From dca8f8b40e7f851531ffdbc69fadc58c8b45f1a6 Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Fri, 4 Oct 2024 17:01:36 -0400 Subject: [PATCH 01/17] Add ANSI-X9.63-KDF support: add ansi-x963-kdf crate --- Cargo.lock | 11 ++++++++++- Cargo.toml | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7c002ca..858fd1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "ansi-x963-kdf" +version = "0.1.0" +dependencies = [ + "digest", + "hex-literal", + "sha2", +] + [[package]] name = "blobby" version = "0.3.1" @@ -82,7 +91,7 @@ checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" [[package]] name = "hkdf" -version = "0.13.0-pre.3" +version = "0.13.0-pre.4" dependencies = [ "blobby", "hex-literal", diff --git a/Cargo.toml b/Cargo.toml index 119ab97..00e0ff2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ resolver = "2" members = [ "hkdf", - "concat-kdf", + "concat-kdf", "ansi-x963-kdf", ] [profile.dev] From 87acb51abc41b85c04c0038c09bbecd94cf373ac Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Fri, 4 Oct 2024 17:01:48 -0400 Subject: [PATCH 02/17] Add ANSI-X9.63-KDF support: add ansi-x963-kdf information --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 1df026d..84908e9 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Collection of [Key Derivation Functions][KDF] (KDF) written in pure Rust. |--------------|----------------|:---------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------:|:-----------------------:| | [HKDF] | [`hkdf`] | [![crates.io](https://img.shields.io/crates/v/hkdf.svg)](https://crates.io/crates/hkdf) | [![Documentation](https://docs.rs/hkdf/badge.svg)](https://docs.rs/hkdf) | ![MSRV 1.41][msrv-1.72] | | [Concat-KDF] | [`concat-kdf`] | [![crates.io](https://img.shields.io/crates/v/concat-kdf.svg)](https://crates.io/crates/concat-kdf) | [![Documentation](https://docs.rs/concat-kdf/badge.svg)](https://docs.rs/concat-kdf) | ![MSRV 1.56][msrv-1.72] | +| [ANSI-X9.63-KDF] | [`ansi-x963-kdf`] | [![crates.io](https://img.shields.io/crates/v/ansi-x963-kdf.svg)](https://crates.io/crates/ansi-x963-kdf) | [![Documentation](https://docs.rs/ansi-x963-kdf/badge.svg)](https://docs.rs/ansi-x963-kdf) | ![MSRV 1.56][msrv-1.72] | *NOTE: for password-based KDFs (e.g. Argon2, PBKDF2, scrypt), please see [RustCrypto/password-hashes]* @@ -43,10 +44,12 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [`hkdf`]: ./hkdf [`concat-kdf`]: ./concat-kdf +[`ansi-x963-kdf`]: ./ansi-x963-kdf [//]: # (algorithms) [KDF]: https://en.wikipedia.org/wiki/Key_derivation_function [HKDF]: https://en.wikipedia.org/wiki/HKDF [Concat-KDF]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-56ar.pdf +[ANSI-X9.63-KDF]: https://www.secg.org/sec1-v2.pdf [RustCrypto/password-hashes]: https://github.com/RustCrypto/password-hashes From cf0d27a0d1cc866cea4f27343d5382e1ac69e070 Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Fri, 4 Oct 2024 17:02:22 -0400 Subject: [PATCH 03/17] Add ANSI-X9.63-KDF support: add implementation and tests --- ansi-x963-kdf/CHANGELOG.md | 8 ++ ansi-x963-kdf/Cargo.toml | 28 ++++ ansi-x963-kdf/README.md | 59 +++++++++ ansi-x963-kdf/src/lib.rs | 121 +++++++++++++++++ ansi-x963-kdf/tests/tests.rs | 247 +++++++++++++++++++++++++++++++++++ 5 files changed, 463 insertions(+) create mode 100644 ansi-x963-kdf/CHANGELOG.md create mode 100644 ansi-x963-kdf/Cargo.toml create mode 100644 ansi-x963-kdf/README.md create mode 100644 ansi-x963-kdf/src/lib.rs create mode 100644 ansi-x963-kdf/tests/tests.rs diff --git a/ansi-x963-kdf/CHANGELOG.md b/ansi-x963-kdf/CHANGELOG.md new file mode 100644 index 0000000..2e1cc9c --- /dev/null +++ b/ansi-x963-kdf/CHANGELOG.md @@ -0,0 +1,8 @@ +# Changelog +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.1.0 (2024-04-10) +- Initial release diff --git a/ansi-x963-kdf/Cargo.toml b/ansi-x963-kdf/Cargo.toml new file mode 100644 index 0000000..53db848 --- /dev/null +++ b/ansi-x963-kdf/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "ansi-x963-kdf" +version = "0.1.0" +description = "ANSI X9.63 Key Derivation Function (ANSI-X9.63-KDF)" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" +edition = "2021" +documentation = "https://docs.rs/ansi-x963-kdf" +repository = "https://github.com/RustCrypto/KDFs" +keywords = ["crypto", "ansi-x963-kdf", "KDF", "SEC1"] +categories = ["cryptography", "no-std"] +rust-version = "1.72" + +[dependencies] +digest = "=0.11.0-pre.9" + +[dev-dependencies] +hex-literal = "0.4" +sha2 = { version = "=0.11.0-pre.4", default-features = false } + +[features] +std = [] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + diff --git a/ansi-x963-kdf/README.md b/ansi-x963-kdf/README.md new file mode 100644 index 0000000..eda8bd3 --- /dev/null +++ b/ansi-x963-kdf/README.md @@ -0,0 +1,59 @@ +# RustCrypto: ANSI X9.63 Key Derivation Function (ANSI-X9.63-KDF) + +[![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] + +Pure Rust implementation of the ANSI X9.63 Key Derivation Function (ANSI-X9.63-KDF) generic over hash function. +This function is described in the section 3.6.1 of [SEC 1: Elliptic Curve Cryptography](http://www.secg.org/sec1-v2.pdf). + +# Usage + +The most common way to use ANSI-X9.63-KDF is as follows: you generate a shared secret with other party (e.g. via Diffie-Hellman algorithm) +and use key derivation function to derive a shared key. + +```rust +let mut key = [0u8; 32]; +ansi_x963_kdf::derive_key_into::(b"shared-secret", b"other-info", &mut key).unwrap(); +``` + +## Minimum Supported Rust Version + +Rust **1.72** 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. + +[crate-image]: https://img.shields.io/crates/v/ansi-x963-kdf.svg +[crate-link]: https://crates.io/crates/ansi-x963-kdf +[docs-image]: https://docs.rs/ansi-x963-kdf/badge.svg +[docs-link]: https://docs.rs/ansi-x963-kdf/ +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.72+-blue.svg +[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg +[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260043-KDFs +[build-image]: https://github.com/RustCrypto/KDFs/workflows/ansi-x963-kdf/badge.svg?branch=master&event=push +[build-link]: https://github.com/RustCrypto/KDFs/actions?query=workflow:ansi-x963-kdf diff --git a/ansi-x963-kdf/src/lib.rs b/ansi-x963-kdf/src/lib.rs new file mode 100644 index 0000000..a19053c --- /dev/null +++ b/ansi-x963-kdf/src/lib.rs @@ -0,0 +1,121 @@ +//! An implementation of ANSI-X9.63 KDF Key Derivation Function. +//! +//! This function is described in the section 3.6.1 of [SEC 1: Elliptic Curve Cryptography][1]. +//! +//! # Usage +//! +//! The most common way to use ANSI-X9.63 KDF is as follows: you generate a shared secret +//! with other party (e.g. via Diffie-Hellman algorithm) and use key derivation function +//! to derive a shared key. +//! +//! ```rust +//! let mut key = [0u8; 32]; +//! ansi_x963_kdf::derive_key_into::(b"shared-secret", b"other-info", &mut key).unwrap(); +//! ``` +//! +//! [1]: https://www.secg.org/sec1-v2.pdf + +#![no_std] +#![cfg_attr(docsrs, feature(doc_cfg))] + +use core::fmt; +use digest::{array::typenum::Unsigned, Digest, FixedOutputReset, Update}; + +#[cfg(feature = "std")] +extern crate std; + +/// ANSI-X9.63 KDF errors. +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum Error { + /// The length of the secret is zero. + NoSecret, + /// The length of the output is zero. + NoOutput, + /// The length of the input is too big + InputOverflow, + /// The length of the output is too big. + CounterOverflow, +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.write_str(match self { + Error::NoSecret => "Buffer for secret has zero length.", + Error::NoOutput => "Buffer for key has zero length.", + Error::InputOverflow => "Input length is to big.", + Error::CounterOverflow => "Requested key length is to big.", + }) + } +} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl ::std::error::Error for Error {} + +/// Derives `key` in-place from `secret` and `other_info`. +/// ```rust +/// let mut key = [0u8; 42]; +/// ansi_x963_kdf::derive_key_into::(b"top-secret", b"info", &mut key).unwrap(); +/// ``` +pub fn derive_key_into(secret: &[u8], other_info: &[u8], key: &mut [u8]) -> Result<(), Error> +where + D: Digest + FixedOutputReset, +{ + if secret.is_empty() { + return Err(Error::NoSecret); + } + + if key.is_empty() { + return Err(Error::NoOutput); + } + + // 1. Check if |Z| + |SharedInfo| + 4 >= hashmaxlen + if secret.len() + other_info.len() + 4 >= D::OutputSize::USIZE * (u32::MAX as usize) { + return Err(Error::InputOverflow); + } + + // Counter overflow is possible only on architectures with usize bigger than 4 bytes. + const OVERFLOW_IS_POSSIBLE: bool = core::mem::size_of::() > 4; + + // 2. Check that keydatalen < hashlen × (2^32 − 1) + if OVERFLOW_IS_POSSIBLE && (key.len() >= D::OutputSize::USIZE * (u32::MAX as usize)) { + return Err(Error::CounterOverflow); + } + + let mut digest = D::new(); + + // 3. Initiate a 4 octet, big-endian octet string Counter as 00000001 + let mut counter: u32 = 1; + + // 4. For i = 1 to keydatalen/hashlen, + for chunk in key.chunks_mut(D::OutputSize::USIZE) { + // 4.1 Compute Ki = Hash(Z ‖ Counter ‖ [SharedInfo]) using the selected hash function + Update::update(&mut digest, secret); + Update::update(&mut digest, &counter.to_be_bytes()); + Update::update(&mut digest, other_info); + chunk.copy_from_slice(&digest.finalize_reset()[..chunk.len()]); + // 4.2. Increment Counter + counter += 1; + } + + Ok(()) +} + +/// Derives and returns `length` bytes key from `secret` and `other_info`. +/// ```rust +/// let key = ansi_x963_kdf::derive_key::(b"top-secret", b"info", 42).unwrap(); +/// ``` +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +pub fn derive_key( + secret: &[u8], + other_info: &[u8], + length: usize, +) -> Result, Error> +where + D: Digest + FixedOutputReset, +{ + let mut key = std::vec![0u8; length]; + derive_key_into::(secret, other_info, &mut key)?; + Ok(key) +} diff --git a/ansi-x963-kdf/tests/tests.rs b/ansi-x963-kdf/tests/tests.rs new file mode 100644 index 0000000..ca44920 --- /dev/null +++ b/ansi-x963-kdf/tests/tests.rs @@ -0,0 +1,247 @@ +use digest::{Digest, FixedOutputReset}; +use hex_literal::hex; +use sha2::{Sha224, Sha256, Sha512}; + +struct Fixture<'a> { + secret: &'a [u8], + other_info: &'a [u8], + expected_key: &'a [u8], +} + +fn test_key_derivation(fixtures: &[Fixture]) +where + D: Digest + FixedOutputReset, +{ + for Fixture { + secret, + other_info, + expected_key, + } in fixtures.iter() + { + for key_length in 1..expected_key.len() { + let mut key = vec![0u8; key_length]; + assert!(ansi_x963_kdf::derive_key_into::(secret, other_info, &mut key).is_ok()); + eprintln!("{}", expected_key.len()); + assert_eq!(&expected_key[..key_length], &key); + } + } +} + +#[test] +fn test_input_output_sha224() { + let fixtures = [ + Fixture { + secret: &hex!("00"), + other_info: &[], + expected_key: &hex!( + "4a6ebc83b8e2b19eea640500be6bcffdddaa07b8b2f81f2c533940e4e6ad6cfd + e680e5ba8eb25351402f0e75a6246cf006f6dd2187185af41d04abb648124e27 + 827cf4f2b871f9bc3fb2313c4f146b44faf3be170f2d87296c9b533c516b9a48 + dc73f73bafcc610bce18965566e3d0ca0f083c8a6a20b3b84457486e204a1014" + ), + }, + Fixture { + secret: &hex!("00"), + other_info: &hex!("00"), + expected_key: &hex!( + "4bfb11552c4bf91bce4833aa06f854ceb8a3f7e435f42907e6d86e7597b20789 + aba17dccaf09d3e26bc3dd0ad6051f0e46b830cc57091bd0ba1da24a4ab96492 + 3b47b4b73ccb6cec6aa1e6339f4fa93995baef4a3ace3cadcf1ee63eaecb868f + 2f8ca06def29797d33673803a185574dec0c4bc0a5d0d0ffb4c527eb738d5bd2 + 4fcc424f46785f693f60ea2f00d3ff38f9f1e73847a50bf6ece7bda4abe3767f + 19f0a767f2ea69ed84f4f5837084edd2945c39d4b459b38fc2e83264ba47896a + a3e106058f1d13f2b1422c7ff33c279dfc7a42cc4f775babcae8122a4dbdf427 + a8634e9464607fe4a6f91fc59f07ab42f18dac313384b50d572cdff0b406cff2" + ), + }, + Fixture { + secret: &hex!("ba5eba11bedabb1ebe5077edb0a710adb01dfacecab005eca11ab1eca55e77e011"), + other_info: &hex!("f005ba1100ddba11"), + expected_key: &hex!( + "20328557e258ecbe845fcde1002aa36dba5e29383d1b9813c2410819c09bd7d7 + 5b75f4d2ca71354080b64b3e8e3ef457f22517b074cbbbbf11d660b7b4706de1 + 5678893c6712e104b34fb776a90341c905a028bf1892aa4487899ef4436f4ac6 + d436db25763c7fa7d43fbedac386aa69f5b156d4a84ede0b4371d34eb083fce1 + 6cb6e051e846a923a82707925838371797b09fc94134d33b48e0ab9175fdbd90 + cd57b1570d55f5d4a391f5c15660757c447e0480bd6b6f0ca80a4e3ab5c40220 + 7d1edcc2210eb77aff4eda6e35afce2815d82ab242574b7b9d0e72d8daa1c853 + e0b3dad4cb384ce70c5a23afd4f1e35a01fdd14f78812a5a99a93f4d57877901" + ), + }, + ]; + + test_key_derivation::(&fixtures); +} + +#[test] +fn test_input_output_sha256() { + let fixtures = [ + Fixture { + secret: &hex!("00"), + other_info: &[], + expected_key: &hex!( + "15f2f1a4339f5f2a313b95015cad8124d054a171ac2f31cf529dda7cfb6a38b4 + 89eefc18fa4b815bd1aded2f24eb28885993aa00b6d0171bf5005f9d39aaea10 + 016a682d1df4f869b32c48b0a9b442a1493949fb85d951d121c1143bd3d5c1af + b59024333110b3108625f25447665c1ebf10c6a6bbe9f018c421f4b0dcb5a993 + 42a5578600f1b0902c599a39268c12bdb1e820fd9a82212db588a71ae74cb6e4 + 1f8a792ae7c5800a0b0e3aea6ed808bedca2b0a3cc8f7b22c5effbd545f632c2 + 043a0631871a3f67ac03c5f8406b69a0dc14bd5b23e55f27a5d4462b0f0a2d23 + 18519afd330d3447bb196dd75ea7a7998db6f2fcb2a5dc134f35690a2dbcc072" + ), + }, + Fixture { + secret: &hex!("00"), + other_info: &hex!("00"), + expected_key: &hex!( + "588611f65741c171a3d92c1d5343f5dd67f4fc472fc56f01c9bc568f5ac2a623 + 55af2e3db27cf364b9465ea89a489710da6c78ecc59ddf3ac6203261a6649d9e + 45673cfcd9849e761a24b07d99f5c35167c343244c160b973b55a29408d9d988 + 654670625fbd22634494df9f4f9a5328352eb92b4104612eef6dff382c119064 + 785b35d50e5df9eee4bb06e5b102b1088d149500e934c04eac6936a09e4b36d1 + 1e4f69ae41148ec0d7b5cca9bde9db8b850660e759c75f32154bb60357145ed3 + c0112a61a92f4eacd699c70a603df40f38babf6420587478c05ec70670e7221e + ce2081d38382369c0d2ec51f89db2e29146d555c7c2aa62518962824682553a7" + ), + }, + Fixture { + secret: &hex!("ba5eba11bedabb1ebe5077edb0a710adb01dfacecab005eca11ab1eca55e77e011"), + other_info: &hex!("f005ba1100ddba11"), + expected_key: &hex!( + "41bf219e0dedf77305f1f79739fd917b3311e61dd504150d6f3c40195837c75a + 441fd05332d739a43fd70e11e4be66683eb05586c6c03bbf6d8030990e724a38 + c2ab1f5c22b0f47a84a2699d11701c6bfb3337e606130522f4f7a26df3b1cb95 + 28ca56781af9af361e7c2ac64d50f73d275d5a6c83fc67b2e05f20ab9b595cce + b8f205c57993647bf64c6f4ad8899eb5d0111efed1859006ec256b2e8cbb058b + b83a8d40fa7f435037acd155b27a87716fdd7619b900f051a2437539f830789b + f71080ff642285a01ff2db3e11ca5377c389be3f3851611cc8189728496fddca + cac6b89565fd78a1b8d4c8d407ff45e39610526668abacabede347d5c1e9fb69" + ), + }, + ]; + + test_key_derivation::(&fixtures); +} + +#[test] +fn test_input_output_sha512() { + let fixtures = [ + Fixture { + secret: &hex!("00"), + other_info: &[], + expected_key: &hex!( + "b8eef223e484fe7a872e4db84711a01db365b205e477c3e3170f26623e2fa230 + 4d93f6c04337d0ea7454d1f2073f8eb8ee58b361438b61f363eb1037a77f716c + e89b92de1146cf3831eff44361d872f61dea1f05b3e08a9330c302949f6c93bd + 3e908f5ce5444e45a47bc0625600fff575472f04bcecc393387c244a93fbd4f4 + 26b22edbdaa5eef8565feb1d6a3c46dedb89c00efcaf3f5d95d53f936b570efb + 18db044083a075f3d1322378a07f00694e4e21a535d91e893cacac87d877b2ab + da0cff964fd1c291b759c38657bc7904be9f98cc8794099a6351b68f382e2df8 + 79cab5d5a1d7f5e9d6461f015b11c47fb14cf99e496905fa95e8d7d5ec59a493" + ), + }, + Fixture { + secret: &hex!("00"), + other_info: &hex!("00"), + expected_key: &hex!( + "74cc6e00677ea1683c3c3fbc6337101db4e2ffdd0053a8783fd4c9f5b53117db + 9089ce3beef287cbe273a7c47ad1e88509842f9a70ff354280dc7a8e1c61214a + e698b4186af5628a28dad9ff4b25d0cfbceac9c9c522d496f8513338a9426991 + 2e0bbd2b2c500b303dae963b707ed4a05e9f57eb0c7de06da884669a93dbb29b + 3d262e7c98e24f8cd68d0ea44fe9d5e4e0b033b0c3f77193cdf2163dfac30da9 + eb39b147e2d9746dd1149ac512920d8e8316577e6713498beb7fa838a80b1736 + 383001d5151582a16bcf9fcc38edbafaf18ab976e01a0244b462c6b6f907ba14 + 32d14e641961c3d48e300ec5561424c4b8125cf172d06f9368bfdec0d5c57b8b" + ), + }, + Fixture { + secret: &hex!("ba5eba11bedabb1ebe5077edb0a710adb01dfacecab005eca11ab1eca55e77e011"), + other_info: &hex!("f005ba1100ddba11"), + expected_key: &hex!( + "ae21b84e638fc7de4d838d2a7232655c39d2794116f00e43891170c0a16df11c + 15afbdb903c5722e22afc885c0f851c2ccacc2a0802437bc5bef6c18a0573246 + 65de72200dac5321ed92f530ed441bc194c402055419d73f52165a2bf9985fab + 756abce8e3b9c5e4a3d179b2eceaa6ef7b335245f480ed32a7f847921ab5e3c1 + a8867aff9802e6f8cec4d6a5fdf3cc0c2c1a14f08ec4df3654f2579164c6ed90 + a2262a8d492a0aa0942838952dc89f494018da5dd16c0b18ca6a9837685489bf + a55debb243045e83a730e5e08917836181693cb4ab1827e968e3bb0e8e3b9a0e + 7cdab180f59168211dad86eb88fc3b4bc1dbeb0c8a8c967c5e0d1b2a84bf215c" + ), + }, + ]; + + test_key_derivation::(&fixtures); +} + +#[test] +fn test_errors() { + // secret has zero length. + assert_eq!( + ansi_x963_kdf::derive_key_into::(&[], &[], &mut [0u8; 42]), + Err(ansi_x963_kdf::Error::NoSecret) + ); + + // key has zero length. + assert_eq!( + ansi_x963_kdf::derive_key_into::(&[0u8; 42], &[], &mut [0u8; 0]), + Err(ansi_x963_kdf::Error::NoOutput) + ); + + // other_info has a length that causes input overflow. + #[cfg(target_pointer_width = "64")] + { + let hashmaxlen = Sha224::output_size() * (u32::MAX as usize); + // Secret + let secret = [0u8; 42]; // Empty secret + // Calculate the required length for other_info to cause an input overflow. + let other_info_len = hashmaxlen - secret.len() - 4; + // Create a layout for allocation. + let layout = std::alloc::Layout::from_size_align(other_info_len, 1).unwrap(); + unsafe { + // Allocate memory without initializing. + let p = std::alloc::alloc(layout); + if p.is_null() { + panic!("Failed to allocate memory"); + } + + // Wrap the allocated pointer in a struct that will deallocate it on drop. + struct AllocGuard { + ptr: *mut u8, + layout: std::alloc::Layout, + } + impl Drop for AllocGuard { + fn drop(&mut self) { + unsafe { + std::alloc::dealloc(self.ptr, self.layout); + } + } + } + let _guard = AllocGuard { ptr: p, layout }; + + // Create a slice from the allocated memory. + let other_info = std::slice::from_raw_parts(p, other_info_len); + + // Attempt to derive the key, which should result in an InputOverflow error. + let res = ansi_x963_kdf::derive_key_into::(&secret, other_info, &mut [0u8; 42]); + + assert_eq!(res, Err(ansi_x963_kdf::Error::InputOverflow)); + } + } + + // key has a length that causes counter overflow. + #[cfg(target_pointer_width = "64")] + { + let size = Sha224::output_size() * u32::MAX as usize; + let layout = std::alloc::Layout::from_size_align(size, 1).unwrap(); + unsafe { + // We assume that OS will not allocate physicall memory for this buffer + let p = std::alloc::alloc_zeroed(layout); + let buf = std::slice::from_raw_parts_mut(p, size); + assert_eq!( + ansi_x963_kdf::derive_key_into::(&[0u8; 42], &[], buf), + Err(ansi_x963_kdf::Error::CounterOverflow) + ); + std::alloc::dealloc(p, layout) + }; + } +} From 33c89940ed2ce31bcf14b48a7440dd60f5b21325 Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Fri, 4 Oct 2024 20:04:21 -0400 Subject: [PATCH 04/17] Add ANSI-X9.63-KDF support: adjust variable name to shared_info to match SEC 1 convention --- ansi-x963-kdf/src/lib.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ansi-x963-kdf/src/lib.rs b/ansi-x963-kdf/src/lib.rs index a19053c..2d1f434 100644 --- a/ansi-x963-kdf/src/lib.rs +++ b/ansi-x963-kdf/src/lib.rs @@ -52,12 +52,12 @@ impl fmt::Display for Error { #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl ::std::error::Error for Error {} -/// Derives `key` in-place from `secret` and `other_info`. +/// Derives `key` in-place from `secret` and `shared_info`. /// ```rust /// let mut key = [0u8; 42]; /// ansi_x963_kdf::derive_key_into::(b"top-secret", b"info", &mut key).unwrap(); /// ``` -pub fn derive_key_into(secret: &[u8], other_info: &[u8], key: &mut [u8]) -> Result<(), Error> +pub fn derive_key_into(secret: &[u8], shared_info: &[u8], key: &mut [u8]) -> Result<(), Error> where D: Digest + FixedOutputReset, { @@ -70,7 +70,7 @@ where } // 1. Check if |Z| + |SharedInfo| + 4 >= hashmaxlen - if secret.len() + other_info.len() + 4 >= D::OutputSize::USIZE * (u32::MAX as usize) { + if secret.len() + shared_info.len() + 4 >= D::OutputSize::USIZE * (u32::MAX as usize) { return Err(Error::InputOverflow); } @@ -92,7 +92,7 @@ where // 4.1 Compute Ki = Hash(Z ‖ Counter ‖ [SharedInfo]) using the selected hash function Update::update(&mut digest, secret); Update::update(&mut digest, &counter.to_be_bytes()); - Update::update(&mut digest, other_info); + Update::update(&mut digest, shared_info); chunk.copy_from_slice(&digest.finalize_reset()[..chunk.len()]); // 4.2. Increment Counter counter += 1; @@ -101,7 +101,7 @@ where Ok(()) } -/// Derives and returns `length` bytes key from `secret` and `other_info`. +/// Derives and returns `length` bytes key from `secret` and `shared_info`. /// ```rust /// let key = ansi_x963_kdf::derive_key::(b"top-secret", b"info", 42).unwrap(); /// ``` @@ -109,13 +109,13 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn derive_key( secret: &[u8], - other_info: &[u8], + shared_info: &[u8], length: usize, ) -> Result, Error> where D: Digest + FixedOutputReset, { let mut key = std::vec![0u8; length]; - derive_key_into::(secret, other_info, &mut key)?; + derive_key_into::(secret, shared_info, &mut key)?; Ok(key) } From 0a9087e354f41cf18332d7655e71b77fa46d9f4a Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Sat, 5 Oct 2024 12:38:41 -0400 Subject: [PATCH 05/17] Add ANSI-X9.63-KDF support: use alloc_zeroed for input overflow test case --- ansi-x963-kdf/tests/tests.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/ansi-x963-kdf/tests/tests.rs b/ansi-x963-kdf/tests/tests.rs index ca44920..a80790b 100644 --- a/ansi-x963-kdf/tests/tests.rs +++ b/ansi-x963-kdf/tests/tests.rs @@ -190,16 +190,15 @@ fn test_errors() { // other_info has a length that causes input overflow. #[cfg(target_pointer_width = "64")] { - let hashmaxlen = Sha224::output_size() * (u32::MAX as usize); // Secret - let secret = [0u8; 42]; // Empty secret - // Calculate the required length for other_info to cause an input overflow. - let other_info_len = hashmaxlen - secret.len() - 4; + let secret = [0u8; 42]; + // Calculate the required length for other_info to cause an input overflow. + let other_info_len = Sha224::output_size() * (u32::MAX as usize) - secret.len() - 4; // Create a layout for allocation. let layout = std::alloc::Layout::from_size_align(other_info_len, 1).unwrap(); unsafe { - // Allocate memory without initializing. - let p = std::alloc::alloc(layout); + // We assume that OS will not allocate physical memory for this buffer + let p = std::alloc::alloc_zeroed(layout); if p.is_null() { panic!("Failed to allocate memory"); } @@ -220,11 +219,10 @@ fn test_errors() { // Create a slice from the allocated memory. let other_info = std::slice::from_raw_parts(p, other_info_len); - - // Attempt to derive the key, which should result in an InputOverflow error. - let res = ansi_x963_kdf::derive_key_into::(&secret, other_info, &mut [0u8; 42]); - - assert_eq!(res, Err(ansi_x963_kdf::Error::InputOverflow)); + assert_eq!( + ansi_x963_kdf::derive_key_into::(&secret, other_info, &mut [0u8; 42]), + Err(ansi_x963_kdf::Error::InputOverflow) + ); } } From f386294afee3a8de9a3fc9202623d40684b135df Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Mon, 7 Oct 2024 20:47:59 -0400 Subject: [PATCH 06/17] Add ANSI-X9.63-KDF support: use Digest::update() --- ansi-x963-kdf/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ansi-x963-kdf/src/lib.rs b/ansi-x963-kdf/src/lib.rs index 2d1f434..9dbd070 100644 --- a/ansi-x963-kdf/src/lib.rs +++ b/ansi-x963-kdf/src/lib.rs @@ -19,7 +19,7 @@ #![cfg_attr(docsrs, feature(doc_cfg))] use core::fmt; -use digest::{array::typenum::Unsigned, Digest, FixedOutputReset, Update}; +use digest::{array::typenum::Unsigned, Digest, FixedOutputReset}; #[cfg(feature = "std")] extern crate std; @@ -90,9 +90,9 @@ where // 4. For i = 1 to keydatalen/hashlen, for chunk in key.chunks_mut(D::OutputSize::USIZE) { // 4.1 Compute Ki = Hash(Z ‖ Counter ‖ [SharedInfo]) using the selected hash function - Update::update(&mut digest, secret); - Update::update(&mut digest, &counter.to_be_bytes()); - Update::update(&mut digest, shared_info); + Digest::update(&mut digest, secret); + Digest::update(&mut digest, &counter.to_be_bytes()); + Digest::update(&mut digest, shared_info); chunk.copy_from_slice(&digest.finalize_reset()[..chunk.len()]); // 4.2. Increment Counter counter += 1; From 7053d879a43c4be34d5b5ab73cc8c5637fab41fe Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Tue, 8 Oct 2024 20:10:36 -0400 Subject: [PATCH 07/17] Add ANSI-X9.63-KDF support: add tests vectors origin --- ansi-x963-kdf/tests/tests.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ansi-x963-kdf/tests/tests.rs b/ansi-x963-kdf/tests/tests.rs index a80790b..aa10729 100644 --- a/ansi-x963-kdf/tests/tests.rs +++ b/ansi-x963-kdf/tests/tests.rs @@ -1,3 +1,8 @@ +//! Tests for ansi-x963-kdf +//! +//! Test vectors have been generated using the java-based Bouncy-Castle +//! KDF2 implementation [KDF2BytesGenerator][1] +//! [1]: https://downloads.bouncycastle.org/java/docs/bcprov-jdk18on-javadoc/ use digest::{Digest, FixedOutputReset}; use hex_literal::hex; use sha2::{Sha224, Sha256, Sha512}; @@ -21,7 +26,6 @@ where for key_length in 1..expected_key.len() { let mut key = vec![0u8; key_length]; assert!(ansi_x963_kdf::derive_key_into::(secret, other_info, &mut key).is_ok()); - eprintln!("{}", expected_key.len()); assert_eq!(&expected_key[..key_length], &key); } } From bdd842b6d6a405e8f38e8675203c12e558bde72b Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Tue, 8 Oct 2024 20:47:26 -0400 Subject: [PATCH 08/17] Add ANSI-X9.63-KDF support: add test assertion --- ansi-x963-kdf/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ansi-x963-kdf/src/lib.rs b/ansi-x963-kdf/src/lib.rs index 9dbd070..459c019 100644 --- a/ansi-x963-kdf/src/lib.rs +++ b/ansi-x963-kdf/src/lib.rs @@ -54,8 +54,10 @@ impl ::std::error::Error for Error {} /// Derives `key` in-place from `secret` and `shared_info`. /// ```rust +/// use hex_literal::hex; /// let mut key = [0u8; 42]; /// ansi_x963_kdf::derive_key_into::(b"top-secret", b"info", &mut key).unwrap(); +/// assert_eq!(key, hex!("85397c03b3894cdc12e7e042698d040f449dbff97a86d0a4dd2d0a4409b8d969e01e57091cf170dfd977")); /// ``` pub fn derive_key_into(secret: &[u8], shared_info: &[u8], key: &mut [u8]) -> Result<(), Error> where @@ -103,7 +105,9 @@ where /// Derives and returns `length` bytes key from `secret` and `shared_info`. /// ```rust +/// use hex_literal::hex; /// let key = ansi_x963_kdf::derive_key::(b"top-secret", b"info", 42).unwrap(); +/// assert_eq!(key, hex!("85397c03b3894cdc12e7e042698d040f449dbff97a86d0a4dd2d0a4409b8d969e01e57091cf170dfd977")); /// ``` #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] From 8322257c67eecbc0aedd9d92d045c8d6e37f7250 Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Wed, 9 Oct 2024 21:36:39 -0400 Subject: [PATCH 09/17] Add ANSI-X9.63-KDF support: use u64 for overflow errors checks --- ansi-x963-kdf/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ansi-x963-kdf/src/lib.rs b/ansi-x963-kdf/src/lib.rs index 459c019..79030b7 100644 --- a/ansi-x963-kdf/src/lib.rs +++ b/ansi-x963-kdf/src/lib.rs @@ -72,7 +72,8 @@ where } // 1. Check if |Z| + |SharedInfo| + 4 >= hashmaxlen - if secret.len() + shared_info.len() + 4 >= D::OutputSize::USIZE * (u32::MAX as usize) { + if secret.len() as u64 + shared_info.len() as u64 + 4 >= D::OutputSize::U64 * (u32::MAX as u64) + { return Err(Error::InputOverflow); } @@ -80,7 +81,7 @@ where const OVERFLOW_IS_POSSIBLE: bool = core::mem::size_of::() > 4; // 2. Check that keydatalen < hashlen × (2^32 − 1) - if OVERFLOW_IS_POSSIBLE && (key.len() >= D::OutputSize::USIZE * (u32::MAX as usize)) { + if OVERFLOW_IS_POSSIBLE && (key.len() as u64 >= D::OutputSize::U64 * (u32::MAX as u64)) { return Err(Error::CounterOverflow); } From c1e81539d51b95873864c6ca702b32ddde961405 Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Wed, 9 Oct 2024 21:40:50 -0400 Subject: [PATCH 10/17] Add ANSI-X9.63-KDF support: adjust variable name to shared_info --- ansi-x963-kdf/tests/tests.rs | 39 +++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/ansi-x963-kdf/tests/tests.rs b/ansi-x963-kdf/tests/tests.rs index aa10729..3015d18 100644 --- a/ansi-x963-kdf/tests/tests.rs +++ b/ansi-x963-kdf/tests/tests.rs @@ -2,6 +2,7 @@ //! //! Test vectors have been generated using the java-based Bouncy-Castle //! KDF2 implementation [KDF2BytesGenerator][1] +//! //! [1]: https://downloads.bouncycastle.org/java/docs/bcprov-jdk18on-javadoc/ use digest::{Digest, FixedOutputReset}; use hex_literal::hex; @@ -9,7 +10,7 @@ use sha2::{Sha224, Sha256, Sha512}; struct Fixture<'a> { secret: &'a [u8], - other_info: &'a [u8], + shared_info: &'a [u8], expected_key: &'a [u8], } @@ -19,13 +20,13 @@ where { for Fixture { secret, - other_info, + shared_info, expected_key, } in fixtures.iter() { for key_length in 1..expected_key.len() { let mut key = vec![0u8; key_length]; - assert!(ansi_x963_kdf::derive_key_into::(secret, other_info, &mut key).is_ok()); + assert!(ansi_x963_kdf::derive_key_into::(secret, shared_info, &mut key).is_ok()); assert_eq!(&expected_key[..key_length], &key); } } @@ -36,7 +37,7 @@ fn test_input_output_sha224() { let fixtures = [ Fixture { secret: &hex!("00"), - other_info: &[], + shared_info: &[], expected_key: &hex!( "4a6ebc83b8e2b19eea640500be6bcffdddaa07b8b2f81f2c533940e4e6ad6cfd e680e5ba8eb25351402f0e75a6246cf006f6dd2187185af41d04abb648124e27 @@ -46,7 +47,7 @@ fn test_input_output_sha224() { }, Fixture { secret: &hex!("00"), - other_info: &hex!("00"), + shared_info: &hex!("00"), expected_key: &hex!( "4bfb11552c4bf91bce4833aa06f854ceb8a3f7e435f42907e6d86e7597b20789 aba17dccaf09d3e26bc3dd0ad6051f0e46b830cc57091bd0ba1da24a4ab96492 @@ -60,7 +61,7 @@ fn test_input_output_sha224() { }, Fixture { secret: &hex!("ba5eba11bedabb1ebe5077edb0a710adb01dfacecab005eca11ab1eca55e77e011"), - other_info: &hex!("f005ba1100ddba11"), + shared_info: &hex!("f005ba1100ddba11"), expected_key: &hex!( "20328557e258ecbe845fcde1002aa36dba5e29383d1b9813c2410819c09bd7d7 5b75f4d2ca71354080b64b3e8e3ef457f22517b074cbbbbf11d660b7b4706de1 @@ -82,7 +83,7 @@ fn test_input_output_sha256() { let fixtures = [ Fixture { secret: &hex!("00"), - other_info: &[], + shared_info: &[], expected_key: &hex!( "15f2f1a4339f5f2a313b95015cad8124d054a171ac2f31cf529dda7cfb6a38b4 89eefc18fa4b815bd1aded2f24eb28885993aa00b6d0171bf5005f9d39aaea10 @@ -96,7 +97,7 @@ fn test_input_output_sha256() { }, Fixture { secret: &hex!("00"), - other_info: &hex!("00"), + shared_info: &hex!("00"), expected_key: &hex!( "588611f65741c171a3d92c1d5343f5dd67f4fc472fc56f01c9bc568f5ac2a623 55af2e3db27cf364b9465ea89a489710da6c78ecc59ddf3ac6203261a6649d9e @@ -110,7 +111,7 @@ fn test_input_output_sha256() { }, Fixture { secret: &hex!("ba5eba11bedabb1ebe5077edb0a710adb01dfacecab005eca11ab1eca55e77e011"), - other_info: &hex!("f005ba1100ddba11"), + shared_info: &hex!("f005ba1100ddba11"), expected_key: &hex!( "41bf219e0dedf77305f1f79739fd917b3311e61dd504150d6f3c40195837c75a 441fd05332d739a43fd70e11e4be66683eb05586c6c03bbf6d8030990e724a38 @@ -132,7 +133,7 @@ fn test_input_output_sha512() { let fixtures = [ Fixture { secret: &hex!("00"), - other_info: &[], + shared_info: &[], expected_key: &hex!( "b8eef223e484fe7a872e4db84711a01db365b205e477c3e3170f26623e2fa230 4d93f6c04337d0ea7454d1f2073f8eb8ee58b361438b61f363eb1037a77f716c @@ -146,7 +147,7 @@ fn test_input_output_sha512() { }, Fixture { secret: &hex!("00"), - other_info: &hex!("00"), + shared_info: &hex!("00"), expected_key: &hex!( "74cc6e00677ea1683c3c3fbc6337101db4e2ffdd0053a8783fd4c9f5b53117db 9089ce3beef287cbe273a7c47ad1e88509842f9a70ff354280dc7a8e1c61214a @@ -160,7 +161,7 @@ fn test_input_output_sha512() { }, Fixture { secret: &hex!("ba5eba11bedabb1ebe5077edb0a710adb01dfacecab005eca11ab1eca55e77e011"), - other_info: &hex!("f005ba1100ddba11"), + shared_info: &hex!("f005ba1100ddba11"), expected_key: &hex!( "ae21b84e638fc7de4d838d2a7232655c39d2794116f00e43891170c0a16df11c 15afbdb903c5722e22afc885c0f851c2ccacc2a0802437bc5bef6c18a0573246 @@ -191,15 +192,17 @@ fn test_errors() { Err(ansi_x963_kdf::Error::NoOutput) ); - // other_info has a length that causes input overflow. + // shared_info has a length that causes input overflow. #[cfg(target_pointer_width = "64")] { // Secret let secret = [0u8; 42]; - // Calculate the required length for other_info to cause an input overflow. - let other_info_len = Sha224::output_size() * (u32::MAX as usize) - secret.len() - 4; + + // Calculate the required length for shared_info to cause an input overflow: |Z| + |SharedInfo| + 4 >= hashmaxlen + let shared_info_len = Sha224::output_size() * (u32::MAX as usize) - secret.len() - 4; + // Create a layout for allocation. - let layout = std::alloc::Layout::from_size_align(other_info_len, 1).unwrap(); + let layout = std::alloc::Layout::from_size_align(shared_info_len, 1).unwrap(); unsafe { // We assume that OS will not allocate physical memory for this buffer let p = std::alloc::alloc_zeroed(layout); @@ -222,9 +225,9 @@ fn test_errors() { let _guard = AllocGuard { ptr: p, layout }; // Create a slice from the allocated memory. - let other_info = std::slice::from_raw_parts(p, other_info_len); + let shared_info = std::slice::from_raw_parts(p, shared_info_len); assert_eq!( - ansi_x963_kdf::derive_key_into::(&secret, other_info, &mut [0u8; 42]), + ansi_x963_kdf::derive_key_into::(&secret, shared_info, &mut [0u8; 42]), Err(ansi_x963_kdf::Error::InputOverflow) ); } From 60863dbfd90c0091f18a13422bfabd43adc99d5a Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Wed, 9 Oct 2024 21:42:46 -0400 Subject: [PATCH 11/17] Add ANSI-X9.63-KDF support: switch to doc_auto_cfg --- ansi-x963-kdf/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ansi-x963-kdf/src/lib.rs b/ansi-x963-kdf/src/lib.rs index 79030b7..d48d53b 100644 --- a/ansi-x963-kdf/src/lib.rs +++ b/ansi-x963-kdf/src/lib.rs @@ -16,7 +16,7 @@ //! [1]: https://www.secg.org/sec1-v2.pdf #![no_std] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] use core::fmt; use digest::{array::typenum::Unsigned, Digest, FixedOutputReset}; From 6610e14c1fdb15430b9260a6e686cdeeab742ca3 Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Wed, 9 Oct 2024 21:50:48 -0400 Subject: [PATCH 12/17] Add ANSI-X9.63-KDF support: set MSRV to 1.81 --- README.md | 2 +- ansi-x963-kdf/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 84908e9..321a7b1 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Collection of [Key Derivation Functions][KDF] (KDF) written in pure Rust. |--------------|----------------|:---------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------:|:-----------------------:| | [HKDF] | [`hkdf`] | [![crates.io](https://img.shields.io/crates/v/hkdf.svg)](https://crates.io/crates/hkdf) | [![Documentation](https://docs.rs/hkdf/badge.svg)](https://docs.rs/hkdf) | ![MSRV 1.41][msrv-1.72] | | [Concat-KDF] | [`concat-kdf`] | [![crates.io](https://img.shields.io/crates/v/concat-kdf.svg)](https://crates.io/crates/concat-kdf) | [![Documentation](https://docs.rs/concat-kdf/badge.svg)](https://docs.rs/concat-kdf) | ![MSRV 1.56][msrv-1.72] | -| [ANSI-X9.63-KDF] | [`ansi-x963-kdf`] | [![crates.io](https://img.shields.io/crates/v/ansi-x963-kdf.svg)](https://crates.io/crates/ansi-x963-kdf) | [![Documentation](https://docs.rs/ansi-x963-kdf/badge.svg)](https://docs.rs/ansi-x963-kdf) | ![MSRV 1.56][msrv-1.72] | +| [ANSI-X9.63-KDF] | [`ansi-x963-kdf`] | [![crates.io](https://img.shields.io/crates/v/ansi-x963-kdf.svg)](https://crates.io/crates/ansi-x963-kdf) | [![Documentation](https://docs.rs/ansi-x963-kdf/badge.svg)](https://docs.rs/ansi-x963-kdf) | ![MSRV 1.81][msrv-1.81] | *NOTE: for password-based KDFs (e.g. Argon2, PBKDF2, scrypt), please see [RustCrypto/password-hashes]* diff --git a/ansi-x963-kdf/Cargo.toml b/ansi-x963-kdf/Cargo.toml index 53db848..739e91a 100644 --- a/ansi-x963-kdf/Cargo.toml +++ b/ansi-x963-kdf/Cargo.toml @@ -10,7 +10,7 @@ documentation = "https://docs.rs/ansi-x963-kdf" repository = "https://github.com/RustCrypto/KDFs" keywords = ["crypto", "ansi-x963-kdf", "KDF", "SEC1"] categories = ["cryptography", "no-std"] -rust-version = "1.72" +rust-version = "1.81" [dependencies] digest = "=0.11.0-pre.9" From d9ee6e70aac9be1c9be7ca5489e9273e5eed9660 Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Wed, 9 Oct 2024 21:51:53 -0400 Subject: [PATCH 13/17] Add ANSI-X9.63-KDF support: switch to core::error::Error --- ansi-x963-kdf/src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ansi-x963-kdf/src/lib.rs b/ansi-x963-kdf/src/lib.rs index d48d53b..92f0e19 100644 --- a/ansi-x963-kdf/src/lib.rs +++ b/ansi-x963-kdf/src/lib.rs @@ -48,9 +48,7 @@ impl fmt::Display for Error { } } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl ::std::error::Error for Error {} +impl ::core::error::Error for Error {} /// Derives `key` in-place from `secret` and `shared_info`. /// ```rust From ab920bf52428e8cea6e1aa627cf2152539acdc66 Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Wed, 9 Oct 2024 21:55:12 -0400 Subject: [PATCH 14/17] Add ANSI-X9.63-KDF support: clippy lint --- ansi-x963-kdf/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ansi-x963-kdf/src/lib.rs b/ansi-x963-kdf/src/lib.rs index 92f0e19..c5dc67e 100644 --- a/ansi-x963-kdf/src/lib.rs +++ b/ansi-x963-kdf/src/lib.rs @@ -92,7 +92,7 @@ where for chunk in key.chunks_mut(D::OutputSize::USIZE) { // 4.1 Compute Ki = Hash(Z ‖ Counter ‖ [SharedInfo]) using the selected hash function Digest::update(&mut digest, secret); - Digest::update(&mut digest, &counter.to_be_bytes()); + Digest::update(&mut digest, counter.to_be_bytes()); Digest::update(&mut digest, shared_info); chunk.copy_from_slice(&digest.finalize_reset()[..chunk.len()]); // 4.2. Increment Counter From 6facd9615105fcf7b5d28abdea5ee1c9f38384a3 Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Wed, 9 Oct 2024 21:57:35 -0400 Subject: [PATCH 15/17] Add ANSI-X9.63-KDF support: add CI job --- .github/workflows/ansi-x963-kdf.yml | 53 +++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 .github/workflows/ansi-x963-kdf.yml diff --git a/.github/workflows/ansi-x963-kdf.yml b/.github/workflows/ansi-x963-kdf.yml new file mode 100644 index 0000000..4b7c0fc --- /dev/null +++ b/.github/workflows/ansi-x963-kdf.yml @@ -0,0 +1,53 @@ +name: ansi-x963-kdf + +on: + pull_request: + paths: + - "ansi-x963-kdf/**" + - "Cargo.*" + push: + branches: master + +defaults: + run: + working-directory: ansi-x963-kdf + +env: + CARGO_INCREMENTAL: 0 + RUSTFLAGS: "-Dwarnings" + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - 1.81.0 # MSRV + - stable + target: + - thumbv7em-none-eabi + - wasm32-unknown-unknown + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + targets: ${{ matrix.target }} + - run: cargo build --no-default-features --target ${{ matrix.target }} + + test: + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - 1.81.0 # MSRV + - stable + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + - run: cargo check --all-features + - run: cargo test --no-default-features + - run: cargo test + - run: cargo test --all-features From 5052040a7cbaa39e5f7c24d953555da17581ecb3 Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Thu, 10 Oct 2024 08:47:09 -0400 Subject: [PATCH 16/17] Add ANSI-X9.63-KDF support: update toolchain to 1.81 for clippy --- .github/workflows/workspace.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index b2fb78f..5005c97 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -17,7 +17,7 @@ jobs: - uses: RustCrypto/actions/cargo-cache@master - uses: dtolnay/rust-toolchain@master with: - toolchain: 1.75.0 + toolchain: 1.81.0 components: clippy - run: cargo clippy --all -- -D warnings From 400e73db30c2e857416633b3991a86a82b45b6e3 Mon Sep 17 00:00:00 2001 From: nemynm <180121731+nemynm@users.noreply.github.com> Date: Thu, 10 Oct 2024 09:34:25 -0400 Subject: [PATCH 17/17] Add ANSI-X9.63-KDF support: adjust comments on hashmaxlen and remove unnecessary overflow check --- ansi-x963-kdf/src/lib.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ansi-x963-kdf/src/lib.rs b/ansi-x963-kdf/src/lib.rs index c5dc67e..1a80357 100644 --- a/ansi-x963-kdf/src/lib.rs +++ b/ansi-x963-kdf/src/lib.rs @@ -69,17 +69,16 @@ where return Err(Error::NoOutput); } - // 1. Check if |Z| + |SharedInfo| + 4 >= hashmaxlen + // 1. Check that |Z| + |SharedInfo| + 4 < hashmaxlen + // where "hashmaxlen denote the maximum length in octets of messages that can be hashed using Hash". + // N.B.: `D::OutputSize::U64 * (u32::MAX as u64)`` is currently used as an approximation of hashmaxlen. if secret.len() as u64 + shared_info.len() as u64 + 4 >= D::OutputSize::U64 * (u32::MAX as u64) { return Err(Error::InputOverflow); } - // Counter overflow is possible only on architectures with usize bigger than 4 bytes. - const OVERFLOW_IS_POSSIBLE: bool = core::mem::size_of::() > 4; - // 2. Check that keydatalen < hashlen × (2^32 − 1) - if OVERFLOW_IS_POSSIBLE && (key.len() as u64 >= D::OutputSize::U64 * (u32::MAX as u64)) { + if key.len() as u64 >= D::OutputSize::U64 * (u32::MAX as u64) { return Err(Error::CounterOverflow); }