1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::fmt;
4use core::ops::{Deref, DerefMut, Range};
5
6use pki_types::{DnsName, FipsStatus};
7
8use crate::client::EchStatus;
9use crate::conn::Exporter;
10use crate::conn::kernel::KernelState;
11use crate::crypto::Identity;
12use crate::crypto::cipher::{
13 DecryptionState, EncodedMessage, EncryptionState, MessageDecrypter, MessageEncrypter,
14 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, ApiMisuse, Error, PeerMisbehaved};
20use crate::hash_hs::HandshakeHash;
21use crate::log::{debug, error, trace, warn};
22use crate::msgs::{
23 AlertLevel, AlertMessagePayload, Codec, Delocator, HandshakeAlignedProof,
24 HandshakeMessagePayload, Locator, Message, MessageFragmenter, MessagePayload,
25};
26use crate::suites::{PartiallyExtractedSecrets, SupportedCipherSuite};
27use crate::tls13::key_schedule::KeyScheduleTrafficSend;
28use crate::unbuffered::{EncryptError, InsufficientSizeError};
29use crate::vecbuf::ChunkVecBuffer;
30use crate::{SideData, quic};
31
32pub(crate) fn process_main_protocol<Data: SideData>(
33 msg: EncodedMessage<&'_ [u8]>,
34 aligned_handshake: Option<HandshakeAlignedProof>,
35 state: Box<dyn State<Data>>,
36 plaintext_locator: &Locator,
37 received_plaintext: &mut Option<UnborrowedPayload>,
38 data: &mut Data,
39) -> Result<Box<dyn State<Data>>, Error> {
40 if msg.typ == ContentType::ChangeCipherSpec && data.recv.drop_tls13_ccs(&msg)? {
42 trace!("Dropping CCS");
43 return Ok(state);
44 }
45
46 let msg = data.parse_and_maybe_drop(&msg)?;
47
48 let Some(msg) = msg else {
49 return Ok(state);
51 };
52
53 let mut cx = CaptureAppData {
54 data,
55 plaintext_locator,
56 received_plaintext,
57 };
58
59 state.handle(
60 Input {
61 message: msg,
62 aligned_handshake,
63 },
64 &mut cx,
65 )
66}
67
68pub struct CommonState {
70 pub(crate) outputs: ConnectionOutputs,
71 pub(crate) send: SendPath,
72 pub(crate) recv: ReceivePath,
73 pub(crate) quic: quic::Quic,
74
75 protocol: Protocol,
77}
78
79impl CommonState {
80 pub(crate) fn new(side: Side, protocol: Protocol) -> Self {
81 Self {
82 outputs: ConnectionOutputs::default(),
83 send: SendPath::default(),
84 recv: ReceivePath::new(side),
85 quic: quic::Quic::default(),
86 protocol,
87 }
88 }
89
90 pub fn wants_write(&self) -> bool {
94 !self.send.sendable_tls.is_empty()
95 }
96
97 pub fn send_close_notify(&mut self) {
105 self.send.send_close_notify()
106 }
107
108 pub fn is_handshaking(&self) -> bool {
116 !(self.send.may_send_application_data && self.recv.may_receive_application_data)
117 }
118
119 pub fn wants_read(&self) -> bool {
129 self.recv.received_plaintext.is_empty()
136 && !self.recv.has_received_close_notify
137 && (self.send.may_send_application_data || self.send.sendable_tls.is_empty())
138 }
139
140 pub(crate) fn current_io_state(&self) -> IoState {
141 IoState {
142 tls_bytes_to_write: self.send.sendable_tls.len(),
143 plaintext_bytes_to_read: self.recv.received_plaintext.len(),
144 peer_has_closed: self.recv.has_received_close_notify,
145 }
146 }
147
148 fn parse_and_maybe_drop<'a>(
149 &mut self,
150 msg: &'a EncodedMessage<&'a [u8]>,
151 ) -> Result<Option<Message<'a>>, Error> {
152 let msg = Message::try_from(msg)?;
154
155 if let MessagePayload::Alert(alert) = &msg.payload {
157 self.recv.process_alert(alert)?;
158 return Ok(None);
159 }
160
161 if self
164 .recv
165 .reject_renegotiation_request(&mut self.send, &msg)?
166 {
167 return Ok(None);
168 }
169
170 Ok(Some(msg))
171 }
172}
173
174impl Output for CommonState {
175 fn emit(&mut self, ev: Event<'_>) {
176 match ev.disposition() {
177 EventDisposition::MessageOutput => match self.protocol {
178 Protocol::Tcp => self.send.emit(ev),
179 Protocol::Quic(_) => self.quic.emit(ev),
180 },
181
182 EventDisposition::SendPath => self.send.emit(ev),
183 EventDisposition::ReceivePath => self.recv.emit(ev),
184 EventDisposition::ConnectionOutputs => self.outputs.emit(ev),
185 EventDisposition::Quic => self.quic.emit(ev),
186 EventDisposition::SideSpecific => unreachable!(),
187
188 EventDisposition::ProtocolVersion(ver) => {
189 self.outputs
190 .emit(Event::ProtocolVersion(ver));
191 self.recv
192 .emit(Event::ProtocolVersion(ver));
193 self.send
194 .emit(Event::ProtocolVersion(ver));
195 }
196 EventDisposition::StartTraffic => {
197 self.recv.emit(Event::StartTraffic);
198 self.send.emit(Event::StartTraffic);
199 }
200 }
201 }
202}
203
204impl Deref for CommonState {
205 type Target = ConnectionOutputs;
206
207 fn deref(&self) -> &Self::Target {
208 &self.outputs
209 }
210}
211
212impl DerefMut for CommonState {
213 fn deref_mut(&mut self) -> &mut Self::Target {
214 &mut self.outputs
215 }
216}
217
218impl fmt::Debug for CommonState {
219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 f.debug_struct("CommonState")
221 .finish_non_exhaustive()
222 }
223}
224
225pub struct ConnectionOutputs {
227 pub(crate) negotiated_version: Option<ProtocolVersion>,
228 handshake_kind: Option<HandshakeKind>,
229 suite: Option<SupportedCipherSuite>,
230 negotiated_kx_group: Option<&'static dyn SupportedKxGroup>,
231 pub(crate) alpn_protocol: Option<ApplicationProtocol<'static>>,
232 pub(crate) peer_identity: Option<Identity<'static>>,
233 pub(crate) exporter: Option<Box<dyn Exporter>>,
234 pub(crate) early_exporter: Option<Box<dyn Exporter>>,
235 pub(crate) fips: FipsStatus,
236 pub(crate) tls13_tickets_received: u32,
237}
238
239impl ConnectionOutputs {
240 pub fn peer_identity(&self) -> Option<&Identity<'static>> {
249 self.peer_identity.as_ref()
250 }
251
252 pub fn alpn_protocol(&self) -> Option<&ApplicationProtocol<'static>> {
258 self.alpn_protocol.as_ref()
259 }
260
261 pub fn negotiated_cipher_suite(&self) -> Option<SupportedCipherSuite> {
265 self.suite
266 }
267
268 pub fn negotiated_key_exchange_group(&self) -> Option<&'static dyn SupportedKxGroup> {
278 self.negotiated_kx_group
279 }
280
281 pub fn protocol_version(&self) -> Option<ProtocolVersion> {
285 self.negotiated_version
286 }
287
288 pub fn handshake_kind(&self) -> Option<HandshakeKind> {
295 self.handshake_kind
296 }
297
298 pub fn tls13_tickets_received(&self) -> u32 {
302 self.tls13_tickets_received
303 }
304
305 pub fn fips(&self) -> FipsStatus {
311 self.fips
312 }
313
314 pub(super) fn into_kernel_parts(self) -> Option<(ProtocolVersion, SupportedCipherSuite)> {
315 let Self {
316 negotiated_version,
317 suite,
318 ..
319 } = self;
320
321 match (negotiated_version, suite) {
322 (Some(version), Some(suite)) => Some((version, suite)),
323 _ => None,
324 }
325 }
326}
327
328impl Output for ConnectionOutputs {
329 fn emit(&mut self, ev: Event<'_>) {
330 match ev {
331 Event::ApplicationProtocol(protocol) => {
332 self.alpn_protocol = Some(ApplicationProtocol::from(protocol.as_ref()).to_owned())
333 }
334 Event::CipherSuite(suite) => self.suite = Some(suite),
335 Event::EarlyExporter(exporter) => self.early_exporter = Some(exporter),
336 Event::Exporter(exporter) => self.exporter = Some(exporter),
337 Event::HandshakeKind(hk) => {
338 assert!(self.handshake_kind.is_none());
339 self.handshake_kind = Some(hk);
340 }
341 Event::KeyExchangeGroup(kxg) => {
342 assert!(self.negotiated_kx_group.is_none());
343 self.negotiated_kx_group = Some(kxg);
344 }
345 Event::PeerIdentity(identity) => self.peer_identity = Some(identity),
346 Event::ProtocolVersion(ver) => {
347 self.negotiated_version = Some(ver);
348 }
349 Event::ReceivedTicket => {
350 self.tls13_tickets_received = self
351 .tls13_tickets_received
352 .saturating_add(1)
353 }
354 _ => unreachable!(),
355 }
356 }
357}
358
359impl Default for ConnectionOutputs {
360 fn default() -> Self {
361 Self {
362 negotiated_version: None,
363 handshake_kind: None,
364 suite: None,
365 negotiated_kx_group: None,
366 alpn_protocol: None,
367 peer_identity: None,
368 exporter: None,
369 early_exporter: None,
370 fips: FipsStatus::Unvalidated,
371 tls13_tickets_received: 0,
372 }
373 }
374}
375
376pub(crate) struct SendPath {
378 pub(crate) encrypt_state: EncryptionState,
379 pub(crate) may_send_application_data: bool,
380 has_sent_fatal_alert: bool,
381 pub(crate) has_sent_close_notify: bool,
383 message_fragmenter: MessageFragmenter,
384 pub(crate) sendable_tls: ChunkVecBuffer,
385 queued_key_update_message: Option<Vec<u8>>,
386 pub(crate) refresh_traffic_keys_pending: bool,
387 negotiated_version: Option<ProtocolVersion>,
388}
389
390impl SendPath {
391 pub(crate) fn maybe_send_fatal_alert(&mut self, error: &Error) {
392 let Ok(alert) = AlertDescription::try_from(error) else {
393 return;
394 };
395 debug_assert!(!self.has_sent_fatal_alert);
396 let m = Message::build_alert(AlertLevel::Fatal, alert);
397 self.send_msg(m, self.encrypt_state.is_encrypting());
398 self.has_sent_fatal_alert = true;
399 }
400
401 pub(crate) fn write_plaintext(
402 &mut self,
403 payload: OutboundPlain<'_>,
404 outgoing_tls: &mut [u8],
405 ) -> Result<usize, EncryptError> {
406 if payload.is_empty() {
407 return Ok(0);
408 }
409
410 let fragments = self
411 .message_fragmenter
412 .fragment_payload(
413 ContentType::ApplicationData,
414 ProtocolVersion::TLSv1_2,
415 payload.clone(),
416 );
417
418 for f in 0..fragments.len() {
419 match self
420 .encrypt_state
421 .pre_encrypt_action(f as u64)
422 {
423 PreEncryptAction::Nothing => {}
424 PreEncryptAction::RefreshOrClose => match self.negotiated_version {
425 Some(ProtocolVersion::TLSv1_3) => {
426 self.refresh_traffic_keys_pending = true;
428 }
429 _ => {
430 error!(
431 "traffic keys exhausted, closing connection to prevent security failure"
432 );
433 self.send_close_notify();
434 return Err(EncryptError::EncryptExhausted);
435 }
436 },
437 PreEncryptAction::Refuse => {
438 return Err(EncryptError::EncryptExhausted);
439 }
440 }
441 }
442
443 self.perhaps_write_key_update();
444
445 self.check_required_size(outgoing_tls, fragments)?;
446
447 let fragments = self
448 .message_fragmenter
449 .fragment_payload(
450 ContentType::ApplicationData,
451 ProtocolVersion::TLSv1_2,
452 payload,
453 );
454
455 Ok(self.write_fragments(outgoing_tls, fragments))
456 }
457
458 #[cfg(feature = "std")]
459 pub(crate) fn send_early_plaintext(&mut self, data: &[u8]) -> usize {
460 debug_assert!(self.encrypt_state.is_encrypting());
461
462 let len = self
465 .sendable_tls
466 .apply_limit(data.len());
467 if len == 0 {
468 return 0;
470 }
471
472 self.send_appdata_encrypt(data[..len].into())
473 }
474
475 fn send_msg_encrypt(&mut self, m: EncodedMessage<Payload<'_>>) {
478 let iter = self
479 .message_fragmenter
480 .fragment_message(&m);
481 for m in iter {
482 self.send_single_fragment(m);
483 }
484 }
485
486 fn send_appdata_encrypt(&mut self, payload: OutboundPlain<'_>) -> usize {
488 let len = payload.len();
489 let iter = self
490 .message_fragmenter
491 .fragment_payload(
492 ContentType::ApplicationData,
493 ProtocolVersion::TLSv1_2,
494 payload,
495 );
496 for m in iter {
497 self.send_single_fragment(m);
498 }
499
500 len
501 }
502
503 fn send_single_fragment(&mut self, m: EncodedMessage<OutboundPlain<'_>>) {
504 if m.typ == ContentType::Alert {
505 let em = self.encrypt_state.encrypt_outgoing(m);
507 self.queue_tls_message(em);
508 return;
509 }
510
511 match self
512 .encrypt_state
513 .next_pre_encrypt_action()
514 {
515 PreEncryptAction::Nothing => {}
516
517 PreEncryptAction::RefreshOrClose => {
520 match self.negotiated_version {
521 Some(ProtocolVersion::TLSv1_3) => {
522 self.refresh_traffic_keys_pending = true;
524 }
525 _ => {
526 error!(
527 "traffic keys exhausted, closing connection to prevent security failure"
528 );
529 self.send_close_notify();
530 return;
531 }
532 }
533 }
534
535 PreEncryptAction::Refuse => {
538 return;
539 }
540 };
541
542 let em = self.encrypt_state.encrypt_outgoing(m);
543 self.queue_tls_message(em);
544 }
545
546 #[cfg(feature = "std")]
552 pub(crate) fn buffer_plaintext(
553 &mut self,
554 payload: OutboundPlain<'_>,
555 sendable_plaintext: &mut ChunkVecBuffer,
556 ) -> usize {
557 self.perhaps_write_key_update();
558 if !self.may_send_application_data {
559 return sendable_plaintext.append_limited_copy(payload);
562 }
563
564 let len = self
567 .sendable_tls
568 .apply_limit(payload.len());
569 if len == 0 {
570 return 0;
572 }
573
574 debug_assert!(self.encrypt_state.is_encrypting());
575 self.send_appdata_encrypt(payload.split_at(len).0)
576 }
577
578 pub(crate) fn send_buffered_plaintext(&mut self, plaintext: &mut ChunkVecBuffer) {
579 while let Some(buf) = plaintext.pop() {
580 self.send_appdata_encrypt(buf.as_slice().into());
581 }
582 }
583
584 fn start_outgoing_traffic(&mut self) {
585 self.may_send_application_data = true;
586 debug_assert!(self.encrypt_state.is_encrypting());
587 }
588
589 fn queue_tls_message(&mut self, m: EncodedMessage<OutboundOpaque>) {
591 self.perhaps_write_key_update();
592 self.sendable_tls.append(m.encode());
593 }
594
595 pub(crate) fn perhaps_write_key_update(&mut self) {
596 if let Some(message) = self.queued_key_update_message.take() {
597 self.sendable_tls.append(message);
598 }
599 }
600
601 fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool) {
603 if !must_encrypt {
604 let msg = &m.into();
605 let iter = self
606 .message_fragmenter
607 .fragment_message(msg);
608 for m in iter {
609 self.queue_tls_message(m.to_unencrypted_opaque());
610 }
611 } else {
612 self.send_msg_encrypt(m.into());
613 }
614 }
615
616 fn send_close_notify(&mut self) {
617 if self.has_sent_fatal_alert {
618 return;
619 }
620 debug!("Sending warning alert {:?}", AlertDescription::CloseNotify);
621 self.has_sent_fatal_alert = true;
622 self.has_sent_close_notify = true;
623 self.send_warning_alert_no_log(AlertDescription::CloseNotify);
624 }
625
626 pub(crate) fn eager_send_close_notify(
627 &mut self,
628 outgoing_tls: &mut [u8],
629 ) -> Result<usize, EncryptError> {
630 self.send_close_notify();
631 self.check_required_size(outgoing_tls, [].into_iter())?;
632 Ok(self.write_fragments(outgoing_tls, [].into_iter()))
633 }
634
635 fn send_warning_alert_no_log(&mut self, desc: AlertDescription) {
636 let m = Message::build_alert(AlertLevel::Warning, desc);
637 self.send_msg(m, self.encrypt_state.is_encrypting());
638 }
639
640 fn check_required_size<'a>(
641 &self,
642 outgoing_tls: &[u8],
643 fragments: impl Iterator<Item = EncodedMessage<OutboundPlain<'a>>>,
644 ) -> Result<(), EncryptError> {
645 let mut required_size = self.sendable_tls.len();
646
647 for m in fragments {
648 required_size += m.encoded_len(&self.encrypt_state);
649 }
650
651 if required_size > outgoing_tls.len() {
652 return Err(EncryptError::InsufficientSize(InsufficientSizeError {
653 required_size,
654 }));
655 }
656
657 Ok(())
658 }
659
660 fn write_fragments<'a>(
661 &mut self,
662 outgoing_tls: &mut [u8],
663 fragments: impl Iterator<Item = EncodedMessage<OutboundPlain<'a>>>,
664 ) -> usize {
665 let mut written = 0;
666
667 while let Some(message) = self.sendable_tls.pop() {
670 let len = message.len();
671 outgoing_tls[written..written + len].copy_from_slice(&message);
672 written += len;
673 }
674
675 for m in fragments {
676 let em = self
677 .encrypt_state
678 .encrypt_outgoing(m)
679 .encode();
680
681 let len = em.len();
682 outgoing_tls[written..written + len].copy_from_slice(&em);
683 written += len;
684 }
685
686 written
687 }
688
689 pub(crate) fn set_max_fragment_size(&mut self, new: Option<usize>) -> Result<(), Error> {
690 self.message_fragmenter
691 .set_max_fragment_size(new)
692 }
693
694 pub(crate) fn ensure_key_update_queued(&mut self) -> bool {
695 if self.queued_key_update_message.is_some() {
696 return false;
697 }
698 let message = EncodedMessage::<Payload<'static>>::from(Message::build_key_update_notify());
699 self.queued_key_update_message = Some(
700 self.encrypt_state
701 .encrypt_outgoing(message.borrow_outbound())
702 .encode(),
703 );
704 true
705 }
706}
707impl Output for SendPath {
708 fn emit(&mut self, ev: Event<'_>) {
709 match ev {
710 Event::EncryptMessage(m) => self.send_msg(m, true),
711 Event::MaybeKeyUpdateRequest(ks) => {
712 if self.ensure_key_update_queued() {
713 ks.update_encrypter_for_key_update(self);
714 }
715 }
716 Event::MessageEncrypter { encrypter, limit } => self
717 .encrypt_state
718 .set_message_encrypter(encrypter, limit),
719 Event::PlainMessage(m) => self.send_msg(m, false),
720 Event::ProtocolVersion(ver) => self.negotiated_version = Some(ver),
721 Event::StartOutgoingTraffic | Event::StartTraffic => self.start_outgoing_traffic(),
722 _ => unreachable!(),
723 }
724 }
725}
726
727impl Default for SendPath {
728 fn default() -> Self {
729 Self {
730 encrypt_state: EncryptionState::new(),
731 may_send_application_data: false,
732 has_sent_fatal_alert: false,
733 has_sent_close_notify: false,
734 message_fragmenter: MessageFragmenter::default(),
735 sendable_tls: ChunkVecBuffer::new(Some(DEFAULT_BUFFER_LIMIT)),
736 queued_key_update_message: None,
737 refresh_traffic_keys_pending: false,
738 negotiated_version: None,
739 }
740 }
741}
742
743pub(crate) struct ReceivePath {
744 side: Side,
745 pub(crate) decrypt_state: DecryptionState,
746 may_receive_application_data: bool,
747 pub(crate) has_received_close_notify: bool,
749 #[cfg(feature = "std")]
750 pub(crate) has_seen_eof: bool,
751 pub(crate) received_plaintext: ChunkVecBuffer,
752 temper_counters: TemperCounters,
753 negotiated_version: Option<ProtocolVersion>,
754}
755
756impl ReceivePath {
757 fn new(side: Side) -> Self {
758 Self {
759 side,
760 decrypt_state: DecryptionState::new(),
761 may_receive_application_data: false,
762 has_received_close_notify: false,
763 #[cfg(feature = "std")]
764 has_seen_eof: false,
765 received_plaintext: ChunkVecBuffer::new(Some(DEFAULT_RECEIVED_PLAINTEXT_LIMIT)),
766 temper_counters: TemperCounters::default(),
767 negotiated_version: None,
768 }
769 }
770
771 fn drop_tls13_ccs(&mut self, msg: &EncodedMessage<&'_ [u8]>) -> Result<bool, Error> {
772 if self.may_receive_application_data
773 || !matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
774 {
775 return Ok(false);
776 }
777
778 if !msg.is_valid_ccs() {
779 return Err(PeerMisbehaved::IllegalMiddleboxChangeCipherSpec.into());
783 }
784
785 self.temper_counters
786 .received_tls13_change_cipher_spec()?;
787 Ok(true)
788 }
789
790 fn reject_renegotiation_request(
791 &mut self,
792 send: &mut SendPath,
793 msg: &Message<'_>,
794 ) -> Result<bool, Error> {
795 if !self.may_receive_application_data
796 || matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
797 {
798 return Ok(false);
799 }
800
801 let reject_ty = match self.side {
802 Side::Client => HandshakeType::HelloRequest,
803 Side::Server => HandshakeType::ClientHello,
804 };
805
806 if msg.handshake_type() != Some(reject_ty) {
807 return Ok(false);
808 }
809 self.temper_counters
810 .received_renegotiation_request()?;
811 let desc = AlertDescription::NoRenegotiation;
812 warn!("sending warning alert {desc:?}");
813 send.send_warning_alert_no_log(desc);
814 Ok(true)
815 }
816
817 pub(crate) fn process_alert(&mut self, alert: &AlertMessagePayload) -> Result<(), Error> {
818 if let AlertLevel::Unknown(level) = alert.level {
820 return Err(PeerMisbehaved::IllegalAlertLevel(level, alert.description).into());
821 }
822
823 if self.may_receive_application_data && alert.description == AlertDescription::CloseNotify {
826 self.has_received_close_notify = true;
827 return Ok(());
828 }
829
830 let err = Error::AlertReceived(alert.description);
833 if alert.level == AlertLevel::Warning {
834 self.temper_counters
835 .received_warning_alert()?;
836 if matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
837 && alert.description != AlertDescription::UserCanceled
838 {
839 return Err(PeerMisbehaved::IllegalWarningAlert(alert.description).into());
840 }
841
842 if alert.description != AlertDescription::UserCanceled || cfg!(debug_assertions) {
845 warn!("TLS alert warning received: {alert:?}");
846 }
847
848 return Ok(());
849 }
850
851 Err(err)
852 }
853}
854
855impl Output for ReceivePath {
856 fn emit(&mut self, ev: Event<'_>) {
857 match ev {
858 Event::MessageDecrypter { decrypter, proof } => self
859 .decrypt_state
860 .set_message_decrypter(decrypter, &proof),
861 Event::MessageDecrypterWithTrialDecryption {
862 decrypter,
863 max_length,
864 proof,
865 } => self
866 .decrypt_state
867 .set_message_decrypter_with_trial_decryption(decrypter, max_length, &proof),
868 Event::ProtocolVersion(ver) => self.negotiated_version = Some(ver),
869 Event::StartTraffic => self.may_receive_application_data = true,
870 _ => unreachable!(),
871 }
872 }
873}
874
875#[derive(Debug, PartialEq, Clone, Copy)]
877#[non_exhaustive]
878pub enum HandshakeKind {
879 Full,
884
885 FullWithHelloRetryRequest,
891
892 Resumed,
898
899 ResumedWithHelloRetryRequest,
905}
906
907#[derive(Debug, Eq, PartialEq)]
912pub struct IoState {
913 tls_bytes_to_write: usize,
914 plaintext_bytes_to_read: usize,
915 peer_has_closed: bool,
916}
917
918impl IoState {
919 pub fn tls_bytes_to_write(&self) -> usize {
924 self.tls_bytes_to_write
925 }
926
927 pub fn plaintext_bytes_to_read(&self) -> usize {
930 self.plaintext_bytes_to_read
931 }
932
933 pub fn peer_has_closed(&self) -> bool {
942 self.peer_has_closed
943 }
944}
945
946pub(crate) trait State<Side: SideData>: Send + Sync {
947 fn handle<'m>(
948 self: Box<Self>,
949 input: Input<'m>,
950 output: &mut dyn Output,
951 ) -> Result<Box<dyn State<Side>>, Error>;
952
953 fn send_key_update_request(&mut self, _output: &mut dyn Output) -> Result<(), Error> {
954 Err(Error::HandshakeNotComplete)
955 }
956
957 fn handle_decrypt_error(&self) {}
958
959 #[cfg_attr(not(feature = "std"), expect(dead_code))]
960 fn set_resumption_data(&mut self, _resumption_data: &[u8]) -> Result<(), Error> {
961 Err(ApiMisuse::ResumptionDataProvidedTooLate.into())
962 }
963
964 fn into_external_state(
965 self: Box<Self>,
966 ) -> Result<(PartiallyExtractedSecrets, Box<dyn KernelState + 'static>), Error> {
967 Err(Error::HandshakeNotComplete)
968 }
969}
970
971struct CaptureAppData<'a> {
972 data: &'a mut dyn Output,
973 plaintext_locator: &'a Locator,
978 received_plaintext: &'a mut Option<UnborrowedPayload>,
985}
986
987impl Output for CaptureAppData<'_> {
988 fn emit(&mut self, ev: Event<'_>) {
989 match ev {
990 Event::ApplicationData(payload) => {
991 let previous = self
998 .received_plaintext
999 .replace(UnborrowedPayload::unborrow(self.plaintext_locator, payload));
1000 debug_assert!(previous.is_none(), "overwrote plaintext data");
1001 }
1002 _ => self.data.emit(ev),
1003 }
1004 }
1005}
1006
1007pub(crate) struct Input<'a> {
1008 pub(crate) message: Message<'a>,
1009 pub(crate) aligned_handshake: Option<HandshakeAlignedProof>,
1010}
1011
1012impl Input<'_> {
1013 pub(crate) fn check_aligned_handshake(&self) -> Result<HandshakeAlignedProof, Error> {
1018 self.aligned_handshake
1019 .ok_or_else(|| PeerMisbehaved::KeyEpochWithPendingFragment.into())
1020 }
1021}
1022
1023pub(crate) trait Output {
1025 fn emit(&mut self, ev: Event<'_>);
1026}
1027
1028pub(crate) enum Event<'a> {
1030 ApplicationData(Payload<'a>),
1031 ApplicationProtocol(ApplicationProtocol<'a>),
1032 CipherSuite(SupportedCipherSuite),
1033 EarlyApplicationData(Payload<'a>),
1034 EarlyData(EarlyDataEvent),
1035 EarlyExporter(Box<dyn Exporter>),
1036 EchStatus(EchStatus),
1037 EncryptMessage(Message<'a>),
1038 Exporter(Box<dyn Exporter>),
1039 HandshakeKind(HandshakeKind),
1040 KeyExchangeGroup(&'static dyn SupportedKxGroup),
1041 MaybeKeyUpdateRequest(&'a mut KeyScheduleTrafficSend),
1042 MessageDecrypter {
1043 decrypter: Box<dyn MessageDecrypter>,
1044 proof: HandshakeAlignedProof,
1045 },
1046 MessageDecrypterWithTrialDecryption {
1047 decrypter: Box<dyn MessageDecrypter>,
1048 max_length: usize,
1049 proof: HandshakeAlignedProof,
1050 },
1051 MessageEncrypter {
1052 encrypter: Box<dyn MessageEncrypter>,
1053 limit: u64,
1054 },
1055 PeerIdentity(Identity<'static>),
1056 PlainMessage(Message<'a>),
1057 ProtocolVersion(ProtocolVersion),
1058 QuicEarlySecret(Option<OkmBlock>),
1059 QuicHandshakeSecrets(quic::Secrets),
1060 QuicTrafficSecrets(quic::Secrets),
1061 QuicTransportParameters(Vec<u8>),
1062 ReceivedServerName(Option<DnsName<'static>>),
1063 ReceivedTicket,
1064 ResumptionData(Vec<u8>),
1065 StartOutgoingTraffic,
1067 StartTraffic,
1069}
1070
1071impl Event<'_> {
1072 fn disposition(&self) -> EventDisposition {
1073 match self {
1074 Event::EncryptMessage(_) | Event::PlainMessage(_) => EventDisposition::MessageOutput,
1076
1077 Event::MaybeKeyUpdateRequest(_)
1079 | Event::MessageEncrypter { .. }
1080 | Event::StartOutgoingTraffic => EventDisposition::SendPath,
1081
1082 Event::MessageDecrypter { .. } | Event::MessageDecrypterWithTrialDecryption { .. } => {
1084 EventDisposition::ReceivePath
1085 }
1086
1087 Event::ApplicationProtocol(_)
1089 | Event::CipherSuite(_)
1090 | Event::EarlyExporter(_)
1091 | Event::Exporter(_)
1092 | Event::HandshakeKind(_)
1093 | Event::KeyExchangeGroup(_)
1094 | Event::PeerIdentity(_)
1095 | Event::ReceivedTicket => EventDisposition::ConnectionOutputs,
1096
1097 Event::QuicEarlySecret(_)
1099 | Event::QuicHandshakeSecrets(_)
1100 | Event::QuicTrafficSecrets(_)
1101 | Event::QuicTransportParameters(_) => EventDisposition::Quic,
1102
1103 Event::ProtocolVersion(ver) => EventDisposition::ProtocolVersion(*ver),
1105
1106 Event::StartTraffic => EventDisposition::StartTraffic,
1107
1108 Event::ApplicationData(_)
1110 | Event::EarlyApplicationData(_)
1111 | Event::EarlyData(_)
1112 | Event::EchStatus(_)
1113 | Event::ReceivedServerName(_)
1114 | Event::ResumptionData(_) => EventDisposition::SideSpecific,
1115 }
1116 }
1117}
1118
1119#[derive(Clone, Copy, Debug)]
1121pub(crate) enum EventDisposition {
1122 MessageOutput,
1124
1125 SendPath,
1127
1128 ReceivePath,
1130
1131 ConnectionOutputs,
1133
1134 Quic,
1136
1137 ProtocolVersion(ProtocolVersion),
1139
1140 StartTraffic,
1142
1143 SideSpecific,
1145}
1146
1147pub(crate) enum EarlyDataEvent {
1148 Accepted,
1150 Enable(usize),
1152 Start,
1154 Finished,
1156 Rejected,
1158}
1159
1160pub(crate) enum UnborrowedPayload {
1165 Unborrowed(Range<usize>),
1166 Owned(Vec<u8>),
1167}
1168
1169impl UnborrowedPayload {
1170 pub(crate) fn unborrow(locator: &Locator, payload: Payload<'_>) -> Self {
1179 match payload {
1180 Payload::Borrowed(payload) => Self::Unborrowed(locator.locate(payload)),
1181 Payload::Owned(payload) => Self::Owned(payload),
1182 }
1183 }
1184
1185 pub(crate) fn reborrow<'b>(self, delocator: &Delocator<'b>) -> Payload<'b> {
1192 match self {
1193 Self::Unborrowed(range) => Payload::Borrowed(delocator.slice_from_range(&range)),
1194 Self::Owned(payload) => Payload::Owned(payload),
1195 }
1196 }
1197}
1198
1199#[expect(clippy::exhaustive_enums)]
1201#[derive(Clone, Copy, Debug, PartialEq)]
1202pub enum Side {
1203 Client,
1205 Server,
1207}
1208
1209#[derive(Copy, Clone, Eq, PartialEq, Debug)]
1210pub(crate) enum Protocol {
1211 Tcp,
1213 #[cfg_attr(not(feature = "std"), expect(dead_code))]
1215 Quic(quic::Version),
1216}
1217
1218impl Protocol {
1219 pub(crate) fn is_quic(&self) -> bool {
1220 matches!(self, Self::Quic(_))
1221 }
1222}
1223
1224struct TemperCounters {
1227 allowed_warning_alerts: u8,
1228 allowed_renegotiation_requests: u8,
1229 allowed_middlebox_ccs: u8,
1230}
1231
1232impl TemperCounters {
1233 fn received_warning_alert(&mut self) -> Result<(), Error> {
1234 match self.allowed_warning_alerts {
1235 0 => Err(PeerMisbehaved::TooManyWarningAlertsReceived.into()),
1236 _ => {
1237 self.allowed_warning_alerts -= 1;
1238 Ok(())
1239 }
1240 }
1241 }
1242
1243 fn received_renegotiation_request(&mut self) -> Result<(), Error> {
1244 match self.allowed_renegotiation_requests {
1245 0 => Err(PeerMisbehaved::TooManyRenegotiationRequests.into()),
1246 _ => {
1247 self.allowed_renegotiation_requests -= 1;
1248 Ok(())
1249 }
1250 }
1251 }
1252
1253 fn received_tls13_change_cipher_spec(&mut self) -> Result<(), Error> {
1254 match self.allowed_middlebox_ccs {
1255 0 => Err(PeerMisbehaved::IllegalMiddleboxChangeCipherSpec.into()),
1256 _ => {
1257 self.allowed_middlebox_ccs -= 1;
1258 Ok(())
1259 }
1260 }
1261 }
1262}
1263
1264impl Default for TemperCounters {
1265 fn default() -> Self {
1266 Self {
1267 allowed_warning_alerts: 4,
1270
1271 allowed_renegotiation_requests: 1,
1274
1275 allowed_middlebox_ccs: 2,
1280 }
1281 }
1282}
1283
1284pub(crate) struct TrafficTemperCounters {
1285 allowed_key_update_requests: u8,
1286}
1287
1288impl TrafficTemperCounters {
1289 pub(crate) fn received_key_update_request(&mut self) -> Result<(), Error> {
1290 match self.allowed_key_update_requests {
1291 0 => Err(PeerMisbehaved::TooManyKeyUpdateRequests.into()),
1292 _ => {
1293 self.allowed_key_update_requests -= 1;
1294 Ok(())
1295 }
1296 }
1297 }
1298
1299 pub(crate) fn received_app_data(&mut self) {
1300 self.allowed_key_update_requests = Self::INITIAL_KEY_UPDATE_REQUESTS;
1301 }
1302
1303 const INITIAL_KEY_UPDATE_REQUESTS: u8 = 32;
1306}
1307
1308impl Default for TrafficTemperCounters {
1309 fn default() -> Self {
1310 Self {
1311 allowed_key_update_requests: Self::INITIAL_KEY_UPDATE_REQUESTS,
1312 }
1313 }
1314}
1315
1316pub(crate) struct HandshakeFlight<'a, const TLS13: bool> {
1317 pub(crate) transcript: &'a mut HandshakeHash,
1318 body: Vec<u8>,
1319}
1320
1321impl<'a, const TLS13: bool> HandshakeFlight<'a, TLS13> {
1322 pub(crate) fn new(transcript: &'a mut HandshakeHash) -> Self {
1323 Self {
1324 transcript,
1325 body: Vec::new(),
1326 }
1327 }
1328
1329 pub(crate) fn add(&mut self, hs: HandshakeMessagePayload<'_>) {
1330 let start_len = self.body.len();
1331 hs.encode(&mut self.body);
1332 self.transcript
1333 .add(&self.body[start_len..]);
1334 }
1335
1336 pub(crate) fn finish(self, output: &mut dyn Output) {
1337 let m = Message {
1338 version: match TLS13 {
1339 true => ProtocolVersion::TLSv1_3,
1340 false => ProtocolVersion::TLSv1_2,
1341 },
1342 payload: MessagePayload::HandshakeFlight(Payload::new(self.body)),
1343 };
1344
1345 output.emit(match TLS13 {
1346 true => Event::EncryptMessage(m),
1347 false => Event::PlainMessage(m),
1348 });
1349 }
1350}
1351
1352pub(crate) type HandshakeFlightTls12<'a> = HandshakeFlight<'a, false>;
1353pub(crate) type HandshakeFlightTls13<'a> = HandshakeFlight<'a, true>;
1354
1355const DEFAULT_RECEIVED_PLAINTEXT_LIMIT: usize = 16 * 1024;
1356pub(crate) const DEFAULT_BUFFER_LIMIT: usize = 64 * 1024;