1 | use crate::enums::ProtocolVersion; |
2 | use crate::enums::{AlertDescription, ContentType, HandshakeType}; |
3 | use crate::error::{Error, InvalidMessage, PeerMisbehaved}; |
4 | use crate::msgs::alert::AlertMessagePayload; |
5 | use crate::msgs::base::Payload; |
6 | use crate::msgs::ccs::ChangeCipherSpecPayload; |
7 | use crate::msgs::codec::{Codec, Reader}; |
8 | use crate::msgs::enums::AlertLevel; |
9 | use crate::msgs::fragmenter::MAX_FRAGMENT_LEN; |
10 | use crate::msgs::handshake::HandshakeMessagePayload; |
11 | |
12 | use alloc::vec::Vec; |
13 | |
14 | #[derive (Debug)] |
15 | pub enum MessagePayload { |
16 | Alert(AlertMessagePayload), |
17 | Handshake { |
18 | parsed: HandshakeMessagePayload, |
19 | encoded: Payload, |
20 | }, |
21 | ChangeCipherSpec(ChangeCipherSpecPayload), |
22 | ApplicationData(Payload), |
23 | } |
24 | |
25 | impl 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)] |
87 | pub struct OpaqueMessage { |
88 | pub typ: ContentType, |
89 | pub version: ProtocolVersion, |
90 | payload: Payload, |
91 | } |
92 | |
93 | impl 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. |
221 | fn 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 | |
231 | impl 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)] |
256 | pub struct PlainMessage { |
257 | pub typ: ContentType, |
258 | pub version: ProtocolVersion, |
259 | pub payload: Payload, |
260 | } |
261 | |
262 | impl 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)] |
282 | pub struct Message { |
283 | pub version: ProtocolVersion, |
284 | pub payload: MessagePayload, |
285 | } |
286 | |
287 | impl 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`]. |
319 | impl 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. |
338 | pub struct BorrowedPlainMessage<'a> { |
339 | pub typ: ContentType, |
340 | pub version: ProtocolVersion, |
341 | pub payload: &'a [u8], |
342 | } |
343 | |
344 | impl<'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)] |
355 | pub enum MessageError { |
356 | TooShortForHeader, |
357 | TooShortForLength, |
358 | InvalidEmptyPayload, |
359 | MessageTooLarge, |
360 | InvalidContentType, |
361 | UnknownProtocolVersion, |
362 | } |
363 | |