rustls/msgs/
message.rs

1use crate::msgs::alert::AlertMessagePayload;
2use crate::msgs::base::Payload;
3use crate::msgs::ccs::ChangeCipherSpecPayload;
4use crate::msgs::codec::{Codec, Reader};
5use crate::msgs::enums::HandshakeType;
6use crate::msgs::enums::{AlertDescription, AlertLevel};
7use crate::msgs::enums::{ContentType, ProtocolVersion};
8use crate::msgs::handshake::HandshakeMessagePayload;
9
10use std::mem;
11
12#[derive(Debug)]
13pub enum MessagePayload {
14    Alert(AlertMessagePayload),
15    Handshake(HandshakeMessagePayload),
16    ChangeCipherSpec(ChangeCipherSpecPayload),
17    Opaque(Payload),
18}
19
20impl MessagePayload {
21    pub fn encode(&self, bytes: &mut Vec<u8>) {
22        match *self {
23            MessagePayload::Alert(ref x) => x.encode(bytes),
24            MessagePayload::Handshake(ref x) => x.encode(bytes),
25            MessagePayload::ChangeCipherSpec(ref x) => x.encode(bytes),
26            MessagePayload::Opaque(ref x) => x.encode(bytes),
27        }
28    }
29
30    pub fn decode_given_type(
31        &self,
32        typ: ContentType,
33        vers: ProtocolVersion,
34    ) -> Option<MessagePayload> {
35        if let MessagePayload::Opaque(ref payload) = *self {
36            let mut r = Reader::init(&payload.0);
37            let parsed = match typ {
38                ContentType::Alert => {
39                    Some(MessagePayload::Alert(AlertMessagePayload::read(&mut r)?))
40                }
41                ContentType::Handshake => {
42                    let p = HandshakeMessagePayload::read_version(&mut r, vers)?;
43                    Some(MessagePayload::Handshake(p))
44                }
45                ContentType::ChangeCipherSpec => {
46                    let p = ChangeCipherSpecPayload::read(&mut r)?;
47                    Some(MessagePayload::ChangeCipherSpec(p))
48                }
49                _ => None,
50            };
51
52            if r.any_left() { None } else { parsed }
53        } else {
54            None
55        }
56    }
57
58    pub fn length(&self) -> usize {
59        match *self {
60            MessagePayload::Alert(ref x) => x.length(),
61            MessagePayload::Handshake(ref x) => x.length(),
62            MessagePayload::ChangeCipherSpec(ref x) => x.length(),
63            MessagePayload::Opaque(ref x) => x.0.len(),
64        }
65    }
66
67    pub fn new_opaque(data: Vec<u8>) -> MessagePayload {
68        MessagePayload::Opaque(Payload::new(data))
69    }
70}
71
72/// A TLS frame, named TLSPlaintext in the standard.
73/// This type owns all memory for its interior parts.
74#[derive(Debug)]
75pub struct Message {
76    pub typ: ContentType,
77    pub version: ProtocolVersion,
78    pub payload: MessagePayload,
79}
80
81impl Message {
82    /// This is the maximum on-the-wire size of a TLSCiphertext.
83    /// That's 2^14 payload bytes, a header, and a 2KB allowance
84    /// for ciphertext overheads.
85    const MAX_PAYLOAD: u16 = 16384 + 2048;
86
87    /// Content type, version and size.
88    const HEADER_SIZE: u16 = 1 + 2 + 2;
89
90    /// Maximum on-wire message size.
91    pub const MAX_WIRE_SIZE: usize = (Message::MAX_PAYLOAD + Message::HEADER_SIZE) as usize;
92}
93
94impl Codec for Message {
95    fn read(r: &mut Reader) -> Option<Message> {
96        Message::read_with_detailed_error(r).ok()
97    }
98
99    fn encode(&self, bytes: &mut Vec<u8>) {
100        self.typ.encode(bytes);
101        self.version.encode(bytes);
102        (self.payload.length() as u16).encode(bytes);
103        self.payload.encode(bytes);
104    }
105}
106
107pub enum MessageError {
108    TooShortForHeader,
109    TooShortForLength,
110    IllegalLength,
111    IllegalContentType,
112    IllegalProtocolVersion,
113}
114
115impl Message {
116    /// Like Message::read(), but allows the important distinction between:
117    /// this message might be valid if we read more data; and this message will
118    /// never be valid.
119    pub fn read_with_detailed_error(r: &mut Reader) -> Result<Message, MessageError> {
120        let typ = ContentType::read(r).ok_or(MessageError::TooShortForHeader)?;
121        let version = ProtocolVersion::read(r).ok_or(MessageError::TooShortForHeader)?;
122        let len = u16::read(r).ok_or(MessageError::TooShortForHeader)?;
123
124        // Reject oversize messages
125        if len >= Message::MAX_PAYLOAD {
126            return Err(MessageError::IllegalLength);
127        }
128
129        // Don't accept any new content-types.
130        if let ContentType::Unknown(_) = typ {
131            return Err(MessageError::IllegalContentType);
132        }
133
134        // Accept only versions 0x03XX for any XX.
135        match version {
136            ProtocolVersion::Unknown(ref v) if (v & 0xff00) != 0x0300 => {
137                return Err(MessageError::IllegalProtocolVersion);
138            }
139            _ => {}
140        };
141
142        let mut sub = r
143            .sub(len as usize)
144            .ok_or(MessageError::TooShortForLength)?;
145        let payload = Payload::read(&mut sub).unwrap();
146
147        Ok(Message {
148            typ,
149            version,
150            payload: MessagePayload::Opaque(payload),
151        })
152    }
153
154    pub fn is_content_type(&self, typ: ContentType) -> bool {
155        self.typ == typ
156    }
157
158    pub fn is_handshake_type(&self, hstyp: HandshakeType) -> bool {
159        // Bit of a layering violation, but OK.
160        if let MessagePayload::Handshake(ref hsp) = self.payload {
161            hsp.typ == hstyp
162        } else {
163            false
164        }
165    }
166
167    pub fn decode_payload(&mut self) -> bool {
168        // Do we need a decode?
169        if self.typ == ContentType::ApplicationData {
170            return true;
171        }
172
173        if let Some(x) = self
174            .payload
175            .decode_given_type(self.typ, self.version)
176        {
177            self.payload = x;
178            true
179        } else {
180            false
181        }
182    }
183
184    pub fn take_payload(self) -> Vec<u8> {
185        self.into_opaque()
186            .take_opaque_payload()
187            .unwrap()
188            .0
189    }
190
191    pub fn take_opaque_payload(&mut self) -> Option<Payload> {
192        if let MessagePayload::Opaque(ref mut op) = self.payload {
193            Some(mem::replace(op, Payload::empty()))
194        } else {
195            None
196        }
197    }
198
199    pub fn into_opaque(self) -> Message {
200        if let MessagePayload::Opaque(_) = self.payload {
201            return self;
202        }
203
204        let mut buf = Vec::new();
205        self.payload.encode(&mut buf);
206
207        Message {
208            typ: self.typ,
209            version: self.version,
210            payload: MessagePayload::new_opaque(buf),
211        }
212    }
213
214    pub fn build_alert(level: AlertLevel, desc: AlertDescription) -> Message {
215        Message {
216            typ: ContentType::Alert,
217            version: ProtocolVersion::TLSv1_2,
218            payload: MessagePayload::Alert(AlertMessagePayload {
219                level,
220                description: desc,
221            }),
222        }
223    }
224
225    pub fn build_key_update_notify() -> Message {
226        Message {
227            typ: ContentType::Handshake,
228            version: ProtocolVersion::TLSv1_3,
229            payload: MessagePayload::Handshake(HandshakeMessagePayload::build_key_update_notify()),
230        }
231    }
232}
233
234impl<'a> Message {
235    pub fn to_borrowed(&'a self) -> BorrowMessage<'a> {
236        if let MessagePayload::Opaque(ref p) = self.payload {
237            BorrowMessage {
238                typ: self.typ,
239                version: self.version,
240                payload: &p.0,
241            }
242        } else {
243            unreachable!("to_borrowed must have opaque message");
244        }
245    }
246}
247
248/// A TLS frame, named TLSPlaintext in the standard.
249///
250/// This type differs from `Message` because it borrows
251/// its payload.  You can make a `Message` from an
252/// `BorrowMessage`, but this involves a copy.
253///
254/// This type also cannot decode its internals and
255/// is not a `Codec` type, only `Message` can do that.
256pub struct BorrowMessage<'a> {
257    pub typ: ContentType,
258    pub version: ProtocolVersion,
259    pub payload: &'a [u8],
260}