feat(core): add QUIC TLS admission transport

This commit is contained in:
sechmachine
2026-08-12 19:08:32 +07:00
parent 7947ebcc75
commit 111092becb
11 changed files with 2304 additions and 38 deletions
+114
View File
@@ -0,0 +1,114 @@
use std::fmt;
use std::io::Cursor;
use std::sync::Arc;
use rustls::client::ResolvesClientCert;
use rustls::pki_types::CertificateDer;
use rustls::sign::{CertifiedKey, Signer, SigningKey};
use rustls::{ClientConfig, RootCertStore, SignatureAlgorithm, SignatureScheme};
use crate::error::{CoreError, Result};
use crate::wire::NativeTunnelCredential;
pub(crate) type SignCallback = dyn Fn(&[u8]) -> Result<[u8; 64]> + Send + Sync;
pub(crate) struct CallbackSigningKey {
callback: Arc<SignCallback>,
}
impl fmt::Debug for CallbackSigningKey {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("CallbackSigningKey")
}
}
impl CallbackSigningKey {
pub(crate) fn new(callback: Arc<SignCallback>) -> Self {
Self { callback }
}
}
impl SigningKey for CallbackSigningKey {
fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
offered
.contains(&SignatureScheme::ED25519)
.then(|| Box::new(CallbackSigner(Arc::clone(&self.callback))) as Box<dyn Signer>)
}
fn algorithm(&self) -> SignatureAlgorithm {
SignatureAlgorithm::ED25519
}
}
struct CallbackSigner(Arc<SignCallback>);
impl fmt::Debug for CallbackSigner {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("CallbackSigner")
}
}
impl Signer for CallbackSigner {
fn sign(&self, message: &[u8]) -> std::result::Result<Vec<u8>, rustls::Error> {
(self.0)(message)
.map(|signature| signature.to_vec())
.map_err(|_| rustls::Error::General("client signing failed".to_owned()))
}
fn scheme(&self) -> SignatureScheme {
SignatureScheme::ED25519
}
}
#[derive(Debug)]
struct ClientIdentity(Arc<CertifiedKey>);
impl ResolvesClientCert for ClientIdentity {
fn resolve(
&self,
_root_hint_subjects: &[&[u8]],
sigschemes: &[SignatureScheme],
) -> Option<Arc<CertifiedKey>> {
sigschemes
.contains(&SignatureScheme::ED25519)
.then(|| Arc::clone(&self.0))
}
fn has_certs(&self) -> bool {
true
}
}
pub(crate) fn client_config(
credential: &NativeTunnelCredential,
callback: Arc<SignCallback>,
) -> Result<ClientConfig> {
let certificate_chain = rustls_pemfile::certs(&mut Cursor::new(
credential.certificate_chain_pem().as_bytes(),
))
.collect::<std::result::Result<Vec<CertificateDer<'static>>, _>>()
.map_err(|_| CoreError::Tls)?;
if certificate_chain.is_empty() {
return Err(CoreError::Tls);
}
let mut roots = RootCertStore::empty();
let trust_bundle =
rustls_pemfile::certs(&mut Cursor::new(credential.trust_bundle_pem().as_bytes()))
.collect::<std::result::Result<Vec<CertificateDer<'static>>, _>>()
.map_err(|_| CoreError::Tls)?;
if trust_bundle.is_empty() || roots.add_parsable_certificates(trust_bundle).1 != 0 {
return Err(CoreError::Tls);
}
let provider = Arc::new(rustls::crypto::ring::default_provider());
let mut config = ClientConfig::builder_with_provider(provider)
.with_protocol_versions(&[&rustls::version::TLS13])
.map_err(|_| CoreError::Tls)?
.with_root_certificates(roots)
.with_client_cert_resolver(Arc::new(ClientIdentity(Arc::new(CertifiedKey::new(
certificate_chain,
Arc::new(CallbackSigningKey::new(callback)),
)))));
config.alpn_protocols = vec![b"versevdi-gateway-v1".to_vec()];
config.enable_early_data = false;
Ok(config)
}