Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove arbitrary HKDF info length limit #424

Merged
merged 5 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion aws-lc-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ fips = ["dep:aws-lc-fips-sys"]
untrusted = { version = "0.7.1", optional = true }
aws-lc-sys = { version = "0.17.0", path = "../aws-lc-sys", optional = true }
aws-lc-fips-sys = { version = "0.12.0", path = "../aws-lc-fips-sys", optional = true }
zeroize = "1.7"
zeroize = { version = "1.7", features = ["zeroize_derive"] }
mirai-annotations = "1.12.0"
paste = "1.0.11"

Expand Down
31 changes: 10 additions & 21 deletions aws-lc-rs/src/hkdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,10 @@ pub static HKDF_SHA512: Algorithm = Algorithm(hmac::HMAC_SHA512);
/// We set the limit to something tolerable, so that the Salt structure can be stack allocatable.
const MAX_HKDF_SALT_LEN: usize = 80;

// This is needed so that the precise value can be provided in the documentation.
macro_rules! max_hkdf_info_len {
() => {
102
};
}

/// General Info length's for HKDF don't normally exceed 256 bits.
/// We set the limit to something tolerable, so that the memory passed into |`HKDF_expand`| is
/// allocated on the stack.
const MAX_HKDF_INFO_LEN: usize = max_hkdf_info_len!();
/// We set the default capacity to a value larger than should be needed
/// so that the value passed to |`HKDF_expand`| is only allocated once.
const HKDF_INFO_DEFAULT_CAPACITY_LEN: usize = 300;

/// The maximum output size of a PRK computed by |`HKDF_extract`| is the maximum digest
/// size that can be outputted by *AWS-LC*.
Expand Down Expand Up @@ -350,9 +343,8 @@ impl Prk {
/// [HKDF-Expand]: https://tools.ietf.org/html/rfc5869#section-2.3
///
/// # Errors
/// Returns `error::Unspecified` if either:
/// Returns `error::Unspecified` if:
/// * `len` is more than 255 times the digest algorithm's output length.
#[doc = concat!(" * the combined lengths of the `info` slices is more than ", max_hkdf_info_len!(), " bytes.")]
// # FIPS
// The following conditions must be met:
// * `Prk` must be constructed using `Salt::extract` prior to calling
Expand All @@ -368,16 +360,13 @@ impl Prk {
if len_cached > 255 * self.algorithm.0.digest_algorithm().output_len {
return Err(Unspecified);
}
let mut info_bytes = [0u8; MAX_HKDF_INFO_LEN];
let mut info_bytes: Vec<u8> = Vec::with_capacity(HKDF_INFO_DEFAULT_CAPACITY_LEN);
let mut info_len = 0;
for byte_ary in info {
let new_info_len = info_len + byte_ary.len();
if new_info_len > MAX_HKDF_INFO_LEN {
return Err(Unspecified);
}
info_bytes[info_len..new_info_len].copy_from_slice(byte_ary);
info_len = new_info_len;
for &byte_ary in info {
info_bytes.extend_from_slice(byte_ary);
info_len += byte_ary.len();
}
let info_bytes = info_bytes.into_boxed_slice();
Ok(Okm {
prk: self,
info_bytes,
Expand Down Expand Up @@ -407,7 +396,7 @@ impl From<Okm<'_, Algorithm>> for Prk {
/// use once.
pub struct Okm<'a, L: KeyType> {
prk: &'a Prk,
info_bytes: [u8; MAX_HKDF_INFO_LEN],
info_bytes: Box<[u8]>,
info_len: usize,
len: L,
}
Expand Down
18 changes: 18 additions & 0 deletions aws-lc-rs/tests/hkdf_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,24 @@ fn hkdf_output_len_tests() {
}
}

#[test]
fn hkdf_info_len_tests() {
for &alg in &[hkdf::HKDF_SHA256, hkdf::HKDF_SHA384, hkdf::HKDF_SHA512] {
for info_length in (50..300).step_by(7) {
let salt = hkdf::Salt::new(alg, &[]);
let prk = salt.extract(&[]); // TODO: enforce minimum length.
let info = vec![1u8; info_length];
let info = &[info.as_slice()];

{
let okm = prk.expand(info, My(2)).unwrap();
let mut buf = [0u8; 2];
assert_eq!(okm.fill(&mut buf), Ok(()));
}
}
}
}

#[test]
/// Try creating various key types via HKDF.
fn hkdf_key_types() {
Expand Down
Loading