Move crypto migration

This commit is contained in:
yostyle 2023-10-13 17:18:32 +02:00
parent fd5530a2f9
commit 7755da881e
2 changed files with 29 additions and 47 deletions

View File

@ -55,6 +55,7 @@ import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.Event 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.EventType
import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
import org.matrix.android.sdk.api.session.events.model.content.RoomKeyContent import org.matrix.android.sdk.api.session.events.model.content.RoomKeyContent
import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent
@ -134,6 +135,7 @@ internal class RustCryptoService @Inject constructor(
private val getRoomUserIds: GetRoomUserIdsUseCase, private val getRoomUserIds: GetRoomUserIdsUseCase,
private val outgoingRequestsProcessor: OutgoingRequestsProcessor, private val outgoingRequestsProcessor: OutgoingRequestsProcessor,
private val matrixConfiguration: MatrixConfiguration, private val matrixConfiguration: MatrixConfiguration,
private val perSessionBackupQueryRateLimiter: PerSessionBackupQueryRateLimiter,
) : CryptoService { ) : CryptoService {
private val isStarting = AtomicBoolean(false) private val isStarting = AtomicBoolean(false)
@ -494,7 +496,32 @@ internal class RustCryptoService @Inject constructor(
*/ */
@Throws(MXCryptoError::class) @Throws(MXCryptoError::class)
override suspend fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult { override suspend fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult {
return olmMachine.decryptRoomEvent(event) return try {
olmMachine.decryptRoomEvent(event)
} catch (mxCryptoError: MXCryptoError) {
if (mxCryptoError is MXCryptoError.Base && (
mxCryptoError.errorType == MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID
|| mxCryptoError.errorType == MXCryptoError.ErrorType.UNKNOWN_MESSAGE_INDEX)) {
Timber.v("Try to perform a lazy migration from legacy store")
/**
* It's a bit hacky, check how this can be better integrated with rust?
*/
val content = event.content?.toModel<EncryptedEventContent>() ?: throw mxCryptoError
val roomId = event.roomId
val sessionId = content.sessionId
val senderKey = content.senderKey
if (roomId != null && sessionId != null) {
// try to perform a lazy migration from legacy store
val legacy = tryOrNull("Failed to access legacy crypto store") {
cryptoStore.getInboundGroupSession(sessionId, senderKey.orEmpty())
}
if (legacy == null || olmMachine.importRoomKey(legacy).isFailure) {
perSessionBackupQueryRateLimiter.tryFromBackupIfPossible(sessionId, roomId)
}
}
}
throw mxCryptoError
}
} }
/** /**

View File

@ -22,23 +22,17 @@ import dagger.Lazy
import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.failure.MatrixError import org.matrix.android.sdk.api.failure.MatrixError
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupLastVersionResult import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupLastVersionResult
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult
import org.matrix.android.sdk.api.session.crypto.model.GossipingToDeviceObject
import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.Event 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.uia.UiaResult import org.matrix.android.sdk.api.session.uia.UiaResult
import org.matrix.android.sdk.internal.auth.registration.handleUIA import org.matrix.android.sdk.internal.auth.registration.handleUIA
import org.matrix.android.sdk.internal.crypto.OlmMachine
import org.matrix.android.sdk.internal.crypto.PerSessionBackupQueryRateLimiter
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.BackupKeysResult import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.BackupKeysResult
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.CreateKeysBackupVersionBody import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.CreateKeysBackupVersionBody
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysBackupData import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysBackupData
@ -59,7 +53,6 @@ import org.matrix.android.sdk.internal.crypto.model.rest.KeysUploadBody
import org.matrix.android.sdk.internal.crypto.model.rest.KeysUploadResponse import org.matrix.android.sdk.internal.crypto.model.rest.KeysUploadResponse
import org.matrix.android.sdk.internal.crypto.model.rest.RestKeyInfo import org.matrix.android.sdk.internal.crypto.model.rest.RestKeyInfo
import org.matrix.android.sdk.internal.crypto.model.rest.SignatureUploadResponse import org.matrix.android.sdk.internal.crypto.model.rest.SignatureUploadResponse
import org.matrix.android.sdk.internal.crypto.store.IMXCommonCryptoStore
import org.matrix.android.sdk.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask import org.matrix.android.sdk.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask
import org.matrix.android.sdk.internal.crypto.tasks.DefaultSendVerificationMessageTask import org.matrix.android.sdk.internal.crypto.tasks.DefaultSendVerificationMessageTask
import org.matrix.android.sdk.internal.crypto.tasks.DownloadKeysForUsersTask import org.matrix.android.sdk.internal.crypto.tasks.DownloadKeysForUsersTask
@ -102,10 +95,7 @@ internal class RequestSender @Inject constructor(
private val getRoomSessionDataTask: GetRoomSessionDataTask, private val getRoomSessionDataTask: GetRoomSessionDataTask,
private val moshi: Moshi, private val moshi: Moshi,
cryptoCoroutineScope: CoroutineScope, cryptoCoroutineScope: CoroutineScope,
private val rateLimiter: PerSessionBackupQueryRateLimiter,
private val cryptoStore: IMXCommonCryptoStore,
private val localEchoRepository: LocalEchoRepository, private val localEchoRepository: LocalEchoRepository,
private val olmMachine: Lazy<OlmMachine>,
) { ) {
private val scope = CoroutineScope( private val scope = CoroutineScope(
@ -246,44 +236,9 @@ internal class RequestSender @Inject constructor(
.newBuilder() .newBuilder()
.add(CheckNumberType.JSON_ADAPTER_FACTORY) .add(CheckNumberType.JSON_ADAPTER_FACTORY)
.build() .build()
.adapter<Map<String, Map<String, Any>>>(Map::class.java) .adapter<Map<String, HashMap<String, Any>>>(Map::class.java)
val jsonBody = adapter.fromJson(body)!! val jsonBody = adapter.fromJson(body)!!
if (eventType == EventType.ROOM_KEY_REQUEST) {
scope.launch {
Timber.v("Intercepting key request, try backup")
/**
* It's a bit hacky, check how this can be better integrated with rust?
*/
try {
jsonBody.forEach { (_, deviceToContent) ->
deviceToContent.forEach { (_, content) ->
val hashMap = content as? Map<*, *>
val action = hashMap?.get("action")?.toString()
if (GossipingToDeviceObject.ACTION_SHARE_REQUEST == action) {
val requestBody = hashMap["body"] as? Map<*, *>
val roomId = requestBody?.get("room_id") as? String
val sessionId = requestBody?.get("session_id") as? String
val senderKey = requestBody?.get("sender_key") as? String
if (roomId != null && sessionId != null) {
// try to perform a lazy migration from legacy store
val legacy = tryOrNull("Failed to access legacy crypto store") {
cryptoStore.getInboundGroupSession(sessionId, senderKey.orEmpty())
}
if (legacy == null || olmMachine.get().importRoomKey(legacy).isFailure) {
rateLimiter.tryFromBackupIfPossible(sessionId, roomId)
}
}
}
}
}
Timber.v("Intercepting key request, try backup")
} catch (failure: Throwable) {
Timber.v(failure, "Failed to use backup")
}
}
}
val userMap = MXUsersDevicesMap<Any>() val userMap = MXUsersDevicesMap<Any>()
userMap.join(jsonBody) userMap.join(jsonBody)