tlsn_core/
webpki.rs

1//! Web PKI types.
2
3use std::time::Duration;
4
5use rustls_pki_types::{self as webpki_types, pem::PemObject};
6use serde::{Deserialize, Serialize};
7
8use crate::connection::ServerName;
9
10/// X.509 certificate, DER encoded.
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct CertificateDer(pub Vec<u8>);
13
14impl CertificateDer {
15    /// Creates a DER-encoded certificate from a PEM-encoded certificate.
16    pub fn from_pem_slice(pem: &[u8]) -> Result<Self, PemError> {
17        let der = webpki_types::CertificateDer::from_pem_slice(pem).map_err(|_| PemError {})?;
18
19        Ok(Self(der.to_vec()))
20    }
21}
22
23/// Private key, DER encoded.
24#[derive(Debug, Clone, zeroize::ZeroizeOnDrop, Serialize, Deserialize)]
25pub struct PrivateKeyDer(pub Vec<u8>);
26
27impl PrivateKeyDer {
28    /// Creates a DER-encoded private key from a PEM-encoded private key.
29    pub fn from_pem_slice(pem: &[u8]) -> Result<Self, PemError> {
30        let der = webpki_types::PrivateKeyDer::from_pem_slice(pem).map_err(|_| PemError {})?;
31
32        Ok(Self(der.secret_der().to_vec()))
33    }
34}
35
36/// PEM parsing error.
37#[derive(Debug, thiserror::Error)]
38#[error("failed to parse PEM object")]
39pub struct PemError {}
40
41/// Root certificate store.
42///
43/// This stores root certificates which are used to verify end-entity
44/// certificates presented by a TLS server.
45#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct RootCertStore {
47    /// Unvalidated DER-encoded X.509 root certificates.
48    pub roots: Vec<CertificateDer>,
49}
50
51impl RootCertStore {
52    /// Creates an empty root certificate store.
53    pub fn empty() -> Self {
54        Self { roots: Vec::new() }
55    }
56
57    /// Creates a root certificate store with Mozilla root certificates.
58    ///
59    /// These certificates are sourced from [`webpki-root-certs`](https://docs.rs/webpki-root-certs/latest/webpki_root_certs/). It is not recommended to use these unless the
60    /// application binary can be recompiled and deployed on-demand in the case
61    /// that the root certificates need to be updated.
62    #[cfg(feature = "mozilla-certs")]
63    pub fn mozilla() -> Self {
64        Self {
65            roots: webpki_root_certs::TLS_SERVER_ROOT_CERTS
66                .iter()
67                .map(|cert| CertificateDer(cert.to_vec()))
68                .collect(),
69        }
70    }
71}
72
73/// Server certificate verifier.
74#[derive(Debug)]
75pub struct ServerCertVerifier {
76    roots: Vec<webpki_types::TrustAnchor<'static>>,
77}
78
79impl ServerCertVerifier {
80    /// Creates a new server certificate verifier.
81    pub fn new(roots: &RootCertStore) -> Result<Self, ServerCertVerifierError> {
82        let roots = roots
83            .roots
84            .iter()
85            .map(|cert| {
86                webpki::anchor_from_trusted_cert(&webpki_types::CertificateDer::from(
87                    cert.0.as_slice(),
88                ))
89                .map(|anchor| anchor.to_owned())
90                .map_err(|err| ServerCertVerifierError::InvalidRootCertificate {
91                    cert: cert.clone(),
92                    reason: err.to_string(),
93                })
94            })
95            .collect::<Result<Vec<_>, _>>()?;
96
97        Ok(Self { roots })
98    }
99
100    /// Creates a server certificate verifier with Mozilla root certificates.
101    ///
102    /// These certificates are sourced from [`webpki-root-certs`](https://docs.rs/webpki-root-certs/latest/webpki_root_certs/). It is not recommended to use these unless the
103    /// application binary can be recompiled and deployed on-demand in the case
104    /// that the root certificates need to be updated.
105    #[cfg(feature = "mozilla-certs")]
106    pub fn mozilla() -> Self {
107        Self {
108            roots: webpki_roots::TLS_SERVER_ROOTS.to_vec(),
109        }
110    }
111
112    /// Verifies the server certificate was valid at the given time of
113    /// presentation.
114    ///
115    /// # Arguments
116    ///
117    /// * `end_entity` - End-entity certificate to verify.
118    /// * `intermediates` - Intermediate certificates to a trust anchor.
119    /// * `server_name` - Server DNS name.
120    /// * `time` - Unix time the certificate was presented.
121    pub fn verify_server_cert(
122        &self,
123        end_entity: &CertificateDer,
124        intermediates: &[CertificateDer],
125        server_name: &ServerName,
126        time: u64,
127    ) -> Result<(), ServerCertVerifierError> {
128        let cert = webpki_types::CertificateDer::from(end_entity.0.as_slice());
129        let cert = webpki::EndEntityCert::try_from(&cert).map_err(|e| {
130            ServerCertVerifierError::InvalidEndEntityCertificate {
131                cert: end_entity.clone(),
132                reason: e.to_string(),
133            }
134        })?;
135        let intermediates = intermediates
136            .iter()
137            .map(|c| webpki_types::CertificateDer::from(c.0.as_slice()))
138            .collect::<Vec<_>>();
139        let server_name = server_name.to_webpki();
140        let time = webpki_types::UnixTime::since_unix_epoch(Duration::from_secs(time));
141
142        cert.verify_for_usage(
143            webpki::ALL_VERIFICATION_ALGS,
144            &self.roots,
145            &intermediates,
146            time,
147            webpki::KeyUsage::server_auth(),
148            None,
149            None,
150        )
151        .map(|_| ())
152        .map_err(|_| ServerCertVerifierError::InvalidPath)?;
153
154        cert.verify_is_valid_for_subject_name(&server_name)
155            .map_err(|_| ServerCertVerifierError::InvalidServerName)?;
156
157        Ok(())
158    }
159}
160
161/// Error for [`ServerCertVerifier`].
162#[derive(Debug, thiserror::Error)]
163#[error("server certificate verification failed: {0}")]
164pub enum ServerCertVerifierError {
165    /// Root certificate store contains invalid certificate.
166    #[error("root certificate store contains invalid certificate: {reason}")]
167    InvalidRootCertificate {
168        /// Invalid certificate.
169        cert: CertificateDer,
170        /// Reason for invalidity.
171        reason: String,
172    },
173    /// End-entity certificate is invalid.
174    #[error("end-entity certificate is invalid: {reason}")]
175    InvalidEndEntityCertificate {
176        /// Invalid certificate.
177        cert: CertificateDer,
178        /// Reason for invalidity.
179        reason: String,
180    },
181    /// Failed to verify certificate path to provided trust anchors.
182    #[error("failed to verify certificate path to provided trust anchors")]
183    InvalidPath,
184    /// Failed to verify certificate is valid for provided server name.
185    #[error("failed to verify certificate is valid for provided server name")]
186    InvalidServerName,
187}