use std::sync::Arc;
use iroh_base::SecretKey;
use quinn::crypto::rustls::{QuicClientConfig, QuicServerConfig};
use tracing::warn;
use self::resolver::AlwaysResolvesCert;
pub(crate) mod name;
mod resolver;
mod verifier;
pub(crate) const DEFAULT_MAX_TLS_TICKETS: usize = 8 * 32;
#[derive(Debug)]
pub(crate) struct TlsConfig {
pub(crate) secret_key: SecretKey,
cert_resolver: Arc<AlwaysResolvesCert>,
server_verifier: Arc<verifier::ServerCertificateVerifier>,
client_verifier: Arc<verifier::ClientCertificateVerifier>,
session_store: Arc<dyn rustls::client::ClientSessionStore>,
}
impl TlsConfig {
pub(crate) fn new(secret_key: SecretKey, max_tls_tickets: usize) -> Self {
let cert_resolver = Arc::new(
AlwaysResolvesCert::new(&secret_key).expect("Client cert key DER is valid; qed"),
);
Self {
secret_key,
cert_resolver,
server_verifier: Arc::new(verifier::ServerCertificateVerifier),
client_verifier: Arc::new(verifier::ClientCertificateVerifier),
session_store: Arc::new(rustls::client::ClientSessionMemoryCache::new(
max_tls_tickets,
)),
}
}
pub(crate) fn make_client_config(
&self,
alpn_protocols: Vec<Vec<u8>>,
keylog: bool,
) -> QuicClientConfig {
let mut crypto = rustls::ClientConfig::builder_with_provider(Arc::new(
rustls::crypto::ring::default_provider(),
))
.with_protocol_versions(verifier::PROTOCOL_VERSIONS)
.expect("version supported by ring")
.dangerous()
.with_custom_certificate_verifier(self.server_verifier.clone())
.with_client_cert_resolver(self.cert_resolver.clone());
crypto.alpn_protocols = alpn_protocols;
crypto.resumption = rustls::client::Resumption::store(self.session_store.clone());
crypto.enable_early_data = true;
if keylog {
warn!("enabling SSLKEYLOGFILE for TLS pre-master keys");
crypto.key_log = Arc::new(rustls::KeyLogFile::new());
}
crypto
.try_into()
.expect("expected to have a TLS1.3-compatible crypto provider set (hardcoded)")
}
pub(crate) fn make_server_config(
&self,
alpn_protocols: Vec<Vec<u8>>,
keylog: bool,
) -> QuicServerConfig {
let mut crypto = rustls::ServerConfig::builder_with_provider(Arc::new(
rustls::crypto::ring::default_provider(),
))
.with_protocol_versions(verifier::PROTOCOL_VERSIONS)
.expect("fixed config")
.with_client_cert_verifier(self.client_verifier.clone())
.with_cert_resolver(self.cert_resolver.clone());
crypto.alpn_protocols = alpn_protocols;
if keylog {
warn!("enabling SSLKEYLOGFILE for TLS pre-master keys");
crypto.key_log = Arc::new(rustls::KeyLogFile::new());
}
crypto.max_early_data_size = u32::MAX;
crypto
.try_into()
.expect("expected to have a TLS1.3-compatible crypto provider set (hardcoded)")
}
}