rustls/msgs/
message.rs

1use crate::enums::ProtocolVersion;
2use crate::enums::{AlertDescription, ContentType, HandshakeType};
3use crate::error::{Error, InvalidMessage};
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::handshake::HandshakeMessagePayload;
10
11#[derive(Debug)]
12pub enum MessagePayload {
13    Alert(AlertMessagePayload),
14    Handshake {
15        parsed: HandshakeMessagePayload,
16        encoded: Payload,
17    },
18    ChangeCipherSpec(ChangeCipherSpecPayload),
19    ApplicationData(Payload),
20}
21
22impl MessagePayload {
23    pub fn encode(&self, bytes: &mut Vec<u8>) {
24        match self {
25            Self::Alert(x) => x.encode(bytes),
26            Self::Handshake { encoded, .. } => bytes.extend(&encoded.0),
27            Self::ChangeCipherSpec(x) => x.encode(bytes),
28            Self::ApplicationData(x) => x.encode(bytes),
29        }
30    }
31
32    pub fn handshake(parsed: HandshakeMessagePayload) -> Self {
33        Self::Handshake {
34            encoded: Payload::new(parsed.get_encoding()),
35            parsed,
36        }
37    }
38
39    pub fn new(
40        typ: ContentType,
41        vers: ProtocolVersion,
42        payload: Payload,
43    ) -> Result<Self, InvalidMessage> {
44        let mut r = Reader::init(&payload.0);
45        match typ {
46            ContentType::ApplicationData => Ok(Self::ApplicationData(payload)),
47            ContentType::Alert => AlertMessagePayload::read(&mut r).map(MessagePayload::Alert),
48            ContentType::Handshake => {
49                HandshakeMessagePayload::read_version(&mut r, vers).map(|parsed| Self::Handshake {
50                    parsed,
51                    encoded: payload,
52                })
53            }
54            ContentType::ChangeCipherSpec => {
55                ChangeCipherSpecPayload::read(&mut r).map(MessagePayload::ChangeCipherSpec)
56            }
57            _ => Err(InvalidMessage::InvalidContentType),
58        }
59    }
60
61    pub fn content_type(&self) -> ContentType {
62        match self {
63            Self::Alert(_) => ContentType::Alert,
64            Self::Handshake { .. } => ContentType::Handshake,
65            Self::ChangeCipherSpec(_) => ContentType::ChangeCipherSpec,
66            Self::ApplicationData(_) => ContentType::ApplicationData,
67        }
68    }
69}
70
71/// A TLS frame, named TLSPlaintext in the standard.
72///
73/// This type owns all memory for its interior parts. It is used to read/write from/to I/O
74/// buffers as well as for fragmenting, joining and encryption/decryption. It can be converted
75/// into a `Message` by decoding the payload.
76#[derive(Clone, Debug)]
77pub struct OpaqueMessage {
78    pub typ: ContentType,
79    pub version: ProtocolVersion,
80    pub payload: Payload,
81}
82
83impl OpaqueMessage {
84    /// `MessageError` allows callers to distinguish between valid prefixes (might
85    /// become valid if we read more data) and invalid data.
86    pub fn read(r: &mut Reader) -> Result<Self, MessageError> {
87        let typ = ContentType::read(r).map_err(|_| MessageError::TooShortForHeader)?;
88        // Don't accept any new content-types.
89        if let ContentType::Unknown(_) = typ {
90            return Err(MessageError::InvalidContentType);
91        }
92
93        let version = ProtocolVersion::read(r).map_err(|_| MessageError::TooShortForHeader)?;
94        // Accept only versions 0x03XX for any XX.
95        match version {
96            ProtocolVersion::Unknown(ref v) if (v & 0xff00) != 0x0300 => {
97                return Err(MessageError::UnknownProtocolVersion);
98            }
99            _ => {}
100        };
101
102        let len = u16::read(r).map_err(|_| MessageError::TooShortForHeader)?;
103
104        // Reject undersize messages
105        //  implemented per section 5.1 of RFC8446 (TLSv1.3)
106        //              per section 6.2.1 of RFC5246 (TLSv1.2)
107        if typ != ContentType::ApplicationData && len == 0 {
108            return Err(MessageError::InvalidEmptyPayload);
109        }
110
111        // Reject oversize messages
112        if len >= Self::MAX_PAYLOAD {
113            return Err(MessageError::MessageTooLarge);
114        }
115
116        let mut sub = r
117            .sub(len as usize)
118            .map_err(|_| MessageError::TooShortForLength)?;
119        let payload = Payload::read(&mut sub);
120
121        Ok(Self {
122            typ,
123            version,
124            payload,
125        })
126    }
127
128    pub fn encode(self) -> Vec<u8> {
129        let mut buf = Vec::new();
130        self.typ.encode(&mut buf);
131        self.version.encode(&mut buf);
132        (self.payload.0.len() as u16).encode(&mut buf);
133        self.payload.encode(&mut buf);
134        buf
135    }
136
137    /// Force conversion into a plaintext message.
138    ///
139    /// This should only be used for messages that are known to be in plaintext. Otherwise, the
140    /// `OpaqueMessage` should be decrypted into a `PlainMessage` using a `MessageDecrypter`.
141    pub fn into_plain_message(self) -> PlainMessage {
142        PlainMessage {
143            version: self.version,
144            typ: self.typ,
145            payload: self.payload,
146        }
147    }
148
149    /// This is the maximum on-the-wire size of a TLSCiphertext.
150    /// That's 2^14 payload bytes, a header, and a 2KB allowance
151    /// for ciphertext overheads.
152    const MAX_PAYLOAD: u16 = 16384 + 2048;
153
154    /// Content type, version and size.
155    const HEADER_SIZE: u16 = 1 + 2 + 2;
156
157    /// Maximum on-wire message size.
158    pub const MAX_WIRE_SIZE: usize = (Self::MAX_PAYLOAD + Self::HEADER_SIZE) as usize;
159}
160
161impl From<Message> for PlainMessage {
162    fn from(msg: Message) -> Self {
163        let typ = msg.payload.content_type();
164        let payload = match msg.payload {
165            MessagePayload::ApplicationData(payload) => payload,
166            _ => {
167                let mut buf = Vec::new();
168                msg.payload.encode(&mut buf);
169                Payload(buf)
170            }
171        };
172
173        Self {
174            typ,
175            version: msg.version,
176            payload,
177        }
178    }
179}
180
181/// A decrypted TLS frame
182///
183/// This type owns all memory for its interior parts. It can be decrypted from an OpaqueMessage
184/// or encrypted into an OpaqueMessage, and it is also used for joining and fragmenting.
185#[derive(Clone, Debug)]
186pub struct PlainMessage {
187    pub typ: ContentType,
188    pub version: ProtocolVersion,
189    pub payload: Payload,
190}
191
192impl PlainMessage {
193    pub fn into_unencrypted_opaque(self) -> OpaqueMessage {
194        OpaqueMessage {
195            version: self.version,
196            typ: self.typ,
197            payload: self.payload,
198        }
199    }
200
201    pub fn borrow(&self) -> BorrowedPlainMessage<'_> {
202        BorrowedPlainMessage {
203            version: self.version,
204            typ: self.typ,
205            payload: &self.payload.0,
206        }
207    }
208}
209
210/// A message with decoded payload
211#[derive(Debug)]
212pub struct Message {
213    pub version: ProtocolVersion,
214    pub payload: MessagePayload,
215}
216
217impl Message {
218    pub fn is_handshake_type(&self, hstyp: HandshakeType) -> bool {
219        // Bit of a layering violation, but OK.
220        if let MessagePayload::Handshake { parsed, .. } = &self.payload {
221            parsed.typ == hstyp
222        } else {
223            false
224        }
225    }
226
227    pub fn build_alert(level: AlertLevel, desc: AlertDescription) -> Self {
228        Self {
229            version: ProtocolVersion::TLSv1_2,
230            payload: MessagePayload::Alert(AlertMessagePayload {
231                level,
232                description: desc,
233            }),
234        }
235    }
236
237    pub fn build_key_update_notify() -> Self {
238        Self {
239            version: ProtocolVersion::TLSv1_3,
240            payload: MessagePayload::handshake(HandshakeMessagePayload::build_key_update_notify()),
241        }
242    }
243}
244
245/// Parses a plaintext message into a well-typed [`Message`].
246///
247/// A [`PlainMessage`] must contain plaintext content. Encrypted content should be stored in an
248/// [`OpaqueMessage`] and decrypted before being stored into a [`PlainMessage`].
249impl TryFrom<PlainMessage> for Message {
250    type Error = Error;
251
252    fn try_from(plain: PlainMessage) -> Result<Self, Self::Error> {
253        Ok(Self {
254            version: plain.version,
255            payload: MessagePayload::new(plain.typ, plain.version, plain.payload)?,
256        })
257    }
258}
259
260/// A TLS frame, named TLSPlaintext in the standard.
261///
262/// This type differs from `OpaqueMessage` because it borrows
263/// its payload.  You can make a `OpaqueMessage` from an
264/// `BorrowMessage`, but this involves a copy.
265///
266/// This type also cannot decode its internals and
267/// cannot be read/encoded; only `OpaqueMessage` can do that.
268pub struct BorrowedPlainMessage<'a> {
269    pub typ: ContentType,
270    pub version: ProtocolVersion,
271    pub payload: &'a [u8],
272}
273
274impl<'a> BorrowedPlainMessage<'a> {
275    pub fn to_unencrypted_opaque(&self) -> OpaqueMessage {
276        OpaqueMessage {
277            version: self.version,
278            typ: self.typ,
279            payload: Payload(self.payload.to_vec()),
280        }
281    }
282}
283
284#[derive(Debug)]
285pub enum MessageError {
286    TooShortForHeader,
287    TooShortForLength,
288    InvalidEmptyPayload,
289    MessageTooLarge,
290    InvalidContentType,
291    UnknownProtocolVersion,
292}