Some more cleanup

This commit is contained in:
ganfra 2022-05-13 18:01:53 +02:00
parent 7e49bad411
commit a559ebad64
34 changed files with 93 additions and 1156 deletions

View File

@ -44,8 +44,6 @@ import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.CryptoTestHelper
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo 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.model.rest.KeyVerificationCancel
import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationStart
import org.matrix.android.sdk.internal.crypto.model.rest.toValue import org.matrix.android.sdk.internal.crypto.model.rest.toValue
import timber.log.Timber import timber.log.Timber
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch

View File

@ -87,7 +87,7 @@ interface CryptoService {
suspend fun getCryptoDeviceInfo(userId: String, deviceId: String?): CryptoDeviceInfo? suspend fun getCryptoDeviceInfo(userId: String, deviceId: String?): CryptoDeviceInfo?
fun reRequestRoomKeyForEvent(event: Event) suspend fun reRequestRoomKeyForEvent(event: Event)
fun addRoomKeysRequestListener(listener: GossipingRequestListener) fun addRoomKeysRequestListener(listener: GossipingRequestListener)

View File

@ -17,46 +17,18 @@ package org.matrix.android.sdk.api.session.room.model.message
import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.events.model.RelationType
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoAccept
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoAcceptFactory
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
internal data class MessageVerificationAcceptContent( internal data class MessageVerificationAcceptContent(
@Json(name = "hash") override val hash: String?, @Json(name = "hash") val hash: String?,
@Json(name = "key_agreement_protocol") override val keyAgreementProtocol: String?, @Json(name = "key_agreement_protocol") val keyAgreementProtocol: String?,
@Json(name = "message_authentication_code") override val messageAuthenticationCode: String?, @Json(name = "message_authentication_code") val messageAuthenticationCode: String?,
@Json(name = "short_authentication_string") override val shortAuthenticationStrings: List<String>?, @Json(name = "short_authentication_string") val shortAuthenticationStrings: List<String>?,
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?, @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?,
@Json(name = "commitment") override var commitment: String? = null @Json(name = "commitment") var commitment: String? = null
) : VerificationInfoAccept { ) {
override val transactionId: String? val transactionId: String? = relatesTo?.eventId
get() = relatesTo?.eventId
override fun toEventContent() = toContent()
companion object : VerificationInfoAcceptFactory {
override fun create(tid: String,
keyAgreementProtocol: String,
hash: String,
commitment: String,
messageAuthenticationCode: String,
shortAuthenticationStrings: List<String>): VerificationInfoAccept {
return MessageVerificationAcceptContent(
hash,
keyAgreementProtocol,
messageAuthenticationCode,
shortAuthenticationStrings,
RelationDefaultContent(
RelationType.REFERENCE,
tid
),
commitment
)
}
}
} }

View File

@ -17,34 +17,14 @@ package org.matrix.android.sdk.api.session.room.model.message
import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
import org.matrix.android.sdk.api.session.events.model.RelationType
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoCancel
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class MessageVerificationCancelContent( data class MessageVerificationCancelContent(
@Json(name = "code") override val code: String? = null, @Json(name = "code") val code: String? = null,
@Json(name = "reason") override val reason: String? = null, @Json(name = "reason") val reason: String? = null,
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent? @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?
) : VerificationInfoCancel { ) {
override val transactionId: String? val transactionId: String? = relatesTo?.eventId
get() = relatesTo?.eventId
override fun toEventContent() = toContent()
companion object {
fun create(transactionId: String, reason: CancelCode): MessageVerificationCancelContent {
return MessageVerificationCancelContent(
reason.value,
reason.humanReadable,
RelationDefaultContent(
RelationType.REFERENCE,
transactionId
)
)
}
}
} }

View File

@ -17,30 +17,12 @@ package org.matrix.android.sdk.api.session.room.model.message
import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfo
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
internal data class MessageVerificationDoneContent( internal data class MessageVerificationDoneContent(
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent? @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?
) : VerificationInfo<ValidVerificationDone> { ) {
override val transactionId: String? val transactionId: String? = relatesTo?.eventId
get() = relatesTo?.eventId
override fun toEventContent(): Content? = toContent()
override fun asValidObject(): ValidVerificationDone? {
val validTransactionId = transactionId?.takeIf { it.isNotEmpty() } ?: return null
return ValidVerificationDone(
validTransactionId
)
} }
}
internal data class ValidVerificationDone(
val transactionId: String
)

View File

@ -17,36 +17,16 @@ package org.matrix.android.sdk.api.session.room.model.message
import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.events.model.RelationType
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoKey
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoKeyFactory
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
internal data class MessageVerificationKeyContent( internal data class MessageVerificationKeyContent(
/** /**
* The devices ephemeral public key, as an unpadded base64 string * The devices ephemeral public key, as an unpadded base64 string
*/ */
@Json(name = "key") override val key: String? = null, @Json(name = "key") val key: String? = null,
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent? @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?
) : VerificationInfoKey { ) {
override val transactionId: String? val transactionId: String? = relatesTo?.eventId
get() = relatesTo?.eventId
override fun toEventContent() = toContent()
companion object : VerificationInfoKeyFactory {
override fun create(tid: String, pubKey: String): VerificationInfoKey {
return MessageVerificationKeyContent(
pubKey,
RelationDefaultContent(
RelationType.REFERENCE,
tid
)
)
}
}
} }

View File

@ -17,34 +17,14 @@ package org.matrix.android.sdk.api.session.room.model.message
import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.events.model.RelationType
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoMac
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoMacFactory
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
internal data class MessageVerificationMacContent( internal data class MessageVerificationMacContent(
@Json(name = "mac") override val mac: Map<String, String>? = null, @Json(name = "mac") val mac: Map<String, String>? = null,
@Json(name = "keys") override val keys: String? = null, @Json(name = "keys") val keys: String? = null,
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent? @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?
) : VerificationInfoMac { ) {
override val transactionId: String? val transactionId: String? = relatesTo?.eventId
get() = relatesTo?.eventId
override fun toEventContent() = toContent()
companion object : VerificationInfoMacFactory {
override fun create(tid: String, mac: Map<String, String>, keys: String): VerificationInfoMac {
return MessageVerificationMacContent(
mac,
keys,
RelationDefaultContent(
RelationType.REFERENCE,
tid
)
)
}
}
} }

View File

@ -17,34 +17,14 @@ package org.matrix.android.sdk.api.session.room.model.message
import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.events.model.RelationType
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
import org.matrix.android.sdk.internal.crypto.verification.MessageVerificationReadyFactory
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoReady
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
internal data class MessageVerificationReadyContent( internal data class MessageVerificationReadyContent(
@Json(name = "from_device") override val fromDevice: String? = null, @Json(name = "from_device") val fromDevice: String? = null,
@Json(name = "methods") override val methods: List<String>? = null, @Json(name = "methods") val methods: List<String>? = null,
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent? @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?
) : VerificationInfoReady { ) {
override val transactionId: String? val transactionId: String? = relatesTo?.eventId
get() = relatesTo?.eventId
override fun toEventContent() = toContent()
companion object : MessageVerificationReadyFactory {
override fun create(tid: String, methods: List<String>, fromDevice: String): VerificationInfoReady {
return MessageVerificationReadyContent(
fromDevice = fromDevice,
methods = methods,
relatesTo = RelationDefaultContent(
RelationType.REFERENCE,
tid
)
)
}
}
} }

View File

@ -20,23 +20,20 @@ import com.squareup.moshi.JsonClass
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.toContent import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoRequest
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class MessageVerificationRequestContent( data class MessageVerificationRequestContent(
@Json(name = MessageContent.MSG_TYPE_JSON_KEY) override val msgType: String = MessageType.MSGTYPE_VERIFICATION_REQUEST, @Json(name = MessageContent.MSG_TYPE_JSON_KEY) override val msgType: String = MessageType.MSGTYPE_VERIFICATION_REQUEST,
@Json(name = "body") override val body: String, @Json(name = "body") override val body: String,
@Json(name = "from_device") override val fromDevice: String?, @Json(name = "from_device") val fromDevice: String?,
@Json(name = "methods") override val methods: List<String>, @Json(name = "methods") val methods: List<String>,
@Json(name = "to") val toUserId: String, @Json(name = "to") val toUserId: String,
@Json(name = "timestamp") override val timestamp: Long?, @Json(name = "timestamp") val timestamp: Long?,
@Json(name = "format") val format: String? = null, @Json(name = "format") val format: String? = null,
@Json(name = "formatted_body") val formattedBody: String? = null, @Json(name = "formatted_body") val formattedBody: String? = null,
@Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null, @Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null,
@Json(name = "m.new_content") override val newContent: Content? = null, @Json(name = "m.new_content") override val newContent: Content? = null,
// Not parsed, but set after, using the eventId // Not parsed, but set after, using the eventId
override val transactionId: String? = null val transactionId: String? = null
) : MessageContent, VerificationInfoRequest { ) : MessageContent
override fun toEventContent() = toContent()
}

View File

@ -17,29 +17,19 @@ package org.matrix.android.sdk.api.session.room.model.message
import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoStart
import org.matrix.android.sdk.internal.util.JsonCanonicalizer
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
internal data class MessageVerificationStartContent( internal data class MessageVerificationStartContent(
@Json(name = "from_device") override val fromDevice: String?, @Json(name = "from_device") val fromDevice: String?,
@Json(name = "hashes") override val hashes: List<String>?, @Json(name = "hashes") val hashes: List<String>?,
@Json(name = "key_agreement_protocols") override val keyAgreementProtocols: List<String>?, @Json(name = "key_agreement_protocols") val keyAgreementProtocols: List<String>?,
@Json(name = "message_authentication_codes") override val messageAuthenticationCodes: List<String>?, @Json(name = "message_authentication_codes") val messageAuthenticationCodes: List<String>?,
@Json(name = "short_authentication_string") override val shortAuthenticationStrings: List<String>?, @Json(name = "short_authentication_string") val shortAuthenticationStrings: List<String>?,
@Json(name = "method") override val method: String?, @Json(name = "method") val method: String?,
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?, @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?,
@Json(name = "secret") override val sharedSecret: String? @Json(name = "secret") val sharedSecret: String?
) : VerificationInfoStart { ) {
override fun toCanonicalJson(): String { val transactionId: String? = relatesTo?.eventId
return JsonCanonicalizer.getCanonicalJson(MessageVerificationStartContent::class.java, this)
}
override val transactionId: String?
get() = relatesTo?.eventId
override fun toEventContent() = toContent()
} }

View File

@ -16,12 +16,14 @@
package org.matrix.android.sdk.internal.crypto package org.matrix.android.sdk.internal.crypto
import com.squareup.moshi.Moshi
import dagger.Binds import dagger.Binds
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import io.realm.RealmConfiguration import io.realm.RealmConfiguration
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.session.crypto.CryptoService import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.crypto.crosssigning.CrossSigningService import org.matrix.android.sdk.api.session.crypto.crosssigning.CrossSigningService
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
@ -55,6 +57,7 @@ import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreRoomSessionD
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreRoomSessionsDataTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreRoomSessionsDataTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreSessionsDataTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreSessionsDataTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.UpdateKeysBackupVersionTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.UpdateKeysBackupVersionTask
import org.matrix.android.sdk.internal.crypto.network.RequestSender
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStore import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStore
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreMigration import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreMigration
@ -88,7 +91,9 @@ import org.matrix.android.sdk.internal.crypto.tasks.UploadSigningKeysTask
import org.matrix.android.sdk.internal.crypto.verification.RustVerificationService import org.matrix.android.sdk.internal.crypto.verification.RustVerificationService
import org.matrix.android.sdk.internal.database.RealmKeysUtils import org.matrix.android.sdk.internal.database.RealmKeysUtils
import org.matrix.android.sdk.internal.di.CryptoDatabase import org.matrix.android.sdk.internal.di.CryptoDatabase
import org.matrix.android.sdk.internal.di.DeviceId
import org.matrix.android.sdk.internal.di.SessionFilesDirectory import org.matrix.android.sdk.internal.di.SessionFilesDirectory
import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.di.UserMd5 import org.matrix.android.sdk.internal.di.UserMd5
import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.session.SessionScope
import org.matrix.android.sdk.internal.session.cache.ClearCacheTask import org.matrix.android.sdk.internal.session.cache.ClearCacheTask

View File

@ -20,7 +20,7 @@ import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import javax.inject.Inject import javax.inject.Inject
internal class DecryptEventUseCase @Inject constructor(olmMachineProvider: OlmMachineProvider) { internal class DecryptRoomEventUseCase @Inject constructor(olmMachineProvider: OlmMachineProvider) {
private val olmMachine = olmMachineProvider.olmMachine private val olmMachine = olmMachineProvider.olmMachine

View File

@ -23,21 +23,15 @@ import androidx.paging.PagedList
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.async
import kotlinx.coroutines.cancelChildren import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import org.matrix.android.sdk.api.crypto.MXCryptoConfig import org.matrix.android.sdk.api.crypto.MXCryptoConfig
import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.listeners.ProgressListener
import org.matrix.android.sdk.api.logger.LoggerTag import org.matrix.android.sdk.api.logger.LoggerTag
import org.matrix.android.sdk.api.session.crypto.CryptoService import org.matrix.android.sdk.api.session.crypto.CryptoService
@ -71,7 +65,7 @@ import org.matrix.android.sdk.api.session.sync.model.DeviceListResponse
import org.matrix.android.sdk.api.session.sync.model.DeviceOneTimeKeysCountSyncResponse import org.matrix.android.sdk.api.session.sync.model.DeviceOneTimeKeysCountSyncResponse
import org.matrix.android.sdk.api.session.sync.model.ToDeviceSyncResponse 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.keysbackup.RustKeyBackupService
import org.matrix.android.sdk.internal.crypto.network.OutgoingRequestsProcessor import org.matrix.android.sdk.internal.crypto.network.NetworkRequestsProcessor
import org.matrix.android.sdk.internal.crypto.network.RequestSender 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.repository.WarnOnUnknownDeviceRepository
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
@ -86,13 +80,9 @@ import org.matrix.android.sdk.internal.session.SessionScope
import org.matrix.android.sdk.internal.session.StreamEventsManager import org.matrix.android.sdk.internal.session.StreamEventsManager
import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask
import timber.log.Timber import timber.log.Timber
import uniffi.olm.Request
import uniffi.olm.RequestType
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.max import kotlin.math.max
import kotlin.system.measureTimeMillis
/** /**
* A `CryptoService` class instance manages the end-to-end crypto for a session. * A `CryptoService` class instance manages the end-to-end crypto for a session.
@ -109,14 +99,8 @@ private val loggerTag = LoggerTag("DefaultCryptoService", LoggerTag.CRYPTO)
@SessionScope @SessionScope
internal class DefaultCryptoService @Inject constructor( internal class DefaultCryptoService @Inject constructor(
@UserId @UserId private val userId: String,
private val userId: String, @DeviceId private val deviceId: String?,
@DeviceId
private val deviceId: String?,
// @SessionId
// private val sessionId: String,
// @SessionFilesDirectory
// private val dataDir: File,
// the crypto store // the crypto store
private val cryptoStore: IMXCryptoStore, private val cryptoStore: IMXCryptoStore,
// Set of parameters used to configure/customize the end-to-end crypto. // Set of parameters used to configure/customize the end-to-end crypto.
@ -128,7 +112,6 @@ internal class DefaultCryptoService @Inject constructor(
private val getDevicesTask: GetDevicesTask, private val getDevicesTask: GetDevicesTask,
private val getDeviceInfoTask: GetDeviceInfoTask, private val getDeviceInfoTask: GetDeviceInfoTask,
private val setDeviceNameTask: SetDeviceNameTask, private val setDeviceNameTask: SetDeviceNameTask,
private val loadRoomMembersTask: LoadRoomMembersTask,
private val cryptoSessionInfoProvider: CryptoSessionInfoProvider, private val cryptoSessionInfoProvider: CryptoSessionInfoProvider,
private val coroutineDispatchers: MatrixCoroutineDispatchers, private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val cryptoCoroutineScope: CoroutineScope, private val cryptoCoroutineScope: CoroutineScope,
@ -141,7 +124,6 @@ internal class DefaultCryptoService @Inject constructor(
private val liveEventManager: dagger.Lazy<StreamEventsManager>, private val liveEventManager: dagger.Lazy<StreamEventsManager>,
private val prepareToEncrypt: PrepareToEncryptUseCase, private val prepareToEncrypt: PrepareToEncryptUseCase,
private val encryptEventContent: EncryptEventContentUseCase, private val encryptEventContent: EncryptEventContentUseCase,
private val shouldEncryptForInvitedMembers: ShouldEncryptForInvitedMembersUseCase,
private val getRoomUserIds: GetRoomUserIdsUseCase, private val getRoomUserIds: GetRoomUserIdsUseCase,
) : CryptoService { ) : CryptoService {
@ -150,13 +132,7 @@ internal class DefaultCryptoService @Inject constructor(
private val olmMachine by lazy { olmMachineProvider.olmMachine } private val olmMachine by lazy { olmMachineProvider.olmMachine }
// The verification service. private val outgoingRequestsProcessor = NetworkRequestsProcessor(
// private var verificationService: RustVerificationService? = null
// private val deviceObserver: DeviceUpdateObserver = DeviceUpdateObserver()
// Locks for some of our operations
private val outgoingRequestsProcessor = OutgoingRequestsProcessor(
requestSender = requestSender, requestSender = requestSender,
coroutineScope = cryptoCoroutineScope, coroutineScope = cryptoCoroutineScope,
cryptoSessionInfoProvider = cryptoSessionInfoProvider, cryptoSessionInfoProvider = cryptoSessionInfoProvider,
@ -274,7 +250,8 @@ internal class DefaultCryptoService @Inject constructor(
setRustLogger() setRustLogger()
Timber.tag(loggerTag.value).v( Timber.tag(loggerTag.value).v(
"## CRYPTO | Successfully started up an Olm machine for " + "## CRYPTO | Successfully started up an Olm machine for " +
"$userId, $deviceId, identity keys: ${this.olmMachine.identityKeys()}") "$userId, $deviceId, identity keys: ${this.olmMachine.identityKeys()}"
)
} catch (throwable: Throwable) { } catch (throwable: Throwable) {
Timber.tag(loggerTag.value).v("Failed create an Olm machine: $throwable") Timber.tag(loggerTag.value).v("Failed create an Olm machine: $throwable")
} }
@ -326,7 +303,7 @@ internal class DefaultCryptoService @Inject constructor(
*/ */
suspend fun onSyncCompleted() { suspend fun onSyncCompleted() {
if (isStarted()) { if (isStarted()) {
outgoingRequestsProcessor.process(olmMachine) outgoingRequestsProcessor.processOutgoingRequests(olmMachine)
// This isn't a copy paste error. Sending the outgoing requests may // This isn't a copy paste error. Sending the outgoing requests may
// claim one-time keys and establish 1-to-1 Olm sessions with devices, while some // claim one-time keys and establish 1-to-1 Olm sessions with devices, while some
// outgoing requests are waiting for an Olm session to be established (e.g. forwarding // outgoing requests are waiting for an Olm session to be established (e.g. forwarding
@ -335,7 +312,7 @@ internal class DefaultCryptoService @Inject constructor(
// The second call sends out those requests that are waiting for the // The second call sends out those requests that are waiting for the
// keys claim request to be sent out. // keys claim request to be sent out.
// This could be omitted but then devices might be waiting for the next // This could be omitted but then devices might be waiting for the next
outgoingRequestsProcessor.process(olmMachine) outgoingRequestsProcessor.processOutgoingRequests(olmMachine)
keysBackupService.maybeBackupKeys() keysBackupService.maybeBackupKeys()
} }
@ -598,17 +575,6 @@ internal class DefaultCryptoService @Inject constructor(
} }
} }
private suspend fun sendToDevice(request: Request.ToDevice) {
try {
requestSender.sendToDevice(request)
olmMachine.markRequestAsSent(request.requestId, RequestType.TO_DEVICE, "{}")
} catch (throwable: Throwable) {
Timber.tag(loggerTag.value).e(throwable, "## CRYPTO sendToDevice(): error")
}
}
/** /**
* Export the crypto keys * Export the crypto keys
* *
@ -737,26 +703,8 @@ internal class DefaultCryptoService @Inject constructor(
* *
* @param event the event to decrypt again. * @param event the event to decrypt again.
*/ */
override fun reRequestRoomKeyForEvent(event: Event) { override suspend fun reRequestRoomKeyForEvent(event: Event) {
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { outgoingRequestsProcessor.processRequestRoomKey(olmMachine, event)
val requestPair = olmMachine.requestRoomKey(event)
val cancellation = requestPair.cancellation
val request = requestPair.keyRequest
when (cancellation) {
is Request.ToDevice -> {
sendToDevice(cancellation)
}
else -> Unit
}
when (request) {
is Request.ToDevice -> {
sendToDevice(request)
}
else -> Unit
}
}
} }
/** /**

View File

@ -1,88 +0,0 @@
/*
* Copyright 2020 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.model.rest
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoAccept
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoAcceptFactory
/**
* Sent by Bob to accept a verification from a previously sent m.key.verification.start message.
*/
@JsonClass(generateAdapter = true)
internal data class KeyVerificationAccept(
/**
* string to identify the transaction.
* This string must be unique for the pair of users performing verification for the duration that the transaction is valid.
* Alices device should record this ID and use it in future messages in this transaction.
*/
@Json(name = "transaction_id")
override val transactionId: String? = null,
/**
* The key agreement protocol that Bobs device has selected to use, out of the list proposed by Alices device
*/
@Json(name = "key_agreement_protocol")
override val keyAgreementProtocol: String? = null,
/**
* The hash algorithm that Bobs device has selected to use, out of the list proposed by Alices device
*/
@Json(name = "hash")
override val hash: String? = null,
/**
* The message authentication code that Bobs device has selected to use, out of the list proposed by Alices device
*/
@Json(name = "message_authentication_code")
override val messageAuthenticationCode: String? = null,
/**
* An array of short authentication string methods that Bobs client (and Bob) understands. Must be a subset of the list proposed by Alices device
*/
@Json(name = "short_authentication_string")
override val shortAuthenticationStrings: List<String>? = null,
/**
* The hash (encoded as unpadded base64) of the concatenation of the devices ephemeral public key (QB, encoded as unpadded base64)
* and the canonical JSON representation of the m.key.verification.start message.
*/
@Json(name = "commitment")
override var commitment: String? = null
) : SendToDeviceObject, VerificationInfoAccept {
override fun toSendToDeviceObject() = this
companion object : VerificationInfoAcceptFactory {
override fun create(tid: String,
keyAgreementProtocol: String,
hash: String,
commitment: String,
messageAuthenticationCode: String,
shortAuthenticationStrings: List<String>): VerificationInfoAccept {
return KeyVerificationAccept(
transactionId = tid,
keyAgreementProtocol = keyAgreementProtocol,
hash = hash,
commitment = commitment,
messageAuthenticationCode = messageAuthenticationCode,
shortAuthenticationStrings = shortAuthenticationStrings
)
}
}
}

View File

@ -1,57 +0,0 @@
/*
* Copyright 2020 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.model.rest
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject
import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoCancel
/**
* To device event sent by either party to cancel a key verification.
*/
@JsonClass(generateAdapter = true)
internal data class KeyVerificationCancel(
/**
* the transaction ID of the verification to cancel
*/
@Json(name = "transaction_id")
override val transactionId: String? = null,
/**
* machine-readable reason for cancelling, see #CancelCode
*/
override val code: String? = null,
/**
* human-readable reason for cancelling. This should only be used if the receiving client does not understand the code given.
*/
override val reason: String? = null
) : SendToDeviceObject, VerificationInfoCancel {
companion object {
fun create(tid: String, cancelCode: CancelCode): KeyVerificationCancel {
return KeyVerificationCancel(
tid,
cancelCode.value,
cancelCode.humanReadable
)
}
}
override fun toSendToDeviceObject() = this
}

View File

@ -1,32 +0,0 @@
/*
* Copyright 2020 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.model.rest
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoDone
/**
* Requests a key verification with another user's devices.
*/
@JsonClass(generateAdapter = true)
internal data class KeyVerificationDone(
@Json(name = "transaction_id") override val transactionId: String? = null
) : SendToDeviceObject, VerificationInfoDone {
override fun toSendToDeviceObject() = this
}

View File

@ -1,48 +0,0 @@
/*
* Copyright 2020 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.model.rest
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoKey
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoKeyFactory
/**
* Sent by both devices to send their ephemeral Curve25519 public key to the other device.
*/
@JsonClass(generateAdapter = true)
internal data class KeyVerificationKey(
/**
* the ID of the transaction that the message is part of
*/
@Json(name = "transaction_id") override val transactionId: String? = null,
/**
* The devices ephemeral public key, as an unpadded base64 string
*/
@Json(name = "key") override val key: String? = null
) : SendToDeviceObject, VerificationInfoKey {
companion object : VerificationInfoKeyFactory {
override fun create(tid: String, pubKey: String): KeyVerificationKey {
return KeyVerificationKey(tid, pubKey)
}
}
override fun toSendToDeviceObject() = this
}

View File

@ -1,42 +0,0 @@
/*
* Copyright 2020 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.model.rest
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoMac
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoMacFactory
/**
* Sent by both devices to send the MAC of their device key to the other device.
*/
@JsonClass(generateAdapter = true)
internal data class KeyVerificationMac(
@Json(name = "transaction_id") override val transactionId: String? = null,
@Json(name = "mac") override val mac: Map<String, String>? = null,
@Json(name = "keys") override val keys: String? = null
) : SendToDeviceObject, VerificationInfoMac {
override fun toSendToDeviceObject(): SendToDeviceObject? = this
companion object : VerificationInfoMacFactory {
override fun create(tid: String, mac: Map<String, String>, keys: String): VerificationInfoMac {
return KeyVerificationMac(tid, mac, keys)
}
}
}

View File

@ -1,34 +0,0 @@
/*
* Copyright 2020 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.model.rest
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoReady
/**
* Requests a key verification with another user's devices.
*/
@JsonClass(generateAdapter = true)
internal data class KeyVerificationReady(
@Json(name = "from_device") override val fromDevice: String?,
@Json(name = "methods") override val methods: List<String>?,
@Json(name = "transaction_id") override val transactionId: String? = null
) : SendToDeviceObject, VerificationInfoReady {
override fun toSendToDeviceObject() = this
}

View File

@ -1,35 +0,0 @@
/*
* Copyright 2020 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.model.rest
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoRequest
/**
* Requests a key verification with another user's devices.
*/
@JsonClass(generateAdapter = true)
internal data class KeyVerificationRequest(
@Json(name = "from_device") override val fromDevice: String?,
@Json(name = "methods") override val methods: List<String>,
@Json(name = "timestamp") override val timestamp: Long?,
@Json(name = "transaction_id") override val transactionId: String? = null
) : SendToDeviceObject, VerificationInfoRequest {
override fun toSendToDeviceObject() = this
}

View File

@ -1,45 +0,0 @@
/*
* Copyright 2020 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.model.rest
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoStart
import org.matrix.android.sdk.internal.util.JsonCanonicalizer
/**
* Sent by Alice to initiate an interactive key verification.
*/
@JsonClass(generateAdapter = true)
internal data class KeyVerificationStart(
@Json(name = "from_device") override val fromDevice: String? = null,
@Json(name = "method") override val method: String? = null,
@Json(name = "transaction_id") override val transactionId: String? = null,
@Json(name = "key_agreement_protocols") override val keyAgreementProtocols: List<String>? = null,
@Json(name = "hashes") override val hashes: List<String>? = null,
@Json(name = "message_authentication_codes") override val messageAuthenticationCodes: List<String>? = null,
@Json(name = "short_authentication_string") override val shortAuthenticationStrings: List<String>? = null,
// For QR code verification
@Json(name = "secret") override val sharedSecret: String? = null
) : SendToDeviceObject, VerificationInfoStart {
override fun toCanonicalJson(): String {
return JsonCanonicalizer.getCanonicalJson(KeyVerificationStart::class.java, this)
}
override fun toSendToDeviceObject() = this
}

View File

@ -25,6 +25,7 @@ import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import org.matrix.android.sdk.api.logger.LoggerTag 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.crypto.model.RoomEncryptionTrustLevel
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.internal.crypto.CryptoSessionInfoProvider import org.matrix.android.sdk.internal.crypto.CryptoSessionInfoProvider
import org.matrix.android.sdk.internal.crypto.OlmMachine import org.matrix.android.sdk.internal.crypto.OlmMachine
import timber.log.Timber import timber.log.Timber
@ -33,10 +34,10 @@ import uniffi.olm.RequestType
private val loggerTag = LoggerTag("OutgoingRequestsProcessor", LoggerTag.CRYPTO) private val loggerTag = LoggerTag("OutgoingRequestsProcessor", LoggerTag.CRYPTO)
internal class OutgoingRequestsProcessor(private val requestSender: RequestSender, internal class NetworkRequestsProcessor(private val requestSender: RequestSender,
private val coroutineScope: CoroutineScope, private val coroutineScope: CoroutineScope,
private val cryptoSessionInfoProvider: CryptoSessionInfoProvider, private val cryptoSessionInfoProvider: CryptoSessionInfoProvider,
private val shieldComputer: ShieldComputer) { private val shieldComputer: ShieldComputer,) {
fun interface ShieldComputer { fun interface ShieldComputer {
suspend fun compute(userIds: List<String>): RoomEncryptionTrustLevel suspend fun compute(userIds: List<String>): RoomEncryptionTrustLevel
@ -44,7 +45,7 @@ internal class OutgoingRequestsProcessor(private val requestSender: RequestSende
private val lock: Mutex = Mutex() private val lock: Mutex = Mutex()
suspend fun process(olmMachine: OlmMachine) { suspend fun processOutgoingRequests(olmMachine: OlmMachine) {
lock.withLock { lock.withLock {
coroutineScope { coroutineScope {
Timber.v("OutgoingRequests: ${olmMachine.outgoingRequests()}") Timber.v("OutgoingRequests: ${olmMachine.outgoingRequests()}")
@ -92,6 +93,25 @@ internal class OutgoingRequestsProcessor(private val requestSender: RequestSende
} }
} }
suspend fun processRequestRoomKey(olmMachine: OlmMachine, event: Event) {
val requestPair = olmMachine.requestRoomKey(event)
val cancellation = requestPair.cancellation
val request = requestPair.keyRequest
when (cancellation) {
is Request.ToDevice -> {
sendToDevice(olmMachine, cancellation)
}
else -> Unit
}
when (request) {
is Request.ToDevice -> {
sendToDevice(olmMachine, request)
}
else -> Unit
}
}
private suspend fun uploadKeys(olmMachine: OlmMachine, request: Request.KeysUpload) { private suspend fun uploadKeys(olmMachine: OlmMachine, request: Request.KeysUpload) {
try { try {
val response = requestSender.uploadKeys(request) val response = requestSender.uploadKeys(request)

View File

@ -85,7 +85,7 @@ internal class RequestSender @Inject constructor(
private val getSessionsDataTask: GetSessionsDataTask, private val getSessionsDataTask: GetSessionsDataTask,
private val getRoomSessionsDataTask: GetRoomSessionsDataTask, private val getRoomSessionsDataTask: GetRoomSessionsDataTask,
private val getRoomSessionDataTask: GetRoomSessionDataTask, private val getRoomSessionDataTask: GetRoomSessionDataTask,
private val moshi: Moshi private val moshi: Moshi,
) { ) {
companion object { companion object {
const val REQUEST_RETRY_COUNT = 3 const val REQUEST_RETRY_COUNT = 3

View File

@ -1,33 +0,0 @@
/*
* Copyright 2020 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.session.crypto.model.SendToDeviceObject
import org.matrix.android.sdk.api.session.events.model.Content
internal interface VerificationInfo<ValidObjectType> {
fun toEventContent(): Content? = null
fun toSendToDeviceObject(): SendToDeviceObject? = null
fun asValidObject(): ValidObjectType?
/**
* String to identify the transaction.
* This string must be unique for the pair of users performing verification for the duration that the transaction is valid.
* Alices device should record this ID and use it in future messages in this transaction.
*/
val transactionId: String?
}

View File

@ -1,81 +0,0 @@
/*
* Copyright 2020 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
internal interface VerificationInfoAccept : VerificationInfo<ValidVerificationInfoAccept> {
/**
* The key agreement protocol that Bobs device has selected to use, out of the list proposed by Alices device
*/
val keyAgreementProtocol: String?
/**
* The hash algorithm that Bobs device has selected to use, out of the list proposed by Alices device
*/
val hash: String?
/**
* The message authentication code that Bobs device has selected to use, out of the list proposed by Alices device
*/
val messageAuthenticationCode: String?
/**
* An array of short authentication string methods that Bobs client (and Bob) understands. Must be a subset of the list proposed by Alices device
*/
val shortAuthenticationStrings: List<String>?
/**
* The hash (encoded as unpadded base64) of the concatenation of the devices ephemeral public key (QB, encoded as unpadded base64)
* and the canonical JSON representation of the m.key.verification.start message.
*/
var commitment: String?
override fun asValidObject(): ValidVerificationInfoAccept? {
val validTransactionId = transactionId?.takeIf { it.isNotEmpty() } ?: return null
val validKeyAgreementProtocol = keyAgreementProtocol?.takeIf { it.isNotEmpty() } ?: return null
val validHash = hash?.takeIf { it.isNotEmpty() } ?: return null
val validMessageAuthenticationCode = messageAuthenticationCode?.takeIf { it.isNotEmpty() } ?: return null
val validShortAuthenticationStrings = shortAuthenticationStrings?.takeIf { it.isNotEmpty() } ?: return null
val validCommitment = commitment?.takeIf { it.isNotEmpty() } ?: return null
return ValidVerificationInfoAccept(
validTransactionId,
validKeyAgreementProtocol,
validHash,
validMessageAuthenticationCode,
validShortAuthenticationStrings,
validCommitment
)
}
}
internal interface VerificationInfoAcceptFactory {
fun create(tid: String,
keyAgreementProtocol: String,
hash: String,
commitment: String,
messageAuthenticationCode: String,
shortAuthenticationStrings: List<String>): VerificationInfoAccept
}
internal data class ValidVerificationInfoAccept(
val transactionId: String,
val keyAgreementProtocol: String,
val hash: String,
val messageAuthenticationCode: String,
val shortAuthenticationStrings: List<String>,
var commitment: String?
)

View File

@ -1,45 +0,0 @@
/*
* Copyright 2020 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
internal interface VerificationInfoCancel : VerificationInfo<ValidVerificationInfoCancel> {
/**
* machine-readable reason for cancelling, see [CancelCode]
*/
val code: String?
/**
* human-readable reason for cancelling. This should only be used if the receiving client does not understand the code given.
*/
val reason: String?
override fun asValidObject(): ValidVerificationInfoCancel? {
val validTransactionId = transactionId?.takeIf { it.isNotEmpty() } ?: return null
val validCode = code?.takeIf { it.isNotEmpty() } ?: return null
return ValidVerificationInfoCancel(
validTransactionId,
validCode,
reason
)
}
}
internal data class ValidVerificationInfoCancel(
val transactionId: String,
val code: String,
val reason: String?
)

View File

@ -1,26 +0,0 @@
/*
* Copyright 2020 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.session.room.model.message.ValidVerificationDone
internal interface VerificationInfoDone : VerificationInfo<ValidVerificationDone> {
override fun asValidObject(): ValidVerificationDone? {
val validTransactionId = transactionId?.takeIf { it.isNotEmpty() } ?: return null
return ValidVerificationDone(validTransactionId)
}
}

View File

@ -1,45 +0,0 @@
/*
* Copyright 2020 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
/**
* Sent by both devices to send their ephemeral Curve25519 public key to the other device.
*/
internal interface VerificationInfoKey : VerificationInfo<ValidVerificationInfoKey> {
/**
* The devices ephemeral public key, as an unpadded base64 string
*/
val key: String?
override fun asValidObject(): ValidVerificationInfoKey? {
val validTransactionId = transactionId?.takeIf { it.isNotEmpty() } ?: return null
val validKey = key?.takeIf { it.isNotEmpty() } ?: return null
return ValidVerificationInfoKey(
validTransactionId,
validKey
)
}
}
internal interface VerificationInfoKeyFactory {
fun create(tid: String, pubKey: String): VerificationInfoKey
}
internal data class ValidVerificationInfoKey(
val transactionId: String,
val key: String
)

View File

@ -1,53 +0,0 @@
/*
* Copyright 2020 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
internal interface VerificationInfoMac : VerificationInfo<ValidVerificationInfoMac> {
/**
* A map of key ID to the MAC of the key, as an unpadded base64 string, calculated using the MAC key
*/
val mac: Map<String, String>?
/**
* The MAC of the comma-separated, sorted list of key IDs given in the mac property,
* as an unpadded base64 string, calculated using the MAC key.
* For example, if the mac property gives MACs for the keys ed25519:ABCDEFG and ed25519:HIJKLMN, then this property will
* give the MAC of the string ed25519:ABCDEFG,ed25519:HIJKLMN.
*/
val keys: String?
override fun asValidObject(): ValidVerificationInfoMac? {
val validTransactionId = transactionId?.takeIf { it.isNotEmpty() } ?: return null
val validMac = mac?.takeIf { it.isNotEmpty() } ?: return null
val validKeys = keys?.takeIf { it.isNotEmpty() } ?: return null
return ValidVerificationInfoMac(
validTransactionId,
validMac,
validKeys
)
}
}
internal interface VerificationInfoMacFactory {
fun create(tid: String, mac: Map<String, String>, keys: String): VerificationInfoMac
}
internal data class ValidVerificationInfoMac(
val transactionId: String,
val mac: Map<String, String>,
val keys: String
)

View File

@ -1,54 +0,0 @@
/*
* Copyright 2020 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.session.crypto.verification.ValidVerificationInfoReady
/**
* A new event type is added to the key verification framework: m.key.verification.ready,
* which may be sent by the target of the m.key.verification.request message, upon receipt of the m.key.verification.request event.
*
* The m.key.verification.ready event is optional; the recipient of the m.key.verification.request event may respond directly
* with a m.key.verification.start event instead.
*/
internal interface VerificationInfoReady : VerificationInfo<ValidVerificationInfoReady> {
/**
* The ID of the device that sent the m.key.verification.ready message
*/
val fromDevice: String?
/**
* An array of verification methods that the device supports
*/
val methods: List<String>?
override fun asValidObject(): ValidVerificationInfoReady? {
val validTransactionId = transactionId?.takeIf { it.isNotEmpty() } ?: return null
val validFromDevice = fromDevice?.takeIf { it.isNotEmpty() } ?: return null
val validMethods = methods?.takeIf { it.isNotEmpty() } ?: return null
return ValidVerificationInfoReady(
validTransactionId,
validFromDevice,
validMethods
)
}
}
internal interface MessageVerificationReadyFactory {
fun create(tid: String, methods: List<String>, fromDevice: String): VerificationInfoReady
}

View File

@ -1,52 +0,0 @@
/*
* Copyright 2020 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.session.crypto.verification.ValidVerificationInfoRequest
internal interface VerificationInfoRequest : VerificationInfo<ValidVerificationInfoRequest> {
/**
* Required. The device ID which is initiating the request.
*/
val fromDevice: String?
/**
* Required. The verification methods supported by the sender.
*/
val methods: List<String>?
/**
* The POSIX timestamp in milliseconds for when the request was made.
* If the request is in the future by more than 5 minutes or more than 10 minutes in the past,
* the message should be ignored by the receiver.
*/
val timestamp: Long?
override fun asValidObject(): ValidVerificationInfoRequest? {
// FIXME No check on Timestamp?
val validTransactionId = transactionId?.takeIf { it.isNotEmpty() } ?: return null
val validFromDevice = fromDevice?.takeIf { it.isNotEmpty() } ?: return null
val validMethods = methods?.takeIf { it.isNotEmpty() } ?: return null
return ValidVerificationInfoRequest(
validTransactionId,
validFromDevice,
validMethods,
timestamp
)
}
}

View File

@ -1,129 +0,0 @@
/*
* Copyright 2020 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.session.crypto.verification.SasMode
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_RECIPROCATE
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_SAS
internal interface VerificationInfoStart : VerificationInfo<ValidVerificationInfoStart> {
val method: String?
/**
* Alices device ID
*/
val fromDevice: String?
/**
* An array of key agreement protocols that Alices client understands.
* Must include curve25519.
* Other methods may be defined in the future
*/
val keyAgreementProtocols: List<String>?
/**
* An array of hashes that Alices client understands.
* Must include sha256. Other methods may be defined in the future.
*/
val hashes: List<String>?
/**
* An array of message authentication codes that Alices client understands.
* Must include hkdf-hmac-sha256.
* Other methods may be defined in the future.
*/
val messageAuthenticationCodes: List<String>?
/**
* An array of short authentication string methods that Alices client (and Alice) understands.
* Must include decimal.
* This document also describes the emoji method.
* Other methods may be defined in the future
*/
val shortAuthenticationStrings: List<String>?
/**
* Shared secret, when starting verification with QR code
*/
val sharedSecret: String?
fun toCanonicalJson(): String
override fun asValidObject(): ValidVerificationInfoStart? {
val validTransactionId = transactionId?.takeIf { it.isNotEmpty() } ?: return null
val validFromDevice = fromDevice?.takeIf { it.isNotEmpty() } ?: return null
return when (method) {
VERIFICATION_METHOD_SAS -> {
val validKeyAgreementProtocols = keyAgreementProtocols?.takeIf { it.isNotEmpty() } ?: return null
val validHashes = hashes?.takeIf { it.contains("sha256") } ?: return null
val validMessageAuthenticationCodes = messageAuthenticationCodes
?.takeIf {
it.contains(SAS_MAC_SHA256) ||
it.contains(SAS_MAC_SHA256_LONGKDF)
}
?: return null
val validShortAuthenticationStrings = shortAuthenticationStrings?.takeIf { it.contains(SasMode.DECIMAL) } ?: return null
ValidVerificationInfoStart.SasVerificationInfoStart(
validTransactionId,
validFromDevice,
validKeyAgreementProtocols,
validHashes,
validMessageAuthenticationCodes,
validShortAuthenticationStrings,
canonicalJson = toCanonicalJson()
)
}
VERIFICATION_METHOD_RECIPROCATE -> {
val validSharedSecret = sharedSecret?.takeIf { it.isNotEmpty() } ?: return null
ValidVerificationInfoStart.ReciprocateVerificationInfoStart(
validTransactionId,
validFromDevice,
validSharedSecret
)
}
else -> null
}
}
companion object {
const val SAS_MAC_SHA256_LONGKDF = "hmac-sha256"
const val SAS_MAC_SHA256 = "hkdf-hmac-sha256"
}
}
internal sealed class ValidVerificationInfoStart(
open val transactionId: String,
open val fromDevice: String) {
data class SasVerificationInfoStart(
override val transactionId: String,
override val fromDevice: String,
val keyAgreementProtocols: List<String>,
val hashes: List<String>,
val messageAuthenticationCodes: List<String>,
val shortAuthenticationStrings: List<String>,
val canonicalJson: String
) : ValidVerificationInfoStart(transactionId, fromDevice)
data class ReciprocateVerificationInfoStart(
override val transactionId: String,
override val fromDevice: String,
val sharedSecret: String
) : ValidVerificationInfoStart(transactionId, fromDevice)
}

View File

@ -19,7 +19,7 @@ package org.matrix.android.sdk.internal.session.room.timeline
import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult
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.internal.crypto.DecryptEventUseCase import org.matrix.android.sdk.internal.crypto.DecryptRoomEventUseCase
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.network.executeRequest
import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.session.room.RoomAPI
@ -37,7 +37,7 @@ internal interface GetEventTask : Task<GetEventTask.Params, Event> {
internal class DefaultGetEventTask @Inject constructor( internal class DefaultGetEventTask @Inject constructor(
private val roomAPI: RoomAPI, private val roomAPI: RoomAPI,
private val globalErrorReceiver: GlobalErrorReceiver, private val globalErrorReceiver: GlobalErrorReceiver,
private val decryptEvent: DecryptEventUseCase, private val decryptEvent: DecryptRoomEventUseCase,
private val clock: Clock, private val clock: Clock,
) : GetEventTask { ) : GetEventTask {

View File

@ -1037,7 +1037,8 @@ class TimelineViewModel @AssistedInject constructor(
if (session.cryptoService().verificationService().readyPendingVerification( if (session.cryptoService().verificationService().readyPendingVerification(
supportedVerificationMethodsProvider.provide(), supportedVerificationMethodsProvider.provide(),
action.otherUserId, action.otherUserId,
action.transactionId)) { action.transactionId
)) {
_viewEvents.post(RoomDetailViewEvents.ActionSuccess(action)) _viewEvents.post(RoomDetailViewEvents.ActionSuccess(action))
} else { } else {
// TODO // TODO
@ -1049,7 +1050,8 @@ class TimelineViewModel @AssistedInject constructor(
viewModelScope.launch { viewModelScope.launch {
session.cryptoService().verificationService().cancelVerificationRequest( session.cryptoService().verificationService().cancelVerificationRequest(
action.otherUserId, action.otherUserId,
action.transactionId) action.transactionId
)
} }
} }
@ -1075,12 +1077,14 @@ class TimelineViewModel @AssistedInject constructor(
} }
private fun handleReRequestKeys(action: RoomDetailAction.ReRequestKeys) { private fun handleReRequestKeys(action: RoomDetailAction.ReRequestKeys) {
viewModelScope.launch {
// Check if this request is still active and handled by me // Check if this request is still active and handled by me
room.getTimelineEvent(action.eventId)?.let { room.getTimelineEvent(action.eventId)?.let {
session.cryptoService().reRequestRoomKeyForEvent(it.root) session.cryptoService().reRequestRoomKeyForEvent(it.root)
_viewEvents.post(RoomDetailViewEvents.ShowMessage(stringProvider.getString(R.string.e2e_re_request_encryption_key_dialog_content))) _viewEvents.post(RoomDetailViewEvents.ShowMessage(stringProvider.getString(R.string.e2e_re_request_encryption_key_dialog_content)))
} }
} }
}
private fun handleTapOnFailedToDecrypt(action: RoomDetailAction.TapOnFailedToDecrypt) { private fun handleTapOnFailedToDecrypt(action: RoomDetailAction.TapOnFailedToDecrypt) {
room.getTimelineEvent(action.eventId)?.let { room.getTimelineEvent(action.eventId)?.let {