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.internal.crypto.model.CryptoDeviceInfo
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 timber.log.Timber
import java.util.concurrent.CountDownLatch

View file

@ -87,7 +87,7 @@ interface CryptoService {
suspend fun getCryptoDeviceInfo(userId: String, deviceId: String?): CryptoDeviceInfo?
fun reRequestRoomKeyForEvent(event: Event)
suspend fun reRequestRoomKeyForEvent(event: Event)
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.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.internal.crypto.verification.VerificationInfoAccept
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoAcceptFactory
@JsonClass(generateAdapter = true)
internal data class MessageVerificationAcceptContent(
@Json(name = "hash") override val hash: String?,
@Json(name = "key_agreement_protocol") override val keyAgreementProtocol: String?,
@Json(name = "message_authentication_code") override val messageAuthenticationCode: String?,
@Json(name = "short_authentication_string") override val shortAuthenticationStrings: List<String>?,
@Json(name = "hash") val hash: String?,
@Json(name = "key_agreement_protocol") val keyAgreementProtocol: String?,
@Json(name = "message_authentication_code") val messageAuthenticationCode: String?,
@Json(name = "short_authentication_string") val shortAuthenticationStrings: List<String>?,
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?,
@Json(name = "commitment") override var commitment: String? = null
) : VerificationInfoAccept {
@Json(name = "commitment") var commitment: String? = null
) {
override val transactionId: String?
get() = relatesTo?.eventId
val transactionId: String? = 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.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.internal.crypto.verification.VerificationInfoCancel
@JsonClass(generateAdapter = true)
data class MessageVerificationCancelContent(
@Json(name = "code") override val code: String? = null,
@Json(name = "reason") override val reason: String? = null,
@Json(name = "code") val code: String? = null,
@Json(name = "reason") val reason: String? = null,
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?
) : VerificationInfoCancel {
) {
override val transactionId: String?
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
)
)
}
}
val transactionId: String? = relatesTo?.eventId
}

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.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.internal.crypto.verification.VerificationInfo
@JsonClass(generateAdapter = true)
internal data class MessageVerificationDoneContent(
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?
) : VerificationInfo<ValidVerificationDone> {
) {
override val transactionId: String?
get() = relatesTo?.eventId
override fun toEventContent(): Content? = toContent()
override fun asValidObject(): ValidVerificationDone? {
val validTransactionId = transactionId?.takeIf { it.isNotEmpty() } ?: return null
return ValidVerificationDone(
validTransactionId
)
}
val transactionId: String? = relatesTo?.eventId
}
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.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.internal.crypto.verification.VerificationInfoKey
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoKeyFactory
@JsonClass(generateAdapter = true)
internal data class MessageVerificationKeyContent(
/**
* 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?
) : VerificationInfoKey {
) {
override val transactionId: String?
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
)
)
}
}
val transactionId: String? = relatesTo?.eventId
}

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.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.internal.crypto.verification.VerificationInfoMac
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoMacFactory
@JsonClass(generateAdapter = true)
internal data class MessageVerificationMacContent(
@Json(name = "mac") override val mac: Map<String, String>? = null,
@Json(name = "keys") override val keys: String? = null,
@Json(name = "mac") val mac: Map<String, String>? = null,
@Json(name = "keys") val keys: String? = null,
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?
) : VerificationInfoMac {
) {
override val transactionId: String?
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
)
)
}
}
val transactionId: String? = relatesTo?.eventId
}

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.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.internal.crypto.verification.MessageVerificationReadyFactory
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoReady
@JsonClass(generateAdapter = true)
internal data class MessageVerificationReadyContent(
@Json(name = "from_device") override val fromDevice: String? = null,
@Json(name = "methods") override val methods: List<String>? = null,
@Json(name = "from_device") val fromDevice: String? = null,
@Json(name = "methods") val methods: List<String>? = null,
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?
) : VerificationInfoReady {
) {
override val transactionId: String?
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
)
)
}
}
val transactionId: String? = relatesTo?.eventId
}

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.toContent
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoRequest
@JsonClass(generateAdapter = true)
data class MessageVerificationRequestContent(
@Json(name = MessageContent.MSG_TYPE_JSON_KEY) override val msgType: String = MessageType.MSGTYPE_VERIFICATION_REQUEST,
@Json(name = "body") override val body: String,
@Json(name = "from_device") override val fromDevice: String?,
@Json(name = "methods") override val methods: List<String>,
@Json(name = "from_device") val fromDevice: String?,
@Json(name = "methods") val methods: List<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 = "formatted_body") val formattedBody: String? = null,
@Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null,
@Json(name = "m.new_content") override val newContent: Content? = null,
// Not parsed, but set after, using the eventId
override val transactionId: String? = null
) : MessageContent, VerificationInfoRequest {
val transactionId: String? = null
) : 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.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.internal.crypto.verification.VerificationInfoStart
import org.matrix.android.sdk.internal.util.JsonCanonicalizer
@JsonClass(generateAdapter = true)
internal data class MessageVerificationStartContent(
@Json(name = "from_device") override val fromDevice: String?,
@Json(name = "hashes") override val hashes: List<String>?,
@Json(name = "key_agreement_protocols") override val keyAgreementProtocols: List<String>?,
@Json(name = "message_authentication_codes") override val messageAuthenticationCodes: List<String>?,
@Json(name = "short_authentication_string") override val shortAuthenticationStrings: List<String>?,
@Json(name = "method") override val method: String?,
@Json(name = "from_device") val fromDevice: String?,
@Json(name = "hashes") val hashes: List<String>?,
@Json(name = "key_agreement_protocols") val keyAgreementProtocols: List<String>?,
@Json(name = "message_authentication_codes") val messageAuthenticationCodes: List<String>?,
@Json(name = "short_authentication_string") val shortAuthenticationStrings: List<String>?,
@Json(name = "method") val method: String?,
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?,
@Json(name = "secret") override val sharedSecret: String?
) : VerificationInfoStart {
@Json(name = "secret") val sharedSecret: String?
) {
override fun toCanonicalJson(): String {
return JsonCanonicalizer.getCanonicalJson(MessageVerificationStartContent::class.java, this)
}
override val transactionId: String?
get() = relatesTo?.eventId
override fun toEventContent() = toContent()
val transactionId: String? = relatesTo?.eventId
}

View file

@ -16,12 +16,14 @@
package org.matrix.android.sdk.internal.crypto
import com.squareup.moshi.Moshi
import dagger.Binds
import dagger.Module
import dagger.Provides
import io.realm.RealmConfiguration
import kotlinx.coroutines.CoroutineScope
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.crosssigning.CrossSigningService
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.StoreSessionsDataTask
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.db.RealmCryptoStore
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.database.RealmKeysUtils
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.UserId
import org.matrix.android.sdk.internal.di.UserMd5
import org.matrix.android.sdk.internal.session.SessionScope
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 javax.inject.Inject
internal class DecryptEventUseCase @Inject constructor(olmMachineProvider: OlmMachineProvider) {
internal class DecryptRoomEventUseCase @Inject constructor(olmMachineProvider: OlmMachineProvider) {
private val olmMachine = olmMachineProvider.olmMachine

View file

@ -23,21 +23,15 @@ import androidx.paging.PagedList
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.async
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
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
import org.matrix.android.sdk.api.crypto.MXCryptoConfig
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.logger.LoggerTag
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.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.NetworkRequestsProcessor
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
@ -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.room.membership.LoadRoomMembersTask
import timber.log.Timber
import uniffi.olm.Request
import uniffi.olm.RequestType
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject
import kotlin.math.max
import kotlin.system.measureTimeMillis
/**
* 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
internal class DefaultCryptoService @Inject constructor(
@UserId
private val userId: String,
@DeviceId
private val deviceId: String?,
// @SessionId
// private val sessionId: String,
// @SessionFilesDirectory
// private val dataDir: File,
@UserId private val userId: 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.
@ -128,7 +112,6 @@ internal class DefaultCryptoService @Inject constructor(
private val getDevicesTask: GetDevicesTask,
private val getDeviceInfoTask: GetDeviceInfoTask,
private val setDeviceNameTask: SetDeviceNameTask,
private val loadRoomMembersTask: LoadRoomMembersTask,
private val cryptoSessionInfoProvider: CryptoSessionInfoProvider,
private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val cryptoCoroutineScope: CoroutineScope,
@ -141,7 +124,6 @@ internal class DefaultCryptoService @Inject constructor(
private val liveEventManager: dagger.Lazy<StreamEventsManager>,
private val prepareToEncrypt: PrepareToEncryptUseCase,
private val encryptEventContent: EncryptEventContentUseCase,
private val shouldEncryptForInvitedMembers: ShouldEncryptForInvitedMembersUseCase,
private val getRoomUserIds: GetRoomUserIdsUseCase,
) : CryptoService {
@ -150,13 +132,7 @@ internal class DefaultCryptoService @Inject constructor(
private val olmMachine by lazy { olmMachineProvider.olmMachine }
// The verification service.
// private var verificationService: RustVerificationService? = null
// private val deviceObserver: DeviceUpdateObserver = DeviceUpdateObserver()
// Locks for some of our operations
private val outgoingRequestsProcessor = OutgoingRequestsProcessor(
private val outgoingRequestsProcessor = NetworkRequestsProcessor(
requestSender = requestSender,
coroutineScope = cryptoCoroutineScope,
cryptoSessionInfoProvider = cryptoSessionInfoProvider,
@ -274,7 +250,8 @@ internal class DefaultCryptoService @Inject constructor(
setRustLogger()
Timber.tag(loggerTag.value).v(
"## 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) {
Timber.tag(loggerTag.value).v("Failed create an Olm machine: $throwable")
}
@ -326,7 +303,7 @@ internal class DefaultCryptoService @Inject constructor(
*/
suspend fun onSyncCompleted() {
if (isStarted()) {
outgoingRequestsProcessor.process(olmMachine)
outgoingRequestsProcessor.processOutgoingRequests(olmMachine)
// 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
// 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
// keys claim request to be sent out.
// This could be omitted but then devices might be waiting for the next
outgoingRequestsProcessor.process(olmMachine)
outgoingRequestsProcessor.processOutgoingRequests(olmMachine)
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
*
@ -737,26 +703,8 @@ internal class DefaultCryptoService @Inject constructor(
*
* @param event the event to decrypt again.
*/
override fun reRequestRoomKeyForEvent(event: Event) {
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
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
}
}
override suspend fun reRequestRoomKeyForEvent(event: Event) {
outgoingRequestsProcessor.processRequestRoomKey(olmMachine, event)
}
/**

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 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.CryptoSessionInfoProvider
import org.matrix.android.sdk.internal.crypto.OlmMachine
import timber.log.Timber
@ -33,10 +34,10 @@ import uniffi.olm.RequestType
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) {
internal class NetworkRequestsProcessor(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
@ -44,7 +45,7 @@ internal class OutgoingRequestsProcessor(private val requestSender: RequestSende
private val lock: Mutex = Mutex()
suspend fun process(olmMachine: OlmMachine) {
suspend fun processOutgoingRequests(olmMachine: OlmMachine) {
lock.withLock {
coroutineScope {
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) {
try {
val response = requestSender.uploadKeys(request)

View file

@ -85,7 +85,7 @@ internal class RequestSender @Inject constructor(
private val getSessionsDataTask: GetSessionsDataTask,
private val getRoomSessionsDataTask: GetRoomSessionsDataTask,
private val getRoomSessionDataTask: GetRoomSessionDataTask,
private val moshi: Moshi
private val moshi: Moshi,
) {
companion object {
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.session.crypto.model.OlmDecryptionResult
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.executeRequest
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(
private val roomAPI: RoomAPI,
private val globalErrorReceiver: GlobalErrorReceiver,
private val decryptEvent: DecryptEventUseCase,
private val decryptEvent: DecryptRoomEventUseCase,
private val clock: Clock,
) : GetEventTask {

View file

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