diff --git a/rust-sdk/Cargo.toml b/rust-sdk/Cargo.toml index fdf306d537..30556a48b4 100644 --- a/rust-sdk/Cargo.toml +++ b/rust-sdk/Cargo.toml @@ -12,6 +12,7 @@ name = "matrix_crypto" serde = "1.0.126" serde_json = "1.0.64" http = "0.2.4" +base64 = "0.13.0" thiserror = "1.0.25" tracing = "0.1.26" @@ -19,20 +20,20 @@ tracing-subscriber = "0.2.18" uniffi = "0.12.0" [dependencies.js_int] -version = "0.2.0" +version = "0.2.1" features = ["lax_deserialize"] [dependencies.matrix-sdk-common] git = "https://github.com/matrix-org/matrix-rust-sdk/" -rev = "710b519c110278a0857f26a86a0f8329609c1a5f" +rev = "b62f725bead1f44b2038784e5321909f71a4af4a" [dependencies.matrix-sdk-crypto] git = "https://github.com/matrix-org/matrix-rust-sdk/" -rev = "710b519c110278a0857f26a86a0f8329609c1a5f" +rev = "b62f725bead1f44b2038784e5321909f71a4af4a" features = ["sled_cryptostore"] [dependencies.tokio] -version = "1.6.0" +version = "1.7.1" default_features = false features = ["rt-multi-thread"] diff --git a/rust-sdk/src/lib.rs b/rust-sdk/src/lib.rs index fe2d973033..e21591d976 100644 --- a/rust-sdk/src/lib.rs +++ b/rust-sdk/src/lib.rs @@ -7,7 +7,7 @@ mod responses; pub use device::Device; pub use error::{CryptoStoreError, DecryptionError, KeyImportError, MachineCreationError}; pub use logger::{set_logger, Logger}; -pub use machine::{KeyRequestPair, OlmMachine, Sas, StartSasResult, VerificationRequest}; +pub use machine::{KeyRequestPair, OlmMachine, Sas, StartSasResult, VerificationRequest, QrCode, Verification}; pub use responses::{ DeviceLists, KeysImportResult, OutgoingVerificationRequest, Request, RequestType, }; diff --git a/rust-sdk/src/machine.rs b/rust-sdk/src/machine.rs index 8cdfd40e57..417cf54c83 100644 --- a/rust-sdk/src/machine.rs +++ b/rust-sdk/src/machine.rs @@ -5,6 +5,7 @@ use std::{ }; use js_int::UInt; +use base64::encode; use ruma::{ api::{ client::r0::{ @@ -30,7 +31,8 @@ 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, - Sas as InnerSas, Verification, VerificationRequest as InnerVerificationRequest, + QrVerification as InnerQr, Sas as InnerSas, Verification as RustVerification, + VerificationRequest as InnerVerificationRequest, }; use crate::{ @@ -46,6 +48,11 @@ pub struct OlmMachine { runtime: Runtime, } +pub enum Verification { + SasV1 { sas: Sas }, + QrCodeV1 { qrcode: QrCode }, +} + pub struct Sas { pub other_user_id: String, pub other_device_id: String, @@ -62,6 +69,36 @@ pub struct Sas { pub timed_out: bool, } +pub struct QrCode { + pub other_user_id: String, + pub flow_id: String, + pub other_device_id: String, + pub room_id: Option, + pub is_cancelled: bool, + pub is_done: bool, + pub we_started: bool, + pub other_side_scanned: bool, + pub cancel_code: Option, + pub cancelled_by_us: Option, +} + +impl From for QrCode { + fn from(qr: InnerQr) -> Self { + Self { + other_user_id: qr.other_user_id().to_string(), + flow_id: qr.flow_id().as_str().to_owned(), + is_cancelled: qr.is_cancelled(), + is_done: qr.is_done(), + cancel_code: qr.cancel_code().map(|c| c.to_string()), + cancelled_by_us: qr.cancelled_by_us(), + we_started: qr.we_started(), + other_side_scanned: qr.is_scanned(), + other_device_id: qr.other_device_id().to_string(), + room_id: qr.room_id().map(|r| r.to_string()), + } + } +} + pub struct StartSasResult { pub sas: Sas, pub request: OutgoingVerificationRequest, @@ -661,11 +698,38 @@ impl OlmMachine { todo!() } - pub fn get_verification(&self, user_id: &str, flow_id: &str) -> Option { + 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())) + .map(|v| match v { + RustVerification::SasV1(s) => Verification::SasV1 { sas: s.into() }, + RustVerification::QrV1(qr) => Verification::QrCodeV1 { qrcode: qr.into() }, + }) + } + + pub fn start_qr_verification( + &self, + user_id: &str, + flow_id: &str, + ) -> Result, CryptoStoreError> { + let user_id = UserId::try_from(user_id)?; + + if let Some(verification) = self.inner.get_verification_request(&user_id, flow_id) { + Ok(self + .runtime + .block_on(verification.generate_qr_code())? + .map(|qr| qr.into())) + } else { + Ok(None) + } + } + + pub fn generate_qr_code(&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.qr_v1().and_then(|qr| qr.to_bytes().map(|b| encode(b)).ok())) } pub fn start_sas_verification( @@ -711,8 +775,10 @@ impl OlmMachine { if let Some(verification) = self.inner.get_verification(&user_id, flow_id) { match verification { - Verification::SasV1(v) => v.cancel_with_code(cancel_code.into()).map(|r| r.into()), - Verification::QrV1(v) => v.cancel().map(|r| r.into()), + RustVerification::SasV1(v) => { + v.cancel_with_code(cancel_code.into()).map(|r| r.into()) + } + RustVerification::QrV1(v) => v.cancel().map(|r| r.into()), } } else { None @@ -729,10 +795,10 @@ impl OlmMachine { Ok( if let Some(verification) = self.inner.get_verification(&user_id, flow_id) { match verification { - Verification::SasV1(v) => { + RustVerification::SasV1(v) => { self.runtime.block_on(v.confirm())?.0.map(|r| r.into()) } - Verification::QrV1(v) => v.confirm_scanning().map(|r| r.into()), + RustVerification::QrV1(v) => v.confirm_scanning().map(|r| r.into()), } } else { None diff --git a/rust-sdk/src/olm.udl b/rust-sdk/src/olm.udl index 41baa128a3..47cb8a6c08 100644 --- a/rust-sdk/src/olm.udl +++ b/rust-sdk/src/olm.udl @@ -86,6 +86,19 @@ dictionary Sas { boolean supports_emoji; }; +dictionary QrCode { + string other_user_id; + string other_device_id; + string flow_id; + string? cancel_code; + string? room_id; + boolean we_started; + boolean? cancelled_by_us; + boolean is_done; + boolean is_cancelled; + boolean other_side_scanned; +}; + dictionary VerificationRequest { string other_user_id; string? other_device_id; @@ -102,6 +115,12 @@ dictionary VerificationRequest { }; +[Enum] +interface Verification { + SasV1(Sas sas); + QrCodeV1(QrCode qrcode); +}; + dictionary KeyRequestPair { Request? cancellation; Request key_request; @@ -167,7 +186,7 @@ interface OlmMachine { sequence get_verification_requests([ByRef] string user_id); VerificationRequest? get_verification_request([ByRef] string user_id, [ByRef] string flow_id); - Sas? get_verification([ByRef] string user_id, [ByRef] string flow_id); + Verification? get_verification([ByRef] string user_id, [ByRef] string flow_id); OutgoingVerificationRequest? accept_verification_request( [ByRef] string user_id, @@ -185,6 +204,9 @@ interface OlmMachine { [ByRef] string cancel_code ); OutgoingVerificationRequest? accept_sas_verification([ByRef] string user_id, [ByRef] string flow_id); + [Throws=CryptoStoreError] + QrCode? start_qr_verification([ByRef] string user_id, [ByRef] string flow_id); + string? generate_qr_code([ByRef] string user_id, [ByRef] string flow_id); sequence? get_emoji_index([ByRef] string user_id, [ByRef] string flow_id); sequence? get_decimals([ByRef] string user_id, [ByRef] string flow_id);