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 debug_assert!(false, "Ciphertext decryption failed");
137 MessageDecryptionError::AeadError
138 })?;
139 log_content!(
140 trace,
141 " Successfully decrypted PublicMessage bytes: {:x?}",
142 private_message_content_bytes
143 );
144 deserialize_ciphertext_content(
145 &mut private_message_content_bytes.as_slice(),
146 self.content_type(),
147 )
148 .map_err(|_| MessageDecryptionError::MalformedContent)
149 }
150
151 pub(crate) fn to_verifiable_content(
155 &self,
156 ciphersuite: Ciphersuite,
157 crypto: &impl OpenMlsCrypto,
158 message_secrets: &mut MessageSecrets,
159 sender_index: LeafNodeIndex,
160 sender_ratchet_configuration: &SenderRatchetConfiguration,
161 sender_data: MlsSenderData,
162 ) -> Result<VerifiableAuthenticatedContentIn, MessageDecryptionError> {
163 let secret_type = SecretType::from(&self.content_type);
164 let (ratchet_key, ratchet_nonce) = message_secrets
166 .secret_tree_mut()
167 .secret_for_decryption(
168 ciphersuite,
169 crypto,
170 sender_index,
171 secret_type,
172 sender_data.generation,
173 sender_ratchet_configuration,
174 )
175 .map_err(|e| {
176 log::error!(
177 " Ciphertext generation out of bounds {}\n\t{e:?}",
178 sender_data.generation
179 );
180 MessageDecryptionError::SecretTreeError(e)
181 })?;
182 let prepared_nonce = ratchet_nonce.xor_with_reuse_guard(&sender_data.reuse_guard);
184 let private_message_content = self.decrypt(crypto, ratchet_key, &prepared_nonce)?;
185
186 let sender = Sender::from_sender_data(sender_data);
188 log_content!(
189 trace,
190 " Successfully decoded PublicMessage with: {:x?}",
191 private_message_content.content
192 );
193
194 let verifiable = VerifiableAuthenticatedContentIn::new(
195 WireFormat::PrivateMessage,
196 FramedContentIn {
197 group_id: self.group_id.clone(),
198 epoch: self.epoch,
199 sender,
200 authenticated_data: self.authenticated_data.clone(),
201 body: private_message_content.content,
202 },
203 Some(message_secrets.serialized_context().to_vec()),
204 private_message_content.auth,
205 );
206 Ok(verifiable)
207 }
208
209 pub(crate) fn group_id(&self) -> &GroupId {
211 &self.group_id
212 }
213
214 pub(crate) fn epoch(&self) -> GroupEpoch {
216 self.epoch
217 }
218
219 pub(crate) fn content_type(&self) -> ContentType {
221 self.content_type
222 }
223
224 #[cfg(test)]
226 pub(crate) fn set_ciphertext(&mut self, ciphertext: Vec<u8>) {
227 self.ciphertext = ciphertext.into();
228 }
229}
230
231#[derive(Debug, Clone)]
254pub(crate) struct PrivateMessageContentIn {
255 pub(crate) content: FramedContentBodyIn,
260 pub(crate) auth: FramedContentAuthData,
261}
262
263#[cfg(any(feature = "test-utils", test))]
266impl From<PrivateMessageIn> for PrivateMessage {
267 fn from(value: PrivateMessageIn) -> Self {
268 Self {
269 group_id: value.group_id,
270 epoch: value.epoch,
271 content_type: value.content_type,
272 authenticated_data: value.authenticated_data,
273 encrypted_sender_data: value.encrypted_sender_data,
274 ciphertext: value.ciphertext,
275 }
276 }
277}
278
279#[cfg(any(feature = "test-utils", test))]
280impl From<PrivateMessage> for PrivateMessageIn {
281 fn from(value: PrivateMessage) -> Self {
282 Self {
283 group_id: value.group_id,
284 epoch: value.epoch,
285 content_type: value.content_type,
286 authenticated_data: value.authenticated_data,
287 encrypted_sender_data: value.encrypted_sender_data,
288 ciphertext: value.ciphertext,
289 }
290 }
291}