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

Handle m.forwarded_room_key events #404

Merged
merged 4 commits into from
Nov 7, 2017
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
10 changes: 7 additions & 3 deletions MatrixSDK/Crypto/Algorithms/MXDecryptionResult.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,13 @@ FOUNDATION_EXPORT NSString* const MXDecryptingErrorMissingPropertyReason;
@property (nonatomic) NSDictionary *keysClaimed;

/**
The keys that the sender of the event is known to have ownership of:
map from key type to base64-encoded key.
The curve25519 key that the sender of the event is known to have ownership of.
*/
@property (nonatomic) NSString *senderKey;

/**
Devices which forwarded this session to us (normally empty).
*/
@property (nonatomic) NSDictionary *keysProved;
@property NSArray<NSString *> *forwardingCurve25519KeyChain;

@end
2 changes: 1 addition & 1 deletion MatrixSDK/Crypto/Algorithms/MXDecryptionResult.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
NSString* const MXDecryptingErrorUnableToDecryptReason = @"Unable to decrypt %@. Algoritm: %@";
NSString* const MXDecryptingErrorOlm = @"Error: OLM.%@";
NSString* const MXDecryptingErrorOlmReason = @"Unable to decrypt %@. OLM error: %@";
NSString* const MXDecryptingErrorUnknownInboundSessionIdReason = @"Unknown inbound session id";
NSString* const MXDecryptingErrorUnknownInboundSessionIdReason = @"Unknown inbound session id";
NSString* const MXDecryptingErrorInboundSessionMismatchRoomIdReason = @"Mismatched room_id for inbound group session (expected %@, was %@)";
NSString* const MXDecryptingErrorMissingFieldsReason = @"Missing fields in input";
NSString* const MXDecryptingErrorMissingCiphertextReason = @"Missing ciphertext";
Expand Down
73 changes: 62 additions & 11 deletions MatrixSDK/Crypto/Algorithms/Megolm/MXMegolmDecryption.m
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ - (BOOL)decryptEvent:(MXEvent *)event inTimeline:(NSString*)timeline
if (result)
{
MXEvent *clearedEvent = [MXEvent modelFromJSON:result.payload];
[event setClearData:clearedEvent keysProved:result.keysProved keysClaimed:result.keysClaimed];
[event setClearData:clearedEvent senderCurve25519Key:result.senderKey claimedEd25519Key:result.keysClaimed[@"ed25519"] forwardingCurve25519KeyChain:result.forwardingCurve25519KeyChain];
}
else
{
Expand Down Expand Up @@ -151,31 +151,82 @@ - (void)addEventToPendingList:(MXEvent*)event inTimeline:(NSString*)timelineId

- (void)onRoomKeyEvent:(MXEvent *)event
{
NSLog(@"[MXMegolmDecryption] onRoomKeyEvent: Adding key from %@", event.JSONDictionary);

NSDictionary *content = event.content;
NSString *roomId, *sessionId, *sessionKey;

MXJSONModelSetString(roomId, event.content[@"room_id"]);
MXJSONModelSetString(sessionId, event.content[@"session_id"]);
MXJSONModelSetString(sessionKey, event.content[@"session_key"]);
MXJSONModelSetString(roomId, content[@"room_id"]);
MXJSONModelSetString(sessionId, content[@"session_id"]);
MXJSONModelSetString(sessionKey, content[@"session_key"]);

if (!roomId || !sessionId || !sessionKey)
{
NSLog(@"[MXMegolmDecryption] onRoomKeyEvent: ERROR: Key event is missing fields");
return;
}

[olmDevice addInboundGroupSession:sessionId sessionKey:sessionKey roomId:roomId senderKey:event.senderKey keysClaimed:event.keysClaimed];
NSString *senderKey = event.senderKey;
if (!senderKey)
{
NSLog(@"[MXMegolmDecryption] onRoomKeyEvent: ERROR: Key event has no sender key (not encrypted?)");
return;
}

NSArray<NSString*> *forwardingKeyChain;
BOOL exportFormat = NO;
NSDictionary *keysClaimed;

if (event.eventType == MXEventTypeRoomForwardedKey)
{
exportFormat = YES;

MXJSONModelSetArray(forwardingKeyChain, content[@"forwarding_curve25519_key_chain"]);
if (!forwardingKeyChain)
{
forwardingKeyChain = @[];
}

// copy content before we modify it
NSMutableArray *forwardingKeyChain2 = [NSMutableArray arrayWithArray:forwardingKeyChain];
[forwardingKeyChain2 addObject:senderKey];
forwardingKeyChain = forwardingKeyChain2;

MXJSONModelSetString(senderKey, content[@"sender_key"]);
if (!senderKey)
{
NSLog(@"[MXMegolmDecryption] onRoomKeyEvent: ERROR: forwarded_room_key event is missing sender_key field");
return;
}

NSString *ed25519Key;
MXJSONModelSetString(ed25519Key, content[@"sender_claimed_ed25519_key"]);
if (!ed25519Key)
{
NSLog(@"[MXMegolmDecryption] onRoomKeyEvent: ERROR: forwarded_room_key_event is missing sender_claimed_ed25519_key field");
return;
}

keysClaimed = @{
@"ed25519": ed25519Key
};
}
else
{
keysClaimed = event.keysClaimed;
}

NSLog(@"[MXMegolmDecryption] onRoomKeyEvent: Adding key from %@", event.JSONDictionary);

[olmDevice addInboundGroupSession:sessionId sessionKey:sessionKey roomId:roomId senderKey:senderKey forwardingCurve25519KeyChain:forwardingKeyChain keysClaimed:keysClaimed exportFormat:exportFormat];

// cancel any outstanding room key requests for this session
[crypto cancelRoomKeyRequest:@{
@"algorithm": event.content[@"algorithm"],
@"room_id": event.content[@"room_id"],
@"session_id": event.content[@"session_id"],
@"algorithm": content[@"algorithm"],
@"room_id": content[@"room_id"],
@"session_id": content[@"session_id"],
@"sender_key": event.senderKey
}];

[self retryDecryption:event.senderKey sessionId:event.content[@"session_id"]];
[self retryDecryption:event.senderKey sessionId:content[@"session_id"]];
}

- (void)importRoomKey:(MXMegolmSessionData *)session
Expand Down
5 changes: 4 additions & 1 deletion MatrixSDK/Crypto/Algorithms/Megolm/MXMegolmEncryption.m
Original file line number Diff line number Diff line change
Expand Up @@ -332,9 +332,12 @@ - (MXOutboundSessionInfo*)prepareNewSession
sessionKey:[crypto.olmDevice sessionKeyForOutboundGroupSession:sessionId]
roomId:roomId
senderKey:crypto.olmDevice.deviceCurve25519Key
forwardingCurve25519KeyChain:@[]
keysClaimed:@{
@"ed25519": crypto.olmDevice.deviceEd25519Key
}];
}
exportFormat:NO
];

return [[MXOutboundSessionInfo alloc] initWithSessionID:sessionId];
}
Expand Down
16 changes: 8 additions & 8 deletions MatrixSDK/Crypto/Algorithms/Olm/MXOlmDecryption.m
Original file line number Diff line number Diff line change
Expand Up @@ -194,23 +194,23 @@ - (BOOL)decryptEvent:(MXEvent *)event inTimeline:(NSString*)timeline

MXEvent *clearedEvent = [MXEvent modelFromJSON:payload];

NSDictionary *claimedKeys = payload[@"keys"];

// @TODO: We should always be on the crypto queue
if ([NSThread currentThread].isMainThread)
{
[event setClearData:clearedEvent
keysProved:@{
@"curve25519": deviceKey
}
keysClaimed:payload[@"keys"]];
senderCurve25519Key:deviceKey
claimedEd25519Key:claimedKeys[@"ed25519"]
forwardingCurve25519KeyChain:nil];
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
[event setClearData:clearedEvent
keysProved:@{
@"curve25519": deviceKey
}
keysClaimed:payload[@"keys"]];
senderCurve25519Key:deviceKey
claimedEd25519Key:claimedKeys[@"ed25519"]
forwardingCurve25519KeyChain:nil];
});
}

Expand Down
5 changes: 5 additions & 0 deletions MatrixSDK/Crypto/Data/MXMegolmSessionData.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
*/
@property NSString *senderKey;

/**
Devices which forwarded this session to us (normally empty).
*/
@property NSArray<NSString *> *forwardingCurve25519KeyChain;

/**
Other keys the sender claims.
*/
Expand Down
4 changes: 3 additions & 1 deletion MatrixSDK/Crypto/Data/MXMegolmSessionData.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ + (id)modelFromJSON:(NSDictionary *)JSONDictionary
MXJSONModelSetString(sessionData.sessionId, JSONDictionary[@"session_id"]);
MXJSONModelSetString(sessionData.sessionKey, JSONDictionary[@"session_key"]);
MXJSONModelSetString(sessionData.algorithm, JSONDictionary[@"algorithm"]);
MXJSONModelSetArray(sessionData.forwardingCurve25519KeyChain, JSONDictionary[@"forwarding_curve25519_key_chain"])
}

return sessionData;
Expand All @@ -42,7 +43,8 @@ - (NSDictionary *)JSONDictionary
@"room_id": _roomId,
@"session_id": _sessionId,
@"session_key":_sessionKey,
@"algorithm": _algorithm
@"algorithm": _algorithm,
@"forwarding_curve25519_key_chain": _forwardingCurve25519KeyChain ? _forwardingCurve25519KeyChain : @[]
};
}

Expand Down
8 changes: 7 additions & 1 deletion MatrixSDK/Crypto/Data/MXOlmInboundGroupSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@
*/
@property (nonatomic) NSString *senderKey;

/**
Devices which forwarded this session to us.
*/
@property NSArray<NSString *> *forwardingCurve25519KeyChain;

/**
Other keys the sender claims.
*/
Expand All @@ -79,7 +84,8 @@
*/
- (MXMegolmSessionData *)exportSessionData;

- (instancetype)initWithSessionData:(MXMegolmSessionData*)data;
- (instancetype)initWithImportedSessionData:(MXMegolmSessionData*)data;
- (instancetype)initWithImportedSessionKey:(NSString*)sessionKey;

@end

Expand Down
21 changes: 17 additions & 4 deletions MatrixSDK/Crypto/Data/MXOlmInboundGroupSession.m
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ - (MXMegolmSessionData *)exportSessionDataAtMessageIndex:(NSUInteger)messageInde
sessionData = [[MXMegolmSessionData alloc] init];

sessionData.senderKey = _senderKey;
sessionData.forwardingCurve25519KeyChain = _forwardingCurve25519KeyChain;
sessionData.senderClaimedKeys = _keysClaimed;
sessionData.roomId = _roomId;
sessionData.sessionId = _session.sessionIdentifier;
Expand All @@ -69,22 +70,32 @@ - (MXMegolmSessionData *)exportSessionData
return [self exportSessionDataAtMessageIndex:_session.firstKnownIndex];
}

- (instancetype)initWithSessionData:(MXMegolmSessionData *)data
- (instancetype)initWithImportedSessionKey:(NSString *)sessionKey
{
self = [self init];
if (self)
{
NSError *error;
_session = [[OLMInboundGroupSession alloc] initInboundGroupSessionWithImportedSession:data.sessionKey error:&error];
_session = [[OLMInboundGroupSession alloc] initInboundGroupSessionWithImportedSession:sessionKey error:&error];
if (!_session)
{
NSLog(@"[MXOlmInboundGroupSession] initWithSessionData failed. Error: %@", error);
NSLog(@"[MXOlmInboundGroupSession] initWithImportedSessionKey failed. Error: %@", error);
return nil;
}
}

return self;
}

- (instancetype)initWithImportedSessionData:(MXMegolmSessionData *)data
{
self = [self initWithImportedSessionKey:data.sessionKey];
if (self)
{
_senderKey = data.senderKey;
_forwardingCurve25519KeyChain = data.forwardingCurve25519KeyChain;
_keysClaimed = data.senderClaimedKeys;
_roomId= data.roomId;
_roomId = data.roomId;
}
return self;
}
Expand All @@ -99,6 +110,7 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder
_session = [aDecoder decodeObjectForKey:@"session"];
_roomId = [aDecoder decodeObjectForKey:@"roomId"];
_senderKey = [aDecoder decodeObjectForKey:@"senderKey"];
_forwardingCurve25519KeyChain = [aDecoder decodeObjectForKey:@"forwardingCurve25519KeyChain"];
_keysClaimed = [aDecoder decodeObjectForKey:@"keysClaimed"];
}
return self;
Expand All @@ -110,6 +122,7 @@ - (void)encodeWithCoder:(NSCoder *)aCoder
[aCoder encodeObject:_roomId forKey:@"roomId"];
[aCoder encodeObject:_senderKey forKey:@"senderKey"];
[aCoder encodeObject:_keysClaimed forKey:@"keysClaimed"];
[aCoder encodeObject:_forwardingCurve25519KeyChain forKey:@"forwardingCurve25519KeyChain"];
}

@end
Expand Down
9 changes: 9 additions & 0 deletions MatrixSDK/Crypto/MXCrypto.m
Original file line number Diff line number Diff line change
Expand Up @@ -1172,6 +1172,14 @@ - (MXDeviceInfo *)eventSenderDeviceOfEvent:(MXEvent *)event
return nil;
}

NSArray *forwardingChain = event.forwardingCurve25519KeyChain;
if (forwardingChain.count > 0)
{
// we got this event from somewhere else
// TODO: check if we can trust the forwarders.
return nil;
}

// senderKey is the Curve25519 identity key of the device which the event
// was sent from. In the case of Megolm, it's actually the Curve25519
// identity key of the device which set up the Megolm session.
Expand Down Expand Up @@ -1724,6 +1732,7 @@ - (void)onToDeviceEvent:(NSNotification *)notification
switch (event.eventType)
{
case MXEventTypeRoomKey:
case MXEventTypeRoomForwardedKey:
{
// Room key is used for decryption. Switch to the associated queue
dispatch_async(_decryptionQueue, ^{
Expand Down
7 changes: 6 additions & 1 deletion MatrixSDK/Crypto/MXOlmDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,13 +216,18 @@ Determine if an incoming messages is a prekey message matching an existing sessi
@param sessionKey base64-encoded secret key.
@param roomId the id of the room in which this session will be used.
@param senderKey the base64-encoded curve25519 key of the sender.
@param forwardingCurve25519KeyChain devices which forwarded this session to us (normally empty)
@param keysClaimed Other keys the sender claims.
@param exportFormat YES if the megolm keys are in export format (ie, they lack an ed25519 signature).

@return YES if the operation succeeds.
*/
- (BOOL)addInboundGroupSession:(NSString*)sessionId sessionKey:(NSString*)sessionKey
roomId:(NSString*)roomId
senderKey:(NSString*)senderKey keysClaimed:(NSDictionary<NSString*, NSString*>*)keysClaimed;
senderKey:(NSString*)senderKey
forwardingCurve25519KeyChain:(NSArray<NSString *> *)forwardingCurve25519KeyChain
keysClaimed:(NSDictionary<NSString*, NSString*>*)keysClaimed
exportFormat:(BOOL)exportFormat;

/**
Add a previously-exported inbound group session to the session store.
Expand Down
Loading