mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-12-28 20:08:50 +03:00
Fix verify with passphrase own device not trusted
This commit is contained in:
parent
2167564812
commit
f0f64d8380
9 changed files with 63 additions and 46 deletions
|
@ -183,8 +183,8 @@ class XSigningTest : InstrumentedTest {
|
||||||
assertNotNull("Bob Second device should be known and persisted from first", bobSecondDevicePOVFirstDevice)
|
assertNotNull("Bob Second device should be known and persisted from first", bobSecondDevicePOVFirstDevice)
|
||||||
|
|
||||||
// Manually mark it as trusted from first session
|
// Manually mark it as trusted from first session
|
||||||
mTestHelper.doSync<Unit> {
|
mTestHelper.runBlockingTest {
|
||||||
bobSession.cryptoService().crossSigningService().trustDevice(bobSecondDeviceId, it)
|
bobSession.cryptoService().crossSigningService().trustDevice(bobSecondDeviceId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now alice should cross trust bob's second device
|
// Now alice should cross trust bob's second device
|
||||||
|
|
|
@ -103,7 +103,7 @@ class KeyShareTests : InstrumentedTest {
|
||||||
|
|
||||||
val outgoingRequestsBefore = aliceSession2.cryptoService().getOutgoingRoomKeyRequests()
|
val outgoingRequestsBefore = aliceSession2.cryptoService().getOutgoingRoomKeyRequests()
|
||||||
// Try to request
|
// Try to request
|
||||||
aliceSession2.cryptoService().requestRoomKeyForEvent(receivedEvent.root)
|
aliceSession2.cryptoService().reRequestRoomKeyForEvent(receivedEvent.root)
|
||||||
|
|
||||||
val waitLatch = CountDownLatch(1)
|
val waitLatch = CountDownLatch(1)
|
||||||
val eventMegolmSessionId = receivedEvent.root.content.toModel<EncryptedEventContent>()?.sessionId
|
val eventMegolmSessionId = receivedEvent.root.content.toModel<EncryptedEventContent>()?.sessionId
|
||||||
|
|
|
@ -24,7 +24,6 @@ import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.junit.runners.MethodSorters
|
import org.junit.runners.MethodSorters
|
||||||
import org.matrix.android.sdk.InstrumentedTest
|
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.extensions.tryOrNull
|
||||||
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
|
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
|
@ -217,8 +216,10 @@ class WithHeldTests : InstrumentedTest {
|
||||||
mCryptoTestHelper.initializeCrossSigning(bobSecondSession)
|
mCryptoTestHelper.initializeCrossSigning(bobSecondSession)
|
||||||
|
|
||||||
// Trust bob second device from Alice POV
|
// Trust bob second device from Alice POV
|
||||||
aliceSession.cryptoService().crossSigningService().trustDevice(bobSecondSession.sessionParams.deviceId!!, NoOpMatrixCallback())
|
mTestHelper.runBlockingTest {
|
||||||
bobSecondSession.cryptoService().crossSigningService().trustDevice(aliceSession.sessionParams.deviceId!!, NoOpMatrixCallback())
|
aliceSession.cryptoService().crossSigningService().trustDevice(bobSecondSession.sessionParams.deviceId!!)
|
||||||
|
bobSecondSession.cryptoService().crossSigningService().trustDevice(aliceSession.sessionParams.deviceId!!)
|
||||||
|
}
|
||||||
|
|
||||||
var sessionId: String? = null
|
var sessionId: String? = null
|
||||||
// Check that the
|
// Check that the
|
||||||
|
|
|
@ -61,7 +61,7 @@ interface CrossSigningService {
|
||||||
* This will check if the injected private cross signing keys match the public ones provided
|
* This will check if the injected private cross signing keys match the public ones provided
|
||||||
* by the server and if they do so
|
* by the server and if they do so
|
||||||
*/
|
*/
|
||||||
fun checkTrustFromPrivateKeys(masterKeyPrivateKey: String?,
|
suspend fun checkTrustFromPrivateKeys(masterKeyPrivateKey: String?,
|
||||||
uskKeyPrivateKey: String?,
|
uskKeyPrivateKey: String?,
|
||||||
sskPrivateKey: String?): UserTrustResult
|
sskPrivateKey: String?): UserTrustResult
|
||||||
|
|
||||||
|
@ -102,8 +102,8 @@ interface CrossSigningService {
|
||||||
/**
|
/**
|
||||||
* Sign one of your devices and upload the signature
|
* Sign one of your devices and upload the signature
|
||||||
*/
|
*/
|
||||||
fun trustDevice(deviceId: String,
|
@Throws
|
||||||
callback: MatrixCallback<Unit>)
|
suspend fun trustDevice(deviceId: String)
|
||||||
|
|
||||||
suspend fun shieldForGroup(userIds: List<String>): RoomEncryptionTrustLevel
|
suspend fun shieldForGroup(userIds: List<String>): RoomEncryptionTrustLevel
|
||||||
|
|
||||||
|
|
|
@ -554,9 +554,17 @@ internal class OlmMachine(
|
||||||
UserIdentity(identity.userId, masterKey, selfSigningKey, this, this.requestSender)
|
UserIdentity(identity.userId, masterKey, selfSigningKey, this, this.requestSender)
|
||||||
}
|
}
|
||||||
is RustUserIdentity.Own -> {
|
is RustUserIdentity.Own -> {
|
||||||
val masterKey = adapter.fromJson(identity.masterKey)!!.toCryptoModel()
|
val verified = this.inner().isIdentityVerified(userId)
|
||||||
val selfSigningKey = adapter.fromJson(identity.selfSigningKey)!!.toCryptoModel()
|
|
||||||
val userSigningKey = adapter.fromJson(identity.userSigningKey)!!.toCryptoModel()
|
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(
|
OwnUserIdentity(
|
||||||
identity.userId,
|
identity.userId,
|
||||||
|
@ -823,13 +831,28 @@ internal class OlmMachine(
|
||||||
suspend fun importCrossSigningKeys(export: PrivateKeysInfo): UserTrustResult {
|
suspend fun importCrossSigningKeys(export: PrivateKeysInfo): UserTrustResult {
|
||||||
val rustExport = CrossSigningKeyExport(export.master, export.selfSigned, export.user)
|
val rustExport = CrossSigningKeyExport(export.master, export.selfSigned, export.user)
|
||||||
|
|
||||||
|
var result: UserTrustResult
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
|
result = try {
|
||||||
inner.importCrossSigningKeys(rustExport)
|
inner.importCrossSigningKeys(rustExport)
|
||||||
}
|
|
||||||
|
|
||||||
this.updateLivePrivateKeys()
|
// Sign the cross signing keys with our device
|
||||||
// TODO map the errors from importCrossSigningKeys to the UserTrustResult
|
// Fail silently if signature upload fails??
|
||||||
return UserTrustResult.Success
|
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>> {
|
suspend fun sign(message: String): Map<String, Map<String, String>> {
|
||||||
|
|
|
@ -73,7 +73,7 @@ internal class RustCrossSigningService @Inject constructor(
|
||||||
if (verified) {
|
if (verified) {
|
||||||
UserTrustResult.Success
|
UserTrustResult.Success
|
||||||
} else {
|
} else {
|
||||||
UserTrustResult.UnknownCrossSignatureInfo(otherUserId)
|
UserTrustResult.Failure("failed to verify $otherUserId")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
UserTrustResult.CrossSigningNotConfigured(otherUserId)
|
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
|
* This will check if the injected private cross signing keys match the public ones provided
|
||||||
* by the server and if they do so
|
* by the server and if they do so
|
||||||
*/
|
*/
|
||||||
override fun checkTrustFromPrivateKeys(
|
override suspend fun checkTrustFromPrivateKeys(
|
||||||
masterKeyPrivateKey: String?,
|
masterKeyPrivateKey: String?,
|
||||||
uskKeyPrivateKey: String?,
|
uskKeyPrivateKey: String?,
|
||||||
sskPrivateKey: String?
|
sskPrivateKey: String?
|
||||||
): UserTrustResult {
|
): UserTrustResult {
|
||||||
val export = PrivateKeysInfo(masterKeyPrivateKey, sskPrivateKey, uskKeyPrivateKey)
|
val export = PrivateKeysInfo(masterKeyPrivateKey, sskPrivateKey, uskKeyPrivateKey)
|
||||||
return runBlocking {
|
return olmMachine.importCrossSigningKeys(export)
|
||||||
olmMachineProvider.olmMachine.importCrossSigningKeys(export)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -171,19 +169,19 @@ internal class RustCrossSigningService @Inject constructor(
|
||||||
/**
|
/**
|
||||||
* Sign one of your devices and upload the signature
|
* Sign one of your devices and upload the signature
|
||||||
*/
|
*/
|
||||||
override fun trustDevice(deviceId: String, callback: MatrixCallback<Unit>) {
|
override suspend fun trustDevice(deviceId: String) {
|
||||||
val device = runBlocking { olmMachine.getDevice(olmMachine.userId(), deviceId) }
|
val device = olmMachine.getDevice(olmMachine.userId(), deviceId)
|
||||||
|
|
||||||
return if (device != null) {
|
return if (device != null) {
|
||||||
val verified = runBlocking { device.verify() }
|
val verified = device.verify()
|
||||||
|
|
||||||
if (verified) {
|
if (verified) {
|
||||||
callback.onSuccess(Unit)
|
return
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
callback.onFailure(IllegalArgumentException("This device [$deviceId] is not known"))
|
throw IllegalArgumentException("This device [$deviceId] is not known")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,6 @@
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.crypto.crosssigning
|
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 {
|
sealed class UserTrustResult {
|
||||||
object Success : UserTrustResult()
|
object Success : UserTrustResult()
|
||||||
|
|
||||||
|
@ -26,10 +23,11 @@ sealed class UserTrustResult {
|
||||||
// data class UnknownDevice(val deviceID: String) : UserTrustResult()
|
// data class UnknownDevice(val deviceID: String) : UserTrustResult()
|
||||||
data class CrossSigningNotConfigured(val userID: String) : UserTrustResult()
|
data class CrossSigningNotConfigured(val userID: String) : UserTrustResult()
|
||||||
|
|
||||||
data class UnknownCrossSignatureInfo(val userID: String) : UserTrustResult()
|
data class Failure(val message: String) : UserTrustResult()
|
||||||
data class KeysNotTrusted(val key: MXCrossSigningInfo) : UserTrustResult()
|
// data class UnknownCrossSignatureInfo(val userID: String) : UserTrustResult()
|
||||||
data class KeyNotSigned(val key: CryptoCrossSigningKey) : UserTrustResult()
|
// data class KeysNotTrusted(val key: MXCrossSigningInfo) : UserTrustResult()
|
||||||
data class InvalidSignature(val key: CryptoCrossSigningKey, val signature: String) : 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
|
fun UserTrustResult.isVerified() = this is UserTrustResult.Success
|
||||||
|
|
|
@ -33,7 +33,6 @@ import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
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.Session
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
|
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
|
import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
|
||||||
|
@ -372,7 +371,8 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
||||||
try {
|
try {
|
||||||
action.cypherData.fromBase64().inputStream().use { ins ->
|
action.cypherData.fromBase64().inputStream().use { ins ->
|
||||||
val res = session.loadSecureSecret<Map<String, String>>(ins, action.alias)
|
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(MASTER_KEY_SSSS_NAME),
|
||||||
res?.get(USER_SIGNING_KEY_SSSS_NAME),
|
res?.get(USER_SIGNING_KEY_SSSS_NAME),
|
||||||
res?.get(SELF_SIGNING_KEY_SSSS_NAME)
|
res?.get(SELF_SIGNING_KEY_SSSS_NAME)
|
||||||
|
@ -380,12 +380,11 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
||||||
if (trustResult.isVerified()) {
|
if (trustResult.isVerified()) {
|
||||||
// Sign this device and upload the signature
|
// Sign this device and upload the signature
|
||||||
session.sessionParams.deviceId?.let { deviceId ->
|
session.sessionParams.deviceId?.let { deviceId ->
|
||||||
session.cryptoService()
|
try {
|
||||||
.crossSigningService().trustDevice(deviceId, object : MatrixCallback<Unit> {
|
crossSigningService.trustDevice(deviceId)
|
||||||
override fun onFailure(failure: Throwable) {
|
} catch (failure: Exception) {
|
||||||
Timber.w(failure, "Failed to sign my device after recovery")
|
Timber.w(failure, "Failed to sign my device after recovery")
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setState {
|
setState {
|
||||||
|
|
|
@ -261,9 +261,7 @@ class DevicesViewModel @AssistedInject constructor(
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
if (state.hasAccountCrossSigning) {
|
if (state.hasAccountCrossSigning) {
|
||||||
try {
|
try {
|
||||||
awaitCallback<Unit> {
|
session.cryptoService().crossSigningService().trustDevice(action.cryptoDeviceInfo.deviceId)
|
||||||
session.cryptoService().crossSigningService().trustDevice(action.cryptoDeviceInfo.deviceId, it)
|
|
||||||
}
|
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
Timber.e("Failed to manually cross sign device ${action.cryptoDeviceInfo.deviceId} : ${failure.localizedMessage}")
|
Timber.e("Failed to manually cross sign device ${action.cryptoDeviceInfo.deviceId} : ${failure.localizedMessage}")
|
||||||
_viewEvents.post(DevicesViewEvents.Failure(failure))
|
_viewEvents.post(DevicesViewEvents.Failure(failure))
|
||||||
|
|
Loading…
Reference in a new issue