crypto: Allow the direct start of the short SAS flow
This commit is contained in:
parent
85e4b5eb49
commit
d24c94d0f9
|
@ -49,7 +49,7 @@ import org.matrix.android.sdk.internal.session.sync.model.ToDeviceSyncResponse
|
|||
import timber.log.Timber
|
||||
import uniffi.olm.CryptoStoreErrorException
|
||||
import uniffi.olm.DecryptionErrorException
|
||||
import uniffi.olm.Device
|
||||
import uniffi.olm.Device as InnerDevice
|
||||
import uniffi.olm.DeviceLists
|
||||
import uniffi.olm.KeyRequestPair
|
||||
import uniffi.olm.Logger
|
||||
|
@ -98,7 +98,7 @@ fun setRustLogger() {
|
|||
}
|
||||
|
||||
/** Convert a Rust Device into a Kotlin CryptoDeviceInfo */
|
||||
private fun toCryptoDeviceInfo(device: Device): CryptoDeviceInfo {
|
||||
private fun toCryptoDeviceInfo(device: InnerDevice): CryptoDeviceInfo {
|
||||
val keys = device.keys.map { (keyId, key) -> "$keyId:$device.deviceId" to key }.toMap()
|
||||
|
||||
return CryptoDeviceInfo(
|
||||
|
@ -128,6 +128,36 @@ internal class DeviceUpdateObserver {
|
|||
}
|
||||
}
|
||||
|
||||
internal class Device(
|
||||
private val machine: uniffi.olm.OlmMachine,
|
||||
private var inner: InnerDevice,
|
||||
private val sender: RequestSender,
|
||||
private val listeners: ArrayList<VerificationService.Listener>,
|
||||
) {
|
||||
@Throws(CryptoStoreErrorException::class)
|
||||
suspend fun startVerification(): SasVerification? {
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
machine.startSasWithDevice(inner.userId, inner.deviceId)
|
||||
}
|
||||
|
||||
return if (result != null) {
|
||||
this.sender.sendVerificationRequest(result.request)
|
||||
SasVerification(
|
||||
this.machine, result.sas, this.sender, this.listeners,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(CryptoStoreErrorException::class)
|
||||
suspend fun markAsTrusted() {
|
||||
withContext(Dispatchers.IO) {
|
||||
machine.markDeviceAsTrusted(inner.userId, inner.deviceId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class QrCodeVerification(
|
||||
private val machine: uniffi.olm.OlmMachine,
|
||||
private var inner: QrCode,
|
||||
|
@ -670,7 +700,7 @@ internal class OlmMachine(
|
|||
runBlocking { inner.discardRoomKey(roomId) }
|
||||
}
|
||||
|
||||
fun getVerificationRequests(userId: String): List<uniffi.olm.VerificationRequest> {
|
||||
fun getVerificationRequests(userId: String): List<VerificationRequest> {
|
||||
return this.inner.getVerificationRequests(userId)
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_REC
|
|||
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_SAS
|
||||
import timber.log.Timber
|
||||
import uniffi.olm.OlmMachine
|
||||
import uniffi.olm.Sas
|
||||
import uniffi.olm.VerificationRequest
|
||||
|
||||
internal class VerificationRequest(
|
||||
|
@ -66,6 +65,21 @@ internal class VerificationRequest(
|
|||
}
|
||||
}
|
||||
|
||||
fun isCanceled(): Boolean {
|
||||
refreshData()
|
||||
return this.inner.isCancelled
|
||||
}
|
||||
|
||||
fun isDone(): Boolean {
|
||||
refreshData()
|
||||
return this.inner.isDone
|
||||
}
|
||||
|
||||
fun isReady(): Boolean {
|
||||
refreshData()
|
||||
return this.inner.isReady
|
||||
}
|
||||
|
||||
internal fun startQrVerification(): QrCodeVerification? {
|
||||
val qrcode = this.machine.startQrVerification(this.inner.otherUserId, this.inner.flowId)
|
||||
|
||||
|
@ -99,7 +113,10 @@ internal class VerificationRequest(
|
|||
}
|
||||
|
||||
val request = this.machine.acceptVerificationRequest(
|
||||
this.inner.otherUserId, this.inner.flowId, stringMethods)
|
||||
this.inner.otherUserId,
|
||||
this.inner.flowId,
|
||||
stringMethods
|
||||
)
|
||||
|
||||
if (request != null) {
|
||||
this.sender.sendVerificationRequest(request)
|
||||
|
@ -116,29 +133,14 @@ internal class VerificationRequest(
|
|||
}
|
||||
}
|
||||
|
||||
fun isCanceled(): Boolean {
|
||||
refreshData()
|
||||
return this.inner.isCancelled
|
||||
}
|
||||
|
||||
fun isDone(): Boolean {
|
||||
refreshData()
|
||||
return this.inner.isDone
|
||||
}
|
||||
|
||||
fun isReady(): Boolean {
|
||||
refreshData()
|
||||
return this.inner.isReady
|
||||
}
|
||||
|
||||
suspend fun startSasVerification(): Sas? {
|
||||
suspend fun startSasVerification(): SasVerification? {
|
||||
refreshData()
|
||||
|
||||
return withContext(Dispatchers.IO) {
|
||||
val result = machine.startSasVerification(inner.otherUserId, inner.flowId)
|
||||
if (result != null) {
|
||||
sender.sendVerificationRequest(result.request)
|
||||
result.sas
|
||||
SasVerification(machine, result.sas, sender, listeners)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
|
|
@ -20,7 +20,9 @@ import android.os.Handler
|
|||
import android.os.Looper
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
|
||||
|
@ -30,6 +32,7 @@ import org.matrix.android.sdk.api.session.events.model.EventType
|
|||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageRelationContent
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
||||
import org.matrix.android.sdk.internal.crypto.Device
|
||||
import org.matrix.android.sdk.internal.crypto.OlmMachine
|
||||
import org.matrix.android.sdk.internal.crypto.QrCodeVerification
|
||||
import org.matrix.android.sdk.internal.crypto.RequestSender
|
||||
|
@ -39,13 +42,13 @@ import org.matrix.android.sdk.internal.session.SessionScope
|
|||
import timber.log.Timber
|
||||
import uniffi.olm.Verification
|
||||
|
||||
private fun getFlowId(event: Event): String? {
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ToDeviceVerificationEvent(
|
||||
@Json(name = "sender") val sender: String?,
|
||||
@Json(name = "transaction_id") val transactionId: String,
|
||||
)
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ToDeviceVerificationEvent(
|
||||
@Json(name = "sender") val sender: String?,
|
||||
@Json(name = "transaction_id") val transactionId: String,
|
||||
)
|
||||
|
||||
private fun getFlowId(event: Event): String? {
|
||||
return if (event.eventId != null) {
|
||||
val relatesTo = event.content.toModel<MessageRelationContent>()?.relatesTo
|
||||
relatesTo?.eventId
|
||||
|
@ -186,9 +189,24 @@ internal class RustVerificationService(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun getDevice(userId: String, deviceID: String): Device? {
|
||||
val device = withContext(Dispatchers.IO) {
|
||||
olmMachine.inner().getDevice(userId, deviceID)
|
||||
}
|
||||
|
||||
return if (device != null) {
|
||||
Device(this.olmMachine.inner(), device, this.requestSender, this.listeners)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun markedLocallyAsManuallyVerified(userId: String, deviceID: String) {
|
||||
// TODO this doesn't seem to be used anymore?
|
||||
runBlocking { olmMachine.markDeviceAsTrusted(userId, deviceID) }
|
||||
runBlocking {
|
||||
val device = getDevice(userId, deviceID)
|
||||
device?.markAsTrusted()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPotentiallyInterestingEventRoomFailToDecrypt(event: Event) {
|
||||
|
@ -200,9 +218,14 @@ internal class RustVerificationService(
|
|||
tid: String,
|
||||
): VerificationTransaction? {
|
||||
val verification = this.olmMachine.getVerification(otherUserId, tid) ?: return null
|
||||
|
||||
return when (verification) {
|
||||
is Verification.QrCodeV1 -> QrCodeVerification(this.olmMachine.inner(), verification.qrcode, this.requestSender, this.listeners)
|
||||
is Verification.SasV1 -> SasVerification(this.olmMachine.inner(), verification.sas, this.requestSender, this.listeners)
|
||||
is Verification.QrCodeV1 -> {
|
||||
QrCodeVerification(this.olmMachine.inner(), verification.qrcode, this.requestSender, this.listeners)
|
||||
}
|
||||
is Verification.SasV1 -> {
|
||||
SasVerification(this.olmMachine.inner(), verification.sas, this.requestSender, this.listeners)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,7 +258,8 @@ internal class RustVerificationService(
|
|||
tid: String?
|
||||
): PendingVerificationRequest? {
|
||||
// This is only used in `RoomDetailViewModel` to resume the verification.
|
||||
TODO()
|
||||
// We don't support resuming in the rust-sdk, at least for now, so let's return null here.
|
||||
return null
|
||||
}
|
||||
|
||||
override fun requestKeyVerification(
|
||||
|
@ -303,27 +327,34 @@ internal class RustVerificationService(
|
|||
): String? {
|
||||
// should check if already one (and cancel it)
|
||||
return if (method == VerificationMethod.SAS) {
|
||||
val request = transactionId?.let { this.getVerificationRequest(otherUserId, it) }
|
||||
if (transactionId != null) {
|
||||
val request = this.getVerificationRequest(otherUserId, transactionId)
|
||||
|
||||
if (request != null) {
|
||||
runBlocking {
|
||||
val sas = request.startSasVerification()
|
||||
val sas = request?.startSasVerification()
|
||||
|
||||
if (sas != null) {
|
||||
val sasTransaction = SasVerification(olmMachine.inner(), sas, requestSender, listeners)
|
||||
dispatchTxAdded(sasTransaction)
|
||||
sasTransaction.transactionId
|
||||
dispatchTxAdded(sas)
|
||||
sas.transactionId
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// This should start the short SAS flow, the one that doesn't start with
|
||||
// This starts the short SAS flow, the one that doesn't start with
|
||||
// a `m.key.verification.request`, Element web stopped doing this, might
|
||||
// be wise do do so as well
|
||||
// DeviceListBottomSheetViewModel triggers this, interestingly the method that
|
||||
// triggers this is called `manuallyVerify()`
|
||||
TODO()
|
||||
runBlocking {
|
||||
val sas = getDevice(otherUserId, otherDeviceId)?.startVerification()
|
||||
if (sas != null) {
|
||||
dispatchTxAdded(sas)
|
||||
sas.transactionId
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw IllegalArgumentException("Unknown verification method")
|
||||
|
|
|
@ -758,6 +758,30 @@ impl OlmMachine {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn start_sas_with_device(
|
||||
&self,
|
||||
user_id: &str,
|
||||
device_id: &str,
|
||||
) -> Result<Option<StartSasResult>, CryptoStoreError> {
|
||||
let user_id = UserId::try_from(user_id)?;
|
||||
|
||||
Ok(
|
||||
if let Some(device) = self
|
||||
.runtime
|
||||
.block_on(self.inner.get_device(&user_id, device_id.into()))?
|
||||
{
|
||||
let (sas, request) = self.runtime.block_on(device.start_verification())?;
|
||||
|
||||
Some(StartSasResult {
|
||||
sas: sas.into(),
|
||||
request: request.into(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn start_sas_verification(
|
||||
&self,
|
||||
user_id: &str,
|
||||
|
|
|
@ -199,6 +199,8 @@ interface OlmMachine {
|
|||
sequence<string> methods
|
||||
);
|
||||
|
||||
[Throws=CryptoStoreError]
|
||||
StartSasResult? start_sas_with_device([ByRef] string user_id, [ByRef] string device_id);
|
||||
[Throws=CryptoStoreError]
|
||||
StartSasResult? start_sas_verification([ByRef] string user_id, [ByRef] string flow_id);
|
||||
[Throws=CryptoStoreError]
|
||||
|
|
|
@ -19,7 +19,7 @@ use ruma::{
|
|||
|
||||
use matrix_sdk_crypto::{
|
||||
IncomingResponse, OutgoingRequest, OutgoingVerificationRequest as SdkVerificationRequest,
|
||||
ToDeviceRequest, RoomMessageRequest,
|
||||
RoomMessageRequest, ToDeviceRequest,
|
||||
};
|
||||
|
||||
pub enum OutgoingVerificationRequest {
|
||||
|
@ -39,11 +39,7 @@ pub enum OutgoingVerificationRequest {
|
|||
impl From<SdkVerificationRequest> for OutgoingVerificationRequest {
|
||||
fn from(r: SdkVerificationRequest) -> Self {
|
||||
match r {
|
||||
SdkVerificationRequest::ToDevice(r) => Self::ToDevice {
|
||||
request_id: r.txn_id_string(),
|
||||
event_type: r.event_type.to_string(),
|
||||
body: serde_json::to_string(&r.messages).expect("Can't serialize to-device body"),
|
||||
},
|
||||
SdkVerificationRequest::ToDevice(r) => r.into(),
|
||||
SdkVerificationRequest::InRoom(r) => Self::InRoom {
|
||||
request_id: r.txn_id.to_string(),
|
||||
room_id: r.room_id.to_string(),
|
||||
|
@ -55,6 +51,16 @@ impl From<SdkVerificationRequest> for OutgoingVerificationRequest {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<ToDeviceRequest> for OutgoingVerificationRequest {
|
||||
fn from(r: ToDeviceRequest) -> Self {
|
||||
Self::ToDevice {
|
||||
request_id: r.txn_id_string(),
|
||||
event_type: r.event_type.to_string(),
|
||||
body: serde_json::to_string(&r.messages).expect("Can't serialize to-device body"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Request {
|
||||
ToDevice {
|
||||
request_id: String,
|
||||
|
@ -138,8 +144,7 @@ impl From<&RoomMessageRequest> for Request {
|
|||
request_id: r.txn_id.to_string(),
|
||||
room_id: r.room_id.to_string(),
|
||||
event_type: r.content.event_type().to_string(),
|
||||
content: serde_json::to_string(&r.content)
|
||||
.expect("Can't serialize message content"),
|
||||
content: serde_json::to_string(&r.content).expect("Can't serialize message content"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue