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 e234c3cd0a..d62d880676 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 @@ -28,12 +28,14 @@ import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.session.crypto.MXCryptoError import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Event +import org.matrix.android.sdk.api.session.crypto.verification.EmojiRepresentation import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.model.rest.UnsignedDeviceInfo +import org.matrix.android.sdk.internal.crypto.verification.getEmojiForCode import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.session.sync.model.DeviceListResponse import org.matrix.android.sdk.internal.session.sync.model.DeviceOneTimeKeysCountSyncResponse @@ -41,6 +43,8 @@ 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.Sas as InnerSas +import uniffi.olm.OutgoingVerificationRequest import uniffi.olm.Device import uniffi.olm.DeviceLists import uniffi.olm.KeyRequestPair @@ -122,6 +126,65 @@ internal class DeviceUpdateObserver { } } +internal class Sas(private val machine: InnerMachine, private var inner: InnerSas) { + private fun refreshData() { + val sas = this.machine.getVerification(this.inner.flowId) + + if (sas != null) { + this.inner = sas + } + + return + } + + fun isCanceled(): Boolean { + refreshData() + return this.inner.isCanceled + } + + fun isDone(): Boolean { + refreshData() + return this.inner.isDone + } + + fun timedOut(): Boolean { + refreshData() + return this.inner.timedOut + } + + fun canBePresented(): Boolean { + refreshData() + return this.inner.canBePresented + } + + fun accept(): OutgoingVerificationRequest? { + return this.machine.acceptVerification(inner.flowId) + } + + @Throws(CryptoStoreErrorException::class) + suspend fun confirm(): OutgoingVerificationRequest? = withContext(Dispatchers.IO) { + machine.confirmVerification(inner.flowId) + } + + fun cancel(): OutgoingVerificationRequest? { + return this.machine.cancelVerification(inner.flowId) + } + + fun emoji(): List { + val emojiIndex = this.machine.getEmojiIndex(this.inner.flowId) + + return if (emojiIndex != null) { + emojiIndex.map { getEmojiForCode(it) } + } else { + listOf() + } + } + + fun decimals(): List? { + return this.machine.getDecimals(this.inner.flowId) + } +} + internal class OlmMachine(user_id: String, device_id: String, path: File, deviceObserver: DeviceUpdateObserver) { private val inner: InnerMachine = InnerMachine(user_id, device_id, path.toString()) private val deviceUpdateObserver = deviceObserver @@ -533,4 +596,17 @@ internal class OlmMachine(user_id: String, device_id: String, path: File, device fun discardRoomKey(roomId: String) { runBlocking { inner.discardRoomKey(roomId) } } + + /** + * Get an active verification + */ + fun getVerification(flowId: String): Sas? { + val sas = this.inner.getVerification(flowId) + + return if (sas == null) { + null + } else { + Sas(this.inner, sas) + } + } } diff --git a/rust-sdk/src/error.rs b/rust-sdk/src/error.rs index aa24c303b2..1d0128a809 100644 --- a/rust-sdk/src/error.rs +++ b/rust-sdk/src/error.rs @@ -1,7 +1,7 @@ -use ruma::identifiers::Error as RumaIdentifierError; use matrix_sdk_crypto::{ store::CryptoStoreError as InnerStoreError, KeyExportError, MegolmError, OlmError, }; +use ruma::identifiers::Error as RumaIdentifierError; #[derive(Debug, thiserror::Error)] pub enum MachineCreationError { diff --git a/rust-sdk/src/lib.rs b/rust-sdk/src/lib.rs index 99f01ad7f3..e7ac395fd9 100644 --- a/rust-sdk/src/lib.rs +++ b/rust-sdk/src/lib.rs @@ -7,8 +7,10 @@ mod responses; pub use device::Device; pub use error::{CryptoStoreError, DecryptionError, KeyImportError, MachineCreationError}; pub use logger::{set_logger, Logger}; -pub use machine::{OlmMachine, Sas, KeyRequestPair}; -pub use responses::{DeviceLists, KeysImportResult, Request, RequestType}; +pub use machine::{KeyRequestPair, OlmMachine, Sas}; +pub use responses::{ + DeviceLists, KeysImportResult, OutgoingVerificationRequest, Request, RequestType, +}; pub trait ProgressListener { fn on_progress(&self, progress: i32, total: i32); diff --git a/rust-sdk/src/machine.rs b/rust-sdk/src/machine.rs index 4c6e42d02f..028169bff1 100644 --- a/rust-sdk/src/machine.rs +++ b/rust-sdk/src/machine.rs @@ -30,12 +30,12 @@ use tokio::runtime::Runtime; use matrix_sdk_common::{deserialized_responses::AlgorithmInfo, uuid::Uuid}; use matrix_sdk_crypto::{ decrypt_key_export, encrypt_key_export, EncryptionSettings, OlmMachine as InnerMachine, - OutgoingVerificationRequest, Sas as InnerSas, + Sas as InnerSas, }; use crate::{ error::{CryptoStoreError, DecryptionError, MachineCreationError}, - responses::{response_from_string, OwnedResponse}, + responses::{response_from_string, OutgoingVerificationRequest, OwnedResponse}, DecryptedEvent, Device, DeviceLists, KeyImportError, KeysImportResult, ProgressListener, Request, RequestType, }; @@ -252,13 +252,11 @@ impl OlmMachine { }) .collect(); - let events = self - .runtime - .block_on( - self.inner - .receive_sync_changes(events, &device_changes, &key_counts), - ) - .unwrap(); + let events = self.runtime.block_on(self.inner.receive_sync_changes( + events, + &device_changes, + &key_counts, + ))?; Ok(serde_json::to_string(&events)?) } @@ -570,6 +568,7 @@ impl OlmMachine { pub fn start_verification(&self, device: &Device) -> Result { let user_id = UserId::try_from(device.user_id.clone())?; let device_id = device.device_id.as_str().into(); + // TODO remove the unwrap let device = self .runtime .block_on(self.inner.get_device(&user_id, device_id))? diff --git a/rust-sdk/src/olm.udl b/rust-sdk/src/olm.udl index 6f2b42e626..cdf5c2d7c4 100644 --- a/rust-sdk/src/olm.udl +++ b/rust-sdk/src/olm.udl @@ -78,6 +78,12 @@ dictionary KeyRequestPair { Request key_request; }; +[Enum] +interface OutgoingVerificationRequest { + ToDevice(string request_id, string event_type, string body); + InRoom(string request_id, string room_id, string event_type, string content); +}; + [Enum] interface Request { ToDevice(string request_id, string event_type, string body); @@ -130,8 +136,17 @@ interface OlmMachine { [Throws=CryptoStoreError] sequence share_room_key([ByRef] string room_id, sequence users); + Sas? get_verification([ByRef] string flow_id); + [Throws=CryptoStoreError] Sas start_verification([ByRef] Device device); + [Throws=CryptoStoreError] + OutgoingVerificationRequest? confirm_verification([ByRef] string flow_id); + OutgoingVerificationRequest? cancel_verification([ByRef] string flow_id); + OutgoingVerificationRequest? accept_verification([ByRef] string flow_id); + + sequence? get_emoji_index([ByRef] string flow_id); + sequence? get_decimals([ByRef] string flow_id); [Throws=DecryptionError] KeyRequestPair request_room_key([ByRef] string event, [ByRef] string room_id); diff --git a/rust-sdk/src/responses.rs b/rust-sdk/src/responses.rs index bda045debf..4cecd4981b 100644 --- a/rust-sdk/src/responses.rs +++ b/rust-sdk/src/responses.rs @@ -13,10 +13,47 @@ use ruma::{ to_device::send_event_to_device::Response as ToDeviceResponse, }, assign, + events::EventContent, identifiers::UserId, }; -use matrix_sdk_crypto::{IncomingResponse, OutgoingRequest, ToDeviceRequest}; +use matrix_sdk_crypto::{ + IncomingResponse, OutgoingRequest, OutgoingVerificationRequest as SdkVerificationRequest, + ToDeviceRequest, +}; + +pub enum OutgoingVerificationRequest { + ToDevice { + request_id: String, + event_type: String, + body: String, + }, + InRoom { + request_id: String, + room_id: String, + event_type: String, + content: String, + }, +} + +impl From 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::InRoom(r) => Self::InRoom { + request_id: r.txn_id.to_string(), + room_id: r.room_id.to_string(), + content: serde_json::to_string(&r.content) + .expect("Can't serialize message content"), + event_type: r.content.event_type().to_string(), + }, + } + } +} pub enum Request { ToDevice { @@ -74,7 +111,7 @@ impl From for Request { Request::ToDevice { request_id: r.txn_id_string(), event_type: r.event_type.to_string(), - body: serde_json::to_string(&r.messages).unwrap(), + body: serde_json::to_string(&r.messages).expect("Can't serialize to-device body"), } } } @@ -84,7 +121,7 @@ impl From<&ToDeviceRequest> for Request { Request::ToDevice { request_id: r.txn_id_string(), event_type: r.event_type.to_string(), - body: serde_json::to_string(&r.messages).unwrap(), + body: serde_json::to_string(&r.messages).expect("Can't serialize to-device body"), } } }