rustls/msgs/
message.rs

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) => 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 = msg.payload.content_type();
234        let payload = match msg.payload {
235            MessagePayload::ApplicationData(payload) => payload,
236            _ => {
237                let mut buf = 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, 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}