This commit is contained in:
Benoit Marty 2019-05-17 11:20:22 +02:00
parent 102bc9c01b
commit a2210a6b0d
12 changed files with 111 additions and 78 deletions

View File

@ -26,8 +26,7 @@ import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
import im.vector.matrix.android.internal.di.MoshiProvider import im.vector.matrix.android.internal.di.MoshiProvider
import timber.log.Timber import timber.log.Timber
import java.lang.reflect.ParameterizedType import java.lang.reflect.ParameterizedType
import java.util.ArrayList import java.util.*
import java.util.HashMap


typealias Content = JsonDict typealias Content = JsonDict


@ -94,7 +93,8 @@ data class Event(
* This is a small MXEvent instance with typically value for `type` and 'content' fields. * This is a small MXEvent instance with typically value for `type` and 'content' fields.
*/ */
@Transient @Transient
private var mClearEvent: Event? = null var mClearEvent: Event? = null
private set


/** /**
* Curve25519 key which we believe belongs to the sender of the event. * Curve25519 key which we believe belongs to the sender of the event.
@ -121,7 +121,8 @@ data class Event(
* Decryption error * Decryption error
*/ */
@Transient @Transient
private var mCryptoError: MXCryptoError? = null var mCryptoError: MXCryptoError? = null
private set


/** /**
* @return true if this event is encrypted. * @return true if this event is encrypted.
@ -141,16 +142,16 @@ data class Event(
mClearEvent = null mClearEvent = null


if (null != decryptionResult) { if (null != decryptionResult) {
if (null != decryptionResult!!.mClearEvent) { if (null != decryptionResult.mClearEvent) {
mClearEvent = decryptionResult!!.mClearEvent mClearEvent = decryptionResult.mClearEvent
} }


if (null != mClearEvent) { if (null != mClearEvent) {
mClearEvent!!.mSenderCurve25519Key = decryptionResult!!.mSenderCurve25519Key mClearEvent!!.mSenderCurve25519Key = decryptionResult.mSenderCurve25519Key
mClearEvent!!.mClaimedEd25519Key = decryptionResult!!.mClaimedEd25519Key mClearEvent!!.mClaimedEd25519Key = decryptionResult.mClaimedEd25519Key


if (null != decryptionResult!!.mForwardingCurve25519KeyChain) { if (null != decryptionResult.mForwardingCurve25519KeyChain) {
mClearEvent!!.mForwardingCurve25519KeyChain = decryptionResult!!.mForwardingCurve25519KeyChain mClearEvent!!.mForwardingCurve25519KeyChain = decryptionResult.mForwardingCurve25519KeyChain
} else { } else {
mClearEvent!!.mForwardingCurve25519KeyChain = ArrayList() mClearEvent!!.mForwardingCurve25519KeyChain = ArrayList()
} }
@ -163,7 +164,7 @@ data class Event(
// .add("m.relates_to", getWireContent().getAsJsonObject().get("m.relates_to")) // .add("m.relates_to", getWireContent().getAsJsonObject().get("m.relates_to"))
//} //}
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e,"Unable to restore 'm.relates_to' the clear event") Timber.e(e, "Unable to restore 'm.relates_to' the clear event")
} }


} }

View File

@ -151,7 +151,7 @@ internal class CryptoManager(


fun onLiveEvent(roomId: String, event: Event) { fun onLiveEvent(roomId: String, event: Event) {
if (event.type == EventType.ENCRYPTION) { if (event.type == EventType.ENCRYPTION) {
onCryptoEvent(roomId, event) onRoomEncryptionEvent(roomId, event)
} else if (event.type == EventType.STATE_ROOM_MEMBER) { } else if (event.type == EventType.STATE_ROOM_MEMBER) {
onRoomMembershipEvent(roomId, event) onRoomMembershipEvent(roomId, event)
} }
@ -206,7 +206,7 @@ internal class CryptoManager(
mCryptoConfig = MXCryptoConfig() mCryptoConfig = MXCryptoConfig()
} }


mRoomEncryptors = HashMap() mRoomEncryptors = HashMap() // TODO Merge with declaration


var deviceId = mCredentials.deviceId var deviceId = mCredentials.deviceId
// deviceId should always be defined // deviceId should always be defined
@ -770,6 +770,7 @@ internal class CryptoManager(


alg.initWithMatrixSession(this, alg.initWithMatrixSession(this,
mOlmDevice, mOlmDevice,
mKeysBackup,
deviceListManager, deviceListManager,
mCredentials, mCredentials,
mSendToDeviceTask, mSendToDeviceTask,
@ -1146,7 +1147,7 @@ internal class CryptoManager(


getDecryptingThreadHandler().post { getDecryptingThreadHandler().post {
var result: MXEventDecryptionResult? = null var result: MXEventDecryptionResult? = null
val alg = roomDecryptorProvider.getRoomDecryptor(event.roomId, eventContent["algorithm"] as String) val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(this, event.roomId, eventContent["algorithm"] as String)


if (null == alg) { if (null == alg) {
val reason = String.format(MXCryptoError.UNABLE_TO_DECRYPT_REASON, event.eventId, eventContent["algorithm"] as String) val reason = String.format(MXCryptoError.UNABLE_TO_DECRYPT_REASON, event.eventId, eventContent["algorithm"] as String)
@ -1342,7 +1343,8 @@ internal class CryptoManager(
* *
* @param event the encryption event. * @param event the encryption event.
*/ */
fun onCryptoEvent(roomId: String, event: Event) { private fun onRoomEncryptionEvent(roomId: String, event: Event) {
// TODO Parse the event
val eventContent = event.content // wireEventContent val eventContent = event.content // wireEventContent


val room = mRoomService.getRoom(roomId)!! val room = mRoomService.getRoom(roomId)!!
@ -1520,7 +1522,7 @@ internal class CryptoManager(
// But that message might never arrive leaving us stuck with duff // But that message might never arrive leaving us stuck with duff
// private keys clogging up our local storage. // private keys clogging up our local storage.
// So we need some kind of enginering compromise to balance all of // So we need some kind of enginering compromise to balance all of
// these factors. // these factors. // TODO Why we do not set mOneTimeKeyCount here?
val keyCount = data.oneTimeKeyCountsForAlgorithm(MXKey.KEY_SIGNED_CURVE_25519_TYPE) val keyCount = data.oneTimeKeyCountsForAlgorithm(MXKey.KEY_SIGNED_CURVE_25519_TYPE)
uploadOTK(keyCount, keyLimit, callback) uploadOTK(keyCount, keyLimit, callback)
} }
@ -1765,7 +1767,7 @@ internal class CryptoManager(
cpt++ cpt++




val decrypting = roomDecryptorProvider.getRoomDecryptor(megolmSessionData.roomId, megolmSessionData.algorithm) val decrypting = roomDecryptorProvider.getOrCreateRoomDecryptor(this, megolmSessionData.roomId, megolmSessionData.algorithm)


if (null != decrypting) { if (null != decrypting) {
try { try {

View File

@ -51,10 +51,10 @@ internal class MXOlmDevice(
var deviceEd25519Key: String? = null var deviceEd25519Key: String? = null
private set private set


// The OLMKit account instance. // The OLM lib account instance.
private var mOlmAccount: OlmAccount? = null private var mOlmAccount: OlmAccount? = null


// The OLMKit utility instance. // The OLM lib utility instance.
private var mOlmUtility: OlmUtility? = null private var mOlmUtility: OlmUtility? = null


// The outbound group session. // The outbound group session.
@ -144,9 +144,7 @@ internal class MXOlmDevice(
* Release the instance * Release the instance
*/ */
fun release() { fun release() {
if (null != mOlmAccount) { mOlmAccount?.releaseAccount()
mOlmAccount!!.releaseAccount()
}
} }


/** /**
@ -265,7 +263,7 @@ internal class MXOlmDevice(


Timber.d("## createInboundSession() : ciphertext: $ciphertext") Timber.d("## createInboundSession() : ciphertext: $ciphertext")
try { try {
Timber.d("## createInboundSession() :ciphertext: SHA256:" + mOlmUtility!!.sha256(URLEncoder.encode(ciphertext, "utf-8"))) Timber.d("## createInboundSession() :ciphertext: SHA256:" + mOlmUtility!!.sha256(URLEncoder.encode(ciphertext, "utf-8"))) // TODO Extract code from the Log method...
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e, "## createInboundSession() :ciphertext: cannot encode ciphertext") Timber.e(e, "## createInboundSession() :ciphertext: cannot encode ciphertext")
} }

View File

@ -298,7 +298,7 @@ internal class MXOutgoingRoomKeyRequestManager(
val contentMap = MXUsersDevicesMap<Any>() val contentMap = MXUsersDevicesMap<Any>()


for (recipient in recipients) { for (recipient in recipients) {
contentMap.setObject(message, recipient["userId"], recipient["deviceId"]) contentMap.setObject(message, recipient["userId"], recipient["deviceId"]) // TODO Change this two hard coded key to something better
} }


mSendToDeviceTask.configureWith(SendToDeviceTask.Params(EventType.ROOM_KEY_REQUEST, contentMap, transactionId)) mSendToDeviceTask.configureWith(SendToDeviceTask.Params(EventType.ROOM_KEY_REQUEST, contentMap, transactionId))

View File

@ -33,7 +33,7 @@ internal class RoomDecryptorProvider(
) { ) {


// A map from algorithm to MXDecrypting instance, for each room // A map from algorithm to MXDecrypting instance, for each room
private val mRoomDecryptors: MutableMap<String, MutableMap<String /* algorithm */, IMXDecrypting>>/* room id */ = HashMap() private val mRoomDecryptors: MutableMap<String /* room id */, MutableMap<String /* algorithm */, IMXDecrypting>> = HashMap()


/** /**
* Get a decryptor for a given room and algorithm. * Get a decryptor for a given room and algorithm.
@ -43,7 +43,7 @@ internal class RoomDecryptorProvider(
* @param roomId the room id * @param roomId the room id
* @param algorithm the crypto algorithm * @param algorithm the crypto algorithm
* @return the decryptor * @return the decryptor
* TODO do not provide cryptoManager? * TODO do not provide cryptoManager? // TODO Create another method for the case of roomId is null
*/ */
fun getOrCreateRoomDecryptor(cryptoManager: CryptoManager, roomId: String?, algorithm: String?): IMXDecrypting? { fun getOrCreateRoomDecryptor(cryptoManager: CryptoManager, roomId: String?, algorithm: String?): IMXDecrypting? {
// sanity check // sanity check

View File

@ -23,6 +23,7 @@ import im.vector.matrix.android.api.session.events.model.Content
import im.vector.matrix.android.internal.crypto.DeviceListManager import im.vector.matrix.android.internal.crypto.DeviceListManager
import im.vector.matrix.android.internal.crypto.MXOlmDevice import im.vector.matrix.android.internal.crypto.MXOlmDevice
import im.vector.matrix.android.internal.crypto.CryptoManager import im.vector.matrix.android.internal.crypto.CryptoManager
import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor


@ -39,6 +40,7 @@ internal interface IMXEncrypting {
*/ */
fun initWithMatrixSession(crypto: CryptoManager, fun initWithMatrixSession(crypto: CryptoManager,
olmDevice: MXOlmDevice, olmDevice: MXOlmDevice,
keysBackup: KeysBackup,
deviceListManager: DeviceListManager, deviceListManager: DeviceListManager,
credentials: Credentials, credentials: Credentials,
sendToDeviceTask: SendToDeviceTask, sendToDeviceTask: SendToDeviceTask,

View File

@ -62,7 +62,7 @@ internal class MXMegolmDecryption : IMXDecrypting {
* Events which we couldn't decrypt due to unknown sessions / indexes: map from * Events which we couldn't decrypt due to unknown sessions / indexes: map from
* senderKey|sessionId to timelines to list of MatrixEvents. * senderKey|sessionId to timelines to list of MatrixEvents.
*/ */
private var mPendingEvents: MutableMap<String, MutableMap<String /* timelineId */, MutableList<Event>>>? = null/* senderKey|sessionId */ private var mPendingEvents: MutableMap<String /* senderKey|sessionId */, MutableMap<String /* timelineId */, MutableList<Event>>> = HashMap()


/** /**
* Init the object fields * Init the object fields
@ -74,11 +74,11 @@ internal class MXMegolmDecryption : IMXDecrypting {
sendToDeviceTask: SendToDeviceTask, sendToDeviceTask: SendToDeviceTask,
taskExecutor: TaskExecutor) { taskExecutor: TaskExecutor) {
mCredentials = credentials mCredentials = credentials
mCrypto = crypto
mOlmDevice = olmDevice
mDeviceListManager = deviceListManager mDeviceListManager = deviceListManager
mSendToDeviceTask = sendToDeviceTask mSendToDeviceTask = sendToDeviceTask
mTaskExecutor = taskExecutor mTaskExecutor = taskExecutor
mOlmDevice = olmDevice
mPendingEvents = HashMap()
} }


@Throws(MXDecryptionException::class) @Throws(MXDecryptionException::class)
@ -167,7 +167,7 @@ internal class MXMegolmDecryption : IMXDecrypting {
val recipients = ArrayList<Map<String, String>>() val recipients = ArrayList<Map<String, String>>()


val selfMap = HashMap<String, String>() val selfMap = HashMap<String, String>()
selfMap["userId"] = mCredentials.userId selfMap["userId"] = mCredentials.userId // TODO Replace this hard coded keys (see MXOutgoingRoomKeyRequestManager)
selfMap["deviceId"] = "*" selfMap["deviceId"] = "*"
recipients.add(selfMap) recipients.add(selfMap)


@ -196,27 +196,21 @@ internal class MXMegolmDecryption : IMXDecrypting {
* @param timelineId the timeline identifier * @param timelineId the timeline identifier
*/ */
private fun addEventToPendingList(event: Event, timelineId: String) { private fun addEventToPendingList(event: Event, timelineId: String) {
var timelineId = timelineId
val encryptedEventContent = event.content.toModel<EncryptedEventContent>()!! val encryptedEventContent = event.content.toModel<EncryptedEventContent>()!!


val k = "${encryptedEventContent.senderKey}|${encryptedEventContent.sessionId}" val k = "${encryptedEventContent.senderKey}|${encryptedEventContent.sessionId}"


// avoid undefined timelineId if (!mPendingEvents.containsKey(k)) {
if (TextUtils.isEmpty(timelineId)) { mPendingEvents[k] = HashMap()
timelineId = ""
} }


if (!mPendingEvents!!.containsKey(k)) { if (!mPendingEvents[k]!!.containsKey(timelineId)) {
mPendingEvents!![k] = HashMap() mPendingEvents[k]!!.put(timelineId, ArrayList<Event>())
} }


if (!mPendingEvents!![k]!!.containsKey(timelineId)) { if (mPendingEvents[k]!![timelineId]!!.indexOf(event) < 0) {
mPendingEvents!![k]!!.put(timelineId, ArrayList<Event>())
}

if (mPendingEvents!![k]!![timelineId]!!.indexOf(event) < 0) {
Timber.d("## addEventToPendingList() : add Event " + event.eventId + " in room id " + event.roomId) Timber.d("## addEventToPendingList() : add Event " + event.eventId + " in room id " + event.roomId)
mPendingEvents!![k]!![timelineId]!!.add(event) mPendingEvents[k]!![timelineId]!!.add(event)
} }
} }


@ -304,11 +298,11 @@ internal class MXMegolmDecryption : IMXDecrypting {
override fun onNewSession(senderKey: String, sessionId: String) { override fun onNewSession(senderKey: String, sessionId: String) {
val k = "$senderKey|$sessionId" val k = "$senderKey|$sessionId"


val pending = mPendingEvents!![k] val pending = mPendingEvents[k]


if (null != pending) { if (null != pending) {
// Have another go at decrypting events sent with this session. // Have another go at decrypting events sent with this session.
mPendingEvents!!.remove(k) mPendingEvents.remove(k)


val timelineIds = pending.keys val timelineIds = pending.keys



View File

@ -27,17 +27,13 @@ import im.vector.matrix.android.api.session.crypto.MXCryptoError
import im.vector.matrix.android.api.session.events.model.Content import im.vector.matrix.android.api.session.events.model.Content
import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toContent import im.vector.matrix.android.api.session.events.model.toContent
import im.vector.matrix.android.internal.crypto.CryptoAsyncHelper import im.vector.matrix.android.internal.crypto.*
import im.vector.matrix.android.internal.crypto.DeviceListManager
import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import im.vector.matrix.android.internal.crypto.MXOlmDevice
import im.vector.matrix.android.internal.crypto.algorithms.IMXEncrypting import im.vector.matrix.android.internal.crypto.algorithms.IMXEncrypting
import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
import im.vector.matrix.android.internal.crypto.model.MXOlmSessionResult import im.vector.matrix.android.internal.crypto.model.MXOlmSessionResult
import im.vector.matrix.android.internal.crypto.model.MXQueuedEncryption import im.vector.matrix.android.internal.crypto.model.MXQueuedEncryption
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
import im.vector.matrix.android.internal.crypto.CryptoManager
import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
import im.vector.matrix.android.internal.di.MoshiProvider import im.vector.matrix.android.internal.di.MoshiProvider
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor
@ -51,15 +47,15 @@ internal class MXMegolmEncryption : IMXEncrypting {


private lateinit var mCrypto: CryptoManager private lateinit var mCrypto: CryptoManager
private lateinit var olmDevice: MXOlmDevice private lateinit var olmDevice: MXOlmDevice
private lateinit var mKeysBackup: KeysBackup
private lateinit var mDeviceListManager: DeviceListManager private lateinit var mDeviceListManager: DeviceListManager


private lateinit var mKeysBackup: KeysBackup
private lateinit var mCredentials: Credentials private lateinit var mCredentials: Credentials
private lateinit var mSendToDeviceTask: SendToDeviceTask private lateinit var mSendToDeviceTask: SendToDeviceTask
private lateinit var mTaskExecutor: TaskExecutor private lateinit var mTaskExecutor: TaskExecutor


// The id of the room we will be sending to. // The id of the room we will be sending to.
private var mRoomId: String? = null private lateinit var mRoomId: String


private var mDeviceId: String? = null private var mDeviceId: String? = null


@ -93,6 +89,7 @@ internal class MXMegolmEncryption : IMXEncrypting {


override fun initWithMatrixSession(crypto: CryptoManager, override fun initWithMatrixSession(crypto: CryptoManager,
olmDevice: MXOlmDevice, olmDevice: MXOlmDevice,
keysBackup: KeysBackup,
deviceListManager: DeviceListManager, deviceListManager: DeviceListManager,
credentials: Credentials, credentials: Credentials,
sendToDeviceTask: SendToDeviceTask, sendToDeviceTask: SendToDeviceTask,
@ -101,6 +98,7 @@ internal class MXMegolmEncryption : IMXEncrypting {
mCrypto = crypto mCrypto = crypto
this.olmDevice = olmDevice this.olmDevice = olmDevice
mDeviceListManager = deviceListManager mDeviceListManager = deviceListManager
mKeysBackup = keysBackup
mCredentials = credentials mCredentials = credentials
mSendToDeviceTask = sendToDeviceTask mSendToDeviceTask = sendToDeviceTask
mTaskExecutor = taskExecutor mTaskExecutor = taskExecutor
@ -108,6 +106,7 @@ internal class MXMegolmEncryption : IMXEncrypting {
mRoomId = roomId mRoomId = roomId
mDeviceId = mCredentials.deviceId mDeviceId = mCredentials.deviceId



// Default rotation periods // Default rotation periods
// TODO: Make it configurable via parameters // TODO: Make it configurable via parameters
mSessionRotationPeriodMsgs = 100 mSessionRotationPeriodMsgs = 100

View File

@ -25,10 +25,9 @@ import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.internal.crypto.* import im.vector.matrix.android.internal.crypto.*
import im.vector.matrix.android.internal.crypto.algorithms.IMXDecrypting import im.vector.matrix.android.internal.crypto.algorithms.IMXDecrypting
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
import im.vector.matrix.android.internal.crypto.CryptoManager
import im.vector.matrix.android.internal.crypto.model.event.OlmEventContent import im.vector.matrix.android.internal.crypto.model.event.OlmEventContent
import im.vector.matrix.android.internal.crypto.model.event.OlmPayloadContent import im.vector.matrix.android.internal.crypto.model.event.OlmPayloadContent
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.util.convertFromUTF8 import im.vector.matrix.android.internal.util.convertFromUTF8
@ -42,7 +41,7 @@ import java.util.*
internal class MXOlmDecryption : IMXDecrypting { internal class MXOlmDecryption : IMXDecrypting {


// The olm device interface // The olm device interface
private var mOlmDevice: MXOlmDevice? = null private lateinit var mOlmDevice: MXOlmDevice


// the matrix credentials // the matrix credentials
private lateinit var mCredentials: Credentials private lateinit var mCredentials: Credentials
@ -60,9 +59,9 @@ internal class MXOlmDecryption : IMXDecrypting {
taskExecutor: TaskExecutor) { taskExecutor: TaskExecutor) {
mCredentials = credentials mCredentials = credentials
mCrypto = crypto mCrypto = crypto
mOlmDevice = olmDevice
mSendToDeviceTask = sendToDeviceTask mSendToDeviceTask = sendToDeviceTask
mTaskExecutor = taskExecutor mTaskExecutor = taskExecutor
mOlmDevice = olmDevice
} }


@Throws(MXDecryptionException::class) @Throws(MXDecryptionException::class)
@ -81,15 +80,15 @@ internal class MXOlmDecryption : IMXDecrypting {
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.MISSING_CIPHER_TEXT_REASON)) MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.MISSING_CIPHER_TEXT_REASON))
} }


if (!olmEventContent.ciphertext!!.containsKey(mOlmDevice!!.deviceCurve25519Key)) { if (!olmEventContent.ciphertext!!.containsKey(mOlmDevice.deviceCurve25519Key)) {
Timber.e("## decryptEvent() : our device " + mOlmDevice!!.deviceCurve25519Key Timber.e("## decryptEvent() : our device " + mOlmDevice.deviceCurve25519Key
+ " is not included in recipients. Event") + " is not included in recipients. Event")
throw MXDecryptionException(MXCryptoError(MXCryptoError.NOT_INCLUDE_IN_RECIPIENTS_ERROR_CODE, throw MXDecryptionException(MXCryptoError(MXCryptoError.NOT_INCLUDE_IN_RECIPIENTS_ERROR_CODE,
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.NOT_INCLUDED_IN_RECIPIENT_REASON)) MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.NOT_INCLUDED_IN_RECIPIENT_REASON))
} }


// The message for myUser // The message for myUser
val message = olmEventContent.ciphertext!![mOlmDevice!!.deviceCurve25519Key] as Map<String, Any> val message = olmEventContent.ciphertext!![mOlmDevice.deviceCurve25519Key] as Map<String, Any>
val payloadString = decryptMessage(message, olmEventContent.senderKey) val payloadString = decryptMessage(message, olmEventContent.senderKey)


if (null == payloadString) { if (null == payloadString) {
@ -131,7 +130,7 @@ internal class MXOlmDecryption : IMXDecrypting {


val ed25519 = olmPayloadContent.recipient_keys!!.get("ed25519") val ed25519 = olmPayloadContent.recipient_keys!!.get("ed25519")


if (!TextUtils.equals(ed25519, mOlmDevice!!.deviceEd25519Key)) { if (!TextUtils.equals(ed25519, mOlmDevice.deviceEd25519Key)) {
Timber.e("## decryptEvent() : Event " + event.eventId + ": Intended recipient ed25519 key " + ed25519 + " did not match ours") Timber.e("## decryptEvent() : Event " + event.eventId + ": Intended recipient ed25519 key " + ed25519 + " did not match ours")
throw MXDecryptionException(MXCryptoError(MXCryptoError.BAD_RECIPIENT_KEY_ERROR_CODE, throw MXDecryptionException(MXCryptoError(MXCryptoError.BAD_RECIPIENT_KEY_ERROR_CODE,
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.BAD_RECIPIENT_KEY_REASON)) MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.BAD_RECIPIENT_KEY_REASON))
@ -194,7 +193,7 @@ internal class MXOlmDecryption : IMXDecrypting {
* @return payload, if decrypted successfully. * @return payload, if decrypted successfully.
*/ */
private fun decryptMessage(message: Map<String, Any>, theirDeviceIdentityKey: String?): String? { private fun decryptMessage(message: Map<String, Any>, theirDeviceIdentityKey: String?): String? {
val sessionIdsSet = mOlmDevice!!.getSessionIds(theirDeviceIdentityKey!!) val sessionIdsSet = mOlmDevice.getSessionIds(theirDeviceIdentityKey!!)


val sessionIds: List<String> val sessionIds: List<String>


@ -226,13 +225,13 @@ internal class MXOlmDecryption : IMXDecrypting {
// Try each session in turn // Try each session in turn
// decryptionErrors = {}; // decryptionErrors = {};
for (sessionId in sessionIds) { for (sessionId in sessionIds) {
val payload = mOlmDevice!!.decryptMessage(messageBody, messageType, sessionId, theirDeviceIdentityKey) val payload = mOlmDevice.decryptMessage(messageBody, messageType, sessionId, theirDeviceIdentityKey)


if (null != payload) { if (null != payload) {
Timber.d("## decryptMessage() : Decrypted Olm message from $theirDeviceIdentityKey with session $sessionId") Timber.d("## decryptMessage() : Decrypted Olm message from $theirDeviceIdentityKey with session $sessionId")
return payload return payload
} else { } else {
val foundSession = mOlmDevice!!.matchesSession(theirDeviceIdentityKey, sessionId, messageType, messageBody) val foundSession = mOlmDevice.matchesSession(theirDeviceIdentityKey, sessionId, messageType, messageBody)


if (foundSession) { if (foundSession) {
// Decryption failed, but it was a prekey message matching this // Decryption failed, but it was a prekey message matching this
@ -258,7 +257,7 @@ internal class MXOlmDecryption : IMXDecrypting {


// prekey message which doesn't match any existing sessions: make a new // prekey message which doesn't match any existing sessions: make a new
// session. // session.
val res = mOlmDevice!!.createInboundSession(theirDeviceIdentityKey, messageType, messageBody) val res = mOlmDevice.createInboundSession(theirDeviceIdentityKey, messageType, messageBody)


if (null == res) { if (null == res) {
Timber.e("## decryptMessage() : Error decrypting non-prekey message with existing sessions") Timber.e("## decryptMessage() : Error decrypting non-prekey message with existing sessions")
@ -269,8 +268,4 @@ internal class MXOlmDecryption : IMXDecrypting {


return res["payload"] return res["payload"]
} }

companion object {
private val LOG_TAG = "MXOlmDecryption"
}
} }

View File

@ -24,13 +24,14 @@ import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.auth.data.Credentials
import im.vector.matrix.android.api.session.events.model.Content import im.vector.matrix.android.api.session.events.model.Content
import im.vector.matrix.android.api.session.events.model.toContent import im.vector.matrix.android.api.session.events.model.toContent
import im.vector.matrix.android.internal.crypto.CryptoManager
import im.vector.matrix.android.internal.crypto.DeviceListManager import im.vector.matrix.android.internal.crypto.DeviceListManager
import im.vector.matrix.android.internal.crypto.MXOlmDevice import im.vector.matrix.android.internal.crypto.MXOlmDevice
import im.vector.matrix.android.internal.crypto.algorithms.IMXEncrypting import im.vector.matrix.android.internal.crypto.algorithms.IMXEncrypting
import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
import im.vector.matrix.android.internal.crypto.model.MXOlmSessionResult import im.vector.matrix.android.internal.crypto.model.MXOlmSessionResult
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
import im.vector.matrix.android.internal.crypto.CryptoManager
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor
import java.util.* import java.util.*
@ -49,6 +50,7 @@ internal class MXOlmEncryption : IMXEncrypting {


override fun initWithMatrixSession(crypto: CryptoManager, override fun initWithMatrixSession(crypto: CryptoManager,
olmDevice: MXOlmDevice, olmDevice: MXOlmDevice,
keysBackup: KeysBackup,
deviceListManager: DeviceListManager, deviceListManager: DeviceListManager,
credentials: Credentials, credentials: Credentials,
sendToDeviceTask: SendToDeviceTask, sendToDeviceTask: SendToDeviceTask,
@ -69,7 +71,7 @@ internal class MXOlmEncryption : IMXEncrypting {
// //
// TODO: there is a race condition here! What if a new user turns up // TODO: there is a race condition here! What if a new user turns up
ensureSession(userIds, object : MatrixCallback<Unit> { ensureSession(userIds, object : MatrixCallback<Unit> {
override fun onSuccess(info: Unit) { override fun onSuccess(data: Unit) {
val deviceInfos = ArrayList<MXDeviceInfo>() val deviceInfos = ArrayList<MXDeviceInfo>()


for (userId in userIds) { for (userId in userIds) {
@ -95,11 +97,11 @@ internal class MXOlmEncryption : IMXEncrypting {
} }


val messageMap = HashMap<String, Any>() val messageMap = HashMap<String, Any>()
messageMap["room_id"] = mRoomId!! messageMap["room_id"] = mRoomId
messageMap["type"] = eventType messageMap["type"] = eventType
messageMap["content"] = eventContent messageMap["content"] = eventContent


mCrypto!!.encryptMessage(messageMap, deviceInfos) mCrypto.encryptMessage(messageMap, deviceInfos)


callback.onSuccess(messageMap.toContent()!!) callback.onSuccess(messageMap.toContent()!!)
} }
@ -116,7 +118,7 @@ internal class MXOlmEncryption : IMXEncrypting {
mDeviceListManager.downloadKeys(users, false, object : MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>> { mDeviceListManager.downloadKeys(users, false, object : MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>> {


override fun onSuccess(data: MXUsersDevicesMap<MXDeviceInfo>) { override fun onSuccess(data: MXUsersDevicesMap<MXDeviceInfo>) {
mCrypto!!.ensureOlmSessionsForUsers(users, object : MatrixCallback<MXUsersDevicesMap<MXOlmSessionResult>> { mCrypto.ensureOlmSessionsForUsers(users, object : MatrixCallback<MXUsersDevicesMap<MXOlmSessionResult>> {
override fun onSuccess(data: MXUsersDevicesMap<MXOlmSessionResult>) { override fun onSuccess(data: MXUsersDevicesMap<MXOlmSessionResult>) {
callback?.onSuccess(Unit) callback?.onSuccess(Unit)
} }

View File

@ -201,7 +201,7 @@ internal class RealmCryptoStore(private val enableFileEncryption: Boolean = fals
.let { u -> .let { u ->
// Add the devices // Add the devices
// Ensure all other devices are deleted // Ensure all other devices are deleted
u.devices.deleteAllFromRealm() u.devices.deleteAllFromRealm() // Device is null!!


u.devices.addAll( u.devices.addAll(
devices.map { devices.map {

View File

@ -16,25 +16,65 @@


package im.vector.matrix.android.internal.session.sync package im.vector.matrix.android.internal.session.sync


import android.text.TextUtils
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.message.MessageContent
import im.vector.matrix.android.internal.crypto.CryptoManager import im.vector.matrix.android.internal.crypto.CryptoManager
import im.vector.matrix.android.internal.crypto.MXDecryptionException
import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
import im.vector.matrix.android.internal.crypto.verification.DefaultSasVerificationService import im.vector.matrix.android.internal.crypto.verification.DefaultSasVerificationService
import im.vector.matrix.android.internal.session.sync.model.SyncResponse import im.vector.matrix.android.internal.session.sync.model.SyncResponse
import im.vector.matrix.android.internal.session.sync.model.ToDeviceSyncResponse import im.vector.matrix.android.internal.session.sync.model.ToDeviceSyncResponse
import timber.log.Timber




internal class CryptoSyncHandler(private val cryptoManager: CryptoManager, internal class CryptoSyncHandler(private val cryptoManager: CryptoManager,
private val sasVerificationService: DefaultSasVerificationService) { private val sasVerificationService: DefaultSasVerificationService) {


fun handleToDevice(toDevice: ToDeviceSyncResponse) { fun handleToDevice(toDevice: ToDeviceSyncResponse) {
toDevice.events?.forEach { toDevice.events?.forEach { event ->
sasVerificationService.onToDeviceEvent(it) // Decrypt event if necessary
cryptoManager.onToDeviceEvent(it) decryptEvent(event, null)
}


if (TextUtils.equals(event.getClearType(), EventType.MESSAGE)
&& event.mClearEvent?.content?.toModel<MessageContent>()?.type == "m.bad.encrypted") {
Timber.e("## handleToDeviceEvent() : Warning: Unable to decrypt to-device event : " + event.content)
} else {
sasVerificationService.onToDeviceEvent(event)
cryptoManager.onToDeviceEvent(event)
}
}
} }


fun onSyncCompleted(syncResponse: SyncResponse, fromToken: String?, catchingUp: Boolean) { fun onSyncCompleted(syncResponse: SyncResponse, fromToken: String?, catchingUp: Boolean) {
cryptoManager.onSyncCompleted(syncResponse, fromToken, catchingUp) cryptoManager.onSyncCompleted(syncResponse, fromToken, catchingUp)
} }



/**
* Decrypt an encrypted event
*
* @param event the event to decrypt
* @param timelineId the timeline identifier
* @return true if the event has been decrypted
*/
private fun decryptEvent(event: Event, timelineId: String?): Boolean {
if (event.type == EventType.ENCRYPTED) {
var result: MXEventDecryptionResult? = null
try {
result = cryptoManager.decryptEvent(event, timelineId ?: "")
} catch (exception: MXDecryptionException) {
event.setCryptoError(exception.cryptoError)
}

if (null != result) {
event.setClearData(result)
return true
}
}

return false
}
} }