1use alloc::vec::Vec;
2use core::fmt;
3use core::ops::{Deref, DerefMut, Range};
4
5use crate::crypto::cipher::RecordLayer;
6use crate::enums::{ContentType, ProtocolVersion};
7use crate::error::{Error, InvalidMessage, PeerMisbehaved};
8use crate::msgs::base::hex;
9use crate::msgs::codec::{Codec, Reader};
10use crate::msgs::fragmenter::MAX_FRAGMENT_LEN;
11use crate::msgs::message::{HEADER_SIZE, read_opaque_message_header};
12
13#[expect(clippy::exhaustive_structs)]
15#[derive(Clone, Debug)]
16pub struct EncodedMessage<P> {
17 pub typ: ContentType,
19 pub version: ProtocolVersion,
21 pub payload: P,
23}
24
25impl<P> EncodedMessage<P> {
26 pub fn new(typ: ContentType, version: ProtocolVersion, payload: P) -> Self {
28 Self {
29 typ,
30 version,
31 payload,
32 }
33 }
34}
35
36impl<'a> EncodedMessage<Payload<'a>> {
37 pub fn read(r: &mut Reader<'a>) -> Result<Self, MessageError> {
42 let (typ, version, len) = read_opaque_message_header(r)?;
43
44 let content = r
45 .take(len as usize)
46 .ok_or(MessageError::TooShortForLength)?;
47
48 Ok(Self {
49 typ,
50 version,
51 payload: Payload::Borrowed(content),
52 })
53 }
54
55 pub fn into_unencrypted_opaque(self) -> EncodedMessage<OutboundOpaque> {
57 EncodedMessage {
58 version: self.version,
59 typ: self.typ,
60 payload: OutboundOpaque::from(self.payload.bytes()),
61 }
62 }
63
64 pub fn borrow_outbound(&'a self) -> EncodedMessage<OutboundPlain<'a>> {
66 EncodedMessage {
67 version: self.version,
68 typ: self.typ,
69 payload: self.payload.bytes().into(),
70 }
71 }
72
73 pub fn into_owned(self) -> Self {
75 Self {
76 typ: self.typ,
77 version: self.version,
78 payload: self.payload.into_owned(),
79 }
80 }
81}
82
83impl EncodedMessage<&'_ [u8]> {
84 pub(crate) fn is_valid_ccs(&self) -> bool {
90 self.typ == ContentType::ChangeCipherSpec && self.payload == [0x01]
91 }
92}
93
94impl<'a> EncodedMessage<InboundOpaque<'a>> {
95 pub fn into_tls13_unpadded_message(mut self) -> Result<EncodedMessage<&'a [u8]>, Error> {
100 let payload = &mut self.payload;
101
102 if payload.len() > MAX_FRAGMENT_LEN + 1 {
103 return Err(Error::PeerSentOversizedRecord);
104 }
105
106 self.typ = unpad_tls13_payload(payload);
107 if self.typ == ContentType::Unknown(0) {
108 return Err(PeerMisbehaved::IllegalTlsInnerPlaintext.into());
109 }
110
111 if payload.len() > MAX_FRAGMENT_LEN {
112 return Err(Error::PeerSentOversizedRecord);
113 }
114
115 self.version = ProtocolVersion::TLSv1_3;
116 Ok(self.into_plain_message())
117 }
118
119 pub fn into_plain_message_range(self, range: Range<usize>) -> EncodedMessage<&'a [u8]> {
128 EncodedMessage {
129 typ: self.typ,
130 version: self.version,
131 payload: &self.payload.into_inner()[range],
132 }
133 }
134
135 pub fn into_plain_message(self) -> EncodedMessage<&'a [u8]> {
141 EncodedMessage {
142 typ: self.typ,
143 version: self.version,
144 payload: self.payload.into_inner(),
145 }
146 }
147}
148
149impl EncodedMessage<OutboundPlain<'_>> {
150 pub(crate) fn to_unencrypted_opaque(&self) -> EncodedMessage<OutboundOpaque> {
151 let mut payload = OutboundOpaque::with_capacity(self.payload.len());
152 payload.extend_from_chunks(&self.payload);
153 EncodedMessage {
154 version: self.version,
155 typ: self.typ,
156 payload,
157 }
158 }
159
160 pub(crate) fn encoded_len(&self, record_layer: &RecordLayer) -> usize {
161 HEADER_SIZE + record_layer.encrypted_len(self.payload.len())
162 }
163}
164
165impl EncodedMessage<OutboundOpaque> {
166 pub fn encode(self) -> Vec<u8> {
168 let length = self.payload.len() as u16;
169 let mut encoded_payload = self.payload.0;
170 encoded_payload[0] = self.typ.into();
171 encoded_payload[1..3].copy_from_slice(&self.version.to_array());
172 encoded_payload[3..5].copy_from_slice(&(length).to_be_bytes());
173 encoded_payload
174 }
175}
176
177#[non_exhaustive]
182#[derive(Debug, Clone)]
183pub enum OutboundPlain<'a> {
184 Single(&'a [u8]),
188 Multiple {
190 chunks: &'a [&'a [u8]],
192 start: usize,
194 end: usize,
196 },
197}
198
199impl<'a> OutboundPlain<'a> {
200 pub fn new(chunks: &'a [&'a [u8]]) -> Self {
203 if chunks.len() == 1 {
204 Self::Single(chunks[0])
205 } else {
206 Self::Multiple {
207 chunks,
208 start: 0,
209 end: chunks
210 .iter()
211 .map(|chunk| chunk.len())
212 .sum(),
213 }
214 }
215 }
216
217 pub fn new_empty() -> Self {
219 Self::Single(&[])
220 }
221
222 pub fn to_vec(&self) -> Vec<u8> {
224 let mut vec = Vec::with_capacity(self.len());
225 self.copy_to_vec(&mut vec);
226 vec
227 }
228
229 pub fn copy_to_vec(&self, vec: &mut Vec<u8>) {
231 match *self {
232 Self::Single(chunk) => vec.extend_from_slice(chunk),
233 Self::Multiple { chunks, start, end } => {
234 let mut size = 0;
235 for chunk in chunks.iter() {
236 let psize = size;
237 let len = chunk.len();
238 size += len;
239 if size <= start || psize >= end {
240 continue;
241 }
242 let start = start.saturating_sub(psize);
243 let end = if end - psize < len { end - psize } else { len };
244 vec.extend_from_slice(&chunk[start..end]);
245 }
246 }
247 }
248 }
249
250 pub(crate) fn split_at(&self, mid: usize) -> (Self, Self) {
253 match *self {
254 Self::Single(chunk) => {
255 let mid = Ord::min(mid, chunk.len());
256 (Self::Single(&chunk[..mid]), Self::Single(&chunk[mid..]))
257 }
258 Self::Multiple { chunks, start, end } => {
259 let mid = Ord::min(start + mid, end);
260 (
261 Self::Multiple {
262 chunks,
263 start,
264 end: mid,
265 },
266 Self::Multiple {
267 chunks,
268 start: mid,
269 end,
270 },
271 )
272 }
273 }
274 }
275
276 pub(crate) fn is_empty(&self) -> bool {
278 self.len() == 0
279 }
280
281 #[expect(clippy::len_without_is_empty)]
283 pub fn len(&self) -> usize {
284 match self {
285 Self::Single(chunk) => chunk.len(),
286 Self::Multiple { start, end, .. } => end - start,
287 }
288 }
289}
290
291impl<'a> From<&'a [u8]> for OutboundPlain<'a> {
292 fn from(payload: &'a [u8]) -> Self {
293 Self::Single(payload)
294 }
295}
296
297#[derive(Clone, Debug)]
304pub struct OutboundOpaque(Vec<u8>);
305
306impl OutboundOpaque {
307 pub fn with_capacity(capacity: usize) -> Self {
311 let mut prefixed_payload = Vec::with_capacity(HEADER_SIZE + capacity);
312 prefixed_payload.resize(HEADER_SIZE, 0);
313 Self(prefixed_payload)
314 }
315
316 pub fn extend_from_slice(&mut self, slice: &[u8]) {
318 self.0.extend_from_slice(slice)
319 }
320
321 pub fn extend_from_chunks(&mut self, chunks: &OutboundPlain<'_>) {
323 chunks.copy_to_vec(&mut self.0)
324 }
325
326 pub fn truncate(&mut self, len: usize) {
328 self.0.truncate(len + HEADER_SIZE)
329 }
330
331 fn len(&self) -> usize {
332 self.0.len() - HEADER_SIZE
333 }
334}
335
336impl AsRef<[u8]> for OutboundOpaque {
337 fn as_ref(&self) -> &[u8] {
338 &self.0[HEADER_SIZE..]
339 }
340}
341
342impl AsMut<[u8]> for OutboundOpaque {
343 fn as_mut(&mut self) -> &mut [u8] {
344 &mut self.0[HEADER_SIZE..]
345 }
346}
347
348impl<'a> Extend<&'a u8> for OutboundOpaque {
349 fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, iter: T) {
350 self.0.extend(iter)
351 }
352}
353
354impl From<&[u8]> for OutboundOpaque {
355 fn from(content: &[u8]) -> Self {
356 let mut payload = Vec::with_capacity(HEADER_SIZE + content.len());
357 payload.extend(&[0u8; HEADER_SIZE]);
358 payload.extend(content);
359 Self(payload)
360 }
361}
362
363impl<const N: usize> From<&[u8; N]> for OutboundOpaque {
364 fn from(content: &[u8; N]) -> Self {
365 Self::from(&content[..])
366 }
367}
368
369#[non_exhaustive]
375#[derive(Clone, Eq, PartialEq)]
376pub enum Payload<'a> {
377 Borrowed(&'a [u8]),
379 Owned(Vec<u8>),
381}
382
383impl<'a> Payload<'a> {
384 pub fn bytes(&'a self) -> &'a [u8] {
386 match self {
387 Self::Borrowed(bytes) => bytes,
388 Self::Owned(bytes) => bytes,
389 }
390 }
391
392 pub(crate) fn into_owned(self) -> Payload<'static> {
393 Payload::Owned(self.into_vec())
394 }
395
396 pub(crate) fn into_vec(self) -> Vec<u8> {
397 match self {
398 Self::Borrowed(bytes) => bytes.to_vec(),
399 Self::Owned(bytes) => bytes,
400 }
401 }
402
403 pub(crate) fn read(r: &mut Reader<'a>) -> Self {
404 Self::Borrowed(r.rest())
405 }
406}
407
408impl Payload<'static> {
409 pub fn new(bytes: impl Into<Vec<u8>>) -> Self {
411 Self::Owned(bytes.into())
412 }
413}
414
415impl<'a> Codec<'a> for Payload<'a> {
416 fn encode(&self, bytes: &mut Vec<u8>) {
417 bytes.extend_from_slice(self.bytes());
418 }
419
420 fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
421 Ok(Self::read(r))
422 }
423}
424
425impl fmt::Debug for Payload<'_> {
426 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
427 hex(f, self.bytes())
428 }
429}
430
431#[expect(clippy::exhaustive_structs)]
433pub struct InboundOpaque<'a>(pub &'a mut [u8]);
434
435impl<'a> InboundOpaque<'a> {
436 pub fn truncate(&mut self, len: usize) {
438 if len >= self.len() {
439 return;
440 }
441
442 self.0 = core::mem::take(&mut self.0)
443 .split_at_mut(len)
444 .0;
445 }
446
447 pub(crate) fn into_inner(self) -> &'a mut [u8] {
448 self.0
449 }
450
451 pub(crate) fn pop(&mut self) -> Option<u8> {
452 if self.is_empty() {
453 return None;
454 }
455
456 let len = self.len();
457 let last = self[len - 1];
458 self.truncate(len - 1);
459 Some(last)
460 }
461}
462
463impl Deref for InboundOpaque<'_> {
464 type Target = [u8];
465
466 fn deref(&self) -> &Self::Target {
467 self.0
468 }
469}
470
471impl DerefMut for InboundOpaque<'_> {
472 fn deref_mut(&mut self) -> &mut Self::Target {
473 self.0
474 }
475}
476
477fn unpad_tls13_payload(p: &mut InboundOpaque<'_>) -> ContentType {
485 loop {
486 match p.pop() {
487 Some(0) => {}
488 Some(content_type) => return ContentType::from(content_type),
489 None => return ContentType::Unknown(0),
490 }
491 }
492}
493
494#[expect(missing_docs)]
496#[non_exhaustive]
497#[derive(Debug)]
498pub enum MessageError {
499 TooShortForHeader,
500 TooShortForLength,
501 InvalidEmptyPayload,
502 MessageTooLarge,
503 InvalidContentType,
504 UnknownProtocolVersion,
505}
506
507#[cfg(test)]
508mod tests {
509 use std::{println, vec};
510
511 use super::*;
512
513 #[test]
514 fn split_at_with_single_slice() {
515 let owner: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7];
516 let borrowed_payload = OutboundPlain::Single(owner);
517
518 let (before, after) = borrowed_payload.split_at(6);
519 println!("before:{before:?}\nafter:{after:?}");
520 assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5]);
521 assert_eq!(after.to_vec(), &[6, 7]);
522 }
523
524 #[test]
525 fn split_at_with_multiple_slices() {
526 let owner: Vec<&[u8]> = vec![&[0, 1, 2, 3], &[4, 5], &[6, 7, 8], &[9, 10, 11, 12]];
527 let borrowed_payload = OutboundPlain::new(&owner);
528
529 let (before, after) = borrowed_payload.split_at(3);
530 println!("before:{before:?}\nafter:{after:?}");
531 assert_eq!(before.to_vec(), &[0, 1, 2]);
532 assert_eq!(after.to_vec(), &[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
533
534 let (before, after) = borrowed_payload.split_at(8);
535 println!("before:{before:?}\nafter:{after:?}");
536 assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5, 6, 7]);
537 assert_eq!(after.to_vec(), &[8, 9, 10, 11, 12]);
538
539 let (before, after) = borrowed_payload.split_at(11);
540 println!("before:{before:?}\nafter:{after:?}");
541 assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
542 assert_eq!(after.to_vec(), &[11, 12]);
543 }
544
545 #[test]
546 fn split_out_of_bounds() {
547 let owner: Vec<&[u8]> = vec![&[0, 1, 2, 3], &[4, 5], &[6, 7, 8], &[9, 10, 11, 12]];
548
549 let single_payload = OutboundPlain::Single(owner[0]);
550 let (before, after) = single_payload.split_at(17);
551 println!("before:{before:?}\nafter:{after:?}");
552 assert_eq!(before.to_vec(), &[0, 1, 2, 3]);
553 assert!(after.is_empty());
554
555 let multiple_payload = OutboundPlain::new(&owner);
556 let (before, after) = multiple_payload.split_at(17);
557 println!("before:{before:?}\nafter:{after:?}");
558 assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
559 assert!(after.is_empty());
560
561 let empty_payload = OutboundPlain::new_empty();
562 let (before, after) = empty_payload.split_at(17);
563 println!("before:{before:?}\nafter:{after:?}");
564 assert!(before.is_empty());
565 assert!(after.is_empty());
566 }
567
568 #[test]
569 fn empty_slices_mixed() {
570 let owner: Vec<&[u8]> = vec![&[], &[], &[0], &[], &[1, 2], &[], &[3], &[4], &[], &[]];
571 let mut borrowed_payload = OutboundPlain::new(&owner);
572 let mut fragment_count = 0;
573 let mut fragment;
574 let expected_fragments: &[&[u8]] = &[&[0, 1], &[2, 3], &[4]];
575
576 while !borrowed_payload.is_empty() {
577 (fragment, borrowed_payload) = borrowed_payload.split_at(2);
578 println!("{fragment:?}");
579 assert_eq!(&expected_fragments[fragment_count], &fragment.to_vec());
580 fragment_count += 1;
581 }
582 assert_eq!(fragment_count, expected_fragments.len());
583 }
584
585 #[test]
586 fn exhaustive_splitting() {
587 let owner: Vec<u8> = (0..127).collect();
588 let slices = (0..7)
589 .map(|i| &owner[((1 << i) - 1)..((1 << (i + 1)) - 1)])
590 .collect::<Vec<_>>();
591 let payload = OutboundPlain::new(&slices);
592
593 assert_eq!(payload.to_vec(), owner);
594 println!("{payload:#?}");
595
596 for start in 0..128 {
597 for end in start..128 {
598 for mid in 0..(end - start) {
599 let witness = owner[start..end].split_at(mid);
600 let split_payload = payload
601 .split_at(end)
602 .0
603 .split_at(start)
604 .1
605 .split_at(mid);
606 assert_eq!(
607 witness.0,
608 split_payload.0.to_vec(),
609 "start: {start}, mid:{mid}, end:{end}"
610 );
611 assert_eq!(
612 witness.1,
613 split_payload.1.to_vec(),
614 "start: {start}, mid:{mid}, end:{end}"
615 );
616 }
617 }
618 }
619 }
620}