Send with held code on key requests
This commit is contained in:
parent
cdb1b8d8f8
commit
3fa2647e92
@ -19,6 +19,8 @@ package im.vector.matrix.android.internal.crypto.gossiping
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import im.vector.matrix.android.InstrumentedTest
|
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.crypto.MXCryptoError
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
@ -128,9 +130,8 @@ class WithHeldTests : InstrumentedTest {
|
|||||||
mTestHelper.signOutAndClose(bobUnverifiedSession)
|
mTestHelper.signOutAndClose(bobUnverifiedSession)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_WithHeldNoOlm() {
|
fun test_WithHeldNoOlm() {
|
||||||
val testData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val testData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
val aliceSession = testData.firstSession
|
val aliceSession = testData.firstSession
|
||||||
val bobSession = testData.secondSession!!
|
val bobSession = testData.secondSession!!
|
||||||
@ -148,8 +149,6 @@ class WithHeldTests : InstrumentedTest {
|
|||||||
|
|
||||||
val roomAlicePov = aliceSession.getRoom(testData.roomId)!!
|
val roomAlicePov = aliceSession.getRoom(testData.roomId)!!
|
||||||
|
|
||||||
// can we force one-time key shortage??
|
|
||||||
|
|
||||||
val eventId = mTestHelper.sendTextMessage(roomAlicePov, "first message", 1).first().eventId
|
val eventId = mTestHelper.sendTextMessage(roomAlicePov, "first message", 1).first().eventId
|
||||||
|
|
||||||
// await for bob session to get the message
|
// await for bob session to get the message
|
||||||
@ -176,7 +175,7 @@ class WithHeldTests : InstrumentedTest {
|
|||||||
val sessionId = eventBobPOV!!.root.content.toModel<EncryptedEventContent>()!!.sessionId!!
|
val sessionId = eventBobPOV!!.root.content.toModel<EncryptedEventContent>()!!.sessionId!!
|
||||||
val chainIndex = aliceSession.cryptoService().getSharedWithInfo(testData.roomId, sessionId).getObject(bobSession.myUserId, bobSession.sessionParams.credentials.deviceId)
|
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
|
// Add a new device for bob
|
||||||
|
|
||||||
aliceInterceptor.clearRules()
|
aliceInterceptor.clearRules()
|
||||||
@ -194,10 +193,55 @@ class WithHeldTests : InstrumentedTest {
|
|||||||
|
|
||||||
val chainIndex2 = aliceSession.cryptoService().getSharedWithInfo(testData.roomId, sessionId).getObject(bobSecondSession.myUserId, bobSecondSession.sessionParams.credentials.deviceId)
|
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)
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.MXDeviceInfo
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult
|
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.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.DeviceInfo
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
|
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
||||||
@ -148,4 +149,5 @@ interface CryptoService {
|
|||||||
|
|
||||||
//For testing shared session
|
//For testing shared session
|
||||||
fun getSharedWithInfo(roomId: String?, sessionId: String) : MXUsersDevicesMap<Int>
|
fun getSharedWithInfo(roomId: String?, sessionId: String) : MXUsersDevicesMap<Int>
|
||||||
|
fun getWithHeldMegolmSession(roomId: String, sessionId: String) : RoomKeyWithHeldContent?
|
||||||
}
|
}
|
||||||
|
@ -1334,6 +1334,9 @@ internal class DefaultCryptoService @Inject constructor(
|
|||||||
return cryptoStore.getSharedWithInfo(roomId, sessionId)
|
return cryptoStore.getSharedWithInfo(roomId, sessionId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getWithHeldMegolmSession(roomId: String, sessionId: String): RoomKeyWithHeldContent? {
|
||||||
|
return cryptoStore.getWithHeldMegolmSession(roomId, sessionId)
|
||||||
|
}
|
||||||
/* ==========================================================================================
|
/* ==========================================================================================
|
||||||
* For test only
|
* For test only
|
||||||
* ========================================================================================== */
|
* ========================================================================================== */
|
||||||
|
@ -94,7 +94,7 @@ internal class MXMegolmEncryption(
|
|||||||
{ it.second },
|
{ it.second },
|
||||||
{ it.first }
|
{ it.first }
|
||||||
).forEach { (code, targets) ->
|
).forEach { (code, targets) ->
|
||||||
notifyKeyWithHeld(targets, outboundSession.sessionId, code)
|
notifyKeyWithHeld(targets, outboundSession.sessionId, olmDevice.deviceCurve25519Key, code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,6 +229,7 @@ internal class MXMegolmEncryption(
|
|||||||
notifyKeyWithHeld(
|
notifyKeyWithHeld(
|
||||||
listOf(UserDevice(userId, deviceID)),
|
listOf(UserDevice(userId, deviceID)),
|
||||||
session.sessionId,
|
session.sessionId,
|
||||||
|
olmDevice.deviceCurve25519Key,
|
||||||
WithHeldCode.NO_OLM
|
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(
|
val withHeldContent = RoomKeyWithHeldContent(
|
||||||
roomId = roomId,
|
roomId = roomId,
|
||||||
senderKey = olmDevice.deviceCurve25519Key,
|
senderKey = senderKey,
|
||||||
algorithm = MXCRYPTO_ALGORITHM_MEGOLM,
|
algorithm = MXCRYPTO_ALGORITHM_MEGOLM,
|
||||||
sessionId = sessionId,
|
sessionId = sessionId,
|
||||||
codeString = code.value
|
codeString = code.value
|
||||||
@ -383,7 +384,11 @@ internal class MXMegolmEncryption(
|
|||||||
|
|
||||||
// Get the chain index of the key we previously sent this device
|
// Get the chain index of the key we previously sent this device
|
||||||
val chainIndex = outboundSession?.sharedWithHelper?.wasSharedWith(userId,deviceId) ?: return false
|
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 devicesByUser = mapOf(userId to listOf(deviceInfo))
|
||||||
val usersDeviceMap = ensureOlmSessionsForDevicesAction.handle(devicesByUser)
|
val usersDeviceMap = ensureOlmSessionsForDevicesAction.handle(devicesByUser)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user