/rust/registry/src/index.crates.io-6f17d22bba15001f/rustls-0.23.22/src/verify.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use alloc::vec::Vec; |
2 | | use core::fmt::Debug; |
3 | | |
4 | | use pki_types::{CertificateDer, ServerName, UnixTime}; |
5 | | |
6 | | use crate::enums::SignatureScheme; |
7 | | use crate::error::{Error, InvalidMessage}; |
8 | | use crate::msgs::base::PayloadU16; |
9 | | use crate::msgs::codec::{Codec, Reader}; |
10 | | use crate::msgs::handshake::DistinguishedName; |
11 | | |
12 | | // Marker types. These are used to bind the fact some verification |
13 | | // (certificate chain or handshake signature) has taken place into |
14 | | // protocol states. We use this to have the compiler check that there |
15 | | // are no 'goto fail'-style elisions of important checks before we |
16 | | // reach the traffic stage. |
17 | | // |
18 | | // These types are public, but cannot be directly constructed. This |
19 | | // means their origins can be precisely determined by looking |
20 | | // for their `assertion` constructors. |
21 | | |
22 | | /// Zero-sized marker type representing verification of a signature. |
23 | | #[derive(Debug)] |
24 | | pub struct HandshakeSignatureValid(()); |
25 | | |
26 | | impl HandshakeSignatureValid { |
27 | | /// Make a `HandshakeSignatureValid` |
28 | 0 | pub fn assertion() -> Self { |
29 | 0 | Self(()) |
30 | 0 | } |
31 | | } |
32 | | |
33 | | #[derive(Debug)] |
34 | | pub(crate) struct FinishedMessageVerified(()); |
35 | | |
36 | | impl FinishedMessageVerified { |
37 | 0 | pub(crate) fn assertion() -> Self { |
38 | 0 | Self(()) |
39 | 0 | } |
40 | | } |
41 | | |
42 | | /// Zero-sized marker type representing verification of a server cert chain. |
43 | | #[allow(unreachable_pub)] |
44 | | #[derive(Debug)] |
45 | | pub struct ServerCertVerified(()); |
46 | | |
47 | | #[allow(unreachable_pub)] |
48 | | impl ServerCertVerified { |
49 | | /// Make a `ServerCertVerified` |
50 | 0 | pub fn assertion() -> Self { |
51 | 0 | Self(()) |
52 | 0 | } |
53 | | } |
54 | | |
55 | | /// Zero-sized marker type representing verification of a client cert chain. |
56 | | #[derive(Debug)] |
57 | | pub struct ClientCertVerified(()); |
58 | | |
59 | | impl ClientCertVerified { |
60 | | /// Make a `ClientCertVerified` |
61 | 0 | pub fn assertion() -> Self { |
62 | 0 | Self(()) |
63 | 0 | } |
64 | | } |
65 | | |
66 | | /// Something that can verify a server certificate chain, and verify |
67 | | /// signatures made by certificates. |
68 | | #[allow(unreachable_pub)] |
69 | | pub trait ServerCertVerifier: Debug + Send + Sync { |
70 | | /// Verify the end-entity certificate `end_entity` is valid for the |
71 | | /// hostname `dns_name` and chains to at least one trust anchor. |
72 | | /// |
73 | | /// `intermediates` contains all certificates other than `end_entity` that |
74 | | /// were sent as part of the server's [Certificate] message. It is in the |
75 | | /// same order that the server sent them and may be empty. |
76 | | /// |
77 | | /// Note that none of the certificates have been parsed yet, so it is the responsibility of |
78 | | /// the implementer to handle invalid data. It is recommended that the implementer returns |
79 | | /// [`Error::InvalidCertificate(CertificateError::BadEncoding)`] when these cases are encountered. |
80 | | /// |
81 | | /// [Certificate]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.4.2 |
82 | | fn verify_server_cert( |
83 | | &self, |
84 | | end_entity: &CertificateDer<'_>, |
85 | | intermediates: &[CertificateDer<'_>], |
86 | | server_name: &ServerName<'_>, |
87 | | ocsp_response: &[u8], |
88 | | now: UnixTime, |
89 | | ) -> Result<ServerCertVerified, Error>; |
90 | | |
91 | | /// Verify a signature allegedly by the given server certificate. |
92 | | /// |
93 | | /// `message` is not hashed, and needs hashing during the verification. |
94 | | /// The signature and algorithm are within `dss`. `cert` contains the |
95 | | /// public key to use. |
96 | | /// |
97 | | /// `cert` has already been validated by [`ServerCertVerifier::verify_server_cert`]. |
98 | | /// |
99 | | /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`. |
100 | | /// Otherwise, return an error -- rustls will send an alert and abort the |
101 | | /// connection. |
102 | | /// |
103 | | /// This method is only called for TLS1.2 handshakes. Note that, in TLS1.2, |
104 | | /// SignatureSchemes such as `SignatureScheme::ECDSA_NISTP256_SHA256` are not |
105 | | /// in fact bound to the specific curve implied in their name. |
106 | | fn verify_tls12_signature( |
107 | | &self, |
108 | | message: &[u8], |
109 | | cert: &CertificateDer<'_>, |
110 | | dss: &DigitallySignedStruct, |
111 | | ) -> Result<HandshakeSignatureValid, Error>; |
112 | | |
113 | | /// Verify a signature allegedly by the given server certificate. |
114 | | /// |
115 | | /// This method is only called for TLS1.3 handshakes. |
116 | | /// |
117 | | /// This method is very similar to `verify_tls12_signature`: but note the |
118 | | /// tighter ECDSA SignatureScheme semantics -- e.g. `SignatureScheme::ECDSA_NISTP256_SHA256` |
119 | | /// must only validate signatures using public keys on the right curve -- |
120 | | /// rustls does not enforce this requirement for you. |
121 | | /// |
122 | | /// `cert` has already been validated by [`ServerCertVerifier::verify_server_cert`]. |
123 | | /// |
124 | | /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`. |
125 | | /// Otherwise, return an error -- rustls will send an alert and abort the |
126 | | /// connection. |
127 | | fn verify_tls13_signature( |
128 | | &self, |
129 | | message: &[u8], |
130 | | cert: &CertificateDer<'_>, |
131 | | dss: &DigitallySignedStruct, |
132 | | ) -> Result<HandshakeSignatureValid, Error>; |
133 | | |
134 | | /// Return the list of SignatureSchemes that this verifier will handle, |
135 | | /// in `verify_tls12_signature` and `verify_tls13_signature` calls. |
136 | | /// |
137 | | /// This should be in priority order, with the most preferred first. |
138 | | fn supported_verify_schemes(&self) -> Vec<SignatureScheme>; |
139 | | |
140 | | /// Returns whether this verifier requires raw public keys as defined |
141 | | /// in [RFC 7250](https://tools.ietf.org/html/rfc7250). |
142 | 0 | fn requires_raw_public_keys(&self) -> bool { |
143 | 0 | false |
144 | 0 | } Unexecuted instantiation: <ztunnel::tls::workload::IdentityVerifier as rustls::verify::ServerCertVerifier>::requires_raw_public_keys Unexecuted instantiation: <ztunnel::tls::control::AltHostnameVerifier as rustls::verify::ServerCertVerifier>::requires_raw_public_keys Unexecuted instantiation: <rustls::webpki::server_verifier::WebPkiServerVerifier as rustls::verify::ServerCertVerifier>::requires_raw_public_keys |
145 | | |
146 | | /// Return the [`DistinguishedName`]s of certificate authorities that this verifier trusts. |
147 | | /// |
148 | | /// If specified, will be sent as the [`certificate_authorities`] extension in ClientHello. |
149 | | /// Note that this is only applicable to TLS 1.3. |
150 | | /// |
151 | | /// [`certificate_authorities`]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.4 |
152 | 0 | fn root_hint_subjects(&self) -> Option<&[DistinguishedName]> { |
153 | 0 | None |
154 | 0 | } Unexecuted instantiation: <ztunnel::tls::workload::IdentityVerifier as rustls::verify::ServerCertVerifier>::root_hint_subjects Unexecuted instantiation: <ztunnel::tls::control::AltHostnameVerifier as rustls::verify::ServerCertVerifier>::root_hint_subjects Unexecuted instantiation: <rustls::webpki::server_verifier::WebPkiServerVerifier as rustls::verify::ServerCertVerifier>::root_hint_subjects |
155 | | } |
156 | | |
157 | | /// Something that can verify a client certificate chain |
158 | | #[allow(unreachable_pub)] |
159 | | pub trait ClientCertVerifier: Debug + Send + Sync { |
160 | | /// Returns `true` to enable the server to request a client certificate and |
161 | | /// `false` to skip requesting a client certificate. Defaults to `true`. |
162 | 0 | fn offer_client_auth(&self) -> bool { |
163 | 0 | true |
164 | 0 | } Unexecuted instantiation: <ztunnel::tls::workload::TrustDomainVerifier as rustls::verify::ClientCertVerifier>::offer_client_auth Unexecuted instantiation: <_ as rustls::verify::ClientCertVerifier>::offer_client_auth |
165 | | |
166 | | /// Return `true` to require a client certificate and `false` to make |
167 | | /// client authentication optional. |
168 | | /// Defaults to `self.offer_client_auth()`. |
169 | 0 | fn client_auth_mandatory(&self) -> bool { |
170 | 0 | self.offer_client_auth() |
171 | 0 | } Unexecuted instantiation: <ztunnel::tls::workload::TrustDomainVerifier as rustls::verify::ClientCertVerifier>::client_auth_mandatory Unexecuted instantiation: <rustls::verify::NoClientAuth as rustls::verify::ClientCertVerifier>::client_auth_mandatory |
172 | | |
173 | | /// Returns the [`DistinguishedName`] [subjects] that the server will hint to clients to |
174 | | /// identify acceptable authentication trust anchors. |
175 | | /// |
176 | | /// These hint values help the client pick a client certificate it believes the server will |
177 | | /// accept. The hints must be DER-encoded X.500 distinguished names, per [RFC 5280 A.1]. They |
178 | | /// are sent in the [`certificate_authorities`] extension of a [`CertificateRequest`] message |
179 | | /// when [ClientCertVerifier::offer_client_auth] is true. When an empty list is sent the client |
180 | | /// should always provide a client certificate if it has one. |
181 | | /// |
182 | | /// Generally this list should contain the [`DistinguishedName`] of each root trust |
183 | | /// anchor in the root cert store that the server is configured to use for authenticating |
184 | | /// presented client certificates. |
185 | | /// |
186 | | /// In some circumstances this list may be customized to include [`DistinguishedName`] entries |
187 | | /// that do not correspond to a trust anchor in the server's root cert store. For example, |
188 | | /// the server may be configured to trust a root CA that cross-signed an issuer certificate |
189 | | /// that the client considers a trust anchor. From the server's perspective the cross-signed |
190 | | /// certificate is an intermediate, and not present in the server's root cert store. The client |
191 | | /// may have the cross-signed certificate configured as a trust anchor, and be unaware of the |
192 | | /// root CA that cross-signed it. If the server's hints list only contained the subjects of the |
193 | | /// server's root store the client would consider a client certificate issued by the cross-signed |
194 | | /// issuer unacceptable, since its subject was not hinted. To avoid this circumstance the server |
195 | | /// should customize the hints list to include the subject of the cross-signed issuer in addition |
196 | | /// to the subjects from the root cert store. |
197 | | /// |
198 | | /// [subjects]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 |
199 | | /// [RFC 5280 A.1]: https://www.rfc-editor.org/rfc/rfc5280#appendix-A.1 |
200 | | /// [`CertificateRequest`]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.3.2 |
201 | | /// [`certificate_authorities`]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.4 |
202 | | fn root_hint_subjects(&self) -> &[DistinguishedName]; |
203 | | |
204 | | /// Verify the end-entity certificate `end_entity` is valid, acceptable, |
205 | | /// and chains to at least one of the trust anchors trusted by |
206 | | /// this verifier. |
207 | | /// |
208 | | /// `intermediates` contains the intermediate certificates the |
209 | | /// client sent along with the end-entity certificate; it is in the same |
210 | | /// order that the peer sent them and may be empty. |
211 | | /// |
212 | | /// Note that none of the certificates have been parsed yet, so it is the responsibility of |
213 | | /// the implementer to handle invalid data. It is recommended that the implementer returns |
214 | | /// an [InvalidCertificate] error with the [BadEncoding] variant when these cases are encountered. |
215 | | /// |
216 | | /// [InvalidCertificate]: Error#variant.InvalidCertificate |
217 | | /// [BadEncoding]: crate::CertificateError#variant.BadEncoding |
218 | | fn verify_client_cert( |
219 | | &self, |
220 | | end_entity: &CertificateDer<'_>, |
221 | | intermediates: &[CertificateDer<'_>], |
222 | | now: UnixTime, |
223 | | ) -> Result<ClientCertVerified, Error>; |
224 | | |
225 | | /// Verify a signature allegedly by the given client certificate. |
226 | | /// |
227 | | /// `message` is not hashed, and needs hashing during the verification. |
228 | | /// The signature and algorithm are within `dss`. `cert` contains the |
229 | | /// public key to use. |
230 | | /// |
231 | | /// `cert` has already been validated by [`ClientCertVerifier::verify_client_cert`]. |
232 | | /// |
233 | | /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`. |
234 | | /// Otherwise, return an error -- rustls will send an alert and abort the |
235 | | /// connection. |
236 | | /// |
237 | | /// This method is only called for TLS1.2 handshakes. Note that, in TLS1.2, |
238 | | /// SignatureSchemes such as `SignatureScheme::ECDSA_NISTP256_SHA256` are not |
239 | | /// in fact bound to the specific curve implied in their name. |
240 | | fn verify_tls12_signature( |
241 | | &self, |
242 | | message: &[u8], |
243 | | cert: &CertificateDer<'_>, |
244 | | dss: &DigitallySignedStruct, |
245 | | ) -> Result<HandshakeSignatureValid, Error>; |
246 | | |
247 | | /// Verify a signature allegedly by the given client certificate. |
248 | | /// |
249 | | /// This method is only called for TLS1.3 handshakes. |
250 | | /// |
251 | | /// This method is very similar to `verify_tls12_signature`, but note the |
252 | | /// tighter ECDSA SignatureScheme semantics in TLS 1.3. For example, |
253 | | /// `SignatureScheme::ECDSA_NISTP256_SHA256` |
254 | | /// must only validate signatures using public keys on the right curve -- |
255 | | /// rustls does not enforce this requirement for you. |
256 | | fn verify_tls13_signature( |
257 | | &self, |
258 | | message: &[u8], |
259 | | cert: &CertificateDer<'_>, |
260 | | dss: &DigitallySignedStruct, |
261 | | ) -> Result<HandshakeSignatureValid, Error>; |
262 | | |
263 | | /// Return the list of SignatureSchemes that this verifier will handle, |
264 | | /// in `verify_tls12_signature` and `verify_tls13_signature` calls. |
265 | | /// |
266 | | /// This should be in priority order, with the most preferred first. |
267 | | fn supported_verify_schemes(&self) -> Vec<SignatureScheme>; |
268 | | |
269 | | /// Returns whether this verifier requires raw public keys as defined |
270 | | /// in [RFC 7250](https://tools.ietf.org/html/rfc7250). |
271 | 0 | fn requires_raw_public_keys(&self) -> bool { |
272 | 0 | false |
273 | 0 | } Unexecuted instantiation: <ztunnel::tls::workload::TrustDomainVerifier as rustls::verify::ClientCertVerifier>::requires_raw_public_keys Unexecuted instantiation: <rustls::webpki::client_verifier::WebPkiClientVerifier as rustls::verify::ClientCertVerifier>::requires_raw_public_keys Unexecuted instantiation: <rustls::verify::NoClientAuth as rustls::verify::ClientCertVerifier>::requires_raw_public_keys |
274 | | } |
275 | | |
276 | | /// Turns off client authentication. |
277 | | /// |
278 | | /// In contrast to using |
279 | | /// `WebPkiClientVerifier::builder(roots).allow_unauthenticated().build()`, the `NoClientAuth` |
280 | | /// `ClientCertVerifier` will not offer client authentication at all, vs offering but not |
281 | | /// requiring it. |
282 | | #[derive(Debug)] |
283 | | pub struct NoClientAuth; |
284 | | |
285 | | impl ClientCertVerifier for NoClientAuth { |
286 | 0 | fn offer_client_auth(&self) -> bool { |
287 | 0 | false |
288 | 0 | } |
289 | | |
290 | 0 | fn root_hint_subjects(&self) -> &[DistinguishedName] { |
291 | 0 | unimplemented!(); |
292 | | } |
293 | | |
294 | 0 | fn verify_client_cert( |
295 | 0 | &self, |
296 | 0 | _end_entity: &CertificateDer<'_>, |
297 | 0 | _intermediates: &[CertificateDer<'_>], |
298 | 0 | _now: UnixTime, |
299 | 0 | ) -> Result<ClientCertVerified, Error> { |
300 | 0 | unimplemented!(); |
301 | | } |
302 | | |
303 | 0 | fn verify_tls12_signature( |
304 | 0 | &self, |
305 | 0 | _message: &[u8], |
306 | 0 | _cert: &CertificateDer<'_>, |
307 | 0 | _dss: &DigitallySignedStruct, |
308 | 0 | ) -> Result<HandshakeSignatureValid, Error> { |
309 | 0 | unimplemented!(); |
310 | | } |
311 | | |
312 | 0 | fn verify_tls13_signature( |
313 | 0 | &self, |
314 | 0 | _message: &[u8], |
315 | 0 | _cert: &CertificateDer<'_>, |
316 | 0 | _dss: &DigitallySignedStruct, |
317 | 0 | ) -> Result<HandshakeSignatureValid, Error> { |
318 | 0 | unimplemented!(); |
319 | | } |
320 | | |
321 | 0 | fn supported_verify_schemes(&self) -> Vec<SignatureScheme> { |
322 | 0 | unimplemented!(); |
323 | | } |
324 | | } |
325 | | |
326 | | /// This type combines a [`SignatureScheme`] and a signature payload produced with that scheme. |
327 | | #[derive(Debug, Clone)] |
328 | | pub struct DigitallySignedStruct { |
329 | | /// The [`SignatureScheme`] used to produce the signature. |
330 | | pub scheme: SignatureScheme, |
331 | | sig: PayloadU16, |
332 | | } |
333 | | |
334 | | impl DigitallySignedStruct { |
335 | 0 | pub(crate) fn new(scheme: SignatureScheme, sig: Vec<u8>) -> Self { |
336 | 0 | Self { |
337 | 0 | scheme, |
338 | 0 | sig: PayloadU16::new(sig), |
339 | 0 | } |
340 | 0 | } |
341 | | |
342 | | /// Get the signature. |
343 | 0 | pub fn signature(&self) -> &[u8] { |
344 | 0 | &self.sig.0 |
345 | 0 | } |
346 | | } |
347 | | |
348 | | impl Codec<'_> for DigitallySignedStruct { |
349 | 0 | fn encode(&self, bytes: &mut Vec<u8>) { |
350 | 0 | self.scheme.encode(bytes); |
351 | 0 | self.sig.encode(bytes); |
352 | 0 | } |
353 | | |
354 | 0 | fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> { |
355 | 0 | let scheme = SignatureScheme::read(r)?; |
356 | 0 | let sig = PayloadU16::read(r)?; |
357 | | |
358 | 0 | Ok(Self { scheme, sig }) |
359 | 0 | } |
360 | | } |
361 | | |
362 | | #[test] |
363 | | fn assertions_are_debug() { |
364 | | use std::format; |
365 | | |
366 | | assert_eq!( |
367 | | format!("{:?}", ClientCertVerified::assertion()), |
368 | | "ClientCertVerified(())" |
369 | | ); |
370 | | assert_eq!( |
371 | | format!("{:?}", HandshakeSignatureValid::assertion()), |
372 | | "HandshakeSignatureValid(())" |
373 | | ); |
374 | | assert_eq!( |
375 | | format!("{:?}", FinishedMessageVerified::assertion()), |
376 | | "FinishedMessageVerified(())" |
377 | | ); |
378 | | assert_eq!( |
379 | | format!("{:?}", ServerCertVerified::assertion()), |
380 | | "ServerCertVerified(())" |
381 | | ); |
382 | | } |