diff --git a/Cargo.toml b/Cargo.toml index ef9797b3..81f47b97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ members = ["client", "server", "common", "save", "save/gen-protos"] [workspace.dependencies] hecs = "0.10.0" nalgebra = { version = "0.32.1", features = ["libm-force"] } -quinn = "0.10.2" +quinn = { version = "0.11", default-features = false, features = ["rustls", "ring", "runtime-tokio"] } toml = { version = "0.8.0", default-features = false, features = ["parse"] } [profile.dev] diff --git a/client/Cargo.toml b/client/Cargo.toml index bfe13572..db598046 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -31,7 +31,6 @@ fxhash = "0.2.1" downcast-rs = "1.1.1" quinn = { workspace = true } futures-util = "0.3.1" -rustls = { version = "0.21.7", features = ["dangerous_configuration"] } webpki = "0.22.0" hecs = { workspace = true } rcgen = { version = "0.13.1", default-features = false, features = ["ring"] } diff --git a/client/src/main.rs b/client/src/main.rs index c41daf1d..b383c5f7 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -4,6 +4,7 @@ use std::{ }; use client::{graphics, metrics, net, Config}; +use quinn::rustls::pki_types::{CertificateDer, PrivatePkcs8KeyDer}; use save::Save; use ash::khr; @@ -44,8 +45,8 @@ fn main() { let _guard = span.enter(); if let Err(e) = server::run( server::NetParams { - certificate_chain: vec![rustls::Certificate(cert)], - private_key: rustls::PrivateKey(key), + certificate_chain: vec![CertificateDer::from(cert)], + private_key: PrivatePkcs8KeyDer::from(key).into(), socket, }, sim_cfg, diff --git a/client/src/net.rs b/client/src/net.rs index 5832aed5..bbbae577 100644 --- a/client/src/net.rs +++ b/client/src/net.rs @@ -1,6 +1,7 @@ use std::{sync::Arc, thread}; use anyhow::{anyhow, Error, Result}; +use quinn::rustls; use tokio::sync::mpsc; use common::{codec, proto}; @@ -44,10 +45,12 @@ async fn run( ) -> Result<()> { let mut endpoint = quinn::Endpoint::client("[::]:0".parse().unwrap())?; let crypto = rustls::ClientConfig::builder() - .with_safe_defaults() + .dangerous() .with_custom_certificate_verifier(Arc::new(AcceptAnyCert)) .with_no_client_auth(); - let client_cfg = quinn::ClientConfig::new(Arc::new(crypto)); + let client_cfg = quinn::ClientConfig::new(Arc::new( + quinn::crypto::rustls::QuicClientConfig::try_from(crypto).unwrap(), + )); endpoint.set_default_client_config(client_cfg); let result = inner(cfg, incoming, outgoing, endpoint.clone()).await; @@ -133,18 +136,51 @@ async fn handle_unordered(incoming: mpsc::UnboundedSender, connection: } } +#[derive(Debug)] struct AcceptAnyCert; -impl rustls::client::ServerCertVerifier for AcceptAnyCert { +impl rustls::client::danger::ServerCertVerifier for AcceptAnyCert { fn verify_server_cert( &self, - _end_entity: &rustls::Certificate, - _intermediates: &[rustls::Certificate], - _server_name: &rustls::ServerName, - _scts: &mut dyn Iterator, + _end_entity: &rustls::pki_types::CertificateDer, + _intermediates: &[rustls::pki_types::CertificateDer], + _server_name: &rustls::pki_types::ServerName, _ocsp_response: &[u8], - _now: std::time::SystemTime, - ) -> Result { - Ok(rustls::client::ServerCertVerified::assertion()) + _now: rustls::pki_types::UnixTime, + ) -> Result { + Ok(rustls::client::danger::ServerCertVerified::assertion()) + } + + fn verify_tls12_signature( + &self, + _message: &[u8], + _cert: &rustls::pki_types::CertificateDer<'_>, + _dss: &rustls::DigitallySignedStruct, + ) -> Result { + // QUIC is TLS 1.3 only + unreachable!(); + } + + fn verify_tls13_signature( + &self, + message: &[u8], + cert: &rustls::pki_types::CertificateDer<'_>, + dss: &rustls::DigitallySignedStruct, + ) -> Result { + rustls::crypto::verify_tls13_signature( + message, + cert, + dss, + &rustls::crypto::CryptoProvider::get_default() + .unwrap() + .signature_verification_algorithms, + ) + } + + fn supported_verify_schemes(&self) -> Vec { + rustls::crypto::CryptoProvider::get_default() + .unwrap() + .signature_verification_algorithms + .supported_schemes() } } diff --git a/common/src/codec.rs b/common/src/codec.rs index 3535d769..1b7ef75c 100644 --- a/common/src/codec.rs +++ b/common/src/codec.rs @@ -18,7 +18,7 @@ pub async fn send(stream: &mut quinn::SendStream, msg: &T pub async fn recv(stream: &mut quinn::RecvStream) -> Result> { let mut tag = [0; 4]; match stream.read_exact(&mut tag[0..3]).await { - Err(quinn::ReadExactError::FinishedEarly) => return Ok(None), + Err(quinn::ReadExactError::FinishedEarly(_)) => return Ok(None), Err(quinn::ReadExactError::ReadError(e)) => return Err(e.into()), Ok(()) => {} } @@ -26,7 +26,7 @@ pub async fn recv(stream: &mut quinn::RecvStream) -> Result let len = u32::from_le_bytes(tag) as usize; let mut buf = vec![0; len]; match stream.read_exact(&mut buf).await { - Err(quinn::ReadExactError::FinishedEarly) => return Ok(None), + Err(quinn::ReadExactError::FinishedEarly(_)) => return Ok(None), Err(quinn::ReadExactError::ReadError(e)) => return Err(e.into()), Ok(()) => {} } @@ -40,7 +40,6 @@ pub async fn send_whole( ) -> std::result::Result<(), quinn::WriteError> { let buf = bincode::serialize(msg).unwrap(); stream.write_all(&buf).await?; - stream.finish().await?; Ok(()) } diff --git a/server/Cargo.toml b/server/Cargo.toml index 28b656d9..f77e6519 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -27,6 +27,5 @@ fxhash = "0.2.1" nalgebra = { workspace = true } libm = "0.2.6" slotmap = "1.0.6" -rustls = "0.21.7" -rustls-pemfile = "1.0.0" +rustls-pemfile = "2.1.2" save = { path = "../save" } diff --git a/server/src/lib.rs b/server/src/lib.rs index dcf6e49d..5b1ee362 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -10,6 +10,7 @@ use std::{net::UdpSocket, sync::Arc, time::Instant}; use anyhow::{Context, Error, Result}; use futures::{select, StreamExt}; use hecs::Entity; +use quinn::rustls::pki_types::{CertificateDer, PrivateKeyDer}; use slotmap::DenseSlotMap; use tokio::sync::mpsc; use tokio_stream::wrappers::{IntervalStream, ReceiverStream}; @@ -21,8 +22,8 @@ use save::Save; use sim::Sim; pub struct NetParams { - pub certificate_chain: Vec, - pub private_key: rustls::PrivateKey, + pub certificate_chain: Vec>, + pub private_key: PrivateKeyDer<'static>, pub socket: UdpSocket, } diff --git a/server/src/main.rs b/server/src/main.rs index d0d4b3c4..63dbf820 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -5,6 +5,7 @@ mod config; use std::{fs, net::UdpSocket, path::Path}; use anyhow::{anyhow, Context, Result}; +use quinn::rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer}; use tracing::{info, warn}; use common::SimConfig; @@ -32,18 +33,15 @@ pub fn run() -> Result<()> { rustls_pemfile::certs( &mut &*fs::read(certificate_chain).context("reading certificate chain")?, ) - .context("parsing certificate chain")? - .into_iter() - .map(rustls::Certificate) - .collect(), + .collect::, _>>() + .context("parsing certificate chain")?, rustls_pemfile::pkcs8_private_keys( &mut &*fs::read(private_key).context("reading private key")?, ) - .context("parsing private key")? - .into_iter() - .map(rustls::PrivateKey) .next() - .ok_or_else(|| anyhow!("no private key found with PKCS #8 format"))?, + .ok_or_else(|| anyhow!("no private key found with PKCS #8 format"))? + .context("parsing private key")? + .into(), ), _ => { // TODO: Cache on disk @@ -61,7 +59,10 @@ pub fn run() -> Result<()> { .unwrap(); let key = certified_key.key_pair.serialize_der(); let cert = certified_key.cert.der().to_vec(); - (vec![rustls::Certificate(cert)], rustls::PrivateKey(key)) + ( + vec![CertificateDer::from(cert)], + PrivateKeyDer::from(PrivatePkcs8KeyDer::from(key)), + ) } };