Skip to content

Commit

Permalink
Upgrade to rustls 0.20
Browse files Browse the repository at this point in the history
  • Loading branch information
djc committed Jul 7, 2021
1 parent 49e3bb0 commit 5293a12
Show file tree
Hide file tree
Showing 19 changed files with 310 additions and 274 deletions.
6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ debug = true

[profile.release]
debug = true

[patch."crates-io"]
rustls = { git = "https://github.com/djc/rustls", rev = "d0a6142e74c84a38a91e166304918daea2902478", features = ["quic"] }

[patch."https://github.com/ctz/rustls"]
rustls = { git = "https://github.com/djc/rustls", rev = "d0a6142e74c84a38a91e166304918daea2902478" }
2 changes: 1 addition & 1 deletion bench/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ futures = "0.3.8"
hdrhistogram = { version = "7.2", default-features = false }
quinn = { path = "../quinn" }
rcgen = "0.8"
rustls = "0.19"
rustls = { version = "0.20.0-beta2", git = "https://github.com/djc/rustls", rev = "d0a6142e74c84a38a91e166304918daea2902478", features = ["quic"] }
structopt = "0.3"
tokio = { version = "1.0.1", features = ["rt"] }
tracing = "0.1.10"
Expand Down
34 changes: 21 additions & 13 deletions bench/src/bulk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use anyhow::{Context, Result};
use bytes::Bytes;
use futures::StreamExt;
use hdrhistogram::Histogram;
use rustls::RootCertStore;
use structopt::StructOpt;
use tokio::runtime::{Builder, Runtime};
use tracing::{info, trace};
Expand All @@ -24,9 +25,9 @@ fn main() {

let cert = rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap();
let key = quinn::PrivateKey::from_der(&cert.serialize_private_key_der()).unwrap();
let cert = quinn::Certificate::from_der(&cert.serialize_der().unwrap()).unwrap();
let cert_der = quinn::Certificate::from_der(&cert.serialize_der().unwrap()).unwrap();

let cert_chain = quinn::CertificateChain::from_certs(vec![cert.clone()]);
let cert_chain = quinn::CertificateChain::from_certs(vec![cert_der]);
let mut server_config = quinn::ServerConfig::with_single_cert(cert_chain, key).unwrap();
server_config.transport = Arc::new(transport_config(&opt));

Expand Down Expand Up @@ -108,18 +109,25 @@ async fn server(mut incoming: quinn::Incoming, opt: Opt) -> Result<()> {
result
}

async fn client(server_addr: SocketAddr, server_cert: quinn::Certificate, opt: Opt) -> Result<()> {
async fn client(server_addr: SocketAddr, server_cert: rcgen::Certificate, opt: Opt) -> Result<()> {
let (endpoint, _) = quinn::EndpointBuilder::default()
.bind(&SocketAddr::new(IpAddr::V6(Ipv6Addr::LOCALHOST), 0))
.unwrap();

let mut client_config =
quinn::ClientConfig::with_root_certificates(vec![server_cert.clone()], None).unwrap();
client_config.transport = Arc::new(transport_config(&opt));
let mut roots = RootCertStore::empty();
roots.add_parsable_certificates(&[server_cert.serialize_der().unwrap()]);
let crypto = rustls::ClientConfig::builder()
.with_cipher_suites(&[opt.cipher.as_rustls()])
.with_safe_default_kx_groups()
.with_protocol_versions(&[&rustls::version::TLS13])
.unwrap()
.with_root_certificates(roots, &[])
.with_no_client_auth();

let crypto_config = Arc::get_mut(&mut client_config.crypto).unwrap();
crypto_config.ciphersuites.clear();
crypto_config.ciphersuites.push(opt.cipher.as_rustls());
let client_config = quinn::ClientConfig {
crypto: Arc::new(crypto),
transport: Arc::new(transport_config(&opt)),
};

let quinn::NewConnection { connection, .. } = endpoint
.connect_with(client_config, &server_addr, "localhost")
Expand Down Expand Up @@ -301,11 +309,11 @@ enum CipherSuite {
}

impl CipherSuite {
fn as_rustls(self) -> &'static rustls::SupportedCipherSuite {
fn as_rustls(self) -> rustls::SupportedCipherSuite {
match self {
CipherSuite::Aes128 => &rustls::ciphersuite::TLS13_AES_128_GCM_SHA256,
CipherSuite::Aes256 => &rustls::ciphersuite::TLS13_AES_256_GCM_SHA384,
CipherSuite::Chacha20 => &rustls::ciphersuite::TLS13_CHACHA20_POLY1305_SHA256,
CipherSuite::Aes128 => rustls::cipher_suite::TLS13_AES_128_GCM_SHA256,
CipherSuite::Aes256 => rustls::cipher_suite::TLS13_AES_256_GCM_SHA384,
CipherSuite::Chacha20 => rustls::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256,
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions interop/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ futures = "0.3.8"
http = "0.2"
http-body = "0.4"
hyper = { version = "0.14.1", features = ["client", "server", "http2"] }
hyper-rustls = "0.22.1"
hyper-rustls = { git = "https://github.com/djc/hyper-rustls", rev = "01982286851da993a984aae5990ed85072b72073" }
lazy_static = "1"
quinn = { path = "../quinn" }
quinn-proto = { path = "../quinn-proto" }
rustls = { version = "0.19", features = ["dangerous_configuration"] }
rustls = { git = "https://github.com/djc/rustls", rev = "d0a6142e74c84a38a91e166304918daea2902478", features = ["dangerous_configuration", "quic"] }
structopt = "0.3.0"
tokio = { version = "1.0.1", features = ["io-util", "macros", "rt", "rt-multi-thread"] }
tokio-rustls = "0.22"
tokio-rustls = { version = "0.23", git = "https://github.com/tokio-rs/tls", rev = "b433932bf1025960e5b99f353cf8eee4ce2f08f3" }
tracing = "0.1.10"
tracing-subscriber = { version = "0.2.5", default-features = false, features = ["env-filter", "fmt", "ansi", "chrono"]}
tracing-futures = { version = "0.2.0", default-features = false, features = ["std-future"] }
webpki = "0.21"
webpki = "0.22"

[[bin]]
name = "main"
Expand Down
27 changes: 17 additions & 10 deletions interop/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,19 +257,23 @@ impl State {
.to_socket_addrs()?
.next()
.ok_or_else(|| anyhow!("couldn't resolve to an address"))?;
let host = if webpki::DNSNameRef::try_from_ascii_str(&peer.host).is_ok() {
let host = if webpki::DnsNameRef::try_from_ascii_str(&peer.host).is_ok() {
&peer.host
} else {
warn!("invalid hostname, using \"example.com\"");
"example.com"
};

let mut tls_config = rustls::ClientConfig::new();
tls_config.versions = vec![rustls::ProtocolVersion::TLSv1_3];
let verifier = InteropVerifier(Arc::new(Mutex::new(false)));
let mut tls_config = rustls::ClientConfig::builder()
.with_safe_default_cipher_suites()
.with_safe_default_kx_groups()
.with_protocol_versions(&[&rustls::version::TLS13])
.unwrap()
.with_custom_certificate_verifier(Arc::new(verifier))
.with_no_client_auth();

tls_config.enable_early_data = true;
tls_config
.dangerous()
.set_certificate_verifier(Arc::new(InteropVerifier(Arc::new(Mutex::new(false)))));
tls_config.alpn_protocols = (&peer.alpn).into();
if keylog {
tls_config.key_log = Arc::new(rustls::KeyLogFile::new());
Expand Down Expand Up @@ -603,14 +607,17 @@ async fn hq_get(stream: (quinn::SendStream, quinn::RecvStream), path: &str) -> R
}

struct InteropVerifier(Arc<Mutex<bool>>);

impl rustls::ServerCertVerifier for InteropVerifier {
fn verify_server_cert(
&self,
_roots: &rustls::RootCertStore,
_presented_certs: &[rustls::Certificate],
_dns_name: webpki::DNSNameRef,
_end_entity: &rustls::Certificate,
_intermediates: &[rustls::Certificate],
_server_name: &rustls::ServerName,
_scts: &mut dyn Iterator<Item = &[u8]>,
_ocsp_response: &[u8],
) -> std::result::Result<rustls::ServerCertVerified, rustls::TLSError> {
_now: std::time::SystemTime,
) -> Result<rustls::ServerCertVerified, rustls::Error> {
*self.0.lock().unwrap() = true;
Ok(rustls::ServerCertVerified::assertion())
}
Expand Down
4 changes: 2 additions & 2 deletions interop/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ async fn main() -> Result<()> {
server_config.use_stateless_retry(true);
let retry = server(server_config.clone(), SocketAddr::new(opt.listen, 4434));

tokio::try_join!(main, default, retry, h2_server(server_config.clone()))?;
tokio::try_join!(main, default, retry, h2_server(server_config))?;

Ok(())
}
Expand Down Expand Up @@ -282,7 +282,7 @@ async fn h2_handle(request: hyper::Request<hyper::Body>) -> Result<hyper::Respon

async fn h2_server(server_config: quinn::ServerConfig) -> Result<()> {
let mut tls_cfg = (*server_config.crypto).clone();
tls_cfg.set_protocols(&[b"h2".to_vec(), b"http/1.1".to_vec()]);
tls_cfg.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
let tls_acceptor = TlsAcceptor::from(sync::Arc::new(tls_cfg));

let tcp = TcpListener::bind(&SocketAddr::new([0, 0, 0, 0].into(), 443)).await?;
Expand Down
5 changes: 3 additions & 2 deletions perf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ futures = "0.3.8"
hdrhistogram = { version = "7.2", default-features = false }
quinn = { path = "../quinn" }
rcgen = "0.8"
rustls = { version = "0.19", features = ["dangerous_configuration"] }
rustls = { version = "0.20.0-beta1", git = "https://github.com/djc/rustls", rev = "d0a6142e74c84a38a91e166304918daea2902478", features = ["dangerous_configuration", "quic"] }
rustls-pemfile = { version = "0.2.1" }
socket2 = "0.4"
webpki = "0.21"
webpki = "0.22"
structopt = "0.3"
tokio = { version = "1.0.1", features = ["rt", "macros", "signal", "net", "sync"] }
tracing = "0.1.10"
Expand Down
55 changes: 27 additions & 28 deletions perf/src/bin/perf_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use anyhow::{Context, Result};
use bytes::Bytes;
use futures::StreamExt;
use hdrhistogram::Histogram;
use rustls::SupportedCipherSuite;
use structopt::StructOpt;
use tokio::sync::Semaphore;
use tracing::{debug, error, info};
Expand Down Expand Up @@ -36,9 +37,6 @@ struct Opt {
/// Number of bytes to transmit, in addition to the request header
#[structopt(long, default_value = "1048576")]
upload_size: u64,
/// Whether to skip certificate validation
#[structopt(long)]
insecure: bool,
/// The time to run in seconds
#[structopt(long, default_value = "60")]
duration: u64,
Expand Down Expand Up @@ -102,27 +100,20 @@ async fn run(opt: Opt) -> Result<()> {

let (endpoint, _) = endpoint.with_socket(socket).context("binding endpoint")?;

let mut cfg = quinn::ClientConfig::with_root_certificates([], None).unwrap();
let tls_config = Arc::get_mut(&mut cfg.crypto).unwrap();
tls_config.alpn_protocols = vec![b"perf".to_vec()];

let tls_config: &mut rustls::ClientConfig = Arc::get_mut(&mut cfg.crypto).unwrap();
if opt.insecure {
tls_config
.dangerous()
.set_certificate_verifier(SkipServerVerification::new());
}
// Configure cipher suites for efficiency
tls_config.ciphersuites.clear();
tls_config
.ciphersuites
.push(&rustls::ciphersuite::TLS13_AES_128_GCM_SHA256);
tls_config
.ciphersuites
.push(&rustls::ciphersuite::TLS13_AES_256_GCM_SHA384);
tls_config
.ciphersuites
.push(&rustls::ciphersuite::TLS13_CHACHA20_POLY1305_SHA256);
let mut crypto = rustls::ClientConfig::builder()
.with_cipher_suites(PERF_CIPHER_SUITES)
.with_safe_default_kx_groups()
.with_protocol_versions(&[&rustls::version::TLS13])
.unwrap()
.with_custom_certificate_verifier(SkipServerVerification::new())
.with_no_client_auth();
crypto.alpn_protocols = vec![b"perf".to_vec()];

let transport = Arc::new(quinn::TransportConfig::default());
let cfg = quinn::ClientConfig {
crypto: Arc::new(crypto),
transport,
};

let stats = Arc::new(Mutex::new(Stats::default()));

Expand Down Expand Up @@ -360,11 +351,13 @@ impl SkipServerVerification {
impl rustls::ServerCertVerifier for SkipServerVerification {
fn verify_server_cert(
&self,
_roots: &rustls::RootCertStore,
_presented_certs: &[rustls::Certificate],
_dns_name: webpki::DNSNameRef,
_end_entity: &rustls::Certificate,
_intermediates: &[rustls::Certificate],
_server_name: &rustls::ServerName,
_scts: &mut dyn Iterator<Item = &[u8]>,
_ocsp_response: &[u8],
) -> Result<rustls::ServerCertVerified, rustls::TLSError> {
_now: std::time::SystemTime,
) -> Result<rustls::ServerCertVerified, rustls::Error> {
Ok(rustls::ServerCertVerified::assertion())
}
}
Expand Down Expand Up @@ -507,3 +500,9 @@ impl Stats {
fn throughput_bps(duration: Duration, size: u64) -> f64 {
(size as f64) / (duration.as_secs_f64())
}

static PERF_CIPHER_SUITES: &[SupportedCipherSuite] = &[
rustls::cipher_suite::TLS13_AES_128_GCM_SHA256,
rustls::cipher_suite::TLS13_AES_256_GCM_SHA384,
rustls::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256,
];
50 changes: 26 additions & 24 deletions perf/src/bin/perf_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,38 +47,34 @@ async fn run(opt: Opt) -> Result<()> {
(&Some(ref key), &Some(ref cert)) => {
let key = fs::read(key).context("reading key")?;
let cert = fs::read(cert).expect("reading cert");
(
quinn::PrivateKey::from_pem(&key).context("parsing key")?,
quinn::CertificateChain::from_pem(&cert).context("parsing cert")?,
)

let mut certs = Vec::new();
for cert in rustls_pemfile::certs(&mut cert.as_ref()).context("parsing cert")? {
certs.push(rustls::Certificate(cert));
}

(rustls::PrivateKey(key), certs)
}
_ => {
let cert = rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap();
(
quinn::PrivateKey::from_der(&cert.serialize_private_key_der()).unwrap(),
quinn::CertificateChain::from_certs(vec![quinn::Certificate::from_der(
&cert.serialize_der().unwrap(),
)
.unwrap()]),
rustls::PrivateKey(cert.serialize_private_key_der()),
vec![rustls::Certificate(cert.serialize_der().unwrap())],
)
}
};

// Configure cipher suites for efficiency
let mut server_config = quinn::ServerConfig::with_single_cert(cert, key).unwrap();
let tls_config = Arc::get_mut(&mut server_config.crypto).unwrap();
tls_config.alpn_protocols = vec![b"perf".to_vec()];
tls_config.ciphersuites.clear();
tls_config
.ciphersuites
.push(&rustls::ciphersuite::TLS13_AES_128_GCM_SHA256);
tls_config
.ciphersuites
.push(&rustls::ciphersuite::TLS13_AES_256_GCM_SHA384);
tls_config
.ciphersuites
.push(&rustls::ciphersuite::TLS13_CHACHA20_POLY1305_SHA256);

let mut crypto = rustls::ServerConfig::builder()
.with_cipher_suites(PERF_CIPHER_SUITES)
.with_safe_default_kx_groups()
.with_protocol_versions(&[&rustls::version::TLS13])
.unwrap()
.with_no_client_auth()
.with_single_cert(cert, key)
.unwrap();
crypto.alpn_protocols = vec![b"perf".to_vec()];

let server_config = quinn::ServerConfig::with_crypto(Arc::new(crypto));
let mut endpoint = quinn::EndpointBuilder::default();
endpoint.listen(server_config);

Expand Down Expand Up @@ -213,3 +209,9 @@ async fn respond(mut bytes: u64, mut stream: quinn::SendStream) -> Result<()> {
debug!("finished responding on {}", stream.id());
Ok(())
}

static PERF_CIPHER_SUITES: &[rustls::SupportedCipherSuite] = &[
rustls::cipher_suite::TLS13_AES_128_GCM_SHA256,
rustls::cipher_suite::TLS13_AES_256_GCM_SHA384,
rustls::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256,
];
13 changes: 7 additions & 6 deletions quinn-proto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,29 @@ maintenance = { status = "experimental" }
default = ["tls-rustls"]
# Use Google's list of CT logs to enable certificate transparency checks
certificate-transparency = ["ct-logs"]
tls-rustls = ["rustls", "webpki", "ring"]
tls-rustls = ["rustls", "webpki", "ring", "rustls-pemfile"]
# Trust the contents of the OS certificate store by default
native-certs = ["rustls-native-certs"]

[dependencies]
arbitrary = { version = "0.4.5", features = ["derive"], optional = true }
bytes = "1"
fxhash = "0.2.1"
ct-logs = { version = "0.8", optional = true }
ct-logs = { version = "0.9", optional = true }
rand = "0.8"
ring = { version = "0.16.7", optional = true }
# If rustls gets updated to a new version which contains
# https://github.com/ctz/rustls/commit/7117a805e0104705da50259357d8effa7d599e37
# the custom cipher list in `quinn-proto/src/crypto/rustls.rs` can be removed.
rustls = { version = "0.19", features = ["quic"], optional = true }
rustls-native-certs = { git = "https://github.com/djc/rustls-native-certs", rev = "c862ff371d8766deab109990f3e7b2e89d9af168", optional = true }
sct = "0.6.1"
rustls = { version = "0.20.0-beta2", git = "https://github.com/djc/rustls", rev = "d0a6142e74c84a38a91e166304918daea2902478", features = ["quic"], optional = true }
rustls-native-certs = { git = "https://github.com/djc/rustls-native-certs", rev = "6116ef59f5825b0ec74a38807635a70433d68c27", optional = true }
rustls-pemfile = { version = "0.2.1", optional = true }
sct = "0.7"
slab = "0.4"
thiserror = "1.0.21"
tinyvec = { version = "1.1", features = ["alloc"] }
tracing = "0.1.10"
webpki = { version = "0.21", optional = true }
webpki = { version = "0.22", optional = true }

[dev-dependencies]
assert_matches = "1.1"
Expand Down
Loading

0 comments on commit 5293a12

Please sign in to comment.