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
58/// Server certificate verifier.
59#[derive(Debug)]
60pub struct ServerCertVerifier {
61    roots: Vec<webpki_types::TrustAnchor<'static>>,
62}
63
64impl ServerCertVerifier {
65    /// Creates a new server certificate verifier.
66    pub fn new(roots: &RootCertStore) -> Result<Self, ServerCertVerifierError> {
67        let roots = roots
68            .roots
69            .iter()
70            .map(|cert| {
71                webpki::anchor_from_trusted_cert(&webpki_types::CertificateDer::from(
72                    cert.0.as_slice(),
73                ))
74                .map(|anchor| anchor.to_owned())
75                .map_err(|err| ServerCertVerifierError::InvalidRootCertificate {
76                    cert: cert.clone(),
77                    reason: err.to_string(),
78                })
79            })
80            .collect::<Result<Vec<_>, _>>()?;
81
82        Ok(Self { roots })
83    }
84
85    /// Creates a new server certificate verifier with Mozilla root
86    /// certificates.
87    pub fn mozilla() -> Self {
88        Self {
89            roots: webpki_roots::TLS_SERVER_ROOTS.to_vec(),
90        }
91    }
92
93    /// Verifies the server certificate was valid at the given time of
94    /// presentation.
95    ///
96    /// # Arguments
97    ///
98    /// * `end_entity` - End-entity certificate to verify.
99    /// * `intermediates` - Intermediate certificates to a trust anchor.
100    /// * `server_name` - Server DNS name.
101    /// * `time` - Unix time the certificate was presented.
102    pub fn verify_server_cert(
103        &self,
104        end_entity: &CertificateDer,
105        intermediates: &[CertificateDer],
106        server_name: &ServerName,
107        time: u64,
108    ) -> Result<(), ServerCertVerifierError> {
109        let cert = webpki_types::CertificateDer::from(end_entity.0.as_slice());
110        let cert = webpki::EndEntityCert::try_from(&cert).map_err(|e| {
111            ServerCertVerifierError::InvalidEndEntityCertificate {
112                cert: end_entity.clone(),
113                reason: e.to_string(),
114            }
115        })?;
116        let intermediates = intermediates
117            .iter()
118            .map(|c| webpki_types::CertificateDer::from(c.0.as_slice()))
119            .collect::<Vec<_>>();
120        let server_name = server_name.to_webpki();
121        let time = webpki_types::UnixTime::since_unix_epoch(Duration::from_secs(time));
122
123        cert.verify_for_usage(
124            webpki::ALL_VERIFICATION_ALGS,
125            &self.roots,
126            &intermediates,
127            time,
128            webpki::KeyUsage::server_auth(),
129            None,
130            None,
131        )
132        .map(|_| ())
133        .map_err(|_| ServerCertVerifierError::InvalidPath)?;
134
135        cert.verify_is_valid_for_subject_name(&server_name)
136            .map_err(|_| ServerCertVerifierError::InvalidServerName)?;
137
138        Ok(())
139    }
140}
141
142/// Error for [`ServerCertVerifier`].
143#[derive(Debug, thiserror::Error)]
144#[error("server certificate verification failed: {0}")]
145pub enum ServerCertVerifierError {
146    /// Root certificate store contains invalid certificate.
147    #[error("root certificate store contains invalid certificate: {reason}")]
148    InvalidRootCertificate {
149        /// Invalid certificate.
150        cert: CertificateDer,
151        /// Reason for invalidity.
152        reason: String,
153    },
154    /// End-entity certificate is invalid.
155    #[error("end-entity certificate is invalid: {reason}")]
156    InvalidEndEntityCertificate {
157        /// Invalid certificate.
158        cert: CertificateDer,
159        /// Reason for invalidity.
160        reason: String,
161    },
162    /// Failed to verify certificate path to provided trust anchors.
163    #[error("failed to verify certificate path to provided trust anchors")]
164    InvalidPath,
165    /// Failed to verify certificate is valid for provided server name.
166    #[error("failed to verify certificate is valid for provided server name")]
167    InvalidServerName,
168}