Coverage Report

Created: 2025-02-25 06:39

/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
}