Skip to content

Commit

Permalink
Verification request and QR listener
Browse files Browse the repository at this point in the history
  • Loading branch information
Anderas committed Dec 15, 2022
1 parent bfc32f9 commit a93c146
Show file tree
Hide file tree
Showing 17 changed files with 373 additions and 514 deletions.
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.6', :configurations => ["DEBUG"], :inhibit_warnings => true
ss.dependency 'MatrixSDKCrypto', '0.1.7', :configurations => ["DEBUG"], :inhibit_warnings => true
end

end
6 changes: 0 additions & 6 deletions MatrixSDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1943,8 +1943,6 @@
ED76A4AE28EDA2CE00036FF0 /* MXKeyVerificationStateResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED76A4AC28EDA2CE00036FF0 /* MXKeyVerificationStateResolver.swift */; };
ED79B9852940BB45008952F6 /* MXToDevicePayloadUnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED79B9842940BB45008952F6 /* MXToDevicePayloadUnitTests.swift */; };
ED79B9862940BB45008952F6 /* MXToDevicePayloadUnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED79B9842940BB45008952F6 /* MXToDevicePayloadUnitTests.swift */; };
ED79B9882940E3CA008952F6 /* MXPlaceholderQRCodeTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED79B9872940E3CA008952F6 /* MXPlaceholderQRCodeTransaction.swift */; };
ED79B9892940E3CA008952F6 /* MXPlaceholderQRCodeTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED79B9872940E3CA008952F6 /* MXPlaceholderQRCodeTransaction.swift */; };
ED825F8F29014EDA006A614E /* MXSession+LegacyCrypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED825F8E29014EDA006A614E /* MXSession+LegacyCrypto.swift */; };
ED825F9029014EDA006A614E /* MXSession+LegacyCrypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED825F8E29014EDA006A614E /* MXSession+LegacyCrypto.swift */; };
ED88999127F2065D00718486 /* MXRoomAliasResolution.h in Headers */ = {isa = PBXBuildFile; fileRef = ED88998F27F2065C00718486 /* MXRoomAliasResolution.h */; settings = {ATTRIBUTES = (Public, ); }; };
Expand Down Expand Up @@ -3091,7 +3089,6 @@
ED751DAD28EDEC7E003748C3 /* MXKeyVerificationStateResolverUnitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXKeyVerificationStateResolverUnitTests.swift; sourceTree = "<group>"; };
ED76A4AC28EDA2CE00036FF0 /* MXKeyVerificationStateResolver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXKeyVerificationStateResolver.swift; sourceTree = "<group>"; };
ED79B9842940BB45008952F6 /* MXToDevicePayloadUnitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXToDevicePayloadUnitTests.swift; sourceTree = "<group>"; };
ED79B9872940E3CA008952F6 /* MXPlaceholderQRCodeTransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXPlaceholderQRCodeTransaction.swift; sourceTree = "<group>"; };
ED825F8E29014EDA006A614E /* MXSession+LegacyCrypto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MXSession+LegacyCrypto.swift"; sourceTree = "<group>"; };
ED88998F27F2065C00718486 /* MXRoomAliasResolution.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXRoomAliasResolution.h; sourceTree = "<group>"; };
ED88999027F2065D00718486 /* MXRoomAliasResolution.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXRoomAliasResolution.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4841,7 +4838,6 @@
B19A309A240424BD00FB6F35 /* MXQRCodeTransaction_Private.h */,
B19A309B240424BD00FB6F35 /* MXQRCodeTransaction.m */,
ED28068628F06D360070AE9F /* MXQRCodeTransactionV2.swift */,
ED79B9872940E3CA008952F6 /* MXPlaceholderQRCodeTransaction.swift */,
);
path = QRCode;
sourceTree = "<group>";
Expand Down Expand Up @@ -6820,7 +6816,6 @@
ECBF658126DE2A8500AA3A99 /* MXMemoryRoomOutgoingMessagesStore.m in Sources */,
32F00ABD2488E1CD00131741 /* MXRecoveryService.m in Sources */,
3275FD9D21A6B60B00B9C13D /* MXLoginPolicy.m in Sources */,
ED79B9882940E3CA008952F6 /* MXPlaceholderQRCodeTransaction.swift in Sources */,
327F8DB31C6112BA00581CA3 /* MXRoomThirdPartyInvite.m in Sources */,
B17982FC2119E4A2001FD722 /* MXRoomPowerLevels.m in Sources */,
ED6DAC0228C76F0A00ECDCB6 /* MXRoomKeyInfo.swift in Sources */,
Expand Down Expand Up @@ -7468,7 +7463,6 @@
ECBF658226DE2A8500AA3A99 /* MXMemoryRoomOutgoingMessagesStore.m in Sources */,
324DD2AF246AEB7B00377005 /* MXSecretStoragePassphrase.m in Sources */,
B14EF1EF2397E90400758AF0 /* MXIdentityService.m in Sources */,
ED79B9892940E3CA008952F6 /* MXPlaceholderQRCodeTransaction.swift in Sources */,
ECF29BE62641953C0053E6D6 /* MXAssertedIdentityModel.m in Sources */,
EC8A53C625B1BC77004E0802 /* MXTurnServerResponse.m in Sources */,
ED6DAC0328C76F0A00ECDCB6 /* MXRoomKeyInfo.swift in Sources */,
Expand Down
16 changes: 2 additions & 14 deletions MatrixSDK/Crypto/CryptoMachine/MXCryptoMachine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,8 @@ extension MXCryptoMachine: MXCryptoVerifying {
content: content
)
}

try await processOutgoingRequests()
}

func handleVerificationConfirmation(_ result: ConfirmVerificationResult) async throws {
Expand Down Expand Up @@ -744,21 +746,7 @@ extension MXCryptoMachine: MXCryptoBackup {

extension MXCryptoMachine: Logger {
func log(logLine: String) {
#if DEBUG
MXLog.debug("[MXCryptoMachine] \(logLine)")
#else
// Filtering out verbose logs for non-debug builds
guard !logLine.starts(with: "DEBUG") else {
return
}
MXLog.debug("[MXCryptoMachine] \(logLine)")
#endif
}

func log(error: String) {
MXLog.error("[MXCryptoMachine] Error", context: [
"error": error
])
}
}

Expand Down
6 changes: 6 additions & 0 deletions MatrixSDK/Crypto/MXCryptoV2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,12 @@ private class MXCryptoV2: NSObject, MXCrypto {
// we need to download their keys to be able to proceed with the verification flow
try await self.machine.downloadKeys(users: [userId])
}

do {
try await self.machine.processOutgoingRequests()
} catch {
self.log.error("Error processing requests", context: error)
}
}
}
}
Expand Down
108 changes: 23 additions & 85 deletions MatrixSDK/Crypto/Verification/MXKeyVerificationManagerV2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,6 @@ import Foundation

import MatrixSDKCrypto

/// Result of processing updates on verification object (request or transaction)
/// after each sync loop
enum MXKeyVerificationUpdateResult {
// The object has not changed since last sync
case noUpdates
// The object's state has changed
case updated
// The object is no longer available (e.g. it was cancelled)
case removed
}

class MXKeyVerificationManagerV2: NSObject, MXKeyVerificationManager {
enum Error: Swift.Error {
case requestNotSupported
Expand Down Expand Up @@ -220,25 +209,23 @@ class MXKeyVerificationManagerV2: NSObject, MXKeyVerificationManager {
return transaction
}

guard let request = activeRequests[transactionId] else {
guard
let activeRequest = activeRequests[transactionId],
let request = handler.verificationRequest(userId: activeRequest.otherUser, flowId: activeRequest.requestId)
else {
log.error("There is no pending verification request")
return nil
}

do {
let qr = try activeRequest.startQrVerification()
log.debug("Starting new QR verification")
let qr = try request.startQrVerification()
return addQrTransaction(for: qr, isIncoming: false)
return addQrTransaction(for: request, qrCode: qr, isIncoming: false)
} catch {
/// Placehoder QR transaction generated in case we cannot start a QR verification flow
/// (the other device cannot scan our code) but we may be able to scan theirs
log.debug("Adding placeholder QR verification")
let transaction = MXPlaceholderQRCodeTransaction(
otherUserId: request.otherUser,
otherDeviceId: request.otherDevice ?? "",
flowId: request.requestId,
roomId: request.roomId
)
activeTransactions[transaction.transactionId] = transaction
return transaction
return addQrTransaction(for: request, qrCode: nil, isIncoming: false)
}
}

Expand All @@ -255,7 +242,6 @@ class MXKeyVerificationManagerV2: NSObject, MXKeyVerificationManager {
@MainActor
func handleDeviceEvent(_ event: MXEvent) {
guard Self.toDeviceEventTypes.contains(event.type) else {
updatePendingVerification()
return
}

Expand All @@ -279,8 +265,6 @@ class MXKeyVerificationManagerV2: NSObject, MXKeyVerificationManager {
default:
log.failure("Event type should not be handled by key verification", context: event.type)
}

updatePendingVerification()
}

@MainActor
Expand All @@ -291,7 +275,6 @@ class MXKeyVerificationManagerV2: NSObject, MXKeyVerificationManager {

if !event.isEncrypted, let roomId = event.roomId {
handler.receiveUnencryptedVerificationEvent(event: event, roomId: roomId)
updatePendingVerification()
}

if event.type == kMXEventTypeStringRoomMessage && event.content?[kMXMessageTypeKey] as? String == kMXMessageTypeKeyVerificationRequest {
Expand All @@ -302,62 +285,13 @@ class MXKeyVerificationManagerV2: NSObject, MXKeyVerificationManager {
handleIncomingVerification(userId: event.sender, flowId: flowId)
return event.sender
} else {
updatePendingVerification()
return nil
}
}

// MARK: - Update

@MainActor
func updatePendingVerification() {
if !activeRequests.isEmpty {
log.debug("Processing \(activeRequests.count) pending requests")
}

let completedStates = Set([
MXKeyVerificationRequestStateAccepted.rawValue,
MXKeyVerificationRequestStateExpired.rawValue,
MXKeyVerificationRequestStateCancelled.rawValue,
MXKeyVerificationRequestStateCancelledByMe.rawValue
])
for request in activeRequests.values {
switch request.processUpdates() {
case .noUpdates:
break
case .updated:
NotificationCenter.default.post(name: .MXKeyVerificationRequestDidChange, object: request)
case .removed:
NotificationCenter.default.post(name: .MXKeyVerificationRequestDidChange, object: request)
activeRequests[request.requestId] = nil
}

if completedStates.contains(request.state.rawValue) {
NotificationCenter.default.post(name: .MXKeyVerificationRequestDidChange, object: request)
activeRequests[request.requestId] = nil
}
}

// QR code transactions do not yet have `changes` listener, so have to manage updates manually
for transaction in activeTransactions.values {
guard let transaction = transaction as? MXQRCodeTransactionV2 else {
continue
}

switch transaction.processUpdates() {
case .noUpdates:
break
case .updated:
NotificationCenter.default.post(name: .MXKeyVerificationTransactionDidChange, object: transaction)
case .removed:
NotificationCenter.default.post(name: .MXKeyVerificationTransactionDidChange, object: transaction)
activeTransactions[transaction.transactionId] = nil
}
}
}

// MARK: - Verification requests

@MainActor
func requestVerificationByToDevice(
withUserId userId: String,
deviceIds: [String]?,
Expand All @@ -379,6 +313,7 @@ class MXKeyVerificationManagerV2: NSObject, MXKeyVerificationManager {
}
}

@MainActor
private func requestVerification(userId: String, roomId: String, methods: [String]) async throws -> MXKeyVerificationRequest {
log.debug("->")

Expand All @@ -387,9 +322,10 @@ class MXKeyVerificationManagerV2: NSObject, MXKeyVerificationManager {
roomId: roomId,
methods: methods
)
return await addRequest(for: request)
return addRequest(for: request)
}

@MainActor
private func requestVerification(userId: String, deviceId: String, methods: [String]) async throws -> MXKeyVerificationRequest {
log.debug("->")

Expand All @@ -398,14 +334,15 @@ class MXKeyVerificationManagerV2: NSObject, MXKeyVerificationManager {
deviceId: deviceId,
methods: methods
)
return await addRequest(for: request)
return addRequest(for: request)
}

@MainActor
private func requestSelfVerification(methods: [String]) async throws -> MXKeyVerificationRequest {
log.debug("->")

let request = try await handler.requestSelfVerification(methods: methods)
return await addRequest(for: request)
return addRequest(for: request)
}

@MainActor
Expand Down Expand Up @@ -464,7 +401,10 @@ class MXKeyVerificationManagerV2: NSObject, MXKeyVerificationManager {
private func handleIncomingVerification(userId: String, flowId: String) {
log.debug(flowId)

guard let verification = handler.verification(userId: userId, flowId: flowId) else {
guard
let request = handler.verificationRequest(userId: userId, flowId: flowId),
let verification = handler.verification(userId: userId, flowId: flowId)
else {
log.error("Verification is not known", context: [
"flow_id": flowId
])
Expand All @@ -478,17 +418,15 @@ class MXKeyVerificationManagerV2: NSObject, MXKeyVerificationManager {
if activeRequests[transaction.transactionId] != nil {
log.debug("Auto-accepting transaction that matches a pending request")
transaction.accept()
updatePendingVerification()
}
case .qrCode(let qrCode):
if activeTransactions[flowId] is MXQRCodeTransaction {
// This flow may happen if we have previously started a QR verification, but so has the other side,
// and we scanned their code which now takes over the verification flow
log.debug("Updating existing QR verification transaction")
updatePendingVerification()
} else {
log.debug("Tracking new QR verification transaction")
_ = addQrTransaction(for: qrCode, isIncoming: true)
_ = addQrTransaction(for: request, qrCode: qrCode, isIncoming: true)
}
}
}
Expand All @@ -501,8 +439,8 @@ class MXKeyVerificationManagerV2: NSObject, MXKeyVerificationManager {
}

@MainActor
private func addQrTransaction(for qrCode: QrCodeProtocol, isIncoming: Bool) -> MXQRCodeTransactionV2 {
let transaction = MXQRCodeTransactionV2(qrCode: qrCode, isIncoming: isIncoming, handler: handler)
private func addQrTransaction(for request: VerificationRequestProtocol, qrCode: QrCodeProtocol?, isIncoming: Bool) -> MXQRCodeTransactionV2 {
let transaction = MXQRCodeTransactionV2(request: request, qrCode: qrCode, isIncoming: isIncoming, handler: handler)
activeTransactions[transaction.transactionId] = transaction
return transaction
}
Expand Down
Loading

0 comments on commit a93c146

Please sign in to comment.