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