1use crate::common_state::State;
2use crate::conn::ConnectionRandoms;
3#[cfg(feature = "tls12")]
4use crate::enums::CipherSuite;
5use crate::enums::{AlertDescription, HandshakeType, ProtocolVersion, SignatureScheme};
6use crate::error::{Error, PeerIncompatible, PeerMisbehaved};
7use crate::hash_hs::{HandshakeHash, HandshakeHashBuffer};
8#[cfg(feature = "logging")]
9use crate::log::{debug, trace};
10use crate::msgs::enums::{Compression, ExtensionType};
11#[cfg(feature = "tls12")]
12use crate::msgs::handshake::SessionId;
13use crate::msgs::handshake::{ClientHelloPayload, Random, ServerExtension};
14use crate::msgs::handshake::{ConvertProtocolNameList, ConvertServerNameList, HandshakePayload};
15use crate::msgs::message::{Message, MessagePayload};
16use crate::msgs::persist;
17use crate::server::{ClientHello, ServerConfig};
18use crate::suites;
19use crate::SupportedCipherSuite;
20
21use super::server_conn::ServerConnectionData;
22#[cfg(feature = "tls12")]
23use super::tls12;
24use crate::server::common::ActiveCertifiedKey;
25use crate::server::tls13;
26
27use pki_types::DnsName;
28
29use alloc::borrow::ToOwned;
30use alloc::boxed::Box;
31use alloc::sync::Arc;
32use alloc::vec::Vec;
33
34pub(super) type NextState = Box<dyn State<ServerConnectionData>>;
35pub(super) type NextStateOrError = Result<NextState, 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 // The RFCs underspecify what happens if we try to resume to
45 // an unoffered/varying suite. We merely don't resume in weird cases.
46 //
47 // RFC 6066 says "A server that implements this extension MUST NOT accept
48 // the request to resume the session if the server_name extension contains
49 // a different name. Instead, it proceeds with a full handshake to
50 // establish a new session."
51 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 // extensions to reply with
59 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 // ALPN
79 let our_protocols = &config.alpn_protocols;
80 let maybe_their_protocols = hello.get_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 // QUIC has strict ALPN, unlike TLS's more backwards-compatible behavior. RFC 9001
109 // says: "The server MUST treat the inability to select a compatible application
110 // protocol as a connection error of type 0x0178". We judge that ALPN was desired
111 // (rather than some out-of-band protocol negotiation mechanism) iff any ALPN
112 // protocols were configured locally or offered by the client. This helps prevent
113 // successful establishment of connections between peers that can't understand
114 // each other.
115 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.get_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 // SNI
136 if !for_resume && hello.get_sni_extension().is_some() {
137 self.exts
138 .push(ServerExtension::ServerNameAck);
139 }
140
141 // Send status_request response if we have one. This is not allowed
142 // if we're resuming, and is only triggered if we have an OCSP response
143 // to send.
144 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 // Only TLS1.2 sends confirmation in ServerHello
151 self.exts
152 .push(ServerExtension::CertificateStatusAck);
153 }
154 } else {
155 // Throw away any OCSP response so we don't try to send it later.
156 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 // Renegotiation.
172 // (We don't do reneg at all, but would support the secure version if we did.)
173 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 // Tickets:
186 // If we get any SessionTicket extension and have tickets enabled,
187 // we send an ack.
188 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 // Confirm use of EMS if offered.
199 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 /// Continues handling of a `ClientHello` message once config and certificate are available.
240 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 {
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 // Are we doing TLS1.3?
255 let maybe_versions_ext = client_hello.get_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 client_hello.client_version.get_u16() < ProtocolVersion::TLSv1_2.get_u16() {
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 // We communicate to the upper layer what kind of key they should choose
294 // via the sigschemes value. Clients tend to treat this extension
295 // orthogonally to offered ciphersuites (even though, in TLS1.2 it is not).
296 // So: reduce the offered sigschemes to those compatible with the
297 // intersection of ciphersuites.
298 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 // Choose a certificate.
315 let certkey = {
316 let client_hello = ClientHello::new(
317 &cx.data.sni,
318 &sig_schemes,
319 client_hello.get_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 // Reduce our supported ciphersuites by the certificate.
338 // (no-op for TLS1.3)
339 let suitable_suites = suites::reduce_given_sigalg(
340 &self.config.provider.cipher_suites,
341 certkey.get_key().algorithm(),
342 );
343
344 // And version
345 let suitable_suites = suites::reduce_given_version_and_protocol(
346 &suitable_suites,
347 version,
348 cx.common.protocol,
349 );
350
351 let suite = if self.config.ignore_client_order {
352 suites::choose_ciphersuite_preferring_server(
353 &client_hello.cipher_suites,
354 &suitable_suites,
355 )
356 } else {
357 suites::choose_ciphersuite_preferring_client(
358 &client_hello.cipher_suites,
359 &suitable_suites,
360 )
361 }
362 .ok_or_else(|| {
363 cx.common.send_fatal_alert(
364 AlertDescription::HandshakeFailure,
365 PeerIncompatible::NoCipherSuitesInCommon,
366 )
367 })?;
368
369 debug!("decided upon suite {:?}", suite);
370 cx.common.suite = Some(suite);
371
372 // Start handshake hash.
373 let starting_hash = suite.hash_provider();
374 let transcript = match self.transcript {
375 HandshakeHashOrBuffer::Buffer(inner) => inner.start_hash(starting_hash),
376 HandshakeHashOrBuffer::Hash(inner)
377 if inner.algorithm() == starting_hash.algorithm() =>
378 {
379 inner
380 }
381 _ => {
382 return Err(cx.common.send_fatal_alert(
383 AlertDescription::IllegalParameter,
384 PeerMisbehaved::HandshakeHashVariedAfterRetry,
385 ));
386 }
387 };
388
389 // Save their Random.
390 let randoms = ConnectionRandoms::new(
391 client_hello.random,
392 Random::new(self.config.provider.secure_random)?,
393 );
394 match suite {
395 SupportedCipherSuite::Tls13(suite) => tls13::CompleteClientHelloHandling {
396 config: self.config,
397 transcript,
398 suite,
399 randoms,
400 done_retry: self.done_retry,
401 send_tickets: self.send_tickets,
402 extra_exts: self.extra_exts,
403 }
404 .handle_client_hello(cx, certkey, m, client_hello, sig_schemes),
405 #[cfg(feature = "tls12")]
406 SupportedCipherSuite::Tls12(suite) => tls12::CompleteClientHelloHandling {
407 config: self.config,
408 transcript,
409 session_id: self.session_id,
410 suite,
411 using_ems: self.using_ems,
412 randoms,
413 send_ticket: self.send_tickets > 0,
414 extra_exts: self.extra_exts,
415 }
416 .handle_client_hello(
417 cx,
418 certkey,
419 m,
420 client_hello,
421 sig_schemes,
422 tls13_enabled,
423 ),
424 }
425 }
426}
427
428impl State<ServerConnectionData> for ExpectClientHello {
429 fn handle(self: Box<Self>, cx: &mut ServerContext<'_>, m: Message) -> NextStateOrError {
430 let (client_hello: &ClientHelloPayload, sig_schemes: Vec) = process_client_hello(&m, self.done_retry, cx)?;
431 self.with_certified_key(sig_schemes, client_hello, &m, cx)
432 }
433}
434
435/// Configuration-independent validation of a `ClientHello` message.
436///
437/// This represents the first part of the `ClientHello` handling, where we do all validation that
438/// doesn't depend on a `ServerConfig` being available and extract everything needed to build a
439/// [`ClientHello`] value for a [`ResolvesServerCert`].
440///
441/// Note that this will modify `data.sni` even if config or certificate resolution fail.
442///
443/// [`ResolvesServerCert`]: crate::server::ResolvesServerCert
444pub(super) fn process_client_hello<'a>(
445 m: &'a Message,
446 done_retry: bool,
447 cx: &mut ServerContext,
448) -> Result<(&'a ClientHelloPayload, Vec<SignatureScheme>), Error> {
449 let client_hello =
450 require_handshake_msg!(m, HandshakeType::ClientHello, HandshakePayload::ClientHello)?;
451 trace!("we got a clienthello {:?}", client_hello);
452
453 if !client_hello
454 .compression_methods
455 .contains(&Compression::Null)
456 {
457 return Err(cx.common.send_fatal_alert(
458 AlertDescription::IllegalParameter,
459 PeerIncompatible::NullCompressionRequired,
460 ));
461 }
462
463 if client_hello.has_duplicate_extension() {
464 return Err(cx.common.send_fatal_alert(
465 AlertDescription::DecodeError,
466 PeerMisbehaved::DuplicateClientHelloExtensions,
467 ));
468 }
469
470 // No handshake messages should follow this one in this flight.
471 cx.common.check_aligned_handshake()?;
472
473 // Extract and validate the SNI DNS name, if any, before giving it to
474 // the cert resolver. In particular, if it is invalid then we should
475 // send an Illegal Parameter alert instead of the Internal Error alert
476 // (or whatever) that we'd send if this were checked later or in a
477 // different way.
478 let sni: Option<DnsName> = match client_hello.get_sni_extension() {
479 Some(sni) => {
480 if sni.has_duplicate_names_for_type() {
481 return Err(cx.common.send_fatal_alert(
482 AlertDescription::DecodeError,
483 PeerMisbehaved::DuplicateServerNameTypes,
484 ));
485 }
486
487 if let Some(hostname) = sni.get_single_hostname() {
488 Some(hostname.to_lowercase_owned())
489 } else {
490 return Err(cx.common.send_fatal_alert(
491 AlertDescription::IllegalParameter,
492 PeerMisbehaved::ServerNameMustContainOneHostName,
493 ));
494 }
495 }
496 None => None,
497 };
498
499 // save only the first SNI
500 if let (Some(sni), false) = (&sni, done_retry) {
501 // Save the SNI into the session.
502 // The SNI hostname is immutable once set.
503 assert!(cx.data.sni.is_none());
504 cx.data.sni = Some(sni.clone());
505 } else if cx.data.sni != sni {
506 return Err(PeerMisbehaved::ServerNameDifferedOnRetry.into());
507 }
508
509 let sig_schemes = client_hello
510 .get_sigalgs_extension()
511 .ok_or_else(|| {
512 cx.common.send_fatal_alert(
513 AlertDescription::HandshakeFailure,
514 PeerIncompatible::SignatureAlgorithmsExtensionRequired,
515 )
516 })?;
517
518 Ok((client_hello, sig_schemes.to_owned()))
519}
520
521#[allow(clippy::large_enum_variant)]
522pub(crate) enum HandshakeHashOrBuffer {
523 Buffer(HandshakeHashBuffer),
524 Hash(HandshakeHash),
525}
526