1use 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#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct CertificateDer(pub Vec<u8>);
13
14impl CertificateDer {
15 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#[derive(Debug, Clone, zeroize::ZeroizeOnDrop, Serialize, Deserialize)]
25pub struct PrivateKeyDer(pub Vec<u8>);
26
27impl PrivateKeyDer {
28 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#[derive(Debug, thiserror::Error)]
38#[error("failed to parse PEM object")]
39pub struct PemError {}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct RootCertStore {
47 pub roots: Vec<CertificateDer>,
49}
50
51impl RootCertStore {
52 pub fn empty() -> Self {
54 Self { roots: Vec::new() }
55 }
56
57 #[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#[derive(Debug)]
75pub struct ServerCertVerifier {
76 roots: Vec<webpki_types::TrustAnchor<'static>>,
77}
78
79impl ServerCertVerifier {
80 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 #[cfg(feature = "mozilla-certs")]
106 pub fn mozilla() -> Self {
107 Self {
108 roots: webpki_roots::TLS_SERVER_ROOTS.to_vec(),
109 }
110 }
111
112 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#[derive(Debug, thiserror::Error)]
163#[error("server certificate verification failed: {0}")]
164pub enum ServerCertVerifierError {
165 #[error("root certificate store contains invalid certificate: {reason}")]
167 InvalidRootCertificate {
168 cert: CertificateDer,
170 reason: String,
172 },
173 #[error("end-entity certificate is invalid: {reason}")]
175 InvalidEndEntityCertificate {
176 cert: CertificateDer,
178 reason: String,
180 },
181 #[error("failed to verify certificate path to provided trust anchors")]
183 InvalidPath,
184 #[error("failed to verify certificate is valid for provided server name")]
186 InvalidServerName,
187}