Fix handling when attempting to decrypt with a session that isn't found

There were two discrepancies between the logic here and the original
logic of libsignal-protocol-java.

First, if the session record had an uninitialized active session, in
Java this would still attempt decryption with the old session states,
but Rust would stop immediately without trying the old states. [I am
not sure if this ever happens but it could possibly occur due to use
of archiveCurrentState]

Secondly, we returned the wrong error condition. We treated lack of a
sender chain as an invalid state (effectively an internal error) but
Java treats it as an invalid message, which makes sense in so far as
it is a message which we are unable to process with the information we
have available. This wrong error type led to an unexpected exception
being thrown in Android.
This commit is contained in:
Jack Lloyd
2021-01-07 14:08:50 -05:00
parent 239534e062
commit e8b4474cb9

View File

@@ -243,21 +243,23 @@ fn decrypt_message_with_record<R: Rng + CryptoRng>(
ciphertext: &SignalMessage,
csprng: &mut R,
) -> Result<Vec<u8>> {
let mut current_state = record.session_state()?.clone();
if let Ok(current_state) = record.session_state() {
let mut current_state = current_state.clone();
let result = decrypt_message_with_state(&mut current_state, ciphertext, csprng);
let result = decrypt_message_with_state(&mut current_state, ciphertext, csprng);
match result {
Ok(ptext) => {
record.set_session_state(current_state)?; // update the state
return Ok(ptext);
match result {
Ok(ptext) => {
record.set_session_state(current_state)?; // update the state
return Ok(ptext);
}
Err(SignalProtocolError::DuplicatedMessage(_, _)) => {
return result;
}
Err(_) => {}
}
Err(SignalProtocolError::DuplicatedMessage(_, _)) => {
return result;
}
Err(_) => {}
}
// Try some old sessions:
let mut updated_session = None;
for (idx, previous) in record.previous_session_states()?.enumerate() {
@@ -293,7 +295,9 @@ fn decrypt_message_with_state<R: Rng + CryptoRng>(
csprng: &mut R,
) -> Result<Vec<u8>> {
if !state.has_sender_chain()? {
return Err(SignalProtocolError::InvalidSessionStructure);
return Err(SignalProtocolError::InvalidMessage(
"No session available to decrypt",
));
}
let ciphertext_version = ciphertext.message_version() as u32;