Skip to content

Commit

Permalink
Merge pull request #1620 from matrix-org/andy/complete_crypto
Browse files Browse the repository at this point in the history
Complete MXCryptoV2 implementation
  • Loading branch information
Anderas authored Oct 31, 2022
2 parents 8a732dd + c58594c commit 4dc8446
Show file tree
Hide file tree
Showing 41 changed files with 1,001 additions and 714 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.3', :configurations => ["DEBUG"]
ss.dependency 'MatrixSDKCrypto', '0.1.5', :configurations => ["DEBUG"]
end

end
10 changes: 8 additions & 2 deletions MatrixSDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -500,8 +500,8 @@
32AF9285240EA2430008A0FD /* MXSecretShareRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 32AF9282240EA2430008A0FD /* MXSecretShareRequest.h */; };
32AF9286240EA2430008A0FD /* MXSecretShareRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 32AF9283240EA2430008A0FD /* MXSecretShareRequest.m */; };
32AF9287240EA2430008A0FD /* MXSecretShareRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 32AF9283240EA2430008A0FD /* MXSecretShareRequest.m */; };
32AF928A240EA3880008A0FD /* MXSecretShareSend.h in Headers */ = {isa = PBXBuildFile; fileRef = 32AF9288240EA3880008A0FD /* MXSecretShareSend.h */; };
32AF928B240EA3880008A0FD /* MXSecretShareSend.h in Headers */ = {isa = PBXBuildFile; fileRef = 32AF9288240EA3880008A0FD /* MXSecretShareSend.h */; };
32AF928A240EA3880008A0FD /* MXSecretShareSend.h in Headers */ = {isa = PBXBuildFile; fileRef = 32AF9288240EA3880008A0FD /* MXSecretShareSend.h */; settings = {ATTRIBUTES = (Public, ); }; };
32AF928B240EA3880008A0FD /* MXSecretShareSend.h in Headers */ = {isa = PBXBuildFile; fileRef = 32AF9288240EA3880008A0FD /* MXSecretShareSend.h */; settings = {ATTRIBUTES = (Public, ); }; };
32AF928C240EA3880008A0FD /* MXSecretShareSend.m in Sources */ = {isa = PBXBuildFile; fileRef = 32AF9289240EA3880008A0FD /* MXSecretShareSend.m */; };
32AF928D240EA3880008A0FD /* MXSecretShareSend.m in Sources */ = {isa = PBXBuildFile; fileRef = 32AF9289240EA3880008A0FD /* MXSecretShareSend.m */; };
32AF928F24110ADD0008A0FD /* MXSecretShareManager_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 32AF928E24110ADD0008A0FD /* MXSecretShareManager_Private.h */; };
Expand Down Expand Up @@ -1941,6 +1941,8 @@
ED8F1D3C2885BB2D00F897E7 /* MXCryptoProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED8F1D3A2885BB2D00F897E7 /* MXCryptoProtocols.swift */; };
EDA2CDD628F5C4230088ACE7 /* MXQRCodeTransactionV2UnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA2CDD528F5C4230088ACE7 /* MXQRCodeTransactionV2UnitTests.swift */; };
EDA2CDD728F5C4230088ACE7 /* MXQRCodeTransactionV2UnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA2CDD528F5C4230088ACE7 /* MXQRCodeTransactionV2UnitTests.swift */; };
EDA69340290BA92E00223252 /* MXCryptoMachineUnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA6933F290BA92E00223252 /* MXCryptoMachineUnitTests.swift */; };
EDA69341290BA92E00223252 /* MXCryptoMachineUnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA6933F290BA92E00223252 /* MXCryptoMachineUnitTests.swift */; };
EDAAC41928E2FCFE00DD89B5 /* MXCryptoSecretStoreV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDAAC41828E2FCFE00DD89B5 /* MXCryptoSecretStoreV2.swift */; };
EDAAC41A28E2FCFE00DD89B5 /* MXCryptoSecretStoreV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDAAC41828E2FCFE00DD89B5 /* MXCryptoSecretStoreV2.swift */; };
EDAAC41C28E30F3C00DD89B5 /* (null) in Headers */ = {isa = PBXBuildFile; settings = {ATTRIBUTES = (Public, ); }; };
Expand Down Expand Up @@ -3059,6 +3061,7 @@
ED8F1D332885ADE200F897E7 /* MXCryptoProtocolStubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXCryptoProtocolStubs.swift; sourceTree = "<group>"; };
ED8F1D3A2885BB2D00F897E7 /* MXCryptoProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MXCryptoProtocols.swift; sourceTree = "<group>"; };
EDA2CDD528F5C4230088ACE7 /* MXQRCodeTransactionV2UnitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXQRCodeTransactionV2UnitTests.swift; sourceTree = "<group>"; };
EDA6933F290BA92E00223252 /* MXCryptoMachineUnitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXCryptoMachineUnitTests.swift; sourceTree = "<group>"; };
EDAAC41228E2F86800DD89B5 /* MXCryptoSecretStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXCryptoSecretStore.h; sourceTree = "<group>"; };
EDAAC41828E2FCFE00DD89B5 /* MXCryptoSecretStoreV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXCryptoSecretStoreV2.swift; sourceTree = "<group>"; };
EDAAC42328E3177000DD89B5 /* MXRecoveryServiceDependencies.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MXRecoveryServiceDependencies.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -5320,6 +5323,7 @@
isa = PBXGroup;
children = (
ED8F1D332885ADE200F897E7 /* MXCryptoProtocolStubs.swift */,
EDA6933F290BA92E00223252 /* MXCryptoMachineUnitTests.swift */,
ED2DD11B286C4F3E00F06731 /* MXCryptoRequestsUnitTests.swift */,
ED8F1D312885AC5700F897E7 /* Device+Stub.swift */,
);
Expand Down Expand Up @@ -7155,6 +7159,7 @@
32832B5E1BCC048300241108 /* MXStoreNoStoreTests.m in Sources */,
A816247C25F60C7700A46F05 /* MXDeviceListOperationsPoolUnitTests.swift in Sources */,
B1660F1C260A20B900C3AA12 /* MXSpaceServiceTest.swift in Sources */,
EDA69340290BA92E00223252 /* MXCryptoMachineUnitTests.swift in Sources */,
ED35652C281150310002BF6A /* MXOlmInboundGroupSessionUnitTests.swift in Sources */,
32C9B71823E81A1C00C6F30A /* MXCrossSigningVerificationTests.m in Sources */,
323C5A081A70E53500FB0549 /* MXToolsUnitTests.m in Sources */,
Expand Down Expand Up @@ -7786,6 +7791,7 @@
32C9B71923E81A1C00C6F30A /* MXCrossSigningVerificationTests.m in Sources */,
B1E09A1D2397FCE90057C069 /* MXCryptoKeyVerificationTests.m in Sources */,
B1E09A472397FD990057C069 /* MXEventScanStoreUnitTests.m in Sources */,
EDA69341290BA92E00223252 /* MXCryptoMachineUnitTests.swift in Sources */,
ED35652D281150310002BF6A /* MXOlmInboundGroupSessionUnitTests.swift in Sources */,
B1E09A3D2397FD820057C069 /* MXStoreFileStoreTests.m in Sources */,
32CEEF3E23AD134A0039BA98 /* MXCrossSigningTests.m in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,12 @@ import MatrixSDKCrypto
self.selfSignedKeys = .init(jsonString: selfSigningKey)
self.userSignedKeys = nil
}

// `MatrixSDKCrypto` does not distinguish local and cross-signed
// verification status for users
trustLevel = MXUserTrustLevel(
crossSigningVerified: isVerified,
locallyVerified: false // Note: Local verification not yet implemented
locallyVerified: isVerified
)
}
}
Expand Down
19 changes: 18 additions & 1 deletion MatrixSDK/Crypto/CrossSigning/MXCrossSigningV2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import Foundation
class MXCrossSigningV2: NSObject, MXCrossSigning {
enum Error: Swift.Error {
case missingAuthSession
case cannotUnsetTrust
}

var state: MXCrossSigningState {
Expand Down Expand Up @@ -120,7 +121,7 @@ class MXCrossSigningV2: NSObject, MXCrossSigning {

Task {
do {
try await crossSigning.downloadKeys(users: [crossSigning.userId])
try await crossSigning.updateTrackedUsers(users: [crossSigning.userId])
myUserCrossSigningKeys = infoSource.crossSigningInfo(userId: crossSigning.userId)

log.debug("Cross signing state refreshed")
Expand Down Expand Up @@ -217,4 +218,20 @@ class MXCrossSigningV2: NSObject, MXCrossSigning {
}
}

extension MXCrossSigningV2: MXRecoveryServiceDelegate {
func setUserVerification(
_ verificationStatus: Bool,
forUser userId: String,
success: @escaping () -> Void,
failure: @escaping (Swift.Error?) -> Void
) {
guard verificationStatus else {
log.failure("Cannot unset user trust")
failure(Error.cannotUnsetTrust)
return
}
signUser(withUserId: userId, success: success, failure: failure)
}
}

#endif
87 changes: 48 additions & 39 deletions MatrixSDK/Crypto/CryptoMachine/MXCryptoMachine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,15 @@ extension MXCryptoMachine: MXCryptoIdentity {

var deviceCurve25519Key: String? {
guard let key = machine.identityKeys()[kMXKeyCurve25519Type] else {
log.error("Cannot get device curve25519 key")
log.failure("Cannot get device curve25519 key")
return nil
}
return key
}

var deviceEd25519Key: String? {
guard let key = machine.identityKeys()[kMXKeyEd25519Type] else {
log.error("Cannot get device ed25519 key")
log.failure("Cannot get device ed25519 key")
return nil
}
return key
Expand Down Expand Up @@ -163,18 +163,22 @@ extension MXCryptoMachine: MXCryptoSyncing {
unusedFallbackKeys: unusedFallbackKeys
)

guard let json = MXTools.deserialiseJSONString(result) as? [AnyHashable: Any] else {
log.error("Result cannot be serialized", context: [
guard
let json = MXTools.deserialiseJSONString(result) as? [Any],
let toDevice = MXToDeviceSyncResponse(fromJSON: ["events": json])
else {
log.failure("Result cannot be serialized", context: [
"result": result
])
return MXToDeviceSyncResponse()
}
return MXToDeviceSyncResponse(fromJSON: json)

return toDevice
}

func completeSync() async throws {
func processOutgoingRequests() async throws {
try await syncQueue.sync { [weak self] in
try await self?.processOutgoingRequests()
try await self?.handleOutgoingRequests()
}
}

Expand Down Expand Up @@ -235,7 +239,7 @@ extension MXCryptoMachine: MXCryptoSyncing {
try self.machine.markRequestAsSent(requestId: requestId, requestType: requestType, response: response ?? "")
}

private func processOutgoingRequests() async throws {
private func handleOutgoingRequests() async throws {
let requests = try machine.outgoingRequests()

try await withThrowingTaskGroup(of: Void.self) { [weak self] group in
Expand Down Expand Up @@ -312,10 +316,32 @@ extension MXCryptoMachine: MXCryptoUserIdentitySource {
}
}

func downloadKeys(users: [String]) async throws {
try await handleRequest(
.keysQuery(requestId: UUID().uuidString, users: users)
)
func isUserTracked(userId: String) -> Bool {
do {
return try machine.isUserTracked(userId: userId)
} catch {
log.error("Failed checking user tracking")
return false
}
}

func updateTrackedUsers(users: [String]) async throws {
machine.updateTrackedUsers(users: users)
try await withThrowingTaskGroup(of: Void.self) { [weak self] group in
guard let self = self else { return }

for request in try machine.outgoingRequests() {
guard case .keysQuery = request else {
continue
}

group.addTask {
try await self.handleRequest(request)
}
}

try await group.waitForAll()
}
}

func manuallyVerifyUser(userId: String) async throws {
Expand All @@ -334,29 +360,31 @@ extension MXCryptoMachine: MXCryptoUserIdentitySource {
}

extension MXCryptoMachine: MXCryptoRoomEventEncrypting {
func shareRoomKeysIfNecessary(roomId: String, users: [String]) async throws {
func shareRoomKeysIfNecessary(
roomId: String,
users: [String],
settings: EncryptionSettings
) async throws {
try await sessionsQueue.sync { [weak self] in
try await self?.updateTrackedUsers(users: users)
try await self?.getMissingSessions(users: users)
}

let roomQueue = await roomQueues.getQueue(for: roomId)
try await roomQueue.sync { [weak self] in
try await self?.shareRoomKey(roomId: roomId, users: users)
try await self?.shareRoomKey(roomId: roomId, users: users, settings: settings)
}
}

func encryptRoomEvent(
content: [AnyHashable : Any],
roomId: String,
eventType: String,
users: [String]
) async throws -> [String : Any] {
eventType: String
) throws -> [String : Any] {
guard let content = MXTools.serialiseJSONObject(content) else {
throw Error.cannotSerialize
}

try await shareRoomKeysIfNecessary(roomId: roomId, users: users)
let event = try machine.encrypt(roomId: roomId, eventType: eventType as String, content: content)
return MXTools.deserialiseJSONString(event) as? [String: Any] ?? [:]
}
Expand Down Expand Up @@ -421,25 +449,6 @@ extension MXCryptoMachine: MXCryptoRoomEventEncrypting {

// MARK: - Private

private func updateTrackedUsers(users: [String]) async throws {
machine.updateTrackedUsers(users: users)
try await withThrowingTaskGroup(of: Void.self) { [weak self] group in
guard let self = self else { return }

for request in try machine.outgoingRequests() {
guard case .keysQuery = request else {
continue
}

group.addTask {
try await self.handleRequest(request)
}
}

try await group.waitForAll()
}
}

private func getMissingSessions(users: [String]) async throws {
guard
let request = try machine.getMissingSessions(users: users),
Expand All @@ -450,8 +459,8 @@ extension MXCryptoMachine: MXCryptoRoomEventEncrypting {
try await handleRequest(request)
}

private func shareRoomKey(roomId: String, users: [String]) async throws {
let requests = try machine.shareRoomKey(roomId: roomId, users: users)
private func shareRoomKey(roomId: String, users: [String], settings: EncryptionSettings) async throws {
let requests = try machine.shareRoomKey(roomId: roomId, users: users, settings: settings)
try await withThrowingTaskGroup(of: Void.self) { [weak self] group in
guard let self = self else { return }

Expand Down
9 changes: 5 additions & 4 deletions MatrixSDK/Crypto/CryptoMachine/MXCryptoProtocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ protocol MXCryptoSyncing: MXCryptoIdentity {
unusedFallbackKeys: [String]?
) throws -> MXToDeviceSyncResponse

func completeSync() async throws
func processOutgoingRequests() async throws
}

/// Source of user devices and their cryptographic trust status
Expand All @@ -52,16 +52,17 @@ protocol MXCryptoDevicesSource: MXCryptoIdentity {
protocol MXCryptoUserIdentitySource: MXCryptoIdentity {
func userIdentity(userId: String) -> UserIdentity?
func isUserVerified(userId: String) -> Bool
func downloadKeys(users: [String]) async throws
func isUserTracked(userId: String) -> Bool
func updateTrackedUsers(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
protocol MXCryptoRoomEventEncrypting: MXCryptoIdentity {
func shareRoomKeysIfNecessary(roomId: String, users: [String]) async throws
func encryptRoomEvent(content: [AnyHashable: Any], roomId: String, eventType: String, users: [String]) async throws -> [String: Any]
func shareRoomKeysIfNecessary(roomId: String, users: [String], settings: EncryptionSettings) async throws
func encryptRoomEvent(content: [AnyHashable: Any], roomId: String, eventType: String) throws -> [String: Any]
func decryptRoomEvent(_ event: MXEvent) -> MXEventDecryptionResult
func requestRoomKey(event: MXEvent) async throws
func discardRoomKey(roomId: String)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ extension MXEventDecryptionResult {
senderCurve25519Key = event.senderCurve25519Key
claimedEd25519Key = event.claimedEd25519Key
forwardingCurve25519KeyChain = event.forwardingCurve25519Chain
isUntrusted = event.verificationState == VerificationState.untrusted
}
}

Expand Down
7 changes: 0 additions & 7 deletions MatrixSDK/Crypto/Data/Store/MXCryptoSecretStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,6 @@ NS_ASSUME_NONNULL_BEGIN
- (nullable NSString *)secretWithSecretId:(NSString *)secretId;


/**
Delete a secret.
@param secretId the id of the secret.
*/
- (void)deleteSecretWithSecretId:(NSString *)secretId;

@end

NS_ASSUME_NONNULL_END
Expand Down
8 changes: 8 additions & 0 deletions MatrixSDK/Crypto/Data/Store/MXCryptoStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,14 @@
*/
- (NSArray<MXCrossSigningInfo*> *)crossSigningKeys;

#pragma mark - Secrets

/**
Delete a secret.
@param secretId the id of the secret.
*/
- (void)deleteSecretWithSecretId:(NSString *)secretId;

#pragma mark - Message keys

Expand Down
10 changes: 7 additions & 3 deletions MatrixSDK/Crypto/Devices/Data/MXCryptoDeviceWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,13 @@ import MatrixSDKCrypto
deviceId = device.deviceId
algorithms = device.algorithms
keys = device.keys
unsignedData = [
"device_display_name": device.displayName as Any
]
if let displayName = device.displayName {
unsignedData = [
"device_display_name": displayName
]
} else {
unsignedData = [:]
}

let status: MXDeviceVerification
if device.isBlocked {
Expand Down
Loading

0 comments on commit 4dc8446

Please sign in to comment.