Skip to main content

webtrans_quinn/tls/
cert.rs

1//! Certificate handling utilities.
2
3use rustls::client::danger::ServerCertVerifier;
4use rustls::pki_types::pem::PemObject;
5use rustls::pki_types::{CertificateDer, ServerName, UnixTime};
6use std::{fs, path::Path, sync::Arc};
7use webtrans_proto::{Error, Result};
8
9/// Get the native certificates from the system.
10pub fn get_native_certs() -> Result<rustls::RootCertStore> {
11    let mut root_store = rustls::RootCertStore::empty();
12
13    let cert_result = rustls_native_certs::load_native_certs();
14
15    for cert in cert_result.certs {
16        let _ = root_store.add(cert);
17    }
18
19    Ok(root_store)
20}
21
22/// Load a certificate chain from a file (.der or .pem).
23pub fn load_certs(cert_path: &Path) -> Result<Vec<CertificateDer<'static>>> {
24    let cert_bytes = fs::read(cert_path).map_err(|e| Error::Io(e.to_string()))?;
25
26    if cert_path.extension().is_some_and(|x| x == "der") {
27        return Ok(vec![CertificateDer::from(cert_bytes)]);
28    }
29
30    CertificateDer::pem_slice_iter(&cert_bytes)
31        .collect::<std::result::Result<Vec<_>, _>>()
32        .map_err(|e| Error::Tls(e.to_string()))
33}
34
35/// Dummy certificate verifier that treats any certificate as valid.
36/// NOTE: This is vulnerable to MITM attacks; use only for testing.
37#[derive(Debug)]
38pub struct SkipServerVerification(Arc<rustls::crypto::CryptoProvider>);
39
40impl SkipServerVerification {
41    /// Use the crate's selected default crypto provider.
42    pub fn new() -> Arc<Self> {
43        Self::with_provider(crate::crypto::default_provider())
44    }
45
46    /// Create a verifier backed by the provided crypto provider.
47    pub fn with_provider(provider: Arc<rustls::crypto::CryptoProvider>) -> Arc<Self> {
48        Arc::new(Self(provider))
49    }
50}
51
52impl ServerCertVerifier for SkipServerVerification {
53    fn verify_server_cert(
54        &self,
55        _end_entity: &CertificateDer<'_>,
56        _intermediates: &[CertificateDer<'_>],
57        _server_name: &ServerName<'_>,
58        _ocsp: &[u8],
59        _now: UnixTime,
60    ) -> std::result::Result<rustls::client::danger::ServerCertVerified, rustls::Error> {
61        Ok(rustls::client::danger::ServerCertVerified::assertion())
62    }
63
64    fn verify_tls12_signature(
65        &self,
66        message: &[u8],
67        cert: &CertificateDer<'_>,
68        dss: &rustls::DigitallySignedStruct,
69    ) -> std::result::Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
70        rustls::crypto::verify_tls12_signature(
71            message,
72            cert,
73            dss,
74            &self.0.signature_verification_algorithms,
75        )
76    }
77
78    fn verify_tls13_signature(
79        &self,
80        message: &[u8],
81        cert: &CertificateDer<'_>,
82        dss: &rustls::DigitallySignedStruct,
83    ) -> std::result::Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
84        rustls::crypto::verify_tls13_signature(
85            message,
86            cert,
87            dss,
88            &self.0.signature_verification_algorithms,
89        )
90    }
91
92    fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
93        self.0.signature_verification_algorithms.supported_schemes()
94    }
95}