From d8de27212fef22af3b62b362db2577c6a1fa7a7c Mon Sep 17 00:00:00 2001 From: stormshield-gt <143998166+stormshield-gt@users.noreply.github.com.> Date: Mon, 28 Oct 2024 08:53:23 +0100 Subject: [PATCH] Add a failing tests for post-quantum key exchange with severals min MTU --- Cargo.toml | 1 + quinn/Cargo.toml | 1 + quinn/tests/many_connections.rs | 10 ++- quinn/tests/post_quantum.rs | 118 ++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 6 deletions(-) create mode 100644 quinn/tests/post_quantum.rs diff --git a/Cargo.toml b/Cargo.toml index fea4af59a..98423e152 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ rustc-hash = "2" rustls = { version = "0.23.5", default-features = false, features = ["std"] } rustls-pemfile = "2" rustls-platform-verifier = "0.4" +rustls-post-quantum = "0.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1" slab = "0.4.6" diff --git a/quinn/Cargo.toml b/quinn/Cargo.toml index 173f1093f..57a718b1c 100644 --- a/quinn/Cargo.toml +++ b/quinn/Cargo.toml @@ -64,6 +64,7 @@ directories-next = { workspace = true } rand = { workspace = true } rcgen = { workspace = true } rustls-pemfile = { workspace = true } +rustls-post-quantum = { workspace = true } clap = { workspace = true } tokio = { workspace = true, features = ["rt", "rt-multi-thread", "time", "macros"] } tracing-subscriber = { workspace = true } diff --git a/quinn/tests/many_connections.rs b/quinn/tests/many_connections.rs index 5083487a6..45185c3e9 100644 --- a/quinn/tests/many_connections.rs +++ b/quinn/tests/many_connections.rs @@ -19,12 +19,10 @@ struct Shared { #[test] #[ignore] fn connect_n_nodes_to_1_and_send_1mb_data() { - tracing::subscriber::set_global_default( - tracing_subscriber::FmtSubscriber::builder() - .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) - .finish(), - ) - .unwrap(); + let _ = tracing_subscriber::FmtSubscriber::builder() + .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) + .with_test_writer() + .try_init(); let runtime = Builder::new_current_thread().enable_all().build().unwrap(); let _guard = runtime.enter(); diff --git a/quinn/tests/post_quantum.rs b/quinn/tests/post_quantum.rs new file mode 100644 index 000000000..c3f81aeff --- /dev/null +++ b/quinn/tests/post_quantum.rs @@ -0,0 +1,118 @@ +#![cfg(feature = "rustls-aws-lc-rs")] +use quinn::{ + crypto::rustls::{HandshakeData, QuicClientConfig, QuicServerConfig}, + Endpoint, +}; +use rustls::{ + pki_types::{CertificateDer, PrivatePkcs8KeyDer}, + NamedGroup, +}; +use std::{ + error::Error, + net::{Ipv4Addr, SocketAddr}, + sync::Arc, +}; +use tracing::info; + +#[tokio::test] +async fn post_quantum_key_worse_case_header() { + check_post_quantum_key_exchange(1274).await; +} + +#[tokio::test] +async fn post_quantum_key_exchange_large_mtu() { + check_post_quantum_key_exchange(1400).await; +} + +async fn check_post_quantum_key_exchange(min_mtu: u16) { + let _ = tracing_subscriber::FmtSubscriber::builder() + .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) + .with_test_writer() + .try_init(); + + let _ = rustls_post_quantum::provider().install_default(); + let server_addr = (Ipv4Addr::LOCALHOST, 8080).into(); + + let (endpoint, server_cert) = make_server_endpoint(server_addr, min_mtu).unwrap(); + // accept a single connection + tokio::spawn(async move { + let incoming_conn = endpoint.accept().await.unwrap(); + let conn = incoming_conn.await.unwrap(); + info!( + "[server] connection accepted: addr={}", + conn.remote_address() + ); + assert_eq!( + conn.handshake_data() + .unwrap() + .downcast::() + .unwrap() + .negotiated_key_exchange_group, + X25519_KYBER768_DRAFT00 + ) + // Dropping all handles associated with a connection implicitly closes it + }); + + let endpoint = + make_client_endpoint((Ipv4Addr::UNSPECIFIED, 0).into(), &[&server_cert]).unwrap(); + // connect to server + let connection = endpoint + .connect(server_addr, "localhost") + .unwrap() + .await + .unwrap(); + info!("[client] connected: addr={}", connection.remote_address()); + + // Waiting for a stream will complete with an error when the server closes the connection + let _ = connection.accept_uni().await; + + // Make sure the server has a chance to clean up + endpoint.wait_idle().await; +} + +fn make_client_endpoint( + bind_addr: SocketAddr, + server_certs: &[&[u8]], +) -> Result> { + let mut certs = rustls::RootCertStore::empty(); + for cert in server_certs { + certs.add(CertificateDer::from(*cert))?; + } + let rustls_config = rustls::ClientConfig::builder() + .with_root_certificates(certs) + .with_no_client_auth(); + + let client_cfg = + quinn::ClientConfig::new(Arc::new(QuicClientConfig::try_from(rustls_config).unwrap())); + let mut endpoint = Endpoint::client(bind_addr)?; + endpoint.set_default_client_config(client_cfg); + Ok(endpoint) +} + +fn make_server_endpoint( + bind_addr: SocketAddr, + min_mtu: u16, +) -> Result<(Endpoint, CertificateDer<'static>), Box> { + let cert = rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap(); + let server_cert = CertificateDer::from(cert.cert); + let priv_key = PrivatePkcs8KeyDer::from(cert.key_pair.serialize_der()); + let mut server_config = quinn::ServerConfig::with_crypto(Arc::new( + QuicServerConfig::try_from( + rustls::ServerConfig::builder() + .with_no_client_auth() + .with_single_cert(vec![server_cert.clone()], priv_key.into()) + .unwrap(), + ) + .unwrap(), + )); + + let transport_config = Arc::get_mut(&mut server_config.transport).unwrap(); + transport_config.max_concurrent_uni_streams(0_u8.into()); + transport_config.min_mtu(min_mtu); + + let endpoint = Endpoint::server(server_config, bind_addr)?; + Ok((endpoint, server_cert)) +} + +/// +const X25519_KYBER768_DRAFT00: NamedGroup = NamedGroup::Unknown(0x06399);