Send with held code on key requests

This commit is contained in:
Valere 2020-06-03 17:58:26 +02:00 committed by Benoit Marty
parent cdb1b8d8f8
commit 3fa2647e92
4 changed files with 65 additions and 11 deletions

View File

@ -19,6 +19,8 @@ package im.vector.matrix.android.internal.crypto.gossiping
import android.util.Log
import androidx.test.ext.junit.runners.AndroidJUnit4
import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.api.NoOpMatrixCallback
import im.vector.matrix.android.api.extensions.tryThis
import im.vector.matrix.android.api.session.crypto.MXCryptoError
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toModel
@ -128,9 +130,8 @@ class WithHeldTests : InstrumentedTest {
mTestHelper.signOutAndClose(bobUnverifiedSession)
}
@Test
fun test_WithHeldNoOlm() {
fun test_WithHeldNoOlm() {
val testData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = testData.firstSession
val bobSession = testData.secondSession!!
@ -148,8 +149,6 @@ class WithHeldTests : InstrumentedTest {
val roomAlicePov = aliceSession.getRoom(testData.roomId)!!
// can we force one-time key shortage??
val eventId = mTestHelper.sendTextMessage(roomAlicePov, "first message", 1).first().eventId
// await for bob session to get the message
@ -176,7 +175,7 @@ class WithHeldTests : InstrumentedTest {
val sessionId = eventBobPOV!!.root.content.toModel<EncryptedEventContent>()!!.sessionId!!
val chainIndex = aliceSession.cryptoService().getSharedWithInfo(testData.roomId, sessionId).getObject(bobSession.myUserId, bobSession.sessionParams.credentials.deviceId)
Assert.assertEquals("Alice should have marked bob's device for this session", 0, chainIndex)
Assert.assertEquals("Alice should have marked bob's device for this session", 0, chainIndex)
// Add a new device for bob
aliceInterceptor.clearRules()
@ -194,10 +193,55 @@ class WithHeldTests : InstrumentedTest {
val chainIndex2 = aliceSession.cryptoService().getSharedWithInfo(testData.roomId, sessionId).getObject(bobSecondSession.myUserId, bobSecondSession.sessionParams.credentials.deviceId)
Assert.assertEquals("Alice should have marked bob's device for this session", 1, chainIndex2)
Assert.assertEquals("Alice should have marked bob's device for this session", 1, chainIndex2)
mTestHelper.signOutAndClose(bobSecondSession)
aliceInterceptor.clearRules()
testData.cleanUp(mTestHelper)
mTestHelper.signOutAndClose(bobSecondSession)
}
@Test
fun test_WithHeldKeyRequest() {
val testData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = testData.firstSession
val bobSession = testData.secondSession!!
val roomAlicePov = aliceSession.getRoom(testData.roomId)!!
val eventId = mTestHelper.sendTextMessage(roomAlicePov, "first message", 1).first().eventId
mTestHelper.signOutAndClose(bobSession)
// Create a new session for bob
val bobSecondSession = mTestHelper.logIntoAccount(bobSession.myUserId, SessionTestParams(true))
// initialize to force request keys if missing
mCryptoTestHelper.initializeCrossSigning(bobSecondSession)
// Trust bob second device from Alice POV
aliceSession.cryptoService().crossSigningService().trustDevice(bobSecondSession.sessionParams.deviceId!!, NoOpMatrixCallback())
bobSecondSession.cryptoService().crossSigningService().trustDevice(aliceSession.sessionParams.deviceId!!, NoOpMatrixCallback())
var sessionId: String? = null
// Check that the
// await for bob SecondSession session to get the message
mTestHelper.waitWithLatch { latch ->
mTestHelper.retryPeriodicallyWithLatch(latch) {
val timeLineEvent = bobSecondSession.getRoom(testData.roomId)?.getTimeLineEvent(eventId)?.also {
// try to decrypt and force key request
tryThis { bobSecondSession.cryptoService().decryptEvent(it.root, "") }
}
sessionId = timeLineEvent?.root?.content?.toModel<EncryptedEventContent>()?.sessionId
timeLineEvent != null
}
}
//Check that bob second session requested the key
mTestHelper.waitWithLatch { latch ->
mTestHelper.retryPeriodicallyWithLatch(latch) {
val wc = bobSecondSession.cryptoService().getWithHeldMegolmSession(roomAlicePov.roomId, sessionId!!)
wc?.code == WithHeldCode.UNAUTHORISED
}
}
}
}

View File

@ -36,6 +36,7 @@ import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
import im.vector.matrix.android.internal.crypto.model.event.RoomKeyWithHeldContent
import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
@ -148,4 +149,5 @@ interface CryptoService {
//For testing shared session
fun getSharedWithInfo(roomId: String?, sessionId: String) : MXUsersDevicesMap<Int>
fun getWithHeldMegolmSession(roomId: String, sessionId: String) : RoomKeyWithHeldContent?
}

View File

@ -1334,6 +1334,9 @@ internal class DefaultCryptoService @Inject constructor(
return cryptoStore.getSharedWithInfo(roomId, sessionId)
}
override fun getWithHeldMegolmSession(roomId: String, sessionId: String): RoomKeyWithHeldContent? {
return cryptoStore.getWithHeldMegolmSession(roomId, sessionId)
}
/* ==========================================================================================
* For test only
* ========================================================================================== */

View File

@ -94,7 +94,7 @@ internal class MXMegolmEncryption(
{ it.second },
{ it.first }
).forEach { (code, targets) ->
notifyKeyWithHeld(targets, outboundSession.sessionId, code)
notifyKeyWithHeld(targets, outboundSession.sessionId, olmDevice.deviceCurve25519Key, code)
}
}
@ -229,6 +229,7 @@ internal class MXMegolmEncryption(
notifyKeyWithHeld(
listOf(UserDevice(userId, deviceID)),
session.sessionId,
olmDevice.deviceCurve25519Key,
WithHeldCode.NO_OLM
)
@ -267,10 +268,10 @@ internal class MXMegolmEncryption(
}
}
private fun notifyKeyWithHeld(targets: List<UserDevice>, sessionId: String, code: WithHeldCode) {
private fun notifyKeyWithHeld(targets: List<UserDevice>, sessionId: String, senderKey: String?, code: WithHeldCode) {
val withHeldContent = RoomKeyWithHeldContent(
roomId = roomId,
senderKey = olmDevice.deviceCurve25519Key,
senderKey = senderKey,
algorithm = MXCRYPTO_ALGORITHM_MEGOLM,
sessionId = sessionId,
codeString = code.value
@ -383,7 +384,11 @@ internal class MXMegolmEncryption(
// Get the chain index of the key we previously sent this device
val chainIndex = outboundSession?.sharedWithHelper?.wasSharedWith(userId,deviceId) ?: return false
.also { Timber.w("[MXMegolmEncryption] reshareKey : ERROR : Never share megolm with this device") }
.also {
// Send a room key with held
notifyKeyWithHeld(listOf(UserDevice(userId, deviceId)), sessionId, senderKey, WithHeldCode.UNAUTHORISED)
Timber.w("[MXMegolmEncryption] reshareKey : ERROR : Never share megolm with this device")
}
val devicesByUser = mapOf(userId to listOf(deviceInfo))
val usersDeviceMap = ensureOlmSessionsForDevicesAction.handle(devicesByUser)