1#[cfg(feature = "logging")]
2use crate::bs_debug;
3use crate::check::inappropriate_handshake_message;
4use crate::common_state::{CommonState, State};
5use crate::conn::ConnectionRandoms;
6use crate::enums::{AlertDescription, CipherSuite, ContentType, HandshakeType, ProtocolVersion};
7use crate::error::{Error, PeerIncompatible, PeerMisbehaved};
8use crate::hash_hs::HandshakeHashBuffer;
9use crate::kx;
10#[cfg(feature = "logging")]
11use crate::log::{debug, trace};
12use crate::msgs::base::Payload;
13use crate::msgs::enums::{Compression, ExtensionType};
14use crate::msgs::enums::{ECPointFormat, PSKKeyExchangeMode};
15use crate::msgs::handshake::ConvertProtocolNameList;
16use crate::msgs::handshake::{CertificateStatusRequest, ClientSessionTicket, Sct};
17use crate::msgs::handshake::{ClientExtension, HasServerExtensions};
18use crate::msgs::handshake::{ClientHelloPayload, HandshakeMessagePayload, HandshakePayload};
19use crate::msgs::handshake::{HelloRetryRequest, KeyShareEntry};
20use crate::msgs::handshake::{Random, SessionId};
21use crate::msgs::message::{Message, MessagePayload};
22use crate::msgs::persist;
23use crate::ticketer::TimeBase;
24use crate::tls13::key_schedule::KeyScheduleEarly;
25use crate::SupportedCipherSuite;
26
27#[cfg(feature = "tls12")]
28use super::tls12;
29use super::Tls12Resumption;
30use crate::client::client_conn::ClientConnectionData;
31use crate::client::common::ClientHelloDetails;
32use crate::client::{tls13, ClientConfig, ServerName};
33
34use std::ops::Deref;
35use std::sync::Arc;
36
37pub(super) type NextState = Box<dyn State<ClientConnectionData>>;
38pub(super) type NextStateOrError = Result<NextState, Error>;
39pub(super) type ClientContext<'a> = crate::common_state::Context<'a, ClientConnectionData>;
40
41fn find_session(
42 server_name: &ServerName,
43 config: &ClientConfig,
44 #[cfg(feature = "quic")] cx: &mut ClientContext<'_>,
45) -> Option<persist::Retrieved<ClientSessionValue>> {
46 #[allow(clippy::let_and_return, clippy::unnecessary_lazy_evaluations)]
47 let found = config
48 .resumption
49 .store
50 .take_tls13_ticket(server_name)
51 .map(ClientSessionValue::Tls13)
52 .or_else(|| {
53 #[cfg(feature = "tls12")]
54 {
55 config
56 .resumption
57 .store
58 .tls12_session(server_name)
59 .map(ClientSessionValue::Tls12)
60 }
61
62 #[cfg(not(feature = "tls12"))]
63 None
64 })
65 .and_then(|resuming| {
66 let retrieved = persist::Retrieved::new(resuming, TimeBase::now().ok()?);
67 match retrieved.has_expired() {
68 false => Some(retrieved),
69 true => None,
70 }
71 })
72 .or_else(|| {
73 debug!("No cached session for {:?}", server_name);
74 None
75 });
76
77 #[cfg(feature = "quic")]
78 if let Some(resuming) = &found {
79 if cx.common.is_quic() {
80 cx.common.quic.params = resuming
81 .tls13()
82 .map(|v| v.quic_params());
83 }
84 }
85
86 found
87}
88
89pub(super) fn start_handshake(
90 server_name: ServerName,
91 extra_exts: Vec<ClientExtension>,
92 config: Arc<ClientConfig>,
93 cx: &mut ClientContext<'_>,
94) -> NextStateOrError {
95 let mut transcript_buffer = HandshakeHashBuffer::new();
96 if config
97 .client_auth_cert_resolver
98 .has_certs()
99 {
100 transcript_buffer.set_client_auth_enabled();
101 }
102
103 let mut resuming = find_session(
104 &server_name,
105 &config,
106 #[cfg(feature = "quic")]
107 cx,
108 );
109
110 let key_share = if config.supports_version(ProtocolVersion::TLSv1_3) {
111 Some(tls13::initial_key_share(&config, &server_name)?)
112 } else {
113 None
114 };
115
116 #[cfg_attr(not(feature = "tls12"), allow(unused_mut))]
117 let mut session_id = None;
118 if let Some(_resuming) = &mut resuming {
119 #[cfg(feature = "tls12")]
120 if let ClientSessionValue::Tls12(inner) = &mut _resuming.value {
121 if !inner.ticket().is_empty() {
125 inner.session_id = SessionId::random()?;
126 }
127 session_id = Some(inner.session_id);
128 }
129
130 debug!("Resuming session");
131 } else {
132 debug!("Not resuming any session");
133 }
134
135 let session_id = match session_id {
138 Some(session_id) => session_id,
139 None if cx.common.is_quic() => SessionId::empty(),
140 None if !config.supports_version(ProtocolVersion::TLSv1_3) => SessionId::empty(),
141 None => SessionId::random()?,
142 };
143
144 let may_send_sct_list = config.verifier.request_scts();
145 Ok(emit_client_hello_for_retry(
146 transcript_buffer,
147 None,
148 key_share,
149 extra_exts,
150 may_send_sct_list,
151 None,
152 ClientHelloInput {
153 config,
154 resuming,
155 random: Random::new()?,
156 #[cfg(feature = "tls12")]
157 using_ems: false,
158 sent_tls13_fake_ccs: false,
159 hello: ClientHelloDetails::new(),
160 session_id,
161 server_name,
162 },
163 cx,
164 ))
165}
166
167struct ExpectServerHello {
168 input: ClientHelloInput,
169 transcript_buffer: HandshakeHashBuffer,
170 early_key_schedule: Option<KeyScheduleEarly>,
171 offered_key_share: Option<kx::KeyExchange>,
172 suite: Option<SupportedCipherSuite>,
173}
174
175struct ExpectServerHelloOrHelloRetryRequest {
176 next: ExpectServerHello,
177 extra_exts: Vec<ClientExtension>,
178}
179
180struct ClientHelloInput {
181 config: Arc<ClientConfig>,
182 resuming: Option<persist::Retrieved<ClientSessionValue>>,
183 random: Random,
184 #[cfg(feature = "tls12")]
185 using_ems: bool,
186 sent_tls13_fake_ccs: bool,
187 hello: ClientHelloDetails,
188 session_id: SessionId,
189 server_name: ServerName,
190}
191
192fn emit_client_hello_for_retry(
193 mut transcript_buffer: HandshakeHashBuffer,
194 retryreq: Option<&HelloRetryRequest>,
195 key_share: Option<kx::KeyExchange>,
196 extra_exts: Vec<ClientExtension>,
197 may_send_sct_list: bool,
198 suite: Option<SupportedCipherSuite>,
199 mut input: ClientHelloInput,
200 cx: &mut ClientContext<'_>,
201) -> NextState {
202 let config = &input.config;
203 let support_tls12 = config.supports_version(ProtocolVersion::TLSv1_2) && !cx.common.is_quic();
204 let support_tls13 = config.supports_version(ProtocolVersion::TLSv1_3);
205
206 let mut supported_versions = Vec::new();
207 if support_tls13 {
208 supported_versions.push(ProtocolVersion::TLSv1_3);
209 }
210
211 if support_tls12 {
212 supported_versions.push(ProtocolVersion::TLSv1_2);
213 }
214
215 assert!(!supported_versions.is_empty());
217
218 let mut exts = vec![
219 ClientExtension::SupportedVersions(supported_versions),
220 ClientExtension::ECPointFormats(ECPointFormat::SUPPORTED.to_vec()),
221 ClientExtension::NamedGroups(
222 config
223 .kx_groups
224 .iter()
225 .map(|skxg| skxg.name)
226 .collect(),
227 ),
228 ClientExtension::SignatureAlgorithms(
229 config
230 .verifier
231 .supported_verify_schemes(),
232 ),
233 ClientExtension::ExtendedMasterSecretRequest,
234 ClientExtension::CertificateStatusRequest(CertificateStatusRequest::build_ocsp()),
235 ];
236
237 if let (Some(sni_name), true) = (input.server_name.for_sni(), config.enable_sni) {
238 exts.push(ClientExtension::make_sni(sni_name));
239 }
240
241 if may_send_sct_list {
242 exts.push(ClientExtension::SignedCertificateTimestampRequest);
243 }
244
245 if let Some(key_share) = &key_share {
246 debug_assert!(support_tls13);
247 let key_share = KeyShareEntry::new(key_share.group(), key_share.pubkey.as_ref());
248 exts.push(ClientExtension::KeyShare(vec![key_share]));
249 }
250
251 if let Some(cookie) = retryreq.and_then(HelloRetryRequest::get_cookie) {
252 exts.push(ClientExtension::Cookie(cookie.clone()));
253 }
254
255 if support_tls13 {
256 let psk_modes = vec![PSKKeyExchangeMode::PSK_DHE_KE];
259 exts.push(ClientExtension::PresharedKeyModes(psk_modes));
260 }
261
262 if !config.alpn_protocols.is_empty() {
263 exts.push(ClientExtension::Protocols(Vec::from_slices(
264 &config
265 .alpn_protocols
266 .iter()
267 .map(|proto| &proto[..])
268 .collect::<Vec<_>>(),
269 )));
270 }
271
272 exts.extend(extra_exts.iter().cloned());
274
275 let tls13_session = prepare_resumption(&input.resuming, &mut exts, suite, cx, config);
277
278 input.hello.sent_extensions = exts
280 .iter()
281 .map(ClientExtension::get_type)
282 .collect();
283
284 let mut cipher_suites: Vec<_> = config
285 .cipher_suites
286 .iter()
287 .map(|cs| cs.suite())
288 .collect();
289 cipher_suites.push(CipherSuite::TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
291
292 let mut chp = HandshakeMessagePayload {
293 typ: HandshakeType::ClientHello,
294 payload: HandshakePayload::ClientHello(ClientHelloPayload {
295 client_version: ProtocolVersion::TLSv1_2,
296 random: input.random,
297 session_id: input.session_id,
298 cipher_suites,
299 compression_methods: vec![Compression::Null],
300 extensions: exts,
301 }),
302 };
303
304 let early_key_schedule = if let Some(resuming) = tls13_session {
305 let schedule = tls13::fill_in_psk_binder(&resuming, &transcript_buffer, &mut chp);
306 Some((resuming.suite(), schedule))
307 } else {
308 None
309 };
310
311 let ch = Message {
312 version: if retryreq.is_some() {
316 ProtocolVersion::TLSv1_2
317 } else {
318 ProtocolVersion::TLSv1_0
319 },
320 payload: MessagePayload::handshake(chp),
321 };
322
323 if retryreq.is_some() {
324 tls13::emit_fake_ccs(&mut input.sent_tls13_fake_ccs, cx.common);
327 }
328
329 trace!("Sending ClientHello {:#?}", ch);
330
331 transcript_buffer.add_message(&ch);
332 cx.common.send_msg(ch, false);
333
334 let early_key_schedule = early_key_schedule.map(|(resuming_suite, schedule)| {
336 if !cx.data.early_data.is_enabled() {
337 return schedule;
338 }
339
340 tls13::derive_early_traffic_secret(
341 &*config.key_log,
342 cx,
343 resuming_suite,
344 &schedule,
345 &mut input.sent_tls13_fake_ccs,
346 &transcript_buffer,
347 &input.random.0,
348 );
349 schedule
350 });
351
352 let next = ExpectServerHello {
353 input,
354 transcript_buffer,
355 early_key_schedule,
356 offered_key_share: key_share,
357 suite,
358 };
359
360 if support_tls13 && retryreq.is_none() {
361 Box::new(ExpectServerHelloOrHelloRetryRequest { next, extra_exts })
362 } else {
363 Box::new(next)
364 }
365}
366
367fn prepare_resumption<'a>(
381 resuming: &'a Option<persist::Retrieved<ClientSessionValue>>,
382 exts: &mut Vec<ClientExtension>,
383 suite: Option<SupportedCipherSuite>,
384 cx: &mut ClientContext<'_>,
385 config: &ClientConfig,
386) -> Option<persist::Retrieved<&'a persist::Tls13ClientSessionValue>> {
387 let resuming = match resuming {
389 Some(resuming) if !resuming.ticket().is_empty() => resuming,
390 _ => {
391 if config.supports_version(ProtocolVersion::TLSv1_3)
392 || config.resumption.tls12_resumption == Tls12Resumption::SessionIdOrTickets
393 {
394 exts.push(ClientExtension::SessionTicket(ClientSessionTicket::Request));
396 }
397 return None;
398 }
399 };
400
401 let tls13 = match resuming.map(|csv| csv.tls13()) {
402 Some(tls13) => tls13,
403 None => {
404 if config.supports_version(ProtocolVersion::TLSv1_2)
406 && config.resumption.tls12_resumption == Tls12Resumption::SessionIdOrTickets
407 {
408 exts.push(ClientExtension::SessionTicket(ClientSessionTicket::Offer(
409 Payload::new(resuming.ticket()),
410 )));
411 }
412 return None; }
414 };
415
416 if !config.supports_version(ProtocolVersion::TLSv1_3) {
417 return None;
418 }
419
420 let suite = match suite {
422 Some(SupportedCipherSuite::Tls13(suite)) => Some(suite),
423 #[cfg(feature = "tls12")]
424 Some(SupportedCipherSuite::Tls12(_)) => return None,
425 None => None,
426 };
427
428 if let Some(suite) = suite {
430 suite.can_resume_from(tls13.suite())?;
431 }
432
433 tls13::prepare_resumption(config, cx, &tls13, exts, suite.is_some());
434 Some(tls13)
435}
436
437pub(super) fn process_alpn_protocol(
438 common: &mut CommonState,
439 config: &ClientConfig,
440 proto: Option<&[u8]>,
441) -> Result<(), Error> {
442 common.alpn_protocol = proto.map(ToOwned::to_owned);
443
444 if let Some(alpn_protocol) = &common.alpn_protocol {
445 if !config
446 .alpn_protocols
447 .contains(alpn_protocol)
448 {
449 return Err(common.send_fatal_alert(
450 AlertDescription::IllegalParameter,
451 PeerMisbehaved::SelectedUnofferedApplicationProtocol,
452 ));
453 }
454 }
455
456 #[cfg(feature = "quic")]
457 {
458 if common.is_quic() && common.alpn_protocol.is_none() && !config.alpn_protocols.is_empty() {
465 return Err(common.send_fatal_alert(
466 AlertDescription::NoApplicationProtocol,
467 Error::NoApplicationProtocol,
468 ));
469 }
470 }
471
472 debug!(
473 "ALPN protocol is {:?}",
474 common
475 .alpn_protocol
476 .as_ref()
477 .map(|v| bs_debug::BsDebug(v))
478 );
479 Ok(())
480}
481
482pub(super) fn sct_list_is_invalid(scts: &[Sct]) -> bool {
483 scts.is_empty()
484 || scts
485 .iter()
486 .any(|sct| sct.as_ref().is_empty())
487}
488
489impl State<ClientConnectionData> for ExpectServerHello {
490 fn handle(mut self: Box<Self>, cx: &mut ClientContext<'_>, m: Message) -> NextStateOrError {
491 let server_hello =
492 require_handshake_msg!(m, HandshakeType::ServerHello, HandshakePayload::ServerHello)?;
493 trace!("We got ServerHello {:#?}", server_hello);
494
495 use crate::ProtocolVersion::{TLSv1_2, TLSv1_3};
496 let config = &self.input.config;
497 let tls13_supported = config.supports_version(TLSv1_3);
498
499 let server_version = if server_hello.legacy_version == TLSv1_2 {
500 server_hello
501 .get_supported_versions()
502 .unwrap_or(server_hello.legacy_version)
503 } else {
504 server_hello.legacy_version
505 };
506
507 let version = match server_version {
508 TLSv1_3 if tls13_supported => TLSv1_3,
509 TLSv1_2 if config.supports_version(TLSv1_2) => {
510 if cx.data.early_data.is_enabled() && cx.common.early_traffic {
511 return Err(PeerMisbehaved::OfferedEarlyDataWithOldProtocolVersion.into());
514 }
515
516 if server_hello
517 .get_supported_versions()
518 .is_some()
519 {
520 return Err({
521 cx.common.send_fatal_alert(
522 AlertDescription::IllegalParameter,
523 PeerMisbehaved::SelectedTls12UsingTls13VersionExtension,
524 )
525 });
526 }
527
528 TLSv1_2
529 }
530 _ => {
531 let reason = match server_version {
532 TLSv1_2 | TLSv1_3 => PeerIncompatible::ServerTlsVersionIsDisabledByOurConfig,
533 _ => PeerIncompatible::ServerDoesNotSupportTls12Or13,
534 };
535 return Err(cx
536 .common
537 .send_fatal_alert(AlertDescription::ProtocolVersion, reason));
538 }
539 };
540
541 if server_hello.compression_method != Compression::Null {
542 return Err({
543 cx.common.send_fatal_alert(
544 AlertDescription::IllegalParameter,
545 PeerMisbehaved::SelectedUnofferedCompression,
546 )
547 });
548 }
549
550 if server_hello.has_duplicate_extension() {
551 return Err(cx.common.send_fatal_alert(
552 AlertDescription::DecodeError,
553 PeerMisbehaved::DuplicateServerHelloExtensions,
554 ));
555 }
556
557 let allowed_unsolicited = [ExtensionType::RenegotiationInfo];
558 if self
559 .input
560 .hello
561 .server_sent_unsolicited_extensions(&server_hello.extensions, &allowed_unsolicited)
562 {
563 return Err(cx.common.send_fatal_alert(
564 AlertDescription::UnsupportedExtension,
565 PeerMisbehaved::UnsolicitedServerHelloExtension,
566 ));
567 }
568
569 cx.common.negotiated_version = Some(version);
570
571 if !cx.common.is_tls13() {
573 process_alpn_protocol(cx.common, config, server_hello.get_alpn_protocol())?;
574 }
575
576 if let Some(point_fmts) = server_hello.get_ecpoints_extension() {
579 if !point_fmts.contains(&ECPointFormat::Uncompressed) {
580 return Err(cx.common.send_fatal_alert(
581 AlertDescription::HandshakeFailure,
582 PeerMisbehaved::ServerHelloMustOfferUncompressedEcPoints,
583 ));
584 }
585 }
586
587 let suite = config
588 .find_cipher_suite(server_hello.cipher_suite)
589 .ok_or_else(|| {
590 cx.common.send_fatal_alert(
591 AlertDescription::HandshakeFailure,
592 PeerMisbehaved::SelectedUnofferedCipherSuite,
593 )
594 })?;
595
596 if version != suite.version().version {
597 return Err({
598 cx.common.send_fatal_alert(
599 AlertDescription::IllegalParameter,
600 PeerMisbehaved::SelectedUnusableCipherSuiteForVersion,
601 )
602 });
603 }
604
605 match self.suite {
606 Some(prev_suite) if prev_suite != suite => {
607 return Err({
608 cx.common.send_fatal_alert(
609 AlertDescription::IllegalParameter,
610 PeerMisbehaved::SelectedDifferentCipherSuiteAfterRetry,
611 )
612 });
613 }
614 _ => {
615 debug!("Using ciphersuite {:?}", suite);
616 self.suite = Some(suite);
617 cx.common.suite = Some(suite);
618 }
619 }
620
621 let mut transcript = self
623 .transcript_buffer
624 .start_hash(suite.hash_algorithm());
625 transcript.add_message(&m);
626
627 let randoms = ConnectionRandoms::new(self.input.random, server_hello.random);
628 match suite {
631 SupportedCipherSuite::Tls13(suite) => {
632 #[allow(clippy::bind_instead_of_map)]
633 let resuming_session = self
634 .input
635 .resuming
636 .and_then(|resuming| match resuming.value {
637 ClientSessionValue::Tls13(inner) => Some(inner),
638 #[cfg(feature = "tls12")]
639 ClientSessionValue::Tls12(_) => None,
640 });
641
642 tls13::handle_server_hello(
643 self.input.config,
644 cx,
645 server_hello,
646 resuming_session,
647 self.input.server_name,
648 randoms,
649 suite,
650 transcript,
651 self.early_key_schedule,
652 self.input.hello,
653 self.offered_key_share.unwrap(),
655 self.input.sent_tls13_fake_ccs,
656 )
657 }
658 #[cfg(feature = "tls12")]
659 SupportedCipherSuite::Tls12(suite) => {
660 let resuming_session = self
661 .input
662 .resuming
663 .and_then(|resuming| match resuming.value {
664 ClientSessionValue::Tls12(inner) => Some(inner),
665 ClientSessionValue::Tls13(_) => None,
666 });
667
668 tls12::CompleteServerHelloHandling {
669 config: self.input.config,
670 resuming_session,
671 server_name: self.input.server_name,
672 randoms,
673 using_ems: self.input.using_ems,
674 transcript,
675 }
676 .handle_server_hello(cx, suite, server_hello, tls13_supported)
677 }
678 }
679 }
680}
681
682impl ExpectServerHelloOrHelloRetryRequest {
683 fn into_expect_server_hello(self) -> NextState {
684 Box::new(self.next)
685 }
686
687 fn handle_hello_retry_request(
688 self,
689 cx: &mut ClientContext<'_>,
690 m: Message,
691 ) -> NextStateOrError {
692 let hrr = require_handshake_msg!(
693 m,
694 HandshakeType::HelloRetryRequest,
695 HandshakePayload::HelloRetryRequest
696 )?;
697 trace!("Got HRR {:?}", hrr);
698
699 cx.common.check_aligned_handshake()?;
700
701 let cookie = hrr.get_cookie();
702 let req_group = hrr.get_requested_key_share_group();
703
704 let offered_key_share = self.next.offered_key_share.unwrap();
706
707 if cookie.is_none() && req_group == Some(offered_key_share.group()) {
710 return Err({
711 cx.common.send_fatal_alert(
712 AlertDescription::IllegalParameter,
713 PeerMisbehaved::IllegalHelloRetryRequestWithOfferedGroup,
714 )
715 });
716 }
717
718 if let Some(cookie) = cookie {
720 if cookie.0.is_empty() {
721 return Err({
722 cx.common.send_fatal_alert(
723 AlertDescription::IllegalParameter,
724 PeerMisbehaved::IllegalHelloRetryRequestWithEmptyCookie,
725 )
726 });
727 }
728 }
729
730 if hrr.has_unknown_extension() {
732 return Err(cx.common.send_fatal_alert(
733 AlertDescription::UnsupportedExtension,
734 PeerIncompatible::ServerSentHelloRetryRequestWithUnknownExtension,
735 ));
736 }
737
738 if hrr.has_duplicate_extension() {
740 return Err({
741 cx.common.send_fatal_alert(
742 AlertDescription::IllegalParameter,
743 PeerMisbehaved::DuplicateHelloRetryRequestExtensions,
744 )
745 });
746 }
747
748 if cookie.is_none() && req_group.is_none() {
750 return Err({
751 cx.common.send_fatal_alert(
752 AlertDescription::IllegalParameter,
753 PeerMisbehaved::IllegalHelloRetryRequestWithNoChanges,
754 )
755 });
756 }
757
758 if hrr.session_id != self.next.input.session_id {
772 return Err({
773 cx.common.send_fatal_alert(
774 AlertDescription::IllegalParameter,
775 PeerMisbehaved::IllegalHelloRetryRequestWithWrongSessionId,
776 )
777 });
778 }
779
780 match hrr.get_supported_versions() {
782 Some(ProtocolVersion::TLSv1_3) => {
783 cx.common.negotiated_version = Some(ProtocolVersion::TLSv1_3);
784 }
785 _ => {
786 return Err({
787 cx.common.send_fatal_alert(
788 AlertDescription::IllegalParameter,
789 PeerMisbehaved::IllegalHelloRetryRequestWithUnsupportedVersion,
790 )
791 });
792 }
793 }
794
795 let config = &self.next.input.config;
797 let cs = match config.find_cipher_suite(hrr.cipher_suite) {
798 Some(cs) => cs,
799 None => {
800 return Err({
801 cx.common.send_fatal_alert(
802 AlertDescription::IllegalParameter,
803 PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedCipherSuite,
804 )
805 });
806 }
807 };
808
809 cx.common.suite = Some(cs);
811
812 let transcript = self
814 .next
815 .transcript_buffer
816 .start_hash(cs.hash_algorithm());
817 let mut transcript_buffer = transcript.into_hrr_buffer();
818 transcript_buffer.add_message(&m);
819
820 if cx.data.early_data.is_enabled() {
822 cx.data.early_data.rejected();
823 }
824
825 let may_send_sct_list = self
826 .next
827 .input
828 .hello
829 .server_may_send_sct_list();
830
831 let key_share = match req_group {
832 Some(group) if group != offered_key_share.group() => {
833 let group = kx::KeyExchange::choose(group, &config.kx_groups).ok_or_else(|| {
834 cx.common.send_fatal_alert(
835 AlertDescription::IllegalParameter,
836 PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedNamedGroup,
837 )
838 })?;
839 kx::KeyExchange::start(group).ok_or(Error::FailedToGetRandomBytes)?
840 }
841 _ => offered_key_share,
842 };
843
844 Ok(emit_client_hello_for_retry(
845 transcript_buffer,
846 Some(hrr),
847 Some(key_share),
848 self.extra_exts,
849 may_send_sct_list,
850 Some(cs),
851 self.next.input,
852 cx,
853 ))
854 }
855}
856
857impl State<ClientConnectionData> for ExpectServerHelloOrHelloRetryRequest {
858 fn handle(self: Box<Self>, cx: &mut ClientContext<'_>, m: Message) -> NextStateOrError {
859 match m.payload {
860 MessagePayload::Handshake {
861 parsed:
862 HandshakeMessagePayload {
863 payload: HandshakePayload::ServerHello(..),
864 ..
865 },
866 ..
867 } => self
868 .into_expect_server_hello()
869 .handle(cx, m),
870 MessagePayload::Handshake {
871 parsed:
872 HandshakeMessagePayload {
873 payload: HandshakePayload::HelloRetryRequest(..),
874 ..
875 },
876 ..
877 } => self.handle_hello_retry_request(cx, m),
878 payload => Err(inappropriate_handshake_message(
879 &payload,
880 &[ContentType::Handshake],
881 &[HandshakeType::ServerHello, HandshakeType::HelloRetryRequest],
882 )),
883 }
884 }
885}
886
887enum ClientSessionValue {
888 Tls13(persist::Tls13ClientSessionValue),
889 #[cfg(feature = "tls12")]
890 Tls12(persist::Tls12ClientSessionValue),
891}
892
893impl ClientSessionValue {
894 fn common(&self) -> &persist::ClientSessionCommon {
895 match self {
896 Self::Tls13(inner) => &inner.common,
897 #[cfg(feature = "tls12")]
898 Self::Tls12(inner) => &inner.common,
899 }
900 }
901
902 fn tls13(&self) -> Option<&persist::Tls13ClientSessionValue> {
903 match self {
904 Self::Tls13(v) => Some(v),
905 #[cfg(feature = "tls12")]
906 Self::Tls12(_) => None,
907 }
908 }
909}
910
911impl Deref for ClientSessionValue {
912 type Target = persist::ClientSessionCommon;
913
914 fn deref(&self) -> &Self::Target {
915 self.common()
916 }
917}