Fix verify with passphrase own device not trusted

This commit is contained in:
Valere 2021-11-19 19:38:10 +01:00
parent 2167564812
commit f0f64d8380
9 changed files with 63 additions and 46 deletions

View file

@ -183,8 +183,8 @@ class XSigningTest : InstrumentedTest {
assertNotNull("Bob Second device should be known and persisted from first", bobSecondDevicePOVFirstDevice)
// Manually mark it as trusted from first session
mTestHelper.doSync<Unit> {
bobSession.cryptoService().crossSigningService().trustDevice(bobSecondDeviceId, it)
mTestHelper.runBlockingTest {
bobSession.cryptoService().crossSigningService().trustDevice(bobSecondDeviceId)
}
// Now alice should cross trust bob's second device

View file

@ -103,7 +103,7 @@ class KeyShareTests : InstrumentedTest {
val outgoingRequestsBefore = aliceSession2.cryptoService().getOutgoingRoomKeyRequests()
// Try to request
aliceSession2.cryptoService().requestRoomKeyForEvent(receivedEvent.root)
aliceSession2.cryptoService().reRequestRoomKeyForEvent(receivedEvent.root)
val waitLatch = CountDownLatch(1)
val eventMegolmSessionId = receivedEvent.root.content.toModel<EncryptedEventContent>()?.sessionId

View file

@ -24,7 +24,6 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.NoOpMatrixCallback
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
import org.matrix.android.sdk.api.session.events.model.EventType
@ -217,8 +216,10 @@ class WithHeldTests : InstrumentedTest {
mCryptoTestHelper.initializeCrossSigning(bobSecondSession)
// Trust bob second device from Alice POV
aliceSession.cryptoService().crossSigningService().trustDevice(bobSecondSession.sessionParams.deviceId!!, NoOpMatrixCallback())
bobSecondSession.cryptoService().crossSigningService().trustDevice(aliceSession.sessionParams.deviceId!!, NoOpMatrixCallback())
mTestHelper.runBlockingTest {
aliceSession.cryptoService().crossSigningService().trustDevice(bobSecondSession.sessionParams.deviceId!!)
bobSecondSession.cryptoService().crossSigningService().trustDevice(aliceSession.sessionParams.deviceId!!)
}
var sessionId: String? = null
// Check that the

View file

@ -61,7 +61,7 @@ interface CrossSigningService {
* This will check if the injected private cross signing keys match the public ones provided
* by the server and if they do so
*/
fun checkTrustFromPrivateKeys(masterKeyPrivateKey: String?,
suspend fun checkTrustFromPrivateKeys(masterKeyPrivateKey: String?,
uskKeyPrivateKey: String?,
sskPrivateKey: String?): UserTrustResult
@ -102,8 +102,8 @@ interface CrossSigningService {
/**
* Sign one of your devices and upload the signature
*/
fun trustDevice(deviceId: String,
callback: MatrixCallback<Unit>)
@Throws
suspend fun trustDevice(deviceId: String)
suspend fun shieldForGroup(userIds: List<String>): RoomEncryptionTrustLevel

View file

@ -554,9 +554,17 @@ internal class OlmMachine(
UserIdentity(identity.userId, masterKey, selfSigningKey, this, this.requestSender)
}
is RustUserIdentity.Own -> {
val masterKey = adapter.fromJson(identity.masterKey)!!.toCryptoModel()
val selfSigningKey = adapter.fromJson(identity.selfSigningKey)!!.toCryptoModel()
val userSigningKey = adapter.fromJson(identity.userSigningKey)!!.toCryptoModel()
val verified = this.inner().isIdentityVerified(userId)
val masterKey = adapter.fromJson(identity.masterKey)!!.toCryptoModel().apply {
trustLevel = DeviceTrustLevel(verified, verified)
}
val selfSigningKey = adapter.fromJson(identity.selfSigningKey)!!.toCryptoModel().apply {
trustLevel = DeviceTrustLevel(verified, verified)
}
val userSigningKey = adapter.fromJson(identity.userSigningKey)!!.toCryptoModel().apply {
trustLevel = DeviceTrustLevel(verified, verified)
}
OwnUserIdentity(
identity.userId,
@ -823,13 +831,28 @@ internal class OlmMachine(
suspend fun importCrossSigningKeys(export: PrivateKeysInfo): UserTrustResult {
val rustExport = CrossSigningKeyExport(export.master, export.selfSigned, export.user)
var result: UserTrustResult
withContext(Dispatchers.IO) {
result = try {
inner.importCrossSigningKeys(rustExport)
}
this.updateLivePrivateKeys()
// TODO map the errors from importCrossSigningKeys to the UserTrustResult
return UserTrustResult.Success
// Sign the cross signing keys with our device
// Fail silently if signature upload fails??
try {
getIdentity(userId())?.verify()
} catch (failure: Throwable) {
Timber.e(failure, "Failed to sign x-keys with own device")
}
UserTrustResult.Success
} catch (failure: Exception) {
// KeyImportError?
UserTrustResult.Failure(failure.localizedMessage)
}
}
withContext(Dispatchers.Main) {
this@OlmMachine.updateLivePrivateKeys()
}
return result
}
suspend fun sign(message: String): Map<String, Map<String, String>> {

View file

@ -73,7 +73,7 @@ internal class RustCrossSigningService @Inject constructor(
if (verified) {
UserTrustResult.Success
} else {
UserTrustResult.UnknownCrossSignatureInfo(otherUserId)
UserTrustResult.Failure("failed to verify $otherUserId")
}
} else {
UserTrustResult.CrossSigningNotConfigured(otherUserId)
@ -94,15 +94,13 @@ internal class RustCrossSigningService @Inject constructor(
* This will check if the injected private cross signing keys match the public ones provided
* by the server and if they do so
*/
override fun checkTrustFromPrivateKeys(
override suspend fun checkTrustFromPrivateKeys(
masterKeyPrivateKey: String?,
uskKeyPrivateKey: String?,
sskPrivateKey: String?
): UserTrustResult {
val export = PrivateKeysInfo(masterKeyPrivateKey, sskPrivateKey, uskKeyPrivateKey)
return runBlocking {
olmMachineProvider.olmMachine.importCrossSigningKeys(export)
}
return olmMachine.importCrossSigningKeys(export)
}
/**
@ -171,19 +169,19 @@ internal class RustCrossSigningService @Inject constructor(
/**
* Sign one of your devices and upload the signature
*/
override fun trustDevice(deviceId: String, callback: MatrixCallback<Unit>) {
val device = runBlocking { olmMachine.getDevice(olmMachine.userId(), deviceId) }
override suspend fun trustDevice(deviceId: String) {
val device = olmMachine.getDevice(olmMachine.userId(), deviceId)
return if (device != null) {
val verified = runBlocking { device.verify() }
val verified = device.verify()
if (verified) {
callback.onSuccess(Unit)
return
} else {
callback.onFailure(IllegalArgumentException("This device [$deviceId] is not known, or not yours"))
throw IllegalArgumentException("This device [$deviceId] is not known, or not yours")
}
} else {
callback.onFailure(IllegalArgumentException("This device [$deviceId] is not known"))
throw IllegalArgumentException("This device [$deviceId] is not known")
}
}

View file

@ -16,9 +16,6 @@
package org.matrix.android.sdk.internal.crypto.crosssigning
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
import org.matrix.android.sdk.internal.crypto.model.CryptoCrossSigningKey
sealed class UserTrustResult {
object Success : UserTrustResult()
@ -26,10 +23,11 @@ sealed class UserTrustResult {
// data class UnknownDevice(val deviceID: String) : UserTrustResult()
data class CrossSigningNotConfigured(val userID: String) : UserTrustResult()
data class UnknownCrossSignatureInfo(val userID: String) : UserTrustResult()
data class KeysNotTrusted(val key: MXCrossSigningInfo) : UserTrustResult()
data class KeyNotSigned(val key: CryptoCrossSigningKey) : UserTrustResult()
data class InvalidSignature(val key: CryptoCrossSigningKey, val signature: String) : UserTrustResult()
data class Failure(val message: String) : UserTrustResult()
// data class UnknownCrossSignatureInfo(val userID: String) : UserTrustResult()
// data class KeysNotTrusted(val key: MXCrossSigningInfo) : UserTrustResult()
// data class KeyNotSigned(val key: CryptoCrossSigningKey) : UserTrustResult()
// data class InvalidSignature(val key: CryptoCrossSigningKey, val signature: String) : UserTrustResult()
}
fun UserTrustResult.isVerified() = this is UserTrustResult.Success

View file

@ -33,7 +33,6 @@ import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
@ -372,7 +371,8 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
try {
action.cypherData.fromBase64().inputStream().use { ins ->
val res = session.loadSecureSecret<Map<String, String>>(ins, action.alias)
val trustResult = session.cryptoService().crossSigningService().checkTrustFromPrivateKeys(
val crossSigningService = session.cryptoService().crossSigningService()
val trustResult = crossSigningService.checkTrustFromPrivateKeys(
res?.get(MASTER_KEY_SSSS_NAME),
res?.get(USER_SIGNING_KEY_SSSS_NAME),
res?.get(SELF_SIGNING_KEY_SSSS_NAME)
@ -380,12 +380,11 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
if (trustResult.isVerified()) {
// Sign this device and upload the signature
session.sessionParams.deviceId?.let { deviceId ->
session.cryptoService()
.crossSigningService().trustDevice(deviceId, object : MatrixCallback<Unit> {
override fun onFailure(failure: Throwable) {
try {
crossSigningService.trustDevice(deviceId)
} catch (failure: Exception) {
Timber.w(failure, "Failed to sign my device after recovery")
}
})
}
setState {

View file

@ -261,9 +261,7 @@ class DevicesViewModel @AssistedInject constructor(
viewModelScope.launch {
if (state.hasAccountCrossSigning) {
try {
awaitCallback<Unit> {
session.cryptoService().crossSigningService().trustDevice(action.cryptoDeviceInfo.deviceId, it)
}
session.cryptoService().crossSigningService().trustDevice(action.cryptoDeviceInfo.deviceId)
} catch (failure: Throwable) {
Timber.e("Failed to manually cross sign device ${action.cryptoDeviceInfo.deviceId} : ${failure.localizedMessage}")
_viewEvents.post(DevicesViewEvents.Failure(failure))