From 74cdc0004d0046634f26d2bd3077cceb25347bb8 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Mon, 4 Dec 2023 11:41:24 +0100 Subject: [PATCH] Update rustls to 0.22 and ring to 0.17 --- Cargo.toml | 3 +++ quinn-proto/Cargo.toml | 12 +++++---- quinn-proto/src/config.rs | 9 ++++--- quinn-proto/src/crypto/rustls.rs | 46 ++++++++++++++++++-------------- quinn-proto/src/tests/mod.rs | 31 ++++++++++----------- quinn-proto/src/tests/util.rs | 19 ++++++------- 6 files changed, 67 insertions(+), 53 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f90603ec0..2d81538a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,6 @@ debug = true [profile.release] debug = true + +[patch."crates-io"] +rustls = { git = "https://github.com/rustls/rustls", branch = "quinn-support" } diff --git a/quinn-proto/Cargo.toml b/quinn-proto/Cargo.toml index 04baa3a4d..92531e86c 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"] -tls-rustls = ["rustls", "ring"] +default = ["tls-rustls", "rustls-ring", "log"] +tls-rustls = ["rustls-pki-types"] +rustls-ring = ["rustls/ring", "ring"] # Allow rustls to be used with other crypto providers # 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 538a97b0e..dfd18763a 100644 --- a/quinn-proto/src/config.rs +++ b/quinn-proto/src/config.rs @@ -1,7 +1,8 @@ use std::{fmt, num::TryFromIntError, sync::Arc, time::Duration}; +#[cfg(feature = "rustls")] +use rustls_pki_types::{CertificateDer, PrivateKeyDer}; use thiserror::Error; - #[cfg(feature = "ring")] use rand::RngCore; @@ -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 7d325508a..97be1dda8 100644 --- a/quinn-proto/src/crypto/rustls.rs +++ b/quinn-proto/src/crypto/rustls.rs @@ -1,4 +1,4 @@ -use std::{any::Any, convert::TryInto, io, str, sync::Arc}; +use std::{any::Any, io, str, sync::Arc}; use bytes::BytesMut; use ring::aead; @@ -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, ServerName}; use crate::{ crypto::{ @@ -61,9 +63,9 @@ impl crypto::Session for TlsSession { } fn peer_identity(&self) -> Option> { - self.inner - .peer_certificates() - .map(|v| -> Box { Box::new(v.to_vec()) }) + self.inner.peer_certificates().map(|v| -> Box { + Box::new(v.iter().map(|v| v.clone().into_owned()).collect::>()) + }) } fn early_crypto(&self) -> Option<(Box, Box)> { @@ -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); @@ -262,9 +264,9 @@ impl crypto::ClientConfig for rustls::ClientConfig { rustls::quic::ClientConnection::new( self, version, - server_name - .try_into() - .map_err(|_| ConnectError::InvalidDnsName(server_name.into()))?, + ServerName::try_from(server_name) + .map_err(|_| ConnectError::InvalidDnsName(server_name.into()))? + .to_owned(), to_vec(params), ) .unwrap(), @@ -332,7 +334,14 @@ 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), @@ -345,7 +354,12 @@ pub(crate) fn initial_keys(version: Version, dst_cid: &ConnectionId, side: Side) } } -impl crypto::PacketKey for PacketKey { +static 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 c41f3592d..f809ba1cc 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 cd7bb1123..1b75588bb 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());