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