Skip to main content

rustls/conn/
receive.rs

1use alloc::vec::Vec;
2use core::marker::PhantomData;
3use core::mem;
4use core::ops::Range;
5use std::io::{self, Read};
6
7use super::send::{SendOutput, SendPath};
8use super::split::SendAdapter;
9use crate::SideData;
10use crate::common_state::{
11    ConnectionOutput, Event, Output, OutputEvent, Side, UnborrowedPayload, maybe_send_fatal_alert,
12};
13use crate::conn::private::SideOutput;
14use crate::conn::{ConnectionCommon, StateMachine};
15use crate::crypto::cipher::{Decrypted, DecryptionState, EncodableVersion, Payload, Record};
16use crate::enums::{ContentType, HandshakeType, ProtocolVersion};
17use crate::error::{AlertDescription, Error, PeerMisbehaved};
18use crate::msgs::{
19    AlertLevel, AlertLevelName, AlertMessagePayload, Deframed, Deframer, Delocator,
20    HandshakeAlignedProof, Locator, Message, MessagePayload,
21};
22use crate::quic::QuicOutput;
23use crate::tracing::{trace, warn};
24
25pub(crate) struct MessageIter<'a, 'm, Side: SideData, Send: SendOutput + 'a> {
26    pub(super) input: &'m mut dyn TlsInputBuffer,
27    pub(super) tls: &'a mut Vec<u8>,
28    pub(super) recv: &'a mut ReceivePath,
29    pub(super) state: &'a mut Result<Side::State, Error>,
30    pub(super) output: JoinOutput<'a, Send>,
31    pub(super) mode: MessageIterMode,
32}
33
34impl<'a, 'm, Side: SideData> MessageIter<'a, 'm, Side, SendPath> {
35    pub(crate) fn new(
36        input: &'m mut dyn TlsInputBuffer,
37        tls: &'a mut Vec<u8>,
38        quic: Option<&'a mut dyn QuicOutput>,
39        conn: &'a mut ConnectionCommon<Side>,
40        mode: MessageIterMode,
41    ) -> Self {
42        Self {
43            input,
44            tls,
45            recv: &mut conn.common.recv,
46            state: &mut conn.state,
47            output: JoinOutput {
48                outputs: &mut conn.common.outputs,
49                quic,
50                send: &mut conn.common.send,
51                side: &mut conn.side,
52            },
53            mode,
54        }
55    }
56}
57
58impl<'a, 'm, 's, Side: SideData> MessageIter<'a, 'm, Side, SendAdapter<'s>> {
59    pub(super) fn receive(
60        input: &'m mut dyn TlsInputBuffer,
61        tls: &'a mut Vec<u8>,
62        state: &'a mut Result<Side::State, Error>,
63        recv: &'a mut ReceivePath,
64        output: JoinOutput<'a, SendAdapter<'s>>,
65        mode: MessageIterMode,
66    ) -> Self {
67        Self {
68            input,
69            tls,
70            recv,
71            state,
72            output,
73            mode,
74        }
75    }
76}
77
78impl<'a, 'm, Side: SideData, Send: SendOutput + 'a> MessageIter<'a, 'm, Side, Send> {
79    pub(crate) fn next(&mut self, early_only: bool) -> Option<Result<UnborrowedPayload, Error>> {
80        let mut st = match mem::replace(self.state, Err(Error::HandshakeNotComplete)) {
81            Ok(state) => state,
82            Err(e) => {
83                *self.state = Err(e.clone());
84                return Some(Err(e));
85            }
86        };
87
88        let mut plaintext = None;
89        while st.wants_input() {
90            let buffer = self.input.slice_mut();
91            let locator = Locator::new(buffer);
92            let res = self.recv.deframe(buffer);
93
94            let mut output = CaptureAppData {
95                recv: self.recv,
96                tls: self.tls,
97                other: &mut self.output,
98                plaintext_locator: &locator,
99                received_plaintext: &mut plaintext,
100                _message_lifetime: PhantomData,
101            };
102
103            let opt_record = match res {
104                Ok(opt_record) => opt_record,
105                Err(e) => {
106                    maybe_send_fatal_alert(output.other.send, &e, output.tls);
107                    if let Error::DecryptError = e {
108                        st.handle_decrypt_error();
109                    }
110                    *self.state = Err(e.clone());
111                    return Some(Err(e));
112                }
113            };
114
115            let Some(record) = opt_record else {
116                break;
117            };
118
119            let Decrypted {
120                plaintext: record,
121                want_close_before_decrypt,
122            } = record;
123
124            if want_close_before_decrypt {
125                output.other.send.send_alert(
126                    AlertLevel::Warning,
127                    AlertDescription::CloseNotify,
128                    output.tls,
129                );
130            } else if record.payload.is_empty()
131                && matches!(record.typ, ContentType::Handshake | ContentType::Alert)
132            {
133                // <https://datatracker.ietf.org/doc/html/rfc9846#section-5.4>
134                output.other.send.send_alert(
135                    AlertLevel::Fatal,
136                    AlertDescription::UnexpectedMessage,
137                    output.tls,
138                );
139                let error = Error::from(PeerMisbehaved::EmptyFragment);
140                *self.state = Err(error.clone());
141                return Some(Err(error));
142            }
143
144            let hs_aligned = output.recv.deframer.aligned();
145            let result =
146                match output
147                    .recv
148                    .receive_record(record, hs_aligned, output.tls, output.other.send)
149                {
150                    Ok(Some(input)) => st.handle(input, &mut output),
151                    Ok(None) => Ok(st),
152                    Err(e) => Err(e),
153                };
154
155            match result {
156                Ok(new) => st = new,
157                Err(e) => {
158                    maybe_send_fatal_alert(output.other.send, &e, output.tls);
159                    *self.state = Err(e.clone());
160                    return Some(Err(e));
161                }
162            }
163
164            if matches!(self.mode, MessageIterMode::All) && !st.wants_input() {
165                st = match st.handle_without_input(&mut output) {
166                    Ok(st) => st,
167                    Err(err) => {
168                        maybe_send_fatal_alert(output.other.send, &err, output.tls);
169                        *self.state = Err(err.clone());
170                        return Some(Err(err));
171                    }
172                };
173            }
174
175            if self.recv.has_received_close_notify {
176                // "Any data received after a closure alert has been received MUST be ignored."
177                // -- <https://datatracker.ietf.org/doc/html/rfc9846#section-6.1>
178
179                // First, discard actually-processed bytes.
180                self.input
181                    .discard(self.recv.deframer.take_discard());
182
183                // Then the rest of any input data.
184                let entirety = self.input.slice_mut().len();
185                self.recv.deframer.set_discard(entirety);
186                self.input.received_close_notify();
187                break;
188            }
189
190            match plaintext.take() {
191                Some(DataKind::Traffic(payload)) if !early_only => {
192                    *self.state = Ok(st);
193                    return Some(Ok(payload));
194                }
195                Some(DataKind::Early(payload)) if early_only => {
196                    *self.state = Ok(st);
197                    return Some(Ok(payload));
198                }
199                _ => {}
200            }
201
202            // Stop before consuming traffic data if the caller only wants early data.
203            if (early_only || matches!(self.mode, MessageIterMode::Handshake)) && st.is_traffic() {
204                break;
205            }
206        }
207
208        *self.state = Ok(st);
209        None
210    }
211}
212
213pub(crate) enum MessageIterMode {
214    /// Iterate through all available messages.
215    All,
216
217    /// Handshake mode.
218    ///
219    /// Stop iteration when when external input is needed to progress handshake, or the handshake ends.
220    Handshake,
221}
222
223pub(crate) struct ReceivePath {
224    side: Side,
225    pub(crate) decrypt_state: DecryptionState,
226    pub(crate) may_receive_application_data: bool,
227    /// If the peer has signaled end of stream.
228    pub(crate) has_received_close_notify: bool,
229    temper_counters: TemperCounters,
230    pub(crate) negotiated_version: Option<ProtocolVersion>,
231    pub(crate) deframer: Deframer,
232
233    /// We limit consecutive empty fragments to avoid a route for the peer to send
234    /// us significant but fruitless traffic.  That includes other record types too.
235    seen_consecutive_empty_fragments: u8,
236
237    pub(crate) tls13_tickets_received: u32,
238}
239
240impl ReceivePath {
241    pub(crate) fn new(side: Side) -> Self {
242        Self {
243            side,
244            decrypt_state: DecryptionState::new(),
245            may_receive_application_data: false,
246            has_received_close_notify: false,
247            temper_counters: TemperCounters::default(),
248            negotiated_version: None,
249            deframer: Deframer::default(),
250            seen_consecutive_empty_fragments: 0,
251            tls13_tickets_received: 0,
252        }
253    }
254
255    /// Pull a potentially coalesced record out of the deframer.
256    fn deframe<'b>(&mut self, buffer: &'b mut [u8]) -> Result<Option<Decrypted<'b>>, Error> {
257        let locator = Locator::new(buffer);
258
259        let mut want_close_before_decrypt = false;
260        loop {
261            // before processing any more of `buffer`, return any extant records from `deframer`
262            if let Some(span) = self.deframer.complete_span() {
263                let plaintext = self.deframer.record(span, buffer);
264
265                // trial decryption finishes with the first handshake message after it started.
266                self.decrypt_state
267                    .finish_trial_decryption();
268
269                return Ok(Some(Decrypted {
270                    plaintext,
271                    want_close_before_decrypt,
272                }));
273            }
274
275            let (record, bounds) = loop {
276                match self.deframe_decrypted(buffer, &locator)? {
277                    DeframeResult::Decrypted(decrypted, bounds) => break (decrypted, bounds),
278                    DeframeResult::DecryptionFailed => continue,
279                    DeframeResult::None => return Ok(None),
280                }
281            };
282
283            want_close_before_decrypt = record.want_close_before_decrypt;
284            let Decrypted {
285                plaintext: record,
286                want_close_before_decrypt: _,
287            } = record;
288
289            if self.deframer.aligned().is_none() && record.typ != ContentType::Handshake {
290                // "Handshake messages MUST NOT be interleaved with other record
291                // types.  That is, if a handshake message is split over two or more
292                // records, there MUST NOT be any other records between them."
293                // https://www.rfc-editor.org/rfc/rfc9846#section-5.1
294                return Err(PeerMisbehaved::MessageInterleavedWithHandshakeMessage.into());
295            }
296
297            match (record.payload.len(), record.typ) {
298                (0, _) => {
299                    if self.seen_consecutive_empty_fragments
300                        == ALLOWED_CONSECUTIVE_EMPTY_FRAGMENTS_MAX
301                    {
302                        return Err(PeerMisbehaved::TooManyEmptyFragments.into());
303                    }
304                    self.seen_consecutive_empty_fragments += 1;
305                }
306                (_, ContentType::Handshake | ContentType::ApplicationData) => {
307                    self.seen_consecutive_empty_fragments = 0;
308                }
309                (_, _) => {}
310            };
311
312            // do an end-run around the borrow checker, converting `record` (containing
313            // a borrowed slice) to an unborrowed one (containing a `Range` into the
314            // same buffer).  the reborrow happens inside the branch that returns the
315            // record.
316            //
317            // is fixed by -Zpolonius
318            // https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md#problem-case-3-conditional-control-flow-across-functions
319            let unborrowed = InboundUnborrowedRecord::unborrow(&locator, record);
320
321            if unborrowed.typ != ContentType::Handshake {
322                let record = unborrowed.reborrow(&Delocator::new(buffer));
323                self.deframer.discard_processed();
324                return Ok(Some(Decrypted {
325                    plaintext: record,
326                    want_close_before_decrypt,
327                }));
328            }
329
330            let record = unborrowed.reborrow(&Delocator::new(buffer));
331            self.deframer
332                .input_message(record.version.version(), bounds, buffer);
333            self.deframer.coalesce(buffer)?;
334        }
335    }
336
337    fn deframe_decrypted<'b>(
338        &mut self,
339        buffer: &'b mut [u8],
340        locator: &Locator,
341    ) -> Result<DeframeResult<'b>, Error> {
342        let (record, bounds) = match self.deframer.deframe(buffer) {
343            Some(Ok(Deframed { record, bounds })) => (record, bounds),
344            Some(Err(err)) => return Err(err),
345            None => return Ok(DeframeResult::None),
346        };
347
348        let allowed_plaintext = match record.typ {
349            // CCS messages are always plaintext.
350            ContentType::ChangeCipherSpec => true,
351            // Alerts are allowed to be plaintext if-and-only-if:
352            // * The negotiated protocol version is TLS 1.3. - In TLS 1.2 it is unambiguous when
353            //   keying changes based on the CCS message. Only TLS 1.3 requires these heuristics.
354            // * We have not yet decrypted any records from the peer - if we have we don't
355            //   expect any plaintext.
356            // * The payload size is indicative of a plaintext alert message.
357            ContentType::Alert
358                if matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
359                    && !self.decrypt_state.has_decrypted()
360                    && record.payload.len() <= 2 =>
361            {
362                true
363            }
364            // In other circumstances, we expect all records to be encrypted.
365            _ => false,
366        };
367
368        if allowed_plaintext && !self.deframer.is_active() {
369            return Ok(DeframeResult::Decrypted(
370                Decrypted {
371                    plaintext: record.into_plain_record(),
372                    want_close_before_decrypt: false,
373                },
374                bounds,
375            ));
376        }
377
378        match self
379            .decrypt_state
380            .decrypt_incoming(record)?
381        {
382            Some(decrypted) => {
383                // After decryption, the payload is shorter
384                let bounds = locator.locate(decrypted.plaintext.payload);
385                Ok(DeframeResult::Decrypted(decrypted, bounds))
386            }
387
388            // failed decryption during trial decryption is not allowed to be
389            // interleaved with partial handshake data.
390            None if self.deframer.aligned().is_none() => {
391                Err(PeerMisbehaved::RejectedEarlyDataInterleavedWithHandshakeMessage.into())
392            }
393
394            // failed decryption during trial decryption.
395            None => Ok(DeframeResult::DecryptionFailed),
396        }
397    }
398
399    /// Take a TLS record and map it into an `Input`
400    ///
401    /// `Input` is the input to our state machine.
402    ///
403    /// The record is mapped into `None` if it should be dropped with no further
404    /// action.
405    ///
406    /// Otherwise the caller must present the returned `Input` to the state machine to
407    /// progress the connection.
408    pub(crate) fn receive_record<'a>(
409        &mut self,
410        record: Record<&'a [u8]>,
411        aligned_handshake: Option<HandshakeAlignedProof>,
412        tls: &mut Vec<u8>,
413        send: &mut dyn SendOutput,
414    ) -> Result<Option<Input<'a>>, Error> {
415        // Drop CCS messages during handshake in TLS1.3
416        if record.typ == ContentType::ChangeCipherSpec && self.drop_tls13_ccs(&record)? {
417            trace!("Dropping CCS");
418            return Ok(None);
419        }
420
421        // Now we can fully parse the record payload.
422        let message = Message::try_from(record)?;
423
424        // For alerts, we have separate logic.
425        if let MessagePayload::Alert(alert) = &message.payload {
426            self.process_alert(alert)?;
427            return Ok(None);
428        }
429
430        // For TLS1.2, outside of the handshake, send rejection alerts for
431        // renegotiation requests.  These can occur any time.
432        if self.reject_renegotiation_request(&message, tls, send)? {
433            return Ok(None);
434        }
435
436        Ok(Some(Input {
437            message,
438            aligned_handshake,
439        }))
440    }
441
442    fn drop_tls13_ccs(&mut self, record: &Record<&'_ [u8]>) -> Result<bool, Error> {
443        if self.may_receive_application_data
444            || !matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
445        {
446            return Ok(false);
447        }
448
449        if !record.is_valid_ccs() {
450            // "An implementation which receives any other change_cipher_spec value or
451            //  which receives a protected change_cipher_spec record MUST abort the
452            //  handshake with an "unexpected_message" alert."
453            return Err(PeerMisbehaved::IllegalMiddleboxChangeCipherSpec.into());
454        }
455
456        self.temper_counters
457            .received_tls13_change_cipher_spec()?;
458        Ok(true)
459    }
460
461    fn reject_renegotiation_request(
462        &mut self,
463        msg: &Message<'_>,
464        tls: &mut Vec<u8>,
465        send: &mut dyn SendOutput,
466    ) -> Result<bool, Error> {
467        if !self.may_receive_application_data
468            || matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
469        {
470            return Ok(false);
471        }
472
473        let reject_ty = match self.side {
474            Side::Client => HandshakeType::HelloRequest,
475            Side::Server => HandshakeType::ClientHello,
476        };
477
478        if msg.handshake_type() != Some(reject_ty) {
479            return Ok(false);
480        }
481        self.temper_counters
482            .received_renegotiation_request()?;
483        let desc = AlertDescription::NoRenegotiation;
484        warn!("sending warning alert {desc:?}");
485        send.send_alert(AlertLevel::Warning, desc, tls);
486        Ok(true)
487    }
488
489    fn process_alert(&mut self, alert: &AlertMessagePayload) -> Result<(), Error> {
490        // Reject unknown AlertLevels.
491        if AlertLevelName::try_from(alert.level).is_err() {
492            return Err(PeerMisbehaved::IllegalAlertLevel(alert.level.0, alert.description).into());
493        }
494
495        // If we get a CloseNotify, make a note to declare EOF to our
496        // caller.  But do not treat unauthenticated alerts like this.
497        if self.may_receive_application_data && alert.description == AlertDescription::CloseNotify {
498            self.has_received_close_notify = true;
499            return Ok(());
500        }
501
502        // Warnings are nonfatal for TLS1.2, but outlawed in TLS1.3
503        // (except, for no good reason, user_cancelled).
504        let err = Error::AlertReceived(alert.description);
505        if alert.level == AlertLevel::Warning {
506            self.temper_counters
507                .received_warning_alert()?;
508            if matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
509                && alert.description != AlertDescription::UserCanceled
510            {
511                return Err(PeerMisbehaved::IllegalWarningAlert(alert.description).into());
512            }
513
514            // Some implementations send pointless `user_canceled` alerts, don't log them
515            // in release mode (https://bugs.openjdk.org/browse/JDK-8323517).
516            if alert.description != AlertDescription::UserCanceled || cfg!(debug_assertions) {
517                warn!("TLS alert warning received: {alert:?}");
518            }
519
520            return Ok(());
521        }
522
523        Err(err)
524    }
525}
526
527enum DeframeResult<'b> {
528    Decrypted(Decrypted<'b>, Range<usize>),
529    DecryptionFailed,
530    None,
531}
532
533struct CaptureAppData<'a, 'j, 'm, Send: SendOutput + 'a> {
534    recv: &'a mut ReceivePath,
535    other: &'a mut JoinOutput<'j, Send>,
536    tls: &'a mut Vec<u8>,
537    /// Store a [`Locator`] initialized from the current receive buffer
538    ///
539    /// Allows received plaintext data to be unborrowed and stored in
540    /// `received_plaintext` for in-place decryption.
541    plaintext_locator: &'a Locator,
542    /// Unborrowed received plaintext data
543    ///
544    /// Set if plaintext data was received.
545    ///
546    /// Plaintext data may be reborrowed using a [`Delocator`] which was
547    /// initialized from the same slice as `plaintext_locator`.
548    received_plaintext: &'a mut Option<DataKind<UnborrowedPayload>>,
549    _message_lifetime: PhantomData<&'m ()>,
550}
551
552impl<'a, 'm, Send: SendOutput + 'a> Output<'m> for CaptureAppData<'a, '_, 'm, Send> {
553    fn emit(&mut self, ev: Event) {
554        self.other.side.emit(ev)
555    }
556
557    fn output(&mut self, ev: OutputEvent<'_>) {
558        if let OutputEvent::ProtocolVersion(ver) = ev {
559            self.recv.negotiated_version = Some(ver);
560            self.other.send.negotiated_version(ver);
561        }
562        self.other.outputs.handle(ev);
563    }
564
565    fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool) {
566        match self.other.quic.as_deref_mut() {
567            Some(quic) => quic.send_msg(m, must_encrypt),
568            None => self
569                .other
570                .send
571                .send_msg(m, must_encrypt, self.tls),
572        }
573    }
574
575    fn quic(&mut self) -> Option<&mut dyn QuicOutput> {
576        match &mut self.other.quic {
577            Some(quic) => Some(*quic),
578            None => None,
579        }
580    }
581
582    fn received_plaintext(&mut self, payload: DataKind<Payload<'m>>) {
583        // Receive plaintext data [`Payload<'_>`].
584        //
585        // Since [`Context`] does not hold a lifetime to the receive buffer the
586        // passed [`Payload`] will have it's lifetime erased by storing an index
587        // into the receive buffer as an [`UnborrowedPayload`]. This enables the
588        // data to be later reborrowed after it has been decrypted in-place.
589        let previous = self
590            .received_plaintext
591            .replace(match payload {
592                DataKind::Early(p) => {
593                    DataKind::Early(UnborrowedPayload::unborrow(self.plaintext_locator, p))
594                }
595                DataKind::Traffic(p) => {
596                    DataKind::Traffic(UnborrowedPayload::unborrow(self.plaintext_locator, p))
597                }
598            });
599        debug_assert!(previous.is_none(), "overwrote plaintext data");
600    }
601
602    fn start_traffic(&mut self) {
603        self.recv.may_receive_application_data = true;
604        self.other.send.start_traffic();
605    }
606
607    fn receive(&mut self) -> &mut ReceivePath {
608        self.recv
609    }
610
611    fn send(&mut self) -> &mut dyn SendOutput {
612        self.other.send
613    }
614}
615
616pub(crate) enum DataKind<T> {
617    Early(T),
618    Traffic(T),
619}
620
621pub(super) struct JoinOutput<'a, Send: SendOutput + 'a> {
622    pub(super) outputs: &'a mut dyn ConnectionOutput,
623    pub(super) quic: Option<&'a mut dyn QuicOutput>,
624    pub(super) send: &'a mut Send,
625    pub(super) side: &'a mut dyn SideOutput,
626}
627
628pub(super) struct Discard;
629
630impl ConnectionOutput for Discard {
631    fn handle(&mut self, _ev: OutputEvent<'_>) {}
632}
633
634impl SideOutput for Discard {
635    fn emit(&mut self, _ev: Event) {}
636}
637
638/// Tracking technically-allowed protocol actions
639/// that we limit to avoid denial-of-service vectors.
640struct TemperCounters {
641    allowed_warning_alerts: u8,
642    allowed_renegotiation_requests: u8,
643    allowed_middlebox_ccs: u8,
644}
645
646impl TemperCounters {
647    fn received_warning_alert(&mut self) -> Result<(), Error> {
648        match self.allowed_warning_alerts {
649            0 => Err(PeerMisbehaved::TooManyWarningAlertsReceived.into()),
650            _ => {
651                self.allowed_warning_alerts -= 1;
652                Ok(())
653            }
654        }
655    }
656
657    fn received_renegotiation_request(&mut self) -> Result<(), Error> {
658        match self.allowed_renegotiation_requests {
659            0 => Err(PeerMisbehaved::TooManyRenegotiationRequests.into()),
660            _ => {
661                self.allowed_renegotiation_requests -= 1;
662                Ok(())
663            }
664        }
665    }
666
667    fn received_tls13_change_cipher_spec(&mut self) -> Result<(), Error> {
668        match self.allowed_middlebox_ccs {
669            0 => Err(PeerMisbehaved::IllegalMiddleboxChangeCipherSpec.into()),
670            _ => {
671                self.allowed_middlebox_ccs -= 1;
672                Ok(())
673            }
674        }
675    }
676}
677
678impl Default for TemperCounters {
679    fn default() -> Self {
680        Self {
681            // cf. BoringSSL `kMaxWarningAlerts`
682            // <https://github.com/google/boringssl/blob/dec5989b793c56ad4dd32173bd2d8595ca78b398/ssl/tls_record.cc#L137-L139>
683            allowed_warning_alerts: 4,
684
685            // we rebuff renegotiation requests with a `NoRenegotiation` warning alerts.
686            // a second request after this is fatal.
687            allowed_renegotiation_requests: 1,
688
689            // At most two CCS are allowed: one after each ClientHello (recall a second
690            // ClientHello happens after a HelloRetryRequest).
691            //
692            // note BoringSSL allows up to 32.
693            allowed_middlebox_ccs: 2,
694        }
695    }
696}
697
698pub(crate) struct TrafficTemperCounters {
699    allowed_consecutive_handshake_messages: u8,
700}
701
702impl TrafficTemperCounters {
703    pub(crate) fn received_handshake_message(&mut self) -> Result<(), Error> {
704        match self.allowed_consecutive_handshake_messages {
705            0 => Err(PeerMisbehaved::TooManyConsecutiveHandshakeMessagesAfterHandshake.into()),
706            _ => {
707                self.allowed_consecutive_handshake_messages -= 1;
708                Ok(())
709            }
710        }
711    }
712
713    pub(crate) fn received_app_data(&mut self) {
714        self.allowed_consecutive_handshake_messages = Self::MAX_CONSECUTIVE_HANDSHAKE_MESSAGES;
715    }
716
717    // cf. BoringSSL `kMaxKeyUpdates`
718    // <https://github.com/google/boringssl/blob/dec5989b793c56ad4dd32173bd2d8595ca78b398/ssl/tls13_both.cc#L35-L38>
719    const MAX_CONSECUTIVE_HANDSHAKE_MESSAGES: u8 = 32;
720}
721
722impl Default for TrafficTemperCounters {
723    fn default() -> Self {
724        Self {
725            allowed_consecutive_handshake_messages: Self::MAX_CONSECUTIVE_HANDSHAKE_MESSAGES,
726        }
727    }
728}
729
730pub(crate) struct Input<'a> {
731    pub(crate) message: Message<'a>,
732    pub(crate) aligned_handshake: Option<HandshakeAlignedProof>,
733}
734
735impl Input<'_> {
736    // Changing the keys must not span any fragmented handshake
737    // messages.  Otherwise the defragmented messages will have
738    // been protected with two different record layer protections,
739    // which is illegal.  Not mentioned in RFC.
740    pub(crate) fn check_aligned_handshake(&self) -> Result<HandshakeAlignedProof, Error> {
741        self.aligned_handshake
742            .ok_or_else(|| PeerMisbehaved::KeyEpochWithPendingFragment.into())
743    }
744}
745
746/// An [`Record<Payload<'_>>`] which does not borrow its payload, but
747/// references a range that can later be borrowed.
748struct InboundUnborrowedRecord {
749    typ: ContentType,
750    version: EncodableVersion,
751    bounds: Range<usize>,
752}
753
754impl InboundUnborrowedRecord {
755    fn unborrow(locator: &Locator, record: Record<&'_ [u8]>) -> Self {
756        Self {
757            typ: record.typ,
758            version: record.version,
759            bounds: locator.locate(record.payload),
760        }
761    }
762
763    fn reborrow<'b>(self, delocator: &Delocator<'b>) -> Record<&'b [u8]> {
764        Record {
765            typ: self.typ,
766            version: self.version,
767            payload: delocator.slice_from_range(&self.bounds),
768        }
769    }
770}
771
772/// A buffer of TLS bytes read from a socket, stored in a `Vec<u8>`.
773#[derive(Default, Debug)]
774pub struct VecInput {
775    /// Buffer of data read from the socket, in the process of being parsed into messages.
776    ///
777    /// For buffer size management, checkout out the [`VecInput::prepare_read()`] method.
778    buf: Vec<u8>,
779
780    /// What size prefix of `buf` is used.
781    used: usize,
782
783    /// Whether we've seen a 0-byte read.
784    has_seen_eof: bool,
785
786    /// Whether a CloseNotify alert has been seen.
787    received_close_notify: bool,
788}
789
790impl VecInput {
791    /// Discard `taken` bytes from the start of our buffer.
792    pub(crate) fn discard(&mut self, taken: usize) {
793        if taken < self.used {
794            /* Before:
795             * +----------+----------+----------+
796             * | taken    | pending  |xxxxxxxxxx|
797             * +----------+----------+----------+
798             * 0          ^ taken    ^ self.used
799             *
800             * After:
801             * +----------+----------+----------+
802             * | pending  |xxxxxxxxxxxxxxxxxxxxx|
803             * +----------+----------+----------+
804             * 0          ^ self.used
805             */
806
807            self.buf
808                .copy_within(taken..self.used, 0);
809            self.used -= taken;
810        } else if taken >= self.used {
811            self.used = 0;
812        }
813    }
814
815    pub(crate) fn filled_mut(&mut self) -> &mut [u8] {
816        &mut self.buf[..self.used]
817    }
818
819    /// Read some bytes from `rd`, and add them to the buffer.
820    ///
821    /// Once the buffer contains 64 kB of data, we will not read any more bytes until some
822    /// are consumed by reading from the buffer via
823    /// [`Connection::read_tls()`][super::Connection::read_tls()].
824    pub fn read(&mut self, rd: &mut dyn Read) -> io::Result<usize> {
825        if self.received_close_notify {
826            return Ok(0);
827        } else if let Err(err) = self.prepare_read() {
828            return Err(io::Error::new(io::ErrorKind::InvalidData, err));
829        }
830
831        // Try to do the largest reads possible. Note that if
832        // we get a record with a length field out of range here,
833        // we do a zero length read.  That looks like an EOF to
834        // the next layer up, which is fine.
835        let new_bytes = rd.read(&mut self.buf[self.used..])?;
836        if new_bytes == 0 {
837            self.has_seen_eof = true;
838        }
839
840        self.used += new_bytes;
841        Ok(new_bytes)
842    }
843
844    /// Resize the internal `buf` if necessary for reading more bytes.
845    fn prepare_read(&mut self) -> Result<(), &'static str> {
846        /// TLS allows for handshake messages of up to 16MB.  We
847        /// restrict that to 64KB to limit potential for denial-of-
848        /// service.
849        const MAX_HANDSHAKE_SIZE: usize = 0xffff;
850
851        const READ_SIZE: usize = 4096;
852
853        // We allow a maximum of 64k of buffered data. Given that the first read of such a
854        // payload will only ever be 4k bytes, the next time we come around here we allow a
855        // larger buffer size. Once the large message and any following handshake messages in
856        // the same flight have been consumed, `pop()` will call `discard()` to reset `used`.
857        // At this point, the buffer resizing logic below should reduce the buffer size.
858        if self.used >= MAX_HANDSHAKE_SIZE {
859            return Err("message buffer full");
860        }
861
862        // If we can and need to increase the buffer size to allow a 4k read, do so. After
863        // dealing with a large handshake message (exceeding `MAX_HANDSHAKE_SIZE`),
864        // make sure to reduce the buffer size again (large messages should be rare).
865        // Also, reduce the buffer size if there are neither full nor partial messages in it,
866        // which usually means that the other side suspended sending data.
867        let need_capacity = Ord::min(MAX_HANDSHAKE_SIZE, self.used + READ_SIZE);
868        if need_capacity > self.buf.len() {
869            self.buf.resize(need_capacity, 0);
870        } else if self.used == 0 || self.buf.len() > MAX_HANDSHAKE_SIZE {
871            self.buf.resize(need_capacity, 0);
872            self.buf.shrink_to(need_capacity);
873        }
874
875        Ok(())
876    }
877}
878
879impl TlsInputBuffer for VecInput {
880    fn slice_mut(&mut self) -> &mut [u8] {
881        self.filled_mut()
882    }
883
884    fn discard(&mut self, num_bytes: usize) {
885        self.discard(num_bytes)
886    }
887
888    fn received_close_notify(&mut self) {
889        self.received_close_notify = true;
890    }
891
892    fn has_seen_eof(&self) -> bool {
893        self.has_seen_eof
894    }
895}
896
897/// A borrowed version of [`VecInput`] that tracks discard operations
898#[derive(Debug)]
899pub struct SliceInput<'a> {
900    // a fully initialized buffer that will be deframed
901    buf: &'a mut [u8],
902    // number of bytes to discard from the front of `buf` at a later time
903    discard: usize,
904    /// Whether we've seen a 0-byte read.
905    has_seen_eof: bool,
906    /// Whether a CloseNotify alert has been seen.
907    received_close_notify: bool,
908}
909
910impl<'a> SliceInput<'a> {
911    /// Create a new [`SliceInput`] from a mutable slice of bytes.
912    pub fn new(buf: &'a mut [u8]) -> Self {
913        Self {
914            buf,
915            discard: 0,
916            has_seen_eof: false,
917            received_close_notify: false,
918        }
919    }
920
921    /// Returns how many bytes were consumed at the start of the original buffer.
922    pub fn into_used(self) -> usize {
923        self.discard
924    }
925}
926
927impl TlsInputBuffer for SliceInput<'_> {
928    fn slice_mut(&mut self) -> &mut [u8] {
929        &mut self.buf[self.discard..]
930    }
931
932    fn discard(&mut self, num_bytes: usize) {
933        self.discard += num_bytes;
934    }
935
936    fn received_close_notify(&mut self) {
937        self.received_close_notify = true;
938    }
939
940    fn has_seen_eof(&self) -> bool {
941        self.has_seen_eof
942    }
943}
944
945/// An abstraction over received data buffers (either owned or borrowed)
946pub trait TlsInputBuffer {
947    /// Return the buffer which contains the received data.
948    ///
949    /// If no data is available, return the empty slice.
950    ///
951    /// This is mutable, because the buffer is used for in-place decryption
952    /// and coalescing of TLS records.  Coalescing of TLS records can happen
953    /// incrementally over multiple calls into rustls.  As a result the
954    /// contents of this buffer must not be altered except to add new bytes
955    /// at the end.
956    fn slice_mut(&mut self) -> &mut [u8];
957
958    /// Discard `num_bytes` from the front of the buffer returned by `slice_mut()`.
959    ///
960    /// Multiple calls to `discard()` are cumulative, rather than "last wins".  In
961    /// other words, `discard(1)` followed by `discard(1)` gives the same result
962    /// as `discard(2)`.
963    ///
964    /// The next call to `slice_mut()` must reflect all previous `discard()`s. In
965    /// other words, if `slice_mut()` returns slice `[p..q]`, it should then
966    /// return `[p+n..q]` after `discard(n)`.
967    ///
968    /// Rustls guarantees it will not `discard()` more bytes than are returned
969    /// from `slice_mut()`.
970    fn discard(&mut self, num_bytes: usize);
971
972    /// Signal that the connection has received a TLS `close_notify` alert.
973    ///
974    /// The buffer should not accept any more data, because the peer has closed the connection.
975    fn received_close_notify(&mut self);
976
977    /// Whether the buffer has seen a TCP EOF.
978    ///
979    /// This is not a TCP-level event, but it is signalled to the TLS state via the input buffer.
980    fn has_seen_eof(&self) -> bool;
981}
982
983/// cf. BoringSSL's `kMaxEmptyRecords`
984/// <https://github.com/google/boringssl/blob/dec5989b793c56ad4dd32173bd2d8595ca78b398/ssl/tls_record.cc#L124-L128>
985const ALLOWED_CONSECUTIVE_EMPTY_FRAGMENTS_MAX: u8 = 32;