1use crate::enums::ProtocolVersion;
2use crate::enums::{AlertDescription, ContentType, HandshakeType};
3use crate::error::{Error, InvalidMessage, PeerMisbehaved};
4use crate::msgs::alert::AlertMessagePayload;
5use crate::msgs::base::Payload;
6use crate::msgs::ccs::ChangeCipherSpecPayload;
7use crate::msgs::codec::{Codec, Reader};
8use crate::msgs::enums::AlertLevel;
9use crate::msgs::fragmenter::MAX_FRAGMENT_LEN;
10use crate::msgs::handshake::HandshakeMessagePayload;
11
12use alloc::vec::Vec;
13
14#[derive(Debug)]
15pub enum MessagePayload {
16 Alert(AlertMessagePayload),
17 Handshake {
18 parsed: HandshakeMessagePayload,
19 encoded: Payload,
20 },
21 ChangeCipherSpec(ChangeCipherSpecPayload),
22 ApplicationData(Payload),
23}
24
25impl MessagePayload {
26 pub fn encode(&self, bytes: &mut Vec<u8>) {
27 match self {
28 Self::Alert(x) => x.encode(bytes),
29 Self::Handshake { encoded, .. } => bytes.extend(&encoded.0),
30 Self::ChangeCipherSpec(x) => x.encode(bytes),
31 Self::ApplicationData(x) => x.encode(bytes),
32 }
33 }
34
35 pub fn handshake(parsed: HandshakeMessagePayload) -> Self {
36 Self::Handshake {
37 encoded: Payload::new(parsed.get_encoding()),
38 parsed,
39 }
40 }
41
42 pub fn new(
43 typ: ContentType,
44 vers: ProtocolVersion,
45 payload: Payload,
46 ) -> Result<Self, InvalidMessage> {
47 let mut r = Reader::init(&payload.0);
48 match typ {
49 ContentType::ApplicationData => Ok(Self::ApplicationData(payload)),
50 ContentType::Alert => AlertMessagePayload::read(&mut r).map(MessagePayload::Alert),
51 ContentType::Handshake => {
52 HandshakeMessagePayload::read_version(&mut r, vers).map(|parsed| Self::Handshake {
53 parsed,
54 encoded: payload,
55 })
56 }
57 ContentType::ChangeCipherSpec => {
58 ChangeCipherSpecPayload::read(&mut r).map(MessagePayload::ChangeCipherSpec)
59 }
60 _ => Err(InvalidMessage::InvalidContentType),
61 }
62 }
63
64 pub fn content_type(&self) -> ContentType {
65 match self {
66 Self::Alert(_) => ContentType::Alert,
67 Self::Handshake { .. } => ContentType::Handshake,
68 Self::ChangeCipherSpec(_) => ContentType::ChangeCipherSpec,
69 Self::ApplicationData(_) => ContentType::ApplicationData,
70 }
71 }
72}
73
74/// A TLS frame, named TLSPlaintext in the standard.
75///
76/// This type owns all memory for its interior parts. It is used to read/write from/to I/O
77/// buffers as well as for fragmenting, joining and encryption/decryption. It can be converted
78/// into a `Message` by decoding the payload.
79///
80/// # Decryption
81/// Internally the message payload is stored as a `Vec<u8>`; this can by mutably borrowed with
82/// [`OpaqueMessage::payload_mut()`]. This is useful for decrypting a message in-place.
83/// After the message is decrypted, call [`OpaqueMessage::into_plain_message()`] or
84/// [`OpaqueMessage::into_tls13_unpadded_message()`] (depending on the
85/// protocol version).
86#[derive(Clone, Debug)]
87pub struct OpaqueMessage {
88 pub typ: ContentType,
89 pub version: ProtocolVersion,
90 payload: Payload,
91}
92
93impl OpaqueMessage {
94 /// Construct a new `OpaqueMessage` from constituent fields.
95 ///
96 /// `body` is moved into the `payload` field.
97 pub fn new(typ: ContentType, version: ProtocolVersion, body: Vec<u8>) -> Self {
98 Self {
99 typ,
100 version,
101 payload: Payload::new(body),
102 }
103 }
104
105 /// Access the message payload as a slice.
106 pub fn payload(&self) -> &[u8] {
107 &self.payload.0
108 }
109
110 /// Access the message payload as a mutable `Vec<u8>`.
111 pub fn payload_mut(&mut self) -> &mut Vec<u8> {
112 &mut self.payload.0
113 }
114
115 /// `MessageError` allows callers to distinguish between valid prefixes (might
116 /// become valid if we read more data) and invalid data.
117 pub fn read(r: &mut Reader) -> Result<Self, MessageError> {
118 let typ = ContentType::read(r).map_err(|_| MessageError::TooShortForHeader)?;
119 // Don't accept any new content-types.
120 if let ContentType::Unknown(_) = typ {
121 return Err(MessageError::InvalidContentType);
122 }
123
124 let version = ProtocolVersion::read(r).map_err(|_| MessageError::TooShortForHeader)?;
125 // Accept only versions 0x03XX for any XX.
126 match version {
127 ProtocolVersion::Unknown(ref v) if (v & 0xff00) != 0x0300 => {
128 return Err(MessageError::UnknownProtocolVersion);
129 }
130 _ => {}
131 };
132
133 let len = u16::read(r).map_err(|_| MessageError::TooShortForHeader)?;
134
135 // Reject undersize messages
136 // implemented per section 5.1 of RFC8446 (TLSv1.3)
137 // per section 6.2.1 of RFC5246 (TLSv1.2)
138 if typ != ContentType::ApplicationData && len == 0 {
139 return Err(MessageError::InvalidEmptyPayload);
140 }
141
142 // Reject oversize messages
143 if len >= Self::MAX_PAYLOAD {
144 return Err(MessageError::MessageTooLarge);
145 }
146
147 let mut sub = r
148 .sub(len as usize)
149 .map_err(|_| MessageError::TooShortForLength)?;
150 let payload = Payload::read(&mut sub);
151
152 Ok(Self {
153 typ,
154 version,
155 payload,
156 })
157 }
158
159 pub fn encode(self) -> Vec<u8> {
160 let mut buf = Vec::new();
161 self.typ.encode(&mut buf);
162 self.version.encode(&mut buf);
163 (self.payload.0.len() as u16).encode(&mut buf);
164 self.payload.encode(&mut buf);
165 buf
166 }
167
168 /// Force conversion into a plaintext message.
169 ///
170 /// This should only be used for messages that are known to be in plaintext. Otherwise, the
171 /// `OpaqueMessage` should be decrypted into a `PlainMessage` using a `MessageDecrypter`.
172 pub fn into_plain_message(self) -> PlainMessage {
173 PlainMessage {
174 version: self.version,
175 typ: self.typ,
176 payload: self.payload,
177 }
178 }
179
180 /// For TLS1.3 (only), checks the length msg.payload is valid and removes the padding.
181 ///
182 /// Returns an error if the message (pre-unpadding) is too long, or the padding is invalid,
183 /// or the message (post-unpadding) is too long.
184 pub fn into_tls13_unpadded_message(mut self) -> Result<PlainMessage, Error> {
185 let payload = &mut self.payload.0;
186
187 if payload.len() > MAX_FRAGMENT_LEN + 1 {
188 return Err(Error::PeerSentOversizedRecord);
189 }
190
191 self.typ = unpad_tls13(payload);
192 if self.typ == ContentType::Unknown(0) {
193 return Err(PeerMisbehaved::IllegalTlsInnerPlaintext.into());
194 }
195
196 if payload.len() > MAX_FRAGMENT_LEN {
197 return Err(Error::PeerSentOversizedRecord);
198 }
199
200 self.version = ProtocolVersion::TLSv1_3;
201 Ok(self.into_plain_message())
202 }
203
204 /// This is the maximum on-the-wire size of a TLSCiphertext.
205 /// That's 2^14 payload bytes, a header, and a 2KB allowance
206 /// for ciphertext overheads.
207 const MAX_PAYLOAD: u16 = 16384 + 2048;
208
209 /// Content type, version and size.
210 const HEADER_SIZE: u16 = 1 + 2 + 2;
211
212 /// Maximum on-wire message size.
213 pub const MAX_WIRE_SIZE: usize = (Self::MAX_PAYLOAD + Self::HEADER_SIZE) as usize;
214}
215
216/// `v` is a message payload, immediately post-decryption. This function
217/// removes zero padding bytes, until a non-zero byte is encountered which is
218/// the content type, which is returned. See RFC8446 s5.2.
219///
220/// ContentType(0) is returned if the message payload is empty or all zeroes.
221fn unpad_tls13(v: &mut Vec<u8>) -> ContentType {
222 loop {
223 match v.pop() {
224 Some(0) => {}
225 Some(content_type: u8) => return ContentType::from(content_type),
226 None => return ContentType::Unknown(0),
227 }
228 }
229}
230
231impl From<Message> for PlainMessage {
232 fn from(msg: Message) -> Self {
233 let typ: ContentType = msg.payload.content_type();
234 let payload: Payload = match msg.payload {
235 MessagePayload::ApplicationData(payload: Payload) => payload,
236 _ => {
237 let mut buf: Vec = Vec::new();
238 msg.payload.encode(&mut buf);
239 Payload(buf)
240 }
241 };
242
243 Self {
244 typ,
245 version: msg.version,
246 payload,
247 }
248 }
249}
250
251/// A decrypted TLS frame
252///
253/// This type owns all memory for its interior parts. It can be decrypted from an OpaqueMessage
254/// or encrypted into an OpaqueMessage, and it is also used for joining and fragmenting.
255#[derive(Clone, Debug)]
256pub struct PlainMessage {
257 pub typ: ContentType,
258 pub version: ProtocolVersion,
259 pub payload: Payload,
260}
261
262impl PlainMessage {
263 pub fn into_unencrypted_opaque(self) -> OpaqueMessage {
264 OpaqueMessage {
265 version: self.version,
266 typ: self.typ,
267 payload: self.payload,
268 }
269 }
270
271 pub fn borrow(&self) -> BorrowedPlainMessage<'_> {
272 BorrowedPlainMessage {
273 version: self.version,
274 typ: self.typ,
275 payload: &self.payload.0,
276 }
277 }
278}
279
280/// A message with decoded payload
281#[derive(Debug)]
282pub struct Message {
283 pub version: ProtocolVersion,
284 pub payload: MessagePayload,
285}
286
287impl Message {
288 pub fn is_handshake_type(&self, hstyp: HandshakeType) -> bool {
289 // Bit of a layering violation, but OK.
290 if let MessagePayload::Handshake { parsed, .. } = &self.payload {
291 parsed.typ == hstyp
292 } else {
293 false
294 }
295 }
296
297 pub fn build_alert(level: AlertLevel, desc: AlertDescription) -> Self {
298 Self {
299 version: ProtocolVersion::TLSv1_2,
300 payload: MessagePayload::Alert(AlertMessagePayload {
301 level,
302 description: desc,
303 }),
304 }
305 }
306
307 pub fn build_key_update_notify() -> Self {
308 Self {
309 version: ProtocolVersion::TLSv1_3,
310 payload: MessagePayload::handshake(HandshakeMessagePayload::build_key_update_notify()),
311 }
312 }
313}
314
315/// Parses a plaintext message into a well-typed [`Message`].
316///
317/// A [`PlainMessage`] must contain plaintext content. Encrypted content should be stored in an
318/// [`OpaqueMessage`] and decrypted before being stored into a [`PlainMessage`].
319impl TryFrom<PlainMessage> for Message {
320 type Error = Error;
321
322 fn try_from(plain: PlainMessage) -> Result<Self, Self::Error> {
323 Ok(Self {
324 version: plain.version,
325 payload: MessagePayload::new(plain.typ, vers:plain.version, plain.payload)?,
326 })
327 }
328}
329
330/// A TLS frame, named TLSPlaintext in the standard.
331///
332/// This type differs from `OpaqueMessage` because it borrows
333/// its payload. You can make a `OpaqueMessage` from an
334/// `BorrowMessage`, but this involves a copy.
335///
336/// This type also cannot decode its internals and
337/// cannot be read/encoded; only `OpaqueMessage` can do that.
338pub struct BorrowedPlainMessage<'a> {
339 pub typ: ContentType,
340 pub version: ProtocolVersion,
341 pub payload: &'a [u8],
342}
343
344impl<'a> BorrowedPlainMessage<'a> {
345 pub fn to_unencrypted_opaque(&self) -> OpaqueMessage {
346 OpaqueMessage {
347 version: self.version,
348 typ: self.typ,
349 payload: Payload(self.payload.to_vec()),
350 }
351 }
352}
353
354#[derive(Debug)]
355pub enum MessageError {
356 TooShortForHeader,
357 TooShortForLength,
358 InvalidEmptyPayload,
359 MessageTooLarge,
360 InvalidContentType,
361 UnknownProtocolVersion,
362}
363