Skip to content

Commit

Permalink
Enable use of aws-lc-rs instead of ring
Browse files Browse the repository at this point in the history
  • Loading branch information
djc committed Aug 8, 2024
1 parent 397c848 commit 267ccbb
Show file tree
Hide file tree
Showing 13 changed files with 62 additions and 33 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ arbitrary = { version = "1.0.1", features = ["derive"] }
async-io = "2"
async-std = "1.11"
assert_matches = "1.1"
aws-lc-rs = { version = "1.8.1", default-features = false }
bencher = "0.1.5"
bytes = "1"
clap = { version = "4", features = ["derive"] }
Expand All @@ -33,7 +34,7 @@ rand = "0.8"
rcgen = "0.13"
ring = "0.17"
rustc-hash = "2"
rustls = { version = "0.23.5", default-features = false, features = ["ring", "std"] }
rustls = { version = "0.23.5", default-features = false, features = ["std"] }
rustls-pemfile = "2"
rustls-platform-verifier = "0.3"
serde = { version = "1.0", features = ["derive"] }
Expand Down
2 changes: 1 addition & 1 deletion deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ allow = [
"ISC",
"MIT",
"MPL-2.0",
"OpenSSL",
"Unicode-DFS-2016",
]
exceptions = [{ allow = ["ISC", "MIT", "OpenSSL"], name = "ring" }]
private = { ignore = true }

[[licenses.clarify]]
Expand Down
6 changes: 5 additions & 1 deletion quinn-proto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ all-features = true

[features]
default = ["rustls", "log"]
rustls = ["dep:rustls", "ring"]
aws-lc-rs = ["dep:aws-lc-rs", "aws-lc-rs/aws-lc-sys"]
rustls = ["rustls-ring"]
rustls-aws-lc-rs = ["dep:rustls", "rustls/aws-lc-rs", "aws-lc-rs"]
rustls-ring = ["dep:rustls", "rustls/ring", "ring"]
ring = ["dep:ring"]
# Enable rustls ring provider and direct ring usage
# Provides `ClientConfig::with_platform_verifier()` convenience method
Expand All @@ -25,6 +28,7 @@ log = ["tracing/log"]

[dependencies]
arbitrary = { workspace = true, optional = true }
aws-lc-rs = { workspace = true, optional = true }
bytes = { workspace = true }
rustc-hash = { workspace = true }
rand = { workspace = true }
Expand Down
1 change: 0 additions & 1 deletion quinn-proto/src/cid_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ mod tests {
use super::*;

#[test]
#[cfg(feature = "ring")]
fn validate_keyed_cid() {
let mut generator = HashedConnectionIdGenerator::new();
let cid = generator.generate_cid();
Expand Down
25 changes: 16 additions & 9 deletions quinn-proto/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ use std::{
time::Duration,
};

#[cfg(feature = "ring")]
use rand::RngCore;
#[cfg(feature = "rustls")]
use rustls::client::WebPkiServerVerifier;
#[cfg(feature = "rustls")]
Expand Down Expand Up @@ -759,16 +757,19 @@ impl fmt::Debug for EndpointConfig {
}
}

#[cfg(feature = "ring")]
#[cfg(any(feature = "aws-lc-rs", feature = "ring"))]
impl Default for EndpointConfig {
fn default() -> Self {
#[cfg(all(feature = "aws-lc-rs", not(feature = "ring")))]
use aws_lc_rs::hmac;
use rand::RngCore;
#[cfg(feature = "ring")]
use ring::hmac;

let mut reset_key = [0; 64];
rand::thread_rng().fill_bytes(&mut reset_key);

Self::new(Arc::new(ring::hmac::Key::new(
ring::hmac::HMAC_SHA256,
&reset_key,
)))
Self::new(Arc::new(hmac::Key::new(hmac::HMAC_SHA256, &reset_key)))
}
}

Expand Down Expand Up @@ -934,16 +935,22 @@ impl ServerConfig {
}
}

#[cfg(feature = "ring")]
#[cfg(any(feature = "aws-lc-rs", feature = "ring"))]
impl ServerConfig {
/// Create a server config with the given [`crypto::ServerConfig`]
///
/// Uses a randomized handshake token key.
pub fn with_crypto(crypto: Arc<dyn crypto::ServerConfig>) -> Self {
#[cfg(all(feature = "aws-lc-rs", not(feature = "ring")))]
use aws_lc_rs::hkdf;
use rand::RngCore;
#[cfg(feature = "ring")]
use ring::hkdf;

let rng = &mut rand::thread_rng();
let mut master_key = [0u8; 64];
rng.fill_bytes(&mut master_key);
let master_key = ring::hkdf::Salt::new(ring::hkdf::HKDF_SHA256, &[]).extract(&master_key);
let master_key = hkdf::Salt::new(hkdf::HKDF_SHA256, &[]).extract(&master_key);

Self::new(crypto, Arc::new(master_key))
}
Expand Down
4 changes: 2 additions & 2 deletions quinn-proto/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use crate::{
};

/// Cryptography interface based on *ring*
#[cfg(feature = "ring")]
pub(crate) mod ring;
#[cfg(any(feature = "aws-lc-rs", feature = "ring"))]
pub(crate) mod ring_like;
/// TLS interface based on rustls
#[cfg(feature = "rustls")]
pub mod rustls;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#[cfg(all(feature = "aws-lc-rs", not(feature = "ring")))]
use aws_lc_rs::{aead, error, hkdf, hmac};
#[cfg(feature = "ring")]
use ring::{aead, error, hkdf, hmac};

use crate::crypto::{self, CryptoError};
Expand Down
22 changes: 14 additions & 8 deletions quinn-proto/src/crypto/rustls.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use std::{any::Any, io, str, sync::Arc};

#[cfg(all(feature = "aws-lc-rs", not(feature = "ring")))]
use aws_lc_rs::aead;
use bytes::BytesMut;
#[cfg(feature = "ring")]
use ring::aead;
pub use rustls::Error;
use rustls::{
Expand Down Expand Up @@ -307,14 +310,17 @@ impl QuicClientConfig {
}

pub(crate) fn inner(verifier: Arc<dyn ServerCertVerifier>) -> rustls::ClientConfig {
let mut config = rustls::ClientConfig::builder_with_provider(
rustls::crypto::ring::default_provider().into(),
)
.with_protocol_versions(&[&rustls::version::TLS13])
.unwrap() // The *ring* default provider supports TLS 1.3
.dangerous()
.with_custom_certificate_verifier(verifier)
.with_no_client_auth();
#[cfg(all(feature = "aws-lc-rs", not(feature = "ring")))]
let provider = rustls::crypto::aws_lc_rs::default_provider();
#[cfg(feature = "ring")]
let provider = rustls::crypto::ring::default_provider();

let mut config = rustls::ClientConfig::builder_with_provider(Arc::new(provider))
.with_protocol_versions(&[&rustls::version::TLS13])
.unwrap() // The default providers support TLS 1.3
.dangerous()
.with_custom_certificate_verifier(verifier)
.with_no_client_auth();

config.enable_early_data = true;
config
Expand Down
2 changes: 1 addition & 1 deletion quinn-proto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ mod cid_queue;
pub mod coding;
mod constant_time;
mod range_set;
#[cfg(all(test, feature = "rustls"))]
#[cfg(all(test, any(feature = "rustls-aws-lc-rs", feature = "rustls-ring")))]
mod tests;
pub mod transport_parameters;
mod varint;
Expand Down
3 changes: 3 additions & 0 deletions quinn-proto/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ use std::{
};

use assert_matches::assert_matches;
#[cfg(all(feature = "aws-lc-rs", not(feature = "ring")))]
use aws_lc_rs::hmac;
use bytes::Bytes;
use hex_literal::hex;
use rand::RngCore;
#[cfg(feature = "ring")]
use ring::hmac;
use rustls::{
pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer},
Expand Down
11 changes: 7 additions & 4 deletions quinn-proto/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,13 @@ impl fmt::Display for ResetToken {
}
}

#[cfg(test)]
#[cfg(all(test, any(feature = "aws-lc-rs", feature = "ring")))]
mod test {
#[cfg(all(feature = "aws-lc-rs", not(feature = "ring")))]
use aws_lc_rs::hkdf;
#[cfg(feature = "ring")]
use ring::hkdf;

#[test]
fn token_sanity() {
use super::*;
Expand All @@ -184,7 +188,7 @@ mod test {
let mut master_key = [0; 64];
rng.fill_bytes(&mut master_key);

let prk = ring::hkdf::Salt::new(ring::hkdf::HKDF_SHA256, &[]).extract(&master_key);
let prk = hkdf::Salt::new(hkdf::HKDF_SHA256, &[]).extract(&master_key);

let addr = SocketAddr::new(Ipv6Addr::LOCALHOST.into(), 4433);
let retry_src_cid = RandomConnectionIdGenerator::new(MAX_CID_SIZE).generate_cid();
Expand All @@ -200,7 +204,6 @@ mod test {
assert_eq!(token.issued, decoded.issued);
}

#[cfg(feature = "ring")]
#[test]
fn invalid_token_returns_err() {
use super::*;
Expand All @@ -214,7 +217,7 @@ mod test {
let mut master_key = [0; 64];
rng.fill_bytes(&mut master_key);

let prk = ring::hkdf::Salt::new(ring::hkdf::HKDF_SHA256, &[]).extract(&master_key);
let prk = hkdf::Salt::new(hkdf::HKDF_SHA256, &[]).extract(&master_key);

let addr = SocketAddr::new(Ipv6Addr::LOCALHOST.into(), 4433);
let retry_src_cid = RandomConnectionIdGenerator::new(MAX_CID_SIZE).generate_cid();
Expand Down
5 changes: 4 additions & 1 deletion quinn/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@ all-features = true

[features]
default = ["log", "platform-verifier", "ring", "runtime-tokio", "rustls"]
aws-lc-rs = ["proto/aws-lc-rs"]
# Records how long locks are held, and warns if they are held >= 1ms
lock_tracking = []
# Provides `ClientConfig::with_platform_verifier()` convenience method
platform-verifier = ["proto/platform-verifier"]
rustls = ["dep:rustls", "proto/rustls", "proto/ring"]
rustls = ["rustls-ring"]
rustls-aws-lc-rs = ["dep:rustls", "proto/rustls-aws-lc-rs", "proto/aws-lc-rs"]
rustls-ring = ["dep:rustls", "proto/rustls-ring", "proto/ring"]
# Enables `Endpoint::client` and `Endpoint::server` conveniences
ring = ["proto/ring"]
runtime-tokio = ["tokio/time", "tokio/rt", "tokio/net"]
Expand Down
8 changes: 4 additions & 4 deletions quinn/src/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::{
time::Instant,
};

#[cfg(feature = "ring")]
#[cfg(any(feature = "aws-lc-rs", feature = "ring"))]
use crate::runtime::default_runtime;
use crate::{
runtime::{AsyncUdpSocket, Runtime},
Expand All @@ -25,7 +25,7 @@ use proto::{
EndpointEvent, ServerConfig,
};
use rustc_hash::FxHashMap;
#[cfg(feature = "ring")]
#[cfg(any(feature = "aws-lc-rs", feature = "ring"))]
use socket2::{Domain, Protocol, Socket, Type};
use tokio::sync::{futures::Notified, mpsc, Notify};
use tracing::{Instrument, Span};
Expand Down Expand Up @@ -67,7 +67,7 @@ impl Endpoint {
///
/// Some environments may not allow creation of dual-stack sockets, in which case an IPv6
/// client will only be able to connect to IPv6 servers. An IPv4 client is never dual-stack.
#[cfg(feature = "ring")]
#[cfg(any(feature = "aws-lc-rs", feature = "ring"))] // `EndpointConfig::default()` is only available with these
pub fn client(addr: SocketAddr) -> io::Result<Self> {
let socket = Socket::new(Domain::for_address(addr), Type::DGRAM, Some(Protocol::UDP))?;
if addr.is_ipv6() {
Expand Down Expand Up @@ -97,7 +97,7 @@ impl Endpoint {
/// IPv6 address on Windows will not by default be able to communicate with IPv4
/// addresses. Portable applications should bind an address that matches the family they wish to
/// communicate within.
#[cfg(feature = "ring")]
#[cfg(any(feature = "aws-lc-rs", feature = "ring"))] // `EndpointConfig::default()` is only available with these
pub fn server(config: ServerConfig, addr: SocketAddr) -> io::Result<Self> {
let socket = std::net::UdpSocket::bind(addr)?;
let runtime = default_runtime()
Expand Down

0 comments on commit 267ccbb

Please sign in to comment.