rustls/
verify.rs

1use alloc::vec::Vec;
2use core::fmt::Debug;
3
4use pki_types::{CertificateDer, ServerName, UnixTime};
5
6use crate::enums::SignatureScheme;
7use crate::error::{Error, InvalidMessage};
8use crate::msgs::base::PayloadU16;
9use crate::msgs::codec::{Codec, Reader};
10use 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)]
24pub struct HandshakeSignatureValid(());
25
26impl HandshakeSignatureValid {
27    /// Make a `HandshakeSignatureValid`
28    pub fn assertion() -> Self {
29        Self(())
30    }
31}
32
33#[derive(Debug)]
34pub(crate) struct FinishedMessageVerified(());
35
36impl FinishedMessageVerified {
37    pub(crate) fn assertion() -> Self {
38        Self(())
39    }
40}
41
42/// Zero-sized marker type representing verification of a server cert chain.
43#[allow(unreachable_pub)]
44#[derive(Debug)]
45pub struct ServerCertVerified(());
46
47#[allow(unreachable_pub)]
48impl ServerCertVerified {
49    /// Make a `ServerCertVerified`
50    pub fn assertion() -> Self {
51        Self(())
52    }
53}
54
55/// Zero-sized marker type representing verification of a client cert chain.
56#[derive(Debug)]
57pub struct ClientCertVerified(());
58
59impl ClientCertVerified {
60    /// Make a `ClientCertVerified`
61    pub fn assertion() -> Self {
62        Self(())
63    }
64}
65
66/// Something that can verify a server certificate chain, and verify
67/// signatures made by certificates.
68#[allow(unreachable_pub)]
69pub 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    fn requires_raw_public_keys(&self) -> bool {
144        false
145    }
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    fn root_hint_subjects(&self) -> Option<&[DistinguishedName]> {
154        None
155    }
156}
157
158/// Something that can verify a client certificate chain
159#[allow(unreachable_pub)]
160pub 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    fn offer_client_auth(&self) -> bool {
164        true
165    }
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    fn client_auth_mandatory(&self) -> bool {
171        self.offer_client_auth()
172    }
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    fn requires_raw_public_keys(&self) -> bool {
273        false
274    }
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)]
284pub struct NoClientAuth;
285
286impl ClientCertVerifier for NoClientAuth {
287    fn offer_client_auth(&self) -> bool {
288        false
289    }
290
291    fn root_hint_subjects(&self) -> &[DistinguishedName] {
292        unimplemented!();
293    }
294
295    fn verify_client_cert(
296        &self,
297        _end_entity: &CertificateDer<'_>,
298        _intermediates: &[CertificateDer<'_>],
299        _now: UnixTime,
300    ) -> Result<ClientCertVerified, Error> {
301        unimplemented!();
302    }
303
304    fn verify_tls12_signature(
305        &self,
306        _message: &[u8],
307        _cert: &CertificateDer<'_>,
308        _dss: &DigitallySignedStruct,
309    ) -> Result<HandshakeSignatureValid, Error> {
310        unimplemented!();
311    }
312
313    fn verify_tls13_signature(
314        &self,
315        _message: &[u8],
316        _cert: &CertificateDer<'_>,
317        _dss: &DigitallySignedStruct,
318    ) -> Result<HandshakeSignatureValid, Error> {
319        unimplemented!();
320    }
321
322    fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
323        unimplemented!();
324    }
325}
326
327/// This type combines a [`SignatureScheme`] and a signature payload produced with that scheme.
328#[derive(Debug, Clone)]
329pub struct DigitallySignedStruct {
330    /// The [`SignatureScheme`] used to produce the signature.
331    pub scheme: SignatureScheme,
332    sig: PayloadU16,
333}
334
335impl DigitallySignedStruct {
336    pub(crate) fn new(scheme: SignatureScheme, sig: Vec<u8>) -> Self {
337        Self {
338            scheme,
339            sig: PayloadU16::new(sig),
340        }
341    }
342
343    /// Get the signature.
344    pub fn signature(&self) -> &[u8] {
345        &self.sig.0
346    }
347}
348
349impl Codec<'_> for DigitallySignedStruct {
350    fn encode(&self, bytes: &mut Vec<u8>) {
351        self.scheme.encode(bytes);
352        self.sig.encode(bytes);
353    }
354
355    fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
356        let scheme = SignatureScheme::read(r)?;
357        let sig = PayloadU16::read(r)?;
358
359        Ok(Self { scheme, sig })
360    }
361}
362
363#[test]
364fn 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}