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::{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    // 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.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) if and only if 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.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.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<'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        // Are we doing TLS1.3?
255        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        // 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.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        // Start handshake hash.
357        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        // Save their Random.
374        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        // Determine which `KeyExchangeAlgorithm`s are theoretically possible, based
421        // on the offered and supported groups.
422        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            // https://datatracker.ietf.org/doc/html/rfc7919#section-4 (paragraph 2)
450            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            // In TLS1.3, the server may only directly negotiate a group.
460            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                // Reduce our supported ciphersuites by the certified key's algorithm.
474                suite.usable_for_signature_algorithm(sig_key_algorithm)
475                // And version
476                && suite.version().version == selected_version
477                // And protocol
478                && suite.usable_for_protocol(protocol)
479                // And support one of key exchange groups
480                && (ecdhe_possible && suite.usable_for_kx_algorithm(KeyExchangeAlgorithm::ECDHE)
481                || ffdhe_possible && suite.usable_for_kx_algorithm(KeyExchangeAlgorithm::DHE))
482            });
483
484        // RFC 7919 (https://datatracker.ietf.org/doc/html/rfc7919#section-4) requires us to send
485        // the InsufficientSecurity alert in case we don't recognize client's FFDHE groups (i.e.,
486        // `suitable_suites` becomes empty). But that does not make a lot of sense (e.g., client
487        // proposes FFDHE4096 and we only support FFDHE2048), so we ignore that requirement here,
488        // and continue to send HandshakeFailure.
489
490        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        // Finally, choose a key exchange group that is compatible with the selected cipher
506        // suite.
507        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            // This unwrap is structurally guaranteed by the early return for `!ffdhe_possible && !ecdhe_possible`
518            return Ok((*suite, *maybe_skxg.unwrap()));
519        }
520
521        // For TLS1.2, the server can unilaterally choose a DHE group if it has one and
522        // there was no better option.
523        match maybe_skxg {
524            Some(skxg) => Ok((*suite, *skxg)),
525            None if suite.usable_for_kx_algorithm(KeyExchangeAlgorithm::DHE) => {
526                // If kx for the selected cipher suite is DHE and no DHE groups are specified in the extension,
527                // the server is free to choose DHE params, we choose the first DHE kx group of the provider.
528                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
557/// Configuration-independent validation of a `ClientHello` message.
558///
559/// This represents the first part of the `ClientHello` handling, where we do all validation that
560/// doesn't depend on a `ServerConfig` being available and extract everything needed to build a
561/// [`ClientHello`] value for a [`ResolvesServerCert`].
562///
563/// Note that this will modify `data.sni` even if config or certificate resolution fail.
564///
565/// [`ResolvesServerCert`]: crate::server::ResolvesServerCert
566pub(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    // No handshake messages should follow this one in this flight.
593    cx.common.check_aligned_handshake()?;
594
595    // Extract and validate the SNI DNS name, if any, before giving it to
596    // the cert resolver. In particular, if it is invalid then we should
597    // send an Illegal Parameter alert instead of the Internal Error alert
598    // (or whatever) that we'd send if this were checked later or in a
599    // different way.
600    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    // save only the first SNI
622    if let (Some(sni), false) = (&sni, done_retry) {
623        // Save the SNI into the session.
624        // The SNI hostname is immutable once set.
625        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}