use crate::record::Direction; use log::info; use std::iter::Peekable; use tokio_rustls::rustls::crypto::CryptoProvider; /// Print ASCII if possible pub fn print_bin(s: &[u8]) { if let Ok(s) = str::from_utf8(s) { println!("{s}"); } else { let mut buf = String::new(); for c in s { if c.is_ascii_control() && *c != b'\n' { continue; } if let Some(c) = c.as_ascii() { buf.push_str(c.as_str()); } else { for c in std::ascii::escape_default(*c) { buf.push(c.as_ascii().unwrap().into()); } } } println!("{buf}"); } } pub struct ResponseStreamer(Peekable); impl ResponseStreamer { pub fn new(inner: I) -> Self { Self(inner.peekable()) } } impl<'a, I: Iterator> Iterator for ResponseStreamer { type Item = (Direction, Vec<(u64, u64)>); fn next(&mut self) -> Option { let (first_req_id, first_direction, first_len) = self.0.next()?; let mut items = vec![(*first_req_id, *first_len)]; while let Some((_req_id, direction, _len)) = self.0.peek() && direction == first_direction { let (req_id, _direction, len) = self.0.next().unwrap(); items.push((*req_id, *len)); } Some((*first_direction, items)) } } pub fn init_provider() { let mut ciphers: Option> = None; let mut kexes: Option> = None; for (var, val) in std::env::vars() { match var.as_str() { "CIPHERS" => ciphers = Some(val.split(',').map(str::to_string).collect()), "KEXES" => kexes = Some(val.split(',').map(str::to_string).collect()), _ => {} } } // Ensure multiple provider cannot be enabled without compile error. let _provider; #[cfg(feature = "aws-lc")] { info!("Using RusTLS provider aws-lc"); let mut prov = rustls_post_quantum::provider(); if let Some(ciphers) = ciphers { prov.cipher_suites.clear(); for cipher in ciphers { match cipher.as_str() { "AES_256_GCM_SHA384" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::aws_lc_rs::cipher_suite::TLS13_AES_256_GCM_SHA384), "AES_128_GCM_SHA256" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::aws_lc_rs::cipher_suite::TLS13_AES_128_GCM_SHA256), "CHACHA20_POLY1305_SHA256" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::aws_lc_rs::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256), "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::aws_lc_rs::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::aws_lc_rs::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::aws_lc_rs::cipher_suite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), "ECDHE_RSA_WITH_AES_256_GCM_SHA384" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::aws_lc_rs::cipher_suite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384), "ECDHE_RSA_WITH_AES_128_GCM_SHA256" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::aws_lc_rs::cipher_suite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), "ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::aws_lc_rs::cipher_suite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), other => { log::error!("Unknown cipher `{other}`") } } } } if let Some(kexes) = kexes { prov.kx_groups.clear(); for kex in kexes { match kex.as_str() { "X25519" => prov .kx_groups .push(tokio_rustls::rustls::crypto::aws_lc_rs::kx_group::X25519), "SECP256R1" => prov .kx_groups .push(tokio_rustls::rustls::crypto::aws_lc_rs::kx_group::SECP256R1), "SECP384R1" => prov .kx_groups .push(tokio_rustls::rustls::crypto::aws_lc_rs::kx_group::SECP384R1), "X25519MLKEM768" => prov .kx_groups .push(tokio_rustls::rustls::crypto::aws_lc_rs::kx_group::X25519MLKEM768), "SECP256R1MLKEM768" => prov .kx_groups .push(tokio_rustls::rustls::crypto::aws_lc_rs::kx_group::SECP256R1MLKEM768), "MLKEM768" => prov .kx_groups .push(tokio_rustls::rustls::crypto::aws_lc_rs::kx_group::MLKEM768), other => { log::error!("Unknown kex `{other}`") } } } } _provider = CryptoProvider::install_default(prov); } #[cfg(feature = "boring")] { info!("Using RusTLS provider boring"); let mut prov = boring_rustls_provider::provider(); if let Some(ciphers) = ciphers { prov.cipher_suites.clear(); for cipher in ciphers { match cipher.as_str() { "AES_256_GCM_SHA384" => prov.cipher_suites.push(tokio_rustls::rustls::SupportedCipherSuite::Tls13( &boring_rustls_provider::tls13::AES_256_GCM_SHA384, )), "AES_128_GCM_SHA256" => prov.cipher_suites.push(tokio_rustls::rustls::SupportedCipherSuite::Tls13( &boring_rustls_provider::tls13::AES_128_GCM_SHA256, )), "CHACHA20_POLY1305_SHA256" => prov.cipher_suites.push(tokio_rustls::rustls::SupportedCipherSuite::Tls13( &boring_rustls_provider::tls13::CHACHA20_POLY1305_SHA256, )), "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" => prov.cipher_suites.push(tokio_rustls::rustls::SupportedCipherSuite::Tls12( &boring_rustls_provider::tls12::ECDHE_ECDSA_AES256_GCM_SHA384, )), "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => prov.cipher_suites.push(tokio_rustls::rustls::SupportedCipherSuite::Tls12( &boring_rustls_provider::tls12::ECDHE_ECDSA_AES128_GCM_SHA256, )), "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => prov.cipher_suites.push(tokio_rustls::rustls::SupportedCipherSuite::Tls12( &boring_rustls_provider::tls12::ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, )), "ECDHE_RSA_WITH_AES_256_GCM_SHA384" => prov.cipher_suites.push(tokio_rustls::rustls::SupportedCipherSuite::Tls12( &boring_rustls_provider::tls12::ECDHE_RSA_AES256_GCM_SHA384, )), "ECDHE_RSA_WITH_AES_128_GCM_SHA256" => prov.cipher_suites.push(tokio_rustls::rustls::SupportedCipherSuite::Tls12( &boring_rustls_provider::tls12::ECDHE_RSA_AES128_GCM_SHA256, )), "ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => prov.cipher_suites.push(tokio_rustls::rustls::SupportedCipherSuite::Tls12( &boring_rustls_provider::tls12::ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, )), other => { log::error!("Unknown cipher `{other}`") } } } } if let Some(kexes) = kexes { prov.kx_groups.clear(); for kex in kexes { match kex.as_str() { "X25519" => prov .kx_groups .push(boring_rustls_provider::ALL_KX_GROUPS[0]), "SECP256R1" => prov .kx_groups .push(boring_rustls_provider::ALL_KX_GROUPS[2]), "SECP384R1" => prov .kx_groups .push(boring_rustls_provider::ALL_KX_GROUPS[3]), other => { log::error!("Unknown kex `{other}`") } } } } _provider = CryptoProvider::install_default(prov); } #[cfg(feature = "graviola")] { info!("Using RusTLS provider graviola"); let mut prov = rustls_graviola::default_provider(); if let Some(ciphers) = ciphers { prov.cipher_suites.clear(); for cipher in ciphers { match cipher.as_str() { "AES_256_GCM_SHA384" => prov .cipher_suites .push(rustls_graviola::suites::TLS13_AES_256_GCM_SHA384), "AES_128_GCM_SHA256" => prov .cipher_suites .push(rustls_graviola::suites::TLS13_AES_128_GCM_SHA256), "CHACHA20_POLY1305_SHA256" => prov .cipher_suites .push(rustls_graviola::suites::TLS13_CHACHA20_POLY1305_SHA256), "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" => prov .cipher_suites .push(rustls_graviola::suites::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => prov .cipher_suites .push(rustls_graviola::suites::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => prov.cipher_suites.push( rustls_graviola::suites::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, ), "ECDHE_RSA_WITH_AES_256_GCM_SHA384" => prov .cipher_suites .push(rustls_graviola::suites::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384), "ECDHE_RSA_WITH_AES_128_GCM_SHA256" => prov .cipher_suites .push(rustls_graviola::suites::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), "ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => prov .cipher_suites .push(rustls_graviola::suites::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), other => { log::error!("Unknown cipher `{other}`") } } } } if let Some(kexes) = kexes { prov.kx_groups.clear(); for kex in kexes { match kex.as_str() { "X25519" => prov.kx_groups.push(&rustls_graviola::kx::X25519), "SECP256R1" => prov.kx_groups.push(&rustls_graviola::kx::P256), "SECP384R1" => prov.kx_groups.push(&rustls_graviola::kx::P384), "X25519MLKEM768" => prov.kx_groups.push(rustls_graviola::kx::X25519MLKEM768), other => { log::error!("Unknown kex `{other}`") } } } } _provider = CryptoProvider::install_default(prov); } #[cfg(any(feature = "openssl", feature = "openssl-static"))] { info!("Using RusTLS provider openssl"); let mut prov = rustls_openssl::default_provider(); if let Some(ciphers) = ciphers { prov.cipher_suites.clear(); for cipher in ciphers { match cipher.as_str() { "AES_256_GCM_SHA384" => prov .cipher_suites .push(rustls_openssl::cipher_suite::TLS13_AES_256_GCM_SHA384), "AES_128_GCM_SHA256" => prov .cipher_suites .push(rustls_openssl::cipher_suite::TLS13_AES_128_GCM_SHA256), "CHACHA20_POLY1305_SHA256" => prov .cipher_suites .push(rustls_openssl::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256), "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" => prov.cipher_suites.push( rustls_openssl::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, ), "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => prov.cipher_suites.push( rustls_openssl::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, ), "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => prov.cipher_suites.push( rustls_openssl::cipher_suite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, ), "ECDHE_RSA_WITH_AES_256_GCM_SHA384" => prov .cipher_suites .push(rustls_openssl::cipher_suite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384), "ECDHE_RSA_WITH_AES_128_GCM_SHA256" => prov .cipher_suites .push(rustls_openssl::cipher_suite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), "ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => prov.cipher_suites.push( rustls_openssl::cipher_suite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, ), other => { log::error!("Unknown cipher `{other}`") } } } } if let Some(kexes) = kexes { prov.kx_groups.clear(); for kex in kexes { match kex.as_str() { "X25519" => prov.kx_groups.push(rustls_openssl::kx_group::X25519), "SECP256R1" => prov.kx_groups.push(rustls_openssl::kx_group::SECP256R1), "SECP384R1" => prov.kx_groups.push(rustls_openssl::kx_group::SECP384R1), "X25519MLKEM768" => prov .kx_groups .push(rustls_openssl::kx_group::X25519MLKEM768), "MLKEM768" => prov.kx_groups.push(rustls_openssl::kx_group::MLKEM768), other => { log::error!("Unknown kex `{other}`") } } } } _provider = CryptoProvider::install_default(prov); } #[cfg(feature = "ring")] { info!("Using RusTLS provider ring"); let mut prov = tokio_rustls::rustls::crypto::ring::default_provider(); if let Some(ciphers) = ciphers { prov.cipher_suites.clear(); for cipher in ciphers { match cipher.as_str() { "AES_256_GCM_SHA384" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::ring::cipher_suite::TLS13_AES_256_GCM_SHA384), "AES_128_GCM_SHA256" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::ring::cipher_suite::TLS13_AES_128_GCM_SHA256), "CHACHA20_POLY1305_SHA256" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::ring::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256), "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::ring::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::ring::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::ring::cipher_suite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), "ECDHE_RSA_WITH_AES_256_GCM_SHA384" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::ring::cipher_suite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384), "ECDHE_RSA_WITH_AES_128_GCM_SHA256" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::ring::cipher_suite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), "ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => prov .cipher_suites .push(tokio_rustls::rustls::crypto::ring::cipher_suite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), other => { log::error!("Unknown cipher `{other}`") } } } } if let Some(kexes) = kexes { prov.kx_groups.clear(); for kex in kexes { match kex.as_str() { "X25519" => prov .kx_groups .push(tokio_rustls::rustls::crypto::ring::kx_group::X25519), "SECP256R1" => prov .kx_groups .push(tokio_rustls::rustls::crypto::ring::kx_group::SECP256R1), "SECP384R1" => prov .kx_groups .push(tokio_rustls::rustls::crypto::ring::kx_group::SECP384R1), other => { log::error!("Unknown kex `{other}`") } } } } _provider = CryptoProvider::install_default(prov); } #[cfg(feature = "symcrypt")] { info!("Using RusTLS provider symcrypt"); let mut prov = rustls_symcrypt::default_symcrypt_provider(); if let Some(ciphers) = ciphers { prov.cipher_suites.clear(); for cipher in ciphers { match cipher.as_str() { "AES_256_GCM_SHA384" => prov .cipher_suites .push(rustls_symcrypt::TLS13_AES_256_GCM_SHA384), "AES_128_GCM_SHA256" => prov .cipher_suites .push(rustls_symcrypt::TLS13_AES_128_GCM_SHA256), "CHACHA20_POLY1305_SHA256" => prov .cipher_suites .push(rustls_symcrypt::TLS13_CHACHA20_POLY1305_SHA256), "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" => prov .cipher_suites .push(rustls_symcrypt::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => prov .cipher_suites .push(rustls_symcrypt::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => prov .cipher_suites .push(rustls_symcrypt::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), "ECDHE_RSA_WITH_AES_256_GCM_SHA384" => prov .cipher_suites .push(rustls_symcrypt::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384), "ECDHE_RSA_WITH_AES_128_GCM_SHA256" => prov .cipher_suites .push(rustls_symcrypt::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), "ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => prov .cipher_suites .push(rustls_symcrypt::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), other => { log::error!("Unknown cipher `{other}`") } } } } if let Some(kexes) = kexes { prov.kx_groups.clear(); for kex in kexes { match kex.as_str() { "X25519" => prov.kx_groups.push(rustls_symcrypt::X25519), "SECP256R1" => prov.kx_groups.push(rustls_symcrypt::SECP256R1), "SECP384R1" => prov.kx_groups.push(rustls_symcrypt::SECP384R1), other => { log::error!("Unknown kex `{other}`") } } } } _provider = CryptoProvider::install_default(prov); } }