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