use of org.matrix.androidsdk.crypto.algorithms.IMXDecrypting in project matrix-android-sdk by matrix-org.
the class MXCrypto method processReceivedRoomKeyRequests.
/**
* Process any m.room_key_request events which were queued up during the
* current sync.
*/
private void processReceivedRoomKeyRequests() {
List<IncomingRoomKeyRequest> receivedRoomKeyRequests = null;
synchronized (mReceivedRoomKeyRequests) {
if (!mReceivedRoomKeyRequests.isEmpty()) {
receivedRoomKeyRequests = new ArrayList(mReceivedRoomKeyRequests);
mReceivedRoomKeyRequests.clear();
}
}
if (null != receivedRoomKeyRequests) {
for (final IncomingRoomKeyRequest request : receivedRoomKeyRequests) {
String userId = request.mUserId;
String deviceId = request.mDeviceId;
RoomKeyRequestBody body = request.mRequestBody;
String roomId = body.room_id;
String alg = body.algorithm;
Log.d(LOG_TAG, "m.room_key_request from " + userId + ":" + deviceId + " for " + roomId + " / " + body.session_id + " id " + request.mRequestId);
if (!TextUtils.equals(mSession.getMyUserId(), userId)) {
// TODO: determine if we sent this device the keys already: in
Log.e(LOG_TAG, "## processReceivedRoomKeyRequests() : Ignoring room key request from other user for now");
return;
}
// todo: should we queue up requests we don't yet have keys for,
// in case they turn up later?
// if we don't have a decryptor for this room/alg, we don't have
// the keys for the requested events, and can drop the requests.
final IMXDecrypting decryptor = getRoomDecryptor(roomId, alg);
if (null == decryptor) {
Log.e(LOG_TAG, "## processReceivedRoomKeyRequests() : room key request for unknown " + alg + " in room " + roomId);
continue;
}
if (!decryptor.hasKeysForKeyRequest(request)) {
Log.e(LOG_TAG, "## processReceivedRoomKeyRequests() : room key request for unknown session " + body.session_id);
mCryptoStore.deleteIncomingRoomKeyRequest(request);
continue;
}
if (TextUtils.equals(deviceId, getMyDevice().deviceId) && TextUtils.equals(mSession.getMyUserId(), userId)) {
Log.d(LOG_TAG, "## processReceivedRoomKeyRequests() : oneself device - ignored");
mCryptoStore.deleteIncomingRoomKeyRequest(request);
continue;
}
request.mShare = new Runnable() {
@Override
public void run() {
getEncryptingThreadHandler().post(new Runnable() {
@Override
public void run() {
decryptor.shareKeysWithDevice(request);
mCryptoStore.deleteIncomingRoomKeyRequest(request);
}
});
}
};
// if the device is is verified already, share the keys
MXDeviceInfo device = mCryptoStore.getUserDevice(deviceId, userId);
if (null != device) {
if (device.isVerified()) {
Log.d(LOG_TAG, "## processReceivedRoomKeyRequests() : device is already verified: sharing keys");
mCryptoStore.deleteIncomingRoomKeyRequest(request);
request.mShare.run();
continue;
}
if (device.isBlocked()) {
Log.d(LOG_TAG, "## processReceivedRoomKeyRequests() : device is blocked -> ignored");
mCryptoStore.deleteIncomingRoomKeyRequest(request);
continue;
}
}
mCryptoStore.storeIncomingRoomKeyRequest(request);
onRoomKeyRequest(request);
}
}
List<IncomingRoomKeyRequestCancellation> receivedRoomKeyRequestCancellations = null;
synchronized (mReceivedRoomKeyRequestCancellations) {
if (!mReceivedRoomKeyRequestCancellations.isEmpty()) {
receivedRoomKeyRequestCancellations = new ArrayList(mReceivedRoomKeyRequestCancellations);
mReceivedRoomKeyRequestCancellations.clear();
}
}
if (null != receivedRoomKeyRequestCancellations) {
for (IncomingRoomKeyRequestCancellation request : receivedRoomKeyRequestCancellations) {
Log.d(LOG_TAG, "## ## processReceivedRoomKeyRequests() : m.room_key_request cancellation for " + request.mUserId + ":" + request.mDeviceId + " id " + request.mRequestId);
// we should probably only notify the app of cancellations we told it
// about, but we don't currently have a record of that, so we just pass
// everything through.
onRoomKeyRequestCancellation(request);
mCryptoStore.deleteIncomingRoomKeyRequest(request);
}
}
}
use of org.matrix.androidsdk.crypto.algorithms.IMXDecrypting in project matrix-android-sdk by matrix-org.
the class MXCrypto method getRoomDecryptor.
/**
* Get a decryptor for a given room and algorithm.
* If we already have a decryptor for the given room and algorithm, return
* it. Otherwise try to instantiate it.
*
* @param roomId the room id
* @param algorithm the crypto algorithm
* @return the decryptor
*/
private IMXDecrypting getRoomDecryptor(String roomId, String algorithm) {
// sanity check
if (TextUtils.isEmpty(algorithm)) {
Log.e(LOG_TAG, "## getRoomDecryptor() : null algorithm");
return null;
}
if (null == mRoomDecryptors) {
Log.e(LOG_TAG, "## getRoomDecryptor() : null mRoomDecryptors");
return null;
}
IMXDecrypting alg = null;
if (!TextUtils.isEmpty(roomId)) {
synchronized (mRoomDecryptors) {
if (!mRoomDecryptors.containsKey(roomId)) {
mRoomDecryptors.put(roomId, new HashMap<String, IMXDecrypting>());
}
alg = mRoomDecryptors.get(roomId).get(algorithm);
}
if (null != alg) {
return alg;
}
}
Class<IMXDecrypting> decryptingClass = MXCryptoAlgorithms.sharedAlgorithms().decryptorClassForAlgorithm(algorithm);
if (null != decryptingClass) {
try {
Constructor<?> ctor = decryptingClass.getConstructors()[0];
alg = (IMXDecrypting) ctor.newInstance();
if (null != alg) {
alg.initWithMatrixSession(mSession);
if (!TextUtils.isEmpty(roomId)) {
synchronized (mRoomDecryptors) {
mRoomDecryptors.get(roomId).put(algorithm, alg);
}
}
}
} catch (Exception e) {
Log.e(LOG_TAG, "## getRoomDecryptor() : fail to load the class");
return null;
}
}
return alg;
}
use of org.matrix.androidsdk.crypto.algorithms.IMXDecrypting in project matrix-android-sdk by matrix-org.
the class MXCrypto method onRoomKeyEvent.
/**
* Handle a key event.
* This method must be called on getDecryptingThreadHandler() thread.
*
* @param event the key event.
*/
private void onRoomKeyEvent(Event event) {
// sanity check
if (null == event) {
Log.e(LOG_TAG, "## onRoomKeyEvent() : null event");
return;
}
RoomKeyContent roomKeyContent = JsonUtils.toRoomKeyContent(event.getContentAsJsonObject());
String roomId = roomKeyContent.room_id;
String algorithm = roomKeyContent.algorithm;
if (TextUtils.isEmpty(roomId) || TextUtils.isEmpty(algorithm)) {
Log.e(LOG_TAG, "## onRoomKeyEvent() : missing fields");
return;
}
IMXDecrypting alg = getRoomDecryptor(roomId, algorithm);
if (null == alg) {
Log.e(LOG_TAG, "## onRoomKeyEvent() : Unable to handle keys for " + algorithm);
return;
}
alg.onRoomKeyEvent(event);
}
use of org.matrix.androidsdk.crypto.algorithms.IMXDecrypting in project matrix-android-sdk by matrix-org.
the class MXCrypto method decryptEvent.
/**
* Decrypt a received event
*
* @param event the raw event.
* @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack.
* @return true if the decryption was successful.
*/
public MXEventDecryptionResult decryptEvent(final Event event, final String timeline) throws MXDecryptionException {
if (null == event) {
Log.e(LOG_TAG, "## decryptEvent : null event");
return null;
}
final EventContent eventContent = event.getWireEventContent();
if (null == eventContent) {
Log.e(LOG_TAG, "## decryptEvent : empty event content");
return null;
}
final List<MXEventDecryptionResult> results = new ArrayList<>();
final CountDownLatch lock = new CountDownLatch(1);
final List<MXDecryptionException> exceptions = new ArrayList<>();
getDecryptingThreadHandler().post(new Runnable() {
@Override
public void run() {
MXEventDecryptionResult result = null;
IMXDecrypting alg = getRoomDecryptor(event.roomId, eventContent.algorithm);
if (null == alg) {
String reason = String.format(MXCryptoError.UNABLE_TO_DECRYPT_REASON, event.eventId, eventContent.algorithm);
Log.e(LOG_TAG, "## decryptEvent() : " + reason);
exceptions.add(new MXDecryptionException(new MXCryptoError(MXCryptoError.UNABLE_TO_DECRYPT_ERROR_CODE, MXCryptoError.UNABLE_TO_DECRYPT, reason)));
} else {
try {
result = alg.decryptEvent(event, timeline);
} catch (MXDecryptionException decryptionException) {
exceptions.add(decryptionException);
}
if (null != result) {
results.add(result);
}
}
lock.countDown();
}
});
try {
lock.await();
} catch (Exception e) {
Log.e(LOG_TAG, "## decryptEvent() : failed " + e.getMessage());
}
if (!exceptions.isEmpty()) {
throw exceptions.get(0);
}
if (!results.isEmpty()) {
return results.get(0);
}
return null;
}
Aggregations