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