refactor: Olm Exceptions

This commit is contained in:
Christian Pauly 2021-01-07 12:34:17 +01:00
parent 33500012b2
commit 39b776716c
4 changed files with 49 additions and 24 deletions

View File

@ -155,7 +155,7 @@ class Encryption {
var canRequestSession = false;
try {
if (event.content['algorithm'] != AlgorithmTypes.megolmV1AesSha2) {
throw (DecryptError.UNKNOWN_ALGORITHM);
throw DecryptException(DecryptException.unknownAlgorithm);
}
final String sessionId = event.content['session_id'];
final String senderKey = event.content['sender_key'];
@ -163,10 +163,11 @@ class Encryption {
keyManager.getInboundGroupSession(roomId, sessionId, senderKey);
if (inboundGroupSession == null) {
canRequestSession = true;
throw (DecryptError.UNKNOWN_SESSION);
throw DecryptException(DecryptException.unknownSession);
}
// decrypt errors here may mean we have a bad session key - others might have a better one
canRequestSession = true;
final decryptResult = inboundGroupSession.inboundGroupSession
.decrypt(event.content['ciphertext']);
canRequestSession = false;
@ -179,7 +180,7 @@ class Encryption {
if (haveIndex &&
inboundGroupSession.indexes[messageIndexKey] != messageIndexValue) {
Logs().e('[Decrypt] Could not decrypt due to a corrupted session.');
throw (DecryptError.CHANNEL_CORRUPTED);
throw DecryptException(DecryptException.channelCorrupted);
}
inboundGroupSession.indexes[messageIndexKey] = messageIndexValue;
if (!haveIndex) {
@ -197,7 +198,7 @@ class Encryption {
} catch (exception) {
// alright, if this was actually by our own outbound group session, we might as well clear it
if (client.enableE2eeRecovery &&
exception != DecryptError.UNKNOWN_SESSION &&
exception.toString() != DecryptException.unknownSession &&
(keyManager
.getOutboundGroupSession(roomId)
?.outboundGroupSession
@ -383,11 +384,30 @@ class Encryption {
}
}
abstract class DecryptError {
static const String NOT_ENABLED = 'Encryption is not enabled in your client.';
static const String UNKNOWN_ALGORITHM = 'Unknown encryption algorithm.';
static const String UNKNOWN_SESSION =
class DecryptException implements Exception {
String cause;
String libolmMessage;
DecryptException(this.cause, [this.libolmMessage]);
@override
String toString() => cause;
static const String notEnabled = 'Encryption is not enabled in your client.';
static const String unknownAlgorithm = 'Unknown encryption algorithm.';
static const String unknownSession =
'The sender has not sent us the session key.';
static const String CHANNEL_CORRUPTED =
static const String channelCorrupted =
'The secure channel with the sender was corrupted.';
static const String unableToDecryptWithAnyOlmSession =
'Unable to decrypt with any existing OLM session';
static const String senderDoesntMatch =
"Message was decrypted but sender doesn't match";
static const String recipientDoesntMatch =
"Message was decrypted but recipient doesn't match";
static const String ownFingerprintDoesntMatch =
"Message was decrypted but own fingerprint Key doesn't match";
static const String isntSentForThisDevice =
"The message isn't sent for this device";
static const String unknownMessageType = 'Unknown message type';
static const String decryptionFailed = 'Decryption failed';
}

View File

@ -248,17 +248,17 @@ class OlmManager {
return event;
}
if (event.content['algorithm'] != AlgorithmTypes.olmV1Curve25519AesSha2) {
throw ('Unknown algorithm: ${event.content['algorithm']}');
throw DecryptException(DecryptException.unknownAlgorithm);
}
if (!event.content['ciphertext'].containsKey(identityKey)) {
throw ("The message isn't sent for this device");
throw DecryptException(DecryptException.isntSentForThisDevice);
}
String plaintext;
final String senderKey = event.content['sender_key'];
final String body = event.content['ciphertext'][identityKey]['body'];
final int type = event.content['ciphertext'][identityKey]['type'];
if (type != 0 && type != 1) {
throw ('Unknown message type');
throw DecryptException(DecryptException.unknownMessageType);
}
final device = client.userDeviceKeys[event.sender]?.deviceKeys?.values
?.firstWhere((d) => d.curve25519Key == senderKey, orElse: () => null);
@ -280,7 +280,12 @@ class OlmManager {
if (existingSessions != null) {
for (var session in existingSessions) {
if (type == 0 && session.session.matches_inbound(body) == true) {
try {
plaintext = session.session.decrypt(type, body);
} catch (e) {
throw DecryptException(
DecryptException.decryptionFailed, e.toString());
}
updateSessionUsage(session);
break;
} else if (type == 1) {
@ -295,7 +300,7 @@ class OlmManager {
}
}
if (plaintext == null && type != 0) {
throw ('Unable to decrypt with any existing OLM session');
throw DecryptException(DecryptException.unableToDecryptWithAnyOlmSession);
}
if (plaintext == null) {
@ -313,24 +318,24 @@ class OlmManager {
lastReceived: DateTime.now(),
)));
updateSessionUsage();
} catch (_) {
} catch (e) {
newSession?.free();
rethrow;
throw DecryptException(DecryptException.decryptionFailed, e.toString());
}
}
final Map<String, dynamic> plainContent = json.decode(plaintext);
if (plainContent.containsKey('sender') &&
plainContent['sender'] != event.sender) {
throw ("Message was decrypted but sender doesn't match");
throw DecryptException(DecryptException.senderDoesntMatch);
}
if (plainContent.containsKey('recipient') &&
plainContent['recipient'] != client.userID) {
throw ("Message was decrypted but recipient doesn't match");
throw DecryptException(DecryptException.recipientDoesntMatch);
}
if (plainContent['recipient_keys'] is Map &&
plainContent['recipient_keys']['ed25519'] is String &&
plainContent['recipient_keys']['ed25519'] != fingerprintKey) {
throw ("Message was decrypted but own fingerprint Key doesn't match");
throw DecryptException(DecryptException.ownFingerprintDoesntMatch);
}
return ToDeviceEvent(
content: plainContent['content'],

View File

@ -43,16 +43,16 @@ abstract class EventLocalizations {
case MessageTypes.BadEncrypted:
String errorText;
switch (event.body) {
case DecryptError.CHANNEL_CORRUPTED:
case DecryptException.channelCorrupted:
errorText = i18n.channelCorruptedDecryptError + '.';
break;
case DecryptError.NOT_ENABLED:
case DecryptException.notEnabled:
errorText = i18n.encryptionNotEnabled + '.';
break;
case DecryptError.UNKNOWN_ALGORITHM:
case DecryptException.unknownAlgorithm:
errorText = i18n.unknownEncryptionAlgorithm + '.';
break;
case DecryptError.UNKNOWN_SESSION:
case DecryptException.unknownSession:
errorText = i18n.noPermission + '.';
break;
default:

View File

@ -302,7 +302,7 @@ void main() {
'status': 2,
'content': json.encode({
'msgtype': 'm.bad.encrypted',
'body': DecryptError.UNKNOWN_SESSION,
'body': DecryptException.unknownSession,
'can_request_session': true,
'algorithm': AlgorithmTypes.megolmV1AesSha2,
'ciphertext': 'AwgAEnACgAkLmt6qF84IK++J7UDH2Za1YVchHyprqTqsg...',