Coverage Report

Created: 2026-09-14 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}