Avoid to inject credential (again)
This commit is contained in:
parent
be77017209
commit
fb5148fd43
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue