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