Request secret from mobile to web

This commit is contained in:
Valere 2020-03-09 17:08:43 +01:00
parent d3d6d44665
commit 5e2f888eaf
12 changed files with 102 additions and 88 deletions

View file

@ -69,6 +69,6 @@ interface CrossSigningService {
otherDeviceId: String,
locallyTrusted: Boolean?): DeviceTrustResult
fun onSecretSSKGossip(sskPrivateKey: String): Boolean
fun onSecretUSKGossip(uskPrivateKey: String): Boolean
fun onSecretSSKGossip(sskPrivateKey: String)
fun onSecretUSKGossip(uskPrivateKey: String)
}

View file

@ -49,7 +49,6 @@ import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAct
import im.vector.matrix.android.internal.crypto.algorithms.IMXEncrypting
import im.vector.matrix.android.internal.crypto.algorithms.megolm.MXMegolmEncryptionFactory
import im.vector.matrix.android.internal.crypto.algorithms.olm.MXOlmEncryptionFactory
import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult
import im.vector.matrix.android.internal.crypto.crosssigning.DefaultCrossSigningService
import im.vector.matrix.android.internal.crypto.crosssigning.DeviceTrustLevel
import im.vector.matrix.android.internal.crypto.keysbackup.DefaultKeysBackupService
@ -756,54 +755,35 @@ internal class DefaultCryptoService @Inject constructor(
return
}
val encryptedEventContent = event.getClearContent().toModel<EncryptedEventContent>()
?: return Unit.also {
Timber.e("## onSecretSend() :Received malformed secret send event")
}
val senderDevice = encryptedEventContent.senderKey
val device = senderDevice?.let { cryptoStore.getUserDevice(event.senderId, it) }
?: return Unit.also {
Timber.e("## processIncomingSecretShareRequest() : Received secret share request from unknown device $senderDevice")
}
try {
val result = decryptEvent(event, "gossip")
event.mxDecryptionResult = OlmDecryptionResult(
payload = result.clearEvent,
senderKey = result.senderCurve25519Key,
keysClaimed = result.claimedEd25519Key?.let { k -> mapOf("ed25519" to k) },
forwardingCurve25519KeyChain = result.forwardingCurve25519KeyChain
)
} catch (failure: Throwable) {
Timber.i("## onSecretSend() :Failed to decrypt secret share: $device")
}
val secretContent = event.getClearContent().toModel<SecretSendEventContent>() ?: return
val existingRequest = cryptoStore
.getPendingIncomingGossipingRequests()
.firstOrNull { it.requestId == secretContent.requestId } as? IncomingSecretShareRequest
.getOutgoingSecretKeyRequests().firstOrNull { it.requestId == secretContent.requestId }
if (existingRequest == null) {
Timber.i("## onSecretSend() :Received secret from unknown request id: ${secretContent.requestId} from device ")
Timber.i("## onSecretSend() : Ignore secret that was not requested: ${secretContent.requestId}")
return
}
if (device.isBlocked || !device.isVerified) {
// Ignore secrets from this
Timber.i("## onSecretSend() :Received secret from untrusted/blocked device: $device")
val deviceId = event.mxDecryptionResult?.payload?.get("sender_device") as? String
val device = deviceId?.let { cryptoStore.getUserDevice(event.senderId, it) }
if (device == null || !device.isVerified || device.isBlocked) {
// Ignore secret from untrusted session?
Timber.i("## onSecretSend() :Received secret from untrusted device $deviceId ")
return
}
when (existingRequest.secretName) {
// "m.key.self_signing",
SELF_SIGNING_KEY_SSSS_NAME -> {
if (device.trustLevel?.isLocallyVerified() == true) {
crossSigningService.onSecretSSKGossip(secretContent.secretValue)
return
}
}
// "m.key.user_signing",
USER_SIGNING_KEY_SSSS_NAME -> {
if (device.trustLevel?.isLocallyVerified() == true) {
cryptoStore.storePrivateKeysInfo(null, null, secretContent.secretValue)

View file

@ -65,9 +65,14 @@ internal class IncomingRoomKeyRequestManager @Inject constructor(
GossipingToDeviceObject.ACTION_SHARE_REQUEST -> {
if (event.getClearType() == EventType.REQUEST_SECRET) {
IncomingSecretShareRequest.fromEvent(event)?.let {
// save in DB
cryptoStore.storeIncomingGossipingRequest(it, ageLocalTs)
receiveGossipingRequests.add(it)
if (event.senderId == credentials.userId && it.deviceId == credentials.deviceId) {
// ignore, it was sent by me as *
Timber.v("## onGossipingRequestEvent type ${event.type} ignore remote echo")
} else {
// save in DB
cryptoStore.storeIncomingGossipingRequest(it, ageLocalTs)
receiveGossipingRequests.add(it)
}
}
} else if (event.getClearType() == EventType.ROOM_KEY_REQUEST) {
IncomingRoomKeyRequest.fromEvent(event)?.let {

View file

@ -43,7 +43,6 @@ import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import im.vector.matrix.android.internal.util.withoutPrefix
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.greenrobot.eventbus.EventBus
import org.matrix.olm.OlmPkSigning
import org.matrix.olm.OlmUtility
@ -300,56 +299,50 @@ internal class DefaultCrossSigningService @Inject constructor(
cryptoStore.clearOtherUserTrust()
}
override fun onSecretSSKGossip(sskPrivateKey: String): Boolean {
override fun onSecretSSKGossip(sskPrivateKey: String) {
Timber.i("## CrossSigning - onSecretSSKGossip")
return runBlocking(coroutineDispatchers.crypto) {
val mxCrossSigningInfo = getMyCrossSigningKeys() ?: return@runBlocking false
val mxCrossSigningInfo = getMyCrossSigningKeys() ?: return
sskPrivateKey.fromBase64()
.let { privateKeySeed ->
val pkSigning = OlmPkSigning()
try {
if (pkSigning.initWithSeed(privateKeySeed) == mxCrossSigningInfo.selfSigningKey()?.unpaddedBase64PublicKey) {
selfSigningPkSigning?.releaseSigning()
selfSigningPkSigning = pkSigning
Timber.i("## CrossSigning - Loading SSK success")
cryptoStore.storePrivateKeysInfo(null, null, sskPrivateKey)
return@runBlocking true
} else {
pkSigning.releaseSigning()
}
} catch (failure: Throwable) {
sskPrivateKey.fromBase64()
.let { privateKeySeed ->
val pkSigning = OlmPkSigning()
try {
if (pkSigning.initWithSeed(privateKeySeed) == mxCrossSigningInfo.selfSigningKey()?.unpaddedBase64PublicKey) {
selfSigningPkSigning?.releaseSigning()
selfSigningPkSigning = pkSigning
Timber.i("## CrossSigning - Loading SSK success")
cryptoStore.storePrivateKeysInfo(null, null, sskPrivateKey)
return
} else {
pkSigning.releaseSigning()
}
} catch (failure: Throwable) {
Timber.e("## CrossSigning - onSecretSSKGossip() ${failure.localizedMessage}")
pkSigning.releaseSigning()
}
return@runBlocking false
}
}
}
override fun onSecretUSKGossip(uskPrivateKey: String): Boolean {
Timber.i("## CrossSigning - onSecretUSKGossip")
return runBlocking(coroutineDispatchers.crypto) {
val mxCrossSigningInfo = getMyCrossSigningKeys() ?: return@runBlocking false
override fun onSecretUSKGossip(uskPrivateKey: String) {
val mxCrossSigningInfo = getMyCrossSigningKeys() ?: return
uskPrivateKey.fromBase64()
.let { privateKeySeed ->
val pkSigning = OlmPkSigning()
try {
if (pkSigning.initWithSeed(privateKeySeed) == mxCrossSigningInfo.selfSigningKey()?.unpaddedBase64PublicKey) {
userPkSigning?.releaseSigning()
userPkSigning = pkSigning
Timber.i("## CrossSigning - Loading USK success")
cryptoStore.storePrivateKeysInfo(null, uskPrivateKey, null)
return@runBlocking true
} else {
pkSigning.releaseSigning()
}
} catch (failure: Throwable) {
uskPrivateKey.fromBase64()
.let { privateKeySeed ->
val pkSigning = OlmPkSigning()
try {
if (pkSigning.initWithSeed(privateKeySeed) == mxCrossSigningInfo.selfSigningKey()?.unpaddedBase64PublicKey) {
userPkSigning?.releaseSigning()
userPkSigning = pkSigning
Timber.i("## CrossSigning - Loading USK success")
cryptoStore.storePrivateKeysInfo(null, uskPrivateKey, null)
return
} else {
pkSigning.releaseSigning()
}
} catch (failure: Throwable) {
pkSigning.releaseSigning()
}
return@runBlocking false
}
}
}
override fun checkTrustFromPrivateKeys(masterKeyPrivateKey: String?,
@ -767,7 +760,7 @@ internal class DefaultCrossSigningService @Inject constructor(
Timber.d("## CrossSigning - onUsersDeviceUpdate for ${userIds.size} users")
userIds.forEach { otherUserId ->
checkUserTrust(otherUserId).let {
Timber.d("## CrossSigning - update trust for $otherUserId , verified=${it.isVerified()}")
Timber.v("## CrossSigning - update trust for $otherUserId , verified=${it.isVerified()}")
setUserKeysAsTrusted(otherUserId, it.isVerified())
}
@ -775,7 +768,7 @@ internal class DefaultCrossSigningService @Inject constructor(
val devices = cryptoStore.getUserDeviceList(otherUserId)
devices?.forEach { device ->
val updatedTrust = checkDeviceTrust(otherUserId, device.deviceId, device.trustLevel?.isLocallyVerified() ?: false)
Timber.d("## CrossSigning - update trust for device ${device.deviceId} of user $otherUserId , verified=$updatedTrust")
Timber.v("## CrossSigning - update trust for device ${device.deviceId} of user $otherUserId , verified=$updatedTrust")
cryptoStore.setDeviceTrust(otherUserId, device.deviceId, updatedTrust.isCrossSignedVerified(), updatedTrust.isLocallyVerified())
}

View file

@ -446,6 +446,7 @@ internal interface IMXCryptoStore {
// Dev tools
fun getOutgoingRoomKeyRequests(): List<OutgoingRoomKeyRequest>
fun getOutgoingSecretKeyRequests(): List<OutgoingSecretRequest>
fun getOutgoingSecretRequest(secretName: String): OutgoingSecretRequest?
fun getIncomingRoomKeyRequests(): List<IncomingRoomKeyRequest>
fun getGossipingEventsTrail(): List<Event>

View file

@ -823,16 +823,13 @@ internal class RealmCryptoStore @Inject constructor(
}
override fun getOutgoingSecretRequest(secretName: String): OutgoingSecretRequest? {
// return monarchy.fetchAllCopiedSync { realm ->
// // realm.where<OutgoingGossipingRequestEntity>()
// // .equalTo(OutgoingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.SECRET.name)
// // .equalTo(GossipingEventEntityFields.SENDER, credentials.userId)
// // }.mapNotNull {
// // ContentMapper.map(it.content)?.toModel<OutgoingSecretRequest>()
// // }.firstOrNull {
// // it.secretName == secretName
// // }
TODO("not implemented")
return monarchy.fetchAllCopiedSync { realm ->
realm.where<OutgoingGossipingRequestEntity>()
.equalTo(OutgoingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.SECRET.name)
.equalTo(OutgoingGossipingRequestEntityFields.REQUESTED_INFO_STR, secretName)
}.mapNotNull {
it.toOutgoingGossipingRequest() as? OutgoingSecretRequest
}.firstOrNull()
}
override fun getIncomingRoomKeyRequests(): List<IncomingRoomKeyRequest> {
@ -1246,6 +1243,16 @@ internal class RealmCryptoStore @Inject constructor(
}).filterNotNull()
}
override fun getOutgoingSecretKeyRequests(): List<OutgoingSecretRequest> {
return monarchy.fetchAllMappedSync({ realm ->
realm
.where(OutgoingGossipingRequestEntity::class.java)
.equalTo(OutgoingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.SECRET.name)
}, { entity ->
entity.toOutgoingGossipingRequest() as? OutgoingSecretRequest
}).filterNotNull()
}
override fun getCrossSigningInfo(userId: String): MXCrossSigningInfo? {
return doRealmQueryAndCopy(realmConfiguration) { realm ->
realm.where(CrossSigningInfoEntity::class.java)

View file

@ -23,6 +23,7 @@ import im.vector.matrix.android.api.session.crypto.verification.IncomingSasVerif
import im.vector.matrix.android.api.session.crypto.verification.SasMode
import im.vector.matrix.android.api.session.crypto.verification.VerificationTxState
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.internal.crypto.OutgoingGossipingRequestManager
import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAction
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
import timber.log.Timber
@ -33,6 +34,7 @@ internal class DefaultIncomingSASDefaultVerificationTransaction(
override val deviceId: String?,
private val cryptoStore: IMXCryptoStore,
crossSigningService: CrossSigningService,
outgoingGossipingRequestManager: OutgoingGossipingRequestManager,
deviceFingerprint: String,
transactionId: String,
otherUserID: String,
@ -43,6 +45,7 @@ internal class DefaultIncomingSASDefaultVerificationTransaction(
deviceId,
cryptoStore,
crossSigningService,
outgoingGossipingRequestManager,
deviceFingerprint,
transactionId,
otherUserID,

View file

@ -20,6 +20,7 @@ import im.vector.matrix.android.api.session.crypto.verification.CancelCode
import im.vector.matrix.android.api.session.crypto.verification.OutgoingSasVerificationTransaction
import im.vector.matrix.android.api.session.crypto.verification.VerificationTxState
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.internal.crypto.OutgoingGossipingRequestManager
import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAction
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
import timber.log.Timber
@ -30,6 +31,7 @@ internal class DefaultOutgoingSASDefaultVerificationTransaction(
deviceId: String?,
cryptoStore: IMXCryptoStore,
crossSigningService: CrossSigningService,
outgoingGossipingRequestManager: OutgoingGossipingRequestManager,
deviceFingerprint: String,
transactionId: String,
otherUserId: String,
@ -40,6 +42,7 @@ internal class DefaultOutgoingSASDefaultVerificationTransaction(
deviceId,
cryptoStore,
crossSigningService,
outgoingGossipingRequestManager,
deviceFingerprint,
transactionId,
otherUserId,

View file

@ -51,6 +51,7 @@ import im.vector.matrix.android.api.session.room.model.message.MessageVerificati
import im.vector.matrix.android.api.session.room.model.message.ValidVerificationDone
import im.vector.matrix.android.internal.crypto.DeviceListManager
import im.vector.matrix.android.internal.crypto.MyDeviceInfoHolder
import im.vector.matrix.android.internal.crypto.OutgoingGossipingRequestManager
import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAction
import im.vector.matrix.android.internal.crypto.crosssigning.DeviceTrustLevel
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
@ -88,6 +89,7 @@ internal class DefaultVerificationService @Inject constructor(
@UserId private val userId: String,
@DeviceId private val deviceId: String?,
private val cryptoStore: IMXCryptoStore,
private val outgoingGossipingRequestManager: OutgoingGossipingRequestManager,
private val myDeviceInfoHolder: Lazy<MyDeviceInfoHolder>,
private val deviceListManager: DeviceListManager,
private val setDeviceVerificationAction: SetDeviceVerificationAction,
@ -505,6 +507,7 @@ internal class DefaultVerificationService @Inject constructor(
deviceId,
cryptoStore,
crossSigningService,
outgoingGossipingRequestManager,
myDeviceInfoHolder.get().myDevice.fingerprint()!!,
startReq.transactionId,
otherUserId,
@ -804,6 +807,7 @@ internal class DefaultVerificationService @Inject constructor(
senderId,
readyReq.fromDevice,
crossSigningService,
outgoingGossipingRequestManager,
cryptoStore,
qrCodeData,
userId,
@ -985,6 +989,7 @@ internal class DefaultVerificationService @Inject constructor(
deviceId,
cryptoStore,
crossSigningService,
outgoingGossipingRequestManager,
myDeviceInfoHolder.get().myDevice.fingerprint()!!,
txID,
otherUserId,
@ -1160,6 +1165,7 @@ internal class DefaultVerificationService @Inject constructor(
deviceId,
cryptoStore,
crossSigningService,
outgoingGossipingRequestManager,
myDeviceInfoHolder.get().myDevice.fingerprint()!!,
transactionId,
otherUserId,
@ -1296,6 +1302,7 @@ internal class DefaultVerificationService @Inject constructor(
otherUserId,
otherDeviceId,
crossSigningService,
outgoingGossipingRequestManager,
cryptoStore,
qrCodeData,
userId,

View file

@ -17,8 +17,11 @@ package im.vector.matrix.android.internal.crypto.verification
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService
import im.vector.matrix.android.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME
import im.vector.matrix.android.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME
import im.vector.matrix.android.api.session.crypto.verification.VerificationTransaction
import im.vector.matrix.android.api.session.crypto.verification.VerificationTxState
import im.vector.matrix.android.internal.crypto.OutgoingGossipingRequestManager
import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAction
import im.vector.matrix.android.internal.crypto.crosssigning.DeviceTrustLevel
import timber.log.Timber
@ -29,6 +32,7 @@ import timber.log.Timber
internal abstract class DefaultVerificationTransaction(
private val setDeviceVerificationAction: SetDeviceVerificationAction,
private val crossSigningService: CrossSigningService,
private val outgoingGossipingRequestManager: OutgoingGossipingRequestManager,
private val userId: String,
override val transactionId: String,
override val otherUserId: String,
@ -70,6 +74,11 @@ internal abstract class DefaultVerificationTransaction(
// Mark my keys as trusted locally
crossSigningService.markMyMasterKeyAsTrusted()
}
outgoingGossipingRequestManager.sendSecretShareRequest(SELF_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*")))
outgoingGossipingRequestManager.sendSecretShareRequest(USER_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*")))
// outgoingGossipingRequestManager.sendSecretShareRequest("m.key.self_signing", mapOf(userId to listOf(otherDeviceId ?: "*")))
// outgoingGossipingRequestManager.sendSecretShareRequest("m.key.user_signing", mapOf(userId to listOf(otherDeviceId ?: "*")))
}
}

View file

@ -24,6 +24,7 @@ import im.vector.matrix.android.api.session.crypto.verification.SasMode
import im.vector.matrix.android.api.session.crypto.verification.SasVerificationTransaction
import im.vector.matrix.android.api.session.crypto.verification.VerificationTxState
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.internal.crypto.OutgoingGossipingRequestManager
import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAction
import im.vector.matrix.android.internal.crypto.model.MXKey
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
@ -42,6 +43,7 @@ internal abstract class SASDefaultVerificationTransaction(
open val deviceId: String?,
private val cryptoStore: IMXCryptoStore,
crossSigningService: CrossSigningService,
outgoingGossipingRequestManager: OutgoingGossipingRequestManager,
private val deviceFingerprint: String,
transactionId: String,
otherUserId: String,
@ -50,6 +52,7 @@ internal abstract class SASDefaultVerificationTransaction(
) : DefaultVerificationTransaction(
setDeviceVerificationAction,
crossSigningService,
outgoingGossipingRequestManager,
userId,
transactionId,
otherUserId,

View file

@ -21,6 +21,7 @@ import im.vector.matrix.android.api.session.crypto.verification.CancelCode
import im.vector.matrix.android.api.session.crypto.verification.QrCodeVerificationTransaction
import im.vector.matrix.android.api.session.crypto.verification.VerificationTxState
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.internal.crypto.OutgoingGossipingRequestManager
import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAction
import im.vector.matrix.android.internal.crypto.crosssigning.fromBase64
import im.vector.matrix.android.internal.crypto.crosssigning.fromBase64Safe
@ -36,6 +37,7 @@ internal class DefaultQrCodeVerificationTransaction(
override val otherUserId: String,
override var otherDeviceId: String?,
private val crossSigningService: CrossSigningService,
outgoingGossipingRequestManager: OutgoingGossipingRequestManager,
private val cryptoStore: IMXCryptoStore,
// Not null only if other user is able to scan QR code
private val qrCodeData: QrCodeData?,
@ -45,6 +47,7 @@ internal class DefaultQrCodeVerificationTransaction(
) : DefaultVerificationTransaction(
setDeviceVerificationAction,
crossSigningService,
outgoingGossipingRequestManager,
userId,
transactionId,
otherUserId,