Skip to content

Commit

Permalink
crypto_provider: avoid rand dep for GREASE HPKE
Browse files Browse the repository at this point in the history
Previously we used the `rand` crate as a convenient way to select
a supported HPKE suite at random for ECH when using GREASE. In general
it's crummy to take a dep for such a minor need.

Instead, adapt the crypto provider CSRNG to this task by performing
a truncated uniform sampling. This should be more than sufficient for
the use-case and avoids an extra dep.
  • Loading branch information
cpu committed Jan 21, 2025
1 parent c74587b commit ae91548
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 9 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ webpki = { package = "rustls-webpki", version = "0.102.0", default-features = fa
libc = "0.2"
log = "0.4.22"
rustls-platform-verifier = "0.5"
rand = "0.8"
regex = "1.9.6"
toml = { version = "0.6.0", default-features = false, features = ["parse"] }
hickory-resolver = { version = "=0.25.0-alpha.4", features = ["dns-over-https-rustls", "webpki-roots"] }
Expand Down
1 change: 0 additions & 1 deletion librustls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ webpki = { workspace = true }
libc = { workspace = true }
log = { workspace = true }
rustls-platform-verifier = { workspace = true }
rand = { workspace = true }

[lib]
name = "rustls_ffi"
Expand Down
7 changes: 6 additions & 1 deletion librustls/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,12 @@ impl rustls_client_config_builder {
let builder = try_mut_from_ptr!(builder);
let hpke = try_ref_from_ptr!(hpke);

let Some((suite, placeholder_pk)) = hpke.grease_public_key() else {
let provider = match &builder.provider {
Some(provider) => provider,
None => return rustls_result::NoDefaultCryptoProvider,
};

let Some((suite, placeholder_pk)) = hpke.grease_public_key(provider) else {
return rustls_result::HpkeError;
};

Expand Down
31 changes: 26 additions & 5 deletions librustls/src/crypto_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use std::slice;
use std::sync::Arc;

use libc::size_t;
use rand::seq::SliceRandom;

#[cfg(feature = "aws-lc-rs")]
use rustls::crypto::aws_lc_rs;
Expand Down Expand Up @@ -509,10 +508,28 @@ impl Hpke {
///
/// Returns both the selected Rustls `hpke::Hpke` suite and the `hpke::HpkePublicKey`
/// or `None` if an error occurs.
pub(crate) fn grease_public_key(&self) -> Option<(&dyn hpke::Hpke, hpke::HpkePublicKey)> {
let suite = self.suites.choose(&mut rand::thread_rng())?;
pub(crate) fn grease_public_key(
&self,
provider: &CryptoProvider,
) -> Option<(&dyn hpke::Hpke, hpke::HpkePublicKey)> {
let num_suites = self.suites.len();
if num_suites == 0 {
return None;
}
debug_assert!(num_suites < u32::MAX as usize);

let mut buf = [0u8; 4];
let threshold = u32::MAX - (u32::MAX % num_suites as u32);
let suite = loop {
provider.secure_random.fill(&mut buf).ok()?;
let value = u32::from_ne_bytes(buf);
if value < threshold {
break self.suites[value as usize / (threshold as usize / num_suites)];
}
};

let pk = suite.generate_key_pair().map(|pair| pair.0).ok()?;
Some((*suite, pk))
Some((suite, pk))
}
}

Expand Down Expand Up @@ -625,13 +642,17 @@ mod tests {
#[test]
#[cfg(feature = "aws-lc-rs")]
fn test_hpke_aws_lc_rs() {
let provider = rustls_crypto_provider_default();
assert!(!provider.is_null());
let provider = try_clone_arc!(provider);

let hpke = rustls_supported_hpke();
assert!(!hpke.is_null());

let hpke = try_ref_from_ptr!(hpke);

// We should be able to pick an HPKE suite and a pubkey for ECH GREASE.
let (suite, pk) = hpke.grease_public_key().unwrap();
let (suite, pk) = hpke.grease_public_key(&provider).unwrap();
// The PK and the suite should be compatible. Setup a sealer to check.
let (_, _) = suite.setup_sealer(&[0xC0, 0xFF, 0xEE], &pk).unwrap();
}
Expand Down

0 comments on commit ae91548

Please sign in to comment.