Fix / Rageshake crashes + cleaning !!
https://github.com/matrix-org/riot-android-rageshakes/issues/5880 https://github.com/matrix-org/riot-android-rageshakes/issues/5877 https://github.com/matrix-org/riot-android-rageshakes/issues/5873 https://github.com/matrix-org/riot-android-rageshakes/issues/5871
This commit is contained in:
parent
20c8e8d922
commit
b4ea85fc76
@ -81,6 +81,7 @@ class MXCryptoError(var code: String,
|
|||||||
/**
|
/**
|
||||||
* Error codes
|
* Error codes
|
||||||
*/
|
*/
|
||||||
|
const val UNKNOWN_ERROR_CODE = "UNKNOWN_ERROR_CODE"
|
||||||
const val ENCRYPTING_NOT_ENABLED_ERROR_CODE = "ENCRYPTING_NOT_ENABLED"
|
const val ENCRYPTING_NOT_ENABLED_ERROR_CODE = "ENCRYPTING_NOT_ENABLED"
|
||||||
const val UNABLE_TO_ENCRYPT_ERROR_CODE = "UNABLE_TO_ENCRYPT"
|
const val UNABLE_TO_ENCRYPT_ERROR_CODE = "UNABLE_TO_ENCRYPT"
|
||||||
const val UNABLE_TO_DECRYPT_ERROR_CODE = "UNABLE_TO_DECRYPT"
|
const val UNABLE_TO_DECRYPT_ERROR_CODE = "UNABLE_TO_DECRYPT"
|
||||||
|
@ -388,12 +388,12 @@ internal class CryptoManager @Inject constructor(
|
|||||||
var isUpdated = false
|
var isUpdated = false
|
||||||
val deviceIds = devicesIdListByUserId[userId]
|
val deviceIds = devicesIdListByUserId[userId]
|
||||||
|
|
||||||
for (deviceId in deviceIds!!) {
|
deviceIds?.forEach { deviceId ->
|
||||||
val device = storedDeviceIDs[deviceId]
|
val device = storedDeviceIDs[deviceId]
|
||||||
|
|
||||||
// assume if the device is either verified or blocked
|
// assume if the device is either verified or blocked
|
||||||
// it means that the device is known
|
// it means that the device is known
|
||||||
if (null != device && device.isUnknown) {
|
if (device?.isUnknown == true) {
|
||||||
device.verified = MXDeviceInfo.DEVICE_VERIFICATION_UNVERIFIED
|
device.verified = MXDeviceInfo.DEVICE_VERIFICATION_UNVERIFIED
|
||||||
isUpdated = true
|
isUpdated = true
|
||||||
}
|
}
|
||||||
@ -445,7 +445,7 @@ internal class CryptoManager @Inject constructor(
|
|||||||
val encryptingClass = MXCryptoAlgorithms.hasEncryptorClassForAlgorithm(algorithm)
|
val encryptingClass = MXCryptoAlgorithms.hasEncryptorClassForAlgorithm(algorithm)
|
||||||
|
|
||||||
if (!encryptingClass) {
|
if (!encryptingClass) {
|
||||||
Timber.e("## setEncryptionInRoom() : Unable to encrypt with " + algorithm!!)
|
Timber.e("## setEncryptionInRoom() : Unable to encrypt room ${roomId} with $algorithm")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -560,7 +560,7 @@ internal class CryptoManager @Inject constructor(
|
|||||||
.fold(
|
.fold(
|
||||||
{ callback.onFailure(it) },
|
{ callback.onFailure(it) },
|
||||||
{
|
{
|
||||||
Timber.v("## encryptEventContent() : succeeds after " + (System.currentTimeMillis() - t0) + " ms")
|
Timber.v("## encryptEventContent() : succeeds after ${System.currentTimeMillis() - t0} ms")
|
||||||
callback.onSuccess(MXEncryptEventContentResult(it, EventType.ENCRYPTED))
|
callback.onSuccess(MXEncryptEventContentResult(it, EventType.ENCRYPTED))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -615,16 +615,17 @@ internal class CryptoManager @Inject constructor(
|
|||||||
* @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack.
|
* @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack.
|
||||||
* @return the MXEventDecryptionResult data, or null in case of error wrapped into [Try]
|
* @return the MXEventDecryptionResult data, or null in case of error wrapped into [Try]
|
||||||
*/
|
*/
|
||||||
private suspend fun internalDecryptEvent(event: Event, timeline: String): Try<MXEventDecryptionResult?> {
|
private suspend fun internalDecryptEvent(event: Event, timeline: String): Try<MXEventDecryptionResult> {
|
||||||
return Try {
|
return Try {
|
||||||
val eventContent = event.content
|
val eventContent = event.content
|
||||||
if (eventContent == null) {
|
if (eventContent == null) {
|
||||||
Timber.e("## decryptEvent : empty event content")
|
Timber.e("## decryptEvent : empty event content")
|
||||||
return@Try null
|
throw MXDecryptionException(MXCryptoError(MXCryptoError.UNKNOWN_ERROR_CODE, MXCryptoError.UNKNOWN_ERROR_CODE))
|
||||||
}
|
}
|
||||||
val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(event.roomId, eventContent["algorithm"] as String)
|
val algorithm = eventContent["algorithm"]?.toString()
|
||||||
|
val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(event.roomId, algorithm)
|
||||||
if (alg == null) {
|
if (alg == null) {
|
||||||
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, algorithm)
|
||||||
Timber.e("## decryptEvent() : $reason")
|
Timber.e("## decryptEvent() : $reason")
|
||||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.UNABLE_TO_DECRYPT_ERROR_CODE, MXCryptoError.UNABLE_TO_DECRYPT, reason))
|
throw MXDecryptionException(MXCryptoError(MXCryptoError.UNABLE_TO_DECRYPT_ERROR_CODE, MXCryptoError.UNABLE_TO_DECRYPT, reason))
|
||||||
} else {
|
} else {
|
||||||
@ -676,7 +677,7 @@ internal class CryptoManager @Inject constructor(
|
|||||||
}
|
}
|
||||||
val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(roomKeyContent.roomId, roomKeyContent.algorithm)
|
val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(roomKeyContent.roomId, roomKeyContent.algorithm)
|
||||||
if (alg == null) {
|
if (alg == null) {
|
||||||
Timber.e("## onRoomKeyEvent() : Unable to handle keys for " + roomKeyContent.algorithm)
|
Timber.e("## onRoomKeyEvent() : Unable to handle keys for ${roomKeyContent.algorithm}")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
alg.onRoomKeyEvent(event, keysBackup)
|
alg.onRoomKeyEvent(event, keysBackup)
|
||||||
@ -692,9 +693,9 @@ internal class CryptoManager @Inject constructor(
|
|||||||
val params = LoadRoomMembersTask.Params(roomId)
|
val params = LoadRoomMembersTask.Params(roomId)
|
||||||
loadRoomMembersTask
|
loadRoomMembersTask
|
||||||
.execute(params)
|
.execute(params)
|
||||||
.map { allLoaded ->
|
.map { _ ->
|
||||||
val userIds = getRoomUserIds(roomId)
|
val userIds = getRoomUserIds(roomId)
|
||||||
setEncryptionInRoom(roomId, event.content!!["algorithm"] as String, true, userIds)
|
setEncryptionInRoom(roomId, event.content?.get("algorithm")?.toString(), true, userIds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -839,7 +840,7 @@ internal class CryptoManager @Inject constructor(
|
|||||||
val roomKeys = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password)
|
val roomKeys = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password)
|
||||||
val t1 = System.currentTimeMillis()
|
val t1 = System.currentTimeMillis()
|
||||||
|
|
||||||
Timber.v("## importRoomKeys : decryptMegolmKeyFile done in " + (t1 - t0) + " ms")
|
Timber.v("""## importRoomKeys : decryptMegolmKeyFile done in ${t1 - t0} ms""")
|
||||||
|
|
||||||
val importedSessions = MoshiProvider.providesMoshi()
|
val importedSessions = MoshiProvider.providesMoshi()
|
||||||
.adapter<List<MegolmSessionData>>(Types.newParameterizedType(List::class.java, MegolmSessionData::class.java))
|
.adapter<List<MegolmSessionData>>(Types.newParameterizedType(List::class.java, MegolmSessionData::class.java))
|
||||||
@ -847,7 +848,7 @@ internal class CryptoManager @Inject constructor(
|
|||||||
|
|
||||||
val t2 = System.currentTimeMillis()
|
val t2 = System.currentTimeMillis()
|
||||||
|
|
||||||
Timber.v("## importRoomKeys : JSON parsing " + (t2 - t1) + " ms")
|
Timber.v("""## importRoomKeys : JSON parsing ${t2 - t1} ms""")
|
||||||
|
|
||||||
if (importedSessions == null) {
|
if (importedSessions == null) {
|
||||||
throw Exception("Error")
|
throw Exception("Error")
|
||||||
@ -931,11 +932,8 @@ internal class CryptoManager @Inject constructor(
|
|||||||
*/
|
*/
|
||||||
// TODO add this info in CryptoRoomEntity?
|
// TODO add this info in CryptoRoomEntity?
|
||||||
override fun isRoomBlacklistUnverifiedDevices(roomId: String?): Boolean {
|
override fun isRoomBlacklistUnverifiedDevices(roomId: String?): Boolean {
|
||||||
return if (null != roomId) {
|
return roomId?.let { cryptoStore.getRoomsListBlacklistUnverifiedDevices().contains(it) }
|
||||||
cryptoStore.getRoomsListBlacklistUnverifiedDevices().contains(roomId)
|
?: false
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -993,18 +991,18 @@ internal class CryptoManager @Inject constructor(
|
|||||||
* @param event the event to decrypt again.
|
* @param event the event to decrypt again.
|
||||||
*/
|
*/
|
||||||
override fun reRequestRoomKeyForEvent(event: Event) {
|
override fun reRequestRoomKeyForEvent(event: Event) {
|
||||||
val wireContent = event.content!!
|
val wireContent = event.content
|
||||||
|
if (wireContent == null) {
|
||||||
val algorithm = wireContent["algorithm"].toString()
|
Timber.e("## reRequestRoomKeyForEvent Failed to re-request key, null content")
|
||||||
val senderKey = wireContent["sender_key"].toString()
|
return
|
||||||
val sessionId = wireContent["session_id"].toString()
|
}
|
||||||
|
|
||||||
val requestBody = RoomKeyRequestBody()
|
val requestBody = RoomKeyRequestBody()
|
||||||
|
|
||||||
requestBody.roomId = event.roomId
|
requestBody.roomId = event.roomId
|
||||||
requestBody.algorithm = algorithm
|
requestBody.algorithm = wireContent["algorithm"].toString()
|
||||||
requestBody.senderKey = senderKey
|
requestBody.senderKey = wireContent["sender_key"].toString()
|
||||||
requestBody.sessionId = sessionId
|
requestBody.sessionId = wireContent["session_id"].toString()
|
||||||
|
|
||||||
outgoingRoomKeyRequestManager.resendRoomKeyRequest(requestBody)
|
outgoingRoomKeyRequestManager.resendRoomKeyRequest(requestBody)
|
||||||
}
|
}
|
||||||
@ -1038,12 +1036,12 @@ internal class CryptoManager @Inject constructor(
|
|||||||
val userIds = devicesInRoom.userIds
|
val userIds = devicesInRoom.userIds
|
||||||
for (userId in userIds) {
|
for (userId in userIds) {
|
||||||
val deviceIds = devicesInRoom.getUserDeviceIds(userId)
|
val deviceIds = devicesInRoom.getUserDeviceIds(userId)
|
||||||
for (deviceId in deviceIds!!) {
|
deviceIds?.forEach { deviceId ->
|
||||||
val deviceInfo = devicesInRoom.getObject(userId, deviceId)
|
devicesInRoom.getObject(userId, deviceId)
|
||||||
|
?.takeIf { it.isUnknown }
|
||||||
if (deviceInfo?.isUnknown == true) {
|
?.let {
|
||||||
unknownDevices.setObject(userId, deviceId, deviceInfo)
|
unknownDevices.setObject(userId, deviceId, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,12 +29,7 @@ import im.vector.matrix.android.internal.di.MoshiProvider
|
|||||||
import im.vector.matrix.android.internal.session.SessionScope
|
import im.vector.matrix.android.internal.session.SessionScope
|
||||||
import im.vector.matrix.android.internal.util.convertFromUTF8
|
import im.vector.matrix.android.internal.util.convertFromUTF8
|
||||||
import im.vector.matrix.android.internal.util.convertToUTF8
|
import im.vector.matrix.android.internal.util.convertToUTF8
|
||||||
import org.matrix.olm.OlmAccount
|
import org.matrix.olm.*
|
||||||
import org.matrix.olm.OlmInboundGroupSession
|
|
||||||
import org.matrix.olm.OlmMessage
|
|
||||||
import org.matrix.olm.OlmOutboundGroupSession
|
|
||||||
import org.matrix.olm.OlmSession
|
|
||||||
import org.matrix.olm.OlmUtility
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -119,13 +114,13 @@ internal class MXOlmDevice @Inject constructor(
|
|||||||
try {
|
try {
|
||||||
deviceCurve25519Key = olmAccount!!.identityKeys()[OlmAccount.JSON_KEY_IDENTITY_KEY]
|
deviceCurve25519Key = olmAccount!!.identityKeys()[OlmAccount.JSON_KEY_IDENTITY_KEY]
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e, "## MXOlmDevice : cannot find " + OlmAccount.JSON_KEY_IDENTITY_KEY + " with error")
|
Timber.e(e, """## MXOlmDevice : cannot find ${OlmAccount.JSON_KEY_IDENTITY_KEY} with error""")
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
deviceEd25519Key = olmAccount!!.identityKeys()[OlmAccount.JSON_KEY_FINGER_PRINT_KEY]
|
deviceEd25519Key = olmAccount!!.identityKeys()[OlmAccount.JSON_KEY_FINGER_PRINT_KEY]
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e, "## MXOlmDevice : cannot find " + OlmAccount.JSON_KEY_FINGER_PRINT_KEY + " with error")
|
Timber.e(e, "## MXOlmDevice : cannot find ${OlmAccount.JSON_KEY_FINGER_PRINT_KEY} with error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,13 +292,13 @@ internal class MXOlmDevice @Inject constructor(
|
|||||||
|
|
||||||
val res = HashMap<String, String>()
|
val res = HashMap<String, String>()
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(payloadString)) {
|
if (!payloadString.isNullOrEmpty()) {
|
||||||
res["payload"] = payloadString!!
|
res["payload"] = payloadString
|
||||||
}
|
}
|
||||||
|
|
||||||
val sessionIdentifier = olmSession.sessionIdentifier()
|
val sessionIdentifier = olmSession.sessionIdentifier()
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(sessionIdentifier)) {
|
if (!sessionIdentifier.isNullOrEmpty()) {
|
||||||
res["session_id"] = sessionIdentifier
|
res["session_id"] = sessionIdentifier
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,9 +520,7 @@ internal class MXOlmDevice @Inject constructor(
|
|||||||
|
|
||||||
//If our existing session is better we keep it
|
//If our existing session is better we keep it
|
||||||
if (newKnownFirstIndex != null && existingFirstKnown <= newKnownFirstIndex) {
|
if (newKnownFirstIndex != null && existingFirstKnown <= newKnownFirstIndex) {
|
||||||
if (session.olmInboundGroupSession != null) {
|
session.olmInboundGroupSession?.releaseSession()
|
||||||
session.olmInboundGroupSession!!.releaseSession()
|
|
||||||
}
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -545,7 +538,7 @@ internal class MXOlmDevice @Inject constructor(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
session.olmInboundGroupSession!!.releaseSession()
|
session.olmInboundGroupSession?.releaseSession()
|
||||||
Timber.e(e, "## addInboundGroupSession : sessionIdentifier() failed")
|
Timber.e(e, "## addInboundGroupSession : sessionIdentifier() failed")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -584,13 +577,13 @@ internal class MXOlmDevice @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sanity check
|
// sanity check
|
||||||
if (null == session || null == session.olmInboundGroupSession) {
|
if (session?.olmInboundGroupSession == null) {
|
||||||
Timber.e("## importInboundGroupSession : invalid session")
|
Timber.e("## importInboundGroupSession : invalid session")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!TextUtils.equals(session.olmInboundGroupSession!!.sessionIdentifier(), sessionId)) {
|
if (!TextUtils.equals(session.olmInboundGroupSession?.sessionIdentifier(), sessionId)) {
|
||||||
Timber.e("## importInboundGroupSession : ERROR: Mismatched group session ID from senderKey: " + senderKey!!)
|
Timber.e("## importInboundGroupSession : ERROR: Mismatched group session ID from senderKey: " + senderKey!!)
|
||||||
if (session.olmInboundGroupSession != null) session.olmInboundGroupSession!!.releaseSession()
|
if (session.olmInboundGroupSession != null) session.olmInboundGroupSession!!.releaseSession()
|
||||||
continue
|
continue
|
||||||
@ -678,7 +671,7 @@ internal class MXOlmDevice @Inject constructor(
|
|||||||
val reason = String.format(MXCryptoError.DUPLICATE_MESSAGE_INDEX_REASON, decryptResult.mIndex)
|
val reason = String.format(MXCryptoError.DUPLICATE_MESSAGE_INDEX_REASON, decryptResult.mIndex)
|
||||||
Timber.e("## decryptGroupMessage() : $reason")
|
Timber.e("## decryptGroupMessage() : $reason")
|
||||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.DUPLICATED_MESSAGE_INDEX_ERROR_CODE,
|
throw MXDecryptionException(MXCryptoError(MXCryptoError.DUPLICATED_MESSAGE_INDEX_ERROR_CODE,
|
||||||
MXCryptoError.UNABLE_TO_DECRYPT, reason))
|
MXCryptoError.UNABLE_TO_DECRYPT, reason))
|
||||||
}
|
}
|
||||||
|
|
||||||
inboundGroupSessionMessageIndexes[timeline]!!.put(messageIndexKey, true)
|
inboundGroupSessionMessageIndexes[timeline]!!.put(messageIndexKey, true)
|
||||||
@ -711,7 +704,7 @@ internal class MXOlmDevice @Inject constructor(
|
|||||||
val reason = String.format(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_REASON, roomId, session.roomId)
|
val reason = String.format(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_REASON, roomId, session.roomId)
|
||||||
Timber.e("## decryptGroupMessage() : $reason")
|
Timber.e("## decryptGroupMessage() : $reason")
|
||||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_ERROR_CODE,
|
throw MXDecryptionException(MXCryptoError(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_ERROR_CODE,
|
||||||
MXCryptoError.UNABLE_TO_DECRYPT, reason))
|
MXCryptoError.UNABLE_TO_DECRYPT, reason))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Timber.e("## decryptGroupMessage() : Cannot retrieve inbound group session $sessionId")
|
Timber.e("## decryptGroupMessage() : Cannot retrieve inbound group session $sessionId")
|
||||||
@ -767,9 +760,9 @@ internal class MXOlmDevice @Inject constructor(
|
|||||||
*/
|
*/
|
||||||
private fun getSessionForDevice(theirDeviceIdentityKey: String, sessionId: String): OlmSessionWrapper? {
|
private fun getSessionForDevice(theirDeviceIdentityKey: String, sessionId: String): OlmSessionWrapper? {
|
||||||
// sanity check
|
// sanity check
|
||||||
return if (!TextUtils.isEmpty(theirDeviceIdentityKey) && !TextUtils.isEmpty(sessionId)) {
|
return if (theirDeviceIdentityKey.isEmpty() || sessionId.isEmpty()) null else {
|
||||||
store.getDeviceSession(sessionId, theirDeviceIdentityKey)
|
store.getDeviceSession(sessionId, theirDeviceIdentityKey)
|
||||||
} else null
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,7 +778,8 @@ internal class MXOlmDevice @Inject constructor(
|
|||||||
fun getInboundGroupSession(sessionId: String?, senderKey: String?, roomId: String?): OlmInboundGroupSessionWrapper? {
|
fun getInboundGroupSession(sessionId: String?, senderKey: String?, roomId: String?): OlmInboundGroupSessionWrapper? {
|
||||||
inboundGroupSessionWithIdError = null
|
inboundGroupSessionWithIdError = null
|
||||||
|
|
||||||
val session = store.getInboundGroupSession(sessionId!!, senderKey!!)
|
if (sessionId.isNullOrBlank() || senderKey.isNullOrBlank()) return null
|
||||||
|
val session = store.getInboundGroupSession(sessionId, senderKey)
|
||||||
|
|
||||||
if (null != session) {
|
if (null != session) {
|
||||||
// Check that the room id matches the original one for the session. This stops
|
// Check that the room id matches the original one for the session. This stops
|
||||||
@ -794,12 +788,12 @@ internal class MXOlmDevice @Inject constructor(
|
|||||||
val errorDescription = String.format(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_REASON, roomId, session.roomId)
|
val errorDescription = String.format(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_REASON, roomId, session.roomId)
|
||||||
Timber.e("## getInboundGroupSession() : $errorDescription")
|
Timber.e("## getInboundGroupSession() : $errorDescription")
|
||||||
inboundGroupSessionWithIdError = MXCryptoError(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_ERROR_CODE,
|
inboundGroupSessionWithIdError = MXCryptoError(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_ERROR_CODE,
|
||||||
MXCryptoError.UNABLE_TO_DECRYPT, errorDescription)
|
MXCryptoError.UNABLE_TO_DECRYPT, errorDescription)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Timber.e("## getInboundGroupSession() : Cannot retrieve inbound group session $sessionId")
|
Timber.e("## getInboundGroupSession() : Cannot retrieve inbound group session $sessionId")
|
||||||
inboundGroupSessionWithIdError = MXCryptoError(MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_ERROR_CODE,
|
inboundGroupSessionWithIdError = MXCryptoError(MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_ERROR_CODE,
|
||||||
MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_REASON, null)
|
MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_REASON, null)
|
||||||
}
|
}
|
||||||
return session
|
return session
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ internal interface IMXDecrypting {
|
|||||||
* @throws MXDecryptionException the decryption failure reason
|
* @throws MXDecryptionException the decryption failure reason
|
||||||
*/
|
*/
|
||||||
@Throws(MXDecryptionException::class)
|
@Throws(MXDecryptionException::class)
|
||||||
suspend fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult?
|
suspend fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a key event.
|
* Handle a key event.
|
||||||
|
@ -43,6 +43,7 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.HashMap
|
||||||
|
|
||||||
internal class MXMegolmDecryption(private val credentials: Credentials,
|
internal class MXMegolmDecryption(private val credentials: Credentials,
|
||||||
private val olmDevice: MXOlmDevice,
|
private val olmDevice: MXOlmDevice,
|
||||||
@ -64,19 +65,19 @@ internal class MXMegolmDecryption(private val credentials: Credentials,
|
|||||||
private var pendingEvents: MutableMap<String /* senderKey|sessionId */, MutableMap<String /* timelineId */, MutableList<Event>>> = HashMap()
|
private var pendingEvents: MutableMap<String /* senderKey|sessionId */, MutableMap<String /* timelineId */, MutableList<Event>>> = HashMap()
|
||||||
|
|
||||||
@Throws(MXDecryptionException::class)
|
@Throws(MXDecryptionException::class)
|
||||||
override suspend fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult? {
|
override suspend fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult {
|
||||||
return decryptEvent(event, timeline, true)
|
return decryptEvent(event, timeline, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(MXDecryptionException::class)
|
@Throws(MXDecryptionException::class)
|
||||||
private fun decryptEvent(event: Event, timeline: String, requestKeysOnFail: Boolean): MXEventDecryptionResult? {
|
private fun decryptEvent(event: Event, timeline: String, requestKeysOnFail: Boolean): MXEventDecryptionResult {
|
||||||
val encryptedEventContent = event.content.toModel<EncryptedEventContent>()!!
|
val encryptedEventContent = event.content.toModel<EncryptedEventContent>()!!
|
||||||
if (TextUtils.isEmpty(encryptedEventContent.senderKey) || TextUtils.isEmpty(encryptedEventContent.sessionId) || TextUtils.isEmpty(encryptedEventContent.ciphertext)) {
|
if (TextUtils.isEmpty(encryptedEventContent.senderKey) || TextUtils.isEmpty(encryptedEventContent.sessionId) || TextUtils.isEmpty(encryptedEventContent.ciphertext)) {
|
||||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.MISSING_FIELDS_ERROR_CODE,
|
throw MXDecryptionException(MXCryptoError(MXCryptoError.MISSING_FIELDS_ERROR_CODE,
|
||||||
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.MISSING_FIELDS_REASON))
|
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.MISSING_FIELDS_REASON))
|
||||||
}
|
}
|
||||||
|
|
||||||
var eventDecryptionResult: MXEventDecryptionResult? = null
|
val eventDecryptionResult: MXEventDecryptionResult?
|
||||||
var cryptoError: MXCryptoError? = null
|
var cryptoError: MXCryptoError? = null
|
||||||
var decryptGroupMessageResult: MXDecryptionResult? = null
|
var decryptGroupMessageResult: MXDecryptionResult? = null
|
||||||
|
|
||||||
@ -86,17 +87,19 @@ internal class MXMegolmDecryption(private val credentials: Credentials,
|
|||||||
cryptoError = e.cryptoError
|
cryptoError = e.cryptoError
|
||||||
}
|
}
|
||||||
// the decryption succeeds
|
// the decryption succeeds
|
||||||
if (decryptGroupMessageResult?.payload != null && cryptoError == null) {
|
if (decryptGroupMessageResult?.payload != null) {
|
||||||
eventDecryptionResult = MXEventDecryptionResult()
|
eventDecryptionResult = MXEventDecryptionResult()
|
||||||
|
|
||||||
eventDecryptionResult.clearEvent = decryptGroupMessageResult.payload
|
eventDecryptionResult.clearEvent = decryptGroupMessageResult.payload
|
||||||
eventDecryptionResult.senderCurve25519Key = decryptGroupMessageResult.senderKey
|
eventDecryptionResult.senderCurve25519Key = decryptGroupMessageResult.senderKey
|
||||||
|
|
||||||
if (null != decryptGroupMessageResult.keysClaimed) {
|
if (null != decryptGroupMessageResult.keysClaimed) {
|
||||||
eventDecryptionResult.claimedEd25519Key = decryptGroupMessageResult.keysClaimed!!["ed25519"]
|
eventDecryptionResult.claimedEd25519Key = decryptGroupMessageResult.keysClaimed?.get("ed25519")
|
||||||
}
|
}
|
||||||
|
|
||||||
eventDecryptionResult.forwardingCurve25519KeyChain = decryptGroupMessageResult.forwardingCurve25519KeyChain!!
|
eventDecryptionResult.forwardingCurve25519KeyChain = decryptGroupMessageResult.forwardingCurve25519KeyChain
|
||||||
|
?: emptyList()
|
||||||
|
return eventDecryptionResult
|
||||||
} else if (cryptoError != null) {
|
} else if (cryptoError != null) {
|
||||||
if (cryptoError.isOlmError) {
|
if (cryptoError.isOlmError) {
|
||||||
if (MXCryptoError.UNKNOWN_MESSAGE_INDEX == cryptoError.message) {
|
if (MXCryptoError.UNKNOWN_MESSAGE_INDEX == cryptoError.message) {
|
||||||
@ -118,13 +121,13 @@ internal class MXMegolmDecryption(private val credentials: Credentials,
|
|||||||
if (requestKeysOnFail) {
|
if (requestKeysOnFail) {
|
||||||
requestKeysForEvent(event)
|
requestKeysForEvent(event)
|
||||||
}
|
}
|
||||||
|
throw MXDecryptionException(cryptoError)
|
||||||
}
|
}
|
||||||
throw MXDecryptionException(cryptoError)
|
|
||||||
}
|
}
|
||||||
|
throw MXDecryptionException(MXCryptoError(MXCryptoError.UNKNOWN_ERROR_CODE, MXCryptoError.UNKNOWN_ERROR_CODE))
|
||||||
return eventDecryptionResult
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper for the real decryptEvent and for _retryDecryption. If
|
* Helper for the real decryptEvent and for _retryDecryption. If
|
||||||
* requestKeysOnFail is true, we'll send an m.room_key_request when we fail
|
* requestKeysOnFail is true, we'll send an m.room_key_request when we fail
|
||||||
@ -172,6 +175,7 @@ internal class MXMegolmDecryption(private val credentials: Credentials,
|
|||||||
val encryptedEventContent = event.content.toModel<EncryptedEventContent>() ?: return
|
val encryptedEventContent = event.content.toModel<EncryptedEventContent>() ?: return
|
||||||
val pendingEventsKey = "${encryptedEventContent.senderKey}|${encryptedEventContent.sessionId}"
|
val pendingEventsKey = "${encryptedEventContent.senderKey}|${encryptedEventContent.sessionId}"
|
||||||
|
|
||||||
|
|
||||||
if (!pendingEvents.containsKey(pendingEventsKey)) {
|
if (!pendingEvents.containsKey(pendingEventsKey)) {
|
||||||
pendingEvents[pendingEventsKey] = HashMap()
|
pendingEvents[pendingEventsKey] = HashMap()
|
||||||
}
|
}
|
||||||
@ -197,22 +201,25 @@ internal class MXMegolmDecryption(private val credentials: Credentials,
|
|||||||
|
|
||||||
var senderKey: String? = event.getSenderKey()
|
var senderKey: String? = event.getSenderKey()
|
||||||
var keysClaimed: MutableMap<String, String> = HashMap()
|
var keysClaimed: MutableMap<String, String> = HashMap()
|
||||||
var forwardingCurve25519KeyChain: MutableList<String> = ArrayList()
|
val forwardingCurve25519KeyChain: MutableList<String> = ArrayList()
|
||||||
|
|
||||||
if (TextUtils.isEmpty(roomKeyContent.roomId) || TextUtils.isEmpty(roomKeyContent.sessionId) || TextUtils.isEmpty(roomKeyContent.sessionKey)) {
|
if (TextUtils.isEmpty(roomKeyContent.roomId) || TextUtils.isEmpty(roomKeyContent.sessionId) || TextUtils.isEmpty(roomKeyContent.sessionKey)) {
|
||||||
Timber.e("## onRoomKeyEvent() : Key event is missing fields")
|
Timber.e("## onRoomKeyEvent() : Key event is missing fields")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (event.getClearType() == EventType.FORWARDED_ROOM_KEY) {
|
if (event.getClearType() == EventType.FORWARDED_ROOM_KEY) {
|
||||||
Timber.v("## onRoomKeyEvent(), forward adding key : roomId " + roomKeyContent.roomId + " sessionId " + roomKeyContent.sessionId
|
Timber.v("## onRoomKeyEvent(), forward adding key : roomId ${roomKeyContent.roomId} sessionId ${roomKeyContent.sessionId} sessionKey ${roomKeyContent.sessionKey}") // from " + event);
|
||||||
+ " sessionKey " + roomKeyContent.sessionKey) // from " + event);
|
|
||||||
val forwardedRoomKeyContent = event.getClearContent().toModel<ForwardedRoomKeyContent>()
|
val forwardedRoomKeyContent = event.getClearContent().toModel<ForwardedRoomKeyContent>()
|
||||||
?: return
|
?: return
|
||||||
forwardingCurve25519KeyChain = if (forwardedRoomKeyContent.forwardingCurve25519KeyChain == null) {
|
|
||||||
ArrayList()
|
forwardedRoomKeyContent.forwardingCurve25519KeyChain?.let {
|
||||||
} else {
|
forwardingCurve25519KeyChain.addAll(it)
|
||||||
ArrayList(forwardedRoomKeyContent.forwardingCurve25519KeyChain)
|
|
||||||
}
|
}
|
||||||
|
// forwardingCurve25519KeyChain = if (forwardedRoomKeyContent.forwardingCurve25519KeyChain == null) {
|
||||||
|
// ArrayList()
|
||||||
|
// } else {
|
||||||
|
// ArrayList(forwardedRoomKeyContent.forwardingCurve25519KeyChain)
|
||||||
|
// }
|
||||||
|
|
||||||
if (senderKey == null) {
|
if (senderKey == null) {
|
||||||
Timber.e("## onRoomKeyEvent() : event is missing sender_key field")
|
Timber.e("## onRoomKeyEvent() : event is missing sender_key field")
|
||||||
@ -284,8 +291,10 @@ internal class MXMegolmDecryption(private val credentials: Credentials,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun hasKeysForKeyRequest(request: IncomingRoomKeyRequest): Boolean {
|
override fun hasKeysForKeyRequest(request: IncomingRoomKeyRequest): Boolean {
|
||||||
return (null != request.requestBody
|
val roomId = request.requestBody?.roomId ?: return false
|
||||||
&& olmDevice.hasInboundSessionKeys(request.requestBody!!.roomId!!, request.requestBody!!.senderKey!!, request.requestBody!!.sessionId!!))
|
val senderKey = request.requestBody?.senderKey ?: return false
|
||||||
|
val sessionId = request.requestBody?.sessionId ?: return false
|
||||||
|
return olmDevice.hasInboundSessionKeys(roomId, senderKey, sessionId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shareKeysWithDevice(request: IncomingRoomKeyRequest) {
|
override fun shareKeysWithDevice(request: IncomingRoomKeyRequest) {
|
||||||
@ -293,13 +302,13 @@ internal class MXMegolmDecryption(private val credentials: Credentials,
|
|||||||
if (request.requestBody == null) {
|
if (request.requestBody == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val userId = request.userId!!
|
val userId = request.userId ?: return
|
||||||
CoroutineScope(coroutineDispatchers.crypto).launch {
|
CoroutineScope(coroutineDispatchers.crypto).launch {
|
||||||
deviceListManager
|
deviceListManager
|
||||||
.downloadKeys(listOf(userId), false)
|
.downloadKeys(listOf(userId), false)
|
||||||
.flatMap {
|
.flatMap {
|
||||||
val deviceId = request.deviceId
|
val deviceId = request.deviceId
|
||||||
val deviceInfo = cryptoStore.getUserDevice(deviceId!!, userId)
|
val deviceInfo = cryptoStore.getUserDevice(deviceId ?: "", userId)
|
||||||
if (deviceInfo == null) {
|
if (deviceInfo == null) {
|
||||||
throw RuntimeException()
|
throw RuntimeException()
|
||||||
} else {
|
} else {
|
||||||
@ -315,9 +324,8 @@ internal class MXMegolmDecryption(private val credentials: Credentials,
|
|||||||
// were no one-time keys.
|
// were no one-time keys.
|
||||||
Try.just(Unit)
|
Try.just(Unit)
|
||||||
}
|
}
|
||||||
Timber.v("## shareKeysWithDevice() : sharing keys for session " + body!!.senderKey + "|" + body.sessionId
|
Timber.v("""## shareKeysWithDevice() : sharing keys for session ${body?.senderKey}|${body?.sessionId} with device $userId:$deviceId""")
|
||||||
+ " with device " + userId + ":" + deviceId)
|
val inboundGroupSession = olmDevice.getInboundGroupSession(body?.sessionId, body?.senderKey, body?.roomId)
|
||||||
val inboundGroupSession = olmDevice.getInboundGroupSession(body.sessionId, body.senderKey, body.roomId)
|
|
||||||
|
|
||||||
val payloadJson = HashMap<String, Any>()
|
val payloadJson = HashMap<String, Any>()
|
||||||
payloadJson["type"] = EventType.FORWARDED_ROOM_KEY
|
payloadJson["type"] = EventType.FORWARDED_ROOM_KEY
|
||||||
|
@ -43,7 +43,7 @@ internal class MXOlmDecryption(
|
|||||||
: IMXDecrypting {
|
: IMXDecrypting {
|
||||||
|
|
||||||
@Throws(MXDecryptionException::class)
|
@Throws(MXDecryptionException::class)
|
||||||
override suspend fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult? {
|
override suspend fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult {
|
||||||
val olmEventContent = event.content.toModel<OlmEventContent>()!!
|
val olmEventContent = event.content.toModel<OlmEventContent>()!!
|
||||||
|
|
||||||
if (null == olmEventContent.ciphertext) {
|
if (null == olmEventContent.ciphertext) {
|
||||||
|
@ -21,4 +21,4 @@ import com.airbnb.mvrx.MvRxState
|
|||||||
import im.vector.riotx.BuildConfig
|
import im.vector.riotx.BuildConfig
|
||||||
|
|
||||||
abstract class VectorViewModel<S : MvRxState>(initialState: S)
|
abstract class VectorViewModel<S : MvRxState>(initialState: S)
|
||||||
: BaseMvRxViewModel<S>(initialState, debugMode = BuildConfig.DEBUG)
|
: BaseMvRxViewModel<S>(initialState, false)
|
Loading…
x
Reference in New Issue
Block a user