crypto: Add some more debug logs.

master
Damir Jelić 2020-04-22 12:54:49 +02:00
parent cb6e43b340
commit 4576e93663
1 changed files with 71 additions and 5 deletions

View File

@ -655,11 +655,13 @@ impl OlmMachine {
async fn try_decrypt_olm_event( async fn try_decrypt_olm_event(
&mut self, &mut self,
sender: &str,
sender_key: &str, sender_key: &str,
message: &OlmMessage, message: &OlmMessage,
) -> Result<Option<String>> { ) -> Result<Option<String>> {
let s = self.store.get_sessions(sender_key).await?; let s = self.store.get_sessions(sender_key).await?;
/// We don't have any existing sessions, return early.
let sessions = if let Some(s) = s { let sessions = if let Some(s) = s {
s s
} else { } else {
@ -669,8 +671,11 @@ impl OlmMachine {
for session in &mut *sessions.lock().await { for session in &mut *sessions.lock().await {
let mut matches = false; let mut matches = false;
// If this is a pre-key message check if it was encrypted for our
// session, if it wasn't decryption will fail so no need to try.
if let OlmMessage::PreKey(m) = &message { if let OlmMessage::PreKey(m) = &message {
matches = session.matches(sender_key, m.clone()).await?; matches = session.matches(sender_key, m.clone()).await?;
if !matches { if !matches {
continue; continue;
} }
@ -679,10 +684,20 @@ impl OlmMachine {
let ret = session.decrypt(message.clone()).await; let ret = session.decrypt(message.clone()).await;
if let Ok(p) = ret { if let Ok(p) = ret {
// Decryption was successful, save the new ratchet state of the
// session.
self.store.save_session(session.clone()).await?; self.store.save_session(session.clone()).await?;
return Ok(Some(p)); return Ok(Some(p));
} else { } else {
// Decryption failed with a matching session, the session is
// likely wedged and needs to be rotated.
if matches { if matches {
warn!(
"Found a matching Olm session yet decryption failed
for sender {} and sender_key {}",
sender, sender_key
);
return Err(OlmError::SessionWedged); return Err(OlmError::SessionWedged);
} }
} }
@ -693,31 +708,74 @@ impl OlmMachine {
async fn decrypt_olm_message( async fn decrypt_olm_message(
&mut self, &mut self,
_sender: &str, sender: &str,
sender_key: &str, sender_key: &str,
message: OlmMessage, message: OlmMessage,
) -> Result<EventResult<ToDeviceEvent>> { ) -> Result<EventResult<ToDeviceEvent>> {
let plaintext = if let Some(p) = self.try_decrypt_olm_event(sender_key, &message).await? { // First try to decrypt using an existing session.
let plaintext = if let Some(p) = self
.try_decrypt_olm_event(sender, sender_key, &message)
.await?
{
// Decryption succeeded, destructure the plaintext out of the
// Option.
p p
} else { } else {
// Decryption failed with every known session, let's try to create a
// new session.
let mut session = match &message { let mut session = match &message {
OlmMessage::Message(_) => return Err(OlmError::SessionWedged), /// A new session can only be created using a pre-key message,
/// return with an error if it isn't one.
OlmMessage::Message(_) => {
warn!(
"Failed to decrypt a non-pre-key message with all
available sessions {} {}",
sender, sender_key
);
return Err(OlmError::SessionWedged);
}
OlmMessage::PreKey(m) => { OlmMessage::PreKey(m) => {
let session = self /// Create the new session.
let session = match self
.account .account
.create_inbound_session(sender_key, m.clone()) .create_inbound_session(sender_key, m.clone())
.await?; .await
{
Ok(s) => s,
Err(e) => {
warn!(
"Failed to create a new Olm session for {} {}
from a prekey message: {}",
sender, sender_key, e
);
return Err(OlmError::SessionWedged);
}
};
/// Save the account since we remove the one-time key that
/// was used to create this session.
self.store.save_account(self.account.clone()).await?; self.store.save_account(self.account.clone()).await?;
session session
} }
}; };
/// Decrypt our message, this shouldn't fail since we're using a
/// newly created Session.
let plaintext = session.decrypt(message).await?; let plaintext = session.decrypt(message).await?;
/// Save the new ratcheted state of the session.
self.store.save_session(session).await?; self.store.save_session(session).await?;
plaintext plaintext
}; };
trace!("Successfully decrypted a Olm message: {}", plaintext); trace!("Successfully decrypted a Olm message: {}", plaintext);
// TODO get the recipient, recipient_keys, and keys out of here
// separately.
// TODO verify that the recipient, recipient_keys match with us.
// TODO verify that the sender in the decrypted event matches the one in
// the unencrypted one.
Ok(serde_json::from_str::<EventResult<ToDeviceEvent>>( Ok(serde_json::from_str::<EventResult<ToDeviceEvent>>(
&plaintext, &plaintext,
)?) )?)
@ -749,19 +807,27 @@ impl OlmMachine {
let own_key = identity_keys.curve25519(); let own_key = identity_keys.curve25519();
let own_ciphertext = content.ciphertext.get(own_key); let own_ciphertext = content.ciphertext.get(own_key);
// Try to find a ciphertext that was meant for our device.
if let Some(ciphertext) = own_ciphertext { if let Some(ciphertext) = own_ciphertext {
let message_type: u8 = ciphertext let message_type: u8 = ciphertext
.message_type .message_type
.try_into() .try_into()
.map_err(|_| OlmError::UnsupportedOlmType)?; .map_err(|_| OlmError::UnsupportedOlmType)?;
// Create a OlmMessage from the ciphertext and the type.
let message = let message =
OlmMessage::from_type_and_ciphertext(message_type.into(), ciphertext.body.clone()) OlmMessage::from_type_and_ciphertext(message_type.into(), ciphertext.body.clone())
.map_err(|_| OlmError::UnsupportedOlmType)?; .map_err(|_| OlmError::UnsupportedOlmType)?;
// Decrypt the OlmMessage and get a Ruma event out of it.
let mut decrypted_event = self let mut decrypted_event = self
.decrypt_olm_message(&event.sender.to_string(), &content.sender_key, message) .decrypt_olm_message(&event.sender.to_string(), &content.sender_key, message)
.await?; .await?;
debug!("Decrypted a to-device event {:?}", decrypted_event); debug!("Decrypted a to-device event {:?}", decrypted_event);
// Handle the decrypted event, e.g. fetch out megolm sessions out of
// the event.
self.handle_decrypted_to_device_event(&content.sender_key, &mut decrypted_event) self.handle_decrypted_to_device_event(&content.sender_key, &mut decrypted_event)
.await?; .await?;