Skip to content

Commit 5996fb7

Browse files
committed
New CryptoMachine on each background operation
1 parent b1b6be3 commit 5996fb7

File tree

2 files changed

+37
-32
lines changed

2 files changed

+37
-32
lines changed

MatrixSDK/Background/Crypto/MXBackgroundCryptoV2.swift

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,29 +27,13 @@ class MXBackgroundCryptoV2: MXBackgroundCrypto {
2727
case missingCredentials
2828
}
2929

30-
private let machine: MXCryptoMachine
30+
private let credentials: MXCredentials
31+
private let restClient: MXRestClient
3132
private let log = MXNamedLog(name: "MXBackgroundCryptoV2")
3233

33-
init(credentials: MXCredentials, restClient: MXRestClient) throws {
34-
guard
35-
let userId = credentials.userId,
36-
let deviceId = credentials.deviceId
37-
else {
38-
throw Error.missingCredentials
39-
}
40-
41-
// `MXCryptoMachine` will load the same store as the main application meaning that background and foreground
42-
// sync services have access to the same data / keys. Possible race conditions are handled internally.
43-
machine = try MXCryptoMachine(
44-
userId: userId,
45-
deviceId: deviceId,
46-
restClient: restClient,
47-
getRoomAction: { [log] _ in
48-
log.error("The background crypto should not be accessing rooms")
49-
return nil
50-
}
51-
)
52-
34+
init(credentials: MXCredentials, restClient: MXRestClient) {
35+
self.credentials = credentials
36+
self.restClient = restClient
5337
log.debug("Initialized background crypto module")
5438
}
5539

@@ -66,6 +50,7 @@ class MXBackgroundCryptoV2: MXBackgroundCrypto {
6650
log.debug(details)
6751

6852
do {
53+
let machine = try createMachine()
6954
_ = try await machine.handleSyncResponse(
7055
toDevice: syncResponse.toDevice,
7156
deviceLists: syncResponse.deviceLists,
@@ -100,6 +85,7 @@ class MXBackgroundCryptoV2: MXBackgroundCrypto {
10085
do {
10186
// Rust-sdk does not expose api to see if we have a given session key yet (will be added in the future)
10287
// so for the time being to find out if we can decrypt we simply perform the (more expensive) decryption
88+
let machine = try createMachine()
10389
_ = try machine.decryptRoomEvent(event)
10490
log.debug("Event `\(eventId)` can be decrypted with session `\(sessionId)`")
10591
return true
@@ -117,6 +103,7 @@ class MXBackgroundCryptoV2: MXBackgroundCrypto {
117103
log.debug("Decrypting event `\(eventId)`")
118104

119105
do {
106+
let machine = try createMachine()
120107
let decrypted = try machine.decryptRoomEvent(event)
121108
let result = try MXEventDecryptionResult(event: decrypted)
122109
event.setClearData(result)
@@ -127,6 +114,30 @@ class MXBackgroundCryptoV2: MXBackgroundCrypto {
127114
throw error
128115
}
129116
}
117+
118+
// `MXCryptoMachine` will load the same store as the main application meaning that background and foreground
119+
// sync services have access to the same data / keys. The machine is not fully multi-thread and multi-process
120+
// safe, and until this is resolved we open a new instance of `MXCryptoMachine` on each background operation
121+
// to ensure we are always up-to-date with whatever has been written by the foreground process in the meanwhile.
122+
// See https://github.com/matrix-org/matrix-rust-sdk/issues/1415 for more details.
123+
private func createMachine() throws -> MXCryptoMachine {
124+
guard
125+
let userId = credentials.userId,
126+
let deviceId = credentials.deviceId
127+
else {
128+
throw Error.missingCredentials
129+
}
130+
131+
return try MXCryptoMachine(
132+
userId: userId,
133+
deviceId: deviceId,
134+
restClient: restClient,
135+
getRoomAction: { [log] _ in
136+
log.error("The background crypto should not be accessing rooms")
137+
return nil
138+
}
139+
)
140+
}
130141
}
131142

132143
#endif

MatrixSDK/Background/MXBackgroundSyncService.swift

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public enum MXBackgroundSyncServiceError: Error {
4040
private let processingQueue: DispatchQueue
4141
public let credentials: MXCredentials
4242
private let syncResponseStoreManager: MXSyncResponseStoreManager
43-
private let crypto: MXBackgroundCrypto?
43+
private let crypto: MXBackgroundCrypto
4444
private var store: MXStore
4545
private let restClient: MXRestClient
4646
private var pushRulesManager: MXBackgroundPushRulesManager
@@ -91,12 +91,7 @@ public enum MXBackgroundSyncServiceError: Error {
9191
crypto = {
9292
#if DEBUG
9393
if MXSDKOptions.sharedInstance().isCryptoSDKAvailable && MXSDKOptions.sharedInstance().enableCryptoSDK {
94-
do {
95-
return try MXBackgroundCryptoV2(credentials: credentials, restClient: restClient)
96-
} catch {
97-
MXLog.failure("Cannot create background crypto", context: error)
98-
return nil
99-
}
94+
return MXBackgroundCryptoV2(credentials: credentials, restClient: restClient)
10095
}
10196
#endif
10297
return MXLegacyBackgroundCrypto(credentials: credentials, resetBackgroundCryptoStore: resetBackgroundCryptoStore)
@@ -299,7 +294,7 @@ public enum MXBackgroundSyncServiceError: Error {
299294
}
300295

301296
// should decrypt it first
302-
if let crypto = crypto, crypto.canDecryptEvent(event) {
297+
if crypto.canDecryptEvent(event) {
303298
// we have keys to decrypt the event
304299
MXLog.debug("[MXBackgroundSyncService] fetchEvent: Event needs to be decrpyted, and we have the keys to decrypt it.")
305300

@@ -406,8 +401,7 @@ public enum MXBackgroundSyncServiceError: Error {
406401
await self.handleSyncResponse(syncResponse, syncToken: eventStreamToken)
407402

408403
if let event = self.syncResponseStoreManager.event(withEventId: eventId, inRoom: roomId),
409-
let crypto = self.crypto,
410-
!crypto.canDecryptEvent(event),
404+
!self.crypto.canDecryptEvent(event),
411405
(syncResponse.toDevice?.events ?? []).count > 0 {
412406
// we got the event but not the keys to decrypt it. continue to sync
413407
self.launchBackgroundSync(forEventId: eventId, roomId: roomId, completion: completion)
@@ -446,7 +440,7 @@ public enum MXBackgroundSyncServiceError: Error {
446440
}
447441
syncResponseStoreManager.updateStore(with: syncResponse, syncToken: syncToken)
448442

449-
await crypto?.handleSyncResponse(syncResponse)
443+
await crypto.handleSyncResponse(syncResponse)
450444

451445
if MXSDKOptions.sharedInstance().autoAcceptRoomInvites,
452446
let invitedRooms = syncResponse.rooms?.invite {

0 commit comments

Comments
 (0)