diff --git a/Cargo.toml b/Cargo.toml index f90603ec03..bb244900e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,6 @@ debug = true [profile.release] debug = true + +[patch."crates-io"] +rustls = { path = "../rustls/rustls" } diff --git a/quinn-proto/Cargo.toml b/quinn-proto/Cargo.toml index 04baa3a4da..da074dca11 100644 --- a/quinn-proto/Cargo.toml +++ b/quinn-proto/Cargo.toml @@ -17,8 +17,9 @@ all-features = true maintenance = { status = "experimental" } [features] -default = ["tls-rustls", "log"] +default = ["tls-rustls", "rustls-ring", "log"] tls-rustls = ["rustls", "ring"] +rustls-ring = ["rustls/ring"] # Provides `ClientConfig::with_native_roots()` convenience method native-certs = ["rustls-native-certs"] # Write logs via the `log` crate when no `tracing` subscriber exists @@ -29,9 +30,10 @@ arbitrary = { version = "1.0.1", features = ["derive"], optional = true } bytes = "1" rustc-hash = "1.1" rand = "0.8" -ring = { version = "0.16.7", optional = true } -rustls = { version = "0.21.0", default-features = false, features = ["quic"], optional = true } -rustls-native-certs = { version = "0.6", optional = true } +ring = { version = "0.17", optional = true } +rustls-pki-types = { version = "1", optional = true } +rustls = { version = "0.22", default-features = false, optional = true } +rustls-native-certs = { version = "0.7", optional = true } slab = "0.4" thiserror = "1.0.21" tinyvec = { version = "1.1", features = ["alloc"] } diff --git a/quinn-proto/src/config.rs b/quinn-proto/src/config.rs index 538a97b0e7..6bb47ae7f1 100644 --- a/quinn-proto/src/config.rs +++ b/quinn-proto/src/config.rs @@ -1,5 +1,6 @@ use std::{fmt, num::TryFromIntError, sync::Arc, time::Duration}; +use rustls_pki_types::{CertificateDer, PrivateKeyDer}; use thiserror::Error; #[cfg(feature = "ring")] @@ -829,8 +830,8 @@ impl ServerConfig { /// /// Uses a randomized handshake token key. pub fn with_single_cert( - cert_chain: Vec, - key: rustls::PrivateKey, + cert_chain: Vec>, + key: PrivateKeyDer<'static>, ) -> Result { let crypto = crypto::rustls::server_config(cert_chain, key)?; Ok(Self::with_crypto(Arc::new(crypto))) @@ -914,7 +915,7 @@ impl ClientConfig { match rustls_native_certs::load_native_certs() { Ok(certs) => { for cert in certs { - if let Err(e) = roots.add(&rustls::Certificate(cert.0)) { + if let Err(e) = roots.add(cert) { tracing::warn!("failed to parse trust anchor: {}", e); } } diff --git a/quinn-proto/src/crypto/rustls.rs b/quinn-proto/src/crypto/rustls.rs index 7d325508ab..0722dd72e6 100644 --- a/quinn-proto/src/crypto/rustls.rs +++ b/quinn-proto/src/crypto/rustls.rs @@ -6,7 +6,9 @@ pub use rustls::Error; use rustls::{ self, quic::{Connection, HeaderProtectionKey, KeyChange, PacketKey, Secrets, Version}, + Tls13CipherSuite, }; +use rustls_pki_types::{CertificateDer, PrivateKeyDer}; use crate::{ crypto::{ @@ -204,7 +206,7 @@ const RETRY_INTEGRITY_NONCE_V1: [u8; 12] = [ 0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2, 0x23, 0x98, 0x25, 0xbb, ]; -impl crypto::HeaderKey for HeaderProtectionKey { +impl crypto::HeaderKey for Box { fn decrypt(&self, pn_offset: usize, packet: &mut [u8]) { let (header, sample) = packet.split_at_mut(pn_offset + 4); let (first, rest) = header.split_at_mut(1); @@ -332,20 +334,32 @@ fn to_vec(params: &TransportParameters) -> Vec { } pub(crate) fn initial_keys(version: Version, dst_cid: &ConnectionId, side: Side) -> Keys { - let keys = rustls::quic::Keys::initial(version, dst_cid, side.into()); + let keys = rustls::quic::Keys::initial( + version, + INITIAL, + INITIAL.quic.unwrap(), + dst_cid, + side.into(), + ); + Keys { header: KeyPair { - local: Box::new(keys.local.header), - remote: Box::new(keys.remote.header), + local: keys.local.header, + remote: keys.remote.header, }, packet: KeyPair { - local: Box::new(keys.local.packet), - remote: Box::new(keys.remote.packet), + local: keys.local.packet, + remote: keys.remote.packet, }, } } -impl crypto::PacketKey for PacketKey { +const INITIAL: &'static Tls13CipherSuite = + rustls::crypto::ring::cipher_suite::TLS13_AES_128_GCM_SHA256 + .tls13() + .unwrap(); + +impl crypto::PacketKey for Box { fn encrypt(&self, packet: u64, buf: &mut [u8], header_len: usize) { let (header, payload_tag) = buf.split_at_mut(header_len); let (payload, tag_storage) = payload_tag.split_at_mut(payload_tag.len() - self.tag_len()); @@ -386,10 +400,6 @@ impl crypto::PacketKey for PacketKey { /// satisfies this requirement. pub(crate) fn client_config(roots: rustls::RootCertStore) -> rustls::ClientConfig { let mut cfg = rustls::ClientConfig::builder() - .with_safe_default_cipher_suites() - .with_safe_default_kx_groups() - .with_protocol_versions(&[&rustls::version::TLS13]) - .unwrap() .with_root_certificates(roots) .with_no_client_auth(); cfg.enable_early_data = true; @@ -402,14 +412,10 @@ pub(crate) fn client_config(roots: rustls::RootCertStore) -> rustls::ClientConfi /// `u32::MAX`. Advanced users can use any [`rustls::ServerConfig`] that satisfies these /// requirements. pub(crate) fn server_config( - cert_chain: Vec, - key: rustls::PrivateKey, + cert_chain: Vec>, + key: PrivateKeyDer<'static>, ) -> Result { let mut cfg = rustls::ServerConfig::builder() - .with_safe_default_cipher_suites() - .with_safe_default_kx_groups() - .with_protocol_versions(&[&rustls::version::TLS13]) - .unwrap() .with_no_client_auth() .with_single_cert(cert_chain, key)?; cfg.max_early_data_size = u32::MAX; diff --git a/quinn-proto/src/tests/mod.rs b/quinn-proto/src/tests/mod.rs index c41f3592d0..f809ba1cce 100644 --- a/quinn-proto/src/tests/mod.rs +++ b/quinn-proto/src/tests/mod.rs @@ -11,7 +11,8 @@ use bytes::{Bytes, BytesMut}; use hex_literal::hex; use rand::RngCore; use ring::hmac; -use rustls::AlertDescription; +use rustls::{server::WebPkiClientVerifier, AlertDescription, RootCertStore}; +use rustls_pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer}; use tracing::info; use super::*; @@ -375,18 +376,16 @@ fn reject_self_signed_server_cert() { fn reject_missing_client_cert() { let _guard = subscribe(); - let key = rustls::PrivateKey(CERTIFICATE.serialize_private_key_der()); - let cert = util::CERTIFICATE.serialize_der().unwrap(); + let key = PrivatePkcs8KeyDer::from(CERTIFICATE.serialize_private_key_der()); + let cert = CertificateDer::from(util::CERTIFICATE.serialize_der().unwrap()); let config = rustls::ServerConfig::builder() - .with_safe_default_cipher_suites() - .with_safe_default_kx_groups() - .with_protocol_versions(&[&rustls::version::TLS13]) - .unwrap() - .with_client_cert_verifier(Arc::new(rustls::server::AllowAnyAuthenticatedClient::new( - rustls::RootCertStore::empty(), - ))) - .with_single_cert(vec![rustls::Certificate(cert)], key) + .with_client_cert_verifier( + WebPkiClientVerifier::builder(Arc::new(RootCertStore::empty())) + .build() + .unwrap(), + ) + .with_single_cert(vec![cert], PrivateKeyDer::from(key)) .unwrap(); let mut pair = Pair::new( @@ -1918,7 +1917,7 @@ fn server_can_send_3_inital_packets() { } /// Generate a big fat certificate that can't fit inside the initial anti-amplification limit -fn big_cert_and_key() -> (rustls::Certificate, rustls::PrivateKey) { +fn big_cert_and_key() -> (CertificateDer<'static>, PrivateKeyDer<'static>) { let cert = rcgen::generate_simple_self_signed( Some("localhost".into()) .into_iter() @@ -1926,9 +1925,11 @@ fn big_cert_and_key() -> (rustls::Certificate, rustls::PrivateKey) { .collect::>(), ) .unwrap(); - let key = rustls::PrivateKey(cert.serialize_private_key_der()); - let cert = rustls::Certificate(cert.serialize_der().unwrap()); - (cert, key) + + ( + CertificateDer::from(cert.serialize_der().unwrap()), + PrivateKeyDer::Pkcs8(cert.serialize_private_key_der().into()), + ) } #[test] diff --git a/quinn-proto/src/tests/util.rs b/quinn-proto/src/tests/util.rs index cd7bb11239..1b75588bb6 100644 --- a/quinn-proto/src/tests/util.rs +++ b/quinn-proto/src/tests/util.rs @@ -14,7 +14,8 @@ use std::{ use assert_matches::assert_matches; use bytes::BytesMut; use lazy_static::lazy_static; -use rustls::{Certificate, KeyLogFile, PrivateKey}; +use rustls::KeyLogFile; +use rustls_pki_types::{CertificateDer, PrivateKeyDer}; use tracing::{info_span, trace}; use super::*; @@ -467,17 +468,17 @@ pub(super) fn server_config() -> ServerConfig { ServerConfig::with_crypto(Arc::new(server_crypto())) } -pub(super) fn server_config_with_cert(cert: Certificate, key: PrivateKey) -> ServerConfig { +pub(super) fn server_config_with_cert(cert: CertificateDer<'static>, key: PrivateKeyDer<'static>) -> ServerConfig { ServerConfig::with_crypto(Arc::new(server_crypto_with_cert(cert, key))) } pub(super) fn server_crypto() -> rustls::ServerConfig { - let cert = Certificate(CERTIFICATE.serialize_der().unwrap()); - let key = PrivateKey(CERTIFICATE.serialize_private_key_der()); + let cert = CertificateDer::from(CERTIFICATE.serialize_der().unwrap()); + let key = PrivateKeyDer::Pkcs8(CERTIFICATE.serialize_private_key_der().into()); server_crypto_with_cert(cert, key) } -pub(super) fn server_crypto_with_cert(cert: Certificate, key: PrivateKey) -> rustls::ServerConfig { +pub(super) fn server_crypto_with_cert(cert: CertificateDer<'static>, key: PrivateKeyDer<'static>) -> rustls::ServerConfig { crate::crypto::rustls::server_config(vec![cert], key).unwrap() } @@ -493,19 +494,19 @@ pub(super) fn client_config_with_deterministic_pns() -> ClientConfig { cfg } -pub(super) fn client_config_with_certs(certs: Vec) -> ClientConfig { +pub(super) fn client_config_with_certs(certs: Vec>) -> ClientConfig { ClientConfig::new(Arc::new(client_crypto_with_certs(certs))) } pub(super) fn client_crypto() -> rustls::ClientConfig { - let cert = rustls::Certificate(CERTIFICATE.serialize_der().unwrap()); + let cert = CertificateDer::from(CERTIFICATE.serialize_der().unwrap()); client_crypto_with_certs(vec![cert]) } -pub(super) fn client_crypto_with_certs(certs: Vec) -> rustls::ClientConfig { +pub(super) fn client_crypto_with_certs(certs: Vec>) -> rustls::ClientConfig { let mut roots = rustls::RootCertStore::empty(); for cert in certs { - roots.add(&cert).unwrap(); + roots.add(cert).unwrap(); } let mut config = crate::crypto::rustls::client_config(roots); config.key_log = Arc::new(KeyLogFile::new());