mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-22 01:15:54 +03:00
configure encryption settings from state
This commit is contained in:
parent
13d3f4f1a7
commit
56b1b9dec1
10 changed files with 177 additions and 14 deletions
|
@ -42,3 +42,6 @@ const val SSSS_ALGORITHM_AES_HMAC_SHA2 = "m.secret_storage.v1.aes-hmac-sha2"
|
|||
// TODO Refacto: use this constants everywhere
|
||||
const val ed25519 = "ed25519"
|
||||
const val curve25519 = "curve25519"
|
||||
|
||||
const val MEGOLM_DEFAULT_ROTATION_MSGS = 100L
|
||||
const val MEGOLM_DEFAULT_ROTATION_PERIOD_MS = 7 * 24 * 3600 * 1000L
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.api.session.crypto.model
|
||||
|
||||
data class CryptoRoomInfo(
|
||||
val algorithm: String,
|
||||
val shouldEncryptForInvitedMembers: Boolean,
|
||||
val blacklistUnverifiedDevices: Boolean,
|
||||
// Determines whether or not room history should be shared on new member invites
|
||||
val shouldShareHistory: Boolean,
|
||||
// This is specific to megolm but not sure how to model it better
|
||||
// a security to ensure that a room will never revert to not encrypted
|
||||
// even if a new state event with empty encryption, or state is reset somehow
|
||||
val wasEncryptedOnce: Boolean,
|
||||
// How long the session should be used before changing it. 604800000 (a week) is the recommended default.
|
||||
val rotationPeriodMs: Long,
|
||||
// How many messages should be sent before changing the session. 100 is the recommended default.
|
||||
val rotationPeriodMsgs: Long,
|
||||
)
|
|
@ -28,11 +28,13 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.UserIdentity
|
|||
import org.matrix.android.sdk.api.session.crypto.keysbackup.SavedKeyBackupKeyInfo
|
||||
import org.matrix.android.sdk.api.session.crypto.model.AuditTrail
|
||||
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
||||
import org.matrix.android.sdk.api.session.crypto.model.CryptoRoomInfo
|
||||
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
|
||||
import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
|
||||
import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody
|
||||
import org.matrix.android.sdk.api.session.crypto.model.TrailType
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
|
||||
import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent
|
||||
import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
|
@ -284,6 +286,9 @@ internal interface IMXCryptoStore {
|
|||
*/
|
||||
fun getRoomAlgorithm(roomId: String): String?
|
||||
|
||||
fun getRoomCryptoInfo(roomId: String): CryptoRoomInfo?
|
||||
fun setAlgorithmInfo(roomId: String, encryption: EncryptionEventContent?)
|
||||
|
||||
/**
|
||||
* This is a bit different than isRoomEncrypted.
|
||||
* A room is encrypted when there is a m.room.encryption state event in the room (malformed/invalid or not).
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.matrix.android.sdk.api.session.crypto.keysbackup.BackupUtils
|
|||
import org.matrix.android.sdk.api.session.crypto.keysbackup.SavedKeyBackupKeyInfo
|
||||
import org.matrix.android.sdk.api.session.crypto.model.AuditTrail
|
||||
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
||||
import org.matrix.android.sdk.api.session.crypto.model.CryptoRoomInfo
|
||||
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
|
||||
import org.matrix.android.sdk.api.session.crypto.model.ForwardInfo
|
||||
import org.matrix.android.sdk.api.session.crypto.model.IncomingKeyRequestInfo
|
||||
|
@ -48,6 +49,7 @@ import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody
|
|||
import org.matrix.android.sdk.api.session.crypto.model.TrailType
|
||||
import org.matrix.android.sdk.api.session.crypto.model.WithheldInfo
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
|
||||
import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent
|
||||
import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
|
@ -58,6 +60,7 @@ import org.matrix.android.sdk.internal.crypto.model.OutboundGroupSessionWrapper
|
|||
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
|
||||
import org.matrix.android.sdk.internal.crypto.store.UserDataToStore
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.mapper.CrossSigningKeysMapper
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.mapper.CryptoRoomInfoMapper
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.mapper.MyDeviceLastSeenInfoEntityMapper
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.AuditTrailEntity
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.AuditTrailEntityFields
|
||||
|
@ -714,6 +717,30 @@ internal class RealmCryptoStore @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun getRoomCryptoInfo(roomId: String): CryptoRoomInfo? {
|
||||
return doWithRealm(realmConfiguration) { realm ->
|
||||
CryptoRoomEntity.getById(realm, roomId)?.let {
|
||||
CryptoRoomInfoMapper.map(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setAlgorithmInfo(roomId: String, encryption: EncryptionEventContent?) {
|
||||
doRealmTransaction("setAlgorithmInfo", realmConfiguration) {
|
||||
CryptoRoomEntity.getOrCreate(it, roomId).let { entity ->
|
||||
entity.algorithm = encryption?.algorithm
|
||||
// store anyway the new algorithm, but mark the room
|
||||
// as having been encrypted once whatever, this can never
|
||||
// go back to false
|
||||
if (encryption?.algorithm == MXCRYPTO_ALGORITHM_MEGOLM) {
|
||||
entity.wasEncryptedOnce = true
|
||||
entity.rotationPeriodMs = encryption.rotationPeriodMs
|
||||
entity.rotationPeriodMsgs = encryption.rotationPeriodMsgs
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun roomWasOnceEncrypted(roomId: String): Boolean {
|
||||
return doWithRealm(realmConfiguration) {
|
||||
CryptoRoomEntity.getById(it, roomId)?.wasEncryptedOnce ?: false
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo
|
|||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo018
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo019
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo020
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo021
|
||||
import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration
|
||||
import org.matrix.android.sdk.internal.util.time.Clock
|
||||
import javax.inject.Inject
|
||||
|
@ -51,7 +52,7 @@ internal class RealmCryptoStoreMigration @Inject constructor(
|
|||
private val clock: Clock,
|
||||
) : MatrixRealmMigration(
|
||||
dbName = "Crypto",
|
||||
schemaVersion = 20L,
|
||||
schemaVersion = 21L,
|
||||
) {
|
||||
/**
|
||||
* Forces all RealmCryptoStoreMigration instances to be equal.
|
||||
|
@ -81,5 +82,6 @@ internal class RealmCryptoStoreMigration @Inject constructor(
|
|||
if (oldVersion < 18) MigrateCryptoTo018(realm).perform()
|
||||
if (oldVersion < 19) MigrateCryptoTo019(realm).perform()
|
||||
if (oldVersion < 20) MigrateCryptoTo020(realm).perform()
|
||||
if (oldVersion < 21) MigrateCryptoTo021(realm).perform()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.crypto.store.db.mapper
|
||||
|
||||
import org.matrix.android.sdk.api.crypto.MEGOLM_DEFAULT_ROTATION_MSGS
|
||||
import org.matrix.android.sdk.api.crypto.MEGOLM_DEFAULT_ROTATION_PERIOD_MS
|
||||
import org.matrix.android.sdk.api.session.crypto.model.CryptoRoomInfo
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntity
|
||||
|
||||
internal object CryptoRoomInfoMapper {
|
||||
|
||||
fun map(entity: CryptoRoomEntity): CryptoRoomInfo? {
|
||||
val algorithm = entity.algorithm ?: return null
|
||||
return CryptoRoomInfo(
|
||||
algorithm = algorithm,
|
||||
shouldEncryptForInvitedMembers = entity.shouldEncryptForInvitedMembers ?: false,
|
||||
blacklistUnverifiedDevices = entity.blacklistUnverifiedDevices,
|
||||
shouldShareHistory = entity.shouldShareHistory,
|
||||
wasEncryptedOnce = entity.wasEncryptedOnce ?: false,
|
||||
rotationPeriodMsgs = entity.rotationPeriodMsgs ?: MEGOLM_DEFAULT_ROTATION_MSGS,
|
||||
rotationPeriodMs = entity.rotationPeriodMs ?: MEGOLM_DEFAULT_ROTATION_PERIOD_MS
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2023 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.crypto.store.db.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.api.crypto.MEGOLM_DEFAULT_ROTATION_MSGS
|
||||
import org.matrix.android.sdk.api.crypto.MEGOLM_DEFAULT_ROTATION_PERIOD_MS
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
/**
|
||||
* This migration stores the rotation parameters for megolm oubound sessions
|
||||
*/
|
||||
internal class MigrateCryptoTo021(realm: DynamicRealm) : RealmMigrator(realm, 21) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("CryptoRoomEntity")
|
||||
?.addField(CryptoRoomEntityFields.ROTATION_PERIOD_MS, Long::class.java)
|
||||
?.setNullable(CryptoRoomEntityFields.ROTATION_PERIOD_MS, true)
|
||||
?.addField(CryptoRoomEntityFields.ROTATION_PERIOD_MSGS, Long::class.java)
|
||||
?.setNullable(CryptoRoomEntityFields.ROTATION_PERIOD_MSGS, true)
|
||||
?.transform {
|
||||
// As a migration we set the default (will be on par with existing code)
|
||||
// A clear cache will have the correct values.
|
||||
it.setLong(CryptoRoomEntityFields.ROTATION_PERIOD_MS, MEGOLM_DEFAULT_ROTATION_PERIOD_MS)
|
||||
it.setLong(CryptoRoomEntityFields.ROTATION_PERIOD_MSGS, MEGOLM_DEFAULT_ROTATION_MSGS)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -32,7 +32,12 @@ internal open class CryptoRoomEntity(
|
|||
var outboundSessionInfo: OutboundGroupSessionInfoEntity? = null,
|
||||
// a security to ensure that a room will never revert to not encrypted
|
||||
// even if a new state event with empty encryption, or state is reset somehow
|
||||
var wasEncryptedOnce: Boolean? = false
|
||||
var wasEncryptedOnce: Boolean? = false,
|
||||
|
||||
// How long the session should be used before changing it. 604800000 (a week) is the recommended default.
|
||||
var rotationPeriodMs: Long? = null,
|
||||
// How many messages should be sent before changing the session. 100 is the recommended default.
|
||||
var rotationPeriodMsgs: Long? = null,
|
||||
) :
|
||||
RealmObject() {
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import kotlinx.coroutines.sync.Mutex
|
|||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
||||
import org.matrix.android.sdk.api.logger.LoggerTag
|
||||
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.RustKeyBackupService
|
||||
|
@ -49,7 +50,8 @@ internal class PrepareToEncryptUseCase @Inject constructor(
|
|||
private val getRoomUserIds: GetRoomUserIdsUseCase,
|
||||
private val requestSender: RequestSender,
|
||||
private val loadRoomMembersTask: LoadRoomMembersTask,
|
||||
private val keysBackupService: RustKeyBackupService
|
||||
private val keysBackupService: RustKeyBackupService,
|
||||
private val shouldEncryptForInvitedMembers: ShouldEncryptForInvitedMembersUseCase,
|
||||
) {
|
||||
|
||||
private val keyClaimLock: Mutex = Mutex()
|
||||
|
@ -87,17 +89,20 @@ internal class PrepareToEncryptUseCase @Inject constructor(
|
|||
val keyShareLock = roomKeyShareLocks.getOrPut(roomId) { Mutex() }
|
||||
var sharedKey = false
|
||||
|
||||
cryptoStore.getBlockUnverifiedDevices(roomId)
|
||||
cryptoStore.shouldShareHistory(roomId)
|
||||
val info = cryptoStore.getRoomCryptoInfo(roomId)
|
||||
?: throw java.lang.IllegalArgumentException("Encryption not configured in this room")
|
||||
// how to react if this is null??
|
||||
if (info.algorithm != MXCRYPTO_ALGORITHM_MEGOLM) {
|
||||
throw java.lang.IllegalArgumentException("Unsupported algorithm ${info.algorithm}")
|
||||
}
|
||||
val settings = EncryptionSettings(
|
||||
algorithm = EventEncryptionAlgorithm.MEGOLM_V1_AES_SHA2,
|
||||
onlyAllowTrustedDevices = cryptoStore.getBlockUnverifiedDevices(roomId),
|
||||
// TODO should take that from m.room.encryption event
|
||||
rotationPeriod = (7 * 24 * 3600 * 1000).toULong(),
|
||||
rotationPeriodMsgs = 100UL,
|
||||
historyVisibility = if (cryptoStore.shouldShareHistory(roomId)) {
|
||||
onlyAllowTrustedDevices = info.blacklistUnverifiedDevices,
|
||||
rotationPeriod = info.rotationPeriodMs.toULong(),
|
||||
rotationPeriodMsgs = info.rotationPeriodMsgs.toULong(),
|
||||
historyVisibility = if (info.shouldShareHistory) {
|
||||
HistoryVisibility.SHARED
|
||||
} else if (cryptoStore.shouldEncryptForInvitedMembers(roomId)) {
|
||||
} else if (shouldEncryptForInvitedMembers.invoke(roomId)) {
|
||||
HistoryVisibility.INVITED
|
||||
} else {
|
||||
HistoryVisibility.JOINED
|
||||
|
|
|
@ -57,6 +57,7 @@ import org.matrix.android.sdk.api.session.crypto.model.TrailType
|
|||
import org.matrix.android.sdk.api.session.events.model.Content
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
|
||||
import org.matrix.android.sdk.api.session.events.model.content.RoomKeyContent
|
||||
import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent
|
||||
import org.matrix.android.sdk.api.session.events.model.content.SecretSendEventContent
|
||||
|
@ -384,12 +385,13 @@ internal class RustCryptoService @Inject constructor(
|
|||
*/
|
||||
private suspend fun setEncryptionInRoom(
|
||||
roomId: String,
|
||||
algorithm: String?,
|
||||
info: EncryptionEventContent?,
|
||||
membersId: List<String>
|
||||
): Boolean {
|
||||
// If we already have encryption in this room, we should ignore this event
|
||||
// (for now at least. Maybe we should alert the user somehow?)
|
||||
val existingAlgorithm = cryptoStore.getRoomAlgorithm(roomId)
|
||||
val algorithm = info?.algorithm
|
||||
|
||||
if (!existingAlgorithm.isNullOrEmpty() && existingAlgorithm != algorithm) {
|
||||
Timber.tag(loggerTag.value).e("setEncryptionInRoom() : Ignoring m.room.encryption event which requests a change of config in $roomId")
|
||||
|
@ -397,7 +399,7 @@ internal class RustCryptoService @Inject constructor(
|
|||
}
|
||||
|
||||
// TODO CHECK WITH VALERE
|
||||
cryptoStore.storeRoomAlgorithm(roomId, algorithm)
|
||||
cryptoStore.setAlgorithmInfo(roomId, info)
|
||||
|
||||
if (algorithm != MXCRYPTO_ALGORITHM_MEGOLM) {
|
||||
Timber.tag(loggerTag.value).e("## CRYPTO | setEncryptionInRoom() : Unable to encrypt room $roomId with $algorithm")
|
||||
|
@ -508,7 +510,7 @@ internal class RustCryptoService @Inject constructor(
|
|||
// Timber.e(throwable, "## CRYPTO | onRoomEncryptionEvent ERROR FAILED TO SETUP CRYPTO ")
|
||||
// } finally {
|
||||
val userIds = getRoomUserIds(roomId)
|
||||
setEncryptionInRoom(roomId, event.content?.get("algorithm")?.toString(), userIds)
|
||||
setEncryptionInRoom(roomId, event.content?.toModel<EncryptionEventContent>(), userIds)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue