mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-29 15:40:55 +08:00
DeviceId should be non-null so we can inject it properly and OlmMachine too.
This commit is contained in:
parent
e519561edf
commit
c1961d1fda
@ -49,7 +49,7 @@ data class Credentials(
|
||||
/**
|
||||
* ID of the logged-in device. Will be the same as the corresponding parameter in the request, if one was specified.
|
||||
*/
|
||||
@Json(name = "device_id") val deviceId: String?,
|
||||
@Json(name = "device_id") val deviceId: String,
|
||||
/**
|
||||
* Optional client configuration provided by the server. If present, clients SHOULD use the provided object to
|
||||
* reconfigure themselves, optionally validating the URLs within.
|
||||
@ -59,5 +59,5 @@ data class Credentials(
|
||||
)
|
||||
|
||||
internal fun Credentials.sessionId(): String {
|
||||
return (if (deviceId.isNullOrBlank()) userId else "$userId|$deviceId").md5()
|
||||
return (if (deviceId.isBlank()) userId else "$userId|$deviceId").md5()
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ interface CryptoService {
|
||||
|
||||
fun shouldEncryptForInvitedMembers(roomId: String): Boolean
|
||||
|
||||
suspend fun downloadKeys(userIds: List<String>, forceDownload: Boolean = false): MXUsersDevicesMap<CryptoDeviceInfo>
|
||||
suspend fun downloadKeysIfNeeded(userIds: List<String>, forceDownload: Boolean = false): MXUsersDevicesMap<CryptoDeviceInfo>
|
||||
|
||||
suspend fun getCryptoDeviceInfoList(userId: String): List<CryptoDeviceInfo>
|
||||
|
||||
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.crypto
|
||||
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class ComputeShieldForGroupUseCase @Inject constructor(
|
||||
@UserId private val myUserId: String
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(olmMachine: OlmMachine, userIds: List<String>): RoomEncryptionTrustLevel {
|
||||
val myIdentity = olmMachine.getIdentity(myUserId)
|
||||
val allTrustedUserIds = userIds
|
||||
.filter { userId ->
|
||||
olmMachine.getIdentity(userId)?.verified() == true
|
||||
}
|
||||
|
||||
return if (allTrustedUserIds.isEmpty()) {
|
||||
RoomEncryptionTrustLevel.Default
|
||||
} else {
|
||||
// If one of the verified user as an untrusted device -> warning
|
||||
// If all devices of all verified users are trusted -> green
|
||||
// else -> black
|
||||
allTrustedUserIds
|
||||
.map { userId ->
|
||||
olmMachine.getUserDevices(userId)
|
||||
}
|
||||
.flatten()
|
||||
.let { allDevices ->
|
||||
if (myIdentity != null) {
|
||||
allDevices.any { !it.toCryptoDeviceInfo().trustLevel?.crossSigningVerified.orFalse() }
|
||||
} else {
|
||||
// TODO check that if myIdentity is null ean
|
||||
// Legacy method
|
||||
allDevices.any { !it.toCryptoDeviceInfo().isVerified }
|
||||
}
|
||||
}
|
||||
.let { hasWarning ->
|
||||
if (hasWarning) {
|
||||
RoomEncryptionTrustLevel.Warning
|
||||
} else {
|
||||
if (userIds.size == allTrustedUserIds.size) {
|
||||
// all users are trusted and all devices are verified
|
||||
RoomEncryptionTrustLevel.Trusted
|
||||
} else {
|
||||
RoomEncryptionTrustLevel.Default
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -20,9 +20,7 @@ import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DecryptRoomEventUseCase @Inject constructor(olmMachineProvider: OlmMachineProvider) {
|
||||
|
||||
private val olmMachine = olmMachineProvider.olmMachine
|
||||
internal class DecryptRoomEventUseCase @Inject constructor(private val olmMachine: OlmMachine) {
|
||||
|
||||
suspend operator fun invoke(event: Event): MXEventDecryptionResult {
|
||||
return olmMachine.decryptRoomEvent(event)
|
||||
|
@ -66,7 +66,6 @@ import org.matrix.android.sdk.api.session.sync.model.DeviceOneTimeKeysCountSyncR
|
||||
import org.matrix.android.sdk.api.session.sync.model.ToDeviceSyncResponse
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.RustKeyBackupService
|
||||
import org.matrix.android.sdk.internal.crypto.network.OutgoingRequestsProcessor
|
||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||
import org.matrix.android.sdk.internal.crypto.repository.WarnOnUnknownDeviceRepository
|
||||
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
|
||||
import org.matrix.android.sdk.internal.crypto.tasks.DeleteDeviceTask
|
||||
@ -99,7 +98,7 @@ private val loggerTag = LoggerTag("DefaultCryptoService", LoggerTag.CRYPTO)
|
||||
@SessionScope
|
||||
internal class DefaultCryptoService @Inject constructor(
|
||||
@UserId private val userId: String,
|
||||
@DeviceId private val deviceId: String?,
|
||||
@DeviceId private val deviceId: String,
|
||||
// the crypto store
|
||||
private val cryptoStore: IMXCryptoStore,
|
||||
// Set of parameters used to configure/customize the end-to-end crypto.
|
||||
@ -114,30 +113,21 @@ internal class DefaultCryptoService @Inject constructor(
|
||||
private val cryptoSessionInfoProvider: CryptoSessionInfoProvider,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val cryptoCoroutineScope: CoroutineScope,
|
||||
private val requestSender: RequestSender,
|
||||
private val olmMachine: OlmMachine,
|
||||
private val crossSigningService: CrossSigningService,
|
||||
private val verificationService: RustVerificationService,
|
||||
private val keysBackupService: RustKeyBackupService,
|
||||
private val megolmSessionImportManager: MegolmSessionImportManager,
|
||||
private val olmMachineProvider: OlmMachineProvider,
|
||||
private val liveEventManager: dagger.Lazy<StreamEventsManager>,
|
||||
private val prepareToEncrypt: PrepareToEncryptUseCase,
|
||||
private val encryptEventContent: EncryptEventContentUseCase,
|
||||
private val getRoomUserIds: GetRoomUserIdsUseCase,
|
||||
private val outgoingRequestsProcessor: OutgoingRequestsProcessor,
|
||||
) : CryptoService {
|
||||
|
||||
private val isStarting = AtomicBoolean(false)
|
||||
private val isStarted = AtomicBoolean(false)
|
||||
|
||||
private val olmMachine by lazy { olmMachineProvider.olmMachine }
|
||||
|
||||
private val outgoingRequestsProcessor = OutgoingRequestsProcessor(
|
||||
requestSender = requestSender,
|
||||
coroutineScope = cryptoCoroutineScope,
|
||||
cryptoSessionInfoProvider = cryptoSessionInfoProvider,
|
||||
shieldComputer = crossSigningService::shieldForGroup
|
||||
)
|
||||
|
||||
fun onStateEvent(roomId: String, event: Event) {
|
||||
when (event.type) {
|
||||
EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
|
||||
@ -164,7 +154,7 @@ internal class DefaultCryptoService @Inject constructor(
|
||||
val params = SetDeviceNameTask.Params(deviceId, deviceName)
|
||||
setDeviceNameTask.execute(params)
|
||||
try {
|
||||
downloadKeys(listOf(userId), true)
|
||||
downloadKeysIfNeeded(listOf(userId), true)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.tag(loggerTag.value).w(failure, "setDeviceName: Failed to refresh of crypto device")
|
||||
}
|
||||
@ -489,7 +479,6 @@ internal class DefaultCryptoService @Inject constructor(
|
||||
if (!isRoomEncrypted(roomId)) {
|
||||
return
|
||||
}
|
||||
|
||||
event.stateKey?.let { userId ->
|
||||
val roomMember: RoomMemberContent? = event.content.toModel()
|
||||
val membership = roomMember?.membership
|
||||
@ -722,7 +711,7 @@ internal class DefaultCryptoService @Inject constructor(
|
||||
// TODO
|
||||
}
|
||||
|
||||
override suspend fun downloadKeys(userIds: List<String>, forceDownload: Boolean): MXUsersDevicesMap<CryptoDeviceInfo> {
|
||||
override suspend fun downloadKeysIfNeeded(userIds: List<String>, forceDownload: Boolean): MXUsersDevicesMap<CryptoDeviceInfo> {
|
||||
return withContext(coroutineDispatchers.crypto) {
|
||||
olmMachine.ensureUserDevicesMap(userIds, forceDownload)
|
||||
}
|
||||
|
@ -16,20 +16,20 @@
|
||||
|
||||
package org.matrix.android.sdk.internal.crypto
|
||||
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel
|
||||
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
||||
import org.matrix.android.sdk.api.session.crypto.model.UnsignedDeviceInfo
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
|
||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||
import org.matrix.android.sdk.internal.crypto.verification.SasVerification
|
||||
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequest
|
||||
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequestFactory
|
||||
import org.matrix.android.sdk.internal.crypto.verification.prepareMethods
|
||||
import uniffi.olm.CryptoStoreException
|
||||
import uniffi.olm.OlmMachine
|
||||
import uniffi.olm.SignatureException
|
||||
import uniffi.olm.Device as InnerDevice
|
||||
|
||||
@ -38,14 +38,22 @@ import uniffi.olm.Device as InnerDevice
|
||||
* This class can be used to directly start a verification flow with the device
|
||||
* or to manually verify the device.
|
||||
*/
|
||||
internal class Device(
|
||||
private val innerMachine: OlmMachine,
|
||||
private var innerDevice: InnerDevice,
|
||||
internal class Device @AssistedInject constructor(
|
||||
@Assisted private var innerDevice: InnerDevice,
|
||||
olmMachine: OlmMachine,
|
||||
private val requestSender: RequestSender,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val listeners: ArrayList<VerificationService.Listener>,
|
||||
private val verificationRequestFactory: VerificationRequestFactory,
|
||||
private val verificationRequestFactory: VerificationRequest.Factory,
|
||||
private val sasVerificationFactory: SasVerification.Factory
|
||||
) {
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(innerDevice: InnerDevice): Device
|
||||
}
|
||||
|
||||
private val innerMachine = olmMachine.inner()
|
||||
|
||||
@Throws(CryptoStoreException::class)
|
||||
private suspend fun refreshData() {
|
||||
val device = withContext(coroutineDispatchers.io) {
|
||||
@ -99,13 +107,7 @@ internal class Device(
|
||||
|
||||
return if (result != null) {
|
||||
requestSender.sendVerificationRequest(result.request)
|
||||
SasVerification(
|
||||
machine = innerMachine,
|
||||
inner = result.sas,
|
||||
sender = requestSender,
|
||||
coroutineDispatchers = coroutineDispatchers,
|
||||
listeners = listeners
|
||||
)
|
||||
sasVerificationFactory.create(result.sas)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
@ -173,6 +175,7 @@ internal class Device(
|
||||
trustLevel = DeviceTrustLevel(crossSigningVerified = innerDevice.crossSigningTrusted, locallyVerified = innerDevice.locallyTrusted),
|
||||
isBlocked = innerDevice.isBlocked,
|
||||
// TODO
|
||||
firstTimeSeenLocalTs = null)
|
||||
firstTimeSeenLocalTs = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -26,15 +26,15 @@ import javax.inject.Inject
|
||||
|
||||
private val loggerTag = LoggerTag("EncryptEventContentUseCase", LoggerTag.CRYPTO)
|
||||
|
||||
internal class EncryptEventContentUseCase @Inject constructor(olmMachineProvider: OlmMachineProvider,
|
||||
private val prepareToEncrypt: PrepareToEncryptUseCase,
|
||||
private val clock: Clock) {
|
||||
internal class EncryptEventContentUseCase @Inject constructor(
|
||||
private val olmMachine: OlmMachine,
|
||||
private val prepareToEncrypt: PrepareToEncryptUseCase,
|
||||
private val clock: Clock) {
|
||||
|
||||
private val olmMachine = olmMachineProvider.olmMachine
|
||||
|
||||
suspend operator fun invoke(eventContent: Content,
|
||||
eventType: String,
|
||||
roomId: String): MXEncryptEventContentResult {
|
||||
suspend operator fun invoke(
|
||||
eventContent: Content,
|
||||
eventType: String,
|
||||
roomId: String): MXEncryptEventContentResult {
|
||||
val t0 = clock.epochMillis()
|
||||
prepareToEncrypt(roomId, ensureAllMembersAreLoaded = false)
|
||||
val content = olmMachine.encrypt(roomId, eventType, eventContent)
|
||||
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.crypto
|
||||
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.internal.crypto.network.OutgoingRequestsProcessor
|
||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||
import uniffi.olm.Request
|
||||
import uniffi.olm.RequestType
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Provider
|
||||
|
||||
internal class EnsureUsersKeysUseCase @Inject constructor(
|
||||
private val olmMachine: Provider<OlmMachine>,
|
||||
private val outgoingRequestsProcessor: OutgoingRequestsProcessor,
|
||||
private val requestSender: RequestSender,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers) {
|
||||
|
||||
suspend operator fun invoke(userIds: List<String>, forceDownload: Boolean) {
|
||||
val olmMachine = olmMachine.get()
|
||||
if (forceDownload) {
|
||||
tryOrNull("Failed to download keys for $userIds") {
|
||||
forceKeyDownload(olmMachine, userIds)
|
||||
}
|
||||
} else {
|
||||
userIds.filter { userId ->
|
||||
!olmMachine.isUserTracked(userId)
|
||||
}.also { untrackedUserIds ->
|
||||
olmMachine.updateTrackedUsers(untrackedUserIds)
|
||||
}
|
||||
outgoingRequestsProcessor.processOutgoingRequests(olmMachine) {
|
||||
it is Request.KeysQuery && it.users.intersect(userIds.toSet()).isNotEmpty()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Throws
|
||||
private suspend fun forceKeyDownload(olmMachine: OlmMachine, userIds: List<String>) {
|
||||
withContext(coroutineDispatchers.io) {
|
||||
val requestId = UUID.randomUUID().toString()
|
||||
val response = requestSender.queryKeys(Request.KeysQuery(requestId, userIds))
|
||||
olmMachine.markRequestAsSent(requestId, RequestType.KEYS_QUERY, response)
|
||||
}
|
||||
}
|
||||
}
|
@ -22,20 +22,22 @@ import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.RestKeyInfo
|
||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequestFactory
|
||||
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequest
|
||||
import uniffi.olm.CryptoStoreException
|
||||
import uniffi.olm.OlmMachine
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Provider
|
||||
|
||||
internal class GetUserIdentityUseCase(
|
||||
private val innerMachine: OlmMachine,
|
||||
internal class GetUserIdentityUseCase @Inject constructor(
|
||||
private val olmMachine: Provider<OlmMachine>,
|
||||
private val requestSender: RequestSender,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val moshi: Moshi,
|
||||
private val verificationRequestFactory: VerificationRequestFactory
|
||||
private val verificationRequestFactory: VerificationRequest.Factory
|
||||
) {
|
||||
|
||||
@Throws(CryptoStoreException::class)
|
||||
suspend operator fun invoke(userId: String): UserIdentities? {
|
||||
val innerMachine = olmMachine.get().inner()
|
||||
val identity = withContext(coroutineDispatchers.io) {
|
||||
innerMachine.getIdentity(userId)
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import kotlinx.coroutines.withContext
|
||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
|
||||
import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.listeners.ProgressListener
|
||||
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
|
||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel
|
||||
@ -38,7 +37,6 @@ import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult
|
||||
import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult
|
||||
import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
|
||||
import org.matrix.android.sdk.api.session.crypto.model.UnsignedDeviceInfo
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction
|
||||
import org.matrix.android.sdk.api.session.events.model.Content
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
@ -52,10 +50,13 @@ import org.matrix.android.sdk.internal.coroutines.builder.safeInvokeOnClose
|
||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||
import org.matrix.android.sdk.internal.crypto.verification.SasVerification
|
||||
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequest
|
||||
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequestFactory
|
||||
import org.matrix.android.sdk.internal.crypto.verification.VerificationsProvider
|
||||
import org.matrix.android.sdk.internal.crypto.verification.qrcode.QrCodeVerification
|
||||
import org.matrix.android.sdk.internal.di.DeviceId
|
||||
import org.matrix.android.sdk.internal.di.SessionFilesDirectory
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.network.parsing.CheckNumberType
|
||||
import org.matrix.android.sdk.internal.util.time.Clock
|
||||
import org.matrix.android.sdk.internal.session.SessionScope
|
||||
import timber.log.Timber
|
||||
import uniffi.olm.BackupKeys
|
||||
import uniffi.olm.CrossSigningKeyExport
|
||||
@ -72,7 +73,7 @@ import uniffi.olm.RoomKeyCounts
|
||||
import uniffi.olm.setLogger
|
||||
import java.io.File
|
||||
import java.nio.charset.Charset
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
import uniffi.olm.OlmMachine as InnerMachine
|
||||
import uniffi.olm.ProgressListener as RustProgressListener
|
||||
|
||||
@ -105,20 +106,22 @@ fun setRustLogger() {
|
||||
setLogger(CryptoLogger() as Logger)
|
||||
}
|
||||
|
||||
internal class OlmMachine(
|
||||
user_id: String,
|
||||
device_id: String,
|
||||
path: File,
|
||||
clock: Clock,
|
||||
@SessionScope
|
||||
internal class OlmMachine @Inject constructor(
|
||||
@UserId userId: String,
|
||||
@DeviceId deviceId: String,
|
||||
@SessionFilesDirectory path: File,
|
||||
private val requestSender: RequestSender,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val moshi: Moshi,
|
||||
private val verificationsProvider: VerificationsProvider,
|
||||
private val deviceFactory: Device.Factory,
|
||||
private val getUserIdentity: GetUserIdentityUseCase,
|
||||
private val ensureUsersKeys: EnsureUsersKeysUseCase,
|
||||
) {
|
||||
|
||||
private val inner: InnerMachine = InnerMachine(user_id, device_id, path.toString(), null)
|
||||
val verificationListeners = ArrayList<VerificationService.Listener>()
|
||||
private val verificationRequestFactory = VerificationRequestFactory(inner, requestSender, coroutineDispatchers, verificationListeners, clock)
|
||||
private val getUserIdentity = GetUserIdentityUseCase(inner, requestSender, coroutineDispatchers, moshi, verificationRequestFactory)
|
||||
private val inner: InnerMachine = InnerMachine(userId, deviceId, path.toString(), null)
|
||||
|
||||
private val flowCollectors = FlowCollectors()
|
||||
|
||||
/** Get our own user ID. */
|
||||
@ -525,13 +528,12 @@ internal class OlmMachine(
|
||||
val innerDevice = withContext(coroutineDispatchers.io) {
|
||||
inner.getDevice(userId, deviceId)
|
||||
} ?: return null
|
||||
|
||||
return innerDevice.wrap()
|
||||
return deviceFactory.create(innerDevice)
|
||||
}
|
||||
|
||||
suspend fun getUserDevices(userId: String): List<Device> {
|
||||
return withContext(coroutineDispatchers.io) {
|
||||
inner.getUserDevices(userId).map { innerDevice -> innerDevice.wrap() }
|
||||
inner.getUserDevices(userId).map(deviceFactory::create)
|
||||
}
|
||||
}
|
||||
|
||||
@ -545,16 +547,6 @@ internal class OlmMachine(
|
||||
@Throws(CryptoStoreException::class)
|
||||
suspend fun getCryptoDeviceInfo(userId: String): List<CryptoDeviceInfo> {
|
||||
return getUserDevices(userId).map { it.toCryptoDeviceInfo() }
|
||||
/*
|
||||
// EA doesn't differentiate much between our own and other devices of
|
||||
// while the rust-sdk does, append our own device here.
|
||||
if (userId == userId()) {
|
||||
devices.add(ownDevice())
|
||||
}
|
||||
|
||||
return devices
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
@ -575,16 +567,7 @@ internal class OlmMachine(
|
||||
return plainDevices
|
||||
}
|
||||
|
||||
@Throws
|
||||
suspend fun forceKeyDownload(userIds: List<String>) {
|
||||
withContext(coroutineDispatchers.io) {
|
||||
val requestId = UUID.randomUUID().toString()
|
||||
val response = requestSender.queryKeys(Request.KeysQuery(requestId, userIds))
|
||||
markRequestAsSent(requestId, RequestType.KEYS_QUERY, response)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getUserDevicesMap(userIds: List<String>): MXUsersDevicesMap<CryptoDeviceInfo> {
|
||||
private suspend fun getUserDevicesMap(userIds: List<String>): MXUsersDevicesMap<CryptoDeviceInfo> {
|
||||
val userMap = MXUsersDevicesMap<CryptoDeviceInfo>()
|
||||
|
||||
for (user in userIds) {
|
||||
@ -616,18 +599,7 @@ internal class OlmMachine(
|
||||
* The key query request will be retried a few time in case of shaky connection, but could fail.
|
||||
*/
|
||||
suspend fun ensureUsersKeys(userIds: List<String>, forceDownload: Boolean = false) {
|
||||
val userIdsToFetchKeys = if (forceDownload) {
|
||||
userIds
|
||||
} else {
|
||||
userIds.mapNotNull { userId ->
|
||||
userId.takeIf { !isUserTracked(it) }
|
||||
}.also {
|
||||
updateTrackedUsers(it)
|
||||
}
|
||||
}
|
||||
tryOrNull("Failed to download keys for $userIdsToFetchKeys") {
|
||||
forceKeyDownload(userIdsToFetchKeys)
|
||||
}
|
||||
ensureUsersKeys.invoke(userIds, forceDownload)
|
||||
}
|
||||
|
||||
fun getLiveUserIdentity(userId: String): Flow<Optional<MXCrossSigningInfo>> {
|
||||
@ -692,14 +664,12 @@ internal class OlmMachine(
|
||||
* @return The list of [VerificationRequest] that we share with the given user
|
||||
*/
|
||||
fun getVerificationRequests(userId: String): List<VerificationRequest> {
|
||||
return inner.getVerificationRequests(userId).map(verificationRequestFactory::create)
|
||||
return verificationsProvider.getVerificationRequests(userId)
|
||||
}
|
||||
|
||||
/** Get a verification request for the given user with the given flow ID */
|
||||
fun getVerificationRequest(userId: String, flowId: String): VerificationRequest? {
|
||||
return inner.getVerificationRequest(userId, flowId)?.let { innerVerificationRequest ->
|
||||
verificationRequestFactory.create(innerVerificationRequest)
|
||||
}
|
||||
return verificationsProvider.getVerificationRequest(userId, flowId)
|
||||
}
|
||||
|
||||
/** Get an active verification for the given user and given flow ID.
|
||||
@ -708,48 +678,7 @@ internal class OlmMachine(
|
||||
* verification.
|
||||
*/
|
||||
fun getVerification(userId: String, flowId: String): VerificationTransaction? {
|
||||
return when (val verification = inner.getVerification(userId, flowId)) {
|
||||
is uniffi.olm.Verification.QrCodeV1 -> {
|
||||
val request = getVerificationRequest(userId, flowId) ?: return null
|
||||
QrCodeVerification(
|
||||
machine = inner,
|
||||
request = request,
|
||||
inner = verification.qrcode,
|
||||
sender = requestSender,
|
||||
coroutineDispatchers = coroutineDispatchers,
|
||||
listeners = verificationListeners
|
||||
)
|
||||
}
|
||||
is uniffi.olm.Verification.SasV1 -> {
|
||||
SasVerification(
|
||||
machine = inner,
|
||||
inner = verification.sas,
|
||||
sender = requestSender,
|
||||
coroutineDispatchers = coroutineDispatchers,
|
||||
listeners = verificationListeners
|
||||
)
|
||||
}
|
||||
null -> {
|
||||
// This branch exists because scanning a QR code is tied to the QrCodeVerification,
|
||||
// i.e. instead of branching into a scanned QR code verification from the verification request,
|
||||
// like it's done for SAS verifications, the public API expects us to create an empty dummy
|
||||
// QrCodeVerification object that gets populated once a QR code is scanned.
|
||||
val request = getVerificationRequest(userId, flowId) ?: return null
|
||||
|
||||
if (request.canScanQrCodes()) {
|
||||
QrCodeVerification(
|
||||
machine = inner,
|
||||
request = request,
|
||||
inner = null,
|
||||
sender = requestSender,
|
||||
coroutineDispatchers = coroutineDispatchers,
|
||||
listeners = verificationListeners
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
return verificationsProvider.getVerification(userId, flowId)
|
||||
}
|
||||
|
||||
suspend fun bootstrapCrossSigning(uiaInterceptor: UserInteractiveAuthInterceptor?) {
|
||||
@ -868,13 +797,4 @@ internal class OlmMachine(
|
||||
inner.verifyBackup(serializedAuthData)
|
||||
}
|
||||
}
|
||||
|
||||
private fun uniffi.olm.Device.wrap() = Device(
|
||||
innerMachine = inner,
|
||||
innerDevice = this,
|
||||
requestSender = requestSender,
|
||||
coroutineDispatchers = coroutineDispatchers,
|
||||
listeners = verificationListeners,
|
||||
verificationRequestFactory = verificationRequestFactory
|
||||
)
|
||||
}
|
||||
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.crypto
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||
import org.matrix.android.sdk.internal.di.DeviceId
|
||||
import org.matrix.android.sdk.internal.di.SessionFilesDirectory
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.SessionScope
|
||||
import org.matrix.android.sdk.internal.util.time.Clock
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
@SessionScope
|
||||
internal class OlmMachineProvider @Inject constructor(
|
||||
@UserId userId: String,
|
||||
@DeviceId deviceId: String?,
|
||||
@SessionFilesDirectory dataDir: File,
|
||||
requestSender: RequestSender,
|
||||
coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
moshi: Moshi,
|
||||
clock: Clock
|
||||
) {
|
||||
|
||||
val olmMachine: OlmMachine by lazy {
|
||||
OlmMachine(
|
||||
user_id = userId,
|
||||
device_id = deviceId!!,
|
||||
path = dataDir,
|
||||
clock = clock,
|
||||
requestSender = requestSender,
|
||||
coroutineDispatchers = coroutineDispatchers,
|
||||
moshi = moshi
|
||||
)
|
||||
}
|
||||
}
|
@ -39,17 +39,16 @@ import javax.inject.Inject
|
||||
private val loggerTag = LoggerTag("PrepareToEncryptUseCase", LoggerTag.CRYPTO)
|
||||
|
||||
@SessionScope
|
||||
internal class PrepareToEncryptUseCase @Inject constructor(olmMachineProvider: OlmMachineProvider,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val cryptoStore: IMXCryptoStore,
|
||||
private val getRoomUserIds: GetRoomUserIdsUseCase,
|
||||
private val requestSender: RequestSender,
|
||||
private val loadRoomMembersTask: LoadRoomMembersTask,
|
||||
private val keysBackupService: RustKeyBackupService
|
||||
internal class PrepareToEncryptUseCase @Inject constructor(
|
||||
private val olmMachine: OlmMachine,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val cryptoStore: IMXCryptoStore,
|
||||
private val getRoomUserIds: GetRoomUserIdsUseCase,
|
||||
private val requestSender: RequestSender,
|
||||
private val loadRoomMembersTask: LoadRoomMembersTask,
|
||||
private val keysBackupService: RustKeyBackupService
|
||||
) {
|
||||
|
||||
private val olmMachine = olmMachineProvider.olmMachine
|
||||
|
||||
private val keyClaimLock: Mutex = Mutex()
|
||||
private val roomKeyShareLocks: ConcurrentHashMap<String, Mutex> = ConcurrentHashMap()
|
||||
|
||||
@ -91,7 +90,7 @@ internal class PrepareToEncryptUseCase @Inject constructor(olmMachineProvider: O
|
||||
is Request.ToDevice -> {
|
||||
sharedKey = true
|
||||
async {
|
||||
sendToDevice(it)
|
||||
sendToDevice(olmMachine, it)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
@ -113,7 +112,7 @@ internal class PrepareToEncryptUseCase @Inject constructor(olmMachineProvider: O
|
||||
}
|
||||
|
||||
private suspend fun claimMissingKeys(roomMembers: List<String>) = keyClaimLock.withLock {
|
||||
val request = this.olmMachine.getMissingSessions(roomMembers)
|
||||
val request = olmMachine.getMissingSessions(roomMembers)
|
||||
// This request can only be a keys claim request.
|
||||
when (request) {
|
||||
is Request.KeysClaim -> {
|
||||
@ -124,7 +123,7 @@ internal class PrepareToEncryptUseCase @Inject constructor(olmMachineProvider: O
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun sendToDevice(request: Request.ToDevice) {
|
||||
private suspend fun sendToDevice(olmMachine: OlmMachine, request: Request.ToDevice) {
|
||||
try {
|
||||
requestSender.sendToDevice(request)
|
||||
olmMachine.markRequestAsSent(request.requestId, RequestType.TO_DEVICE, "{}")
|
||||
|
@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.crypto
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.CrossSigningService
|
||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustResult
|
||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
|
||||
@ -27,17 +26,13 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.UserTrustResult
|
||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified
|
||||
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class RustCrossSigningService @Inject constructor(
|
||||
// @SessionId private val sessionId: String,
|
||||
@UserId private val myUserId: String,
|
||||
private val olmMachineProvider: OlmMachineProvider
|
||||
private val olmMachine: OlmMachine,
|
||||
private val computeShieldForGroup: ComputeShieldForGroupUseCase
|
||||
) : CrossSigningService {
|
||||
|
||||
val olmMachine = olmMachineProvider.olmMachine
|
||||
|
||||
/**
|
||||
* Is our own device signed by our own cross signing identity
|
||||
*/
|
||||
@ -211,44 +206,6 @@ internal class RustCrossSigningService @Inject constructor(
|
||||
}
|
||||
|
||||
override suspend fun shieldForGroup(userIds: List<String>): RoomEncryptionTrustLevel {
|
||||
val myIdentity = olmMachine.getIdentity(myUserId)
|
||||
val allTrustedUserIds = userIds
|
||||
.filter { userId ->
|
||||
olmMachine.getIdentity(userId)?.verified() == true
|
||||
}
|
||||
|
||||
return if (allTrustedUserIds.isEmpty()) {
|
||||
RoomEncryptionTrustLevel.Default
|
||||
} else {
|
||||
// If one of the verified user as an untrusted device -> warning
|
||||
// If all devices of all verified users are trusted -> green
|
||||
// else -> black
|
||||
allTrustedUserIds
|
||||
.map { userId ->
|
||||
olmMachineProvider.olmMachine.getUserDevices(userId)
|
||||
}
|
||||
.flatten()
|
||||
.let { allDevices ->
|
||||
if (myIdentity != null) {
|
||||
allDevices.any { !it.toCryptoDeviceInfo().trustLevel?.crossSigningVerified.orFalse() }
|
||||
} else {
|
||||
// TODO check that if myIdentity is null ean
|
||||
// Legacy method
|
||||
allDevices.any { !it.toCryptoDeviceInfo().isVerified }
|
||||
}
|
||||
}
|
||||
.let { hasWarning ->
|
||||
if (hasWarning) {
|
||||
RoomEncryptionTrustLevel.Warning
|
||||
} else {
|
||||
if (userIds.size == allTrustedUserIds.size) {
|
||||
// all users are trusted and all devices are verified
|
||||
RoomEncryptionTrustLevel.Trusted
|
||||
} else {
|
||||
RoomEncryptionTrustLevel.Default
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return computeShieldForGroup(olmMachine, userIds)
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequest
|
||||
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequestFactory
|
||||
import org.matrix.android.sdk.internal.crypto.verification.prepareMethods
|
||||
import uniffi.olm.CryptoStoreException
|
||||
import uniffi.olm.OlmMachine
|
||||
@ -85,7 +84,7 @@ internal class OwnUserIdentity(
|
||||
private val innerMachine: OlmMachine,
|
||||
private val requestSender: RequestSender,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val verificationRequestFactory: VerificationRequestFactory,
|
||||
private val verificationRequestFactory: VerificationRequest.Factory,
|
||||
) : UserIdentities() {
|
||||
/**
|
||||
* Our own user id.
|
||||
@ -174,7 +173,7 @@ internal class UserIdentity(
|
||||
private val innerMachine: OlmMachine,
|
||||
private val requestSender: RequestSender,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val verificationRequestFactory: VerificationRequestFactory,
|
||||
private val verificationRequestFactory: VerificationRequest.Factory,
|
||||
) : UserIdentities() {
|
||||
/**
|
||||
* The unique ID of the user that this identity belongs to.
|
||||
|
@ -49,7 +49,7 @@ import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
|
||||
import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult
|
||||
import org.matrix.android.sdk.internal.crypto.MegolmSessionData
|
||||
import org.matrix.android.sdk.internal.crypto.MegolmSessionImportManager
|
||||
import org.matrix.android.sdk.internal.crypto.OlmMachineProvider
|
||||
import org.matrix.android.sdk.internal.crypto.OlmMachine
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.SignalableMegolmBackupAuthData
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.CreateKeysBackupVersionBody
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeyBackupData
|
||||
@ -73,7 +73,7 @@ import kotlin.random.Random
|
||||
*/
|
||||
@SessionScope
|
||||
internal class RustKeyBackupService @Inject constructor(
|
||||
olmMachineProvider: OlmMachineProvider,
|
||||
private val olmMachine: OlmMachine,
|
||||
private val sender: RequestSender,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val megolmSessionImportManager: MegolmSessionImportManager,
|
||||
@ -88,8 +88,6 @@ internal class RustKeyBackupService @Inject constructor(
|
||||
|
||||
private val keysBackupStateManager = KeysBackupStateManager(uiHandler)
|
||||
|
||||
private val olmMachine = olmMachineProvider.olmMachine
|
||||
|
||||
// The backup version
|
||||
override var keysBackupVersion: KeysVersionResult? = null
|
||||
private set
|
||||
|
@ -18,38 +18,43 @@ package org.matrix.android.sdk.internal.crypto.network
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.joinAll
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import org.matrix.android.sdk.api.logger.LoggerTag
|
||||
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.internal.crypto.ComputeShieldForGroupUseCase
|
||||
import org.matrix.android.sdk.internal.crypto.CryptoSessionInfoProvider
|
||||
import org.matrix.android.sdk.internal.crypto.OlmMachine
|
||||
import org.matrix.android.sdk.internal.session.SessionScope
|
||||
import timber.log.Timber
|
||||
import uniffi.olm.Request
|
||||
import uniffi.olm.RequestType
|
||||
import javax.inject.Inject
|
||||
|
||||
private val loggerTag = LoggerTag("OutgoingRequestsProcessor", LoggerTag.CRYPTO)
|
||||
|
||||
internal class OutgoingRequestsProcessor(private val requestSender: RequestSender,
|
||||
private val coroutineScope: CoroutineScope,
|
||||
private val cryptoSessionInfoProvider: CryptoSessionInfoProvider,
|
||||
private val shieldComputer: ShieldComputer,) {
|
||||
|
||||
fun interface ShieldComputer {
|
||||
suspend fun compute(userIds: List<String>): RoomEncryptionTrustLevel
|
||||
}
|
||||
@SessionScope
|
||||
internal class OutgoingRequestsProcessor @Inject constructor(
|
||||
private val requestSender: RequestSender,
|
||||
private val coroutineScope: CoroutineScope,
|
||||
private val cryptoSessionInfoProvider: CryptoSessionInfoProvider,
|
||||
private val computeShieldForGroup: ComputeShieldForGroupUseCase
|
||||
) {
|
||||
|
||||
private val lock: Mutex = Mutex()
|
||||
|
||||
suspend fun processOutgoingRequests(olmMachine: OlmMachine) {
|
||||
lock.withLock {
|
||||
suspend fun processOutgoingRequests(olmMachine: OlmMachine,
|
||||
filter: (Request) -> Boolean = { true }
|
||||
): Boolean {
|
||||
return lock.withLock {
|
||||
coroutineScope {
|
||||
Timber.v("OutgoingRequests: ${olmMachine.outgoingRequests()}")
|
||||
olmMachine.outgoingRequests().map {
|
||||
val outgoingRequests = olmMachine.outgoingRequests()
|
||||
val filteredOutgoingRequests = outgoingRequests.filter(filter)
|
||||
Timber.v("OutgoingRequests to process: $filteredOutgoingRequests}")
|
||||
filteredOutgoingRequests.map {
|
||||
when (it) {
|
||||
is Request.KeysUpload -> {
|
||||
async {
|
||||
@ -85,10 +90,11 @@ internal class OutgoingRequestsProcessor(private val requestSender: RequestSende
|
||||
async {
|
||||
// The rust-sdk won't ever produce KeysBackup requests here,
|
||||
// those only get explicitly created.
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}.joinAll()
|
||||
}.awaitAll().all { it }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -112,66 +118,78 @@ internal class OutgoingRequestsProcessor(private val requestSender: RequestSende
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun uploadKeys(olmMachine: OlmMachine, request: Request.KeysUpload) {
|
||||
try {
|
||||
private suspend fun uploadKeys(olmMachine: OlmMachine, request: Request.KeysUpload): Boolean {
|
||||
return try {
|
||||
val response = requestSender.uploadKeys(request)
|
||||
olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_UPLOAD, response)
|
||||
true
|
||||
} catch (throwable: Throwable) {
|
||||
Timber.tag(loggerTag.value).e(throwable, "## uploadKeys(): error")
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun queryKeys(olmMachine: OlmMachine, request: Request.KeysQuery) {
|
||||
try {
|
||||
private suspend fun queryKeys(olmMachine: OlmMachine, request: Request.KeysQuery): Boolean {
|
||||
return try {
|
||||
val response = requestSender.queryKeys(request)
|
||||
olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_QUERY, response)
|
||||
coroutineScope.updateShields(request.users)
|
||||
coroutineScope.updateShields(olmMachine, request.users)
|
||||
true
|
||||
} catch (throwable: Throwable) {
|
||||
Timber.tag(loggerTag.value).e(throwable, "## queryKeys(): error")
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun CoroutineScope.updateShields(userIds: List<String>) = launch {
|
||||
private fun CoroutineScope.updateShields(olmMachine: OlmMachine, userIds: List<String>) = launch {
|
||||
cryptoSessionInfoProvider.getRoomsWhereUsersAreParticipating(userIds).forEach { roomId ->
|
||||
val userGroup = cryptoSessionInfoProvider.getUserListForShieldComputation(roomId)
|
||||
val shield = shieldComputer.compute(userGroup)
|
||||
val shield = computeShieldForGroup(olmMachine, userGroup)
|
||||
cryptoSessionInfoProvider.updateShieldForRoom(roomId, shield)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun sendToDevice(olmMachine: OlmMachine, request: Request.ToDevice) {
|
||||
try {
|
||||
private suspend fun sendToDevice(olmMachine: OlmMachine, request: Request.ToDevice): Boolean {
|
||||
return try {
|
||||
requestSender.sendToDevice(request)
|
||||
olmMachine.markRequestAsSent(request.requestId, RequestType.TO_DEVICE, "{}")
|
||||
true
|
||||
} catch (throwable: Throwable) {
|
||||
Timber.tag(loggerTag.value).e(throwable, "## sendToDevice(): error")
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun claimKeys(olmMachine: OlmMachine, request: Request.KeysClaim) {
|
||||
try {
|
||||
private suspend fun claimKeys(olmMachine: OlmMachine, request: Request.KeysClaim): Boolean {
|
||||
return try {
|
||||
val response = requestSender.claimKeys(request)
|
||||
olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_CLAIM, response)
|
||||
true
|
||||
} catch (throwable: Throwable) {
|
||||
Timber.tag(loggerTag.value).e(throwable, "## claimKeys(): error")
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun signatureUpload(olmMachine: OlmMachine, request: Request.SignatureUpload) {
|
||||
try {
|
||||
private suspend fun signatureUpload(olmMachine: OlmMachine, request: Request.SignatureUpload): Boolean {
|
||||
return try {
|
||||
val response = requestSender.sendSignatureUpload(request)
|
||||
olmMachine.markRequestAsSent(request.requestId, RequestType.SIGNATURE_UPLOAD, response)
|
||||
true
|
||||
} catch (throwable: Throwable) {
|
||||
Timber.tag(loggerTag.value).e(throwable, "## signatureUpload(): error")
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun sendRoomMessage(olmMachine: OlmMachine, request: Request.RoomMessage) {
|
||||
try {
|
||||
private suspend fun sendRoomMessage(olmMachine: OlmMachine, request: Request.RoomMessage): Boolean {
|
||||
return try {
|
||||
val response = requestSender.sendRoomMessage(request)
|
||||
olmMachine.markRequestAsSent(request.requestId, RequestType.ROOM_MESSAGE, response)
|
||||
true
|
||||
} catch (throwable: Throwable) {
|
||||
Timber.tag(loggerTag.value).e(throwable, "## sendRoomMessage(): error")
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ internal class RealmCryptoStore @Inject constructor(
|
||||
@CryptoDatabase private val realmConfiguration: RealmConfiguration,
|
||||
private val crossSigningKeysMapper: CrossSigningKeysMapper,
|
||||
@UserId private val userId: String,
|
||||
@DeviceId private val deviceId: String?,
|
||||
@DeviceId private val deviceId: String,
|
||||
private val clock: Clock,
|
||||
) : IMXCryptoStore {
|
||||
|
||||
@ -155,7 +155,7 @@ internal class RealmCryptoStore @Inject constructor(
|
||||
// The device id may not have been provided in credentials.
|
||||
// Check it only if provided, else trust the stored one.
|
||||
if (currentMetadata.userId != userId ||
|
||||
(deviceId != null && deviceId != currentMetadata.deviceId)) {
|
||||
(deviceId != currentMetadata.deviceId)) {
|
||||
Timber.w("## open() : Credentials do not match, close this store and delete data")
|
||||
deleteAll = true
|
||||
currentMetadata = null
|
||||
|
@ -28,7 +28,7 @@ import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageRelationContent
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
||||
import org.matrix.android.sdk.internal.crypto.OlmMachineProvider
|
||||
import org.matrix.android.sdk.internal.crypto.OlmMachine
|
||||
import org.matrix.android.sdk.internal.crypto.OwnUserIdentity
|
||||
import org.matrix.android.sdk.internal.crypto.UserIdentity
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SCAN
|
||||
@ -70,13 +70,9 @@ internal fun prepareMethods(methods: List<VerificationMethod>): List<String> {
|
||||
}
|
||||
|
||||
@SessionScope
|
||||
internal class RustVerificationService @Inject constructor(private val olmMachineProvider: OlmMachineProvider) : VerificationService {
|
||||
|
||||
val olmMachine by lazy {
|
||||
olmMachineProvider.olmMachine
|
||||
}
|
||||
|
||||
private val dispatcher = UpdateDispatcher(olmMachine.verificationListeners)
|
||||
internal class RustVerificationService @Inject constructor(
|
||||
private val olmMachine: OlmMachine,
|
||||
private val verificationListenersHolder: VerificationListenersHolder) : VerificationService {
|
||||
|
||||
/**
|
||||
*
|
||||
@ -121,7 +117,7 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
|
||||
|
||||
olmMachine.getVerificationRequest(sender, flowId)?.dispatchRequestUpdated()
|
||||
val verification = getExistingTransaction(sender, flowId) ?: return
|
||||
dispatcher.dispatchTxUpdated(verification)
|
||||
verificationListenersHolder.dispatchTxUpdated(verification)
|
||||
}
|
||||
|
||||
/** Check if the start event created new verification objects and dispatch updates */
|
||||
@ -141,15 +137,15 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
|
||||
Timber.d("## Verification: Auto accepting SAS verification with $sender")
|
||||
verification.accept()
|
||||
} else {
|
||||
dispatcher.dispatchTxUpdated(verification)
|
||||
verificationListenersHolder.dispatchTxUpdated(verification)
|
||||
}
|
||||
} else {
|
||||
// This didn't originate from a request, so tell our listeners that
|
||||
// this is a new verification.
|
||||
dispatcher.dispatchTxAdded(verification)
|
||||
verificationListenersHolder.dispatchTxAdded(verification)
|
||||
// The IncomingVerificationRequestHandler seems to only listen to updates
|
||||
// so let's trigger an update after the addition as well.
|
||||
dispatcher.dispatchTxUpdated(verification)
|
||||
verificationListenersHolder.dispatchTxUpdated(verification)
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,15 +159,15 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
|
||||
val sender = event.senderId ?: return
|
||||
val request = getExistingVerificationRequest(sender, flowId) ?: return
|
||||
|
||||
dispatcher.dispatchRequestAdded(request)
|
||||
verificationListenersHolder.dispatchRequestAdded(request)
|
||||
}
|
||||
|
||||
override fun addListener(listener: VerificationService.Listener) {
|
||||
dispatcher.addListener(listener)
|
||||
verificationListenersHolder.addListener(listener)
|
||||
}
|
||||
|
||||
override fun removeListener(listener: VerificationService.Listener) {
|
||||
dispatcher.removeListener(listener)
|
||||
verificationListenersHolder.removeListener(listener)
|
||||
}
|
||||
|
||||
override suspend fun markedLocallyAsManuallyVerified(userId: String, deviceID: String) {
|
||||
@ -275,7 +271,7 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
|
||||
val qrcode = request.startQrVerification()
|
||||
|
||||
if (qrcode != null) {
|
||||
dispatcher.dispatchTxAdded(qrcode)
|
||||
verificationListenersHolder.dispatchTxAdded(qrcode)
|
||||
}
|
||||
|
||||
true
|
||||
@ -298,7 +294,7 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
|
||||
val sas = request?.startSasVerification()
|
||||
|
||||
if (sas != null) {
|
||||
dispatcher.dispatchTxAdded(sas)
|
||||
verificationListenersHolder.dispatchTxAdded(sas)
|
||||
sas.transactionId
|
||||
} else {
|
||||
null
|
||||
@ -317,7 +313,7 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
|
||||
val otherDevice = olmMachine.getDevice(otherUserId, otherDeviceId)
|
||||
val verification = otherDevice?.startVerification()
|
||||
return if (verification != null) {
|
||||
dispatcher.dispatchTxAdded(verification)
|
||||
verificationListenersHolder.dispatchTxAdded(verification)
|
||||
verification.transactionId
|
||||
} else {
|
||||
null
|
||||
|
@ -16,34 +16,42 @@
|
||||
|
||||
package org.matrix.android.sdk.internal.crypto.verification
|
||||
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.EmojiRepresentation
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.safeValueOf
|
||||
import org.matrix.android.sdk.internal.crypto.OlmMachine
|
||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||
import uniffi.olm.CryptoStoreException
|
||||
import uniffi.olm.OlmMachine
|
||||
import uniffi.olm.Sas
|
||||
import uniffi.olm.Verification
|
||||
|
||||
/** Class representing a short auth string verification flow */
|
||||
internal class SasVerification(
|
||||
private val machine: OlmMachine,
|
||||
private var inner: Sas,
|
||||
internal class SasVerification @AssistedInject constructor(
|
||||
@Assisted private var inner: Sas,
|
||||
private val olmMachine: OlmMachine,
|
||||
private val sender: RequestSender,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
listeners: ArrayList<VerificationService.Listener>
|
||||
private val verificationListenersHolder: VerificationListenersHolder
|
||||
) :
|
||||
SasVerificationTransaction {
|
||||
private val dispatcher = UpdateDispatcher(listeners)
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(inner: Sas): SasVerification
|
||||
}
|
||||
|
||||
private val innerMachine = olmMachine.inner()
|
||||
|
||||
private fun dispatchTxUpdated() {
|
||||
refreshData()
|
||||
dispatcher.dispatchTxUpdated(this)
|
||||
verificationListenersHolder.dispatchTxUpdated(this)
|
||||
}
|
||||
|
||||
/** The user ID of the other user that is participating in this verification flow */
|
||||
@ -167,7 +175,7 @@ internal class SasVerification(
|
||||
* in a presentable state.
|
||||
*/
|
||||
override fun getDecimalCodeRepresentation(): String {
|
||||
val decimals = machine.getDecimals(inner.otherUserId, inner.flowId)
|
||||
val decimals = innerMachine.getDecimals(inner.otherUserId, inner.flowId)
|
||||
|
||||
return decimals?.joinToString(" ") ?: ""
|
||||
}
|
||||
@ -179,13 +187,13 @@ internal class SasVerification(
|
||||
* state.
|
||||
*/
|
||||
override fun getEmojiCodeRepresentation(): List<EmojiRepresentation> {
|
||||
val emojiIndex = machine.getEmojiIndex(inner.otherUserId, inner.flowId)
|
||||
val emojiIndex = innerMachine.getEmojiIndex(inner.otherUserId, inner.flowId)
|
||||
|
||||
return emojiIndex?.map { getEmojiForCode(it) } ?: listOf()
|
||||
}
|
||||
|
||||
internal suspend fun accept() {
|
||||
val request = machine.acceptSasVerification(inner.otherUserId, inner.flowId)
|
||||
val request = innerMachine.acceptSasVerification(inner.otherUserId, inner.flowId)
|
||||
|
||||
if (request != null) {
|
||||
sender.sendVerificationRequest(request)
|
||||
@ -196,7 +204,7 @@ internal class SasVerification(
|
||||
@Throws(CryptoStoreException::class)
|
||||
private suspend fun confirm() {
|
||||
val result = withContext(coroutineDispatchers.io) {
|
||||
machine.confirmVerification(inner.otherUserId, inner.flowId)
|
||||
innerMachine.confirmVerification(inner.otherUserId, inner.flowId)
|
||||
}
|
||||
if (result != null) {
|
||||
for (verificationRequest in result.requests) {
|
||||
@ -211,7 +219,7 @@ internal class SasVerification(
|
||||
}
|
||||
|
||||
private suspend fun cancelHelper(code: CancelCode) {
|
||||
val request = machine.cancelVerification(inner.otherUserId, inner.flowId, code.value)
|
||||
val request = innerMachine.cancelVerification(inner.otherUserId, inner.flowId, code.value)
|
||||
|
||||
if (request != null) {
|
||||
sender.sendVerificationRequest(request)
|
||||
@ -221,7 +229,7 @@ internal class SasVerification(
|
||||
|
||||
/** Fetch fresh data from the Rust side for our verification flow */
|
||||
private fun refreshData() {
|
||||
when (val verification = machine.getVerification(inner.otherUserId, inner.flowId)) {
|
||||
when (val verification = innerMachine.getVerification(inner.otherUserId, inner.flowId)) {
|
||||
is Verification.SasV1 -> {
|
||||
inner = verification.sas
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,13 +21,20 @@ import android.os.Looper
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction
|
||||
import org.matrix.android.sdk.internal.session.SessionScope
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@SessionScope
|
||||
internal class VerificationListenersHolder @Inject constructor() {
|
||||
|
||||
private val listeners = ArrayList<VerificationService.Listener>()
|
||||
|
||||
/** Class that implements some common methods to dispatch updates for the verification related classes */
|
||||
internal class UpdateDispatcher(private val listeners: ArrayList<VerificationService.Listener>) {
|
||||
private val uiHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
internal fun addListener(listener: VerificationService.Listener) {
|
||||
fun listeners(): List<VerificationService.Listener> = listeners
|
||||
|
||||
fun addListener(listener: VerificationService.Listener) {
|
||||
uiHandler.post {
|
||||
if (!this.listeners.contains(listener)) {
|
||||
this.listeners.add(listener)
|
||||
@ -35,11 +42,11 @@ internal class UpdateDispatcher(private val listeners: ArrayList<VerificationSer
|
||||
}
|
||||
}
|
||||
|
||||
internal fun removeListener(listener: VerificationService.Listener) {
|
||||
fun removeListener(listener: VerificationService.Listener) {
|
||||
uiHandler.post { this.listeners.remove(listener) }
|
||||
}
|
||||
|
||||
internal fun dispatchTxAdded(tx: VerificationTransaction) {
|
||||
fun dispatchTxAdded(tx: VerificationTransaction) {
|
||||
uiHandler.post {
|
||||
this.listeners.forEach {
|
||||
try {
|
||||
@ -51,7 +58,7 @@ internal class UpdateDispatcher(private val listeners: ArrayList<VerificationSer
|
||||
}
|
||||
}
|
||||
|
||||
internal fun dispatchTxUpdated(tx: VerificationTransaction) {
|
||||
fun dispatchTxUpdated(tx: VerificationTransaction) {
|
||||
uiHandler.post {
|
||||
this.listeners.forEach {
|
||||
try {
|
||||
@ -63,12 +70,24 @@ internal class UpdateDispatcher(private val listeners: ArrayList<VerificationSer
|
||||
}
|
||||
}
|
||||
|
||||
internal fun dispatchRequestAdded(tx: PendingVerificationRequest) {
|
||||
Timber.v("## SAS dispatchRequestAdded txId:${tx.transactionId} $tx")
|
||||
fun dispatchRequestAdded(verificationRequest: PendingVerificationRequest) {
|
||||
Timber.v("## SAS dispatchRequestAdded txId:${verificationRequest.transactionId} $verificationRequest")
|
||||
uiHandler.post {
|
||||
this.listeners.forEach {
|
||||
try {
|
||||
it.verificationRequestCreated(tx)
|
||||
it.verificationRequestCreated(verificationRequest)
|
||||
} catch (e: Throwable) {
|
||||
Timber.e(e, "## Error while notifying listeners")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun dispatchRequestUpdated(verificationRequest: PendingVerificationRequest) {
|
||||
uiHandler.post {
|
||||
listeners.forEach {
|
||||
try {
|
||||
it.verificationRequestUpdated(verificationRequest)
|
||||
} catch (e: Throwable) {
|
||||
Timber.e(e, "## Error while notifying listeners")
|
||||
}
|
@ -16,8 +16,9 @@
|
||||
|
||||
package org.matrix.android.sdk.internal.crypto.verification
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
|
||||
@ -25,16 +26,14 @@ import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificatio
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.ValidVerificationInfoReady
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.ValidVerificationInfoRequest
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.safeValueOf
|
||||
import org.matrix.android.sdk.api.util.toBase64NoPadding
|
||||
import org.matrix.android.sdk.internal.crypto.OlmMachine
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SCAN
|
||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||
import org.matrix.android.sdk.internal.crypto.verification.qrcode.QrCodeVerification
|
||||
import org.matrix.android.sdk.internal.util.time.Clock
|
||||
import timber.log.Timber
|
||||
import uniffi.olm.OlmMachine
|
||||
import uniffi.olm.VerificationRequest
|
||||
import uniffi.olm.VerificationRequest as InnerVerificationRequest
|
||||
|
||||
/** A verification request object
|
||||
*
|
||||
@ -43,26 +42,27 @@ import uniffi.olm.VerificationRequest
|
||||
* Once the VerificationRequest gets to a ready state users can transition into the different
|
||||
* concrete verification flows.
|
||||
*/
|
||||
internal class VerificationRequest(
|
||||
private val innerOlmMachine: OlmMachine,
|
||||
private var innerVerificationRequest: VerificationRequest,
|
||||
internal class VerificationRequest @AssistedInject constructor(
|
||||
@Assisted private var innerVerificationRequest: InnerVerificationRequest,
|
||||
olmMachine: OlmMachine,
|
||||
private val requestSender: RequestSender,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val listeners: ArrayList<VerificationService.Listener>,
|
||||
private val verificationListenersHolder: VerificationListenersHolder,
|
||||
private val sasVerificationFactory: SasVerification.Factory,
|
||||
private val qrCodeVerificationFactory: QrCodeVerification.Factory,
|
||||
private val clock: Clock,
|
||||
) {
|
||||
private val uiHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
private val innerOlmMachine = olmMachine.inner()
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(innerVerificationRequest: InnerVerificationRequest): VerificationRequest
|
||||
}
|
||||
|
||||
internal fun dispatchRequestUpdated() {
|
||||
uiHandler.post {
|
||||
listeners.forEach {
|
||||
try {
|
||||
it.verificationRequestUpdated(toPendingVerificationRequest())
|
||||
} catch (e: Throwable) {
|
||||
Timber.e(e, "## Error while notifying listeners")
|
||||
}
|
||||
}
|
||||
}
|
||||
val tx = toPendingVerificationRequest()
|
||||
verificationListenersHolder.dispatchRequestUpdated(tx)
|
||||
}
|
||||
|
||||
/** Get the flow ID of this verification request
|
||||
@ -167,7 +167,7 @@ internal class VerificationRequest(
|
||||
|
||||
if (result != null) {
|
||||
requestSender.sendVerificationRequest(result.request)
|
||||
SasVerification(innerOlmMachine, result.sas, requestSender, coroutineDispatchers, listeners)
|
||||
sasVerificationFactory.create(result.sas)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
@ -194,7 +194,7 @@ internal class VerificationRequest(
|
||||
val result = innerOlmMachine.scanQrCode(otherUser(), flowId(), encodedData) ?: return null
|
||||
|
||||
requestSender.sendVerificationRequest(result.request)
|
||||
return QrCodeVerification(innerOlmMachine, this, result.qr, requestSender, coroutineDispatchers, listeners)
|
||||
return qrCodeVerificationFactory.create(this, result.qr)
|
||||
}
|
||||
|
||||
/** Transition into a QR code verification to display a QR code
|
||||
@ -216,16 +216,8 @@ internal class VerificationRequest(
|
||||
*/
|
||||
internal fun startQrVerification(): QrCodeVerification? {
|
||||
val qrcode = innerOlmMachine.startQrVerification(innerVerificationRequest.otherUserId, innerVerificationRequest.flowId)
|
||||
|
||||
return if (qrcode != null) {
|
||||
QrCodeVerification(
|
||||
machine = innerOlmMachine,
|
||||
request = this,
|
||||
inner = qrcode,
|
||||
sender = requestSender,
|
||||
coroutineDispatchers = coroutineDispatchers,
|
||||
listeners = listeners,
|
||||
)
|
||||
qrCodeVerificationFactory.create(this, qrcode)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.crypto.verification
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
|
||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||
import org.matrix.android.sdk.internal.util.time.Clock
|
||||
import uniffi.olm.OlmMachine
|
||||
|
||||
internal class VerificationRequestFactory(
|
||||
private val innerOlmMachine: OlmMachine,
|
||||
private val requestSender: RequestSender,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val listeners: ArrayList<VerificationService.Listener>,
|
||||
private val clock: Clock,
|
||||
) {
|
||||
|
||||
fun create(inner: uniffi.olm.VerificationRequest): VerificationRequest {
|
||||
return VerificationRequest(
|
||||
innerOlmMachine = innerOlmMachine,
|
||||
innerVerificationRequest = inner,
|
||||
requestSender = requestSender,
|
||||
coroutineDispatchers = coroutineDispatchers,
|
||||
listeners = listeners,
|
||||
clock = clock
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.crypto.verification
|
||||
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction
|
||||
import org.matrix.android.sdk.internal.crypto.OlmMachine
|
||||
import org.matrix.android.sdk.internal.crypto.verification.qrcode.QrCodeVerification
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Provider
|
||||
import uniffi.olm.OlmMachine as InnerOlmMachine
|
||||
|
||||
internal class VerificationsProvider @Inject constructor(
|
||||
private val olmMachine: Provider<OlmMachine>,
|
||||
private val verificationRequestFactory: VerificationRequest.Factory,
|
||||
private val sasVerificationFactory: SasVerification.Factory,
|
||||
private val qrVerificationFactory: QrCodeVerification.Factory) {
|
||||
|
||||
private val innerMachine: InnerOlmMachine
|
||||
get() = olmMachine.get().inner()
|
||||
|
||||
fun getVerificationRequests(userId: String): List<VerificationRequest> {
|
||||
return innerMachine.getVerificationRequests(userId).map(verificationRequestFactory::create)
|
||||
}
|
||||
|
||||
/** Get a verification request for the given user with the given flow ID */
|
||||
fun getVerificationRequest(userId: String, flowId: String): VerificationRequest? {
|
||||
return innerMachine.getVerificationRequest(userId, flowId)?.let { innerVerificationRequest ->
|
||||
verificationRequestFactory.create(innerVerificationRequest)
|
||||
}
|
||||
}
|
||||
|
||||
/** Get an active verification for the given user and given flow ID.
|
||||
*
|
||||
* @return Either a [SasVerification] verification or a [QrCodeVerification]
|
||||
* verification.
|
||||
*/
|
||||
fun getVerification(userId: String, flowId: String): VerificationTransaction? {
|
||||
return when (val verification = innerMachine.getVerification(userId, flowId)) {
|
||||
is uniffi.olm.Verification.QrCodeV1 -> {
|
||||
val request = getVerificationRequest(userId, flowId) ?: return null
|
||||
qrVerificationFactory.create(request, verification.qrcode)
|
||||
}
|
||||
is uniffi.olm.Verification.SasV1 -> {
|
||||
sasVerificationFactory.create(verification.sas)
|
||||
}
|
||||
null -> {
|
||||
// This branch exists because scanning a QR code is tied to the QrCodeVerification,
|
||||
// i.e. instead of branching into a scanned QR code verification from the verification request,
|
||||
// like it's done for SAS verifications, the public API expects us to create an empty dummy
|
||||
// QrCodeVerification object that gets populated once a QR code is scanned.
|
||||
val request = getVerificationRequest(userId, flowId) ?: return null
|
||||
if (request.canScanQrCodes()) {
|
||||
qrVerificationFactory.create(request, null)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -16,37 +16,44 @@
|
||||
|
||||
package org.matrix.android.sdk.internal.crypto.verification.qrcode
|
||||
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.QrCodeVerificationTransaction
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.safeValueOf
|
||||
import org.matrix.android.sdk.api.util.fromBase64
|
||||
import org.matrix.android.sdk.internal.crypto.OlmMachine
|
||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||
import org.matrix.android.sdk.internal.crypto.verification.UpdateDispatcher
|
||||
import org.matrix.android.sdk.internal.crypto.verification.VerificationListenersHolder
|
||||
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequest
|
||||
import uniffi.olm.CryptoStoreException
|
||||
import uniffi.olm.OlmMachine
|
||||
import uniffi.olm.QrCode
|
||||
import uniffi.olm.Verification
|
||||
|
||||
/** Class representing a QR code based verification flow */
|
||||
internal class QrCodeVerification(
|
||||
private val machine: OlmMachine,
|
||||
private var request: VerificationRequest,
|
||||
private var inner: QrCode?,
|
||||
internal class QrCodeVerification @AssistedInject constructor(
|
||||
@Assisted private var request: VerificationRequest,
|
||||
@Assisted private var inner: QrCode?,
|
||||
private val olmMachine: OlmMachine,
|
||||
private val sender: RequestSender,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
listeners: ArrayList<VerificationService.Listener>
|
||||
private val verificationListenersHolder: VerificationListenersHolder,
|
||||
) : QrCodeVerificationTransaction {
|
||||
|
||||
private val dispatcher = UpdateDispatcher(listeners)
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(request: VerificationRequest, inner: QrCode?): QrCodeVerification
|
||||
}
|
||||
|
||||
private val innerMachine = olmMachine.inner()
|
||||
|
||||
private fun dispatchTxUpdated() {
|
||||
refreshData()
|
||||
dispatcher.dispatchTxUpdated(this)
|
||||
verificationListenersHolder.dispatchTxUpdated(this)
|
||||
}
|
||||
|
||||
/** Generate, if possible, data that should be encoded as a QR code for QR code verification.
|
||||
@ -63,7 +70,7 @@ internal class QrCodeVerification(
|
||||
*/
|
||||
override val qrCodeText: String?
|
||||
get() {
|
||||
val data = inner?.let { machine.generateQrCode(it.otherUserId, it.flowId) }
|
||||
val data = inner?.let { innerMachine.generateQrCode(it.otherUserId, it.flowId) }
|
||||
|
||||
// TODO Why are we encoding this to ISO_8859_1? If we're going to encode, why not base64?
|
||||
return data?.fromBase64()?.toString(Charsets.ISO_8859_1)
|
||||
@ -176,7 +183,7 @@ internal class QrCodeVerification(
|
||||
@Throws(CryptoStoreException::class)
|
||||
private suspend fun confirm() {
|
||||
val result = withContext(coroutineDispatchers.io) {
|
||||
machine.confirmVerification(request.otherUser(), request.flowId())
|
||||
innerMachine.confirmVerification(request.otherUser(), request.flowId())
|
||||
}
|
||||
|
||||
if (result != null) {
|
||||
@ -192,7 +199,7 @@ internal class QrCodeVerification(
|
||||
}
|
||||
|
||||
private suspend fun cancelHelper(code: CancelCode) {
|
||||
val request = machine.cancelVerification(request.otherUser(), request.flowId(), code.value)
|
||||
val request = innerMachine.cancelVerification(request.otherUser(), request.flowId(), code.value)
|
||||
|
||||
if (request != null) {
|
||||
sender.sendVerificationRequest(request)
|
||||
@ -202,7 +209,7 @@ internal class QrCodeVerification(
|
||||
|
||||
/** Fetch fresh data from the Rust side for our verification flow */
|
||||
private fun refreshData() {
|
||||
when (val verification = machine.getVerification(request.otherUser(), request.flowId())) {
|
||||
when (val verification = innerMachine.getVerification(request.otherUser(), request.flowId())) {
|
||||
is Verification.QrCodeV1 -> {
|
||||
inner = verification.qrcode
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.api.auth.data.SessionParams
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.internal.crypto.CryptoModule
|
||||
import org.matrix.android.sdk.internal.crypto.OlmMachineProvider
|
||||
import org.matrix.android.sdk.internal.crypto.OlmMachine
|
||||
import org.matrix.android.sdk.internal.di.MatrixComponent
|
||||
import org.matrix.android.sdk.internal.federation.FederationModule
|
||||
import org.matrix.android.sdk.internal.network.NetworkConnectivityChecker
|
||||
@ -113,9 +113,9 @@ internal interface SessionComponent {
|
||||
|
||||
fun networkConnectivityChecker(): NetworkConnectivityChecker
|
||||
|
||||
fun taskExecutor(): TaskExecutor
|
||||
//fun olmMachine(): OlmMachine
|
||||
|
||||
fun olmMachineProvider(): OlmMachineProvider
|
||||
fun taskExecutor(): TaskExecutor
|
||||
|
||||
fun inject(worker: SendEventWorker)
|
||||
|
||||
|
@ -142,7 +142,7 @@ internal abstract class SessionModule {
|
||||
@JvmStatic
|
||||
@DeviceId
|
||||
@Provides
|
||||
fun providesDeviceId(credentials: Credentials): String? {
|
||||
fun providesDeviceId(credentials: Credentials): String {
|
||||
return credentials.deviceId
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ import org.matrix.android.sdk.internal.util.time.Clock
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class MxCallFactory @Inject constructor(
|
||||
@DeviceId private val deviceId: String?,
|
||||
@DeviceId private val deviceId: String,
|
||||
private val localEchoEventFactory: LocalEchoEventFactory,
|
||||
private val eventSenderProcessor: EventSenderProcessor,
|
||||
private val matrixConfiguration: MatrixConfiguration,
|
||||
@ -48,7 +48,7 @@ internal class MxCallFactory @Inject constructor(
|
||||
isOutgoing = false,
|
||||
roomId = roomId,
|
||||
userId = userId,
|
||||
ourPartyId = deviceId ?: "",
|
||||
ourPartyId = deviceId,
|
||||
isVideoCall = content.isVideo(),
|
||||
localEchoEventFactory = localEchoEventFactory,
|
||||
eventSenderProcessor = eventSenderProcessor,
|
||||
@ -66,7 +66,7 @@ internal class MxCallFactory @Inject constructor(
|
||||
isOutgoing = true,
|
||||
roomId = roomId,
|
||||
userId = userId,
|
||||
ourPartyId = deviceId ?: "",
|
||||
ourPartyId = deviceId,
|
||||
isVideoCall = isVideoCall,
|
||||
localEchoEventFactory = localEchoEventFactory,
|
||||
eventSenderProcessor = eventSenderProcessor,
|
||||
|
@ -180,7 +180,7 @@ internal class CreateRoomBodyBuilder @Inject constructor(
|
||||
params.invite3pids.isEmpty() &&
|
||||
params.invitedUserIds.isNotEmpty() &&
|
||||
params.invitedUserIds.let { userIds ->
|
||||
val keys = cryptoService.downloadKeys(userIds, forceDownload = false)
|
||||
val keys = cryptoService.downloadKeysIfNeeded(userIds, forceDownload = false)
|
||||
userIds.all { userId ->
|
||||
keys.map[userId].let { deviceMap ->
|
||||
if (deviceMap.isNullOrEmpty()) {
|
||||
|
@ -39,7 +39,7 @@ import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||
import org.matrix.android.sdk.api.session.sync.model.RoomSyncSummary
|
||||
import org.matrix.android.sdk.api.session.sync.model.RoomSyncUnreadNotifications
|
||||
import org.matrix.android.sdk.internal.crypto.OlmMachineProvider
|
||||
import org.matrix.android.sdk.internal.crypto.OlmMachine
|
||||
import org.matrix.android.sdk.internal.database.mapper.ContentMapper
|
||||
import org.matrix.android.sdk.internal.database.mapper.asDomain
|
||||
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity
|
||||
@ -71,12 +71,10 @@ internal class RoomSummaryUpdater @Inject constructor(
|
||||
@UserId private val userId: String,
|
||||
private val roomDisplayNameResolver: RoomDisplayNameResolver,
|
||||
private val roomAvatarResolver: RoomAvatarResolver,
|
||||
private val olmMachineProvider: OlmMachineProvider,
|
||||
private val olmMachine: OlmMachine,
|
||||
private val roomAccountDataDataSource: RoomAccountDataDataSource
|
||||
) {
|
||||
|
||||
private val olmMachine = olmMachineProvider.olmMachine
|
||||
|
||||
fun refreshLatestPreviewContent(realm: Realm, roomId: String) {
|
||||
val roomSummaryEntity = RoomSummaryEntity.getOrNull(realm, roomId)
|
||||
if (roomSummaryEntity != null) {
|
||||
|
@ -120,7 +120,7 @@ class KeyRequestHandler @Inject constructor(
|
||||
|
||||
scope?.launch {
|
||||
try {
|
||||
val data = session?.cryptoService()?.downloadKeys(listOf(userId), false)
|
||||
val data = session?.cryptoService()?.downloadKeysIfNeeded(listOf(userId), false)
|
||||
?: return@launch
|
||||
val deviceInfo = data.getObject(userId, deviceId)
|
||||
|
||||
|
@ -243,7 +243,7 @@ class HomeActivityViewModel @AssistedInject constructor(
|
||||
val session = activeSessionHolder.getSafeActiveSession() ?: return@launch
|
||||
|
||||
tryOrNull("## MaybeBootstrapCrossSigning: Failed to download keys") {
|
||||
session.cryptoService().downloadKeys(listOf(session.myUserId), true)
|
||||
session.cryptoService().downloadKeysIfNeeded(listOf(session.myUserId), true)
|
||||
}
|
||||
|
||||
// From there we are up to date with server
|
||||
|
@ -155,7 +155,7 @@ class DevicesViewModel @AssistedInject constructor(
|
||||
refreshSource.stream().throttleFirst(4_000)
|
||||
.onEach {
|
||||
session.cryptoService().fetchDevicesList()
|
||||
session.cryptoService().downloadKeys(listOf(session.myUserId), true)
|
||||
session.cryptoService().downloadKeysIfNeeded(listOf(session.myUserId), true)
|
||||
}
|
||||
.launchIn(viewModelScope)
|
||||
// then force download
|
||||
|
Loading…
Reference in New Issue
Block a user