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(crate) fn sender_data(
51 &self,
52 message_secrets: &MessageSecrets,
53 crypto: &impl OpenMlsCrypto,
54 ciphersuite: Ciphersuite,
55 ) -> Result<MlsSenderData, MessageDecryptionError> {
56 log::debug!("Decrypting PrivateMessage");
57 let sender_data_key = message_secrets
59 .sender_data_secret()
60 .derive_aead_key(crypto, ciphersuite, self.ciphertext.as_slice())
61 .map_err(LibraryError::unexpected_crypto_error)?;
62 let sender_data_nonce = message_secrets
64 .sender_data_secret()
65 .derive_aead_nonce(ciphersuite, crypto, self.ciphertext.as_slice())
66 .map_err(LibraryError::unexpected_crypto_error)?;
67 let mls_sender_data_aad =
69 MlsSenderDataAad::new(self.group_id.clone(), self.epoch, self.content_type);
70 let mls_sender_data_aad_bytes = mls_sender_data_aad
71 .tls_serialize_detached()
72 .map_err(LibraryError::missing_bound_check)?;
73 log_crypto!(
75 trace,
76 "Decryption key for sender data: {sender_data_key:x?}"
77 );
78 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?}");
79 let sender_data_bytes = sender_data_key
80 .aead_open(
81 crypto,
82 self.encrypted_sender_data.as_slice(),
83 &mls_sender_data_aad_bytes,
84 &sender_data_nonce,
85 )
86 .map_err(|_| {
87 log::error!("Sender data decryption error");
88 MessageDecryptionError::AeadError
89 })?;
90 log::trace!(" Successfully decrypted sender data.");
91 MlsSenderData::tls_deserialize(&mut sender_data_bytes.as_slice())
92 .map_err(|_| MessageDecryptionError::MalformedContent)
93 }
94
95 #[inline]
98 fn decrypt(
99 &self,
100 crypto: &impl OpenMlsCrypto,
101 ratchet_key: AeadKey,
102 ratchet_nonce: &AeadNonce,
103 ) -> Result<PrivateMessageContentIn, MessageDecryptionError> {
104 let private_message_content_aad_bytes = PrivateContentAad {
106 group_id: self.group_id.clone(),
107 epoch: self.epoch,
108 content_type: self.content_type,
109 authenticated_data: VLByteSlice(self.authenticated_data.as_slice()),
110 }
111 .tls_serialize_detached()
112 .map_err(LibraryError::missing_bound_check)?;
113 log_crypto!(
115 trace,
116 "Decryption key for private message: {ratchet_key:x?}"
117 );
118 log_crypto!(trace, "Decryption of private message private_message_content_aad_bytes: {private_message_content_aad_bytes:x?} - ratchet_nonce: {ratchet_nonce:x?}");
119 log::trace!("Decrypting ciphertext {:x?}", self.ciphertext);
120 let private_message_content_bytes = ratchet_key
121 .aead_open(
122 crypto,
123 self.ciphertext.as_slice(),
124 &private_message_content_aad_bytes,
125 ratchet_nonce,
126 )
127 .map_err(|_| {
128 log::error!(" Ciphertext decryption error");
129 debug_assert!(false, "Ciphertext decryption failed");
130 MessageDecryptionError::AeadError
131 })?;
132 log_content!(
133 trace,
134 " Successfully decrypted PublicMessage bytes: {:x?}",
135 private_message_content_bytes
136 );
137 deserialize_ciphertext_content(
138 &mut private_message_content_bytes.as_slice(),
139 self.content_type(),
140 )
141 .map_err(|_| MessageDecryptionError::MalformedContent)
142 }
143
144 pub(crate) fn to_verifiable_content(
148 &self,
149 ciphersuite: Ciphersuite,
150 crypto: &impl OpenMlsCrypto,
151 message_secrets: &mut MessageSecrets,
152 sender_index: LeafNodeIndex,
153 sender_ratchet_configuration: &SenderRatchetConfiguration,
154 sender_data: MlsSenderData,
155 ) -> Result<VerifiableAuthenticatedContentIn, MessageDecryptionError> {
156 let secret_type = SecretType::from(&self.content_type);
157 let (ratchet_key, ratchet_nonce) = message_secrets
159 .secret_tree_mut()
160 .secret_for_decryption(
161 ciphersuite,
162 crypto,
163 sender_index,
164 secret_type,
165 sender_data.generation,
166 sender_ratchet_configuration,
167 )
168 .map_err(|e| {
169 log::error!(
170 " Ciphertext generation out of bounds {}\n\t{e:?}",
171 sender_data.generation
172 );
173 MessageDecryptionError::SecretTreeError(e)
174 })?;
175 let prepared_nonce = ratchet_nonce.xor_with_reuse_guard(&sender_data.reuse_guard);
177 let private_message_content = self.decrypt(crypto, ratchet_key, &prepared_nonce)?;
178
179 let sender = Sender::from_sender_data(sender_data);
181 log_content!(
182 trace,
183 " Successfully decoded PublicMessage with: {:x?}",
184 private_message_content.content
185 );
186
187 let verifiable = VerifiableAuthenticatedContentIn::new(
188 WireFormat::PrivateMessage,
189 FramedContentIn {
190 group_id: self.group_id.clone(),
191 epoch: self.epoch,
192 sender,
193 authenticated_data: self.authenticated_data.clone(),
194 body: private_message_content.content,
195 },
196 Some(message_secrets.serialized_context().to_vec()),
197 private_message_content.auth,
198 );
199 Ok(verifiable)
200 }
201
202 pub(crate) fn group_id(&self) -> &GroupId {
204 &self.group_id
205 }
206
207 pub(crate) fn epoch(&self) -> GroupEpoch {
209 self.epoch
210 }
211
212 pub(crate) fn content_type(&self) -> ContentType {
214 self.content_type
215 }
216
217 #[cfg(test)]
219 pub(crate) fn set_ciphertext(&mut self, ciphertext: Vec<u8>) {
220 self.ciphertext = ciphertext.into();
221 }
222}
223
224#[derive(Debug, Clone)]
247pub(crate) struct PrivateMessageContentIn {
248 pub(crate) content: FramedContentBodyIn,
253 pub(crate) auth: FramedContentAuthData,
254}
255
256#[cfg(any(feature = "test-utils", test))]
259impl From<PrivateMessageIn> for PrivateMessage {
260 fn from(value: PrivateMessageIn) -> Self {
261 Self {
262 group_id: value.group_id,
263 epoch: value.epoch,
264 content_type: value.content_type,
265 authenticated_data: value.authenticated_data,
266 encrypted_sender_data: value.encrypted_sender_data,
267 ciphertext: value.ciphertext,
268 }
269 }
270}
271
272#[cfg(any(feature = "test-utils", test))]
273impl From<PrivateMessage> for PrivateMessageIn {
274 fn from(value: PrivateMessage) -> Self {
275 Self {
276 group_id: value.group_id,
277 epoch: value.epoch,
278 content_type: value.content_type,
279 authenticated_data: value.authenticated_data,
280 encrypted_sender_data: value.encrypted_sender_data,
281 ciphertext: value.ciphertext,
282 }
283 }
284}