1use alloc::borrow::ToOwned;
2use alloc::boxed::Box;
3use alloc::sync::Arc;
4use alloc::vec::Vec;
5
6use pki_types::DnsName;
7
8use super::server_conn::ServerConnectionData;
9#[cfg(feature = "tls12")]
10use super::tls12;
11use crate::common_state::{
12 KxState, Protocol, RawKeyNegotationResult, RawKeyNegotiationParams, State,
13};
14use crate::conn::ConnectionRandoms;
15use crate::crypto::SupportedKxGroup;
16use crate::enums::{
17 AlertDescription, CipherSuite, HandshakeType, ProtocolVersion, SignatureAlgorithm,
18 SignatureScheme,
19};
20use crate::error::{Error, PeerIncompatible, PeerMisbehaved};
21use crate::hash_hs::{HandshakeHash, HandshakeHashBuffer};
22use crate::log::{debug, trace};
23use crate::msgs::enums::{CertificateType, Compression, ExtensionType, NamedGroup};
24#[cfg(feature = "tls12")]
25use crate::msgs::handshake::SessionId;
26use crate::msgs::handshake::{
27 ClientHelloPayload, ConvertProtocolNameList, ConvertServerNameList, HandshakePayload,
28 KeyExchangeAlgorithm, Random, ServerExtension,
29};
30use crate::msgs::message::{Message, MessagePayload};
31use crate::msgs::persist;
32use crate::server::common::ActiveCertifiedKey;
33use crate::server::{tls13, ClientHello, ServerConfig};
34use crate::{suites, SupportedCipherSuite};
35
36pub(super) type NextState<'a> = Box<dyn State<ServerConnectionData> + 'a>;
37pub(super) type NextStateOrError<'a> = Result<NextState<'a>, Error>;
38pub(super) type ServerContext<'a> = crate::common_state::Context<'a, ServerConnectionData>;
39
40pub(super) fn can_resume(
41 suite: SupportedCipherSuite,
42 sni: &Option<DnsName<'_>>,
43 using_ems: bool,
44 resumedata: &persist::ServerSessionValue,
45) -> bool {
46 resumedata.cipher_suite == suite.suite()
54 && (resumedata.extended_ms == using_ems || (resumedata.extended_ms && !using_ems))
55 && &resumedata.sni == sni
56}
57
58#[derive(Default)]
59pub(super) struct ExtensionProcessing {
60 pub(super) exts: Vec<ServerExtension>,
62 #[cfg(feature = "tls12")]
63 pub(super) send_ticket: bool,
64}
65
66impl ExtensionProcessing {
67 pub(super) fn new() -> Self {
68 Default::default()
69 }
70
71 pub(super) fn process_common(
72 &mut self,
73 config: &ServerConfig,
74 cx: &mut ServerContext<'_>,
75 ocsp_response: &mut Option<&[u8]>,
76 hello: &ClientHelloPayload,
77 resumedata: Option<&persist::ServerSessionValue>,
78 extra_exts: Vec<ServerExtension>,
79 ) -> Result<(), Error> {
80 let our_protocols = &config.alpn_protocols;
82 let maybe_their_protocols = hello.alpn_extension();
83 if let Some(their_protocols) = maybe_their_protocols {
84 let their_protocols = their_protocols.to_slices();
85
86 if their_protocols
87 .iter()
88 .any(|protocol| protocol.is_empty())
89 {
90 return Err(PeerMisbehaved::OfferedEmptyApplicationProtocol.into());
91 }
92
93 cx.common.alpn_protocol = our_protocols
94 .iter()
95 .find(|protocol| their_protocols.contains(&protocol.as_slice()))
96 .cloned();
97 if let Some(ref selected_protocol) = cx.common.alpn_protocol {
98 debug!("Chosen ALPN protocol {:?}", selected_protocol);
99 self.exts
100 .push(ServerExtension::make_alpn(&[selected_protocol]));
101 } else if !our_protocols.is_empty() {
102 return Err(cx.common.send_fatal_alert(
103 AlertDescription::NoApplicationProtocol,
104 Error::NoApplicationProtocol,
105 ));
106 }
107 }
108
109 if cx.common.is_quic() {
110 if cx.common.alpn_protocol.is_none()
118 && (!our_protocols.is_empty() || maybe_their_protocols.is_some())
119 {
120 return Err(cx.common.send_fatal_alert(
121 AlertDescription::NoApplicationProtocol,
122 Error::NoApplicationProtocol,
123 ));
124 }
125
126 match hello.quic_params_extension() {
127 Some(params) => cx.common.quic.params = Some(params),
128 None => {
129 return Err(cx
130 .common
131 .missing_extension(PeerMisbehaved::MissingQuicTransportParameters));
132 }
133 }
134 }
135
136 let for_resume = resumedata.is_some();
137 if !for_resume && hello.sni_extension().is_some() {
139 self.exts
140 .push(ServerExtension::ServerNameAck);
141 }
142
143 if !for_resume
147 && hello
148 .find_extension(ExtensionType::StatusRequest)
149 .is_some()
150 {
151 if ocsp_response.is_some() && !cx.common.is_tls13() {
152 self.exts
154 .push(ServerExtension::CertificateStatusAck);
155 }
156 } else {
157 ocsp_response.take();
159 }
160
161 self.validate_server_cert_type_extension(hello, config, cx)?;
162 self.validate_client_cert_type_extension(hello, config, cx)?;
163
164 self.exts.extend(extra_exts);
165
166 Ok(())
167 }
168
169 #[cfg(feature = "tls12")]
170 pub(super) fn process_tls12(
171 &mut self,
172 config: &ServerConfig,
173 hello: &ClientHelloPayload,
174 using_ems: bool,
175 ) {
176 let secure_reneg_offered = hello
179 .find_extension(ExtensionType::RenegotiationInfo)
180 .is_some()
181 || hello
182 .cipher_suites
183 .contains(&CipherSuite::TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
184
185 if secure_reneg_offered {
186 self.exts
187 .push(ServerExtension::make_empty_renegotiation_info());
188 }
189
190 if hello
194 .find_extension(ExtensionType::SessionTicket)
195 .is_some()
196 && config.ticketer.enabled()
197 {
198 self.send_ticket = true;
199 self.exts
200 .push(ServerExtension::SessionTicketAck);
201 }
202
203 if using_ems {
205 self.exts
206 .push(ServerExtension::ExtendedMasterSecretAck);
207 }
208 }
209
210 fn validate_server_cert_type_extension(
211 &mut self,
212 hello: &ClientHelloPayload,
213 config: &ServerConfig,
214 cx: &mut ServerContext<'_>,
215 ) -> Result<(), Error> {
216 let requires_server_rpk = config
217 .cert_resolver
218 .only_raw_public_keys();
219 let client_allows_rpk = hello
220 .server_certificate_extension()
221 .map(|certificate_types| certificate_types.contains(&CertificateType::RawPublicKey))
222 .unwrap_or(false);
223
224 let raw_key_negotation_params = RawKeyNegotiationParams {
225 peer_supports_raw_key: client_allows_rpk,
226 local_expects_raw_key: requires_server_rpk,
227 extension_type: ExtensionType::ServerCertificateType,
228 };
229
230 self.process_cert_type_extension(
231 raw_key_negotation_params.validate_raw_key_negotiation(),
232 cx,
233 )
234 }
235
236 fn validate_client_cert_type_extension(
237 &mut self,
238 hello: &ClientHelloPayload,
239 config: &ServerConfig,
240 cx: &mut ServerContext<'_>,
241 ) -> Result<(), Error> {
242 let requires_client_rpk = config
243 .verifier
244 .requires_raw_public_keys();
245 let client_offers_rpk = hello
246 .client_certificate_extension()
247 .map(|certificate_types| certificate_types.contains(&CertificateType::RawPublicKey))
248 .unwrap_or(false);
249
250 let raw_key_negotation_params = RawKeyNegotiationParams {
251 peer_supports_raw_key: client_offers_rpk,
252 local_expects_raw_key: requires_client_rpk,
253 extension_type: ExtensionType::ClientCertificateType,
254 };
255 self.process_cert_type_extension(
256 raw_key_negotation_params.validate_raw_key_negotiation(),
257 cx,
258 )
259 }
260
261 fn process_cert_type_extension(
262 &mut self,
263 raw_key_negotiation_result: RawKeyNegotationResult,
264 cx: &mut ServerContext<'_>,
265 ) -> Result<(), Error> {
266 match raw_key_negotiation_result {
267 RawKeyNegotationResult::Negotiated(ExtensionType::ClientCertificateType) => {
268 self.exts
269 .push(ServerExtension::ClientCertType(
270 CertificateType::RawPublicKey,
271 ));
272 }
273 RawKeyNegotationResult::Negotiated(ExtensionType::ServerCertificateType) => {
274 self.exts
275 .push(ServerExtension::ServerCertType(
276 CertificateType::RawPublicKey,
277 ));
278 }
279 RawKeyNegotationResult::Err(err) => {
280 return Err(cx
281 .common
282 .send_fatal_alert(AlertDescription::HandshakeFailure, err));
283 }
284 RawKeyNegotationResult::NotNegotiated => {}
285 RawKeyNegotationResult::Negotiated(_) => unreachable!(
286 "The extension type should only ever be ClientCertificateType or ServerCertificateType"
287 ),
288 }
289 Ok(())
290 }
291}
292
293pub(super) struct ExpectClientHello {
294 pub(super) config: Arc<ServerConfig>,
295 pub(super) extra_exts: Vec<ServerExtension>,
296 pub(super) transcript: HandshakeHashOrBuffer,
297 #[cfg(feature = "tls12")]
298 pub(super) session_id: SessionId,
299 #[cfg(feature = "tls12")]
300 pub(super) using_ems: bool,
301 pub(super) done_retry: bool,
302 pub(super) send_tickets: usize,
303}
304
305impl ExpectClientHello {
306 pub(super) fn new(config: Arc<ServerConfig>, extra_exts: Vec<ServerExtension>) -> Self {
307 let mut transcript_buffer = HandshakeHashBuffer::new();
308
309 if config.verifier.offer_client_auth() {
310 transcript_buffer.set_client_auth_enabled();
311 }
312
313 Self {
314 config,
315 extra_exts,
316 transcript: HandshakeHashOrBuffer::Buffer(transcript_buffer),
317 #[cfg(feature = "tls12")]
318 session_id: SessionId::empty(),
319 #[cfg(feature = "tls12")]
320 using_ems: false,
321 done_retry: false,
322 send_tickets: 0,
323 }
324 }
325
326 pub(super) fn with_certified_key(
328 self,
329 mut sig_schemes: Vec<SignatureScheme>,
330 client_hello: &ClientHelloPayload,
331 m: &Message<'_>,
332 cx: &mut ServerContext<'_>,
333 ) -> NextStateOrError<'static> {
334 let tls13_enabled = self
335 .config
336 .supports_version(ProtocolVersion::TLSv1_3);
337 let tls12_enabled = self
338 .config
339 .supports_version(ProtocolVersion::TLSv1_2);
340
341 let maybe_versions_ext = client_hello.versions_extension();
343 let version = if let Some(versions) = maybe_versions_ext {
344 if versions.contains(&ProtocolVersion::TLSv1_3) && tls13_enabled {
345 ProtocolVersion::TLSv1_3
346 } else if !versions.contains(&ProtocolVersion::TLSv1_2) || !tls12_enabled {
347 return Err(cx.common.send_fatal_alert(
348 AlertDescription::ProtocolVersion,
349 PeerIncompatible::Tls12NotOfferedOrEnabled,
350 ));
351 } else if cx.common.is_quic() {
352 return Err(cx.common.send_fatal_alert(
353 AlertDescription::ProtocolVersion,
354 PeerIncompatible::Tls13RequiredForQuic,
355 ));
356 } else {
357 ProtocolVersion::TLSv1_2
358 }
359 } else if u16::from(client_hello.client_version) < u16::from(ProtocolVersion::TLSv1_2) {
360 return Err(cx.common.send_fatal_alert(
361 AlertDescription::ProtocolVersion,
362 PeerIncompatible::Tls12NotOffered,
363 ));
364 } else if !tls12_enabled && tls13_enabled {
365 return Err(cx.common.send_fatal_alert(
366 AlertDescription::ProtocolVersion,
367 PeerIncompatible::SupportedVersionsExtensionRequired,
368 ));
369 } else if cx.common.is_quic() {
370 return Err(cx.common.send_fatal_alert(
371 AlertDescription::ProtocolVersion,
372 PeerIncompatible::Tls13RequiredForQuic,
373 ));
374 } else {
375 ProtocolVersion::TLSv1_2
376 };
377
378 cx.common.negotiated_version = Some(version);
379
380 let client_suites = self
386 .config
387 .provider
388 .cipher_suites
389 .iter()
390 .copied()
391 .filter(|scs| {
392 client_hello
393 .cipher_suites
394 .contains(&scs.suite())
395 })
396 .collect::<Vec<_>>();
397
398 sig_schemes
399 .retain(|scheme| suites::compatible_sigscheme_for_suites(*scheme, &client_suites));
400
401 let certkey = {
403 let client_hello = ClientHello {
404 server_name: &cx.data.sni,
405 signature_schemes: &sig_schemes,
406 alpn: client_hello.alpn_extension(),
407 client_cert_types: client_hello.server_certificate_extension(),
408 server_cert_types: client_hello.client_certificate_extension(),
409 cipher_suites: &client_hello.cipher_suites,
410 };
411 trace!("Resolving server certificate: {client_hello:#?}");
412
413 let certkey = self
414 .config
415 .cert_resolver
416 .resolve(client_hello);
417
418 certkey.ok_or_else(|| {
419 cx.common.send_fatal_alert(
420 AlertDescription::AccessDenied,
421 Error::General("no server certificate chain resolved".to_owned()),
422 )
423 })?
424 };
425 let certkey = ActiveCertifiedKey::from_certified_key(&certkey);
426
427 let (suite, skxg) = self
428 .choose_suite_and_kx_group(
429 version,
430 certkey.get_key().algorithm(),
431 cx.common.protocol,
432 client_hello
433 .namedgroups_extension()
434 .unwrap_or(&[]),
435 &client_hello.cipher_suites,
436 )
437 .map_err(|incompat| {
438 cx.common
439 .send_fatal_alert(AlertDescription::HandshakeFailure, incompat)
440 })?;
441
442 debug!("decided upon suite {:?}", suite);
443 cx.common.suite = Some(suite);
444 cx.common.kx_state = KxState::Start(skxg);
445
446 let starting_hash = suite.hash_provider();
448 let transcript = match self.transcript {
449 HandshakeHashOrBuffer::Buffer(inner) => inner.start_hash(starting_hash),
450 HandshakeHashOrBuffer::Hash(inner)
451 if inner.algorithm() == starting_hash.algorithm() =>
452 {
453 inner
454 }
455 _ => {
456 return Err(cx.common.send_fatal_alert(
457 AlertDescription::IllegalParameter,
458 PeerMisbehaved::HandshakeHashVariedAfterRetry,
459 ));
460 }
461 };
462
463 let randoms = ConnectionRandoms::new(
465 client_hello.random,
466 Random::new(self.config.provider.secure_random)?,
467 );
468 match suite {
469 SupportedCipherSuite::Tls13(suite) => tls13::CompleteClientHelloHandling {
470 config: self.config,
471 transcript,
472 suite,
473 randoms,
474 done_retry: self.done_retry,
475 send_tickets: self.send_tickets,
476 extra_exts: self.extra_exts,
477 }
478 .handle_client_hello(cx, certkey, m, client_hello, skxg, sig_schemes),
479 #[cfg(feature = "tls12")]
480 SupportedCipherSuite::Tls12(suite) => tls12::CompleteClientHelloHandling {
481 config: self.config,
482 transcript,
483 session_id: self.session_id,
484 suite,
485 using_ems: self.using_ems,
486 randoms,
487 send_ticket: self.send_tickets > 0,
488 extra_exts: self.extra_exts,
489 }
490 .handle_client_hello(
491 cx,
492 certkey,
493 m,
494 client_hello,
495 skxg,
496 sig_schemes,
497 tls13_enabled,
498 ),
499 }
500 }
501
502 fn choose_suite_and_kx_group(
503 &self,
504 selected_version: ProtocolVersion,
505 sig_key_algorithm: SignatureAlgorithm,
506 protocol: Protocol,
507 client_groups: &[NamedGroup],
508 client_suites: &[CipherSuite],
509 ) -> Result<(SupportedCipherSuite, &'static dyn SupportedKxGroup), PeerIncompatible> {
510 let mut ecdhe_possible = false;
513 let mut ffdhe_possible = false;
514 let mut ffdhe_offered = false;
515 let mut supported_groups = Vec::with_capacity(client_groups.len());
516
517 for offered_group in client_groups {
518 let supported = self
519 .config
520 .provider
521 .kx_groups
522 .iter()
523 .find(|skxg| {
524 skxg.usable_for_version(selected_version) && skxg.name() == *offered_group
525 });
526
527 match offered_group.key_exchange_algorithm() {
528 KeyExchangeAlgorithm::DHE => {
529 ffdhe_possible |= supported.is_some();
530 ffdhe_offered = true;
531 }
532 KeyExchangeAlgorithm::ECDHE => {
533 ecdhe_possible |= supported.is_some();
534 }
535 }
536
537 supported_groups.push(supported);
538 }
539
540 let first_supported_dhe_kxg = if selected_version == ProtocolVersion::TLSv1_2 {
541 let first_supported_dhe_kxg = self
543 .config
544 .provider
545 .kx_groups
546 .iter()
547 .find(|skxg| skxg.name().key_exchange_algorithm() == KeyExchangeAlgorithm::DHE);
548 ffdhe_possible |= !ffdhe_offered && first_supported_dhe_kxg.is_some();
549 first_supported_dhe_kxg
550 } else {
551 None
553 };
554
555 if !ecdhe_possible && !ffdhe_possible {
556 return Err(PeerIncompatible::NoKxGroupsInCommon);
557 }
558
559 let mut suitable_suites_iter = self
560 .config
561 .provider
562 .cipher_suites
563 .iter()
564 .filter(|suite| {
565 suite.usable_for_signature_algorithm(sig_key_algorithm)
567 && suite.version().version == selected_version
569 && suite.usable_for_protocol(protocol)
571 && (ecdhe_possible && suite.usable_for_kx_algorithm(KeyExchangeAlgorithm::ECDHE)
573 || ffdhe_possible && suite.usable_for_kx_algorithm(KeyExchangeAlgorithm::DHE))
574 });
575
576 let suite = if self.config.ignore_client_order {
583 suitable_suites_iter.find(|suite| client_suites.contains(&suite.suite()))
584 } else {
585 let suitable_suites = suitable_suites_iter.collect::<Vec<_>>();
586 client_suites
587 .iter()
588 .find_map(|client_suite| {
589 suitable_suites
590 .iter()
591 .find(|x| *client_suite == x.suite())
592 })
593 .copied()
594 }
595 .ok_or(PeerIncompatible::NoCipherSuitesInCommon)?;
596
597 let maybe_skxg = supported_groups
600 .iter()
601 .find_map(|maybe_skxg| match maybe_skxg {
602 Some(skxg) => suite
603 .usable_for_kx_algorithm(skxg.name().key_exchange_algorithm())
604 .then_some(*skxg),
605 None => None,
606 });
607
608 if selected_version == ProtocolVersion::TLSv1_3 {
609 return Ok((*suite, *maybe_skxg.unwrap()));
611 }
612
613 match maybe_skxg {
616 Some(skxg) => Ok((*suite, *skxg)),
617 None if suite.usable_for_kx_algorithm(KeyExchangeAlgorithm::DHE) => {
618 if let Some(server_selected_ffdhe_skxg) = first_supported_dhe_kxg {
621 Ok((*suite, *server_selected_ffdhe_skxg))
622 } else {
623 Err(PeerIncompatible::NoKxGroupsInCommon)
624 }
625 }
626 None => Err(PeerIncompatible::NoKxGroupsInCommon),
627 }
628 }
629}
630
631impl State<ServerConnectionData> for ExpectClientHello {
632 fn handle<'m>(
633 self: Box<Self>,
634 cx: &mut ServerContext<'_>,
635 m: Message<'m>,
636 ) -> NextStateOrError<'m>
637 where
638 Self: 'm,
639 {
640 let (client_hello, sig_schemes) = process_client_hello(&m, self.done_retry, cx)?;
641 self.with_certified_key(sig_schemes, client_hello, &m, cx)
642 }
643
644 fn into_owned(self: Box<Self>) -> NextState<'static> {
645 self
646 }
647}
648
649pub(super) fn process_client_hello<'m>(
659 m: &'m Message<'m>,
660 done_retry: bool,
661 cx: &mut ServerContext<'_>,
662) -> Result<(&'m ClientHelloPayload, Vec<SignatureScheme>), Error> {
663 let client_hello =
664 require_handshake_msg!(m, HandshakeType::ClientHello, HandshakePayload::ClientHello)?;
665 trace!("we got a clienthello {:?}", client_hello);
666
667 if !client_hello
668 .compression_methods
669 .contains(&Compression::Null)
670 {
671 return Err(cx.common.send_fatal_alert(
672 AlertDescription::IllegalParameter,
673 PeerIncompatible::NullCompressionRequired,
674 ));
675 }
676
677 if client_hello.has_duplicate_extension() {
678 return Err(cx.common.send_fatal_alert(
679 AlertDescription::DecodeError,
680 PeerMisbehaved::DuplicateClientHelloExtensions,
681 ));
682 }
683
684 cx.common.check_aligned_handshake()?;
686
687 let sni: Option<DnsName<'_>> = match client_hello.sni_extension() {
693 Some(sni) => {
694 if sni.has_duplicate_names_for_type() {
695 return Err(cx.common.send_fatal_alert(
696 AlertDescription::DecodeError,
697 PeerMisbehaved::DuplicateServerNameTypes,
698 ));
699 }
700
701 if let Some(hostname) = sni.single_hostname() {
702 Some(hostname.to_lowercase_owned())
703 } else {
704 return Err(cx.common.send_fatal_alert(
705 AlertDescription::IllegalParameter,
706 PeerMisbehaved::ServerNameMustContainOneHostName,
707 ));
708 }
709 }
710 None => None,
711 };
712
713 if let (Some(sni), false) = (&sni, done_retry) {
715 assert!(cx.data.sni.is_none());
718 cx.data.sni = Some(sni.clone());
719 } else if cx.data.sni != sni {
720 return Err(PeerMisbehaved::ServerNameDifferedOnRetry.into());
721 }
722
723 let sig_schemes = client_hello
724 .sigalgs_extension()
725 .ok_or_else(|| {
726 cx.common.send_fatal_alert(
727 AlertDescription::HandshakeFailure,
728 PeerIncompatible::SignatureAlgorithmsExtensionRequired,
729 )
730 })?;
731
732 Ok((client_hello, sig_schemes.to_owned()))
733}
734
735pub(crate) enum HandshakeHashOrBuffer {
736 Buffer(HandshakeHashBuffer),
737 Hash(HandshakeHash),
738}