rustls_platform_verifier/verification/
others.rs1use std::fmt::Debug;
2use std::sync::Arc;
3
4use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
5use rustls::client::WebPkiServerVerifier;
6use rustls::pki_types;
7use rustls::{
8 crypto::CryptoProvider, CertificateError, DigitallySignedStruct, Error as TlsError, OtherError,
9 SignatureScheme,
10};
11
12use super::log_server_cert;
13
14#[derive(Debug)]
16pub struct Verifier {
17 inner: Arc<WebPkiServerVerifier>,
25}
26
27impl Verifier {
28 pub fn new(crypto_provider: Arc<CryptoProvider>) -> Result<Self, TlsError> {
31 Self::new_inner([], None, crypto_provider)
32 }
33
34 pub fn new_with_extra_roots(
38 extra_roots: impl IntoIterator<Item = pki_types::CertificateDer<'static>>,
39 crypto_provider: Arc<CryptoProvider>,
40 ) -> Result<Self, TlsError> {
41 Self::new_inner(extra_roots, None, crypto_provider)
42 }
43
44 #[cfg(any(test, feature = "ffi-testing", feature = "dbg"))]
46 pub(crate) fn new_with_fake_root(
47 root: pki_types::CertificateDer<'static>,
48 crypto_provider: Arc<CryptoProvider>,
49 ) -> Self {
50 Self::new_inner([], Some(root), crypto_provider)
51 .expect("failed to create verifier with fake root")
52 }
53
54 fn new_inner(
58 extra_roots: impl IntoIterator<Item = pki_types::CertificateDer<'static>>,
59 #[allow(unused)] test_root: Option<pki_types::CertificateDer<'static>>,
61 crypto_provider: Arc<CryptoProvider>,
62 ) -> Result<Self, TlsError> {
63 let mut root_store = rustls::RootCertStore::empty();
64
65 #[cfg(any(test, feature = "ffi-testing", feature = "dbg"))]
67 {
68 if let Some(test_root) = test_root {
69 root_store.add(test_root)?;
70 return Ok(Self {
71 inner: WebPkiServerVerifier::builder_with_provider(
72 root_store.into(),
73 crypto_provider.clone(),
74 )
75 .build()
76 .map_err(|e| TlsError::Other(OtherError(Arc::new(e))))?,
77 });
78 }
79 }
80
81 for cert in extra_roots {
84 root_store.add(cert)?;
85 }
86
87 #[cfg(all(
88 unix,
89 not(target_os = "android"),
90 not(target_vendor = "apple"),
91 not(target_arch = "wasm32"),
92 ))]
93 {
94 let result = rustls_native_certs::load_native_certs();
95 let (added, ignored) = root_store.add_parsable_certificates(result.certs);
96 if ignored > 0 {
97 log::warn!("{ignored} platform CA root certificates were ignored due to errors");
98 }
99
100 for error in result.errors {
101 log::warn!("Error loading CA root certificate: {error}");
102 }
103
104 if root_store.is_empty() {
107 return Err(rustls::Error::General(
108 "No CA certificates were loaded from the system".to_owned(),
109 ));
110 } else {
111 log::debug!("Loaded {added} CA root certificates from the system");
112 }
113 }
114
115 #[cfg(target_arch = "wasm32")]
116 {
117 root_store.add_parsable_certificates(
118 webpki_root_certs::TLS_SERVER_ROOT_CERTS.iter().cloned(),
119 );
120 };
121
122 Ok(Self {
123 inner: WebPkiServerVerifier::builder_with_provider(
124 root_store.into(),
125 crypto_provider.clone(),
126 )
127 .build()
128 .map_err(|e| TlsError::Other(OtherError(Arc::new(e))))?,
129 })
130 }
131}
132
133impl ServerCertVerifier for Verifier {
134 fn verify_server_cert(
135 &self,
136 end_entity: &pki_types::CertificateDer<'_>,
137 intermediates: &[pki_types::CertificateDer<'_>],
138 server_name: &pki_types::ServerName,
139 ocsp_response: &[u8],
140 now: pki_types::UnixTime,
141 ) -> Result<ServerCertVerified, TlsError> {
142 log_server_cert(end_entity);
143
144 self.inner
145 .verify_server_cert(end_entity, intermediates, server_name, ocsp_response, now)
146 .map_err(map_webpki_errors)
147 .map_err(|e| {
150 log::error!("failed to verify TLS certificate: {}", e);
151 e
152 })
153 }
154
155 fn verify_tls12_signature(
156 &self,
157 message: &[u8],
158 cert: &pki_types::CertificateDer<'_>,
159 dss: &DigitallySignedStruct,
160 ) -> Result<HandshakeSignatureValid, TlsError> {
161 self.inner.verify_tls12_signature(message, cert, dss)
162 }
163
164 fn verify_tls13_signature(
165 &self,
166 message: &[u8],
167 cert: &pki_types::CertificateDer<'_>,
168 dss: &DigitallySignedStruct,
169 ) -> Result<HandshakeSignatureValid, TlsError> {
170 self.inner.verify_tls13_signature(message, cert, dss)
171 }
172
173 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
174 self.inner.supported_verify_schemes()
175 }
176}
177
178fn map_webpki_errors(err: TlsError) -> TlsError {
179 match &err {
180 TlsError::InvalidCertificate(CertificateError::InvalidPurpose)
181 | TlsError::InvalidCertificate(CertificateError::InvalidPurposeContext { .. }) => {
182 TlsError::InvalidCertificate(CertificateError::Other(OtherError(Arc::new(
183 super::EkuError,
184 ))))
185 }
186 _ => err,
187 }
188}