1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::fmt;
4use core::ops::{Deref, DerefMut, Range};
5
6use pki_types::DnsName;
7
8use crate::client::EchStatus;
9use crate::conn::Exporter;
10use crate::conn::unbuffered::{EncryptError, InsufficientSizeError};
11use crate::crypto::Identity;
12use crate::crypto::cipher::{
13 Decrypted, DecryptionState, EncodedMessage, EncryptionState, MessageDecrypter,
14 MessageEncrypter, OutboundOpaque, OutboundPlain, Payload, PreEncryptAction,
15};
16use crate::crypto::kx::SupportedKxGroup;
17use crate::crypto::tls13::OkmBlock;
18use crate::enums::{ApplicationProtocol, ContentType, HandshakeType, ProtocolVersion};
19use crate::error::{AlertDescription, Error, PeerMisbehaved};
20use crate::hash_hs::HandshakeHash;
21use crate::log::{debug, error, trace, warn};
22use crate::msgs::{
23 AlertLevel, AlertMessagePayload, BufferProgress, Codec, DeframerIter, Delocator,
24 HandshakeAlignedProof, HandshakeDeframer, HandshakeMessagePayload, Locator, Message,
25 MessageFragmenter, MessagePayload,
26};
27use crate::quic;
28use crate::suites::SupportedCipherSuite;
29use crate::tls13::key_schedule::KeyScheduleTrafficSend;
30use crate::vecbuf::ChunkVecBuffer;
31
32pub struct CommonState {
34 pub(crate) outputs: ConnectionOutputs,
35 pub(crate) send: SendPath,
36 pub(crate) recv: ReceivePath,
37 pub(crate) quic: quic::Quic,
38
39 pub(crate) protocol: Protocol,
41}
42
43impl CommonState {
44 pub(crate) fn new(side: Side, protocol: Protocol) -> Self {
45 Self {
46 outputs: ConnectionOutputs::default(),
47 send: SendPath::default(),
48 recv: ReceivePath::new(side),
49 quic: quic::Quic::default(),
50 protocol,
51 }
52 }
53
54 pub fn wants_write(&self) -> bool {
58 !self.send.sendable_tls.is_empty()
59 }
60
61 pub fn send_close_notify(&mut self) {
69 self.send.send_close_notify()
70 }
71
72 pub fn is_handshaking(&self) -> bool {
80 !(self.send.may_send_application_data && self.recv.may_receive_application_data)
81 }
82}
83
84impl Output for CommonState {
85 fn emit(&mut self, ev: Event<'_>) {
86 match ev.disposition() {
87 EventDisposition::MessageOutput => match self.protocol {
88 Protocol::Tcp => self.send.emit(ev),
89 Protocol::Quic(_) => self.quic.emit(ev),
90 },
91
92 EventDisposition::SendPath => self.send.emit(ev),
93 EventDisposition::ReceivePath => self.recv.emit(ev),
94 EventDisposition::ConnectionOutputs => self.outputs.emit(ev),
95 EventDisposition::Quic => self.quic.emit(ev),
96 EventDisposition::SideSpecific => unreachable!(),
97
98 EventDisposition::ProtocolVersion(ver) => {
99 self.outputs
100 .emit(Event::ProtocolVersion(ver));
101 self.recv
102 .emit(Event::ProtocolVersion(ver));
103 self.send
104 .emit(Event::ProtocolVersion(ver));
105 }
106 EventDisposition::StartTraffic => {
107 self.recv.emit(Event::StartTraffic);
108 self.send.emit(Event::StartTraffic);
109 }
110 }
111 }
112}
113
114impl Deref for CommonState {
115 type Target = ConnectionOutputs;
116
117 fn deref(&self) -> &Self::Target {
118 &self.outputs
119 }
120}
121
122impl DerefMut for CommonState {
123 fn deref_mut(&mut self) -> &mut Self::Target {
124 &mut self.outputs
125 }
126}
127
128impl fmt::Debug for CommonState {
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 f.debug_struct("CommonState")
131 .finish_non_exhaustive()
132 }
133}
134
135#[derive(Default)]
137pub struct ConnectionOutputs {
138 negotiated_version: Option<ProtocolVersion>,
139 handshake_kind: Option<HandshakeKind>,
140 suite: Option<SupportedCipherSuite>,
141 negotiated_kx_group: Option<&'static dyn SupportedKxGroup>,
142 alpn_protocol: Option<ApplicationProtocol<'static>>,
143 peer_identity: Option<Identity<'static>>,
144 pub(crate) exporter: Option<Box<dyn Exporter>>,
145 pub(crate) early_exporter: Option<Box<dyn Exporter>>,
146}
147
148impl ConnectionOutputs {
149 pub fn peer_identity(&self) -> Option<&Identity<'static>> {
158 self.peer_identity.as_ref()
159 }
160
161 pub fn alpn_protocol(&self) -> Option<&ApplicationProtocol<'static>> {
167 self.alpn_protocol.as_ref()
168 }
169
170 pub fn negotiated_cipher_suite(&self) -> Option<SupportedCipherSuite> {
174 self.suite
175 }
176
177 pub fn negotiated_key_exchange_group(&self) -> Option<&'static dyn SupportedKxGroup> {
187 self.negotiated_kx_group
188 }
189
190 pub fn protocol_version(&self) -> Option<ProtocolVersion> {
194 self.negotiated_version
195 }
196
197 pub fn handshake_kind(&self) -> Option<HandshakeKind> {
204 self.handshake_kind
205 }
206
207 pub(super) fn into_kernel_parts(self) -> Option<(ProtocolVersion, SupportedCipherSuite)> {
208 let Self {
209 negotiated_version,
210 suite,
211 ..
212 } = self;
213
214 match (negotiated_version, suite) {
215 (Some(version), Some(suite)) => Some((version, suite)),
216 _ => None,
217 }
218 }
219}
220
221impl Output for ConnectionOutputs {
222 fn emit(&mut self, ev: Event<'_>) {
223 match ev {
224 Event::ApplicationProtocol(protocol) => {
225 self.alpn_protocol = Some(ApplicationProtocol::from(protocol.as_ref()).to_owned())
226 }
227 Event::CipherSuite(suite) => self.suite = Some(suite),
228 Event::EarlyExporter(exporter) => self.early_exporter = Some(exporter),
229 Event::Exporter(exporter) => self.exporter = Some(exporter),
230 Event::HandshakeKind(hk) => {
231 assert!(self.handshake_kind.is_none());
232 self.handshake_kind = Some(hk);
233 }
234 Event::KeyExchangeGroup(kxg) => {
235 assert!(self.negotiated_kx_group.is_none());
236 self.negotiated_kx_group = Some(kxg);
237 }
238 Event::PeerIdentity(identity) => self.peer_identity = Some(identity),
239 Event::ProtocolVersion(ver) => {
240 self.negotiated_version = Some(ver);
241 }
242 _ => unreachable!(),
243 }
244 }
245}
246
247pub(crate) fn maybe_send_fatal_alert(output: &mut dyn Output, error: &Error) {
249 let Ok(alert) = AlertDescription::try_from(error) else {
250 return;
251 };
252 output.emit(Event::SendAlert(AlertLevel::Fatal, alert));
253}
254
255pub(crate) struct SendPath {
257 pub(crate) encrypt_state: EncryptionState,
258 pub(crate) may_send_application_data: bool,
259 has_sent_fatal_alert: bool,
260 pub(crate) has_sent_close_notify: bool,
262 message_fragmenter: MessageFragmenter,
263 pub(crate) sendable_tls: ChunkVecBuffer,
264 queued_key_update_message: Option<Vec<u8>>,
265 pub(crate) refresh_traffic_keys_pending: bool,
266 negotiated_version: Option<ProtocolVersion>,
267 pub(crate) tls13_key_schedule: Option<Box<KeyScheduleTrafficSend>>,
268}
269
270impl SendPath {
271 #[expect(dead_code)]
272 pub(crate) fn write_plaintext(
273 &mut self,
274 payload: OutboundPlain<'_>,
275 outgoing_tls: &mut [u8],
276 ) -> Result<usize, EncryptError> {
277 if payload.is_empty() {
278 return Ok(0);
279 }
280
281 let fragments = self
282 .message_fragmenter
283 .fragment_payload(
284 ContentType::ApplicationData,
285 ProtocolVersion::TLSv1_2,
286 payload.clone(),
287 );
288
289 for f in 0..fragments.len() {
290 match self
291 .encrypt_state
292 .pre_encrypt_action(f as u64)
293 {
294 PreEncryptAction::Nothing => {}
295 PreEncryptAction::RefreshOrClose => match self.negotiated_version {
296 Some(ProtocolVersion::TLSv1_3) => {
297 self.refresh_traffic_keys_pending = true;
299 }
300 _ => {
301 error!(
302 "traffic keys exhausted, closing connection to prevent security failure"
303 );
304 self.send_close_notify();
305 return Err(EncryptError::EncryptExhausted);
306 }
307 },
308 PreEncryptAction::Refuse => {
309 return Err(EncryptError::EncryptExhausted);
310 }
311 }
312 }
313
314 self.perhaps_write_key_update();
315
316 self.check_required_size(outgoing_tls, fragments)?;
317
318 let fragments = self
319 .message_fragmenter
320 .fragment_payload(
321 ContentType::ApplicationData,
322 ProtocolVersion::TLSv1_2,
323 payload,
324 );
325
326 Ok(self.write_fragments(outgoing_tls, fragments))
327 }
328
329 pub(crate) fn send_early_plaintext(&mut self, data: &[u8]) -> usize {
330 debug_assert!(self.encrypt_state.is_encrypting());
331
332 let len = self
335 .sendable_tls
336 .apply_limit(data.len());
337 if len == 0 {
338 return 0;
340 }
341
342 self.send_appdata_encrypt(data[..len].into())
343 }
344
345 fn send_msg_encrypt(&mut self, m: EncodedMessage<Payload<'_>>) {
348 let iter = self
349 .message_fragmenter
350 .fragment_message(&m);
351 for m in iter {
352 self.send_single_fragment(m);
353 }
354 }
355
356 fn send_appdata_encrypt(&mut self, payload: OutboundPlain<'_>) -> usize {
358 let len = payload.len();
359 let iter = self
360 .message_fragmenter
361 .fragment_payload(
362 ContentType::ApplicationData,
363 ProtocolVersion::TLSv1_2,
364 payload,
365 );
366 for m in iter {
367 self.send_single_fragment(m);
368 }
369
370 len
371 }
372
373 fn send_single_fragment(&mut self, m: EncodedMessage<OutboundPlain<'_>>) {
374 if m.typ == ContentType::Alert {
375 let em = self.encrypt_state.encrypt_outgoing(m);
377 self.queue_tls_message(em);
378 return;
379 }
380
381 match self
382 .encrypt_state
383 .next_pre_encrypt_action()
384 {
385 PreEncryptAction::Nothing => {}
386
387 PreEncryptAction::RefreshOrClose => {
390 match self.negotiated_version {
391 Some(ProtocolVersion::TLSv1_3) => {
392 self.refresh_traffic_keys_pending = true;
394 }
395 _ => {
396 error!(
397 "traffic keys exhausted, closing connection to prevent security failure"
398 );
399 self.send_close_notify();
400 return;
401 }
402 }
403 }
404
405 PreEncryptAction::Refuse => {
408 return;
409 }
410 };
411
412 let em = self.encrypt_state.encrypt_outgoing(m);
413 self.queue_tls_message(em);
414 }
415
416 pub(crate) fn buffer_plaintext(
422 &mut self,
423 payload: OutboundPlain<'_>,
424 sendable_plaintext: &mut ChunkVecBuffer,
425 ) -> usize {
426 self.perhaps_write_key_update();
427 if !self.may_send_application_data {
428 return sendable_plaintext.append_limited_copy(payload);
431 }
432
433 let len = self
436 .sendable_tls
437 .apply_limit(payload.len());
438 if len == 0 {
439 return 0;
441 }
442
443 debug_assert!(self.encrypt_state.is_encrypting());
444 self.send_appdata_encrypt(payload.split_at(len).0)
445 }
446
447 pub(crate) fn send_buffered_plaintext(&mut self, plaintext: &mut ChunkVecBuffer) {
448 while let Some(buf) = plaintext.pop() {
449 self.send_appdata_encrypt(buf.as_slice().into());
450 }
451 }
452
453 fn start_outgoing_traffic(&mut self) {
454 self.may_send_application_data = true;
455 debug_assert!(self.encrypt_state.is_encrypting());
456 }
457
458 fn queue_tls_message(&mut self, m: EncodedMessage<OutboundOpaque>) {
460 self.perhaps_write_key_update();
461 self.sendable_tls.append(m.encode());
462 }
463
464 fn perhaps_write_key_update(&mut self) {
465 if let Some(message) = self.queued_key_update_message.take() {
466 self.sendable_tls.append(message);
467 }
468 }
469
470 fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool) {
472 if !must_encrypt {
473 let msg = &m.into();
474 let iter = self
475 .message_fragmenter
476 .fragment_message(msg);
477 for m in iter {
478 self.queue_tls_message(m.to_unencrypted_opaque());
479 }
480 } else {
481 self.send_msg_encrypt(m.into());
482 }
483 }
484
485 fn send_close_notify(&mut self) {
486 if self.has_sent_close_notify {
487 return;
488 }
489 debug!("Sending warning alert {:?}", AlertDescription::CloseNotify);
490 self.has_sent_close_notify = true;
491 self.send_alert(AlertLevel::Warning, AlertDescription::CloseNotify);
492 }
493
494 #[expect(dead_code)]
495 pub(crate) fn eager_send_close_notify(
496 &mut self,
497 outgoing_tls: &mut [u8],
498 ) -> Result<usize, EncryptError> {
499 self.send_close_notify();
500 self.check_required_size(outgoing_tls, [].into_iter())?;
501 Ok(self.write_fragments(outgoing_tls, [].into_iter()))
502 }
503
504 fn send_alert(&mut self, level: AlertLevel, desc: AlertDescription) {
505 match level {
506 AlertLevel::Fatal if self.has_sent_fatal_alert => return,
507 AlertLevel::Fatal => self.has_sent_fatal_alert = true,
508 _ => {}
509 };
510 self.send_msg(
511 Message::build_alert(level, desc),
512 self.encrypt_state.is_encrypting(),
513 );
514 }
515
516 fn check_required_size<'a>(
517 &self,
518 outgoing_tls: &[u8],
519 fragments: impl Iterator<Item = EncodedMessage<OutboundPlain<'a>>>,
520 ) -> Result<(), EncryptError> {
521 let mut required_size = self.sendable_tls.len();
522
523 for m in fragments {
524 required_size += m.encoded_len(&self.encrypt_state);
525 }
526
527 if required_size > outgoing_tls.len() {
528 return Err(EncryptError::InsufficientSize(InsufficientSizeError {
529 required_size,
530 }));
531 }
532
533 Ok(())
534 }
535
536 fn write_fragments<'a>(
537 &mut self,
538 outgoing_tls: &mut [u8],
539 fragments: impl Iterator<Item = EncodedMessage<OutboundPlain<'a>>>,
540 ) -> usize {
541 let mut written = 0;
542
543 while let Some(message) = self.sendable_tls.pop() {
546 let len = message.len();
547 outgoing_tls[written..written + len].copy_from_slice(&message);
548 written += len;
549 }
550
551 for m in fragments {
552 let em = self
553 .encrypt_state
554 .encrypt_outgoing(m)
555 .encode();
556
557 let len = em.len();
558 outgoing_tls[written..written + len].copy_from_slice(&em);
559 written += len;
560 }
561
562 written
563 }
564
565 pub(crate) fn set_max_fragment_size(&mut self, new: Option<usize>) -> Result<(), Error> {
566 self.message_fragmenter
567 .set_max_fragment_size(new)
568 }
569
570 fn ensure_key_update_queued(&mut self) -> bool {
571 if self.queued_key_update_message.is_some() {
572 return false;
573 }
574 let message = EncodedMessage::<Payload<'static>>::from(Message::build_key_update_notify());
575 self.queued_key_update_message = Some(
576 self.encrypt_state
577 .encrypt_outgoing(message.borrow_outbound())
578 .encode(),
579 );
580 true
581 }
582
583 pub(crate) fn maybe_refresh_traffic_keys(&mut self) {
585 if self.refresh_traffic_keys_pending {
586 let _ = self.refresh_traffic_keys();
587 }
588 }
589
590 pub(crate) fn refresh_traffic_keys(&mut self) -> Result<(), Error> {
591 let ks = self.tls13_key_schedule.take();
592
593 let Some(mut ks) = ks else {
594 return Err(Error::HandshakeNotComplete);
595 };
596
597 ks.request_key_update_and_update_encrypter(self);
598 self.refresh_traffic_keys_pending = false;
599 self.tls13_key_schedule = Some(ks);
600 Ok(())
601 }
602}
603
604impl Output for SendPath {
605 fn emit(&mut self, ev: Event<'_>) {
606 match ev {
607 Event::EncryptMessage(m) => self.send_msg(m, true),
608 Event::MaybeKeyUpdateRequest => {
609 if self.ensure_key_update_queued() {
610 if let Some(mut ks) = self.tls13_key_schedule.take() {
611 ks.update_encrypter_for_key_update(self);
612 self.tls13_key_schedule = Some(ks);
613 }
614 }
615 }
616 Event::MessageEncrypter { encrypter, limit } => self
617 .encrypt_state
618 .set_message_encrypter(encrypter, limit),
619 Event::OutgoingKeySchedule(klc) => self.tls13_key_schedule = Some(klc),
620 Event::PlainMessage(m) => self.send_msg(m, false),
621 Event::ProtocolVersion(ver) => self.negotiated_version = Some(ver),
622 Event::SendAlert(level, desc) => self.send_alert(level, desc),
623 Event::StartHalfRttTraffic | Event::StartTraffic => self.start_outgoing_traffic(),
624 _ => unreachable!(),
625 }
626 }
627}
628
629impl Default for SendPath {
630 fn default() -> Self {
631 Self {
632 encrypt_state: EncryptionState::new(),
633 may_send_application_data: false,
634 has_sent_fatal_alert: false,
635 has_sent_close_notify: false,
636 message_fragmenter: MessageFragmenter::default(),
637 sendable_tls: ChunkVecBuffer::new(Some(DEFAULT_BUFFER_LIMIT)),
638 queued_key_update_message: None,
639 refresh_traffic_keys_pending: false,
640 negotiated_version: None,
641 tls13_key_schedule: None,
642 }
643 }
644}
645
646pub(crate) struct ReceivePath {
647 side: Side,
648 pub(crate) decrypt_state: DecryptionState,
649 may_receive_application_data: bool,
650 pub(crate) has_received_close_notify: bool,
652 temper_counters: TemperCounters,
653 negotiated_version: Option<ProtocolVersion>,
654 pub(crate) hs_deframer: HandshakeDeframer,
655
656 seen_consecutive_empty_fragments: u8,
659
660 pub(crate) tls13_tickets_received: u32,
661}
662
663impl ReceivePath {
664 fn new(side: Side) -> Self {
665 Self {
666 side,
667 decrypt_state: DecryptionState::new(),
668 may_receive_application_data: false,
669 has_received_close_notify: false,
670 temper_counters: TemperCounters::default(),
671 negotiated_version: None,
672 hs_deframer: HandshakeDeframer::default(),
673 seen_consecutive_empty_fragments: 0,
674 tls13_tickets_received: 0,
675 }
676 }
677
678 pub(crate) fn deframe<'b>(
680 &mut self,
681 buffer: &'b mut [u8],
682 buffer_progress: &mut BufferProgress,
683 ) -> Result<Option<Decrypted<'b>>, Error> {
684 if self.hs_deframer.has_message_ready() {
686 Ok(self.take_handshake_message(buffer, buffer_progress))
687 } else {
688 self.process_more_input(buffer, buffer_progress)
689 }
690 }
691
692 fn take_handshake_message<'b>(
693 &mut self,
694 buffer: &'b [u8],
695 buffer_progress: &mut BufferProgress,
696 ) -> Option<Decrypted<'b>> {
697 self.hs_deframer
698 .iter(buffer)
699 .next()
700 .map(|(message, discard)| {
701 buffer_progress.add_discard(discard);
702 Decrypted {
703 want_close_before_decrypt: false,
704 plaintext: message,
705 }
706 })
707 }
708
709 fn process_more_input<'b>(
710 &mut self,
711 buffer: &'b mut [u8],
712 buffer_progress: &mut BufferProgress,
713 ) -> Result<Option<Decrypted<'b>>, Error> {
714 let version_is_tls13 = matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3));
715
716 let locator = Locator::new(buffer);
717
718 loop {
719 let mut iter = DeframerIter::new(&mut buffer[buffer_progress.processed()..]);
720
721 let (message, processed) = loop {
722 let message = match iter.next().transpose() {
723 Ok(Some(message)) => message,
724 Ok(None) => return Ok(None),
725 Err(err) => return Err(err),
726 };
727
728 let allowed_plaintext = match message.typ {
729 ContentType::ChangeCipherSpec => true,
731 ContentType::Alert
738 if version_is_tls13
739 && !self.decrypt_state.has_decrypted()
740 && message.payload.len() <= 2 =>
741 {
742 true
743 }
744 _ => false,
746 };
747
748 if allowed_plaintext && !self.hs_deframer.is_active() {
749 break (
750 Decrypted {
751 plaintext: message.into_plain_message(),
752 want_close_before_decrypt: false,
753 },
754 iter.bytes_consumed(),
755 );
756 }
757
758 let message = match self
759 .decrypt_state
760 .decrypt_incoming(message)
761 {
762 Ok(None) if self.hs_deframer.aligned().is_none() => {
765 return Err(
766 PeerMisbehaved::RejectedEarlyDataInterleavedWithHandshakeMessage.into(),
767 );
768 }
769
770 Ok(None) => continue,
772
773 Ok(Some(message)) => message,
774
775 Err(err) => return Err(err),
776 };
777
778 break (message, iter.bytes_consumed());
779 };
780
781 let Decrypted {
782 plaintext: message,
783 want_close_before_decrypt,
784 } = message;
785
786 if self.hs_deframer.aligned().is_none() && message.typ != ContentType::Handshake {
787 return Err(PeerMisbehaved::MessageInterleavedWithHandshakeMessage.into());
792 }
793
794 match message.payload.len() {
795 0 => {
796 if self.seen_consecutive_empty_fragments
797 == ALLOWED_CONSECUTIVE_EMPTY_FRAGMENTS_MAX
798 {
799 return Err(PeerMisbehaved::TooManyEmptyFragments.into());
800 }
801 self.seen_consecutive_empty_fragments += 1;
802 }
803 _ => {
804 self.seen_consecutive_empty_fragments = 0;
805 }
806 };
807
808 buffer_progress.add_processed(processed);
809
810 let unborrowed = InboundUnborrowedMessage::unborrow(&locator, message);
818
819 if unborrowed.typ != ContentType::Handshake {
820 let message = unborrowed.reborrow(&Delocator::new(buffer));
821 buffer_progress.add_discard(processed);
822 return Ok(Some(Decrypted {
823 plaintext: message,
824 want_close_before_decrypt,
825 }));
826 }
827
828 let message = unborrowed.reborrow(&Delocator::new(buffer));
829 self.hs_deframer
830 .input_message(message, &locator, buffer_progress.processed());
831 self.hs_deframer.coalesce(buffer)?;
832
833 if self.hs_deframer.has_message_ready() {
834 self.decrypt_state
836 .finish_trial_decryption();
837
838 return Ok(self
839 .take_handshake_message(buffer, buffer_progress)
840 .map(|decrypted| Decrypted {
841 plaintext: decrypted.plaintext,
842 want_close_before_decrypt,
843 }));
844 }
845 }
846 }
847
848 pub(crate) fn receive_message<'a>(
858 &mut self,
859 msg: EncodedMessage<&'a [u8]>,
860 aligned_handshake: Option<HandshakeAlignedProof>,
861 send_path: &mut dyn Output,
862 ) -> Result<Option<Input<'a>>, Error> {
863 if msg.typ == ContentType::ChangeCipherSpec && self.drop_tls13_ccs(&msg)? {
865 trace!("Dropping CCS");
866 return Ok(None);
867 }
868
869 let message = Message::try_from(msg)?;
871
872 if let MessagePayload::Alert(alert) = &message.payload {
874 self.process_alert(alert)?;
875 return Ok(None);
876 }
877
878 if self.reject_renegotiation_request(&message, send_path)? {
881 return Ok(None);
882 }
883
884 Ok(Some(Input {
885 message,
886 aligned_handshake,
887 }))
888 }
889
890 fn drop_tls13_ccs(&mut self, msg: &EncodedMessage<&'_ [u8]>) -> Result<bool, Error> {
891 if self.may_receive_application_data
892 || !matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
893 {
894 return Ok(false);
895 }
896
897 if !msg.is_valid_ccs() {
898 return Err(PeerMisbehaved::IllegalMiddleboxChangeCipherSpec.into());
902 }
903
904 self.temper_counters
905 .received_tls13_change_cipher_spec()?;
906 Ok(true)
907 }
908
909 fn reject_renegotiation_request(
910 &mut self,
911 msg: &Message<'_>,
912 output: &mut dyn Output,
913 ) -> Result<bool, Error> {
914 if !self.may_receive_application_data
915 || matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
916 {
917 return Ok(false);
918 }
919
920 let reject_ty = match self.side {
921 Side::Client => HandshakeType::HelloRequest,
922 Side::Server => HandshakeType::ClientHello,
923 };
924
925 if msg.handshake_type() != Some(reject_ty) {
926 return Ok(false);
927 }
928 self.temper_counters
929 .received_renegotiation_request()?;
930 let desc = AlertDescription::NoRenegotiation;
931 warn!("sending warning alert {desc:?}");
932 output.emit(Event::SendAlert(AlertLevel::Warning, desc));
933 Ok(true)
934 }
935
936 fn process_alert(&mut self, alert: &AlertMessagePayload) -> Result<(), Error> {
937 if let AlertLevel::Unknown(level) = alert.level {
939 return Err(PeerMisbehaved::IllegalAlertLevel(level, alert.description).into());
940 }
941
942 if self.may_receive_application_data && alert.description == AlertDescription::CloseNotify {
945 self.has_received_close_notify = true;
946 return Ok(());
947 }
948
949 let err = Error::AlertReceived(alert.description);
952 if alert.level == AlertLevel::Warning {
953 self.temper_counters
954 .received_warning_alert()?;
955 if matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
956 && alert.description != AlertDescription::UserCanceled
957 {
958 return Err(PeerMisbehaved::IllegalWarningAlert(alert.description).into());
959 }
960
961 if alert.description != AlertDescription::UserCanceled || cfg!(debug_assertions) {
964 warn!("TLS alert warning received: {alert:?}");
965 }
966
967 return Ok(());
968 }
969
970 Err(err)
971 }
972}
973
974impl Output for ReceivePath {
975 fn emit(&mut self, ev: Event<'_>) {
976 match ev {
977 Event::MessageDecrypter { decrypter, proof } => self
978 .decrypt_state
979 .set_message_decrypter(decrypter, &proof),
980 Event::MessageDecrypterWithTrialDecryption {
981 decrypter,
982 max_length,
983 proof,
984 } => self
985 .decrypt_state
986 .set_message_decrypter_with_trial_decryption(decrypter, max_length, &proof),
987 Event::ProtocolVersion(ver) => self.negotiated_version = Some(ver),
988 Event::ReceivedTicket => {
989 self.tls13_tickets_received = self
990 .tls13_tickets_received
991 .saturating_add(1)
992 }
993 Event::StartTraffic => self.may_receive_application_data = true,
994 _ => unreachable!(),
995 }
996 }
997}
998
999#[derive(Debug, PartialEq, Clone, Copy)]
1001#[non_exhaustive]
1002pub enum HandshakeKind {
1003 Full,
1008
1009 FullWithHelloRetryRequest,
1015
1016 Resumed,
1022
1023 ResumedWithHelloRetryRequest,
1029}
1030
1031pub(crate) struct CaptureAppData<'a> {
1032 pub(crate) data: &'a mut dyn Output,
1033 pub(crate) plaintext_locator: &'a Locator,
1038 pub(crate) received_plaintext: &'a mut Option<UnborrowedPayload>,
1045}
1046
1047impl Output for CaptureAppData<'_> {
1048 fn emit(&mut self, ev: Event<'_>) {
1049 self.data.emit(ev)
1050 }
1051
1052 fn received_plaintext(&mut self, payload: Payload<'_>) {
1053 let previous = self
1060 .received_plaintext
1061 .replace(UnborrowedPayload::unborrow(self.plaintext_locator, payload));
1062 debug_assert!(previous.is_none(), "overwrote plaintext data");
1063 }
1064}
1065
1066pub(crate) struct SplitReceive<'a> {
1067 pub(crate) recv: &'a mut dyn Output,
1068 pub(crate) other: &'a mut dyn Output,
1069}
1070
1071impl Output for SplitReceive<'_> {
1072 fn emit(&mut self, ev: Event<'_>) {
1073 match ev.disposition() {
1074 EventDisposition::ReceivePath => self.recv.emit(ev),
1075 EventDisposition::ProtocolVersion(ver) => {
1076 self.recv
1077 .emit(Event::ProtocolVersion(ver));
1078 self.other
1079 .emit(Event::ProtocolVersion(ver));
1080 }
1081 EventDisposition::StartTraffic => {
1082 self.recv.emit(Event::StartTraffic);
1083 self.other.emit(Event::StartTraffic);
1084 }
1085 _ => self.other.emit(ev),
1086 }
1087 }
1088}
1089
1090pub(crate) struct JoinOutput<'a> {
1091 pub(crate) protocol: Protocol,
1092 pub(crate) outputs: &'a mut dyn Output,
1093 pub(crate) quic: &'a mut dyn Output,
1094 pub(crate) send: &'a mut dyn Output,
1095 pub(crate) side: &'a mut dyn Output,
1096}
1097
1098impl Output for JoinOutput<'_> {
1099 fn emit(&mut self, ev: Event<'_>) {
1100 match ev.disposition() {
1101 EventDisposition::ReceivePath => unreachable!(),
1102 EventDisposition::ProtocolVersion(ver) => {
1103 self.outputs
1104 .emit(Event::ProtocolVersion(ver));
1105 self.quic
1106 .emit(Event::ProtocolVersion(ver));
1107 self.send
1108 .emit(Event::ProtocolVersion(ver));
1109 }
1110 EventDisposition::ConnectionOutputs => self.outputs.emit(ev),
1111 EventDisposition::Quic => self.quic.emit(ev),
1112 EventDisposition::SendPath => self.send.emit(ev),
1113 EventDisposition::MessageOutput => match self.protocol {
1114 Protocol::Tcp => self.send.emit(ev),
1115 Protocol::Quic(_) => self.quic.emit(ev),
1116 },
1117 EventDisposition::StartTraffic => self.send.emit(ev),
1118 EventDisposition::SideSpecific => self.side.emit(ev),
1119 }
1120 }
1121}
1122
1123pub(crate) struct Input<'a> {
1124 pub(crate) message: Message<'a>,
1125 pub(crate) aligned_handshake: Option<HandshakeAlignedProof>,
1126}
1127
1128impl Input<'_> {
1129 pub(crate) fn check_aligned_handshake(&self) -> Result<HandshakeAlignedProof, Error> {
1134 self.aligned_handshake
1135 .ok_or_else(|| PeerMisbehaved::KeyEpochWithPendingFragment.into())
1136 }
1137}
1138
1139pub(crate) trait Output {
1141 fn emit(&mut self, ev: Event<'_>);
1142
1143 fn received_plaintext(&mut self, _payload: Payload<'_>) {}
1144}
1145
1146pub(crate) enum Event<'a> {
1148 ApplicationProtocol(ApplicationProtocol<'a>),
1149 CipherSuite(SupportedCipherSuite),
1150 EarlyApplicationData(Payload<'a>),
1151 EarlyData(EarlyDataEvent),
1152 EarlyExporter(Box<dyn Exporter>),
1153 EchStatus(EchStatus),
1154 EncryptMessage(Message<'a>),
1155 Exporter(Box<dyn Exporter>),
1156 HandshakeKind(HandshakeKind),
1157 KeyExchangeGroup(&'static dyn SupportedKxGroup),
1158 MaybeKeyUpdateRequest,
1159 MessageDecrypter {
1160 decrypter: Box<dyn MessageDecrypter>,
1161 proof: HandshakeAlignedProof,
1162 },
1163 MessageDecrypterWithTrialDecryption {
1164 decrypter: Box<dyn MessageDecrypter>,
1165 max_length: usize,
1166 proof: HandshakeAlignedProof,
1167 },
1168 MessageEncrypter {
1169 encrypter: Box<dyn MessageEncrypter>,
1170 limit: u64,
1171 },
1172 OutgoingKeySchedule(Box<KeyScheduleTrafficSend>),
1173 PeerIdentity(Identity<'static>),
1174 PlainMessage(Message<'a>),
1175 ProtocolVersion(ProtocolVersion),
1176 QuicEarlySecret(Option<OkmBlock>),
1177 QuicHandshakeSecrets(quic::Secrets),
1178 QuicTrafficSecrets(quic::Secrets),
1179 QuicTransportParameters(Vec<u8>),
1180 ReceivedServerName(Option<DnsName<'static>>),
1181 ReceivedTicket,
1182 ResumptionData(Vec<u8>),
1183 SendAlert(AlertLevel, AlertDescription),
1184 StartHalfRttTraffic,
1186 StartTraffic,
1188}
1189
1190impl Event<'_> {
1191 pub(crate) fn disposition(&self) -> EventDisposition {
1192 match self {
1193 Event::EncryptMessage(_) | Event::PlainMessage(_) => EventDisposition::MessageOutput,
1195
1196 Event::MaybeKeyUpdateRequest
1198 | Event::MessageEncrypter { .. }
1199 | Event::OutgoingKeySchedule(_)
1200 | Event::SendAlert(..)
1201 | Event::StartHalfRttTraffic => EventDisposition::SendPath,
1202
1203 Event::MessageDecrypter { .. }
1205 | Event::MessageDecrypterWithTrialDecryption { .. }
1206 | Event::ReceivedTicket => EventDisposition::ReceivePath,
1207
1208 Event::ApplicationProtocol(_)
1210 | Event::CipherSuite(_)
1211 | Event::EarlyExporter(_)
1212 | Event::Exporter(_)
1213 | Event::HandshakeKind(_)
1214 | Event::KeyExchangeGroup(_)
1215 | Event::PeerIdentity(_) => EventDisposition::ConnectionOutputs,
1216
1217 Event::QuicEarlySecret(_)
1219 | Event::QuicHandshakeSecrets(_)
1220 | Event::QuicTrafficSecrets(_)
1221 | Event::QuicTransportParameters(_) => EventDisposition::Quic,
1222
1223 Event::ProtocolVersion(ver) => EventDisposition::ProtocolVersion(*ver),
1225
1226 Event::StartTraffic => EventDisposition::StartTraffic,
1227
1228 Event::EarlyApplicationData(_)
1230 | Event::EarlyData(_)
1231 | Event::EchStatus(_)
1232 | Event::ReceivedServerName(_)
1233 | Event::ResumptionData(_) => EventDisposition::SideSpecific,
1234 }
1235 }
1236}
1237
1238#[derive(Clone, Copy, Debug)]
1240pub(crate) enum EventDisposition {
1241 MessageOutput,
1243
1244 SendPath,
1246
1247 ReceivePath,
1249
1250 ConnectionOutputs,
1252
1253 Quic,
1255
1256 ProtocolVersion(ProtocolVersion),
1258
1259 StartTraffic,
1261
1262 SideSpecific,
1264}
1265
1266pub(crate) enum EarlyDataEvent {
1267 Accepted,
1269 Enable(usize),
1271 Start,
1273 Finished,
1275 Rejected,
1277}
1278
1279pub(crate) enum UnborrowedPayload {
1284 Unborrowed(Range<usize>),
1285 Owned(Vec<u8>),
1286}
1287
1288impl UnborrowedPayload {
1289 pub(crate) fn unborrow(locator: &Locator, payload: Payload<'_>) -> Self {
1298 match payload {
1299 Payload::Borrowed(payload) => Self::Unborrowed(locator.locate(payload)),
1300 Payload::Owned(payload) => Self::Owned(payload),
1301 }
1302 }
1303
1304 pub(crate) fn reborrow<'b>(self, delocator: &Delocator<'b>) -> Payload<'b> {
1311 match self {
1312 Self::Unborrowed(range) => Payload::Borrowed(delocator.slice_from_range(&range)),
1313 Self::Owned(payload) => Payload::Owned(payload),
1314 }
1315 }
1316}
1317
1318#[expect(clippy::exhaustive_enums)]
1320#[derive(Clone, Copy, Debug, PartialEq)]
1321pub enum Side {
1322 Client,
1324 Server,
1326}
1327
1328#[derive(Copy, Clone, Eq, PartialEq, Debug)]
1329pub(crate) enum Protocol {
1330 Tcp,
1332 Quic(quic::Version),
1334}
1335
1336impl Protocol {
1337 pub(crate) fn is_quic(&self) -> bool {
1338 matches!(self, Self::Quic(_))
1339 }
1340}
1341
1342struct TemperCounters {
1345 allowed_warning_alerts: u8,
1346 allowed_renegotiation_requests: u8,
1347 allowed_middlebox_ccs: u8,
1348}
1349
1350impl TemperCounters {
1351 fn received_warning_alert(&mut self) -> Result<(), Error> {
1352 match self.allowed_warning_alerts {
1353 0 => Err(PeerMisbehaved::TooManyWarningAlertsReceived.into()),
1354 _ => {
1355 self.allowed_warning_alerts -= 1;
1356 Ok(())
1357 }
1358 }
1359 }
1360
1361 fn received_renegotiation_request(&mut self) -> Result<(), Error> {
1362 match self.allowed_renegotiation_requests {
1363 0 => Err(PeerMisbehaved::TooManyRenegotiationRequests.into()),
1364 _ => {
1365 self.allowed_renegotiation_requests -= 1;
1366 Ok(())
1367 }
1368 }
1369 }
1370
1371 fn received_tls13_change_cipher_spec(&mut self) -> Result<(), Error> {
1372 match self.allowed_middlebox_ccs {
1373 0 => Err(PeerMisbehaved::IllegalMiddleboxChangeCipherSpec.into()),
1374 _ => {
1375 self.allowed_middlebox_ccs -= 1;
1376 Ok(())
1377 }
1378 }
1379 }
1380}
1381
1382impl Default for TemperCounters {
1383 fn default() -> Self {
1384 Self {
1385 allowed_warning_alerts: 4,
1388
1389 allowed_renegotiation_requests: 1,
1392
1393 allowed_middlebox_ccs: 2,
1398 }
1399 }
1400}
1401
1402pub(crate) struct TrafficTemperCounters {
1403 allowed_key_update_requests: u8,
1404}
1405
1406impl TrafficTemperCounters {
1407 pub(crate) fn received_key_update_request(&mut self) -> Result<(), Error> {
1408 match self.allowed_key_update_requests {
1409 0 => Err(PeerMisbehaved::TooManyKeyUpdateRequests.into()),
1410 _ => {
1411 self.allowed_key_update_requests -= 1;
1412 Ok(())
1413 }
1414 }
1415 }
1416
1417 pub(crate) fn received_app_data(&mut self) {
1418 self.allowed_key_update_requests = Self::INITIAL_KEY_UPDATE_REQUESTS;
1419 }
1420
1421 const INITIAL_KEY_UPDATE_REQUESTS: u8 = 32;
1424}
1425
1426impl Default for TrafficTemperCounters {
1427 fn default() -> Self {
1428 Self {
1429 allowed_key_update_requests: Self::INITIAL_KEY_UPDATE_REQUESTS,
1430 }
1431 }
1432}
1433
1434pub(crate) struct HandshakeFlight<'a, const TLS13: bool> {
1435 pub(crate) transcript: &'a mut HandshakeHash,
1436 body: Vec<u8>,
1437}
1438
1439impl<'a, const TLS13: bool> HandshakeFlight<'a, TLS13> {
1440 pub(crate) fn new(transcript: &'a mut HandshakeHash) -> Self {
1441 Self {
1442 transcript,
1443 body: Vec::new(),
1444 }
1445 }
1446
1447 pub(crate) fn add(&mut self, hs: HandshakeMessagePayload<'_>) {
1448 let start_len = self.body.len();
1449 hs.encode(&mut self.body);
1450 self.transcript
1451 .add(&self.body[start_len..]);
1452 }
1453
1454 pub(crate) fn finish(self, output: &mut dyn Output) {
1455 let m = Message {
1456 version: match TLS13 {
1457 true => ProtocolVersion::TLSv1_3,
1458 false => ProtocolVersion::TLSv1_2,
1459 },
1460 payload: MessagePayload::HandshakeFlight(Payload::new(self.body)),
1461 };
1462
1463 output.emit(match TLS13 {
1464 true => Event::EncryptMessage(m),
1465 false => Event::PlainMessage(m),
1466 });
1467 }
1468}
1469
1470pub(crate) type HandshakeFlightTls12<'a> = HandshakeFlight<'a, false>;
1471pub(crate) type HandshakeFlightTls13<'a> = HandshakeFlight<'a, true>;
1472
1473struct InboundUnborrowedMessage {
1476 typ: ContentType,
1477 version: ProtocolVersion,
1478 bounds: Range<usize>,
1479}
1480
1481impl InboundUnborrowedMessage {
1482 fn unborrow(locator: &Locator, msg: EncodedMessage<&'_ [u8]>) -> Self {
1483 Self {
1484 typ: msg.typ,
1485 version: msg.version,
1486 bounds: locator.locate(msg.payload),
1487 }
1488 }
1489
1490 fn reborrow<'b>(self, delocator: &Delocator<'b>) -> EncodedMessage<&'b [u8]> {
1491 EncodedMessage {
1492 typ: self.typ,
1493 version: self.version,
1494 payload: delocator.slice_from_range(&self.bounds),
1495 }
1496 }
1497}
1498
1499const ALLOWED_CONSECUTIVE_EMPTY_FRAGMENTS_MAX: u8 = 32;
1502
1503pub(crate) const DEFAULT_BUFFER_LIMIT: usize = 64 * 1024;