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(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.0;
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(Vec<u8>);
303
304impl OutboundOpaque {
305 pub fn with_capacity(capacity: usize) -> Self {
309 let mut prefixed_payload = Vec::with_capacity(HEADER_SIZE + capacity);
310 prefixed_payload.resize(HEADER_SIZE, 0);
311 Self(prefixed_payload)
312 }
313
314 pub fn extend_from_slice(&mut self, slice: &[u8]) {
316 self.0.extend_from_slice(slice)
317 }
318
319 pub fn extend_from_chunks(&mut self, chunks: &OutboundPlain<'_>) {
321 chunks.copy_to_vec(&mut self.0)
322 }
323
324 pub fn truncate(&mut self, len: usize) {
326 self.0.truncate(len + HEADER_SIZE)
327 }
328
329 fn len(&self) -> usize {
330 self.0.len() - HEADER_SIZE
331 }
332}
333
334impl AsRef<[u8]> for OutboundOpaque {
335 fn as_ref(&self) -> &[u8] {
336 &self.0[HEADER_SIZE..]
337 }
338}
339
340impl AsMut<[u8]> for OutboundOpaque {
341 fn as_mut(&mut self) -> &mut [u8] {
342 &mut self.0[HEADER_SIZE..]
343 }
344}
345
346impl<'a> Extend<&'a u8> for OutboundOpaque {
347 fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, iter: T) {
348 self.0.extend(iter)
349 }
350}
351
352impl From<&[u8]> for OutboundOpaque {
353 fn from(content: &[u8]) -> Self {
354 let mut payload = Vec::with_capacity(HEADER_SIZE + content.len());
355 payload.extend(&[0u8; HEADER_SIZE]);
356 payload.extend(content);
357 Self(payload)
358 }
359}
360
361impl<const N: usize> From<&[u8; N]> for OutboundOpaque {
362 fn from(content: &[u8; N]) -> Self {
363 Self::from(&content[..])
364 }
365}
366
367#[non_exhaustive]
373#[derive(Clone, Eq, PartialEq)]
374pub enum Payload<'a> {
375 Borrowed(&'a [u8]),
377 Owned(Vec<u8>),
379}
380
381impl<'a> Payload<'a> {
382 pub fn bytes(&'a self) -> &'a [u8] {
384 match self {
385 Self::Borrowed(bytes) => bytes,
386 Self::Owned(bytes) => bytes,
387 }
388 }
389
390 pub(crate) fn into_owned(self) -> Payload<'static> {
391 Payload::Owned(self.into_vec())
392 }
393
394 pub(crate) fn into_vec(self) -> Vec<u8> {
395 match self {
396 Self::Borrowed(bytes) => bytes.to_vec(),
397 Self::Owned(bytes) => bytes,
398 }
399 }
400
401 pub(crate) fn read(r: &mut Reader<'a>) -> Self {
402 Self::Borrowed(r.rest())
403 }
404}
405
406impl Payload<'static> {
407 pub fn new(bytes: impl Into<Vec<u8>>) -> Self {
409 Self::Owned(bytes.into())
410 }
411}
412
413impl<'a> Codec<'a> for Payload<'a> {
414 fn encode(&self, bytes: &mut Vec<u8>) {
415 bytes.extend_from_slice(self.bytes());
416 }
417
418 fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
419 Ok(Self::read(r))
420 }
421}
422
423impl fmt::Debug for Payload<'_> {
424 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
425 hex(f, self.bytes())
426 }
427}
428
429#[expect(clippy::exhaustive_structs)]
431pub struct InboundOpaque<'a>(pub &'a mut [u8]);
432
433impl<'a> InboundOpaque<'a> {
434 pub fn truncate(&mut self, len: usize) {
436 if len >= self.len() {
437 return;
438 }
439
440 self.0 = core::mem::take(&mut self.0)
441 .split_at_mut(len)
442 .0;
443 }
444
445 pub(crate) fn into_inner(self) -> &'a mut [u8] {
446 self.0
447 }
448
449 pub(crate) fn pop(&mut self) -> Option<u8> {
450 if self.is_empty() {
451 return None;
452 }
453
454 let len = self.len();
455 let last = self[len - 1];
456 self.truncate(len - 1);
457 Some(last)
458 }
459}
460
461impl Deref for InboundOpaque<'_> {
462 type Target = [u8];
463
464 fn deref(&self) -> &Self::Target {
465 self.0
466 }
467}
468
469impl DerefMut for InboundOpaque<'_> {
470 fn deref_mut(&mut self) -> &mut Self::Target {
471 self.0
472 }
473}
474
475fn unpad_tls13_payload(p: &mut InboundOpaque<'_>) -> ContentType {
483 loop {
484 match p.pop() {
485 Some(0) => {}
486 Some(content_type) => return ContentType::from(content_type),
487 None => return ContentType(0),
488 }
489 }
490}
491
492#[expect(missing_docs)]
494#[non_exhaustive]
495#[derive(Debug)]
496pub enum MessageError {
497 TooShortForHeader,
498 TooShortForLength,
499 InvalidEmptyPayload,
500 MessageTooLarge,
501 InvalidContentType,
502 UnknownProtocolVersion,
503}
504
505#[cfg(test)]
506mod tests {
507 use std::{println, vec};
508
509 use super::*;
510
511 #[test]
512 fn split_at_with_single_slice() {
513 let owner: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7];
514 let borrowed_payload = OutboundPlain::Single(owner);
515
516 let (before, after) = borrowed_payload.split_at(6);
517 println!("before:{before:?}\nafter:{after:?}");
518 assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5]);
519 assert_eq!(after.to_vec(), &[6, 7]);
520 }
521
522 #[test]
523 fn split_at_with_multiple_slices() {
524 let owner: Vec<&[u8]> = vec![&[0, 1, 2, 3], &[4, 5], &[6, 7, 8], &[9, 10, 11, 12]];
525 let borrowed_payload = OutboundPlain::new(&owner);
526
527 let (before, after) = borrowed_payload.split_at(3);
528 println!("before:{before:?}\nafter:{after:?}");
529 assert_eq!(before.to_vec(), &[0, 1, 2]);
530 assert_eq!(after.to_vec(), &[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
531
532 let (before, after) = borrowed_payload.split_at(8);
533 println!("before:{before:?}\nafter:{after:?}");
534 assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5, 6, 7]);
535 assert_eq!(after.to_vec(), &[8, 9, 10, 11, 12]);
536
537 let (before, after) = borrowed_payload.split_at(11);
538 println!("before:{before:?}\nafter:{after:?}");
539 assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
540 assert_eq!(after.to_vec(), &[11, 12]);
541 }
542
543 #[test]
544 fn split_out_of_bounds() {
545 let owner: Vec<&[u8]> = vec![&[0, 1, 2, 3], &[4, 5], &[6, 7, 8], &[9, 10, 11, 12]];
546
547 let single_payload = OutboundPlain::Single(owner[0]);
548 let (before, after) = single_payload.split_at(17);
549 println!("before:{before:?}\nafter:{after:?}");
550 assert_eq!(before.to_vec(), &[0, 1, 2, 3]);
551 assert!(after.is_empty());
552
553 let multiple_payload = OutboundPlain::new(&owner);
554 let (before, after) = multiple_payload.split_at(17);
555 println!("before:{before:?}\nafter:{after:?}");
556 assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
557 assert!(after.is_empty());
558
559 let empty_payload = OutboundPlain::new_empty();
560 let (before, after) = empty_payload.split_at(17);
561 println!("before:{before:?}\nafter:{after:?}");
562 assert!(before.is_empty());
563 assert!(after.is_empty());
564 }
565
566 #[test]
567 fn empty_slices_mixed() {
568 let owner: Vec<&[u8]> = vec![&[], &[], &[0], &[], &[1, 2], &[], &[3], &[4], &[], &[]];
569 let mut borrowed_payload = OutboundPlain::new(&owner);
570 let mut fragment_count = 0;
571 let mut fragment;
572 let expected_fragments: &[&[u8]] = &[&[0, 1], &[2, 3], &[4]];
573
574 while !borrowed_payload.is_empty() {
575 (fragment, borrowed_payload) = borrowed_payload.split_at(2);
576 println!("{fragment:?}");
577 assert_eq!(&expected_fragments[fragment_count], &fragment.to_vec());
578 fragment_count += 1;
579 }
580 assert_eq!(fragment_count, expected_fragments.len());
581 }
582
583 #[test]
584 fn exhaustive_splitting() {
585 let owner: Vec<u8> = (0..127).collect();
586 let slices = (0..7)
587 .map(|i| &owner[((1 << i) - 1)..((1 << (i + 1)) - 1)])
588 .collect::<Vec<_>>();
589 let payload = OutboundPlain::new(&slices);
590
591 assert_eq!(payload.to_vec(), owner);
592 println!("{payload:#?}");
593
594 for start in 0..128 {
595 for end in start..128 {
596 for mid in 0..(end - start) {
597 let witness = owner[start..end].split_at(mid);
598 let split_payload = payload
599 .split_at(end)
600 .0
601 .split_at(start)
602 .1
603 .split_at(mid);
604 assert_eq!(
605 witness.0,
606 split_payload.0.to_vec(),
607 "start: {start}, mid:{mid}, end:{end}"
608 );
609 assert_eq!(
610 witness.1,
611 split_payload.1.to_vec(),
612 "start: {start}, mid:{mid}, end:{end}"
613 );
614 }
615 }
616 }
617 }
618}