From 3c614a8d7d92f846d191cc98ae1824113574ef83 Mon Sep 17 00:00:00 2001 From: Andy Uhnak Date: Mon, 17 Apr 2023 16:43:12 +0100 Subject: [PATCH 1/3] Deprecate MXLegacyCrypto --- .../Background/MXBackgroundSyncService.swift | 12 +- MatrixSDK/Contrib/Swift/MXSession.swift | 18 -- MatrixSDK/Crypto/MXCrypto.m | 29 -- .../EventTimeline/Room/MXRoomEventTimeline.m | 6 - .../Thread/MXThreadEventTimeline.swift | 6 - MatrixSDK/MXSDKOptions.h | 20 -- MatrixSDK/MXSDKOptions.m | 7 - MatrixSDK/MXSession.h | 20 +- MatrixSDK/MXSession.m | 303 +++--------------- MatrixSDKTests/MXCryptoKeyVerificationTests.m | 6 - MatrixSDKTests/MXCryptoTests.m | 291 +++-------------- MatrixSDKTests/MatrixSDKTestsData.m | 33 +- changelog.d/pr-1772.change | 1 + 13 files changed, 118 insertions(+), 634 deletions(-) create mode 100644 changelog.d/pr-1772.change diff --git a/MatrixSDK/Background/MXBackgroundSyncService.swift b/MatrixSDK/Background/MXBackgroundSyncService.swift index 5fe4e5abfb..efb2ad4d1f 100644 --- a/MatrixSDK/Background/MXBackgroundSyncService.swift +++ b/MatrixSDK/Background/MXBackgroundSyncService.swift @@ -67,7 +67,6 @@ public enum MXBackgroundSyncServiceError: Error { /// - Parameter credentials: account credentials public init( withCredentials credentials: MXCredentials, - isCryptoSDKEnabled: Bool = false, persistTokenDataHandler: MXRestClientPersistTokenDataHandler? = nil, unauthenticatedHandler: MXRestClientUnauthenticatedHandler? = nil ) { @@ -90,16 +89,9 @@ public enum MXBackgroundSyncServiceError: Error { self.restClient = restClient store = MXBackgroundStore(withCredentials: credentials) - // We can flush any crypto data if our sync response store is empty - let resetBackgroundCryptoStore = syncResponseStoreManager.syncToken() == nil - if isCryptoSDKEnabled { - MXLog.debug("[MXBackgroundSyncService] init: constructing crypto v2") - crypto = MXBackgroundCryptoV2(credentials: credentials, restClient: restClient) - } else { - MXLog.debug("[MXBackgroundSyncService] init: constructing legacy crypto") - crypto = MXLegacyBackgroundCrypto(credentials: credentials, resetBackgroundCryptoStore: resetBackgroundCryptoStore) - } + MXLog.debug("[MXBackgroundSyncService] init: constructing crypto") + crypto = MXBackgroundCryptoV2(credentials: credentials, restClient: restClient) pushRulesManager = MXBackgroundPushRulesManager(withCredentials: credentials) MXLog.debug("[MXBackgroundSyncService] init complete") diff --git a/MatrixSDK/Contrib/Swift/MXSession.swift b/MatrixSDK/Contrib/Swift/MXSession.swift index e738b0e1e4..912332af48 100644 --- a/MatrixSDK/Contrib/Swift/MXSession.swift +++ b/MatrixSDK/Contrib/Swift/MXSession.swift @@ -127,24 +127,6 @@ public extension MXSession { __setStore(store, success: currySuccess(completion), failure: curryFailure(completion)) } - - /** - Enable End-to-End encryption. - - In case of enabling, the operation will complete when the session will be ready - to make encrytion with other users devices - - - parameters: - - isEnabled: `false` stops crypto and erases crypto data. - - completion: A block called when the SDK has completed a catchup, or times out. - - response: Indicates whether the sync was successful. - */ - @nonobjc func enableCrypto(_ isEnabled: Bool, completion: @escaping (_ response: MXResponse) -> Void) { - __enableCrypto(isEnabled, success: currySuccess(completion), failure: curryFailure(completion)) - } - - - /// Create a new room with the given parameters. /// - Parameters: /// - name: Name of the room diff --git a/MatrixSDK/Crypto/MXCrypto.m b/MatrixSDK/Crypto/MXCrypto.m index 9cf0f2511a..fc599496f7 100644 --- a/MatrixSDK/Crypto/MXCrypto.m +++ b/MatrixSDK/Crypto/MXCrypto.m @@ -156,12 +156,6 @@ @implementation MXLegacyCrypto __block id crypto; #ifdef MX_CRYPTO - if (MXSDKOptions.sharedInstance.enableCryptoSDK) - { - MXLogFailure(@"[MXCrypto] createCryptoWithMatrixSession: Crypto V2 should not be created directly, use initializeCryptoWithMatrixSession instead"); - return nil; - } - dispatch_queue_t cryptoQueue = [MXLegacyCrypto dispatchQueueForUser:mxSession.matrixRestClient.credentials.userId]; dispatch_sync(cryptoQueue, ^{ @@ -180,29 +174,6 @@ + (void)initializeCryptoWithMatrixSession:(MXSession *)mxSession complete:(void (^)(id crypto, NSError *error))complete { #ifdef MX_CRYPTO - - if (MXSDKOptions.sharedInstance.enableCryptoSDK) - { - BOOL enableCrypto = [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession || [MXCryptoV2Factory.shared hasCryptoDataFor:mxSession]; - if (enableCrypto) - { - [MXCryptoV2Factory.shared buildCryptoWithSession:mxSession - migrationProgress:migrationProgress - success:^(id crypto) { - complete(crypto, nil); } - failure:^(NSError *error) { - complete(nil, error); - }]; - } - else - { - dispatch_async(dispatch_get_main_queue(), ^{ - complete(nil, nil); - }); - } - return; - } - [self initalizeLegacyCryptoWithMatrixSession:mxSession complete:complete]; #else complete(nil); diff --git a/MatrixSDK/Data/EventTimeline/Room/MXRoomEventTimeline.m b/MatrixSDK/Data/EventTimeline/Room/MXRoomEventTimeline.m index cf9dabcaad..300ab9934a 100644 --- a/MatrixSDK/Data/EventTimeline/Room/MXRoomEventTimeline.m +++ b/MatrixSDK/Data/EventTimeline/Room/MXRoomEventTimeline.m @@ -142,8 +142,6 @@ - (void)initialiseState:(NSArray *)stateEvents - (void)destroy { - [room.mxSession resetReplayAttackCheckInTimeline:_timelineId]; - if (httpOperation) { // Cancel the current server request @@ -190,8 +188,6 @@ - (BOOL)canPaginate:(MXTimelineDirection)direction - (void)resetPagination { - [room.mxSession resetReplayAttackCheckInTimeline:_timelineId]; - // Reset the back state to the current room state backState = [[MXRoomState alloc] initBackStateWith:_state]; @@ -203,8 +199,6 @@ - (MXHTTPOperation *)resetPaginationAroundInitialEventWithLimit:(NSUInteger)limi { NSParameterAssert(success); NSAssert(_initialEventId, @"[MXRoomEventTimeline] resetPaginationAroundInitialEventWithLimit cannot be called on live timeline"); - - [room.mxSession resetReplayAttackCheckInTimeline:_timelineId]; // Reset the store if (!store.isPermanent) diff --git a/MatrixSDK/Data/EventTimeline/Thread/MXThreadEventTimeline.swift b/MatrixSDK/Data/EventTimeline/Thread/MXThreadEventTimeline.swift index b5fada9a90..f3b0c1e380 100644 --- a/MatrixSDK/Data/EventTimeline/Thread/MXThreadEventTimeline.swift +++ b/MatrixSDK/Data/EventTimeline/Thread/MXThreadEventTimeline.swift @@ -99,8 +99,6 @@ public class MXThreadEventTimeline: NSObject, MXEventTimeline { } public func destroy() { - thread.session?.resetReplayAttackCheck(inTimeline: timelineId) - removeAllListeners() currentHttpOperation?.cancel() @@ -132,8 +130,6 @@ public class MXThreadEventTimeline: NSObject, MXEventTimeline { } public func resetPagination() { - thread.session?.resetReplayAttackCheck(inTimeline: timelineId) - // Reset store pagination storeMessagesEnumerator = store.messagesEnumerator(forRoom: thread.roomId) @@ -150,8 +146,6 @@ public class MXThreadEventTimeline: NSObject, MXEventTimeline { fatalError("[MXThreadEventTimeline][\(timelineId)] resetPaginationAroundInitialEventWithLimit cannot be called on live timeline") } - thread.session?.resetReplayAttackCheck(inTimeline: timelineId) - // Reset the store if !store.isPermanent { store.deleteAllData() diff --git a/MatrixSDK/MXSDKOptions.h b/MatrixSDK/MXSDKOptions.h index 422a8c6617..778ab3d6d5 100644 --- a/MatrixSDK/MXSDKOptions.h +++ b/MatrixSDK/MXSDKOptions.h @@ -203,13 +203,6 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic) BOOL enableRoomSharedHistoryOnInvite; -/** - Use the newer rust-based `MatrixCryptoSDK` instead of the legacy `MatrixSDK`'s internal crypto module. - - @remark YES by default - */ -@property (nonatomic) BOOL enableCryptoSDK; - /** Flag indicating whether this account requires a re-verification after migrating to Crypto SDK @@ -220,11 +213,6 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic) BOOL needsVerificationUpgrade; -/** - The text-based identifier for the crypto module being used (e.g. native vs rust) - */ -@property (nonatomic, readonly) NSString *cryptoModuleId; - /** Enable symmetric room key backups @@ -239,14 +227,6 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic) BOOL enableNewClientInformationFeature; -/** - Enable the calculating and display of progress during session startup, incl store migration, - syncing and response processing. - - @remark YES by default - */ -@property (nonatomic) BOOL enableStartupProgress; - @end NS_ASSUME_NONNULL_END diff --git a/MatrixSDK/MXSDKOptions.m b/MatrixSDK/MXSDKOptions.m index e1cc0fa19f..0652f18fdc 100644 --- a/MatrixSDK/MXSDKOptions.m +++ b/MatrixSDK/MXSDKOptions.m @@ -54,21 +54,14 @@ - (instancetype)init _authEnableRefreshTokens = NO; _enableThreads = NO; _enableRoomSharedHistoryOnInvite = NO; - _enableCryptoSDK = YES; _needsVerificationUpgrade = NO; _enableSymmetricBackup = NO; _enableNewClientInformationFeature = NO; - _enableStartupProgress = YES; } return self; } -- (NSString *)cryptoModuleId -{ - return self.enableCryptoSDK ? @"rust" : @"native"; -} - - (void)setRoomListDataManagerClass:(Class)roomListDataManagerClass { // Sanity check diff --git a/MatrixSDK/MXSession.h b/MatrixSDK/MXSession.h index a9ce329a02..31e274dc32 100644 --- a/MatrixSDK/MXSession.h +++ b/MatrixSDK/MXSession.h @@ -776,17 +776,9 @@ typedef void (^MXOnBackgroundSyncFail)(NSError *error); - (void)enableVoIPWithCallStack:(id)callStack; /** - Enable End-to-End encryption. - - In case of enabling, the operation will complete when the session will be ready - to make encrytion with other users devices - - @param enableCrypto NO stops crypto and erases crypto data. - - @param success A block object called when the operation succeeds. - @param failure A block object called when the operation fails. + Disable End-to-End encryption. */ -- (void)enableCrypto:(BOOL)enableCrypto success:(void (^)(void))success failure:(void (^)(NSError *error))failure NS_REFINED_FOR_SWIFT; +- (void)disableCrypto; /** Get the versions of the specification supported by the server. @@ -1596,14 +1588,6 @@ typedef void (^MXOnBackgroundSyncFail)(NSError *error); inTimeline:(NSString*)timeline onComplete:(void (^)(NSArray *failedEvents))onComplete; -/** - Reset replay attack data for the given timeline. - - @param timeline the id of the timeline. - */ -- (void)resetReplayAttackCheckInTimeline:(NSString*)timeline; - - #pragma mark - Global events listeners /** Register a global listener to events related to the current session. diff --git a/MatrixSDK/MXSession.m b/MatrixSDK/MXSession.m index 051b41d122..2b0b16e362 100644 --- a/MatrixSDK/MXSession.m +++ b/MatrixSDK/MXSession.m @@ -312,10 +312,7 @@ - (id)initWithMatrixRestClient:(MXRestClient*)mxRestClient _homeserverCapabilitiesService = [[MXHomeserverCapabilitiesService alloc] initWithSession: self]; [_homeserverCapabilitiesService updateWithCompletion:nil]; - if (MXSDKOptions.sharedInstance.enableStartupProgress) - { - _startupProgress = [[MXSessionStartupProgress alloc] init]; - } + _startupProgress = [[MXSessionStartupProgress alloc] init]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onDidDecryptEvent:) name:kMXEventDidDecryptNotification object:nil]; @@ -398,24 +395,12 @@ -(void)setStore:(id)store success:(void (^)(void))onStoreDataReady fail // Check if the user has enabled crypto MXWeakify(self); - [MXLegacyCrypto initializeCryptoWithMatrixSession:self migrationProgress:^(double progress) { - if (MXSDKOptions.sharedInstance.enableStartupProgress) - { - [self.startupProgress updateProgressForStage:MXSessionStartupStageStoreMigration progress:progress]; - } + [self initializeCryptoWithProgress:^(double progress) { + [self.startupProgress updateProgressForStage:MXSessionStartupStageStoreMigration progress:progress]; - } complete:^(id crypto, NSError *error) { + } success:^(id crypto) { MXStrongifyAndReturnIfNil(self); - if (!crypto && error) - { - if (failure) - { - failure(error); - } - return; - } - self->_crypto = crypto; // Sanity check: The session may be closed before the end of this operation. @@ -539,6 +524,11 @@ -(void)setStore:(id)store success:(void (^)(void))onStoreDataReady fail // The SDK client can use this data onStoreDataReady(); } + } failure:^(NSError *error) { + if (failure) + { + failure(error); + } }]; } failure:^(NSError *error) { @@ -551,6 +541,34 @@ -(void)setStore:(id)store success:(void (^)(void))onStoreDataReady fail }]; } +- (void)initializeCryptoWithProgress:(void (^)(double))progress + success:(void (^)(id crypto))success + failure:(void (^)(NSError *error))failure +{ + BOOL enableCrypto = [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession || [MXCryptoV2Factory.shared hasCryptoDataFor:self]; + if (!enableCrypto) + { + MXLogWarning(@"[MXSession] initializeCrypto: Not starting crypto automatically due to SDK settings"); + dispatch_async(dispatch_get_main_queue(), ^{ + success(nil); + }); + return; + } + + [MXCryptoV2Factory.shared buildCryptoWithSession:self + migrationProgress:progress + success:^(id crypto) { + + MXLogDebug(@"[MXSession] initializeCrypto: Successfully initialized crypto module"); + success(crypto); + + } failure:^(NSError *error) { + + MXLogErrorDetails(@"[MXSession] initializeCrypto: Error initialized crypto module", error); + failure(error); + }]; +} + - (void)setRoomListDataManager:(id)roomListDataManager { NSParameterAssert(_roomListDataManager == nil); @@ -574,7 +592,7 @@ - (void)handleSyncResponse:(MXSyncResponse *)syncResponse // Check whether this is the initial sync BOOL isInitialSync = !self.isEventStreamInitialised; - [self handleCryptoSyncResponse:syncResponse onComplete:^{ + [self handleCryptoEventsInSyncResponse:syncResponse onComplete:^{ dispatch_group_t dispatchGroup = dispatch_group_create(); @@ -591,7 +609,7 @@ - (void)handleSyncResponse:(MXSyncResponse *)syncResponse void(^dispatch_group_leave_with_progress)(dispatch_group_t) = ^(dispatch_group_t dispatchGroup) { dispatch_group_leave(dispatchGroup); - if (MXSDKOptions.sharedInstance.enableStartupProgress && progress) + if (progress) { progress([self.startupProgress overallProgressForStep:completedRooms totalCount:totalRooms progress:1]); completedRooms += 1; @@ -778,30 +796,6 @@ - (void)handleSyncResponse:(MXSyncResponse *)syncResponse // Sync point: wait that all rooms in the /sync response have been loaded // and their /sync response has been processed dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ - - // Legacy crypto requires that we deal with device list changes, OTKs etc at the end of the sync loop. - // This will be removed altogether with `MXLegacyCrypto` - if ([self.crypto isKindOfClass:[MXLegacyCrypto class]]) - { - // Handle device list updates - if (syncResponse.deviceLists) - { - [(MXLegacyCrypto *)self.crypto handleDeviceListsChanges:syncResponse.deviceLists]; - } - - // Handle one_time_keys_count - if (syncResponse.deviceOneTimeKeysCount) - { - [(MXLegacyCrypto *)self.crypto handleDeviceOneTimeKeysCount:syncResponse.deviceOneTimeKeysCount]; - } - - [(MXLegacyCrypto *)self.crypto handleDeviceUnusedFallbackKeys:syncResponse.unusedFallbackKeys]; - - // Tell the crypto module to do its processing - [(MXLegacyCrypto *)self.crypto onSyncCompleted:self.store.eventStreamToken - nextSyncToken:syncResponse.nextBatch - catchingUp:self.catchingUp]; - } // Update live event stream token MXLogDebug(@"[MXSession] Next sync token: %@", syncResponse.nextBatch); @@ -1357,25 +1351,12 @@ - (void)close - (MXHTTPOperation*)logout:(void (^)(void))success failure:(void (^)(NSError *error))failure { - // Create an empty operation that will be mutated later - MXHTTPOperation *operation = [[MXHTTPOperation alloc] init]; - // Clear crypto data // For security and because it will be no more useful as we will get a new device id // on the next log in - MXWeakify(self); - [self enableCrypto:NO success:^{ - MXStrongifyAndReturnIfNil(self); - - if (!operation.isCancelled) - { - MXHTTPOperation *operation2 = [self.matrixRestClient logout:success failure:failure]; - [operation mutateTo:operation2]; - } - - } failure:nil]; - - return operation; + [self disableCrypto]; + + return [self.matrixRestClient logout:success failure:failure]; } - (MXHTTPOperation*)deactivateAccountWithAuthParameters:(NSDictionary*)authParameters @@ -1458,7 +1439,7 @@ - (void)serverSyncWithServerTimeout:(NSUInteger)serverTimeout setPresence:(NSString*)setPresence { // We only want to report sync progress when doing initial sync - BOOL shoulReportStartupProgress = MXSDKOptions.sharedInstance.enableStartupProgress && !self.isEventStreamInitialised; + BOOL shoulReportStartupProgress = !self.isEventStreamInitialised; if (shoulReportStartupProgress) { // There is no way to track percentage progress when syncing with the server, so we always use 0% @@ -1994,7 +1975,6 @@ - (void)handleAccountData:(NSDictionary*)accountDataUpdate } } - [self validateAccountData]; self.store.userAccountData = _accountData.accountData; // Trigger a global notification for the account data update @@ -2007,27 +1987,6 @@ - (void)handleAccountData:(NSDictionary*)accountDataUpdate } } -/** - Private method to validate local account data and report any potential state corruption - */ -- (void)validateAccountData -{ - if (![self.crypto isKindOfClass:[MXLegacyCrypto class]]) - { - return; - } - - // Detecting an issue in legacy crypto where more than one valid SSSS key is present on the client - // https://github.com/vector-im/element-ios/issues/4569 - NSInteger keysCount = ((MXLegacyCrypto *)self.crypto).secretStorage.numberOfValidKeys; - if (keysCount > 1) - { - MXLogErrorDetails(@"[MXSession] validateAccountData: Detected multiple valid SSSS keys, should only have one at most", @{ - @"count": @(keysCount) - }); - } -} - - (void)updateSummaryDirectUserIdForRooms:(NSSet *)roomIds { // If the initial sync response is not processed enough, rooms is not yet mounted. @@ -2052,95 +2011,15 @@ - (void)updateSummaryDirectUserIdForRooms:(NSSet *)roomIds } } -// Temporary junction to deal with sync response depending on the variant of crypto -// that cannot be easily hidden behind a protocol. Legacy implementation will eventually -// be fully removed. -- (void)handleCryptoSyncResponse:(MXSyncResponse *)syncResponse - onComplete:(void (^)(void))onComplete +- (void)handleCryptoEventsInSyncResponse:(MXSyncResponse *)syncResponse onComplete:(void (^)(void))onComplete { - if (!self.crypto || [self.crypto isKindOfClass:[MXLegacyCrypto class]]) - { - // Legacy crypto requires pre-processed to-device events before everything else to make future decryptions work - [self handleToDeviceEvents:syncResponse.toDevice.events onComplete:onComplete]; - } - else - { - // New and all future crypto modules can handle the entire sync response in full - [self.crypto handleSyncResponse:syncResponse onComplete:onComplete]; - } -} - -- (void)handleToDeviceEvents:(NSArray *)events onComplete:(void (^)(void))onComplete -{ - NSMutableArray *supportedEvents = [NSMutableArray arrayWithCapacity:events.count]; - for (MXEvent *event in events) - { - if ([MXTools isSupportedToDeviceEvent:event]) - { - MXLogDebug(@"[MXSession] handleToDeviceEvents: Processing new to-device event msgid: %@", event.content[kMXToDeviceMessageId]) - [supportedEvents addObject:event]; - } - } - - if (supportedEvents.count == 0) + if (!self.crypto) { onComplete(); return; } - [self decryptEvents:supportedEvents inTimeline:nil onComplete:^(NSArray *failedEvents) { - dispatch_group_t dispatchGroup = dispatch_group_create(); - - for (MXEvent *event in supportedEvents) - { - if (!event.decryptionError) - { - MXLogDebug(@"[MXSession] handleToDeviceEvents: Received new to-device event `%@` from `%@` msgid: %@", event.type, event.sender, event.wireContent[kMXToDeviceMessageId]) - dispatch_group_enter(dispatchGroup); - [self handleToDeviceEvent:event onComplete:^{ - dispatch_group_leave(dispatchGroup); - }]; - } - else - { - MXLogDebug(@"[MXSession] handleToDeviceEvents: Warning: Unable to decrypt to-device event: %@\nError: %@", event.wireContent[kMXMessageBodyKey], event.decryptionError); - } - } - - dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ - onComplete(); - }); - }]; -} - -- (void)handleToDeviceEvent:(MXEvent *)event onComplete:(void (^)(void))onComplete -{ - void (^onHandleToDeviceEventDone)(void) = ^(void) { - [[NSNotificationCenter defaultCenter] postNotificationName:kMXSessionOnToDeviceEventNotification - object:self - userInfo:@{ - kMXSessionNotificationEventKey: event - }]; - - onComplete(); - }; - - switch (event.eventType) - { - case MXEventTypeRoomKey: - { - if ([_crypto isKindOfClass:[MXLegacyCrypto class]]) - { - [(MXLegacyCrypto *)_crypto handleRoomKeyEvent:event onComplete:onHandleToDeviceEventDone]; - } - break; - } - - default: - onHandleToDeviceEventDone(); - break; - } - [_eventStreamService dispatchOnLiveToDeviceWithEvent:event]; + [self.crypto handleSyncResponse:syncResponse onComplete:onComplete]; } /** @@ -2221,17 +2100,10 @@ - (void)handleBackgroundSyncCacheIfRequiredWithCompletion:(void (^)(void))comple [asyncTaskQueue asyncWithExecute:^(void (^ taskCompleted)(void)) { [syncResponseStoreManager mergedSyncResponseFromSyncResponseIds:outdatedSyncResponseIds completion:^(MXCachedSyncResponse * _Nullable outdatedCachedSyncResponse) { - if (outdatedCachedSyncResponse) - { - [self handleOutdatedSyncResponse:outdatedCachedSyncResponse.syncResponse - completion:^{ - taskCompleted(); - }]; - } - else - { + // There is no need to handle `outdatedCachedSyncResponse` manually anymore, ignoring the result + dispatch_async(dispatch_get_main_queue(), ^{ taskCompleted(); - } + }); }]; }]; @@ -2280,26 +2152,6 @@ - (void)handleBackgroundSyncCacheIfRequiredWithCompletion:(void (^)(void))comple }]; } -- (void)handleOutdatedSyncResponse:(MXSyncResponse *)syncResponse - completion:(void (^)(void))completion -{ - MXLogDebug(@"[MXSession] handleOutdatedSyncResponse: %tu joined rooms, %tu invited rooms, %tu left rooms, %tu toDevice events.", syncResponse.rooms.join.count, syncResponse.rooms.invite.count, syncResponse.rooms.leave.count, syncResponse.toDevice.events.count); - - if (!self.crypto || [self.crypto isKindOfClass:[MXLegacyCrypto class]]) - { - // Legacy crypto requires pre-processed to-device events before everything else to make future decryptions work - [self handleToDeviceEvents:syncResponse.toDevice.events onComplete:completion]; - } - else - { - // Only legacy crypto requires different DBs for foreground and background processes, other crypto modules - // write to a single DB in both processes, so there is no need to replay outdated sync response - dispatch_async(dispatch_get_main_queue(), ^{ - completion(); - }); - } -} - #pragma mark - Options - (void)enableVoIPWithCallStack:(id)callStack { @@ -2309,56 +2161,15 @@ - (void)enableVoIPWithCallStack:(id)callStack _callManager = [[MXCallManager alloc] initWithMatrixSession:self andCallStack:callStack]; } -- (void)enableCrypto:(BOOL)enableCrypto success:(void (^)(void))success failure:(void (^)(NSError *))failure +- (void)disableCrypto { - MXLogDebug(@"[MXSesion] enableCrypto: %@", @(enableCrypto)); + MXLogDebug(@"[MXSesion] disableCrypto"); - if (enableCrypto && !_crypto) - { - NSError *error; - _crypto = [MXLegacyCrypto createCryptoWithMatrixSession:self error:&error]; - if (!_crypto && error) - { - if (failure) - { - failure(error); - } - return; - } - - if (_state == MXSessionStateRunning) - { - [self startCrypto:success failure:failure]; - } - else - { - MXLogDebug(@"[MXSesion] enableCrypto: crypto module will be start later (MXSession.state: %@)", [MXTools readableSessionState:_state]); - - if (success) - { - dispatch_async(dispatch_get_main_queue(), ^{ - success(); - }); - } - } - } - else if (!enableCrypto && _crypto) + if (_crypto) { // Erase all crypto data of this user [_crypto close:YES]; _crypto = nil; - - if (success) - { - success(); - } - } - else - { - if (success) - { - success(); - } } } @@ -3415,7 +3226,7 @@ - (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.enableStartupProgress && progress) + if (progress) { progress([self.startupProgress overallProgressForStep:completedRooms totalCount:self.rooms.count progress:1]); completedRooms += 1; @@ -5056,14 +4867,6 @@ - (void)decryptEvents:(NSArray *)events } } -- (void)resetReplayAttackCheckInTimeline:(NSString*)timeline -{ - if ([_crypto isKindOfClass:[MXLegacyCrypto class]]) - { - [(MXLegacyCrypto *)_crypto resetReplayAttackCheckInTimeline:timeline]; - } -} - // Called when an event finally got decrypted after a late room key reception - (void)onDidDecryptEvent:(NSNotification *)notification { diff --git a/MatrixSDKTests/MXCryptoKeyVerificationTests.m b/MatrixSDKTests/MXCryptoKeyVerificationTests.m index cb8f68918d..c803b60442 100644 --- a/MatrixSDKTests/MXCryptoKeyVerificationTests.m +++ b/MatrixSDKTests/MXCryptoKeyVerificationTests.m @@ -455,12 +455,6 @@ - (void)testVerificationByToDeviceRequestCancellation success:^(id requestFromAliceDevice1POV) { // -> The other device list should have been computed well - 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]; - return; - } MXKeyVerificationByToDeviceRequest *toDeviceRequestFromAliceDevice1POV = (MXKeyVerificationByToDeviceRequest*)requestFromAliceDevice1POV; XCTAssertNotNil(toDeviceRequestFromAliceDevice1POV.requestedOtherDeviceIds); NSSet *expectedRequestedDevices = [NSSet setWithArray:@[aliceSession2DeviceId, aliceSession3DeviceId]]; diff --git a/MatrixSDKTests/MXCryptoTests.m b/MatrixSDKTests/MXCryptoTests.m index d300fa9e72..4021b939b7 100644 --- a/MatrixSDKTests/MXCryptoTests.m +++ b/MatrixSDKTests/MXCryptoTests.m @@ -105,38 +105,6 @@ - (NSUInteger)checkEncryptedEvent:(MXEvent*)event roomId:(NSString*)roomId clear #pragma mark - MXCrypto -- (void)testEnableCrypto -{ - [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation) { - - XCTAssertNil(mxSession.crypto, @"Crypto is disabled by default"); - - XCTAssertFalse([mxSession.legacyCrypto.store.class hasDataForCredentials:mxSession.matrixRestClient.credentials]); - - [mxSession enableCrypto:YES success:^{ - - XCTAssert(mxSession.crypto); - XCTAssert([mxSession.legacyCrypto.store.class hasDataForCredentials:mxSession.matrixRestClient.credentials]); - - [mxSession enableCrypto:NO success:^{ - - XCTAssertNil(mxSession.crypto); - XCTAssertFalse([mxSession.legacyCrypto.store.class hasDataForCredentials:mxSession.matrixRestClient.credentials], @"Crypto data must have been trashed"); - - [expectation fulfill]; - - } failure:^(NSError *error) { - XCTFail(@"The request should not fail - NSError: %@", error); - [expectation fulfill]; - }]; - - } failure:^(NSError *error) { - XCTFail(@"The request should not fail - NSError: %@", error); - [expectation fulfill]; - }]; - }]; -} - - (void)testMXSDKOptionsEnableCryptoWhenOpeningMXSession { [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = YES; @@ -149,90 +117,11 @@ - (void)testMXSDKOptionsEnableCryptoWhenOpeningMXSession XCTAssert(mxSession.crypto); - [mxSession enableCrypto:NO success:^{ - - XCTAssertNil(mxSession.crypto); - - [expectation fulfill]; - - } failure:^(NSError *error) { - XCTFail(@"The request should not fail - NSError: %@", error); - [expectation fulfill]; - }]; - - }]; -} - -- (void)testCryptoNoDeviceId -{ - [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation) { - // Simulate no device id provided by the home server - mxSession.matrixRestClient.credentials.deviceId = nil; - - [mxSession enableCrypto:YES success:^{ - - XCTAssertGreaterThan(mxSession.legacyCrypto.store.deviceId.length, 0, "If the hs did not provide a device id, the crypto module must create one"); - [expectation fulfill]; - - } failure:^(NSError *error) { - XCTFail(@"The request should not fail - NSError: %@", error); - [expectation fulfill]; - }]; - - }]; -} - -- (void)testCryptoPersistenceInStore -{ - [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation) { - - XCTAssertNil(mxSession.crypto, @"Crypto is disabled by default"); - - __block MXSession *mxSession2 = mxSession; - - [mxSession enableCrypto:YES success:^{ - - XCTAssert(mxSession2.crypto); - - NSString *deviceCurve25519Key = mxSession2.legacyCrypto.olmDevice.deviceCurve25519Key; - NSString *deviceEd25519Key = mxSession2.legacyCrypto.olmDevice.deviceEd25519Key; - - NSArray *myUserDevices = [mxSession2.legacyCrypto.deviceList storedDevicesForUser:mxSession.myUserId]; - XCTAssertEqual(myUserDevices.count, 1); - - MXRestClient *bobRestClient = mxSession2.matrixRestClient; - [mxSession2 close]; - mxSession2 = nil; - - // Reopen the session - MXFileStore *store = [[MXFileStore alloc] init]; - - mxSession2 = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; - [matrixSDKTestsData retain:mxSession2]; - - [mxSession2 setStore:store success:^{ - - XCTAssert(mxSession2.crypto, @"MXSession must recall that it has crypto engaged"); - - XCTAssertEqualObjects(deviceCurve25519Key, mxSession2.legacyCrypto.olmDevice.deviceCurve25519Key); - XCTAssertEqualObjects(deviceEd25519Key, mxSession2.legacyCrypto.olmDevice.deviceEd25519Key); - - NSArray *myUserDevices2 = [mxSession2.legacyCrypto.deviceList storedDevicesForUser:mxSession2.myUser.userId]; - XCTAssertEqual(myUserDevices2.count, 1); - - XCTAssertEqualObjects(myUserDevices[0].deviceId, myUserDevices2[0].deviceId); + [mxSession disableCrypto]; - [expectation fulfill]; - - } failure:^(NSError *error) { - XCTFail(@"Cannot set up intial test conditions - error: %@", error); - [expectation fulfill]; - }]; + XCTAssertNil(mxSession.crypto); - } failure:^(NSError *error) { - XCTFail(@"The request should not fail - NSError: %@", error); - [expectation fulfill]; - }]; + [expectation fulfill]; }]; } @@ -2318,44 +2207,39 @@ - (void)testLeftAndJoinedBob // Make Bob come back to the room with a new device // Clear his crypto store - [bobSession enableCrypto:NO success:^{ - - // Relog bob to simulate a new device - [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = YES; - [matrixSDKTestsData relogUserSession:self session:bobSession withPassword:MXTESTS_BOB_PWD onComplete:^(MXSession *bobSession2) { - - [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; + [bobSession disableCrypto]; - [bobSession2 joinRoom:roomFromAlicePOV.roomId viaServers:nil success:^(MXRoom *roomFromBobPOV2) { + // Relog bob to simulate a new device + [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = YES; + [matrixSDKTestsData relogUserSession:self session:bobSession withPassword:MXTESTS_BOB_PWD onComplete:^(MXSession *bobSession2) { - // Bob should be able to receive the message from Alice - [roomFromBobPOV2 liveTimeline:^(id liveTimeline) { - [liveTimeline listenToEventsOfTypes:@[kMXEventTypeStringRoomMessage, kMXEventTypeStringRoomEncrypted] onEvent:^(MXEvent *event, MXTimelineDirection direction, MXRoomState *roomState) { + [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; - XCTAssert(event.clearEvent, @"Bob must be able to decrypt this new message on his new device"); + [bobSession2 joinRoom:roomFromAlicePOV.roomId viaServers:nil success:^(MXRoom *roomFromBobPOV2) { - XCTAssertEqual(0, [self checkEncryptedEvent:event roomId:roomFromBobPOV2.roomId clearMessage:message2FromAlice senderSession:aliceSession]); + // Bob should be able to receive the message from Alice + [roomFromBobPOV2 liveTimeline:^(id liveTimeline) { + [liveTimeline listenToEventsOfTypes:@[kMXEventTypeStringRoomMessage, kMXEventTypeStringRoomEncrypted] onEvent:^(MXEvent *event, MXTimelineDirection direction, MXRoomState *roomState) { - [expectation fulfill]; + XCTAssert(event.clearEvent, @"Bob must be able to decrypt this new message on his new device"); - }]; - }]; + XCTAssertEqual(0, [self checkEncryptedEvent:event roomId:roomFromBobPOV2.roomId clearMessage:message2FromAlice senderSession:aliceSession]); - [roomFromAlicePOV sendTextMessage:message2FromAlice threadId:nil success:nil failure:^(NSError *error) { - XCTFail(@"Cannot set up intial test conditions - error: %@", error); [expectation fulfill]; + }]; + }]; - } failure:^(NSError *error) { + [roomFromAlicePOV sendTextMessage:message2FromAlice threadId:nil success:nil failure:^(NSError *error) { XCTFail(@"Cannot set up intial test conditions - error: %@", error); [expectation fulfill]; }]; + } failure:^(NSError *error) { + XCTFail(@"Cannot set up intial test conditions - error: %@", error); + [expectation fulfill]; }]; - } failure:^(NSError *error) { - XCTFail(@"Cannot set up intial test conditions - error: %@", error); - [expectation fulfill]; }]; } failure:^(NSError *error) { @@ -2497,51 +2381,47 @@ - (void)testEnableEncryptionAfterNonCryptedMessages // Make Bob come back to the room with a new device // Clear his crypto store - [bobSession enableCrypto:NO success:^{ + [bobSession disableCrypto]; - // Relog bob to simulate a new device - [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = YES; - [matrixSDKTestsData relogUserSession:self session:bobSession withPassword:MXTESTS_BOB_PWD onComplete:^(MXSession *newBobSession) { + // Relog bob to simulate a new device + [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = YES; + [matrixSDKTestsData relogUserSession:self session:bobSession withPassword:MXTESTS_BOB_PWD onComplete:^(MXSession *newBobSession) { - [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; + [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; - MXRoom *roomFromNewBobPOV = [newBobSession roomWithRoomId:roomFromAlicePOV.roomId]; + MXRoom *roomFromNewBobPOV = [newBobSession roomWithRoomId:roomFromAlicePOV.roomId]; - NSDictionary *bobDevices = [aliceSession.legacyCrypto.store devicesForUser:newBobSession.myUser.userId]; - XCTAssertEqual(bobDevices.count, 0, @"Alice should not have needed Bob's keys at this time"); + NSDictionary *bobDevices = [aliceSession.legacyCrypto.store devicesForUser:newBobSession.myUser.userId]; + XCTAssertEqual(bobDevices.count, 0, @"Alice should not have needed Bob's keys at this time"); - // Turn the crypto ON in the room - [roomFromAlicePOV enableEncryptionWithAlgorithm:kMXCryptoMegolmAlgorithm success:^{ + // Turn the crypto ON in the room + [roomFromAlicePOV enableEncryptionWithAlgorithm:kMXCryptoMegolmAlgorithm success:^{ - [roomFromNewBobPOV liveTimeline:^(id liveTimeline) { - [liveTimeline listenToEventsOfTypes:@[kMXEventTypeStringRoomMessage, kMXEventTypeStringRoomEncrypted] onEvent:^(MXEvent *event, MXTimelineDirection direction, MXRoomState *roomState) { + [roomFromNewBobPOV liveTimeline:^(id liveTimeline) { + [liveTimeline listenToEventsOfTypes:@[kMXEventTypeStringRoomMessage, kMXEventTypeStringRoomEncrypted] onEvent:^(MXEvent *event, MXTimelineDirection direction, MXRoomState *roomState) { - XCTAssert(event.clearEvent, @"Bob must be able to decrypt message from his new device after the crypto is ON"); + XCTAssert(event.clearEvent, @"Bob must be able to decrypt message from his new device after the crypto is ON"); - XCTAssertEqual(0, [self checkEncryptedEvent:event roomId:roomFromNewBobPOV.roomId clearMessage:encryptedMessageFromAlice senderSession:aliceSession]); + XCTAssertEqual(0, [self checkEncryptedEvent:event roomId:roomFromNewBobPOV.roomId clearMessage:encryptedMessageFromAlice senderSession:aliceSession]); - NSDictionary *bobDevices = [aliceSession.legacyCrypto.store devicesForUser:newBobSession.myUser.userId]; - XCTAssertEqual(bobDevices.count, 1, @"Alice must now know Bob's device keys"); + NSDictionary *bobDevices = [aliceSession.legacyCrypto.store devicesForUser:newBobSession.myUser.userId]; + XCTAssertEqual(bobDevices.count, 1, @"Alice must now know Bob's device keys"); - [expectation fulfill]; + [expectation fulfill]; - }]; }]; + }]; - // Post an encrypted message - [roomFromAlicePOV sendTextMessage:encryptedMessageFromAlice threadId:nil success:nil failure:^(NSError *error) { - XCTFail(@"Cannot set up intial test conditions - error: %@", error); - [expectation fulfill]; - }]; - - } failure:^(NSError *error) { - XCTFail(@"The operation should not fail - NSError: %@", error); + // Post an encrypted message + [roomFromAlicePOV sendTextMessage:encryptedMessageFromAlice threadId:nil success:nil failure:^(NSError *error) { + XCTFail(@"Cannot set up intial test conditions - error: %@", error); [expectation fulfill]; }]; + + } failure:^(NSError *error) { + XCTFail(@"The operation should not fail - NSError: %@", error); + [expectation fulfill]; }]; - } failure:^(NSError *error) { - XCTFail(@"The operation should not fail - NSError: %@", error); - [expectation fulfill]; }]; } failure:^(NSError *error) { @@ -2685,87 +2565,6 @@ - (void)testEnableEncryptionAfterNonCryptedMessages #pragma mark - import/export -// Almost same code as testImportRoomKeys -- (void)testExportImportRoomKeysWithPassword -{ - [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoomWithCryptedMessages:self cryptedBob:YES readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - - NSString *password = @"motdepasse"; - - [bobSession.crypto exportRoomKeysWithPassword:password success:^(NSData *keyFile) { - - // Clear bob crypto data - [bobSession enableCrypto:NO success:^{ - - XCTAssertFalse([bobSession.legacyCrypto.store.class hasDataForCredentials:bobSession.matrixRestClient.credentials], @"Bob's keys should have been deleted"); - - [bobSession enableCrypto:YES success:^{ - - MXRoom *roomFromBobPOV = [bobSession roomWithRoomId:roomId]; - - - NSMutableArray *encryptedEvents = [NSMutableArray array]; - - [roomFromBobPOV liveTimeline:^(id liveTimeline) { - [liveTimeline listenToEventsOfTypes:@[kMXEventTypeStringRoomEncrypted] onEvent:^(MXEvent *event, MXTimelineDirection direction, MXRoomState *roomState) { - - [encryptedEvents addObject:event]; - }]; - - - [liveTimeline resetPagination]; - [liveTimeline paginate:100 direction:MXTimelineDirectionBackwards onlyFromStore:NO complete:^{ - - XCTAssertEqual(encryptedEvents.count, 5, @"There are 5 encrypted messages in the room. They cannot be decrypted at this step in the test"); - - - // All these events must be decrypted once we import the keys - observer = [[NSNotificationCenter defaultCenter] addObserverForName:kMXEventDidDecryptNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { - - [encryptedEvents removeObject:note.object]; - }]; - - // Import the exported keys - [bobSession.crypto importRoomKeys:keyFile withPassword:password success:^(NSUInteger total, NSUInteger imported) { - - XCTAssertGreaterThan(total, 0); - XCTAssertEqual(total, imported); - - XCTAssertEqual(encryptedEvents.count, 0, @"All events should have been decrypted after the keys import"); - - [expectation fulfill]; - - } failure:^(NSError *error) { - - XCTFail(@"The operation should not fail - NSError: %@", error); - [expectation fulfill]; - }]; - - } failure:^(NSError *error) { - XCTFail(@"The operation should not fail - NSError: %@", error); - [expectation fulfill]; - }]; - }]; - - } failure:^(NSError *error) { - XCTFail(@"The operation should not fail - NSError: %@", error); - [expectation fulfill]; - }]; - - - } failure:^(NSError *error) { - XCTFail(@"The operation should not fail - NSError: %@", error); - [expectation fulfill]; - }]; - - } failure:^(NSError *error) { - XCTFail(@"The operation should not fail - NSError: %@", error); - [expectation fulfill]; - }]; - - }]; -} - - (void)testImportRoomKeysWithWrongPassword { [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoomWithCryptedMessages:self cryptedBob:YES readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { diff --git a/MatrixSDKTests/MatrixSDKTestsData.m b/MatrixSDKTests/MatrixSDKTestsData.m index 7d0b7b68bb..79e5521068 100644 --- a/MatrixSDKTests/MatrixSDKTestsData.m +++ b/MatrixSDKTests/MatrixSDKTestsData.m @@ -901,35 +901,32 @@ - (void)relogUserSessionWithNewDevice:(XCTestCase*)testCase { NSString *userId = session.matrixRestClient.credentials.userId; - [session enableCrypto:NO success:^{ + [session disableCrypto]; - [session close]; - - MXRestClient *mxRestClient = [[MXRestClient alloc] initWithHomeServer:kMXTestsHomeServerURL - andOnUnrecognizedCertificateBlock:nil]; - [self retain:mxRestClient]; + [session close]; - [mxRestClient loginWithLoginType:kMXLoginFlowTypePassword username:userId password:password success:^(MXCredentials *credentials) { + MXRestClient *mxRestClient = [[MXRestClient alloc] initWithHomeServer:kMXTestsHomeServerURL + andOnUnrecognizedCertificateBlock:nil]; + [self retain:mxRestClient]; - MXRestClient *mxRestClient2 = [[MXRestClient alloc] initWithCredentials:credentials andOnUnrecognizedCertificateBlock:nil]; - [self retain:mxRestClient2]; + [mxRestClient loginWithLoginType:kMXLoginFlowTypePassword username:userId password:password success:^(MXCredentials *credentials) { - MXSession *newSession = [[MXSession alloc] initWithMatrixRestClient:mxRestClient2]; - [self retain:newSession]; + MXRestClient *mxRestClient2 = [[MXRestClient alloc] initWithCredentials:credentials andOnUnrecognizedCertificateBlock:nil]; + [self retain:mxRestClient2]; - [newSession start:^{ + MXSession *newSession = [[MXSession alloc] initWithMatrixRestClient:mxRestClient2]; + [self retain:newSession]; - onComplete(newSession); + [newSession start:^{ - } failure:^(NSError *error) { - [self breakTestCase:testCase reason:@"Cannot set up intial test conditions - error: %@", error]; - }]; + onComplete(newSession); } failure:^(NSError *error) { - [self breakTestCase:testCase reason:@"Cannot relog %@. Error: %@", userId, error]; + [self breakTestCase:testCase reason:@"Cannot set up intial test conditions - error: %@", error]; }]; + } failure:^(NSError *error) { - [self breakTestCase:testCase reason:@"Cannot logout %@. Error: %@", userId, error]; + [self breakTestCase:testCase reason:@"Cannot relog %@. Error: %@", userId, error]; }]; } diff --git a/changelog.d/pr-1772.change b/changelog.d/pr-1772.change new file mode 100644 index 0000000000..7b85c1e3aa --- /dev/null +++ b/changelog.d/pr-1772.change @@ -0,0 +1 @@ +Crypto: Deprecate MXLegacyCrypto From 0b9001f33ce83d030cff02930571c6a64441c855 Mon Sep 17 00:00:00 2001 From: Andy Uhnak Date: Tue, 18 Apr 2023 11:42:35 +0100 Subject: [PATCH 2/3] Add crypto migration delegate --- MatrixSDK/Contrib/Swift/MXSession.swift | 18 ++ .../CrossSigning/MXCrossSigningV2.swift | 2 +- MatrixSDK/Crypto/MXCryptoV2Factory.swift | 12 +- MatrixSDK/MXSDKOptions.h | 11 +- MatrixSDK/MXSDKOptions.m | 2 +- MatrixSDK/MXSession.h | 12 +- MatrixSDK/MXSession.m | 72 ++++- MatrixSDKTests/MXCryptoTests.m | 287 +++++++++++++++--- MatrixSDKTests/MatrixSDKTestsData.m | 33 +- .../TestPlans/AllWorkingTests.xctestplan | 1 - 10 files changed, 371 insertions(+), 79 deletions(-) diff --git a/MatrixSDK/Contrib/Swift/MXSession.swift b/MatrixSDK/Contrib/Swift/MXSession.swift index 912332af48..e738b0e1e4 100644 --- a/MatrixSDK/Contrib/Swift/MXSession.swift +++ b/MatrixSDK/Contrib/Swift/MXSession.swift @@ -127,6 +127,24 @@ public extension MXSession { __setStore(store, success: currySuccess(completion), failure: curryFailure(completion)) } + + /** + Enable End-to-End encryption. + + In case of enabling, the operation will complete when the session will be ready + to make encrytion with other users devices + + - parameters: + - isEnabled: `false` stops crypto and erases crypto data. + - completion: A block called when the SDK has completed a catchup, or times out. + - response: Indicates whether the sync was successful. + */ + @nonobjc func enableCrypto(_ isEnabled: Bool, completion: @escaping (_ response: MXResponse) -> Void) { + __enableCrypto(isEnabled, success: currySuccess(completion), failure: curryFailure(completion)) + } + + + /// Create a new room with the given parameters. /// - Parameters: /// - name: Name of the room diff --git a/MatrixSDK/Crypto/CrossSigning/MXCrossSigningV2.swift b/MatrixSDK/Crypto/CrossSigning/MXCrossSigningV2.swift index 92eadb8cfb..e8ab628c8f 100644 --- a/MatrixSDK/Crypto/CrossSigning/MXCrossSigningV2.swift +++ b/MatrixSDK/Crypto/CrossSigning/MXCrossSigningV2.swift @@ -126,7 +126,7 @@ class MXCrossSigningV2: NSObject, MXCrossSigning { // If we are considered verified, there is no need for a verification upgrade // after migrating from legacy crypto if myUserCrossSigningKeys?.trustLevel.isVerified == true { - MXSDKOptions.sharedInstance().needsVerificationUpgrade = false + MXSDKOptions.sharedInstance().cryptoMigrationDelegate?.needsVerificationUpgrade = false } log.debug("Cross signing state refreshed, new state: \(state)") diff --git a/MatrixSDK/Crypto/MXCryptoV2Factory.swift b/MatrixSDK/Crypto/MXCryptoV2Factory.swift index 1843f49fc0..d910a1dc7a 100644 --- a/MatrixSDK/Crypto/MXCryptoV2Factory.swift +++ b/MatrixSDK/Crypto/MXCryptoV2Factory.swift @@ -16,6 +16,16 @@ import Foundation +/// Delegate for migrating account data from legacy crypto to rust-based Crypto SDK +@objc public protocol MXCryptoV2MigrationDelegate { + + /// Flag indicating whether this account requires a re-verification after migrating to Crypto SDK + /// + /// This flag is set to true if the legacy account is considered verified but the rust account + /// does not consider the migrated data secure enough, as it applies stricter security conditions. + var needsVerificationUpgrade: Bool { get set } +} + @objc public class MXCryptoV2Factory: NSObject { enum Error: Swift.Error { case cryptoNotAvailable @@ -139,7 +149,7 @@ import Foundation // unless the rust-based crypto already considers the current session to be verified given // the migration data log.debug("Needs verification upgrade") - MXSDKOptions.sharedInstance().needsVerificationUpgrade = true + MXSDKOptions.sharedInstance().cryptoMigrationDelegate?.needsVerificationUpgrade = true } } } diff --git a/MatrixSDK/MXSDKOptions.h b/MatrixSDK/MXSDKOptions.h index 778ab3d6d5..e4f82bdba1 100644 --- a/MatrixSDK/MXSDKOptions.h +++ b/MatrixSDK/MXSDKOptions.h @@ -48,7 +48,7 @@ typedef NS_ENUM(NSUInteger, MXCallTransferType) NS_ASSUME_NONNULL_BEGIN -@protocol MXBackgroundModeHandler, MXCryptoV2Feature; +@protocol MXBackgroundModeHandler, MXCryptoV2MigrationDelegate; /** SDK options that can be set at the launch time. @@ -204,14 +204,11 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic) BOOL enableRoomSharedHistoryOnInvite; /** - Flag indicating whether this account requires a re-verification after migrating to Crypto SDK + The delegate for migrating account data from legacy crypto to rust-based Crypto SDK - This flag is set to true if the legacy account is considered verified but the rust account - does not consider the migrated data secure enough, as it applies stricter security conditions. - - @remark NO by default. + By default, nil. */ -@property (nonatomic) BOOL needsVerificationUpgrade; +@property (nonatomic, nullable, weak) id cryptoMigrationDelegate; /** Enable symmetric room key backups diff --git a/MatrixSDK/MXSDKOptions.m b/MatrixSDK/MXSDKOptions.m index 0652f18fdc..d1f9f103ab 100644 --- a/MatrixSDK/MXSDKOptions.m +++ b/MatrixSDK/MXSDKOptions.m @@ -54,9 +54,9 @@ - (instancetype)init _authEnableRefreshTokens = NO; _enableThreads = NO; _enableRoomSharedHistoryOnInvite = NO; - _needsVerificationUpgrade = NO; _enableSymmetricBackup = NO; _enableNewClientInformationFeature = NO; + _cryptoMigrationDelegate = nil; } return self; diff --git a/MatrixSDK/MXSession.h b/MatrixSDK/MXSession.h index 31e274dc32..bfcb723119 100644 --- a/MatrixSDK/MXSession.h +++ b/MatrixSDK/MXSession.h @@ -776,9 +776,17 @@ typedef void (^MXOnBackgroundSyncFail)(NSError *error); - (void)enableVoIPWithCallStack:(id)callStack; /** - Disable End-to-End encryption. + Enable End-to-End encryption. + + In case of enabling, the operation will complete when the session will be ready + to make encrytion with other users devices + + @param enableCrypto NO stops crypto and erases crypto data. + + @param success A block object called when the operation succeeds. + @param failure A block object called when the operation fails. */ -- (void)disableCrypto; +- (void)enableCrypto:(BOOL)enableCrypto success:(void (^)(void))success failure:(void (^)(NSError *error))failure NS_REFINED_FOR_SWIFT; /** Get the versions of the specification supported by the server. diff --git a/MatrixSDK/MXSession.m b/MatrixSDK/MXSession.m index 2b0b16e362..2942cc4b36 100644 --- a/MatrixSDK/MXSession.m +++ b/MatrixSDK/MXSession.m @@ -1351,12 +1351,25 @@ - (void)close - (MXHTTPOperation*)logout:(void (^)(void))success failure:(void (^)(NSError *error))failure { + // Create an empty operation that will be mutated later + MXHTTPOperation *operation = [[MXHTTPOperation alloc] init]; + // Clear crypto data // For security and because it will be no more useful as we will get a new device id // on the next log in - [self disableCrypto]; - - return [self.matrixRestClient logout:success failure:failure]; + MXWeakify(self); + [self enableCrypto:NO success:^{ + MXStrongifyAndReturnIfNil(self); + + if (!operation.isCancelled) + { + MXHTTPOperation *operation2 = [self.matrixRestClient logout:success failure:failure]; + [operation mutateTo:operation2]; + } + + } failure:nil]; + + return operation; } - (MXHTTPOperation*)deactivateAccountWithAuthParameters:(NSDictionary*)authParameters @@ -2161,15 +2174,62 @@ - (void)enableVoIPWithCallStack:(id)callStack _callManager = [[MXCallManager alloc] initWithMatrixSession:self andCallStack:callStack]; } -- (void)disableCrypto +- (void)enableCrypto:(BOOL)enableCrypto success:(void (^)(void))success failure:(void (^)(NSError *))failure { - MXLogDebug(@"[MXSesion] disableCrypto"); + MXLogDebug(@"[MXSesion] enableCrypto: %@", @(enableCrypto)); - if (_crypto) + if (enableCrypto && !_crypto) + { + MXWeakify(self); + [MXCryptoV2Factory.shared buildCryptoWithSession:self + migrationProgress:nil + success:^(id crypto) { + + MXLogDebug(@"[MXSession] enableCrypto: Successfully initialized crypto module"); + MXStrongifyAndReturnIfNil(self); + self->_crypto = crypto; + + if (self->_state == MXSessionStateRunning) + { + [self startCrypto:success failure:failure]; + } + else + { + MXLogDebug(@"[MXSesion] enableCrypto: crypto module will be start later (MXSession.state: %@)", [MXTools readableSessionState:self->_state]); + + if (success) + { + dispatch_async(dispatch_get_main_queue(), ^{ + success(); + }); + } + } + + } failure:^(NSError *error) { + MXLogErrorDetails(@"[MXSession] enableCrypto: Error initialized crypto module", error); + if (failure) + { + failure(error); + } + }]; + } + else if (!enableCrypto && _crypto) { // Erase all crypto data of this user [_crypto close:YES]; _crypto = nil; + + if (success) + { + success(); + } + } + else + { + if (success) + { + success(); + } } } diff --git a/MatrixSDKTests/MXCryptoTests.m b/MatrixSDKTests/MXCryptoTests.m index 4021b939b7..36b50f5138 100644 --- a/MatrixSDKTests/MXCryptoTests.m +++ b/MatrixSDKTests/MXCryptoTests.m @@ -105,6 +105,35 @@ - (NSUInteger)checkEncryptedEvent:(MXEvent*)event roomId:(NSString*)roomId clear #pragma mark - MXCrypto +- (void)testEnableCrypto +{ + [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation) { + + XCTAssertNil(mxSession.crypto, @"Crypto is disabled by default"); + + MXKeyProvider.sharedInstance.delegate = [[MXKeyProviderStub alloc] init]; + [mxSession enableCrypto:YES success:^{ + MXKeyProvider.sharedInstance.delegate = nil; + + XCTAssert(mxSession.crypto); + + [mxSession enableCrypto:NO success:^{ + + XCTAssertNil(mxSession.crypto); + [expectation fulfill]; + + } failure:^(NSError *error) { + XCTFail(@"The request should not fail - NSError: %@", error); + [expectation fulfill]; + }]; + + } failure:^(NSError *error) { + XCTFail(@"The request should not fail - NSError: %@", error); + [expectation fulfill]; + }]; + }]; +} + - (void)testMXSDKOptionsEnableCryptoWhenOpeningMXSession { [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = YES; @@ -117,11 +146,89 @@ - (void)testMXSDKOptionsEnableCryptoWhenOpeningMXSession XCTAssert(mxSession.crypto); - [mxSession disableCrypto]; + [mxSession enableCrypto:NO success:^{ - XCTAssertNil(mxSession.crypto); + XCTAssertNil(mxSession.crypto); + [expectation fulfill]; - [expectation fulfill]; + } failure:^(NSError *error) { + XCTFail(@"The request should not fail - NSError: %@", error); + [expectation fulfill]; + }]; + + }]; +} + +- (void)testCryptoNoDeviceId +{ + [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation) { + // Simulate no device id provided by the home server + mxSession.matrixRestClient.credentials.deviceId = nil; + + [mxSession enableCrypto:YES success:^{ + + XCTAssertGreaterThan(mxSession.legacyCrypto.store.deviceId.length, 0, "If the hs did not provide a device id, the crypto module must create one"); + [expectation fulfill]; + + } failure:^(NSError *error) { + XCTFail(@"The request should not fail - NSError: %@", error); + [expectation fulfill]; + }]; + + }]; +} + +- (void)testCryptoPersistenceInStore +{ + [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation) { + + XCTAssertNil(mxSession.crypto, @"Crypto is disabled by default"); + + __block MXSession *mxSession2 = mxSession; + + [mxSession enableCrypto:YES success:^{ + + XCTAssert(mxSession2.crypto); + + NSString *deviceCurve25519Key = mxSession2.legacyCrypto.olmDevice.deviceCurve25519Key; + NSString *deviceEd25519Key = mxSession2.legacyCrypto.olmDevice.deviceEd25519Key; + + NSArray *myUserDevices = [mxSession2.legacyCrypto.deviceList storedDevicesForUser:mxSession.myUserId]; + XCTAssertEqual(myUserDevices.count, 1); + + MXRestClient *bobRestClient = mxSession2.matrixRestClient; + [mxSession2 close]; + mxSession2 = nil; + + // Reopen the session + MXFileStore *store = [[MXFileStore alloc] init]; + + mxSession2 = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession2]; + + [mxSession2 setStore:store success:^{ + + XCTAssert(mxSession2.crypto, @"MXSession must recall that it has crypto engaged"); + + XCTAssertEqualObjects(deviceCurve25519Key, mxSession2.legacyCrypto.olmDevice.deviceCurve25519Key); + XCTAssertEqualObjects(deviceEd25519Key, mxSession2.legacyCrypto.olmDevice.deviceEd25519Key); + + NSArray *myUserDevices2 = [mxSession2.legacyCrypto.deviceList storedDevicesForUser:mxSession2.myUser.userId]; + XCTAssertEqual(myUserDevices2.count, 1); + + XCTAssertEqualObjects(myUserDevices[0].deviceId, myUserDevices2[0].deviceId); + + [expectation fulfill]; + + } failure:^(NSError *error) { + XCTFail(@"Cannot set up intial test conditions - error: %@", error); + [expectation fulfill]; + }]; + + } failure:^(NSError *error) { + XCTFail(@"The request should not fail - NSError: %@", error); + [expectation fulfill]; + }]; }]; } @@ -2207,39 +2314,44 @@ - (void)testLeftAndJoinedBob // Make Bob come back to the room with a new device // Clear his crypto store - [bobSession disableCrypto]; + [bobSession enableCrypto:NO success:^{ - // Relog bob to simulate a new device - [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = YES; - [matrixSDKTestsData relogUserSession:self session:bobSession withPassword:MXTESTS_BOB_PWD onComplete:^(MXSession *bobSession2) { + // Relog bob to simulate a new device + [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = YES; + [matrixSDKTestsData relogUserSession:self session:bobSession withPassword:MXTESTS_BOB_PWD onComplete:^(MXSession *bobSession2) { - [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; + [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; - [bobSession2 joinRoom:roomFromAlicePOV.roomId viaServers:nil success:^(MXRoom *roomFromBobPOV2) { + [bobSession2 joinRoom:roomFromAlicePOV.roomId viaServers:nil success:^(MXRoom *roomFromBobPOV2) { - // Bob should be able to receive the message from Alice - [roomFromBobPOV2 liveTimeline:^(id liveTimeline) { - [liveTimeline listenToEventsOfTypes:@[kMXEventTypeStringRoomMessage, kMXEventTypeStringRoomEncrypted] onEvent:^(MXEvent *event, MXTimelineDirection direction, MXRoomState *roomState) { + // Bob should be able to receive the message from Alice + [roomFromBobPOV2 liveTimeline:^(id liveTimeline) { + [liveTimeline listenToEventsOfTypes:@[kMXEventTypeStringRoomMessage, kMXEventTypeStringRoomEncrypted] onEvent:^(MXEvent *event, MXTimelineDirection direction, MXRoomState *roomState) { - XCTAssert(event.clearEvent, @"Bob must be able to decrypt this new message on his new device"); + XCTAssert(event.clearEvent, @"Bob must be able to decrypt this new message on his new device"); - XCTAssertEqual(0, [self checkEncryptedEvent:event roomId:roomFromBobPOV2.roomId clearMessage:message2FromAlice senderSession:aliceSession]); + XCTAssertEqual(0, [self checkEncryptedEvent:event roomId:roomFromBobPOV2.roomId clearMessage:message2FromAlice senderSession:aliceSession]); - [expectation fulfill]; + [expectation fulfill]; + }]; + }]; + + [roomFromAlicePOV sendTextMessage:message2FromAlice threadId:nil success:nil failure:^(NSError *error) { + XCTFail(@"Cannot set up intial test conditions - error: %@", error); + [expectation fulfill]; }]; - }]; - [roomFromAlicePOV sendTextMessage:message2FromAlice threadId:nil success:nil failure:^(NSError *error) { + } failure:^(NSError *error) { XCTFail(@"Cannot set up intial test conditions - error: %@", error); [expectation fulfill]; }]; - } failure:^(NSError *error) { - XCTFail(@"Cannot set up intial test conditions - error: %@", error); - [expectation fulfill]; }]; + } failure:^(NSError *error) { + XCTFail(@"Cannot set up intial test conditions - error: %@", error); + [expectation fulfill]; }]; } failure:^(NSError *error) { @@ -2381,47 +2493,51 @@ - (void)testEnableEncryptionAfterNonCryptedMessages // Make Bob come back to the room with a new device // Clear his crypto store - [bobSession disableCrypto]; + [bobSession enableCrypto:NO success:^{ - // Relog bob to simulate a new device - [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = YES; - [matrixSDKTestsData relogUserSession:self session:bobSession withPassword:MXTESTS_BOB_PWD onComplete:^(MXSession *newBobSession) { + // Relog bob to simulate a new device + [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = YES; + [matrixSDKTestsData relogUserSession:self session:bobSession withPassword:MXTESTS_BOB_PWD onComplete:^(MXSession *newBobSession) { - [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; + [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; - MXRoom *roomFromNewBobPOV = [newBobSession roomWithRoomId:roomFromAlicePOV.roomId]; + MXRoom *roomFromNewBobPOV = [newBobSession roomWithRoomId:roomFromAlicePOV.roomId]; - NSDictionary *bobDevices = [aliceSession.legacyCrypto.store devicesForUser:newBobSession.myUser.userId]; - XCTAssertEqual(bobDevices.count, 0, @"Alice should not have needed Bob's keys at this time"); + NSDictionary *bobDevices = [aliceSession.legacyCrypto.store devicesForUser:newBobSession.myUser.userId]; + XCTAssertEqual(bobDevices.count, 0, @"Alice should not have needed Bob's keys at this time"); - // Turn the crypto ON in the room - [roomFromAlicePOV enableEncryptionWithAlgorithm:kMXCryptoMegolmAlgorithm success:^{ + // Turn the crypto ON in the room + [roomFromAlicePOV enableEncryptionWithAlgorithm:kMXCryptoMegolmAlgorithm success:^{ - [roomFromNewBobPOV liveTimeline:^(id liveTimeline) { - [liveTimeline listenToEventsOfTypes:@[kMXEventTypeStringRoomMessage, kMXEventTypeStringRoomEncrypted] onEvent:^(MXEvent *event, MXTimelineDirection direction, MXRoomState *roomState) { + [roomFromNewBobPOV liveTimeline:^(id liveTimeline) { + [liveTimeline listenToEventsOfTypes:@[kMXEventTypeStringRoomMessage, kMXEventTypeStringRoomEncrypted] onEvent:^(MXEvent *event, MXTimelineDirection direction, MXRoomState *roomState) { - XCTAssert(event.clearEvent, @"Bob must be able to decrypt message from his new device after the crypto is ON"); + XCTAssert(event.clearEvent, @"Bob must be able to decrypt message from his new device after the crypto is ON"); - XCTAssertEqual(0, [self checkEncryptedEvent:event roomId:roomFromNewBobPOV.roomId clearMessage:encryptedMessageFromAlice senderSession:aliceSession]); + XCTAssertEqual(0, [self checkEncryptedEvent:event roomId:roomFromNewBobPOV.roomId clearMessage:encryptedMessageFromAlice senderSession:aliceSession]); - NSDictionary *bobDevices = [aliceSession.legacyCrypto.store devicesForUser:newBobSession.myUser.userId]; - XCTAssertEqual(bobDevices.count, 1, @"Alice must now know Bob's device keys"); + NSDictionary *bobDevices = [aliceSession.legacyCrypto.store devicesForUser:newBobSession.myUser.userId]; + XCTAssertEqual(bobDevices.count, 1, @"Alice must now know Bob's device keys"); - [expectation fulfill]; + [expectation fulfill]; + }]; }]; - }]; - // Post an encrypted message - [roomFromAlicePOV sendTextMessage:encryptedMessageFromAlice threadId:nil success:nil failure:^(NSError *error) { - XCTFail(@"Cannot set up intial test conditions - error: %@", error); + // Post an encrypted message + [roomFromAlicePOV sendTextMessage:encryptedMessageFromAlice threadId:nil success:nil failure:^(NSError *error) { + XCTFail(@"Cannot set up intial test conditions - error: %@", error); + [expectation fulfill]; + }]; + + } failure:^(NSError *error) { + XCTFail(@"The operation should not fail - NSError: %@", error); [expectation fulfill]; }]; - - } failure:^(NSError *error) { - XCTFail(@"The operation should not fail - NSError: %@", error); - [expectation fulfill]; }]; + } failure:^(NSError *error) { + XCTFail(@"The operation should not fail - NSError: %@", error); + [expectation fulfill]; }]; } failure:^(NSError *error) { @@ -2565,6 +2681,87 @@ - (void)testEnableEncryptionAfterNonCryptedMessages #pragma mark - import/export +// Almost same code as testImportRoomKeys +- (void)testExportImportRoomKeysWithPassword +{ + [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoomWithCryptedMessages:self cryptedBob:YES readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { + + NSString *password = @"motdepasse"; + + [bobSession.crypto exportRoomKeysWithPassword:password success:^(NSData *keyFile) { + + // Clear bob crypto data + [bobSession enableCrypto:NO success:^{ + + XCTAssertFalse([bobSession.legacyCrypto.store.class hasDataForCredentials:bobSession.matrixRestClient.credentials], @"Bob's keys should have been deleted"); + + [bobSession enableCrypto:YES success:^{ + + MXRoom *roomFromBobPOV = [bobSession roomWithRoomId:roomId]; + + + NSMutableArray *encryptedEvents = [NSMutableArray array]; + + [roomFromBobPOV liveTimeline:^(id liveTimeline) { + [liveTimeline listenToEventsOfTypes:@[kMXEventTypeStringRoomEncrypted] onEvent:^(MXEvent *event, MXTimelineDirection direction, MXRoomState *roomState) { + + [encryptedEvents addObject:event]; + }]; + + + [liveTimeline resetPagination]; + [liveTimeline paginate:100 direction:MXTimelineDirectionBackwards onlyFromStore:NO complete:^{ + + XCTAssertEqual(encryptedEvents.count, 5, @"There are 5 encrypted messages in the room. They cannot be decrypted at this step in the test"); + + + // All these events must be decrypted once we import the keys + observer = [[NSNotificationCenter defaultCenter] addObserverForName:kMXEventDidDecryptNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { + + [encryptedEvents removeObject:note.object]; + }]; + + // Import the exported keys + [bobSession.crypto importRoomKeys:keyFile withPassword:password success:^(NSUInteger total, NSUInteger imported) { + + XCTAssertGreaterThan(total, 0); + XCTAssertEqual(total, imported); + + XCTAssertEqual(encryptedEvents.count, 0, @"All events should have been decrypted after the keys import"); + + [expectation fulfill]; + + } failure:^(NSError *error) { + + XCTFail(@"The operation should not fail - NSError: %@", error); + [expectation fulfill]; + }]; + + } failure:^(NSError *error) { + XCTFail(@"The operation should not fail - NSError: %@", error); + [expectation fulfill]; + }]; + }]; + + } failure:^(NSError *error) { + XCTFail(@"The operation should not fail - NSError: %@", error); + [expectation fulfill]; + }]; + + + } failure:^(NSError *error) { + XCTFail(@"The operation should not fail - NSError: %@", error); + [expectation fulfill]; + }]; + + } failure:^(NSError *error) { + XCTFail(@"The operation should not fail - NSError: %@", error); + [expectation fulfill]; + }]; + + }]; +} + - (void)testImportRoomKeysWithWrongPassword { [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoomWithCryptedMessages:self cryptedBob:YES readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { diff --git a/MatrixSDKTests/MatrixSDKTestsData.m b/MatrixSDKTests/MatrixSDKTestsData.m index 79e5521068..7d0b7b68bb 100644 --- a/MatrixSDKTests/MatrixSDKTestsData.m +++ b/MatrixSDKTests/MatrixSDKTestsData.m @@ -901,32 +901,35 @@ - (void)relogUserSessionWithNewDevice:(XCTestCase*)testCase { NSString *userId = session.matrixRestClient.credentials.userId; - [session disableCrypto]; + [session enableCrypto:NO success:^{ - [session close]; + [session close]; - MXRestClient *mxRestClient = [[MXRestClient alloc] initWithHomeServer:kMXTestsHomeServerURL - andOnUnrecognizedCertificateBlock:nil]; - [self retain:mxRestClient]; + MXRestClient *mxRestClient = [[MXRestClient alloc] initWithHomeServer:kMXTestsHomeServerURL + andOnUnrecognizedCertificateBlock:nil]; + [self retain:mxRestClient]; - [mxRestClient loginWithLoginType:kMXLoginFlowTypePassword username:userId password:password success:^(MXCredentials *credentials) { + [mxRestClient loginWithLoginType:kMXLoginFlowTypePassword username:userId password:password success:^(MXCredentials *credentials) { - MXRestClient *mxRestClient2 = [[MXRestClient alloc] initWithCredentials:credentials andOnUnrecognizedCertificateBlock:nil]; - [self retain:mxRestClient2]; + MXRestClient *mxRestClient2 = [[MXRestClient alloc] initWithCredentials:credentials andOnUnrecognizedCertificateBlock:nil]; + [self retain:mxRestClient2]; - MXSession *newSession = [[MXSession alloc] initWithMatrixRestClient:mxRestClient2]; - [self retain:newSession]; + MXSession *newSession = [[MXSession alloc] initWithMatrixRestClient:mxRestClient2]; + [self retain:newSession]; + + [newSession start:^{ - [newSession start:^{ + onComplete(newSession); - onComplete(newSession); + } failure:^(NSError *error) { + [self breakTestCase:testCase reason:@"Cannot set up intial test conditions - error: %@", error]; + }]; } failure:^(NSError *error) { - [self breakTestCase:testCase reason:@"Cannot set up intial test conditions - error: %@", error]; + [self breakTestCase:testCase reason:@"Cannot relog %@. Error: %@", userId, error]; }]; - } failure:^(NSError *error) { - [self breakTestCase:testCase reason:@"Cannot relog %@. Error: %@", userId, error]; + [self breakTestCase:testCase reason:@"Cannot logout %@. Error: %@", userId, error]; }]; } diff --git a/MatrixSDKTests/TestPlans/AllWorkingTests.xctestplan b/MatrixSDKTests/TestPlans/AllWorkingTests.xctestplan index 61e671924d..711f37fbce 100644 --- a/MatrixSDKTests/TestPlans/AllWorkingTests.xctestplan +++ b/MatrixSDKTests/TestPlans/AllWorkingTests.xctestplan @@ -82,7 +82,6 @@ "MXCryptoTests\/testDiscardAndRestoreOlmOutboundKey", "MXCryptoTests\/testDownloadKeysForUserWithNoDevice", "MXCryptoTests\/testDownloadKeysWithUnreachableHS", - "MXCryptoTests\/testEnableCrypto", "MXCryptoTests\/testEnableEncryptionAfterNonCryptedMessages", "MXCryptoTests\/testEncryptionAlgorithmChange", "MXCryptoTests\/testEnsureSingleOlmSession", From 485490eba7330233a748e51268d39a093a2eb642 Mon Sep 17 00:00:00 2001 From: Andy Uhnak Date: Wed, 19 Apr 2023 14:13:27 +0100 Subject: [PATCH 3/3] One more legacy crypto use --- MatrixSDK/Data/MXRoom.m | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/MatrixSDK/Data/MXRoom.m b/MatrixSDK/Data/MXRoom.m index 020af712d3..b626989f0b 100644 --- a/MatrixSDK/Data/MXRoom.m +++ b/MatrixSDK/Data/MXRoom.m @@ -82,11 +82,6 @@ The list of room operations (sending of text, images...) that must be sent FIFO queue of failure blocks waiting for [self members:]. */ NSMutableArray *pendingMembersFailureBlocks; - - /** - The manager for sharing keys of messages with invited users - */ - MXSharedHistoryKeyManager *sharedHistoryKeyManager; } @end @@ -123,14 +118,6 @@ - (id)initWithRoomId:(NSString *)roomId matrixSession:(MXSession *)mxSession2 an { _roomId = roomId; mxSession = mxSession2; - - if ([mxSession.crypto isKindOfClass:[MXLegacyCrypto class]]) - { - MXMegolmDecryption *decryption = [[MXMegolmDecryption alloc] initWithCrypto:mxSession.crypto]; - sharedHistoryKeyManager = [[MXSharedHistoryKeyManager alloc] initWithRoomId:roomId - crypto:mxSession.crypto - service:decryption]; - } if (store) { @@ -1977,24 +1964,9 @@ - (MXHTTPOperation*)inviteUser:(NSString*)userId success:(void (^)(void))success failure:(void (^)(NSError *error))failure { - if (MXSDKOptions.sharedInstance.enableRoomSharedHistoryOnInvite) - { - [self shareRoomKeysWith:userId]; - } return [mxSession.matrixRestClient inviteUser:userId toRoom:self.roomId success:success failure:failure]; } -- (void)shareRoomKeysWith:(NSString *)userId -{ - // The value of 20 is arbitrary and imprecise, we merely want to ensure that when a user is invited to a room - // they are able to read any immediately preciding messages that may be relevant to the invite. - NSInteger numberOfSharedMessage = 20; - id enumerator = [self enumeratorForStoredMessagesWithTypeIn:@[kMXEventTypeStringRoomMessage]]; - [sharedHistoryKeyManager shareMessageKeysWithUserId:userId - messageEnumerator:enumerator - limit:numberOfSharedMessage]; -} - - (MXHTTPOperation*)inviteUserByEmail:(NSString*)email success:(void (^)(void))success failure:(void (^)(NSError *error))failure