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