Create enum for errorType and fix a few issues

This commit is contained in:
Benoit Marty 2019-07-05 15:43:28 +02:00
parent 07f80f43bd
commit 4a512d2425
8 changed files with 117 additions and 125 deletions

View File

@ -98,6 +98,7 @@ interface CryptoService {
roomId: String, roomId: String,
callback: MatrixCallback<MXEncryptEventContentResult>) callback: MatrixCallback<MXEncryptEventContentResult>)


@Throws(MXCryptoError::class)
fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult


fun decryptEventAsync(event: Event, timeline: String, callback: MatrixCallback<MXEventDecryptionResult>) fun decryptEventAsync(event: Event, timeline: String, callback: MatrixCallback<MXEventDecryptionResult>)

View File

@ -20,62 +20,56 @@ package im.vector.matrix.android.api.session.crypto


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.MXUsersDevicesMap import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
import org.matrix.olm.OlmException


/** /**
* Represents a crypto error response. * Represents a crypto error response.
*/ */
sealed class MXCryptoError : Throwable() { sealed class MXCryptoError : Throwable() {


// TODO Create data class for all cases, and remove error code data class Base(val errorType: ErrorType,
data class Base(val code: String, val technicalMessage: String,
val _message: String,
/** /**
* Describe the error with more details * Describe the error with more details
*/ */
val detailedErrorDescription: String? = null) : MXCryptoError() val detailedErrorDescription: String? = null) : MXCryptoError()


data class OlmError(val olmException: OlmException) : MXCryptoError()

data class UnknownDevice(val deviceList: MXUsersDevicesMap<MXDeviceInfo>) : MXCryptoError() data class UnknownDevice(val deviceList: MXUsersDevicesMap<MXDeviceInfo>) : MXCryptoError()


enum class ErrorType {
ENCRYPTING_NOT_ENABLED_ERROR_CODE,
UNABLE_TO_ENCRYPT_ERROR_CODE,
UNABLE_TO_DECRYPT_ERROR_CODE,
UNKNOWN_INBOUND_SESSION_ID_ERROR_CODE,
INBOUND_SESSION_MISMATCH_ROOM_ID_ERROR_CODE,
MISSING_FIELDS_ERROR_CODE,
BAD_EVENT_FORMAT_ERROR_CODE,
MISSING_SENDER_KEY_ERROR_CODE,
MISSING_CIPHER_TEXT_ERROR_CODE,
BAD_DECRYPTED_FORMAT_ERROR_CODE,
NOT_INCLUDE_IN_RECIPIENTS_ERROR_CODE,
BAD_RECIPIENT_ERROR_CODE,
BAD_RECIPIENT_KEY_ERROR_CODE,
FORWARDED_MESSAGE_ERROR_CODE,
BAD_ROOM_ERROR_CODE,
BAD_ENCRYPTED_MESSAGE_ERROR_CODE,
DUPLICATED_MESSAGE_INDEX_ERROR_CODE,
MISSING_PROPERTY_ERROR_CODE,
OLM_ERROR_CODE,
UNKNOWN_DEVICES_CODE,
UNKNOWN_MESSAGE_INDEX
}

companion object { companion object {
/** /**
* Error codes * Resource for technicalMessage
*/ */
const val ENCRYPTING_NOT_ENABLED_ERROR_CODE = "ENCRYPTING_NOT_ENABLED"
const val UNABLE_TO_ENCRYPT_ERROR_CODE = "UNABLE_TO_ENCRYPT"
const val UNABLE_TO_DECRYPT_ERROR_CODE = "UNABLE_TO_DECRYPT"
const val UNKNOWN_INBOUND_SESSION_ID_ERROR_CODE = "UNKNOWN_INBOUND_SESSION_ID"
const val INBOUND_SESSION_MISMATCH_ROOM_ID_ERROR_CODE = "INBOUND_SESSION_MISMATCH_ROOM_ID"
const val MISSING_FIELDS_ERROR_CODE = "MISSING_FIELDS"
const val BAD_EVENT_FORMAT_ERROR_CODE = "BAD_EVENT_FORMAT_ERROR_CODE"
const val MISSING_SENDER_KEY_ERROR_CODE = "MISSING_SENDER_KEY_ERROR_CODE"
const val MISSING_CIPHER_TEXT_ERROR_CODE = "MISSING_CIPHER_TEXT"
const val BAD_DECRYPTED_FORMAT_ERROR_CODE = "BAD_DECRYPTED_FORMAT_ERROR_CODE"
const val NOT_INCLUDE_IN_RECIPIENTS_ERROR_CODE = "NOT_INCLUDE_IN_RECIPIENTS"
const val BAD_RECIPIENT_ERROR_CODE = "BAD_RECIPIENT"
const val BAD_RECIPIENT_KEY_ERROR_CODE = "BAD_RECIPIENT_KEY"
const val FORWARDED_MESSAGE_ERROR_CODE = "FORWARDED_MESSAGE"
const val BAD_ROOM_ERROR_CODE = "BAD_ROOM"
const val BAD_ENCRYPTED_MESSAGE_ERROR_CODE = "BAD_ENCRYPTED_MESSAGE"
const val DUPLICATED_MESSAGE_INDEX_ERROR_CODE = "DUPLICATED_MESSAGE_INDEX"
const val MISSING_PROPERTY_ERROR_CODE = "MISSING_PROPERTY"
const val OLM_ERROR_CODE = "OLM_ERROR_CODE"
const val UNKNOWN_DEVICES_CODE = "UNKNOWN_DEVICES_CODE"
const val UNKNOWN_MESSAGE_INDEX = "UNKNOWN_MESSAGE_INDEX"

/**
* short error reasons
*/
const val UNABLE_TO_DECRYPT = "Unable to decrypt"
const val UNABLE_TO_ENCRYPT = "Unable to encrypt"

/**
* Detailed error reasons
*/
const val ENCRYPTING_NOT_ENABLED_REASON = "Encryption not enabled"
const val UNABLE_TO_ENCRYPT_REASON = "Unable to encrypt %s" const val UNABLE_TO_ENCRYPT_REASON = "Unable to encrypt %s"
const val UNABLE_TO_DECRYPT_REASON = "Unable to decrypt %1\$s. Algorithm: %2\$s" const val UNABLE_TO_DECRYPT_REASON = "Unable to decrypt %1\$s. Algorithm: %2\$s"
const val OLM_REASON = "OLM error: %1\$s" const val OLM_REASON = "OLM error: %1\$s"
const val DETAILLED_OLM_REASON = "Unable to decrypt %1\$s. OLM error: %2\$s" const val DETAILED_OLM_REASON = "Unable to decrypt %1\$s. OLM error: %2\$s"
const val UNKNOWN_INBOUND_SESSION_ID_REASON = "Unknown inbound session id" const val UNKNOWN_INBOUND_SESSION_ID_REASON = "Unknown inbound session id"
const val INBOUND_SESSION_MISMATCH_ROOM_ID_REASON = "Mismatched room_id for inbound group session (expected %1\$s, was %2\$s)" const val INBOUND_SESSION_MISMATCH_ROOM_ID_REASON = "Mismatched room_id for inbound group session (expected %1\$s, was %2\$s)"
const val MISSING_FIELDS_REASON = "Missing fields in input" const val MISSING_FIELDS_REASON = "Missing fields in input"

View File

@ -569,7 +569,7 @@ internal class CryptoManager @Inject constructor(
val reason = String.format(MXCryptoError.UNABLE_TO_ENCRYPT_REASON, val reason = String.format(MXCryptoError.UNABLE_TO_ENCRYPT_REASON,
algorithm ?: MXCryptoError.NO_MORE_ALGORITHM_REASON) algorithm ?: MXCryptoError.NO_MORE_ALGORITHM_REASON)
Timber.e("## encryptEventContent() : $reason") Timber.e("## encryptEventContent() : $reason")
callback.onFailure(Failure.CryptoError(MXCryptoError.Base(MXCryptoError.UNABLE_TO_ENCRYPT_ERROR_CODE, reason))) callback.onFailure(Failure.CryptoError(MXCryptoError.Base(MXCryptoError.ErrorType.UNABLE_TO_ENCRYPT_ERROR_CODE, reason)))
} }
} }
} }
@ -618,14 +618,14 @@ internal class CryptoManager @Inject constructor(
val eventContent = event.content val eventContent = event.content
return if (eventContent == null) { return if (eventContent == null) {
Timber.e("## decryptEvent : empty event content") Timber.e("## decryptEvent : empty event content")
Try.Failure(MXCryptoError.Base(MXCryptoError.BAD_ENCRYPTED_MESSAGE_ERROR_CODE, MXCryptoError.BAD_ENCRYPTED_MESSAGE_REASON)) Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.BAD_ENCRYPTED_MESSAGE_ERROR_CODE, MXCryptoError.BAD_ENCRYPTED_MESSAGE_REASON))
} else { } else {
val algorithm = eventContent["algorithm"]?.toString() val algorithm = eventContent["algorithm"]?.toString()
val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(event.roomId, algorithm) val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(event.roomId, algorithm)
if (alg == null) { if (alg == null) {
val reason = String.format(MXCryptoError.UNABLE_TO_DECRYPT_REASON, event.eventId, algorithm) val reason = String.format(MXCryptoError.UNABLE_TO_DECRYPT_REASON, event.eventId, algorithm)
Timber.e("## decryptEvent() : $reason") Timber.e("## decryptEvent() : $reason")
Try.Failure(MXCryptoError.Base(MXCryptoError.UNABLE_TO_DECRYPT_ERROR_CODE, reason)) Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.UNABLE_TO_DECRYPT_ERROR_CODE, reason))
} else { } else {
alg.decryptEvent(event, timeline) alg.decryptEvent(event, timeline)
} }

View File

@ -653,58 +653,52 @@ internal class MXOlmDevice @Inject constructor(
// 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
// the HS pretending a message was targeting a different room. // the HS pretending a message was targeting a different room.
if (roomId == session.roomId) { if (roomId == session.roomId) {
var errorMessage = ""
var decryptResult: OlmInboundGroupSession.DecryptMessageResult? = null var decryptResult: OlmInboundGroupSession.DecryptMessageResult? = null
try { try {
decryptResult = session.olmInboundGroupSession!!.decryptMessage(body) decryptResult = session.olmInboundGroupSession!!.decryptMessage(body)
} catch (e: Exception) { } catch (e: OlmException) {
Timber.e(e, "## decryptGroupMessage () : decryptMessage failed") Timber.e(e, "## decryptGroupMessage () : decryptMessage failed")
errorMessage = e.message ?: "" return@flatMap Try.Failure(MXCryptoError.OlmError(e))
} }


if (null != decryptResult) { if (null != timeline) {
if (null != timeline) { if (!inboundGroupSessionMessageIndexes.containsKey(timeline)) {
if (!inboundGroupSessionMessageIndexes.containsKey(timeline)) { inboundGroupSessionMessageIndexes[timeline] = HashMap()
inboundGroupSessionMessageIndexes[timeline] = HashMap()
}

val messageIndexKey = senderKey + "|" + sessionId + "|" + decryptResult.mIndex

if (inboundGroupSessionMessageIndexes[timeline]?.get(messageIndexKey) != null) {
val reason = String.format(MXCryptoError.DUPLICATE_MESSAGE_INDEX_REASON, decryptResult.mIndex)
Timber.e("## decryptGroupMessage() : $reason")
return@flatMap Try.Failure(MXCryptoError.Base(MXCryptoError.DUPLICATED_MESSAGE_INDEX_ERROR_CODE, reason))
}

inboundGroupSessionMessageIndexes[timeline]!!.put(messageIndexKey, true)
} }


store.storeInboundGroupSessions(listOf(session)) val messageIndexKey = senderKey + "|" + sessionId + "|" + decryptResult.mIndex
val payload = try {
val adapter = MoshiProvider.providesMoshi().adapter<JsonDict>(JSON_DICT_PARAMETERIZED_TYPE) if (inboundGroupSessionMessageIndexes[timeline]?.get(messageIndexKey) != null) {
val payloadString = convertFromUTF8(decryptResult.mDecryptedMessage) val reason = String.format(MXCryptoError.DUPLICATE_MESSAGE_INDEX_REASON, decryptResult.mIndex)
adapter.fromJson(payloadString) Timber.e("## decryptGroupMessage() : $reason")
} catch (e: Exception) { return@flatMap Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.DUPLICATED_MESSAGE_INDEX_ERROR_CODE, reason))
Timber.e("## decryptGroupMessage() : fails to parse the payload")
return@flatMap Try.Failure(MXCryptoError.Base(MXCryptoError.BAD_DECRYPTED_FORMAT_ERROR_CODE, MXCryptoError.BAD_DECRYPTED_FORMAT_TEXT_REASON))
} }


return@flatMap Try.just( inboundGroupSessionMessageIndexes[timeline]!!.put(messageIndexKey, true)
OlmDecryptionResult(
payload,
session.keysClaimed,
senderKey,
session.forwardingCurve25519KeyChain
)
)
} else {
Timber.e("## decryptGroupMessage() : failed to decode the message")
return@flatMap Try.Failure(MXCryptoError.Base(MXCryptoError.OLM_ERROR_CODE, errorMessage))
} }

store.storeInboundGroupSessions(listOf(session))
val payload = try {
val adapter = MoshiProvider.providesMoshi().adapter<JsonDict>(JSON_DICT_PARAMETERIZED_TYPE)
val payloadString = convertFromUTF8(decryptResult.mDecryptedMessage)
adapter.fromJson(payloadString)
} catch (e: Exception) {
Timber.e("## decryptGroupMessage() : fails to parse the payload")
return@flatMap Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.BAD_DECRYPTED_FORMAT_ERROR_CODE, MXCryptoError.BAD_DECRYPTED_FORMAT_TEXT_REASON))
}

return@flatMap Try.just(
OlmDecryptionResult(
payload,
session.keysClaimed,
senderKey,
session.forwardingCurve25519KeyChain
)
)
} else { } else {
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")
return@flatMap Try.Failure(MXCryptoError.Base(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_ERROR_CODE, reason)) return@flatMap Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.INBOUND_SESSION_MISMATCH_ROOM_ID_ERROR_CODE, reason))
} }
} }
} }
@ -772,7 +766,7 @@ internal class MXOlmDevice @Inject constructor(
*/ */
fun getInboundGroupSession(sessionId: String?, senderKey: String?, roomId: String?): Try<OlmInboundGroupSessionWrapper> { fun getInboundGroupSession(sessionId: String?, senderKey: String?, roomId: String?): Try<OlmInboundGroupSessionWrapper> {
if (sessionId.isNullOrBlank() || senderKey.isNullOrBlank()) { if (sessionId.isNullOrBlank() || senderKey.isNullOrBlank()) {
return Try.Failure(MXCryptoError.Base(MXCryptoError.MISSING_SENDER_KEY_ERROR_CODE, MXCryptoError.ERROR_MISSING_PROPERTY_REASON)) return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_SENDER_KEY_ERROR_CODE, MXCryptoError.ERROR_MISSING_PROPERTY_REASON))
} }


val session = store.getInboundGroupSession(sessionId, senderKey) val session = store.getInboundGroupSession(sessionId, senderKey)
@ -783,13 +777,13 @@ internal class MXOlmDevice @Inject constructor(
if (!TextUtils.equals(roomId, session.roomId)) { if (!TextUtils.equals(roomId, session.roomId)) {
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")
Try.Failure(MXCryptoError.Base(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_ERROR_CODE, errorDescription)) Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.INBOUND_SESSION_MISMATCH_ROOM_ID_ERROR_CODE, errorDescription))
} else { } else {
Try.just(session) Try.just(session)
} }
} else { } else {
Timber.e("## getInboundGroupSession() : Cannot retrieve inbound group session $sessionId") Timber.e("## getInboundGroupSession() : Cannot retrieve inbound group session $sessionId")
Try.Failure(MXCryptoError.Base(MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_ERROR_CODE, MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_REASON)) Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID_ERROR_CODE, MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_REASON))
} }
} }



View File

@ -69,34 +69,37 @@ internal class MXMegolmDecryption(private val credentials: Credentials,


private fun decryptEvent(event: Event, timeline: String, requestKeysOnFail: Boolean): Try<MXEventDecryptionResult> { private fun decryptEvent(event: Event, timeline: String, requestKeysOnFail: Boolean): Try<MXEventDecryptionResult> {
val encryptedEventContent = event.content.toModel<EncryptedEventContent>() val encryptedEventContent = event.content.toModel<EncryptedEventContent>()
?: throw MXCryptoError.Base(MXCryptoError.MISSING_FIELDS_ERROR_CODE, MXCryptoError.MISSING_FIELDS_REASON) ?: return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_FIELDS_ERROR_CODE, MXCryptoError.MISSING_FIELDS_REASON))


if (TextUtils.isEmpty(encryptedEventContent.senderKey) if (TextUtils.isEmpty(encryptedEventContent.senderKey)
|| TextUtils.isEmpty(encryptedEventContent.sessionId) || TextUtils.isEmpty(encryptedEventContent.sessionId)
|| TextUtils.isEmpty(encryptedEventContent.ciphertext)) { || TextUtils.isEmpty(encryptedEventContent.ciphertext)) {
throw MXCryptoError.Base(MXCryptoError.MISSING_FIELDS_ERROR_CODE, MXCryptoError.MISSING_FIELDS_REASON) return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_FIELDS_ERROR_CODE, MXCryptoError.MISSING_FIELDS_REASON))
} }


// TODO Why AS says this code is unreachable?
return olmDevice.decryptGroupMessage(encryptedEventContent.ciphertext!!, event.roomId!!, timeline, encryptedEventContent.sessionId!!, encryptedEventContent.senderKey!!) return olmDevice.decryptGroupMessage(encryptedEventContent.ciphertext!!, event.roomId!!, timeline, encryptedEventContent.sessionId!!, encryptedEventContent.senderKey!!)
.fold( .fold(
{ throwable -> { throwable ->
if (throwable is MXCryptoError.Base) { if (throwable is MXCryptoError.OlmError) {
if (throwable.code == MXCryptoError.OLM_ERROR_CODE) { // TODO Check the value of .message
if (MXCryptoError.UNKNOWN_MESSAGE_INDEX == throwable._message) { if (throwable.olmException.message == "UNKNOWN_MESSAGE_INDEX") {
addEventToPendingList(event, timeline) addEventToPendingList(event, timeline)
if (requestKeysOnFail) { if (requestKeysOnFail) {
requestKeysForEvent(event) requestKeysForEvent(event)
}
} }
}


val reason = String.format(MXCryptoError.OLM_REASON, throwable._message) val reason = String.format(MXCryptoError.OLM_REASON, throwable.olmException.message)
val detailedReason = String.format(MXCryptoError.DETAILLED_OLM_REASON, encryptedEventContent.ciphertext, throwable._message) val detailedReason = String.format(MXCryptoError.DETAILED_OLM_REASON, encryptedEventContent.ciphertext, reason)


throw MXCryptoError.Base( return Try.Failure(MXCryptoError.Base(
MXCryptoError.OLM_ERROR_CODE, MXCryptoError.ErrorType.OLM_ERROR_CODE,
reason, reason,
detailedReason) detailedReason))
} else if (throwable.code == MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_ERROR_CODE) { }
if (throwable is MXCryptoError.Base) {
if (throwable.errorType == MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID_ERROR_CODE) {
addEventToPendingList(event, timeline) addEventToPendingList(event, timeline)
if (requestKeysOnFail) { if (requestKeysOnFail) {
requestKeysForEvent(event) requestKeysForEvent(event)
@ -104,12 +107,12 @@ internal class MXMegolmDecryption(private val credentials: Credentials,
} }
} }


throw throwable return Try.Failure(throwable)
}, },
{ decryptionResult -> { decryptionResult ->
// the decryption succeeds // the decryption succeeds
if (decryptionResult.payload != null) { return if (decryptionResult.payload != null) {
return Try.just( Try.just(
MXEventDecryptionResult( MXEventDecryptionResult(
clearEvent = decryptionResult.payload, clearEvent = decryptionResult.payload,
senderCurve25519Key = decryptionResult.senderKey, senderCurve25519Key = decryptionResult.senderKey,
@ -118,7 +121,7 @@ internal class MXMegolmDecryption(private val credentials: Credentials,
) )
) )
} else { } else {
throw MXCryptoError.Base(MXCryptoError.MISSING_FIELDS_ERROR_CODE, MXCryptoError.MISSING_FIELDS_REASON) Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_FIELDS_ERROR_CODE, MXCryptoError.MISSING_FIELDS_REASON))
} }
} }
) )

View File

@ -44,25 +44,25 @@ internal class MXOlmDecryption(
override suspend fun decryptEvent(event: Event, timeline: String): Try<MXEventDecryptionResult> { override suspend fun decryptEvent(event: Event, timeline: String): Try<MXEventDecryptionResult> {
val olmEventContent = event.content.toModel<OlmEventContent>() ?: run { val olmEventContent = event.content.toModel<OlmEventContent>() ?: run {
Timber.e("## decryptEvent() : bad event format") Timber.e("## decryptEvent() : bad event format")
return Try.Failure(MXCryptoError.Base(MXCryptoError.BAD_EVENT_FORMAT_ERROR_CODE, return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.BAD_EVENT_FORMAT_ERROR_CODE,
MXCryptoError.BAD_EVENT_FORMAT_TEXT_REASON)) MXCryptoError.BAD_EVENT_FORMAT_TEXT_REASON))
} }


val cipherText = olmEventContent.ciphertext ?: run { val cipherText = olmEventContent.ciphertext ?: run {
Timber.e("## decryptEvent() : missing cipher text") Timber.e("## decryptEvent() : missing cipher text")
return Try.Failure(MXCryptoError.Base(MXCryptoError.MISSING_CIPHER_TEXT_ERROR_CODE, return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_CIPHER_TEXT_ERROR_CODE,
MXCryptoError.MISSING_CIPHER_TEXT_REASON)) MXCryptoError.MISSING_CIPHER_TEXT_REASON))
} }


val senderKey = olmEventContent.senderKey ?: run { val senderKey = olmEventContent.senderKey ?: run {
Timber.e("## decryptEvent() : missing sender key") Timber.e("## decryptEvent() : missing sender key")
return Try.Failure(MXCryptoError.Base(MXCryptoError.MISSING_SENDER_KEY_ERROR_CODE, return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_SENDER_KEY_ERROR_CODE,
MXCryptoError.MISSING_SENDER_KEY_TEXT_REASON)) MXCryptoError.MISSING_SENDER_KEY_TEXT_REASON))
} }


val messageAny = cipherText[olmDevice.deviceCurve25519Key] ?: run { val messageAny = cipherText[olmDevice.deviceCurve25519Key] ?: run {
Timber.e("## decryptEvent() : our device ${olmDevice.deviceCurve25519Key} is not included in recipients") Timber.e("## decryptEvent() : our device ${olmDevice.deviceCurve25519Key} is not included in recipients")
return Try.Failure(MXCryptoError.Base(MXCryptoError.NOT_INCLUDE_IN_RECIPIENTS_ERROR_CODE, return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.NOT_INCLUDE_IN_RECIPIENTS_ERROR_CODE,
MXCryptoError.NOT_INCLUDED_IN_RECIPIENT_REASON)) MXCryptoError.NOT_INCLUDED_IN_RECIPIENT_REASON))
} }


@ -73,13 +73,13 @@ internal class MXOlmDecryption(


if (decryptedPayload == null) { if (decryptedPayload == null) {
Timber.e("## decryptEvent() Failed to decrypt Olm event (id= ${event.eventId} from $senderKey") Timber.e("## decryptEvent() Failed to decrypt Olm event (id= ${event.eventId} from $senderKey")
return Try.Failure(MXCryptoError.Base(MXCryptoError.BAD_ENCRYPTED_MESSAGE_ERROR_CODE, return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.BAD_ENCRYPTED_MESSAGE_ERROR_CODE,
MXCryptoError.BAD_ENCRYPTED_MESSAGE_REASON)) MXCryptoError.BAD_ENCRYPTED_MESSAGE_REASON))
} }
val payloadString = convertFromUTF8(decryptedPayload) val payloadString = convertFromUTF8(decryptedPayload)
if (payloadString == null) { if (payloadString == null) {
Timber.e("## decryptEvent() Failed to decrypt Olm event (id= ${event.eventId} from $senderKey") Timber.e("## decryptEvent() Failed to decrypt Olm event (id= ${event.eventId} from $senderKey")
return Try.Failure(MXCryptoError.Base(MXCryptoError.BAD_ENCRYPTED_MESSAGE_ERROR_CODE, return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.BAD_ENCRYPTED_MESSAGE_ERROR_CODE,
MXCryptoError.BAD_ENCRYPTED_MESSAGE_REASON)) MXCryptoError.BAD_ENCRYPTED_MESSAGE_REASON))
} }


@ -88,32 +88,32 @@ internal class MXOlmDecryption(


if (payload == null) { if (payload == null) {
Timber.e("## decryptEvent failed : null payload") Timber.e("## decryptEvent failed : null payload")
return Try.Failure(MXCryptoError.Base(MXCryptoError.UNABLE_TO_DECRYPT_ERROR_CODE, return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.UNABLE_TO_DECRYPT_ERROR_CODE,
MXCryptoError.MISSING_CIPHER_TEXT_REASON)) MXCryptoError.MISSING_CIPHER_TEXT_REASON))
} }


val olmPayloadContent = OlmPayloadContent.fromJsonString(payloadString) ?: run { val olmPayloadContent = OlmPayloadContent.fromJsonString(payloadString) ?: run {
Timber.e("## decryptEvent() : bad olmPayloadContent format") Timber.e("## decryptEvent() : bad olmPayloadContent format")
return Try.Failure(MXCryptoError.Base(MXCryptoError.BAD_DECRYPTED_FORMAT_ERROR_CODE, return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.BAD_DECRYPTED_FORMAT_ERROR_CODE,
MXCryptoError.BAD_DECRYPTED_FORMAT_TEXT_REASON)) MXCryptoError.BAD_DECRYPTED_FORMAT_TEXT_REASON))
} }


if (olmPayloadContent.recipient.isNullOrBlank()) { if (olmPayloadContent.recipient.isNullOrBlank()) {
val reason = String.format(MXCryptoError.ERROR_MISSING_PROPERTY_REASON, "recipient") val reason = String.format(MXCryptoError.ERROR_MISSING_PROPERTY_REASON, "recipient")
Timber.e("## decryptEvent() : $reason") Timber.e("## decryptEvent() : $reason")
return Try.Failure(MXCryptoError.Base(MXCryptoError.MISSING_PROPERTY_ERROR_CODE, return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_PROPERTY_ERROR_CODE,
reason)) reason))
} }


if (olmPayloadContent.recipient != credentials.userId) { if (olmPayloadContent.recipient != credentials.userId) {
Timber.e("## decryptEvent() : Event ${event.eventId}: Intended recipient ${olmPayloadContent.recipient} does not match our id ${credentials.userId}") Timber.e("## decryptEvent() : Event ${event.eventId}: Intended recipient ${olmPayloadContent.recipient} does not match our id ${credentials.userId}")
return Try.Failure(MXCryptoError.Base(MXCryptoError.BAD_RECIPIENT_ERROR_CODE, return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.BAD_RECIPIENT_ERROR_CODE,
String.format(MXCryptoError.BAD_RECIPIENT_REASON, olmPayloadContent.recipient))) String.format(MXCryptoError.BAD_RECIPIENT_REASON, olmPayloadContent.recipient)))
} }


val recipientKeys = olmPayloadContent.recipient_keys ?: run { val recipientKeys = olmPayloadContent.recipient_keys ?: run {
Timber.e("## decryptEvent() : Olm event (id=${event.eventId}) contains no 'recipient_keys' property; cannot prevent unknown-key attack") Timber.e("## decryptEvent() : Olm event (id=${event.eventId}) contains no 'recipient_keys' property; cannot prevent unknown-key attack")
return Try.Failure(MXCryptoError.Base(MXCryptoError.MISSING_PROPERTY_ERROR_CODE, return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_PROPERTY_ERROR_CODE,
String.format(MXCryptoError.ERROR_MISSING_PROPERTY_REASON, "recipient_keys"))) String.format(MXCryptoError.ERROR_MISSING_PROPERTY_REASON, "recipient_keys")))
} }


@ -121,31 +121,31 @@ internal class MXOlmDecryption(


if (ed25519 != olmDevice.deviceEd25519Key) { if (ed25519 != olmDevice.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")
return Try.Failure(MXCryptoError.Base(MXCryptoError.BAD_RECIPIENT_KEY_ERROR_CODE, return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.BAD_RECIPIENT_KEY_ERROR_CODE,
MXCryptoError.BAD_RECIPIENT_KEY_REASON)) MXCryptoError.BAD_RECIPIENT_KEY_REASON))
} }


if (olmPayloadContent.sender.isNullOrBlank()) { if (olmPayloadContent.sender.isNullOrBlank()) {
Timber.e("## decryptEvent() : Olm event (id=${event.eventId}) contains no 'sender' property; cannot prevent unknown-key attack") Timber.e("## decryptEvent() : Olm event (id=${event.eventId}) contains no 'sender' property; cannot prevent unknown-key attack")
return Try.Failure(MXCryptoError.Base(MXCryptoError.MISSING_PROPERTY_ERROR_CODE, return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_PROPERTY_ERROR_CODE,
String.format(MXCryptoError.ERROR_MISSING_PROPERTY_REASON, "sender"))) String.format(MXCryptoError.ERROR_MISSING_PROPERTY_REASON, "sender")))
} }


if (olmPayloadContent.sender != event.senderId) { if (olmPayloadContent.sender != event.senderId) {
Timber.e("Event ${event.eventId}: original sender ${olmPayloadContent.sender} does not match reported sender ${event.senderId}") Timber.e("Event ${event.eventId}: original sender ${olmPayloadContent.sender} does not match reported sender ${event.senderId}")
return Try.Failure(MXCryptoError.Base(MXCryptoError.FORWARDED_MESSAGE_ERROR_CODE, return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.FORWARDED_MESSAGE_ERROR_CODE,
String.format(MXCryptoError.FORWARDED_MESSAGE_REASON, olmPayloadContent.sender))) String.format(MXCryptoError.FORWARDED_MESSAGE_REASON, olmPayloadContent.sender)))
} }


if (olmPayloadContent.room_id != event.roomId) { if (olmPayloadContent.room_id != event.roomId) {
Timber.e("## decryptEvent() : Event ${event.eventId}: original room ${olmPayloadContent.room_id} does not match reported room ${event.roomId}") Timber.e("## decryptEvent() : Event ${event.eventId}: original room ${olmPayloadContent.room_id} does not match reported room ${event.roomId}")
return Try.Failure(MXCryptoError.Base(MXCryptoError.BAD_ROOM_ERROR_CODE, return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.BAD_ROOM_ERROR_CODE,
String.format(MXCryptoError.BAD_ROOM_REASON, olmPayloadContent.room_id))) String.format(MXCryptoError.BAD_ROOM_REASON, olmPayloadContent.room_id)))
} }


val keys = olmPayloadContent.keys ?: run { val keys = olmPayloadContent.keys ?: run {
Timber.e("## decryptEvent failed : null keys") Timber.e("## decryptEvent failed : null keys")
return Try.Failure(MXCryptoError.Base(MXCryptoError.UNABLE_TO_DECRYPT_ERROR_CODE, return Try.Failure(MXCryptoError.Base(MXCryptoError.ErrorType.UNABLE_TO_DECRYPT_ERROR_CODE,
MXCryptoError.MISSING_CIPHER_TEXT_REASON)) MXCryptoError.MISSING_CIPHER_TEXT_REASON))
} }



View File

@ -16,8 +16,8 @@


package im.vector.matrix.android.internal.session.room.timeline package im.vector.matrix.android.internal.session.room.timeline


import im.vector.matrix.android.api.failure.Failure
import im.vector.matrix.android.api.session.crypto.CryptoService import im.vector.matrix.android.api.session.crypto.CryptoService
import im.vector.matrix.android.api.session.crypto.MXCryptoError
import im.vector.matrix.android.api.session.events.model.Event 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.EventType
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
@ -81,8 +81,8 @@ internal class SimpleTimelineEventFactory @Inject constructor(private val roomMe
event.setClearData(result) event.setClearData(result)
} catch (failure: Throwable) { } catch (failure: Throwable) {
Timber.e("Encrypted event: decryption failed") Timber.e("Encrypted event: decryption failed")
if (failure is Failure.CryptoError) { if (failure is MXCryptoError) {
event.setCryptoError(failure.error) event.setCryptoError(failure)
} }
} }
} }
@ -138,9 +138,9 @@ internal class InMemoryTimelineEventFactory @Inject constructor(private val room
decryptionCache[cacheKey] = result decryptionCache[cacheKey] = result
event.setClearData(result) event.setClearData(result)
} catch (failure: Throwable) { } catch (failure: Throwable) {
Timber.e("Encrypted event: decryption failed ${failure.localizedMessage}") Timber.e("Encrypted event: decryption failed: $failure")
if (failure is Failure.CryptoError) { if (failure is MXCryptoError) {
event.setCryptoError(failure.error) event.setCryptoError(failure)
} else { } else {
// Other error // Other error
Timber.e("Other error, should be handled") Timber.e("Other error, should be handled")

View File

@ -49,11 +49,11 @@ class EncryptedItemFactory @Inject constructor(private val messageInformationDat
val cryptoError = event.root.mCryptoError val cryptoError = event.root.mCryptoError
val errorDescription = val errorDescription =
if (cryptoError is MXCryptoError.Base) { if (cryptoError is MXCryptoError.Base) {
if (cryptoError.code == MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_ERROR_CODE) { if (cryptoError.errorType == MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID_ERROR_CODE) {
stringProvider.getString(R.string.notice_crypto_error_unkwown_inbound_session_id) stringProvider.getString(R.string.notice_crypto_error_unkwown_inbound_session_id)
} else { } else {
// TODO i18n // TODO i18n
cryptoError._message cryptoError.technicalMessage
} }
} else { } else {
// Cannot happen (for now) // Cannot happen (for now)