diff --git a/MatrixSDK.podspec b/MatrixSDK.podspec index cb472b38f8..98a36bc877 100644 --- a/MatrixSDK.podspec +++ b/MatrixSDK.podspec @@ -66,7 +66,7 @@ Pod::Spec.new do |s| # Experimental / NOT production-ready Rust-based crypto library s.subspec 'CryptoSDK' do |ss| - ss.dependency 'MatrixSDKCrypto', '0.1.7', :configurations => ["DEBUG"], :inhibit_warnings => true + ss.dependency 'MatrixSDKCrypto', '0.1.8', :configurations => ["DEBUG"], :inhibit_warnings => true end end diff --git a/MatrixSDK.xcodeproj/project.pbxproj b/MatrixSDK.xcodeproj/project.pbxproj index 10052ebebd..5fff74b920 100644 --- a/MatrixSDK.xcodeproj/project.pbxproj +++ b/MatrixSDK.xcodeproj/project.pbxproj @@ -1882,6 +1882,10 @@ ED558071296F1BEE003443E3 /* MXCryptoMigrationV2Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED55806F296F1BEE003443E3 /* MXCryptoMigrationV2Tests.swift */; }; ED5580732970265A003443E3 /* MXCryptoMachineLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5580722970265A003443E3 /* MXCryptoMachineLogger.swift */; }; ED5580742970265A003443E3 /* MXCryptoMachineLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5580722970265A003443E3 /* MXCryptoMachineLogger.swift */; }; + ED55807629709943003443E3 /* MatrixSDKTestsE2EData.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED55807529709943003443E3 /* MatrixSDKTestsE2EData.swift */; }; + ED55807729709943003443E3 /* MatrixSDKTestsE2EData.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED55807529709943003443E3 /* MatrixSDKTestsE2EData.swift */; }; + ED5580792970A879003443E3 /* MatrixSDKTestsData.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5580782970A879003443E3 /* MatrixSDKTestsData.swift */; }; + ED55807A2970A879003443E3 /* MatrixSDKTestsData.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5580782970A879003443E3 /* MatrixSDKTestsData.swift */; }; ED5AE8C52816C8CF00105072 /* MXCoreDataRoomSummaryStore.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = ED5AE8C22816C8CF00105072 /* MXCoreDataRoomSummaryStore.xcdatamodeld */; }; ED5AE8C62816C8CF00105072 /* MXCoreDataRoomSummaryStore.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = ED5AE8C22816C8CF00105072 /* MXCoreDataRoomSummaryStore.xcdatamodeld */; }; ED5C753C28B3E80300D24E85 /* MXLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = ED5C753528B3E80300D24E85 /* MXLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1900,8 +1904,8 @@ ED5C754928B3E80300D24E85 /* MXLogObjcWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = ED5C753B28B3E80300D24E85 /* MXLogObjcWrapper.h */; settings = {ATTRIBUTES = (Public, ); }; }; ED5C95CE2833E85600843D82 /* MXOlmDeviceUnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5C95CD2833E85600843D82 /* MXOlmDeviceUnitTests.swift */; }; ED5C95CF2833E85600843D82 /* MXOlmDeviceUnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5C95CD2833E85600843D82 /* MXOlmDeviceUnitTests.swift */; }; - ED647E3E292CE64400A47519 /* MXSessionSyncProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED647E3D292CE64400A47519 /* MXSessionSyncProgress.swift */; }; - ED647E3F292CE64400A47519 /* MXSessionSyncProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED647E3D292CE64400A47519 /* MXSessionSyncProgress.swift */; }; + ED647E3E292CE64400A47519 /* MXSessionStartupProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED647E3D292CE64400A47519 /* MXSessionStartupProgress.swift */; }; + ED647E3F292CE64400A47519 /* MXSessionStartupProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED647E3D292CE64400A47519 /* MXSessionStartupProgress.swift */; }; ED6DABFC28C7542800ECDCB6 /* MXRoomKeyInfoFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED6DABFB28C7542800ECDCB6 /* MXRoomKeyInfoFactory.swift */; }; ED6DABFD28C7542800ECDCB6 /* MXRoomKeyInfoFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED6DABFB28C7542800ECDCB6 /* MXRoomKeyInfoFactory.swift */; }; ED6DAC0228C76F0A00ECDCB6 /* MXRoomKeyInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED6DAC0128C76F0A00ECDCB6 /* MXRoomKeyInfo.swift */; }; @@ -1975,8 +1979,8 @@ ED8F1D3C2885BB2D00F897E7 /* MXCryptoProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED8F1D3A2885BB2D00F897E7 /* MXCryptoProtocols.swift */; }; ED96F2BA294A2E9A002DB8F6 /* MXDummyBackgroundCrypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED96F2B9294A2E9A002DB8F6 /* MXDummyBackgroundCrypto.swift */; }; ED96F2BB294A2E9A002DB8F6 /* MXDummyBackgroundCrypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED96F2B9294A2E9A002DB8F6 /* MXDummyBackgroundCrypto.swift */; }; - ED997856292E2877006B5248 /* MXSessionSyncProgressUnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED997855292E2877006B5248 /* MXSessionSyncProgressUnitTests.swift */; }; - ED997857292E2877006B5248 /* MXSessionSyncProgressUnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED997855292E2877006B5248 /* MXSessionSyncProgressUnitTests.swift */; }; + ED997856292E2877006B5248 /* MXSessionStartupProgressUnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED997855292E2877006B5248 /* MXSessionStartupProgressUnitTests.swift */; }; + ED997857292E2877006B5248 /* MXSessionStartupProgressUnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED997855292E2877006B5248 /* MXSessionStartupProgressUnitTests.swift */; }; EDA2CDD628F5C4230088ACE7 /* MXQRCodeTransactionV2UnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA2CDD528F5C4230088ACE7 /* MXQRCodeTransactionV2UnitTests.swift */; }; EDA2CDD728F5C4230088ACE7 /* MXQRCodeTransactionV2UnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA2CDD528F5C4230088ACE7 /* MXQRCodeTransactionV2UnitTests.swift */; }; EDA69340290BA92E00223252 /* MXCryptoMachineUnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA6933F290BA92E00223252 /* MXCryptoMachineUnitTests.swift */; }; @@ -3079,6 +3083,8 @@ ED55806C296F0E3A003443E3 /* MXCryptoMigrationStoreUnitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXCryptoMigrationStoreUnitTests.swift; sourceTree = ""; }; ED55806F296F1BEE003443E3 /* MXCryptoMigrationV2Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXCryptoMigrationV2Tests.swift; sourceTree = ""; }; ED5580722970265A003443E3 /* MXCryptoMachineLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXCryptoMachineLogger.swift; sourceTree = ""; }; + ED55807529709943003443E3 /* MatrixSDKTestsE2EData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixSDKTestsE2EData.swift; sourceTree = ""; }; + ED5580782970A879003443E3 /* MatrixSDKTestsData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixSDKTestsData.swift; sourceTree = ""; }; ED5AE8C32816C8CF00105072 /* MXRoomSummaryCoreDataStore2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MXRoomSummaryCoreDataStore2.xcdatamodel; sourceTree = ""; }; ED5AE8C42816C8CF00105072 /* MXRoomSummaryCoreDataStore.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MXRoomSummaryCoreDataStore.xcdatamodel; sourceTree = ""; }; ED5C753528B3E80300D24E85 /* MXLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXLogger.h; sourceTree = ""; }; @@ -3089,7 +3095,7 @@ ED5C753A28B3E80300D24E85 /* MXLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXLogger.m; sourceTree = ""; }; ED5C753B28B3E80300D24E85 /* MXLogObjcWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXLogObjcWrapper.h; sourceTree = ""; }; ED5C95CD2833E85600843D82 /* MXOlmDeviceUnitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXOlmDeviceUnitTests.swift; sourceTree = ""; }; - ED647E3D292CE64400A47519 /* MXSessionSyncProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXSessionSyncProgress.swift; sourceTree = ""; }; + ED647E3D292CE64400A47519 /* MXSessionStartupProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXSessionStartupProgress.swift; sourceTree = ""; }; ED6DABFB28C7542800ECDCB6 /* MXRoomKeyInfoFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MXRoomKeyInfoFactory.swift; sourceTree = ""; }; ED6DAC0128C76F0A00ECDCB6 /* MXRoomKeyInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXRoomKeyInfo.swift; sourceTree = ""; }; ED6DAC0628C77E1100ECDCB6 /* MXForwardedRoomKeyEventContentUnitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXForwardedRoomKeyEventContentUnitTests.swift; sourceTree = ""; }; @@ -3126,7 +3132,7 @@ ED8F1D332885ADE200F897E7 /* MXCryptoProtocolStubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXCryptoProtocolStubs.swift; sourceTree = ""; }; ED8F1D3A2885BB2D00F897E7 /* MXCryptoProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MXCryptoProtocols.swift; sourceTree = ""; }; ED96F2B9294A2E9A002DB8F6 /* MXDummyBackgroundCrypto.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MXDummyBackgroundCrypto.swift; sourceTree = ""; }; - ED997855292E2877006B5248 /* MXSessionSyncProgressUnitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXSessionSyncProgressUnitTests.swift; sourceTree = ""; }; + ED997855292E2877006B5248 /* MXSessionStartupProgressUnitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXSessionStartupProgressUnitTests.swift; sourceTree = ""; }; EDA2CDD528F5C4230088ACE7 /* MXQRCodeTransactionV2UnitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXQRCodeTransactionV2UnitTests.swift; sourceTree = ""; }; EDA6933F290BA92E00223252 /* MXCryptoMachineUnitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXCryptoMachineUnitTests.swift; sourceTree = ""; }; EDAAC41228E2F86800DD89B5 /* MXCryptoSecretStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXCryptoSecretStore.h; sourceTree = ""; }; @@ -4249,7 +4255,7 @@ 320DFDD519DD99B60068622A /* MXRestClient.m */, F0C34CBA1C18C93700C36F09 /* MXSDKOptions.m */, 320DFDD119DD99B60068622A /* MXSession.m */, - ED647E3D292CE64400A47519 /* MXSessionSyncProgress.swift */, + ED647E3D292CE64400A47519 /* MXSessionStartupProgress.swift */, 327E9AEC2289C5EC00A98BC1 /* Aggregations */, EC383BA0253DE49B002FBBE6 /* Background */, 3259CFD9260266F700C365DB /* Categories */, @@ -4297,7 +4303,9 @@ 32832B5B1BCC048300241108 /* MXStoreTests.h */, 32C03CB52123076F00D92712 /* DirectRoomTests.m */, 3281E8A719E41A2000976E1A /* MatrixSDKTestsData.m */, + ED5580782970A879003443E3 /* MatrixSDKTestsData.swift */, 32BD34BD1E84134A006EDC0D /* MatrixSDKTestsE2EData.m */, + ED55807529709943003443E3 /* MatrixSDKTestsE2EData.swift */, 3264DB931CECA72900B99881 /* MXAccountDataTests.m */, EC40385C28A16EDA0067D5B8 /* MXAes256KeyBackupTests.m */, 32792BE02296C64200F4FC9D /* MXAggregatedEditsTests.m */, @@ -4384,7 +4392,7 @@ 3A4BB661291D93EA006F7585 /* MXRoomEventFilterUnitTests.swift */, EC1165CB27107F3E0089FA56 /* MXRoomListDataManagerTests.swift */, ED51943828462D130006EEC6 /* MXRoomStateUnitTests.swift */, - ED997855292E2877006B5248 /* MXSessionSyncProgressUnitTests.swift */, + ED997855292E2877006B5248 /* MXSessionStartupProgressUnitTests.swift */, B1F939F426289F2600D0E525 /* MXSpaceChildContentTests.swift */, B1660F1B260A20B900C3AA12 /* MXSpaceServiceTest.swift */, EC1165CA27107F3E0089FA56 /* MXStoreRoomListDataManagerUnitTests.swift */, @@ -6994,7 +7002,7 @@ EDAAC42428E3177000DD89B5 /* MXRecoveryServiceDependencies.swift in Sources */, 3A7509BB26FC61DF00B85773 /* MXSpaceNotificationCounter.swift in Sources */, 32E402BA21C957D2004E87A6 /* MXOlmSession.m in Sources */, - ED647E3E292CE64400A47519 /* MXSessionSyncProgress.swift in Sources */, + ED647E3E292CE64400A47519 /* MXSessionStartupProgress.swift in Sources */, EC8A53C525B1BC77004E0802 /* MXTurnServerResponse.m in Sources */, 32A151271DABB0CB00400192 /* MXMegolmDecryption.m in Sources */, ED558068296F0361003443E3 /* MXCryptoMigrationStore.swift in Sources */, @@ -7317,6 +7325,7 @@ 32684CB821085F770046D2F9 /* MXLazyLoadingTests.m in Sources */, 18121F75273E6D2400B68ADF /* MXPollBuilderTests.swift in Sources */, ED7019F72886CA6C00FC31B9 /* VerificationRequestStub.swift in Sources */, + ED55807629709943003443E3 /* MatrixSDKTestsE2EData.swift in Sources */, B14EECEE2578FE3F00448735 /* MXAuthenticationSessionUnitTests.swift in Sources */, ED558070296F1BEE003443E3 /* MXCryptoMigrationV2Tests.swift in Sources */, ED2DD11D286C4F4400F06731 /* MXCryptoRequestsUnitTests.swift in Sources */, @@ -7355,7 +7364,8 @@ 32EEA84A2603FDD60041425B /* MXResponseUnitTests.swift in Sources */, 32322A481E57264E005DD155 /* MXSelfSignedHomeserverTests.m in Sources */, 325653831A2E14ED00CC0423 /* MXStoreTests.m in Sources */, - ED997856292E2877006B5248 /* MXSessionSyncProgressUnitTests.swift in Sources */, + ED997856292E2877006B5248 /* MXSessionStartupProgressUnitTests.swift in Sources */, + ED5580792970A879003443E3 /* MatrixSDKTestsData.swift in Sources */, 18C26C4A273C0B3A00805154 /* PollAggregator.swift in Sources */, 3295719A1B024D2B00ABB3BA /* MXMockCallStackCall.m in Sources */, 324DD2BB246C3ADE00377005 /* MXCryptoSecretStorageTests.m in Sources */, @@ -7650,7 +7660,7 @@ EDAAC42528E3177300DD89B5 /* MXRecoveryServiceDependencies.swift in Sources */, EC60EDAB265CFE3B00B39A4E /* MXRoomSyncTimeline.m in Sources */, B14EF2202397E90400758AF0 /* (null) in Sources */, - ED647E3F292CE64400A47519 /* MXSessionSyncProgress.swift in Sources */, + ED647E3F292CE64400A47519 /* MXSessionStartupProgress.swift in Sources */, B14EF2212397E90400758AF0 /* MX3PID.swift in Sources */, 18121F79273E6E4100B68ADF /* PollBuilder.swift in Sources */, ED558069296F0361003443E3 /* MXCryptoMigrationStore.swift in Sources */, @@ -7973,6 +7983,7 @@ EDF1B6942876CD8600BBBCEE /* MXTaskQueueUnitTests.swift in Sources */, B1E09A442397FD940057C069 /* Dummy.swift in Sources */, ED7019F82886CA6C00FC31B9 /* VerificationRequestStub.swift in Sources */, + ED55807729709943003443E3 /* MatrixSDKTestsE2EData.swift in Sources */, 18121F76273E6D2400B68ADF /* MXPollBuilderTests.swift in Sources */, ED558071296F1BEE003443E3 /* MXCryptoMigrationV2Tests.swift in Sources */, B1E09A1A2397FCE90057C069 /* MXAggregatedEditsTests.m in Sources */, @@ -8011,7 +8022,8 @@ B1E09A1E2397FCE90057C069 /* MXCryptoShareTests.m in Sources */, B1E09A422397FD820057C069 /* MXCryptoTests.m in Sources */, B1E09A382397FD7D0057C069 /* MXUserTests.m in Sources */, - ED997857292E2877006B5248 /* MXSessionSyncProgressUnitTests.swift in Sources */, + ED997857292E2877006B5248 /* MXSessionStartupProgressUnitTests.swift in Sources */, + ED55807A2970A879003443E3 /* MatrixSDKTestsData.swift in Sources */, 18C26C4B273C0B3A00805154 /* PollAggregator.swift in Sources */, 324DD2BC246C3ADE00377005 /* MXCryptoSecretStorageTests.m in Sources */, B19A30D92404335D00FB6F35 /* MXQRCodeDataUnitTests.m in Sources */, diff --git a/MatrixSDK/Background/MXBackgroundSyncService.swift b/MatrixSDK/Background/MXBackgroundSyncService.swift index 8695914aa3..a83d4ef272 100644 --- a/MatrixSDK/Background/MXBackgroundSyncService.swift +++ b/MatrixSDK/Background/MXBackgroundSyncService.swift @@ -83,7 +83,7 @@ public enum MXBackgroundSyncServiceError: Error { crypto = { #if DEBUG - if MXSDKOptions.sharedInstance().enableCryptoV2 { + if MXSDKOptions.sharedInstance().isCryptoSDKAvailable && MXSDKOptions.sharedInstance().enableCryptoSDK { // Crypto V2 is currently unable to decrypt notifications due to single-process store, // so it uses dummy background crypto that does not do anything. return MXDummyBackgroundCrypto() diff --git a/MatrixSDK/Crypto/Algorithms/RoomEvent/MXRoomEventDecryption.swift b/MatrixSDK/Crypto/Algorithms/RoomEvent/MXRoomEventDecryption.swift index b666371dd2..0707c503f5 100644 --- a/MatrixSDK/Crypto/Algorithms/RoomEvent/MXRoomEventDecryption.swift +++ b/MatrixSDK/Crypto/Algorithms/RoomEvent/MXRoomEventDecryption.swift @@ -250,6 +250,13 @@ actor MXRoomEventDecryption: MXRoomEventDecrypting { ]) return trackedDecryptionResult(for: event, error: error) } + case .Store(let message): + log.error("Failed to decrypt event due to store error", context: [ + "session_id": sessionId, + "message": message, + "error": error + ]) + return trackedDecryptionResult(for: event, error: error) } } diff --git a/MatrixSDK/Crypto/CryptoMachine/MXCryptoMachine.swift b/MatrixSDK/Crypto/CryptoMachine/MXCryptoMachine.swift index 328213415e..ba072848c6 100644 --- a/MatrixSDK/Crypto/CryptoMachine/MXCryptoMachine.swift +++ b/MatrixSDK/Crypto/CryptoMachine/MXCryptoMachine.swift @@ -94,16 +94,18 @@ class MXCryptoMachine { try await requests.queryKeys(users: users) } self.getRoomAction = getRoomAction - } - - func start() async throws { + let details = """ - Starting the crypto machine for \(userId) + Initialized the crypto machine for \(userId) - device id : \(deviceId) - ed25519 : \(deviceEd25519Key ?? "") - curve25519 : \(deviceCurve25519Key ?? "") """ log.debug(details) + } + + func uploadKeysIfNecessary() async throws { + log.debug("Checking for keys to upload") var keysUploadRequest: Request? for request in try machine.outgoingRequests() { @@ -120,7 +122,6 @@ class MXCryptoMachine { } try await handleRequest(request) - log.debug("Keys successfully uploaded") } @@ -468,7 +469,7 @@ extension MXCryptoMachine: MXCryptoRoomEventDecrypting { log.failure("Invalid event") throw Error.invalidEvent } - return try machine.decryptRoomEvent(event: eventString, roomId: roomId) + return try machine.decryptRoomEvent(event: eventString, roomId: roomId, handleVerificatonEvents: true) } func requestRoomKey(event: MXEvent) async throws { diff --git a/MatrixSDK/Crypto/MXCrypto.m b/MatrixSDK/Crypto/MXCrypto.m index d014cc9039..2eff514c60 100644 --- a/MatrixSDK/Crypto/MXCrypto.m +++ b/MatrixSDK/Crypto/MXCrypto.m @@ -158,7 +158,7 @@ @implementation MXLegacyCrypto #ifdef MX_CRYPTO #if DEBUG - if (MXSDKOptions.sharedInstance.enableCryptoV2) + if (MXSDKOptions.sharedInstance.isCryptoSDKAvailable && MXSDKOptions.sharedInstance.enableCryptoSDK) { return [self createCryptoV2WithSession:mxSession error:error]; } @@ -182,7 +182,7 @@ + (void)checkCryptoWithMatrixSession:(MXSession *)mxSession { #ifdef MX_CRYPTO #if DEBUG - if (MXSDKOptions.sharedInstance.enableCryptoV2) + if (MXSDKOptions.sharedInstance.isCryptoSDKAvailable && MXSDKOptions.sharedInstance.enableCryptoSDK) { NSError *error; id crypto = [self createCryptoV2WithSession:mxSession error:&error]; diff --git a/MatrixSDK/Crypto/MXCryptoV2.swift b/MatrixSDK/Crypto/MXCryptoV2.swift index 68d6fb225f..be7adaec41 100644 --- a/MatrixSDK/Crypto/MXCryptoV2.swift +++ b/MatrixSDK/Crypto/MXCryptoV2.swift @@ -203,7 +203,9 @@ private class MXCryptoV2: NSObject, MXCrypto { log.debug("->") startTask = Task { do { - try await machine.start() + try migrateIfNecessary() + + try await machine.uploadKeysIfNecessary() crossSigning.refreshState(success: nil) backup?.checkAndStart() @@ -247,6 +249,20 @@ private class MXCryptoV2: NSObject, MXCrypto { } } + private func migrateIfNecessary() throws { + guard legacyStore.cryptoVersion.rawValue < MXCryptoVersion.versionLegacyDeprecated.rawValue else { + log.debug("Legacy crypto has already been deprecated, no need to migrate") + return + } + + log.debug("Requires migration from legacy crypto") + let migration = MXCryptoMigrationV2(legacyStore: legacyStore) + try migration.migrateCrypto() + + log.debug("Marking legacy crypto as deprecated") + legacyStore.cryptoVersion = MXCryptoVersion.versionLegacyDeprecated + } + // MARK: - Event Encryption public func isRoomEncrypted(_ roomId: String) -> Bool { diff --git a/MatrixSDK/Crypto/Migration/MXCryptoVersion.h b/MatrixSDK/Crypto/Migration/MXCryptoVersion.h index 332a58873d..6fd9a648a8 100644 --- a/MatrixSDK/Crypto/Migration/MXCryptoVersion.h +++ b/MatrixSDK/Crypto/Migration/MXCryptoVersion.h @@ -32,8 +32,13 @@ typedef NS_ENUM(NSInteger, MXCryptoVersion) // https://github.com/vector-im/element-ios/issues/3818 MXCryptoVersion2, - // Keep it at the last position. It is used to compute MXCryptoVersionLast. + // Keep it at the last position of valid versions, except for the deprecated variant. + // It is used to compute MXCryptoVersionLast. MXCryptoVersionCount, + + // The internal crypto module has been deprecated in favour of `MatrixCryptoSDK` + // The value is set manually to leave room for intermediate version 3, 4 ... + MXCryptoVersionLegacyDeprecated = 1000, }; // The current version of MXCrypto diff --git a/MatrixSDK/MXSDKOptions.h b/MatrixSDK/MXSDKOptions.h index d6d8a9dba3..7e01d0775b 100644 --- a/MatrixSDK/MXSDKOptions.h +++ b/MatrixSDK/MXSDKOptions.h @@ -34,7 +34,6 @@ typedef NS_ENUM(NSUInteger, MXCallTransferType) MXCallTransferTypeLocal }; - #pragma mark - Build time options /** @@ -207,12 +206,23 @@ NS_ASSUME_NONNULL_BEGIN #if DEBUG /** - Enable Crypto module V2, a work-in-progress and NOT production-ready implementation - of [matrix-rust-sdk](https://github.com/matrix-org/matrix-rust-sdk/tree/main/crates/matrix-sdk-crypto). + The state of the rust-based `MatrixCryptoSDK` which replaces `MatrixSDK`'s internal crypto module, + and whether it is available to a user as an option. + + To control which crypto module is actually used, set `enableCryptoSDK`. + + @remark NO by default. + */ +@property (nonatomic) BOOL isCryptoSDKAvailable; + +/** + Use the rust-based `MatrixCryptoSDK` instead of `MatrixSDK`'s internal crypto module. + + This option should only be enabled if `isCryptoSDKAvailable` is set to YES. @remark NO by default. */ -@property (nonatomic) BOOL enableCryptoV2; +@property (nonatomic) BOOL enableCryptoSDK; #endif @@ -231,12 +241,12 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic) BOOL enableNewClientInformationFeature; /** - Enable the calculating of progress during sync, incl counting the number + Enable the calculating of progress during session startup, incl counting the number of attempts to sync with the server and percentage of response data processed. @remark NO by default */ -@property (nonatomic) BOOL enableSyncProgress; +@property (nonatomic) BOOL enableStartupProgress; @end diff --git a/MatrixSDK/MXSDKOptions.m b/MatrixSDK/MXSDKOptions.m index e0b80e81ce..bbcb538c73 100644 --- a/MatrixSDK/MXSDKOptions.m +++ b/MatrixSDK/MXSDKOptions.m @@ -56,12 +56,13 @@ - (instancetype)init _enableRoomSharedHistoryOnInvite = NO; #if DEBUG - _enableCryptoV2 = NO; + _isCryptoSDKAvailable = NO; + _enableCryptoSDK = NO; #endif _enableSymmetricBackup = NO; _enableNewClientInformationFeature = NO; - _enableSyncProgress = NO; + _enableStartupProgress = NO; } return self; diff --git a/MatrixSDK/MXSession.h b/MatrixSDK/MXSession.h index df449e087f..f20031909a 100644 --- a/MatrixSDK/MXSession.h +++ b/MatrixSDK/MXSession.h @@ -351,7 +351,7 @@ FOUNDATION_EXPORT NSString *const kMXSessionNoRoomTag; @class MXCapabilities; @class MXEventStreamService; @class MXLocationService; -@class MXSessionSyncProgress; +@class MXSessionStartupProgress; #pragma mark - MXSession /** @@ -434,9 +434,9 @@ FOUNDATION_EXPORT NSString *const kMXSessionNoRoomTag; @property (nonatomic, readonly) BOOL syncWithLazyLoadOfRoomMembers; /** - Handler that can compute the overal progress of sync and report it to a delegate + Handler that can compute the overal progress of session startup and report it to a delegate */ -@property (nonatomic, readonly) MXSessionSyncProgress *syncProgress; +@property (nonatomic, readonly) MXSessionStartupProgress *startupProgress; /** The profile of the current user. diff --git a/MatrixSDK/MXSession.m b/MatrixSDK/MXSession.m index 222ce9ef84..82b60b8eff 100644 --- a/MatrixSDK/MXSession.m +++ b/MatrixSDK/MXSession.m @@ -217,7 +217,7 @@ Queue of requested direct room change operations ([MXSession setRoom:directWithU @property (nonatomic, readwrite) MXClientInformationService *clientInformationService; -@property (nonatomic, strong) MXSessionSyncProgress *syncProgress; +@property (nonatomic, strong) MXSessionStartupProgress *startupProgress; @end @@ -312,9 +312,9 @@ - (id)initWithMatrixRestClient:(MXRestClient*)mxRestClient _homeserverCapabilitiesService = [[MXHomeserverCapabilitiesService alloc] initWithSession: self]; [_homeserverCapabilitiesService updateWithCompletion:nil]; - if (MXSDKOptions.sharedInstance.enableSyncProgress) + if (MXSDKOptions.sharedInstance.enableStartupProgress) { - _syncProgress = [[MXSessionSyncProgress alloc] init]; + _startupProgress = [[MXSessionStartupProgress alloc] init]; } [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onDidDecryptEvent:) name:kMXEventDidDecryptNotification object:nil]; @@ -585,10 +585,10 @@ - (void)handleSyncResponse:(MXSyncResponse *)syncResponse void(^dispatch_group_leave_with_progress)(dispatch_group_t) = ^(dispatch_group_t dispatchGroup) { dispatch_group_leave(dispatchGroup); - if (MXSDKOptions.sharedInstance.enableSyncProgress && progress) + if (MXSDKOptions.sharedInstance.enableStartupProgress && progress) { completedRooms += 1; - progress([self syncProgressForCompleted:completedRooms total:totalRooms]); + progress([self startupProgressForCompleted:completedRooms total:totalRooms]); } }; @@ -1277,7 +1277,7 @@ - (void)close // Clean any cached initial sync response [self.initialSyncResponseCache deleteData]; - self.syncProgress = nil; + self.startupProgress = nil; // Flush the store [self.storeService closeStores]; @@ -1451,9 +1451,9 @@ - (void)serverSyncWithServerTimeout:(NSUInteger)serverTimeout clientTimeout:(NSUInteger)clientTimeout setPresence:(NSString*)setPresence { - if (MXSDKOptions.sharedInstance.enableSyncProgress) + if (MXSDKOptions.sharedInstance.enableStartupProgress) { - [self.syncProgress incrementSyncAttempt]; + [self.startupProgress incrementSyncAttempt]; } dispatch_group_t initialSyncDispatchGroup = dispatch_group_create(); @@ -1556,9 +1556,9 @@ - (void)serverSyncWithServerTimeout:(NSUInteger)serverTimeout [self handleSyncResponse:syncResponse progress:^(CGFloat progress) { - if (MXSDKOptions.sharedInstance.enableSyncProgress) + if (MXSDKOptions.sharedInstance.enableStartupProgress) { - [self.syncProgress updateProcessingProgress:progress forPhase:MXSessionSyncProcessingPhaseSyncResponse]; + [self.startupProgress updateProcessingProgress:progress forPhase:MXSessionProcessingResponsePhaseSyncResponse]; } } completion:^{ @@ -1571,9 +1571,9 @@ - (void)serverSyncWithServerTimeout:(NSUInteger)serverTimeout [self fixRoomsSummariesLastMessageWithMaxServerPaginationCount:MXRoomSummaryPaginationChunkSize force:YES progress:^(CGFloat progress) { - if (MXSDKOptions.sharedInstance.enableSyncProgress) + if (MXSDKOptions.sharedInstance.enableStartupProgress) { - [self.syncProgress updateProcessingProgress:progress forPhase:MXSessionSyncProcessingPhaseRoomSummaries]; + [self.startupProgress updateProcessingProgress:progress forPhase:MXSessionProcessingResponsePhaseRoomSummaries]; } } completion:^{ @@ -2266,7 +2266,7 @@ - (void)handleOutdatedSyncResponse:(MXSyncResponse *)syncResponse [self handleCryptoSyncResponse:syncResponse onComplete:completion]; } -- (CGFloat)syncProgressForCompleted:(NSInteger)completed total:(NSInteger)total +- (CGFloat)startupProgressForCompleted:(NSInteger)completed total:(NSInteger)total { return total > 0 ? (CGFloat)completed/(CGFloat)total : 0; } @@ -3368,10 +3368,10 @@ - (void)fixRoomsSummariesLastMessageWithMaxServerPaginationCount:(NSUInteger)max __block NSInteger completedRooms = 0; void(^dispatch_group_leave_with_progress)(dispatch_group_t) = ^(dispatch_group_t dispatchGroup) { dispatch_group_leave(dispatchGroup); - if (MXSDKOptions.sharedInstance.enableSyncProgress && progress) + if (MXSDKOptions.sharedInstance.enableStartupProgress && progress) { completedRooms += 1; - progress([self syncProgressForCompleted:completedRooms total:self.rooms.count]); + progress([self startupProgressForCompleted:completedRooms total:self.rooms.count]); } }; diff --git a/MatrixSDK/MXSessionStartupProgress.swift b/MatrixSDK/MXSessionStartupProgress.swift new file mode 100644 index 0000000000..9725888e5d --- /dev/null +++ b/MatrixSDK/MXSessionStartupProgress.swift @@ -0,0 +1,98 @@ +// +// Copyright 2022 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. +// + +import Foundation + +/// Different stages of starting up a session that may complete +/// in non-trivial amount of time. These stages can be observed +/// and used to update the user interface during session loading. +public enum MXSessionStartupStage { + + /// Migrating data to a new store version + case migratingData(progress: Double) + + /// Syncing with the server as Nth attempt + case serverSyncing(attempt: Int) + + /// Processing server response + case processingResponse(progress: Double) + + var isSyncing: Bool { + guard case .serverSyncing = self else { + return false + } + return true + } +} + +/// Delegate that recieves stage updates +public protocol MXSessionStartupProgressDelegate: AnyObject { + func sessionDidUpdateStartupStage(_ stage: MXSessionStartupStage) +} + +/// Distinct phases of the `processingResponse` stage that report +/// their own local progress separately and complete in a given order +@objc public enum MXSessionProcessingResponsePhase: Int, CaseIterable { + + /// Processing the response from the server + case syncResponse + + /// Updating room summaries + case roomSummaries +} + +/// `MXSessionStartupProgress` tracks individual stages and per-stage progress +/// during a session startup, where the application may be blocking user interactions. +@objc public class MXSessionStartupProgress: NSObject { + private var syncAttempts = 0 + private var stage: MXSessionStartupStage? { + didSet { + if let state = stage { + delegate?.sessionDidUpdateStartupStage(state) + } + } + } + + public weak var delegate: MXSessionStartupProgressDelegate? { + didSet { + if let state = stage { + delegate?.sessionDidUpdateStartupStage(state) + } + } + } + + /// Increment the total number of sync attempts during the `serverSyncing` stage + @objc public func incrementSyncAttempt() { + guard stage == nil || stage?.isSyncing == true else { + return + } + + syncAttempts += 1 + stage = .serverSyncing(attempt: syncAttempts) + } + + /// Update the local progress of a specific phase within `processingResponse` + /// + /// The overal progress will be computed and reported automatically + @objc public func updateProcessingProgress(_ progress: Double, forPhase phase: MXSessionProcessingResponsePhase) { + let totalPhases = Double(MXSessionProcessingResponsePhase.allCases.count) + let currentPhaseProgress = progress / totalPhases + let previousPhasesProgress = Double(phase.rawValue) / totalPhases + let totalProgress = previousPhasesProgress + currentPhaseProgress + + stage = .processingResponse(progress: totalProgress) + } +} diff --git a/MatrixSDK/MXSessionSyncProgress.swift b/MatrixSDK/MXSessionSyncProgress.swift deleted file mode 100644 index 4dd18b60fe..0000000000 --- a/MatrixSDK/MXSessionSyncProgress.swift +++ /dev/null @@ -1,93 +0,0 @@ -// -// Copyright 2022 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. -// - -import Foundation - -/// Represents all possible states that a sync can be in -public enum MXSessionSyncState { - - /// Syncing with the server as Nth attempt - case serverSyncing(attempt: Int) - - /// Processing server response with 0.0 - 1.0 completed - case processingResponse(progress: Double) - - var isSyncing: Bool { - guard case .serverSyncing = self else { - return false - } - return true - } -} - -/// Delegate that recieves sync state updates -public protocol MXSessionSyncProgressDelegate: AnyObject { - func sessionDidUpdateSyncState(_ state: MXSessionSyncState) -} - -/// Distinct phases of the `processingResponse` state that report -/// their own local progress separately and complete in a given order -@objc public enum MXSessionSyncProcessingPhase: Int, CaseIterable { - - /// Processing the response from the server - case syncResponse - - /// Updating room summaries - case roomSummaries -} - -/// `MXSessionSyncProgress` tracks the overal state of sync and reports -/// this state to its delegate -@objcMembers public class MXSessionSyncProgress: NSObject { - private var syncAttempts = 0 - private var state: MXSessionSyncState? { - didSet { - if let state = state { - delegate?.sessionDidUpdateSyncState(state) - } - } - } - - public weak var delegate: MXSessionSyncProgressDelegate? { - didSet { - if let state = state { - delegate?.sessionDidUpdateSyncState(state) - } - } - } - - /// Increment the total number of sync attempts - public func incrementSyncAttempt() { - guard state == nil || state?.isSyncing == true else { - return - } - - syncAttempts += 1 - state = .serverSyncing(attempt: syncAttempts) - } - - /// Update the local progress of a specific processing phase - /// - /// The overal progress will be computed and reported automatically - public func updateProcessingProgress(_ progress: Double, forPhase phase: MXSessionSyncProcessingPhase) { - let totalPhases = Double(MXSessionSyncProcessingPhase.allCases.count) - let currentPhaseProgress = progress / totalPhases - let previousPhasesProgress = Double(phase.rawValue) / totalPhases - let totalProgress = previousPhasesProgress + currentPhaseProgress - - state = .processingResponse(progress: totalProgress) - } -} diff --git a/MatrixSDKTests/Crypto/Migration/MXCryptoMigrationV2Tests.swift b/MatrixSDKTests/Crypto/Migration/MXCryptoMigrationV2Tests.swift index df449a6b35..e79c80d1f9 100644 --- a/MatrixSDKTests/Crypto/Migration/MXCryptoMigrationV2Tests.swift +++ b/MatrixSDKTests/Crypto/Migration/MXCryptoMigrationV2Tests.swift @@ -22,6 +22,10 @@ import MatrixSDKCrypto @testable import MatrixSDK class MXCryptoMigrationV2Tests: XCTestCase { + enum Error: Swift.Error { + case missingDependencies + } + class KeyProvider: NSObject, MXKeyProviderDelegate { func isEncryptionAvailableForData(ofType dataType: String) -> Bool { return true @@ -38,82 +42,177 @@ class MXCryptoMigrationV2Tests: XCTestCase { var data: MatrixSDKTestsData! var e2eData: MatrixSDKTestsE2EData! - var keyProvider: KeyProvider! override func setUp() { data = MatrixSDKTestsData() e2eData = MatrixSDKTestsE2EData(matrixSDKTestsData: data) - - keyProvider = KeyProvider() - MXKeyProvider.sharedInstance().delegate = keyProvider + setLogger(logger: self) } - override func tearDown() { + // MARK: - Helpers + + private func migratedOlmMachine(session: MXSession) throws -> MXCryptoMachine { + guard + let store = session.legacyCrypto?.store, + let restClient = session.matrixRestClient + else { + throw Error.missingDependencies + } + + MXKeyProvider.sharedInstance().delegate = KeyProvider() + let migration = MXCryptoMigrationV2(legacyStore: store) + try migration.migrateCrypto() MXKeyProvider.sharedInstance().delegate = nil + + return try MXCryptoMachine( + userId: store.userId(), + deviceId: store.deviceId(), + restClient: restClient, + getRoomAction: { _ in + return nil + }) } - func test_canDecryptMessageAfterMigratingLegacyCrypto() throws { - e2eData.doE2ETestWithAliceAndBob(inARoom: self, cryptedBob: true, warnOnUnknowDevices: false) { aliceSession, bobSession, roomId, exp in - guard - let session = aliceSession, - let userId = session.myUserId, - let deviceId = session.myDeviceId, - let store = session.legacyCrypto?.store, - let room = session.room(withRoomId: roomId) - else { - XCTFail("Missing dependencies") - return + // MARK: - Tests + + func test_migratesAccountDetails() async throws { + let env = try await e2eData.startE2ETest() + let legacySession = env.session + + let machine = try self.migratedOlmMachine(session: env.session) + + XCTAssertEqual(machine.userId, legacySession.myUserId) + XCTAssertEqual(machine.deviceId, legacySession.myDeviceId) + XCTAssertEqual(machine.deviceCurve25519Key, legacySession.crypto.deviceCurve25519Key) + XCTAssertEqual(machine.deviceEd25519Key, legacySession.crypto.deviceEd25519Key) + } + + func test_canDecryptMegolmMessageAfterMigration() async throws { + let env = try await e2eData.startE2ETest() + + guard let room = env.session.room(withRoomId: env.roomId) else { + throw Error.missingDependencies + } + + // Send a new message in encrypted room + let event = try await room.sendTextMessage("Hi bob") + + // Erase cleartext and make sure the event was indeed encrypted + event.setClearData(nil) + XCTAssertTrue(event.isEncrypted) + XCTAssertEqual(event.content["algorithm"] as? String, kMXCryptoMegolmAlgorithm) + XCTAssertNotNil(event.content["ciphertext"]) + + // Migrate the session to crypto v2 + let machine = try self.migratedOlmMachine(session: env.session) + + // Decrypt the event using crypto v2 + let decrypted = try machine.decryptRoomEvent(event) + let result = try MXEventDecryptionResult(event: decrypted) + let content = result.clearEvent["content"] as? [String: Any] + + // At this point we should be able to read back the original message after + // having decrypted the event with room keys migrated earlier + XCTAssertEqual(content?["body"] as? String, "Hi bob") + } + + func test_migratesCrossSigningStatus() async throws { + let env = try await e2eData.startE2ETest() + + // We start with user who cannot cross-sign (did not setup cross signing keys) + let legacyCrossSigning = env.session.crypto.crossSigning + XCTAssertFalse(legacyCrossSigning.canCrossSign) + XCTAssertFalse(legacyCrossSigning.hasAllPrivateKeys) + + // We then migrate the user into crypto v2 + var machine = try migratedOlmMachine(session: env.session) + var crossSigningV2 = MXCrossSigningV2(crossSigning: machine, restClient: env.session.matrixRestClient) + try await crossSigningV2.refreshState() + + // As expected we cannot cross sign in v2 either + XCTAssertFalse(crossSigningV2.canCrossSign) + XCTAssertFalse(crossSigningV2.hasAllPrivateKeys) + + // Now we setup cross-signing with password on the original / legacy session + try await legacyCrossSigning.setup(withPassword: MXTESTS_ALICE_PWD) + XCTAssertTrue(legacyCrossSigning.canCrossSign) + XCTAssertTrue(legacyCrossSigning.hasAllPrivateKeys) + + // We have to migrate the data once again into crypto v2 + machine = try migratedOlmMachine(session: env.session) + crossSigningV2 = MXCrossSigningV2(crossSigning: machine, restClient: env.session.matrixRestClient) + try await crossSigningV2.refreshState() + + // And confirm that cross signing is ready + XCTAssertTrue(crossSigningV2.canCrossSign) + XCTAssertTrue(crossSigningV2.hasAllPrivateKeys) + } +} + +private extension MXCrypto { + func downloadKeys(userIds: [String]) async throws { + return try await withCheckedThrowingContinuation { continuation in + downloadKeys(userIds, forceDownload: false) { _, _ in + continuation.resume() } - - var event: MXEvent! - let clearTextMessage = "Hi bob" - - // Send clear text message to an E2E room - room.sendTextMessage(clearTextMessage, localEcho: &event) { _ in - - // Erase cleartext and make sure the event was indeed encrypted - event.setClearData(nil) - XCTAssertTrue(event.isEncrypted) - XCTAssertEqual(event.content["algorithm"] as? String, kMXCryptoMegolmAlgorithm) - XCTAssertNotNil(event.content["ciphertext"]) - - // Migrate data using crypto v2 migration and legacy store - do { - let migration = MXCryptoMigrationV2(legacyStore: store) - try migration.migrateCrypto() - } catch { - XCTFail("Cannot migrate - \(error)") - } - - // Now instantiate crypto machine (crypto v2) that should be able to find - // the migrated data and use it to decrypt the event - do { - let url = try MXCryptoMachine.storeURL(for: userId) - let machine = try OlmMachine( - userId: userId, - deviceId: deviceId, - path: url.path, - passphrase: nil - ) - - let decrypted = try machine.decryptRoomEvent(event: event.jsonString() ?? "", roomId: roomId!) - let result = try MXEventDecryptionResult(event: decrypted) - let content = result.clearEvent["content"] as? [String: Any] - - // At this point we should be able to read back the original message after - // having decrypted the event with room keys migrated earlier - XCTAssertEqual(content?["body"] as? String, clearTextMessage) - - } catch { - XCTFail("Cannot decrypt - \(error)") - } - - session.close() - bobSession?.close() - exp?.fulfill() + } + } +} + +private extension MXCrossSigning { + func refreshState() async throws { + return try await withCheckedThrowingContinuation { continuation in + refreshState { _ in + continuation.resume() + } failure: { error in + continuation.resume(throwing: error) + } + } + } + + func signUser(userId: String) async throws { + return try await withCheckedThrowingContinuation { continuation in + signUser(withUserId: userId) { + continuation.resume() + } failure: { error in + continuation.resume(throwing: error) + } + } + } + + func setup(withPassword password: String) async throws { + return try await withCheckedThrowingContinuation { continuation in + setup(withPassword: password) { + continuation.resume() + } failure: { error in + continuation.resume(throwing: error) } } } } +private extension MXRoom { + enum Error: Swift.Error { + case cannotSendMessage + } + + func sendTextMessage(_ text: String) async throws -> MXEvent { + var event: MXEvent? + _ = try await performCallbackRequest { + sendTextMessage(text, localEcho: &event, completion: $0) + } + + guard let event = event else { + throw Error.cannotSendMessage + } + return event + } +} + +extension MXCryptoMigrationV2Tests: Logger { + func log(logLine: String) { + MXLog.debug("[MXCryptoMigrationV2Tests]: \(logLine)") + } +} + #endif diff --git a/MatrixSDKTests/MXCryptoKeyVerificationTests.m b/MatrixSDKTests/MXCryptoKeyVerificationTests.m index d4e8f381f0..08b3a7c81e 100644 --- a/MatrixSDKTests/MXCryptoKeyVerificationTests.m +++ b/MatrixSDKTests/MXCryptoKeyVerificationTests.m @@ -457,7 +457,7 @@ - (void)testVerificationByToDeviceRequestCancellation success:^(id requestFromAliceDevice1POV) { // -> The other device list should have been computed well - if (MXSDKOptions.sharedInstance.enableCryptoV2) + if (MXSDKOptions.sharedInstance.enableCryptoSDK) { XCTFail(@"This test uses `MXKeyVerificationByToDeviceRequest` which is only compatible with Crypto V1. Replace assertions to make it compatible with V2 as well"); [expectation fulfill]; diff --git a/MatrixSDKTests/MXSessionSyncProgressUnitTests.swift b/MatrixSDKTests/MXSessionStartupProgressUnitTests.swift similarity index 60% rename from MatrixSDKTests/MXSessionSyncProgressUnitTests.swift rename to MatrixSDKTests/MXSessionStartupProgressUnitTests.swift index f42c083bd1..c115ee3431 100644 --- a/MatrixSDKTests/MXSessionSyncProgressUnitTests.swift +++ b/MatrixSDKTests/MXSessionStartupProgressUnitTests.swift @@ -17,84 +17,84 @@ import Foundation import MatrixSDK -class MXSessionSyncProgressUnitTests: XCTestCase { - class SpyDelegate: MXSessionSyncProgressDelegate { - var state: MXSessionSyncState? - func sessionDidUpdateSyncState(_ state: MXSessionSyncState) { - self.state = state +class MXSessionStartupProgressUnitTests: XCTestCase { + class SpyDelegate: MXSessionStartupProgressDelegate { + var stage: MXSessionStartupStage? + func sessionDidUpdateStartupStage(_ stage: MXSessionStartupStage) { + self.stage = stage } } var delegate: SpyDelegate! - var progress: MXSessionSyncProgress! + var progress: MXSessionStartupProgress! override func setUp() { delegate = SpyDelegate() - progress = MXSessionSyncProgress() + progress = MXSessionStartupProgress() progress.delegate = delegate } func testIncrementsSyncAttempt() { - XCTAssertNil(delegate.state) + XCTAssertNil(delegate.stage) progress.incrementSyncAttempt() - XCTAssertIsNthSyncingAttempt(1, state: delegate.state) + XCTAssertIsNthSyncingAttempt(1, stage: delegate.stage) progress.incrementSyncAttempt() - XCTAssertIsNthSyncingAttempt(2, state: delegate.state) + XCTAssertIsNthSyncingAttempt(2, stage: delegate.stage) progress.incrementSyncAttempt() - XCTAssertIsNthSyncingAttempt(3, state: delegate.state) + XCTAssertIsNthSyncingAttempt(3, stage: delegate.stage) } func testUpdatesProcessingProgressForMultiplePhases() { - XCTAssertNil(delegate.state) + XCTAssertNil(delegate.stage) progress.updateProcessingProgress(0, forPhase: .syncResponse) - XCTAssertProcessingProgress(0, state: delegate.state) + XCTAssertProcessingProgress(0, stage: delegate.stage) // Sync response is one of 2 possible phases, so its progress contributes 50% to the overal progress progress.updateProcessingProgress(0.5, forPhase: .syncResponse) - XCTAssertProcessingProgress(0.25, state: delegate.state) + XCTAssertProcessingProgress(0.25, stage: delegate.stage) // Reporting progress for next phase assumes the previous phase has completed, progress.updateProcessingProgress(0.5, forPhase: .roomSummaries) - XCTAssertProcessingProgress(0.75, state: delegate.state) + XCTAssertProcessingProgress(0.75, stage: delegate.stage) // Full progress for the last phase means the overal progres is complete as well progress.updateProcessingProgress(1, forPhase: .roomSummaries) - XCTAssertProcessingProgress(1, state: delegate.state) + XCTAssertProcessingProgress(1, stage: delegate.stage) } func testIgnoresSyncAttemptWhenProcessing() { progress.incrementSyncAttempt() - XCTAssertIsNthSyncingAttempt(1, state: delegate.state) + XCTAssertIsNthSyncingAttempt(1, stage: delegate.stage) progress.updateProcessingProgress(0, forPhase: .syncResponse) - XCTAssertProcessingProgress(0, state: delegate.state) + XCTAssertProcessingProgress(0, stage: delegate.stage) progress.incrementSyncAttempt() - XCTAssertProcessingProgress(0, state: delegate.state) + XCTAssertProcessingProgress(0, stage: delegate.stage) } // MARK: - Assertion helpers - private func XCTAssertIsNthSyncingAttempt(_ expectedAttempt: Int, state: MXSessionSyncState?, file: StaticString = #file, line: UInt = #line) { - if case .serverSyncing(attempt: let attempt) = state { + private func XCTAssertIsNthSyncingAttempt(_ expectedAttempt: Int, stage: MXSessionStartupStage?, file: StaticString = #file, line: UInt = #line) { + if case .serverSyncing(attempt: let attempt) = stage { XCTAssertEqual(attempt, expectedAttempt, file: file, line: line) - } else if let state = state { - XCTFail("Unexpected state \(state)", file: file, line: line) + } else if let stage = stage { + XCTFail("Unexpected stage \(stage)", file: file, line: line) } else { - XCTFail("State is nil", file: file, line: line) + XCTFail("stage is nil", file: file, line: line) } } - private func XCTAssertProcessingProgress(_ expectedProgress: Double, state: MXSessionSyncState?, file: StaticString = #file, line: UInt = #line) { - if case .processingResponse(progress: let progress) = state { + private func XCTAssertProcessingProgress(_ expectedProgress: Double, stage: MXSessionStartupStage?, file: StaticString = #file, line: UInt = #line) { + if case .processingResponse(progress: let progress) = stage { XCTAssertEqual(progress, expectedProgress, file: file, line: line) - } else if let state = state { - XCTFail("Unexpected state \(state)", file: file, line: line) + } else if let stage = stage { + XCTFail("Unexpected stage \(stage)", file: file, line: line) } else { - XCTFail("State is nil", file: file, line: line) + XCTFail("stage is nil", file: file, line: line) } } } diff --git a/MatrixSDKTests/MatrixSDKTestsData.swift b/MatrixSDKTests/MatrixSDKTestsData.swift new file mode 100644 index 0000000000..c7265a2fa2 --- /dev/null +++ b/MatrixSDKTests/MatrixSDKTestsData.swift @@ -0,0 +1,35 @@ +// +// Copyright 2023 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. +// + +import Foundation + +extension MatrixSDKTestsData { + enum Error: Swift.Error { + case missingDependencies + } + + func startMXSession() async throws -> MXSession { + return try await withCheckedThrowingContinuation { continuation in + doMXSessionTest(withAUser: nil) { session, _ in + guard let session = session else { + continuation.resume(throwing: Error.missingDependencies) + return + } + continuation.resume(returning: session) + } + } + } +} diff --git a/MatrixSDKTests/MatrixSDKTestsE2EData.swift b/MatrixSDKTests/MatrixSDKTestsE2EData.swift new file mode 100644 index 0000000000..63b414eef0 --- /dev/null +++ b/MatrixSDKTests/MatrixSDKTestsE2EData.swift @@ -0,0 +1,52 @@ +// +// Copyright 2023 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. +// + +import Foundation + +extension MatrixSDKTestsE2EData { + enum Error: Swift.Error { + case missingDependencies + } + + class Environment { + let session: MXSession + let roomId: String + + init(session: MXSession, roomId: String) { + self.session = session + self.roomId = roomId + } + + deinit { + let session = session + DispatchQueue.main.async { + session.close() + } + } + } + + func startE2ETest() async throws -> Environment { + return try await withCheckedThrowingContinuation { continuation in + doE2ETestWithAlice(inARoom: nil) { session, roomId, _ in + guard let session = session, let roomId = roomId else { + continuation.resume(throwing: Error.missingDependencies) + return + } + continuation.resume(returning: .init(session: session, roomId: roomId)) + } + } + } +} diff --git a/MatrixSDKTests/TestPlans/UnitTests.xctestplan b/MatrixSDKTests/TestPlans/UnitTests.xctestplan index 97d3e21d66..e41e043294 100644 --- a/MatrixSDKTests/TestPlans/UnitTests.xctestplan +++ b/MatrixSDKTests/TestPlans/UnitTests.xctestplan @@ -85,7 +85,7 @@ "MXRoomKeyInfoFactoryUnitTests", "MXRoomStateUnitTests", "MXSASTransactionV2UnitTests", - "MXSessionSyncProgressUnitTests", + "MXSessionStartupProgressUnitTests", "MXSharedHistoryKeyManagerUnitTests", "MXStoreRoomListDataManagerUnitTests", "MXSyncResponseUnitTests", diff --git a/MatrixSDKTests/TestPlans/UnitTestsWithSanitizers.xctestplan b/MatrixSDKTests/TestPlans/UnitTestsWithSanitizers.xctestplan index 091a1f90c8..913c8a271f 100644 --- a/MatrixSDKTests/TestPlans/UnitTestsWithSanitizers.xctestplan +++ b/MatrixSDKTests/TestPlans/UnitTestsWithSanitizers.xctestplan @@ -93,7 +93,7 @@ "MXRoomKeyInfoFactoryUnitTests", "MXRoomStateUnitTests", "MXSASTransactionV2UnitTests", - "MXSessionSyncProgressUnitTests", + "MXSessionStartupProgressUnitTests", "MXSharedHistoryKeyManagerUnitTests", "MXStoreRoomListDataManagerUnitTests", "MXSyncResponseUnitTests", diff --git a/Podfile b/Podfile index c6254e4717..03e0ae9391 100644 --- a/Podfile +++ b/Podfile @@ -16,7 +16,7 @@ abstract_target 'MatrixSDK' do pod 'Realm', '10.27.0' pod 'libbase58', '~> 0.1.4' - pod 'MatrixSDKCrypto', "0.1.7", :configurations => ['DEBUG'], :inhibit_warnings => true + pod 'MatrixSDKCrypto', "0.1.8", :configurations => ['DEBUG'], :inhibit_warnings => true target 'MatrixSDK-iOS' do platform :ios, '11.0' diff --git a/Podfile.lock b/Podfile.lock index 1f9eb0d3cc..1dd208427d 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -16,7 +16,7 @@ PODS: - AFNetworking/NSURLSession - GZIP (1.3.0) - libbase58 (0.1.4) - - MatrixSDKCrypto (0.1.7) + - MatrixSDKCrypto (0.1.8) - OHHTTPStubs (9.1.0): - OHHTTPStubs/Default (= 9.1.0) - OHHTTPStubs/Core (9.1.0) @@ -44,7 +44,7 @@ DEPENDENCIES: - AFNetworking (~> 4.0.0) - GZIP (~> 1.3.0) - libbase58 (~> 0.1.4) - - MatrixSDKCrypto (= 0.1.7) + - MatrixSDKCrypto (= 0.1.8) - OHHTTPStubs (~> 9.1.0) - OLMKit (~> 3.2.5) - Realm (= 10.27.0) @@ -65,12 +65,12 @@ SPEC CHECKSUMS: AFNetworking: 7864c38297c79aaca1500c33288e429c3451fdce GZIP: 416858efbe66b41b206895ac6dfd5493200d95b3 libbase58: 7c040313537b8c44b6e2d15586af8e21f7354efd - MatrixSDKCrypto: 2bd9ca41b2c644839f4e680a64897d56b3f95392 + MatrixSDKCrypto: 862d9b4dbb6861da030943f5a18c39258ed7345b OHHTTPStubs: 90eac6d8f2c18317baeca36698523dc67c513831 OLMKit: da115f16582e47626616874e20f7bb92222c7a51 Realm: 9ca328bd7e700cc19703799785e37f77d1a130f2 SwiftyBeaver: 84069991dd5dca07d7069100985badaca7f0ce82 -PODFILE CHECKSUM: 93a0998328575ae2705bf230f5bb9d4939048618 +PODFILE CHECKSUM: 21de6a6ceff05a5422b7901025346fe4ff6bae99 COCOAPODS: 1.11.3 diff --git a/changelog.d/pr-1684.change b/changelog.d/pr-1684.change new file mode 100644 index 0000000000..0edafe0aae --- /dev/null +++ b/changelog.d/pr-1684.change @@ -0,0 +1 @@ +CryptoSDK: Perform crypto migration if necessary diff --git a/changelog.d/pr-1686.change b/changelog.d/pr-1686.change new file mode 100644 index 0000000000..17ec70706c --- /dev/null +++ b/changelog.d/pr-1686.change @@ -0,0 +1 @@ +Rename MXSessionSyncProgress