/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.37/src/client/tls13.rs
Line | Count | Source |
1 | | use alloc::boxed::Box; |
2 | | use alloc::vec; |
3 | | use alloc::vec::Vec; |
4 | | |
5 | | use pki_types::ServerName; |
6 | | use subtle::ConstantTimeEq; |
7 | | |
8 | | use super::client_conn::ClientConnectionData; |
9 | | use super::hs::{ClientContext, ClientHelloInput, ClientSessionValue}; |
10 | | use crate::check::inappropriate_handshake_message; |
11 | | use crate::client::common::{ClientAuthDetails, ClientHelloDetails, ServerCertDetails}; |
12 | | use crate::client::ech::{self, EchState, EchStatus}; |
13 | | use crate::client::{ClientConfig, ClientSessionStore, hs}; |
14 | | use crate::common_state::{ |
15 | | CommonState, HandshakeFlightTls13, HandshakeKind, KxState, Protocol, Side, State, |
16 | | }; |
17 | | use crate::conn::ConnectionRandoms; |
18 | | use crate::conn::kernel::{Direction, KernelContext, KernelState}; |
19 | | use crate::crypto::hash::Hash; |
20 | | use crate::crypto::{ActiveKeyExchange, SharedSecret}; |
21 | | use crate::enums::{ |
22 | | AlertDescription, ContentType, HandshakeType, ProtocolVersion, SignatureScheme, |
23 | | }; |
24 | | use crate::error::{Error, InvalidMessage, PeerIncompatible, PeerMisbehaved}; |
25 | | use crate::hash_hs::{HandshakeHash, HandshakeHashBuffer}; |
26 | | use crate::log::{debug, trace, warn}; |
27 | | use crate::msgs::base::{Payload, PayloadU8}; |
28 | | use crate::msgs::ccs::ChangeCipherSpecPayload; |
29 | | use crate::msgs::codec::{Codec, Reader}; |
30 | | use crate::msgs::enums::{ExtensionType, KeyUpdateRequest}; |
31 | | use crate::msgs::handshake::{ |
32 | | CERTIFICATE_MAX_SIZE_LIMIT, CertificatePayloadTls13, ClientExtensions, EchConfigPayload, |
33 | | HandshakeMessagePayload, HandshakePayload, KeyShareEntry, NewSessionTicketPayloadTls13, |
34 | | PresharedKeyBinder, PresharedKeyIdentity, PresharedKeyOffer, ServerExtensions, |
35 | | ServerHelloPayload, |
36 | | }; |
37 | | use crate::msgs::message::{Message, MessagePayload}; |
38 | | use crate::msgs::persist::{self, Retrieved}; |
39 | | use crate::sign::{CertifiedKey, Signer}; |
40 | | use crate::suites::PartiallyExtractedSecrets; |
41 | | use crate::sync::Arc; |
42 | | use crate::tls13::key_schedule::{ |
43 | | KeyScheduleEarly, KeyScheduleHandshake, KeySchedulePreHandshake, KeyScheduleResumption, |
44 | | KeyScheduleTraffic, |
45 | | }; |
46 | | use crate::tls13::{ |
47 | | Tls13CipherSuite, construct_client_verify_message, construct_server_verify_message, |
48 | | }; |
49 | | use crate::verify::{self, DigitallySignedStruct}; |
50 | | use crate::{ConnectionTrafficSecrets, KeyLog, compress, crypto}; |
51 | | |
52 | | // Extensions we expect in plaintext in the ServerHello. |
53 | | static ALLOWED_PLAINTEXT_EXTS: &[ExtensionType] = &[ |
54 | | ExtensionType::KeyShare, |
55 | | ExtensionType::PreSharedKey, |
56 | | ExtensionType::SupportedVersions, |
57 | | ]; |
58 | | |
59 | | // Only the intersection of things we offer, and those disallowed |
60 | | // in TLS1.3 |
61 | | static DISALLOWED_TLS13_EXTS: &[ExtensionType] = &[ |
62 | | ExtensionType::ECPointFormats, |
63 | | ExtensionType::SessionTicket, |
64 | | ExtensionType::RenegotiationInfo, |
65 | | ExtensionType::ExtendedMasterSecret, |
66 | | ]; |
67 | | |
68 | | /// `early_data_key_schedule` is `Some` if we sent the |
69 | | /// "early_data" extension to the server. |
70 | 0 | pub(super) fn handle_server_hello( |
71 | 0 | cx: &mut ClientContext<'_>, |
72 | 0 | server_hello: &ServerHelloPayload, |
73 | 0 | mut randoms: ConnectionRandoms, |
74 | 0 | suite: &'static Tls13CipherSuite, |
75 | 0 | mut transcript: HandshakeHash, |
76 | 0 | early_data_key_schedule: Option<KeyScheduleEarly>, |
77 | 0 | our_key_share: Box<dyn ActiveKeyExchange>, |
78 | 0 | server_hello_msg: &Message<'_>, |
79 | 0 | ech_state: Option<EchState>, |
80 | 0 | input: ClientHelloInput, |
81 | 0 | ) -> hs::NextStateOrError<'static> { |
82 | 0 | validate_server_hello(cx.common, server_hello)?; |
83 | | |
84 | 0 | let their_key_share = server_hello |
85 | 0 | .key_share |
86 | 0 | .as_ref() |
87 | 0 | .ok_or_else(|| { |
88 | 0 | cx.common.send_fatal_alert( |
89 | 0 | AlertDescription::MissingExtension, |
90 | 0 | PeerMisbehaved::MissingKeyShare, |
91 | | ) |
92 | 0 | })?; |
93 | | |
94 | | let ClientHelloInput { |
95 | 0 | config, |
96 | 0 | resuming, |
97 | 0 | mut sent_tls13_fake_ccs, |
98 | 0 | mut hello, |
99 | 0 | server_name, |
100 | | .. |
101 | 0 | } = input; |
102 | | |
103 | 0 | let mut resuming_session = match resuming { |
104 | | Some(Retrieved { |
105 | 0 | value: ClientSessionValue::Tls13(value), |
106 | | .. |
107 | 0 | }) => Some(value), |
108 | 0 | _ => None, |
109 | | }; |
110 | | |
111 | 0 | let our_key_share = KeyExchangeChoice::new(&config, cx, our_key_share, their_key_share) |
112 | 0 | .map_err(|_| { |
113 | 0 | cx.common.send_fatal_alert( |
114 | 0 | AlertDescription::IllegalParameter, |
115 | 0 | PeerMisbehaved::WrongGroupForKeyShare, |
116 | | ) |
117 | 0 | })?; |
118 | | |
119 | 0 | let key_schedule_pre_handshake = match (server_hello.preshared_key, early_data_key_schedule) { |
120 | 0 | (Some(selected_psk), Some(early_key_schedule)) => { |
121 | 0 | match &resuming_session { |
122 | 0 | Some(resuming) => { |
123 | 0 | let Some(resuming_suite) = suite.can_resume_from(resuming.suite()) else { |
124 | 0 | return Err({ |
125 | 0 | cx.common.send_fatal_alert( |
126 | 0 | AlertDescription::IllegalParameter, |
127 | 0 | PeerMisbehaved::ResumptionOfferedWithIncompatibleCipherSuite, |
128 | 0 | ) |
129 | 0 | }); |
130 | | }; |
131 | | |
132 | | // If the server varies the suite here, we will have encrypted early data with |
133 | | // the wrong suite. |
134 | 0 | if cx.data.early_data.is_enabled() && resuming_suite != suite { |
135 | 0 | return Err({ |
136 | 0 | cx.common.send_fatal_alert( |
137 | 0 | AlertDescription::IllegalParameter, |
138 | 0 | PeerMisbehaved::EarlyDataOfferedWithVariedCipherSuite, |
139 | 0 | ) |
140 | 0 | }); |
141 | 0 | } |
142 | | |
143 | 0 | if selected_psk != 0 { |
144 | 0 | return Err({ |
145 | 0 | cx.common.send_fatal_alert( |
146 | 0 | AlertDescription::IllegalParameter, |
147 | 0 | PeerMisbehaved::SelectedInvalidPsk, |
148 | 0 | ) |
149 | 0 | }); |
150 | 0 | } |
151 | | |
152 | 0 | debug!("Resuming using PSK"); |
153 | | // The key schedule has been initialized and set in fill_in_psk_binder() |
154 | | } |
155 | | _ => { |
156 | 0 | return Err(PeerMisbehaved::SelectedUnofferedPsk.into()); |
157 | | } |
158 | | } |
159 | 0 | KeySchedulePreHandshake::from(early_key_schedule) |
160 | | } |
161 | | _ => { |
162 | 0 | debug!("Not resuming"); |
163 | | // Discard the early data key schedule. |
164 | 0 | cx.data.early_data.rejected(); |
165 | 0 | cx.common.early_traffic = false; |
166 | 0 | resuming_session.take(); |
167 | 0 | KeySchedulePreHandshake::new(suite) |
168 | | } |
169 | | }; |
170 | | |
171 | 0 | cx.common.kx_state.complete(); |
172 | 0 | let shared_secret = our_key_share |
173 | 0 | .complete(&their_key_share.payload.0) |
174 | 0 | .map_err(|err| { |
175 | 0 | cx.common |
176 | 0 | .send_fatal_alert(AlertDescription::IllegalParameter, err) |
177 | 0 | })?; |
178 | | |
179 | 0 | let mut key_schedule = key_schedule_pre_handshake.into_handshake(shared_secret); |
180 | | |
181 | | // If we have ECH state, check that the server accepted our offer. |
182 | 0 | if let Some(ech_state) = ech_state { |
183 | | let Message { |
184 | | payload: |
185 | | MessagePayload::Handshake { |
186 | 0 | encoded: server_hello_encoded, |
187 | | .. |
188 | | }, |
189 | | .. |
190 | 0 | } = &server_hello_msg |
191 | | else { |
192 | 0 | unreachable!("ServerHello is a handshake message"); |
193 | | }; |
194 | 0 | cx.data.ech_status = match ech_state.confirm_acceptance( |
195 | 0 | &mut key_schedule, |
196 | 0 | server_hello, |
197 | 0 | server_hello_encoded, |
198 | 0 | suite.common.hash_provider, |
199 | 0 | )? { |
200 | | // The server accepted our ECH offer, so complete the inner transcript with the |
201 | | // server hello message, and switch the relevant state to the copies for the |
202 | | // inner client hello. |
203 | 0 | Some(mut accepted) => { |
204 | 0 | accepted |
205 | 0 | .transcript |
206 | 0 | .add_message(server_hello_msg); |
207 | 0 | transcript = accepted.transcript; |
208 | 0 | randoms.client = accepted.random.0; |
209 | 0 | hello.sent_extensions = accepted.sent_extensions; |
210 | 0 | EchStatus::Accepted |
211 | | } |
212 | | // The server rejected our ECH offer. |
213 | 0 | None => EchStatus::Rejected, |
214 | | }; |
215 | 0 | } |
216 | | |
217 | | // Remember what KX group the server liked for next time. |
218 | 0 | config |
219 | 0 | .resumption |
220 | 0 | .store |
221 | 0 | .set_kx_hint(server_name.clone(), their_key_share.group); |
222 | | |
223 | | // If we change keying when a subsequent handshake message is being joined, |
224 | | // the two halves will have different record layer protections. Disallow this. |
225 | 0 | cx.common.check_aligned_handshake()?; |
226 | | |
227 | 0 | let hash_at_client_recvd_server_hello = transcript.current_hash(); |
228 | 0 | let key_schedule = key_schedule.derive_client_handshake_secrets( |
229 | 0 | cx.data.early_data.is_enabled(), |
230 | 0 | hash_at_client_recvd_server_hello, |
231 | 0 | suite, |
232 | 0 | &*config.key_log, |
233 | 0 | &randoms.client, |
234 | 0 | cx.common, |
235 | | ); |
236 | | |
237 | 0 | emit_fake_ccs(&mut sent_tls13_fake_ccs, cx.common); |
238 | | |
239 | 0 | Ok(Box::new(ExpectEncryptedExtensions { |
240 | 0 | config, |
241 | 0 | resuming_session, |
242 | 0 | server_name, |
243 | 0 | randoms, |
244 | 0 | suite, |
245 | 0 | transcript, |
246 | 0 | key_schedule, |
247 | 0 | hello, |
248 | 0 | })) |
249 | 0 | } |
250 | | |
251 | | enum KeyExchangeChoice { |
252 | | Whole(Box<dyn ActiveKeyExchange>), |
253 | | Component(Box<dyn ActiveKeyExchange>), |
254 | | } |
255 | | |
256 | | impl KeyExchangeChoice { |
257 | | /// Decide between `our_key_share` or `our_key_share.hybrid_component()` |
258 | | /// based on the selection of the server expressed in `their_key_share`. |
259 | 0 | fn new( |
260 | 0 | config: &Arc<ClientConfig>, |
261 | 0 | cx: &mut ClientContext<'_>, |
262 | 0 | our_key_share: Box<dyn ActiveKeyExchange>, |
263 | 0 | their_key_share: &KeyShareEntry, |
264 | 0 | ) -> Result<Self, ()> { |
265 | 0 | if our_key_share.group() == their_key_share.group { |
266 | 0 | return Ok(Self::Whole(our_key_share)); |
267 | 0 | } |
268 | | |
269 | 0 | let (component_group, _) = our_key_share |
270 | 0 | .hybrid_component() |
271 | 0 | .ok_or(())?; |
272 | | |
273 | 0 | if component_group != their_key_share.group { |
274 | 0 | return Err(()); |
275 | 0 | } |
276 | | |
277 | | // correct the record for the benefit of accuracy of |
278 | | // `negotiated_key_exchange_group()` |
279 | 0 | let actual_skxg = config |
280 | 0 | .find_kx_group(component_group, ProtocolVersion::TLSv1_3) |
281 | 0 | .ok_or(())?; |
282 | 0 | cx.common.kx_state = KxState::Start(actual_skxg); |
283 | | |
284 | 0 | Ok(Self::Component(our_key_share)) |
285 | 0 | } |
286 | | |
287 | 0 | fn complete(self, peer_pub_key: &[u8]) -> Result<SharedSecret, Error> { |
288 | 0 | match self { |
289 | 0 | Self::Whole(akx) => akx.complete(peer_pub_key), |
290 | 0 | Self::Component(akx) => akx.complete_hybrid_component(peer_pub_key), |
291 | | } |
292 | 0 | } |
293 | | } |
294 | | |
295 | 0 | fn validate_server_hello( |
296 | 0 | common: &mut CommonState, |
297 | 0 | server_hello: &ServerHelloPayload, |
298 | 0 | ) -> Result<(), Error> { |
299 | 0 | if !server_hello.only_contains(ALLOWED_PLAINTEXT_EXTS) { |
300 | 0 | return Err(common.send_fatal_alert( |
301 | 0 | AlertDescription::UnsupportedExtension, |
302 | 0 | PeerMisbehaved::UnexpectedCleartextExtension, |
303 | 0 | )); |
304 | 0 | } |
305 | | |
306 | 0 | Ok(()) |
307 | 0 | } |
308 | | |
309 | 0 | pub(super) fn initial_key_share( |
310 | 0 | config: &ClientConfig, |
311 | 0 | server_name: &ServerName<'_>, |
312 | 0 | kx_state: &mut KxState, |
313 | 0 | ) -> Result<Box<dyn ActiveKeyExchange>, Error> { |
314 | 0 | let group = config |
315 | 0 | .resumption |
316 | 0 | .store |
317 | 0 | .kx_hint(server_name) |
318 | 0 | .and_then(|group_name| config.find_kx_group(group_name, ProtocolVersion::TLSv1_3)) |
319 | 0 | .unwrap_or_else(|| { |
320 | 0 | config |
321 | 0 | .provider |
322 | 0 | .kx_groups |
323 | 0 | .iter() |
324 | 0 | .copied() |
325 | 0 | .next() |
326 | 0 | .expect("No kx groups configured") |
327 | 0 | }); |
328 | | |
329 | 0 | *kx_state = KxState::Start(group); |
330 | 0 | group.start() |
331 | 0 | } |
332 | | |
333 | | /// This implements the horrifying TLS1.3 hack where PSK binders have a |
334 | | /// data dependency on the message they are contained within. |
335 | 0 | pub(super) fn fill_in_psk_binder( |
336 | 0 | resuming: &persist::Tls13ClientSessionValue, |
337 | 0 | transcript: &HandshakeHashBuffer, |
338 | 0 | hmp: &mut HandshakeMessagePayload<'_>, |
339 | 0 | ) -> KeyScheduleEarly { |
340 | | // We need to know the hash function of the suite we're trying to resume into. |
341 | 0 | let suite = resuming.suite(); |
342 | 0 | let suite_hash = suite.common.hash_provider; |
343 | | |
344 | | // The binder is calculated over the clienthello, but doesn't include itself or its |
345 | | // length, or the length of its container. |
346 | 0 | let binder_plaintext = hmp.encoding_for_binder_signing(); |
347 | 0 | let handshake_hash = transcript.hash_given(suite_hash, &binder_plaintext); |
348 | | |
349 | | // Run a fake key_schedule to simulate what the server will do if it chooses |
350 | | // to resume. |
351 | 0 | let key_schedule = KeyScheduleEarly::new(suite, resuming.secret()); |
352 | 0 | let real_binder = key_schedule.resumption_psk_binder_key_and_sign_verify_data(&handshake_hash); |
353 | | |
354 | 0 | if let HandshakePayload::ClientHello(ch) = &mut hmp.0 { |
355 | | if let Some(PresharedKeyOffer { |
356 | 0 | binders, |
357 | 0 | identities, |
358 | 0 | }) = &mut ch.preshared_key_offer |
359 | | { |
360 | | // the caller of this function must have set up the desired identity, and a |
361 | | // matching (dummy) binder; or else the binder we compute here will be incorrect. |
362 | | // See `prepare_resumption()`. |
363 | 0 | debug_assert_eq!(identities.len(), 1); |
364 | 0 | debug_assert_eq!(binders.len(), 1); |
365 | 0 | debug_assert_eq!(binders[0].as_ref().len(), real_binder.as_ref().len()); |
366 | 0 | binders[0] = PresharedKeyBinder::from(real_binder.as_ref().to_vec()); |
367 | 0 | } |
368 | 0 | }; |
369 | | |
370 | 0 | key_schedule |
371 | 0 | } |
372 | | |
373 | 0 | pub(super) fn prepare_resumption( |
374 | 0 | config: &ClientConfig, |
375 | 0 | cx: &mut ClientContext<'_>, |
376 | 0 | resuming_session: &Retrieved<&persist::Tls13ClientSessionValue>, |
377 | 0 | exts: &mut ClientExtensions<'_>, |
378 | 0 | doing_retry: bool, |
379 | 0 | ) { |
380 | 0 | let resuming_suite = resuming_session.suite(); |
381 | 0 | cx.common.suite = Some(resuming_suite.into()); |
382 | | // The EarlyData extension MUST be supplied together with the |
383 | | // PreSharedKey extension. |
384 | 0 | let max_early_data_size = resuming_session.max_early_data_size(); |
385 | 0 | if config.enable_early_data && max_early_data_size > 0 && !doing_retry { |
386 | 0 | cx.data |
387 | 0 | .early_data |
388 | 0 | .enable(max_early_data_size as usize); |
389 | 0 | exts.early_data_request = Some(()); |
390 | 0 | } |
391 | | |
392 | | // Finally, and only for TLS1.3 with a ticket resumption, include a binder |
393 | | // for our ticket. This must go last. |
394 | | // |
395 | | // Include an empty binder. It gets filled in below because it depends on |
396 | | // the message it's contained in (!!!). |
397 | 0 | let obfuscated_ticket_age = resuming_session.obfuscated_ticket_age(); |
398 | | |
399 | 0 | let binder_len = resuming_suite |
400 | 0 | .common |
401 | 0 | .hash_provider |
402 | 0 | .output_len(); |
403 | 0 | let binder = vec![0u8; binder_len]; |
404 | | |
405 | 0 | let psk_identity = |
406 | 0 | PresharedKeyIdentity::new(resuming_session.ticket().to_vec(), obfuscated_ticket_age); |
407 | 0 | let psk_offer = PresharedKeyOffer::new(psk_identity, binder); |
408 | 0 | exts.preshared_key_offer = Some(psk_offer); |
409 | 0 | } |
410 | | |
411 | 0 | pub(super) fn derive_early_traffic_secret( |
412 | 0 | key_log: &dyn KeyLog, |
413 | 0 | cx: &mut ClientContext<'_>, |
414 | 0 | hash_alg: &'static dyn Hash, |
415 | 0 | early_key_schedule: &KeyScheduleEarly, |
416 | 0 | sent_tls13_fake_ccs: &mut bool, |
417 | 0 | transcript_buffer: &HandshakeHashBuffer, |
418 | 0 | client_random: &[u8; 32], |
419 | 0 | ) { |
420 | | // For middlebox compatibility |
421 | 0 | emit_fake_ccs(sent_tls13_fake_ccs, cx.common); |
422 | | |
423 | 0 | let client_hello_hash = transcript_buffer.hash_given(hash_alg, &[]); |
424 | 0 | early_key_schedule.client_early_traffic_secret( |
425 | 0 | &client_hello_hash, |
426 | 0 | key_log, |
427 | 0 | client_random, |
428 | 0 | cx.common, |
429 | | ); |
430 | | |
431 | | // Now the client can send encrypted early data |
432 | 0 | cx.common.early_traffic = true; |
433 | 0 | trace!("Starting early data traffic"); |
434 | 0 | } |
435 | | |
436 | 0 | pub(super) fn emit_fake_ccs(sent_tls13_fake_ccs: &mut bool, common: &mut CommonState) { |
437 | 0 | if common.is_quic() { |
438 | 0 | return; |
439 | 0 | } |
440 | | |
441 | 0 | if core::mem::replace(sent_tls13_fake_ccs, true) { |
442 | 0 | return; |
443 | 0 | } |
444 | | |
445 | 0 | let m = Message { |
446 | 0 | version: ProtocolVersion::TLSv1_2, |
447 | 0 | payload: MessagePayload::ChangeCipherSpec(ChangeCipherSpecPayload {}), |
448 | 0 | }; |
449 | 0 | common.send_msg(m, false); |
450 | 0 | } |
451 | | |
452 | 0 | fn validate_encrypted_extensions( |
453 | 0 | common: &mut CommonState, |
454 | 0 | hello: &ClientHelloDetails, |
455 | 0 | exts: &ServerExtensions<'_>, |
456 | 0 | ) -> Result<(), Error> { |
457 | 0 | if hello.server_sent_unsolicited_extensions(exts, &[]) { |
458 | 0 | return Err(common.send_fatal_alert( |
459 | 0 | AlertDescription::UnsupportedExtension, |
460 | 0 | PeerMisbehaved::UnsolicitedEncryptedExtension, |
461 | 0 | )); |
462 | 0 | } |
463 | | |
464 | 0 | if exts.contains_any(ALLOWED_PLAINTEXT_EXTS) || exts.contains_any(DISALLOWED_TLS13_EXTS) { |
465 | 0 | return Err(common.send_fatal_alert( |
466 | 0 | AlertDescription::UnsupportedExtension, |
467 | 0 | PeerMisbehaved::DisallowedEncryptedExtension, |
468 | 0 | )); |
469 | 0 | } |
470 | | |
471 | 0 | Ok(()) |
472 | 0 | } |
473 | | |
474 | | struct ExpectEncryptedExtensions { |
475 | | config: Arc<ClientConfig>, |
476 | | resuming_session: Option<persist::Tls13ClientSessionValue>, |
477 | | server_name: ServerName<'static>, |
478 | | randoms: ConnectionRandoms, |
479 | | suite: &'static Tls13CipherSuite, |
480 | | transcript: HandshakeHash, |
481 | | key_schedule: KeyScheduleHandshake, |
482 | | hello: ClientHelloDetails, |
483 | | } |
484 | | |
485 | | impl State<ClientConnectionData> for ExpectEncryptedExtensions { |
486 | 0 | fn handle<'m>( |
487 | 0 | mut self: Box<Self>, |
488 | 0 | cx: &mut ClientContext<'_>, |
489 | 0 | m: Message<'m>, |
490 | 0 | ) -> hs::NextStateOrError<'m> |
491 | 0 | where |
492 | 0 | Self: 'm, |
493 | | { |
494 | 0 | let exts = require_handshake_msg!( |
495 | | m, |
496 | | HandshakeType::EncryptedExtensions, |
497 | | HandshakePayload::EncryptedExtensions |
498 | 0 | )?; |
499 | 0 | debug!("TLS1.3 encrypted extensions: {exts:?}"); |
500 | 0 | self.transcript.add_message(&m); |
501 | | |
502 | 0 | validate_encrypted_extensions(cx.common, &self.hello, exts)?; |
503 | 0 | hs::process_alpn_protocol( |
504 | 0 | cx.common, |
505 | 0 | &self.hello.alpn_protocols, |
506 | 0 | exts.selected_protocol |
507 | 0 | .as_ref() |
508 | 0 | .map(|protocol| protocol.as_ref()), |
509 | 0 | )?; |
510 | 0 | hs::process_client_cert_type_extension( |
511 | 0 | cx.common, |
512 | 0 | &self.config, |
513 | 0 | exts.client_certificate_type.as_ref(), |
514 | 0 | )?; |
515 | 0 | hs::process_server_cert_type_extension( |
516 | 0 | cx.common, |
517 | 0 | &self.config, |
518 | 0 | exts.server_certificate_type.as_ref(), |
519 | 0 | )?; |
520 | | |
521 | 0 | let ech_retry_configs = match (cx.data.ech_status, &exts.encrypted_client_hello_ack) { |
522 | | // If we didn't offer ECH, or ECH was accepted, but the server sent an ECH encrypted |
523 | | // extension with retry configs, we must error. |
524 | | (EchStatus::NotOffered | EchStatus::Accepted, Some(_)) => { |
525 | 0 | return Err(cx.common.send_fatal_alert( |
526 | 0 | AlertDescription::UnsupportedExtension, |
527 | 0 | PeerMisbehaved::UnsolicitedEchExtension, |
528 | 0 | )); |
529 | | } |
530 | | // If we offered ECH, and it was rejected, store the retry configs (if any) from |
531 | | // the server's ECH extension. We will return them in an error produced at the end |
532 | | // of the handshake. |
533 | 0 | (EchStatus::Rejected, ext) => ext |
534 | 0 | .as_ref() |
535 | 0 | .map(|ext| ext.retry_configs.to_vec()), |
536 | 0 | _ => None, |
537 | | }; |
538 | | |
539 | | // QUIC transport parameters |
540 | 0 | if cx.common.is_quic() { |
541 | 0 | match exts |
542 | 0 | .transport_parameters |
543 | 0 | .as_ref() |
544 | 0 | .or(exts.transport_parameters_draft.as_ref()) |
545 | | { |
546 | 0 | Some(params) => cx.common.quic.params = Some(params.clone().into_vec()), |
547 | | None => { |
548 | 0 | return Err(cx |
549 | 0 | .common |
550 | 0 | .missing_extension(PeerMisbehaved::MissingQuicTransportParameters)); |
551 | | } |
552 | | } |
553 | 0 | } |
554 | | |
555 | 0 | match self.resuming_session { |
556 | 0 | Some(resuming_session) => { |
557 | 0 | let was_early_traffic = cx.common.early_traffic; |
558 | 0 | if was_early_traffic { |
559 | 0 | match exts.early_data_ack { |
560 | 0 | Some(()) => cx.data.early_data.accepted(), |
561 | 0 | None => { |
562 | 0 | cx.data.early_data.rejected(); |
563 | 0 | cx.common.early_traffic = false; |
564 | 0 | } |
565 | | } |
566 | 0 | } |
567 | | |
568 | 0 | if was_early_traffic && !cx.common.early_traffic { |
569 | 0 | // If no early traffic, set the encryption key for handshakes |
570 | 0 | self.key_schedule |
571 | 0 | .set_handshake_encrypter(cx.common); |
572 | 0 | } |
573 | | |
574 | 0 | cx.common.peer_certificates = Some( |
575 | 0 | resuming_session |
576 | 0 | .server_cert_chain() |
577 | 0 | .clone(), |
578 | 0 | ); |
579 | 0 | cx.common.handshake_kind = Some(HandshakeKind::Resumed); |
580 | | |
581 | | // We *don't* reverify the certificate chain here: resumption is a |
582 | | // continuation of the previous session in terms of security policy. |
583 | 0 | let cert_verified = verify::ServerCertVerified::assertion(); |
584 | 0 | let sig_verified = verify::HandshakeSignatureValid::assertion(); |
585 | 0 | Ok(Box::new(ExpectFinished { |
586 | 0 | config: self.config, |
587 | 0 | server_name: self.server_name, |
588 | 0 | randoms: self.randoms, |
589 | 0 | suite: self.suite, |
590 | 0 | transcript: self.transcript, |
591 | 0 | key_schedule: self.key_schedule, |
592 | 0 | client_auth: None, |
593 | 0 | cert_verified, |
594 | 0 | sig_verified, |
595 | 0 | ech_retry_configs, |
596 | 0 | })) |
597 | | } |
598 | | _ => { |
599 | 0 | if exts.early_data_ack.is_some() { |
600 | 0 | return Err(PeerMisbehaved::EarlyDataExtensionWithoutResumption.into()); |
601 | 0 | } |
602 | 0 | cx.common |
603 | 0 | .handshake_kind |
604 | 0 | .get_or_insert(HandshakeKind::Full); |
605 | | |
606 | 0 | Ok(if self.hello.offered_cert_compression { |
607 | 0 | Box::new(ExpectCertificateOrCompressedCertificateOrCertReq { |
608 | 0 | config: self.config, |
609 | 0 | server_name: self.server_name, |
610 | 0 | randoms: self.randoms, |
611 | 0 | suite: self.suite, |
612 | 0 | transcript: self.transcript, |
613 | 0 | key_schedule: self.key_schedule, |
614 | 0 | ech_retry_configs, |
615 | 0 | }) |
616 | | } else { |
617 | 0 | Box::new(ExpectCertificateOrCertReq { |
618 | 0 | config: self.config, |
619 | 0 | server_name: self.server_name, |
620 | 0 | randoms: self.randoms, |
621 | 0 | suite: self.suite, |
622 | 0 | transcript: self.transcript, |
623 | 0 | key_schedule: self.key_schedule, |
624 | 0 | ech_retry_configs, |
625 | 0 | }) |
626 | | }) |
627 | | } |
628 | | } |
629 | 0 | } |
630 | | |
631 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
632 | 0 | self |
633 | 0 | } |
634 | | } |
635 | | |
636 | | struct ExpectCertificateOrCompressedCertificateOrCertReq { |
637 | | config: Arc<ClientConfig>, |
638 | | server_name: ServerName<'static>, |
639 | | randoms: ConnectionRandoms, |
640 | | suite: &'static Tls13CipherSuite, |
641 | | transcript: HandshakeHash, |
642 | | key_schedule: KeyScheduleHandshake, |
643 | | ech_retry_configs: Option<Vec<EchConfigPayload>>, |
644 | | } |
645 | | |
646 | | impl State<ClientConnectionData> for ExpectCertificateOrCompressedCertificateOrCertReq { |
647 | 0 | fn handle<'m>( |
648 | 0 | self: Box<Self>, |
649 | 0 | cx: &mut ClientContext<'_>, |
650 | 0 | m: Message<'m>, |
651 | 0 | ) -> hs::NextStateOrError<'m> |
652 | 0 | where |
653 | 0 | Self: 'm, |
654 | | { |
655 | 0 | match m.payload { |
656 | | MessagePayload::Handshake { |
657 | | parsed: HandshakeMessagePayload(HandshakePayload::CertificateTls13(..)), |
658 | | .. |
659 | 0 | } => Box::new(ExpectCertificate { |
660 | 0 | config: self.config, |
661 | 0 | server_name: self.server_name, |
662 | 0 | randoms: self.randoms, |
663 | 0 | suite: self.suite, |
664 | 0 | transcript: self.transcript, |
665 | 0 | key_schedule: self.key_schedule, |
666 | 0 | client_auth: None, |
667 | 0 | message_already_in_transcript: false, |
668 | 0 | ech_retry_configs: self.ech_retry_configs, |
669 | 0 | }) |
670 | 0 | .handle(cx, m), |
671 | | MessagePayload::Handshake { |
672 | | parsed: HandshakeMessagePayload(HandshakePayload::CompressedCertificate(..)), |
673 | | .. |
674 | 0 | } => Box::new(ExpectCompressedCertificate { |
675 | 0 | config: self.config, |
676 | 0 | server_name: self.server_name, |
677 | 0 | randoms: self.randoms, |
678 | 0 | suite: self.suite, |
679 | 0 | transcript: self.transcript, |
680 | 0 | key_schedule: self.key_schedule, |
681 | 0 | client_auth: None, |
682 | 0 | ech_retry_configs: self.ech_retry_configs, |
683 | 0 | }) |
684 | 0 | .handle(cx, m), |
685 | | MessagePayload::Handshake { |
686 | | parsed: HandshakeMessagePayload(HandshakePayload::CertificateRequestTls13(..)), |
687 | | .. |
688 | 0 | } => Box::new(ExpectCertificateRequest { |
689 | 0 | config: self.config, |
690 | 0 | server_name: self.server_name, |
691 | 0 | randoms: self.randoms, |
692 | 0 | suite: self.suite, |
693 | 0 | transcript: self.transcript, |
694 | 0 | key_schedule: self.key_schedule, |
695 | 0 | offered_cert_compression: true, |
696 | 0 | ech_retry_configs: self.ech_retry_configs, |
697 | 0 | }) |
698 | 0 | .handle(cx, m), |
699 | 0 | payload => Err(inappropriate_handshake_message( |
700 | 0 | &payload, |
701 | 0 | &[ContentType::Handshake], |
702 | 0 | &[ |
703 | 0 | HandshakeType::Certificate, |
704 | 0 | HandshakeType::CertificateRequest, |
705 | 0 | HandshakeType::CompressedCertificate, |
706 | 0 | ], |
707 | 0 | )), |
708 | | } |
709 | 0 | } |
710 | | |
711 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
712 | 0 | self |
713 | 0 | } |
714 | | } |
715 | | |
716 | | struct ExpectCertificateOrCompressedCertificate { |
717 | | config: Arc<ClientConfig>, |
718 | | server_name: ServerName<'static>, |
719 | | randoms: ConnectionRandoms, |
720 | | suite: &'static Tls13CipherSuite, |
721 | | transcript: HandshakeHash, |
722 | | key_schedule: KeyScheduleHandshake, |
723 | | client_auth: Option<ClientAuthDetails>, |
724 | | ech_retry_configs: Option<Vec<EchConfigPayload>>, |
725 | | } |
726 | | |
727 | | impl State<ClientConnectionData> for ExpectCertificateOrCompressedCertificate { |
728 | 0 | fn handle<'m>( |
729 | 0 | self: Box<Self>, |
730 | 0 | cx: &mut ClientContext<'_>, |
731 | 0 | m: Message<'m>, |
732 | 0 | ) -> hs::NextStateOrError<'m> |
733 | 0 | where |
734 | 0 | Self: 'm, |
735 | | { |
736 | 0 | match m.payload { |
737 | | MessagePayload::Handshake { |
738 | | parsed: HandshakeMessagePayload(HandshakePayload::CertificateTls13(..)), |
739 | | .. |
740 | 0 | } => Box::new(ExpectCertificate { |
741 | 0 | config: self.config, |
742 | 0 | server_name: self.server_name, |
743 | 0 | randoms: self.randoms, |
744 | 0 | suite: self.suite, |
745 | 0 | transcript: self.transcript, |
746 | 0 | key_schedule: self.key_schedule, |
747 | 0 | client_auth: self.client_auth, |
748 | 0 | message_already_in_transcript: false, |
749 | 0 | ech_retry_configs: self.ech_retry_configs, |
750 | 0 | }) |
751 | 0 | .handle(cx, m), |
752 | | MessagePayload::Handshake { |
753 | | parsed: HandshakeMessagePayload(HandshakePayload::CompressedCertificate(..)), |
754 | | .. |
755 | 0 | } => Box::new(ExpectCompressedCertificate { |
756 | 0 | config: self.config, |
757 | 0 | server_name: self.server_name, |
758 | 0 | randoms: self.randoms, |
759 | 0 | suite: self.suite, |
760 | 0 | transcript: self.transcript, |
761 | 0 | key_schedule: self.key_schedule, |
762 | 0 | client_auth: self.client_auth, |
763 | 0 | ech_retry_configs: self.ech_retry_configs, |
764 | 0 | }) |
765 | 0 | .handle(cx, m), |
766 | 0 | payload => Err(inappropriate_handshake_message( |
767 | 0 | &payload, |
768 | 0 | &[ContentType::Handshake], |
769 | 0 | &[ |
770 | 0 | HandshakeType::Certificate, |
771 | 0 | HandshakeType::CompressedCertificate, |
772 | 0 | ], |
773 | 0 | )), |
774 | | } |
775 | 0 | } |
776 | | |
777 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
778 | 0 | self |
779 | 0 | } |
780 | | } |
781 | | |
782 | | struct ExpectCertificateOrCertReq { |
783 | | config: Arc<ClientConfig>, |
784 | | server_name: ServerName<'static>, |
785 | | randoms: ConnectionRandoms, |
786 | | suite: &'static Tls13CipherSuite, |
787 | | transcript: HandshakeHash, |
788 | | key_schedule: KeyScheduleHandshake, |
789 | | ech_retry_configs: Option<Vec<EchConfigPayload>>, |
790 | | } |
791 | | |
792 | | impl State<ClientConnectionData> for ExpectCertificateOrCertReq { |
793 | 0 | fn handle<'m>( |
794 | 0 | self: Box<Self>, |
795 | 0 | cx: &mut ClientContext<'_>, |
796 | 0 | m: Message<'m>, |
797 | 0 | ) -> hs::NextStateOrError<'m> |
798 | 0 | where |
799 | 0 | Self: 'm, |
800 | | { |
801 | 0 | match m.payload { |
802 | | MessagePayload::Handshake { |
803 | | parsed: HandshakeMessagePayload(HandshakePayload::CertificateTls13(..)), |
804 | | .. |
805 | 0 | } => Box::new(ExpectCertificate { |
806 | 0 | config: self.config, |
807 | 0 | server_name: self.server_name, |
808 | 0 | randoms: self.randoms, |
809 | 0 | suite: self.suite, |
810 | 0 | transcript: self.transcript, |
811 | 0 | key_schedule: self.key_schedule, |
812 | 0 | client_auth: None, |
813 | 0 | message_already_in_transcript: false, |
814 | 0 | ech_retry_configs: self.ech_retry_configs, |
815 | 0 | }) |
816 | 0 | .handle(cx, m), |
817 | | MessagePayload::Handshake { |
818 | | parsed: HandshakeMessagePayload(HandshakePayload::CertificateRequestTls13(..)), |
819 | | .. |
820 | 0 | } => Box::new(ExpectCertificateRequest { |
821 | 0 | config: self.config, |
822 | 0 | server_name: self.server_name, |
823 | 0 | randoms: self.randoms, |
824 | 0 | suite: self.suite, |
825 | 0 | transcript: self.transcript, |
826 | 0 | key_schedule: self.key_schedule, |
827 | 0 | offered_cert_compression: false, |
828 | 0 | ech_retry_configs: self.ech_retry_configs, |
829 | 0 | }) |
830 | 0 | .handle(cx, m), |
831 | 0 | payload => Err(inappropriate_handshake_message( |
832 | 0 | &payload, |
833 | 0 | &[ContentType::Handshake], |
834 | 0 | &[ |
835 | 0 | HandshakeType::Certificate, |
836 | 0 | HandshakeType::CertificateRequest, |
837 | 0 | ], |
838 | 0 | )), |
839 | | } |
840 | 0 | } |
841 | | |
842 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
843 | 0 | self |
844 | 0 | } |
845 | | } |
846 | | |
847 | | // TLS1.3 version of CertificateRequest handling. We then move to expecting the server |
848 | | // Certificate. Unfortunately the CertificateRequest type changed in an annoying way |
849 | | // in TLS1.3. |
850 | | struct ExpectCertificateRequest { |
851 | | config: Arc<ClientConfig>, |
852 | | server_name: ServerName<'static>, |
853 | | randoms: ConnectionRandoms, |
854 | | suite: &'static Tls13CipherSuite, |
855 | | transcript: HandshakeHash, |
856 | | key_schedule: KeyScheduleHandshake, |
857 | | offered_cert_compression: bool, |
858 | | ech_retry_configs: Option<Vec<EchConfigPayload>>, |
859 | | } |
860 | | |
861 | | impl State<ClientConnectionData> for ExpectCertificateRequest { |
862 | 0 | fn handle<'m>( |
863 | 0 | mut self: Box<Self>, |
864 | 0 | cx: &mut ClientContext<'_>, |
865 | 0 | m: Message<'m>, |
866 | 0 | ) -> hs::NextStateOrError<'m> |
867 | 0 | where |
868 | 0 | Self: 'm, |
869 | | { |
870 | 0 | let certreq = &require_handshake_msg!( |
871 | | m, |
872 | | HandshakeType::CertificateRequest, |
873 | | HandshakePayload::CertificateRequestTls13 |
874 | 0 | )?; |
875 | 0 | self.transcript.add_message(&m); |
876 | 0 | debug!("Got CertificateRequest {certreq:?}"); |
877 | | |
878 | | // Fortunately the problems here in TLS1.2 and prior are corrected in |
879 | | // TLS1.3. |
880 | | |
881 | | // Must be empty during handshake. |
882 | 0 | if !certreq.context.0.is_empty() { |
883 | 0 | warn!("Server sent non-empty certreq context"); |
884 | 0 | return Err(cx.common.send_fatal_alert( |
885 | 0 | AlertDescription::DecodeError, |
886 | 0 | InvalidMessage::InvalidCertRequest, |
887 | 0 | )); |
888 | 0 | } |
889 | | |
890 | 0 | let compat_sigschemes = certreq |
891 | 0 | .extensions |
892 | 0 | .signature_algorithms |
893 | 0 | .as_deref() |
894 | 0 | .unwrap_or_default() |
895 | 0 | .iter() |
896 | 0 | .cloned() |
897 | 0 | .filter(SignatureScheme::supported_in_tls13) |
898 | 0 | .collect::<Vec<SignatureScheme>>(); |
899 | | |
900 | 0 | if compat_sigschemes.is_empty() { |
901 | 0 | return Err(cx.common.send_fatal_alert( |
902 | 0 | AlertDescription::HandshakeFailure, |
903 | 0 | PeerIncompatible::NoCertificateRequestSignatureSchemesInCommon, |
904 | 0 | )); |
905 | 0 | } |
906 | | |
907 | 0 | let compat_compressor = certreq |
908 | 0 | .extensions |
909 | 0 | .certificate_compression_algorithms |
910 | 0 | .as_deref() |
911 | 0 | .and_then(|offered| { |
912 | 0 | self.config |
913 | 0 | .cert_compressors |
914 | 0 | .iter() |
915 | 0 | .find(|compressor| offered.contains(&compressor.algorithm())) |
916 | 0 | }) |
917 | 0 | .cloned(); |
918 | | |
919 | 0 | let client_auth = ClientAuthDetails::resolve( |
920 | 0 | self.config |
921 | 0 | .client_auth_cert_resolver |
922 | 0 | .as_ref(), |
923 | 0 | certreq |
924 | 0 | .extensions |
925 | 0 | .authority_names |
926 | 0 | .as_deref(), |
927 | 0 | &compat_sigschemes, |
928 | 0 | Some(certreq.context.0.clone()), |
929 | 0 | compat_compressor, |
930 | | ); |
931 | | |
932 | 0 | Ok(if self.offered_cert_compression { |
933 | 0 | Box::new(ExpectCertificateOrCompressedCertificate { |
934 | 0 | config: self.config, |
935 | 0 | server_name: self.server_name, |
936 | 0 | randoms: self.randoms, |
937 | 0 | suite: self.suite, |
938 | 0 | transcript: self.transcript, |
939 | 0 | key_schedule: self.key_schedule, |
940 | 0 | client_auth: Some(client_auth), |
941 | 0 | ech_retry_configs: self.ech_retry_configs, |
942 | 0 | }) |
943 | | } else { |
944 | 0 | Box::new(ExpectCertificate { |
945 | 0 | config: self.config, |
946 | 0 | server_name: self.server_name, |
947 | 0 | randoms: self.randoms, |
948 | 0 | suite: self.suite, |
949 | 0 | transcript: self.transcript, |
950 | 0 | key_schedule: self.key_schedule, |
951 | 0 | client_auth: Some(client_auth), |
952 | 0 | message_already_in_transcript: false, |
953 | 0 | ech_retry_configs: self.ech_retry_configs, |
954 | 0 | }) |
955 | | }) |
956 | 0 | } |
957 | | |
958 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
959 | 0 | self |
960 | 0 | } |
961 | | } |
962 | | |
963 | | struct ExpectCompressedCertificate { |
964 | | config: Arc<ClientConfig>, |
965 | | server_name: ServerName<'static>, |
966 | | randoms: ConnectionRandoms, |
967 | | suite: &'static Tls13CipherSuite, |
968 | | transcript: HandshakeHash, |
969 | | key_schedule: KeyScheduleHandshake, |
970 | | client_auth: Option<ClientAuthDetails>, |
971 | | ech_retry_configs: Option<Vec<EchConfigPayload>>, |
972 | | } |
973 | | |
974 | | impl State<ClientConnectionData> for ExpectCompressedCertificate { |
975 | 0 | fn handle<'m>( |
976 | 0 | mut self: Box<Self>, |
977 | 0 | cx: &mut ClientContext<'_>, |
978 | 0 | m: Message<'m>, |
979 | 0 | ) -> hs::NextStateOrError<'m> |
980 | 0 | where |
981 | 0 | Self: 'm, |
982 | | { |
983 | 0 | self.transcript.add_message(&m); |
984 | 0 | let compressed_cert = require_handshake_msg_move!( |
985 | | m, |
986 | | HandshakeType::CompressedCertificate, |
987 | | HandshakePayload::CompressedCertificate |
988 | 0 | )?; |
989 | | |
990 | 0 | let selected_decompressor = self |
991 | 0 | .config |
992 | 0 | .cert_decompressors |
993 | 0 | .iter() |
994 | 0 | .find(|item| item.algorithm() == compressed_cert.alg); |
995 | | |
996 | 0 | let Some(decompressor) = selected_decompressor else { |
997 | 0 | return Err(cx.common.send_fatal_alert( |
998 | 0 | AlertDescription::BadCertificate, |
999 | 0 | PeerMisbehaved::SelectedUnofferedCertCompression, |
1000 | 0 | )); |
1001 | | }; |
1002 | | |
1003 | 0 | if compressed_cert.uncompressed_len as usize > CERTIFICATE_MAX_SIZE_LIMIT { |
1004 | 0 | return Err(cx.common.send_fatal_alert( |
1005 | 0 | AlertDescription::BadCertificate, |
1006 | 0 | InvalidMessage::MessageTooLarge, |
1007 | 0 | )); |
1008 | 0 | } |
1009 | | |
1010 | 0 | let mut decompress_buffer = vec![0u8; compressed_cert.uncompressed_len as usize]; |
1011 | | if let Err(compress::DecompressionFailed) = |
1012 | 0 | decompressor.decompress(compressed_cert.compressed.0.bytes(), &mut decompress_buffer) |
1013 | | { |
1014 | 0 | return Err(cx.common.send_fatal_alert( |
1015 | 0 | AlertDescription::BadCertificate, |
1016 | 0 | PeerMisbehaved::InvalidCertCompression, |
1017 | 0 | )); |
1018 | 0 | } |
1019 | | |
1020 | 0 | let cert_payload = |
1021 | 0 | match CertificatePayloadTls13::read(&mut Reader::init(&decompress_buffer)) { |
1022 | 0 | Ok(cm) => cm, |
1023 | 0 | Err(err) => { |
1024 | 0 | return Err(cx |
1025 | 0 | .common |
1026 | 0 | .send_fatal_alert(AlertDescription::BadCertificate, err)); |
1027 | | } |
1028 | | }; |
1029 | 0 | trace!( |
1030 | 0 | "Server certificate decompressed using {:?} ({} bytes -> {})", |
1031 | | compressed_cert.alg, |
1032 | 0 | compressed_cert |
1033 | 0 | .compressed |
1034 | 0 | .0 |
1035 | 0 | .bytes() |
1036 | 0 | .len(), |
1037 | | compressed_cert.uncompressed_len, |
1038 | | ); |
1039 | | |
1040 | 0 | let m = Message { |
1041 | 0 | version: ProtocolVersion::TLSv1_3, |
1042 | 0 | payload: MessagePayload::handshake(HandshakeMessagePayload( |
1043 | 0 | HandshakePayload::CertificateTls13(cert_payload.into_owned()), |
1044 | 0 | )), |
1045 | 0 | }; |
1046 | | |
1047 | 0 | Box::new(ExpectCertificate { |
1048 | 0 | config: self.config, |
1049 | 0 | server_name: self.server_name, |
1050 | 0 | randoms: self.randoms, |
1051 | 0 | suite: self.suite, |
1052 | 0 | transcript: self.transcript, |
1053 | 0 | key_schedule: self.key_schedule, |
1054 | 0 | client_auth: self.client_auth, |
1055 | 0 | message_already_in_transcript: true, |
1056 | 0 | ech_retry_configs: self.ech_retry_configs, |
1057 | 0 | }) |
1058 | 0 | .handle(cx, m) |
1059 | 0 | } |
1060 | | |
1061 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
1062 | 0 | self |
1063 | 0 | } |
1064 | | } |
1065 | | |
1066 | | struct ExpectCertificate { |
1067 | | config: Arc<ClientConfig>, |
1068 | | server_name: ServerName<'static>, |
1069 | | randoms: ConnectionRandoms, |
1070 | | suite: &'static Tls13CipherSuite, |
1071 | | transcript: HandshakeHash, |
1072 | | key_schedule: KeyScheduleHandshake, |
1073 | | client_auth: Option<ClientAuthDetails>, |
1074 | | message_already_in_transcript: bool, |
1075 | | ech_retry_configs: Option<Vec<EchConfigPayload>>, |
1076 | | } |
1077 | | |
1078 | | impl State<ClientConnectionData> for ExpectCertificate { |
1079 | 0 | fn handle<'m>( |
1080 | 0 | mut self: Box<Self>, |
1081 | 0 | cx: &mut ClientContext<'_>, |
1082 | 0 | m: Message<'m>, |
1083 | 0 | ) -> hs::NextStateOrError<'m> |
1084 | 0 | where |
1085 | 0 | Self: 'm, |
1086 | | { |
1087 | 0 | if !self.message_already_in_transcript { |
1088 | 0 | self.transcript.add_message(&m); |
1089 | 0 | } |
1090 | 0 | let cert_chain = require_handshake_msg_move!( |
1091 | | m, |
1092 | | HandshakeType::Certificate, |
1093 | | HandshakePayload::CertificateTls13 |
1094 | 0 | )?; |
1095 | | |
1096 | | // This is only non-empty for client auth. |
1097 | 0 | if !cert_chain.context.0.is_empty() { |
1098 | 0 | return Err(cx.common.send_fatal_alert( |
1099 | 0 | AlertDescription::DecodeError, |
1100 | 0 | InvalidMessage::InvalidCertRequest, |
1101 | 0 | )); |
1102 | 0 | } |
1103 | | |
1104 | 0 | let end_entity_ocsp = cert_chain.end_entity_ocsp().to_vec(); |
1105 | 0 | let server_cert = ServerCertDetails::new( |
1106 | 0 | cert_chain |
1107 | 0 | .into_certificate_chain() |
1108 | 0 | .into_owned(), |
1109 | 0 | end_entity_ocsp, |
1110 | | ); |
1111 | | |
1112 | 0 | Ok(Box::new(ExpectCertificateVerify { |
1113 | 0 | config: self.config, |
1114 | 0 | server_name: self.server_name, |
1115 | 0 | randoms: self.randoms, |
1116 | 0 | suite: self.suite, |
1117 | 0 | transcript: self.transcript, |
1118 | 0 | key_schedule: self.key_schedule, |
1119 | 0 | server_cert, |
1120 | 0 | client_auth: self.client_auth, |
1121 | 0 | ech_retry_configs: self.ech_retry_configs, |
1122 | 0 | })) |
1123 | 0 | } |
1124 | | |
1125 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
1126 | 0 | self |
1127 | 0 | } |
1128 | | } |
1129 | | |
1130 | | // --- TLS1.3 CertificateVerify --- |
1131 | | struct ExpectCertificateVerify<'a> { |
1132 | | config: Arc<ClientConfig>, |
1133 | | server_name: ServerName<'static>, |
1134 | | randoms: ConnectionRandoms, |
1135 | | suite: &'static Tls13CipherSuite, |
1136 | | transcript: HandshakeHash, |
1137 | | key_schedule: KeyScheduleHandshake, |
1138 | | server_cert: ServerCertDetails<'a>, |
1139 | | client_auth: Option<ClientAuthDetails>, |
1140 | | ech_retry_configs: Option<Vec<EchConfigPayload>>, |
1141 | | } |
1142 | | |
1143 | | impl State<ClientConnectionData> for ExpectCertificateVerify<'_> { |
1144 | 0 | fn handle<'m>( |
1145 | 0 | mut self: Box<Self>, |
1146 | 0 | cx: &mut ClientContext<'_>, |
1147 | 0 | m: Message<'m>, |
1148 | 0 | ) -> hs::NextStateOrError<'m> |
1149 | 0 | where |
1150 | 0 | Self: 'm, |
1151 | | { |
1152 | 0 | let cert_verify = require_handshake_msg!( |
1153 | | m, |
1154 | | HandshakeType::CertificateVerify, |
1155 | | HandshakePayload::CertificateVerify |
1156 | 0 | )?; |
1157 | | |
1158 | 0 | trace!("Server cert is {:?}", self.server_cert.cert_chain); |
1159 | | |
1160 | | // 1. Verify the certificate chain. |
1161 | 0 | let (end_entity, intermediates) = self |
1162 | 0 | .server_cert |
1163 | 0 | .cert_chain |
1164 | 0 | .split_first() |
1165 | 0 | .ok_or(Error::NoCertificatesPresented)?; |
1166 | | |
1167 | 0 | let now = self.config.current_time()?; |
1168 | | |
1169 | 0 | let cert_verified = self |
1170 | 0 | .config |
1171 | 0 | .verifier |
1172 | 0 | .verify_server_cert( |
1173 | 0 | end_entity, |
1174 | 0 | intermediates, |
1175 | 0 | &self.server_name, |
1176 | 0 | &self.server_cert.ocsp_response, |
1177 | 0 | now, |
1178 | 0 | ) |
1179 | 0 | .map_err(|err| { |
1180 | 0 | cx.common |
1181 | 0 | .send_cert_verify_error_alert(err) |
1182 | 0 | })?; |
1183 | | |
1184 | | // 2. Verify their signature on the handshake. |
1185 | 0 | let handshake_hash = self.transcript.current_hash(); |
1186 | 0 | let sig_verified = self |
1187 | 0 | .config |
1188 | 0 | .verifier |
1189 | 0 | .verify_tls13_signature( |
1190 | 0 | construct_server_verify_message(&handshake_hash).as_ref(), |
1191 | 0 | end_entity, |
1192 | 0 | cert_verify, |
1193 | 0 | ) |
1194 | 0 | .map_err(|err| { |
1195 | 0 | cx.common |
1196 | 0 | .send_cert_verify_error_alert(err) |
1197 | 0 | })?; |
1198 | | |
1199 | 0 | cx.common.peer_certificates = Some(self.server_cert.cert_chain.into_owned()); |
1200 | 0 | self.transcript.add_message(&m); |
1201 | | |
1202 | 0 | Ok(Box::new(ExpectFinished { |
1203 | 0 | config: self.config, |
1204 | 0 | server_name: self.server_name, |
1205 | 0 | randoms: self.randoms, |
1206 | 0 | suite: self.suite, |
1207 | 0 | transcript: self.transcript, |
1208 | 0 | key_schedule: self.key_schedule, |
1209 | 0 | client_auth: self.client_auth, |
1210 | 0 | cert_verified, |
1211 | 0 | sig_verified, |
1212 | 0 | ech_retry_configs: self.ech_retry_configs, |
1213 | 0 | })) |
1214 | 0 | } |
1215 | | |
1216 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
1217 | 0 | Box::new(ExpectCertificateVerify { |
1218 | 0 | config: self.config, |
1219 | 0 | server_name: self.server_name, |
1220 | 0 | randoms: self.randoms, |
1221 | 0 | suite: self.suite, |
1222 | 0 | transcript: self.transcript, |
1223 | 0 | key_schedule: self.key_schedule, |
1224 | 0 | server_cert: self.server_cert.into_owned(), |
1225 | 0 | client_auth: self.client_auth, |
1226 | 0 | ech_retry_configs: self.ech_retry_configs, |
1227 | 0 | }) |
1228 | 0 | } |
1229 | | } |
1230 | | |
1231 | 0 | fn emit_compressed_certificate_tls13( |
1232 | 0 | flight: &mut HandshakeFlightTls13<'_>, |
1233 | 0 | certkey: &CertifiedKey, |
1234 | 0 | auth_context: Option<Vec<u8>>, |
1235 | 0 | compressor: &dyn compress::CertCompressor, |
1236 | 0 | config: &ClientConfig, |
1237 | 0 | ) { |
1238 | 0 | let mut cert_payload = CertificatePayloadTls13::new(certkey.cert.iter(), None); |
1239 | 0 | cert_payload.context = PayloadU8::new(auth_context.clone().unwrap_or_default()); |
1240 | | |
1241 | 0 | let Ok(compressed) = config |
1242 | 0 | .cert_compression_cache |
1243 | 0 | .compression_for(compressor, &cert_payload) |
1244 | | else { |
1245 | 0 | return emit_certificate_tls13(flight, Some(certkey), auth_context); |
1246 | | }; |
1247 | | |
1248 | 0 | flight.add(HandshakeMessagePayload( |
1249 | 0 | HandshakePayload::CompressedCertificate(compressed.compressed_cert_payload()), |
1250 | 0 | )); |
1251 | 0 | } |
1252 | | |
1253 | 0 | fn emit_certificate_tls13( |
1254 | 0 | flight: &mut HandshakeFlightTls13<'_>, |
1255 | 0 | certkey: Option<&CertifiedKey>, |
1256 | 0 | auth_context: Option<Vec<u8>>, |
1257 | 0 | ) { |
1258 | 0 | let certs = certkey |
1259 | 0 | .map(|ck| ck.cert.as_ref()) |
1260 | 0 | .unwrap_or(&[][..]); |
1261 | 0 | let mut cert_payload = CertificatePayloadTls13::new(certs.iter(), None); |
1262 | 0 | cert_payload.context = PayloadU8::new(auth_context.unwrap_or_default()); |
1263 | | |
1264 | 0 | flight.add(HandshakeMessagePayload(HandshakePayload::CertificateTls13( |
1265 | 0 | cert_payload, |
1266 | 0 | ))); |
1267 | 0 | } |
1268 | | |
1269 | 0 | fn emit_certverify_tls13( |
1270 | 0 | flight: &mut HandshakeFlightTls13<'_>, |
1271 | 0 | signer: &dyn Signer, |
1272 | 0 | ) -> Result<(), Error> { |
1273 | 0 | let message = construct_client_verify_message(&flight.transcript.current_hash()); |
1274 | | |
1275 | 0 | let scheme = signer.scheme(); |
1276 | 0 | let sig = signer.sign(message.as_ref())?; |
1277 | 0 | let dss = DigitallySignedStruct::new(scheme, sig); |
1278 | | |
1279 | 0 | flight.add(HandshakeMessagePayload( |
1280 | 0 | HandshakePayload::CertificateVerify(dss), |
1281 | 0 | )); |
1282 | 0 | Ok(()) |
1283 | 0 | } |
1284 | | |
1285 | 0 | fn emit_finished_tls13(flight: &mut HandshakeFlightTls13<'_>, verify_data: &crypto::hmac::Tag) { |
1286 | 0 | let verify_data_payload = Payload::new(verify_data.as_ref()); |
1287 | | |
1288 | 0 | flight.add(HandshakeMessagePayload(HandshakePayload::Finished( |
1289 | 0 | verify_data_payload, |
1290 | 0 | ))); |
1291 | 0 | } |
1292 | | |
1293 | 0 | fn emit_end_of_early_data_tls13(transcript: &mut HandshakeHash, common: &mut CommonState) { |
1294 | 0 | if common.is_quic() { |
1295 | 0 | return; |
1296 | 0 | } |
1297 | | |
1298 | 0 | let m = Message { |
1299 | 0 | version: ProtocolVersion::TLSv1_3, |
1300 | 0 | payload: MessagePayload::handshake(HandshakeMessagePayload( |
1301 | 0 | HandshakePayload::EndOfEarlyData, |
1302 | 0 | )), |
1303 | 0 | }; |
1304 | | |
1305 | 0 | transcript.add_message(&m); |
1306 | 0 | common.send_msg(m, true); |
1307 | 0 | } |
1308 | | |
1309 | | struct ExpectFinished { |
1310 | | config: Arc<ClientConfig>, |
1311 | | server_name: ServerName<'static>, |
1312 | | randoms: ConnectionRandoms, |
1313 | | suite: &'static Tls13CipherSuite, |
1314 | | transcript: HandshakeHash, |
1315 | | key_schedule: KeyScheduleHandshake, |
1316 | | client_auth: Option<ClientAuthDetails>, |
1317 | | cert_verified: verify::ServerCertVerified, |
1318 | | sig_verified: verify::HandshakeSignatureValid, |
1319 | | ech_retry_configs: Option<Vec<EchConfigPayload>>, |
1320 | | } |
1321 | | |
1322 | | impl State<ClientConnectionData> for ExpectFinished { |
1323 | 0 | fn handle<'m>( |
1324 | 0 | self: Box<Self>, |
1325 | 0 | cx: &mut ClientContext<'_>, |
1326 | 0 | m: Message<'m>, |
1327 | 0 | ) -> hs::NextStateOrError<'m> |
1328 | 0 | where |
1329 | 0 | Self: 'm, |
1330 | | { |
1331 | 0 | let mut st = *self; |
1332 | 0 | let finished = |
1333 | 0 | require_handshake_msg!(m, HandshakeType::Finished, HandshakePayload::Finished)?; |
1334 | | |
1335 | 0 | let handshake_hash = st.transcript.current_hash(); |
1336 | 0 | let expect_verify_data = st |
1337 | 0 | .key_schedule |
1338 | 0 | .sign_server_finish(&handshake_hash); |
1339 | | |
1340 | 0 | let fin = match ConstantTimeEq::ct_eq(expect_verify_data.as_ref(), finished.bytes()).into() |
1341 | | { |
1342 | 0 | true => verify::FinishedMessageVerified::assertion(), |
1343 | | false => { |
1344 | 0 | return Err(cx |
1345 | 0 | .common |
1346 | 0 | .send_fatal_alert(AlertDescription::DecryptError, Error::DecryptError)); |
1347 | | } |
1348 | | }; |
1349 | | |
1350 | 0 | st.transcript.add_message(&m); |
1351 | | |
1352 | 0 | let hash_after_handshake = st.transcript.current_hash(); |
1353 | | /* The EndOfEarlyData message to server is still encrypted with early data keys, |
1354 | | * but appears in the transcript after the server Finished. */ |
1355 | 0 | if cx.common.early_traffic { |
1356 | 0 | emit_end_of_early_data_tls13(&mut st.transcript, cx.common); |
1357 | 0 | cx.common.early_traffic = false; |
1358 | 0 | cx.data.early_data.finished(); |
1359 | 0 | st.key_schedule |
1360 | 0 | .set_handshake_encrypter(cx.common); |
1361 | 0 | } |
1362 | | |
1363 | 0 | let mut flight = HandshakeFlightTls13::new(&mut st.transcript); |
1364 | | |
1365 | | /* Send our authentication/finished messages. These are still encrypted |
1366 | | * with our handshake keys. */ |
1367 | 0 | if let Some(client_auth) = st.client_auth { |
1368 | 0 | match client_auth { |
1369 | | ClientAuthDetails::Empty { |
1370 | 0 | auth_context_tls13: auth_context, |
1371 | 0 | } => { |
1372 | 0 | emit_certificate_tls13(&mut flight, None, auth_context); |
1373 | 0 | } |
1374 | | ClientAuthDetails::Verify { |
1375 | 0 | auth_context_tls13: auth_context, |
1376 | | .. |
1377 | 0 | } if cx.data.ech_status == EchStatus::Rejected => { |
1378 | 0 | // If ECH was offered, and rejected, we MUST respond with |
1379 | 0 | // an empty certificate message. |
1380 | 0 | emit_certificate_tls13(&mut flight, None, auth_context); |
1381 | 0 | } |
1382 | | ClientAuthDetails::Verify { |
1383 | 0 | certkey, |
1384 | 0 | signer, |
1385 | 0 | auth_context_tls13: auth_context, |
1386 | 0 | compressor, |
1387 | | } => { |
1388 | 0 | if let Some(compressor) = compressor { |
1389 | 0 | emit_compressed_certificate_tls13( |
1390 | 0 | &mut flight, |
1391 | 0 | &certkey, |
1392 | 0 | auth_context, |
1393 | 0 | compressor, |
1394 | 0 | &st.config, |
1395 | 0 | ); |
1396 | 0 | } else { |
1397 | 0 | emit_certificate_tls13(&mut flight, Some(&certkey), auth_context); |
1398 | 0 | } |
1399 | 0 | emit_certverify_tls13(&mut flight, signer.as_ref())?; |
1400 | | } |
1401 | | } |
1402 | 0 | } |
1403 | | |
1404 | 0 | let (key_schedule_pre_finished, verify_data) = st |
1405 | 0 | .key_schedule |
1406 | 0 | .into_pre_finished_client_traffic( |
1407 | 0 | hash_after_handshake, |
1408 | 0 | flight.transcript.current_hash(), |
1409 | 0 | &*st.config.key_log, |
1410 | 0 | &st.randoms.client, |
1411 | 0 | ); |
1412 | | |
1413 | 0 | emit_finished_tls13(&mut flight, &verify_data); |
1414 | 0 | flight.finish(cx.common); |
1415 | | |
1416 | | /* We're now sure this server supports TLS1.3. But if we run out of TLS1.3 tickets |
1417 | | * when connecting to it again, we definitely don't want to attempt a TLS1.2 resumption. */ |
1418 | 0 | st.config |
1419 | 0 | .resumption |
1420 | 0 | .store |
1421 | 0 | .remove_tls12_session(&st.server_name); |
1422 | | |
1423 | | /* Now move to our application traffic keys. */ |
1424 | 0 | cx.common.check_aligned_handshake()?; |
1425 | 0 | let (key_schedule, resumption) = |
1426 | 0 | key_schedule_pre_finished.into_traffic(cx.common, st.transcript.current_hash()); |
1427 | 0 | cx.common |
1428 | 0 | .start_traffic(&mut cx.sendable_plaintext); |
1429 | | |
1430 | | // Now that we've reached the end of the normal handshake we must enforce ECH acceptance by |
1431 | | // sending an alert and returning an error (potentially with retry configs) if the server |
1432 | | // did not accept our ECH offer. |
1433 | 0 | if cx.data.ech_status == EchStatus::Rejected { |
1434 | 0 | return Err(ech::fatal_alert_required(st.ech_retry_configs, cx.common)); |
1435 | 0 | } |
1436 | | |
1437 | 0 | let st = ExpectTraffic { |
1438 | 0 | config: st.config.clone(), |
1439 | 0 | session_storage: st.config.resumption.store.clone(), |
1440 | 0 | server_name: st.server_name, |
1441 | 0 | suite: st.suite, |
1442 | 0 | key_schedule, |
1443 | 0 | resumption, |
1444 | 0 | _cert_verified: st.cert_verified, |
1445 | 0 | _sig_verified: st.sig_verified, |
1446 | 0 | _fin_verified: fin, |
1447 | 0 | }; |
1448 | | |
1449 | 0 | Ok(match cx.common.is_quic() { |
1450 | 0 | true => Box::new(ExpectQuicTraffic(st)), |
1451 | 0 | false => Box::new(st), |
1452 | | }) |
1453 | 0 | } |
1454 | | |
1455 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
1456 | 0 | self |
1457 | 0 | } |
1458 | | } |
1459 | | |
1460 | | // -- Traffic transit state (TLS1.3) -- |
1461 | | // In this state we can be sent tickets, key updates, |
1462 | | // and application data. |
1463 | | struct ExpectTraffic { |
1464 | | config: Arc<ClientConfig>, |
1465 | | session_storage: Arc<dyn ClientSessionStore>, |
1466 | | server_name: ServerName<'static>, |
1467 | | suite: &'static Tls13CipherSuite, |
1468 | | key_schedule: KeyScheduleTraffic, |
1469 | | resumption: KeyScheduleResumption, |
1470 | | _cert_verified: verify::ServerCertVerified, |
1471 | | _sig_verified: verify::HandshakeSignatureValid, |
1472 | | _fin_verified: verify::FinishedMessageVerified, |
1473 | | } |
1474 | | |
1475 | | impl ExpectTraffic { |
1476 | 0 | fn handle_new_ticket_impl( |
1477 | 0 | &mut self, |
1478 | 0 | cx: &mut KernelContext<'_>, |
1479 | 0 | nst: &NewSessionTicketPayloadTls13, |
1480 | 0 | ) -> Result<(), Error> { |
1481 | 0 | let secret = self |
1482 | 0 | .resumption |
1483 | 0 | .derive_ticket_psk(&nst.nonce.0); |
1484 | | |
1485 | 0 | let now = self.config.current_time()?; |
1486 | | |
1487 | | #[allow(unused_mut)] |
1488 | 0 | let mut value = persist::Tls13ClientSessionValue::new( |
1489 | 0 | self.suite, |
1490 | 0 | nst.ticket.clone(), |
1491 | 0 | secret.as_ref(), |
1492 | 0 | cx.peer_certificates |
1493 | 0 | .cloned() |
1494 | 0 | .unwrap_or_default(), |
1495 | 0 | &self.config.verifier, |
1496 | 0 | &self.config.client_auth_cert_resolver, |
1497 | 0 | now, |
1498 | 0 | nst.lifetime, |
1499 | 0 | nst.age_add, |
1500 | 0 | nst.extensions |
1501 | 0 | .max_early_data_size |
1502 | 0 | .unwrap_or_default(), |
1503 | | ); |
1504 | | |
1505 | 0 | if cx.is_quic() { |
1506 | 0 | if let Some(sz) = nst.extensions.max_early_data_size { |
1507 | 0 | if sz != 0 && sz != 0xffff_ffff { |
1508 | 0 | return Err(PeerMisbehaved::InvalidMaxEarlyDataSize.into()); |
1509 | 0 | } |
1510 | 0 | } |
1511 | | |
1512 | 0 | if let Some(quic_params) = &cx.quic.params { |
1513 | 0 | value.set_quic_params(quic_params); |
1514 | 0 | } |
1515 | 0 | } |
1516 | | |
1517 | 0 | self.session_storage |
1518 | 0 | .insert_tls13_ticket(self.server_name.clone(), value); |
1519 | 0 | Ok(()) |
1520 | 0 | } |
1521 | | |
1522 | 0 | fn handle_new_ticket_tls13( |
1523 | 0 | &mut self, |
1524 | 0 | cx: &mut ClientContext<'_>, |
1525 | 0 | nst: &NewSessionTicketPayloadTls13, |
1526 | 0 | ) -> Result<(), Error> { |
1527 | 0 | let mut kcx = KernelContext { |
1528 | 0 | peer_certificates: cx.common.peer_certificates.as_ref(), |
1529 | 0 | protocol: cx.common.protocol, |
1530 | 0 | quic: &cx.common.quic, |
1531 | 0 | }; |
1532 | 0 | cx.common.tls13_tickets_received = cx |
1533 | 0 | .common |
1534 | 0 | .tls13_tickets_received |
1535 | 0 | .saturating_add(1); |
1536 | 0 | self.handle_new_ticket_impl(&mut kcx, nst) |
1537 | 0 | } |
1538 | | |
1539 | 0 | fn handle_key_update( |
1540 | 0 | &mut self, |
1541 | 0 | common: &mut CommonState, |
1542 | 0 | key_update_request: &KeyUpdateRequest, |
1543 | 0 | ) -> Result<(), Error> { |
1544 | 0 | if let Protocol::Quic = common.protocol { |
1545 | 0 | return Err(common.send_fatal_alert( |
1546 | 0 | AlertDescription::UnexpectedMessage, |
1547 | 0 | PeerMisbehaved::KeyUpdateReceivedInQuicConnection, |
1548 | 0 | )); |
1549 | 0 | } |
1550 | | |
1551 | | // Mustn't be interleaved with other handshake messages. |
1552 | 0 | common.check_aligned_handshake()?; |
1553 | | |
1554 | 0 | if common.should_update_key(key_update_request)? { |
1555 | 0 | self.key_schedule |
1556 | 0 | .update_encrypter_and_notify(common); |
1557 | 0 | } |
1558 | | |
1559 | | // Update our read-side keys. |
1560 | 0 | self.key_schedule |
1561 | 0 | .update_decrypter(common); |
1562 | 0 | Ok(()) |
1563 | 0 | } |
1564 | | } |
1565 | | |
1566 | | impl State<ClientConnectionData> for ExpectTraffic { |
1567 | 0 | fn handle<'m>( |
1568 | 0 | mut self: Box<Self>, |
1569 | 0 | cx: &mut ClientContext<'_>, |
1570 | 0 | m: Message<'m>, |
1571 | 0 | ) -> hs::NextStateOrError<'m> |
1572 | 0 | where |
1573 | 0 | Self: 'm, |
1574 | | { |
1575 | 0 | match m.payload { |
1576 | 0 | MessagePayload::ApplicationData(payload) => cx |
1577 | 0 | .common |
1578 | 0 | .take_received_plaintext(payload), |
1579 | | MessagePayload::Handshake { |
1580 | 0 | parsed: HandshakeMessagePayload(HandshakePayload::NewSessionTicketTls13(new_ticket)), |
1581 | | .. |
1582 | 0 | } => self.handle_new_ticket_tls13(cx, &new_ticket)?, |
1583 | | MessagePayload::Handshake { |
1584 | 0 | parsed: HandshakeMessagePayload(HandshakePayload::KeyUpdate(key_update)), |
1585 | | .. |
1586 | 0 | } => self.handle_key_update(cx.common, &key_update)?, |
1587 | 0 | payload => { |
1588 | 0 | return Err(inappropriate_handshake_message( |
1589 | 0 | &payload, |
1590 | 0 | &[ContentType::ApplicationData, ContentType::Handshake], |
1591 | 0 | &[HandshakeType::NewSessionTicket, HandshakeType::KeyUpdate], |
1592 | 0 | )); |
1593 | | } |
1594 | | } |
1595 | | |
1596 | 0 | Ok(self) |
1597 | 0 | } |
1598 | | |
1599 | 0 | fn send_key_update_request(&mut self, common: &mut CommonState) -> Result<(), Error> { |
1600 | 0 | self.key_schedule |
1601 | 0 | .request_key_update_and_update_encrypter(common) |
1602 | 0 | } |
1603 | | |
1604 | 0 | fn export_keying_material( |
1605 | 0 | &self, |
1606 | 0 | output: &mut [u8], |
1607 | 0 | label: &[u8], |
1608 | 0 | context: Option<&[u8]>, |
1609 | 0 | ) -> Result<(), Error> { |
1610 | 0 | self.key_schedule |
1611 | 0 | .export_keying_material(output, label, context) |
1612 | 0 | } |
1613 | | |
1614 | 0 | fn extract_secrets(&self) -> Result<PartiallyExtractedSecrets, Error> { |
1615 | 0 | self.key_schedule |
1616 | 0 | .extract_secrets(Side::Client) |
1617 | 0 | } |
1618 | | |
1619 | 0 | fn into_external_state(self: Box<Self>) -> Result<Box<dyn KernelState + 'static>, Error> { |
1620 | 0 | Ok(self) |
1621 | 0 | } |
1622 | | |
1623 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
1624 | 0 | self |
1625 | 0 | } |
1626 | | } |
1627 | | |
1628 | | impl KernelState for ExpectTraffic { |
1629 | 0 | fn update_secrets(&mut self, dir: Direction) -> Result<ConnectionTrafficSecrets, Error> { |
1630 | 0 | self.key_schedule |
1631 | 0 | .refresh_traffic_secret(match dir { |
1632 | 0 | Direction::Transmit => Side::Client, |
1633 | 0 | Direction::Receive => Side::Server, |
1634 | | }) |
1635 | 0 | } |
1636 | | |
1637 | 0 | fn handle_new_session_ticket( |
1638 | 0 | &mut self, |
1639 | 0 | cx: &mut KernelContext<'_>, |
1640 | 0 | message: &NewSessionTicketPayloadTls13, |
1641 | 0 | ) -> Result<(), Error> { |
1642 | 0 | self.handle_new_ticket_impl(cx, message) |
1643 | 0 | } |
1644 | | } |
1645 | | |
1646 | | struct ExpectQuicTraffic(ExpectTraffic); |
1647 | | |
1648 | | impl State<ClientConnectionData> for ExpectQuicTraffic { |
1649 | 0 | fn handle<'m>( |
1650 | 0 | mut self: Box<Self>, |
1651 | 0 | cx: &mut ClientContext<'_>, |
1652 | 0 | m: Message<'m>, |
1653 | 0 | ) -> hs::NextStateOrError<'m> |
1654 | 0 | where |
1655 | 0 | Self: 'm, |
1656 | | { |
1657 | 0 | let nst = require_handshake_msg!( |
1658 | | m, |
1659 | | HandshakeType::NewSessionTicket, |
1660 | | HandshakePayload::NewSessionTicketTls13 |
1661 | 0 | )?; |
1662 | 0 | self.0 |
1663 | 0 | .handle_new_ticket_tls13(cx, nst)?; |
1664 | 0 | Ok(self) |
1665 | 0 | } |
1666 | | |
1667 | 0 | fn export_keying_material( |
1668 | 0 | &self, |
1669 | 0 | output: &mut [u8], |
1670 | 0 | label: &[u8], |
1671 | 0 | context: Option<&[u8]>, |
1672 | 0 | ) -> Result<(), Error> { |
1673 | 0 | self.0 |
1674 | 0 | .export_keying_material(output, label, context) |
1675 | 0 | } |
1676 | | |
1677 | 0 | fn into_external_state(self: Box<Self>) -> Result<Box<dyn KernelState + 'static>, Error> { |
1678 | 0 | Ok(self) |
1679 | 0 | } |
1680 | | |
1681 | 0 | fn into_owned(self: Box<Self>) -> hs::NextState<'static> { |
1682 | 0 | self |
1683 | 0 | } |
1684 | | } |
1685 | | |
1686 | | impl KernelState for ExpectQuicTraffic { |
1687 | 0 | fn update_secrets(&mut self, _: Direction) -> Result<ConnectionTrafficSecrets, Error> { |
1688 | 0 | Err(Error::General( |
1689 | 0 | "KeyUpdate is not supported for QUIC connections".into(), |
1690 | 0 | )) |
1691 | 0 | } |
1692 | | |
1693 | 0 | fn handle_new_session_ticket( |
1694 | 0 | &mut self, |
1695 | 0 | cx: &mut KernelContext<'_>, |
1696 | 0 | nst: &NewSessionTicketPayloadTls13, |
1697 | 0 | ) -> Result<(), Error> { |
1698 | 0 | self.0.handle_new_ticket_impl(cx, nst) |
1699 | 0 | } |
1700 | | } |