rustls/msgs/message/
inbound.rs1use core::ops::{Deref, DerefMut, Range};
2
3use crate::enums::{ContentType, ProtocolVersion};
4use crate::error::{Error, PeerMisbehaved};
5use crate::msgs::fragmenter::MAX_FRAGMENT_LEN;
6
7pub struct InboundOpaqueMessage<'a> {
12    pub typ: ContentType,
13    pub version: ProtocolVersion,
14    pub payload: BorrowedPayload<'a>,
15}
16
17impl<'a> InboundOpaqueMessage<'a> {
18    pub fn new(typ: ContentType, version: ProtocolVersion, payload: &'a mut [u8]) -> Self {
22        Self {
23            typ,
24            version,
25            payload: BorrowedPayload(payload),
26        }
27    }
28
29    pub fn into_plain_message(self) -> InboundPlainMessage<'a> {
34        InboundPlainMessage {
35            typ: self.typ,
36            version: self.version,
37            payload: self.payload.into_inner(),
38        }
39    }
40
41    pub fn into_plain_message_range(self, range: Range<usize>) -> InboundPlainMessage<'a> {
49        InboundPlainMessage {
50            typ: self.typ,
51            version: self.version,
52            payload: &self.payload.into_inner()[range],
53        }
54    }
55
56    pub fn into_tls13_unpadded_message(mut self) -> Result<InboundPlainMessage<'a>, Error> {
61        let payload = &mut self.payload;
62
63        if payload.len() > MAX_FRAGMENT_LEN + 1 {
64            return Err(Error::PeerSentOversizedRecord);
65        }
66
67        self.typ = unpad_tls13_payload(payload);
68        if self.typ == ContentType::Unknown(0) {
69            return Err(PeerMisbehaved::IllegalTlsInnerPlaintext.into());
70        }
71
72        if payload.len() > MAX_FRAGMENT_LEN {
73            return Err(Error::PeerSentOversizedRecord);
74        }
75
76        self.version = ProtocolVersion::TLSv1_3;
77        Ok(self.into_plain_message())
78    }
79}
80
81pub struct BorrowedPayload<'a>(&'a mut [u8]);
82
83impl Deref for BorrowedPayload<'_> {
84    type Target = [u8];
85
86    fn deref(&self) -> &Self::Target {
87        self.0
88    }
89}
90
91impl DerefMut for BorrowedPayload<'_> {
92    fn deref_mut(&mut self) -> &mut Self::Target {
93        self.0
94    }
95}
96
97impl<'a> BorrowedPayload<'a> {
98    pub fn truncate(&mut self, len: usize) {
99        if len >= self.len() {
100            return;
101        }
102
103        self.0 = core::mem::take(&mut self.0)
104            .split_at_mut(len)
105            .0;
106    }
107
108    pub(crate) fn into_inner(self) -> &'a mut [u8] {
109        self.0
110    }
111
112    pub(crate) fn pop(&mut self) -> Option<u8> {
113        if self.is_empty() {
114            return None;
115        }
116
117        let len = self.len();
118        let last = self[len - 1];
119        self.truncate(len - 1);
120        Some(last)
121    }
122}
123
124#[derive(Debug)]
129pub struct InboundPlainMessage<'a> {
130    pub typ: ContentType,
131    pub version: ProtocolVersion,
132    pub payload: &'a [u8],
133}
134
135impl InboundPlainMessage<'_> {
136    pub(crate) fn is_valid_ccs(&self) -> bool {
142        self.typ == ContentType::ChangeCipherSpec && self.payload == [0x01]
143    }
144}
145
146fn unpad_tls13_payload(p: &mut BorrowedPayload<'_>) -> ContentType {
154    loop {
155        match p.pop() {
156            Some(0) => {}
157            Some(content_type) => return ContentType::from(content_type),
158            None => return ContentType::Unknown(0),
159        }
160    }
161}