rustls_platform_verifier/verification/
others.rs1use super::log_server_cert;
2use once_cell::sync::OnceCell;
3use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
4use rustls::client::WebPkiServerVerifier;
5use rustls::pki_types;
6use rustls::{
7 crypto::CryptoProvider, CertificateError, DigitallySignedStruct, Error as TlsError, OtherError,
8 SignatureScheme,
9};
10use std::fmt::Debug;
11use std::sync::{Arc, Mutex};
12
13#[derive(Debug)]
15pub struct Verifier {
16 inner: OnceCell<Arc<WebPkiServerVerifier>>,
24
25 extra_roots: Mutex<Vec<pki_types::TrustAnchor<'static>>>,
28
29 #[cfg(any(test, feature = "ffi-testing", feature = "dbg"))]
31 test_only_root_ca_override: Option<Vec<u8>>,
32
33 pub(super) crypto_provider: OnceCell<Arc<CryptoProvider>>,
34}
35
36impl Verifier {
37 pub fn new() -> Self {
44 Self {
45 inner: OnceCell::new(),
46 extra_roots: Vec::new().into(),
47 #[cfg(any(test, feature = "ffi-testing", feature = "dbg"))]
48 test_only_root_ca_override: None,
49 crypto_provider: OnceCell::new(),
50 }
51 }
52
53 pub fn new_with_extra_roots(
57 roots: impl IntoIterator<Item = pki_types::CertificateDer<'static>>,
58 ) -> Result<Self, TlsError> {
59 Ok(Self {
60 inner: OnceCell::new(),
61 extra_roots: roots
62 .into_iter()
63 .flat_map(|root| {
64 webpki::anchor_from_trusted_cert(&root).map(|anchor| anchor.to_owned())
65 })
66 .collect::<Vec<_>>()
67 .into(),
68 #[cfg(any(test, feature = "ffi-testing", feature = "dbg"))]
69 test_only_root_ca_override: None,
70 crypto_provider: OnceCell::new(),
71 })
72 }
73
74 #[cfg(any(test, feature = "ffi-testing", feature = "dbg"))]
76 pub(crate) fn new_with_fake_root(root: &[u8]) -> Self {
77 Self {
78 inner: OnceCell::new(),
79 extra_roots: Vec::new().into(),
80 test_only_root_ca_override: Some(root.into()),
81 crypto_provider: OnceCell::new(),
82 }
83 }
84
85 fn get_or_init_verifier(&self) -> Result<&Arc<WebPkiServerVerifier>, TlsError> {
86 self.inner.get_or_try_init(|| self.init_verifier())
87 }
88
89 fn init_verifier(&self) -> Result<Arc<WebPkiServerVerifier>, TlsError> {
91 let mut root_store = rustls::RootCertStore::empty();
92
93 #[cfg(any(test, feature = "ffi-testing", feature = "dbg"))]
95 {
96 if let Some(test_root) = &self.test_only_root_ca_override {
97 let (added, ignored) =
98 root_store.add_parsable_certificates([pki_types::CertificateDer::from(
99 test_root.as_ref(),
100 )]);
101 if (added != 1) || (ignored != 0) {
102 panic!("Failed to insert fake, test-only root trust anchor");
103 }
104 return Ok(WebPkiServerVerifier::builder_with_provider(
105 root_store.into(),
106 Arc::clone(self.get_provider()),
107 )
108 .build()
109 .unwrap());
110 }
111 }
112
113 let mut extra_roots = self.extra_roots.try_lock().unwrap();
116 if !extra_roots.is_empty() {
117 let count = extra_roots.len();
118 root_store.extend(extra_roots.drain(..));
119 log::debug!(
120 "Loaded {count} extra CA certificates in addition to possible system roots",
121 );
122 }
123
124 #[cfg(all(
125 unix,
126 not(target_os = "android"),
127 not(target_vendor = "apple"),
128 not(target_arch = "wasm32"),
129 ))]
130 {
131 let result = rustls_native_certs::load_native_certs();
132 let (added, ignored) = root_store.add_parsable_certificates(result.certs);
133 if ignored != 0 {
134 log::warn!("Some CA root certificates were ignored due to errors");
135 }
136
137 for error in result.errors {
138 log::warn!("Error loading CA root certificate: {error}");
139 }
140
141 if root_store.is_empty() {
144 return Err(rustls::Error::General(
145 "No CA certificates were loaded from the system".to_owned(),
146 ));
147 } else {
148 log::debug!("Loaded {added} CA certificates from the system");
149 }
150 }
151
152 #[cfg(target_arch = "wasm32")]
153 {
154 root_store.add_parsable_certificates(
155 webpki_root_certs::TLS_SERVER_ROOT_CERTS.iter().cloned(),
156 );
157 };
158
159 WebPkiServerVerifier::builder_with_provider(
160 root_store.into(),
161 Arc::clone(self.get_provider()),
162 )
163 .build()
164 .map_err(|e| TlsError::Other(OtherError(Arc::new(e))))
165 }
166}
167
168impl ServerCertVerifier for Verifier {
169 fn verify_server_cert(
170 &self,
171 end_entity: &pki_types::CertificateDer<'_>,
172 intermediates: &[pki_types::CertificateDer<'_>],
173 server_name: &pki_types::ServerName,
174 ocsp_response: &[u8],
175 now: pki_types::UnixTime,
176 ) -> Result<ServerCertVerified, TlsError> {
177 log_server_cert(end_entity);
178
179 self.get_or_init_verifier()?
180 .verify_server_cert(end_entity, intermediates, server_name, ocsp_response, now)
181 .map_err(map_webpki_errors)
182 .map_err(|e| {
185 log::error!("failed to verify TLS certificate: {}", e);
186 e
187 })
188 }
189
190 fn verify_tls12_signature(
191 &self,
192 message: &[u8],
193 cert: &pki_types::CertificateDer<'_>,
194 dss: &DigitallySignedStruct,
195 ) -> Result<HandshakeSignatureValid, TlsError> {
196 self.get_or_init_verifier()?
197 .verify_tls12_signature(message, cert, dss)
198 }
199
200 fn verify_tls13_signature(
201 &self,
202 message: &[u8],
203 cert: &pki_types::CertificateDer<'_>,
204 dss: &DigitallySignedStruct,
205 ) -> Result<HandshakeSignatureValid, TlsError> {
206 self.get_or_init_verifier()?
207 .verify_tls13_signature(message, cert, dss)
208 }
209
210 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
211 self.get_provider()
216 .signature_verification_algorithms
217 .supported_schemes()
218 }
219}
220
221impl Default for Verifier {
222 fn default() -> Self {
223 Self::new()
224 }
225}
226
227fn map_webpki_errors(err: TlsError) -> TlsError {
228 if let TlsError::InvalidCertificate(CertificateError::InvalidPurpose) = &err {
229 return TlsError::InvalidCertificate(CertificateError::Other(OtherError(Arc::new(
230 super::EkuError,
231 ))));
232 }
233
234 err
235}