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
9#[cfg(feature = "tls12")]
10use super::tls12;
11use super::{ResolvesClientCert, Tls12Resumption};
12use crate::SupportedCipherSuite;
13#[cfg(feature = "logging")]
14use crate::bs_debug;
15use crate::check::inappropriate_handshake_message;
16use crate::client::client_conn::ClientConnectionData;
17use crate::client::common::ClientHelloDetails;
18use crate::client::ech::EchState;
19use crate::client::{ClientConfig, EchMode, EchStatus, tls13};
20use crate::common_state::{CommonState, HandshakeKind, KxState, State};
21use crate::conn::ConnectionRandoms;
22use crate::crypto::{ActiveKeyExchange, KeyExchangeAlgorithm};
23use crate::enums::{
24 AlertDescription, CertificateType, CipherSuite, ContentType, HandshakeType, ProtocolVersion,
25};
26use crate::error::{Error, PeerIncompatible, PeerMisbehaved};
27use crate::hash_hs::HandshakeHashBuffer;
28use crate::log::{debug, trace};
29use crate::msgs::base::Payload;
30use crate::msgs::enums::{Compression, ExtensionType};
31use crate::msgs::handshake::{
32 CertificateStatusRequest, ClientExtensions, ClientExtensionsInput, ClientHelloPayload,
33 ClientSessionTicket, ClientTicketRequest, EncryptedClientHello, HandshakeMessagePayload,
34 HandshakePayload, HelloRetryRequest, KeyShareEntry, ProtocolName, PskKeyExchangeModes, Random,
35 ServerNamePayload, SessionId, SupportedEcPointFormats, SupportedProtocolVersions,
36 TransportParameters,
37};
38use crate::msgs::message::{Message, MessagePayload};
39use crate::msgs::persist;
40use crate::sync::Arc;
41use crate::tls13::key_schedule::KeyScheduleEarly;
42use crate::verify::ServerCertVerifier;
43
44pub(super) type NextState<'a> = Box<dyn State<ClientConnectionData> + 'a>;
45pub(super) type NextStateOrError<'a> = Result<NextState<'a>, Error>;
46pub(super) type ClientContext<'a> = crate::common_state::Context<'a, ClientConnectionData>;
47
48struct ExpectServerHello {
49 input: ClientHelloInput,
50 transcript_buffer: HandshakeHashBuffer,
51 early_data_key_schedule: Option<KeyScheduleEarly>,
59 offered_key_share: Option<Box<dyn ActiveKeyExchange>>,
60 suite: Option<SupportedCipherSuite>,
61 ech_state: Option<EchState>,
62}
63
64struct ExpectServerHelloOrHelloRetryRequest {
65 next: ExpectServerHello,
66 extra_exts: ClientExtensionsInput<'static>,
67}
68
69pub(super) struct ClientHelloInput {
70 pub(super) config: Arc<ClientConfig>,
71 pub(super) resuming: Option<persist::Retrieved<ClientSessionValue>>,
72 pub(super) random: Random,
73 pub(super) sent_tls13_fake_ccs: bool,
74 pub(super) hello: ClientHelloDetails,
75 pub(super) session_id: SessionId,
76 pub(super) server_name: ServerName<'static>,
77 pub(super) prev_ech_ext: Option<EncryptedClientHello>,
78}
79
80impl ClientHelloInput {
81 pub(super) fn new(
82 server_name: ServerName<'static>,
83 extra_exts: &ClientExtensionsInput<'_>,
84 cx: &mut ClientContext<'_>,
85 config: Arc<ClientConfig>,
86 ) -> Result<Self, Error> {
87 let mut resuming = ClientSessionValue::retrieve(&server_name, &config, cx);
88 let session_id = match &mut resuming {
89 Some(_resuming) => {
90 debug!("Resuming session");
91 match &mut _resuming.value {
92 #[cfg(feature = "tls12")]
93 ClientSessionValue::Tls12(inner) => {
94 if !inner.ticket().0.is_empty() {
98 inner.session_id = SessionId::random(config.provider.secure_random)?;
99 }
100 Some(inner.session_id)
101 }
102 _ => None,
103 }
104 }
105 _ => {
106 debug!("Not resuming any session");
107 None
108 }
109 };
110
111 let session_id = match session_id {
114 Some(session_id) => session_id,
115 None if cx.common.is_quic() => SessionId::empty(),
116 None if !config.supports_version(ProtocolVersion::TLSv1_3) => SessionId::empty(),
117 None => SessionId::random(config.provider.secure_random)?,
118 };
119
120 let hello = ClientHelloDetails::new(
121 extra_exts
122 .protocols
123 .clone()
124 .unwrap_or_default(),
125 crate::rand::random_u16(config.provider.secure_random)?,
126 );
127
128 Ok(Self {
129 resuming,
130 random: Random::new(config.provider.secure_random)?,
131 sent_tls13_fake_ccs: false,
132 hello,
133 session_id,
134 server_name,
135 prev_ech_ext: None,
136 config,
137 })
138 }
139
140 pub(super) fn start_handshake(
141 self,
142 extra_exts: ClientExtensionsInput<'static>,
143 cx: &mut ClientContext<'_>,
144 ) -> NextStateOrError<'static> {
145 let mut transcript_buffer = HandshakeHashBuffer::new();
146 if self
147 .config
148 .client_auth_cert_resolver
149 .has_certs()
150 {
151 transcript_buffer.set_client_auth_enabled();
152 }
153
154 let key_share = if self.config.needs_key_share() {
155 Some(tls13::initial_key_share(
156 &self.config,
157 &self.server_name,
158 &mut cx.common.kx_state,
159 )?)
160 } else {
161 None
162 };
163
164 let ech_state = match self.config.ech_mode.as_ref() {
165 Some(EchMode::Enable(ech_config)) => {
166 Some(ech_config.state(self.server_name.clone(), &self.config)?)
167 }
168 _ => None,
169 };
170
171 emit_client_hello_for_retry(
172 transcript_buffer,
173 None,
174 key_share,
175 extra_exts,
176 None,
177 self,
178 cx,
179 ech_state,
180 )
181 }
182}
183
184fn emit_client_hello_for_retry(
190 mut transcript_buffer: HandshakeHashBuffer,
191 retryreq: Option<&HelloRetryRequest>,
192 key_share: Option<Box<dyn ActiveKeyExchange>>,
193 extra_exts: ClientExtensionsInput<'static>,
194 suite: Option<SupportedCipherSuite>,
195 mut input: ClientHelloInput,
196 cx: &mut ClientContext<'_>,
197 mut ech_state: Option<EchState>,
198) -> NextStateOrError<'static> {
199 let config = &input.config;
200 let forbids_tls12 = cx.common.is_quic() || ech_state.is_some();
203
204 let supported_versions = SupportedProtocolVersions {
205 tls12: config.supports_version(ProtocolVersion::TLSv1_2) && !forbids_tls12,
206 tls13: config.supports_version(ProtocolVersion::TLSv1_3),
207 };
208
209 assert!(supported_versions.any(|_| true));
211
212 let mut exts = Box::new(ClientExtensions {
213 named_groups: Some(
215 config
216 .provider
217 .kx_groups
218 .iter()
219 .filter(|skxg| supported_versions.any(|v| skxg.usable_for_version(v)))
220 .map(|skxg| skxg.name())
221 .collect(),
222 ),
223 supported_versions: Some(supported_versions),
224 signature_schemes: Some(
225 config
226 .verifier
227 .supported_verify_schemes(),
228 ),
229 extended_master_secret_request: Some(()),
230 certificate_status_request: Some(CertificateStatusRequest::build_ocsp()),
231 protocols: extra_exts.protocols.clone(),
232 ..Default::default()
233 });
234
235 match extra_exts.transport_parameters.clone() {
236 Some(TransportParameters::Quic(v)) => exts.transport_parameters = Some(v),
237 Some(TransportParameters::QuicDraft(v)) => exts.transport_parameters_draft = Some(v),
238 None => {}
239 };
240
241 if supported_versions.tls13 {
242 if let Some(cas_extension) = config.verifier.root_hint_subjects() {
243 exts.certificate_authority_names = Some(cas_extension.to_owned());
244 }
245 }
246
247 if config
249 .provider
250 .kx_groups
251 .iter()
252 .any(|skxg| skxg.name().key_exchange_algorithm() == KeyExchangeAlgorithm::ECDHE)
253 {
254 exts.ec_point_formats = Some(SupportedEcPointFormats::default());
255 }
256
257 exts.server_name = match (ech_state.as_ref(), config.enable_sni) {
258 (Some(ech_state), _) => Some(ServerNamePayload::from(&ech_state.outer_name)),
263
264 (None, true) => match &input.server_name {
267 ServerName::DnsName(dns_name) => Some(ServerNamePayload::from(dns_name)),
268 _ => None,
269 },
270
271 (None, false) => None,
273 };
274
275 if let Some(key_share) = &key_share {
276 debug_assert!(supported_versions.tls13);
277 let mut shares = vec![KeyShareEntry::new(key_share.group(), key_share.pub_key())];
278
279 if !retryreq
280 .map(|rr| rr.key_share.is_some())
281 .unwrap_or_default()
282 {
283 if let Some((component_group, component_share)) =
288 key_share
289 .hybrid_component()
290 .filter(|(group, _)| {
291 config
292 .find_kx_group(*group, ProtocolVersion::TLSv1_3)
293 .is_some()
294 })
295 {
296 shares.push(KeyShareEntry::new(component_group, component_share));
297 }
298 }
299
300 exts.key_shares = Some(shares);
301 }
302
303 if let Some(cookie) = retryreq.and_then(|hrr| hrr.cookie.as_ref()) {
304 exts.cookie = Some(cookie.clone());
305 }
306
307 if supported_versions.tls13 {
308 exts.preshared_key_modes = Some(PskKeyExchangeModes {
311 psk: false,
312 psk_dhe: true,
313 });
314
315 if let Some(ticket_req) = &config.send_ticket_request {
316 exts.ticket_request = Some(ClientTicketRequest {
317 new_session_count: ticket_req.new_session_count,
318 resumption_count: ticket_req.resumption_count,
319 });
320 }
321 }
322
323 input.hello.offered_cert_compression =
324 if supported_versions.tls13 && !config.cert_decompressors.is_empty() {
325 exts.certificate_compression_algorithms = Some(
326 config
327 .cert_decompressors
328 .iter()
329 .map(|dec| dec.algorithm())
330 .collect(),
331 );
332 true
333 } else {
334 false
335 };
336
337 if config
338 .client_auth_cert_resolver
339 .only_raw_public_keys()
340 {
341 exts.client_certificate_types = Some(vec![CertificateType::RawPublicKey]);
342 }
343
344 if config
345 .verifier
346 .requires_raw_public_keys()
347 {
348 exts.server_certificate_types = Some(vec![CertificateType::RawPublicKey]);
349 }
350
351 if matches!(cx.data.ech_status, EchStatus::Rejected | EchStatus::Grease) & retryreq.is_some() {
355 if let Some(prev_ech_ext) = input.prev_ech_ext.take() {
356 exts.encrypted_client_hello = Some(prev_ech_ext);
357 }
358 }
359
360 let tls13_session = prepare_resumption(&input.resuming, &mut exts, suite, cx, config);
362
363 exts.order_seed = input.hello.extension_order_seed;
366
367 let mut cipher_suites: Vec<_> = config
368 .provider
369 .cipher_suites
370 .iter()
371 .filter_map(|cs| match cs.usable_for_protocol(cx.common.protocol) {
372 true => Some(cs.suite()),
373 false => None,
374 })
375 .collect();
376
377 if supported_versions.tls12 {
378 cipher_suites.push(CipherSuite::TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
380 }
381
382 let mut chp_payload = ClientHelloPayload {
383 client_version: ProtocolVersion::TLSv1_2,
384 random: input.random,
385 session_id: input.session_id,
386 cipher_suites,
387 compression_methods: vec![Compression::Null],
388 extensions: exts,
389 };
390
391 let ech_grease_ext = config
392 .ech_mode
393 .as_ref()
394 .and_then(|mode| match mode {
395 EchMode::Grease(cfg) => Some(cfg.grease_ext(
396 config.provider.secure_random,
397 input.server_name.clone(),
398 &chp_payload,
399 )),
400 _ => None,
401 });
402
403 match (cx.data.ech_status, &mut ech_state) {
404 (EchStatus::NotOffered | EchStatus::Offered, Some(ech_state)) => {
407 chp_payload = ech_state.ech_hello(chp_payload, retryreq, &tls13_session)?;
409 cx.data.ech_status = EchStatus::Offered;
410 input.prev_ech_ext = chp_payload
412 .encrypted_client_hello
413 .clone();
414 }
415 (EchStatus::NotOffered, None) => {
418 if let Some(grease_ext) = ech_grease_ext {
419 let grease_ext = grease_ext?;
421 chp_payload.encrypted_client_hello = Some(grease_ext.clone());
422 cx.data.ech_status = EchStatus::Grease;
423 input.prev_ech_ext = Some(grease_ext);
426 }
427 }
428 _ => {}
429 }
430
431 input.hello.sent_extensions = chp_payload.collect_used();
433
434 let mut chp = HandshakeMessagePayload(HandshakePayload::ClientHello(chp_payload));
435
436 let tls13_early_data_key_schedule = match (ech_state.as_mut(), tls13_session) {
437 (Some(ech_state), Some(tls13_session)) => ech_state
440 .early_data_key_schedule
441 .take()
442 .map(|schedule| (tls13_session.suite(), schedule)),
443
444 (_, Some(tls13_session)) => Some((
447 tls13_session.suite(),
448 tls13::fill_in_psk_binder(&tls13_session, &transcript_buffer, &mut chp),
449 )),
450
451 _ => None,
453 };
454
455 let ch = Message {
456 version: match retryreq {
457 Some(_) => ProtocolVersion::TLSv1_2,
461 None => ProtocolVersion::TLSv1_0,
467 },
468 payload: MessagePayload::handshake(chp),
469 };
470
471 if retryreq.is_some() {
472 tls13::emit_fake_ccs(&mut input.sent_tls13_fake_ccs, cx.common);
475 }
476
477 trace!("Sending ClientHello {ch:#?}");
478
479 transcript_buffer.add_message(&ch);
480 cx.common.send_msg(ch, false);
481
482 let early_data_key_schedule =
484 tls13_early_data_key_schedule.map(|(resuming_suite, schedule)| {
485 if !cx.data.early_data.is_enabled() {
486 return schedule;
487 }
488
489 let (transcript_buffer, random) = match &ech_state {
490 Some(ech_state) => (
493 &ech_state.inner_hello_transcript,
494 &ech_state.inner_hello_random.0,
495 ),
496 None => (&transcript_buffer, &input.random.0),
497 };
498
499 tls13::derive_early_traffic_secret(
500 &*config.key_log,
501 cx,
502 resuming_suite.common.hash_provider,
503 &schedule,
504 &mut input.sent_tls13_fake_ccs,
505 transcript_buffer,
506 random,
507 );
508 schedule
509 });
510
511 let next = ExpectServerHello {
512 input,
513 transcript_buffer,
514 early_data_key_schedule,
515 offered_key_share: key_share,
516 suite,
517 ech_state,
518 };
519
520 Ok(if supported_versions.tls13 && retryreq.is_none() {
521 Box::new(ExpectServerHelloOrHelloRetryRequest {
522 next,
523 extra_exts: extra_exts.into_owned(),
524 })
525 } else {
526 Box::new(next)
527 })
528}
529
530fn prepare_resumption<'a>(
546 resuming: &'a Option<persist::Retrieved<ClientSessionValue>>,
547 exts: &mut ClientExtensions<'_>,
548 suite: Option<SupportedCipherSuite>,
549 cx: &mut ClientContext<'_>,
550 config: &ClientConfig,
551) -> Option<persist::Retrieved<&'a persist::Tls13ClientSessionValue>> {
552 let resuming = match resuming {
554 Some(resuming) if !resuming.ticket().is_empty() => resuming,
555 _ => {
556 if config.supports_version(ProtocolVersion::TLSv1_2)
557 && config.resumption.tls12_resumption == Tls12Resumption::SessionIdOrTickets
558 {
559 exts.session_ticket = Some(ClientSessionTicket::Request);
561 }
562 return None;
563 }
564 };
565
566 let Some(tls13) = resuming.map(|csv| csv.tls13()) else {
567 if config.supports_version(ProtocolVersion::TLSv1_2)
569 && config.resumption.tls12_resumption == Tls12Resumption::SessionIdOrTickets
570 {
571 exts.session_ticket = Some(ClientSessionTicket::Offer(Payload::new(resuming.ticket())));
572 }
573 return None; };
575
576 if !config.supports_version(ProtocolVersion::TLSv1_3) {
577 return None;
578 }
579
580 let suite = match suite {
582 Some(SupportedCipherSuite::Tls13(suite)) => Some(suite),
583 #[cfg(feature = "tls12")]
584 Some(SupportedCipherSuite::Tls12(_)) => return None,
585 None => None,
586 };
587
588 if let Some(suite) = suite {
590 suite.can_resume_from(tls13.suite())?;
591 }
592
593 tls13::prepare_resumption(config, cx, &tls13, exts, suite.is_some());
594 Some(tls13)
595}
596
597pub(super) fn process_alpn_protocol(
598 common: &mut CommonState,
599 offered_protocols: &[ProtocolName],
600 selected: Option<&ProtocolName>,
601 check_selected_offered: bool,
602) -> Result<(), Error> {
603 common.alpn_protocol = selected.map(ToOwned::to_owned);
604
605 if let Some(alpn_protocol) = &common.alpn_protocol {
606 if check_selected_offered && !offered_protocols.contains(alpn_protocol) {
607 return Err(common.send_fatal_alert(
608 AlertDescription::IllegalParameter,
609 PeerMisbehaved::SelectedUnofferedApplicationProtocol,
610 ));
611 }
612 }
613
614 if common.is_quic() && common.alpn_protocol.is_none() && !offered_protocols.is_empty() {
621 return Err(common.send_fatal_alert(
622 AlertDescription::NoApplicationProtocol,
623 Error::NoApplicationProtocol,
624 ));
625 }
626
627 debug!(
628 "ALPN protocol is {:?}",
629 common
630 .alpn_protocol
631 .as_ref()
632 .map(|v| bs_debug::BsDebug(v.as_ref()))
633 );
634 Ok(())
635}
636
637pub(super) fn process_server_cert_type_extension(
638 common: &mut CommonState,
639 config: &ClientConfig,
640 server_cert_extension: Option<&CertificateType>,
641) -> Result<Option<(ExtensionType, CertificateType)>, Error> {
642 process_cert_type_extension(
643 common,
644 config
645 .verifier
646 .requires_raw_public_keys(),
647 server_cert_extension.copied(),
648 ExtensionType::ServerCertificateType,
649 )
650}
651
652pub(super) fn process_client_cert_type_extension(
653 common: &mut CommonState,
654 config: &ClientConfig,
655 client_cert_extension: Option<&CertificateType>,
656) -> Result<Option<(ExtensionType, CertificateType)>, Error> {
657 process_cert_type_extension(
658 common,
659 config
660 .client_auth_cert_resolver
661 .only_raw_public_keys(),
662 client_cert_extension.copied(),
663 ExtensionType::ClientCertificateType,
664 )
665}
666
667impl State<ClientConnectionData> for ExpectServerHello {
668 fn handle<'m>(
669 mut self: Box<Self>,
670 cx: &mut ClientContext<'_>,
671 m: Message<'m>,
672 ) -> NextStateOrError<'m>
673 where
674 Self: 'm,
675 {
676 let server_hello =
677 require_handshake_msg!(m, HandshakeType::ServerHello, HandshakePayload::ServerHello)?;
678 trace!("We got ServerHello {server_hello:#?}");
679
680 use crate::ProtocolVersion::{TLSv1_2, TLSv1_3};
681 let config = &self.input.config;
682 let tls13_supported = config.supports_version(TLSv1_3);
683
684 let server_version = if server_hello.legacy_version == TLSv1_2 {
685 server_hello
686 .selected_version
687 .unwrap_or(server_hello.legacy_version)
688 } else {
689 server_hello.legacy_version
690 };
691
692 let version = match server_version {
693 TLSv1_3 if tls13_supported => TLSv1_3,
694 TLSv1_2 if config.supports_version(TLSv1_2) => {
695 if cx.data.early_data.is_enabled() && cx.common.early_traffic {
696 return Err(PeerMisbehaved::OfferedEarlyDataWithOldProtocolVersion.into());
699 }
700
701 if server_hello.selected_version.is_some() {
702 return Err({
703 cx.common.send_fatal_alert(
704 AlertDescription::IllegalParameter,
705 PeerMisbehaved::SelectedTls12UsingTls13VersionExtension,
706 )
707 });
708 }
709
710 TLSv1_2
711 }
712 _ => {
713 let reason = match server_version {
714 TLSv1_2 | TLSv1_3 => PeerIncompatible::ServerTlsVersionIsDisabledByOurConfig,
715 _ => PeerIncompatible::ServerDoesNotSupportTls12Or13,
716 };
717 return Err(cx
718 .common
719 .send_fatal_alert(AlertDescription::ProtocolVersion, reason));
720 }
721 };
722
723 if server_hello.compression_method != Compression::Null {
724 return Err({
725 cx.common.send_fatal_alert(
726 AlertDescription::IllegalParameter,
727 PeerMisbehaved::SelectedUnofferedCompression,
728 )
729 });
730 }
731
732 let allowed_unsolicited = [ExtensionType::RenegotiationInfo];
733 if self
734 .input
735 .hello
736 .server_sent_unsolicited_extensions(server_hello, &allowed_unsolicited)
737 {
738 return Err(cx.common.send_fatal_alert(
739 AlertDescription::UnsupportedExtension,
740 PeerMisbehaved::UnsolicitedServerHelloExtension,
741 ));
742 }
743
744 cx.common.negotiated_version = Some(version);
745
746 if !cx.common.is_tls13() {
748 process_alpn_protocol(
749 cx.common,
750 &self.input.hello.alpn_protocols,
751 server_hello
752 .selected_protocol
753 .as_ref()
754 .map(|s| s.as_ref()),
755 self.input.config.check_selected_alpn,
756 )?;
757 }
758
759 if let Some(point_fmts) = &server_hello.ec_point_formats {
762 if !point_fmts.uncompressed {
763 return Err(cx.common.send_fatal_alert(
764 AlertDescription::HandshakeFailure,
765 PeerMisbehaved::ServerHelloMustOfferUncompressedEcPoints,
766 ));
767 }
768 }
769
770 let suite = config
771 .find_cipher_suite(server_hello.cipher_suite)
772 .ok_or_else(|| {
773 cx.common.send_fatal_alert(
774 AlertDescription::HandshakeFailure,
775 PeerMisbehaved::SelectedUnofferedCipherSuite,
776 )
777 })?;
778
779 if version != suite.version().version {
780 return Err({
781 cx.common.send_fatal_alert(
782 AlertDescription::IllegalParameter,
783 PeerMisbehaved::SelectedUnusableCipherSuiteForVersion,
784 )
785 });
786 }
787
788 match self.suite {
789 Some(prev_suite) if prev_suite != suite => {
790 return Err({
791 cx.common.send_fatal_alert(
792 AlertDescription::IllegalParameter,
793 PeerMisbehaved::SelectedDifferentCipherSuiteAfterRetry,
794 )
795 });
796 }
797 _ => {
798 debug!("Using ciphersuite {suite:?}");
799 self.suite = Some(suite);
800 cx.common.suite = Some(suite);
801 }
802 }
803
804 let mut transcript = self
806 .transcript_buffer
807 .start_hash(suite.hash_provider());
808 transcript.add_message(&m);
809
810 let randoms = ConnectionRandoms::new(self.input.random, server_hello.random);
811 match suite {
814 SupportedCipherSuite::Tls13(suite) => {
815 tls13::handle_server_hello(
816 cx,
817 server_hello,
818 randoms,
819 suite,
820 transcript,
821 self.early_data_key_schedule,
822 self.offered_key_share.unwrap(),
824 &m,
825 self.ech_state,
826 self.input,
827 )
828 }
829 #[cfg(feature = "tls12")]
830 SupportedCipherSuite::Tls12(suite) => tls12::CompleteServerHelloHandling {
831 randoms,
832 transcript,
833 input: self.input,
834 }
835 .handle_server_hello(cx, suite, server_hello, tls13_supported),
836 }
837 }
838
839 fn into_owned(self: Box<Self>) -> NextState<'static> {
840 self
841 }
842}
843
844impl ExpectServerHelloOrHelloRetryRequest {
845 fn into_expect_server_hello(self) -> NextState<'static> {
846 Box::new(self.next)
847 }
848
849 fn handle_hello_retry_request(
850 mut self,
851 cx: &mut ClientContext<'_>,
852 m: Message<'_>,
853 ) -> NextStateOrError<'static> {
854 let hrr = require_handshake_msg!(
855 m,
856 HandshakeType::HelloRetryRequest,
857 HandshakePayload::HelloRetryRequest
858 )?;
859 trace!("Got HRR {hrr:?}");
860
861 cx.common.check_aligned_handshake()?;
862
863 let offered_key_share = self.next.offered_key_share.unwrap();
865
866 let config = &self.next.input.config;
869
870 if let (None, Some(req_group)) = (&hrr.cookie, hrr.key_share) {
871 let offered_hybrid = offered_key_share
872 .hybrid_component()
873 .and_then(|(group_name, _)| {
874 config.find_kx_group(group_name, ProtocolVersion::TLSv1_3)
875 })
876 .map(|skxg| skxg.name());
877
878 if req_group == offered_key_share.group() || Some(req_group) == offered_hybrid {
879 return Err({
880 cx.common.send_fatal_alert(
881 AlertDescription::IllegalParameter,
882 PeerMisbehaved::IllegalHelloRetryRequestWithOfferedGroup,
883 )
884 });
885 }
886 }
887
888 if let Some(cookie) = &hrr.cookie {
890 if cookie.0.is_empty() {
891 return Err({
892 cx.common.send_fatal_alert(
893 AlertDescription::IllegalParameter,
894 PeerMisbehaved::IllegalHelloRetryRequestWithEmptyCookie,
895 )
896 });
897 }
898 }
899
900 if hrr.cookie.is_none() && hrr.key_share.is_none() {
902 return Err({
903 cx.common.send_fatal_alert(
904 AlertDescription::IllegalParameter,
905 PeerMisbehaved::IllegalHelloRetryRequestWithNoChanges,
906 )
907 });
908 }
909
910 if hrr.session_id != self.next.input.session_id {
924 return Err({
925 cx.common.send_fatal_alert(
926 AlertDescription::IllegalParameter,
927 PeerMisbehaved::IllegalHelloRetryRequestWithWrongSessionId,
928 )
929 });
930 }
931
932 match hrr.supported_versions {
934 Some(ProtocolVersion::TLSv1_3) => {
935 cx.common.negotiated_version = Some(ProtocolVersion::TLSv1_3);
936 }
937 _ => {
938 return Err({
939 cx.common.send_fatal_alert(
940 AlertDescription::IllegalParameter,
941 PeerMisbehaved::IllegalHelloRetryRequestWithUnsupportedVersion,
942 )
943 });
944 }
945 }
946
947 let Some(cs) = config.find_cipher_suite(hrr.cipher_suite) else {
949 return Err({
950 cx.common.send_fatal_alert(
951 AlertDescription::IllegalParameter,
952 PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedCipherSuite,
953 )
954 });
955 };
956
957 if cx.data.ech_status == EchStatus::NotOffered && hrr.encrypted_client_hello.is_some() {
959 return Err({
960 cx.common.send_fatal_alert(
961 AlertDescription::UnsupportedExtension,
962 PeerMisbehaved::IllegalHelloRetryRequestWithInvalidEch,
963 )
964 });
965 }
966
967 cx.common.suite = Some(cs);
969 cx.common.handshake_kind = Some(HandshakeKind::FullWithHelloRetryRequest);
970
971 match (self.next.ech_state.as_ref(), cs.tls13()) {
973 (Some(ech_state), Some(tls13_cs))
977 if !ech_state.confirm_hrr_acceptance(hrr, tls13_cs, cx.common)? =>
978 {
979 cx.data.ech_status = EchStatus::Rejected
980 }
981 (Some(_), None) => {
982 unreachable!("ECH state should only be set when TLS 1.3 was negotiated")
983 }
984 _ => {}
985 };
986
987 let transcript = self
989 .next
990 .transcript_buffer
991 .start_hash(cs.hash_provider());
992 let mut transcript_buffer = transcript.into_hrr_buffer();
993 transcript_buffer.add_message(&m);
994
995 if let Some(ech_state) = self.next.ech_state.as_mut() {
998 ech_state.transcript_hrr_update(cs.hash_provider(), &m);
999 }
1000
1001 if cx.data.early_data.is_enabled() {
1003 cx.data.early_data.rejected();
1004 }
1005
1006 let key_share = match hrr.key_share {
1007 Some(group) if group != offered_key_share.group() => {
1008 let Some(skxg) = config.find_kx_group(group, ProtocolVersion::TLSv1_3) else {
1009 return Err(cx.common.send_fatal_alert(
1010 AlertDescription::IllegalParameter,
1011 PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedNamedGroup,
1012 ));
1013 };
1014
1015 cx.common.kx_state = KxState::Start(skxg);
1016 skxg.start()?
1017 }
1018 _ => offered_key_share,
1019 };
1020
1021 emit_client_hello_for_retry(
1022 transcript_buffer,
1023 Some(hrr),
1024 Some(key_share),
1025 self.extra_exts,
1026 Some(cs),
1027 self.next.input,
1028 cx,
1029 self.next.ech_state,
1030 )
1031 }
1032}
1033
1034impl State<ClientConnectionData> for ExpectServerHelloOrHelloRetryRequest {
1035 fn handle<'m>(
1036 self: Box<Self>,
1037 cx: &mut ClientContext<'_>,
1038 m: Message<'m>,
1039 ) -> NextStateOrError<'m>
1040 where
1041 Self: 'm,
1042 {
1043 match m.payload {
1044 MessagePayload::Handshake {
1045 parsed: HandshakeMessagePayload(HandshakePayload::ServerHello(..)),
1046 ..
1047 } => self
1048 .into_expect_server_hello()
1049 .handle(cx, m),
1050 MessagePayload::Handshake {
1051 parsed: HandshakeMessagePayload(HandshakePayload::HelloRetryRequest(..)),
1052 ..
1053 } => self.handle_hello_retry_request(cx, m),
1054 payload => Err(inappropriate_handshake_message(
1055 &payload,
1056 &[ContentType::Handshake],
1057 &[HandshakeType::ServerHello, HandshakeType::HelloRetryRequest],
1058 )),
1059 }
1060 }
1061
1062 fn into_owned(self: Box<Self>) -> NextState<'static> {
1063 self
1064 }
1065}
1066
1067fn process_cert_type_extension(
1068 common: &mut CommonState,
1069 client_expects: bool,
1070 server_negotiated: Option<CertificateType>,
1071 extension_type: ExtensionType,
1072) -> Result<Option<(ExtensionType, CertificateType)>, Error> {
1073 match (client_expects, server_negotiated) {
1074 (true, Some(CertificateType::RawPublicKey)) => {
1075 Ok(Some((extension_type, CertificateType::RawPublicKey)))
1076 }
1077 (true, _) => Err(common.send_fatal_alert(
1078 AlertDescription::HandshakeFailure,
1079 Error::PeerIncompatible(PeerIncompatible::IncorrectCertificateTypeExtension),
1080 )),
1081 (_, Some(CertificateType::RawPublicKey)) => {
1082 unreachable!("Caught by `PeerMisbehaved::UnsolicitedEncryptedExtension`")
1083 }
1084 (_, _) => Ok(None),
1085 }
1086}
1087
1088pub(super) enum ClientSessionValue {
1089 Tls13(persist::Tls13ClientSessionValue),
1090 #[cfg(feature = "tls12")]
1091 Tls12(persist::Tls12ClientSessionValue),
1092}
1093
1094impl ClientSessionValue {
1095 fn retrieve(
1096 server_name: &ServerName<'static>,
1097 config: &ClientConfig,
1098 cx: &mut ClientContext<'_>,
1099 ) -> Option<persist::Retrieved<Self>> {
1100 let found = config
1101 .resumption
1102 .store
1103 .take_tls13_ticket(server_name)
1104 .map(ClientSessionValue::Tls13)
1105 .or_else(|| {
1106 #[cfg(feature = "tls12")]
1107 {
1108 config
1109 .resumption
1110 .store
1111 .tls12_session(server_name)
1112 .map(ClientSessionValue::Tls12)
1113 }
1114
1115 #[cfg(not(feature = "tls12"))]
1116 None
1117 })
1118 .and_then(|resuming| {
1119 resuming.compatible_config(&config.verifier, &config.client_auth_cert_resolver)
1120 })
1121 .and_then(|resuming| {
1122 let now = config
1123 .current_time()
1124 .map_err(|_err| debug!("Could not get current time: {_err}"))
1125 .ok()?;
1126
1127 let retrieved = persist::Retrieved::new(resuming, now);
1128 match retrieved.has_expired() {
1129 false => Some(retrieved),
1130 true => None,
1131 }
1132 })
1133 .or_else(|| {
1134 debug!("No cached session for {server_name:?}");
1135 None
1136 });
1137
1138 if let Some(resuming) = &found {
1139 if cx.common.is_quic() {
1140 cx.common.quic.params = resuming
1141 .tls13()
1142 .map(|v| v.quic_params());
1143 }
1144 }
1145
1146 found
1147 }
1148
1149 fn common(&self) -> &persist::ClientSessionCommon {
1150 match self {
1151 Self::Tls13(inner) => &inner.common,
1152 #[cfg(feature = "tls12")]
1153 Self::Tls12(inner) => &inner.common,
1154 }
1155 }
1156
1157 fn tls13(&self) -> Option<&persist::Tls13ClientSessionValue> {
1158 match self {
1159 Self::Tls13(v) => Some(v),
1160 #[cfg(feature = "tls12")]
1161 Self::Tls12(_) => None,
1162 }
1163 }
1164
1165 fn compatible_config(
1166 self,
1167 server_cert_verifier: &Arc<dyn ServerCertVerifier>,
1168 client_creds: &Arc<dyn ResolvesClientCert>,
1169 ) -> Option<Self> {
1170 match &self {
1171 Self::Tls13(v) => v
1172 .compatible_config(server_cert_verifier, client_creds)
1173 .then_some(self),
1174 #[cfg(feature = "tls12")]
1175 Self::Tls12(v) => v
1176 .compatible_config(server_cert_verifier, client_creds)
1177 .then_some(self),
1178 }
1179 }
1180}
1181
1182impl Deref for ClientSessionValue {
1183 type Target = persist::ClientSessionCommon;
1184
1185 fn deref(&self) -> &Self::Target {
1186 self.common()
1187 }
1188}