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