mls_spec/drafts/
additional_wire_formats.rs1use crate::{
2 SensitiveBytes,
3 crypto::Mac,
4 defs::{Epoch, WireFormat},
5 group::GroupId,
6 messages::{ContentType, ContentTypeInner, FramedContentAuthData, Sender},
7};
8
9pub const WIRE_FORMAT_MLS_MESSAGE_WITHOUT_AAD: u16 = 0xFADF; static_assertions::const_assert!(
11 *WireFormat::RESERVED_PRIVATE_USE_RANGE.start() <= WIRE_FORMAT_MLS_MESSAGE_WITHOUT_AAD
12 && WIRE_FORMAT_MLS_MESSAGE_WITHOUT_AAD <= *WireFormat::RESERVED_PRIVATE_USE_RANGE.end()
13);
14
15#[derive(
16 Debug,
17 Clone,
18 Copy,
19 PartialEq,
20 Eq,
21 tls_codec::TlsSize,
22 tls_codec::TlsSerialize,
23 tls_codec::TlsDeserialize,
24)]
25#[cfg_attr(
26 feature = "serde",
27 derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr)
28)]
29#[repr(u8)]
30pub enum MessageWithoutAadType {
31 PublicMessage = 0,
32 PrivateMessage = 1,
33}
34
35#[derive(
46 Debug,
47 Clone,
48 PartialEq,
49 Eq,
50 tls_codec::TlsSize,
51 tls_codec::TlsSerialize,
52 tls_codec::TlsDeserialize,
53)]
54#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
55#[repr(u8)]
56#[allow(clippy::large_enum_variant)]
57pub enum MessageWithoutAad {
58 #[tls_codec(discriminant = "MessageWithoutAadType::PublicMessage")]
59 PublicMessageWithoutAad(PublicMessageWithoutAad),
60 #[tls_codec(discriminant = "MessageWithoutAadType::PrivateMessage")]
61 PrivateMessageWithoutAad(PrivateMessageWithoutAad),
62}
63
64#[derive(
84 Debug,
85 Clone,
86 PartialEq,
87 Eq,
88 tls_codec::TlsSize,
89 tls_codec::TlsSerialize,
90 tls_codec::TlsDeserialize,
91)]
92#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
93pub struct FramedContentWithoutAad {
94 #[tls_codec(with = "crate::tlspl::bytes")]
95 pub group_id: GroupId,
96 pub epoch: Epoch,
97 pub sender: Sender,
98 pub content: ContentTypeInner,
99}
100
101#[derive(Debug, Clone, PartialEq, Eq)]
102#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
103pub struct PublicMessageWithoutAad {
104 pub content: FramedContentWithoutAad,
105 pub auth: FramedContentAuthData,
106 pub membership_tag: Option<Mac>,
107}
108
109impl tls_codec::Serialize for PublicMessageWithoutAad {
110 fn tls_serialize<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, tls_codec::Error> {
111 let mut written = self.content.tls_serialize(writer)?;
112 written += self.auth.tls_serialize(writer)?;
113 if matches!(self.content.sender, Sender::Member(_)) {
114 let Some(mac) = &self.membership_tag else {
115 return Err(tls_codec::Error::EncodingError(
116 "PublicMessageWithoutAad.content.sender is Member but `membership_tag` is missing".into(),
117 ));
118 };
119 written += mac.tls_serialize(writer)?;
120 }
121
122 Ok(written)
123 }
124}
125
126impl tls_codec::Deserialize for PublicMessageWithoutAad {
127 fn tls_deserialize<R: std::io::Read>(bytes: &mut R) -> Result<Self, tls_codec::Error>
128 where
129 Self: Sized,
130 {
131 let content = FramedContentWithoutAad::tls_deserialize(bytes)?;
132 let auth = FramedContentAuthData::tls_deserialize_with_content_type(
133 bytes,
134 (&content.content).into(),
135 )?;
136
137 let membership_tag = if matches!(content.sender, Sender::Member(_)) {
138 Some(Mac::tls_deserialize(bytes)?)
139 } else {
140 None
141 };
142
143 Ok(Self {
144 content,
145 auth,
146 membership_tag,
147 })
148 }
149}
150
151impl tls_codec::Size for PublicMessageWithoutAad {
152 fn tls_serialized_len(&self) -> usize {
153 let membership_tag_len = if matches!(self.content.sender, Sender::Member(_)) {
154 self.membership_tag
155 .as_ref()
156 .map(tls_codec::Size::tls_serialized_len)
157 .unwrap_or_default()
158 } else {
159 debug_assert!(
160 self.membership_tag.is_none(),
161 "PublicMessageWithoutAad contains a membership_tag while it shouldn't. There's a bug somewhere"
162 );
163
164 0
165 };
166
167 self.content.tls_serialized_len() + self.auth.tls_serialized_len() + membership_tag_len
168 }
169}
170
171#[derive(
172 Debug,
173 Clone,
174 PartialEq,
175 Eq,
176 tls_codec::TlsSize,
177 tls_codec::TlsSerialize,
178 tls_codec::TlsDeserialize,
179)]
180#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
181pub struct PrivateMessageWithoutAad {
182 #[tls_codec(with = "crate::tlspl::bytes")]
183 pub group_id: GroupId,
184 pub epoch: Epoch,
185 pub content_type: ContentType,
186 pub encrypted_sender_data: SensitiveBytes,
187 pub ciphertext: SensitiveBytes,
188}