rustls/msgs/message/
mod.rs

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