1
- use super :: log_server_cert;
2
- use once_cell:: sync:: OnceCell ;
1
+ use std:: fmt:: Debug ;
2
+ use std:: sync:: Arc ;
3
+
3
4
use rustls:: client:: danger:: { HandshakeSignatureValid , ServerCertVerified , ServerCertVerifier } ;
4
5
use rustls:: client:: WebPkiServerVerifier ;
6
+ use rustls:: pki_types;
5
7
use rustls:: {
6
8
crypto:: CryptoProvider , CertificateError , DigitallySignedStruct , Error as TlsError , OtherError ,
7
9
SignatureScheme ,
8
10
} ;
9
- use std :: fmt :: Debug ;
10
- use std :: sync :: { Arc , Mutex } ;
11
+
12
+ use super :: log_server_cert ;
11
13
12
14
/// A TLS certificate verifier that uses the system's root store and WebPKI.
13
15
#[ derive( Debug ) ]
@@ -19,52 +21,24 @@ pub struct Verifier {
19
21
// locking and unlocking the application will pull fresh root
20
22
// certificates from disk, picking up on any changes
21
23
// that might have been made since.
22
- inner : OnceCell < Arc < WebPkiServerVerifier > > ,
23
-
24
- // Extra trust anchors to add to the verifier above and beyond those provided by the
25
- // platform via rustls-native-certs.
26
- extra_roots : Mutex < Vec < pki_types:: TrustAnchor < ' static > > > ,
27
-
28
- /// Testing only: an additional root CA certificate to trust.
29
- #[ cfg( any( test, feature = "ffi-testing" , feature = "dbg" ) ) ]
30
- test_only_root_ca_override : Option < pki_types:: CertificateDer < ' static > > ,
31
-
32
- crypto_provider : Arc < CryptoProvider > ,
24
+ inner : Arc < WebPkiServerVerifier > ,
33
25
}
34
26
35
27
impl Verifier {
36
28
/// Creates a new verifier whose certificate validation is provided by
37
29
/// WebPKI, using root certificates provided by the platform.
38
- pub fn new ( crypto_provider : Arc < CryptoProvider > ) -> Self {
39
- Self {
40
- inner : OnceCell :: new ( ) ,
41
- extra_roots : Vec :: new ( ) . into ( ) ,
42
- #[ cfg( any( test, feature = "ffi-testing" , feature = "dbg" ) ) ]
43
- test_only_root_ca_override : None ,
44
- crypto_provider,
45
- }
30
+ pub fn new ( crypto_provider : Arc < CryptoProvider > ) -> Result < Self , TlsError > {
31
+ Self :: new_inner ( [ ] , None , crypto_provider)
46
32
}
47
33
48
34
/// Creates a new verifier whose certificate validation is provided by
49
35
/// WebPKI, using root certificates provided by the platform and augmented by
50
36
/// the provided extra root certificates.
51
37
pub fn new_with_extra_roots (
52
- roots : impl IntoIterator < Item = pki_types:: CertificateDer < ' static > > ,
38
+ extra_roots : impl IntoIterator < Item = pki_types:: CertificateDer < ' static > > ,
53
39
crypto_provider : Arc < CryptoProvider > ,
54
40
) -> Result < Self , TlsError > {
55
- Ok ( Self {
56
- inner : OnceCell :: new ( ) ,
57
- extra_roots : roots
58
- . into_iter ( )
59
- . flat_map ( |root| {
60
- webpki:: anchor_from_trusted_cert ( & root) . map ( |anchor| anchor. to_owned ( ) )
61
- } )
62
- . collect :: < Vec < _ > > ( )
63
- . into ( ) ,
64
- #[ cfg( any( test, feature = "ffi-testing" , feature = "dbg" ) ) ]
65
- test_only_root_ca_override : None ,
66
- crypto_provider,
67
- } )
41
+ Self :: new_inner ( extra_roots, None , crypto_provider)
68
42
}
69
43
70
44
/// Creates a test-only TLS certificate verifier which trusts our fake root CA cert.
@@ -73,51 +47,49 @@ impl Verifier {
73
47
root : pki_types:: CertificateDer < ' static > ,
74
48
crypto_provider : Arc < CryptoProvider > ,
75
49
) -> Self {
76
- Self {
77
- inner : OnceCell :: new ( ) ,
78
- extra_roots : Vec :: new ( ) . into ( ) ,
79
- test_only_root_ca_override : Some ( root) ,
80
- crypto_provider,
81
- }
50
+ Self :: new_inner ( [ ] , Some ( root) , crypto_provider)
51
+ . expect ( "failed to create verifier with fake root" )
82
52
}
83
53
84
- fn get_or_init_verifier ( & self ) -> Result < & Arc < WebPkiServerVerifier > , TlsError > {
85
- self . inner . get_or_try_init ( || self . init_verifier ( ) )
86
- }
87
-
88
- // Attempt to load CA root certificates present on system, fallback to WebPKI roots if error
89
- fn init_verifier ( & self ) -> Result < Arc < WebPkiServerVerifier > , TlsError > {
54
+ /// Creates a new verifier whose certificate validation is provided by
55
+ /// WebPKI, using root certificates provided by the platform and augmented by
56
+ /// the provided extra root certificates.
57
+ fn new_inner (
58
+ extra_roots : impl IntoIterator < Item = pki_types:: CertificateDer < ' static > > ,
59
+ #[ allow( unused) ] // test_root is only used in tests
60
+ test_root : Option < pki_types:: CertificateDer < ' static > > ,
61
+ crypto_provider : Arc < CryptoProvider > ,
62
+ ) -> Result < Self , TlsError > {
90
63
let mut root_store = rustls:: RootCertStore :: empty ( ) ;
91
64
92
65
// For testing only: load fake root cert, instead of native/WebPKI roots
93
66
#[ cfg( any( test, feature = "ffi-testing" , feature = "dbg" ) ) ]
94
67
{
95
- if let Some ( test_root) = & self . test_only_root_ca_override {
96
- let ( added, ignored) =
97
- root_store. add_parsable_certificates ( [ pki_types:: CertificateDer :: from (
98
- test_root. as_ref ( ) ,
99
- ) ] ) ;
100
- if ( added != 1 ) || ( ignored != 0 ) {
101
- panic ! ( "Failed to insert fake, test-only root trust anchor" ) ;
102
- }
103
- return Ok ( WebPkiServerVerifier :: builder_with_provider (
104
- root_store. into ( ) ,
105
- self . crypto_provider . clone ( ) ,
106
- )
107
- . build ( )
108
- . unwrap ( ) ) ;
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
+ } ) ;
109
78
}
110
79
}
111
80
112
- // Safety: There's no way for the mutex to be locked multiple times, so this is
113
- // an infallible operation.
114
- let mut extra_roots = self . extra_roots . try_lock ( ) . unwrap ( ) ;
115
- if !extra_roots. is_empty ( ) {
116
- let count = extra_roots. len ( ) ;
117
- root_store. extend ( extra_roots. drain ( ..) ) ;
118
- log:: debug!(
119
- "Loaded {count} extra CA certificates in addition to possible system roots" ,
120
- ) ;
81
+ let mut num_extra_roots = 0 ;
82
+ let ( added, ignored) =
83
+ root_store. add_parsable_certificates ( extra_roots. into_iter ( ) . inspect ( |_| {
84
+ num_extra_roots += 1 ;
85
+ } ) ) ;
86
+
87
+ if num_extra_roots > 0 {
88
+ if ignored > 0 {
89
+ log:: warn!( "{ignored} extra CA root certificates were ignored due to errors" ) ;
90
+ } else {
91
+ log:: debug!( "Loaded {added} CA root certificates from extra roots" ) ;
92
+ }
121
93
}
122
94
123
95
#[ cfg( all(
@@ -129,8 +101,8 @@ impl Verifier {
129
101
{
130
102
let result = rustls_native_certs:: load_native_certs ( ) ;
131
103
let ( added, ignored) = root_store. add_parsable_certificates ( result. certs ) ;
132
- if ignored != 0 {
133
- log:: warn!( "Some CA root certificates were ignored due to errors" ) ;
104
+ if ignored > 0 {
105
+ log:: warn!( "{ignored} platform CA root certificates were ignored due to errors" ) ;
134
106
}
135
107
136
108
for error in result. errors {
@@ -144,7 +116,7 @@ impl Verifier {
144
116
"No CA certificates were loaded from the system" . to_owned ( ) ,
145
117
) ) ;
146
118
} else {
147
- log:: debug!( "Loaded {added} CA certificates from the system" ) ;
119
+ log:: debug!( "Loaded {added} CA root certificates from the system" ) ;
148
120
}
149
121
}
150
122
@@ -155,9 +127,14 @@ impl Verifier {
155
127
) ;
156
128
} ;
157
129
158
- WebPkiServerVerifier :: builder_with_provider ( root_store. into ( ) , self . crypto_provider . clone ( ) )
130
+ Ok ( Self {
131
+ inner : WebPkiServerVerifier :: builder_with_provider (
132
+ root_store. into ( ) ,
133
+ crypto_provider. clone ( ) ,
134
+ )
159
135
. build ( )
160
- . map_err ( |e| TlsError :: Other ( OtherError ( Arc :: new ( e) ) ) )
136
+ . map_err ( |e| TlsError :: Other ( OtherError ( Arc :: new ( e) ) ) ) ?,
137
+ } )
161
138
}
162
139
}
163
140
@@ -172,7 +149,7 @@ impl ServerCertVerifier for Verifier {
172
149
) -> Result < ServerCertVerified , TlsError > {
173
150
log_server_cert ( end_entity) ;
174
151
175
- self . get_or_init_verifier ( ) ?
152
+ self . inner
176
153
. verify_server_cert ( end_entity, intermediates, server_name, ocsp_response, now)
177
154
. map_err ( map_webpki_errors)
178
155
// This only contains information from the system or other public
@@ -189,8 +166,7 @@ impl ServerCertVerifier for Verifier {
189
166
cert : & pki_types:: CertificateDer < ' _ > ,
190
167
dss : & DigitallySignedStruct ,
191
168
) -> Result < HandshakeSignatureValid , TlsError > {
192
- self . get_or_init_verifier ( ) ?
193
- . verify_tls12_signature ( message, cert, dss)
169
+ self . inner . verify_tls12_signature ( message, cert, dss)
194
170
}
195
171
196
172
fn verify_tls13_signature (
@@ -199,18 +175,11 @@ impl ServerCertVerifier for Verifier {
199
175
cert : & pki_types:: CertificateDer < ' _ > ,
200
176
dss : & DigitallySignedStruct ,
201
177
) -> Result < HandshakeSignatureValid , TlsError > {
202
- self . get_or_init_verifier ( ) ?
203
- . verify_tls13_signature ( message, cert, dss)
178
+ self . inner . verify_tls13_signature ( message, cert, dss)
204
179
}
205
180
206
181
fn supported_verify_schemes ( & self ) -> Vec < SignatureScheme > {
207
- // XXX: Don't go through `self.verifier` here: It introduces extra failure
208
- // cases and is strictly unneeded because `get_provider` is the same provider and
209
- // set of algorithms passed into the wrapped `WebPkiServerVerifier`. Given this,
210
- // the list of schemes are identical.
211
- self . crypto_provider
212
- . signature_verification_algorithms
213
- . supported_schemes ( )
182
+ self . inner . supported_verify_schemes ( )
214
183
}
215
184
}
216
185
0 commit comments