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}