1use alloc::vec::Vec;
2use core::marker::PhantomData;
3use core::mem;
4use core::ops::Range;
5use std::io::{self, Read};
6
7use super::SendOutput;
8use crate::SideData;
9use crate::common_state::{
10 ConnectionOutput, Event, Output, OutputEvent, Side, UnborrowedPayload, maybe_send_fatal_alert,
11};
12use crate::conn::private::SideOutput;
13use crate::conn::{ConnectionCore, StateMachine};
14use crate::crypto::cipher::{Decrypted, DecryptionState, EncodedMessage, Payload};
15use crate::enums::{ContentType, HandshakeType, ProtocolVersion};
16use crate::error::{AlertDescription, Error, PeerMisbehaved};
17use crate::log::{trace, warn};
18use crate::msgs::{
19 AlertLevel, AlertLevelName, AlertMessagePayload, Deframed, Deframer, Delocator,
20 HandshakeAlignedProof, Locator, Message, MessagePayload,
21};
22use crate::quic::QuicOutput;
23
24pub(crate) struct MessageIter<'a, 'm, Side: SideData> {
25 input: &'m mut dyn TlsInputBuffer,
26 recv: &'a mut ReceivePath,
27 state: &'a mut Result<Side::State, Error>,
28 output: JoinOutput<'a>,
29}
30
31impl<'a, 'm, Side: SideData> MessageIter<'a, 'm, Side> {
32 pub(crate) fn new(
33 input: &'m mut dyn TlsInputBuffer,
34 quic: Option<&'a mut dyn QuicOutput>,
35 conn: &'a mut ConnectionCore<Side>,
36 ) -> Self {
37 Self {
38 recv: &mut conn.common.recv,
39 input,
40 state: &mut conn.state,
41 output: JoinOutput {
42 outputs: &mut conn.common.outputs,
43 quic,
44 send: &mut conn.common.send,
45 side: &mut conn.side,
46 },
47 }
48 }
49
50 pub(super) fn receive(
51 input: &'m mut dyn TlsInputBuffer,
52 state: &'a mut Result<Side::State, Error>,
53 recv: &'a mut ReceivePath,
54 output: JoinOutput<'a>,
55 ) -> Self {
56 Self {
57 recv,
58 input,
59 state,
60 output,
61 }
62 }
63
64 pub(crate) fn next(&mut self) -> Option<Result<UnborrowedPayload, Error>> {
65 let mut st = match mem::replace(self.state, Err(Error::HandshakeNotComplete)) {
66 Ok(state) => state,
67 Err(e) => {
68 *self.state = Err(e.clone());
69 return Some(Err(e));
70 }
71 };
72
73 let mut plaintext = None;
74 while st.wants_input() {
75 let buffer = self.input.slice_mut();
76 let locator = Locator::new(buffer);
77 let res = self.recv.deframe(buffer);
78
79 let mut output = CaptureAppData {
80 recv: self.recv,
81 other: &mut self.output,
82 plaintext_locator: &locator,
83 received_plaintext: &mut plaintext,
84 _message_lifetime: PhantomData,
85 };
86
87 let opt_msg = match res {
88 Ok(opt_msg) => opt_msg,
89 Err(e) => {
90 maybe_send_fatal_alert(output.other.send, &e);
91 if let Error::DecryptError = e {
92 st.handle_decrypt_error();
93 }
94 *self.state = Err(e.clone());
95 return Some(Err(e));
96 }
97 };
98
99 let Some(msg) = opt_msg else {
100 break;
101 };
102
103 let Decrypted {
104 plaintext: msg,
105 want_close_before_decrypt,
106 } = msg;
107
108 if want_close_before_decrypt {
109 output
110 .other
111 .send
112 .send_alert(AlertLevel::Warning, AlertDescription::CloseNotify);
113 } else if msg.payload.is_empty()
114 && matches!(msg.typ, ContentType::Handshake | ContentType::Alert)
115 {
116 output
118 .other
119 .send
120 .send_alert(AlertLevel::Fatal, AlertDescription::UnexpectedMessage);
121 return Some(Err(PeerMisbehaved::EmptyFragment.into()));
122 }
123
124 let hs_aligned = output.recv.deframer.aligned();
125 let result = match output
126 .recv
127 .receive_message(msg, hs_aligned, output.other.send)
128 {
129 Ok(Some(input)) => st.handle(input, &mut output),
130 Ok(None) => Ok(st),
131 Err(e) => Err(e),
132 };
133
134 match result {
135 Ok(new) => st = new,
136 Err(e) => {
137 maybe_send_fatal_alert(output.other.send, &e);
138 *self.state = Err(e.clone());
139 return Some(Err(e));
140 }
141 }
142
143 if self.recv.has_received_close_notify {
144 self.input
149 .discard(self.recv.deframer.take_discard());
150
151 let entirety = self.input.slice_mut().len();
153 self.recv.deframer.set_discard(entirety);
154 self.input.received_close_notify();
155 break;
156 }
157
158 if let Some(payload) = plaintext.take() {
159 *self.state = Ok(st);
160 return Some(Ok(payload));
161 }
162 }
163
164 *self.state = Ok(st);
165 None
166 }
167
168 pub(super) fn input(&mut self) -> &mut dyn TlsInputBuffer {
169 self.input
170 }
171
172 pub(crate) fn state(&self) -> &Result<Side::State, Error> {
173 self.state
174 }
175}
176
177pub(crate) struct ReceivePath {
178 side: Side,
179 pub(crate) decrypt_state: DecryptionState,
180 pub(crate) may_receive_application_data: bool,
181 pub(crate) has_received_close_notify: bool,
183 temper_counters: TemperCounters,
184 pub(crate) negotiated_version: Option<ProtocolVersion>,
185 pub(crate) deframer: Deframer,
186
187 seen_consecutive_empty_fragments: u8,
190
191 pub(crate) tls13_tickets_received: u32,
192}
193
194impl ReceivePath {
195 pub(crate) fn new(side: Side) -> Self {
196 Self {
197 side,
198 decrypt_state: DecryptionState::new(),
199 may_receive_application_data: false,
200 has_received_close_notify: false,
201 temper_counters: TemperCounters::default(),
202 negotiated_version: None,
203 deframer: Deframer::default(),
204 seen_consecutive_empty_fragments: 0,
205 tls13_tickets_received: 0,
206 }
207 }
208
209 fn deframe<'b>(&mut self, buffer: &'b mut [u8]) -> Result<Option<Decrypted<'b>>, Error> {
211 let locator = Locator::new(buffer);
212
213 let mut want_close_before_decrypt = false;
214 loop {
215 if let Some(span) = self.deframer.complete_span() {
217 let plaintext = self.deframer.message(span, buffer);
218
219 self.decrypt_state
221 .finish_trial_decryption();
222
223 return Ok(Some(Decrypted {
224 plaintext,
225 want_close_before_decrypt,
226 }));
227 }
228
229 let (message, bounds) = loop {
230 match self.deframe_decrypted(buffer, &locator)? {
231 DeframeResult::Decrypted(decrypted, bounds) => break (decrypted, bounds),
232 DeframeResult::DecryptionFailed => continue,
233 DeframeResult::None => return Ok(None),
234 }
235 };
236
237 want_close_before_decrypt = message.want_close_before_decrypt;
238 let Decrypted {
239 plaintext: message,
240 want_close_before_decrypt: _,
241 } = message;
242
243 if self.deframer.aligned().is_none() && message.typ != ContentType::Handshake {
244 return Err(PeerMisbehaved::MessageInterleavedWithHandshakeMessage.into());
249 }
250
251 match message.payload.len() {
252 0 => {
253 if self.seen_consecutive_empty_fragments
254 == ALLOWED_CONSECUTIVE_EMPTY_FRAGMENTS_MAX
255 {
256 return Err(PeerMisbehaved::TooManyEmptyFragments.into());
257 }
258 self.seen_consecutive_empty_fragments += 1;
259 }
260 _ => {
261 self.seen_consecutive_empty_fragments = 0;
262 }
263 };
264
265 let unborrowed = InboundUnborrowedMessage::unborrow(&locator, message);
273
274 if unborrowed.typ != ContentType::Handshake {
275 let message = unborrowed.reborrow(&Delocator::new(buffer));
276 self.deframer.discard_processed();
277 return Ok(Some(Decrypted {
278 plaintext: message,
279 want_close_before_decrypt,
280 }));
281 }
282
283 let message = unborrowed.reborrow(&Delocator::new(buffer));
284 self.deframer
285 .input_message(message.version, bounds, buffer);
286 self.deframer.coalesce(buffer)?;
287 }
288 }
289
290 fn deframe_decrypted<'b>(
291 &mut self,
292 buffer: &'b mut [u8],
293 locator: &Locator,
294 ) -> Result<DeframeResult<'b>, Error> {
295 let (message, bounds) = match self.deframer.deframe(buffer) {
296 Some(Ok(Deframed { message, bounds })) => (message, bounds),
297 Some(Err(err)) => return Err(err),
298 None => return Ok(DeframeResult::None),
299 };
300
301 let allowed_plaintext = match message.typ {
302 ContentType::ChangeCipherSpec => true,
304 ContentType::Alert
311 if matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
312 && !self.decrypt_state.has_decrypted()
313 && message.payload.len() <= 2 =>
314 {
315 true
316 }
317 _ => false,
319 };
320
321 if allowed_plaintext && !self.deframer.is_active() {
322 return Ok(DeframeResult::Decrypted(
323 Decrypted {
324 plaintext: message.into_plain_message(),
325 want_close_before_decrypt: false,
326 },
327 bounds,
328 ));
329 }
330
331 match self
332 .decrypt_state
333 .decrypt_incoming(message)?
334 {
335 Some(decrypted) => {
336 let bounds = locator.locate(decrypted.plaintext.payload);
338 Ok(DeframeResult::Decrypted(decrypted, bounds))
339 }
340
341 None if self.deframer.aligned().is_none() => {
344 Err(PeerMisbehaved::RejectedEarlyDataInterleavedWithHandshakeMessage.into())
345 }
346
347 None => Ok(DeframeResult::DecryptionFailed),
349 }
350 }
351
352 pub(crate) fn receive_message<'a>(
362 &mut self,
363 msg: EncodedMessage<&'a [u8]>,
364 aligned_handshake: Option<HandshakeAlignedProof>,
365 send: &mut dyn SendOutput,
366 ) -> Result<Option<Input<'a>>, Error> {
367 if msg.typ == ContentType::ChangeCipherSpec && self.drop_tls13_ccs(&msg)? {
369 trace!("Dropping CCS");
370 return Ok(None);
371 }
372
373 let message = Message::try_from(msg)?;
375
376 if let MessagePayload::Alert(alert) = &message.payload {
378 self.process_alert(alert)?;
379 return Ok(None);
380 }
381
382 if self.reject_renegotiation_request(&message, send)? {
385 return Ok(None);
386 }
387
388 Ok(Some(Input {
389 message,
390 aligned_handshake,
391 }))
392 }
393
394 fn drop_tls13_ccs(&mut self, msg: &EncodedMessage<&'_ [u8]>) -> Result<bool, Error> {
395 if self.may_receive_application_data
396 || !matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
397 {
398 return Ok(false);
399 }
400
401 if !msg.is_valid_ccs() {
402 return Err(PeerMisbehaved::IllegalMiddleboxChangeCipherSpec.into());
406 }
407
408 self.temper_counters
409 .received_tls13_change_cipher_spec()?;
410 Ok(true)
411 }
412
413 fn reject_renegotiation_request(
414 &mut self,
415 msg: &Message<'_>,
416 send: &mut dyn SendOutput,
417 ) -> Result<bool, Error> {
418 if !self.may_receive_application_data
419 || matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
420 {
421 return Ok(false);
422 }
423
424 let reject_ty = match self.side {
425 Side::Client => HandshakeType::HelloRequest,
426 Side::Server => HandshakeType::ClientHello,
427 };
428
429 if msg.handshake_type() != Some(reject_ty) {
430 return Ok(false);
431 }
432 self.temper_counters
433 .received_renegotiation_request()?;
434 let desc = AlertDescription::NoRenegotiation;
435 warn!("sending warning alert {desc:?}");
436 send.send_alert(AlertLevel::Warning, desc);
437 Ok(true)
438 }
439
440 fn process_alert(&mut self, alert: &AlertMessagePayload) -> Result<(), Error> {
441 if AlertLevelName::try_from(alert.level).is_err() {
443 return Err(PeerMisbehaved::IllegalAlertLevel(alert.level.0, alert.description).into());
444 }
445
446 if self.may_receive_application_data && alert.description == AlertDescription::CloseNotify {
449 self.has_received_close_notify = true;
450 return Ok(());
451 }
452
453 let err = Error::AlertReceived(alert.description);
456 if alert.level == AlertLevel::Warning {
457 self.temper_counters
458 .received_warning_alert()?;
459 if matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
460 && alert.description != AlertDescription::UserCanceled
461 {
462 return Err(PeerMisbehaved::IllegalWarningAlert(alert.description).into());
463 }
464
465 if alert.description != AlertDescription::UserCanceled || cfg!(debug_assertions) {
468 warn!("TLS alert warning received: {alert:?}");
469 }
470
471 return Ok(());
472 }
473
474 Err(err)
475 }
476}
477
478enum DeframeResult<'b> {
479 Decrypted(Decrypted<'b>, Range<usize>),
480 DecryptionFailed,
481 None,
482}
483
484struct CaptureAppData<'a, 'j, 'm> {
485 recv: &'a mut ReceivePath,
486 other: &'a mut JoinOutput<'j>,
487 plaintext_locator: &'a Locator,
492 received_plaintext: &'a mut Option<UnborrowedPayload>,
499 _message_lifetime: PhantomData<&'m ()>,
500}
501
502impl<'m> Output<'m> for CaptureAppData<'_, '_, 'm> {
503 fn emit(&mut self, ev: Event<'_>) {
504 self.other.side.emit(ev)
505 }
506
507 fn output(&mut self, ev: OutputEvent<'_>) {
508 if let OutputEvent::ProtocolVersion(ver) = ev {
509 self.recv.negotiated_version = Some(ver);
510 self.other.send.negotiated_version(ver);
511 }
512 self.other.outputs.handle(ev);
513 }
514
515 fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool) {
516 match self.other.quic.as_deref_mut() {
517 Some(quic) => quic.send_msg(m, must_encrypt),
518 None => self
519 .other
520 .send
521 .send_msg(m, must_encrypt),
522 }
523 }
524
525 fn quic(&mut self) -> Option<&mut dyn QuicOutput> {
526 match &mut self.other.quic {
527 Some(quic) => Some(*quic),
528 None => None,
529 }
530 }
531
532 fn received_plaintext(&mut self, payload: Payload<'m>) {
533 let previous = self
540 .received_plaintext
541 .replace(UnborrowedPayload::unborrow(self.plaintext_locator, payload));
542 debug_assert!(previous.is_none(), "overwrote plaintext data");
543 }
544
545 fn start_traffic(&mut self) {
546 self.recv.may_receive_application_data = true;
547 self.other.send.start_traffic();
548 }
549
550 fn receive(&mut self) -> &mut ReceivePath {
551 self.recv
552 }
553
554 fn send(&mut self) -> &mut dyn SendOutput {
555 self.other.send
556 }
557}
558
559pub(super) struct JoinOutput<'a> {
560 pub(super) outputs: &'a mut dyn ConnectionOutput,
561 pub(super) quic: Option<&'a mut dyn QuicOutput>,
562 pub(super) send: &'a mut dyn SendOutput,
563 pub(super) side: &'a mut dyn SideOutput,
564}
565
566pub(super) struct Discard;
567
568impl ConnectionOutput for Discard {
569 fn handle(&mut self, _ev: OutputEvent<'_>) {}
570}
571
572impl SideOutput for Discard {
573 fn emit(&mut self, _ev: Event<'_>) {}
574}
575
576struct TemperCounters {
579 allowed_warning_alerts: u8,
580 allowed_renegotiation_requests: u8,
581 allowed_middlebox_ccs: u8,
582}
583
584impl TemperCounters {
585 fn received_warning_alert(&mut self) -> Result<(), Error> {
586 match self.allowed_warning_alerts {
587 0 => Err(PeerMisbehaved::TooManyWarningAlertsReceived.into()),
588 _ => {
589 self.allowed_warning_alerts -= 1;
590 Ok(())
591 }
592 }
593 }
594
595 fn received_renegotiation_request(&mut self) -> Result<(), Error> {
596 match self.allowed_renegotiation_requests {
597 0 => Err(PeerMisbehaved::TooManyRenegotiationRequests.into()),
598 _ => {
599 self.allowed_renegotiation_requests -= 1;
600 Ok(())
601 }
602 }
603 }
604
605 fn received_tls13_change_cipher_spec(&mut self) -> Result<(), Error> {
606 match self.allowed_middlebox_ccs {
607 0 => Err(PeerMisbehaved::IllegalMiddleboxChangeCipherSpec.into()),
608 _ => {
609 self.allowed_middlebox_ccs -= 1;
610 Ok(())
611 }
612 }
613 }
614}
615
616impl Default for TemperCounters {
617 fn default() -> Self {
618 Self {
619 allowed_warning_alerts: 4,
622
623 allowed_renegotiation_requests: 1,
626
627 allowed_middlebox_ccs: 2,
632 }
633 }
634}
635
636pub(crate) struct TrafficTemperCounters {
637 allowed_consecutive_handshake_messages: u8,
638}
639
640impl TrafficTemperCounters {
641 pub(crate) fn received_handshake_message(&mut self) -> Result<(), Error> {
642 match self.allowed_consecutive_handshake_messages {
643 0 => Err(PeerMisbehaved::TooManyConsecutiveHandshakeMessagesAfterHandshake.into()),
644 _ => {
645 self.allowed_consecutive_handshake_messages -= 1;
646 Ok(())
647 }
648 }
649 }
650
651 pub(crate) fn received_app_data(&mut self) {
652 self.allowed_consecutive_handshake_messages = Self::MAX_CONSECUTIVE_HANDSHAKE_MESSAGES;
653 }
654
655 const MAX_CONSECUTIVE_HANDSHAKE_MESSAGES: u8 = 32;
658}
659
660impl Default for TrafficTemperCounters {
661 fn default() -> Self {
662 Self {
663 allowed_consecutive_handshake_messages: Self::MAX_CONSECUTIVE_HANDSHAKE_MESSAGES,
664 }
665 }
666}
667
668pub(crate) struct Input<'a> {
669 pub(crate) message: Message<'a>,
670 pub(crate) aligned_handshake: Option<HandshakeAlignedProof>,
671}
672
673impl Input<'_> {
674 pub(crate) fn check_aligned_handshake(&self) -> Result<HandshakeAlignedProof, Error> {
679 self.aligned_handshake
680 .ok_or_else(|| PeerMisbehaved::KeyEpochWithPendingFragment.into())
681 }
682}
683
684struct InboundUnborrowedMessage {
687 typ: ContentType,
688 version: ProtocolVersion,
689 bounds: Range<usize>,
690}
691
692impl InboundUnborrowedMessage {
693 fn unborrow(locator: &Locator, msg: EncodedMessage<&'_ [u8]>) -> Self {
694 Self {
695 typ: msg.typ,
696 version: msg.version,
697 bounds: locator.locate(msg.payload),
698 }
699 }
700
701 fn reborrow<'b>(self, delocator: &Delocator<'b>) -> EncodedMessage<&'b [u8]> {
702 EncodedMessage {
703 typ: self.typ,
704 version: self.version,
705 payload: delocator.slice_from_range(&self.bounds),
706 }
707 }
708}
709
710#[derive(Default, Debug)]
712pub struct VecInput {
713 buf: Vec<u8>,
717
718 used: usize,
720
721 has_seen_eof: bool,
723
724 received_close_notify: bool,
726}
727
728impl VecInput {
729 pub(crate) fn discard(&mut self, taken: usize) {
731 if taken < self.used {
732 self.buf
746 .copy_within(taken..self.used, 0);
747 self.used -= taken;
748 } else if taken >= self.used {
749 self.used = 0;
750 }
751 }
752
753 pub(crate) fn filled_mut(&mut self) -> &mut [u8] {
754 &mut self.buf[..self.used]
755 }
756
757 pub fn read(&mut self, rd: &mut dyn Read) -> io::Result<usize> {
759 if self.received_close_notify {
760 return Ok(0);
761 } else if let Err(err) = self.prepare_read() {
762 return Err(io::Error::new(io::ErrorKind::InvalidData, err));
763 }
764
765 let new_bytes = rd.read(&mut self.buf[self.used..])?;
770 if new_bytes == 0 {
771 self.has_seen_eof = true;
772 }
773
774 self.used += new_bytes;
775 Ok(new_bytes)
776 }
777
778 fn prepare_read(&mut self) -> Result<(), &'static str> {
780 const MAX_HANDSHAKE_SIZE: usize = 0xffff;
784
785 const READ_SIZE: usize = 4096;
786
787 if self.used >= MAX_HANDSHAKE_SIZE {
793 return Err("message buffer full");
794 }
795
796 let need_capacity = Ord::min(MAX_HANDSHAKE_SIZE, self.used + READ_SIZE);
802 if need_capacity > self.buf.len() {
803 self.buf.resize(need_capacity, 0);
804 } else if self.used == 0 || self.buf.len() > MAX_HANDSHAKE_SIZE {
805 self.buf.resize(need_capacity, 0);
806 self.buf.shrink_to(need_capacity);
807 }
808
809 Ok(())
810 }
811}
812
813impl TlsInputBuffer for VecInput {
814 fn slice_mut(&mut self) -> &mut [u8] {
815 self.filled_mut()
816 }
817
818 fn discard(&mut self, num_bytes: usize) {
819 self.discard(num_bytes)
820 }
821
822 fn received_close_notify(&mut self) {
823 self.received_close_notify = true;
824 }
825
826 fn has_seen_eof(&self) -> bool {
827 self.has_seen_eof
828 }
829}
830
831#[derive(Debug)]
833pub struct SliceInput<'a> {
834 buf: &'a mut [u8],
836 discard: usize,
838 has_seen_eof: bool,
840 received_close_notify: bool,
842}
843
844impl<'a> SliceInput<'a> {
845 pub fn new(buf: &'a mut [u8]) -> Self {
847 Self {
848 buf,
849 discard: 0,
850 has_seen_eof: false,
851 received_close_notify: false,
852 }
853 }
854
855 pub fn into_used(self) -> usize {
857 self.discard
858 }
859}
860
861impl TlsInputBuffer for SliceInput<'_> {
862 fn slice_mut(&mut self) -> &mut [u8] {
863 &mut self.buf[self.discard..]
864 }
865
866 fn discard(&mut self, num_bytes: usize) {
867 self.discard += num_bytes;
868 }
869
870 fn received_close_notify(&mut self) {
871 self.received_close_notify = true;
872 }
873
874 fn has_seen_eof(&self) -> bool {
875 self.has_seen_eof
876 }
877}
878
879pub trait TlsInputBuffer {
881 fn slice_mut(&mut self) -> &mut [u8];
891
892 fn discard(&mut self, num_bytes: usize);
905
906 fn received_close_notify(&mut self);
910
911 fn has_seen_eof(&self) -> bool;
915}
916
917const ALLOWED_CONSECUTIVE_EMPTY_FRAGMENTS_MAX: u8 = 32;