1use openmls_traits::crypto::OpenMlsCrypto;
2use openmls_traits::types::Ciphersuite;
3use tls_codec::{
4 Deserialize, Serialize, TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize,
5};
6
7use super::{
8 codec::deserialize_ciphertext_content, mls_auth_content::FramedContentAuthData,
9 mls_auth_content_in::VerifiableAuthenticatedContentIn, mls_content_in::FramedContentBodyIn,
10};
11
12use crate::{
13 binary_tree::array_representation::LeafNodeIndex,
14 error::LibraryError,
15 framing::mls_content_in::FramedContentIn,
16 tree::{secret_tree::SecretType, sender_ratchet::SenderRatchetConfiguration},
17};
18
19use super::*;
20
21#[derive(
37 Debug, PartialEq, Eq, Clone, TlsSerialize, TlsSize, TlsDeserialize, TlsDeserializeBytes,
38)]
39pub struct PrivateMessageIn {
40 group_id: GroupId,
41 epoch: GroupEpoch,
42 content_type: ContentType,
43 authenticated_data: VLBytes,
44 encrypted_sender_data: VLBytes,
45 ciphertext: VLBytes,
46}
47
48impl PrivateMessageIn {
49 pub fn aad(&self) -> &[u8] {
53 self.authenticated_data.as_slice()
54 }
55
56 pub(crate) fn sender_data(
58 &self,
59 message_secrets: &MessageSecrets,
60 crypto: &impl OpenMlsCrypto,
61 ciphersuite: Ciphersuite,
62 ) -> Result<MlsSenderData, MessageDecryptionError> {
63 log::debug!("Decrypting PrivateMessage");
64 let sender_data_key = message_secrets
66 .sender_data_secret()
67 .derive_aead_key(crypto, ciphersuite, self.ciphertext.as_slice())
68 .map_err(LibraryError::unexpected_crypto_error)?;
69 let sender_data_nonce = message_secrets
71 .sender_data_secret()
72 .derive_aead_nonce(ciphersuite, crypto, self.ciphertext.as_slice())
73 .map_err(LibraryError::unexpected_crypto_error)?;
74 let mls_sender_data_aad =
76 MlsSenderDataAad::new(self.group_id.clone(), self.epoch, self.content_type);
77 let mls_sender_data_aad_bytes = mls_sender_data_aad
78 .tls_serialize_detached()
79 .map_err(LibraryError::missing_bound_check)?;
80 log_crypto!(
82 trace,
83 "Decryption key for sender data: {sender_data_key:x?}"
84 );
85 log_crypto!(trace, "Decryption of sender data mls_sender_data_aad_bytes: {mls_sender_data_aad_bytes:x?} - sender_data_nonce: {sender_data_nonce:x?}");
86 let sender_data_bytes = sender_data_key
87 .aead_open(
88 crypto,
89 self.encrypted_sender_data.as_slice(),
90 &mls_sender_data_aad_bytes,
91 &sender_data_nonce,
92 )
93 .map_err(|_| {
94 log::error!("Sender data decryption error");
95 MessageDecryptionError::AeadError
96 })?;
97 log::trace!(" Successfully decrypted sender data.");
98 MlsSenderData::tls_deserialize(&mut sender_data_bytes.as_slice())
99 .map_err(|_| MessageDecryptionError::MalformedContent)
100 }
101
102 #[inline]
105 fn decrypt(
106 &self,
107 crypto: &impl OpenMlsCrypto,
108 ratchet_key: AeadKey,
109 ratchet_nonce: &AeadNonce,
110 ) -> Result<PrivateMessageContentIn, MessageDecryptionError> {
111 let private_message_content_aad_bytes = PrivateContentAad {
113 group_id: self.group_id.clone(),
114 epoch: self.epoch,
115 content_type: self.content_type,
116 authenticated_data: VLByteSlice(self.authenticated_data.as_slice()),
117 }
118 .tls_serialize_detached()
119 .map_err(LibraryError::missing_bound_check)?;
120 log_crypto!(
122 trace,
123 "Decryption key for private message: {ratchet_key:x?}"
124 );
125 log_crypto!(trace, "Decryption of private message private_message_content_aad_bytes: {private_message_content_aad_bytes:x?} - ratchet_nonce: {ratchet_nonce:x?}");
126 log::trace!("Decrypting ciphertext {:x?}", self.ciphertext);
127 let private_message_content_bytes = ratchet_key
128 .aead_open(
129 crypto,
130 self.ciphertext.as_slice(),
131 &private_message_content_aad_bytes,
132 ratchet_nonce,
133 )
134 .map_err(|_| {
135 log::error!(" Ciphertext decryption error");
136 MessageDecryptionError::AeadError
137 })?;
138 log_content!(
139 trace,
140 " Successfully decrypted PublicMessage bytes: {:x?}",
141 private_message_content_bytes
142 );
143 deserialize_ciphertext_content(
144 &mut private_message_content_bytes.as_slice(),
145 self.content_type(),
146 )
147 .map_err(|_| MessageDecryptionError::MalformedContent)
148 }
149
150 pub(crate) fn to_verifiable_content(
154 &self,
155 ciphersuite: Ciphersuite,
156 crypto: &impl OpenMlsCrypto,
157 message_secrets: &mut MessageSecrets,
158 sender_index: LeafNodeIndex,
159 sender_ratchet_configuration: &SenderRatchetConfiguration,
160 sender_data: MlsSenderData,
161 ) -> Result<VerifiableAuthenticatedContentIn, MessageDecryptionError> {
162 let secret_type = SecretType::from(&self.content_type);
163 let (ratchet_key, ratchet_nonce) = message_secrets
165 .secret_tree_mut()
166 .secret_for_decryption(
167 ciphersuite,
168 crypto,
169 sender_index,
170 secret_type,
171 sender_data.generation,
172 sender_ratchet_configuration,
173 )
174 .map_err(|e| {
175 log::error!(
176 " Ciphertext generation out of bounds {}\n\t{e:?}",
177 sender_data.generation
178 );
179 MessageDecryptionError::SecretTreeError(e)
180 })?;
181 let prepared_nonce = ratchet_nonce.xor_with_reuse_guard(&sender_data.reuse_guard);
183 let private_message_content = self.decrypt(crypto, ratchet_key, &prepared_nonce)?;
184
185 let sender = Sender::from_sender_data(sender_data);
187 log_content!(
188 trace,
189 " Successfully decoded PublicMessage with: {:x?}",
190 private_message_content.content
191 );
192
193 let verifiable = VerifiableAuthenticatedContentIn::new(
194 WireFormat::PrivateMessage,
195 FramedContentIn {
196 group_id: self.group_id.clone(),
197 epoch: self.epoch,
198 sender,
199 authenticated_data: self.authenticated_data.clone(),
200 body: private_message_content.content,
201 },
202 Some(message_secrets.serialized_context().to_vec()),
203 private_message_content.auth,
204 );
205 Ok(verifiable)
206 }
207
208 pub(crate) fn group_id(&self) -> &GroupId {
210 &self.group_id
211 }
212
213 pub(crate) fn epoch(&self) -> GroupEpoch {
215 self.epoch
216 }
217
218 pub(crate) fn content_type(&self) -> ContentType {
220 self.content_type
221 }
222
223 #[cfg(test)]
225 pub(crate) fn set_ciphertext(&mut self, ciphertext: Vec<u8>) {
226 self.ciphertext = ciphertext.into();
227 }
228}
229
230#[derive(Debug, Clone)]
253pub(crate) struct PrivateMessageContentIn {
254 pub(crate) content: FramedContentBodyIn,
259 pub(crate) auth: FramedContentAuthData,
260}
261
262#[cfg(any(feature = "test-utils", test))]
265impl From<PrivateMessageIn> for PrivateMessage {
266 fn from(value: PrivateMessageIn) -> Self {
267 Self {
268 group_id: value.group_id,
269 epoch: value.epoch,
270 content_type: value.content_type,
271 authenticated_data: value.authenticated_data,
272 encrypted_sender_data: value.encrypted_sender_data,
273 ciphertext: value.ciphertext,
274 }
275 }
276}
277
278#[cfg(any(feature = "test-utils", test))]
279impl From<PrivateMessage> for PrivateMessageIn {
280 fn from(value: PrivateMessage) -> Self {
281 Self {
282 group_id: value.group_id,
283 epoch: value.epoch,
284 content_type: value.content_type,
285 authenticated_data: value.authenticated_data,
286 encrypted_sender_data: value.encrypted_sender_data,
287 ciphertext: value.ciphertext,
288 }
289 }
290}