Skip to content

Commit 4ecf5eb

Browse files
committed
Add debug logs for AEAD error debugging - INTERNAL BUILDS ONLY
1 parent 02595f6 commit 4ecf5eb

2 files changed

Lines changed: 117 additions & 5 deletions

File tree

openmls/src/framing/private_message.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use openmls_traits::types::HashType;
12
use openmls_traits::{crypto::OpenMlsCrypto, random::OpenMlsRand, types::Ciphersuite};
23
use std::io::Write;
34
use tls_codec::{Serialize, Size, TlsSerialize, TlsSize};
@@ -242,6 +243,36 @@ impl PrivateMessage {
242243
&sender_data_nonce,
243244
)
244245
.map_err(LibraryError::unexpected_crypto_error)?;
246+
247+
// XMTP: Debug logging to correlate AEAD failures between sender and receiver.
248+
// We avoid logging raw secrets and instead log short, reproducible tags derived
249+
// from on-the-wire values (ciphertext and sender-data AAD).
250+
// Still for internal debug Builds only!
251+
let ciphertext_tag = crypto
252+
.hash(HashType::Sha2_256, &ciphertext)
253+
.unwrap_or_default();
254+
let sender_data_aad_tag = crypto
255+
.hash(HashType::Sha2_256, &mls_sender_data_aad_bytes)
256+
.unwrap_or_default();
257+
258+
// Truncate tags to the first 8 bytes for compact logging.
259+
let ciphertext_tag_short = &ciphertext_tag[..ciphertext_tag.len().min(8)];
260+
let sender_data_aad_tag_short = &sender_data_aad_tag[..sender_data_aad_tag.len().min(8)];
261+
262+
log::info!(
263+
"XMTP DEBUG LOGS: PrivateMessage handshake send: \
264+
group_id={:?}, epoch={:?}, sender={:?}, content_type={:?}, secret_type={:?}, \
265+
generation={}, reuse_guard={:x?}, ciphertext_tag={:x?}, sender_data_aad_tag={:x?}",
266+
header.group_id,
267+
header.epoch,
268+
header.sender,
269+
public_message.content().content_type(),
270+
secret_type,
271+
generation,
272+
reuse_guard,
273+
ciphertext_tag_short,
274+
sender_data_aad_tag_short,
275+
);
245276
Ok(PrivateMessage {
246277
group_id: header.group_id.clone(),
247278
epoch: header.epoch,

openmls/src/framing/private_message_in.rs

Lines changed: 86 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use openmls_traits::crypto::OpenMlsCrypto;
22
use openmls_traits::types::Ciphersuite;
3+
use openmls_traits::types::HashType;
34
use tls_codec::{
45
Deserialize, Serialize, TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize,
56
};
@@ -70,6 +71,21 @@ impl PrivateMessageIn {
7071
let mls_sender_data_aad_bytes = mls_sender_data_aad
7172
.tls_serialize_detached()
7273
.map_err(LibraryError::missing_bound_check)?;
74+
75+
// XMTP: Debug logging to correlate AEAD failures between sender and receiver.
76+
// We avoid logging raw secrets and instead log short, reproducible tags derived
77+
// from on-the-wire values (ciphertext and sender-data AAD).
78+
// Still for internal debug builds only!
79+
let ciphertext_tag = crypto
80+
.hash(ciphersuite.hash_algorithm(), self.ciphertext.as_slice())
81+
.unwrap_or_default();
82+
let sender_data_aad_tag = crypto
83+
.hash(ciphersuite.hash_algorithm(), &mls_sender_data_aad_bytes)
84+
.unwrap_or_default();
85+
86+
let ciphertext_tag_short = &ciphertext_tag[..ciphertext_tag.len().min(8)];
87+
let sender_data_aad_tag_short = &sender_data_aad_tag[..sender_data_aad_tag.len().min(8)];
88+
7389
// Decrypt sender data
7490
log_crypto!(
7591
trace,
@@ -84,12 +100,35 @@ impl PrivateMessageIn {
84100
&sender_data_nonce,
85101
)
86102
.map_err(|_| {
87-
log::error!("Sender data decryption error");
103+
log::error!(
104+
"XMTP DEBUG LOGS: Sender data decryption error. \
105+
group_id={:?}, epoch={:?}, content_type={:?}, \
106+
ciphertext_tag={:x?}, sender_data_aad_tag={:x?}",
107+
self.group_id,
108+
self.epoch,
109+
self.content_type,
110+
ciphertext_tag_short,
111+
sender_data_aad_tag_short,
112+
);
88113
MessageDecryptionError::AeadError
89114
})?;
90115
log::trace!(" Successfully decrypted sender data.");
91-
MlsSenderData::tls_deserialize(&mut sender_data_bytes.as_slice())
92-
.map_err(|_| MessageDecryptionError::MalformedContent)
116+
let sender_data = MlsSenderData::tls_deserialize(&mut sender_data_bytes.as_slice())
117+
.map_err(|_| MessageDecryptionError::MalformedContent)?;
118+
119+
log::info!(
120+
"XMTP DEBUG LOGS: PrivateMessage handshake recv (sender data): \
121+
group_id={:?}, epoch={:?}, leaf_index={:?}, generation={}, \
122+
ciphertext_tag={:x?}, sender_data_aad_tag={:x?}",
123+
self.group_id,
124+
self.epoch,
125+
sender_data.leaf_index,
126+
sender_data.generation,
127+
ciphertext_tag_short,
128+
sender_data_aad_tag_short,
129+
);
130+
131+
Ok(sender_data)
93132
}
94133

95134
/// Decrypt this [`PrivateMessage`] and return the
@@ -110,13 +149,32 @@ impl PrivateMessageIn {
110149
}
111150
.tls_serialize_detached()
112151
.map_err(LibraryError::missing_bound_check)?;
152+
153+
// --- XMTP: derive short tags to correlate AEAD failures with libxmtp logs ---
154+
// These mirror what you’re already doing in sender_data().
155+
let ciphertext_tag = crypto
156+
.hash(HashType::Sha2_256, self.ciphertext.as_slice())
157+
.unwrap_or_default();
158+
let content_aad_tag = crypto
159+
.hash(HashType::Sha2_256, &private_message_content_aad_bytes)
160+
.unwrap_or_default();
161+
162+
let ciphertext_tag_short = &ciphertext_tag[..ciphertext_tag.len().min(8)];
163+
let content_aad_tag_short = &content_aad_tag[..content_aad_tag.len().min(8)];
164+
// --- end XMTP tags ---
165+
113166
// Decrypt payload
114167
log_crypto!(
115168
trace,
116169
"Decryption key for private message: {ratchet_key:x?}"
117170
);
118-
log_crypto!(trace, "Decryption of private message private_message_content_aad_bytes: {private_message_content_aad_bytes:x?} - ratchet_nonce: {ratchet_nonce:x?}");
171+
log_crypto!(
172+
trace,
173+
"Decryption of private message private_message_content_aad_bytes: \
174+
{private_message_content_aad_bytes:x?} - ratchet_nonce: {ratchet_nonce:x?}"
175+
);
119176
log::trace!("Decrypting ciphertext {:x?}", self.ciphertext);
177+
120178
let private_message_content_bytes = ratchet_key
121179
.aead_open(
122180
crypto,
@@ -125,15 +183,27 @@ impl PrivateMessageIn {
125183
ratchet_nonce,
126184
)
127185
.map_err(|_| {
128-
log::error!(" Ciphertext decryption error");
186+
// --- XMTP: upgraded AEAD failure logging for *content* ---
187+
log::error!(
188+
"XMTP DEBUG LOGS:Ciphertext decryption error. \
189+
stage=content, group_id={:?}, epoch={:?}, content_type={:?}, \
190+
ciphertext_tag={:x?}, content_aad_tag={:x?}",
191+
self.group_id,
192+
self.epoch,
193+
self.content_type,
194+
ciphertext_tag_short,
195+
content_aad_tag_short,
196+
);
129197
debug_assert!(false, "Ciphertext decryption failed");
130198
MessageDecryptionError::AeadError
131199
})?;
200+
132201
log_content!(
133202
trace,
134203
" Successfully decrypted PublicMessage bytes: {:x?}",
135204
private_message_content_bytes
136205
);
206+
137207
deserialize_ciphertext_content(
138208
&mut private_message_content_bytes.as_slice(),
139209
self.content_type(),
@@ -174,6 +244,17 @@ impl PrivateMessageIn {
174244
})?;
175245
// Prepare the nonce by xoring with the reuse guard.
176246
let prepared_nonce = ratchet_nonce.xor_with_reuse_guard(&sender_data.reuse_guard);
247+
248+
log::info!(
249+
"XMTP DEBUG LOGS: PrivateMessage content recv (before decrypt): \
250+
group_id={:?}, epoch={:?}, leaf_index={:?}, generation={}, reuse_guard={:x?}",
251+
self.group_id,
252+
self.epoch,
253+
sender_index,
254+
sender_data.generation,
255+
sender_data.reuse_guard,
256+
);
257+
177258
let private_message_content = self.decrypt(crypto, ratchet_key, &prepared_nonce)?;
178259

179260
// Extract sender. The sender type is always of type Member for PrivateMessage.

0 commit comments

Comments
 (0)