1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::marker::PhantomData;
4use core::ops::Range;
5use core::{fmt, mem};
6use std::io::{self, Read};
7
8use super::private::SideOutput;
9use super::send::{SendOutput, SendPath};
10use super::split::SendAdapter;
11use super::{Connection, SEQ_SOFT_LIMIT, SideData, StateMachine, Transport};
12use crate::common_state::{
13 ConnectionOutput, Event, Output, OutputEvent, Side, UnborrowedPayload, maybe_send_fatal_alert,
14};
15use crate::crypto::cipher::{EncodableVersion, InboundOpaque, Payload, Record, RecordDecrypter};
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<T: Transport>(
36 input: &'m mut dyn TlsInputBuffer,
37 tls: &'a mut Vec<u8>,
38 conn: &'a mut Connection<Side, T>,
39 mode: MessageIterMode,
40 ) -> Self {
41 Self {
42 input,
43 tls,
44 recv: &mut conn.common.recv,
45 state: &mut conn.state,
46 output: JoinOutput {
47 outputs: &mut conn.common.outputs,
48 quic: conn.transport.quic(),
49 send: &mut conn.common.send,
50 side: &mut conn.side,
51 },
52 mode,
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 mode: MessageIterMode,
65 ) -> Self {
66 Self {
67 input,
68 tls,
69 recv,
70 state,
71 output,
72 mode,
73 }
74 }
75}
76
77impl<'a, 'm, Side: SideData, Send: SendOutput + 'a> MessageIter<'a, 'm, Side, Send> {
78 pub(crate) fn next(&mut self, early_only: bool) -> Option<Result<UnborrowedPayload, Error>> {
79 let mut st = match mem::replace(self.state, Err(Error::HandshakeNotComplete)) {
80 Ok(state) => state,
81 Err(e) => {
82 *self.state = Err(e.clone());
83 return Some(Err(e));
84 }
85 };
86
87 let mut plaintext = None;
88 while st.wants_input() {
89 let buffer = self.input.slice_mut();
90 let locator = Locator::new(buffer);
91 let res = self.recv.deframe(buffer);
92
93 let mut output = CaptureAppData {
94 recv: self.recv,
95 tls: self.tls,
96 other: &mut self.output,
97 plaintext_locator: &locator,
98 received_plaintext: &mut plaintext,
99 _message_lifetime: PhantomData,
100 };
101
102 let opt_record = match res {
103 Ok(opt_record) => opt_record,
104 Err(e) => {
105 let _ = maybe_send_fatal_alert(output.other.send, &e, output.tls);
106 if let Error::DecryptError = e {
107 st.handle_decrypt_error();
108 }
109 *self.state = Err(e.clone());
110 return Some(Err(e));
111 }
112 };
113
114 let Some(record) = opt_record else {
115 break;
116 };
117
118 let Decrypted {
119 plaintext: record,
120 want_close_before_decrypt,
121 } = record;
122
123 if want_close_before_decrypt {
124 let _ = output.other.send.send_alert(
125 AlertLevel::Warning,
126 AlertDescription::CloseNotify,
127 output.tls,
128 );
129 } else if record.payload.is_empty()
130 && matches!(record.typ, ContentType::Handshake | ContentType::Alert)
131 {
132 let _ = output.other.send.send_alert(
134 AlertLevel::Fatal,
135 AlertDescription::UnexpectedMessage,
136 output.tls,
137 );
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 let _ = 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 let _ = 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 self.input
181 .discard(self.recv.deframer.take_discard());
182
183 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 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 All,
216
217 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 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 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 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 if let Some(span) = self.deframer.complete_span() {
263 let plaintext = self.deframer.record(span, buffer);
264
265 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 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 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 ContentType::ChangeCipherSpec => true,
351 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 _ => 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 let bounds = locator.locate(decrypted.plaintext.payload);
385 Ok(DeframeResult::Decrypted(decrypted, bounds))
386 }
387
388 None if self.deframer.aligned().is_none() => {
391 Err(PeerMisbehaved::RejectedEarlyDataInterleavedWithHandshakeMessage.into())
392 }
393
394 None => Ok(DeframeResult::DecryptionFailed),
396 }
397 }
398
399 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 if record.typ == ContentType::ChangeCipherSpec && self.drop_tls13_ccs(&record)? {
417 trace!("Dropping CCS");
418 return Ok(None);
419 }
420
421 let message = Message::try_from(record)?;
423
424 if let MessagePayload::Alert(alert) = &message.payload {
426 self.process_alert(alert)?;
427 return Ok(None);
428 }
429
430 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 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 if AlertLevelName::try_from(alert.level).is_err() {
492 return Err(PeerMisbehaved::IllegalAlertLevel(alert.level.0, alert.description).into());
493 }
494
495 if self.may_receive_application_data && alert.description == AlertDescription::CloseNotify {
498 self.has_received_close_notify = true;
499 return Ok(());
500 }
501
502 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 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
533pub(crate) struct DecryptionState {
535 record_decrypter: Option<Box<dyn RecordDecrypter>>,
536 read_seq: u64,
537 has_decrypted: bool,
538
539 trial_decryption_len: Option<usize>,
543}
544
545impl DecryptionState {
546 pub(crate) fn new() -> Self {
548 Self {
549 record_decrypter: None,
550 read_seq: 0,
551 has_decrypted: false,
552 trial_decryption_len: None,
553 }
554 }
555
556 pub(crate) fn decrypt_incoming<'a>(
562 &mut self,
563 encr: Record<InboundOpaque<'a>>,
564 ) -> Result<Option<Decrypted<'a>>, Error> {
565 let Some(decrypter) = &mut self.record_decrypter else {
566 return Ok(Some(Decrypted {
567 want_close_before_decrypt: false,
568 plaintext: encr.into_plain_record(),
569 }));
570 };
571
572 let want_close_before_decrypt = self.read_seq == SEQ_SOFT_LIMIT;
581
582 let encrypted_len = encr.payload.len();
583 match decrypter.decrypt(encr, self.read_seq) {
584 Ok(plaintext) => {
585 self.read_seq += 1;
586 if !self.has_decrypted {
587 self.has_decrypted = true;
588 }
589 Ok(Some(Decrypted {
590 want_close_before_decrypt,
591 plaintext,
592 }))
593 }
594 Err(Error::DecryptError) if self.doing_trial_decryption(encrypted_len) => {
595 trace!("Dropping undecryptable record after aborted early_data");
596 Ok(None)
597 }
598 Err(err) => Err(err),
599 }
600 }
601
602 pub(crate) fn set_record_decrypter(
605 &mut self,
606 cipher: Box<dyn RecordDecrypter>,
607 _proof: &HandshakeAlignedProof,
608 ) {
609 self.record_decrypter = Some(cipher);
610 self.read_seq = 0;
611 self.trial_decryption_len = None;
612 }
613
614 pub(crate) fn set_record_decrypter_with_trial_decryption(
618 &mut self,
619 cipher: Box<dyn RecordDecrypter>,
620 max_length: usize,
621 _proof: &HandshakeAlignedProof,
622 ) {
623 self.record_decrypter = Some(cipher);
624 self.read_seq = 0;
625 self.trial_decryption_len = Some(max_length);
626 }
627
628 pub(crate) fn finish_trial_decryption(&mut self) {
629 self.trial_decryption_len = None;
630 }
631
632 pub(crate) fn has_decrypted(&self) -> bool {
635 self.has_decrypted
636 }
637
638 pub(crate) fn read_seq(&self) -> u64 {
639 self.read_seq
640 }
641
642 fn doing_trial_decryption(&mut self, requested: usize) -> bool {
643 match self
644 .trial_decryption_len
645 .and_then(|value| value.checked_sub(requested))
646 {
647 Some(remaining) => {
648 self.trial_decryption_len = Some(remaining);
649 true
650 }
651 _ => false,
652 }
653 }
654}
655
656pub(crate) struct Decrypted<'a> {
658 pub(crate) want_close_before_decrypt: bool,
660 pub(crate) plaintext: Record<&'a [u8]>,
662}
663
664struct CaptureAppData<'a, 'j, 'm, Send: SendOutput + 'a> {
665 recv: &'a mut ReceivePath,
666 other: &'a mut JoinOutput<'j, Send>,
667 tls: &'a mut Vec<u8>,
668 plaintext_locator: &'a Locator,
673 received_plaintext: &'a mut Option<DataKind<UnborrowedPayload>>,
680 _message_lifetime: PhantomData<&'m ()>,
681}
682
683impl<'a, 'm, Send: SendOutput + 'a> Output<'m> for CaptureAppData<'a, '_, 'm, Send> {
684 fn emit(&mut self, ev: Event) {
685 self.other.side.emit(ev)
686 }
687
688 fn output(&mut self, ev: OutputEvent<'_>) {
689 if let OutputEvent::ProtocolVersion(ver) = ev {
690 self.recv.negotiated_version = Some(ver);
691 self.other.send.negotiated_version(ver);
692 }
693 self.other.outputs.handle(ev);
694 }
695
696 fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool) -> Result<(), Error> {
697 match self.other.quic.as_deref_mut() {
698 Some(quic) => {
699 quic.send_msg(m, must_encrypt);
700 Ok(())
701 }
702 None => self
703 .other
704 .send
705 .send_msg(m, must_encrypt, self.tls),
706 }
707 }
708
709 fn quic(&mut self) -> Option<&mut dyn QuicOutput> {
710 match &mut self.other.quic {
711 Some(quic) => Some(*quic),
712 None => None,
713 }
714 }
715
716 fn received_plaintext(&mut self, payload: DataKind<Payload<'m>>) {
717 let previous = self
724 .received_plaintext
725 .replace(match payload {
726 DataKind::Early(p) => {
727 DataKind::Early(UnborrowedPayload::unborrow(self.plaintext_locator, p))
728 }
729 DataKind::Traffic(p) => {
730 DataKind::Traffic(UnborrowedPayload::unborrow(self.plaintext_locator, p))
731 }
732 });
733 debug_assert!(previous.is_none(), "overwrote plaintext data");
734 }
735
736 fn start_traffic(&mut self) {
737 self.recv.may_receive_application_data = true;
738 self.other.send.start_traffic();
739 }
740
741 fn receive(&mut self) -> &mut ReceivePath {
742 self.recv
743 }
744
745 fn send(&mut self) -> &mut dyn SendOutput {
746 self.other.send
747 }
748}
749
750pub(crate) enum DataKind<T> {
751 Early(T),
752 Traffic(T),
753}
754
755pub(super) struct JoinOutput<'a, Send: SendOutput + 'a> {
756 pub(super) outputs: &'a mut dyn ConnectionOutput,
757 pub(super) quic: Option<&'a mut dyn QuicOutput>,
758 pub(super) send: &'a mut Send,
759 pub(super) side: &'a mut dyn SideOutput,
760}
761
762pub(super) struct Discard;
763
764impl ConnectionOutput for Discard {
765 fn handle(&mut self, _ev: OutputEvent<'_>) {}
766}
767
768impl SideOutput for Discard {
769 fn emit(&mut self, _ev: Event) {}
770}
771
772struct TemperCounters {
775 allowed_warning_alerts: u8,
776 allowed_renegotiation_requests: u8,
777 allowed_middlebox_ccs: u8,
778}
779
780impl TemperCounters {
781 fn received_warning_alert(&mut self) -> Result<(), Error> {
782 match self.allowed_warning_alerts {
783 0 => Err(PeerMisbehaved::TooManyWarningAlertsReceived.into()),
784 _ => {
785 self.allowed_warning_alerts -= 1;
786 Ok(())
787 }
788 }
789 }
790
791 fn received_renegotiation_request(&mut self) -> Result<(), Error> {
792 match self.allowed_renegotiation_requests {
793 0 => Err(PeerMisbehaved::TooManyRenegotiationRequests.into()),
794 _ => {
795 self.allowed_renegotiation_requests -= 1;
796 Ok(())
797 }
798 }
799 }
800
801 fn received_tls13_change_cipher_spec(&mut self) -> Result<(), Error> {
802 match self.allowed_middlebox_ccs {
803 0 => Err(PeerMisbehaved::IllegalMiddleboxChangeCipherSpec.into()),
804 _ => {
805 self.allowed_middlebox_ccs -= 1;
806 Ok(())
807 }
808 }
809 }
810}
811
812impl Default for TemperCounters {
813 fn default() -> Self {
814 Self {
815 allowed_warning_alerts: 4,
818
819 allowed_renegotiation_requests: 1,
822
823 allowed_middlebox_ccs: 2,
828 }
829 }
830}
831
832pub(crate) struct TrafficTemperCounters {
833 allowed_consecutive_handshake_messages: u8,
834}
835
836impl TrafficTemperCounters {
837 pub(crate) fn received_handshake_message(&mut self) -> Result<(), Error> {
838 match self.allowed_consecutive_handshake_messages {
839 0 => Err(PeerMisbehaved::TooManyConsecutiveHandshakeMessagesAfterHandshake.into()),
840 _ => {
841 self.allowed_consecutive_handshake_messages -= 1;
842 Ok(())
843 }
844 }
845 }
846
847 pub(crate) fn received_app_data(&mut self) {
848 self.allowed_consecutive_handshake_messages = Self::MAX_CONSECUTIVE_HANDSHAKE_MESSAGES;
849 }
850
851 const MAX_CONSECUTIVE_HANDSHAKE_MESSAGES: u8 = 32;
854}
855
856impl Default for TrafficTemperCounters {
857 fn default() -> Self {
858 Self {
859 allowed_consecutive_handshake_messages: Self::MAX_CONSECUTIVE_HANDSHAKE_MESSAGES,
860 }
861 }
862}
863
864pub(crate) struct Input<'a> {
865 pub(crate) message: Message<'a>,
866 pub(crate) aligned_handshake: Option<HandshakeAlignedProof>,
867}
868
869impl Input<'_> {
870 pub(crate) fn check_aligned_handshake(&self) -> Result<HandshakeAlignedProof, Error> {
875 self.aligned_handshake
876 .ok_or_else(|| PeerMisbehaved::KeyEpochWithPendingFragment.into())
877 }
878}
879
880struct InboundUnborrowedRecord {
883 typ: ContentType,
884 version: EncodableVersion,
885 bounds: Range<usize>,
886}
887
888impl InboundUnborrowedRecord {
889 fn unborrow(locator: &Locator, record: Record<&'_ [u8]>) -> Self {
890 Self {
891 typ: record.typ,
892 version: record.version,
893 bounds: locator.locate(record.payload),
894 }
895 }
896
897 fn reborrow<'b>(self, delocator: &Delocator<'b>) -> Record<&'b [u8]> {
898 Record {
899 typ: self.typ,
900 version: self.version,
901 payload: delocator.slice_from_range(&self.bounds),
902 }
903 }
904}
905
906#[derive(Default)]
908pub struct VecInput {
909 buf: Vec<u8>,
913
914 used: usize,
916
917 has_seen_eof: bool,
919
920 received_close_notify: bool,
922}
923
924impl VecInput {
925 pub(crate) fn discard(&mut self, taken: usize) {
927 if taken < self.used {
928 self.buf
942 .copy_within(taken..self.used, 0);
943 self.used -= taken;
944 } else if taken >= self.used {
945 self.used = 0;
946 }
947 }
948
949 pub(crate) fn filled_mut(&mut self) -> &mut [u8] {
950 &mut self.buf[..self.used]
951 }
952
953 pub fn read(&mut self, rd: &mut dyn Read) -> io::Result<usize> {
959 if self.received_close_notify {
960 return Ok(0);
961 } else if let Err(err) = self.prepare_read() {
962 return Err(io::Error::new(io::ErrorKind::InvalidData, err));
963 }
964
965 let new_bytes = rd.read(&mut self.buf[self.used..])?;
970 if new_bytes == 0 {
971 self.has_seen_eof = true;
972 }
973
974 self.used += new_bytes;
975 Ok(new_bytes)
976 }
977
978 fn prepare_read(&mut self) -> Result<(), &'static str> {
980 const MAX_HANDSHAKE_SIZE: usize = 0xffff;
984
985 const READ_SIZE: usize = 4096;
986
987 if self.used >= MAX_HANDSHAKE_SIZE {
993 return Err("message buffer full");
994 }
995
996 let need_capacity = Ord::min(MAX_HANDSHAKE_SIZE, self.used + READ_SIZE);
1002 if need_capacity > self.buf.len() {
1003 self.buf.resize(need_capacity, 0);
1004 } else if self.used == 0 || self.buf.len() > MAX_HANDSHAKE_SIZE {
1005 self.buf.resize(need_capacity, 0);
1006 self.buf.shrink_to(need_capacity);
1007 }
1008
1009 Ok(())
1010 }
1011}
1012
1013impl TlsInputBuffer for VecInput {
1014 fn slice_mut(&mut self) -> &mut [u8] {
1015 self.filled_mut()
1016 }
1017
1018 fn discard(&mut self, num_bytes: usize) {
1019 self.discard(num_bytes)
1020 }
1021
1022 fn received_close_notify(&mut self) {
1023 self.received_close_notify = true;
1024 }
1025
1026 fn has_seen_eof(&self) -> bool {
1027 self.has_seen_eof
1028 }
1029}
1030
1031impl fmt::Debug for VecInput {
1032 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1033 let Self {
1034 buf,
1035 used,
1036 has_seen_eof,
1037 received_close_notify,
1038 } = self;
1039 f.debug_struct("VecInput")
1040 .field("buf_len", &buf.len())
1041 .field("used", used)
1042 .field("has_seen_eof", has_seen_eof)
1043 .field("received_close_notify", received_close_notify)
1044 .finish_non_exhaustive()
1045 }
1046}
1047
1048pub struct SliceInput<'a> {
1050 buf: &'a mut [u8],
1052 discard: usize,
1054 has_seen_eof: bool,
1056 received_close_notify: bool,
1058}
1059
1060impl<'a> SliceInput<'a> {
1061 pub fn new(buf: &'a mut [u8]) -> Self {
1063 Self {
1064 buf,
1065 discard: 0,
1066 has_seen_eof: false,
1067 received_close_notify: false,
1068 }
1069 }
1070
1071 pub fn into_used(self) -> usize {
1073 self.discard
1074 }
1075}
1076
1077impl TlsInputBuffer for SliceInput<'_> {
1078 fn slice_mut(&mut self) -> &mut [u8] {
1079 &mut self.buf[self.discard..]
1080 }
1081
1082 fn discard(&mut self, num_bytes: usize) {
1083 self.discard += num_bytes;
1084 }
1085
1086 fn received_close_notify(&mut self) {
1087 self.received_close_notify = true;
1088 }
1089
1090 fn has_seen_eof(&self) -> bool {
1091 self.has_seen_eof
1092 }
1093}
1094
1095impl fmt::Debug for SliceInput<'_> {
1096 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1097 let Self {
1098 buf,
1099 discard,
1100 has_seen_eof,
1101 received_close_notify,
1102 } = self;
1103 f.debug_struct("SliceInput")
1104 .field("buf_len", &buf.len())
1105 .field("discard", discard)
1106 .field("has_seen_eof", has_seen_eof)
1107 .field("received_close_notify", received_close_notify)
1108 .finish_non_exhaustive()
1109 }
1110}
1111
1112pub trait TlsInputBuffer {
1114 fn slice_mut(&mut self) -> &mut [u8];
1124
1125 fn discard(&mut self, num_bytes: usize);
1138
1139 fn received_close_notify(&mut self);
1143
1144 fn has_seen_eof(&self) -> bool;
1148}
1149
1150const ALLOWED_CONSECUTIVE_EMPTY_FRAGMENTS_MAX: u8 = 32;
1153
1154#[cfg(test)]
1155mod tests {
1156 use alloc::format;
1157
1158 use super::*;
1159
1160 #[test]
1161 fn test_has_decrypted() {
1162 struct PassThroughDecrypter;
1163 impl RecordDecrypter for PassThroughDecrypter {
1164 fn decrypt<'a>(
1165 &mut self,
1166 record: Record<InboundOpaque<'a>>,
1167 _: u64,
1168 ) -> Result<Record<&'a [u8]>, Error> {
1169 Ok(record.into_plain_record())
1170 }
1171 }
1172
1173 let mut record_layer = DecryptionState::new();
1175 assert!(record_layer.record_decrypter.is_none());
1176 assert_eq!(record_layer.read_seq, 0);
1177 assert!(!record_layer.has_decrypted());
1178
1179 let deframer = Deframer::default();
1182 record_layer
1183 .set_record_decrypter(Box::new(PassThroughDecrypter), &deframer.aligned().unwrap());
1184 assert!(record_layer.record_decrypter.is_some());
1185 assert_eq!(record_layer.read_seq, 0);
1186 assert!(!record_layer.has_decrypted());
1187
1188 record_layer
1191 .decrypt_incoming(Record::new(
1192 ContentType::Handshake,
1193 EncodableVersion::Legacy(ProtocolVersion::TLSv1_2),
1194 InboundOpaque(&mut [0xC0, 0xFF, 0xEE]),
1195 ))
1196 .unwrap();
1197 assert_eq!(record_layer.read_seq, 1);
1198 assert!(record_layer.has_decrypted());
1199
1200 record_layer
1203 .set_record_decrypter(Box::new(PassThroughDecrypter), &deframer.aligned().unwrap());
1204 assert_eq!(record_layer.read_seq, 0);
1205 assert!(record_layer.has_decrypted());
1206 }
1207
1208 #[test]
1209 fn debug_of_input_types() {
1210 let mut buffer = [b'a'; 32];
1211 let mut slice = SliceInput::new(&mut buffer);
1212 slice.discard(2);
1213 assert_eq!(
1214 format!("{slice:?}"),
1215 "SliceInput { buf_len: 32, discard: 2, has_seen_eof: false, received_close_notify: false, .. }"
1216 );
1217
1218 let mut vec = VecInput::default();
1219 vec.prepare_read().unwrap();
1220 assert_eq!(
1221 format!("{vec:?}"),
1222 "VecInput { buf_len: 4096, used: 0, has_seen_eof: false, received_close_notify: false, .. }"
1223 );
1224 }
1225}