Fix / Refresh trust state on own keys/device trust change

This commit is contained in:
Valere 2020-01-30 16:10:59 +01:00
parent e2c2c2418c
commit ff95392e10
4 changed files with 120 additions and 22 deletions

View File

@ -114,7 +114,7 @@ internal class DefaultCrossSigningService @Inject constructor(
}
// Recover local trust in case private key are there?
cryptoStore.setUserKeysAsTrusted(userId, checkUserTrust(userId).isVerified())
setUserKeysAsTrusted(userId, checkUserTrust(userId).isVerified())
}
} catch (e: Throwable) {
// Mmm this kind of a big issue
@ -205,7 +205,7 @@ internal class DefaultCrossSigningService @Inject constructor(
val crossSigningInfo = MXCrossSigningInfo(userId, listOf(params.masterKey, params.userKey, params.selfSignedKey))
cryptoStore.setMyCrossSigningInfo(crossSigningInfo)
cryptoStore.setUserKeysAsTrusted(userId)
setUserKeysAsTrusted(userId, true)
cryptoStore.storePrivateKeysInfo(masterKeyPrivateKey?.toBase64NoPadding(), uskPrivateKey?.toBase64NoPadding(), sskPrivateKey?.toBase64NoPadding())
uploadSigningKeysTask.configureWith(params) {
@ -615,7 +615,7 @@ internal class DefaultCrossSigningService @Inject constructor(
checkUserTrust(otherUserId).let {
Timber.d("## CrossSigning - update trust for $otherUserId , verified=${it.isVerified()}")
cryptoStore.setUserKeysAsTrusted(otherUserId, it.isVerified())
setUserKeysAsTrusted(otherUserId, it.isVerified())
}
// TODO if my keys have changes, i should recheck all devices of all users?
@ -625,6 +625,34 @@ internal class DefaultCrossSigningService @Inject constructor(
Timber.d("## CrossSigning - update trust for device ${device.deviceId} of user $otherUserId , verified=$updatedTrust")
cryptoStore.setDeviceTrust(otherUserId, device.deviceId, updatedTrust.isCrossSignedVerified(), updatedTrust.isLocallyVerified())
}
if (otherUserId == userId) {
// It's me, i should check if a newly trusted device is signing my master key
// In this case it will change my MSK trust, and should then re-trigger a check of all other user trust
setUserKeysAsTrusted(otherUserId, checkSelfTrust().isVerified())
}
}
}
private fun setUserKeysAsTrusted(otherUserId: String, trusted: Boolean) {
val currentTrust = cryptoStore.getCrossSigningInfo(otherUserId)?.isTrusted()
cryptoStore.setUserKeysAsTrusted(otherUserId, trusted)
// If it's me, recheck trust of all users and devices?
val users = ArrayList<String>()
if (otherUserId == userId && currentTrust != trusted) {
cryptoStore.updateUsersTrust {
users.add(it)
checkUserTrust(it).isVerified()
}
users.forEach {
cryptoStore.getUserDeviceList(it)?.forEach { device ->
val updatedTrust = checkDeviceTrust(it, device.deviceId, device.trustLevel?.isLocallyVerified() ?: false)
Timber.d("## CrossSigning - update trust for device ${device.deviceId} of user $otherUserId , verified=$updatedTrust")
cryptoStore.setDeviceTrust(it, device.deviceId, updatedTrust.isCrossSignedVerified(), updatedTrust.isLocallyVerified())
}
}
}
}
}

View File

@ -414,4 +414,6 @@ internal interface IMXCryptoStore {
fun setDeviceTrust(userId: String, deviceId: String, crossSignedVerified: Boolean, locallyVerified : Boolean)
fun clearOtherUserTrust()
fun updateUsersTrust(check: (String) -> Boolean)
}

View File

@ -962,34 +962,66 @@ internal class RealmCryptoStore(private val realmConfiguration: RealmConfigurati
}
}
override fun updateUsersTrust(check: (String) -> Boolean) {
doRealmTransaction(realmConfiguration) { realm ->
val xInfoEntities = realm.where(CrossSigningInfoEntity::class.java)
.findAll()
xInfoEntities?.forEach { xInfoEntity ->
// Need to ignore mine
if (xInfoEntity.userId == credentials.userId) return@forEach
val mapped = mapCrossSigningInfoEntity(xInfoEntity)
val currentTrust = mapped.isTrusted()
val newTrust = check(mapped.userId)
if (currentTrust != newTrust) {
xInfoEntity.crossSigningKeys.forEach { info ->
val level = info.trustLevelEntity
if (level == null) {
val newLevel = realm.createObject(TrustLevelEntity::class.java)
newLevel.locallyVerified = newTrust
newLevel.crossSignedVerified = newTrust
info.trustLevelEntity = newLevel
} else {
level.locallyVerified = newTrust
level.crossSignedVerified = newTrust
}
}
}
}
}
}
override fun getCrossSigningInfo(userId: String): MXCrossSigningInfo? {
return doRealmQueryAndCopy(realmConfiguration) { realm ->
realm.where(CrossSigningInfoEntity::class.java)
.equalTo(CrossSigningInfoEntityFields.USER_ID, userId)
.findFirst()
}?.let { xsignInfo ->
MXCrossSigningInfo(
userId = userId,
crossSigningKeys = xsignInfo.crossSigningKeys.mapNotNull {
val pubKey = it.publicKeyBase64 ?: return@mapNotNull null
CryptoCrossSigningKey(
userId = userId,
keys = mapOf("ed25519:$pubKey" to pubKey),
usages = it.usages.map { it },
signatures = it.getSignatures(),
trustLevel = it.trustLevelEntity?.let {
DeviceTrustLevel(
crossSigningVerified = it.crossSignedVerified ?: false,
locallyVerified = it.locallyVerified ?: false
)
}
)
}
)
mapCrossSigningInfoEntity(xsignInfo)
}
}
private fun mapCrossSigningInfoEntity(xsignInfo: CrossSigningInfoEntity): MXCrossSigningInfo {
return MXCrossSigningInfo(
userId = xsignInfo.userId ?: "",
crossSigningKeys = xsignInfo.crossSigningKeys.mapNotNull {
val pubKey = it.publicKeyBase64 ?: return@mapNotNull null
CryptoCrossSigningKey(
userId = xsignInfo.userId ?: "",
keys = mapOf("ed25519:$pubKey" to pubKey),
usages = it.usages.map { it },
signatures = it.getSignatures(),
trustLevel = it.trustLevelEntity?.let {
DeviceTrustLevel(
crossSigningVerified = it.crossSignedVerified ?: false,
locallyVerified = it.locallyVerified ?: false
)
}
)
}
)
}
override fun getLiveCrossSigningInfo(userId: String): LiveData<Optional<MXCrossSigningInfo>> {
val liveData = monarchy.findAllMappedWithChanges(
{ realm: Realm ->

View File

@ -0,0 +1,36 @@
/*
* Copyright 2019 New Vector Ltd
*
* 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 im.vector.matrix.android.internal.crypto.verification
interface VerificationInfoRequest : VerificationInfo {
/**
* Required. The device ID which is initiating the request.
*/
val fromDevice: String?
/**
* Required. The verification methods supported by the sender.
*/
val methods: List<String>?
/**
* The POSIX timestamp in milliseconds for when the request was made.
* If the request is in the future by more than 5 minutes or more than 10 minutes in the past,
* the message should be ignored by the receiver.
*/
val timestamp: Long?
}