434 lines
16 KiB
Rust
434 lines
16 KiB
Rust
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<I: Iterator>(Peekable<I>);
|
|
|
|
impl<I: Iterator> ResponseStreamer<I> {
|
|
pub fn new(inner: I) -> Self {
|
|
Self(inner.peekable())
|
|
}
|
|
}
|
|
|
|
impl<'a, I: Iterator<Item = &'a (u64, Direction, u64)>> Iterator for ResponseStreamer<I> {
|
|
type Item = (Direction, Vec<(u64, u64)>);
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
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<Vec<String>> = None;
|
|
let mut kexes: Option<Vec<String>> = 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);
|
|
}
|
|
}
|