mls_spec/messages/
message_kinds.rs1use crate::{
2 SensitiveBytes,
3 crypto::Mac,
4 defs::WireFormat,
5 group::GroupId,
6 messages::{ContentType, FramedContent, FramedContentAuthData, FramedContentTBS, Sender},
7};
8
9use super::{AuthenticatedContent, AuthenticatedContentRef};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
33#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
34pub struct PublicMessage {
35 pub content: FramedContent,
36 pub auth: FramedContentAuthData,
37 pub membership_tag: Option<Mac>,
38}
39
40impl PublicMessage {
41 const AUTH_CONTENT_REF_WF: WireFormat =
42 WireFormat::new_unchecked(WireFormat::MLS_PUBLIC_MESSAGE);
43
44 pub fn into_authenticated_content(self) -> AuthenticatedContent {
45 AuthenticatedContent {
46 wire_format: Self::AUTH_CONTENT_REF_WF,
47 content: self.content,
48 auth: self.auth,
49 }
50 }
51
52 pub fn as_authenticated_content(&self) -> AuthenticatedContentRef {
53 AuthenticatedContentRef {
54 wire_format: &Self::AUTH_CONTENT_REF_WF,
55 content: &self.content,
56 auth: &self.auth,
57 }
58 }
59}
60
61impl tls_codec::Serialize for PublicMessage {
62 fn tls_serialize<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, tls_codec::Error> {
63 let mut written = self.content.tls_serialize(writer)?;
64 written += self.auth.tls_serialize(writer)?;
65 if matches!(self.content.sender, Sender::Member(_)) {
66 let Some(mac) = &self.membership_tag else {
67 return Err(tls_codec::Error::EncodingError(
68 "PublicMessage.content.sender is Member but `membership_tag` is missing".into(),
69 ));
70 };
71 written += mac.tls_serialize(writer)?;
72 }
73
74 Ok(written)
75 }
76}
77
78impl tls_codec::Deserialize for PublicMessage {
79 fn tls_deserialize<R: std::io::Read>(bytes: &mut R) -> Result<Self, tls_codec::Error>
80 where
81 Self: Sized,
82 {
83 let content = FramedContent::tls_deserialize(bytes)?;
84 let auth = FramedContentAuthData::tls_deserialize_with_content_type(
85 bytes,
86 (&content.content).into(),
87 )?;
88
89 let membership_tag = if matches!(content.sender, Sender::Member(_)) {
90 Some(Mac::tls_deserialize(bytes)?)
91 } else {
92 None
93 };
94
95 Ok(Self {
96 content,
97 auth,
98 membership_tag,
99 })
100 }
101}
102
103impl tls_codec::Size for PublicMessage {
104 fn tls_serialized_len(&self) -> usize {
105 let membership_tag_len = if matches!(self.content.sender, Sender::Member(_)) {
106 self.membership_tag
107 .as_ref()
108 .map(tls_codec::Size::tls_serialized_len)
109 .unwrap_or_default()
110 } else {
111 debug_assert!(
112 self.membership_tag.is_none(),
113 "PublicMessage contains a membership_tag while it shouldn't. There's a bug somewhere"
114 );
115
116 0
117 };
118
119 self.content.tls_serialized_len() + self.auth.tls_serialized_len() + membership_tag_len
120 }
121}
122
123#[derive(Debug, Clone, PartialEq, Eq, tls_codec::TlsSerialize, tls_codec::TlsSize)]
136pub struct AuthenticatedContentTBM<'a> {
137 pub content_tbs: FramedContentTBS<'a>,
138 pub auth: &'a FramedContentAuthData,
139}
140
141#[derive(
158 Debug,
159 Clone,
160 PartialEq,
161 Eq,
162 tls_codec::TlsSerialize,
163 tls_codec::TlsDeserialize,
164 tls_codec::TlsSize,
165)]
166#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
167pub struct PrivateMessage {
168 pub group_id: GroupId,
169 pub epoch: u64,
170 pub content_type: ContentType,
171 pub authenticated_data: SensitiveBytes,
172 pub encrypted_sender_data: SensitiveBytes,
173 pub ciphertext: SensitiveBytes,
174}