clia_rustls_mod/msgs/message/
mod.rs1use 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;
8use crate::msgs::handshake::HandshakeMessagePayload;
9
10mod inbound;
11pub use inbound::{BorrowedPayload, InboundOpaqueMessage, InboundPlainMessage};
12
13mod outbound;
14use alloc::vec::Vec;
15
16pub use outbound::{OutboundChunks, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload};
17
18#[derive(Debug)]
19pub enum MessagePayload<'a> {
20 Alert(AlertMessagePayload),
21 Handshake {
22 parsed: HandshakeMessagePayload<'a>,
23 encoded: Payload<'a>,
24 },
25 ChangeCipherSpec(ChangeCipherSpecPayload),
26 ApplicationData(Payload<'a>),
27}
28
29impl<'a> MessagePayload<'a> {
30 pub fn encode(&self, bytes: &mut Vec<u8>) {
31 match self {
32 Self::Alert(x) => x.encode(bytes),
33 Self::Handshake { encoded, .. } => bytes.extend(encoded.bytes()),
34 Self::ChangeCipherSpec(x) => x.encode(bytes),
35 Self::ApplicationData(x) => x.encode(bytes),
36 }
37 }
38
39 pub fn handshake(parsed: HandshakeMessagePayload<'a>) -> Self {
40 Self::Handshake {
41 encoded: Payload::new(parsed.get_encoding()),
42 parsed,
43 }
44 }
45
46 pub fn new(
47 typ: ContentType,
48 vers: ProtocolVersion,
49 payload: &'a [u8],
50 ) -> Result<Self, InvalidMessage> {
51 let mut r = Reader::init(payload);
52 match typ {
53 ContentType::ApplicationData => Ok(Self::ApplicationData(Payload::Borrowed(payload))),
54 ContentType::Alert => AlertMessagePayload::read(&mut r).map(MessagePayload::Alert),
55 ContentType::Handshake => {
56 HandshakeMessagePayload::read_version(&mut r, vers).map(|parsed| Self::Handshake {
57 parsed,
58 encoded: Payload::Borrowed(payload),
59 })
60 }
61 ContentType::ChangeCipherSpec => {
62 ChangeCipherSpecPayload::read(&mut r).map(MessagePayload::ChangeCipherSpec)
63 }
64 _ => Err(InvalidMessage::InvalidContentType),
65 }
66 }
67
68 pub fn content_type(&self) -> ContentType {
69 match self {
70 Self::Alert(_) => ContentType::Alert,
71 Self::Handshake { .. } => ContentType::Handshake,
72 Self::ChangeCipherSpec(_) => ContentType::ChangeCipherSpec,
73 Self::ApplicationData(_) => ContentType::ApplicationData,
74 }
75 }
76
77 pub(crate) fn into_owned(self) -> MessagePayload<'static> {
78 use MessagePayload::*;
79 match self {
80 Alert(x) => Alert(x),
81 Handshake { parsed, encoded } => Handshake {
82 parsed: parsed.into_owned(),
83 encoded: encoded.into_owned(),
84 },
85 ChangeCipherSpec(x) => ChangeCipherSpec(x),
86 ApplicationData(x) => ApplicationData(x.into_owned()),
87 }
88 }
89}
90
91impl From<Message<'_>> for PlainMessage {
92 fn from(msg: Message) -> Self {
93 let typ = msg.payload.content_type();
94 let payload = match msg.payload {
95 MessagePayload::ApplicationData(payload) => payload.into_owned(),
96 _ => {
97 let mut buf = Vec::new();
98 msg.payload.encode(&mut buf);
99 Payload::Owned(buf)
100 }
101 };
102
103 Self {
104 typ,
105 version: msg.version,
106 payload,
107 }
108 }
109}
110
111#[derive(Clone, Debug)]
116pub struct PlainMessage {
117 pub typ: ContentType,
118 pub version: ProtocolVersion,
119 pub payload: Payload<'static>,
120}
121
122impl PlainMessage {
123 pub fn into_unencrypted_opaque(self) -> OutboundOpaqueMessage {
124 OutboundOpaqueMessage {
125 version: self.version,
126 typ: self.typ,
127 payload: PrefixedPayload::from(self.payload.bytes()),
128 }
129 }
130
131 pub fn borrow_inbound(&self) -> InboundPlainMessage<'_> {
132 InboundPlainMessage {
133 version: self.version,
134 typ: self.typ,
135 payload: self.payload.bytes(),
136 }
137 }
138
139 pub fn borrow_outbound(&self) -> OutboundPlainMessage<'_> {
140 OutboundPlainMessage {
141 version: self.version,
142 typ: self.typ,
143 payload: self.payload.bytes().into(),
144 }
145 }
146}
147
148#[derive(Debug)]
150pub struct Message<'a> {
151 pub version: ProtocolVersion,
152 pub payload: MessagePayload<'a>,
153}
154
155impl Message<'_> {
156 pub fn is_handshake_type(&self, hstyp: HandshakeType) -> bool {
157 if let MessagePayload::Handshake { parsed, .. } = &self.payload {
159 parsed.typ == hstyp
160 } else {
161 false
162 }
163 }
164
165 pub fn build_alert(level: AlertLevel, desc: AlertDescription) -> Self {
166 Self {
167 version: ProtocolVersion::TLSv1_2,
168 payload: MessagePayload::Alert(AlertMessagePayload {
169 level,
170 description: desc,
171 }),
172 }
173 }
174
175 pub fn build_key_update_notify() -> Self {
176 Self {
177 version: ProtocolVersion::TLSv1_3,
178 payload: MessagePayload::handshake(HandshakeMessagePayload::build_key_update_notify()),
179 }
180 }
181
182 #[cfg(feature = "std")]
183 pub(crate) fn into_owned(self) -> Message<'static> {
184 let Self { version, payload } = self;
185 Message {
186 version,
187 payload: payload.into_owned(),
188 }
189 }
190}
191
192impl TryFrom<PlainMessage> for Message<'static> {
193 type Error = Error;
194
195 fn try_from(plain: PlainMessage) -> Result<Self, Self::Error> {
196 Ok(Self {
197 version: plain.version,
198 payload: MessagePayload::new(plain.typ, plain.version, plain.payload.bytes())?
199 .into_owned(),
200 })
201 }
202}
203
204impl<'a> TryFrom<InboundPlainMessage<'a>> for Message<'a> {
209 type Error = Error;
210
211 fn try_from(plain: InboundPlainMessage<'a>) -> Result<Self, Self::Error> {
212 Ok(Self {
213 version: plain.version,
214 payload: MessagePayload::new(plain.typ, plain.version, plain.payload)?,
215 })
216 }
217}
218
219#[derive(Debug)]
220pub enum MessageError {
221 TooShortForHeader,
222 TooShortForLength,
223 InvalidEmptyPayload,
224 MessageTooLarge,
225 InvalidContentType,
226 UnknownProtocolVersion,
227}
228
229pub(crate) const HEADER_SIZE: usize = 1 + 2 + 2;
231
232const MAX_PAYLOAD: u16 = 16_384 + 2048;
235
236#[cfg(feature = "std")]
238pub(crate) const MAX_WIRE_SIZE: usize = MAX_PAYLOAD as usize + HEADER_SIZE;