1use alloc::borrow::ToOwned;
2use alloc::boxed::Box;
3use alloc::vec;
4use alloc::vec::Vec;
5use core::ops::Deref;
6
7use pki_types::ServerName;
8
9use super::ResolvesClientCert;
10use super::Tls12Resumption;
11#[cfg(feature = "tls12")]
12use super::tls12;
13use crate::SupportedCipherSuite;
14#[cfg(feature = "logging")]
15use crate::bs_debug;
16use crate::check::inappropriate_handshake_message;
17use crate::client::client_conn::ClientConnectionData;
18use crate::client::common::ClientHelloDetails;
19use crate::client::ech::EchState;
20use crate::client::{ClientConfig, EchMode, EchStatus, tls13};
21use crate::common_state::{CommonState, HandshakeKind, KxState, State};
22use crate::conn::ConnectionRandoms;
23use crate::crypto::{ActiveKeyExchange, KeyExchangeAlgorithm};
24use crate::enums::{AlertDescription, CipherSuite, ContentType, HandshakeType, ProtocolVersion};
25use crate::error::{Error, PeerIncompatible, PeerMisbehaved};
26use crate::hash_hs::HandshakeHashBuffer;
27use crate::log::{debug, trace};
28use crate::msgs::base::Payload;
29use crate::msgs::enums::{
30 CertificateType, Compression, ECPointFormat, ExtensionType, PSKKeyExchangeMode,
31};
32use crate::msgs::handshake::{
33 CertificateStatusRequest, ClientExtension, ClientHelloPayload, ClientSessionTicket,
34 ConvertProtocolNameList, HandshakeMessagePayload, HandshakePayload, HasServerExtensions,
35 HelloRetryRequest, KeyShareEntry, Random, SessionId,
36};
37use crate::msgs::message::{Message, MessagePayload};
38use crate::msgs::persist;
39use crate::sync::Arc;
40use crate::tls13::key_schedule::KeyScheduleEarly;
41use crate::verify::ServerCertVerifier;
42
43pub(super) type NextState<'a> = Box<dyn State<ClientConnectionData> + 'a>;
44pub(super) type NextStateOrError<'a> = Result<NextState<'a>, Error>;
45pub(super) type ClientContext<'a> = crate::common_state::Context<'a, ClientConnectionData>;
46
47fn find_session(
48 server_name: &ServerName<'static>,
49 config: &ClientConfig,
50 cx: &mut ClientContext<'_>,
51) -> Option<persist::Retrieved<ClientSessionValue>> {
52 let found = config
53 .resumption
54 .store
55 .take_tls13_ticket(server_name)
56 .map(ClientSessionValue::Tls13)
57 .or_else(|| {
58 #[cfg(feature = "tls12")]
59 {
60 config
61 .resumption
62 .store
63 .tls12_session(server_name)
64 .map(ClientSessionValue::Tls12)
65 }
66
67 #[cfg(not(feature = "tls12"))]
68 None
69 })
70 .and_then(|resuming| {
71 resuming.compatible_config(&config.verifier, &config.client_auth_cert_resolver)
72 })
73 .and_then(|resuming| {
74 let now = config
75 .current_time()
76 .map_err(|_err| debug!("Could not get current time: {_err}"))
77 .ok()?;
78
79 let retrieved = persist::Retrieved::new(resuming, now);
80 match retrieved.has_expired() {
81 false => Some(retrieved),
82 true => None,
83 }
84 })
85 .or_else(|| {
86 debug!("No cached session for {:?}", server_name);
87 None
88 });
89
90 if let Some(resuming) = &found {
91 if cx.common.is_quic() {
92 cx.common.quic.params = resuming
93 .tls13()
94 .map(|v| v.quic_params());
95 }
96 }
97
98 found
99}
100
101pub(super) fn start_handshake(
102 server_name: ServerName<'static>,
103 extra_exts: Vec<ClientExtension>,
104 config: Arc<ClientConfig>,
105 cx: &mut ClientContext<'_>,
106) -> NextStateOrError<'static> {
107 let mut transcript_buffer = HandshakeHashBuffer::new();
108 if config
109 .client_auth_cert_resolver
110 .has_certs()
111 {
112 transcript_buffer.set_client_auth_enabled();
113 }
114
115 let mut resuming = find_session(&server_name, &config, cx);
116
117 let key_share = if config.supports_version(ProtocolVersion::TLSv1_3) {
118 Some(tls13::initial_key_share(
119 &config,
120 &server_name,
121 &mut cx.common.kx_state,
122 )?)
123 } else {
124 None
125 };
126
127 let session_id = match &mut resuming {
128 Some(_resuming) => {
129 debug!("Resuming session");
130 match &mut _resuming.value {
131 #[cfg(feature = "tls12")]
132 ClientSessionValue::Tls12(inner) => {
133 // If we have a ticket, we use the sessionid as a signal that
134 // we're doing an abbreviated handshake. See section 3.4 in
135 // RFC5077.
136 if !inner.ticket().0.is_empty() {
137 inner.session_id = SessionId::random(config.provider.secure_random)?;
138 }
139 Some(inner.session_id)
140 }
141 _ => None,
142 }
143 }
144 _ => {
145 debug!("Not resuming any session");
146 None
147 }
148 };
149
150 // https://tools.ietf.org/html/rfc8446#appendix-D.4
151 // https://tools.ietf.org/html/draft-ietf-quic-tls-34#section-8.4
152 let session_id = match session_id {
153 Some(session_id) => session_id,
154 None if cx.common.is_quic() => SessionId::empty(),
155 None if !config.supports_version(ProtocolVersion::TLSv1_3) => SessionId::empty(),
156 None => SessionId::random(config.provider.secure_random)?,
157 };
158
159 let random = Random::new(config.provider.secure_random)?;
160 let extension_order_seed = crate::rand::random_u16(config.provider.secure_random)?;
161
162 let ech_state = match config.ech_mode.as_ref() {
163 Some(EchMode::Enable(ech_config)) => Some(EchState::new(
164 ech_config,
165 server_name.clone(),
166 config
167 .client_auth_cert_resolver
168 .has_certs(),
169 config.provider.secure_random,
170 config.enable_sni,
171 )?),
172 _ => None,
173 };
174
175 emit_client_hello_for_retry(
176 transcript_buffer,
177 None,
178 key_share,
179 extra_exts,
180 None,
181 ClientHelloInput {
182 config,
183 resuming,
184 random,
185 #[cfg(feature = "tls12")]
186 using_ems: false,
187 sent_tls13_fake_ccs: false,
188 hello: ClientHelloDetails::new(extension_order_seed),
189 session_id,
190 server_name,
191 prev_ech_ext: None,
192 },
193 cx,
194 ech_state,
195 )
196}
197
198struct ExpectServerHello {
199 input: ClientHelloInput,
200 transcript_buffer: HandshakeHashBuffer,
201 early_key_schedule: Option<KeyScheduleEarly>,
202 offered_key_share: Option<Box<dyn ActiveKeyExchange>>,
203 suite: Option<SupportedCipherSuite>,
204 ech_state: Option<EchState>,
205}
206
207struct ExpectServerHelloOrHelloRetryRequest {
208 next: ExpectServerHello,
209 extra_exts: Vec<ClientExtension>,
210}
211
212struct ClientHelloInput {
213 config: Arc<ClientConfig>,
214 resuming: Option<persist::Retrieved<ClientSessionValue>>,
215 random: Random,
216 #[cfg(feature = "tls12")]
217 using_ems: bool,
218 sent_tls13_fake_ccs: bool,
219 hello: ClientHelloDetails,
220 session_id: SessionId,
221 server_name: ServerName<'static>,
222 prev_ech_ext: Option<ClientExtension>,
223}
224
225fn emit_client_hello_for_retry(
226 mut transcript_buffer: HandshakeHashBuffer,
227 retryreq: Option<&HelloRetryRequest>,
228 key_share: Option<Box<dyn ActiveKeyExchange>>,
229 extra_exts: Vec<ClientExtension>,
230 suite: Option<SupportedCipherSuite>,
231 mut input: ClientHelloInput,
232 cx: &mut ClientContext<'_>,
233 mut ech_state: Option<EchState>,
234) -> NextStateOrError<'static> {
235 let config = &input.config;
236 // Defense in depth: the ECH state should be None if ECH is disabled based on config
237 // builder semantics.
238 let forbids_tls12 = cx.common.is_quic() || ech_state.is_some();
239 let support_tls12 = config.supports_version(ProtocolVersion::TLSv1_2) && !forbids_tls12;
240 let support_tls13 = config.supports_version(ProtocolVersion::TLSv1_3);
241
242 let mut supported_versions = Vec::new();
243 if support_tls13 {
244 supported_versions.push(ProtocolVersion::TLSv1_3);
245 }
246
247 if support_tls12 {
248 supported_versions.push(ProtocolVersion::TLSv1_2);
249 }
250
251 // should be unreachable thanks to config builder
252 assert!(!supported_versions.is_empty());
253
254 // offer groups which are usable for any offered version
255 let offered_groups = config
256 .provider
257 .kx_groups
258 .iter()
259 .filter(|skxg| {
260 supported_versions
261 .iter()
262 .any(|v| skxg.usable_for_version(*v))
263 })
264 .map(|skxg| skxg.name())
265 .collect();
266
267 let mut exts = vec![
268 ClientExtension::SupportedVersions(supported_versions),
269 ClientExtension::NamedGroups(offered_groups),
270 ClientExtension::SignatureAlgorithms(
271 config
272 .verifier
273 .supported_verify_schemes(),
274 ),
275 ClientExtension::ExtendedMasterSecretRequest,
276 ClientExtension::CertificateStatusRequest(CertificateStatusRequest::build_ocsp()),
277 ];
278
279 if support_tls13 {
280 if let Some(cas_extension) = config.verifier.root_hint_subjects() {
281 exts.push(ClientExtension::AuthorityNames(cas_extension.to_owned()));
282 }
283 }
284
285 // Send the ECPointFormat extension only if we are proposing ECDHE
286 if config
287 .provider
288 .kx_groups
289 .iter()
290 .any(|skxg| skxg.name().key_exchange_algorithm() == KeyExchangeAlgorithm::ECDHE)
291 {
292 exts.push(ClientExtension::EcPointFormats(
293 ECPointFormat::SUPPORTED.to_vec(),
294 ));
295 }
296
297 match (ech_state.as_ref(), config.enable_sni) {
298 // If we have ECH state we have a "cover name" to send in the outer hello
299 // as the SNI domain name. This happens unconditionally so we ignore the
300 // `enable_sni` value. That will be used later to decide what to do for
301 // the protected inner hello's SNI.
302 (Some(ech_state), _) => exts.push(ClientExtension::make_sni(&ech_state.outer_name)),
303
304 // If we have no ECH state, and SNI is enabled, try to use the input server_name
305 // for the SNI domain name.
306 (None, true) => {
307 if let ServerName::DnsName(dns_name) = &input.server_name {
308 exts.push(ClientExtension::make_sni(dns_name))
309 }
310 }
311
312 // If we have no ECH state, and SNI is not enabled, there's nothing to do.
313 (None, false) => {}
314 };
315
316 if let Some(key_share) = &key_share {
317 debug_assert!(support_tls13);
318 let mut shares = vec![KeyShareEntry::new(key_share.group(), key_share.pub_key())];
319
320 if !retryreq
321 .map(|rr| rr.requested_key_share_group().is_some())
322 .unwrap_or_default()
323 {
324 // Only for the initial client hello, or a HRR that does not specify a kx group,
325 // see if we can send a second KeyShare for "free". We only do this if the same
326 // algorithm is also supported separately by our provider for this version
327 // (`find_kx_group` looks that up).
328 if let Some((component_group, component_share)) =
329 key_share
330 .hybrid_component()
331 .filter(|(group, _)| {
332 config
333 .find_kx_group(*group, ProtocolVersion::TLSv1_3)
334 .is_some()
335 })
336 {
337 shares.push(KeyShareEntry::new(component_group, component_share));
338 }
339 }
340
341 exts.push(ClientExtension::KeyShare(shares));
342 }
343
344 if let Some(cookie) = retryreq.and_then(HelloRetryRequest::cookie) {
345 exts.push(ClientExtension::Cookie(cookie.clone()));
346 }
347
348 if support_tls13 {
349 // We could support PSK_KE here too. Such connections don't
350 // have forward secrecy, and are similar to TLS1.2 resumption.
351 let psk_modes = vec![PSKKeyExchangeMode::PSK_DHE_KE];
352 exts.push(ClientExtension::PresharedKeyModes(psk_modes));
353 }
354
355 if !config.alpn_protocols.is_empty() {
356 exts.push(ClientExtension::Protocols(Vec::from_slices(
357 &config
358 .alpn_protocols
359 .iter()
360 .map(|proto| &proto[..])
361 .collect::<Vec<_>>(),
362 )));
363 }
364
365 input.hello.offered_cert_compression = if support_tls13 && !config.cert_decompressors.is_empty()
366 {
367 exts.push(ClientExtension::CertificateCompressionAlgorithms(
368 config
369 .cert_decompressors
370 .iter()
371 .map(|dec| dec.algorithm())
372 .collect(),
373 ));
374 true
375 } else {
376 false
377 };
378
379 if config
380 .client_auth_cert_resolver
381 .only_raw_public_keys()
382 {
383 exts.push(ClientExtension::ClientCertTypes(vec![
384 CertificateType::RawPublicKey,
385 ]));
386 }
387
388 if config
389 .verifier
390 .requires_raw_public_keys()
391 {
392 exts.push(ClientExtension::ServerCertTypes(vec![
393 CertificateType::RawPublicKey,
394 ]));
395 }
396
397 // Extra extensions must be placed before the PSK extension
398 exts.extend(extra_exts.iter().cloned());
399
400 // If this is a second client hello we're constructing in response to an HRR, and
401 // we've rejected ECH or sent GREASE ECH, then we need to carry forward the
402 // exact same ECH extension we used in the first hello.
403 if matches!(cx.data.ech_status, EchStatus::Rejected | EchStatus::Grease) & retryreq.is_some() {
404 if let Some(prev_ech_ext) = input.prev_ech_ext.take() {
405 exts.push(prev_ech_ext);
406 }
407 }
408
409 // Do we have a SessionID or ticket cached for this host?
410 let tls13_session = prepare_resumption(&input.resuming, &mut exts, suite, cx, config);
411
412 // Extensions MAY be randomized
413 // but they also need to keep the same order as the previous ClientHello
414 exts.sort_by_cached_key(|new_ext| {
415 match (&cx.data.ech_status, new_ext) {
416 // When not offering ECH/GREASE, the PSK extension is always last.
417 (EchStatus::NotOffered, ClientExtension::PresharedKey(..)) => return u32::MAX,
418 // When ECH or GREASE are in-play, the ECH extension is always last.
419 (_, ClientExtension::EncryptedClientHello(_)) => return u32::MAX,
420 // ... and the PSK extension should be second-to-last.
421 (_, ClientExtension::PresharedKey(..)) => return u32::MAX - 1,
422 _ => {}
423 };
424
425 let seed = ((input.hello.extension_order_seed as u32) << 16)
426 | (u16::from(new_ext.ext_type()) as u32);
427 match low_quality_integer_hash(seed) {
428 u32::MAX => 0,
429 key => key,
430 }
431 });
432
433 let mut cipher_suites: Vec<_> = config
434 .provider
435 .cipher_suites
436 .iter()
437 .filter_map(|cs| match cs.usable_for_protocol(cx.common.protocol) {
438 true => Some(cs.suite()),
439 false => None,
440 })
441 .collect();
442 // We don't do renegotiation at all, in fact.
443 cipher_suites.push(CipherSuite::TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
444
445 let mut chp_payload = ClientHelloPayload {
446 client_version: ProtocolVersion::TLSv1_2,
447 random: input.random,
448 session_id: input.session_id,
449 cipher_suites,
450 compression_methods: vec![Compression::Null],
451 extensions: exts,
452 };
453
454 let ech_grease_ext = config
455 .ech_mode
456 .as_ref()
457 .and_then(|mode| match mode {
458 EchMode::Grease(cfg) => Some(cfg.grease_ext(
459 config.provider.secure_random,
460 input.server_name.clone(),
461 &chp_payload,
462 )),
463 _ => None,
464 });
465
466 match (cx.data.ech_status, &mut ech_state) {
467 // If we haven't offered ECH, or have offered ECH but got a non-rejecting HRR, then
468 // we need to replace the client hello payload with an ECH client hello payload.
469 (EchStatus::NotOffered | EchStatus::Offered, Some(ech_state)) => {
470 // Replace the client hello payload with an ECH client hello payload.
471 chp_payload = ech_state.ech_hello(chp_payload, retryreq, &tls13_session)?;
472 cx.data.ech_status = EchStatus::Offered;
473 // Store the ECH extension in case we need to carry it forward in a subsequent hello.
474 input.prev_ech_ext = chp_payload.extensions.last().cloned();
475 }
476 // If we haven't offered ECH, and have no ECH state, then consider whether to use GREASE
477 // ECH.
478 (EchStatus::NotOffered, None) => {
479 if let Some(grease_ext) = ech_grease_ext {
480 // Add the GREASE ECH extension.
481 let grease_ext = grease_ext?;
482 chp_payload
483 .extensions
484 .push(grease_ext.clone());
485 cx.data.ech_status = EchStatus::Grease;
486 // Store the GREASE ECH extension in case we need to carry it forward in a
487 // subsequent hello.
488 input.prev_ech_ext = Some(grease_ext);
489 }
490 }
491 _ => {}
492 }
493
494 // Note what extensions we sent.
495 input.hello.sent_extensions = chp_payload
496 .extensions
497 .iter()
498 .map(ClientExtension::ext_type)
499 .collect();
500
501 let mut chp = HandshakeMessagePayload {
502 typ: HandshakeType::ClientHello,
503 payload: HandshakePayload::ClientHello(chp_payload),
504 };
505
506 let early_key_schedule = match (ech_state.as_mut(), tls13_session) {
507 // If we're performing ECH and resuming, then the PSK binder will have been dealt with
508 // separately, and we need to take the early_data_key_schedule computed for the inner hello.
509 (Some(ech_state), Some(tls13_session)) => ech_state
510 .early_data_key_schedule
511 .take()
512 .map(|schedule| (tls13_session.suite(), schedule)),
513
514 // When we're not doing ECH and resuming, then the PSK binder need to be filled in as
515 // normal.
516 (_, Some(tls13_session)) => Some((
517 tls13_session.suite(),
518 tls13::fill_in_psk_binder(&tls13_session, &transcript_buffer, &mut chp),
519 )),
520
521 // No early key schedule in other cases.
522 _ => None,
523 };
524
525 let ch = Message {
526 version: match retryreq {
527 // <https://datatracker.ietf.org/doc/html/rfc8446#section-5.1>:
528 // "This value MUST be set to 0x0303 for all records generated
529 // by a TLS 1.3 implementation ..."
530 Some(_) => ProtocolVersion::TLSv1_2,
531 // "... other than an initial ClientHello (i.e., one not
532 // generated after a HelloRetryRequest), where it MAY also be
533 // 0x0301 for compatibility purposes"
534 //
535 // (retryreq == None means we're in the "initial ClientHello" case)
536 None => ProtocolVersion::TLSv1_0,
537 },
538 payload: MessagePayload::handshake(chp),
539 };
540
541 if retryreq.is_some() {
542 // send dummy CCS to fool middleboxes prior
543 // to second client hello
544 tls13::emit_fake_ccs(&mut input.sent_tls13_fake_ccs, cx.common);
545 }
546
547 trace!("Sending ClientHello {:#?}", ch);
548
549 transcript_buffer.add_message(&ch);
550 cx.common.send_msg(ch, false);
551
552 // Calculate the hash of ClientHello and use it to derive EarlyTrafficSecret
553 let early_key_schedule = early_key_schedule.map(|(resuming_suite, schedule)| {
554 if !cx.data.early_data.is_enabled() {
555 return schedule;
556 }
557
558 let (transcript_buffer, random) = match &ech_state {
559 // When using ECH the early data key schedule is derived based on the inner
560 // hello transcript and random.
561 Some(ech_state) => (
562 &ech_state.inner_hello_transcript,
563 &ech_state.inner_hello_random.0,
564 ),
565 None => (&transcript_buffer, &input.random.0),
566 };
567
568 tls13::derive_early_traffic_secret(
569 &*config.key_log,
570 cx,
571 resuming_suite,
572 &schedule,
573 &mut input.sent_tls13_fake_ccs,
574 transcript_buffer,
575 random,
576 );
577 schedule
578 });
579
580 let next = ExpectServerHello {
581 input,
582 transcript_buffer,
583 early_key_schedule,
584 offered_key_share: key_share,
585 suite,
586 ech_state,
587 };
588
589 Ok(if support_tls13 && retryreq.is_none() {
590 Box::new(ExpectServerHelloOrHelloRetryRequest { next, extra_exts })
591 } else {
592 Box::new(next)
593 })
594}
595
596/// Prepare resumption with the session state retrieved from storage.
597///
598/// This function will push onto `exts` to
599///
600/// (a) request a new ticket if we don't have one,
601/// (b) send our TLS 1.2 ticket after retrieving an 1.2 session,
602/// (c) send a request for 1.3 early data if allowed and
603/// (d) send a 1.3 preshared key if we have one.
604///
605/// For resumption to work, the currently negotiated cipher suite (if available) must be
606/// able to resume from the resuming session's cipher suite.
607///
608/// If 1.3 resumption can continue, returns the 1.3 session value for further processing.
609fn prepare_resumption<'a>(
610 resuming: &'a Option<persist::Retrieved<ClientSessionValue>>,
611 exts: &mut Vec<ClientExtension>,
612 suite: Option<SupportedCipherSuite>,
613 cx: &mut ClientContext<'_>,
614 config: &ClientConfig,
615) -> Option<persist::Retrieved<&'a persist::Tls13ClientSessionValue>> {
616 // Check whether we're resuming with a non-empty ticket.
617 let resuming = match resuming {
618 Some(resuming) if !resuming.ticket().is_empty() => resuming,
619 _ => {
620 if config.supports_version(ProtocolVersion::TLSv1_2)
621 && config.resumption.tls12_resumption == Tls12Resumption::SessionIdOrTickets
622 {
623 // If we don't have a ticket, request one.
624 exts.push(ClientExtension::SessionTicket(ClientSessionTicket::Request));
625 }
626 return None;
627 }
628 };
629
630 let Some(tls13) = resuming.map(|csv| csv.tls13()) else {
631 // TLS 1.2; send the ticket if we have support this protocol version
632 if config.supports_version(ProtocolVersion::TLSv1_2)
633 && config.resumption.tls12_resumption == Tls12Resumption::SessionIdOrTickets
634 {
635 exts.push(ClientExtension::SessionTicket(ClientSessionTicket::Offer(
636 Payload::new(resuming.ticket()),
637 )));
638 }
639 return None; // TLS 1.2, so nothing to return here
640 };
641
642 if !config.supports_version(ProtocolVersion::TLSv1_3) {
643 return None;
644 }
645
646 // If the server selected TLS 1.2, we can't resume.
647 let suite = match suite {
648 Some(SupportedCipherSuite::Tls13(suite)) => Some(suite),
649 #[cfg(feature = "tls12")]
650 Some(SupportedCipherSuite::Tls12(_)) => return None,
651 None => None,
652 };
653
654 // If the selected cipher suite can't select from the session's, we can't resume.
655 if let Some(suite) = suite {
656 suite.can_resume_from(tls13.suite())?;
657 }
658
659 tls13::prepare_resumption(config, cx, &tls13, exts, suite.is_some());
660 Some(tls13)
661}
662
663pub(super) fn process_alpn_protocol(
664 common: &mut CommonState,
665 config: &ClientConfig,
666 proto: Option<&[u8]>,
667) -> Result<(), Error> {
668 common.alpn_protocol = proto.map(ToOwned::to_owned);
669
670 if let Some(alpn_protocol) = &common.alpn_protocol {
671 if !config
672 .alpn_protocols
673 .contains(alpn_protocol)
674 {
675 return Err(common.send_fatal_alert(
676 AlertDescription::IllegalParameter,
677 PeerMisbehaved::SelectedUnofferedApplicationProtocol,
678 ));
679 }
680 }
681
682 // RFC 9001 says: "While ALPN only specifies that servers use this alert, QUIC clients MUST
683 // use error 0x0178 to terminate a connection when ALPN negotiation fails." We judge that
684 // the user intended to use ALPN (rather than some out-of-band protocol negotiation
685 // mechanism) if and only if any ALPN protocols were configured. This defends against badly-behaved
686 // servers which accept a connection that requires an application-layer protocol they do not
687 // understand.
688 if common.is_quic() && common.alpn_protocol.is_none() && !config.alpn_protocols.is_empty() {
689 return Err(common.send_fatal_alert(
690 AlertDescription::NoApplicationProtocol,
691 Error::NoApplicationProtocol,
692 ));
693 }
694
695 debug!(
696 "ALPN protocol is {:?}",
697 common
698 .alpn_protocol
699 .as_ref()
700 .map(|v| bs_debug::BsDebug(v))
701 );
702 Ok(())
703}
704
705pub(super) fn process_server_cert_type_extension(
706 common: &mut CommonState,
707 config: &ClientConfig,
708 server_cert_extension: Option<&CertificateType>,
709) -> Result<Option<(ExtensionType, CertificateType)>, Error> {
710 process_cert_type_extension(
711 common,
712 client_expects:config
713 .verifier
714 .requires_raw_public_keys(),
715 server_negotiated:server_cert_extension.copied(),
716 ExtensionType::ServerCertificateType,
717 )
718}
719
720pub(super) fn process_client_cert_type_extension(
721 common: &mut CommonState,
722 config: &ClientConfig,
723 client_cert_extension: Option<&CertificateType>,
724) -> Result<Option<(ExtensionType, CertificateType)>, Error> {
725 process_cert_type_extension(
726 common,
727 client_expects:config
728 .client_auth_cert_resolver
729 .only_raw_public_keys(),
730 server_negotiated:client_cert_extension.copied(),
731 ExtensionType::ClientCertificateType,
732 )
733}
734
735impl State<ClientConnectionData> for ExpectServerHello {
736 fn handle<'m>(
737 mut self: Box<Self>,
738 cx: &mut ClientContext<'_>,
739 m: Message<'m>,
740 ) -> NextStateOrError<'m>
741 where
742 Self: 'm,
743 {
744 let server_hello =
745 require_handshake_msg!(m, HandshakeType::ServerHello, HandshakePayload::ServerHello)?;
746 trace!("We got ServerHello {:#?}", server_hello);
747
748 use crate::ProtocolVersion::{TLSv1_2, TLSv1_3};
749 let config = &self.input.config;
750 let tls13_supported = config.supports_version(TLSv1_3);
751
752 let server_version = if server_hello.legacy_version == TLSv1_2 {
753 server_hello
754 .supported_versions()
755 .unwrap_or(server_hello.legacy_version)
756 } else {
757 server_hello.legacy_version
758 };
759
760 let version = match server_version {
761 TLSv1_3 if tls13_supported => TLSv1_3,
762 TLSv1_2 if config.supports_version(TLSv1_2) => {
763 if cx.data.early_data.is_enabled() && cx.common.early_traffic {
764 // The client must fail with a dedicated error code if the server
765 // responds with TLS 1.2 when offering 0-RTT.
766 return Err(PeerMisbehaved::OfferedEarlyDataWithOldProtocolVersion.into());
767 }
768
769 if server_hello
770 .supported_versions()
771 .is_some()
772 {
773 return Err({
774 cx.common.send_fatal_alert(
775 AlertDescription::IllegalParameter,
776 PeerMisbehaved::SelectedTls12UsingTls13VersionExtension,
777 )
778 });
779 }
780
781 TLSv1_2
782 }
783 _ => {
784 let reason = match server_version {
785 TLSv1_2 | TLSv1_3 => PeerIncompatible::ServerTlsVersionIsDisabledByOurConfig,
786 _ => PeerIncompatible::ServerDoesNotSupportTls12Or13,
787 };
788 return Err(cx
789 .common
790 .send_fatal_alert(AlertDescription::ProtocolVersion, reason));
791 }
792 };
793
794 if server_hello.compression_method != Compression::Null {
795 return Err({
796 cx.common.send_fatal_alert(
797 AlertDescription::IllegalParameter,
798 PeerMisbehaved::SelectedUnofferedCompression,
799 )
800 });
801 }
802
803 if server_hello.has_duplicate_extension() {
804 return Err(cx.common.send_fatal_alert(
805 AlertDescription::DecodeError,
806 PeerMisbehaved::DuplicateServerHelloExtensions,
807 ));
808 }
809
810 let allowed_unsolicited = [ExtensionType::RenegotiationInfo];
811 if self
812 .input
813 .hello
814 .server_sent_unsolicited_extensions(&server_hello.extensions, &allowed_unsolicited)
815 {
816 return Err(cx.common.send_fatal_alert(
817 AlertDescription::UnsupportedExtension,
818 PeerMisbehaved::UnsolicitedServerHelloExtension,
819 ));
820 }
821
822 cx.common.negotiated_version = Some(version);
823
824 // Extract ALPN protocol
825 if !cx.common.is_tls13() {
826 process_alpn_protocol(cx.common, config, server_hello.alpn_protocol())?;
827 }
828
829 // If ECPointFormats extension is supplied by the server, it must contain
830 // Uncompressed. But it's allowed to be omitted.
831 if let Some(point_fmts) = server_hello.ecpoints_extension() {
832 if !point_fmts.contains(&ECPointFormat::Uncompressed) {
833 return Err(cx.common.send_fatal_alert(
834 AlertDescription::HandshakeFailure,
835 PeerMisbehaved::ServerHelloMustOfferUncompressedEcPoints,
836 ));
837 }
838 }
839
840 let suite = config
841 .find_cipher_suite(server_hello.cipher_suite)
842 .ok_or_else(|| {
843 cx.common.send_fatal_alert(
844 AlertDescription::HandshakeFailure,
845 PeerMisbehaved::SelectedUnofferedCipherSuite,
846 )
847 })?;
848
849 if version != suite.version().version {
850 return Err({
851 cx.common.send_fatal_alert(
852 AlertDescription::IllegalParameter,
853 PeerMisbehaved::SelectedUnusableCipherSuiteForVersion,
854 )
855 });
856 }
857
858 match self.suite {
859 Some(prev_suite) if prev_suite != suite => {
860 return Err({
861 cx.common.send_fatal_alert(
862 AlertDescription::IllegalParameter,
863 PeerMisbehaved::SelectedDifferentCipherSuiteAfterRetry,
864 )
865 });
866 }
867 _ => {
868 debug!("Using ciphersuite {:?}", suite);
869 self.suite = Some(suite);
870 cx.common.suite = Some(suite);
871 }
872 }
873
874 // Start our handshake hash, and input the server-hello.
875 let mut transcript = self
876 .transcript_buffer
877 .start_hash(suite.hash_provider());
878 transcript.add_message(&m);
879
880 let randoms = ConnectionRandoms::new(self.input.random, server_hello.random);
881 // For TLS1.3, start message encryption using
882 // handshake_traffic_secret.
883 match suite {
884 SupportedCipherSuite::Tls13(suite) => {
885 #[allow(clippy::bind_instead_of_map)]
886 let resuming_session = self
887 .input
888 .resuming
889 .and_then(|resuming| match resuming.value {
890 ClientSessionValue::Tls13(inner) => Some(inner),
891 #[cfg(feature = "tls12")]
892 ClientSessionValue::Tls12(_) => None,
893 });
894
895 tls13::handle_server_hello(
896 self.input.config,
897 cx,
898 server_hello,
899 resuming_session,
900 self.input.server_name,
901 randoms,
902 suite,
903 transcript,
904 self.early_key_schedule,
905 self.input.hello,
906 // We always send a key share when TLS 1.3 is enabled.
907 self.offered_key_share.unwrap(),
908 self.input.sent_tls13_fake_ccs,
909 &m,
910 self.ech_state,
911 )
912 }
913 #[cfg(feature = "tls12")]
914 SupportedCipherSuite::Tls12(suite) => {
915 // If we didn't have an input session to resume, and we sent a session ID,
916 // that implies we sent a TLS 1.3 legacy_session_id for compatibility purposes.
917 // In this instance since we're now continuing a TLS 1.2 handshake the server
918 // should not have echoed it back: it's a randomly generated session ID it couldn't
919 // have known.
920 if self.input.resuming.is_none()
921 && !self.input.session_id.is_empty()
922 && self.input.session_id == server_hello.session_id
923 {
924 return Err({
925 cx.common.send_fatal_alert(
926 AlertDescription::IllegalParameter,
927 PeerMisbehaved::ServerEchoedCompatibilitySessionId,
928 )
929 });
930 }
931
932 let resuming_session = self
933 .input
934 .resuming
935 .and_then(|resuming| match resuming.value {
936 ClientSessionValue::Tls12(inner) => Some(inner),
937 ClientSessionValue::Tls13(_) => None,
938 });
939
940 tls12::CompleteServerHelloHandling {
941 config: self.input.config,
942 resuming_session,
943 server_name: self.input.server_name,
944 randoms,
945 using_ems: self.input.using_ems,
946 transcript,
947 }
948 .handle_server_hello(cx, suite, server_hello, tls13_supported)
949 }
950 }
951 }
952
953 fn into_owned(self: Box<Self>) -> NextState<'static> {
954 self
955 }
956}
957
958impl ExpectServerHelloOrHelloRetryRequest {
959 fn into_expect_server_hello(self) -> NextState<'static> {
960 Box::new(self.next)
961 }
962
963 fn handle_hello_retry_request(
964 mut self,
965 cx: &mut ClientContext<'_>,
966 m: Message<'_>,
967 ) -> NextStateOrError<'static> {
968 let hrr = require_handshake_msg!(
969 m,
970 HandshakeType::HelloRetryRequest,
971 HandshakePayload::HelloRetryRequest
972 )?;
973 trace!("Got HRR {:?}", hrr);
974
975 cx.common.check_aligned_handshake()?;
976
977 let cookie = hrr.cookie();
978 let req_group = hrr.requested_key_share_group();
979
980 // We always send a key share when TLS 1.3 is enabled.
981 let offered_key_share = self.next.offered_key_share.unwrap();
982
983 // A retry request is illegal if it contains no cookie and asks for
984 // retry of a group we already sent.
985 let config = &self.next.input.config;
986
987 if let (None, Some(req_group)) = (cookie, req_group) {
988 let offered_hybrid = offered_key_share
989 .hybrid_component()
990 .and_then(|(group_name, _)| {
991 config.find_kx_group(group_name, ProtocolVersion::TLSv1_3)
992 })
993 .map(|skxg| skxg.name());
994
995 if req_group == offered_key_share.group() || Some(req_group) == offered_hybrid {
996 return Err({
997 cx.common.send_fatal_alert(
998 AlertDescription::IllegalParameter,
999 PeerMisbehaved::IllegalHelloRetryRequestWithOfferedGroup,
1000 )
1001 });
1002 }
1003 }
1004
1005 // Or has an empty cookie.
1006 if let Some(cookie) = cookie {
1007 if cookie.0.is_empty() {
1008 return Err({
1009 cx.common.send_fatal_alert(
1010 AlertDescription::IllegalParameter,
1011 PeerMisbehaved::IllegalHelloRetryRequestWithEmptyCookie,
1012 )
1013 });
1014 }
1015 }
1016
1017 // Or has something unrecognised
1018 if hrr.has_unknown_extension() {
1019 return Err(cx.common.send_fatal_alert(
1020 AlertDescription::UnsupportedExtension,
1021 PeerIncompatible::ServerSentHelloRetryRequestWithUnknownExtension,
1022 ));
1023 }
1024
1025 // Or has the same extensions more than once
1026 if hrr.has_duplicate_extension() {
1027 return Err({
1028 cx.common.send_fatal_alert(
1029 AlertDescription::IllegalParameter,
1030 PeerMisbehaved::DuplicateHelloRetryRequestExtensions,
1031 )
1032 });
1033 }
1034
1035 // Or asks us to change nothing.
1036 if cookie.is_none() && req_group.is_none() {
1037 return Err({
1038 cx.common.send_fatal_alert(
1039 AlertDescription::IllegalParameter,
1040 PeerMisbehaved::IllegalHelloRetryRequestWithNoChanges,
1041 )
1042 });
1043 }
1044
1045 // Or does not echo the session_id from our ClientHello:
1046 //
1047 // > the HelloRetryRequest has the same format as a ServerHello message,
1048 // > and the legacy_version, legacy_session_id_echo, cipher_suite, and
1049 // > legacy_compression_method fields have the same meaning
1050 // <https://www.rfc-editor.org/rfc/rfc8446#section-4.1.4>
1051 //
1052 // and
1053 //
1054 // > A client which receives a legacy_session_id_echo field that does not
1055 // > match what it sent in the ClientHello MUST abort the handshake with an
1056 // > "illegal_parameter" alert.
1057 // <https://www.rfc-editor.org/rfc/rfc8446#section-4.1.3>
1058 if hrr.session_id != self.next.input.session_id {
1059 return Err({
1060 cx.common.send_fatal_alert(
1061 AlertDescription::IllegalParameter,
1062 PeerMisbehaved::IllegalHelloRetryRequestWithWrongSessionId,
1063 )
1064 });
1065 }
1066
1067 // Or asks us to talk a protocol we didn't offer, or doesn't support HRR at all.
1068 match hrr.supported_versions() {
1069 Some(ProtocolVersion::TLSv1_3) => {
1070 cx.common.negotiated_version = Some(ProtocolVersion::TLSv1_3);
1071 }
1072 _ => {
1073 return Err({
1074 cx.common.send_fatal_alert(
1075 AlertDescription::IllegalParameter,
1076 PeerMisbehaved::IllegalHelloRetryRequestWithUnsupportedVersion,
1077 )
1078 });
1079 }
1080 }
1081
1082 // Or asks us to use a ciphersuite we didn't offer.
1083 let Some(cs) = config.find_cipher_suite(hrr.cipher_suite) else {
1084 return Err({
1085 cx.common.send_fatal_alert(
1086 AlertDescription::IllegalParameter,
1087 PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedCipherSuite,
1088 )
1089 });
1090 };
1091
1092 // Or offers ECH related extensions when we didn't offer ECH.
1093 if cx.data.ech_status == EchStatus::NotOffered && hrr.ech().is_some() {
1094 return Err({
1095 cx.common.send_fatal_alert(
1096 AlertDescription::UnsupportedExtension,
1097 PeerMisbehaved::IllegalHelloRetryRequestWithInvalidEch,
1098 )
1099 });
1100 }
1101
1102 // HRR selects the ciphersuite.
1103 cx.common.suite = Some(cs);
1104 cx.common.handshake_kind = Some(HandshakeKind::FullWithHelloRetryRequest);
1105
1106 // If we offered ECH, we need to confirm that the server accepted it.
1107 match (self.next.ech_state.as_ref(), cs.tls13()) {
1108 (Some(ech_state), Some(tls13_cs)) => {
1109 if !ech_state.confirm_hrr_acceptance(hrr, tls13_cs, cx.common)? {
1110 // If the server did not confirm, then note the new ECH status but
1111 // continue the handshake. We will abort with an ECH required error
1112 // at the end.
1113 cx.data.ech_status = EchStatus::Rejected;
1114 }
1115 }
1116 (Some(_), None) => {
1117 unreachable!("ECH state should only be set when TLS 1.3 was negotiated")
1118 }
1119 _ => {}
1120 };
1121
1122 // This is the draft19 change where the transcript became a tree
1123 let transcript = self
1124 .next
1125 .transcript_buffer
1126 .start_hash(cs.hash_provider());
1127 let mut transcript_buffer = transcript.into_hrr_buffer();
1128 transcript_buffer.add_message(&m);
1129
1130 // If we offered ECH and the server accepted, we also need to update the separate
1131 // ECH transcript with the hello retry request message.
1132 if let Some(ech_state) = self.next.ech_state.as_mut() {
1133 ech_state.transcript_hrr_update(cs.hash_provider(), &m);
1134 }
1135
1136 // Early data is not allowed after HelloRetryrequest
1137 if cx.data.early_data.is_enabled() {
1138 cx.data.early_data.rejected();
1139 }
1140
1141 let key_share = match req_group {
1142 Some(group) if group != offered_key_share.group() => {
1143 let Some(skxg) = config.find_kx_group(group, ProtocolVersion::TLSv1_3) else {
1144 return Err(cx.common.send_fatal_alert(
1145 AlertDescription::IllegalParameter,
1146 PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedNamedGroup,
1147 ));
1148 };
1149
1150 cx.common.kx_state = KxState::Start(skxg);
1151 skxg.start()?
1152 }
1153 _ => offered_key_share,
1154 };
1155
1156 emit_client_hello_for_retry(
1157 transcript_buffer,
1158 Some(hrr),
1159 Some(key_share),
1160 self.extra_exts,
1161 Some(cs),
1162 self.next.input,
1163 cx,
1164 self.next.ech_state,
1165 )
1166 }
1167}
1168
1169impl State<ClientConnectionData> for ExpectServerHelloOrHelloRetryRequest {
1170 fn handle<'m>(
1171 self: Box<Self>,
1172 cx: &mut ClientContext<'_>,
1173 m: Message<'m>,
1174 ) -> NextStateOrError<'m>
1175 where
1176 Self: 'm,
1177 {
1178 match m.payload {
1179 MessagePayload::Handshake {
1180 parsed:
1181 HandshakeMessagePayload {
1182 payload: HandshakePayload::ServerHello(..),
1183 ..
1184 },
1185 ..
1186 } => self
1187 .into_expect_server_hello()
1188 .handle(cx, m),
1189 MessagePayload::Handshake {
1190 parsed:
1191 HandshakeMessagePayload {
1192 payload: HandshakePayload::HelloRetryRequest(..),
1193 ..
1194 },
1195 ..
1196 } => self.handle_hello_retry_request(cx, m),
1197 payload => Err(inappropriate_handshake_message(
1198 &payload,
1199 &[ContentType::Handshake],
1200 &[HandshakeType::ServerHello, HandshakeType::HelloRetryRequest],
1201 )),
1202 }
1203 }
1204
1205 fn into_owned(self: Box<Self>) -> NextState<'static> {
1206 self
1207 }
1208}
1209
1210fn process_cert_type_extension(
1211 common: &mut CommonState,
1212 client_expects: bool,
1213 server_negotiated: Option<CertificateType>,
1214 extension_type: ExtensionType,
1215) -> Result<Option<(ExtensionType, CertificateType)>, Error> {
1216 match (client_expects, server_negotiated) {
1217 (true, Some(CertificateType::RawPublicKey)) => {
1218 Ok(Some((extension_type, CertificateType::RawPublicKey)))
1219 }
1220 (true, _) => Err(common.send_fatal_alert(
1221 desc:AlertDescription::HandshakeFailure,
1222 err:Error::PeerIncompatible(PeerIncompatible::IncorrectCertificateTypeExtension),
1223 )),
1224 (_, Some(CertificateType::RawPublicKey)) => {
1225 unreachable!("Caught by `PeerMisbehaved::UnsolicitedEncryptedExtension`")
1226 }
1227 (_, _) => Ok(None),
1228 }
1229}
1230
1231enum ClientSessionValue {
1232 Tls13(persist::Tls13ClientSessionValue),
1233 #[cfg(feature = "tls12")]
1234 Tls12(persist::Tls12ClientSessionValue),
1235}
1236
1237impl ClientSessionValue {
1238 fn common(&self) -> &persist::ClientSessionCommon {
1239 match self {
1240 Self::Tls13(inner) => &inner.common,
1241 #[cfg(feature = "tls12")]
1242 Self::Tls12(inner) => &inner.common,
1243 }
1244 }
1245
1246 fn tls13(&self) -> Option<&persist::Tls13ClientSessionValue> {
1247 match self {
1248 Self::Tls13(v) => Some(v),
1249 #[cfg(feature = "tls12")]
1250 Self::Tls12(_) => None,
1251 }
1252 }
1253
1254 fn compatible_config(
1255 self,
1256 server_cert_verifier: &Arc<dyn ServerCertVerifier>,
1257 client_creds: &Arc<dyn ResolvesClientCert>,
1258 ) -> Option<Self> {
1259 match &self {
1260 Self::Tls13(v) => v
1261 .compatible_config(server_cert_verifier, client_creds)
1262 .then_some(self),
1263 #[cfg(feature = "tls12")]
1264 Self::Tls12(v) => v
1265 .compatible_config(server_cert_verifier, client_creds)
1266 .then_some(self),
1267 }
1268 }
1269}
1270
1271impl Deref for ClientSessionValue {
1272 type Target = persist::ClientSessionCommon;
1273
1274 fn deref(&self) -> &Self::Target {
1275 self.common()
1276 }
1277}
1278
1279fn low_quality_integer_hash(mut x: u32) -> u32 {
1280 x = xu32
1281 .wrapping_add(0x7ed55d16)
1282 .wrapping_add(x << 12);
1283 x = (x ^ 0xc761c23c) ^ (x >> 19);
1284 x = xu32
1285 .wrapping_add(0x165667b1)
1286 .wrapping_add(x << 5);
1287 x = x.wrapping_add(0xd3a2646c) ^ (x << 9);
1288 x = xu32
1289 .wrapping_add(0xfd7046c5)
1290 .wrapping_add(x << 3);
1291 x = (x ^ 0xb55a4f09) ^ (x >> 16);
1292 x
1293}
1294