Skip to main content

network_protocol/transport/
tls.rs

1//! # TLS Transport Layer
2//!
3//! This file is part of the Network Protocol project.
4//!
5//! It defines the TLS transport layer for secure network communication,
6//! particularly for external untrusted connections.
7//!
8//! The TLS transport layer provides a secure channel for communication
9//! using industry-standard TLS protocol, ensuring confidentiality,
10//! integrity, and authentication of the data transmitted.
11//!
12//! ## Responsibilities
13//! - Establish secure TLS connections
14//! - Handle TLS certificates and verification
15//! - Provide secure framed transport for higher protocol layers
16//! - Compatible with existing packet codec infrastructure
17
18use std::fs::File;
19use std::io::{self, BufReader, Seek, Write};
20use std::net::SocketAddr;
21use std::path::Path;
22use std::sync::Arc;
23
24use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
25use rustls::crypto::{CryptoProvider, WebPkiSupportedAlgorithms};
26use rustls::pki_types::pem::PemObject;
27use rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer, ServerName, UnixTime};
28use rustls::{ClientConfig, DigitallySignedStruct, RootCertStore, ServerConfig};
29use tokio::net::{TcpListener, TcpStream};
30use tokio_rustls::client::TlsStream as ClientTlsStream;
31use tokio_rustls::server::TlsStream as ServerTlsStream;
32use tokio_rustls::{TlsAcceptor, TlsConnector};
33use tokio_util::codec::Framed;
34use tracing::{debug, error, info, instrument, warn};
35
36use crate::core::codec::PacketCodec;
37use crate::core::packet::Packet;
38use crate::error::{ProtocolError, Result};
39use futures::{SinkExt, StreamExt};
40
41// Custom certificate verifiers.
42//
43// Both verifiers replace only the certificate *validation* step (chain building and
44// hostname checks). They still verify the handshake signature with the provider's
45// signature algorithms, which is what proves that the server holds the private key
46// for the certificate it presented. Without that check a pinned certificate, which is
47// public, could be replayed by any server.
48
49/// Accepts only a server certificate whose SHA-256 fingerprint matches the pin.
50#[derive(Debug)]
51struct CertificateFingerprint {
52    fingerprint: Vec<u8>,
53    supported_algs: WebPkiSupportedAlgorithms,
54}
55
56impl ServerCertVerifier for CertificateFingerprint {
57    fn verify_server_cert(
58        &self,
59        end_entity: &CertificateDer<'_>,
60        _intermediates: &[CertificateDer<'_>],
61        _server_name: &ServerName,
62        _ocsp_response: &[u8],
63        _now: UnixTime,
64    ) -> std::result::Result<ServerCertVerified, rustls::Error> {
65        use sha2::{Digest, Sha256};
66
67        let mut hasher = Sha256::new();
68        hasher.update(end_entity);
69        let hash = hasher.finalize();
70
71        if hash.as_slice() == self.fingerprint.as_slice() {
72            Ok(ServerCertVerified::assertion())
73        } else {
74            Err(rustls::Error::General(
75                "Pinned certificate hash mismatch".into(),
76            ))
77        }
78    }
79
80    fn verify_tls12_signature(
81        &self,
82        message: &[u8],
83        cert: &CertificateDer<'_>,
84        dss: &DigitallySignedStruct,
85    ) -> std::result::Result<HandshakeSignatureValid, rustls::Error> {
86        rustls::crypto::verify_tls12_signature(message, cert, dss, &self.supported_algs)
87    }
88
89    fn verify_tls13_signature(
90        &self,
91        message: &[u8],
92        cert: &CertificateDer<'_>,
93        dss: &DigitallySignedStruct,
94    ) -> std::result::Result<HandshakeSignatureValid, rustls::Error> {
95        rustls::crypto::verify_tls13_signature(message, cert, dss, &self.supported_algs)
96    }
97
98    fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
99        self.supported_algs.supported_schemes()
100    }
101}
102
103/// Accepts any server certificate (insecure mode without a pin), but still requires a
104/// valid handshake signature from the key in that certificate.
105#[derive(Debug)]
106struct AcceptAnyServerCert {
107    supported_algs: WebPkiSupportedAlgorithms,
108}
109
110impl ServerCertVerifier for AcceptAnyServerCert {
111    fn verify_server_cert(
112        &self,
113        _end_entity: &CertificateDer<'_>,
114        _intermediates: &[CertificateDer<'_>],
115        _server_name: &ServerName,
116        _ocsp_response: &[u8],
117        _now: UnixTime,
118    ) -> std::result::Result<ServerCertVerified, rustls::Error> {
119        Ok(ServerCertVerified::assertion())
120    }
121
122    fn verify_tls12_signature(
123        &self,
124        message: &[u8],
125        cert: &CertificateDer<'_>,
126        dss: &DigitallySignedStruct,
127    ) -> std::result::Result<HandshakeSignatureValid, rustls::Error> {
128        rustls::crypto::verify_tls12_signature(message, cert, dss, &self.supported_algs)
129    }
130
131    fn verify_tls13_signature(
132        &self,
133        message: &[u8],
134        cert: &CertificateDer<'_>,
135        dss: &DigitallySignedStruct,
136    ) -> std::result::Result<HandshakeSignatureValid, rustls::Error> {
137        rustls::crypto::verify_tls13_signature(message, cert, dss, &self.supported_algs)
138    }
139
140    fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
141        self.supported_algs.supported_schemes()
142    }
143}
144
145/// The crypto provider used by every TLS config and verifier in this module.
146///
147/// rustls APIs without a `_with_provider` suffix fall back to the process-level default
148/// provider, which panics when more than one rustls crypto backend is compiled in and
149/// none has been installed. Always pass this provider explicitly instead.
150fn crypto_provider() -> Arc<CryptoProvider> {
151    Arc::new(rustls::crypto::ring::default_provider())
152}
153
154/// Resolves the versions and cipher suites requested with `with_tls_versions()` and
155/// `with_cipher_suites()` into the protocol versions to enable and a provider whose
156/// cipher suites are restricted to the requested ones.
157///
158/// `None` means the rustls defaults. Cipher suites are matched by their IANA identifier
159/// against the suites of [`crypto_provider()`], keeping that provider's preference order.
160/// Requests that leave nothing usable are rejected here rather than falling back to the
161/// defaults.
162fn resolve_protocol_settings(
163    tls_versions: Option<&[TlsVersion]>,
164    cipher_suites: Option<&[rustls::SupportedCipherSuite]>,
165) -> Result<(
166    Arc<CryptoProvider>,
167    Vec<&'static rustls::SupportedProtocolVersion>,
168)> {
169    let versions: Vec<&'static rustls::SupportedProtocolVersion> = match tls_versions {
170        None => rustls::DEFAULT_VERSIONS.to_vec(),
171        Some(requested) => {
172            let mut has_tls13 = false;
173            let mut has_tls12 = false;
174            for v in requested {
175                match v {
176                    TlsVersion::TLS12 => has_tls12 = true,
177                    TlsVersion::TLS13 => has_tls13 = true,
178                    TlsVersion::All => {
179                        has_tls13 = true;
180                        has_tls12 = true;
181                    }
182                }
183            }
184            debug!(
185                "TLS versions requested: TLS1.2={}, TLS1.3={}",
186                has_tls12, has_tls13
187            );
188
189            let mut versions = Vec::with_capacity(2);
190            if has_tls13 {
191                versions.push(&rustls::version::TLS13);
192            }
193            if has_tls12 {
194                versions.push(&rustls::version::TLS12);
195            }
196            if versions.is_empty() {
197                return Err(ProtocolError::TlsError(
198                    "No TLS protocol versions configured: with_tls_versions() was given an empty list"
199                        .into(),
200                ));
201            }
202            versions
203        }
204    };
205
206    let mut provider = CryptoProvider::clone(&crypto_provider());
207    if let Some(requested) = cipher_suites {
208        for suite in requested {
209            if !provider
210                .cipher_suites
211                .iter()
212                .any(|s| s.suite() == suite.suite())
213            {
214                warn!(suite = ?suite.suite(), "Requested cipher suite is not supported and was ignored");
215            }
216        }
217        provider
218            .cipher_suites
219            .retain(|s| requested.iter().any(|r| r.suite() == s.suite()));
220        if provider.cipher_suites.is_empty() {
221            return Err(ProtocolError::TlsError(
222                "No supported cipher suites configured: none of the suites given to with_cipher_suites() are available"
223                    .into(),
224            ));
225        }
226        debug!(
227            suites = ?provider.cipher_suites.iter().map(|s| s.suite()).collect::<Vec<_>>(),
228            "TLS cipher suites restricted"
229        );
230    }
231
232    if !provider
233        .cipher_suites
234        .iter()
235        .any(|s| versions.contains(&s.version()))
236    {
237        return Err(ProtocolError::TlsError(
238            "None of the configured cipher suites can be used with the configured TLS versions"
239                .into(),
240        ));
241    }
242
243    Ok((Arc::new(provider), versions))
244}
245
246/// Helper function to load a private key from PKCS8 format
247fn load_private_key(reader: &mut BufReader<File>) -> Result<PrivateKeyDer<'static>> {
248    // Try to load PKCS8 keys
249    // Seek to beginning of file first
250    reader
251        .seek(std::io::SeekFrom::Start(0))
252        .map_err(ProtocolError::Io)?;
253
254    // Collect every PKCS8 private key section in the PEM input
255    let keys: std::result::Result<Vec<_>, _> =
256        PrivatePkcs8KeyDer::pem_reader_iter(reader).collect();
257    let keys =
258        keys.map_err(|_| ProtocolError::TlsError("Failed to parse PKCS8 private key".into()))?;
259
260    if !keys.is_empty() {
261        return Ok(PrivateKeyDer::Pkcs8(keys[0].clone_key()));
262    }
263
264    // Note: Add support for other key formats like RSA or EC if needed
265
266    Err(ProtocolError::TlsError(
267        "No supported private key format found".into(),
268    ))
269}
270
271/// TLS protocol version
272pub enum TlsVersion {
273    /// TLS 1.2
274    TLS12,
275    /// TLS 1.3
276    TLS13,
277    /// Both TLS 1.2 and 1.3
278    All,
279}
280
281/// TLS server configuration
282pub struct TlsServerConfig {
283    cert_path: String,
284    key_path: String,
285    /// Optional path to client CA certificates for mTLS
286    client_ca_path: Option<String>,
287    /// Whether to require client certificates (mTLS)
288    require_client_auth: bool,
289    /// Allowed TLS protocol versions (None = use rustls defaults)
290    tls_versions: Option<Vec<TlsVersion>>,
291    /// Allowed cipher suites (None = use rustls defaults)
292    cipher_suites: Option<Vec<rustls::SupportedCipherSuite>>,
293    /// ALPN protocols to advertise (default: ["h2", "http/1.1"])
294    alpn_protocols: Option<Vec<Vec<u8>>>,
295}
296
297impl TlsServerConfig {
298    /// Create a new TLS server configuration
299    pub fn new<P: AsRef<std::path::Path>>(cert_path: P, key_path: P) -> Self {
300        Self {
301            cert_path: cert_path.as_ref().to_string_lossy().to_string(),
302            key_path: key_path.as_ref().to_string_lossy().to_string(),
303            client_ca_path: None,
304            require_client_auth: false,
305            tls_versions: None,
306            cipher_suites: None,
307            alpn_protocols: Some(vec![b"h2".to_vec(), b"http/1.1".to_vec()]),
308        }
309    }
310
311    /// Set allowed TLS protocol versions
312    ///
313    /// Only the listed versions are enabled. An empty list is rejected when the
314    /// config is loaded.
315    pub fn with_tls_versions(mut self, versions: Vec<TlsVersion>) -> Self {
316        self.tls_versions = Some(versions);
317        self
318    }
319
320    /// Set allowed cipher suites
321    ///
322    /// Only the listed suites are enabled, matched by suite identifier and kept in this
323    /// crate's preference order. Loading the config fails if none of them is supported,
324    /// or if none of them can be used with the enabled TLS versions.
325    pub fn with_cipher_suites(mut self, cipher_suites: Vec<rustls::SupportedCipherSuite>) -> Self {
326        self.cipher_suites = Some(cipher_suites);
327        self
328    }
329
330    /// Enable mutual TLS authentication by providing a CA certificate path
331    pub fn with_client_auth<S: Into<String>>(mut self, client_ca_path: S) -> Self {
332        self.client_ca_path = Some(client_ca_path.into());
333        self.require_client_auth = true;
334        self
335    }
336
337    /// Set whether client authentication is required (true) or optional (false)
338    ///
339    /// Only has an effect together with `with_client_auth()`, which sets it to `true`.
340    /// When optional, clients without a certificate are accepted, but a certificate that
341    /// is presented must still be signed by the client CA.
342    pub fn require_client_auth(mut self, required: bool) -> Self {
343        self.require_client_auth = required;
344        self
345    }
346
347    /// Set ALPN protocols to advertise during TLS handshake
348    pub fn with_alpn_protocols(mut self, protocols: Vec<Vec<u8>>) -> Self {
349        self.alpn_protocols = Some(protocols);
350        self
351    }
352
353    /// Generate a self-signed certificate for development/testing purposes
354    pub fn generate_self_signed<P: AsRef<Path>>(cert_path: P, key_path: P) -> io::Result<Self> {
355        let cert = rcgen::generate_simple_self_signed(vec!["localhost".into()])
356            .map_err(|e| io::Error::other(format!("Certificate generation error: {e}")))?;
357
358        // Write certificate
359        let mut cert_file = File::create(&cert_path)?;
360        let pem = cert.cert.pem();
361        cert_file.write_all(pem.as_bytes())?;
362
363        // Write private key
364        let mut key_file = File::create(&key_path)?;
365        key_file.write_all(cert.signing_key.serialize_pem().as_bytes())?;
366
367        Ok(Self {
368            cert_path: cert_path.as_ref().to_string_lossy().to_string(),
369            key_path: key_path.as_ref().to_string_lossy().to_string(),
370            client_ca_path: None,
371            require_client_auth: false,
372            tls_versions: None,
373            cipher_suites: None,
374            alpn_protocols: Some(vec![b"h2".to_vec(), b"http/1.1".to_vec()]),
375        })
376    }
377
378    /// Load the TLS configuration from files
379    pub fn load_server_config(&self) -> Result<ServerConfig> {
380        // Load certificate
381        let cert_file = File::open(&self.cert_path)
382            .map_err(|e| ProtocolError::TlsError(format!("Failed to open cert file: {e}")))?;
383        let mut cert_reader = BufReader::new(cert_file);
384        let cert_chain: std::result::Result<Vec<_>, _> =
385            CertificateDer::pem_reader_iter(&mut cert_reader).collect();
386        let cert_chain: Vec<CertificateDer<'static>> = cert_chain
387            .map_err(|_| ProtocolError::TlsError("Failed to parse certificate".into()))?;
388
389        if cert_chain.is_empty() {
390            return Err(ProtocolError::TlsError("No certificates found".into()));
391        }
392
393        // Load private key
394        let key_file = File::open(&self.key_path)
395            .map_err(|e| ProtocolError::TlsError(format!("Failed to open key file: {e}")))?;
396        let mut key_reader = BufReader::new(key_file);
397        let private_key = load_private_key(&mut key_reader)?;
398
399        let (provider, versions) =
400            resolve_protocol_settings(self.tls_versions.as_deref(), self.cipher_suites.as_deref())?;
401        let config_builder = ServerConfig::builder_with_provider(provider.clone())
402            .with_protocol_versions(&versions)
403            .map_err(|e| {
404                ProtocolError::TlsError(format!("Failed to configure TLS protocol versions: {e}"))
405            })?;
406
407        // Configure client authentication (mTLS) if a client CA was given
408        let cert_builder = if let Some(client_ca_path) = &self.client_ca_path {
409            // Load client CA certificates
410            let client_ca_file = File::open(client_ca_path).map_err(|e| {
411                ProtocolError::TlsError(format!("Failed to open client CA file: {e}"))
412            })?;
413            let mut client_ca_reader = BufReader::new(client_ca_file);
414            let client_ca_certs: std::result::Result<Vec<_>, _> =
415                CertificateDer::pem_reader_iter(&mut client_ca_reader).collect();
416            let client_ca_certs: Vec<CertificateDer<'static>> = client_ca_certs.map_err(|_| {
417                ProtocolError::TlsError("Failed to parse client CA certificate".into())
418            })?;
419
420            if client_ca_certs.is_empty() {
421                return Err(ProtocolError::TlsError(
422                    "No client CA certificates found".into(),
423                ));
424            }
425
426            // Create client cert verifier
427            let mut client_root_store = RootCertStore::empty();
428            for cert in client_ca_certs {
429                client_root_store.add(cert).map_err(|e| {
430                    ProtocolError::TlsError(format!("Failed to add client CA cert: {e}"))
431                })?;
432            }
433
434            // Create client authentication verifier using WebPkiClientVerifier.
435            // The provider is passed explicitly: `WebPkiClientVerifier::builder` uses the
436            // process-level default, which panics when it cannot be chosen automatically.
437            let mut verifier_builder = rustls::server::WebPkiClientVerifier::builder_with_provider(
438                Arc::new(client_root_store),
439                provider,
440            );
441            if !self.require_client_auth {
442                // Optional client auth: a client without a certificate is accepted, but a
443                // certificate that is presented must still chain to the client CA.
444                verifier_builder = verifier_builder.allow_unauthenticated();
445            }
446            let client_auth = verifier_builder.build().map_err(|e| {
447                ProtocolError::TlsError(format!("Failed to build client verifier: {e}"))
448            })?;
449
450            if self.require_client_auth {
451                debug!("mTLS enabled with client certificate verification required");
452            } else {
453                debug!("mTLS enabled with optional client certificate verification");
454            }
455            config_builder.with_client_cert_verifier(client_auth)
456        } else {
457            config_builder.with_no_client_auth()
458        };
459
460        // Build config with certificates
461        let mut config = cert_builder
462            .with_single_cert(cert_chain, private_key)
463            .map_err(|e| ProtocolError::TlsError(format!("TLS error: {e}")))?;
464
465        // Configure ALPN protocols if specified
466        if let Some(protocols) = &self.alpn_protocols {
467            config.alpn_protocols = protocols.clone();
468            debug!(
469                protocol_count = protocols.len(),
470                "ALPN protocols configured"
471            );
472        }
473
474        Ok(config)
475    }
476
477    /// Calculate SHA-256 hash for a certificate to use with pinning
478    pub fn calculate_cert_hash(cert: &CertificateDer<'_>) -> Vec<u8> {
479        use sha2::{Digest, Sha256};
480        let mut hasher = Sha256::new();
481        hasher.update(cert.as_ref());
482        hasher.finalize().to_vec()
483    }
484}
485
486/// TLS Client Configuration
487pub struct TlsClientConfig {
488    server_name: String,
489    insecure: bool,
490    /// Optional certificate hash to pin (SHA-256 fingerprint)
491    pinned_cert_hash: Option<Vec<u8>>,
492    /// Optional client certificate path for mTLS
493    client_cert_path: Option<String>,
494    /// Optional client key path for mTLS
495    client_key_path: Option<String>,
496    /// Allowed TLS protocol versions (None = use rustls defaults)
497    tls_versions: Option<Vec<TlsVersion>>,
498    /// Allowed cipher suites (None = use rustls defaults)
499    cipher_suites: Option<Vec<rustls::SupportedCipherSuite>>,
500}
501
502impl TlsClientConfig {
503    /// Create a new TLS client configuration
504    pub fn new<S: Into<String>>(server_name: S) -> Self {
505        Self {
506            server_name: server_name.into(),
507            insecure: false,
508            pinned_cert_hash: None,
509            client_cert_path: None,
510            client_key_path: None,
511            tls_versions: None,
512            cipher_suites: None,
513        }
514    }
515
516    /// Set allowed TLS protocol versions
517    ///
518    /// Only the listed versions are enabled. An empty list is rejected when the
519    /// config is loaded.
520    pub fn with_tls_versions(mut self, versions: Vec<TlsVersion>) -> Self {
521        self.tls_versions = Some(versions);
522        self
523    }
524
525    /// Set allowed cipher suites
526    ///
527    /// Only the listed suites are enabled, matched by suite identifier and kept in this
528    /// crate's preference order. Loading the config fails if none of them is supported,
529    /// or if none of them can be used with the enabled TLS versions.
530    pub fn with_cipher_suites(mut self, cipher_suites: Vec<rustls::SupportedCipherSuite>) -> Self {
531        self.cipher_suites = Some(cipher_suites);
532        self
533    }
534
535    /// Configure client authentication for mTLS
536    pub fn with_client_certificate<S: Into<String>>(mut self, cert_path: S, key_path: S) -> Self {
537        self.client_cert_path = Some(cert_path.into());
538        self.client_key_path = Some(key_path.into());
539        self
540    }
541
542    /// Allow insecure connections (skip certificate verification)
543    ///
544    /// # WARNING: Security Risk
545    /// This mode skips certificate validation (no CA chain or hostname checks), so any
546    /// certificate is accepted unless one is pinned with `with_pinned_cert_hash()`. The
547    /// server must still prove that it holds the private key for the certificate it
548    /// presents: the handshake signature is always verified. This mode should ONLY be used for:
549    /// - Development and testing
550    /// - Debugging environments
551    /// - Internal networks with certificate pinning enabled
552    ///
553    /// **NEVER** use this in production without explicit certificate pinning via `with_pinned_cert_hash()`.
554    ///
555    /// For maximum security, only use this with the "dangerous_configuration" feature enabled,
556    /// which is a strong indicator this is for testing/development only.
557    pub fn insecure(mut self) -> Self {
558        warn!("INSECURE MODE ENABLED: Certificate verification is disabled. This should only be used for development/testing.");
559        self.insecure = true;
560        self
561    }
562
563    /// Pin a certificate by its SHA-256 hash/fingerprint
564    ///
565    /// This provides additional security by only accepting connections
566    /// from servers with the exact certificate matching this hash.
567    /// Can be combined with insecure mode for development environments where
568    /// you want to skip standard CA verification but still verify a specific cert.
569    /// The handshake signature is verified against the pinned certificate's public key,
570    /// so a server that has the certificate but not its private key is rejected.
571    pub fn with_pinned_cert_hash(mut self, hash: Vec<u8>) -> Self {
572        if hash.len() != 32 {
573            warn!(
574                "Certificate hash has unexpected length: {} (expected 32 bytes for SHA-256)",
575                hash.len()
576            );
577        }
578        self.pinned_cert_hash = Some(hash);
579        self
580    }
581
582    /// Load the TLS client configuration
583    pub fn load_client_config(&self) -> Result<ClientConfig> {
584        if self.insecure {
585            self.build_insecure_client_config()
586        } else {
587            self.build_secure_client_config()
588        }
589    }
590
591    /// Start a client config builder with the configured provider, versions and suites
592    fn client_config_builder(
593        &self,
594    ) -> Result<(
595        Arc<CryptoProvider>,
596        rustls::ConfigBuilder<ClientConfig, rustls::WantsVerifier>,
597    )> {
598        let (provider, versions) =
599            resolve_protocol_settings(self.tls_versions.as_deref(), self.cipher_suites.as_deref())?;
600        let builder = ClientConfig::builder_with_provider(provider.clone())
601            .with_protocol_versions(&versions)
602            .map_err(|e| {
603                ProtocolError::TlsError(format!("Failed to configure TLS protocol versions: {e}"))
604            })?;
605        Ok((provider, builder))
606    }
607
608    /// Build secure client config with system root CAs
609    fn build_secure_client_config(&self) -> Result<ClientConfig> {
610        let (_, builder) = self.client_config_builder()?;
611        let root_store = self.load_system_root_certificates()?;
612        let builder = builder.with_root_certificates(root_store);
613
614        // Apply client auth directly
615        if let (Some(client_cert_path), Some(client_key_path)) =
616            (&self.client_cert_path, &self.client_key_path)
617        {
618            let (cert_chain, key) =
619                self.load_client_credentials(client_cert_path, client_key_path)?;
620            builder.with_client_auth_cert(cert_chain, key).map_err(|e| {
621                ProtocolError::TlsError(format!("Failed to set client certificate: {e}"))
622            })
623        } else {
624            Ok(builder.with_no_client_auth())
625        }
626    }
627
628    /// Build insecure client config with custom verifier
629    fn build_insecure_client_config(&self) -> Result<ClientConfig> {
630        let (provider, builder) = self.client_config_builder()?;
631        let verifier = self.create_custom_verifier(&provider);
632        let custom_builder = builder
633            .dangerous()
634            .with_custom_certificate_verifier(verifier);
635
636        // Apply client auth directly
637        if let (Some(client_cert_path), Some(client_key_path)) =
638            (&self.client_cert_path, &self.client_key_path)
639        {
640            let (cert_chain, key) =
641                self.load_client_credentials(client_cert_path, client_key_path)?;
642            custom_builder
643                .with_client_auth_cert(cert_chain, key)
644                .map_err(|e| {
645                    ProtocolError::TlsError(format!("Failed to set client certificate: {e}"))
646                })
647        } else {
648            Ok(custom_builder.with_no_client_auth())
649        }
650    }
651
652    /// Load system root certificates
653    fn load_system_root_certificates(&self) -> Result<RootCertStore> {
654        let mut root_store = RootCertStore::empty();
655        let native_certs = rustls_native_certs::load_native_certs();
656        if let Some(e) = native_certs.errors.first() {
657            return Err(ProtocolError::TlsError(format!(
658                "Failed to load native certs: {e}"
659            )));
660        }
661
662        for cert in native_certs.certs {
663            root_store.add(cert).map_err(|e| {
664                ProtocolError::TlsError(format!("Failed to add cert to root store: {e}"))
665            })?;
666        }
667
668        Ok(root_store)
669    }
670
671    /// Create custom certificate verifier (pinning or accept-any)
672    ///
673    /// Handshake signatures are checked with the same provider's signature algorithms.
674    fn create_custom_verifier(&self, provider: &CryptoProvider) -> Arc<dyn ServerCertVerifier> {
675        let supported_algs = provider.signature_verification_algorithms;
676        if let Some(hash) = &self.pinned_cert_hash {
677            Arc::new(CertificateFingerprint {
678                fingerprint: hash.clone(),
679                supported_algs,
680            })
681        } else {
682            Arc::new(AcceptAnyServerCert { supported_algs })
683        }
684    }
685
686    /// Load client certificate and private key
687    fn load_client_credentials(
688        &self,
689        cert_path: &str,
690        key_path: &str,
691    ) -> Result<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)> {
692        // Load certificate
693        let cert_file = File::open(cert_path).map_err(ProtocolError::Io)?;
694        let mut cert_reader = BufReader::new(cert_file);
695        let certs_result: std::result::Result<Vec<_>, _> =
696            CertificateDer::pem_reader_iter(&mut cert_reader).collect();
697        let certs: Vec<CertificateDer<'static>> = certs_result
698            .map_err(|_| ProtocolError::TlsError("Failed to parse client certificate".into()))?;
699
700        if certs.is_empty() {
701            return Err(ProtocolError::TlsError(
702                "No client certificates found".into(),
703            ));
704        }
705
706        // Load private key
707        let key_file = File::open(key_path).map_err(ProtocolError::Io)?;
708        let mut key_reader = BufReader::new(key_file);
709        let key = load_private_key(&mut key_reader)?;
710
711        Ok((certs, key))
712    }
713
714    /// Get the server name as a rustls::ServerName
715    pub fn server_name(&self) -> Result<ServerName<'_>> {
716        ServerName::try_from(self.server_name.as_str())
717            .map_err(|_| ProtocolError::TlsError("Invalid server name".into()))
718    }
719
720    /// Get the server name as an owned String
721    pub fn server_name_string(&self) -> String {
722        self.server_name.clone()
723    }
724}
725
726/// Start a TLS server on the given address
727#[instrument(skip(config))]
728pub async fn start_server(addr: &str, config: TlsServerConfig) -> Result<()> {
729    let tls_config = config.load_server_config()?;
730    let acceptor = TlsAcceptor::from(Arc::new(tls_config));
731    let listener = TcpListener::bind(addr).await?;
732
733    info!(address=%addr, "TLS server listening");
734
735    loop {
736        let (stream, peer) = listener.accept().await?;
737        let acceptor = acceptor.clone();
738
739        tokio::spawn(async move {
740            match acceptor.accept(stream).await {
741                Ok(tls_stream) => {
742                    if let Err(e) = handle_tls_connection(tls_stream, peer).await {
743                        error!(%peer, error=%e, "Connection error");
744                    }
745                }
746                Err(e) => {
747                    error!(%peer, error=%e, "TLS handshake failed");
748                }
749            }
750        });
751    }
752}
753
754/// Handle a TLS connection
755#[instrument(skip(tls_stream), fields(peer=%peer))]
756async fn handle_tls_connection(
757    tls_stream: ServerTlsStream<TcpStream>,
758    peer: SocketAddr,
759) -> Result<()> {
760    let mut framed = Framed::new(tls_stream, PacketCodec);
761
762    info!("TLS connection established");
763
764    while let Some(packet) = framed.next().await {
765        match packet {
766            Ok(pkt) => {
767                debug!(bytes = pkt.payload.len(), "Received data");
768                on_packet(pkt, &mut framed).await?;
769            }
770            Err(e) => {
771                error!(error=%e, "Protocol error");
772                break;
773            }
774        }
775    }
776
777    info!("TLS connection closed");
778    Ok(())
779}
780
781/// Handle incoming TLS packets
782#[instrument(skip(framed), fields(packet_version=pkt.version, payload_size=pkt.payload.len()))]
783async fn on_packet<T>(pkt: Packet, framed: &mut Framed<T, PacketCodec>) -> Result<()>
784where
785    T: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin,
786{
787    // Echo the packet back (sample implementation)
788    let response = Packet {
789        version: pkt.version,
790        payload: pkt.payload,
791    };
792
793    framed.send(response).await?;
794    Ok(())
795}
796
797/// Connect to a TLS server
798pub async fn connect(
799    addr: &str,
800    config: TlsClientConfig,
801) -> Result<Framed<ClientTlsStream<TcpStream>, PacketCodec>> {
802    let tls_config = Arc::new(config.load_client_config()?);
803    let connector = TlsConnector::from(tls_config);
804
805    let stream = TcpStream::connect(addr).await?;
806
807    // Create ServerName from owned string to ensure 'static lifetime
808    // Note: Box::leak() is used here to satisfy tokio_rustls' 'static requirement
809    let server_name_str = config.server_name_string();
810    let domain_static: &'static str = Box::leak(server_name_str.into_boxed_str());
811    let domain = ServerName::try_from(domain_static)
812        .map_err(|_| ProtocolError::TlsError("Invalid server name".into()))?;
813
814    let tls_stream = connector
815        .connect(domain, stream)
816        .await
817        .map_err(|e| ProtocolError::TlsError(format!("TLS connection failed: {e}")))?;
818
819    let framed = Framed::new(tls_stream, PacketCodec);
820    Ok(framed)
821}