Search in sources :

Example 1 with IMXDecrypting

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);
        }
    }
}
Also used : RoomKeyRequestBody(org.matrix.androidsdk.rest.model.crypto.RoomKeyRequestBody) MXDeviceInfo(org.matrix.androidsdk.crypto.data.MXDeviceInfo) ArrayList(java.util.ArrayList) IMXDecrypting(org.matrix.androidsdk.crypto.algorithms.IMXDecrypting)

Example 2 with IMXDecrypting

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;
}
Also used : IMXDecrypting(org.matrix.androidsdk.crypto.algorithms.IMXDecrypting)

Example 3 with IMXDecrypting

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);
}
Also used : RoomKeyContent(org.matrix.androidsdk.rest.model.crypto.RoomKeyContent) IMXDecrypting(org.matrix.androidsdk.crypto.algorithms.IMXDecrypting)

Example 4 with IMXDecrypting

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;
}
Also used : ArrayList(java.util.ArrayList) IMXDecrypting(org.matrix.androidsdk.crypto.algorithms.IMXDecrypting) CountDownLatch(java.util.concurrent.CountDownLatch) EventContent(org.matrix.androidsdk.rest.model.EventContent)

Aggregations

IMXDecrypting (org.matrix.androidsdk.crypto.algorithms.IMXDecrypting)4 ArrayList (java.util.ArrayList)2 CountDownLatch (java.util.concurrent.CountDownLatch)1 MXDeviceInfo (org.matrix.androidsdk.crypto.data.MXDeviceInfo)1 EventContent (org.matrix.androidsdk.rest.model.EventContent)1 RoomKeyContent (org.matrix.androidsdk.rest.model.crypto.RoomKeyContent)1 RoomKeyRequestBody (org.matrix.androidsdk.rest.model.crypto.RoomKeyRequestBody)1