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

MXCrypto: Move decryptions out of the main thread #1091

Merged
merged 35 commits into from
May 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
c1fd75c
MXEventDecryptionResult: Add an error property
manuroe May 5, 2021
75f5aa8
MXEventTimeline: Have a dedicated method to ensure roomId in MXEvent
manuroe May 5, 2021
0cd77a9
MXSession/MXCrypto: Add decryptEvents to decrypt by batch asynchronously
manuroe May 10, 2021
38df17f
MXSession: Decrypt event asynchronously during sync response handling
manuroe May 10, 2021
e3b6c91
MXEventTimeline: paginate: decrypt events asynchronously
manuroe May 10, 2021
3938d43
MXCrypto: Change signature of decryptEvents(): Not all events have ev…
manuroe May 11, 2021
f5e09cd
MXSession: decryptEvents: Decrypt only encrypted events
manuroe May 11, 2021
8c2479a
MXSession: handleSyncResponse: Decrypt asynchronously to_device events
manuroe May 11, 2021
44ec72d
MXRoomSummary: Remove noisy logs
manuroe May 11, 2021
fbde49c
MXEvent: editedEventFromReplacementEvent: Use decrypted replacing eve…
manuroe May 12, 2021
7668262
MXEvent: eventWithNewReferenceRelation: Reuse already decrypted data
manuroe May 12, 2021
142554c
MXAggregations: referenceEventsForEvent: Do not decrypt on the main t…
manuroe May 12, 2021
3ddfacb
Tests: Use everywhere the new way to reinject room key to_device event
manuroe May 12, 2021
7540bd5
MXSession: eventWithEventId: Decrypt the event if needed.
manuroe May 12, 2021
e6d5f2d
Tests: Remove all synchronous decryptions
manuroe May 12, 2021
3ef3d87
MXAggregatedEditsUpdater: Do not need to decrypt the event. It has be…
manuroe May 12, 2021
b0352f2
MXRoomSummary: Reimplement fetchLastMessage
manuroe May 12, 2021
ba2f1b5
MXRoomSummaryTests: Fixed testLateRoomKey that did reset all decrypti…
manuroe May 12, 2021
f9e5d9d
MXRoomSummaryTests: Add some delays to fix tests :/
manuroe May 12, 2021
ee740cd
MXRoomSummary: Do not decrypt synchronously lastMessageEvent anymore
manuroe May 14, 2021
15b0f71
Asynchronous decryption: Polishing before PR review
manuroe May 14, 2021
2a87567
oops
manuroe May 14, 2021
949389a
MXCrypto: Make sure we get algorithm from the wire JSON content
manuroe May 19, 2021
e6e7b2c
MXRoomSummary: Implement fetchLastMessage in another way
manuroe May 19, 2021
4534cff
MXRoomSummary: Fix crash in loadLastEvent
manuroe May 19, 2021
000e144
MXRoom: MXRoom.outgoingMessages does not decrypt messages anymore
manuroe May 19, 2021
2275162
MXCrypto: Deprecate [MXSession decryptEvent:inTimeline:] and [MXCryp…
manuroe May 19, 2021
fa92f6b
XCrypto: [MXCrypto hasKeysToDecryptEvent:] is now asynchronous.
manuroe May 19, 2021
7c23242
MXCrypto: eventDeviceInfo: Do not synchronise the operation anymore w…
manuroe May 19, 2021
aa775ff
MXEventTimeline: Fix regression on paginate:
manuroe May 19, 2021
873158b
MXCrossSigning: Fix a race condition in refreshStateWithSuccess
manuroe May 19, 2021
af236fe
Update MatrixSDK/Data/MXEventTimeline.m
manuroe May 20, 2021
b95906a
Update MatrixSDK/Data/MXEventTimeline.m
manuroe May 20, 2021
6e58796
MXEventTimeline: Fix review comments
manuroe May 20, 2021
d8ed7e2
Merge pull request #1095 from matrix-org/manu/async_decryption2
manuroe May 20, 2021
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
12 changes: 10 additions & 2 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,20 @@ Changes to be released in next version
🙌 Improvements
* MXSession: Cache initial sync response until it is fully handled (vector-im/element-ios/issues/4317).
* MXStore: New commit method accepting a completion block.
* MXCrypto: Decrypt events asynchronously and no more on the main thread )(vector-im/element-ios/issues/4306).
* MXSession: Add the decryptEvents method to decypt a bunch of events asynchronously.
* MXSession: Make the eventWithEventId method decrypt the event if needed.
* MXEventTimeline: Add NSCopying implementation so that another pagination can be done on the same set of data.
* MXCrypto: eventDeviceInfo: Do not synchronise anymore the operation with the decryption queue.

🐛 Bugfix
*
* MXRoomSummary: Fix decryption of the last message when it is edited (vector-im/element-ios/issues/4322).

⚠️ API Changes
*
* MXRoom: MXRoom.outgoingMessages does not decrypt messages anymore. Use MXSession.decryptEvents to get decrypted events.
* MXSession: [MXSession decryptEvent:inTimeline:] is deprecated, use [MXSession decryptEvents:inTimeline:onComplete:] instead.
* MXCrypto: [MXCrypto decryptEvent:inTimeline:] is deprecated, use [MXCrypto decryptEvents:inTimeline:onComplete:] instead.
* MXCrypto: [MXCrypto hasKeysToDecryptEvent:] is now asynchronous.

🗣 Translations
*
Expand Down
18 changes: 0 additions & 18 deletions MatrixSDK/Aggregations/MXAggregatedEditsUpdater.m
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,6 @@ - (MXHTTPOperation*)replaceTextMessageEvent:(MXEvent*)event
failure(nil);
return nil;
}

// If it is not already done, decrypt the event to build the new content
if (event.isEncrypted && !event.clearEvent)
{
if (![self.mxSession decryptEvent:event inTimeline:nil])
{
NSLog(@"[MXAggregations] replaceTextMessageEvent: Fail to decrypt original event: %@", event.eventId);
failure(nil);
return nil;
}
}

NSString *messageType = event.content[@"msgtype"];

Expand Down Expand Up @@ -243,13 +232,6 @@ - (void)handleReplace:(MXEvent *)replaceEvent
if (editedEvent)
{
[self.matrixStore replaceEvent:editedEvent inRoom:roomId];

if (editedEvent.isEncrypted && !editedEvent.clearEvent)
{
[self.mxSession decryptEvent:editedEvent inTimeline:nil];
}


[self notifyEventEditsListenersOfRoom:roomId replaceEvent:replaceEvent];
}
}
Expand Down
5 changes: 0 additions & 5 deletions MatrixSDK/Aggregations/MXAggregatedReferencesUpdater.m
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,6 @@ - (void)handleReference:(MXEvent *)referenceEvent
{
[self.matrixStore replaceEvent:newEvent inRoom:roomId];

if (newEvent.isEncrypted && !newEvent.clearEvent)
{
[self.mxSession decryptEvent:newEvent inTimeline:nil];
}

// TODO or not?
//[self notifyEventEditsListenersOfRoom:roomId replaceEvent:replaceEvent];
}
Expand Down
14 changes: 12 additions & 2 deletions MatrixSDK/Aggregations/MXAggregations.m
Original file line number Diff line number Diff line change
Expand Up @@ -158,15 +158,25 @@ - (MXHTTPOperation*)referenceEventsForEvent:(NSString*)eventId
}
}

NSMutableArray *eventsToDecrypt = [NSMutableArray array];
for (MXEvent *event in allEvents)
{
if (event.isEncrypted && !event.clearEvent)
{
[self.mxSession decryptEvent:event inTimeline:nil];
[eventsToDecrypt addObject:event];
}
}

success(paginatedResponse);
if (eventsToDecrypt.count)
{
[self.mxSession decryptEvents:eventsToDecrypt inTimeline:nil onComplete:^(NSArray<MXEvent *> *failedEvents) {
success(paginatedResponse);
}];
}
else
{
success(paginatedResponse);
}
};

MXEvent *event = [self.mxSession.store eventWithEventId:eventId inRoom:roomId];
Expand Down
10 changes: 3 additions & 7 deletions MatrixSDK/Crypto/Algorithms/MXDecrypting.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,13 @@
/**
Decrypt a message.

In case of success, the event is updated with clear data.
In case of failure, event.decryptionError contains the error.

@param event the raw event.
@param timeline the id of the timeline where the event is decrypted. It is used
to prevent replay attack.
@param error the result error if there is a problem decrypting the event.
to prevent replay attack. Can be nil.

@return The decryption result. Nil if it failed.
@return The decryption result.
*/
- (MXEventDecryptionResult *)decryptEvent:(MXEvent*)event inTimeline:(NSString*)timeline error:(NSError** )error;
- (MXEventDecryptionResult *)decryptEvent:(MXEvent*)event inTimeline:(NSString*)timeline;

/**
* Handle a key event.
Expand Down
6 changes: 6 additions & 0 deletions MatrixSDK/Crypto/Algorithms/MXEventDecryptionResult.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
Copyright 2017 Vector Creations Ltd
Copyright 2021 The Matrix.org Foundation C.I.C

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -44,4 +45,9 @@
*/
@property NSArray<NSString *> *forwardingCurve25519KeyChain;

/**
If any, the error that occured during decryption.
*/
@property (nonatomic) NSError *error;

@end
56 changes: 23 additions & 33 deletions MatrixSDK/Crypto/Algorithms/Megolm/MXMegolmDecryption.m
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ - (BOOL)hasKeysToDecryptEvent:(MXEvent *)event

NSString *senderKey, *sessionId;

MXJSONModelSetString(senderKey, event.content[@"sender_key"]);
MXJSONModelSetString(sessionId, event.content[@"session_id"]);
MXJSONModelSetString(senderKey, event.wireContent[@"sender_key"]);
MXJSONModelSetString(sessionId, event.wireContent[@"session_id"]);
if (senderKey && sessionId)
{
hasKeys = ([crypto.store inboundGroupSessionWithId:sessionId andSenderKey:senderKey] != nil);
Expand All @@ -78,35 +78,32 @@ - (BOOL)hasKeysToDecryptEvent:(MXEvent *)event
return hasKeys;
}

- (MXEventDecryptionResult *)decryptEvent:(MXEvent*)event inTimeline:(NSString*)timeline error:(NSError** )error;
- (MXEventDecryptionResult *)decryptEvent:(MXEvent*)event inTimeline:(NSString*)timeline
{
MXEventDecryptionResult *result;
NSString *senderKey, *ciphertext, *sessionId;

MXJSONModelSetString(senderKey, event.content[@"sender_key"]);
MXJSONModelSetString(ciphertext, event.content[@"ciphertext"]);
MXJSONModelSetString(sessionId, event.content[@"session_id"]);
MXJSONModelSetString(senderKey, event.wireContent[@"sender_key"]);
MXJSONModelSetString(ciphertext, event.wireContent[@"ciphertext"]);
MXJSONModelSetString(sessionId, event.wireContent[@"session_id"]);

if (!senderKey || !sessionId || !ciphertext)
{
if (error)
{
*error = [NSError errorWithDomain:MXDecryptingErrorDomain
result = [MXEventDecryptionResult new];
result.error = [NSError errorWithDomain:MXDecryptingErrorDomain
code:MXDecryptingErrorMissingFieldsCode
userInfo:@{
NSLocalizedDescriptionKey: MXDecryptingErrorMissingFieldsReason
}];
}
return nil;
return result;
}

NSError *olmError;
MXDecryptionResult *olmResult = [olmDevice decryptGroupMessage:ciphertext roomId:event.roomId inTimeline:timeline sessionId:sessionId senderKey:senderKey error:&olmError];

result = [MXEventDecryptionResult new];
if (olmResult)
{
result = [[MXEventDecryptionResult alloc] init];

result.clearEvent = olmResult.payload;
result.senderCurve25519Key = olmResult.senderKey;
result.claimedEd25519Key = olmResult.keysClaimed[@"ed25519"];
Expand Down Expand Up @@ -141,10 +138,7 @@ - (MXEventDecryptionResult *)decryptEvent:(MXEvent*)event inTimeline:(NSString*)
});
}

if (error)
{
*error = olmError;
}
result.error = olmError;
}

return result;
Expand Down Expand Up @@ -400,29 +394,25 @@ - (void)retryDecryption:(NSString*)senderKey sessionId:(NSString*)sessionId comp
else
{
// Decrypt on the current thread (Must be MXCrypto.cryptoQueue)
NSError *error;
MXEventDecryptionResult *result = [self decryptEvent:event inTimeline:(timelineId.length ? timelineId : nil) error:&error];
MXEventDecryptionResult *result = [self decryptEvent:event inTimeline:(timelineId.length ? timelineId : nil)];

// And set the result on the main thread to be compatible with other modules
dispatch_group_enter(group);
dispatch_async(dispatch_get_main_queue(), ^{
if (result)
if (result.error)
{
if (event.clearEvent)
{
// This can happen when the event is in several timelines
NSLog(@"[MXMegolmDecryption] retryDecryption: %@ already decrypted on main thread", event.eventId);
}
else
{
[event setClearData:result];
}
NSLog(@"[MXMegolmDecryption] retryDecryption: Still can't decrypt %@. Error: %@", event.eventId, result.error);
allDecrypted = NO;
}
else if (error)

if (event.clearEvent)
{
NSLog(@"[MXMegolmDecryption] retryDecryption: Still can't decrypt %@. Error: %@", event.eventId, event.decryptionError);
event.decryptionError = error;
allDecrypted = NO;
// This can happen when the event is in several timelines
NSLog(@"[MXMegolmDecryption] retryDecryption: %@ already decrypted on main thread", event.eventId);
}
else
{
[event setClearData:result];
}

dispatch_group_leave(group);
Expand Down
Loading