summaryrefslogtreecommitdiffstats
path: root/vendor/hkdf/src
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/src
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/src')
-rw-r--r--vendor/hkdf/src/errors.rs29
-rw-r--r--vendor/hkdf/src/lib.rs280
-rw-r--r--vendor/hkdf/src/sealed.rs97
3 files changed, 406 insertions, 0 deletions
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())
+ }
+}