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