Skip to main content

rustls/
verify.rs

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