rustls/server/
hs.rs

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    // The RFCs underspecify what happens if we try to resume to
47    // an unoffered/varying suite.  We merely don't resume in weird cases.
48    //
49    // RFC 6066 says "A server that implements this extension MUST NOT accept
50    // the request to resume the session if the server_name extension contains
51    // a different name. Instead, it proceeds with a full handshake to
52    // establish a new session."
53    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    // extensions to reply with
61    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        // ALPN
81        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            // QUIC has strict ALPN, unlike TLS's more backwards-compatible behavior. RFC 9001
111            // says: "The server MUST treat the inability to select a compatible application
112            // protocol as a connection error of type 0x0178". We judge that ALPN was desired
113            // (rather than some out-of-band protocol negotiation mechanism) if and only if any ALPN
114            // protocols were configured locally or offered by the client. This helps prevent
115            // successful establishment of connections between peers that can't understand
116            // each other.
117            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        // SNI
138        if !for_resume && hello.sni_extension().is_some() {
139            self.exts
140                .push(ServerExtension::ServerNameAck);
141        }
142
143        // Send status_request response if we have one.  This is not allowed
144        // if we're resuming, and is only triggered if we have an OCSP response
145        // to send.
146        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                // Only TLS1.2 sends confirmation in ServerHello
153                self.exts
154                    .push(ServerExtension::CertificateStatusAck);
155            }
156        } else {
157            // Throw away any OCSP response so we don't try to send it later.
158            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        // Renegotiation.
177        // (We don't do reneg at all, but would support the secure version if we did.)
178        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        // Tickets:
191        // If we get any SessionTicket extension and have tickets enabled,
192        // we send an ack.
193        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        // Confirm use of EMS if offered.
204        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    /// Continues handling of a `ClientHello` message once config and certificate are available.
327    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        // Are we doing TLS1.3?
342        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        // We communicate to the upper layer what kind of key they should choose
381        // via the sigschemes value.  Clients tend to treat this extension
382        // orthogonally to offered ciphersuites (even though, in TLS1.2 it is not).
383        // So: reduce the offered sigschemes to those compatible with the
384        // intersection of ciphersuites.
385        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        // Choose a certificate.
402        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        // Start handshake hash.
447        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        // Save their Random.
464        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        // Determine which `KeyExchangeAlgorithm`s are theoretically possible, based
511        // on the offered and supported groups.
512        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            // https://datatracker.ietf.org/doc/html/rfc7919#section-4 (paragraph 2)
542            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            // In TLS1.3, the server may only directly negotiate a group.
552            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                // Reduce our supported ciphersuites by the certified key's algorithm.
566                suite.usable_for_signature_algorithm(sig_key_algorithm)
567                // And version
568                && suite.version().version == selected_version
569                // And protocol
570                && suite.usable_for_protocol(protocol)
571                // And support one of key exchange groups
572                && (ecdhe_possible && suite.usable_for_kx_algorithm(KeyExchangeAlgorithm::ECDHE)
573                || ffdhe_possible && suite.usable_for_kx_algorithm(KeyExchangeAlgorithm::DHE))
574            });
575
576        // RFC 7919 (https://datatracker.ietf.org/doc/html/rfc7919#section-4) requires us to send
577        // the InsufficientSecurity alert in case we don't recognize client's FFDHE groups (i.e.,
578        // `suitable_suites` becomes empty). But that does not make a lot of sense (e.g., client
579        // proposes FFDHE4096 and we only support FFDHE2048), so we ignore that requirement here,
580        // and continue to send HandshakeFailure.
581
582        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        // Finally, choose a key exchange group that is compatible with the selected cipher
598        // suite.
599        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            // This unwrap is structurally guaranteed by the early return for `!ffdhe_possible && !ecdhe_possible`
610            return Ok((*suite, *maybe_skxg.unwrap()));
611        }
612
613        // For TLS1.2, the server can unilaterally choose a DHE group if it has one and
614        // there was no better option.
615        match maybe_skxg {
616            Some(skxg) => Ok((*suite, *skxg)),
617            None if suite.usable_for_kx_algorithm(KeyExchangeAlgorithm::DHE) => {
618                // If kx for the selected cipher suite is DHE and no DHE groups are specified in the extension,
619                // the server is free to choose DHE params, we choose the first DHE kx group of the provider.
620                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
649/// Configuration-independent validation of a `ClientHello` message.
650///
651/// This represents the first part of the `ClientHello` handling, where we do all validation that
652/// doesn't depend on a `ServerConfig` being available and extract everything needed to build a
653/// [`ClientHello`] value for a [`ResolvesServerCert`].
654///
655/// Note that this will modify `data.sni` even if config or certificate resolution fail.
656///
657/// [`ResolvesServerCert`]: crate::server::ResolvesServerCert
658pub(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    // No handshake messages should follow this one in this flight.
685    cx.common.check_aligned_handshake()?;
686
687    // Extract and validate the SNI DNS name, if any, before giving it to
688    // the cert resolver. In particular, if it is invalid then we should
689    // send an Illegal Parameter alert instead of the Internal Error alert
690    // (or whatever) that we'd send if this were checked later or in a
691    // different way.
692    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    // save only the first SNI
714    if let (Some(sni), false) = (&sni, done_retry) {
715        // Save the SNI into the session.
716        // The SNI hostname is immutable once set.
717        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}