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 Sep 24, 2024
1 parent 425f147 commit 9a656d2
Show file tree
Hide file tree
Showing 19 changed files with 107 additions and 61 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ jobs:
- run: cargo test --manifest-path fuzz/Cargo.toml
if: ${{ matrix.rust }} == "stable"

test-aws-lc-rs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
# Prevent feature unification from selecting *ring* as the crypto provider
- run: RUST_BACKTRACE=1 cargo test --manifest-path quinn-proto/Cargo.toml --no-default-features --features rustls-aws-lc-rs
- run: RUST_BACKTRACE=1 cargo test --manifest-path quinn/Cargo.toml --no-default-features --features rustls-aws-lc-rs,runtime-tokio

msrv:
runs-on: ubuntu-latest
steps:
Expand Down
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.9", 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
13 changes: 10 additions & 3 deletions quinn-proto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,14 @@ workspace = ".."
all-features = true

[features]
default = ["rustls", "log"]
rustls = ["dep:rustls", "ring"]
default = ["rustls-ring", "log"]
aws-lc-rs = ["dep:aws-lc-rs", "aws-lc-rs/aws-lc-sys", "aws-lc-rs/prebuilt-nasm"]
# For backwards compatibility, `rustls` forwards to `rustls-ring`
rustls = ["rustls-ring"]
# Enable rustls with the `aws-lc-rs` crypto provider
rustls-aws-lc-rs = ["dep:rustls", "rustls/aws-lc-rs", "aws-lc-rs"]
# Enable rustls with the `ring` crypto provider
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,14 +31,15 @@ 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 }
ring = { workspace = true, optional = true }
rustls = { workspace = true, optional = true }
rustls-platform-verifier = { workspace = true, optional = true }
slab = { workspace = true }
thiserror = { workspace= true }
thiserror = { workspace = true }
tinyvec = { workspace = true, features = ["alloc"] }
tracing = { workspace = true }

Expand Down
39 changes: 23 additions & 16 deletions quinn-proto/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,14 @@ use std::{
time::Duration,
};

#[cfg(feature = "ring")]
use rand::RngCore;
#[cfg(feature = "rustls")]
#[cfg(any(feature = "rustls-aws-lc-rs", feature = "rustls-ring"))]
use rustls::client::WebPkiServerVerifier;
#[cfg(feature = "rustls")]
#[cfg(any(feature = "rustls-aws-lc-rs", feature = "rustls-ring"))]
use rustls::pki_types::{CertificateDer, PrivateKeyDer};
use thiserror::Error;

#[cfg(feature = "rustls")]
use crate::crypto::rustls::QuicServerConfig;
#[cfg(any(feature = "rustls-aws-lc-rs", feature = "rustls-ring"))]
use crate::crypto::rustls::{configured_provider, QuicServerConfig};
use crate::{
cid_generator::{ConnectionIdGenerator, HashedConnectionIdGenerator},
congestion,
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 @@ -919,7 +920,7 @@ impl ServerConfig {
}
}

#[cfg(feature = "rustls")]
#[cfg(any(feature = "rustls-aws-lc-rs", feature = "rustls-ring"))]
impl ServerConfig {
/// Create a server config with the given certificate chain to be presented to clients
///
Expand All @@ -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 Expand Up @@ -1030,7 +1037,7 @@ impl ClientConfig {
}
}

#[cfg(feature = "rustls")]
#[cfg(any(feature = "rustls-aws-lc-rs", feature = "rustls-ring"))]
impl ClientConfig {
/// Create a client configuration that trusts the platform's native roots
#[cfg(feature = "platform-verifier")]
Expand All @@ -1045,7 +1052,7 @@ impl ClientConfig {
roots: Arc<rustls::RootCertStore>,
) -> Result<Self, rustls::client::VerifierBuilderError> {
Ok(Self::new(Arc::new(crypto::rustls::QuicClientConfig::new(
WebPkiServerVerifier::builder(roots).build()?,
WebPkiServerVerifier::builder_with_provider(roots, configured_provider()).build()?,
))))
}
}
Expand Down
6 changes: 3 additions & 3 deletions quinn-proto/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ 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")]
#[cfg(any(feature = "rustls-aws-lc-rs", feature = "rustls-ring"))]
pub mod rustls;

/// A cryptographic session (commonly TLS)
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
37 changes: 22 additions & 15 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,12 @@ 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();
let mut config = rustls::ClientConfig::builder_with_provider(configured_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 Expand Up @@ -446,13 +447,11 @@ impl QuicServerConfig {
cert_chain: Vec<CertificateDer<'static>>,
key: PrivateKeyDer<'static>,
) -> Result<rustls::ServerConfig, rustls::Error> {
let mut inner = rustls::ServerConfig::builder_with_provider(
rustls::crypto::ring::default_provider().into(),
)
.with_protocol_versions(&[&rustls::version::TLS13])
.unwrap() // The *ring* default provider supports TLS 1.3
.with_no_client_auth()
.with_single_cert(cert_chain, key)?;
let mut inner = rustls::ServerConfig::builder_with_provider(configured_provider())
.with_protocol_versions(&[&rustls::version::TLS13])
.unwrap() // The *ring* default provider supports TLS 1.3
.with_no_client_auth()
.with_single_cert(cert_chain, key)?;

inner.max_early_data_size = u32::MAX;
Ok(inner)
Expand Down Expand Up @@ -549,6 +548,14 @@ pub(crate) fn initial_suite_from_provider(
.flatten()
}

pub(crate) fn configured_provider() -> Arc<rustls::crypto::CryptoProvider> {
#[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();
Arc::new(provider)
}

fn to_vec(params: &TransportParameters) -> Vec<u8> {
let mut bytes = Vec::new();
params.write(&mut bytes);
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
8 changes: 3 additions & 5 deletions quinn-proto/src/packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -898,8 +898,6 @@ impl SpaceId {
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "rustls")]
use crate::DEFAULT_SUPPORTED_VERSIONS;
use hex_literal::hex;
use std::io;

Expand Down Expand Up @@ -936,7 +934,7 @@ mod tests {
}
}

#[cfg(feature = "rustls")]
#[cfg(any(feature = "rustls-aws-lc-rs", feature = "rustls-ring"))]
#[test]
fn header_encoding() {
use crate::crypto::rustls::{initial_keys, initial_suite_from_provider};
Expand All @@ -955,7 +953,7 @@ mod tests {
src_cid: ConnectionId::new(&[]),
dst_cid: dcid,
token: Bytes::new(),
version: DEFAULT_SUPPORTED_VERSIONS[0],
version: crate::DEFAULT_SUPPORTED_VERSIONS[0],
});
let encode = header.encode(&mut buf);
let header_len = buf.len();
Expand All @@ -979,7 +977,7 @@ mod tests {
);

let server = initial_keys(Version::V1, &dcid, Side::Server, &suite);
let supported_versions = DEFAULT_SUPPORTED_VERSIONS.to_vec();
let supported_versions = crate::DEFAULT_SUPPORTED_VERSIONS.to_vec();
let decode = PartialDecode::new(
buf.as_slice().into(),
&FixedLengthConnectionIdParser::new(0),
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, BytesMut};
use hex_literal::hex;
use rand::RngCore;
#[cfg(feature = "ring")]
use ring::hmac;
use rustls::{
pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer},
Expand Down
4 changes: 2 additions & 2 deletions quinn-proto/src/tests/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use rustls::{
};
use tracing::{info_span, trace};

use super::crypto::rustls::{QuicClientConfig, QuicServerConfig};
use super::crypto::rustls::{configured_provider, QuicClientConfig, QuicServerConfig};
use super::*;

pub(super) const DEFAULT_MTU: usize = 1452;
Expand Down Expand Up @@ -640,7 +640,7 @@ fn client_crypto_inner(
}

let mut inner = QuicClientConfig::inner(
WebPkiServerVerifier::builder(Arc::new(roots))
WebPkiServerVerifier::builder_with_provider(Arc::new(roots), configured_provider())
.build()
.unwrap(),
);
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
Loading

0 comments on commit 9a656d2

Please sign in to comment.