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