Avoid to inject credential (again)

This commit is contained in:
Benoit Marty 2020-01-25 12:52:40 +01:00
parent be77017209
commit fb5148fd43
2 changed files with 76 additions and 76 deletions

View File

@ -26,33 +26,39 @@ import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
interface CrossSigningService { interface CrossSigningService {
fun isUserTrusted(userId: String) : Boolean fun isUserTrusted(otherUserId: String): Boolean
/** /**
* Will not force a download of the key, but will verify signatures trust chain. * Will not force a download of the key, but will verify signatures trust chain.
* Checks that my trusted user key has signed the other user UserKey * Checks that my trusted user key has signed the other user UserKey
*/ */
fun checkUserTrust(userId: String) : UserTrustResult fun checkUserTrust(otherUserId: String): UserTrustResult
/** /**
* Initialize cross signing for this user. * Initialize cross signing for this user.
* Users needs to enter credentials * Users needs to enter credentials
*/ */
fun initializeCrossSigning(authParams: UserPasswordAuth?, callback: MatrixCallback<Unit>? = null) fun initializeCrossSigning(authParams: UserPasswordAuth?,
callback: MatrixCallback<Unit>? = null)
fun getUserCrossSigningKeys(userId: String): MXCrossSigningInfo? fun getUserCrossSigningKeys(otherUserId: String): MXCrossSigningInfo?
fun getLiveCrossSigningKeys(userId: String): LiveData<Optional<MXCrossSigningInfo>> fun getLiveCrossSigningKeys(userId: String): LiveData<Optional<MXCrossSigningInfo>>
fun getMyCrossSigningKeys(): MXCrossSigningInfo? fun getMyCrossSigningKeys(): MXCrossSigningInfo?
fun canCrossSign(): Boolean fun canCrossSign(): Boolean
fun trustUser(userId: String, callback: MatrixCallback<Unit>) fun trustUser(otherUserId: String,
callback: MatrixCallback<Unit>)
/** /**
* Sign one of your devices and upload the signature * Sign one of your devices and upload the signature
*/ */
fun signDevice(deviceId: String, callback: MatrixCallback<Unit>) fun signDevice(deviceId: String,
callback: MatrixCallback<Unit>)
fun checkDeviceTrust(userId: String, deviceId: String, locallyTrusted: Boolean?) : DeviceTrustResult fun checkDeviceTrust(otherUserId: String,
otherDeviceId: String,
locallyTrusted: Boolean?): DeviceTrustResult
} }

View File

@ -19,7 +19,6 @@ package im.vector.matrix.android.internal.crypto.crosssigning
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import dagger.Lazy import dagger.Lazy
import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.auth.data.Credentials
import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService
import im.vector.matrix.android.api.session.crypto.crosssigning.MXCrossSigningInfo import im.vector.matrix.android.api.session.crypto.crosssigning.MXCrossSigningInfo
import im.vector.matrix.android.api.util.Optional import im.vector.matrix.android.api.util.Optional
@ -50,7 +49,6 @@ import javax.inject.Inject
@SessionScope @SessionScope
internal class DefaultCrossSigningService @Inject constructor( internal class DefaultCrossSigningService @Inject constructor(
@UserId private val userId: String, @UserId private val userId: String,
private val credentials: Credentials,
private val cryptoStore: IMXCryptoStore, private val cryptoStore: IMXCryptoStore,
private val myDeviceInfoHolder: Lazy<MyDeviceInfoHolder>, private val myDeviceInfoHolder: Lazy<MyDeviceInfoHolder>,
private val olmDevice: MXOlmDevice, private val olmDevice: MXOlmDevice,
@ -145,8 +143,6 @@ internal class DefaultCrossSigningService @Inject constructor(
override fun initializeCrossSigning(authParams: UserPasswordAuth?, callback: MatrixCallback<Unit>?) { override fun initializeCrossSigning(authParams: UserPasswordAuth?, callback: MatrixCallback<Unit>?) {
Timber.d("## CrossSigning initializeCrossSigning") Timber.d("## CrossSigning initializeCrossSigning")
val myUserID = credentials.userId
// ================= // =================
// MASTER KEY // MASTER KEY
// ================= // =================
@ -166,7 +162,7 @@ internal class DefaultCrossSigningService @Inject constructor(
Timber.v("## CrossSigning - uskPublicKey:$uskPublicKey") Timber.v("## CrossSigning - uskPublicKey:$uskPublicKey")
// Sign userSigningKey with master // Sign userSigningKey with master
val signedUSK = CryptoCrossSigningKey.Builder(myUserID, KeyUsage.USER_SIGNING) val signedUSK = CryptoCrossSigningKey.Builder(userId, KeyUsage.USER_SIGNING)
.key(uskPublicKey) .key(uskPublicKey)
.build() .build()
.canonicalSignable() .canonicalSignable()
@ -182,23 +178,23 @@ internal class DefaultCrossSigningService @Inject constructor(
Timber.v("## CrossSigning - sskPublicKey:$sskPublicKey") Timber.v("## CrossSigning - sskPublicKey:$sskPublicKey")
// Sign userSigningKey with master // Sign userSigningKey with master
val signedSSK = JsonCanonicalizer.getCanonicalJson(Map::class.java, CryptoCrossSigningKey.Builder(myUserID, KeyUsage.SELF_SIGNING) val signedSSK = JsonCanonicalizer.getCanonicalJson(Map::class.java, CryptoCrossSigningKey.Builder(userId, KeyUsage.SELF_SIGNING)
.key(sskPublicKey) .key(sskPublicKey)
.build().signalableJSONDictionary()).let { masterPkOlm.sign(it) } .build().signalableJSONDictionary()).let { masterPkOlm.sign(it) }
// I need to upload the keys // I need to upload the keys
val mskCrossSigningKeyInfo = CryptoCrossSigningKey.Builder(myUserID, KeyUsage.MASTER) val mskCrossSigningKeyInfo = CryptoCrossSigningKey.Builder(userId, KeyUsage.MASTER)
.key(masterPublicKey) .key(masterPublicKey)
.build() .build()
val params = UploadSigningKeysTask.Params( val params = UploadSigningKeysTask.Params(
masterKey = mskCrossSigningKeyInfo, masterKey = mskCrossSigningKeyInfo,
userKey = CryptoCrossSigningKey.Builder(myUserID, KeyUsage.USER_SIGNING) userKey = CryptoCrossSigningKey.Builder(userId, KeyUsage.USER_SIGNING)
.key(uskPublicKey) .key(uskPublicKey)
.signature(myUserID, masterPublicKey, signedUSK) .signature(userId, masterPublicKey, signedUSK)
.build(), .build(),
selfSignedKey = CryptoCrossSigningKey.Builder(myUserID, KeyUsage.SELF_SIGNING) selfSignedKey = CryptoCrossSigningKey.Builder(userId, KeyUsage.SELF_SIGNING)
.key(sskPublicKey) .key(sskPublicKey)
.signature(myUserID, masterPublicKey, signedSSK) .signature(userId, masterPublicKey, signedSSK)
.build(), .build(),
userPasswordAuth = authParams userPasswordAuth = authParams
) )
@ -207,9 +203,9 @@ internal class DefaultCrossSigningService @Inject constructor(
this.userPkSigning = userSigningPkOlm this.userPkSigning = userSigningPkOlm
this.selfSigningPkSigning = selfSigningPkOlm this.selfSigningPkSigning = selfSigningPkOlm
val crossSigningInfo = MXCrossSigningInfo(myUserID, listOf(params.masterKey, params.userKey, params.selfSignedKey)) val crossSigningInfo = MXCrossSigningInfo(userId, listOf(params.masterKey, params.userKey, params.selfSignedKey))
cryptoStore.setMyCrossSigningInfo(crossSigningInfo) cryptoStore.setMyCrossSigningInfo(crossSigningInfo)
cryptoStore.setUserKeysAsTrusted(myUserID) cryptoStore.setUserKeysAsTrusted(userId)
cryptoStore.storePrivateKeysInfo(masterKeyPrivateKey?.toBase64NoPadding(), uskPrivateKey?.toBase64NoPadding(), sskPrivateKey?.toBase64NoPadding()) cryptoStore.storePrivateKeysInfo(masterKeyPrivateKey?.toBase64NoPadding(), uskPrivateKey?.toBase64NoPadding(), sskPrivateKey?.toBase64NoPadding())
uploadSigningKeysTask.configureWith(params) { uploadSigningKeysTask.configureWith(params) {
@ -225,7 +221,7 @@ internal class DefaultCrossSigningService @Inject constructor(
val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, myDevice.signalableJSONDictionary()) val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, myDevice.signalableJSONDictionary())
val signedDevice = selfSigningPkOlm.sign(canonicalJson) val signedDevice = selfSigningPkOlm.sign(canonicalJson)
val updateSignatures = (myDevice.signatures?.toMutableMap() ?: HashMap()).also { val updateSignatures = (myDevice.signatures?.toMutableMap() ?: HashMap()).also {
it[myUserID] = (it[myUserID] it[userId] = (it[userId]
?: HashMap()) + mapOf("ed25519:$sskPublicKey" to signedDevice) ?: HashMap()) + mapOf("ed25519:$sskPublicKey" to signedDevice)
} }
myDevice.copy(signatures = updateSignatures).let { myDevice.copy(signatures = updateSignatures).let {
@ -236,7 +232,7 @@ internal class DefaultCrossSigningService @Inject constructor(
olmDevice.signMessage(JsonCanonicalizer.getCanonicalJson(Map::class.java, mskCrossSigningKeyInfo.signalableJSONDictionary()))?.let { sign -> olmDevice.signMessage(JsonCanonicalizer.getCanonicalJson(Map::class.java, mskCrossSigningKeyInfo.signalableJSONDictionary()))?.let { sign ->
val mskUpdatedSignatures = (mskCrossSigningKeyInfo.signatures?.toMutableMap() val mskUpdatedSignatures = (mskCrossSigningKeyInfo.signatures?.toMutableMap()
?: HashMap()).also { ?: HashMap()).also {
it[myUserID] = (it[myUserID] it[userId] = (it[userId]
?: HashMap()) + mapOf("ed25519:${myDevice.deviceId}" to sign) ?: HashMap()) + mapOf("ed25519:${myDevice.deviceId}" to sign)
} }
mskCrossSigningKeyInfo.copy( mskCrossSigningKeyInfo.copy(
@ -310,16 +306,16 @@ internal class DefaultCrossSigningService @Inject constructor(
* BOB's Device * BOB's Device
* *
*/ */
override fun isUserTrusted(userId: String): Boolean { override fun isUserTrusted(otherUserId: String): Boolean {
return cryptoStore.getCrossSigningInfo(userId)?.isTrusted() == true return cryptoStore.getCrossSigningInfo(userId)?.isTrusted() == true
} }
/** /**
* Will not force a download of the key, but will verify signatures trust chain * Will not force a download of the key, but will verify signatures trust chain
*/ */
override fun checkUserTrust(userId: String): UserTrustResult { override fun checkUserTrust(otherUserId: String): UserTrustResult {
Timber.d("## CrossSigning checkUserTrust for $userId") Timber.d("## CrossSigning checkUserTrust for $otherUserId")
if (userId == credentials.userId) { if (otherUserId == userId) {
return checkSelfTrust() return checkSelfTrust()
} }
// I trust a user if I trust his master key // I trust a user if I trust his master key
@ -327,25 +323,25 @@ internal class DefaultCrossSigningService @Inject constructor(
// TODO what if the master key is signed by a device key that i have verified // TODO what if the master key is signed by a device key that i have verified
// First let's get my user key // First let's get my user key
val myCrossSigningInfo = cryptoStore.getCrossSigningInfo(credentials.userId) val myCrossSigningInfo = cryptoStore.getCrossSigningInfo(userId)
val myUserKey = myCrossSigningInfo?.userKey() val myUserKey = myCrossSigningInfo?.userKey()
?: return UserTrustResult.CrossSigningNotConfigured(credentials.userId) ?: return UserTrustResult.CrossSigningNotConfigured(userId)
if (!myCrossSigningInfo.isTrusted()) { if (!myCrossSigningInfo.isTrusted()) {
return UserTrustResult.KeysNotTrusted(myCrossSigningInfo) return UserTrustResult.KeysNotTrusted(myCrossSigningInfo)
} }
// Let's get the other user master key // Let's get the other user master key
val otherMasterKey = cryptoStore.getCrossSigningInfo(userId)?.masterKey() val otherMasterKey = cryptoStore.getCrossSigningInfo(otherUserId)?.masterKey()
?: return UserTrustResult.UnknownCrossSignatureInfo(userId) ?: return UserTrustResult.UnknownCrossSignatureInfo(otherUserId)
val masterKeySignaturesMadeByMyUserKey = otherMasterKey.signatures val masterKeySignaturesMadeByMyUserKey = otherMasterKey.signatures
?.get(credentials.userId) // Signatures made by me ?.get(userId) // Signatures made by me
?.get("ed25519:${myUserKey.unpaddedBase64PublicKey}") ?.get("ed25519:${myUserKey.unpaddedBase64PublicKey}")
if (masterKeySignaturesMadeByMyUserKey.isNullOrBlank()) { if (masterKeySignaturesMadeByMyUserKey.isNullOrBlank()) {
Timber.d("## CrossSigning checkUserTrust false for $userId, not signed by my UserSigningKey") Timber.d("## CrossSigning checkUserTrust false for $otherUserId, not signed by my UserSigningKey")
return UserTrustResult.KeyNotSigned(otherMasterKey) return UserTrustResult.KeyNotSigned(otherMasterKey)
} }
@ -363,12 +359,10 @@ internal class DefaultCrossSigningService @Inject constructor(
// Special case when it's me, // Special case when it's me,
// I have to check that MSK -> USK -> SSK // I have to check that MSK -> USK -> SSK
// and that MSK is trusted (i know the private key, or is signed by a trusted device) // and that MSK is trusted (i know the private key, or is signed by a trusted device)
val myCrossSigningInfo = cryptoStore.getCrossSigningInfo(userId)
val myUserId = credentials.userId
val myCrossSigningInfo = cryptoStore.getCrossSigningInfo(myUserId)
val myMasterKey = myCrossSigningInfo?.masterKey() val myMasterKey = myCrossSigningInfo?.masterKey()
?: return UserTrustResult.CrossSigningNotConfigured(myUserId) ?: return UserTrustResult.CrossSigningNotConfigured(userId)
// Is the master key trusted // Is the master key trusted
// 1) check if I know the private key // 1) check if I know the private key
@ -390,9 +384,9 @@ internal class DefaultCrossSigningService @Inject constructor(
olmPkSigning?.releaseSigning() olmPkSigning?.releaseSigning()
} else { } else {
// Maybe it's signed by a locally trusted device? // Maybe it's signed by a locally trusted device?
myMasterKey.signatures?.get(myUserId)?.forEach { (key, value) -> myMasterKey.signatures?.get(userId)?.forEach { (key, value) ->
val potentialDeviceId = if (key.startsWith("ed25519:")) key.substring("ed25519:".length) else key val potentialDeviceId = if (key.startsWith("ed25519:")) key.substring("ed25519:".length) else key
val potentialDevice = cryptoStore.getUserDevice(myUserId, potentialDeviceId) val potentialDevice = cryptoStore.getUserDevice(userId, potentialDeviceId)
if (potentialDevice != null && potentialDevice.isVerified) { if (potentialDevice != null && potentialDevice.isVerified) {
// Check signature validity? // Check signature validity?
try { try {
@ -412,10 +406,10 @@ internal class DefaultCrossSigningService @Inject constructor(
} }
val myUserKey = myCrossSigningInfo.userKey() val myUserKey = myCrossSigningInfo.userKey()
?: return UserTrustResult.CrossSigningNotConfigured(myUserId) ?: return UserTrustResult.CrossSigningNotConfigured(userId)
val userKeySignaturesMadeByMyMasterKey = myUserKey.signatures val userKeySignaturesMadeByMyMasterKey = myUserKey.signatures
?.get(myUserId) // Signatures made by me ?.get(userId) // Signatures made by me
?.get("ed25519:${myMasterKey.unpaddedBase64PublicKey}") ?.get("ed25519:${myMasterKey.unpaddedBase64PublicKey}")
if (userKeySignaturesMadeByMyMasterKey.isNullOrBlank()) { if (userKeySignaturesMadeByMyMasterKey.isNullOrBlank()) {
@ -431,29 +425,29 @@ internal class DefaultCrossSigningService @Inject constructor(
} }
val mySSKey = myCrossSigningInfo.selfSigningKey() val mySSKey = myCrossSigningInfo.selfSigningKey()
?: return UserTrustResult.CrossSigningNotConfigured(myUserId) ?: return UserTrustResult.CrossSigningNotConfigured(userId)
val SSKeySignaturesMadeByMyMasterKey = mySSKey.signatures val ssKeySignaturesMadeByMyMasterKey = mySSKey.signatures
?.get(myUserId) // Signatures made by me ?.get(userId) // Signatures made by me
?.get("ed25519:${myMasterKey.unpaddedBase64PublicKey}") ?.get("ed25519:${myMasterKey.unpaddedBase64PublicKey}")
if (SSKeySignaturesMadeByMyMasterKey.isNullOrBlank()) { if (ssKeySignaturesMadeByMyMasterKey.isNullOrBlank()) {
Timber.d("## CrossSigning checkUserTrust false for $userId, SSK not signed by MSK") Timber.d("## CrossSigning checkUserTrust false for $userId, SSK not signed by MSK")
return UserTrustResult.KeyNotSigned(mySSKey) return UserTrustResult.KeyNotSigned(mySSKey)
} }
// Check that Alice USK signature of Alice MSK is valid // Check that Alice USK signature of Alice MSK is valid
try { try {
olmUtility!!.verifyEd25519Signature(SSKeySignaturesMadeByMyMasterKey, myMasterKey.unpaddedBase64PublicKey, mySSKey.canonicalSignable()) olmUtility!!.verifyEd25519Signature(ssKeySignaturesMadeByMyMasterKey, myMasterKey.unpaddedBase64PublicKey, mySSKey.canonicalSignable())
} catch (failure: Throwable) { } catch (failure: Throwable) {
return UserTrustResult.InvalidSignature(mySSKey, SSKeySignaturesMadeByMyMasterKey) return UserTrustResult.InvalidSignature(mySSKey, ssKeySignaturesMadeByMyMasterKey)
} }
return UserTrustResult.Success return UserTrustResult.Success
} }
override fun getUserCrossSigningKeys(userId: String): MXCrossSigningInfo? { override fun getUserCrossSigningKeys(otherUserId: String): MXCrossSigningInfo? {
return cryptoStore.getCrossSigningInfo(userId) return cryptoStore.getCrossSigningInfo(otherUserId)
} }
override fun getLiveCrossSigningKeys(userId: String): LiveData<Optional<MXCrossSigningInfo>> { override fun getLiveCrossSigningKeys(userId: String): LiveData<Optional<MXCrossSigningInfo>> {
@ -468,15 +462,15 @@ internal class DefaultCrossSigningService @Inject constructor(
return checkSelfTrust().isVerified() && cryptoStore.getCrossSigningPrivateKeys()?.selfSigned != null return checkSelfTrust().isVerified() && cryptoStore.getCrossSigningPrivateKeys()?.selfSigned != null
} }
override fun trustUser(userId: String, callback: MatrixCallback<Unit>) { override fun trustUser(otherUserId: String, callback: MatrixCallback<Unit>) {
Timber.d("## CrossSigning - Mark user $userId as trusted ") Timber.d("## CrossSigning - Mark user $userId as trusted ")
// We should have this user keys // We should have this user keys
val otherMasterKeys = getUserCrossSigningKeys(userId)?.masterKey() val otherMasterKeys = getUserCrossSigningKeys(otherUserId)?.masterKey()
if (otherMasterKeys == null) { if (otherMasterKeys == null) {
callback.onFailure(Throwable("## CrossSigning - Other master signing key is not known")) callback.onFailure(Throwable("## CrossSigning - Other master signing key is not known"))
return return
} }
val myKeys = getUserCrossSigningKeys(credentials.userId) val myKeys = getUserCrossSigningKeys(userId)
if (myKeys == null) { if (myKeys == null) {
callback.onFailure(Throwable("## CrossSigning - CrossSigning is not setup for this account")) callback.onFailure(Throwable("## CrossSigning - CrossSigning is not setup for this account"))
return return
@ -487,7 +481,7 @@ internal class DefaultCrossSigningService @Inject constructor(
return return
} }
// Sign the other MasterKey with our UserSiging key // Sign the other MasterKey with our UserSigning key
val newSignature = JsonCanonicalizer.getCanonicalJson(Map::class.java, val newSignature = JsonCanonicalizer.getCanonicalJson(Map::class.java,
otherMasterKeys.signalableJSONDictionary()).let { userPkSigning?.sign(it) } otherMasterKeys.signalableJSONDictionary()).let { userPkSigning?.sign(it) }
@ -497,12 +491,12 @@ internal class DefaultCrossSigningService @Inject constructor(
return return
} }
cryptoStore.setUserKeysAsTrusted(userId, true) cryptoStore.setUserKeysAsTrusted(otherUserId, true)
// TODO update local copy with new signature directly here? kind of local echo of trust? // TODO update local copy with new signature directly here? kind of local echo of trust?
Timber.d("## CrossSigning - Upload signature of $userId MSK signed by USK") Timber.d("## CrossSigning - Upload signature of $userId MSK signed by USK")
val uploadQuery = UploadSignatureQueryBuilder() val uploadQuery = UploadSignatureQueryBuilder()
.withSigningKeyInfo(otherMasterKeys.copyForSignature(credentials.userId, userPubKey, newSignature)) .withSigningKeyInfo(otherMasterKeys.copyForSignature(userId, userPubKey, newSignature))
.build() .build()
uploadSignaturesTask.configureWith(UploadSignaturesTask.Params(uploadQuery)) { uploadSignaturesTask.configureWith(UploadSignaturesTask.Params(uploadQuery)) {
this.callback = callback this.callback = callback
@ -511,13 +505,13 @@ internal class DefaultCrossSigningService @Inject constructor(
override fun signDevice(deviceId: String, callback: MatrixCallback<Unit>) { override fun signDevice(deviceId: String, callback: MatrixCallback<Unit>) {
// This device should be yours // This device should be yours
val device = cryptoStore.getUserDevice(credentials.userId, deviceId) val device = cryptoStore.getUserDevice(userId, deviceId)
if (device == null) { if (device == null) {
callback.onFailure(IllegalArgumentException("This device [$deviceId] is not known, or not yours")) callback.onFailure(IllegalArgumentException("This device [$deviceId] is not known, or not yours"))
return return
} }
val myKeys = getUserCrossSigningKeys(credentials.userId) val myKeys = getUserCrossSigningKeys(userId)
if (myKeys == null) { if (myKeys == null) {
callback.onFailure(Throwable("CrossSigning is not setup for this account")) callback.onFailure(Throwable("CrossSigning is not setup for this account"))
return return
@ -539,7 +533,7 @@ internal class DefaultCrossSigningService @Inject constructor(
} }
val toUpload = device.copy( val toUpload = device.copy(
signatures = mapOf( signatures = mapOf(
credentials.userId userId
to to
mapOf( mapOf(
"ed25519:$ssPubKey" to newSignature "ed25519:$ssPubKey" to newSignature
@ -555,17 +549,17 @@ internal class DefaultCrossSigningService @Inject constructor(
}.executeBy(taskExecutor) }.executeBy(taskExecutor)
} }
override fun checkDeviceTrust(userId: String, deviceId: String, locallyTrusted: Boolean?): DeviceTrustResult { override fun checkDeviceTrust(otherUserId: String, otherDeviceId: String, locallyTrusted: Boolean?): DeviceTrustResult {
val otherDevice = cryptoStore.getUserDevice(userId, deviceId) val otherDevice = cryptoStore.getUserDevice(otherUserId, otherDeviceId)
?: return DeviceTrustResult.UnknownDevice(deviceId) ?: return DeviceTrustResult.UnknownDevice(otherDeviceId)
val myKeys = getUserCrossSigningKeys(credentials.userId) val myKeys = getUserCrossSigningKeys(userId)
?: return legacyFallbackTrust(locallyTrusted, DeviceTrustResult.CrossSigningNotConfigured(credentials.userId)) ?: return legacyFallbackTrust(locallyTrusted, DeviceTrustResult.CrossSigningNotConfigured(userId))
if (!myKeys.isTrusted()) return legacyFallbackTrust(locallyTrusted, DeviceTrustResult.KeysNotTrusted(myKeys)) if (!myKeys.isTrusted()) return legacyFallbackTrust(locallyTrusted, DeviceTrustResult.KeysNotTrusted(myKeys))
val otherKeys = getUserCrossSigningKeys(userId) val otherKeys = getUserCrossSigningKeys(otherUserId)
?: return legacyFallbackTrust(locallyTrusted, DeviceTrustResult.CrossSigningNotConfigured(userId)) ?: return legacyFallbackTrust(locallyTrusted, DeviceTrustResult.CrossSigningNotConfigured(otherUserId))
// TODO should we force verification ? // TODO should we force verification ?
if (!otherKeys.isTrusted()) return legacyFallbackTrust(locallyTrusted, DeviceTrustResult.KeysNotTrusted(otherKeys)) if (!otherKeys.isTrusted()) return legacyFallbackTrust(locallyTrusted, DeviceTrustResult.KeysNotTrusted(otherKeys))
@ -589,15 +583,15 @@ internal class DefaultCrossSigningService @Inject constructor(
* *
*/ */
val otherSSKSignature = otherDevice.signatures?.get(userId)?.get("ed25519:${otherKeys.selfSigningKey()?.unpaddedBase64PublicKey}") val otherSSKSignature = otherDevice.signatures?.get(otherUserId)?.get("ed25519:${otherKeys.selfSigningKey()?.unpaddedBase64PublicKey}")
?: return legacyFallbackTrust(locallyTrusted, DeviceTrustResult.MissingDeviceSignature(deviceId, otherKeys.selfSigningKey()?.unpaddedBase64PublicKey ?: return legacyFallbackTrust(locallyTrusted, DeviceTrustResult.MissingDeviceSignature(otherDeviceId, otherKeys.selfSigningKey()?.unpaddedBase64PublicKey
?: "")) ?: ""))
// Check bob's device is signed by bob's SSK // Check bob's device is signed by bob's SSK
try { try {
olmUtility!!.verifyEd25519Signature(otherSSKSignature, otherKeys.selfSigningKey()?.unpaddedBase64PublicKey, otherDevice.canonicalSignable()) olmUtility!!.verifyEd25519Signature(otherSSKSignature, otherKeys.selfSigningKey()?.unpaddedBase64PublicKey, otherDevice.canonicalSignable())
} catch (e: Throwable) { } catch (e: Throwable) {
return legacyFallbackTrust(locallyTrusted, DeviceTrustResult.InvalidDeviceSignature(deviceId, otherSSKSignature, e)) return legacyFallbackTrust(locallyTrusted, DeviceTrustResult.InvalidDeviceSignature(otherDeviceId, otherSSKSignature, e))
} }
return DeviceTrustResult.Success(DeviceTrustLevel(crossSigningVerified = true, locallyVerified = locallyTrusted)) return DeviceTrustResult.Success(DeviceTrustLevel(crossSigningVerified = true, locallyVerified = locallyTrusted))
@ -614,19 +608,19 @@ internal class DefaultCrossSigningService @Inject constructor(
override fun onUsersDeviceUpdate(users: List<String>) { override fun onUsersDeviceUpdate(users: List<String>) {
Timber.d("## CrossSigning - onUsersDeviceUpdate for ${users.size} users") Timber.d("## CrossSigning - onUsersDeviceUpdate for ${users.size} users")
users.forEach { userId -> users.forEach { otherUserId ->
checkUserTrust(userId).let { checkUserTrust(otherUserId).let {
Timber.d("## CrossSigning - update trust for ${userId} , verified=${it.isVerified()}") Timber.d("## CrossSigning - update trust for $otherUserId , verified=${it.isVerified()}")
cryptoStore.setUserKeysAsTrusted(userId, it.isVerified()) cryptoStore.setUserKeysAsTrusted(otherUserId, it.isVerified())
} }
// TODO if my keys have changes, i should recheck all devices of all users? // TODO if my keys have changes, i should recheck all devices of all users?
val devices = cryptoStore.getUserDeviceList(userId) val devices = cryptoStore.getUserDeviceList(otherUserId)
devices?.forEach { device -> devices?.forEach { device ->
val updatedTrust = checkDeviceTrust(userId, device.deviceId, device.trustLevel?.isLocallyVerified() ?: false) val updatedTrust = checkDeviceTrust(otherUserId, device.deviceId, device.trustLevel?.isLocallyVerified() ?: false)
Timber.d("## CrossSigning - update trust for device ${device.deviceId} of user ${userId} , verified=$updatedTrust") Timber.d("## CrossSigning - update trust for device ${device.deviceId} of user $otherUserId , verified=$updatedTrust")
cryptoStore.setDeviceTrust(userId, device.deviceId, updatedTrust.isCrossSignedVerified(), updatedTrust.isLocallyVerified()) cryptoStore.setDeviceTrust(otherUserId, device.deviceId, updatedTrust.isCrossSignedVerified(), updatedTrust.isLocallyVerified())
} }
} }
} }