Skip to main content

rustls/
verify.rs

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