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}