use boring::ssl::{
CertificateCompressionAlgorithm, CertificateCompressor, SslConnector, SslMethod,
};
use std::io::{Read, Write};
use crate::error::Result;
use crate::profile::TlsProfile;
pub struct BrotliCompressor;
impl CertificateCompressor for BrotliCompressor {
const ALGORITHM: CertificateCompressionAlgorithm = CertificateCompressionAlgorithm::BROTLI;
const CAN_COMPRESS: bool = false;
const CAN_DECOMPRESS: bool = true;
fn decompress<W>(&self, input: &[u8], output: &mut W) -> std::io::Result<()>
where
W: Write,
{
let mut reader = brotli::Decompressor::new(input, 4096);
let mut buf = [0u8; 4096];
loop {
let n = reader.read(&mut buf)?;
if n == 0 {
break;
}
output.write_all(&buf[..n])?;
}
Ok(())
}
}
pub fn build_connector(profile: &TlsProfile) -> Result<SslConnector> {
tracing::debug!("Building TLS connector...");
let mut builder = SslConnector::builder(SslMethod::tls_client())?;
builder.set_min_proto_version(Some(profile.min_version))?;
builder.set_max_proto_version(Some(profile.max_version))?;
builder.set_cipher_list(profile.cipher_list)?;
let mut curves_str = String::new();
for (i, &group) in profile.curves.iter().enumerate() {
if i > 0 {
curves_str.push(':');
}
match group {
4588 => curves_str.push_str("X25519Kyber768Draft00"),
29 => curves_str.push_str("X25519"),
23 => curves_str.push_str("P-256"),
24 => curves_str.push_str("P-384"),
_ => curves_str.push_str(&group.to_string()),
}
}
builder.set_curves_list(&curves_str)?;
if profile.grease_enabled {
builder.set_grease_enabled(true);
}
if profile.permute_extensions {
builder.set_permute_extensions(true);
}
let mut alpn = Vec::new();
for proto in profile.alpn_protocols {
alpn.push(proto.len() as u8);
alpn.extend_from_slice(proto);
}
builder.set_alpn_protos(&alpn)?;
builder.enable_signed_cert_timestamps();
let ctx_ptr = builder.as_ptr();
unsafe {
let sigalgs_i32: Vec<i32> = profile.sigalgs.iter().map(|&s| s as i32).collect();
boring_sys::SSL_CTX_set1_sigalgs(ctx_ptr, sigalgs_i32.as_ptr(), sigalgs_i32.len());
}
if profile.compress_certificate {
builder.add_certificate_compression_algorithm(BrotliCompressor)?;
}
Ok(builder.build())
}