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::{KxState, Protocol, State};
12use crate::conn::ConnectionRandoms;
13use crate::crypto::SupportedKxGroup;
14use crate::enums::{
15 AlertDescription, CipherSuite, HandshakeType, ProtocolVersion, SignatureAlgorithm,
16 SignatureScheme,
17};
18use crate::error::{Error, PeerIncompatible, PeerMisbehaved};
19use crate::hash_hs::{HandshakeHash, HandshakeHashBuffer};
20use crate::log::{debug, trace};
21use crate::msgs::enums::{Compression, ExtensionType, NamedGroup};
22#[cfg(feature = "tls12")]
23use crate::msgs::handshake::SessionId;
24use crate::msgs::handshake::{
25 ClientHelloPayload, ConvertProtocolNameList, ConvertServerNameList, HandshakePayload,
26 KeyExchangeAlgorithm, Random, ServerExtension,
27};
28use crate::msgs::message::{Message, MessagePayload};
29use crate::msgs::persist;
30use crate::server::common::ActiveCertifiedKey;
31use crate::server::{tls13, ClientHello, ServerConfig};
32use crate::{suites, SupportedCipherSuite};
33
34pub(super) type NextState<'a> = Box<dyn State<ServerConnectionData> + 'a>;
35pub(super) type NextStateOrError<'a> = Result<NextState<'a>, Error>;
36pub(super) type ServerContext<'a> = crate::common_state::Context<'a, ServerConnectionData>;
37
38pub(super) fn can_resume(
39 suite: SupportedCipherSuite,
40 sni: &Option<DnsName<'_>>,
41 using_ems: bool,
42 resumedata: &persist::ServerSessionValue,
43) -> bool {
44 resumedata.cipher_suite == suite.suite()
52 && (resumedata.extended_ms == using_ems || (resumedata.extended_ms && !using_ems))
53 && &resumedata.sni == sni
54}
55
56#[derive(Default)]
57pub(super) struct ExtensionProcessing {
58 pub(super) exts: Vec<ServerExtension>,
60 #[cfg(feature = "tls12")]
61 pub(super) send_ticket: bool,
62}
63
64impl ExtensionProcessing {
65 pub(super) fn new() -> Self {
66 Default::default()
67 }
68
69 pub(super) fn process_common(
70 &mut self,
71 config: &ServerConfig,
72 cx: &mut ServerContext<'_>,
73 ocsp_response: &mut Option<&[u8]>,
74 hello: &ClientHelloPayload,
75 resumedata: Option<&persist::ServerSessionValue>,
76 extra_exts: Vec<ServerExtension>,
77 ) -> Result<(), Error> {
78 let our_protocols = &config.alpn_protocols;
80 let maybe_their_protocols = hello.alpn_extension();
81 if let Some(their_protocols) = maybe_their_protocols {
82 let their_protocols = their_protocols.to_slices();
83
84 if their_protocols
85 .iter()
86 .any(|protocol| protocol.is_empty())
87 {
88 return Err(PeerMisbehaved::OfferedEmptyApplicationProtocol.into());
89 }
90
91 cx.common.alpn_protocol = our_protocols
92 .iter()
93 .find(|protocol| their_protocols.contains(&protocol.as_slice()))
94 .cloned();
95 if let Some(ref selected_protocol) = cx.common.alpn_protocol {
96 debug!("Chosen ALPN protocol {:?}", selected_protocol);
97 self.exts
98 .push(ServerExtension::make_alpn(&[selected_protocol]));
99 } else if !our_protocols.is_empty() {
100 return Err(cx.common.send_fatal_alert(
101 AlertDescription::NoApplicationProtocol,
102 Error::NoApplicationProtocol,
103 ));
104 }
105 }
106
107 if cx.common.is_quic() {
108 if cx.common.alpn_protocol.is_none()
116 && (!our_protocols.is_empty() || maybe_their_protocols.is_some())
117 {
118 return Err(cx.common.send_fatal_alert(
119 AlertDescription::NoApplicationProtocol,
120 Error::NoApplicationProtocol,
121 ));
122 }
123
124 match hello.quic_params_extension() {
125 Some(params) => cx.common.quic.params = Some(params),
126 None => {
127 return Err(cx
128 .common
129 .missing_extension(PeerMisbehaved::MissingQuicTransportParameters));
130 }
131 }
132 }
133
134 let for_resume = resumedata.is_some();
135 if !for_resume && hello.sni_extension().is_some() {
137 self.exts
138 .push(ServerExtension::ServerNameAck);
139 }
140
141 if !for_resume
145 && hello
146 .find_extension(ExtensionType::StatusRequest)
147 .is_some()
148 {
149 if ocsp_response.is_some() && !cx.common.is_tls13() {
150 self.exts
152 .push(ServerExtension::CertificateStatusAck);
153 }
154 } else {
155 ocsp_response.take();
157 }
158
159 self.exts.extend(extra_exts);
160
161 Ok(())
162 }
163
164 #[cfg(feature = "tls12")]
165 pub(super) fn process_tls12(
166 &mut self,
167 config: &ServerConfig,
168 hello: &ClientHelloPayload,
169 using_ems: bool,
170 ) {
171 let secure_reneg_offered = hello
174 .find_extension(ExtensionType::RenegotiationInfo)
175 .is_some()
176 || hello
177 .cipher_suites
178 .contains(&CipherSuite::TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
179
180 if secure_reneg_offered {
181 self.exts
182 .push(ServerExtension::make_empty_renegotiation_info());
183 }
184
185 if hello
189 .find_extension(ExtensionType::SessionTicket)
190 .is_some()
191 && config.ticketer.enabled()
192 {
193 self.send_ticket = true;
194 self.exts
195 .push(ServerExtension::SessionTicketAck);
196 }
197
198 if using_ems {
200 self.exts
201 .push(ServerExtension::ExtendedMasterSecretAck);
202 }
203 }
204}
205
206pub(super) struct ExpectClientHello {
207 pub(super) config: Arc<ServerConfig>,
208 pub(super) extra_exts: Vec<ServerExtension>,
209 pub(super) transcript: HandshakeHashOrBuffer,
210 #[cfg(feature = "tls12")]
211 pub(super) session_id: SessionId,
212 #[cfg(feature = "tls12")]
213 pub(super) using_ems: bool,
214 pub(super) done_retry: bool,
215 pub(super) send_tickets: usize,
216}
217
218impl ExpectClientHello {
219 pub(super) fn new(config: Arc<ServerConfig>, extra_exts: Vec<ServerExtension>) -> Self {
220 let mut transcript_buffer = HandshakeHashBuffer::new();
221
222 if config.verifier.offer_client_auth() {
223 transcript_buffer.set_client_auth_enabled();
224 }
225
226 Self {
227 config,
228 extra_exts,
229 transcript: HandshakeHashOrBuffer::Buffer(transcript_buffer),
230 #[cfg(feature = "tls12")]
231 session_id: SessionId::empty(),
232 #[cfg(feature = "tls12")]
233 using_ems: false,
234 done_retry: false,
235 send_tickets: 0,
236 }
237 }
238
239 pub(super) fn with_certified_key(
241 self,
242 mut sig_schemes: Vec<SignatureScheme>,
243 client_hello: &ClientHelloPayload,
244 m: &Message<'_>,
245 cx: &mut ServerContext<'_>,
246 ) -> NextStateOrError<'static> {
247 let tls13_enabled = self
248 .config
249 .supports_version(ProtocolVersion::TLSv1_3);
250 let tls12_enabled = self
251 .config
252 .supports_version(ProtocolVersion::TLSv1_2);
253
254 let maybe_versions_ext = client_hello.versions_extension();
256 let version = if let Some(versions) = maybe_versions_ext {
257 if versions.contains(&ProtocolVersion::TLSv1_3) && tls13_enabled {
258 ProtocolVersion::TLSv1_3
259 } else if !versions.contains(&ProtocolVersion::TLSv1_2) || !tls12_enabled {
260 return Err(cx.common.send_fatal_alert(
261 AlertDescription::ProtocolVersion,
262 PeerIncompatible::Tls12NotOfferedOrEnabled,
263 ));
264 } else if cx.common.is_quic() {
265 return Err(cx.common.send_fatal_alert(
266 AlertDescription::ProtocolVersion,
267 PeerIncompatible::Tls13RequiredForQuic,
268 ));
269 } else {
270 ProtocolVersion::TLSv1_2
271 }
272 } else if u16::from(client_hello.client_version) < u16::from(ProtocolVersion::TLSv1_2) {
273 return Err(cx.common.send_fatal_alert(
274 AlertDescription::ProtocolVersion,
275 PeerIncompatible::Tls12NotOffered,
276 ));
277 } else if !tls12_enabled && tls13_enabled {
278 return Err(cx.common.send_fatal_alert(
279 AlertDescription::ProtocolVersion,
280 PeerIncompatible::SupportedVersionsExtensionRequired,
281 ));
282 } else if cx.common.is_quic() {
283 return Err(cx.common.send_fatal_alert(
284 AlertDescription::ProtocolVersion,
285 PeerIncompatible::Tls13RequiredForQuic,
286 ));
287 } else {
288 ProtocolVersion::TLSv1_2
289 };
290
291 cx.common.negotiated_version = Some(version);
292
293 let client_suites = self
299 .config
300 .provider
301 .cipher_suites
302 .iter()
303 .copied()
304 .filter(|scs| {
305 client_hello
306 .cipher_suites
307 .contains(&scs.suite())
308 })
309 .collect::<Vec<_>>();
310
311 sig_schemes
312 .retain(|scheme| suites::compatible_sigscheme_for_suites(*scheme, &client_suites));
313
314 let certkey = {
316 let client_hello = ClientHello::new(
317 &cx.data.sni,
318 &sig_schemes,
319 client_hello.alpn_extension(),
320 &client_hello.cipher_suites,
321 );
322
323 let certkey = self
324 .config
325 .cert_resolver
326 .resolve(client_hello);
327
328 certkey.ok_or_else(|| {
329 cx.common.send_fatal_alert(
330 AlertDescription::AccessDenied,
331 Error::General("no server certificate chain resolved".to_owned()),
332 )
333 })?
334 };
335 let certkey = ActiveCertifiedKey::from_certified_key(&certkey);
336
337 let (suite, skxg) = self
338 .choose_suite_and_kx_group(
339 version,
340 certkey.get_key().algorithm(),
341 cx.common.protocol,
342 client_hello
343 .namedgroups_extension()
344 .unwrap_or(&[]),
345 &client_hello.cipher_suites,
346 )
347 .map_err(|incompat| {
348 cx.common
349 .send_fatal_alert(AlertDescription::HandshakeFailure, incompat)
350 })?;
351
352 debug!("decided upon suite {:?}", suite);
353 cx.common.suite = Some(suite);
354 cx.common.kx_state = KxState::Start(skxg);
355
356 let starting_hash = suite.hash_provider();
358 let transcript = match self.transcript {
359 HandshakeHashOrBuffer::Buffer(inner) => inner.start_hash(starting_hash),
360 HandshakeHashOrBuffer::Hash(inner)
361 if inner.algorithm() == starting_hash.algorithm() =>
362 {
363 inner
364 }
365 _ => {
366 return Err(cx.common.send_fatal_alert(
367 AlertDescription::IllegalParameter,
368 PeerMisbehaved::HandshakeHashVariedAfterRetry,
369 ));
370 }
371 };
372
373 let randoms = ConnectionRandoms::new(
375 client_hello.random,
376 Random::new(self.config.provider.secure_random)?,
377 );
378 match suite {
379 SupportedCipherSuite::Tls13(suite) => tls13::CompleteClientHelloHandling {
380 config: self.config,
381 transcript,
382 suite,
383 randoms,
384 done_retry: self.done_retry,
385 send_tickets: self.send_tickets,
386 extra_exts: self.extra_exts,
387 }
388 .handle_client_hello(cx, certkey, m, client_hello, skxg, sig_schemes),
389 #[cfg(feature = "tls12")]
390 SupportedCipherSuite::Tls12(suite) => tls12::CompleteClientHelloHandling {
391 config: self.config,
392 transcript,
393 session_id: self.session_id,
394 suite,
395 using_ems: self.using_ems,
396 randoms,
397 send_ticket: self.send_tickets > 0,
398 extra_exts: self.extra_exts,
399 }
400 .handle_client_hello(
401 cx,
402 certkey,
403 m,
404 client_hello,
405 skxg,
406 sig_schemes,
407 tls13_enabled,
408 ),
409 }
410 }
411
412 fn choose_suite_and_kx_group(
413 &self,
414 selected_version: ProtocolVersion,
415 sig_key_algorithm: SignatureAlgorithm,
416 protocol: Protocol,
417 client_groups: &[NamedGroup],
418 client_suites: &[CipherSuite],
419 ) -> Result<(SupportedCipherSuite, &'static dyn SupportedKxGroup), PeerIncompatible> {
420 let mut ecdhe_possible = false;
423 let mut ffdhe_possible = false;
424 let mut ffdhe_offered = false;
425 let mut supported_groups = Vec::with_capacity(client_groups.len());
426
427 for offered_group in client_groups {
428 let supported = self
429 .config
430 .provider
431 .kx_groups
432 .iter()
433 .find(|skxg| skxg.name() == *offered_group);
434
435 match offered_group.key_exchange_algorithm() {
436 KeyExchangeAlgorithm::DHE => {
437 ffdhe_possible |= supported.is_some();
438 ffdhe_offered = true;
439 }
440 KeyExchangeAlgorithm::ECDHE => {
441 ecdhe_possible |= supported.is_some();
442 }
443 }
444
445 supported_groups.push(supported);
446 }
447
448 let first_supported_dhe_kxg = if selected_version == ProtocolVersion::TLSv1_2 {
449 let first_supported_dhe_kxg = self
451 .config
452 .provider
453 .kx_groups
454 .iter()
455 .find(|skxg| skxg.name().key_exchange_algorithm() == KeyExchangeAlgorithm::DHE);
456 ffdhe_possible |= !ffdhe_offered && first_supported_dhe_kxg.is_some();
457 first_supported_dhe_kxg
458 } else {
459 None
461 };
462
463 if !ecdhe_possible && !ffdhe_possible {
464 return Err(PeerIncompatible::NoKxGroupsInCommon);
465 }
466
467 let mut suitable_suites_iter = self
468 .config
469 .provider
470 .cipher_suites
471 .iter()
472 .filter(|suite| {
473 suite.usable_for_signature_algorithm(sig_key_algorithm)
475 && suite.version().version == selected_version
477 && suite.usable_for_protocol(protocol)
479 && (ecdhe_possible && suite.usable_for_kx_algorithm(KeyExchangeAlgorithm::ECDHE)
481 || ffdhe_possible && suite.usable_for_kx_algorithm(KeyExchangeAlgorithm::DHE))
482 });
483
484 let suite = if self.config.ignore_client_order {
491 suitable_suites_iter.find(|suite| client_suites.contains(&suite.suite()))
492 } else {
493 let suitable_suites = suitable_suites_iter.collect::<Vec<_>>();
494 client_suites
495 .iter()
496 .find_map(|client_suite| {
497 suitable_suites
498 .iter()
499 .find(|x| *client_suite == x.suite())
500 })
501 .copied()
502 }
503 .ok_or(PeerIncompatible::NoCipherSuitesInCommon)?;
504
505 let maybe_skxg = supported_groups
508 .iter()
509 .find_map(|maybe_skxg| match maybe_skxg {
510 Some(skxg) => suite
511 .usable_for_kx_algorithm(skxg.name().key_exchange_algorithm())
512 .then_some(*skxg),
513 None => None,
514 });
515
516 if selected_version == ProtocolVersion::TLSv1_3 {
517 return Ok((*suite, *maybe_skxg.unwrap()));
519 }
520
521 match maybe_skxg {
524 Some(skxg) => Ok((*suite, *skxg)),
525 None if suite.usable_for_kx_algorithm(KeyExchangeAlgorithm::DHE) => {
526 if let Some(server_selected_ffdhe_skxg) = first_supported_dhe_kxg {
529 Ok((*suite, *server_selected_ffdhe_skxg))
530 } else {
531 Err(PeerIncompatible::NoKxGroupsInCommon)
532 }
533 }
534 None => Err(PeerIncompatible::NoKxGroupsInCommon),
535 }
536 }
537}
538
539impl State<ServerConnectionData> for ExpectClientHello {
540 fn handle<'m>(
541 self: Box<Self>,
542 cx: &mut ServerContext<'_>,
543 m: Message<'m>,
544 ) -> NextStateOrError<'m>
545 where
546 Self: 'm,
547 {
548 let (client_hello, sig_schemes) = process_client_hello(&m, self.done_retry, cx)?;
549 self.with_certified_key(sig_schemes, client_hello, &m, cx)
550 }
551
552 fn into_owned(self: Box<Self>) -> NextState<'static> {
553 self
554 }
555}
556
557pub(super) fn process_client_hello<'m>(
567 m: &'m Message<'m>,
568 done_retry: bool,
569 cx: &mut ServerContext<'_>,
570) -> Result<(&'m ClientHelloPayload, Vec<SignatureScheme>), Error> {
571 let client_hello =
572 require_handshake_msg!(m, HandshakeType::ClientHello, HandshakePayload::ClientHello)?;
573 trace!("we got a clienthello {:?}", client_hello);
574
575 if !client_hello
576 .compression_methods
577 .contains(&Compression::Null)
578 {
579 return Err(cx.common.send_fatal_alert(
580 AlertDescription::IllegalParameter,
581 PeerIncompatible::NullCompressionRequired,
582 ));
583 }
584
585 if client_hello.has_duplicate_extension() {
586 return Err(cx.common.send_fatal_alert(
587 AlertDescription::DecodeError,
588 PeerMisbehaved::DuplicateClientHelloExtensions,
589 ));
590 }
591
592 cx.common.check_aligned_handshake()?;
594
595 let sni: Option<DnsName<'_>> = match client_hello.sni_extension() {
601 Some(sni) => {
602 if sni.has_duplicate_names_for_type() {
603 return Err(cx.common.send_fatal_alert(
604 AlertDescription::DecodeError,
605 PeerMisbehaved::DuplicateServerNameTypes,
606 ));
607 }
608
609 if let Some(hostname) = sni.single_hostname() {
610 Some(hostname.to_lowercase_owned())
611 } else {
612 return Err(cx.common.send_fatal_alert(
613 AlertDescription::IllegalParameter,
614 PeerMisbehaved::ServerNameMustContainOneHostName,
615 ));
616 }
617 }
618 None => None,
619 };
620
621 if let (Some(sni), false) = (&sni, done_retry) {
623 assert!(cx.data.sni.is_none());
626 cx.data.sni = Some(sni.clone());
627 } else if cx.data.sni != sni {
628 return Err(PeerMisbehaved::ServerNameDifferedOnRetry.into());
629 }
630
631 let sig_schemes = client_hello
632 .sigalgs_extension()
633 .ok_or_else(|| {
634 cx.common.send_fatal_alert(
635 AlertDescription::HandshakeFailure,
636 PeerIncompatible::SignatureAlgorithmsExtensionRequired,
637 )
638 })?;
639
640 Ok((client_hello, sig_schemes.to_owned()))
641}
642
643pub(crate) enum HandshakeHashOrBuffer {
644 Buffer(HandshakeHashBuffer),
645 Hash(HandshakeHash),
646}