Store device key in SharedSessionEntity

Code review changes


Fix database migraiton


Fix wrong self assignement + comment
This commit is contained in:
Valere 2021-09-10 14:27:39 +02:00 committed by Benoit Marty
parent ed2c21781a
commit 8d2f95d5db
7 changed files with 70 additions and 18 deletions

View file

@ -170,7 +170,7 @@ internal class MXMegolmEncryption(
val deviceIds = devicesInRoom.getUserDeviceIds(userId) val deviceIds = devicesInRoom.getUserDeviceIds(userId)
for (deviceId in deviceIds!!) { for (deviceId in deviceIds!!) {
val deviceInfo = devicesInRoom.getObject(userId, deviceId) val deviceInfo = devicesInRoom.getObject(userId, deviceId)
if (deviceInfo != null && !cryptoStore.getSharedSessionInfo(roomId, safeSession.sessionId, userId, deviceId).found) { if (deviceInfo != null && !cryptoStore.getSharedSessionInfo(roomId, safeSession.sessionId, deviceInfo).found) {
val devices = shareMap.getOrPut(userId) { ArrayList() } val devices = shareMap.getOrPut(userId) { ArrayList() }
devices.add(deviceInfo) devices.add(deviceInfo)
} }
@ -270,8 +270,8 @@ internal class MXMegolmEncryption(
// for dead devices on every message. // for dead devices on every message.
val gossipingEventBuffer = arrayListOf<Event>() val gossipingEventBuffer = arrayListOf<Event>()
for ((userId, devicesToShareWith) in devicesByUser) { for ((userId, devicesToShareWith) in devicesByUser) {
for ((deviceId) in devicesToShareWith) { for (deviceInfo in devicesToShareWith) {
session.sharedWithHelper.markedSessionAsShared(userId, deviceId, chainIndex) session.sharedWithHelper.markedSessionAsShared(deviceInfo, chainIndex)
gossipingEventBuffer.add( gossipingEventBuffer.add(
Event( Event(
type = EventType.ROOM_KEY, type = EventType.ROOM_KEY,
@ -279,7 +279,7 @@ internal class MXMegolmEncryption(
content = submap.apply { content = submap.apply {
this["session_key"] = "" this["session_key"] = ""
// we add a fake key for trail // we add a fake key for trail
this["_dest"] = "$userId|$deviceId" this["_dest"] = "$userId|${deviceInfo.deviceId}"
} }
)) ))
} }
@ -429,7 +429,7 @@ internal class MXMegolmEncryption(
.also { Timber.w("## Crypto reshareKey: Device not found") } .also { Timber.w("## Crypto reshareKey: Device not found") }
// 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 wasSessionSharedWithUser = cryptoStore.getSharedSessionInfo(roomId, sessionId, userId, deviceId) val wasSessionSharedWithUser = cryptoStore.getSharedSessionInfo(roomId, sessionId, deviceInfo)
if (!wasSessionSharedWithUser.found) { if (!wasSessionSharedWithUser.found) {
// This session was never shared with this user // This session was never shared with this user
// Send a room key with held // Send a room key with held

View file

@ -16,6 +16,7 @@
package org.matrix.android.sdk.internal.crypto.algorithms.megolm package org.matrix.android.sdk.internal.crypto.algorithms.megolm
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
@ -28,7 +29,13 @@ internal class SharedWithHelper(
return cryptoStore.getSharedWithInfo(roomId, sessionId) return cryptoStore.getSharedWithInfo(roomId, sessionId)
} }
fun markedSessionAsShared(userId: String, deviceId: String, chainIndex: Int) { fun markedSessionAsShared(deviceInfo: CryptoDeviceInfo, chainIndex: Int) {
cryptoStore.markedSessionAsShared(roomId, sessionId, userId, deviceId, chainIndex) cryptoStore.markedSessionAsShared(
roomId = roomId,
sessionId = sessionId,
userId = deviceInfo.userId,
deviceId = deviceInfo.deviceId,
deviceIdentityKey = deviceInfo.identityKey() ?: "",
chainIndex = chainIndex)
} }
} }

View file

@ -450,7 +450,8 @@ internal interface IMXCryptoStore {
fun addWithHeldMegolmSession(withHeldContent: RoomKeyWithHeldContent) fun addWithHeldMegolmSession(withHeldContent: RoomKeyWithHeldContent)
fun getWithHeldMegolmSession(roomId: String, sessionId: String): RoomKeyWithHeldContent? fun getWithHeldMegolmSession(roomId: String, sessionId: String): RoomKeyWithHeldContent?
fun markedSessionAsShared(roomId: String?, sessionId: String, userId: String, deviceId: String, chainIndex: Int) fun markedSessionAsShared(roomId: String?, sessionId: String, userId: String, deviceId: String,
deviceIdentityKey: String, chainIndex: Int)
/** /**
* Query for information on this session sharing history. * Query for information on this session sharing history.
@ -459,7 +460,7 @@ internal interface IMXCryptoStore {
* in this case chainIndex is not nullindicates the ratchet position. * in this case chainIndex is not nullindicates the ratchet position.
* In found is false, chainIndex is null * In found is false, chainIndex is null
*/ */
fun getSharedSessionInfo(roomId: String?, sessionId: String, userId: String, deviceId: String): SharedSessionResult fun getSharedSessionInfo(roomId: String?, sessionId: String, deviceInfo: CryptoDeviceInfo): SharedSessionResult
data class SharedSessionResult(val found: Boolean, val chainIndex: Int?) data class SharedSessionResult(val found: Boolean, val chainIndex: Int?)
fun getSharedWithInfo(roomId: String?, sessionId: String): MXUsersDevicesMap<Int> fun getSharedWithInfo(roomId: String?, sessionId: String): MXUsersDevicesMap<Int>

View file

@ -1681,7 +1681,12 @@ internal class RealmCryptoStore @Inject constructor(
} }
} }
override fun markedSessionAsShared(roomId: String?, sessionId: String, userId: String, deviceId: String, chainIndex: Int) { override fun markedSessionAsShared(roomId: String?,
sessionId: String,
userId: String,
deviceId: String,
deviceIdentityKey: String,
chainIndex: Int) {
doRealmTransaction(realmConfiguration) { realm -> doRealmTransaction(realmConfiguration) { realm ->
SharedSessionEntity.create( SharedSessionEntity.create(
realm = realm, realm = realm,
@ -1689,14 +1694,22 @@ internal class RealmCryptoStore @Inject constructor(
sessionId = sessionId, sessionId = sessionId,
userId = userId, userId = userId,
deviceId = deviceId, deviceId = deviceId,
deviceIdentityKey = deviceIdentityKey,
chainIndex = chainIndex chainIndex = chainIndex
) )
} }
} }
override fun getSharedSessionInfo(roomId: String?, sessionId: String, userId: String, deviceId: String): IMXCryptoStore.SharedSessionResult { override fun getSharedSessionInfo(roomId: String?, sessionId: String, deviceInfo: CryptoDeviceInfo): IMXCryptoStore.SharedSessionResult {
return doWithRealm(realmConfiguration) { realm -> return doWithRealm(realmConfiguration) { realm ->
SharedSessionEntity.get(realm, roomId, sessionId, userId, deviceId)?.let { SharedSessionEntity.get(
realm = realm,
roomId = roomId,
sessionId = sessionId,
userId = deviceInfo.userId,
deviceId = deviceInfo.deviceId,
deviceIdentityKey = deviceInfo.identityKey()
)?.let {
IMXCryptoStore.SharedSessionResult(true, it.chainIndex) IMXCryptoStore.SharedSessionResult(true, it.chainIndex)
} ?: IMXCryptoStore.SharedSessionResult(false, null) } ?: IMXCryptoStore.SharedSessionResult(false, null)
} }

View file

@ -55,7 +55,7 @@ internal object RealmCryptoStoreMigration : RealmMigration {
// 0, 1, 2: legacy Riot-Android // 0, 1, 2: legacy Riot-Android
// 3: migrate to RiotX schema // 3: migrate to RiotX schema
// 4, 5, 6, 7, 8, 9: migrations from RiotX (which was previously 1, 2, 3, 4, 5, 6) // 4, 5, 6, 7, 8, 9: migrations from RiotX (which was previously 1, 2, 3, 4, 5, 6)
const val CRYPTO_STORE_SCHEMA_VERSION = 13L const val CRYPTO_STORE_SCHEMA_VERSION = 14L
private fun RealmObjectSchema.addFieldIfNotExists(fieldName: String, fieldType: Class<*>): RealmObjectSchema { private fun RealmObjectSchema.addFieldIfNotExists(fieldName: String, fieldType: Class<*>): RealmObjectSchema {
if (!hasField(fieldName)) { if (!hasField(fieldName)) {
@ -94,6 +94,7 @@ internal object RealmCryptoStoreMigration : RealmMigration {
if (oldVersion <= 10) migrateTo11(realm) if (oldVersion <= 10) migrateTo11(realm)
if (oldVersion <= 11) migrateTo12(realm) if (oldVersion <= 11) migrateTo12(realm)
if (oldVersion <= 12) migrateTo13(realm) if (oldVersion <= 12) migrateTo13(realm)
if (oldVersion <= 13) migrateTo14(realm)
} }
private fun migrateTo1Legacy(realm: DynamicRealm) { private fun migrateTo1Legacy(realm: DynamicRealm) {
@ -554,4 +555,21 @@ internal object RealmCryptoStoreMigration : RealmMigration {
Timber.e("TrustLevelEntity cleanup: Something is not correct...") Timber.e("TrustLevelEntity cleanup: Something is not correct...")
} }
} }
// Version 14L Update the way we remember key sharing
private fun migrateTo14(realm: DynamicRealm) {
Timber.d("Step 13 -> 14")
realm.schema.get("SharedSessionEntity")
?.addField(SharedSessionEntityFields.DEVICE_IDENTITY_KEY, String::class.java)
?.addIndex(SharedSessionEntityFields.DEVICE_IDENTITY_KEY)
?.transform {
val sharedUserId = it.getString(SharedSessionEntityFields.USER_ID)
val sharedDeviceId = it.getString(SharedSessionEntityFields.DEVICE_ID)
val knownDevice = realm.where("DeviceInfoEntity")
.equalTo(DeviceInfoEntityFields.USER_ID, sharedUserId)
.equalTo(DeviceInfoEntityFields.DEVICE_ID, sharedDeviceId)
.findFirst()
it.setString(SharedSessionEntityFields.DEVICE_IDENTITY_KEY, knownDevice?.getString(DeviceInfoEntityFields.IDENTITY_KEY))
}
}
} }

View file

@ -30,6 +30,7 @@ internal open class SharedSessionEntity(
@Index var sessionId: String? = null, @Index var sessionId: String? = null,
@Index var userId: String? = null, @Index var userId: String? = null,
@Index var deviceId: String? = null, @Index var deviceId: String? = null,
@Index var deviceIdentityKey: String? = null,
var chainIndex: Int? = null var chainIndex: Int? = null
) : RealmObject() { ) : RealmObject() {

View file

@ -16,15 +16,20 @@
package org.matrix.android.sdk.internal.crypto.store.db.query package org.matrix.android.sdk.internal.crypto.store.db.query
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntityFields
import io.realm.Realm import io.realm.Realm
import io.realm.RealmResults import io.realm.RealmResults
import io.realm.kotlin.createObject import io.realm.kotlin.createObject
import io.realm.kotlin.where import io.realm.kotlin.where
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntityFields
internal fun SharedSessionEntity.Companion.get(realm: Realm, roomId: String?, sessionId: String, userId: String, deviceId: String) internal fun SharedSessionEntity.Companion.get(realm: Realm,
roomId: String?,
sessionId: String,
userId: String,
deviceId: String,
deviceIdentityKey: String?)
: SharedSessionEntity? { : SharedSessionEntity? {
return realm.where<SharedSessionEntity>() return realm.where<SharedSessionEntity>()
.equalTo(SharedSessionEntityFields.ROOM_ID, roomId) .equalTo(SharedSessionEntityFields.ROOM_ID, roomId)
@ -32,6 +37,7 @@ internal fun SharedSessionEntity.Companion.get(realm: Realm, roomId: String?, se
.equalTo(SharedSessionEntityFields.ALGORITHM, MXCRYPTO_ALGORITHM_MEGOLM) .equalTo(SharedSessionEntityFields.ALGORITHM, MXCRYPTO_ALGORITHM_MEGOLM)
.equalTo(SharedSessionEntityFields.USER_ID, userId) .equalTo(SharedSessionEntityFields.USER_ID, userId)
.equalTo(SharedSessionEntityFields.DEVICE_ID, deviceId) .equalTo(SharedSessionEntityFields.DEVICE_ID, deviceId)
.equalTo(SharedSessionEntityFields.DEVICE_IDENTITY_KEY, deviceIdentityKey)
.findFirst() .findFirst()
} }
@ -44,7 +50,12 @@ internal fun SharedSessionEntity.Companion.get(realm: Realm, roomId: String?, se
.findAll() .findAll()
} }
internal fun SharedSessionEntity.Companion.create(realm: Realm, roomId: String?, sessionId: String, userId: String, deviceId: String, chainIndex: Int) internal fun SharedSessionEntity.Companion.create(realm: Realm, roomId: String?,
sessionId: String,
userId: String,
deviceId: String,
deviceIdentityKey: String,
chainIndex: Int)
: SharedSessionEntity { : SharedSessionEntity {
return realm.createObject<SharedSessionEntity>().apply { return realm.createObject<SharedSessionEntity>().apply {
this.roomId = roomId this.roomId = roomId
@ -52,6 +63,7 @@ internal fun SharedSessionEntity.Companion.create(realm: Realm, roomId: String?,
this.sessionId = sessionId this.sessionId = sessionId
this.userId = userId this.userId = userId
this.deviceId = deviceId this.deviceId = deviceId
this.deviceIdentityKey = deviceIdentityKey
this.chainIndex = chainIndex this.chainIndex = chainIndex
} }
} }