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::crypto::ActiveKeyExchange;
7use crate::enums::{AlertDescription, CipherSuite, ContentType, HandshakeType, ProtocolVersion};
8use crate::error::{Error, PeerIncompatible, PeerMisbehaved};
9use crate::hash_hs::HandshakeHashBuffer;
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};
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::tls13::key_schedule::KeyScheduleEarly;
24use crate::SupportedCipherSuite;
25
26#[cfg(feature = "tls12")]
27use super::tls12;
28use super::Tls12Resumption;
29use crate::client::client_conn::ClientConnectionData;
30use crate::client::common::ClientHelloDetails;
31use crate::client::{tls13, ClientConfig};
32
33use pki_types::{ServerName, UnixTime};
34
35use alloc::borrow::ToOwned;
36use alloc::boxed::Box;
37use alloc::sync::Arc;
38use alloc::vec;
39use alloc::vec::Vec;
40use core::ops::Deref;
41
42pub(super) type NextState = Box<dyn State<ClientConnectionData>>;
43pub(super) type NextStateOrError = Result<NextState, Error>;
44pub(super) type ClientContext<'a> = crate::common_state::Context<'a, ClientConnectionData>;
45
46fn find_session(
47 server_name: &ServerName<'static>,
48 config: &ClientConfig,
49 cx: &mut ClientContext<'_>,
50) -> Option<persist::Retrieved<ClientSessionValue>> {
51 #[allow(clippy::let_and_return, clippy::unnecessary_lazy_evaluations)]
52 let found = config
53 .resumption
54 .store
55 .take_tls13_ticket(server_name)
56 .map(ClientSessionValue::Tls13)
57 .or_else(|| {
58 #[cfg(feature = "tls12")]
59 {
60 config
61 .resumption
62 .store
63 .tls12_session(server_name)
64 .map(ClientSessionValue::Tls12)
65 }
66
67 #[cfg(not(feature = "tls12"))]
68 None
69 })
70 .and_then(|resuming| {
71 let retrieved = persist::Retrieved::new(resuming, UnixTime::now());
72 match retrieved.has_expired() {
73 false => Some(retrieved),
74 true => None,
75 }
76 })
77 .or_else(|| {
78 debug!("No cached session for {:?}", server_name);
79 None
80 });
81
82 if let Some(resuming) = &found {
83 if cx.common.is_quic() {
84 cx.common.quic.params = resuming
85 .tls13()
86 .map(|v| v.quic_params());
87 }
88 }
89
90 found
91}
92
93pub(super) fn start_handshake(
94 server_name: ServerName<'static>,
95 extra_exts: Vec<ClientExtension>,
96 config: Arc<ClientConfig>,
97 cx: &mut ClientContext<'_>,
98) -> NextStateOrError {
99 let mut transcript_buffer = HandshakeHashBuffer::new();
100 if config
101 .client_auth_cert_resolver
102 .has_certs()
103 {
104 transcript_buffer.set_client_auth_enabled();
105 }
106
107 let mut resuming = find_session(&server_name, &config, cx);
108
109 let key_share = if config.supports_version(ProtocolVersion::TLSv1_3) {
110 Some(tls13::initial_key_share(&config, &server_name)?)
111 } else {
112 None
113 };
114
115 #[cfg_attr(not(feature = "tls12"), allow(unused_mut))]
116 let mut session_id = None;
117 if let Some(_resuming) = &mut resuming {
118 #[cfg(feature = "tls12")]
119 if let ClientSessionValue::Tls12(inner) = &mut _resuming.value {
120 // If we have a ticket, we use the sessionid as a signal that
121 // we're doing an abbreviated handshake. See section 3.4 in
122 // RFC5077.
123 if !inner.ticket().is_empty() {
124 inner.session_id = SessionId::random(config.provider.secure_random)?;
125 }
126 session_id = Some(inner.session_id);
127 }
128
129 debug!("Resuming session");
130 } else {
131 debug!("Not resuming any session");
132 }
133
134 // https://tools.ietf.org/html/rfc8446#appendix-D.4
135 // https://tools.ietf.org/html/draft-ietf-quic-tls-34#section-8.4
136 let session_id = match session_id {
137 Some(session_id) => session_id,
138 None if cx.common.is_quic() => SessionId::empty(),
139 None if !config.supports_version(ProtocolVersion::TLSv1_3) => SessionId::empty(),
140 None => SessionId::random(config.provider.secure_random)?,
141 };
142
143 let random = Random::new(config.provider.secure_random)?;
144
145 Ok(emit_client_hello_for_retry(
146 transcript_buffer,
147 None,
148 key_share,
149 extra_exts,
150 None,
151 ClientHelloInput {
152 config,
153 resuming,
154 random,
155 #[cfg(feature = "tls12")]
156 using_ems: false,
157 sent_tls13_fake_ccs: false,
158 hello: ClientHelloDetails::new(),
159 session_id,
160 server_name,
161 },
162 cx,
163 ))
164}
165
166struct ExpectServerHello {
167 input: ClientHelloInput,
168 transcript_buffer: HandshakeHashBuffer,
169 early_key_schedule: Option<KeyScheduleEarly>,
170 offered_key_share: Option<Box<dyn ActiveKeyExchange>>,
171 suite: Option<SupportedCipherSuite>,
172}
173
174struct ExpectServerHelloOrHelloRetryRequest {
175 next: ExpectServerHello,
176 extra_exts: Vec<ClientExtension>,
177}
178
179struct ClientHelloInput {
180 config: Arc<ClientConfig>,
181 resuming: Option<persist::Retrieved<ClientSessionValue>>,
182 random: Random,
183 #[cfg(feature = "tls12")]
184 using_ems: bool,
185 sent_tls13_fake_ccs: bool,
186 hello: ClientHelloDetails,
187 session_id: SessionId,
188 server_name: ServerName<'static>,
189}
190
191fn emit_client_hello_for_retry(
192 mut transcript_buffer: HandshakeHashBuffer,
193 retryreq: Option<&HelloRetryRequest>,
194 key_share: Option<Box<dyn ActiveKeyExchange>>,
195 extra_exts: Vec<ClientExtension>,
196 suite: Option<SupportedCipherSuite>,
197 mut input: ClientHelloInput,
198 cx: &mut ClientContext<'_>,
199) -> NextState {
200 let config = &input.config;
201 let support_tls12 = config.supports_version(ProtocolVersion::TLSv1_2) && !cx.common.is_quic();
202 let support_tls13 = config.supports_version(ProtocolVersion::TLSv1_3);
203
204 let mut supported_versions = Vec::new();
205 if support_tls13 {
206 supported_versions.push(ProtocolVersion::TLSv1_3);
207 }
208
209 if support_tls12 {
210 supported_versions.push(ProtocolVersion::TLSv1_2);
211 }
212
213 // should be unreachable thanks to config builder
214 assert!(!supported_versions.is_empty());
215
216 let mut exts = vec![
217 ClientExtension::SupportedVersions(supported_versions),
218 ClientExtension::EcPointFormats(ECPointFormat::SUPPORTED.to_vec()),
219 ClientExtension::NamedGroups(
220 config
221 .provider
222 .kx_groups
223 .iter()
224 .map(|skxg| skxg.name())
225 .collect(),
226 ),
227 ClientExtension::SignatureAlgorithms(
228 config
229 .verifier
230 .supported_verify_schemes(),
231 ),
232 ClientExtension::ExtendedMasterSecretRequest,
233 ClientExtension::CertificateStatusRequest(CertificateStatusRequest::build_ocsp()),
234 ];
235
236 if let (ServerName::DnsName(dns), true) = (&input.server_name, config.enable_sni) {
237 // We only want to send the SNI extension if the server name contains a DNS name.
238 exts.push(ClientExtension::make_sni(dns));
239 }
240
241 if let Some(key_share) = &key_share {
242 debug_assert!(support_tls13);
243 let key_share = KeyShareEntry::new(key_share.group(), key_share.pub_key());
244 exts.push(ClientExtension::KeyShare(vec![key_share]));
245 }
246
247 if let Some(cookie) = retryreq.and_then(HelloRetryRequest::get_cookie) {
248 exts.push(ClientExtension::Cookie(cookie.clone()));
249 }
250
251 if support_tls13 {
252 // We could support PSK_KE here too. Such connections don't
253 // have forward secrecy, and are similar to TLS1.2 resumption.
254 let psk_modes = vec![PSKKeyExchangeMode::PSK_DHE_KE];
255 exts.push(ClientExtension::PresharedKeyModes(psk_modes));
256 }
257
258 if !config.alpn_protocols.is_empty() {
259 exts.push(ClientExtension::Protocols(Vec::from_slices(
260 &config
261 .alpn_protocols
262 .iter()
263 .map(|proto| &proto[..])
264 .collect::<Vec<_>>(),
265 )));
266 }
267
268 // Extra extensions must be placed before the PSK extension
269 exts.extend(extra_exts.iter().cloned());
270
271 // Do we have a SessionID or ticket cached for this host?
272 let tls13_session = prepare_resumption(&input.resuming, &mut exts, suite, cx, config);
273
274 // Note what extensions we sent.
275 input.hello.sent_extensions = exts
276 .iter()
277 .map(ClientExtension::get_type)
278 .collect();
279
280 let mut cipher_suites: Vec<_> = config
281 .provider
282 .cipher_suites
283 .iter()
284 .filter_map(|cs| match cs.usable_for_protocol(cx.common.protocol) {
285 true => Some(cs.suite()),
286 false => None,
287 })
288 .collect();
289 // We don't do renegotiation at all, in fact.
290 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 // "This value MUST be set to 0x0303 for all records generated
313 // by a TLS 1.3 implementation other than an initial ClientHello
314 // (i.e., one not generated after a HelloRetryRequest)"
315 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 // send dummy CCS to fool middleboxes prior
325 // to second client hello
326 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 // Calculate the hash of ClientHello and use it to derive EarlyTrafficSecret
335 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
367/// Prepare resumption with the session state retrieved from storage.
368///
369/// This function will push onto `exts` to
370///
371/// (a) request a new ticket if we don't have one,
372/// (b) send our TLS 1.2 ticket after retrieving an 1.2 session,
373/// (c) send a request for 1.3 early data if allowed and
374/// (d) send a 1.3 preshared key if we have one.
375///
376/// For resumption to work, the currently negotiated cipher suite (if available) must be
377/// able to resume from the resuming session's cipher suite.
378///
379/// If 1.3 resumption can continue, returns the 1.3 session value for further processing.
380fn 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 // Check whether we're resuming with a non-empty ticket.
388 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 // If we don't have a ticket, request one.
395 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 // TLS 1.2; send the ticket if we have support this protocol version
405 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; // TLS 1.2, so nothing to return here
413 }
414 };
415
416 if !config.supports_version(ProtocolVersion::TLSv1_3) {
417 return None;
418 }
419
420 // If the server selected TLS 1.2, we can't resume.
421 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 the selected cipher suite can't select from the session's, we can't resume.
429 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 // RFC 9001 says: "While ALPN only specifies that servers use this alert, QUIC clients MUST
457 // use error 0x0178 to terminate a connection when ALPN negotiation fails." We judge that
458 // the user intended to use ALPN (rather than some out-of-band protocol negotiation
459 // mechanism) iff any ALPN protocols were configured. This defends against badly-behaved
460 // servers which accept a connection that requires an application-layer protocol they do not
461 // understand.
462 if common.is_quic() && common.alpn_protocol.is_none() && !config.alpn_protocols.is_empty() {
463 return Err(common.send_fatal_alert(
464 AlertDescription::NoApplicationProtocol,
465 Error::NoApplicationProtocol,
466 ));
467 }
468
469 debug!(
470 "ALPN protocol is {:?}",
471 common
472 .alpn_protocol
473 .as_ref()
474 .map(|v| bs_debug::BsDebug(v))
475 );
476 Ok(())
477}
478
479impl State<ClientConnectionData> for ExpectServerHello {
480 fn handle(mut self: Box<Self>, cx: &mut ClientContext<'_>, m: Message) -> NextStateOrError {
481 let server_hello =
482 require_handshake_msg!(m, HandshakeType::ServerHello, HandshakePayload::ServerHello)?;
483 trace!("We got ServerHello {:#?}", server_hello);
484
485 use crate::ProtocolVersion::{TLSv1_2, TLSv1_3};
486 let config = &self.input.config;
487 let tls13_supported = config.supports_version(TLSv1_3);
488
489 let server_version = if server_hello.legacy_version == TLSv1_2 {
490 server_hello
491 .get_supported_versions()
492 .unwrap_or(server_hello.legacy_version)
493 } else {
494 server_hello.legacy_version
495 };
496
497 let version = match server_version {
498 TLSv1_3 if tls13_supported => TLSv1_3,
499 TLSv1_2 if config.supports_version(TLSv1_2) => {
500 if cx.data.early_data.is_enabled() && cx.common.early_traffic {
501 // The client must fail with a dedicated error code if the server
502 // responds with TLS 1.2 when offering 0-RTT.
503 return Err(PeerMisbehaved::OfferedEarlyDataWithOldProtocolVersion.into());
504 }
505
506 if server_hello
507 .get_supported_versions()
508 .is_some()
509 {
510 return Err({
511 cx.common.send_fatal_alert(
512 AlertDescription::IllegalParameter,
513 PeerMisbehaved::SelectedTls12UsingTls13VersionExtension,
514 )
515 });
516 }
517
518 TLSv1_2
519 }
520 _ => {
521 let reason = match server_version {
522 TLSv1_2 | TLSv1_3 => PeerIncompatible::ServerTlsVersionIsDisabledByOurConfig,
523 _ => PeerIncompatible::ServerDoesNotSupportTls12Or13,
524 };
525 return Err(cx
526 .common
527 .send_fatal_alert(AlertDescription::ProtocolVersion, reason));
528 }
529 };
530
531 if server_hello.compression_method != Compression::Null {
532 return Err({
533 cx.common.send_fatal_alert(
534 AlertDescription::IllegalParameter,
535 PeerMisbehaved::SelectedUnofferedCompression,
536 )
537 });
538 }
539
540 if server_hello.has_duplicate_extension() {
541 return Err(cx.common.send_fatal_alert(
542 AlertDescription::DecodeError,
543 PeerMisbehaved::DuplicateServerHelloExtensions,
544 ));
545 }
546
547 let allowed_unsolicited = [ExtensionType::RenegotiationInfo];
548 if self
549 .input
550 .hello
551 .server_sent_unsolicited_extensions(&server_hello.extensions, &allowed_unsolicited)
552 {
553 return Err(cx.common.send_fatal_alert(
554 AlertDescription::UnsupportedExtension,
555 PeerMisbehaved::UnsolicitedServerHelloExtension,
556 ));
557 }
558
559 cx.common.negotiated_version = Some(version);
560
561 // Extract ALPN protocol
562 if !cx.common.is_tls13() {
563 process_alpn_protocol(cx.common, config, server_hello.get_alpn_protocol())?;
564 }
565
566 // If ECPointFormats extension is supplied by the server, it must contain
567 // Uncompressed. But it's allowed to be omitted.
568 if let Some(point_fmts) = server_hello.get_ecpoints_extension() {
569 if !point_fmts.contains(&ECPointFormat::Uncompressed) {
570 return Err(cx.common.send_fatal_alert(
571 AlertDescription::HandshakeFailure,
572 PeerMisbehaved::ServerHelloMustOfferUncompressedEcPoints,
573 ));
574 }
575 }
576
577 let suite = config
578 .find_cipher_suite(server_hello.cipher_suite)
579 .ok_or_else(|| {
580 cx.common.send_fatal_alert(
581 AlertDescription::HandshakeFailure,
582 PeerMisbehaved::SelectedUnofferedCipherSuite,
583 )
584 })?;
585
586 if version != suite.version().version {
587 return Err({
588 cx.common.send_fatal_alert(
589 AlertDescription::IllegalParameter,
590 PeerMisbehaved::SelectedUnusableCipherSuiteForVersion,
591 )
592 });
593 }
594
595 match self.suite {
596 Some(prev_suite) if prev_suite != suite => {
597 return Err({
598 cx.common.send_fatal_alert(
599 AlertDescription::IllegalParameter,
600 PeerMisbehaved::SelectedDifferentCipherSuiteAfterRetry,
601 )
602 });
603 }
604 _ => {
605 debug!("Using ciphersuite {:?}", suite);
606 self.suite = Some(suite);
607 cx.common.suite = Some(suite);
608 }
609 }
610
611 // Start our handshake hash, and input the server-hello.
612 let mut transcript = self
613 .transcript_buffer
614 .start_hash(suite.hash_provider());
615 transcript.add_message(&m);
616
617 let randoms = ConnectionRandoms::new(self.input.random, server_hello.random);
618 // For TLS1.3, start message encryption using
619 // handshake_traffic_secret.
620 match suite {
621 SupportedCipherSuite::Tls13(suite) => {
622 #[allow(clippy::bind_instead_of_map)]
623 let resuming_session = self
624 .input
625 .resuming
626 .and_then(|resuming| match resuming.value {
627 ClientSessionValue::Tls13(inner) => Some(inner),
628 #[cfg(feature = "tls12")]
629 ClientSessionValue::Tls12(_) => None,
630 });
631
632 tls13::handle_server_hello(
633 self.input.config,
634 cx,
635 server_hello,
636 resuming_session,
637 self.input.server_name,
638 randoms,
639 suite,
640 transcript,
641 self.early_key_schedule,
642 self.input.hello,
643 // We always send a key share when TLS 1.3 is enabled.
644 self.offered_key_share.unwrap(),
645 self.input.sent_tls13_fake_ccs,
646 )
647 }
648 #[cfg(feature = "tls12")]
649 SupportedCipherSuite::Tls12(suite) => {
650 let resuming_session = self
651 .input
652 .resuming
653 .and_then(|resuming| match resuming.value {
654 ClientSessionValue::Tls12(inner) => Some(inner),
655 ClientSessionValue::Tls13(_) => None,
656 });
657
658 tls12::CompleteServerHelloHandling {
659 config: self.input.config,
660 resuming_session,
661 server_name: self.input.server_name,
662 randoms,
663 using_ems: self.input.using_ems,
664 transcript,
665 }
666 .handle_server_hello(cx, suite, server_hello, tls13_supported)
667 }
668 }
669 }
670}
671
672impl ExpectServerHelloOrHelloRetryRequest {
673 fn into_expect_server_hello(self) -> NextState {
674 Box::new(self.next)
675 }
676
677 fn handle_hello_retry_request(
678 self,
679 cx: &mut ClientContext<'_>,
680 m: Message,
681 ) -> NextStateOrError {
682 let hrr = require_handshake_msg!(
683 m,
684 HandshakeType::HelloRetryRequest,
685 HandshakePayload::HelloRetryRequest
686 )?;
687 trace!("Got HRR {:?}", hrr);
688
689 cx.common.check_aligned_handshake()?;
690
691 let cookie = hrr.get_cookie();
692 let req_group = hrr.get_requested_key_share_group();
693
694 // We always send a key share when TLS 1.3 is enabled.
695 let offered_key_share = self.next.offered_key_share.unwrap();
696
697 // A retry request is illegal if it contains no cookie and asks for
698 // retry of a group we already sent.
699 if cookie.is_none() && req_group == Some(offered_key_share.group()) {
700 return Err({
701 cx.common.send_fatal_alert(
702 AlertDescription::IllegalParameter,
703 PeerMisbehaved::IllegalHelloRetryRequestWithOfferedGroup,
704 )
705 });
706 }
707
708 // Or has an empty cookie.
709 if let Some(cookie) = cookie {
710 if cookie.0.is_empty() {
711 return Err({
712 cx.common.send_fatal_alert(
713 AlertDescription::IllegalParameter,
714 PeerMisbehaved::IllegalHelloRetryRequestWithEmptyCookie,
715 )
716 });
717 }
718 }
719
720 // Or has something unrecognised
721 if hrr.has_unknown_extension() {
722 return Err(cx.common.send_fatal_alert(
723 AlertDescription::UnsupportedExtension,
724 PeerIncompatible::ServerSentHelloRetryRequestWithUnknownExtension,
725 ));
726 }
727
728 // Or has the same extensions more than once
729 if hrr.has_duplicate_extension() {
730 return Err({
731 cx.common.send_fatal_alert(
732 AlertDescription::IllegalParameter,
733 PeerMisbehaved::DuplicateHelloRetryRequestExtensions,
734 )
735 });
736 }
737
738 // Or asks us to change nothing.
739 if cookie.is_none() && req_group.is_none() {
740 return Err({
741 cx.common.send_fatal_alert(
742 AlertDescription::IllegalParameter,
743 PeerMisbehaved::IllegalHelloRetryRequestWithNoChanges,
744 )
745 });
746 }
747
748 // Or does not echo the session_id from our ClientHello:
749 //
750 // > the HelloRetryRequest has the same format as a ServerHello message,
751 // > and the legacy_version, legacy_session_id_echo, cipher_suite, and
752 // > legacy_compression_method fields have the same meaning
753 // <https://www.rfc-editor.org/rfc/rfc8446#section-4.1.4>
754 //
755 // and
756 //
757 // > A client which receives a legacy_session_id_echo field that does not
758 // > match what it sent in the ClientHello MUST abort the handshake with an
759 // > "illegal_parameter" alert.
760 // <https://www.rfc-editor.org/rfc/rfc8446#section-4.1.3>
761 if hrr.session_id != self.next.input.session_id {
762 return Err({
763 cx.common.send_fatal_alert(
764 AlertDescription::IllegalParameter,
765 PeerMisbehaved::IllegalHelloRetryRequestWithWrongSessionId,
766 )
767 });
768 }
769
770 // Or asks us to talk a protocol we didn't offer, or doesn't support HRR at all.
771 match hrr.get_supported_versions() {
772 Some(ProtocolVersion::TLSv1_3) => {
773 cx.common.negotiated_version = Some(ProtocolVersion::TLSv1_3);
774 }
775 _ => {
776 return Err({
777 cx.common.send_fatal_alert(
778 AlertDescription::IllegalParameter,
779 PeerMisbehaved::IllegalHelloRetryRequestWithUnsupportedVersion,
780 )
781 });
782 }
783 }
784
785 // Or asks us to use a ciphersuite we didn't offer.
786 let config = &self.next.input.config;
787 let cs = match config.find_cipher_suite(hrr.cipher_suite) {
788 Some(cs) => cs,
789 None => {
790 return Err({
791 cx.common.send_fatal_alert(
792 AlertDescription::IllegalParameter,
793 PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedCipherSuite,
794 )
795 });
796 }
797 };
798
799 // HRR selects the ciphersuite.
800 cx.common.suite = Some(cs);
801
802 // This is the draft19 change where the transcript became a tree
803 let transcript = self
804 .next
805 .transcript_buffer
806 .start_hash(cs.hash_provider());
807 let mut transcript_buffer = transcript.into_hrr_buffer();
808 transcript_buffer.add_message(&m);
809
810 // Early data is not allowed after HelloRetryrequest
811 if cx.data.early_data.is_enabled() {
812 cx.data.early_data.rejected();
813 }
814
815 let key_share = match req_group {
816 Some(group) if group != offered_key_share.group() => {
817 let skxg = match config.find_kx_group(group) {
818 Some(skxg) => skxg,
819 None => {
820 return Err(cx.common.send_fatal_alert(
821 AlertDescription::IllegalParameter,
822 PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedNamedGroup,
823 ));
824 }
825 };
826
827 skxg.start()
828 .map_err(|_| Error::FailedToGetRandomBytes)?
829 }
830 _ => offered_key_share,
831 };
832
833 Ok(emit_client_hello_for_retry(
834 transcript_buffer,
835 Some(hrr),
836 Some(key_share),
837 self.extra_exts,
838 Some(cs),
839 self.next.input,
840 cx,
841 ))
842 }
843}
844
845impl State<ClientConnectionData> for ExpectServerHelloOrHelloRetryRequest {
846 fn handle(self: Box<Self>, cx: &mut ClientContext<'_>, m: Message) -> NextStateOrError {
847 match m.payload {
848 MessagePayload::Handshake {
849 parsed:
850 HandshakeMessagePayload {
851 payload: HandshakePayload::ServerHello(..),
852 ..
853 },
854 ..
855 } => self
856 .into_expect_server_hello()
857 .handle(cx, m),
858 MessagePayload::Handshake {
859 parsed:
860 HandshakeMessagePayload {
861 payload: HandshakePayload::HelloRetryRequest(..),
862 ..
863 },
864 ..
865 } => self.handle_hello_retry_request(cx, m),
866 payload => Err(inappropriate_handshake_message(
867 &payload,
868 &[ContentType::Handshake],
869 &[HandshakeType::ServerHello, HandshakeType::HelloRetryRequest],
870 )),
871 }
872 }
873}
874
875enum ClientSessionValue {
876 Tls13(persist::Tls13ClientSessionValue),
877 #[cfg(feature = "tls12")]
878 Tls12(persist::Tls12ClientSessionValue),
879}
880
881impl ClientSessionValue {
882 fn common(&self) -> &persist::ClientSessionCommon {
883 match self {
884 Self::Tls13(inner: &Tls13ClientSessionValue) => &inner.common,
885 #[cfg(feature = "tls12")]
886 Self::Tls12(inner: &Tls12ClientSessionValue) => &inner.common,
887 }
888 }
889
890 fn tls13(&self) -> Option<&persist::Tls13ClientSessionValue> {
891 match self {
892 Self::Tls13(v: &Tls13ClientSessionValue) => Some(v),
893 #[cfg(feature = "tls12")]
894 Self::Tls12(_) => None,
895 }
896 }
897}
898
899impl Deref for ClientSessionValue {
900 type Target = persist::ClientSessionCommon;
901
902 fn deref(&self) -> &Self::Target {
903 self.common()
904 }
905}
906