Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure OTKs are uploaded when the session is created #3724

Merged
merged 6 commits into from
Jul 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/3724.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Ensure OTKs are uploaded when the session is created
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,12 @@ internal class DefaultCryptoService @Inject constructor(
cryptoCoroutineScope.launchToCallback(coroutineDispatchers.crypto, NoOpMatrixCallback()) {
// Open the store
cryptoStore.open()

if (!cryptoStore.areDeviceKeysUploaded()) {
// Schedule upload of OTK
oneTimeKeysUploader.updateOneTimeKeyCount(0)
}

// this can throw if no network
tryOrNull {
uploadDeviceKeys()
Expand Down Expand Up @@ -905,7 +911,7 @@ internal class DefaultCryptoService @Inject constructor(
* Upload my user's device keys.
*/
private suspend fun uploadDeviceKeys() {
if (cryptoStore.getDeviceKeysUploaded()) {
if (cryptoStore.areDeviceKeysUploaded()) {
Timber.d("Keys already uploaded, nothing to do")
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.matrix.android.sdk.internal.crypto

import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.internal.crypto.model.MXKey
import org.matrix.android.sdk.internal.crypto.model.rest.KeysUploadResponse
import org.matrix.android.sdk.internal.crypto.tasks.UploadKeysTask
Expand Down Expand Up @@ -77,6 +78,10 @@ internal class OneTimeKeysUploader @Inject constructor(
// discard the oldest private keys first. This will eventually clean
// out stale private keys that won't receive a message.
val keyLimit = floor(maxOneTimeKeys / 2.0).toInt()
if (oneTimeKeyCount == null) {
// Ask the server how many otk he has
oneTimeKeyCount = fetchOtkCount()
}
val oneTimeKeyCountFromSync = oneTimeKeyCount
if (oneTimeKeyCountFromSync != null) {
// We need to keep a pool of one time public keys on the server so that
Expand All @@ -90,17 +95,22 @@ internal class OneTimeKeysUploader @Inject constructor(
// private keys clogging up our local storage.
// So we need some kind of engineering compromise to balance all of
// these factors.
try {
tryOrNull("Unable to upload OTK") {
val uploadedKeys = uploadOTK(oneTimeKeyCountFromSync, keyLimit)
Timber.v("## uploadKeys() : success, $uploadedKeys key(s) sent")
} finally {
oneTimeKeyCheckInProgress = false
}
} else {
Timber.w("maybeUploadOneTimeKeys: waiting to know the number of OTK from the sync")
oneTimeKeyCheckInProgress = false
lastOneTimeKeyCheck = 0
}
oneTimeKeyCheckInProgress = false
}

private suspend fun fetchOtkCount(): Int? {
return tryOrNull("Unable to get OTK count") {
val result = uploadKeysTask.execute(UploadKeysTask.Params(null, null))
result.oneTimeKeyCountsForAlgorithm(MXKey.KEY_SIGNED_CURVE_25519_TYPE)
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ internal interface IMXCryptoStore {
fun getGossipingEvents(): List<Event>

fun setDeviceKeysUploaded(uploaded: Boolean)
fun getDeviceKeysUploaded(): Boolean
fun areDeviceKeysUploaded(): Boolean
fun tidyUpDataBase()
fun logDbUsageInfo()
}
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,7 @@ internal class RealmCryptoStore @Inject constructor(
}
}

override fun getDeviceKeysUploaded(): Boolean {
override fun areDeviceKeysUploaded(): Boolean {
return doWithRealm(realmConfiguration) {
it.where<CryptoMetadataEntity>().findFirst()?.deviceKeysSentToServer
} ?: false
Expand Down