1use alloc::vec::Vec;
2use core::ops::{Deref, DerefMut, Range};
3use core::{fmt, slice};
4
5use crate::Protocol;
6use crate::crypto::cipher::EncryptionState;
7use crate::enums::{ContentType, ProtocolVersion};
8use crate::error::{ApiMisuse, Error, InvalidMessage, PeerMisbehaved};
9use crate::msgs::{Codec, HEADER_SIZE, MAX_FRAGMENT_LEN, Reader, hex, read_opaque_message_header};
10
11#[expect(clippy::exhaustive_structs)]
13#[derive(Clone, Debug)]
14pub struct EncodedMessage<P> {
15 pub typ: ContentType,
17 pub version: EncodableVersion,
19 pub payload: P,
21}
22
23impl<P> EncodedMessage<P> {
24 pub fn new(typ: ContentType, version: EncodableVersion, payload: P) -> Self {
26 Self {
27 typ,
28 version,
29 payload,
30 }
31 }
32}
33
34impl<'a> EncodedMessage<Payload<'a>> {
35 pub(crate) fn read(r: &mut Reader<'a>) -> Result<Self, MessageError> {
40 let (typ, version, len) = read_opaque_message_header(r)?;
41
42 let content = r
43 .take(len as usize)
44 .ok_or(MessageError::TooShortForLength)?;
45
46 Ok(Self {
47 typ,
48 version: EncodableVersion::Legacy(version),
49 payload: Payload::Borrowed(content),
50 })
51 }
52
53 pub fn borrow_outbound(&'a self) -> EncodedMessage<OutboundPlain<'a>> {
55 EncodedMessage {
56 typ: self.typ,
57 version: self.version,
58 payload: self.payload.bytes().into(),
59 }
60 }
61
62 pub fn into_owned(self) -> Self {
64 Self {
65 typ: self.typ,
66 version: self.version,
67 payload: self.payload.into_owned(),
68 }
69 }
70}
71
72impl EncodedMessage<&'_ [u8]> {
73 pub(crate) fn is_valid_ccs(&self) -> bool {
79 self.typ == ContentType::ChangeCipherSpec && self.payload == [0x01]
80 }
81}
82
83impl<'a> EncodedMessage<InboundOpaque<'a>> {
84 pub fn into_tls13_unpadded_message(mut self) -> Result<EncodedMessage<&'a [u8]>, Error> {
89 let payload = &mut self.payload;
90
91 if self.typ != ContentType::ApplicationData {
92 return Err(PeerMisbehaved::IllegalTls13ContentType.into());
93 }
94
95 if payload.len() > MAX_FRAGMENT_LEN.get() + 1 {
96 return Err(Error::PeerSentOversizedRecord);
97 }
98
99 self.typ = unpad_tls13_payload(payload);
100 if self.typ == ContentType(0) {
101 return Err(PeerMisbehaved::IllegalTlsInnerPlaintext.into());
102 }
103
104 if payload.len() > MAX_FRAGMENT_LEN.get() {
105 return Err(Error::PeerSentOversizedRecord);
106 }
107
108 self.version = EncodableVersion::Legacy(ProtocolVersion::TLSv1_3);
109 Ok(self.into_plain_message())
110 }
111
112 pub fn into_plain_message_range(self, range: Range<usize>) -> EncodedMessage<&'a [u8]> {
121 EncodedMessage {
122 typ: self.typ,
123 version: self.version,
124 payload: &self.payload.into_inner()[range],
125 }
126 }
127
128 pub fn into_plain_message(self) -> EncodedMessage<&'a [u8]> {
134 EncodedMessage {
135 typ: self.typ,
136 version: self.version,
137 payload: self.payload.into_inner(),
138 }
139 }
140}
141
142impl EncodedMessage<OutboundPlain<'_>> {
143 pub(crate) fn to_unencrypted_bytes(&self) -> Vec<u8> {
146 let len = self.payload.len();
147 debug_assert!(len <= usize::from(u16::MAX));
148 let mut buf = Vec::with_capacity(HEADER_SIZE + len);
149 self.encode_unencrypted(&mut buf);
150 buf
151 }
152
153 pub(crate) fn encode_unencrypted(&self, buf: &mut Vec<u8>) {
154 let len = self.payload.len();
155 debug_assert!(len <= usize::from(u16::MAX));
156 buf.extend_from_slice(&encode_record_header(self.typ, self.version, len as u16));
157 self.payload.copy_to_vec(buf);
158 }
159
160 #[expect(dead_code)]
161 pub(crate) fn encoded_len(&self, record_layer: &EncryptionState) -> usize {
162 HEADER_SIZE + record_layer.encrypted_len(self.payload.len())
163 }
164}
165
166pub(crate) fn encode_record_header(
170 typ: ContentType,
171 version: EncodableVersion,
172 len: u16,
173) -> [u8; HEADER_SIZE] {
174 let [version_hi, version_lo] = version.encode().to_array();
175 let [len_hi, len_lo] = len.to_be_bytes();
176 [typ.into(), version_hi, version_lo, len_hi, len_lo]
177}
178
179#[non_exhaustive]
184#[derive(Debug, Clone)]
185pub enum OutboundPlain<'a> {
186 Single(&'a [u8]),
190 Multiple {
192 chunks: &'a [&'a [u8]],
194 start: usize,
200 end: usize,
204 },
205}
206
207impl<'a> OutboundPlain<'a> {
208 pub fn new(chunks: &'a [&'a [u8]]) -> Self {
211 if chunks.len() == 1 {
212 Self::Single(chunks[0])
213 } else {
214 Self::Multiple {
215 chunks,
216 start: 0,
217 end: chunks
218 .iter()
219 .map(|chunk| chunk.len())
220 .sum(),
221 }
222 }
223 }
224
225 pub fn new_empty() -> Self {
227 Self::Single(&[])
228 }
229
230 pub fn to_vec(&self) -> Vec<u8> {
232 let mut vec = Vec::with_capacity(self.len());
233 self.copy_to_vec(&mut vec);
234 vec
235 }
236
237 pub fn copy_to_vec(&self, vec: &mut Vec<u8>) {
239 for chunk in self.chunks() {
240 vec.extend_from_slice(chunk);
241 }
242 }
243
244 pub fn chunks(&self) -> impl Iterator<Item = &[u8]> + '_ {
248 match self {
249 Self::Single(chunk) => Chunks::Single((!chunk.is_empty()).then_some(*chunk)),
250 Self::Multiple { chunks, start, end } => Chunks::Multiple {
251 chunks: chunks.iter(),
252 skip: *start,
253 remaining: end - start,
254 },
255 }
256 }
257
258 pub fn single_chunk(&self) -> Option<&'a [u8]> {
263 match *self {
264 Self::Single(chunk) => Some(chunk),
265 Self::Multiple { .. } => None,
266 }
267 }
268
269 pub(crate) fn split_at(&self, mid: usize) -> (Self, Self) {
272 match *self {
273 Self::Single(chunk) => {
274 let mid = Ord::min(mid, chunk.len());
275 (Self::Single(&chunk[..mid]), Self::Single(&chunk[mid..]))
276 }
277 Self::Multiple { chunks, start, end } => {
278 let mid = Ord::min(start + mid, end);
279 (
280 Self::Multiple {
281 chunks,
282 start,
283 end: mid,
284 },
285 Self::Multiple {
286 chunks,
287 start: mid,
288 end,
289 },
290 )
291 }
292 }
293 }
294
295 pub(crate) fn is_empty(&self) -> bool {
297 self.len() == 0
298 }
299
300 #[expect(clippy::len_without_is_empty)]
302 pub fn len(&self) -> usize {
303 match self {
304 Self::Single(chunk) => chunk.len(),
305 Self::Multiple { start, end, .. } => end - start,
306 }
307 }
308}
309
310enum Chunks<'a> {
312 Single(Option<&'a [u8]>),
313 Multiple {
314 chunks: slice::Iter<'a, &'a [u8]>,
316 skip: usize,
318 remaining: usize,
320 },
321}
322
323impl<'a> Iterator for Chunks<'a> {
324 type Item = &'a [u8];
325
326 fn next(&mut self) -> Option<Self::Item> {
327 let (chunks, skip, remaining) = match self {
328 Self::Single(chunk) => return chunk.take(),
329 Self::Multiple {
330 chunks,
331 skip,
332 remaining,
333 } => (chunks, skip, remaining),
334 };
335
336 loop {
337 if *remaining == 0 {
338 return None;
339 }
340
341 let chunk = chunks.next()?;
342 let Some((_, chunk)) = chunk.split_at_checked(*skip) else {
343 *skip -= chunk.len();
344 continue;
345 };
346
347 *skip = 0;
348 if chunk.is_empty() {
349 continue;
350 }
351
352 let take = Ord::min(chunk.len(), *remaining);
353 *remaining -= take;
354 return Some(&chunk[..take]);
355 }
356 }
357}
358
359impl<'a> From<&'a [u8]> for OutboundPlain<'a> {
360 fn from(payload: &'a [u8]) -> Self {
361 Self::Single(payload)
362 }
363}
364
365impl<'a, const N: usize> From<&'a [u8; N]> for OutboundPlain<'a> {
366 fn from(payload: &'a [u8; N]) -> Self {
367 Self::Single(payload)
368 }
369}
370
371impl<'a> From<&'a Vec<u8>> for OutboundPlain<'a> {
372 fn from(payload: &'a Vec<u8>) -> Self {
373 Self::Single(payload)
374 }
375}
376
377pub struct EncryptBuffer<'a> {
396 buf: &'a mut [u8],
397 used: usize,
398}
399
400impl<'a> EncryptBuffer<'a> {
401 pub fn new(out: &'a mut [u8], len: usize) -> Result<Self, Error> {
405 let provided = out.len();
406 match out.get_mut(..len) {
407 Some(buf) => Ok(Self { buf, used: 0 }),
408 None => Err(ApiMisuse::EncryptBufferTooSmall {
409 required: len,
410 provided,
411 }
412 .into()),
413 }
414 }
415
416 pub fn extend_from_chunks(&mut self, chunks: &OutboundPlain<'_>) {
422 match chunks {
423 OutboundPlain::Single(chunk) => self.extend_from_slice(chunk),
425 chunks => {
426 for chunk in chunks.chunks() {
427 self.extend_from_slice(chunk);
428 }
429 }
430 }
431 }
432
433 pub fn extend_from_slice(&mut self, slice: &[u8]) {
439 self.buf[self.used..self.used + slice.len()].copy_from_slice(slice);
440 self.used += slice.len();
441 }
442
443 pub fn into_written(self) -> &'a [u8] {
445 &self.buf[..self.used]
446 }
447}
448
449impl AsMut<[u8]> for EncryptBuffer<'_> {
450 fn as_mut(&mut self) -> &mut [u8] {
451 &mut self.buf[..self.used]
452 }
453}
454
455#[non_exhaustive]
462#[derive(Clone, Eq, PartialEq)]
463pub enum Payload<'a> {
464 Borrowed(&'a [u8]),
466 Owned(Vec<u8>),
468}
469
470impl<'a> Payload<'a> {
471 pub fn bytes(&'a self) -> &'a [u8] {
473 match self {
474 Self::Borrowed(bytes) => bytes,
475 Self::Owned(bytes) => bytes,
476 }
477 }
478
479 pub(crate) fn into_owned(self) -> Payload<'static> {
480 Payload::Owned(self.into_vec())
481 }
482
483 pub(crate) fn into_vec(self) -> Vec<u8> {
484 match self {
485 Self::Borrowed(bytes) => bytes.to_vec(),
486 Self::Owned(bytes) => bytes,
487 }
488 }
489
490 pub(crate) fn read(r: &mut Reader<'a>) -> Self {
491 Self::Borrowed(r.rest())
492 }
493}
494
495impl Payload<'static> {
496 pub fn new(bytes: impl Into<Vec<u8>>) -> Self {
498 Self::Owned(bytes.into())
499 }
500}
501
502impl<'a> Codec<'a> for Payload<'a> {
503 fn encode(&self, bytes: &mut Vec<u8>) {
504 bytes.extend_from_slice(self.bytes());
505 }
506
507 fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
508 Ok(Self::read(r))
509 }
510}
511
512impl fmt::Debug for Payload<'_> {
513 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
514 hex(f, self.bytes())
515 }
516}
517
518#[expect(clippy::exhaustive_structs)]
520pub struct InboundOpaque<'a>(pub &'a mut [u8]);
521
522impl<'a> InboundOpaque<'a> {
523 pub fn truncate(&mut self, len: usize) {
525 if len >= self.len() {
526 return;
527 }
528
529 self.0 = core::mem::take(&mut self.0)
530 .split_at_mut(len)
531 .0;
532 }
533
534 pub(crate) fn into_inner(self) -> &'a mut [u8] {
535 self.0
536 }
537
538 pub(crate) fn pop(&mut self) -> Option<u8> {
539 if self.is_empty() {
540 return None;
541 }
542
543 let len = self.len();
544 let last = self[len - 1];
545 self.truncate(len - 1);
546 Some(last)
547 }
548}
549
550impl Deref for InboundOpaque<'_> {
551 type Target = [u8];
552
553 fn deref(&self) -> &Self::Target {
554 self.0
555 }
556}
557
558impl DerefMut for InboundOpaque<'_> {
559 fn deref_mut(&mut self) -> &mut Self::Target {
560 self.0
561 }
562}
563
564#[derive(Clone, Copy, Debug, PartialEq, Eq)]
566#[non_exhaustive]
567pub enum EncodableVersion {
568 Legacy(ProtocolVersion),
575 InitialClientHello(Protocol),
582}
583
584impl EncodableVersion {
585 pub fn encode(&self) -> ProtocolVersion {
587 match self {
588 Self::Legacy(_) => ProtocolVersion::TLSv1_2,
589 Self::InitialClientHello(Protocol::Tcp | Protocol::Quic(_)) => ProtocolVersion::TLSv1_0,
590 }
591 }
592
593 pub fn version(&self) -> ProtocolVersion {
595 match self {
596 Self::Legacy(v) => *v,
597 Self::InitialClientHello(Protocol::Tcp | Protocol::Quic(_)) => ProtocolVersion::TLSv1_2,
598 }
599 }
600}
601
602fn unpad_tls13_payload(p: &mut InboundOpaque<'_>) -> ContentType {
610 loop {
611 match p.pop() {
612 Some(0) => {}
613 Some(content_type) => return ContentType::from(content_type),
614 None => return ContentType(0),
615 }
616 }
617}
618
619#[expect(missing_docs)]
621#[non_exhaustive]
622#[derive(Debug)]
623pub enum MessageError {
624 TooShortForHeader,
625 TooShortForLength,
626 InvalidEmptyPayload,
627 MessageTooLarge,
628 InvalidContentType,
629 UnknownProtocolVersion,
630}
631
632#[cfg(test)]
633mod tests {
634 use std::{println, vec};
635
636 use super::*;
637 use crate::quic;
638
639 #[test]
640 fn encrypt_buffer_appends() {
641 let mut space = [0u8; 8];
642 let mut buf = EncryptBuffer::new(&mut space[..], 6).unwrap();
643 buf.extend_from_slice(&[1, 2]);
644 buf.extend_from_chunks(&OutboundPlain::new(&[&[3u8, 4][..], &[5][..]]));
645 buf.extend_from_slice(&[6]);
646 assert_eq!(buf.as_mut(), &mut [1, 2, 3, 4, 5, 6]);
647 assert_eq!(buf.into_written(), &[1, 2, 3, 4, 5, 6]);
648 assert_eq!(space, [1, 2, 3, 4, 5, 6, 0, 0]);
649 }
650
651 #[test]
652 fn encrypt_buffer_rejects_short_buffer() {
653 let mut space = [0u8; 4];
654 assert!(matches!(
655 EncryptBuffer::new(&mut space[..], 5),
656 Err(Error::ApiMisuse(ApiMisuse::EncryptBufferTooSmall {
657 required: 5,
658 provided: 4,
659 }))
660 ));
661 }
662
663 #[test]
664 fn chunks_iteration() {
665 assert_eq!(
667 OutboundPlain::Single(&[1, 2, 3])
668 .chunks()
669 .collect::<Vec<_>>(),
670 [&[1u8, 2, 3][..]],
671 );
672 assert_eq!(
673 OutboundPlain::new_empty()
674 .chunks()
675 .count(),
676 0
677 );
678
679 let owner: Vec<&[u8]> = vec![&[], &[1, 2, 3], &[], &[4, 5], &[], &[6, 7], &[]];
682 let (_, tail) = OutboundPlain::new(&owner).split_at(1);
683 let (window, _) = tail.split_at(5);
684 assert_eq!(
685 window.chunks().collect::<Vec<_>>(),
686 [&[2u8, 3][..], &[4, 5][..], &[6][..]],
687 );
688 }
689
690 #[test]
691 fn split_at_with_single_slice() {
692 let owner: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7];
693 let borrowed_payload = OutboundPlain::Single(owner);
694
695 let (before, after) = borrowed_payload.split_at(6);
696 println!("before:{before:?}\nafter:{after:?}");
697 assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5]);
698 assert_eq!(after.to_vec(), &[6, 7]);
699 }
700
701 #[test]
702 fn split_at_with_multiple_slices() {
703 let owner: Vec<&[u8]> = vec![&[0, 1, 2, 3], &[4, 5], &[6, 7, 8], &[9, 10, 11, 12]];
704 let borrowed_payload = OutboundPlain::new(&owner);
705
706 let (before, after) = borrowed_payload.split_at(3);
707 println!("before:{before:?}\nafter:{after:?}");
708 assert_eq!(before.to_vec(), &[0, 1, 2]);
709 assert_eq!(after.to_vec(), &[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
710
711 let (before, after) = borrowed_payload.split_at(8);
712 println!("before:{before:?}\nafter:{after:?}");
713 assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5, 6, 7]);
714 assert_eq!(after.to_vec(), &[8, 9, 10, 11, 12]);
715
716 let (before, after) = borrowed_payload.split_at(11);
717 println!("before:{before:?}\nafter:{after:?}");
718 assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
719 assert_eq!(after.to_vec(), &[11, 12]);
720 }
721
722 #[test]
723 fn split_out_of_bounds() {
724 let owner: Vec<&[u8]> = vec![&[0, 1, 2, 3], &[4, 5], &[6, 7, 8], &[9, 10, 11, 12]];
725
726 let single_payload = OutboundPlain::Single(owner[0]);
727 let (before, after) = single_payload.split_at(17);
728 println!("before:{before:?}\nafter:{after:?}");
729 assert_eq!(before.to_vec(), &[0, 1, 2, 3]);
730 assert!(after.is_empty());
731
732 let multiple_payload = OutboundPlain::new(&owner);
733 let (before, after) = multiple_payload.split_at(17);
734 println!("before:{before:?}\nafter:{after:?}");
735 assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
736 assert!(after.is_empty());
737
738 let empty_payload = OutboundPlain::new_empty();
739 let (before, after) = empty_payload.split_at(17);
740 println!("before:{before:?}\nafter:{after:?}");
741 assert!(before.is_empty());
742 assert!(after.is_empty());
743 }
744
745 #[test]
746 fn empty_slices_mixed() {
747 let owner: Vec<&[u8]> = vec![&[], &[], &[0], &[], &[1, 2], &[], &[3], &[4], &[], &[]];
748 let mut borrowed_payload = OutboundPlain::new(&owner);
749 let mut fragment_count = 0;
750 let mut fragment;
751 let expected_fragments: &[&[u8]] = &[&[0, 1], &[2, 3], &[4]];
752
753 while !borrowed_payload.is_empty() {
754 (fragment, borrowed_payload) = borrowed_payload.split_at(2);
755 println!("{fragment:?}");
756 assert_eq!(&expected_fragments[fragment_count], &fragment.to_vec());
757 fragment_count += 1;
758 }
759 assert_eq!(fragment_count, expected_fragments.len());
760 }
761
762 #[test]
763 fn exhaustive_splitting() {
764 let owner: Vec<u8> = (0..127).collect();
765 let slices = (0..7)
766 .map(|i| &owner[((1 << i) - 1)..((1 << (i + 1)) - 1)])
767 .collect::<Vec<_>>();
768 let payload = OutboundPlain::new(&slices);
769
770 assert_eq!(payload.to_vec(), owner);
771 println!("{payload:#?}");
772
773 for start in 0..128 {
774 for end in start..128 {
775 for mid in 0..(end - start) {
776 let witness = owner[start..end].split_at(mid);
777 let split_payload = payload
778 .split_at(end)
779 .0
780 .split_at(start)
781 .1
782 .split_at(mid);
783 assert_eq!(
784 witness.0,
785 split_payload.0.to_vec(),
786 "start: {start}, mid:{mid}, end:{end}"
787 );
788 assert_eq!(
789 witness.1,
790 split_payload.1.to_vec(),
791 "start: {start}, mid:{mid}, end:{end}"
792 );
793 }
794 }
795 }
796 }
797
798 #[test]
799 fn encoded_message_encoding_version() {
800 for (version, expect) in [
801 (
802 EncodableVersion::InitialClientHello(Protocol::Tcp),
803 ProtocolVersion::TLSv1_0,
804 ),
805 (
806 EncodableVersion::InitialClientHello(Protocol::Quic(quic::Version::V2)),
807 ProtocolVersion::TLSv1_0,
808 ),
809 (
810 EncodableVersion::Legacy(ProtocolVersion::TLSv1_3),
811 ProtocolVersion::TLSv1_2,
812 ),
813 (
814 EncodableVersion::Legacy(ProtocolVersion::TLSv1_2),
815 ProtocolVersion::TLSv1_2,
816 ),
817 ] {
818 let encoded_message = EncodedMessage {
819 typ: ContentType::Handshake,
820 version,
821 payload: OutboundPlain::Single(&[0, 1, 2, 3, 4]),
822 };
823 let encoded = encoded_message.to_unencrypted_bytes();
824 let decoded = EncodedMessage::<Payload<'_>>::read(&mut Reader::new(&encoded)).unwrap();
825 assert_eq!(decoded.version.version(), expect);
826 }
827 }
828}