Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/aris/crypto replay attack #6077

Merged
merged 11 commits into from
May 25, 2022

Conversation

ariskotsomitopoulos
Copy link
Contributor

This PR aims to reduce the UISI DUPLICATED_MESSAGE_INDEX.

  • With respect to this issue, the code is enhanced to check whether a given key (ratcheted to some particular index) was used to decrypt more than one different event. Two events are considered different if their eventId differs
  • Tests are added to ensure that decrypting the same event with the same message index will prevent UISI
  • Adds a custom timelineId when decryption is called from RoomSyncHandler

@github-actions
Copy link

github-actions bot commented May 17, 2022

Unit Test Results

124 files  ±0  124 suites  ±0   2m 3s ⏱️ -7s
217 tests ±0  217 ✔️ ±0  0 💤 ±0  0 ±0 
714 runs  ±0  714 ✔️ ±0  0 💤 ±0  0 ±0 

Results for commit 85f3592. ± Comparison against base commit 4094a66.

♻️ This comment has been updated with latest results.

// 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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd do a try {.. decrypt } catch (error) { fail("Shouldn't throw a decryption error for same event") }

Timber.tag(loggerTag.value).d("## decryptGroupMessage() eventId: $eventId")
Timber.tag(loggerTag.value).d("## decryptGroupMessage() mIndex: ${decryptResult.mIndex}")

if (timeline?.isNotBlank() == true) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we might need some concurrency issues when accessing the timelineset. Maybe use a mutex for that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its the way the current code works, I will have a look

}
timelineSet.add(messageIndexKey)
}
replayAttackMap[messageIndexKey] = eventId
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels strange to have the replayAttackMap global and shared by everyone.
I would have made inboundGroupSessionMessageIndexes a Map<timelineId, replayAttackMap>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeap, its a good point will refactor it a bit

@@ -537,6 +539,11 @@ internal class RoomSyncHandler @Inject constructor(
}
}

private fun generateTimelineId(roomId: String, event: Event): String {
val threadIndicator = if (event.isThread()) "_thread_" else "_"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we make a different timeline id between thread and normal?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the fact that it's technically a different timeline, that can contain the same events with the main timeline in parallel. But maybe re-using the main timelineId is enough, will update it

}

val messageIndexKey = senderKey + "|" + sessionId + "|" + roomId + "|" + decryptResult.mIndex
Timber.tag(loggerTag.value).d("##########################################################")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reduce log visibility to verbose!

Copy link
Member

@BillCarsonFr BillCarsonFr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, could you just reduce the log visibility to verbose


// Alice will send a message
val sentEvents = testHelper.sendTextMessage(aliceRoomPOV, "Hello I will be decrypted twice", 1)
Assert.assertTrue("Message should be sent", sentEvents.size == 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be better to use assertEqual for better test failure report (for instance "expected 1, actual 2", rather than "expected true, actual false" when using assertTrue

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

@@ -537,6 +538,10 @@ internal class RoomSyncHandler @Inject constructor(
}
}

private fun generateTimelineId(roomId: String): String {
return "${RoomSyncHandler::class.java.simpleName}$roomId"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange to use RoomSyncHandler::class.java.simpleName here, can't it be a hard-coded prefix?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it doesn't really matters. I hardcoded the prefix

@BillCarsonFr BillCarsonFr merged commit 52eb48d into develop May 25, 2022
@BillCarsonFr BillCarsonFr deleted the feature/aris/crypto_replay_attack branch May 25, 2022 14:20
@github-actions
Copy link

Matrix SDK

Integration Tests Results:

  • [org.matrix.android.sdk.session]
    = passed=20 failures=0 errors=0 skipped=3
  • [org.matrix.android.sdk.account]
    = passed=3 failures=0 errors=0 skipped=2
  • [org.matrix.android.sdk.internal]
    = passed=22 failures=1 errors=0 skipped=1
  • [org.matrix.android.sdk.ordering]
    = passed=16 failures=0 errors=0 skipped=0
  • [org.matrix.android.sdk.PermalinkParserTest]
    = passed=2 failures=0 errors=0 skipped=0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants