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