1 #[cfg(feature = "logging")]
2 use crate::bs_debug;
3 use crate::check::check_message;
4 use crate::conn::{CommonState, ConnectionRandoms, State};
5 use crate::error::Error;
6 use crate::hash_hs::HandshakeHashBuffer;
7 use crate::kx;
8 #[cfg(feature = "logging")]
9 use crate::log::{debug, trace};
10 use crate::msgs::base::Payload;
11 #[cfg(feature = "quic")]
12 use crate::msgs::base::PayloadU16;
13 use crate::msgs::codec::{Codec, Reader};
14 use crate::msgs::enums::{AlertDescription, CipherSuite, Compression, ProtocolVersion};
15 use crate::msgs::enums::{ContentType, ExtensionType, HandshakeType};
16 use crate::msgs::enums::{ECPointFormat, PSKKeyExchangeMode};
17 use crate::msgs::handshake::{CertificateStatusRequest, ClientSessionTicket, SCTList};
18 use crate::msgs::handshake::{ClientExtension, HasServerExtensions};
19 use crate::msgs::handshake::{ClientHelloPayload, HandshakeMessagePayload, HandshakePayload};
20 use crate::msgs::handshake::{ConvertProtocolNameList, ProtocolNameList};
21 use crate::msgs::handshake::{ECPointFormatList, SupportedPointFormats};
22 use crate::msgs::handshake::{HelloRetryRequest, KeyShareEntry};
23 use crate::msgs::handshake::{Random, SessionID};
24 use crate::msgs::message::{Message, MessagePayload};
25 use crate::msgs::persist;
26 use crate::ticketer::TimeBase;
27 use crate::tls13::key_schedule::KeyScheduleEarly;
28 use crate::SupportedCipherSuite;
29
30 #[cfg(feature = "tls12")]
31 use super::tls12;
32 use crate::client::client_conn::ClientConnectionData;
33 use crate::client::common::ClientHelloDetails;
34 use crate::client::{tls13, ClientConfig, ServerName};
35
36 use std::sync::Arc;
37
38 pub(super) type NextState = Box<dyn State<ClientConnectionData>>;
39 pub(super) type NextStateOrError = Result<NextState, Error>;
40 pub(super) type ClientContext<'a> = crate::conn::Context<'a, ClientConnectionData>;
41
find_session( server_name: &ServerName, config: &ClientConfig, #[cfg(feature = "quic")] cx: &mut ClientContext<'_>, ) -> Option<persist::Retrieved<persist::ClientSessionValue>>42 fn find_session(
43 server_name: &ServerName,
44 config: &ClientConfig,
45 #[cfg(feature = "quic")] cx: &mut ClientContext<'_>,
46 ) -> Option<persist::Retrieved<persist::ClientSessionValue>> {
47 let key = persist::ClientSessionKey::session_for_server_name(server_name);
48 let key_buf = key.get_encoding();
49
50 let value = config
51 .session_storage
52 .get(&key_buf)
53 .or_else(|| {
54 debug!("No cached session for {:?}", server_name);
55 None
56 })?;
57
58 #[allow(unused_mut)]
59 let mut reader = Reader::init(&value[2..]);
60 CipherSuite::read_bytes(&value[..2])
61 .and_then(|suite| {
62 persist::ClientSessionValue::read(&mut reader, suite, &config.cipher_suites)
63 })
64 .and_then(|resuming| {
65 let retrieved = persist::Retrieved::new(resuming, TimeBase::now().ok()?);
66 match retrieved.has_expired() {
67 false => Some(retrieved),
68 true => None,
69 }
70 })
71 .and_then(|resuming| {
72 #[cfg(feature = "quic")]
73 if cx.common.is_quic() {
74 let params = PayloadU16::read(&mut reader)?;
75 cx.common.quic.params = Some(params.0);
76 }
77 Some(resuming)
78 })
79 }
80
start_handshake( server_name: ServerName, extra_exts: Vec<ClientExtension>, config: Arc<ClientConfig>, cx: &mut ClientContext<'_>, ) -> NextStateOrError81 pub(super) fn start_handshake(
82 server_name: ServerName,
83 extra_exts: Vec<ClientExtension>,
84 config: Arc<ClientConfig>,
85 cx: &mut ClientContext<'_>,
86 ) -> NextStateOrError {
87 let mut transcript_buffer = HandshakeHashBuffer::new();
88 if config
89 .client_auth_cert_resolver
90 .has_certs()
91 {
92 transcript_buffer.set_client_auth_enabled();
93 }
94
95 let support_tls13 = config.supports_version(ProtocolVersion::TLSv1_3);
96
97 let mut session_id: Option<SessionID> = None;
98 let mut resuming_session = find_session(
99 &server_name,
100 &config,
101 #[cfg(feature = "quic")]
102 cx,
103 );
104
105 let key_share = if support_tls13 {
106 Some(tls13::initial_key_share(&config, &server_name)?)
107 } else {
108 None
109 };
110
111 if let Some(_resuming) = &mut resuming_session {
112 #[cfg(feature = "tls12")]
113 if let persist::ClientSessionValue::Tls12(inner) = &mut _resuming.value {
114 // If we have a ticket, we use the sessionid as a signal that
115 // we're doing an abbreviated handshake. See section 3.4 in
116 // RFC5077.
117 if !inner.ticket().is_empty() {
118 inner.session_id = SessionID::random()?;
119 }
120 session_id = Some(inner.session_id);
121 }
122
123 debug!("Resuming session");
124 } else {
125 debug!("Not resuming any session");
126 }
127
128 // https://tools.ietf.org/html/rfc8446#appendix-D.4
129 // https://tools.ietf.org/html/draft-ietf-quic-tls-34#section-8.4
130 if session_id.is_none() && !cx.common.is_quic() {
131 session_id = Some(SessionID::random()?);
132 }
133
134 let random = Random::new()?;
135 let hello_details = ClientHelloDetails::new();
136 let sent_tls13_fake_ccs = false;
137 let may_send_sct_list = config.verifier.request_scts();
138 Ok(emit_client_hello_for_retry(
139 config,
140 cx,
141 resuming_session,
142 random,
143 false,
144 transcript_buffer,
145 sent_tls13_fake_ccs,
146 hello_details,
147 session_id,
148 None,
149 server_name,
150 key_share,
151 extra_exts,
152 may_send_sct_list,
153 None,
154 ))
155 }
156
157 struct ExpectServerHello {
158 config: Arc<ClientConfig>,
159 resuming_session: Option<persist::Retrieved<persist::ClientSessionValue>>,
160 server_name: ServerName,
161 random: Random,
162 using_ems: bool,
163 transcript_buffer: HandshakeHashBuffer,
164 early_key_schedule: Option<KeyScheduleEarly>,
165 hello: ClientHelloDetails,
166 offered_key_share: Option<kx::KeyExchange>,
167 session_id: SessionID,
168 sent_tls13_fake_ccs: bool,
169 suite: Option<SupportedCipherSuite>,
170 }
171
172 struct ExpectServerHelloOrHelloRetryRequest {
173 next: ExpectServerHello,
174 extra_exts: Vec<ClientExtension>,
175 }
176
emit_client_hello_for_retry( config: Arc<ClientConfig>, cx: &mut ClientContext<'_>, resuming_session: Option<persist::Retrieved<persist::ClientSessionValue>>, random: Random, using_ems: bool, mut transcript_buffer: HandshakeHashBuffer, mut sent_tls13_fake_ccs: bool, mut hello: ClientHelloDetails, session_id: Option<SessionID>, retryreq: Option<&HelloRetryRequest>, server_name: ServerName, key_share: Option<kx::KeyExchange>, extra_exts: Vec<ClientExtension>, may_send_sct_list: bool, suite: Option<SupportedCipherSuite>, ) -> NextState177 fn emit_client_hello_for_retry(
178 config: Arc<ClientConfig>,
179 cx: &mut ClientContext<'_>,
180 resuming_session: Option<persist::Retrieved<persist::ClientSessionValue>>,
181 random: Random,
182 using_ems: bool,
183 mut transcript_buffer: HandshakeHashBuffer,
184 mut sent_tls13_fake_ccs: bool,
185 mut hello: ClientHelloDetails,
186 session_id: Option<SessionID>,
187 retryreq: Option<&HelloRetryRequest>,
188 server_name: ServerName,
189 key_share: Option<kx::KeyExchange>,
190 extra_exts: Vec<ClientExtension>,
191 may_send_sct_list: bool,
192 suite: Option<SupportedCipherSuite>,
193 ) -> NextState {
194 // Do we have a SessionID or ticket cached for this host?
195 let (ticket, resume_version) = if let Some(resuming) = &resuming_session {
196 match &resuming.value {
197 persist::ClientSessionValue::Tls13(inner) => {
198 (inner.ticket().to_vec(), ProtocolVersion::TLSv1_3)
199 }
200 #[cfg(feature = "tls12")]
201 persist::ClientSessionValue::Tls12(inner) => {
202 (inner.ticket().to_vec(), ProtocolVersion::TLSv1_2)
203 }
204 }
205 } else {
206 (Vec::new(), ProtocolVersion::Unknown(0))
207 };
208
209 let support_tls12 = config.supports_version(ProtocolVersion::TLSv1_2) && !cx.common.is_quic();
210 let support_tls13 = config.supports_version(ProtocolVersion::TLSv1_3);
211
212 let mut supported_versions = Vec::new();
213 if support_tls13 {
214 supported_versions.push(ProtocolVersion::TLSv1_3);
215 }
216
217 if support_tls12 {
218 supported_versions.push(ProtocolVersion::TLSv1_2);
219 }
220
221 let mut exts = Vec::new();
222 if !supported_versions.is_empty() {
223 exts.push(ClientExtension::SupportedVersions(supported_versions));
224 }
225 if let (Some(sni_name), true) = (server_name.for_sni(), config.enable_sni) {
226 exts.push(ClientExtension::make_sni(sni_name));
227 }
228 exts.push(ClientExtension::ECPointFormats(
229 ECPointFormatList::supported(),
230 ));
231 exts.push(ClientExtension::NamedGroups(
232 config
233 .kx_groups
234 .iter()
235 .map(|skxg| skxg.name)
236 .collect(),
237 ));
238 exts.push(ClientExtension::SignatureAlgorithms(
239 config
240 .verifier
241 .supported_verify_schemes(),
242 ));
243 exts.push(ClientExtension::ExtendedMasterSecretRequest);
244 exts.push(ClientExtension::CertificateStatusRequest(
245 CertificateStatusRequest::build_ocsp(),
246 ));
247
248 if may_send_sct_list {
249 exts.push(ClientExtension::SignedCertificateTimestampRequest);
250 }
251
252 if let Some(key_share) = &key_share {
253 debug_assert!(support_tls13);
254 let key_share = KeyShareEntry::new(key_share.group(), key_share.pubkey.as_ref());
255 exts.push(ClientExtension::KeyShare(vec![key_share]));
256 }
257
258 if let Some(cookie) = retryreq.and_then(HelloRetryRequest::get_cookie) {
259 exts.push(ClientExtension::Cookie(cookie.clone()));
260 }
261
262 if support_tls13 && config.enable_tickets {
263 // We could support PSK_KE here too. Such connections don't
264 // have forward secrecy, and are similar to TLS1.2 resumption.
265 let psk_modes = vec![PSKKeyExchangeMode::PSK_DHE_KE];
266 exts.push(ClientExtension::PresharedKeyModes(psk_modes));
267 }
268
269 if !config.alpn_protocols.is_empty() {
270 exts.push(ClientExtension::Protocols(ProtocolNameList::from_slices(
271 &config
272 .alpn_protocols
273 .iter()
274 .map(|proto| &proto[..])
275 .collect::<Vec<_>>(),
276 )));
277 }
278
279 // Extra extensions must be placed before the PSK extension
280 exts.extend(extra_exts.iter().cloned());
281
282 let fill_in_binder = if support_tls13
283 && config.enable_tickets
284 && resume_version == ProtocolVersion::TLSv1_3
285 && !ticket.is_empty()
286 {
287 resuming_session
288 .as_ref()
289 .and_then(|resuming| match (suite, resuming.tls13()) {
290 (Some(suite), Some(resuming)) => {
291 suite
292 .tls13()?
293 .can_resume_from(resuming.suite())?;
294 Some(resuming)
295 }
296 (None, Some(resuming)) => Some(resuming),
297 _ => None,
298 })
299 .map(|resuming| {
300 tls13::prepare_resumption(
301 &config,
302 cx,
303 ticket,
304 &resuming,
305 &mut exts,
306 retryreq.is_some(),
307 );
308 resuming
309 })
310 } else if config.enable_tickets {
311 // If we have a ticket, include it. Otherwise, request one.
312 if ticket.is_empty() {
313 exts.push(ClientExtension::SessionTicket(ClientSessionTicket::Request));
314 } else {
315 exts.push(ClientExtension::SessionTicket(ClientSessionTicket::Offer(
316 Payload::new(ticket),
317 )));
318 }
319 None
320 } else {
321 None
322 };
323
324 // Note what extensions we sent.
325 hello.sent_extensions = exts
326 .iter()
327 .map(ClientExtension::get_type)
328 .collect();
329
330 let session_id = session_id.unwrap_or_else(SessionID::empty);
331 let mut cipher_suites: Vec<_> = config
332 .cipher_suites
333 .iter()
334 .map(|cs| cs.suite())
335 .collect();
336 // We don't do renegotiation at all, in fact.
337 cipher_suites.push(CipherSuite::TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
338
339 let mut chp = HandshakeMessagePayload {
340 typ: HandshakeType::ClientHello,
341 payload: HandshakePayload::ClientHello(ClientHelloPayload {
342 client_version: ProtocolVersion::TLSv1_2,
343 random,
344 session_id,
345 cipher_suites,
346 compression_methods: vec![Compression::Null],
347 extensions: exts,
348 }),
349 };
350
351 let early_key_schedule = if let Some(resuming) = fill_in_binder {
352 let schedule = tls13::fill_in_psk_binder(&resuming, &transcript_buffer, &mut chp);
353 Some((resuming.suite(), schedule))
354 } else {
355 None
356 };
357
358 let ch = Message {
359 // "This value MUST be set to 0x0303 for all records generated
360 // by a TLS 1.3 implementation other than an initial ClientHello
361 // (i.e., one not generated after a HelloRetryRequest)"
362 version: if retryreq.is_some() {
363 ProtocolVersion::TLSv1_2
364 } else {
365 ProtocolVersion::TLSv1_0
366 },
367 payload: MessagePayload::Handshake(chp),
368 };
369
370 if retryreq.is_some() {
371 // send dummy CCS to fool middleboxes prior
372 // to second client hello
373 tls13::emit_fake_ccs(&mut sent_tls13_fake_ccs, cx.common);
374 }
375
376 trace!("Sending ClientHello {:#?}", ch);
377
378 transcript_buffer.add_message(&ch);
379 cx.common.send_msg(ch, false);
380
381 // Calculate the hash of ClientHello and use it to derive EarlyTrafficSecret
382 let early_key_schedule = early_key_schedule.map(|(resuming_suite, schedule)| {
383 if !cx.data.early_data.is_enabled() {
384 return schedule;
385 }
386
387 tls13::derive_early_traffic_secret(
388 &*config.key_log,
389 cx,
390 resuming_suite,
391 &schedule,
392 &mut sent_tls13_fake_ccs,
393 &transcript_buffer,
394 &random.0,
395 );
396 schedule
397 });
398
399 let next = ExpectServerHello {
400 config,
401 resuming_session,
402 server_name,
403 random,
404 using_ems,
405 transcript_buffer,
406 early_key_schedule,
407 hello,
408 offered_key_share: key_share,
409 session_id,
410 sent_tls13_fake_ccs,
411 suite,
412 };
413
414 if support_tls13 && retryreq.is_none() {
415 Box::new(ExpectServerHelloOrHelloRetryRequest { next, extra_exts })
416 } else {
417 Box::new(next)
418 }
419 }
420
process_alpn_protocol( cx: &mut ClientContext<'_>, config: &ClientConfig, proto: Option<&[u8]>, ) -> Result<(), Error>421 pub(super) fn process_alpn_protocol(
422 cx: &mut ClientContext<'_>,
423 config: &ClientConfig,
424 proto: Option<&[u8]>,
425 ) -> Result<(), Error> {
426 cx.common.alpn_protocol = proto.map(ToOwned::to_owned);
427
428 if let Some(alpn_protocol) = &cx.common.alpn_protocol {
429 if !config
430 .alpn_protocols
431 .contains(alpn_protocol)
432 {
433 return Err(cx
434 .common
435 .illegal_param("server sent non-offered ALPN protocol"));
436 }
437 }
438
439 debug!(
440 "ALPN protocol is {:?}",
441 cx.common
442 .alpn_protocol
443 .as_ref()
444 .map(|v| bs_debug::BsDebug(v))
445 );
446 Ok(())
447 }
448
sct_list_is_invalid(scts: &SCTList) -> bool449 pub(super) fn sct_list_is_invalid(scts: &SCTList) -> bool {
450 scts.is_empty() || scts.iter().any(|sct| sct.0.is_empty())
451 }
452
453 impl State<ClientConnectionData> for ExpectServerHello {
handle(mut self: Box<Self>, cx: &mut ClientContext<'_>, m: Message) -> NextStateOrError454 fn handle(mut self: Box<Self>, cx: &mut ClientContext<'_>, m: Message) -> NextStateOrError {
455 let server_hello =
456 require_handshake_msg!(m, HandshakeType::ServerHello, HandshakePayload::ServerHello)?;
457 trace!("We got ServerHello {:#?}", server_hello);
458
459 use crate::ProtocolVersion::{TLSv1_2, TLSv1_3};
460 let tls13_supported = self.config.supports_version(TLSv1_3);
461
462 let server_version = if server_hello.legacy_version == TLSv1_2 {
463 server_hello
464 .get_supported_versions()
465 .unwrap_or(server_hello.legacy_version)
466 } else {
467 server_hello.legacy_version
468 };
469
470 let version = match server_version {
471 TLSv1_3 if tls13_supported => TLSv1_3,
472 TLSv1_2 if self.config.supports_version(TLSv1_2) => {
473 if cx.data.early_data.is_enabled() && cx.common.early_traffic {
474 // The client must fail with a dedicated error code if the server
475 // responds with TLS 1.2 when offering 0-RTT.
476 return Err(Error::PeerMisbehavedError(
477 "server chose v1.2 when offering 0-rtt".to_string(),
478 ));
479 }
480
481 if server_hello
482 .get_supported_versions()
483 .is_some()
484 {
485 return Err(cx
486 .common
487 .illegal_param("server chose v1.2 using v1.3 extension"));
488 }
489
490 TLSv1_2
491 }
492 _ => {
493 cx.common
494 .send_fatal_alert(AlertDescription::ProtocolVersion);
495 let msg = match server_version {
496 TLSv1_2 | TLSv1_3 => "server's TLS version is disabled in client",
497 _ => "server does not support TLS v1.2/v1.3",
498 };
499 return Err(Error::PeerIncompatibleError(msg.to_string()));
500 }
501 };
502
503 if server_hello.compression_method != Compression::Null {
504 return Err(cx
505 .common
506 .illegal_param("server chose non-Null compression"));
507 }
508
509 if server_hello.has_duplicate_extension() {
510 cx.common
511 .send_fatal_alert(AlertDescription::DecodeError);
512 return Err(Error::PeerMisbehavedError(
513 "server sent duplicate extensions".to_string(),
514 ));
515 }
516
517 let allowed_unsolicited = [ExtensionType::RenegotiationInfo];
518 if self
519 .hello
520 .server_sent_unsolicited_extensions(&server_hello.extensions, &allowed_unsolicited)
521 {
522 cx.common
523 .send_fatal_alert(AlertDescription::UnsupportedExtension);
524 return Err(Error::PeerMisbehavedError(
525 "server sent unsolicited extension".to_string(),
526 ));
527 }
528
529 cx.common.negotiated_version = Some(version);
530
531 // Extract ALPN protocol
532 if !cx.common.is_tls13() {
533 process_alpn_protocol(cx, &self.config, server_hello.get_alpn_protocol())?;
534 }
535
536 // If ECPointFormats extension is supplied by the server, it must contain
537 // Uncompressed. But it's allowed to be omitted.
538 if let Some(point_fmts) = server_hello.get_ecpoints_extension() {
539 if !point_fmts.contains(&ECPointFormat::Uncompressed) {
540 cx.common
541 .send_fatal_alert(AlertDescription::HandshakeFailure);
542 return Err(Error::PeerMisbehavedError(
543 "server does not support uncompressed points".to_string(),
544 ));
545 }
546 }
547
548 let suite = self
549 .config
550 .find_cipher_suite(server_hello.cipher_suite)
551 .ok_or_else(|| {
552 cx.common
553 .send_fatal_alert(AlertDescription::HandshakeFailure);
554 Error::PeerMisbehavedError("server chose non-offered ciphersuite".to_string())
555 })?;
556
557 if version != suite.version().version {
558 return Err(cx
559 .common
560 .illegal_param("server chose unusable ciphersuite for version"));
561 }
562
563 match self.suite {
564 Some(prev_suite) if prev_suite != suite => {
565 return Err(cx
566 .common
567 .illegal_param("server varied selected ciphersuite"));
568 }
569 _ => {
570 debug!("Using ciphersuite {:?}", suite);
571 self.suite = Some(suite);
572 cx.common.suite = Some(suite);
573 }
574 }
575
576 // Start our handshake hash, and input the server-hello.
577 let mut transcript = self
578 .transcript_buffer
579 .start_hash(suite.hash_algorithm());
580 transcript.add_message(&m);
581
582 let randoms = ConnectionRandoms::new(self.random, server_hello.random, true);
583 // For TLS1.3, start message encryption using
584 // handshake_traffic_secret.
585 match suite {
586 SupportedCipherSuite::Tls13(suite) => {
587 let resuming_session = self
588 .resuming_session
589 .and_then(|resuming| match resuming.value {
590 persist::ClientSessionValue::Tls13(inner) => Some(inner),
591 #[cfg(feature = "tls12")]
592 persist::ClientSessionValue::Tls12(_) => None,
593 });
594
595 tls13::handle_server_hello(
596 self.config,
597 cx,
598 server_hello,
599 resuming_session,
600 self.server_name,
601 randoms,
602 suite,
603 transcript,
604 self.early_key_schedule,
605 self.hello,
606 // We always send a key share when TLS 1.3 is enabled.
607 self.offered_key_share.unwrap(),
608 self.sent_tls13_fake_ccs,
609 )
610 }
611 #[cfg(feature = "tls12")]
612 SupportedCipherSuite::Tls12(suite) => {
613 let resuming_session = self
614 .resuming_session
615 .and_then(|resuming| match resuming.value {
616 persist::ClientSessionValue::Tls12(inner) => Some(inner),
617 persist::ClientSessionValue::Tls13(_) => None,
618 });
619
620 tls12::CompleteServerHelloHandling {
621 config: self.config,
622 resuming_session,
623 server_name: self.server_name,
624 randoms,
625 using_ems: self.using_ems,
626 transcript,
627 }
628 .handle_server_hello(cx, suite, server_hello, tls13_supported)
629 }
630 }
631 }
632 }
633
634 impl ExpectServerHelloOrHelloRetryRequest {
into_expect_server_hello(self) -> NextState635 fn into_expect_server_hello(self) -> NextState {
636 Box::new(self.next)
637 }
638
handle_hello_retry_request( self, cx: &mut ClientContext<'_>, m: Message, ) -> NextStateOrError639 fn handle_hello_retry_request(
640 self,
641 cx: &mut ClientContext<'_>,
642 m: Message,
643 ) -> NextStateOrError {
644 let hrr = require_handshake_msg!(
645 m,
646 HandshakeType::HelloRetryRequest,
647 HandshakePayload::HelloRetryRequest
648 )?;
649 trace!("Got HRR {:?}", hrr);
650
651 cx.common.check_aligned_handshake()?;
652
653 let cookie = hrr.get_cookie();
654 let req_group = hrr.get_requested_key_share_group();
655
656 // We always send a key share when TLS 1.3 is enabled.
657 let offered_key_share = self.next.offered_key_share.unwrap();
658
659 // A retry request is illegal if it contains no cookie and asks for
660 // retry of a group we already sent.
661 if cookie.is_none() && req_group == Some(offered_key_share.group()) {
662 return Err(cx
663 .common
664 .illegal_param("server requested hrr with our group"));
665 }
666
667 // Or has an empty cookie.
668 if let Some(cookie) = cookie {
669 if cookie.0.is_empty() {
670 return Err(cx
671 .common
672 .illegal_param("server requested hrr with empty cookie"));
673 }
674 }
675
676 // Or has something unrecognised
677 if hrr.has_unknown_extension() {
678 cx.common
679 .send_fatal_alert(AlertDescription::UnsupportedExtension);
680 return Err(Error::PeerIncompatibleError(
681 "server sent hrr with unhandled extension".to_string(),
682 ));
683 }
684
685 // Or has the same extensions more than once
686 if hrr.has_duplicate_extension() {
687 return Err(cx
688 .common
689 .illegal_param("server send duplicate hrr extensions"));
690 }
691
692 // Or asks us to change nothing.
693 if cookie.is_none() && req_group.is_none() {
694 return Err(cx
695 .common
696 .illegal_param("server requested hrr with no changes"));
697 }
698
699 // Or asks us to talk a protocol we didn't offer, or doesn't support HRR at all.
700 match hrr.get_supported_versions() {
701 Some(ProtocolVersion::TLSv1_3) => {
702 cx.common.negotiated_version = Some(ProtocolVersion::TLSv1_3);
703 }
704 _ => {
705 return Err(cx
706 .common
707 .illegal_param("server requested unsupported version in hrr"));
708 }
709 }
710
711 // Or asks us to use a ciphersuite we didn't offer.
712 let maybe_cs = self
713 .next
714 .config
715 .find_cipher_suite(hrr.cipher_suite);
716 let cs = match maybe_cs {
717 Some(cs) => cs,
718 None => {
719 return Err(cx
720 .common
721 .illegal_param("server requested unsupported cs in hrr"));
722 }
723 };
724
725 // HRR selects the ciphersuite.
726 cx.common.suite = Some(cs);
727
728 // This is the draft19 change where the transcript became a tree
729 let transcript = self
730 .next
731 .transcript_buffer
732 .start_hash(cs.hash_algorithm());
733 let mut transcript_buffer = transcript.into_hrr_buffer();
734 transcript_buffer.add_message(&m);
735
736 // Early data is not allowed after HelloRetryrequest
737 if cx.data.early_data.is_enabled() {
738 cx.data.early_data.rejected();
739 }
740
741 let may_send_sct_list = self
742 .next
743 .hello
744 .server_may_send_sct_list();
745
746 let key_share = match req_group {
747 Some(group) if group != offered_key_share.group() => {
748 let group = kx::KeyExchange::choose(group, &self.next.config.kx_groups)
749 .ok_or_else(|| {
750 cx.common
751 .illegal_param("server requested hrr with bad group")
752 })?;
753 kx::KeyExchange::start(group).ok_or(Error::FailedToGetRandomBytes)?
754 }
755 _ => offered_key_share,
756 };
757
758 Ok(emit_client_hello_for_retry(
759 self.next.config,
760 cx,
761 self.next.resuming_session,
762 self.next.random,
763 self.next.using_ems,
764 transcript_buffer,
765 self.next.sent_tls13_fake_ccs,
766 self.next.hello,
767 Some(self.next.session_id),
768 Some(hrr),
769 self.next.server_name,
770 Some(key_share),
771 self.extra_exts,
772 may_send_sct_list,
773 Some(cs),
774 ))
775 }
776 }
777
778 impl State<ClientConnectionData> for ExpectServerHelloOrHelloRetryRequest {
handle(self: Box<Self>, cx: &mut ClientContext<'_>, m: Message) -> NextStateOrError779 fn handle(self: Box<Self>, cx: &mut ClientContext<'_>, m: Message) -> NextStateOrError {
780 check_message(
781 &m,
782 &[ContentType::Handshake],
783 &[HandshakeType::ServerHello, HandshakeType::HelloRetryRequest],
784 )?;
785 if m.is_handshake_type(HandshakeType::ServerHello) {
786 self.into_expect_server_hello()
787 .handle(cx, m)
788 } else {
789 self.handle_hello_retry_request(cx, m)
790 }
791 }
792 }
793
send_cert_error_alert(common: &mut CommonState, err: Error) -> Error794 pub(super) fn send_cert_error_alert(common: &mut CommonState, err: Error) -> Error {
795 match err {
796 Error::InvalidCertificateEncoding => {
797 common.send_fatal_alert(AlertDescription::DecodeError);
798 }
799 Error::PeerMisbehavedError(_) => {
800 common.send_fatal_alert(AlertDescription::IllegalParameter);
801 }
802 _ => {
803 common.send_fatal_alert(AlertDescription::BadCertificate);
804 }
805 };
806
807 err
808 }
809