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::{Identity, SignatureScheme};
8use crate::enums::CertificateType;
9use crate::error::{Error, InvalidMessage};
10use crate::msgs::base::{NonEmpty, PayloadU16};
11use crate::msgs::codec::{Codec, ListLength, Reader, 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
122/// Something that can verify a client certificate chain
123pub trait ClientVerifier: Debug + Send + Sync {
124 /// Verify the client's identity.
125 ///
126 /// Note that none of the certificates have been parsed yet, so it is the responsibility of
127 /// the implementer to handle invalid data. It is recommended that the implementer returns
128 /// a [`CertificateError::BadEncoding`] error when these cases are encountered.
129 ///
130 /// [`CertificateError::BadEncoding`]: crate::error::CertificateError::BadEncoding
131 fn verify_identity(&self, identity: &ClientIdentity<'_>) -> Result<PeerVerified, Error>;
132
133 /// Verify a signature allegedly by the given client certificate.
134 ///
135 /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`.
136 /// Otherwise, return an error -- rustls will send an alert and abort the
137 /// connection.
138 ///
139 /// This method is only called for TLS1.2 handshakes. Note that, in TLS1.2,
140 /// SignatureSchemes such as `SignatureScheme::ECDSA_NISTP256_SHA256` are not
141 /// in fact bound to the specific curve implied in their name.
142 fn verify_tls12_signature(
143 &self,
144 input: &SignatureVerificationInput<'_>,
145 ) -> Result<HandshakeSignatureValid, Error>;
146
147 /// Verify a signature allegedly by the given client certificate.
148 ///
149 /// This method is only called for TLS1.3 handshakes.
150 ///
151 /// This method is very similar to `verify_tls12_signature`, but note the
152 /// tighter ECDSA SignatureScheme semantics in TLS 1.3. For example,
153 /// `SignatureScheme::ECDSA_NISTP256_SHA256`
154 /// must only validate signatures using public keys on the right curve --
155 /// rustls does not enforce this requirement for you.
156 fn verify_tls13_signature(
157 &self,
158 input: &SignatureVerificationInput<'_>,
159 ) -> Result<HandshakeSignatureValid, Error>;
160
161 /// Returns the [`DistinguishedName`] [subjects] that the server will hint to clients to
162 /// identify acceptable authentication trust anchors.
163 ///
164 /// These hint values help the client pick a client certificate it believes the server will
165 /// accept. The hints must be DER-encoded X.500 distinguished names, per [RFC 5280 A.1]. They
166 /// are sent in the [`certificate_authorities`] extension of a [`CertificateRequest`] message
167 /// when [ClientVerifier::offer_client_auth] is true. When an empty list is sent the client
168 /// should always provide a client certificate if it has one.
169 ///
170 /// Generally this list should contain the [`DistinguishedName`] of each root trust
171 /// anchor in the root cert store that the server is configured to use for authenticating
172 /// presented client certificates.
173 ///
174 /// In some circumstances this list may be customized to include [`DistinguishedName`] entries
175 /// that do not correspond to a trust anchor in the server's root cert store. For example,
176 /// the server may be configured to trust a root CA that cross-signed an issuer certificate
177 /// that the client considers a trust anchor. From the server's perspective the cross-signed
178 /// certificate is an intermediate, and not present in the server's root cert store. The client
179 /// may have the cross-signed certificate configured as a trust anchor, and be unaware of the
180 /// root CA that cross-signed it. If the server's hints list only contained the subjects of the
181 /// server's root store the client would consider a client certificate issued by the cross-signed
182 /// issuer unacceptable, since its subject was not hinted. To avoid this circumstance the server
183 /// should customize the hints list to include the subject of the cross-signed issuer in addition
184 /// to the subjects from the root cert store.
185 ///
186 /// [subjects]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6
187 /// [RFC 5280 A.1]: https://www.rfc-editor.org/rfc/rfc5280#appendix-A.1
188 /// [`CertificateRequest`]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.3.2
189 /// [`certificate_authorities`]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.4
190 fn root_hint_subjects(&self) -> Arc<[DistinguishedName]>;
191
192 /// Return `true` to require a client certificate and `false` to make
193 /// client authentication optional.
194 /// Defaults to `self.offer_client_auth()`.
195 fn client_auth_mandatory(&self) -> bool {
196 self.offer_client_auth()
197 }
198
199 /// Returns `true` to enable the server to request a client certificate and
200 /// `false` to skip requesting a client certificate. Defaults to `true`.
201 fn offer_client_auth(&self) -> bool {
202 true
203 }
204
205 /// Return the list of SignatureSchemes that this verifier will handle,
206 /// in `verify_tls12_signature` and `verify_tls13_signature` calls.
207 ///
208 /// This should be in priority order, with the most preferred first.
209 fn supported_verify_schemes(&self) -> Vec<SignatureScheme>;
210
211 /// Returns which [`CertificateType`]s this verifier supports.
212 ///
213 /// Returning an empty slice will result in an error. The default implementation signals
214 /// support for X.509 certificates. Implementations should return the same value every time.
215 ///
216 /// See [RFC 7250](https://tools.ietf.org/html/rfc7250) for more information.
217 fn supported_certificate_types(&self) -> &'static [CertificateType] {
218 &[CertificateType::X509]
219 }
220}
221
222/// Data required to verify a client's identity.
223#[non_exhaustive]
224#[derive(Debug)]
225pub struct ClientIdentity<'a> {
226 /// Identity information presented by the client.
227 pub identity: &'a Identity<'a>,
228 /// Current time against which time-sensitive inputs should be validated.
229 pub now: UnixTime,
230}
231
232/// Input for message signature verification.
233#[non_exhaustive]
234#[derive(Debug)]
235pub struct SignatureVerificationInput<'a> {
236 /// The message is not hashed, and needs hashing during verification.
237 pub message: &'a [u8],
238 /// The public key to use.
239 ///
240 /// `signer` has already been validated by the point this is called.
241 pub signer: &'a SignerPublicKey<'a>,
242 /// The signature scheme and payload.
243 pub signature: &'a DigitallySignedStruct,
244}
245
246/// Public key used to verify a signature.
247///
248/// Used as part of [`SignatureVerificationInput`].
249#[non_exhaustive]
250#[derive(Debug)]
251pub enum SignerPublicKey<'a> {
252 /// An X.509 certificate for the signing peer.
253 X509(&'a CertificateDer<'a>),
254 /// A raw public key, as defined in [RFC 7250](https://tools.ietf.org/html/rfc7250).
255 RawPublicKey(&'a SubjectPublicKeyInfoDer<'a>),
256}
257
258/// Turns off client authentication.
259///
260/// In contrast to using
261/// `WebPkiClientVerifier::builder(roots).allow_unauthenticated().build()`, the `NoClientAuth`
262/// `ClientVerifier` will not offer client authentication at all, vs offering but not
263/// requiring it.
264#[expect(clippy::exhaustive_structs)]
265#[derive(Debug)]
266pub struct NoClientAuth;
267
268impl ClientVerifier for NoClientAuth {
269 fn verify_identity(&self, _identity: &ClientIdentity<'_>) -> Result<PeerVerified, Error> {
270 unimplemented!();
271 }
272
273 fn verify_tls12_signature(
274 &self,
275 _input: &SignatureVerificationInput<'_>,
276 ) -> Result<HandshakeSignatureValid, Error> {
277 unimplemented!();
278 }
279
280 fn verify_tls13_signature(
281 &self,
282 _input: &SignatureVerificationInput<'_>,
283 ) -> Result<HandshakeSignatureValid, Error> {
284 unimplemented!();
285 }
286
287 fn root_hint_subjects(&self) -> Arc<[DistinguishedName]> {
288 unimplemented!();
289 }
290
291 fn offer_client_auth(&self) -> bool {
292 false
293 }
294
295 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
296 unimplemented!();
297 }
298}
299
300/// This type combines a [`SignatureScheme`] and a signature payload produced with that scheme.
301#[derive(Debug, Clone)]
302pub struct DigitallySignedStruct {
303 /// The [`SignatureScheme`] used to produce the signature.
304 pub scheme: SignatureScheme,
305 sig: PayloadU16,
306}
307
308impl DigitallySignedStruct {
309 pub(crate) fn new(scheme: SignatureScheme, sig: Vec<u8>) -> Self {
310 Self {
311 scheme,
312 sig: PayloadU16::new(sig),
313 }
314 }
315
316 /// Get the signature.
317 pub fn signature(&self) -> &[u8] {
318 &self.sig.0
319 }
320}
321
322impl Codec<'_> for DigitallySignedStruct {
323 fn encode(&self, bytes: &mut Vec<u8>) {
324 self.scheme.encode(bytes);
325 self.sig.encode(bytes);
326 }
327
328 fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
329 let scheme = SignatureScheme::read(r)?;
330 let sig = PayloadU16::read(r)?;
331
332 Ok(Self { scheme, sig })
333 }
334}
335
336wrapped_payload!(
337 /// A `DistinguishedName` is a `Vec<u8>` wrapped in internal types.
338 ///
339 /// It contains the DER or BER encoded [`Subject` field from RFC 5280](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6)
340 /// for a single certificate. The Subject field is [encoded as an RFC 5280 `Name`](https://datatracker.ietf.org/doc/html/rfc5280#page-116).
341 /// It can be decoded using [x509-parser's FromDer trait](https://docs.rs/x509-parser/latest/x509_parser/prelude/trait.FromDer.html).
342 ///
343 /// ```ignore
344 /// for name in distinguished_names {
345 /// use x509_parser::prelude::FromDer;
346 /// println!("{}", x509_parser::x509::X509Name::from_der(&name.0)?.1);
347 /// }
348 /// ```
349 ///
350 /// The TLS encoding is defined in RFC5246: `opaque DistinguishedName<1..2^16-1>;`
351 pub struct DistinguishedName,
352 PayloadU16<NonEmpty>,
353);
354
355impl DistinguishedName {
356 /// Create a [`DistinguishedName`] after prepending its outer SEQUENCE encoding.
357 ///
358 /// This can be decoded using [x509-parser's FromDer trait](https://docs.rs/x509-parser/latest/x509_parser/prelude/trait.FromDer.html).
359 ///
360 /// ```ignore
361 /// use x509_parser::prelude::FromDer;
362 /// println!("{}", x509_parser::x509::X509Name::from_der(dn.as_ref())?.1);
363 /// ```
364 pub fn in_sequence(bytes: &[u8]) -> Self {
365 Self(PayloadU16::new(wrap_in_sequence(bytes)))
366 }
367}
368
369impl PartialEq for DistinguishedName {
370 fn eq(&self, other: &Self) -> bool {
371 self.0.0 == other.0.0
372 }
373}
374
375/// RFC8446: `DistinguishedName authorities<3..2^16-1>;` however,
376/// RFC5246: `DistinguishedName certificate_authorities<0..2^16-1>;`
377impl TlsListElement for DistinguishedName {
378 const SIZE_LEN: ListLength = ListLength::U16;
379}
380
381/// Zero-sized marker type representing verification of a signature.
382#[derive(Debug)]
383pub struct HandshakeSignatureValid(());
384
385impl HandshakeSignatureValid {
386 /// Make a `HandshakeSignatureValid`
387 pub fn assertion() -> Self {
388 Self(())
389 }
390}
391
392#[derive(Debug)]
393pub(crate) struct FinishedMessageVerified(());
394
395impl FinishedMessageVerified {
396 pub(crate) fn assertion() -> Self {
397 Self(())
398 }
399}
400
401/// Zero-sized marker type representing verification of the peer's identity.
402#[derive(Debug)]
403pub struct PeerVerified(());
404
405impl PeerVerified {
406 /// Make a `PeerVerified`
407 pub fn assertion() -> Self {
408 Self(())
409 }
410}
411
412#[test]
413fn assertions_are_debug() {
414 use std::format;
415
416 assert_eq!(
417 format!("{:?}", PeerVerified::assertion()),
418 "PeerVerified(())"
419 );
420 assert_eq!(
421 format!("{:?}", HandshakeSignatureValid::assertion()),
422 "HandshakeSignatureValid(())"
423 );
424 assert_eq!(
425 format!("{:?}", FinishedMessageVerified::assertion()),
426 "FinishedMessageVerified(())"
427 );
428}