1 | use alloc::vec::Vec; |
2 | use core::fmt::Debug; |
3 | |
4 | use pki_types::{CertificateDer, ServerName, UnixTime}; |
5 | |
6 | use crate::enums::SignatureScheme; |
7 | use crate::error::{Error, InvalidMessage}; |
8 | use crate::msgs::base::PayloadU16; |
9 | use crate::msgs::codec::{Codec, Reader}; |
10 | use 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)] |
24 | pub struct HandshakeSignatureValid(()); |
25 | |
26 | impl HandshakeSignatureValid { |
27 | /// Make a `HandshakeSignatureValid` |
28 | pub fn assertion() -> Self { |
29 | Self(()) |
30 | } |
31 | } |
32 | |
33 | #[derive (Debug)] |
34 | pub(crate) struct FinishedMessageVerified(()); |
35 | |
36 | impl 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)] |
45 | pub struct ServerCertVerified(()); |
46 | |
47 | #[allow (unreachable_pub)] |
48 | impl 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)] |
57 | pub struct ClientCertVerified(()); |
58 | |
59 | impl 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)] |
69 | pub 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 | /// Return the [`DistinguishedName`]s of certificate authorities that this verifier trusts. |
147 | /// |
148 | /// If specified, will be sent as the [`certificate_authorities`] extension in ClientHello. |
149 | /// Note that this is only applicable to TLS 1.3. |
150 | /// |
151 | /// [`certificate_authorities`]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.4 |
152 | fn root_hint_subjects(&self) -> Option<&[DistinguishedName]> { |
153 | None |
154 | } |
155 | } |
156 | |
157 | /// Something that can verify a client certificate chain |
158 | #[allow (unreachable_pub)] |
159 | pub trait ClientCertVerifier: Debug + Send + Sync { |
160 | /// Returns `true` to enable the server to request a client certificate and |
161 | /// `false` to skip requesting a client certificate. Defaults to `true`. |
162 | fn offer_client_auth(&self) -> bool { |
163 | true |
164 | } |
165 | |
166 | /// Return `true` to require a client certificate and `false` to make |
167 | /// client authentication optional. |
168 | /// Defaults to `self.offer_client_auth()`. |
169 | fn client_auth_mandatory(&self) -> bool { |
170 | self.offer_client_auth() |
171 | } |
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 [ClientCertVerifier::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) -> &[DistinguishedName]; |
203 | |
204 | /// Verify the end-entity certificate `end_entity` is valid, acceptable, |
205 | /// and chains to at least one of the trust anchors trusted by |
206 | /// this verifier. |
207 | /// |
208 | /// `intermediates` contains the intermediate certificates the |
209 | /// client sent along with the end-entity certificate; it is in the same |
210 | /// order that the peer sent them and may be empty. |
211 | /// |
212 | /// Note that none of the certificates have been parsed yet, so it is the responsibility of |
213 | /// the implementer to handle invalid data. It is recommended that the implementer returns |
214 | /// an [InvalidCertificate] error with the [BadEncoding] variant when these cases are encountered. |
215 | /// |
216 | /// [InvalidCertificate]: Error#variant.InvalidCertificate |
217 | /// [BadEncoding]: crate::CertificateError#variant.BadEncoding |
218 | fn verify_client_cert( |
219 | &self, |
220 | end_entity: &CertificateDer<'_>, |
221 | intermediates: &[CertificateDer<'_>], |
222 | now: UnixTime, |
223 | ) -> Result<ClientCertVerified, Error>; |
224 | |
225 | /// Verify a signature allegedly by the given client certificate. |
226 | /// |
227 | /// `message` is not hashed, and needs hashing during the verification. |
228 | /// The signature and algorithm are within `dss`. `cert` contains the |
229 | /// public key to use. |
230 | /// |
231 | /// `cert` has already been validated by [`ClientCertVerifier::verify_client_cert`]. |
232 | /// |
233 | /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`. |
234 | /// Otherwise, return an error -- rustls will send an alert and abort the |
235 | /// connection. |
236 | /// |
237 | /// This method is only called for TLS1.2 handshakes. Note that, in TLS1.2, |
238 | /// SignatureSchemes such as `SignatureScheme::ECDSA_NISTP256_SHA256` are not |
239 | /// in fact bound to the specific curve implied in their name. |
240 | fn verify_tls12_signature( |
241 | &self, |
242 | message: &[u8], |
243 | cert: &CertificateDer<'_>, |
244 | dss: &DigitallySignedStruct, |
245 | ) -> Result<HandshakeSignatureValid, Error>; |
246 | |
247 | /// Verify a signature allegedly by the given client certificate. |
248 | /// |
249 | /// This method is only called for TLS1.3 handshakes. |
250 | /// |
251 | /// This method is very similar to `verify_tls12_signature`, but note the |
252 | /// tighter ECDSA SignatureScheme semantics in TLS 1.3. For example, |
253 | /// `SignatureScheme::ECDSA_NISTP256_SHA256` |
254 | /// must only validate signatures using public keys on the right curve -- |
255 | /// rustls does not enforce this requirement for you. |
256 | fn verify_tls13_signature( |
257 | &self, |
258 | message: &[u8], |
259 | cert: &CertificateDer<'_>, |
260 | dss: &DigitallySignedStruct, |
261 | ) -> Result<HandshakeSignatureValid, Error>; |
262 | |
263 | /// Return the list of SignatureSchemes that this verifier will handle, |
264 | /// in `verify_tls12_signature` and `verify_tls13_signature` calls. |
265 | /// |
266 | /// This should be in priority order, with the most preferred first. |
267 | fn supported_verify_schemes(&self) -> Vec<SignatureScheme>; |
268 | |
269 | /// Returns whether this verifier requires raw public keys as defined |
270 | /// in [RFC 7250](https://tools.ietf.org/html/rfc7250). |
271 | fn requires_raw_public_keys(&self) -> bool { |
272 | false |
273 | } |
274 | } |
275 | |
276 | /// Turns off client authentication. |
277 | /// |
278 | /// In contrast to using |
279 | /// `WebPkiClientVerifier::builder(roots).allow_unauthenticated().build()`, the `NoClientAuth` |
280 | /// `ClientCertVerifier` will not offer client authentication at all, vs offering but not |
281 | /// requiring it. |
282 | #[derive (Debug)] |
283 | pub struct NoClientAuth; |
284 | |
285 | impl ClientCertVerifier for NoClientAuth { |
286 | fn offer_client_auth(&self) -> bool { |
287 | false |
288 | } |
289 | |
290 | fn root_hint_subjects(&self) -> &[DistinguishedName] { |
291 | unimplemented!(); |
292 | } |
293 | |
294 | fn verify_client_cert( |
295 | &self, |
296 | _end_entity: &CertificateDer<'_>, |
297 | _intermediates: &[CertificateDer<'_>], |
298 | _now: UnixTime, |
299 | ) -> Result<ClientCertVerified, Error> { |
300 | unimplemented!(); |
301 | } |
302 | |
303 | fn verify_tls12_signature( |
304 | &self, |
305 | _message: &[u8], |
306 | _cert: &CertificateDer<'_>, |
307 | _dss: &DigitallySignedStruct, |
308 | ) -> Result<HandshakeSignatureValid, Error> { |
309 | unimplemented!(); |
310 | } |
311 | |
312 | fn verify_tls13_signature( |
313 | &self, |
314 | _message: &[u8], |
315 | _cert: &CertificateDer<'_>, |
316 | _dss: &DigitallySignedStruct, |
317 | ) -> Result<HandshakeSignatureValid, Error> { |
318 | unimplemented!(); |
319 | } |
320 | |
321 | fn supported_verify_schemes(&self) -> Vec<SignatureScheme> { |
322 | unimplemented!(); |
323 | } |
324 | } |
325 | |
326 | /// This type combines a [`SignatureScheme`] and a signature payload produced with that scheme. |
327 | #[derive (Debug, Clone)] |
328 | pub struct DigitallySignedStruct { |
329 | /// The [`SignatureScheme`] used to produce the signature. |
330 | pub scheme: SignatureScheme, |
331 | sig: PayloadU16, |
332 | } |
333 | |
334 | impl DigitallySignedStruct { |
335 | pub(crate) fn new(scheme: SignatureScheme, sig: Vec<u8>) -> Self { |
336 | Self { |
337 | scheme, |
338 | sig: PayloadU16::new(bytes:sig), |
339 | } |
340 | } |
341 | |
342 | /// Get the signature. |
343 | pub fn signature(&self) -> &[u8] { |
344 | &self.sig.0 |
345 | } |
346 | } |
347 | |
348 | impl Codec<'_> for DigitallySignedStruct { |
349 | fn encode(&self, bytes: &mut Vec<u8>) { |
350 | self.scheme.encode(bytes); |
351 | self.sig.encode(bytes); |
352 | } |
353 | |
354 | fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> { |
355 | let scheme: SignatureScheme = SignatureScheme::read(r)?; |
356 | let sig: PayloadU16 = PayloadU16::read(r)?; |
357 | |
358 | Ok(Self { scheme, sig }) |
359 | } |
360 | } |
361 | |
362 | #[test ] |
363 | fn assertions_are_debug() { |
364 | use std::format; |
365 | |
366 | assert_eq!( |
367 | format!("{:?}" , ClientCertVerified::assertion()), |
368 | "ClientCertVerified(())" |
369 | ); |
370 | assert_eq!( |
371 | format!("{:?}" , HandshakeSignatureValid::assertion()), |
372 | "HandshakeSignatureValid(())" |
373 | ); |
374 | assert_eq!( |
375 | format!("{:?}" , FinishedMessageVerified::assertion()), |
376 | "FinishedMessageVerified(())" |
377 | ); |
378 | assert_eq!( |
379 | format!("{:?}" , ServerCertVerified::assertion()), |
380 | "ServerCertVerified(())" |
381 | ); |
382 | } |
383 | |