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