rustls/msgs/message/
mod.rs

1use crate::enums::{AlertDescription, ContentType, HandshakeType, ProtocolVersion};
2use crate::error::InvalidMessage;
3use crate::msgs::alert::AlertMessagePayload;
4use crate::msgs::base::Payload;
5use crate::msgs::ccs::ChangeCipherSpecPayload;
6use crate::msgs::codec::{Codec, Reader};
7use crate::msgs::enums::{AlertLevel, KeyUpdateRequest};
8use crate::msgs::handshake::{HandshakeMessagePayload, HandshakePayload};
9
10mod inbound;
11pub use inbound::{BorrowedPayload, InboundOpaqueMessage, InboundPlainMessage};
12
13mod outbound;
14use alloc::vec::Vec;
15
16pub(crate) use outbound::read_opaque_message_header;
17pub use outbound::{OutboundChunks, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload};
18
19#[derive(Debug)]
20pub enum MessagePayload<'a> {
21    Alert(AlertMessagePayload),
22    // one handshake message, parsed
23    Handshake {
24        parsed: HandshakeMessagePayload<'a>,
25        encoded: Payload<'a>,
26    },
27    // (potentially) multiple handshake messages, unparsed
28    HandshakeFlight(Payload<'a>),
29    ChangeCipherSpec(ChangeCipherSpecPayload),
30    ApplicationData(Payload<'a>),
31}
32
33impl<'a> MessagePayload<'a> {
34    pub fn encode(&self, bytes: &mut Vec<u8>) {
35        match self {
36            Self::Alert(x) => x.encode(bytes),
37            Self::Handshake { encoded, .. } => bytes.extend(encoded.bytes()),
38            Self::HandshakeFlight(x) => bytes.extend(x.bytes()),
39            Self::ChangeCipherSpec(x) => x.encode(bytes),
40            Self::ApplicationData(x) => x.encode(bytes),
41        }
42    }
43
44    pub fn handshake(parsed: HandshakeMessagePayload<'a>) -> Self {
45        Self::Handshake {
46            encoded: Payload::new(parsed.get_encoding()),
47            parsed,
48        }
49    }
50
51    pub fn new(
52        typ: ContentType,
53        vers: ProtocolVersion,
54        payload: &'a [u8],
55    ) -> Result<Self, InvalidMessage> {
56        let mut r = Reader::init(payload);
57        match typ {
58            ContentType::ApplicationData => Ok(Self::ApplicationData(Payload::Borrowed(payload))),
59            ContentType::Alert => AlertMessagePayload::read(&mut r).map(MessagePayload::Alert),
60            ContentType::Handshake => {
61                HandshakeMessagePayload::read_version(&mut r, vers).map(|parsed| Self::Handshake {
62                    parsed,
63                    encoded: Payload::Borrowed(payload),
64                })
65            }
66            ContentType::ChangeCipherSpec => {
67                ChangeCipherSpecPayload::read(&mut r).map(MessagePayload::ChangeCipherSpec)
68            }
69            _ => Err(InvalidMessage::InvalidContentType),
70        }
71    }
72
73    pub fn content_type(&self) -> ContentType {
74        match self {
75            Self::Alert(_) => ContentType::Alert,
76            Self::Handshake { .. } | Self::HandshakeFlight(_) => ContentType::Handshake,
77            Self::ChangeCipherSpec(_) => ContentType::ChangeCipherSpec,
78            Self::ApplicationData(_) => ContentType::ApplicationData,
79        }
80    }
81
82    pub(crate) fn into_owned(self) -> MessagePayload<'static> {
83        use MessagePayload::*;
84        match self {
85            Alert(x) => Alert(x),
86            Handshake { parsed, encoded } => Handshake {
87                parsed: parsed.into_owned(),
88                encoded: encoded.into_owned(),
89            },
90            HandshakeFlight(x) => HandshakeFlight(x.into_owned()),
91            ChangeCipherSpec(x) => ChangeCipherSpec(x),
92            ApplicationData(x) => ApplicationData(x.into_owned()),
93        }
94    }
95}
96
97impl From<Message<'_>> for PlainMessage {
98    fn from(msg: Message<'_>) -> Self {
99        let typ = msg.payload.content_type();
100        let payload = match msg.payload {
101            MessagePayload::ApplicationData(payload) => payload.into_owned(),
102            _ => {
103                let mut buf = Vec::new();
104                msg.payload.encode(&mut buf);
105                Payload::Owned(buf)
106            }
107        };
108
109        Self {
110            typ,
111            version: msg.version,
112            payload,
113        }
114    }
115}
116
117/// A decrypted TLS frame
118///
119/// This type owns all memory for its interior parts. It can be decrypted from an OpaqueMessage
120/// or encrypted into an OpaqueMessage, and it is also used for joining and fragmenting.
121#[derive(Clone, Debug)]
122pub struct PlainMessage {
123    pub typ: ContentType,
124    pub version: ProtocolVersion,
125    pub payload: Payload<'static>,
126}
127
128impl PlainMessage {
129    pub fn into_unencrypted_opaque(self) -> OutboundOpaqueMessage {
130        OutboundOpaqueMessage {
131            version: self.version,
132            typ: self.typ,
133            payload: PrefixedPayload::from(self.payload.bytes()),
134        }
135    }
136
137    pub fn borrow_inbound(&self) -> InboundPlainMessage<'_> {
138        InboundPlainMessage {
139            version: self.version,
140            typ: self.typ,
141            payload: self.payload.bytes(),
142        }
143    }
144
145    pub fn borrow_outbound(&self) -> OutboundPlainMessage<'_> {
146        OutboundPlainMessage {
147            version: self.version,
148            typ: self.typ,
149            payload: self.payload.bytes().into(),
150        }
151    }
152}
153
154/// A message with decoded payload
155#[derive(Debug)]
156pub struct Message<'a> {
157    pub version: ProtocolVersion,
158    pub payload: MessagePayload<'a>,
159}
160
161impl Message<'_> {
162    pub fn is_handshake_type(&self, hstyp: HandshakeType) -> bool {
163        // Bit of a layering violation, but OK.
164        if let MessagePayload::Handshake { parsed, .. } = &self.payload {
165            parsed.0.handshake_type() == hstyp
166        } else {
167            false
168        }
169    }
170
171    pub fn build_alert(level: AlertLevel, desc: AlertDescription) -> Self {
172        Self {
173            version: ProtocolVersion::TLSv1_2,
174            payload: MessagePayload::Alert(AlertMessagePayload {
175                level,
176                description: desc,
177            }),
178        }
179    }
180
181    pub fn build_key_update_notify() -> Self {
182        Self {
183            version: ProtocolVersion::TLSv1_3,
184            payload: MessagePayload::handshake(HandshakeMessagePayload(
185                HandshakePayload::KeyUpdate(KeyUpdateRequest::UpdateNotRequested),
186            )),
187        }
188    }
189
190    pub fn build_key_update_request() -> Self {
191        Self {
192            version: ProtocolVersion::TLSv1_3,
193            payload: MessagePayload::handshake(HandshakeMessagePayload(
194                HandshakePayload::KeyUpdate(KeyUpdateRequest::UpdateRequested),
195            )),
196        }
197    }
198
199    #[cfg(feature = "std")]
200    pub(crate) fn into_owned(self) -> Message<'static> {
201        let Self { version, payload } = self;
202        Message {
203            version,
204            payload: payload.into_owned(),
205        }
206    }
207
208    #[cfg(test)]
209    pub(crate) fn into_wire_bytes(self) -> Vec<u8> {
210        PlainMessage::from(self)
211            .into_unencrypted_opaque()
212            .encode()
213    }
214}
215
216impl TryFrom<PlainMessage> for Message<'static> {
217    type Error = InvalidMessage;
218
219    fn try_from(plain: PlainMessage) -> Result<Self, Self::Error> {
220        Ok(Self {
221            version: plain.version,
222            payload: MessagePayload::new(plain.typ, plain.version, plain.payload.bytes())?
223                .into_owned(),
224        })
225    }
226}
227
228/// Parses a plaintext message into a well-typed [`Message`].
229///
230/// A [`PlainMessage`] must contain plaintext content. Encrypted content should be stored in an
231/// [`InboundOpaqueMessage`] and decrypted before being stored into a [`PlainMessage`].
232impl<'a> TryFrom<InboundPlainMessage<'a>> for Message<'a> {
233    type Error = InvalidMessage;
234
235    fn try_from(plain: InboundPlainMessage<'a>) -> Result<Self, Self::Error> {
236        Ok(Self {
237            version: plain.version,
238            payload: MessagePayload::new(plain.typ, plain.version, plain.payload)?,
239        })
240    }
241}
242
243#[derive(Debug)]
244pub enum MessageError {
245    TooShortForHeader,
246    TooShortForLength,
247    InvalidEmptyPayload,
248    MessageTooLarge,
249    InvalidContentType,
250    UnknownProtocolVersion,
251}
252
253/// Content type, version and size.
254pub(crate) const HEADER_SIZE: usize = 1 + 2 + 2;
255
256/// Maximum message payload size.
257/// That's 2^14 payload bytes and a 2KB allowance for ciphertext overheads.
258const MAX_PAYLOAD: u16 = 16_384 + 2048;
259
260/// Maximum on-the-wire message size.
261#[cfg(feature = "std")]
262pub(crate) const MAX_WIRE_SIZE: usize = MAX_PAYLOAD as usize + HEADER_SIZE;