diff --git a/matrix_sdk_crypto/src/error.rs b/matrix_sdk_crypto/src/error.rs index 6d9aacdc..24d68f1c 100644 --- a/matrix_sdk_crypto/src/error.rs +++ b/matrix_sdk_crypto/src/error.rs @@ -47,9 +47,16 @@ pub enum OlmError { Store(#[from] CryptoStoreError), /// The session with a device has become corrupted. - #[error("decryption failed likely because an Olm from {0} with sender key {1} was wedged")] + #[error( + "decryption failed likely because an Olm session from {0} with sender key {1} was wedged" + )] SessionWedged(UserId, String), + /// An Olm message got replayed while the Olm ratchet has already moved + /// forward. + #[error("decryption failed because an Olm message from {0} with sender key {1} was replayed")] + ReplayedMessage(UserId, String), + /// Encryption failed because the device does not have a valid Olm session /// with us. #[error( diff --git a/matrix_sdk_crypto/src/olm/account.rs b/matrix_sdk_crypto/src/olm/account.rs index 5fce59d5..1861c254 100644 --- a/matrix_sdk_crypto/src/olm/account.rs +++ b/matrix_sdk_crypto/src/olm/account.rs @@ -131,7 +131,10 @@ impl Account { .chain(&[message_type]) .chain(&ciphertext.body); - let hash = encode(sha.finalize().as_slice()); + let message_hash = OlmMessageHash { + sender_key: content.sender_key.clone(), + hash: encode(sha.finalize().as_slice()), + }; // Create a OlmMessage from the ciphertext and the type. let message = @@ -139,18 +142,26 @@ impl Account { .map_err(|_| EventError::UnsupportedOlmType)?; // Decrypt the OlmMessage and get a Ruma event out of it. - let (session, event, signing_key) = self + let (session, event, signing_key) = match self .decrypt_olm_message(&event.sender, &content.sender_key, message) - .await?; + .await + { + Ok(d) => d, + Err(OlmError::SessionWedged(user_id, sender_key)) => { + if self.store.is_message_known(&message_hash).await? { + return Err(OlmError::ReplayedMessage(user_id, sender_key)); + } else { + return Err(OlmError::SessionWedged(user_id, sender_key)); + } + } + Err(e) => return Err(e.into()), + }; debug!("Decrypted a to-device event {:?}", event); Ok(OlmDecryptionInfo { session, - message_hash: OlmMessageHash { - hash, - sender_key: content.sender_key.clone(), - }, + message_hash, event, signing_key, sender_key: content.sender_key.clone(),