Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set local trust with Crypto V2 and deprecate legacy verification method #1613

Merged
merged 1 commit into from
Oct 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion MatrixSDK.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -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.2', :configurations => ["DEBUG"]
ss.dependency 'MatrixSDKCrypto', '0.1.3', :configurations => ["DEBUG"]
end

end
20 changes: 12 additions & 8 deletions MatrixSDK/Crypto/CryptoMachine/MXCryptoMachine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,10 @@ extension MXCryptoMachine: MXCryptoUserIdentitySource {
let request = try machine.verifyDevice(userId: userId, deviceId: deviceId)
try await requests.uploadSignatures(request: request)
}

func setLocalTrust(userId: String, deviceId: String, trust: LocalTrust) throws {
try machine.setLocalTrust(userId: userId, deviceId: deviceId, trustState: trust)
}
}

extension MXCryptoMachine: MXCryptoRoomEventEncrypting {
Expand Down Expand Up @@ -540,6 +544,14 @@ extension MXCryptoMachine: MXCryptoVerificationRequesting {
return request
}

func requestVerification(userId: String, deviceId: String, methods: [String]) async throws -> VerificationRequest {
guard let result = try machine.requestVerificationWithDevice(userId: userId, deviceId: deviceId, methods: methods) else {
throw Error.missingVerificationRequest
}
try await handleOutgoingVerificationRequest(result.request)
return result.verification
}

func verificationRequests(userId: String) -> [VerificationRequest] {
return machine.getVerificationRequests(userId: userId)
}
Expand Down Expand Up @@ -619,14 +631,6 @@ extension MXCryptoMachine: MXCryptoSASVerifying {
return result.sas
}

func startSasVerification(userId: String, deviceId: String) async throws -> Sas {
guard let result = try machine.startSasWithDevice(userId: userId, deviceId: deviceId) else {
throw Error.missingVerification
}
try await handleOutgoingVerificationRequest(result.request)
return result.sas
}

func acceptSasVerification(userId: String, flowId: String) async throws {
guard let request = machine.acceptSasVerification(userId: userId, flowId: flowId) else {
throw Error.missingVerification
Expand Down
3 changes: 2 additions & 1 deletion MatrixSDK/Crypto/CryptoMachine/MXCryptoProtocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ protocol MXCryptoUserIdentitySource: MXCryptoIdentity {
func downloadKeys(users: [String]) async throws
func manuallyVerifyUser(userId: String) async throws
func manuallyVerifyDevice(userId: String, deviceId: String) async throws
func setLocalTrust(userId: String, deviceId: String, trust: LocalTrust) throws
}

/// Event encryption and decryption
Expand All @@ -79,6 +80,7 @@ protocol MXCryptoVerificationRequesting: MXCryptoIdentity {
func receiveUnencryptedVerificationEvent(event: MXEvent, roomId: String)
func requestSelfVerification(methods: [String]) async throws -> VerificationRequest
func requestVerification(userId: String, roomId: String, methods: [String]) async throws -> VerificationRequest
func requestVerification(userId: String, deviceId: String, methods: [String]) async throws -> VerificationRequest
func verificationRequests(userId: String) -> [VerificationRequest]
func verificationRequest(userId: String, flowId: String) -> VerificationRequest?
func acceptVerificationRequest(userId: String, flowId: String, methods: [String]) async throws
Expand All @@ -95,7 +97,6 @@ protocol MXCryptoVerifying: MXCryptoIdentity {
/// Lifecycle of SAS-specific verification transaction
protocol MXCryptoSASVerifying: MXCryptoVerifying {
func startSasVerification(userId: String, flowId: String) async throws -> Sas
func startSasVerification(userId: String, deviceId: String) async throws -> Sas
func acceptSasVerification(userId: String, flowId: String) async throws
func emojiIndexes(sas: Sas) throws -> [Int]
func sasDecimals(sas: Sas) throws -> [Int]
Expand Down
124 changes: 96 additions & 28 deletions MatrixSDK/Crypto/MXCryptoV2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ private class MXCryptoV2: MXCrypto {
private let keyBackup: MXKeyBackup
private var recovery: MXRecoveryService

private var undecryptableEvents = [String: MXEvent]()

private let log = MXNamedLog(name: "MXCryptoV2")

public init(userId: String, deviceId: String, session: MXSession, restClient: MXRestClient) throws {
Expand Down Expand Up @@ -281,7 +283,11 @@ private class MXCryptoV2: MXCrypto {
return MXEventDecryptionResult()
}

return machine.decryptRoomEvent(event)
let result = machine.decryptRoomEvent(event)
if result.clearEvent == nil {
undecryptableEvents[event.eventId] = event
}
return result
}

public override func decryptEvents(
Expand Down Expand Up @@ -334,6 +340,15 @@ private class MXCryptoV2: MXCrypto {
onComplete?()
}

private func retryDecryptEvent(event: MXEvent) -> Bool {
guard let result = decryptEvent(event, inTimeline: nil) else {
log.error("Cannot get decryption result")
return false
}
event.setClearData(result)
return result.clearEvent != nil
}

// MARK: - Sync

public override func handle(_ syncResponse: MXSyncResponse!) {
Expand Down Expand Up @@ -476,17 +491,19 @@ private class MXCryptoV2: MXCrypto {
return
}

log.debug("Setting device verification status manually")
log.debug("Setting device verification status manually to \(verificationStatus)")

switch verificationStatus {
case .unverified, .blocked, .unknown:
log.error("Not implemented")
let localTrust = verificationStatus.localTrust
switch localTrust {
case .verified:
// If we want to set verified status, we will manually verify the device,
// including uploading relevant signatures

Task {
do {
try await machine.manuallyVerifyDevice(userId: userId, deviceId: deviceId)
log.debug("Successfully marked device as verified")
await MainActor.run {
await MainActor.run {
success?()
}
} catch {
Expand All @@ -496,11 +513,18 @@ private class MXCryptoV2: MXCrypto {
}
}
}
@unknown default:
log.failure("Unknown verification status", context: [
"status": verificationStatus
])
failure?(nil)

case .blackListed, .ignored, .unset:
// In other cases we will only set local trust level

do {
try machine.setLocalTrust(userId: userId, deviceId: deviceId, trust: localTrust)
log.debug("Successfully set local trust to \(localTrust)")
success?()
} catch {
log.error("Failed setting local trust", context: error)
failure?(error)
}
}
}

Expand Down Expand Up @@ -613,13 +637,21 @@ private class MXCryptoV2: MXCrypto {
success: ((Data?) -> Void)!,
failure: ((Swift.Error?) -> Void)!
) {
do {
let data = try backupEngine.exportRoomKeys(passphrase: password)
log.debug("Exported room keys")
success(data)
} catch {
log.error("Failed exporting room keys", context: error)
failure(error)
Task.detached { [weak self] in
guard let self = self else { return }

do {
let data = try self.backupEngine.exportRoomKeys(passphrase: password)
await MainActor.run {
self.log.debug("Exported room keys")
success(data)
}
} catch {
await MainActor.run {
self.log.error("Failed exporting room keys", context: error)
failure(error)
}
}
}
}

Expand All @@ -635,13 +667,28 @@ private class MXCryptoV2: MXCrypto {
return
}

do {
let result = try backupEngine.importRoomKeys(data, passphrase: password)
log.debug("Imported room keys")
success(UInt(result.total), UInt(result.imported))
} catch {
log.error("Failed importing room keys", context: error)
failure(error)
Task.detached { [weak self] in
guard let self = self else { return }

do {
let result = try self.backupEngine.importRoomKeys(data, passphrase: password)

await MainActor.run {
for (eventId, event) in self.undecryptableEvents {
if self.retryDecryptEvent(event: event) {
self.undecryptableEvents[eventId] = nil
}
}

self.log.debug("Imported room keys")
success(UInt(result.total), UInt(result.imported))
}
} catch {
await MainActor.run {
self.log.error("Failed importing room keys", context: error)
failure(error)
}
}
}
}

Expand Down Expand Up @@ -731,9 +778,12 @@ private class MXCryptoV2: MXCrypto {
}

public override func isRoomEncrypted(_ roomId: String!) -> Bool {
log.debug("Not implemented")
// All rooms encrypted by default for now
return true
guard let roomId = roomId, let summary = session?.room(withRoomId: roomId)?.summary else {
log.error("Missing room")
return false
}
// State of room encryption will be moved to MatrixSDKCrypto
return summary.isEncrypted
}

public override func isRoomSharingHistory(_ roomId: String!) -> Bool {
Expand All @@ -754,4 +804,22 @@ private class MXCryptoV2: MXCrypto {
}
}

private extension MXDeviceVerification {
var localTrust: LocalTrust {
switch self {
case .unverified:
return .unset
case .verified:
return .verified
case .blocked:
return .blackListed
case .unknown:
return .unset
@unknown default:
MXNamedLog(name: "MXDeviceVerification").failure("Unknown device verification", context: self)
return .unset
}
}
}

#endif
15 changes: 0 additions & 15 deletions MatrixSDK/Crypto/Verification/MXKeyVerificationManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,21 +124,6 @@ FOUNDATION_EXPORT NSString *const MXKeyVerificationManagerNotificationTransactio

#pragma mark - Transactions

/**
Begin a device verification.

@param userId the other user id.
@param deviceId the other user device id.
@param method the verification method (ex: MXKeyVerificationMethodSAS).
@param success a block called when the operation succeeds.
@param failure a block called when the operation fails.
*/
- (void)beginKeyVerificationWithUserId:(NSString*)userId
andDeviceId:(NSString*)deviceId
method:(NSString*)method
success:(void(^)(id<MXKeyVerificationTransaction> transaction))success
failure:(void(^)(NSError *error))failure __attribute__((deprecated("Start key verification with a request (requestVerificationByToDeviceWithUserId) instead")));

/**
Begin a device verification from a request.

Expand Down
9 changes: 0 additions & 9 deletions MatrixSDK/Crypto/Verification/MXKeyVerificationManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -243,15 +243,6 @@ - (void)requestVerificationByDMWithUserId2:(NSString*)userId

#pragma mark Transactions

- (void)beginKeyVerificationWithUserId:(NSString*)userId
andDeviceId:(NSString*)deviceId
method:(NSString*)method
success:(void(^)(id<MXKeyVerificationTransaction> transaction))success
failure:(void(^)(NSError *error))failure
{
[self beginKeyVerificationWithUserId:userId andDeviceId:deviceId transactionId:nil dmRoomId:nil dmEventId:nil method:method success:success failure:failure];
}

- (void)beginKeyVerificationFromRequest:(id<MXKeyVerificationRequest>)request
method:(NSString*)method
success:(void(^)(id<MXKeyVerificationTransaction> transaction))success
Expand Down
Loading