From 6649aaca2eddc984e229583892dafa13946a6f37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Mon, 28 Jun 2021 11:37:14 +0200 Subject: [PATCH] crypto: Support SAS verification up to showing emojis --- .../android/sdk/internal/crypto/OlmMachine.kt | 36 +++++++++++-- .../verification/RustVerificationService.kt | 53 ++++++++++++++----- rust-sdk/Cargo.toml | 8 ++- rust-sdk/src/machine.rs | 10 ++-- rust-sdk/src/olm.udl | 1 + 5 files changed, 83 insertions(+), 25 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt index 19d8233462..196eced925 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt @@ -185,11 +185,17 @@ internal class VerificationRequest( return this.inner.isReady } - suspend fun startSasVerification(): StartSasResult? { + suspend fun startSasVerification(): Pair? { refreshData() return withContext(Dispatchers.IO) { - machine.startSasVerification(inner.otherUserId, inner.flowId) + val response = machine.startSasVerification(inner.otherUserId, inner.flowId) + + if (response != null) { + Pair(response.request, SasVerification(machine, response.sas)) + } else { + null + } } } @@ -325,7 +331,22 @@ public class SasVerification(private val machine: InnerMachine, private var inne override var state: VerificationTxState get() { - TODO() + refreshData() + return when { + this.inner.canBePresented -> { + VerificationTxState.ShortCodeReady + } + this.inner.isCancelled -> { + // TODO fetch the cancel code from the rust side + VerificationTxState.Cancelled(CancelCode.User, false) + } + this.inner.isDone -> { + VerificationTxState.Verified + } + else -> { + VerificationTxState.Started + } + } } set(v) { this.stateField = v @@ -353,11 +374,16 @@ public class SasVerification(private val machine: InnerMachine, private var inne } override fun supportsDecimal(): Boolean { - return false + // This is ignored anyways, throw it away? + // The spec also mandates that devices support + // at least decimal and the rust-sdk cancels if + // devices don't support it + return true } override fun supportsEmoji(): Boolean { - return false + refreshData() + return this.inner.supportsEmoji } override fun userHasVerifiedShortCode() { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/RustVerificationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/RustVerificationService.kt index b561e90d5f..91c68e18cf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/RustVerificationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/RustVerificationService.kt @@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.crypto.verification import android.os.Handler import android.os.Looper +import kotlinx.coroutines.flow.flow import javax.inject.Inject import kotlin.collections.set import kotlinx.coroutines.runBlocking @@ -31,6 +32,8 @@ import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.message.MessageType import org.matrix.android.sdk.internal.crypto.OlmMachine import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationDone +import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationKey import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationRequest import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask import org.matrix.android.sdk.internal.di.MoshiProvider @@ -132,10 +135,14 @@ constructor( EventType.KEY_VERIFICATION_START -> {} EventType.KEY_VERIFICATION_CANCEL -> {} EventType.KEY_VERIFICATION_ACCEPT -> {} - EventType.KEY_VERIFICATION_KEY -> {} + EventType.KEY_VERIFICATION_KEY -> { + onKeyReceived(event) + } EventType.KEY_VERIFICATION_MAC -> {} EventType.KEY_VERIFICATION_READY -> {} - EventType.KEY_VERIFICATION_DONE -> {} + EventType.KEY_VERIFICATION_DONE -> { + onDone(event) + } MessageType.MSGTYPE_VERIFICATION_REQUEST -> { onRequestReceived(event) } @@ -143,10 +150,23 @@ constructor( // ignore } } - event == event - // TODO get the sender and flow id out of the event and depending on the - // event type either get the verification request or verification and - // dispatch updates here + } + + private fun onDone(event: Event) { + val content = event.getClearContent().toModel() ?: return + val flowId = content.transactionId ?: return + val sender = event.senderId ?: return + + val verification = this.getExistingTransaction(sender, flowId) ?: return + dispatchTxUpdated(verification) + } + private fun onKeyReceived(event: Event) { + val content = event.getClearContent().toModel() ?: return + val flowId = content.transactionId ?: return + val sender = event.senderId ?: return + + val verification = this.getExistingTransaction(sender, flowId) ?: return + dispatchTxUpdated(verification) } private fun onRequestReceived(event: Event) { @@ -166,9 +186,9 @@ constructor( // TODO All this methods should be delegated to a TransactionStore override fun getExistingTransaction( otherUserId: String, - tid: String + tid: String, ): VerificationTransaction? { - return null + return this.olmMachine.getVerification(otherUserId, tid) } override fun getExistingVerificationRequests( @@ -210,10 +230,19 @@ constructor( transactionId: String? ): String? { // should check if already one (and cancel it) - if (method == VerificationMethod.SAS) { - // TODO start SAS verification here, don't we need to see if there's - // a request? - TODO() + return if (method == VerificationMethod.SAS) { + val flowId = transactionId ?: return null + val request = this.olmMachine.getVerificationRequest(otherUserId, flowId) + runBlocking { + val response = request?.startSasVerification() + if (response != null) { + sendRequest(response.first) + dispatchTxAdded(response.second) + response.second.transactionId + } else { + null + } + } } else { throw IllegalArgumentException("Unknown verification method") } diff --git a/rust-sdk/Cargo.toml b/rust-sdk/Cargo.toml index d70e7e4418..a311211950 100644 --- a/rust-sdk/Cargo.toml +++ b/rust-sdk/Cargo.toml @@ -23,12 +23,10 @@ version = "0.2.0" features = ["lax_deserialize"] [dependencies.matrix-sdk-common] -git = "https://github.com/matrix-org/matrix-rust-sdk/" -rev = "0fb3dedd1cd3b0766fa7378754480d52d38e8ef2" +version = "0.3.0" [dependencies.matrix-sdk-crypto] -git = "https://github.com/matrix-org/matrix-rust-sdk/" -rev = "0fb3dedd1cd3b0766fa7378754480d52d38e8ef2" +version = "0.3.0" features = ["sled_cryptostore"] [dependencies.tokio] @@ -37,7 +35,7 @@ default_features = false features = ["rt-multi-thread"] [dependencies.ruma] -version = "*" +version = "0.2.0" features = ["client-api"] [build-dependencies] diff --git a/rust-sdk/src/machine.rs b/rust-sdk/src/machine.rs index ff657953ef..47dd74c95b 100644 --- a/rust-sdk/src/machine.rs +++ b/rust-sdk/src/machine.rs @@ -53,6 +53,7 @@ pub struct Sas { pub is_cancelled: bool, pub is_done: bool, pub can_be_presented: bool, + pub supports_emoji: bool, pub timed_out: bool, } @@ -71,6 +72,7 @@ impl From for Sas { is_done: sas.is_done(), can_be_presented: sas.can_be_presented(), timed_out: sas.timed_out(), + supports_emoji: sas.supports_emoji(), } } } @@ -649,9 +651,11 @@ impl OlmMachine { todo!() } - pub fn get_verification(&self, user_id: &str, _flow_id: &str) -> Option { - let _user_id = UserId::try_from(user_id).ok()?; - todo!() + pub fn get_verification(&self, user_id: &str, flow_id: &str) -> Option { + let user_id = UserId::try_from(user_id).ok()?; + self.inner + .get_verification(&user_id, flow_id) + .and_then(|v| v.sas_v1().map(|s| s.into())) } pub fn start_sas_verification( diff --git a/rust-sdk/src/olm.udl b/rust-sdk/src/olm.udl index be552c6643..0986c87450 100644 --- a/rust-sdk/src/olm.udl +++ b/rust-sdk/src/olm.udl @@ -76,6 +76,7 @@ dictionary Sas { boolean is_cancelled; boolean can_be_presented; boolean timed_out; + boolean supports_emoji; }; dictionary VerificationRequest {