summaryrefslogtreecommitdiffstats
path: root/vendor/hkdf
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
commit10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch)
treebdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/hkdf
parentReleasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff)
downloadrustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz
rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/hkdf')
-rw-r--r--vendor/hkdf/.cargo-checksum.json1
-rw-r--r--vendor/hkdf/CHANGELOG.md115
-rw-r--r--vendor/hkdf/Cargo.toml44
-rw-r--r--vendor/hkdf/LICENSE-APACHE201
-rw-r--r--vendor/hkdf/LICENSE-MIT26
-rw-r--r--vendor/hkdf/README.md85
-rw-r--r--vendor/hkdf/benches/mod.rs27
-rw-r--r--vendor/hkdf/src/errors.rs29
-rw-r--r--vendor/hkdf/src/lib.rs280
-rw-r--r--vendor/hkdf/src/sealed.rs97
-rw-r--r--vendor/hkdf/tests/data/wycheproof-sha1.blbbin0 -> 23773 bytes
-rw-r--r--vendor/hkdf/tests/data/wycheproof-sha256.blbbin0 -> 33115 bytes
-rw-r--r--vendor/hkdf/tests/data/wycheproof-sha384.blbbin0 -> 45304 bytes
-rw-r--r--vendor/hkdf/tests/data/wycheproof-sha512.blbbin0 -> 57877 bytes
-rw-r--r--vendor/hkdf/tests/tests.rs448
15 files changed, 1353 insertions, 0 deletions
diff --git a/vendor/hkdf/.cargo-checksum.json b/vendor/hkdf/.cargo-checksum.json
new file mode 100644
index 000000000..13ce04190
--- /dev/null
+++ b/vendor/hkdf/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"a62505032740ed6600e51c157e0fddf5987aa5bd1f88afbc9acc8ff309af938c","Cargo.toml":"2bb17aca400fdb8071fa155d7fa4b630648dcbc5c9ef1bb1c94757afa083c2e6","LICENSE-APACHE":"59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018","LICENSE-MIT":"d288f9c9b4590446ec18c22ead8f8b5a12a3d4025b68f62dc9015063eb9cca69","README.md":"2d81cae833da6b98af93e747cb7ca024c94e4998465a56eeee3f8398be5b5071","benches/mod.rs":"ecb5e2dd2f9c65bd034edb93060d005a2e73ba4d02a6dab5088aa3dab36aa579","src/errors.rs":"5f10c52e5feab73bf3ac7dc8b5e50a149f6949747eabd5284a71bd4b0b6af552","src/lib.rs":"9d3bda187a3d14c45b632a453fb31693e0bfb3d611a2ce0f495d7b186bb16da4","src/sealed.rs":"4d4a88eb1b4467a64f937a59e97619d8144a2b5f705cd5edf7f40cde77f6be2f","tests/data/wycheproof-sha1.blb":"b058851715d3c81bf73987dd5e3671c49a58e330735a37b4011d22c0553b5f8b","tests/data/wycheproof-sha256.blb":"294e7574c0da80a174939f474745a83b0374a232110e0f4b466ff81325280ecc","tests/data/wycheproof-sha384.blb":"fed469c38b390a3f985ba27b11575dede03b606e30484b0fa769e74101b05cd0","tests/data/wycheproof-sha512.blb":"dc4f36baff633b33fa0f71abccc91f5a1a16fa4b06569b6f970712b2972001a8","tests/tests.rs":"a56e47de69ffc02fb9fea210382db78e82cbe5e8cbe81020d0e51cf1ad0278e0"},"package":"791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"} \ No newline at end of file
diff --git a/vendor/hkdf/CHANGELOG.md b/vendor/hkdf/CHANGELOG.md
new file mode 100644
index 000000000..4e8c3210b
--- /dev/null
+++ b/vendor/hkdf/CHANGELOG.md
@@ -0,0 +1,115 @@
+# 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.12.3 (2022-02-17)
+### Fixed
+- Minimal versions build ([#63])
+
+[#63]: https://github.com/RustCrypto/KDFs/pull/63
+
+## 0.12.2 (2022-01-27)
+### Fixed
+- Re-export `InvalidLength` and `InvalidPrkLength` ([#59])
+
+[#59]: https://github.com/RustCrypto/KDFs/pull/59
+
+## 0.12.1 (2022-01-27) [YANKED]
+### Added
+- Ability to switch HMAC implementation to `SimpleHmac` with respective `SimpleHkdfExtract` and `SimpleHkdf` aliases ([#57])
+
+[#57]: https://github.com/RustCrypto/KDFs/pull/55
+
+## 0.12.0 (2021-12-07)
+### Changed
+- Bump `hmac` crate dependency to v0.12 and `digest` to v0.10 ([#52])
+
+[#52]: https://github.com/RustCrypto/KDFs/pull/52
+
+## 0.11.0 (2021-04-29)
+### Added
+- Wycheproof HKDF test vectors ([#49])
+
+### Changed
+- Bump `hmac` crate dependency to v0.11 ([#50])
+
+### Fixed
+- HKDF-Extract with empty salt ([#46])
+
+[#46]: https://github.com/RustCrypto/KDFs/pull/46
+[#49]: https://github.com/RustCrypto/KDFs/pull/49
+[#50]: https://github.com/RustCrypto/KDFs/pull/50
+
+## 0.10.0 (2020-10-26)
+### Changed
+- Bump `hmac` dependency to v0.10 ([#40])
+
+[#40]: https://github.com/RustCrypto/KDFs/pull/40
+
+## 0.9.0 (2020-06-22)
+### Added
+- Multipart features for HKDF-Extract and HKDF-Expand ([#34])
+
+### Changed
+- Bump `digest` v0.9; `hmac` v0.9 ([#35])
+
+[#34]: https://github.com/RustCrypto/KDFs/pull/34
+[#35]: https://github.com/RustCrypto/KDFs/pull/35
+
+## 0.8.0 (2019-07-26)
+### Added
+- `Hkdf::from_prk()`, `Hkdf::extract()`
+
+## 0.7.1 (2019-07-15)
+
+## 0.7.0 (2018-10-16)
+### Changed
+- Update digest to 0.8
+- Refactor for API changes
+
+### Removed
+- Redundant `generic-array` crate.
+
+## 0.6.0 (2018-08-20)
+### Changed
+- The `expand` signature has changed.
+
+### Removed
+- `std` requirement
+
+## 0.5.0 (2018-05-20)
+### Fixed
+- Omitting HKDF salt.
+
+### Removed
+- Deprecated interface
+
+## 0.4.0 (2018-03-20
+### Added
+- Benchmarks
+- derive `Clone`
+
+### Changed
+- RFC-inspired interface
+- Reduce heap allocation
+- Bump deps: hex-0.3
+
+### Removed
+- Unnecessary mut
+
+## 0.3.0 (2017-11-29)
+### Changed
+- update dependencies: digest-0.7, hmac-0.5
+
+## 0.2.0 (2017-09-21)
+### Fixed
+- Support for rustc 1.20.0
+
+## 0.1.2 (2017-09-21)
+### Fixed
+- Support for rustc 1.5.0
+
+## 0.1.0 (2017-09-21)
+- Initial release
diff --git a/vendor/hkdf/Cargo.toml b/vendor/hkdf/Cargo.toml
new file mode 100644
index 000000000..03596456a
--- /dev/null
+++ b/vendor/hkdf/Cargo.toml
@@ -0,0 +1,44 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "hkdf"
+version = "0.12.3"
+authors = ["RustCrypto Developers"]
+description = "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"
+homepage = "https://github.com/RustCrypto/KDFs/"
+readme = "README.md"
+keywords = ["crypto", "HKDF", "KDF"]
+categories = ["cryptography", "no-std"]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/RustCrypto/KDFs/"
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = ["--cfg", "docsrs"]
+[dependencies.hmac]
+version = "0.12.1"
+[dev-dependencies.blobby]
+version = "0.3"
+
+[dev-dependencies.hex-literal]
+version = "0.2.2"
+
+[dev-dependencies.sha-1]
+version = "0.10"
+default-features = false
+
+[dev-dependencies.sha2]
+version = "0.10"
+default-features = false
+
+[features]
+std = ["hmac/std"]
diff --git a/vendor/hkdf/LICENSE-APACHE b/vendor/hkdf/LICENSE-APACHE
new file mode 100644
index 000000000..53b7ccd84
--- /dev/null
+++ b/vendor/hkdf/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. \ No newline at end of file
diff --git a/vendor/hkdf/LICENSE-MIT b/vendor/hkdf/LICENSE-MIT
new file mode 100644
index 000000000..c0d07816b
--- /dev/null
+++ b/vendor/hkdf/LICENSE-MIT
@@ -0,0 +1,26 @@
+Copyright (c) 2015-2018 Vlad Filippov
+Copyright (c) 2018-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/vendor/hkdf/README.md b/vendor/hkdf/README.md
new file mode 100644
index 000000000..76efd86e1
--- /dev/null
+++ b/vendor/hkdf/README.md
@@ -0,0 +1,85 @@
+# RustCrypto: HKDF
+
+[![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 [HMAC-based Extract-and-Expand Key Derivation Function (HKDF)](https://tools.ietf.org/html/rfc5869) generic over hash function.
+
+# Usage
+
+The most common way to use HKDF is as follows: you provide the Initial Key Material (IKM) and an optional salt, then you expand it (perhaps multiple times) into some Output Key Material (OKM) bound to an "info" context string.
+
+```rust
+use sha2::Sha256;
+use hkdf::Hkdf;
+use hex_literal::hex;
+
+let ikm = hex!("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
+let salt = hex!("000102030405060708090a0b0c");
+let info = hex!("f0f1f2f3f4f5f6f7f8f9");
+
+let hk = Hkdf::<Sha256>::new(Some(&salt[..]), &ikm);
+let mut okm = [0u8; 42];
+hk.expand(&info, &mut okm)
+ .expect("42 is a valid length for Sha256 to output");
+
+let expected = hex!("
+ 3cb25f25faacd57a90434f64d0362f2a
+ 2d2d0a90cf1a5a4c5db02d56ecc4c5bf
+ 34007208d5b887185865
+");
+assert_eq!(okm, expected);
+```
+
+Normally the PRK (Pseudo-Random Key) remains hidden within the HKDF object, but if you need to access it, use `Hkdf::extract` instead of `Hkdf::new`.
+
+```rust
+let (prk, hk) = Hkdf::<Sha256>::extract(Some(&salt[..]), &ikm);
+let expected = hex!("
+ 077709362c2e32df0ddc3f0dc47bba63
+ 90b6c73bb50f9c3122ec844ad7c2b3e5
+");
+assert_eq!(prk[..], expected[..]);
+```
+
+If you already have a strong key to work from (uniformly-distributed and
+long enough), you can save a tiny amount of time by skipping the extract
+step. In this case, you pass a Pseudo-Random Key (PRK) into the
+`Hkdf::from_prk` constructor, then use the resulting `Hkdf` object
+as usual.
+
+```rust
+let prk = hex!("
+ 077709362c2e32df0ddc3f0dc47bba63
+ 90b6c73bb50f9c3122ec844ad7c2b3e5
+");
+
+let hk = Hkdf::<Sha256>::from_prk(&prk).expect("PRK should be large enough");
+let mut okm = [0u8; 42];
+hk.expand(&info, &mut okm)
+ .expect("42 is a valid length for Sha256 to output");
+
+let expected = hex!("
+ 3cb25f25faacd57a90434f64d0362f2a
+ 2d2d0a90cf1a5a4c5db02d56ecc4c5bf
+ 34007208d5b887185865
+");
+assert_eq!(okm, expected);
+```
+
+[//]: # (badges)
+
+[crate-image]: https://img.shields.io/crates/v/hkdf.svg
+[crate-link]: https://crates.io/crates/hkdf
+[docs-image]: https://docs.rs/hkdf/badge.svg
+[docs-link]: https://docs.rs/hkdf/
+[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/260043-KDFs
+[build-image]: https://github.com/RustCrypto/KDFs/workflows/hkdf/badge.svg?branch=master&event=push
+[build-link]: https://github.com/RustCrypto/KDFs/actions?query=workflow:hkdf
diff --git a/vendor/hkdf/benches/mod.rs b/vendor/hkdf/benches/mod.rs
new file mode 100644
index 000000000..4679b59b7
--- /dev/null
+++ b/vendor/hkdf/benches/mod.rs
@@ -0,0 +1,27 @@
+#![feature(test)]
+extern crate test;
+
+use test::Bencher;
+
+type HkdfSha256 = hkdf::Hkdf<sha2::Sha256>;
+
+#[bench]
+fn hkdf_sha256_10(b: &mut Bencher) {
+ let mut okm = vec![0u8; 10];
+ b.iter(|| HkdfSha256::new(Some(&[]), &[]).expand(&[], &mut okm));
+ b.bytes = okm.len() as u64;
+}
+
+#[bench]
+fn hkdf_sha256_1024(b: &mut Bencher) {
+ let mut okm = vec![0u8; 1024];
+ b.iter(|| HkdfSha256::new(Some(&[]), &[]).expand(&[], &mut okm));
+ b.bytes = okm.len() as u64;
+}
+
+#[bench]
+fn hkdf_sha256_8000(b: &mut Bencher) {
+ let mut okm = vec![0u8; 8000];
+ b.iter(|| HkdfSha256::new(Some(&[]), &[]).expand(&[], &mut okm));
+ b.bytes = okm.len() as u64;
+}
diff --git a/vendor/hkdf/src/errors.rs b/vendor/hkdf/src/errors.rs
new file mode 100644
index 000000000..e2109b473
--- /dev/null
+++ b/vendor/hkdf/src/errors.rs
@@ -0,0 +1,29 @@
+use core::fmt;
+
+/// Error that is returned when supplied pseudorandom key (PRK) is not long enough.
+#[derive(Copy, Clone, Debug)]
+pub struct InvalidPrkLength;
+
+impl fmt::Display for InvalidPrkLength {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
+ f.write_str("invalid pseudorandom key length, too short")
+ }
+}
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+impl ::std::error::Error for InvalidPrkLength {}
+
+/// Structure for InvalidLength, used for output error handling.
+#[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 number of blocks, too large output")
+ }
+}
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+impl ::std::error::Error for InvalidLength {}
diff --git a/vendor/hkdf/src/lib.rs b/vendor/hkdf/src/lib.rs
new file mode 100644
index 000000000..ca05bf7a3
--- /dev/null
+++ b/vendor/hkdf/src/lib.rs
@@ -0,0 +1,280 @@
+//! An implementation of HKDF, the [HMAC-based Extract-and-Expand Key Derivation Function][1].
+//!
+//! # Usage
+//!
+//! The most common way to use HKDF is as follows: you provide the Initial Key
+//! Material (IKM) and an optional salt, then you expand it (perhaps multiple times)
+//! into some Output Key Material (OKM) bound to an "info" context string.
+//!
+//! ```rust
+//! use sha2::Sha256;
+//! use hkdf::Hkdf;
+//! use hex_literal::hex;
+//!
+//! let ikm = hex!("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
+//! let salt = hex!("000102030405060708090a0b0c");
+//! let info = hex!("f0f1f2f3f4f5f6f7f8f9");
+//!
+//! let hk = Hkdf::<Sha256>::new(Some(&salt[..]), &ikm);
+//! let mut okm = [0u8; 42];
+//! hk.expand(&info, &mut okm)
+//! .expect("42 is a valid length for Sha256 to output");
+//!
+//! let expected = hex!("
+//! 3cb25f25faacd57a90434f64d0362f2a
+//! 2d2d0a90cf1a5a4c5db02d56ecc4c5bf
+//! 34007208d5b887185865
+//! ");
+//! assert_eq!(okm[..], expected[..]);
+//! ```
+//!
+//! Normally the PRK (Pseudo-Random Key) remains hidden within the HKDF
+//! object, but if you need to access it, use [`Hkdf::extract`] instead of
+//! [`Hkdf::new`].
+//!
+//! ```rust
+//! # use sha2::Sha256;
+//! # use hkdf::Hkdf;
+//! # use hex_literal::hex;
+//! # let ikm = hex!("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
+//! # let salt = hex!("000102030405060708090a0b0c");
+//!
+//! let (prk, hk) = Hkdf::<Sha256>::extract(Some(&salt[..]), &ikm);
+//! let expected = hex!("
+//! 077709362c2e32df0ddc3f0dc47bba63
+//! 90b6c73bb50f9c3122ec844ad7c2b3e5
+//! ");
+//! assert_eq!(prk[..], expected[..]);
+//! ```
+//!
+//! If you already have a strong key to work from (uniformly-distributed and
+//! long enough), you can save a tiny amount of time by skipping the extract
+//! step. In this case, you pass a Pseudo-Random Key (PRK) into the
+//! [`Hkdf::from_prk`] constructor, then use the resulting [`Hkdf`] object
+//! as usual.
+//!
+//! ```rust
+//! # use sha2::Sha256;
+//! # use hkdf::Hkdf;
+//! # use hex_literal::hex;
+//! # let salt = hex!("000102030405060708090a0b0c");
+//! # let info = hex!("f0f1f2f3f4f5f6f7f8f9");
+//! let prk = hex!("
+//! 077709362c2e32df0ddc3f0dc47bba63
+//! 90b6c73bb50f9c3122ec844ad7c2b3e5
+//! ");
+//!
+//! let hk = Hkdf::<Sha256>::from_prk(&prk).expect("PRK should be large enough");
+//! let mut okm = [0u8; 42];
+//! hk.expand(&info, &mut okm)
+//! .expect("42 is a valid length for Sha256 to output");
+//!
+//! let expected = hex!("
+//! 3cb25f25faacd57a90434f64d0362f2a
+//! 2d2d0a90cf1a5a4c5db02d56ecc4c5bf
+//! 34007208d5b887185865
+//! ");
+//! assert_eq!(okm[..], expected[..]);
+//! ```
+//!
+//! [1]: https://tools.ietf.org/html/rfc5869
+
+#![no_std]
+#![doc(
+ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
+ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
+ html_root_url = "https://docs.rs/hkdf/0.12.3"
+)]
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![forbid(unsafe_code)]
+#![warn(missing_docs, rust_2018_idioms)]
+
+#[cfg(feature = "std")]
+extern crate std;
+
+pub use hmac;
+
+use core::fmt;
+use core::marker::PhantomData;
+use hmac::digest::{
+ crypto_common::AlgorithmName, generic_array::typenum::Unsigned, Output, OutputSizeUser,
+};
+use hmac::{Hmac, SimpleHmac};
+
+mod errors;
+mod sealed;
+
+pub use errors::{InvalidLength, InvalidPrkLength};
+
+/// [`HkdfExtract`] variant which uses [`SimpleHmac`] for underlying HMAC
+/// implementation.
+pub type SimpleHkdfExtract<H> = HkdfExtract<H, SimpleHmac<H>>;
+/// [`Hkdf`] variant which uses [`SimpleHmac`] for underlying HMAC
+/// implementation.
+pub type SimpleHkdf<H> = Hkdf<H, SimpleHmac<H>>;
+
+/// Structure representing the streaming context of an HKDF-Extract operation
+/// ```rust
+/// # use hkdf::{Hkdf, HkdfExtract};
+/// # use sha2::Sha256;
+/// let mut extract_ctx = HkdfExtract::<Sha256>::new(Some(b"mysalt"));
+/// extract_ctx.input_ikm(b"hello");
+/// extract_ctx.input_ikm(b" world");
+/// let (streamed_res, _) = extract_ctx.finalize();
+///
+/// let (oneshot_res, _) = Hkdf::<Sha256>::extract(Some(b"mysalt"), b"hello world");
+/// assert_eq!(streamed_res, oneshot_res);
+/// ```
+#[derive(Clone)]
+pub struct HkdfExtract<H, I = Hmac<H>>
+where
+ H: OutputSizeUser,
+ I: HmacImpl<H>,
+{
+ hmac: I,
+ _pd: PhantomData<H>,
+}
+
+impl<H, I> HkdfExtract<H, I>
+where
+ H: OutputSizeUser,
+ I: HmacImpl<H>,
+{
+ /// Initiates the HKDF-Extract context with the given optional salt
+ pub fn new(salt: Option<&[u8]>) -> Self {
+ let default_salt = Output::<H>::default();
+ let salt = salt.unwrap_or(&default_salt);
+ Self {
+ hmac: I::new_from_slice(salt),
+ _pd: PhantomData,
+ }
+ }
+
+ /// Feeds in additional input key material to the HKDF-Extract context
+ pub fn input_ikm(&mut self, ikm: &[u8]) {
+ self.hmac.update(ikm);
+ }
+
+ /// Completes the HKDF-Extract operation, returning both the generated pseudorandom key and
+ /// `Hkdf` struct for expanding.
+ pub fn finalize(self) -> (Output<H>, Hkdf<H, I>) {
+ let prk = self.hmac.finalize();
+ let hkdf = Hkdf::from_prk(&prk).expect("PRK size is correct");
+ (prk, hkdf)
+ }
+}
+
+impl<H, I> fmt::Debug for HkdfExtract<H, I>
+where
+ H: OutputSizeUser + AlgorithmName,
+ I: HmacImpl<H>,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("HkdfExtract<")?;
+ <H as AlgorithmName>::write_alg_name(f)?;
+ f.write_str("> { ... }")
+ }
+}
+
+/// Structure representing the HKDF, capable of HKDF-Expand and HKDF-Extract operations.
+#[derive(Clone)]
+pub struct Hkdf<H: OutputSizeUser, I: HmacImpl<H> = Hmac<H>> {
+ hmac: I::Core,
+ _pd: PhantomData<H>,
+}
+
+impl<H: OutputSizeUser, I: HmacImpl<H>> Hkdf<H, I> {
+ /// Convenience method for [`extract`][Hkdf::extract] when the generated
+ /// pseudorandom key can be ignored and only HKDF-Expand operation is needed. This is the most
+ /// common constructor.
+ pub fn new(salt: Option<&[u8]>, ikm: &[u8]) -> Self {
+ let (_, hkdf) = Self::extract(salt, ikm);
+ hkdf
+ }
+
+ /// Create `Hkdf` from an already cryptographically strong pseudorandom key
+ /// as per section 3.3 from RFC5869.
+ pub fn from_prk(prk: &[u8]) -> Result<Self, InvalidPrkLength> {
+ // section 2.3 specifies that prk must be "at least HashLen octets"
+ if prk.len() < <H as OutputSizeUser>::OutputSize::to_usize() {
+ return Err(InvalidPrkLength);
+ }
+ Ok(Self {
+ hmac: I::new_core(prk),
+ _pd: PhantomData,
+ })
+ }
+
+ /// The RFC5869 HKDF-Extract operation returning both the generated
+ /// pseudorandom key and `Hkdf` struct for expanding.
+ pub fn extract(salt: Option<&[u8]>, ikm: &[u8]) -> (Output<H>, Self) {
+ let mut extract_ctx = HkdfExtract::new(salt);
+ extract_ctx.input_ikm(ikm);
+ extract_ctx.finalize()
+ }
+
+ /// The RFC5869 HKDF-Expand operation. This is equivalent to calling
+ /// [`expand`][Hkdf::extract] with the `info` argument set equal to the
+ /// concatenation of all the elements of `info_components`.
+ pub fn expand_multi_info(
+ &self,
+ info_components: &[&[u8]],
+ okm: &mut [u8],
+ ) -> Result<(), InvalidLength> {
+ let mut prev: Option<Output<H>> = None;
+
+ let chunk_len = <H as OutputSizeUser>::OutputSize::USIZE;
+ if okm.len() > chunk_len * 255 {
+ return Err(InvalidLength);
+ }
+
+ for (block_n, block) in okm.chunks_mut(chunk_len).enumerate() {
+ let mut hmac = I::from_core(&self.hmac);
+
+ if let Some(ref prev) = prev {
+ hmac.update(prev)
+ };
+
+ // Feed in the info components in sequence. This is equivalent to feeding in the
+ // concatenation of all the info components
+ for info in info_components {
+ hmac.update(info);
+ }
+
+ hmac.update(&[block_n as u8 + 1]);
+
+ let output = hmac.finalize();
+
+ let block_len = block.len();
+ block.copy_from_slice(&output[..block_len]);
+
+ prev = Some(output);
+ }
+
+ Ok(())
+ }
+
+ /// The RFC5869 HKDF-Expand operation
+ ///
+ /// If you don't have any `info` to pass, use an empty slice.
+ pub fn expand(&self, info: &[u8], okm: &mut [u8]) -> Result<(), InvalidLength> {
+ self.expand_multi_info(&[info], okm)
+ }
+}
+
+impl<H, I> fmt::Debug for Hkdf<H, I>
+where
+ H: OutputSizeUser + AlgorithmName,
+ I: HmacImpl<H>,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("Hkdf<")?;
+ <H as AlgorithmName>::write_alg_name(f)?;
+ f.write_str("> { ... }")
+ }
+}
+
+/// Sealed trait implemented for [`Hmac`] and [`SimpleHmac`].
+pub trait HmacImpl<H: OutputSizeUser>: sealed::Sealed<H> {}
+
+impl<H: OutputSizeUser, T: sealed::Sealed<H>> HmacImpl<H> for T {}
diff --git a/vendor/hkdf/src/sealed.rs b/vendor/hkdf/src/sealed.rs
new file mode 100644
index 000000000..5a2ec6214
--- /dev/null
+++ b/vendor/hkdf/src/sealed.rs
@@ -0,0 +1,97 @@
+use hmac::digest::{
+ block_buffer::Eager,
+ core_api::{
+ BlockSizeUser, BufferKindUser, CoreProxy, CoreWrapper, FixedOutputCore, OutputSizeUser,
+ UpdateCore,
+ },
+ generic_array::typenum::{IsLess, Le, NonZero, U256},
+ Digest, FixedOutput, HashMarker, KeyInit, Output, Update,
+};
+use hmac::{Hmac, HmacCore, SimpleHmac};
+
+pub trait Sealed<H: OutputSizeUser> {
+ type Core: Clone;
+
+ fn new_from_slice(key: &[u8]) -> Self;
+
+ fn new_core(key: &[u8]) -> Self::Core;
+
+ fn from_core(core: &Self::Core) -> Self;
+
+ fn update(&mut self, data: &[u8]);
+
+ fn finalize(self) -> Output<H>;
+}
+
+impl<H> Sealed<H> for Hmac<H>
+where
+ H: CoreProxy + OutputSizeUser,
+ H::Core: HashMarker
+ + UpdateCore
+ + FixedOutputCore
+ + BufferKindUser<BufferKind = Eager>
+ + Default
+ + Clone,
+ <H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
+ Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
+{
+ type Core = HmacCore<H>;
+
+ #[inline(always)]
+ fn new_from_slice(key: &[u8]) -> Self {
+ KeyInit::new_from_slice(key).expect("HMAC can take a key of any size")
+ }
+
+ #[inline(always)]
+ fn new_core(key: &[u8]) -> Self::Core {
+ HmacCore::new_from_slice(key).expect("HMAC can take a key of any size")
+ }
+
+ #[inline(always)]
+ fn from_core(core: &Self::Core) -> Self {
+ CoreWrapper::from_core(core.clone())
+ }
+
+ #[inline(always)]
+ fn update(&mut self, data: &[u8]) {
+ Update::update(self, data);
+ }
+
+ #[inline(always)]
+ fn finalize(self) -> Output<H> {
+ // Output<H> and Output<H::Core> are always equal to each other,
+ // but we can not prove it at type level
+ Output::<H>::clone_from_slice(&self.finalize_fixed())
+ }
+}
+
+impl<H: Digest + BlockSizeUser + Clone> Sealed<H> for SimpleHmac<H> {
+ type Core = Self;
+
+ #[inline(always)]
+ fn new_from_slice(key: &[u8]) -> Self {
+ KeyInit::new_from_slice(key).expect("HMAC can take a key of any size")
+ }
+
+ #[inline(always)]
+ fn new_core(key: &[u8]) -> Self::Core {
+ KeyInit::new_from_slice(key).expect("HMAC can take a key of any size")
+ }
+
+ #[inline(always)]
+ fn from_core(core: &Self::Core) -> Self {
+ core.clone()
+ }
+
+ #[inline(always)]
+ fn update(&mut self, data: &[u8]) {
+ Update::update(self, data);
+ }
+
+ #[inline(always)]
+ fn finalize(self) -> Output<H> {
+ // Output<H> and Output<H::Core> are always equal to each other,
+ // but we can not prove it at type level
+ Output::<H>::clone_from_slice(&self.finalize_fixed())
+ }
+}
diff --git a/vendor/hkdf/tests/data/wycheproof-sha1.blb b/vendor/hkdf/tests/data/wycheproof-sha1.blb
new file mode 100644
index 000000000..cb7dd3c4b
--- /dev/null
+++ b/vendor/hkdf/tests/data/wycheproof-sha1.blb
Binary files differ
diff --git a/vendor/hkdf/tests/data/wycheproof-sha256.blb b/vendor/hkdf/tests/data/wycheproof-sha256.blb
new file mode 100644
index 000000000..6213609a3
--- /dev/null
+++ b/vendor/hkdf/tests/data/wycheproof-sha256.blb
Binary files differ
diff --git a/vendor/hkdf/tests/data/wycheproof-sha384.blb b/vendor/hkdf/tests/data/wycheproof-sha384.blb
new file mode 100644
index 000000000..2323055a4
--- /dev/null
+++ b/vendor/hkdf/tests/data/wycheproof-sha384.blb
Binary files differ
diff --git a/vendor/hkdf/tests/data/wycheproof-sha512.blb b/vendor/hkdf/tests/data/wycheproof-sha512.blb
new file mode 100644
index 000000000..7a75318ee
--- /dev/null
+++ b/vendor/hkdf/tests/data/wycheproof-sha512.blb
Binary files differ
diff --git a/vendor/hkdf/tests/tests.rs b/vendor/hkdf/tests/tests.rs
new file mode 100644
index 000000000..689388956
--- /dev/null
+++ b/vendor/hkdf/tests/tests.rs
@@ -0,0 +1,448 @@
+use core::iter;
+
+use hex_literal::hex;
+use hkdf::{Hkdf, HkdfExtract, SimpleHkdf, SimpleHkdfExtract};
+use sha1::Sha1;
+use sha2::{Sha256, Sha384, Sha512};
+
+struct Test<'a> {
+ ikm: &'a [u8],
+ salt: &'a [u8],
+ info: &'a [u8],
+ prk: &'a [u8],
+ okm: &'a [u8],
+}
+
+// Test Vectors from https://tools.ietf.org/html/rfc5869.
+#[test]
+#[rustfmt::skip]
+fn test_rfc5869_sha256() {
+ let tests = [
+ Test {
+ // Test Case 1
+ ikm: &hex!("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
+ salt: &hex!("000102030405060708090a0b0c"),
+ info: &hex!("f0f1f2f3f4f5f6f7f8f9"),
+ prk: &hex!("
+ 077709362c2e32df0ddc3f0dc47bba63
+ 90b6c73bb50f9c3122ec844ad7c2b3e5
+ "),
+ okm: &hex!("
+ 3cb25f25faacd57a90434f64d0362f2a
+ 2d2d0a90cf1a5a4c5db02d56ecc4c5bf
+ 34007208d5b887185865
+ "),
+ },
+ Test {
+ // Test Case 2
+ ikm: &hex!("
+ 000102030405060708090a0b0c0d0e0f
+ 101112131415161718191a1b1c1d1e1f
+ 202122232425262728292a2b2c2d2e2f
+ 303132333435363738393a3b3c3d3e3f
+ 404142434445464748494a4b4c4d4e4f
+ "),
+ salt: &hex!("
+ 606162636465666768696a6b6c6d6e6f
+ 707172737475767778797a7b7c7d7e7f
+ 808182838485868788898a8b8c8d8e8f
+ 909192939495969798999a9b9c9d9e9f
+ a0a1a2a3a4a5a6a7a8a9aaabacadaeaf
+ "),
+ info: &hex!("
+ b0b1b2b3b4b5b6b7b8b9babbbcbdbebf
+ c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+ d0d1d2d3d4d5d6d7d8d9dadbdcdddedf
+ e0e1e2e3e4e5e6e7e8e9eaebecedeeef
+ f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+ "),
+ prk: &hex!("
+ 06a6b88c5853361a06104c9ceb35b45c
+ ef760014904671014a193f40c15fc244
+ "),
+ okm: &hex!("
+ b11e398dc80327a1c8e7f78c596a4934
+ 4f012eda2d4efad8a050cc4c19afa97c
+ 59045a99cac7827271cb41c65e590e09
+ da3275600c2f09b8367793a9aca3db71
+ cc30c58179ec3e87c14c01d5c1f3434f
+ 1d87
+ "),
+ },
+ Test {
+ // Test Case 3
+ ikm: &hex!("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
+ salt: &hex!(""),
+ info: &hex!(""),
+ prk: &hex!("
+ 19ef24a32c717b167f33a91d6f648bdf
+ 96596776afdb6377ac434c1c293ccb04
+ "),
+ okm: &hex!("
+ 8da4e775a563c18f715f802a063c5a31
+ b8a11f5c5ee1879ec3454e5f3c738d2d
+ 9d201395faa4b61a96c8
+ "),
+ },
+ ];
+ for Test { ikm, salt, info, prk, okm } in tests.iter() {
+ let salt = if salt.is_empty() {
+ None
+ } else {
+ Some(&salt[..])
+ };
+ let (prk2, hkdf) = Hkdf::<Sha256>::extract(salt, ikm);
+ let mut okm2 = vec![0u8; okm.len()];
+ assert!(hkdf.expand(&info[..], &mut okm2).is_ok());
+
+ assert_eq!(prk2[..], prk[..]);
+ assert_eq!(okm2[..], okm[..]);
+
+ okm2.iter_mut().for_each(|b| *b = 0);
+ let hkdf = Hkdf::<Sha256>::from_prk(prk).unwrap();
+ assert!(hkdf.expand(&info[..], &mut okm2).is_ok());
+ assert_eq!(okm2[..], okm[..]);
+ }
+}
+
+#[test]
+#[rustfmt::skip]
+fn test_rfc5869_sha1() {
+ let tests = [
+ Test {
+ // Test Case 4
+ ikm: &hex!("0b0b0b0b0b0b0b0b0b0b0b"),
+ salt: &hex!("000102030405060708090a0b0c"),
+ info: &hex!("f0f1f2f3f4f5f6f7f8f9"),
+ prk: &hex!("9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243"),
+ okm: &hex!("
+ 085a01ea1b10f36933068b56efa5ad81
+ a4f14b822f5b091568a9cdd4f155fda2
+ c22e422478d305f3f896
+ "),
+ },
+ Test {
+ // Test Case 5
+ ikm: &hex!("
+ 000102030405060708090a0b0c0d0e0f
+ 101112131415161718191a1b1c1d1e1f
+ 202122232425262728292a2b2c2d2e2f
+ 303132333435363738393a3b3c3d3e3f
+ 404142434445464748494a4b4c4d4e4f
+ "),
+ salt: &hex!("
+ 606162636465666768696a6b6c6d6e6f
+ 707172737475767778797a7b7c7d7e7f
+ 808182838485868788898a8b8c8d8e8f
+ 909192939495969798999a9b9c9d9e9f
+ a0a1a2a3a4a5a6a7a8a9aaabacadaeaf
+ "),
+ info: &hex!("
+ b0b1b2b3b4b5b6b7b8b9babbbcbdbebf
+ c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+ d0d1d2d3d4d5d6d7d8d9dadbdcdddedf
+ e0e1e2e3e4e5e6e7e8e9eaebecedeeef
+ f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+ "),
+ prk: &hex!("8adae09a2a307059478d309b26c4115a224cfaf6"),
+ okm: &hex!("
+ 0bd770a74d1160f7c9f12cd5912a06eb
+ ff6adcae899d92191fe4305673ba2ffe
+ 8fa3f1a4e5ad79f3f334b3b202b2173c
+ 486ea37ce3d397ed034c7f9dfeb15c5e
+ 927336d0441f4c4300e2cff0d0900b52
+ d3b4
+ "),
+ },
+ Test {
+ // Test Case 6
+ ikm: &hex!("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
+ salt: &hex!(""),
+ info: &hex!(""),
+ prk: &hex!("da8c8a73c7fa77288ec6f5e7c297786aa0d32d01"),
+ okm: &hex!("
+ 0ac1af7002b3d761d1e55298da9d0506
+ b9ae52057220a306e07b6b87e8df21d0
+ ea00033de03984d34918
+ "),
+ },
+ Test {
+ // Test Case 7
+ ikm: &hex!("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c"),
+ salt: &hex!(""), // "Not Provided"
+ info: &hex!(""),
+ prk: &hex!("2adccada18779e7c2077ad2eb19d3f3e731385dd"),
+ okm: &hex!("
+ 2c91117204d745f3500d636a62f64f0a
+ b3bae548aa53d423b0d1f27ebba6f5e5
+ 673a081d70cce7acfc48
+ "),
+ },
+ ];
+ for Test { ikm, salt, info, prk, okm } in tests.iter() {
+ let salt = if salt.is_empty() {
+ None
+ } else {
+ Some(&salt[..])
+ };
+ let (prk2, hkdf) = Hkdf::<Sha1>::extract(salt, ikm);
+ let mut okm2 = vec![0u8; okm.len()];
+ assert!(hkdf.expand(&info[..], &mut okm2).is_ok());
+
+ assert_eq!(prk2[..], prk[..]);
+ assert_eq!(okm2[..], okm[..]);
+
+ okm2.iter_mut().for_each(|b| *b = 0);
+ let hkdf = Hkdf::<Sha1>::from_prk(prk).unwrap();
+ assert!(hkdf.expand(&info[..], &mut okm2).is_ok());
+ assert_eq!(okm2[..], okm[..]);
+ }
+}
+
+const MAX_SHA256_LENGTH: usize = 255 * (256 / 8); // =8160
+
+#[test]
+fn test_lengths() {
+ let hkdf = Hkdf::<Sha256>::new(None, &[]);
+ let mut longest = vec![0u8; MAX_SHA256_LENGTH];
+ assert!(hkdf.expand(&[], &mut longest).is_ok());
+ // Runtime is O(length), so exhaustively testing all legal lengths
+ // would take too long (at least without --release). Only test a
+ // subset: the first 500, the last 10, and every 100th in between.
+ let lengths = (0..MAX_SHA256_LENGTH + 1)
+ .filter(|&len| len < 500 || len > MAX_SHA256_LENGTH - 10 || len % 100 == 0);
+
+ for length in lengths {
+ let mut okm = vec![0u8; length];
+ assert!(hkdf.expand(&[], &mut okm).is_ok());
+ assert_eq!(okm.len(), length);
+ assert_eq!(okm[..], longest[..length]);
+ }
+}
+
+#[test]
+fn test_max_length() {
+ let hkdf = Hkdf::<Sha256>::new(Some(&[]), &[]);
+ let mut okm = vec![0u8; MAX_SHA256_LENGTH];
+ assert!(hkdf.expand(&[], &mut okm).is_ok());
+}
+
+#[test]
+fn test_max_length_exceeded() {
+ let hkdf = Hkdf::<Sha256>::new(Some(&[]), &[]);
+ let mut okm = vec![0u8; MAX_SHA256_LENGTH + 1];
+ assert!(hkdf.expand(&[], &mut okm).is_err());
+}
+
+#[test]
+fn test_unsupported_length() {
+ let hkdf = Hkdf::<Sha256>::new(Some(&[]), &[]);
+ let mut okm = vec![0u8; 90000];
+ assert!(hkdf.expand(&[], &mut okm).is_err());
+}
+
+#[test]
+fn test_prk_too_short() {
+ use sha2::digest::Digest;
+
+ let output_len = Sha256::output_size();
+ let prk = vec![0; output_len - 1];
+ assert!(Hkdf::<Sha256>::from_prk(&prk).is_err());
+}
+
+#[test]
+#[rustfmt::skip]
+fn test_derive_sha1_with_none() {
+ let ikm = hex!("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c");
+ let salt = None;
+ let info = hex!("");
+ let (prk, hkdf) = Hkdf::<Sha1>::extract(salt, &ikm[..]);
+ let mut okm = [0u8; 42];
+ assert!(hkdf.expand(&info[..], &mut okm).is_ok());
+
+ assert_eq!(
+ prk[..],
+ hex!("2adccada18779e7c2077ad2eb19d3f3e731385dd")[..]
+ );
+ assert_eq!(
+ okm[..],
+ hex!("
+ 2c91117204d745f3500d636a62f64f0a
+ b3bae548aa53d423b0d1f27ebba6f5e5
+ 673a081d70cce7acfc48
+ ")[..],
+ );
+}
+
+#[test]
+fn test_expand_multi_info() {
+ let info_components = &[
+ &b"09090909090909090909090909090909090909090909"[..],
+ &b"8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a"[..],
+ &b"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0"[..],
+ &b"4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4"[..],
+ &b"1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d"[..],
+ ];
+
+ let (_, hkdf_ctx) = Hkdf::<Sha256>::extract(None, b"some ikm here");
+
+ // Compute HKDF-Expand on the concatenation of all the info components
+ let mut oneshot_res = [0u8; 16];
+ hkdf_ctx
+ .expand(&info_components.concat(), &mut oneshot_res)
+ .unwrap();
+
+ // Now iteratively join the components of info_components until it's all 1 component. The value
+ // of HKDF-Expand should be the same throughout
+ let mut num_concatted = 0;
+ let mut info_head = Vec::new();
+
+ while num_concatted < info_components.len() {
+ info_head.extend(info_components[num_concatted]);
+
+ // Build the new input to be the info head followed by the remaining components
+ let input: Vec<&[u8]> = iter::once(info_head.as_slice())
+ .chain(info_components.iter().cloned().skip(num_concatted + 1))
+ .collect();
+
+ // Compute and compare to the one-shot answer
+ let mut multipart_res = [0u8; 16];
+ hkdf_ctx
+ .expand_multi_info(&input, &mut multipart_res)
+ .unwrap();
+ assert_eq!(multipart_res, oneshot_res);
+
+ num_concatted += 1;
+ }
+}
+
+#[test]
+fn test_extract_streaming() {
+ let ikm_components = &[
+ &b"09090909090909090909090909090909090909090909"[..],
+ &b"8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a"[..],
+ &b"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0"[..],
+ &b"4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4"[..],
+ &b"1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d"[..],
+ ];
+ let salt = b"mysalt";
+
+ // Compute HKDF-Extract on the concatenation of all the IKM components
+ let (oneshot_res, _) = Hkdf::<Sha256>::extract(Some(&salt[..]), &ikm_components.concat());
+
+ // Now iteratively join the components of ikm_components until it's all 1 component. The value
+ // of HKDF-Extract should be the same throughout
+ let mut num_concatted = 0;
+ let mut ikm_head = Vec::new();
+
+ while num_concatted < ikm_components.len() {
+ ikm_head.extend(ikm_components[num_concatted]);
+
+ // Make a new extraction context and build the new input to be the IKM head followed by the
+ // remaining components
+ let mut extract_ctx = HkdfExtract::<Sha256>::new(Some(&salt[..]));
+ let input = iter::once(ikm_head.as_slice())
+ .chain(ikm_components.iter().cloned().skip(num_concatted + 1));
+
+ // Stream in the IKM input in the chunks specified
+ for ikm in input {
+ extract_ctx.input_ikm(ikm);
+ }
+
+ // Finalize and compare to the one-shot answer
+ let (multipart_res, _) = extract_ctx.finalize();
+ assert_eq!(multipart_res, oneshot_res);
+
+ num_concatted += 1;
+ }
+
+ let mut num_concatted = 0;
+ let mut ikm_head = Vec::new();
+
+ while num_concatted < ikm_components.len() {
+ ikm_head.extend(ikm_components[num_concatted]);
+
+ // Make a new extraction context and build the new input to be the IKM head followed by the
+ // remaining components
+ let mut extract_ctx = SimpleHkdfExtract::<Sha256>::new(Some(&salt[..]));
+ let input = iter::once(ikm_head.as_slice())
+ .chain(ikm_components.iter().cloned().skip(num_concatted + 1));
+
+ // Stream in the IKM input in the chunks specified
+ for ikm in input {
+ extract_ctx.input_ikm(ikm);
+ }
+
+ // Finalize and compare to the one-shot answer
+ let (multipart_res, _) = extract_ctx.finalize();
+ assert_eq!(multipart_res, oneshot_res);
+
+ num_concatted += 1;
+ }
+}
+
+/// Define test
+macro_rules! new_test {
+ ($name:ident, $test_name:expr, $hkdf:ty) => {
+ #[test]
+ fn $name() {
+ use blobby::Blob4Iterator;
+
+ fn run_test(ikm: &[u8], salt: &[u8], info: &[u8], okm: &[u8]) -> Option<&'static str> {
+ let prk = <$hkdf>::new(Some(salt), ikm);
+ let mut got_okm = vec![0; okm.len()];
+
+ if prk.expand(info, &mut got_okm).is_err() {
+ return Some("prk expand");
+ }
+ if got_okm != okm {
+ return Some("mismatch in okm");
+ }
+ None
+ }
+
+ let data = include_bytes!(concat!("data/", $test_name, ".blb"));
+
+ for (i, row) in Blob4Iterator::new(data).unwrap().enumerate() {
+ let [ikm, salt, info, okm] = row.unwrap();
+ if let Some(desc) = run_test(ikm, salt, info, okm) {
+ panic!(
+ "\n\
+ Failed test №{}: {}\n\
+ ikm:\t{:?}\n\
+ salt:\t{:?}\n\
+ info:\t{:?}\n\
+ okm:\t{:?}\n",
+ i, desc, ikm, salt, info, okm
+ );
+ }
+ }
+ }
+ };
+}
+
+new_test!(wycheproof_sha1, "wycheproof-sha1", Hkdf::<Sha1>);
+new_test!(wycheproof_sha256, "wycheproof-sha256", Hkdf::<Sha256>);
+new_test!(wycheproof_sha384, "wycheproof-sha384", Hkdf::<Sha384>);
+new_test!(wycheproof_sha512, "wycheproof-sha512", Hkdf::<Sha512>);
+
+new_test!(
+ wycheproof_sha1_simple,
+ "wycheproof-sha1",
+ SimpleHkdf::<Sha1>
+);
+new_test!(
+ wycheproof_sha256_simple,
+ "wycheproof-sha256",
+ SimpleHkdf::<Sha256>
+);
+new_test!(
+ wycheproof_sha384_simple,
+ "wycheproof-sha384",
+ SimpleHkdf::<Sha384>
+);
+new_test!(
+ wycheproof_sha512_simple,
+ "wycheproof-sha512",
+ SimpleHkdf::<Sha512>
+);