Skip to main content

rustls/
common_state.rs

1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::fmt;
4use core::ops::{Deref, DerefMut, Range};
5
6use pki_types::{DnsName, FipsStatus};
7
8use crate::client::EchStatus;
9use crate::conn::Exporter;
10use crate::conn::kernel::KernelState;
11use crate::crypto::Identity;
12use crate::crypto::cipher::{
13    DecryptionState, EncodedMessage, EncryptionState, MessageDecrypter, MessageEncrypter,
14    OutboundOpaque, OutboundPlain, Payload, PreEncryptAction,
15};
16use crate::crypto::kx::SupportedKxGroup;
17use crate::crypto::tls13::OkmBlock;
18use crate::enums::{ApplicationProtocol, ContentType, HandshakeType, ProtocolVersion};
19use crate::error::{AlertDescription, ApiMisuse, Error, PeerMisbehaved};
20use crate::hash_hs::HandshakeHash;
21use crate::log::{debug, error, trace, warn};
22use crate::msgs::{
23    AlertLevel, AlertMessagePayload, Codec, Delocator, HandshakeAlignedProof,
24    HandshakeMessagePayload, Locator, Message, MessageFragmenter, MessagePayload,
25};
26use crate::suites::{PartiallyExtractedSecrets, SupportedCipherSuite};
27use crate::tls13::key_schedule::KeyScheduleTrafficSend;
28use crate::unbuffered::{EncryptError, InsufficientSizeError};
29use crate::vecbuf::ChunkVecBuffer;
30use crate::{SideData, quic};
31
32pub(crate) fn process_main_protocol<Data: SideData>(
33    msg: EncodedMessage<&'_ [u8]>,
34    aligned_handshake: Option<HandshakeAlignedProof>,
35    state: Box<dyn State<Data>>,
36    plaintext_locator: &Locator,
37    received_plaintext: &mut Option<UnborrowedPayload>,
38    data: &mut Data,
39) -> Result<Box<dyn State<Data>>, Error> {
40    // Drop CCS messages during handshake in TLS1.3
41    if msg.typ == ContentType::ChangeCipherSpec && data.recv.drop_tls13_ccs(&msg)? {
42        trace!("Dropping CCS");
43        return Ok(state);
44    }
45
46    let msg = data.parse_and_maybe_drop(&msg)?;
47
48    let Some(msg) = msg else {
49        // Message is dropped.
50        return Ok(state);
51    };
52
53    let mut cx = CaptureAppData {
54        data,
55        plaintext_locator,
56        received_plaintext,
57    };
58
59    state.handle(
60        Input {
61            message: msg,
62            aligned_handshake,
63        },
64        &mut cx,
65    )
66}
67
68/// Connection state common to both client and server connections.
69pub struct CommonState {
70    pub(crate) outputs: ConnectionOutputs,
71    pub(crate) send: SendPath,
72    pub(crate) recv: ReceivePath,
73    pub(crate) quic: quic::Quic,
74
75    /// Protocol whose key schedule should be used. Unused for TLS < 1.3.
76    protocol: Protocol,
77}
78
79impl CommonState {
80    pub(crate) fn new(side: Side, protocol: Protocol) -> Self {
81        Self {
82            outputs: ConnectionOutputs::default(),
83            send: SendPath::default(),
84            recv: ReceivePath::new(side),
85            quic: quic::Quic::default(),
86            protocol,
87        }
88    }
89
90    /// Returns true if the caller should call [`Connection::write_tls`] as soon as possible.
91    ///
92    /// [`Connection::write_tls`]: crate::Connection::write_tls
93    pub fn wants_write(&self) -> bool {
94        !self.send.sendable_tls.is_empty()
95    }
96
97    /// Queues a `close_notify` warning alert to be sent in the next
98    /// [`Connection::write_tls`] call.  This informs the peer that the
99    /// connection is being closed.
100    ///
101    /// Does nothing if any `close_notify` or fatal alert was already sent.
102    ///
103    /// [`Connection::write_tls`]: crate::Connection::write_tls
104    pub fn send_close_notify(&mut self) {
105        self.send.send_close_notify()
106    }
107
108    /// Returns true if the connection is currently performing the TLS handshake.
109    ///
110    /// During this time plaintext written to the connection is buffered in memory. After
111    /// [`Connection::process_new_packets()`] has been called, this might start to return `false`
112    /// while the final handshake packets still need to be extracted from the connection's buffers.
113    ///
114    /// [`Connection::process_new_packets()`]: crate::Connection::process_new_packets
115    pub fn is_handshaking(&self) -> bool {
116        !(self.send.may_send_application_data && self.recv.may_receive_application_data)
117    }
118
119    /// Returns true if the caller should call [`Connection::read_tls`] as soon
120    /// as possible.
121    ///
122    /// If there is pending plaintext data to read with [`Connection::reader`],
123    /// this returns false.  If your application respects this mechanism,
124    /// only one full TLS message will be buffered by rustls.
125    ///
126    /// [`Connection::reader`]: crate::Connection::reader
127    /// [`Connection::read_tls`]: crate::Connection::read_tls
128    pub fn wants_read(&self) -> bool {
129        // We want to read more data all the time, except when we have unprocessed plaintext.
130        // This provides back-pressure to the TCP buffers. We also don't want to read more after
131        // the peer has sent us a close notification.
132        //
133        // In the handshake case we don't have readable plaintext before the handshake has
134        // completed, but also don't want to read if we still have sendable tls.
135        self.recv.received_plaintext.is_empty()
136            && !self.recv.has_received_close_notify
137            && (self.send.may_send_application_data || self.send.sendable_tls.is_empty())
138    }
139
140    pub(crate) fn current_io_state(&self) -> IoState {
141        IoState {
142            tls_bytes_to_write: self.send.sendable_tls.len(),
143            plaintext_bytes_to_read: self.recv.received_plaintext.len(),
144            peer_has_closed: self.recv.has_received_close_notify,
145        }
146    }
147
148    fn parse_and_maybe_drop<'a>(
149        &mut self,
150        msg: &'a EncodedMessage<&'a [u8]>,
151    ) -> Result<Option<Message<'a>>, Error> {
152        // Now we can fully parse the message payload.
153        let msg = Message::try_from(msg)?;
154
155        // For alerts, we have separate logic.
156        if let MessagePayload::Alert(alert) = &msg.payload {
157            self.recv.process_alert(alert)?;
158            return Ok(None);
159        }
160
161        // For TLS1.2, outside of the handshake, send rejection alerts for
162        // renegotiation requests.  These can occur any time.
163        if self
164            .recv
165            .reject_renegotiation_request(&mut self.send, &msg)?
166        {
167            return Ok(None);
168        }
169
170        Ok(Some(msg))
171    }
172}
173
174impl Output for CommonState {
175    fn emit(&mut self, ev: Event<'_>) {
176        match ev.disposition() {
177            EventDisposition::MessageOutput => match self.protocol {
178                Protocol::Tcp => self.send.emit(ev),
179                Protocol::Quic(_) => self.quic.emit(ev),
180            },
181
182            EventDisposition::SendPath => self.send.emit(ev),
183            EventDisposition::ReceivePath => self.recv.emit(ev),
184            EventDisposition::ConnectionOutputs => self.outputs.emit(ev),
185            EventDisposition::Quic => self.quic.emit(ev),
186            EventDisposition::SideSpecific => unreachable!(),
187
188            EventDisposition::ProtocolVersion(ver) => {
189                self.outputs
190                    .emit(Event::ProtocolVersion(ver));
191                self.recv
192                    .emit(Event::ProtocolVersion(ver));
193                self.send
194                    .emit(Event::ProtocolVersion(ver));
195            }
196            EventDisposition::StartTraffic => {
197                self.recv.emit(Event::StartTraffic);
198                self.send.emit(Event::StartTraffic);
199            }
200        }
201    }
202}
203
204impl Deref for CommonState {
205    type Target = ConnectionOutputs;
206
207    fn deref(&self) -> &Self::Target {
208        &self.outputs
209    }
210}
211
212impl DerefMut for CommonState {
213    fn deref_mut(&mut self) -> &mut Self::Target {
214        &mut self.outputs
215    }
216}
217
218impl fmt::Debug for CommonState {
219    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220        f.debug_struct("CommonState")
221            .finish_non_exhaustive()
222    }
223}
224
225/// Facts about the connection learned through the handshake.
226pub struct ConnectionOutputs {
227    pub(crate) negotiated_version: Option<ProtocolVersion>,
228    handshake_kind: Option<HandshakeKind>,
229    suite: Option<SupportedCipherSuite>,
230    negotiated_kx_group: Option<&'static dyn SupportedKxGroup>,
231    pub(crate) alpn_protocol: Option<ApplicationProtocol<'static>>,
232    pub(crate) peer_identity: Option<Identity<'static>>,
233    pub(crate) exporter: Option<Box<dyn Exporter>>,
234    pub(crate) early_exporter: Option<Box<dyn Exporter>>,
235    pub(crate) fips: FipsStatus,
236    pub(crate) tls13_tickets_received: u32,
237}
238
239impl ConnectionOutputs {
240    /// Retrieves the certificate chain or the raw public key used by the peer to authenticate.
241    ///
242    /// This is made available for both full and resumed handshakes.
243    ///
244    /// For clients, this is the identity of the server. For servers, this is the identity of the
245    /// client, if client authentication was completed.
246    ///
247    /// The return value is None until this value is available.
248    pub fn peer_identity(&self) -> Option<&Identity<'static>> {
249        self.peer_identity.as_ref()
250    }
251
252    /// Retrieves the protocol agreed with the peer via ALPN.
253    ///
254    /// A return value of `None` after handshake completion
255    /// means no protocol was agreed (because no protocols
256    /// were offered or accepted by the peer).
257    pub fn alpn_protocol(&self) -> Option<&ApplicationProtocol<'static>> {
258        self.alpn_protocol.as_ref()
259    }
260
261    /// Retrieves the cipher suite agreed with the peer.
262    ///
263    /// This returns None until the cipher suite is agreed.
264    pub fn negotiated_cipher_suite(&self) -> Option<SupportedCipherSuite> {
265        self.suite
266    }
267
268    /// Retrieves the key exchange group agreed with the peer.
269    ///
270    /// This function may return `None` depending on the state of the connection,
271    /// the type of handshake, and the protocol version.
272    ///
273    /// If [`CommonState::is_handshaking()`] is true this function will return `None`.
274    /// Similarly, if the [`ConnectionOutputs::handshake_kind()`] is [`HandshakeKind::Resumed`]
275    /// and the [`ConnectionOutputs::protocol_version()`] is TLS 1.2, then no key exchange will have
276    /// occurred and this function will return `None`.
277    pub fn negotiated_key_exchange_group(&self) -> Option<&'static dyn SupportedKxGroup> {
278        self.negotiated_kx_group
279    }
280
281    /// Retrieves the protocol version agreed with the peer.
282    ///
283    /// This returns `None` until the version is agreed.
284    pub fn protocol_version(&self) -> Option<ProtocolVersion> {
285        self.negotiated_version
286    }
287
288    /// Which kind of handshake was performed.
289    ///
290    /// This tells you whether the handshake was a resumption or not.
291    ///
292    /// This will return `None` before it is known which sort of
293    /// handshake occurred.
294    pub fn handshake_kind(&self) -> Option<HandshakeKind> {
295        self.handshake_kind
296    }
297
298    /// Returns the number of TLS1.3 tickets that have been received.
299    ///
300    /// Only clients receive tickets, so this is zero for servers.
301    pub fn tls13_tickets_received(&self) -> u32 {
302        self.tls13_tickets_received
303    }
304
305    /// Return the FIPS validation status of the connection.
306    ///
307    /// This is different from [`crate::crypto::CryptoProvider::fips()`]:
308    /// it is concerned only with cryptography, whereas this _also_ covers TLS-level
309    /// configuration that NIST recommends, as well as ECH HPKE suites if applicable.
310    pub fn fips(&self) -> FipsStatus {
311        self.fips
312    }
313
314    pub(super) fn into_kernel_parts(self) -> Option<(ProtocolVersion, SupportedCipherSuite)> {
315        let Self {
316            negotiated_version,
317            suite,
318            ..
319        } = self;
320
321        match (negotiated_version, suite) {
322            (Some(version), Some(suite)) => Some((version, suite)),
323            _ => None,
324        }
325    }
326}
327
328impl Output for ConnectionOutputs {
329    fn emit(&mut self, ev: Event<'_>) {
330        match ev {
331            Event::ApplicationProtocol(protocol) => {
332                self.alpn_protocol = Some(ApplicationProtocol::from(protocol.as_ref()).to_owned())
333            }
334            Event::CipherSuite(suite) => self.suite = Some(suite),
335            Event::EarlyExporter(exporter) => self.early_exporter = Some(exporter),
336            Event::Exporter(exporter) => self.exporter = Some(exporter),
337            Event::HandshakeKind(hk) => {
338                assert!(self.handshake_kind.is_none());
339                self.handshake_kind = Some(hk);
340            }
341            Event::KeyExchangeGroup(kxg) => {
342                assert!(self.negotiated_kx_group.is_none());
343                self.negotiated_kx_group = Some(kxg);
344            }
345            Event::PeerIdentity(identity) => self.peer_identity = Some(identity),
346            Event::ProtocolVersion(ver) => {
347                self.negotiated_version = Some(ver);
348            }
349            Event::ReceivedTicket => {
350                self.tls13_tickets_received = self
351                    .tls13_tickets_received
352                    .saturating_add(1)
353            }
354            _ => unreachable!(),
355        }
356    }
357}
358
359impl Default for ConnectionOutputs {
360    fn default() -> Self {
361        Self {
362            negotiated_version: None,
363            handshake_kind: None,
364            suite: None,
365            negotiated_kx_group: None,
366            alpn_protocol: None,
367            peer_identity: None,
368            exporter: None,
369            early_exporter: None,
370            fips: FipsStatus::Unvalidated,
371            tls13_tickets_received: 0,
372        }
373    }
374}
375
376/// The data path from us to the peer.
377pub(crate) struct SendPath {
378    pub(crate) encrypt_state: EncryptionState,
379    pub(crate) may_send_application_data: bool,
380    has_sent_fatal_alert: bool,
381    /// If we signaled end of stream.
382    pub(crate) has_sent_close_notify: bool,
383    message_fragmenter: MessageFragmenter,
384    pub(crate) sendable_tls: ChunkVecBuffer,
385    queued_key_update_message: Option<Vec<u8>>,
386    pub(crate) refresh_traffic_keys_pending: bool,
387    negotiated_version: Option<ProtocolVersion>,
388}
389
390impl SendPath {
391    pub(crate) fn maybe_send_fatal_alert(&mut self, error: &Error) {
392        let Ok(alert) = AlertDescription::try_from(error) else {
393            return;
394        };
395        debug_assert!(!self.has_sent_fatal_alert);
396        let m = Message::build_alert(AlertLevel::Fatal, alert);
397        self.send_msg(m, self.encrypt_state.is_encrypting());
398        self.has_sent_fatal_alert = true;
399    }
400
401    pub(crate) fn write_plaintext(
402        &mut self,
403        payload: OutboundPlain<'_>,
404        outgoing_tls: &mut [u8],
405    ) -> Result<usize, EncryptError> {
406        if payload.is_empty() {
407            return Ok(0);
408        }
409
410        let fragments = self
411            .message_fragmenter
412            .fragment_payload(
413                ContentType::ApplicationData,
414                ProtocolVersion::TLSv1_2,
415                payload.clone(),
416            );
417
418        for f in 0..fragments.len() {
419            match self
420                .encrypt_state
421                .pre_encrypt_action(f as u64)
422            {
423                PreEncryptAction::Nothing => {}
424                PreEncryptAction::RefreshOrClose => match self.negotiated_version {
425                    Some(ProtocolVersion::TLSv1_3) => {
426                        // driven by caller, as we don't have the `State` here
427                        self.refresh_traffic_keys_pending = true;
428                    }
429                    _ => {
430                        error!(
431                            "traffic keys exhausted, closing connection to prevent security failure"
432                        );
433                        self.send_close_notify();
434                        return Err(EncryptError::EncryptExhausted);
435                    }
436                },
437                PreEncryptAction::Refuse => {
438                    return Err(EncryptError::EncryptExhausted);
439                }
440            }
441        }
442
443        self.perhaps_write_key_update();
444
445        self.check_required_size(outgoing_tls, fragments)?;
446
447        let fragments = self
448            .message_fragmenter
449            .fragment_payload(
450                ContentType::ApplicationData,
451                ProtocolVersion::TLSv1_2,
452                payload,
453            );
454
455        Ok(self.write_fragments(outgoing_tls, fragments))
456    }
457
458    #[cfg(feature = "std")]
459    pub(crate) fn send_early_plaintext(&mut self, data: &[u8]) -> usize {
460        debug_assert!(self.encrypt_state.is_encrypting());
461
462        // Limit on `sendable_tls` should apply to encrypted data but is enforced
463        // for plaintext data instead which does not include cipher+record overhead.
464        let len = self
465            .sendable_tls
466            .apply_limit(data.len());
467        if len == 0 {
468            // Don't send empty fragments.
469            return 0;
470        }
471
472        self.send_appdata_encrypt(data[..len].into())
473    }
474
475    /// Fragment `m`, encrypt the fragments, and then queue
476    /// the encrypted fragments for sending.
477    fn send_msg_encrypt(&mut self, m: EncodedMessage<Payload<'_>>) {
478        let iter = self
479            .message_fragmenter
480            .fragment_message(&m);
481        for m in iter {
482            self.send_single_fragment(m);
483        }
484    }
485
486    /// Like send_msg_encrypt, but operate on an appdata directly.
487    fn send_appdata_encrypt(&mut self, payload: OutboundPlain<'_>) -> usize {
488        let len = payload.len();
489        let iter = self
490            .message_fragmenter
491            .fragment_payload(
492                ContentType::ApplicationData,
493                ProtocolVersion::TLSv1_2,
494                payload,
495            );
496        for m in iter {
497            self.send_single_fragment(m);
498        }
499
500        len
501    }
502
503    fn send_single_fragment(&mut self, m: EncodedMessage<OutboundPlain<'_>>) {
504        if m.typ == ContentType::Alert {
505            // Alerts are always sendable -- never quashed by a PreEncryptAction.
506            let em = self.encrypt_state.encrypt_outgoing(m);
507            self.queue_tls_message(em);
508            return;
509        }
510
511        match self
512            .encrypt_state
513            .next_pre_encrypt_action()
514        {
515            PreEncryptAction::Nothing => {}
516
517            // Close connection once we start to run out of
518            // sequence space.
519            PreEncryptAction::RefreshOrClose => {
520                match self.negotiated_version {
521                    Some(ProtocolVersion::TLSv1_3) => {
522                        // driven by caller, as we don't have the `State` here
523                        self.refresh_traffic_keys_pending = true;
524                    }
525                    _ => {
526                        error!(
527                            "traffic keys exhausted, closing connection to prevent security failure"
528                        );
529                        self.send_close_notify();
530                        return;
531                    }
532                }
533            }
534
535            // Refuse to wrap counter at all costs.  This
536            // is basically untestable unfortunately.
537            PreEncryptAction::Refuse => {
538                return;
539            }
540        };
541
542        let em = self.encrypt_state.encrypt_outgoing(m);
543        self.queue_tls_message(em);
544    }
545
546    /// Send plaintext application data, fragmenting and
547    /// encrypting it as it goes out.
548    ///
549    /// If internal buffers are too small, this function will not accept
550    /// all the data.
551    #[cfg(feature = "std")]
552    pub(crate) fn buffer_plaintext(
553        &mut self,
554        payload: OutboundPlain<'_>,
555        sendable_plaintext: &mut ChunkVecBuffer,
556    ) -> usize {
557        self.perhaps_write_key_update();
558        if !self.may_send_application_data {
559            // If we haven't completed handshaking, buffer
560            // plaintext to send once we do.
561            return sendable_plaintext.append_limited_copy(payload);
562        }
563
564        // Limit on `sendable_tls` should apply to encrypted data but is enforced
565        // for plaintext data instead which does not include cipher+record overhead.
566        let len = self
567            .sendable_tls
568            .apply_limit(payload.len());
569        if len == 0 {
570            // Don't send empty fragments.
571            return 0;
572        }
573
574        debug_assert!(self.encrypt_state.is_encrypting());
575        self.send_appdata_encrypt(payload.split_at(len).0)
576    }
577
578    pub(crate) fn send_buffered_plaintext(&mut self, plaintext: &mut ChunkVecBuffer) {
579        while let Some(buf) = plaintext.pop() {
580            self.send_appdata_encrypt(buf.as_slice().into());
581        }
582    }
583
584    fn start_outgoing_traffic(&mut self) {
585        self.may_send_application_data = true;
586        debug_assert!(self.encrypt_state.is_encrypting());
587    }
588
589    // Put m into sendable_tls for writing.
590    fn queue_tls_message(&mut self, m: EncodedMessage<OutboundOpaque>) {
591        self.perhaps_write_key_update();
592        self.sendable_tls.append(m.encode());
593    }
594
595    pub(crate) fn perhaps_write_key_update(&mut self) {
596        if let Some(message) = self.queued_key_update_message.take() {
597            self.sendable_tls.append(message);
598        }
599    }
600
601    /// Send a raw TLS message, fragmenting it if needed.
602    fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool) {
603        if !must_encrypt {
604            let msg = &m.into();
605            let iter = self
606                .message_fragmenter
607                .fragment_message(msg);
608            for m in iter {
609                self.queue_tls_message(m.to_unencrypted_opaque());
610            }
611        } else {
612            self.send_msg_encrypt(m.into());
613        }
614    }
615
616    fn send_close_notify(&mut self) {
617        if self.has_sent_fatal_alert {
618            return;
619        }
620        debug!("Sending warning alert {:?}", AlertDescription::CloseNotify);
621        self.has_sent_fatal_alert = true;
622        self.has_sent_close_notify = true;
623        self.send_warning_alert_no_log(AlertDescription::CloseNotify);
624    }
625
626    pub(crate) fn eager_send_close_notify(
627        &mut self,
628        outgoing_tls: &mut [u8],
629    ) -> Result<usize, EncryptError> {
630        self.send_close_notify();
631        self.check_required_size(outgoing_tls, [].into_iter())?;
632        Ok(self.write_fragments(outgoing_tls, [].into_iter()))
633    }
634
635    fn send_warning_alert_no_log(&mut self, desc: AlertDescription) {
636        let m = Message::build_alert(AlertLevel::Warning, desc);
637        self.send_msg(m, self.encrypt_state.is_encrypting());
638    }
639
640    fn check_required_size<'a>(
641        &self,
642        outgoing_tls: &[u8],
643        fragments: impl Iterator<Item = EncodedMessage<OutboundPlain<'a>>>,
644    ) -> Result<(), EncryptError> {
645        let mut required_size = self.sendable_tls.len();
646
647        for m in fragments {
648            required_size += m.encoded_len(&self.encrypt_state);
649        }
650
651        if required_size > outgoing_tls.len() {
652            return Err(EncryptError::InsufficientSize(InsufficientSizeError {
653                required_size,
654            }));
655        }
656
657        Ok(())
658    }
659
660    fn write_fragments<'a>(
661        &mut self,
662        outgoing_tls: &mut [u8],
663        fragments: impl Iterator<Item = EncodedMessage<OutboundPlain<'a>>>,
664    ) -> usize {
665        let mut written = 0;
666
667        // Any pre-existing encrypted messages in `sendable_tls` must
668        // be output before encrypting any of the `fragments`.
669        while let Some(message) = self.sendable_tls.pop() {
670            let len = message.len();
671            outgoing_tls[written..written + len].copy_from_slice(&message);
672            written += len;
673        }
674
675        for m in fragments {
676            let em = self
677                .encrypt_state
678                .encrypt_outgoing(m)
679                .encode();
680
681            let len = em.len();
682            outgoing_tls[written..written + len].copy_from_slice(&em);
683            written += len;
684        }
685
686        written
687    }
688
689    pub(crate) fn set_max_fragment_size(&mut self, new: Option<usize>) -> Result<(), Error> {
690        self.message_fragmenter
691            .set_max_fragment_size(new)
692    }
693
694    pub(crate) fn ensure_key_update_queued(&mut self) -> bool {
695        if self.queued_key_update_message.is_some() {
696            return false;
697        }
698        let message = EncodedMessage::<Payload<'static>>::from(Message::build_key_update_notify());
699        self.queued_key_update_message = Some(
700            self.encrypt_state
701                .encrypt_outgoing(message.borrow_outbound())
702                .encode(),
703        );
704        true
705    }
706}
707impl Output for SendPath {
708    fn emit(&mut self, ev: Event<'_>) {
709        match ev {
710            Event::EncryptMessage(m) => self.send_msg(m, true),
711            Event::MaybeKeyUpdateRequest(ks) => {
712                if self.ensure_key_update_queued() {
713                    ks.update_encrypter_for_key_update(self);
714                }
715            }
716            Event::MessageEncrypter { encrypter, limit } => self
717                .encrypt_state
718                .set_message_encrypter(encrypter, limit),
719            Event::PlainMessage(m) => self.send_msg(m, false),
720            Event::ProtocolVersion(ver) => self.negotiated_version = Some(ver),
721            Event::StartOutgoingTraffic | Event::StartTraffic => self.start_outgoing_traffic(),
722            _ => unreachable!(),
723        }
724    }
725}
726
727impl Default for SendPath {
728    fn default() -> Self {
729        Self {
730            encrypt_state: EncryptionState::new(),
731            may_send_application_data: false,
732            has_sent_fatal_alert: false,
733            has_sent_close_notify: false,
734            message_fragmenter: MessageFragmenter::default(),
735            sendable_tls: ChunkVecBuffer::new(Some(DEFAULT_BUFFER_LIMIT)),
736            queued_key_update_message: None,
737            refresh_traffic_keys_pending: false,
738            negotiated_version: None,
739        }
740    }
741}
742
743pub(crate) struct ReceivePath {
744    side: Side,
745    pub(crate) decrypt_state: DecryptionState,
746    may_receive_application_data: bool,
747    /// If the peer has signaled end of stream.
748    pub(crate) has_received_close_notify: bool,
749    #[cfg(feature = "std")]
750    pub(crate) has_seen_eof: bool,
751    pub(crate) received_plaintext: ChunkVecBuffer,
752    temper_counters: TemperCounters,
753    negotiated_version: Option<ProtocolVersion>,
754}
755
756impl ReceivePath {
757    fn new(side: Side) -> Self {
758        Self {
759            side,
760            decrypt_state: DecryptionState::new(),
761            may_receive_application_data: false,
762            has_received_close_notify: false,
763            #[cfg(feature = "std")]
764            has_seen_eof: false,
765            received_plaintext: ChunkVecBuffer::new(Some(DEFAULT_RECEIVED_PLAINTEXT_LIMIT)),
766            temper_counters: TemperCounters::default(),
767            negotiated_version: None,
768        }
769    }
770
771    fn drop_tls13_ccs(&mut self, msg: &EncodedMessage<&'_ [u8]>) -> Result<bool, Error> {
772        if self.may_receive_application_data
773            || !matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
774        {
775            return Ok(false);
776        }
777
778        if !msg.is_valid_ccs() {
779            // "An implementation which receives any other change_cipher_spec value or
780            //  which receives a protected change_cipher_spec record MUST abort the
781            //  handshake with an "unexpected_message" alert."
782            return Err(PeerMisbehaved::IllegalMiddleboxChangeCipherSpec.into());
783        }
784
785        self.temper_counters
786            .received_tls13_change_cipher_spec()?;
787        Ok(true)
788    }
789
790    fn reject_renegotiation_request(
791        &mut self,
792        send: &mut SendPath,
793        msg: &Message<'_>,
794    ) -> Result<bool, Error> {
795        if !self.may_receive_application_data
796            || matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
797        {
798            return Ok(false);
799        }
800
801        let reject_ty = match self.side {
802            Side::Client => HandshakeType::HelloRequest,
803            Side::Server => HandshakeType::ClientHello,
804        };
805
806        if msg.handshake_type() != Some(reject_ty) {
807            return Ok(false);
808        }
809        self.temper_counters
810            .received_renegotiation_request()?;
811        let desc = AlertDescription::NoRenegotiation;
812        warn!("sending warning alert {desc:?}");
813        send.send_warning_alert_no_log(desc);
814        Ok(true)
815    }
816
817    pub(crate) fn process_alert(&mut self, alert: &AlertMessagePayload) -> Result<(), Error> {
818        // Reject unknown AlertLevels.
819        if let AlertLevel::Unknown(level) = alert.level {
820            return Err(PeerMisbehaved::IllegalAlertLevel(level, alert.description).into());
821        }
822
823        // If we get a CloseNotify, make a note to declare EOF to our
824        // caller.  But do not treat unauthenticated alerts like this.
825        if self.may_receive_application_data && alert.description == AlertDescription::CloseNotify {
826            self.has_received_close_notify = true;
827            return Ok(());
828        }
829
830        // Warnings are nonfatal for TLS1.2, but outlawed in TLS1.3
831        // (except, for no good reason, user_cancelled).
832        let err = Error::AlertReceived(alert.description);
833        if alert.level == AlertLevel::Warning {
834            self.temper_counters
835                .received_warning_alert()?;
836            if matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
837                && alert.description != AlertDescription::UserCanceled
838            {
839                return Err(PeerMisbehaved::IllegalWarningAlert(alert.description).into());
840            }
841
842            // Some implementations send pointless `user_canceled` alerts, don't log them
843            // in release mode (https://bugs.openjdk.org/browse/JDK-8323517).
844            if alert.description != AlertDescription::UserCanceled || cfg!(debug_assertions) {
845                warn!("TLS alert warning received: {alert:?}");
846            }
847
848            return Ok(());
849        }
850
851        Err(err)
852    }
853}
854
855impl Output for ReceivePath {
856    fn emit(&mut self, ev: Event<'_>) {
857        match ev {
858            Event::MessageDecrypter { decrypter, proof } => self
859                .decrypt_state
860                .set_message_decrypter(decrypter, &proof),
861            Event::MessageDecrypterWithTrialDecryption {
862                decrypter,
863                max_length,
864                proof,
865            } => self
866                .decrypt_state
867                .set_message_decrypter_with_trial_decryption(decrypter, max_length, &proof),
868            Event::ProtocolVersion(ver) => self.negotiated_version = Some(ver),
869            Event::StartTraffic => self.may_receive_application_data = true,
870            _ => unreachable!(),
871        }
872    }
873}
874
875/// Describes which sort of handshake happened.
876#[derive(Debug, PartialEq, Clone, Copy)]
877#[non_exhaustive]
878pub enum HandshakeKind {
879    /// A full handshake.
880    ///
881    /// This is the typical TLS connection initiation process when resumption is
882    /// not yet unavailable, and the initial `ClientHello` was accepted by the server.
883    Full,
884
885    /// A full TLS1.3 handshake, with an extra round-trip for a `HelloRetryRequest`.
886    ///
887    /// The server can respond with a `HelloRetryRequest` if the initial `ClientHello`
888    /// is unacceptable for several reasons, the most likely being if no supported key
889    /// shares were offered by the client.
890    FullWithHelloRetryRequest,
891
892    /// A resumed handshake.
893    ///
894    /// Resumed handshakes involve fewer round trips and less cryptography than
895    /// full ones, but can only happen when the peers have previously done a full
896    /// handshake together, and then remember data about it.
897    Resumed,
898
899    /// A resumed handshake, with an extra round-trip for a `HelloRetryRequest`.
900    ///
901    /// The server can respond with a `HelloRetryRequest` if the initial `ClientHello`
902    /// is unacceptable for several reasons, but this does not prevent the client
903    /// from resuming.
904    ResumedWithHelloRetryRequest,
905}
906
907/// Values of this structure are returned from [`Connection::process_new_packets`]
908/// and tell the caller the current I/O state of the TLS connection.
909///
910/// [`Connection::process_new_packets`]: crate::Connection::process_new_packets
911#[derive(Debug, Eq, PartialEq)]
912pub struct IoState {
913    tls_bytes_to_write: usize,
914    plaintext_bytes_to_read: usize,
915    peer_has_closed: bool,
916}
917
918impl IoState {
919    /// How many bytes could be written by [`Connection::write_tls`] if called
920    /// right now.  A non-zero value implies [`CommonState::wants_write`].
921    ///
922    /// [`Connection::write_tls`]: crate::Connection::write_tls
923    pub fn tls_bytes_to_write(&self) -> usize {
924        self.tls_bytes_to_write
925    }
926
927    /// How many plaintext bytes could be obtained via [`std::io::Read`]
928    /// without further I/O.
929    pub fn plaintext_bytes_to_read(&self) -> usize {
930        self.plaintext_bytes_to_read
931    }
932
933    /// True if the peer has sent us a close_notify alert.  This is
934    /// the TLS mechanism to securely half-close a TLS connection,
935    /// and signifies that the peer will not send any further data
936    /// on this connection.
937    ///
938    /// This is also signalled via returning `Ok(0)` from
939    /// [`std::io::Read`], after all the received bytes have been
940    /// retrieved.
941    pub fn peer_has_closed(&self) -> bool {
942        self.peer_has_closed
943    }
944}
945
946pub(crate) trait State<Side: SideData>: Send + Sync {
947    fn handle<'m>(
948        self: Box<Self>,
949        input: Input<'m>,
950        output: &mut dyn Output,
951    ) -> Result<Box<dyn State<Side>>, Error>;
952
953    fn send_key_update_request(&mut self, _output: &mut dyn Output) -> Result<(), Error> {
954        Err(Error::HandshakeNotComplete)
955    }
956
957    fn handle_decrypt_error(&self) {}
958
959    #[cfg_attr(not(feature = "std"), expect(dead_code))]
960    fn set_resumption_data(&mut self, _resumption_data: &[u8]) -> Result<(), Error> {
961        Err(ApiMisuse::ResumptionDataProvidedTooLate.into())
962    }
963
964    fn into_external_state(
965        self: Box<Self>,
966    ) -> Result<(PartiallyExtractedSecrets, Box<dyn KernelState + 'static>), Error> {
967        Err(Error::HandshakeNotComplete)
968    }
969}
970
971struct CaptureAppData<'a> {
972    data: &'a mut dyn Output,
973    /// Store a [`Locator`] initialized from the current receive buffer
974    ///
975    /// Allows received plaintext data to be unborrowed and stored in
976    /// `received_plaintext` for in-place decryption.
977    plaintext_locator: &'a Locator,
978    /// Unborrowed received plaintext data
979    ///
980    /// Set if plaintext data was received.
981    ///
982    /// Plaintext data may be reborrowed using a [`Delocator`] which was
983    /// initialized from the same slice as `plaintext_locator`.
984    received_plaintext: &'a mut Option<UnborrowedPayload>,
985}
986
987impl Output for CaptureAppData<'_> {
988    fn emit(&mut self, ev: Event<'_>) {
989        match ev {
990            Event::ApplicationData(payload) => {
991                // Receive plaintext data [`Payload<'_>`].
992                //
993                // Since [`Context`] does not hold a lifetime to the receive buffer the
994                // passed [`Payload`] will have it's lifetime erased by storing an index
995                // into the receive buffer as an [`UnborrowedPayload`]. This enables the
996                // data to be later reborrowed after it has been decrypted in-place.
997                let previous = self
998                    .received_plaintext
999                    .replace(UnborrowedPayload::unborrow(self.plaintext_locator, payload));
1000                debug_assert!(previous.is_none(), "overwrote plaintext data");
1001            }
1002            _ => self.data.emit(ev),
1003        }
1004    }
1005}
1006
1007pub(crate) struct Input<'a> {
1008    pub(crate) message: Message<'a>,
1009    pub(crate) aligned_handshake: Option<HandshakeAlignedProof>,
1010}
1011
1012impl Input<'_> {
1013    // Changing the keys must not span any fragmented handshake
1014    // messages.  Otherwise the defragmented messages will have
1015    // been protected with two different record layer protections,
1016    // which is illegal.  Not mentioned in RFC.
1017    pub(crate) fn check_aligned_handshake(&self) -> Result<HandshakeAlignedProof, Error> {
1018        self.aligned_handshake
1019            .ok_or_else(|| PeerMisbehaved::KeyEpochWithPendingFragment.into())
1020    }
1021}
1022
1023/// The route for handshake state machine to surface determinations about the connection.
1024pub(crate) trait Output {
1025    fn emit(&mut self, ev: Event<'_>);
1026}
1027
1028/// The set of events output by the low-level handshake state machine.
1029pub(crate) enum Event<'a> {
1030    ApplicationData(Payload<'a>),
1031    ApplicationProtocol(ApplicationProtocol<'a>),
1032    CipherSuite(SupportedCipherSuite),
1033    EarlyApplicationData(Payload<'a>),
1034    EarlyData(EarlyDataEvent),
1035    EarlyExporter(Box<dyn Exporter>),
1036    EchStatus(EchStatus),
1037    EncryptMessage(Message<'a>),
1038    Exporter(Box<dyn Exporter>),
1039    HandshakeKind(HandshakeKind),
1040    KeyExchangeGroup(&'static dyn SupportedKxGroup),
1041    MaybeKeyUpdateRequest(&'a mut KeyScheduleTrafficSend),
1042    MessageDecrypter {
1043        decrypter: Box<dyn MessageDecrypter>,
1044        proof: HandshakeAlignedProof,
1045    },
1046    MessageDecrypterWithTrialDecryption {
1047        decrypter: Box<dyn MessageDecrypter>,
1048        max_length: usize,
1049        proof: HandshakeAlignedProof,
1050    },
1051    MessageEncrypter {
1052        encrypter: Box<dyn MessageEncrypter>,
1053        limit: u64,
1054    },
1055    PeerIdentity(Identity<'static>),
1056    PlainMessage(Message<'a>),
1057    ProtocolVersion(ProtocolVersion),
1058    QuicEarlySecret(Option<OkmBlock>),
1059    QuicHandshakeSecrets(quic::Secrets),
1060    QuicTrafficSecrets(quic::Secrets),
1061    QuicTransportParameters(Vec<u8>),
1062    ReceivedServerName(Option<DnsName<'static>>),
1063    ReceivedTicket,
1064    ResumptionData(Vec<u8>),
1065    /// Mark the connection as ready to send application data.
1066    StartOutgoingTraffic,
1067    /// Mark the connection as ready to send and receive application data.
1068    StartTraffic,
1069}
1070
1071impl Event<'_> {
1072    fn disposition(&self) -> EventDisposition {
1073        match self {
1074            // message dispatch
1075            Event::EncryptMessage(_) | Event::PlainMessage(_) => EventDisposition::MessageOutput,
1076
1077            // send-specific events
1078            Event::MaybeKeyUpdateRequest(_)
1079            | Event::MessageEncrypter { .. }
1080            | Event::StartOutgoingTraffic => EventDisposition::SendPath,
1081
1082            // recv-specific events
1083            Event::MessageDecrypter { .. } | Event::MessageDecrypterWithTrialDecryption { .. } => {
1084                EventDisposition::ReceivePath
1085            }
1086
1087            // presentation API events
1088            Event::ApplicationProtocol(_)
1089            | Event::CipherSuite(_)
1090            | Event::EarlyExporter(_)
1091            | Event::Exporter(_)
1092            | Event::HandshakeKind(_)
1093            | Event::KeyExchangeGroup(_)
1094            | Event::PeerIdentity(_)
1095            | Event::ReceivedTicket => EventDisposition::ConnectionOutputs,
1096
1097            // quic-specific events
1098            Event::QuicEarlySecret(_)
1099            | Event::QuicHandshakeSecrets(_)
1100            | Event::QuicTrafficSecrets(_)
1101            | Event::QuicTransportParameters(_) => EventDisposition::Quic,
1102
1103            // broadcast events
1104            Event::ProtocolVersion(ver) => EventDisposition::ProtocolVersion(*ver),
1105
1106            Event::StartTraffic => EventDisposition::StartTraffic,
1107
1108            // higher levels
1109            Event::ApplicationData(_)
1110            | Event::EarlyApplicationData(_)
1111            | Event::EarlyData(_)
1112            | Event::EchStatus(_)
1113            | Event::ReceivedServerName(_)
1114            | Event::ResumptionData(_) => EventDisposition::SideSpecific,
1115        }
1116    }
1117}
1118
1119/// Where a given `Event` should be routed to.
1120#[derive(Clone, Copy, Debug)]
1121pub(crate) enum EventDisposition {
1122    /// Events related to message output
1123    MessageOutput,
1124
1125    /// Events destined for `SendPath`
1126    SendPath,
1127
1128    /// Events destined for `ReceivePath`
1129    ReceivePath,
1130
1131    /// Events destined for `ConnectionOutputs`
1132    ConnectionOutputs,
1133
1134    /// Events related only to QUIC
1135    Quic,
1136
1137    /// Event broadcast into `SendPath`, `ReceivePath`, and `ConnectionOutputs`
1138    ProtocolVersion(ProtocolVersion),
1139
1140    /// Event broadcast into `SendPath` and `ReceivePath`
1141    StartTraffic,
1142
1143    /// Events which are side (client or server) specific
1144    SideSpecific,
1145}
1146
1147pub(crate) enum EarlyDataEvent {
1148    /// server: we accepted an early_data offer
1149    Accepted,
1150    /// client: declares the maximum amount of early data that can be sent
1151    Enable(usize),
1152    /// client: early data can now be sent using the record layer as normal
1153    Start,
1154    /// client: early data phase has closed after sending EndOfEarlyData
1155    Finished,
1156    /// client: the server rejected our request for early data
1157    Rejected,
1158}
1159
1160/// Lifetime-erased equivalent to [`Payload`]
1161///
1162/// Stores an index into [`Payload`] buffer enabling in-place decryption
1163/// without holding a lifetime to the receive buffer.
1164pub(crate) enum UnborrowedPayload {
1165    Unborrowed(Range<usize>),
1166    Owned(Vec<u8>),
1167}
1168
1169impl UnborrowedPayload {
1170    /// Convert [`Payload`] into [`UnborrowedPayload`] which stores a range
1171    /// into the [`Payload`] slice without borrowing such that it can be later
1172    /// reborrowed.
1173    ///
1174    /// # Panics
1175    ///
1176    /// Passed [`Locator`] must have been created from the same slice which
1177    /// contains the payload.
1178    pub(crate) fn unborrow(locator: &Locator, payload: Payload<'_>) -> Self {
1179        match payload {
1180            Payload::Borrowed(payload) => Self::Unborrowed(locator.locate(payload)),
1181            Payload::Owned(payload) => Self::Owned(payload),
1182        }
1183    }
1184
1185    /// Convert [`UnborrowedPayload`] back into [`Payload`]
1186    ///
1187    /// # Panics
1188    ///
1189    /// Passed [`Delocator`] must have been created from the same slice that
1190    /// [`UnborrowedPayload`] was originally unborrowed from.
1191    pub(crate) fn reborrow<'b>(self, delocator: &Delocator<'b>) -> Payload<'b> {
1192        match self {
1193            Self::Unborrowed(range) => Payload::Borrowed(delocator.slice_from_range(&range)),
1194            Self::Owned(payload) => Payload::Owned(payload),
1195        }
1196    }
1197}
1198
1199/// Side of the connection.
1200#[expect(clippy::exhaustive_enums)]
1201#[derive(Clone, Copy, Debug, PartialEq)]
1202pub enum Side {
1203    /// A client initiates the connection.
1204    Client,
1205    /// A server waits for a client to connect.
1206    Server,
1207}
1208
1209#[derive(Copy, Clone, Eq, PartialEq, Debug)]
1210pub(crate) enum Protocol {
1211    /// TCP-TLS, standardized in RFC5246 and RFC8446
1212    Tcp,
1213    /// QUIC, standardized in RFC9001
1214    #[cfg_attr(not(feature = "std"), expect(dead_code))]
1215    Quic(quic::Version),
1216}
1217
1218impl Protocol {
1219    pub(crate) fn is_quic(&self) -> bool {
1220        matches!(self, Self::Quic(_))
1221    }
1222}
1223
1224/// Tracking technically-allowed protocol actions
1225/// that we limit to avoid denial-of-service vectors.
1226struct TemperCounters {
1227    allowed_warning_alerts: u8,
1228    allowed_renegotiation_requests: u8,
1229    allowed_middlebox_ccs: u8,
1230}
1231
1232impl TemperCounters {
1233    fn received_warning_alert(&mut self) -> Result<(), Error> {
1234        match self.allowed_warning_alerts {
1235            0 => Err(PeerMisbehaved::TooManyWarningAlertsReceived.into()),
1236            _ => {
1237                self.allowed_warning_alerts -= 1;
1238                Ok(())
1239            }
1240        }
1241    }
1242
1243    fn received_renegotiation_request(&mut self) -> Result<(), Error> {
1244        match self.allowed_renegotiation_requests {
1245            0 => Err(PeerMisbehaved::TooManyRenegotiationRequests.into()),
1246            _ => {
1247                self.allowed_renegotiation_requests -= 1;
1248                Ok(())
1249            }
1250        }
1251    }
1252
1253    fn received_tls13_change_cipher_spec(&mut self) -> Result<(), Error> {
1254        match self.allowed_middlebox_ccs {
1255            0 => Err(PeerMisbehaved::IllegalMiddleboxChangeCipherSpec.into()),
1256            _ => {
1257                self.allowed_middlebox_ccs -= 1;
1258                Ok(())
1259            }
1260        }
1261    }
1262}
1263
1264impl Default for TemperCounters {
1265    fn default() -> Self {
1266        Self {
1267            // cf. BoringSSL `kMaxWarningAlerts`
1268            // <https://github.com/google/boringssl/blob/dec5989b793c56ad4dd32173bd2d8595ca78b398/ssl/tls_record.cc#L137-L139>
1269            allowed_warning_alerts: 4,
1270
1271            // we rebuff renegotiation requests with a `NoRenegotiation` warning alerts.
1272            // a second request after this is fatal.
1273            allowed_renegotiation_requests: 1,
1274
1275            // At most two CCS are allowed: one after each ClientHello (recall a second
1276            // ClientHello happens after a HelloRetryRequest).
1277            //
1278            // note BoringSSL allows up to 32.
1279            allowed_middlebox_ccs: 2,
1280        }
1281    }
1282}
1283
1284pub(crate) struct TrafficTemperCounters {
1285    allowed_key_update_requests: u8,
1286}
1287
1288impl TrafficTemperCounters {
1289    pub(crate) fn received_key_update_request(&mut self) -> Result<(), Error> {
1290        match self.allowed_key_update_requests {
1291            0 => Err(PeerMisbehaved::TooManyKeyUpdateRequests.into()),
1292            _ => {
1293                self.allowed_key_update_requests -= 1;
1294                Ok(())
1295            }
1296        }
1297    }
1298
1299    pub(crate) fn received_app_data(&mut self) {
1300        self.allowed_key_update_requests = Self::INITIAL_KEY_UPDATE_REQUESTS;
1301    }
1302
1303    // cf. BoringSSL `kMaxKeyUpdates`
1304    // <https://github.com/google/boringssl/blob/dec5989b793c56ad4dd32173bd2d8595ca78b398/ssl/tls13_both.cc#L35-L38>
1305    const INITIAL_KEY_UPDATE_REQUESTS: u8 = 32;
1306}
1307
1308impl Default for TrafficTemperCounters {
1309    fn default() -> Self {
1310        Self {
1311            allowed_key_update_requests: Self::INITIAL_KEY_UPDATE_REQUESTS,
1312        }
1313    }
1314}
1315
1316pub(crate) struct HandshakeFlight<'a, const TLS13: bool> {
1317    pub(crate) transcript: &'a mut HandshakeHash,
1318    body: Vec<u8>,
1319}
1320
1321impl<'a, const TLS13: bool> HandshakeFlight<'a, TLS13> {
1322    pub(crate) fn new(transcript: &'a mut HandshakeHash) -> Self {
1323        Self {
1324            transcript,
1325            body: Vec::new(),
1326        }
1327    }
1328
1329    pub(crate) fn add(&mut self, hs: HandshakeMessagePayload<'_>) {
1330        let start_len = self.body.len();
1331        hs.encode(&mut self.body);
1332        self.transcript
1333            .add(&self.body[start_len..]);
1334    }
1335
1336    pub(crate) fn finish(self, output: &mut dyn Output) {
1337        let m = Message {
1338            version: match TLS13 {
1339                true => ProtocolVersion::TLSv1_3,
1340                false => ProtocolVersion::TLSv1_2,
1341            },
1342            payload: MessagePayload::HandshakeFlight(Payload::new(self.body)),
1343        };
1344
1345        output.emit(match TLS13 {
1346            true => Event::EncryptMessage(m),
1347            false => Event::PlainMessage(m),
1348        });
1349    }
1350}
1351
1352pub(crate) type HandshakeFlightTls12<'a> = HandshakeFlight<'a, false>;
1353pub(crate) type HandshakeFlightTls13<'a> = HandshakeFlight<'a, true>;
1354
1355const DEFAULT_RECEIVED_PLAINTEXT_LIMIT: usize = 16 * 1024;
1356pub(crate) const DEFAULT_BUFFER_LIMIT: usize = 64 * 1024;