fix: Message index replay attack check

This commit is contained in:
Sorunome 2020-09-21 10:24:15 +02:00
parent 0ff971faa9
commit 70939a7c9c
No known key found for this signature in database
GPG Key ID: B19471D07FC9BE9C
2 changed files with 15 additions and 16 deletions

View File

@ -160,24 +160,18 @@ class Encryption {
final decryptResult = inboundGroupSession.inboundGroupSession final decryptResult = inboundGroupSession.inboundGroupSession
.decrypt(event.content['ciphertext']); .decrypt(event.content['ciphertext']);
canRequestSession = false; canRequestSession = false;
final messageIndexKey = event.eventId + // we can't have the key be an int, else json-serializing will fail, thus we need it to be a string
final messageIndexKey = 'key-' + decryptResult.message_index.toString();
final messageIndexValue = event.eventId +
'|' +
event.originServerTs.millisecondsSinceEpoch.toString(); event.originServerTs.millisecondsSinceEpoch.toString();
var haveIndex = inboundGroupSession.indexes.containsKey(messageIndexKey); var haveIndex = inboundGroupSession.indexes.containsKey(messageIndexKey);
if (haveIndex && if (haveIndex &&
inboundGroupSession.indexes[messageIndexKey] != inboundGroupSession.indexes[messageIndexKey] != messageIndexValue) {
decryptResult.message_index) {
// TODO: maybe clear outbound session, if it is ours // TODO: maybe clear outbound session, if it is ours
throw (DecryptError.CHANNEL_CORRUPTED); throw (DecryptError.CHANNEL_CORRUPTED);
} }
final existingIndex = inboundGroupSession.indexes.entries.firstWhere( inboundGroupSession.indexes[messageIndexKey] = messageIndexValue;
(e) => e.value == decryptResult.message_index,
orElse: () => null);
if (existingIndex != null && existingIndex.key != messageIndexKey) {
// TODO: maybe clear outbound session, if it is ours
throw (DecryptError.CHANNEL_CORRUPTED);
}
inboundGroupSession.indexes[messageIndexKey] =
decryptResult.message_index;
if (!haveIndex) { if (!haveIndex) {
// now we persist the udpated indexes into the database. // now we persist the udpated indexes into the database.
// the entry should always exist. In the case it doesn't, the following // the entry should always exist. In the case it doesn't, the following

View File

@ -26,7 +26,7 @@ import '../../src/utils/logs.dart';
class SessionKey { class SessionKey {
Map<String, dynamic> content; Map<String, dynamic> content;
Map<String, int> indexes; Map<String, String> indexes;
olm.InboundGroupSession inboundGroupSession; olm.InboundGroupSession inboundGroupSession;
final String key; final String key;
List<String> get forwardingCurve25519KeyChain => List<String> get forwardingCurve25519KeyChain =>
@ -60,9 +60,14 @@ class SessionKey {
Event.getMapFromPayload(dbEntry.senderClaimedKeys); Event.getMapFromPayload(dbEntry.senderClaimedKeys);
content = content =
parsedContent != null ? Map<String, dynamic>.from(parsedContent) : null; parsedContent != null ? Map<String, dynamic>.from(parsedContent) : null;
indexes = parsedIndexes != null // we need to try...catch as the map used to be <String, int> and that will throw an error.
? Map<String, int>.from(parsedIndexes) try {
: <String, int>{}; indexes = parsedIndexes != null
? Map<String, String>.from(parsedIndexes)
: <String, String>{};
} catch (e) {
indexes = <String, String>{};
}
roomId = dbEntry.roomId; roomId = dbEntry.roomId;
sessionId = dbEntry.sessionId; sessionId = dbEntry.sessionId;
_setSenderKey(dbEntry.senderKey); _setSenderKey(dbEntry.senderKey);