rustls/msgs/message/
inbound.rs1use core::ops::{Deref, DerefMut};
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_tls13_unpadded_message(mut self) -> Result<InboundPlainMessage<'a>, Error> {
46 let payload = &mut self.payload;
47
48 if payload.len() > MAX_FRAGMENT_LEN + 1 {
49 return Err(Error::PeerSentOversizedRecord);
50 }
51
52 self.typ = unpad_tls13_payload(payload);
53 if self.typ == ContentType::Unknown(0) {
54 return Err(PeerMisbehaved::IllegalTlsInnerPlaintext.into());
55 }
56
57 if payload.len() > MAX_FRAGMENT_LEN {
58 return Err(Error::PeerSentOversizedRecord);
59 }
60
61 self.version = ProtocolVersion::TLSv1_3;
62 Ok(self.into_plain_message())
63 }
64}
65
66pub struct BorrowedPayload<'a>(&'a mut [u8]);
67
68impl Deref for BorrowedPayload<'_> {
69 type Target = [u8];
70
71 fn deref(&self) -> &Self::Target {
72 self.0
73 }
74}
75
76impl<'a> DerefMut for BorrowedPayload<'a> {
77 fn deref_mut(&mut self) -> &mut Self::Target {
78 self.0
79 }
80}
81
82impl<'a> BorrowedPayload<'a> {
83 pub fn truncate(&mut self, len: usize) {
84 if len >= self.len() {
85 return;
86 }
87
88 self.0 = core::mem::take(&mut self.0)
89 .split_at_mut(len)
90 .0;
91 }
92
93 pub(crate) fn into_inner(self) -> &'a mut [u8] {
94 self.0
95 }
96
97 pub(crate) fn pop(&mut self) -> Option<u8> {
98 if self.is_empty() {
99 return None;
100 }
101
102 let len = self.len();
103 let last = self[len - 1];
104 self.truncate(len - 1);
105 Some(last)
106 }
107}
108
109#[derive(Debug)]
114pub struct InboundPlainMessage<'a> {
115 pub typ: ContentType,
116 pub version: ProtocolVersion,
117 pub payload: &'a [u8],
118}
119
120impl InboundPlainMessage<'_> {
121 pub(crate) fn is_valid_ccs(&self) -> bool {
127 self.typ == ContentType::ChangeCipherSpec && self.payload == [0x01]
128 }
129}
130
131fn unpad_tls13_payload(p: &mut BorrowedPayload<'_>) -> ContentType {
139 loop {
140 match p.pop() {
141 Some(0) => {}
142 Some(content_type) => return ContentType::from(content_type),
143 None => return ContentType::Unknown(0),
144 }
145 }
146}