Skip to content

Commit

Permalink
New CryptoMachine on each background operation
Browse files Browse the repository at this point in the history
  • Loading branch information
Anderas committed Jan 31, 2023
1 parent b1b6be3 commit 5996fb7
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 32 deletions.
53 changes: 32 additions & 21 deletions MatrixSDK/Background/Crypto/MXBackgroundCryptoV2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,13 @@ class MXBackgroundCryptoV2: MXBackgroundCrypto {
case missingCredentials
}

private let machine: MXCryptoMachine
private let credentials: MXCredentials
private let restClient: MXRestClient
private let log = MXNamedLog(name: "MXBackgroundCryptoV2")

init(credentials: MXCredentials, restClient: MXRestClient) throws {
guard
let userId = credentials.userId,
let deviceId = credentials.deviceId
else {
throw Error.missingCredentials
}

// `MXCryptoMachine` will load the same store as the main application meaning that background and foreground
// sync services have access to the same data / keys. Possible race conditions are handled internally.
machine = try MXCryptoMachine(
userId: userId,
deviceId: deviceId,
restClient: restClient,
getRoomAction: { [log] _ in
log.error("The background crypto should not be accessing rooms")
return nil
}
)

init(credentials: MXCredentials, restClient: MXRestClient) {
self.credentials = credentials
self.restClient = restClient
log.debug("Initialized background crypto module")
}

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

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

do {
let machine = try createMachine()
let decrypted = try machine.decryptRoomEvent(event)
let result = try MXEventDecryptionResult(event: decrypted)
event.setClearData(result)
Expand All @@ -127,6 +114,30 @@ class MXBackgroundCryptoV2: MXBackgroundCrypto {
throw error
}
}

// `MXCryptoMachine` will load the same store as the main application meaning that background and foreground
// sync services have access to the same data / keys. The machine is not fully multi-thread and multi-process
// safe, and until this is resolved we open a new instance of `MXCryptoMachine` on each background operation
// to ensure we are always up-to-date with whatever has been written by the foreground process in the meanwhile.
// See https://github.com/matrix-org/matrix-rust-sdk/issues/1415 for more details.
private func createMachine() throws -> MXCryptoMachine {
guard
let userId = credentials.userId,
let deviceId = credentials.deviceId
else {
throw Error.missingCredentials
}

return try MXCryptoMachine(
userId: userId,
deviceId: deviceId,
restClient: restClient,
getRoomAction: { [log] _ in
log.error("The background crypto should not be accessing rooms")
return nil
}
)
}
}

#endif
16 changes: 5 additions & 11 deletions MatrixSDK/Background/MXBackgroundSyncService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public enum MXBackgroundSyncServiceError: Error {
private let processingQueue: DispatchQueue
public let credentials: MXCredentials
private let syncResponseStoreManager: MXSyncResponseStoreManager
private let crypto: MXBackgroundCrypto?
private let crypto: MXBackgroundCrypto
private var store: MXStore
private let restClient: MXRestClient
private var pushRulesManager: MXBackgroundPushRulesManager
Expand Down Expand Up @@ -91,12 +91,7 @@ public enum MXBackgroundSyncServiceError: Error {
crypto = {
#if DEBUG
if MXSDKOptions.sharedInstance().isCryptoSDKAvailable && MXSDKOptions.sharedInstance().enableCryptoSDK {
do {
return try MXBackgroundCryptoV2(credentials: credentials, restClient: restClient)
} catch {
MXLog.failure("Cannot create background crypto", context: error)
return nil
}
return MXBackgroundCryptoV2(credentials: credentials, restClient: restClient)
}
#endif
return MXLegacyBackgroundCrypto(credentials: credentials, resetBackgroundCryptoStore: resetBackgroundCryptoStore)
Expand Down Expand Up @@ -299,7 +294,7 @@ public enum MXBackgroundSyncServiceError: Error {
}

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

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

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

await crypto?.handleSyncResponse(syncResponse)
await crypto.handleSyncResponse(syncResponse)

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

0 comments on commit 5996fb7

Please sign in to comment.