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::{
16 Decrypted, DecryptionState, EncodableVersion, EncodedMessage, Payload,
17};
18use crate::enums::{ContentType, HandshakeType, ProtocolVersion};
19use crate::error::{AlertDescription, Error, PeerMisbehaved};
20use crate::msgs::{
21 AlertLevel, AlertLevelName, AlertMessagePayload, Deframed, Deframer, Delocator,
22 HandshakeAlignedProof, Locator, Message, MessagePayload,
23};
24use crate::quic::QuicOutput;
25use crate::tracing::{trace, warn};
26
27pub(crate) struct MessageIter<'a, 'm, Side: SideData, Send: SendOutput + 'a> {
28 pub(super) input: &'m mut dyn TlsInputBuffer,
29 pub(super) tls: &'a mut Vec<u8>,
30 pub(super) recv: &'a mut ReceivePath,
31 pub(super) state: &'a mut Result<Side::State, Error>,
32 pub(super) output: JoinOutput<'a, Send>,
33}
34
35impl<'a, 'm, Side: SideData> MessageIter<'a, 'm, Side, SendPath> {
36 pub(crate) fn new(
37 input: &'m mut dyn TlsInputBuffer,
38 tls: &'a mut Vec<u8>,
39 quic: Option<&'a mut dyn QuicOutput>,
40 conn: &'a mut ConnectionCommon<Side>,
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 }
54 }
55}
56
57impl<'a, 'm, 's, Side: SideData> MessageIter<'a, 'm, Side, SendAdapter<'s>> {
58 pub(super) fn receive(
59 input: &'m mut dyn TlsInputBuffer,
60 tls: &'a mut Vec<u8>,
61 state: &'a mut Result<Side::State, Error>,
62 recv: &'a mut ReceivePath,
63 output: JoinOutput<'a, SendAdapter<'s>>,
64 ) -> Self {
65 Self {
66 input,
67 tls,
68 recv,
69 state,
70 output,
71 }
72 }
73}
74
75impl<'a, 'm, Side: SideData, Send: SendOutput + 'a> MessageIter<'a, 'm, Side, Send> {
76 pub(crate) fn next(&mut self) -> Option<Result<UnborrowedPayload, Error>> {
77 let mut st = match mem::replace(self.state, Err(Error::HandshakeNotComplete)) {
78 Ok(state) => state,
79 Err(e) => {
80 *self.state = Err(e.clone());
81 return Some(Err(e));
82 }
83 };
84
85 let mut plaintext = None;
86 while st.wants_input() {
87 let buffer = self.input.slice_mut();
88 let locator = Locator::new(buffer);
89 let res = self.recv.deframe(buffer);
90
91 let mut output = CaptureAppData {
92 recv: self.recv,
93 tls: self.tls,
94 other: &mut self.output,
95 plaintext_locator: &locator,
96 received_plaintext: &mut plaintext,
97 _message_lifetime: PhantomData,
98 };
99
100 let opt_msg = match res {
101 Ok(opt_msg) => opt_msg,
102 Err(e) => {
103 maybe_send_fatal_alert(output.other.send, &e, output.tls);
104 if let Error::DecryptError = e {
105 st.handle_decrypt_error();
106 }
107 *self.state = Err(e.clone());
108 return Some(Err(e));
109 }
110 };
111
112 let Some(msg) = opt_msg else {
113 break;
114 };
115
116 let Decrypted {
117 plaintext: msg,
118 want_close_before_decrypt,
119 } = msg;
120
121 if want_close_before_decrypt {
122 output.other.send.send_alert(
123 AlertLevel::Warning,
124 AlertDescription::CloseNotify,
125 output.tls,
126 );
127 } else if msg.payload.is_empty()
128 && matches!(msg.typ, ContentType::Handshake | ContentType::Alert)
129 {
130 output.other.send.send_alert(
132 AlertLevel::Fatal,
133 AlertDescription::UnexpectedMessage,
134 output.tls,
135 );
136 let error = Error::from(PeerMisbehaved::EmptyFragment);
137 *self.state = Err(error.clone());
138 return Some(Err(error));
139 }
140
141 let hs_aligned = output.recv.deframer.aligned();
142 let result =
143 match output
144 .recv
145 .receive_message(msg, hs_aligned, output.tls, output.other.send)
146 {
147 Ok(Some(input)) => st.handle(input, &mut output),
148 Ok(None) => Ok(st),
149 Err(e) => Err(e),
150 };
151
152 match result {
153 Ok(new) => st = new,
154 Err(e) => {
155 maybe_send_fatal_alert(output.other.send, &e, output.tls);
156 *self.state = Err(e.clone());
157 return Some(Err(e));
158 }
159 }
160
161 if self.recv.has_received_close_notify {
162 self.input
167 .discard(self.recv.deframer.take_discard());
168
169 let entirety = self.input.slice_mut().len();
171 self.recv.deframer.set_discard(entirety);
172 self.input.received_close_notify();
173 break;
174 }
175
176 if let Some(payload) = plaintext.take() {
177 *self.state = Ok(st);
178 return Some(Ok(payload));
179 }
180 }
181
182 *self.state = Ok(st);
183 None
184 }
185
186 pub(crate) fn state(&self) -> &Result<Side::State, Error> {
187 self.state
188 }
189}
190
191pub(crate) struct ReceivePath {
192 side: Side,
193 pub(crate) decrypt_state: DecryptionState,
194 pub(crate) may_receive_application_data: bool,
195 pub(crate) has_received_close_notify: bool,
197 temper_counters: TemperCounters,
198 pub(crate) negotiated_version: Option<ProtocolVersion>,
199 pub(crate) deframer: Deframer,
200
201 seen_consecutive_empty_fragments: u8,
204
205 pub(crate) tls13_tickets_received: u32,
206}
207
208impl ReceivePath {
209 pub(crate) fn new(side: Side) -> Self {
210 Self {
211 side,
212 decrypt_state: DecryptionState::new(),
213 may_receive_application_data: false,
214 has_received_close_notify: false,
215 temper_counters: TemperCounters::default(),
216 negotiated_version: None,
217 deframer: Deframer::default(),
218 seen_consecutive_empty_fragments: 0,
219 tls13_tickets_received: 0,
220 }
221 }
222
223 fn deframe<'b>(&mut self, buffer: &'b mut [u8]) -> Result<Option<Decrypted<'b>>, Error> {
225 let locator = Locator::new(buffer);
226
227 let mut want_close_before_decrypt = false;
228 loop {
229 if let Some(span) = self.deframer.complete_span() {
231 let plaintext = self.deframer.message(span, buffer);
232
233 self.decrypt_state
235 .finish_trial_decryption();
236
237 return Ok(Some(Decrypted {
238 plaintext,
239 want_close_before_decrypt,
240 }));
241 }
242
243 let (message, bounds) = loop {
244 match self.deframe_decrypted(buffer, &locator)? {
245 DeframeResult::Decrypted(decrypted, bounds) => break (decrypted, bounds),
246 DeframeResult::DecryptionFailed => continue,
247 DeframeResult::None => return Ok(None),
248 }
249 };
250
251 want_close_before_decrypt = message.want_close_before_decrypt;
252 let Decrypted {
253 plaintext: message,
254 want_close_before_decrypt: _,
255 } = message;
256
257 if self.deframer.aligned().is_none() && message.typ != ContentType::Handshake {
258 return Err(PeerMisbehaved::MessageInterleavedWithHandshakeMessage.into());
263 }
264
265 match message.payload.len() {
266 0 => {
267 if self.seen_consecutive_empty_fragments
268 == ALLOWED_CONSECUTIVE_EMPTY_FRAGMENTS_MAX
269 {
270 return Err(PeerMisbehaved::TooManyEmptyFragments.into());
271 }
272 self.seen_consecutive_empty_fragments += 1;
273 }
274 _ => {
275 self.seen_consecutive_empty_fragments = 0;
276 }
277 };
278
279 let unborrowed = InboundUnborrowedMessage::unborrow(&locator, message);
287
288 if unborrowed.typ != ContentType::Handshake {
289 let message = unborrowed.reborrow(&Delocator::new(buffer));
290 self.deframer.discard_processed();
291 return Ok(Some(Decrypted {
292 plaintext: message,
293 want_close_before_decrypt,
294 }));
295 }
296
297 let message = unborrowed.reborrow(&Delocator::new(buffer));
298 self.deframer
299 .input_message(message.version.version(), bounds, buffer);
300 self.deframer.coalesce(buffer)?;
301 }
302 }
303
304 fn deframe_decrypted<'b>(
305 &mut self,
306 buffer: &'b mut [u8],
307 locator: &Locator,
308 ) -> Result<DeframeResult<'b>, Error> {
309 let (message, bounds) = match self.deframer.deframe(buffer) {
310 Some(Ok(Deframed { message, bounds })) => (message, bounds),
311 Some(Err(err)) => return Err(err),
312 None => return Ok(DeframeResult::None),
313 };
314
315 let allowed_plaintext = match message.typ {
316 ContentType::ChangeCipherSpec => true,
318 ContentType::Alert
325 if matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
326 && !self.decrypt_state.has_decrypted()
327 && message.payload.len() <= 2 =>
328 {
329 true
330 }
331 _ => false,
333 };
334
335 if allowed_plaintext && !self.deframer.is_active() {
336 return Ok(DeframeResult::Decrypted(
337 Decrypted {
338 plaintext: message.into_plain_message(),
339 want_close_before_decrypt: false,
340 },
341 bounds,
342 ));
343 }
344
345 match self
346 .decrypt_state
347 .decrypt_incoming(message)?
348 {
349 Some(decrypted) => {
350 let bounds = locator.locate(decrypted.plaintext.payload);
352 Ok(DeframeResult::Decrypted(decrypted, bounds))
353 }
354
355 None if self.deframer.aligned().is_none() => {
358 Err(PeerMisbehaved::RejectedEarlyDataInterleavedWithHandshakeMessage.into())
359 }
360
361 None => Ok(DeframeResult::DecryptionFailed),
363 }
364 }
365
366 pub(crate) fn receive_message<'a>(
376 &mut self,
377 msg: EncodedMessage<&'a [u8]>,
378 aligned_handshake: Option<HandshakeAlignedProof>,
379 tls: &mut Vec<u8>,
380 send: &mut dyn SendOutput,
381 ) -> Result<Option<Input<'a>>, Error> {
382 if msg.typ == ContentType::ChangeCipherSpec && self.drop_tls13_ccs(&msg)? {
384 trace!("Dropping CCS");
385 return Ok(None);
386 }
387
388 let message = Message::try_from(msg)?;
390
391 if let MessagePayload::Alert(alert) = &message.payload {
393 self.process_alert(alert)?;
394 return Ok(None);
395 }
396
397 if self.reject_renegotiation_request(&message, tls, send)? {
400 return Ok(None);
401 }
402
403 Ok(Some(Input {
404 message,
405 aligned_handshake,
406 }))
407 }
408
409 fn drop_tls13_ccs(&mut self, msg: &EncodedMessage<&'_ [u8]>) -> Result<bool, Error> {
410 if self.may_receive_application_data
411 || !matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
412 {
413 return Ok(false);
414 }
415
416 if !msg.is_valid_ccs() {
417 return Err(PeerMisbehaved::IllegalMiddleboxChangeCipherSpec.into());
421 }
422
423 self.temper_counters
424 .received_tls13_change_cipher_spec()?;
425 Ok(true)
426 }
427
428 fn reject_renegotiation_request(
429 &mut self,
430 msg: &Message<'_>,
431 tls: &mut Vec<u8>,
432 send: &mut dyn SendOutput,
433 ) -> Result<bool, Error> {
434 if !self.may_receive_application_data
435 || matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
436 {
437 return Ok(false);
438 }
439
440 let reject_ty = match self.side {
441 Side::Client => HandshakeType::HelloRequest,
442 Side::Server => HandshakeType::ClientHello,
443 };
444
445 if msg.handshake_type() != Some(reject_ty) {
446 return Ok(false);
447 }
448 self.temper_counters
449 .received_renegotiation_request()?;
450 let desc = AlertDescription::NoRenegotiation;
451 warn!("sending warning alert {desc:?}");
452 send.send_alert(AlertLevel::Warning, desc, tls);
453 Ok(true)
454 }
455
456 fn process_alert(&mut self, alert: &AlertMessagePayload) -> Result<(), Error> {
457 if AlertLevelName::try_from(alert.level).is_err() {
459 return Err(PeerMisbehaved::IllegalAlertLevel(alert.level.0, alert.description).into());
460 }
461
462 if self.may_receive_application_data && alert.description == AlertDescription::CloseNotify {
465 self.has_received_close_notify = true;
466 return Ok(());
467 }
468
469 let err = Error::AlertReceived(alert.description);
472 if alert.level == AlertLevel::Warning {
473 self.temper_counters
474 .received_warning_alert()?;
475 if matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
476 && alert.description != AlertDescription::UserCanceled
477 {
478 return Err(PeerMisbehaved::IllegalWarningAlert(alert.description).into());
479 }
480
481 if alert.description != AlertDescription::UserCanceled || cfg!(debug_assertions) {
484 warn!("TLS alert warning received: {alert:?}");
485 }
486
487 return Ok(());
488 }
489
490 Err(err)
491 }
492}
493
494enum DeframeResult<'b> {
495 Decrypted(Decrypted<'b>, Range<usize>),
496 DecryptionFailed,
497 None,
498}
499
500struct CaptureAppData<'a, 'j, 'm, Send: SendOutput + 'a> {
501 recv: &'a mut ReceivePath,
502 other: &'a mut JoinOutput<'j, Send>,
503 tls: &'a mut Vec<u8>,
504 plaintext_locator: &'a Locator,
509 received_plaintext: &'a mut Option<UnborrowedPayload>,
516 _message_lifetime: PhantomData<&'m ()>,
517}
518
519impl<'a, 'm, Send: SendOutput + 'a> Output<'m> for CaptureAppData<'a, '_, 'm, Send> {
520 fn emit(&mut self, ev: Event<'_>) {
521 self.other.side.emit(ev)
522 }
523
524 fn output(&mut self, ev: OutputEvent<'_>) {
525 if let OutputEvent::ProtocolVersion(ver) = ev {
526 self.recv.negotiated_version = Some(ver);
527 self.other.send.negotiated_version(ver);
528 }
529 self.other.outputs.handle(ev);
530 }
531
532 fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool) {
533 match self.other.quic.as_deref_mut() {
534 Some(quic) => quic.send_msg(m, must_encrypt),
535 None => self
536 .other
537 .send
538 .send_msg(m, must_encrypt, self.tls),
539 }
540 }
541
542 fn quic(&mut self) -> Option<&mut dyn QuicOutput> {
543 match &mut self.other.quic {
544 Some(quic) => Some(*quic),
545 None => None,
546 }
547 }
548
549 fn received_plaintext(&mut self, payload: Payload<'m>) {
550 let previous = self
557 .received_plaintext
558 .replace(UnborrowedPayload::unborrow(self.plaintext_locator, payload));
559 debug_assert!(previous.is_none(), "overwrote plaintext data");
560 }
561
562 fn start_traffic(&mut self) {
563 self.recv.may_receive_application_data = true;
564 self.other.send.start_traffic();
565 }
566
567 fn receive(&mut self) -> &mut ReceivePath {
568 self.recv
569 }
570
571 fn send(&mut self) -> &mut dyn SendOutput {
572 self.other.send
573 }
574}
575
576pub(super) struct JoinOutput<'a, Send: SendOutput + 'a> {
577 pub(super) outputs: &'a mut dyn ConnectionOutput,
578 pub(super) quic: Option<&'a mut dyn QuicOutput>,
579 pub(super) send: &'a mut Send,
580 pub(super) side: &'a mut dyn SideOutput,
581}
582
583pub(super) struct Discard;
584
585impl ConnectionOutput for Discard {
586 fn handle(&mut self, _ev: OutputEvent<'_>) {}
587}
588
589impl SideOutput for Discard {
590 fn emit(&mut self, _ev: Event<'_>) {}
591}
592
593struct TemperCounters {
596 allowed_warning_alerts: u8,
597 allowed_renegotiation_requests: u8,
598 allowed_middlebox_ccs: u8,
599}
600
601impl TemperCounters {
602 fn received_warning_alert(&mut self) -> Result<(), Error> {
603 match self.allowed_warning_alerts {
604 0 => Err(PeerMisbehaved::TooManyWarningAlertsReceived.into()),
605 _ => {
606 self.allowed_warning_alerts -= 1;
607 Ok(())
608 }
609 }
610 }
611
612 fn received_renegotiation_request(&mut self) -> Result<(), Error> {
613 match self.allowed_renegotiation_requests {
614 0 => Err(PeerMisbehaved::TooManyRenegotiationRequests.into()),
615 _ => {
616 self.allowed_renegotiation_requests -= 1;
617 Ok(())
618 }
619 }
620 }
621
622 fn received_tls13_change_cipher_spec(&mut self) -> Result<(), Error> {
623 match self.allowed_middlebox_ccs {
624 0 => Err(PeerMisbehaved::IllegalMiddleboxChangeCipherSpec.into()),
625 _ => {
626 self.allowed_middlebox_ccs -= 1;
627 Ok(())
628 }
629 }
630 }
631}
632
633impl Default for TemperCounters {
634 fn default() -> Self {
635 Self {
636 allowed_warning_alerts: 4,
639
640 allowed_renegotiation_requests: 1,
643
644 allowed_middlebox_ccs: 2,
649 }
650 }
651}
652
653pub(crate) struct TrafficTemperCounters {
654 allowed_consecutive_handshake_messages: u8,
655}
656
657impl TrafficTemperCounters {
658 pub(crate) fn received_handshake_message(&mut self) -> Result<(), Error> {
659 match self.allowed_consecutive_handshake_messages {
660 0 => Err(PeerMisbehaved::TooManyConsecutiveHandshakeMessagesAfterHandshake.into()),
661 _ => {
662 self.allowed_consecutive_handshake_messages -= 1;
663 Ok(())
664 }
665 }
666 }
667
668 pub(crate) fn received_app_data(&mut self) {
669 self.allowed_consecutive_handshake_messages = Self::MAX_CONSECUTIVE_HANDSHAKE_MESSAGES;
670 }
671
672 const MAX_CONSECUTIVE_HANDSHAKE_MESSAGES: u8 = 32;
675}
676
677impl Default for TrafficTemperCounters {
678 fn default() -> Self {
679 Self {
680 allowed_consecutive_handshake_messages: Self::MAX_CONSECUTIVE_HANDSHAKE_MESSAGES,
681 }
682 }
683}
684
685pub(crate) struct Input<'a> {
686 pub(crate) message: Message<'a>,
687 pub(crate) aligned_handshake: Option<HandshakeAlignedProof>,
688}
689
690impl Input<'_> {
691 pub(crate) fn check_aligned_handshake(&self) -> Result<HandshakeAlignedProof, Error> {
696 self.aligned_handshake
697 .ok_or_else(|| PeerMisbehaved::KeyEpochWithPendingFragment.into())
698 }
699}
700
701struct InboundUnborrowedMessage {
704 typ: ContentType,
705 version: EncodableVersion,
706 bounds: Range<usize>,
707}
708
709impl InboundUnborrowedMessage {
710 fn unborrow(locator: &Locator, msg: EncodedMessage<&'_ [u8]>) -> Self {
711 Self {
712 typ: msg.typ,
713 version: msg.version,
714 bounds: locator.locate(msg.payload),
715 }
716 }
717
718 fn reborrow<'b>(self, delocator: &Delocator<'b>) -> EncodedMessage<&'b [u8]> {
719 EncodedMessage {
720 typ: self.typ,
721 version: self.version,
722 payload: delocator.slice_from_range(&self.bounds),
723 }
724 }
725}
726
727#[derive(Default, Debug)]
729pub struct VecInput {
730 buf: Vec<u8>,
734
735 used: usize,
737
738 has_seen_eof: bool,
740
741 received_close_notify: bool,
743}
744
745impl VecInput {
746 pub(crate) fn discard(&mut self, taken: usize) {
748 if taken < self.used {
749 self.buf
763 .copy_within(taken..self.used, 0);
764 self.used -= taken;
765 } else if taken >= self.used {
766 self.used = 0;
767 }
768 }
769
770 pub(crate) fn filled_mut(&mut self) -> &mut [u8] {
771 &mut self.buf[..self.used]
772 }
773
774 pub fn read(&mut self, rd: &mut dyn Read) -> io::Result<usize> {
780 if self.received_close_notify {
781 return Ok(0);
782 } else if let Err(err) = self.prepare_read() {
783 return Err(io::Error::new(io::ErrorKind::InvalidData, err));
784 }
785
786 let new_bytes = rd.read(&mut self.buf[self.used..])?;
791 if new_bytes == 0 {
792 self.has_seen_eof = true;
793 }
794
795 self.used += new_bytes;
796 Ok(new_bytes)
797 }
798
799 fn prepare_read(&mut self) -> Result<(), &'static str> {
801 const MAX_HANDSHAKE_SIZE: usize = 0xffff;
805
806 const READ_SIZE: usize = 4096;
807
808 if self.used >= MAX_HANDSHAKE_SIZE {
814 return Err("message buffer full");
815 }
816
817 let need_capacity = Ord::min(MAX_HANDSHAKE_SIZE, self.used + READ_SIZE);
823 if need_capacity > self.buf.len() {
824 self.buf.resize(need_capacity, 0);
825 } else if self.used == 0 || self.buf.len() > MAX_HANDSHAKE_SIZE {
826 self.buf.resize(need_capacity, 0);
827 self.buf.shrink_to(need_capacity);
828 }
829
830 Ok(())
831 }
832}
833
834impl TlsInputBuffer for VecInput {
835 fn slice_mut(&mut self) -> &mut [u8] {
836 self.filled_mut()
837 }
838
839 fn discard(&mut self, num_bytes: usize) {
840 self.discard(num_bytes)
841 }
842
843 fn received_close_notify(&mut self) {
844 self.received_close_notify = true;
845 }
846
847 fn has_seen_eof(&self) -> bool {
848 self.has_seen_eof
849 }
850}
851
852#[derive(Debug)]
854pub struct SliceInput<'a> {
855 buf: &'a mut [u8],
857 discard: usize,
859 has_seen_eof: bool,
861 received_close_notify: bool,
863}
864
865impl<'a> SliceInput<'a> {
866 pub fn new(buf: &'a mut [u8]) -> Self {
868 Self {
869 buf,
870 discard: 0,
871 has_seen_eof: false,
872 received_close_notify: false,
873 }
874 }
875
876 pub fn into_used(self) -> usize {
878 self.discard
879 }
880}
881
882impl TlsInputBuffer for SliceInput<'_> {
883 fn slice_mut(&mut self) -> &mut [u8] {
884 &mut self.buf[self.discard..]
885 }
886
887 fn discard(&mut self, num_bytes: usize) {
888 self.discard += num_bytes;
889 }
890
891 fn received_close_notify(&mut self) {
892 self.received_close_notify = true;
893 }
894
895 fn has_seen_eof(&self) -> bool {
896 self.has_seen_eof
897 }
898}
899
900pub trait TlsInputBuffer {
902 fn slice_mut(&mut self) -> &mut [u8];
912
913 fn discard(&mut self, num_bytes: usize);
926
927 fn received_close_notify(&mut self);
931
932 fn has_seen_eof(&self) -> bool;
936}
937
938const ALLOWED_CONSECUTIVE_EMPTY_FRAGMENTS_MAX: u8 = 32;