Skip to content
This repository has been archived by the owner on Apr 12, 2022. It is now read-only.

Commit

Permalink
add_room_key_request
Browse files Browse the repository at this point in the history
  • Loading branch information
ylecollen committed Oct 25, 2017
1 parent c9926de commit fb24b5d
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package org.matrix.androidsdk.crypto;

import android.text.TextUtils;
import android.util.Pair;

import org.matrix.androidsdk.util.Log;

import com.google.gson.JsonParser;
Expand Down Expand Up @@ -775,4 +777,38 @@ private MXOlmInboundGroupSession2 getInboundGroupSession(String sessionId, Strin
}
return session;
}

/**
* Determine if we have the keys for a given megolm session.
*
* @param roomId room in which the message was received
* @param senderKey base64-encoded curve25519 key of the sender
* @param sessionId session identifier
* @return
*/
public boolean hasInboundSessionKeys(String roomId, String senderKey, String sessionId) {
return null != getInboundGroupSession(sessionId, senderKey, roomId);
}


/**
* Extract the keys to a given megolm session, for sharing
* @param roomId room in which the message was received
* @param senderKey Base64-encoded curve25519 key of the sender
* @param sessionId session identifier
* @return a Pair<chain_index, key is a base64-encoded megolm key in export format>
*/
public Pair<Long, String> getInboundGroupSessionKey(String roomId, String senderKey, String sessionId) {
MXOlmInboundGroupSession2 session = getInboundGroupSession(sessionId, senderKey, roomId);

if (null != session) {
Long index = session.getFirstKnownIndex();

if (null != index) {
return new Pair<>(index, session.exportSession(index));
}
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,16 @@
package org.matrix.androidsdk.crypto.algorithms.megolm;

import android.text.TextUtils;
import android.util.Pair;

import org.matrix.androidsdk.crypto.IncomingRoomKeyRequest;
import org.matrix.androidsdk.crypto.MXCryptoAlgorithms;
import org.matrix.androidsdk.crypto.data.MXDeviceInfo;
import org.matrix.androidsdk.crypto.data.MXOlmSessionResult;
import org.matrix.androidsdk.crypto.data.MXUsersDevicesMap;
import org.matrix.androidsdk.rest.callback.ApiCallback;
import org.matrix.androidsdk.rest.model.MatrixError;
import org.matrix.androidsdk.rest.model.RoomKeyRequestBody;
import org.matrix.androidsdk.util.Log;

import org.matrix.androidsdk.MXSession;
Expand All @@ -32,14 +40,16 @@
import org.matrix.androidsdk.util.JsonUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MXMegolmDecryption implements IMXDecrypting {
private static final String LOG_TAG = "MXMegolmDecryption";

/**
* The olm device interface
* The olm device interface
*/
private MXOlmDevice mOlmDevice;

Expand All @@ -51,10 +61,11 @@ public class MXMegolmDecryption implements IMXDecrypting {
* senderKey|sessionId to timelines to list of MatrixEvents.
*/
private HashMap<String, /* senderKey|sessionId */
HashMap<String /* timelineId */, ArrayList<Event>>> mPendingEvents;
HashMap<String /* timelineId */, ArrayList<Event>>> mPendingEvents;

/**
* Init the object fields
*
* @param matrixSession the matrix session
*/
@Override
Expand Down Expand Up @@ -120,7 +131,8 @@ public boolean decryptEvent(Event event, String timeline) {
/**
* Add an event to the list of those we couldn't decrypt the first time we
* saw them.
* @param event the event to try to decrypt later
*
* @param event the event to try to decrypt later
* @param timelineId the timeline identifier
*/
private void addEventToPendingList(Event event, String timelineId) {
Expand Down Expand Up @@ -152,6 +164,7 @@ private void addEventToPendingList(Event event, String timelineId) {

/**
* Handle a key event.
*
* @param roomKeyEvent the key event.
*/
@Override
Expand All @@ -176,6 +189,7 @@ public void onRoomKeyEvent(Event roomKeyEvent) {

/**
* Check if the some messages can be decrypted with a new session
*
* @param senderKey the session sender key
* @param sessionId the session id
*/
Expand Down Expand Up @@ -212,11 +226,102 @@ public void run() {
}

@Override
public boolean hasKeysForKeyRequest(IncomingRoomKeyRequest request){
public boolean hasKeysForKeyRequest(IncomingRoomKeyRequest request) {
if ((null != request) && (null != request.mRequestBody)) {
return mOlmDevice.hasInboundSessionKeys(request.mRequestBody.room_id, request.mRequestBody.sender_key, request.mRequestBody.session_id);
}

return false;
}

@Override
public void shareKeysWithDevice(IncomingRoomKeyRequest request) {
public void shareKeysWithDevice(final IncomingRoomKeyRequest request) {
// sanity checks
if ((null == request) || (null == request.mRequestBody)) {
return;
}

final String userId = request.mUserId;
final String deviceId = request.mDeviceId;
final MXDeviceInfo deviceInfo = mSession.getCrypto().mCryptoStore.getUserDevice(deviceId, userId);
final RoomKeyRequestBody body = request.mRequestBody;

HashMap<String, ArrayList<MXDeviceInfo>> devicesByUser = new HashMap<>();
devicesByUser.put(userId, new ArrayList<>(Arrays.asList(deviceInfo)));

mSession.getCrypto().ensureOlmSessionsForDevices(devicesByUser, new ApiCallback<MXUsersDevicesMap<MXOlmSessionResult>>() {
@Override
public void onSuccess(MXUsersDevicesMap<MXOlmSessionResult> map) {
MXOlmSessionResult olmSessionResult = map.getObject(deviceId, userId);

if ((null == olmSessionResult) && (null == olmSessionResult.mSessionId)) {
// no session with this device, probably because there
// were no one-time keys.
//
// ensureOlmSessionsForUsers has already done the logging,
// so just skip it.
return;
}

Log.d(LOG_TAG, "## shareKeysWithDevice() : sharing keys for session " + body.sender_key + "|" + body.session_id + " with device " + userId + ":" + deviceId);

Pair<Long, String> key = mSession.getCrypto().getOlmDevice().getInboundGroupSessionKey(body.room_id, body.sender_key, body.session_id);

Map<String, Object> payloadJson = new HashMap<>();
payloadJson.put("type", Event.EVENT_TYPE_FORWARDED_ROOM_KEY);

Map<String, Object> contentMap = new HashMap<>();
payloadJson.put("content", contentMap);

contentMap.put("algorithm", MXCryptoAlgorithms.MXCRYPTO_ALGORITHM_MEGOLM);
contentMap.put("room_id", body.room_id);
contentMap.put("sender_key", body.sender_key);
contentMap.put("session_id", body.session_id);
contentMap.put("session_key", key.second);
contentMap.put("chain_index", key.first);

Map<String, Object> encodedPayload = mSession.getCrypto().encryptMessage(payloadJson, Arrays.asList(deviceInfo));
MXUsersDevicesMap<Map<String, Object>> sendToDeviceMap = new MXUsersDevicesMap<>();
sendToDeviceMap.setObject(encodedPayload, userId, deviceId);

Log.d(LOG_TAG, "## shareKeysWithDevice() : sending to " + userId + ":" + deviceId);
mSession.getCryptoRestClient().sendToDevice(Event.EVENT_TYPE_MESSAGE_ENCRYPTED, sendToDeviceMap, new ApiCallback<Void>() {
@Override
public void onSuccess(Void info) {
Log.d(LOG_TAG, "## shareKeysWithDevice() : sent to " + userId + ":" + deviceId);
}

@Override
public void onNetworkError(Exception e) {
Log.e(LOG_TAG, "## shareKeysWithDevice() : sendToDevice " + userId + ":" + deviceId + " failed " + e.getMessage());
}

@Override
public void onMatrixError(MatrixError e) {
Log.e(LOG_TAG, "## shareKeysWithDevice() : sendToDevice " + userId + ":" + deviceId + " failed " + e.getMessage());
}

@Override
public void onUnexpectedError(Exception e) {
Log.e(LOG_TAG, "## shareKeysWithDevice() : sendToDevice " + userId + ":" + deviceId + " failed " + e.getMessage());
}
});
}

@Override
public void onNetworkError(Exception e) {
Log.e(LOG_TAG, "## shareKeysWithDevice() : ensureOlmSessionsForDevices " + userId + ":" + deviceId + " failed " + e.getMessage());
}

@Override
public void onMatrixError(MatrixError e) {
Log.e(LOG_TAG, "## shareKeysWithDevice() : ensureOlmSessionsForDevices " + userId + ":" + deviceId + " failed " + e.getMessage());
}

@Override
public void onUnexpectedError(Exception e) {
Log.e(LOG_TAG, "## shareKeysWithDevice() : ensureOlmSessionsForDevices " + userId + ":" + deviceId + " failed " + e.getMessage());
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ public void onSuccess(final MXUsersDevicesMap<MXOlmSessionResult> results) {
@Override
public void run() {
Log.d(LOG_TAG, "## shareUserDevicesKey() : ensureOlmSessionsForDevices succeeds after " + (System.currentTimeMillis() - t0) + " ms");
MXUsersDevicesMap<Map<String, Object>> mContentMap = new MXUsersDevicesMap<>();
MXUsersDevicesMap<Map<String, Object>> contentMap = new MXUsersDevicesMap<>();

boolean haveTargets = false;
List<String> userIds = results.getUserIds();
Expand Down Expand Up @@ -468,7 +468,7 @@ public void run() {

Log.d(LOG_TAG, "## shareUserDevicesKey() : Sharing keys with device " + userId + ":" + deviceID);
//noinspection ArraysAsListWithZeroOrOneArgument,ArraysAsListWithZeroOrOneArgument
mContentMap.setObject(mCrypto.encryptMessage(payload, Arrays.asList(sessionResult.mDevice)), userId, deviceID);
contentMap.setObject(mCrypto.encryptMessage(payload, Arrays.asList(sessionResult.mDevice)), userId, deviceID);
haveTargets = true;
}
}
Expand All @@ -477,7 +477,7 @@ public void run() {
final long t0 = System.currentTimeMillis();
Log.d(LOG_TAG, "## shareUserDevicesKey() : has target");

mSession.getCryptoRestClient().sendToDevice(Event.EVENT_TYPE_MESSAGE_ENCRYPTED, mContentMap, new ApiCallback<Void>() {
mSession.getCryptoRestClient().sendToDevice(Event.EVENT_TYPE_MESSAGE_ENCRYPTED, contentMap, new ApiCallback<Void>() {
@Override
public void onSuccess(Void info) {
mCrypto.getEncryptingThreadHandler().post(new Runnable() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import android.text.TextUtils;

import org.matrix.androidsdk.crypto.MXCryptoAlgorithms;
import org.matrix.androidsdk.rest.model.Event;
import org.matrix.androidsdk.util.Log;

import org.matrix.olm.OlmInboundGroupSession;
Expand Down Expand Up @@ -116,4 +117,36 @@ public Map<String, Object> exportKeys() {

return map;
}

/**
* @return the first known message index
*/
public Long getFirstKnownIndex() {
if (null != mSession) {
try {
return mSession.getFirstKnownIndex();
} catch (Exception e) {
Log.e(LOG_TAG, "## getFirstKnownIndex() : getFirstKnownIndex failed " + e.getMessage());
}
}

return null;
}

/**
* Export the session for a message index.
* @param messageIndex the message index
* @return the exported data
*/
public String exportSession(long messageIndex) {
if (null != mSession) {
try {
return mSession.export(messageIndex);
} catch (Exception e) {
Log.e(LOG_TAG, "## exportSession() : export failed " + e.getMessage());
}
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public enum SentState {
public static final String EVENT_TYPE_ROOM_PLUMBING = "m.room.plumbing";
public static final String EVENT_TYPE_ROOM_BOT_OPTIONS = "m.room.bot.options";
public static final String EVENT_TYPE_ROOM_KEY_REQUEST = "m.room_key_request";
public static final String EVENT_TYPE_FORWARDED_ROOM_KEY = "m.forwarded_room_key";

// State events
public static final String EVENT_TYPE_STATE_ROOM_NAME = "m.room.name";
Expand Down

0 comments on commit fb24b5d

Please sign in to comment.