clia_rustls_mod/msgs/message/
inbound.rs1use core::ops::{Deref, DerefMut};
2
3use super::outbound::read_opaque_message_header;
4use super::MessageError;
5use crate::enums::{ContentType, ProtocolVersion};
6use crate::error::{Error, PeerMisbehaved};
7use crate::msgs::codec::ReaderMut;
8use crate::msgs::fragmenter::MAX_FRAGMENT_LEN;
9
10pub struct InboundOpaqueMessage<'a> {
15 pub typ: ContentType,
16 pub version: ProtocolVersion,
17 pub payload: BorrowedPayload<'a>,
18}
19
20impl<'a> InboundOpaqueMessage<'a> {
21 pub fn new(typ: ContentType, version: ProtocolVersion, payload: &'a mut [u8]) -> Self {
25 Self {
26 typ,
27 version,
28 payload: BorrowedPayload(payload),
29 }
30 }
31
32 pub fn into_plain_message(self) -> InboundPlainMessage<'a> {
37 InboundPlainMessage {
38 typ: self.typ,
39 version: self.version,
40 payload: self.payload.into_inner(),
41 }
42 }
43
44 pub fn into_tls13_unpadded_message(mut self) -> Result<InboundPlainMessage<'a>, Error> {
49 let payload = &mut self.payload;
50
51 if payload.len() > MAX_FRAGMENT_LEN + 1 {
52 return Err(Error::PeerSentOversizedRecord);
53 }
54
55 self.typ = unpad_tls13_payload(payload);
56 if self.typ == ContentType::Unknown(0) {
57 return Err(PeerMisbehaved::IllegalTlsInnerPlaintext.into());
58 }
59
60 if payload.len() > MAX_FRAGMENT_LEN {
61 return Err(Error::PeerSentOversizedRecord);
62 }
63
64 self.version = ProtocolVersion::TLSv1_3;
65 Ok(self.into_plain_message())
66 }
67
68 pub(crate) fn read(r: &mut ReaderMut<'a>) -> Result<Self, MessageError> {
69 let (typ, version, len) = r.as_reader(read_opaque_message_header)?;
70
71 let mut sub = r
72 .sub(len as usize)
73 .map_err(|_| MessageError::TooShortForLength)?;
74 let payload = BorrowedPayload::read(&mut sub);
75
76 Ok(Self {
77 typ,
78 version,
79 payload,
80 })
81 }
82}
83
84pub struct BorrowedPayload<'a>(&'a mut [u8]);
85
86impl Deref for BorrowedPayload<'_> {
87 type Target = [u8];
88
89 fn deref(&self) -> &Self::Target {
90 self.0
91 }
92}
93
94impl<'a> DerefMut for BorrowedPayload<'a> {
95 fn deref_mut(&mut self) -> &mut Self::Target {
96 self.0
97 }
98}
99
100impl<'a> BorrowedPayload<'a> {
101 pub fn truncate(&mut self, len: usize) {
102 if len >= self.len() {
103 return;
104 }
105
106 self.0 = core::mem::take(&mut self.0)
107 .split_at_mut(len)
108 .0;
109 }
110
111 pub(crate) fn read(r: &mut ReaderMut<'a>) -> Self {
112 Self(r.rest())
113 }
114
115 pub(crate) fn into_inner(self) -> &'a mut [u8] {
116 self.0
117 }
118
119 pub(crate) fn pop(&mut self) -> Option<u8> {
120 if self.is_empty() {
121 return None;
122 }
123
124 let len = self.len();
125 let last = self[len - 1];
126 self.truncate(len - 1);
127 Some(last)
128 }
129}
130
131#[derive(Debug)]
138pub struct InboundPlainMessage<'a> {
139 pub typ: ContentType,
140 pub version: ProtocolVersion,
141 pub payload: &'a [u8],
142}
143
144impl InboundPlainMessage<'_> {
145 pub(crate) fn is_valid_ccs(&self) -> bool {
151 self.typ == ContentType::ChangeCipherSpec && self.payload == [0x01]
152 }
153
154 #[cfg(all(test, feature = "std"))]
155 pub(crate) fn into_owned(self) -> super::PlainMessage {
156 super::PlainMessage {
157 version: self.version,
158 typ: self.typ,
159 payload: crate::msgs::base::Payload::Owned(self.payload.to_vec()),
160 }
161 }
162}
163
164fn unpad_tls13_payload(p: &mut BorrowedPayload) -> ContentType {
172 loop {
173 match p.pop() {
174 Some(0) => {}
175 Some(content_type) => return ContentType::from(content_type),
176 None => return ContentType::Unknown(0),
177 }
178 }
179}