1#[cfg(feature = "logging")]
2use crate::bs_debug;
3use crate::check::check_message;
4use crate::cipher;
5use crate::client::ClientSessionImpl;
6use crate::error::TLSError;
7use crate::key_schedule::{KeyScheduleEarly, KeyScheduleHandshake};
8#[cfg(feature = "logging")]
9use crate::log::{debug, trace};
10use crate::msgs::base::Payload;
11#[cfg(feature = "quic")]
12use crate::msgs::base::PayloadU16;
13use crate::msgs::codec::{Codec, Reader};
14use crate::msgs::enums::{AlertDescription, Compression, ProtocolVersion};
15use crate::msgs::enums::{ContentType, ExtensionType, HandshakeType};
16use crate::msgs::enums::{ECPointFormat, PSKKeyExchangeMode};
17use crate::msgs::handshake::HelloRetryRequest;
18use crate::msgs::handshake::{CertificateStatusRequest, SCTList};
19use crate::msgs::handshake::{ClientExtension, HasServerExtensions};
20use crate::msgs::handshake::{ClientHelloPayload, HandshakeMessagePayload, HandshakePayload};
21use crate::msgs::handshake::{ConvertProtocolNameList, ProtocolNameList};
22use crate::msgs::handshake::{ECPointFormatList, SupportedPointFormats};
23use crate::msgs::handshake::{Random, SessionID};
24use crate::msgs::message::{Message, MessagePayload};
25use crate::msgs::persist;
26use crate::rand;
27use crate::session::SessionSecrets;
28use crate::suites;
29use crate::ticketer;
30use crate::verify;
31
32use crate::client::common::{ClientHelloDetails, ReceivedTicketDetails};
33use crate::client::common::{HandshakeDetails, ServerCertDetails};
34use crate::client::{tls12, tls13};
35
36use webpki;
37
38pub type NextState = Box<dyn State + Send + Sync>;
39pub type NextStateOrError = Result<NextState, TLSError>;
40
41pub trait State {
42 fn handle(self: Box<Self>, sess: &mut ClientSessionImpl, m: Message) -> NextStateOrError;
45
46 fn export_keying_material(
47 &self,
48 _output: &mut [u8],
49 _label: &[u8],
50 _context: Option<&[u8]>,
51 ) -> Result<(), TLSError> {
52 Err(TLSError::HandshakeNotComplete)
53 }
54
55 fn perhaps_write_key_update(&mut self, _sess: &mut ClientSessionImpl) {}
56}
57
58pub fn illegal_param(sess: &mut ClientSessionImpl, why: &str) -> TLSError {
59 sess.common
60 .send_fatal_alert(AlertDescription::IllegalParameter);
61 TLSError::PeerMisbehavedError(why.to_string())
62}
63
64pub fn check_aligned_handshake(sess: &mut ClientSessionImpl) -> Result<(), TLSError> {
65 if !sess.common.handshake_joiner.is_empty() {
66 sess.common
67 .send_fatal_alert(AlertDescription::UnexpectedMessage);
68 Err(TLSError::PeerMisbehavedError(
69 "key epoch or handshake flight with pending fragment".to_string(),
70 ))
71 } else {
72 Ok(())
73 }
74}
75
76fn find_session(
77 sess: &mut ClientSessionImpl,
78 dns_name: webpki::DNSNameRef,
79) -> Option<persist::ClientSessionValue> {
80 let key = persist::ClientSessionKey::session_for_dns_name(dns_name);
81 let key_buf = key.get_encoding();
82
83 let maybe_value = sess
84 .config
85 .session_persistence
86 .get(&key_buf);
87
88 if maybe_value.is_none() {
89 debug!("No cached session for {:?}", dns_name);
90 return None;
91 }
92
93 let value = maybe_value.unwrap();
94 let mut reader = Reader::init(&value[..]);
95 if let Some(result) = persist::ClientSessionValue::read(&mut reader) {
96 if result.has_expired(ticketer::timebase()) {
97 None
98 } else {
99 #[cfg(feature = "quic")]
100 {
101 if sess.common.is_quic() {
102 let params = PayloadU16::read(&mut reader)?;
103 sess.common.quic.params = Some(params.0);
104 }
105 }
106 Some(result)
107 }
108 } else {
109 None
110 }
111}
112
113fn random_sessionid() -> SessionID {
114 let mut random_id = [0u8; 32];
115 rand::fill_random(&mut random_id);
116 SessionID::new(&random_id)
117}
118
119fn random_sessionid_for_ticket(csv: &mut persist::ClientSessionValue) {
122 if !csv.ticket.0.is_empty() {
123 csv.session_id = random_sessionid();
124 }
125}
126
127struct InitialState {
128 handshake: HandshakeDetails,
129}
130
131impl InitialState {
132 fn new(host_name: webpki::DNSName, extra_exts: Vec<ClientExtension>) -> InitialState {
133 InitialState {
134 handshake: HandshakeDetails::new(host_name, extra_exts),
135 }
136 }
137
138 fn emit_initial_client_hello(mut self, sess: &mut ClientSessionImpl) -> NextState {
139 if sess
140 .config
141 .client_auth_cert_resolver
142 .has_certs()
143 {
144 self.handshake
145 .transcript
146 .set_client_auth_enabled();
147 }
148 let hello_details = ClientHelloDetails::new();
149 emit_client_hello_for_retry(sess, self.handshake, hello_details, None)
150 }
151}
152
153pub fn start_handshake(
154 sess: &mut ClientSessionImpl,
155 host_name: webpki::DNSName,
156 extra_exts: Vec<ClientExtension>,
157) -> NextState {
158 InitialState::new(host_name, extra_exts).emit_initial_client_hello(sess)
159}
160
161struct ExpectServerHello {
162 handshake: HandshakeDetails,
163 early_key_schedule: Option<KeyScheduleEarly>,
164 hello: ClientHelloDetails,
165 server_cert: ServerCertDetails,
166 may_send_cert_status: bool,
167 must_issue_new_ticket: bool,
168}
169
170struct ExpectServerHelloOrHelloRetryRequest(ExpectServerHello);
171
172pub fn compatible_suite(
173 sess: &ClientSessionImpl,
174 resuming_suite: Option<&suites::SupportedCipherSuite>,
175) -> bool {
176 match resuming_suite {
177 Some(resuming_suite) => {
178 if let Some(suite) = sess.common.get_suite() {
179 suite.can_resume_to(&resuming_suite)
180 } else {
181 true
182 }
183 }
184 None => false,
185 }
186}
187
188fn emit_client_hello_for_retry(
189 sess: &mut ClientSessionImpl,
190 mut handshake: HandshakeDetails,
191 mut hello: ClientHelloDetails,
192 retryreq: Option<&HelloRetryRequest>,
193) -> NextState {
194 handshake.resuming_session = find_session(sess, handshake.dns_name.as_ref());
196 let (session_id, ticket, resume_version) = if handshake.resuming_session.is_some() {
197 let resuming = handshake
198 .resuming_session
199 .as_mut()
200 .unwrap();
201 if resuming.version == ProtocolVersion::TLSv1_2 {
202 random_sessionid_for_ticket(resuming);
203 }
204 debug!("Resuming session");
205 (
206 resuming.session_id,
207 resuming.ticket.0.clone(),
208 resuming.version,
209 )
210 } else {
211 debug!("Not resuming any session");
212 if handshake.session_id.is_empty() && !sess.common.is_quic() {
213 handshake.session_id = random_sessionid();
214 }
215 (
216 handshake.session_id,
217 Vec::new(),
218 ProtocolVersion::Unknown(0),
219 )
220 };
221
222 let support_tls12 = sess
223 .config
224 .supports_version(ProtocolVersion::TLSv1_2);
225 let support_tls13 = sess
226 .config
227 .supports_version(ProtocolVersion::TLSv1_3);
228
229 let mut supported_versions = Vec::new();
230 if support_tls13 {
231 supported_versions.push(ProtocolVersion::TLSv1_3);
232 }
233
234 if support_tls12 {
235 supported_versions.push(ProtocolVersion::TLSv1_2);
236 }
237
238 let mut exts = Vec::new();
239 if !supported_versions.is_empty() {
240 exts.push(ClientExtension::SupportedVersions(supported_versions));
241 }
242 if sess.config.enable_sni {
243 exts.push(ClientExtension::make_sni(handshake.dns_name.as_ref()));
244 }
245 exts.push(ClientExtension::ECPointFormats(
246 ECPointFormatList::supported(),
247 ));
248 exts.push(ClientExtension::NamedGroups(
249 suites::KeyExchange::supported_groups().to_vec(),
250 ));
251 exts.push(ClientExtension::SignatureAlgorithms(
252 sess.config
253 .get_verifier()
254 .supported_verify_schemes(),
255 ));
256 exts.push(ClientExtension::ExtendedMasterSecretRequest);
257 exts.push(ClientExtension::CertificateStatusRequest(
258 CertificateStatusRequest::build_ocsp(),
259 ));
260
261 if sess.config.ct_logs.is_some() {
262 exts.push(ClientExtension::SignedCertificateTimestampRequest);
263 }
264
265 if support_tls13 {
266 tls13::choose_kx_groups(sess, &mut exts, &mut hello, &mut handshake, retryreq);
267 }
268
269 if let Some(cookie) = retryreq.and_then(HelloRetryRequest::get_cookie) {
270 exts.push(ClientExtension::Cookie(cookie.clone()));
271 }
272
273 if support_tls13 && sess.config.enable_tickets {
274 let psk_modes = vec![PSKKeyExchangeMode::PSK_DHE_KE];
277 exts.push(ClientExtension::PresharedKeyModes(psk_modes));
278 }
279
280 if !sess.config.alpn_protocols.is_empty() {
281 exts.push(ClientExtension::Protocols(ProtocolNameList::from_slices(
282 &sess
283 .config
284 .alpn_protocols
285 .iter()
286 .map(|proto| &proto[..])
287 .collect::<Vec<_>>(),
288 )));
289 }
290
291 exts.extend(handshake.extra_exts.iter().cloned());
293
294 let fill_in_binder = if support_tls13
295 && sess.config.enable_tickets
296 && resume_version == ProtocolVersion::TLSv1_3
297 && !ticket.is_empty()
298 {
299 tls13::prepare_resumption(sess, ticket, &handshake, &mut exts, retryreq.is_some())
300 } else if sess.config.enable_tickets {
301 if ticket.is_empty() {
303 exts.push(ClientExtension::SessionTicketRequest);
304 } else {
305 exts.push(ClientExtension::SessionTicketOffer(Payload::new(ticket)));
306 }
307 false
308 } else {
309 false
310 };
311
312 hello.sent_extensions = exts
314 .iter()
315 .map(ClientExtension::get_type)
316 .collect();
317
318 let mut chp = HandshakeMessagePayload {
319 typ: HandshakeType::ClientHello,
320 payload: HandshakePayload::ClientHello(ClientHelloPayload {
321 client_version: ProtocolVersion::TLSv1_2,
322 random: Random::from_slice(&handshake.randoms.client),
323 session_id,
324 cipher_suites: sess.get_cipher_suites(),
325 compression_methods: vec![Compression::Null],
326 extensions: exts,
327 }),
328 };
329
330 let early_key_schedule = if fill_in_binder {
331 Some(tls13::fill_in_psk_binder(sess, &mut handshake, &mut chp))
332 } else {
333 None
334 };
335
336 let ch = Message {
337 typ: ContentType::Handshake,
338 version: if retryreq.is_some() {
342 ProtocolVersion::TLSv1_2
343 } else {
344 ProtocolVersion::TLSv1_0
345 },
346 payload: MessagePayload::Handshake(chp),
347 };
348
349 if retryreq.is_some() {
350 tls13::emit_fake_ccs(&mut handshake, sess);
353 }
354
355 trace!("Sending ClientHello {:#?}", ch);
356
357 handshake.transcript.add_message(&ch);
358 sess.common.send_msg(ch, false);
359
360 if sess.early_data.is_enabled() {
362 tls13::emit_fake_ccs(&mut handshake, sess);
364
365 let resuming_suite = handshake
367 .resuming_session
368 .as_ref()
369 .and_then(|resume| sess.find_cipher_suite(resume.cipher_suite))
370 .unwrap();
371
372 let client_hello_hash = handshake
373 .transcript
374 .get_hash_given(resuming_suite.get_hash(), &[]);
375 let client_early_traffic_secret = early_key_schedule
376 .as_ref()
377 .unwrap()
378 .client_early_traffic_secret(
379 &client_hello_hash,
380 &*sess.config.key_log,
381 &handshake.randoms.client,
382 );
383 sess.common
385 .record_layer
386 .set_message_encrypter(cipher::new_tls13_write(
387 resuming_suite,
388 &client_early_traffic_secret,
389 ));
390
391 #[cfg(feature = "quic")]
392 {
393 sess.common.quic.early_secret = Some(client_early_traffic_secret);
394 }
395
396 sess.common.early_traffic = true;
398 trace!("Starting early data traffic");
399 }
400
401 let next = ExpectServerHello {
402 handshake,
403 hello,
404 early_key_schedule,
405 server_cert: ServerCertDetails::new(),
406 may_send_cert_status: false,
407 must_issue_new_ticket: false,
408 };
409
410 if support_tls13 && retryreq.is_none() {
411 Box::new(ExpectServerHelloOrHelloRetryRequest(next))
412 } else {
413 Box::new(next)
414 }
415}
416
417pub fn process_alpn_protocol(
418 sess: &mut ClientSessionImpl,
419 proto: Option<&[u8]>,
420) -> Result<(), TLSError> {
421 sess.alpn_protocol = proto.map(ToOwned::to_owned);
422 if sess.alpn_protocol.is_some()
423 && !sess
424 .config
425 .alpn_protocols
426 .contains(sess.alpn_protocol.as_ref().unwrap())
427 {
428 return Err(illegal_param(sess, "server sent non-offered ALPN protocol"));
429 }
430 debug!(
431 "ALPN protocol is {:?}",
432 sess.alpn_protocol
433 .as_ref()
434 .map(|v| bs_debug::BsDebug(&v))
435 );
436 Ok(())
437}
438
439pub fn sct_list_is_invalid(scts: &SCTList) -> bool {
440 scts.is_empty() || scts.iter().any(|sct| sct.0.is_empty())
441}
442
443impl ExpectServerHello {
444 fn into_expect_tls13_encrypted_extensions(
445 self,
446 key_schedule: KeyScheduleHandshake,
447 ) -> NextState {
448 Box::new(tls13::ExpectEncryptedExtensions {
449 handshake: self.handshake,
450 key_schedule,
451 server_cert: self.server_cert,
452 hello: self.hello,
453 })
454 }
455
456 fn into_expect_tls12_new_ticket_resume(
457 self,
458 secrets: SessionSecrets,
459 certv: verify::ServerCertVerified,
460 sigv: verify::HandshakeSignatureValid,
461 ) -> NextState {
462 Box::new(tls12::ExpectNewTicket {
463 secrets,
464 handshake: self.handshake,
465 resuming: true,
466 cert_verified: certv,
467 sig_verified: sigv,
468 })
469 }
470
471 fn into_expect_tls12_ccs_resume(
472 self,
473 secrets: SessionSecrets,
474 certv: verify::ServerCertVerified,
475 sigv: verify::HandshakeSignatureValid,
476 ) -> NextState {
477 Box::new(tls12::ExpectCCS {
478 secrets,
479 handshake: self.handshake,
480 ticket: ReceivedTicketDetails::new(),
481 resuming: true,
482 cert_verified: certv,
483 sig_verified: sigv,
484 })
485 }
486
487 fn into_expect_tls12_certificate(self) -> NextState {
488 Box::new(tls12::ExpectCertificate {
489 handshake: self.handshake,
490 server_cert: self.server_cert,
491 may_send_cert_status: self.may_send_cert_status,
492 must_issue_new_ticket: self.must_issue_new_ticket,
493 })
494 }
495}
496
497impl State for ExpectServerHello {
498 fn handle(mut self: Box<Self>, sess: &mut ClientSessionImpl, m: Message) -> NextStateOrError {
499 let server_hello =
500 require_handshake_msg!(m, HandshakeType::ServerHello, HandshakePayload::ServerHello)?;
501 trace!("We got ServerHello {:#?}", server_hello);
502
503 use crate::ProtocolVersion::{TLSv1_2, TLSv1_3};
504 let tls13_supported = sess.config.supports_version(TLSv1_3);
505
506 let server_version = if server_hello.legacy_version == TLSv1_2 {
507 server_hello
508 .get_supported_versions()
509 .unwrap_or(server_hello.legacy_version)
510 } else {
511 server_hello.legacy_version
512 };
513
514 match server_version {
515 TLSv1_3 if tls13_supported => {
516 sess.common.negotiated_version = Some(TLSv1_3);
517 }
518 TLSv1_2 if sess.config.supports_version(TLSv1_2) => {
519 if sess.early_data.is_enabled() && sess.common.early_traffic {
520 return Err(TLSError::PeerMisbehavedError(
523 "server chose v1.2 when offering 0-rtt".to_string(),
524 ));
525 }
526 sess.common.negotiated_version = Some(TLSv1_2);
527
528 if server_hello
529 .get_supported_versions()
530 .is_some()
531 {
532 return Err(illegal_param(
533 sess,
534 "server chose v1.2 using v1.3 extension",
535 ));
536 }
537 }
538 _ => {
539 sess.common
540 .send_fatal_alert(AlertDescription::ProtocolVersion);
541 return Err(TLSError::PeerIncompatibleError(
542 "server does not support TLS v1.2/v1.3".to_string(),
543 ));
544 }
545 };
546
547 if server_hello.compression_method != Compression::Null {
548 return Err(illegal_param(sess, "server chose non-Null compression"));
549 }
550
551 if server_hello.has_duplicate_extension() {
552 sess.common
553 .send_fatal_alert(AlertDescription::DecodeError);
554 return Err(TLSError::PeerMisbehavedError(
555 "server sent duplicate extensions".to_string(),
556 ));
557 }
558
559 let allowed_unsolicited = [ExtensionType::RenegotiationInfo];
560 if self
561 .hello
562 .server_sent_unsolicited_extensions(&server_hello.extensions, &allowed_unsolicited)
563 {
564 sess.common
565 .send_fatal_alert(AlertDescription::UnsupportedExtension);
566 return Err(TLSError::PeerMisbehavedError(
567 "server sent unsolicited extension".to_string(),
568 ));
569 }
570
571 if !sess.common.is_tls13() {
573 process_alpn_protocol(sess, 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 sess.common
581 .send_fatal_alert(AlertDescription::HandshakeFailure);
582 return Err(TLSError::PeerMisbehavedError(
583 "server does not support uncompressed points".to_string(),
584 ));
585 }
586 }
587
588 let scs = sess.find_cipher_suite(server_hello.cipher_suite);
589
590 if scs.is_none() {
591 sess.common
592 .send_fatal_alert(AlertDescription::HandshakeFailure);
593 return Err(TLSError::PeerMisbehavedError(
594 "server chose non-offered ciphersuite".to_string(),
595 ));
596 }
597
598 debug!("Using ciphersuite {:?}", server_hello.cipher_suite);
599 if !sess.common.set_suite(scs.unwrap()) {
600 return Err(illegal_param(sess, "server varied selected ciphersuite"));
601 }
602
603 let version = sess.common.negotiated_version.unwrap();
604 if !sess
605 .common
606 .get_suite_assert()
607 .usable_for_version(version)
608 {
609 return Err(illegal_param(
610 sess,
611 "server chose unusable ciphersuite for version",
612 ));
613 }
614
615 let starting_hash = sess
617 .common
618 .get_suite_assert()
619 .get_hash();
620 self.handshake
621 .transcript
622 .start_hash(starting_hash);
623 self.handshake
624 .transcript
625 .add_message(&m);
626
627 if sess.common.is_tls13() {
630 tls13::validate_server_hello(sess, &server_hello)?;
631 let key_schedule = tls13::start_handshake_traffic(
632 sess,
633 self.early_key_schedule.take(),
634 &server_hello,
635 &mut self.handshake,
636 &mut self.hello,
637 )?;
638 tls13::emit_fake_ccs(&mut self.handshake, sess);
639 return Ok(self.into_expect_tls13_encrypted_extensions(key_schedule));
640 }
641
642 server_hello
646 .random
647 .write_slice(&mut self.handshake.randoms.server);
648 self.handshake.session_id = server_hello.session_id;
649
650 if tls13_supported
652 && self
653 .handshake
654 .randoms
655 .has_tls12_downgrade_marker()
656 {
657 return Err(illegal_param(
658 sess,
659 "downgrade to TLS1.2 when TLS1.3 is supported",
660 ));
661 }
662
663 if server_hello.ems_support_acked() {
665 self.handshake.using_ems = true;
666 }
667
668 let with_tickets = if server_hello
670 .find_extension(ExtensionType::SessionTicket)
671 .is_some()
672 {
673 debug!("Server supports tickets");
674 true
675 } else {
676 false
677 };
678 self.must_issue_new_ticket = with_tickets;
679
680 if server_hello
683 .find_extension(ExtensionType::StatusRequest)
684 .is_some()
685 {
686 debug!("Server may staple OCSP response");
687 self.may_send_cert_status = true;
688 }
689
690 if let Some(sct_list) = server_hello.get_sct_list() {
692 debug!("Server sent {:?} SCTs", sct_list.len());
693
694 if sct_list_is_invalid(sct_list) {
695 let error_msg = "server sent invalid SCT list".to_string();
696 return Err(TLSError::PeerMisbehavedError(error_msg));
697 }
698 self.server_cert.scts = Some(sct_list.clone());
699 }
700
701 if let Some(ref resuming) = self.handshake.resuming_session {
703 if resuming.session_id == self.handshake.session_id {
704 debug!("Server agreed to resume");
705
706 if resuming.cipher_suite != scs.unwrap().suite {
708 let error_msg = "abbreviated handshake offered, but with varied cs".to_string();
709 return Err(TLSError::PeerMisbehavedError(error_msg));
710 }
711
712 if resuming.extended_ms != self.handshake.using_ems {
714 let error_msg = "server varied ems support over resume".to_string();
715 return Err(TLSError::PeerMisbehavedError(error_msg));
716 }
717
718 let secrets = SessionSecrets::new_resume(
719 &self.handshake.randoms,
720 scs.unwrap().get_hash(),
721 &resuming.master_secret.0,
722 );
723 sess.config.key_log.log(
724 "CLIENT_RANDOM",
725 &secrets.randoms.client,
726 &secrets.master_secret,
727 );
728 sess.common
729 .start_encryption_tls12(&secrets);
730
731 sess.server_cert_chain = resuming.server_cert_chain.clone();
734 let certv = verify::ServerCertVerified::assertion();
735 let sigv = verify::HandshakeSignatureValid::assertion();
736
737 return if self.must_issue_new_ticket {
738 Ok(self.into_expect_tls12_new_ticket_resume(secrets, certv, sigv))
739 } else {
740 Ok(self.into_expect_tls12_ccs_resume(secrets, certv, sigv))
741 };
742 }
743 }
744
745 Ok(self.into_expect_tls12_certificate())
746 }
747}
748
749impl ExpectServerHelloOrHelloRetryRequest {
750 fn into_expect_server_hello(self) -> NextState {
751 Box::new(self.0)
752 }
753
754 fn handle_hello_retry_request(
755 mut self,
756 sess: &mut ClientSessionImpl,
757 m: Message,
758 ) -> NextStateOrError {
759 let hrr = require_handshake_msg!(
760 m,
761 HandshakeType::HelloRetryRequest,
762 HandshakePayload::HelloRetryRequest
763 )?;
764 trace!("Got HRR {:?}", hrr);
765
766 check_aligned_handshake(sess)?;
767
768 let has_cookie = hrr.get_cookie().is_some();
769 let req_group = hrr.get_requested_key_share_group();
770
771 if !has_cookie
774 && req_group
775 .map(|g| self.0.hello.has_key_share(g))
776 .unwrap_or(false)
777 {
778 return Err(illegal_param(sess, "server requested hrr with our group"));
779 }
780
781 if let Some(group) = req_group {
783 if !suites::KeyExchange::supported_groups().contains(&group) {
784 return Err(illegal_param(sess, "server requested hrr with bad group"));
785 }
786 }
787
788 if has_cookie && hrr.get_cookie().unwrap().0.is_empty() {
790 return Err(illegal_param(
791 sess,
792 "server requested hrr with empty cookie",
793 ));
794 }
795
796 if hrr.has_unknown_extension() {
798 sess.common
799 .send_fatal_alert(AlertDescription::UnsupportedExtension);
800 return Err(TLSError::PeerIncompatibleError(
801 "server sent hrr with unhandled extension".to_string(),
802 ));
803 }
804
805 if hrr.has_duplicate_extension() {
807 return Err(illegal_param(sess, "server send duplicate hrr extensions"));
808 }
809
810 if !has_cookie && req_group.is_none() {
812 return Err(illegal_param(sess, "server requested hrr with no changes"));
813 }
814
815 match hrr.get_supported_versions() {
817 Some(ProtocolVersion::TLSv1_3) => {
818 sess.common.negotiated_version = Some(ProtocolVersion::TLSv1_3);
819 }
820 _ => {
821 return Err(illegal_param(
822 sess,
823 "server requested unsupported version in hrr",
824 ));
825 }
826 }
827
828 let maybe_cs = sess.find_cipher_suite(hrr.cipher_suite);
830 let cs = match maybe_cs {
831 Some(cs) => cs,
832 None => {
833 return Err(illegal_param(
834 sess,
835 "server requested unsupported cs in hrr",
836 ));
837 }
838 };
839
840 sess.common.set_suite(cs);
842
843 self.0
845 .handshake
846 .transcript
847 .start_hash(cs.get_hash());
848 self.0
849 .handshake
850 .transcript
851 .rollup_for_hrr();
852 self.0
853 .handshake
854 .transcript
855 .add_message(&m);
856
857 if sess.early_data.is_enabled() {
859 sess.early_data.rejected();
860 }
861
862 Ok(emit_client_hello_for_retry(
863 sess,
864 self.0.handshake,
865 self.0.hello,
866 Some(&hrr),
867 ))
868 }
869}
870
871impl State for ExpectServerHelloOrHelloRetryRequest {
872 fn handle(self: Box<Self>, sess: &mut ClientSessionImpl, m: Message) -> NextStateOrError {
873 check_message(
874 &m,
875 &[ContentType::Handshake],
876 &[HandshakeType::ServerHello, HandshakeType::HelloRetryRequest],
877 )?;
878 if m.is_handshake_type(HandshakeType::ServerHello) {
879 self.into_expect_server_hello()
880 .handle(sess, m)
881 } else {
882 self.handle_hello_retry_request(sess, m)
883 }
884 }
885}
886
887pub fn send_cert_error_alert(sess: &mut ClientSessionImpl, err: TLSError) -> TLSError {
888 match err {
889 TLSError::WebPKIError(webpki::Error::BadDER) => {
890 sess.common
891 .send_fatal_alert(AlertDescription::DecodeError);
892 }
893 TLSError::PeerMisbehavedError(_) => {
894 sess.common
895 .send_fatal_alert(AlertDescription::IllegalParameter);
896 }
897 _ => {
898 sess.common
899 .send_fatal_alert(AlertDescription::BadCertificate);
900 }
901 };
902
903 err
904}