From b9adbb7d60bee6a09163c24678610206edc85f48 Mon Sep 17 00:00:00 2001 From: ariskotsomitopoulos Date: Wed, 18 May 2022 14:05:58 +0300 Subject: [PATCH] PR remarks --- .../crypto/replayattack/ReplayAttackTest.kt | 9 ++++++-- .../sdk/internal/crypto/MXOlmDevice.kt | 21 ++++++------------- .../sync/handler/room/RoomSyncHandler.kt | 8 +++---- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/replayattack/ReplayAttackTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/replayattack/ReplayAttackTest.kt index cb672f5e8d..69be4a3678 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/replayattack/ReplayAttackTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/replayattack/ReplayAttackTest.kt @@ -20,6 +20,7 @@ import androidx.test.filters.LargeTest import org.amshove.kluent.internal.assertFailsWith import org.junit.Assert import org.junit.Assert.assertEquals +import org.junit.Assert.fail import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith @@ -101,8 +102,12 @@ class ReplayAttackTest : InstrumentedTest { val timelineId = "timelineId" // Lets decrypt the original event aliceSession.cryptoService().decryptEvent(sentEvents[0].root, timelineId) - // Lets try to decrypt the same event - aliceSession.cryptoService().decryptEvent(sentEvents[0].root, timelineId) + try { + // Lets try to decrypt the same event + aliceSession.cryptoService().decryptEvent(sentEvents[0].root, timelineId) + } catch (ex: Throwable) { + fail("Shouldn't throw a decryption error for same event") + } } cryptoTestData.cleanUp(testHelper) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt index 16e6bb173d..87384b3fe2 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt @@ -96,10 +96,9 @@ internal class MXOlmDevice @Inject constructor( // So, store these message indexes per timeline id. // // The first level keys are timeline ids. - // The second level keys are strings of form "||" - private val inboundGroupSessionMessageIndexes: MutableMap> = HashMap() - - private val replayAttackMap: MutableMap = HashMap() + // The second level values is a Map that represents: + // "|||" --> eventId + private val inboundGroupSessionMessageIndexes: MutableMap> = HashMap() init { // Retrieve the account from the store @@ -798,15 +797,14 @@ internal class MXOlmDevice @Inject constructor( Timber.tag(loggerTag.value).d("## decryptGroupMessage() mIndex: ${decryptResult.mIndex}") if (timeline?.isNotBlank() == true) { - val timelineSet = inboundGroupSessionMessageIndexes.getOrPut(timeline) { mutableSetOf() } - if (timelineSet.contains(messageIndexKey) && messageIndexKey.alreadyUsed(eventId)) { + val replayAttackMap = inboundGroupSessionMessageIndexes.getOrPut(timeline) { mutableMapOf() } + if (replayAttackMap.contains(messageIndexKey) && replayAttackMap[messageIndexKey] != eventId) { val reason = String.format(MXCryptoError.DUPLICATE_MESSAGE_INDEX_REASON, decryptResult.mIndex) Timber.tag(loggerTag.value).e("## decryptGroupMessage() timelineId=$timeline: $reason") throw MXCryptoError.Base(MXCryptoError.ErrorType.DUPLICATED_MESSAGE_INDEX, reason) } - timelineSet.add(messageIndexKey) + replayAttackMap[messageIndexKey] = eventId } - replayAttackMap[messageIndexKey] = eventId inboundGroupSessionStore.storeInBoundGroupSession(sessionHolder, sessionId, senderKey) val payload = try { val adapter = MoshiProvider.providesMoshi().adapter(JSON_DICT_PARAMETERIZED_TYPE) @@ -825,13 +823,6 @@ internal class MXOlmDevice @Inject constructor( ) } - /** - * Determines whether or not the messageKey has already been used to decrypt another eventId - */ - private fun String.alreadyUsed(eventId: String): Boolean { - return replayAttackMap[this] != null && replayAttackMap[this] != eventId - } - /** * Reset replay attack data for the given timeline. * diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt index 879bde1862..cf916dc907 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt @@ -25,7 +25,6 @@ import org.matrix.android.sdk.api.session.crypto.MXCryptoError import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType -import org.matrix.android.sdk.api.session.events.model.isThread import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService import org.matrix.android.sdk.api.session.initsync.InitSyncStep @@ -521,7 +520,7 @@ internal class RoomSyncHandler @Inject constructor( private fun decryptIfNeeded(event: Event, roomId: String) { try { - val timelineId = generateTimelineId(roomId, event) + val timelineId = generateTimelineId(roomId) // Event from sync does not have roomId, so add it to the event first // note: runBlocking should be used here while we are in realm single thread executor, to avoid thread switching val result = runBlocking { cryptoService.decryptEvent(event.copy(roomId = roomId), timelineId) } @@ -539,9 +538,8 @@ internal class RoomSyncHandler @Inject constructor( } } - private fun generateTimelineId(roomId: String, event: Event): String { - val threadIndicator = if (event.isThread()) "_thread_" else "_" - return "${RoomSyncHandler::class.java.simpleName}$threadIndicator$roomId" + private fun generateTimelineId(roomId: String): String { + return "${RoomSyncHandler::class.java.simpleName}$roomId" } data class EphemeralResult(