Skip to main content

rustls/
verify.rs

1use alloc::vec::Vec;
2use core::fmt::Debug;
3use core::hash::Hasher;
4
5use pki_types::{CertificateDer, ServerName, SubjectPublicKeyInfoDer, UnixTime};
6
7use crate::crypto::cipher::Payload;
8use crate::crypto::{Identity, SignatureScheme};
9use crate::enums::CertificateType;
10use crate::error::{Error, InvalidMessage};
11use crate::msgs::{Codec, ListLength, MaybeEmpty, NonEmpty, Reader, SizedPayload, TlsListElement};
12use crate::sync::Arc;
13use crate::x509::wrap_in_sequence;
14
15// Marker types.  These are used to bind the fact some verification
16// (certificate chain or handshake signature) has taken place into
17// protocol states.  We use this to have the compiler check that there
18// are no 'goto fail'-style elisions of important checks before we
19// reach the traffic stage.
20//
21// These types are public, but cannot be directly constructed.  This
22// means their origins can be precisely determined by looking
23// for their `assertion` constructors.
24
25/// Something that can verify a server certificate chain, and verify
26/// signatures made by certificates.
27pub trait ServerVerifier: Debug + Send + Sync {
28    /// Verify the server's identity.
29    ///
30    /// Note that none of the certificates have been parsed yet, so it is the responsibility of
31    /// the implementer to handle invalid data. It is recommended that the implementer returns
32    /// [`Error::InvalidCertificate`] containing [`CertificateError::BadEncoding`] when these cases are encountered.
33    ///
34    /// [Certificate]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.4.2
35    /// [`CertificateError::BadEncoding`]: crate::error::CertificateError::BadEncoding
36    fn verify_identity(&self, identity: &ServerIdentity<'_>) -> Result<PeerVerified, Error>;
37
38    /// Verify a signature allegedly by the given server certificate.
39    ///
40    /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`.
41    /// Otherwise, return an error -- rustls will send an alert and abort the
42    /// connection.
43    ///
44    /// This method is only called for TLS1.2 handshakes.  Note that, in TLS1.2,
45    /// SignatureSchemes such as `SignatureScheme::ECDSA_NISTP256_SHA256` are not
46    /// in fact bound to the specific curve implied in their name.
47    fn verify_tls12_signature(
48        &self,
49        input: &SignatureVerificationInput<'_>,
50    ) -> Result<HandshakeSignatureValid, Error>;
51
52    /// Verify a signature allegedly by the given server certificate.
53    ///
54    /// This method is only called for TLS1.3 handshakes.
55    ///
56    /// This method is very similar to `verify_tls12_signature`: but note the
57    /// tighter ECDSA SignatureScheme semantics -- e.g. `SignatureScheme::ECDSA_NISTP256_SHA256`
58    /// must only validate signatures using public keys on the right curve --
59    /// rustls does not enforce this requirement for you.
60    ///
61    /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`.
62    /// Otherwise, return an error -- rustls will send an alert and abort the
63    /// connection.
64    fn verify_tls13_signature(
65        &self,
66        input: &SignatureVerificationInput<'_>,
67    ) -> Result<HandshakeSignatureValid, Error>;
68
69    /// Return the list of SignatureSchemes that this verifier will handle,
70    /// in `verify_tls12_signature` and `verify_tls13_signature` calls.
71    ///
72    /// This should be in priority order, with the most preferred first.
73    fn supported_verify_schemes(&self) -> Vec<SignatureScheme>;
74
75    /// Return true if this verifier will process stapled OCSP responses.
76    ///
77    /// This controls whether a client will ask the server for a stapled OCSP response.
78    /// There is no guarantee the server will provide one.
79    fn request_ocsp_response(&self) -> bool;
80
81    /// Returns which [`CertificateType`]s this verifier supports.
82    ///
83    /// Returning an empty slice will result in an error. The default implementation signals
84    /// support for X.509 certificates. Implementations should return the same value every time.
85    ///
86    /// See [RFC 7250](https://tools.ietf.org/html/rfc7250) for more information.
87    fn supported_certificate_types(&self) -> &'static [CertificateType] {
88        &[CertificateType::X509]
89    }
90
91    /// Return the [`DistinguishedName`]s of certificate authorities that this verifier trusts.
92    ///
93    /// If specified, will be sent as the [`certificate_authorities`] extension in ClientHello.
94    /// Note that this is only applicable to TLS 1.3.
95    ///
96    /// [`certificate_authorities`]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.4
97    fn root_hint_subjects(&self) -> Option<Arc<[DistinguishedName]>> {
98        None
99    }
100
101    /// Instance configuration should be input to `h`.
102    fn hash_config(&self, h: &mut dyn Hasher);
103}
104
105/// Data required to verify a server's identity.
106#[non_exhaustive]
107#[derive(Debug)]
108pub struct ServerIdentity<'a> {
109    /// Identity information presented by the server.
110    pub identity: &'a Identity<'a>,
111    /// The server name the client specified when connecting to the server.
112    pub server_name: &'a ServerName<'a>,
113    /// OCSP response stapled to the server's `Certificate` message, if any.
114    ///
115    /// Empty if no OCSP response was received, and that also
116    /// covers the case where `request_ocsp_response()` returns false.
117    pub ocsp_response: &'a [u8],
118    /// Current time against which time-sensitive inputs should be validated.
119    pub now: UnixTime,
120}
121
122impl<'a> ServerIdentity<'a> {
123    /// Create a new `ServerIdentity` instance with empty OCSP response.
124    pub fn new(identity: &'a Identity<'a>, server_name: &'a ServerName<'a>, now: UnixTime) -> Self {
125        Self {
126            identity,
127            server_name,
128            ocsp_response: &[],
129            now,
130        }
131    }
132}
133
134/// Something that can verify a client certificate chain
135pub trait ClientVerifier: Debug + Send + Sync {
136    /// Verify the client's identity.
137    ///
138    /// Note that none of the certificates have been parsed yet, so it is the responsibility of
139    /// the implementer to handle invalid data. It is recommended that the implementer returns
140    /// a [`CertificateError::BadEncoding`] error when these cases are encountered.
141    ///
142    /// [`CertificateError::BadEncoding`]: crate::error::CertificateError::BadEncoding
143    fn verify_identity(&self, identity: &ClientIdentity<'_>) -> Result<PeerVerified, Error>;
144
145    /// Verify a signature allegedly by the given client certificate.
146    ///
147    /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`.
148    /// Otherwise, return an error -- rustls will send an alert and abort the
149    /// connection.
150    ///
151    /// This method is only called for TLS1.2 handshakes.  Note that, in TLS1.2,
152    /// SignatureSchemes such as `SignatureScheme::ECDSA_NISTP256_SHA256` are not
153    /// in fact bound to the specific curve implied in their name.
154    fn verify_tls12_signature(
155        &self,
156        input: &SignatureVerificationInput<'_>,
157    ) -> Result<HandshakeSignatureValid, Error>;
158
159    /// Verify a signature allegedly by the given client certificate.
160    ///
161    /// This method is only called for TLS1.3 handshakes.
162    ///
163    /// This method is very similar to `verify_tls12_signature`, but note the
164    /// tighter ECDSA SignatureScheme semantics in TLS 1.3. For example,
165    /// `SignatureScheme::ECDSA_NISTP256_SHA256`
166    /// must only validate signatures using public keys on the right curve --
167    /// rustls does not enforce this requirement for you.
168    fn verify_tls13_signature(
169        &self,
170        input: &SignatureVerificationInput<'_>,
171    ) -> Result<HandshakeSignatureValid, Error>;
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 [ClientVerifier::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) -> Arc<[DistinguishedName]>;
203
204    /// Return `true` to require a client certificate and `false` to make
205    /// client authentication optional.
206    /// Defaults to `self.offer_client_auth()`.
207    fn client_auth_mandatory(&self) -> bool {
208        self.offer_client_auth()
209    }
210
211    /// Returns `true` to enable the server to request a client certificate and
212    /// `false` to skip requesting a client certificate. Defaults to `true`.
213    fn offer_client_auth(&self) -> bool {
214        true
215    }
216
217    /// Return the list of SignatureSchemes that this verifier will handle,
218    /// in `verify_tls12_signature` and `verify_tls13_signature` calls.
219    ///
220    /// This should be in priority order, with the most preferred first.
221    fn supported_verify_schemes(&self) -> Vec<SignatureScheme>;
222
223    /// Returns which [`CertificateType`]s this verifier supports.
224    ///
225    /// Returning an empty slice will result in an error. The default implementation signals
226    /// support for X.509 certificates. Implementations should return the same value every time.
227    ///
228    /// See [RFC 7250](https://tools.ietf.org/html/rfc7250) for more information.
229    fn supported_certificate_types(&self) -> &'static [CertificateType] {
230        &[CertificateType::X509]
231    }
232}
233
234/// Data required to verify a client's identity.
235#[non_exhaustive]
236#[derive(Debug)]
237pub struct ClientIdentity<'a> {
238    /// Identity information presented by the client.
239    pub identity: &'a Identity<'a>,
240    /// Current time against which time-sensitive inputs should be validated.
241    pub now: UnixTime,
242}
243
244/// Input for message signature verification.
245#[non_exhaustive]
246#[derive(Debug)]
247pub struct SignatureVerificationInput<'a> {
248    /// The message is not hashed, and needs hashing during verification.
249    pub message: &'a [u8],
250    /// The public key to use.
251    ///
252    /// `signer` has already been validated by the point this is called.
253    pub signer: &'a SignerPublicKey<'a>,
254    /// The signature scheme and payload.
255    pub signature: &'a DigitallySignedStruct,
256}
257
258/// Public key used to verify a signature.
259///
260/// Used as part of [`SignatureVerificationInput`].
261#[non_exhaustive]
262#[derive(Debug)]
263pub enum SignerPublicKey<'a> {
264    /// An X.509 certificate for the signing peer.
265    X509(&'a CertificateDer<'a>),
266    /// A raw public key, as defined in [RFC 7250](https://tools.ietf.org/html/rfc7250).
267    RawPublicKey(&'a SubjectPublicKeyInfoDer<'a>),
268}
269
270/// Turns off client authentication.
271///
272/// In contrast to using
273/// `WebPkiClientVerifier::builder(roots).allow_unauthenticated().build()`, the `NoClientAuth`
274/// `ClientVerifier` will not offer client authentication at all, vs offering but not
275/// requiring it.
276#[expect(clippy::exhaustive_structs)]
277#[derive(Debug)]
278pub struct NoClientAuth;
279
280impl ClientVerifier for NoClientAuth {
281    fn verify_identity(&self, _identity: &ClientIdentity<'_>) -> Result<PeerVerified, Error> {
282        unimplemented!();
283    }
284
285    fn verify_tls12_signature(
286        &self,
287        _input: &SignatureVerificationInput<'_>,
288    ) -> Result<HandshakeSignatureValid, Error> {
289        unimplemented!();
290    }
291
292    fn verify_tls13_signature(
293        &self,
294        _input: &SignatureVerificationInput<'_>,
295    ) -> Result<HandshakeSignatureValid, Error> {
296        unimplemented!();
297    }
298
299    fn root_hint_subjects(&self) -> Arc<[DistinguishedName]> {
300        unimplemented!();
301    }
302
303    fn offer_client_auth(&self) -> bool {
304        false
305    }
306
307    fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
308        unimplemented!();
309    }
310}
311
312/// This type combines a [`SignatureScheme`] and a signature payload produced with that scheme.
313#[derive(Debug, Clone)]
314pub struct DigitallySignedStruct {
315    /// The [`SignatureScheme`] used to produce the signature.
316    pub scheme: SignatureScheme,
317    sig: SizedPayload<'static, u16, MaybeEmpty>,
318}
319
320impl DigitallySignedStruct {
321    pub(crate) fn new(scheme: SignatureScheme, sig: Vec<u8>) -> Self {
322        Self {
323            scheme,
324            sig: SizedPayload::from(Payload::new(sig)),
325        }
326    }
327
328    /// Get the signature.
329    pub fn signature(&self) -> &[u8] {
330        self.sig.bytes()
331    }
332}
333
334impl Codec<'_> for DigitallySignedStruct {
335    fn encode(&self, bytes: &mut Vec<u8>) {
336        self.scheme.encode(bytes);
337        self.sig.encode(bytes);
338    }
339
340    fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
341        Ok(Self {
342            scheme: SignatureScheme::read(r)?,
343            sig: SizedPayload::read(r)?.into_owned(),
344        })
345    }
346}
347
348wrapped_payload!(
349    /// A `DistinguishedName` is a `Vec<u8>` wrapped in internal types.
350    ///
351    /// It contains the DER or BER encoded [`Subject` field from RFC 5280](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6)
352    /// for a single certificate. The Subject field is [encoded as an RFC 5280 `Name`](https://datatracker.ietf.org/doc/html/rfc5280#page-116).
353    /// It can be decoded using [x509-parser's FromDer trait](https://docs.rs/x509-parser/latest/x509_parser/prelude/trait.FromDer.html).
354    ///
355    /// ```ignore
356    /// for name in distinguished_names {
357    ///     use x509_parser::prelude::FromDer;
358    ///     println!("{}", x509_parser::x509::X509Name::from_der(&name.0)?.1);
359    /// }
360    /// ```
361    ///
362    /// The TLS encoding is defined in RFC5246: `opaque DistinguishedName<1..2^16-1>;`
363    pub struct DistinguishedName,
364    SizedPayload<u16, NonEmpty>,
365);
366
367impl DistinguishedName {
368    /// Create a [`DistinguishedName`] after prepending its outer SEQUENCE encoding.
369    ///
370    /// This can be decoded using [x509-parser's FromDer trait](https://docs.rs/x509-parser/latest/x509_parser/prelude/trait.FromDer.html).
371    ///
372    /// ```ignore
373    /// use x509_parser::prelude::FromDer;
374    /// println!("{}", x509_parser::x509::X509Name::from_der(dn.as_ref())?.1);
375    /// ```
376    pub fn in_sequence(bytes: &[u8]) -> Self {
377        Self(SizedPayload::from(Payload::new(wrap_in_sequence(bytes))))
378    }
379}
380
381impl PartialEq for DistinguishedName {
382    fn eq(&self, other: &Self) -> bool {
383        self.0.bytes() == other.0.bytes()
384    }
385}
386
387/// RFC8446: `DistinguishedName authorities<3..2^16-1>;` however,
388/// RFC5246: `DistinguishedName certificate_authorities<0..2^16-1>;`
389impl TlsListElement for DistinguishedName {
390    const SIZE_LEN: ListLength = ListLength::U16;
391}
392
393/// Zero-sized marker type representing verification of a signature.
394#[derive(Debug)]
395pub struct HandshakeSignatureValid(());
396
397impl HandshakeSignatureValid {
398    /// Make a `HandshakeSignatureValid`
399    pub fn assertion() -> Self {
400        Self(())
401    }
402}
403
404#[derive(Debug)]
405pub(crate) struct FinishedMessageVerified(());
406
407impl FinishedMessageVerified {
408    pub(crate) fn assertion() -> Self {
409        Self(())
410    }
411}
412
413/// Zero-sized marker type representing verification of the peer's identity.
414#[derive(Debug)]
415pub struct PeerVerified(());
416
417impl PeerVerified {
418    /// Make a `PeerVerified`
419    pub fn assertion() -> Self {
420        Self(())
421    }
422}
423
424#[test]
425fn assertions_are_debug() {
426    use std::format;
427
428    assert_eq!(
429        format!("{:?}", PeerVerified::assertion()),
430        "PeerVerified(())"
431    );
432    assert_eq!(
433        format!("{:?}", HandshakeSignatureValid::assertion()),
434        "HandshakeSignatureValid(())"
435    );
436    assert_eq!(
437        format!("{:?}", FinishedMessageVerified::assertion()),
438        "FinishedMessageVerified(())"
439    );
440}