rustls/verify.rs
1use alloc::vec::Vec;
2use core::fmt::Debug;
3
4use pki_types::{CertificateDer, ServerName, UnixTime};
5
6use crate::enums::SignatureScheme;
7use crate::error::{Error, InvalidMessage};
8use crate::msgs::base::PayloadU16;
9use crate::msgs::codec::{Codec, Reader};
10use crate::msgs::handshake::DistinguishedName;
11use crate::sync::Arc;
12
13// Marker types. These are used to bind the fact some verification
14// (certificate chain or handshake signature) has taken place into
15// protocol states. We use this to have the compiler check that there
16// are no 'goto fail'-style elisions of important checks before we
17// reach the traffic stage.
18//
19// These types are public, but cannot be directly constructed. This
20// means their origins can be precisely determined by looking
21// for their `assertion` constructors.
22
23/// Zero-sized marker type representing verification of a signature.
24#[derive(Debug)]
25pub struct HandshakeSignatureValid(());
26
27impl HandshakeSignatureValid {
28 /// Make a `HandshakeSignatureValid`
29 pub fn assertion() -> Self {
30 Self(())
31 }
32}
33
34#[derive(Debug)]
35pub(crate) struct FinishedMessageVerified(());
36
37impl FinishedMessageVerified {
38 pub(crate) fn assertion() -> Self {
39 Self(())
40 }
41}
42
43/// Zero-sized marker type representing verification of a server cert chain.
44#[allow(unreachable_pub)]
45#[derive(Debug)]
46pub struct ServerCertVerified(());
47
48#[allow(unreachable_pub)]
49impl ServerCertVerified {
50 /// Make a `ServerCertVerified`
51 pub fn assertion() -> Self {
52 Self(())
53 }
54}
55
56/// Zero-sized marker type representing verification of a client cert chain.
57#[derive(Debug)]
58pub struct ClientCertVerified(());
59
60impl ClientCertVerified {
61 /// Make a `ClientCertVerified`
62 pub fn assertion() -> Self {
63 Self(())
64 }
65}
66
67/// Something that can verify a server certificate chain, and verify
68/// signatures made by certificates.
69#[allow(unreachable_pub)]
70pub trait ServerCertVerifier: Debug + Send + Sync {
71 /// Verify the end-entity certificate `end_entity` is valid for the
72 /// hostname `dns_name` and chains to at least one trust anchor.
73 ///
74 /// `intermediates` contains all certificates other than `end_entity` that
75 /// were sent as part of the server's [Certificate] message. It is in the
76 /// same order that the server sent them and may be empty.
77 ///
78 /// `ocsp_response` is empty if no OCSP response was received, and that also
79 /// covers the case where `request_ocsp_response()` returns false.
80 ///
81 /// Note that none of the certificates have been parsed yet, so it is the responsibility of
82 /// the implementer to handle invalid data. It is recommended that the implementer returns
83 /// [`Error::InvalidCertificate`] containing [`CertificateError::BadEncoding`] when these cases are encountered.
84 ///
85 /// [Certificate]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.4.2
86 /// [`CertificateError::BadEncoding`]: crate::error::CertificateError::BadEncoding
87 fn verify_server_cert(
88 &self,
89 end_entity: &CertificateDer<'_>,
90 intermediates: &[CertificateDer<'_>],
91 server_name: &ServerName<'_>,
92 ocsp_response: &[u8],
93 now: UnixTime,
94 ) -> Result<ServerCertVerified, Error>;
95
96 /// Verify a signature allegedly by the given server certificate.
97 ///
98 /// `message` is not hashed, and needs hashing during the verification.
99 /// The signature and algorithm are within `dss`. `cert` contains the
100 /// public key to use.
101 ///
102 /// `cert` has already been validated by [`ServerCertVerifier::verify_server_cert`].
103 ///
104 /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`.
105 /// Otherwise, return an error -- rustls will send an alert and abort the
106 /// connection.
107 ///
108 /// This method is only called for TLS1.2 handshakes. Note that, in TLS1.2,
109 /// SignatureSchemes such as `SignatureScheme::ECDSA_NISTP256_SHA256` are not
110 /// in fact bound to the specific curve implied in their name.
111 fn verify_tls12_signature(
112 &self,
113 message: &[u8],
114 cert: &CertificateDer<'_>,
115 dss: &DigitallySignedStruct,
116 ) -> Result<HandshakeSignatureValid, Error>;
117
118 /// Verify a signature allegedly by the given server certificate.
119 ///
120 /// This method is only called for TLS1.3 handshakes.
121 ///
122 /// This method is very similar to `verify_tls12_signature`: but note the
123 /// tighter ECDSA SignatureScheme semantics -- e.g. `SignatureScheme::ECDSA_NISTP256_SHA256`
124 /// must only validate signatures using public keys on the right curve --
125 /// rustls does not enforce this requirement for you.
126 ///
127 /// `cert` has already been validated by [`ServerCertVerifier::verify_server_cert`].
128 ///
129 /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`.
130 /// Otherwise, return an error -- rustls will send an alert and abort the
131 /// connection.
132 fn verify_tls13_signature(
133 &self,
134 message: &[u8],
135 cert: &CertificateDer<'_>,
136 dss: &DigitallySignedStruct,
137 ) -> Result<HandshakeSignatureValid, Error>;
138
139 /// Return the list of SignatureSchemes that this verifier will handle,
140 /// in `verify_tls12_signature` and `verify_tls13_signature` calls.
141 ///
142 /// This should be in priority order, with the most preferred first.
143 fn supported_verify_schemes(&self) -> Vec<SignatureScheme>;
144
145 /// Return true if this verifier will process stapled OCSP responses.
146 ///
147 /// This controls whether a client will ask the server for a stapled OCSP response.
148 /// There is no guarantee the server will provide one.
149 fn request_ocsp_response(&self) -> bool;
150
151 /// Returns whether this verifier requires raw public keys as defined
152 /// in [RFC 7250](https://tools.ietf.org/html/rfc7250).
153 fn requires_raw_public_keys(&self) -> bool {
154 false
155 }
156
157 /// Return the [`DistinguishedName`]s of certificate authorities that this verifier trusts.
158 ///
159 /// If specified, will be sent as the [`certificate_authorities`] extension in ClientHello.
160 /// Note that this is only applicable to TLS 1.3.
161 ///
162 /// [`certificate_authorities`]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.4
163 fn root_hint_subjects(&self) -> Option<Arc<[DistinguishedName]>> {
164 None
165 }
166}
167
168/// Something that can verify a client certificate chain
169#[allow(unreachable_pub)]
170pub trait ClientCertVerifier: Debug + Send + Sync {
171 /// Returns `true` to enable the server to request a client certificate and
172 /// `false` to skip requesting a client certificate. Defaults to `true`.
173 fn offer_client_auth(&self) -> bool {
174 true
175 }
176
177 /// Return `true` to require a client certificate and `false` to make
178 /// client authentication optional.
179 /// Defaults to `self.offer_client_auth()`.
180 fn client_auth_mandatory(&self) -> bool {
181 self.offer_client_auth()
182 }
183
184 /// Returns the [`DistinguishedName`] [subjects] that the server will hint to clients to
185 /// identify acceptable authentication trust anchors.
186 ///
187 /// These hint values help the client pick a client certificate it believes the server will
188 /// accept. The hints must be DER-encoded X.500 distinguished names, per [RFC 5280 A.1]. They
189 /// are sent in the [`certificate_authorities`] extension of a [`CertificateRequest`] message
190 /// when [ClientCertVerifier::offer_client_auth] is true. When an empty list is sent the client
191 /// should always provide a client certificate if it has one.
192 ///
193 /// Generally this list should contain the [`DistinguishedName`] of each root trust
194 /// anchor in the root cert store that the server is configured to use for authenticating
195 /// presented client certificates.
196 ///
197 /// In some circumstances this list may be customized to include [`DistinguishedName`] entries
198 /// that do not correspond to a trust anchor in the server's root cert store. For example,
199 /// the server may be configured to trust a root CA that cross-signed an issuer certificate
200 /// that the client considers a trust anchor. From the server's perspective the cross-signed
201 /// certificate is an intermediate, and not present in the server's root cert store. The client
202 /// may have the cross-signed certificate configured as a trust anchor, and be unaware of the
203 /// root CA that cross-signed it. If the server's hints list only contained the subjects of the
204 /// server's root store the client would consider a client certificate issued by the cross-signed
205 /// issuer unacceptable, since its subject was not hinted. To avoid this circumstance the server
206 /// should customize the hints list to include the subject of the cross-signed issuer in addition
207 /// to the subjects from the root cert store.
208 ///
209 /// [subjects]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6
210 /// [RFC 5280 A.1]: https://www.rfc-editor.org/rfc/rfc5280#appendix-A.1
211 /// [`CertificateRequest`]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.3.2
212 /// [`certificate_authorities`]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.4
213 fn root_hint_subjects(&self) -> Arc<[DistinguishedName]>;
214
215 /// Verify the end-entity certificate `end_entity` is valid, acceptable,
216 /// and chains to at least one of the trust anchors trusted by
217 /// this verifier.
218 ///
219 /// `intermediates` contains the intermediate certificates the
220 /// client sent along with the end-entity certificate; it is in the same
221 /// order that the peer sent them and may be empty.
222 ///
223 /// Note that none of the certificates have been parsed yet, so it is the responsibility of
224 /// the implementer to handle invalid data. It is recommended that the implementer returns
225 /// an [InvalidCertificate] error with the [BadEncoding] variant when these cases are encountered.
226 ///
227 /// [InvalidCertificate]: Error#variant.InvalidCertificate
228 /// [BadEncoding]: crate::CertificateError#variant.BadEncoding
229 fn verify_client_cert(
230 &self,
231 end_entity: &CertificateDer<'_>,
232 intermediates: &[CertificateDer<'_>],
233 now: UnixTime,
234 ) -> Result<ClientCertVerified, Error>;
235
236 /// Verify a signature allegedly by the given client certificate.
237 ///
238 /// `message` is not hashed, and needs hashing during the verification.
239 /// The signature and algorithm are within `dss`. `cert` contains the
240 /// public key to use.
241 ///
242 /// `cert` has already been validated by [`ClientCertVerifier::verify_client_cert`].
243 ///
244 /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`.
245 /// Otherwise, return an error -- rustls will send an alert and abort the
246 /// connection.
247 ///
248 /// This method is only called for TLS1.2 handshakes. Note that, in TLS1.2,
249 /// SignatureSchemes such as `SignatureScheme::ECDSA_NISTP256_SHA256` are not
250 /// in fact bound to the specific curve implied in their name.
251 fn verify_tls12_signature(
252 &self,
253 message: &[u8],
254 cert: &CertificateDer<'_>,
255 dss: &DigitallySignedStruct,
256 ) -> Result<HandshakeSignatureValid, Error>;
257
258 /// Verify a signature allegedly by the given client certificate.
259 ///
260 /// This method is only called for TLS1.3 handshakes.
261 ///
262 /// This method is very similar to `verify_tls12_signature`, but note the
263 /// tighter ECDSA SignatureScheme semantics in TLS 1.3. For example,
264 /// `SignatureScheme::ECDSA_NISTP256_SHA256`
265 /// must only validate signatures using public keys on the right curve --
266 /// rustls does not enforce this requirement for you.
267 fn verify_tls13_signature(
268 &self,
269 message: &[u8],
270 cert: &CertificateDer<'_>,
271 dss: &DigitallySignedStruct,
272 ) -> Result<HandshakeSignatureValid, Error>;
273
274 /// Return the list of SignatureSchemes that this verifier will handle,
275 /// in `verify_tls12_signature` and `verify_tls13_signature` calls.
276 ///
277 /// This should be in priority order, with the most preferred first.
278 fn supported_verify_schemes(&self) -> Vec<SignatureScheme>;
279
280 /// Returns whether this verifier requires raw public keys as defined
281 /// in [RFC 7250](https://tools.ietf.org/html/rfc7250).
282 fn requires_raw_public_keys(&self) -> bool {
283 false
284 }
285}
286
287/// Turns off client authentication.
288///
289/// In contrast to using
290/// `WebPkiClientVerifier::builder(roots).allow_unauthenticated().build()`, the `NoClientAuth`
291/// `ClientCertVerifier` will not offer client authentication at all, vs offering but not
292/// requiring it.
293#[allow(clippy::exhaustive_structs)]
294#[derive(Debug)]
295pub struct NoClientAuth;
296
297impl ClientCertVerifier for NoClientAuth {
298 fn offer_client_auth(&self) -> bool {
299 false
300 }
301
302 fn root_hint_subjects(&self) -> Arc<[DistinguishedName]> {
303 unimplemented!();
304 }
305
306 fn verify_client_cert(
307 &self,
308 _end_entity: &CertificateDer<'_>,
309 _intermediates: &[CertificateDer<'_>],
310 _now: UnixTime,
311 ) -> Result<ClientCertVerified, Error> {
312 unimplemented!();
313 }
314
315 fn verify_tls12_signature(
316 &self,
317 _message: &[u8],
318 _cert: &CertificateDer<'_>,
319 _dss: &DigitallySignedStruct,
320 ) -> Result<HandshakeSignatureValid, Error> {
321 unimplemented!();
322 }
323
324 fn verify_tls13_signature(
325 &self,
326 _message: &[u8],
327 _cert: &CertificateDer<'_>,
328 _dss: &DigitallySignedStruct,
329 ) -> Result<HandshakeSignatureValid, Error> {
330 unimplemented!();
331 }
332
333 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
334 unimplemented!();
335 }
336}
337
338/// This type combines a [`SignatureScheme`] and a signature payload produced with that scheme.
339#[derive(Debug, Clone)]
340pub struct DigitallySignedStruct {
341 /// The [`SignatureScheme`] used to produce the signature.
342 pub scheme: SignatureScheme,
343 sig: PayloadU16,
344}
345
346impl DigitallySignedStruct {
347 pub(crate) fn new(scheme: SignatureScheme, sig: Vec<u8>) -> Self {
348 Self {
349 scheme,
350 sig: PayloadU16::new(sig),
351 }
352 }
353
354 /// Get the signature.
355 pub fn signature(&self) -> &[u8] {
356 &self.sig.0
357 }
358}
359
360impl Codec<'_> for DigitallySignedStruct {
361 fn encode(&self, bytes: &mut Vec<u8>) {
362 self.scheme.encode(bytes);
363 self.sig.encode(bytes);
364 }
365
366 fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
367 let scheme = SignatureScheme::read(r)?;
368 let sig = PayloadU16::read(r)?;
369
370 Ok(Self { scheme, sig })
371 }
372}
373
374#[test]
375fn assertions_are_debug() {
376 use std::format;
377
378 assert_eq!(
379 format!("{:?}", ClientCertVerified::assertion()),
380 "ClientCertVerified(())"
381 );
382 assert_eq!(
383 format!("{:?}", HandshakeSignatureValid::assertion()),
384 "HandshakeSignatureValid(())"
385 );
386 assert_eq!(
387 format!("{:?}", FinishedMessageVerified::assertion()),
388 "FinishedMessageVerified(())"
389 );
390 assert_eq!(
391 format!("{:?}", ServerCertVerified::assertion()),
392 "ServerCertVerified(())"
393 );
394}