diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoModule.kt index a786ebd4b2..b9070994e4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoModule.kt @@ -72,6 +72,7 @@ import org.matrix.android.sdk.internal.crypto.tasks.DefaultSendToDeviceTask import org.matrix.android.sdk.internal.crypto.tasks.DefaultSendVerificationMessageTask import org.matrix.android.sdk.internal.crypto.tasks.DefaultSetDeviceNameTask import org.matrix.android.sdk.internal.crypto.tasks.DefaultUploadKeysTask +import org.matrix.android.sdk.internal.crypto.tasks.NewDefaultUploadKeysTask import org.matrix.android.sdk.internal.crypto.tasks.DefaultUploadSignaturesTask import org.matrix.android.sdk.internal.crypto.tasks.DefaultUploadSigningKeysTask import org.matrix.android.sdk.internal.crypto.tasks.DeleteDeviceTask @@ -86,6 +87,7 @@ import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask import org.matrix.android.sdk.internal.crypto.tasks.SendVerificationMessageTask import org.matrix.android.sdk.internal.crypto.tasks.SetDeviceNameTask import org.matrix.android.sdk.internal.crypto.tasks.UploadKeysTask +import org.matrix.android.sdk.internal.crypto.tasks.NewUploadKeysTask import org.matrix.android.sdk.internal.crypto.tasks.UploadSignaturesTask import org.matrix.android.sdk.internal.crypto.tasks.UploadSigningKeysTask import org.matrix.android.sdk.internal.database.RealmKeysUtils @@ -177,6 +179,9 @@ internal abstract class CryptoModule { @Binds abstract fun bindUploadKeysTask(task: DefaultUploadKeysTask): UploadKeysTask + @Binds + abstract fun bindNewUploadKeysTask(task: NewDefaultUploadKeysTask): NewUploadKeysTask + @Binds abstract fun bindUploadSigningKeysTask(task: DefaultUploadSigningKeysTask): UploadSigningKeysTask diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt index dc321c0a88..ac51e1dca0 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt @@ -55,6 +55,7 @@ import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent import org.matrix.android.sdk.api.session.room.model.RoomMemberContent +import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.internal.OlmMachine import org.matrix.android.sdk.internal.crypto.actions.MegolmSessionDataImporter import org.matrix.android.sdk.internal.crypto.actions.SetDeviceVerificationAction @@ -76,14 +77,15 @@ import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyWithHeldContent import org.matrix.android.sdk.internal.crypto.model.event.SecretSendEventContent import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse +import org.matrix.android.sdk.internal.crypto.model.rest.KeysUploadResponse import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody -import org.matrix.android.sdk.internal.crypto.model.toRest import org.matrix.android.sdk.internal.crypto.repository.WarnOnUnknownDeviceRepository import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.DeleteDeviceTask import org.matrix.android.sdk.internal.crypto.tasks.DeleteDeviceWithUserPasswordTask import org.matrix.android.sdk.internal.crypto.tasks.GetDeviceInfoTask import org.matrix.android.sdk.internal.crypto.tasks.GetDevicesTask +import org.matrix.android.sdk.internal.crypto.tasks.NewUploadKeysTask import org.matrix.android.sdk.internal.crypto.tasks.SetDeviceNameTask import org.matrix.android.sdk.internal.crypto.tasks.UploadKeysTask import org.matrix.android.sdk.internal.crypto.verification.DefaultVerificationService @@ -99,11 +101,11 @@ import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.task.TaskThread import org.matrix.android.sdk.internal.task.configureWith import org.matrix.android.sdk.internal.task.launchToCallback -import org.matrix.android.sdk.internal.util.JsonCanonicalizer import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers import org.matrix.olm.OlmManager import timber.log.Timber import uniffi.olm.Request +import uniffi.olm.RequestType /** * A `CryptoService` class instance manages the end-to-end crypto for a session. @@ -166,6 +168,7 @@ internal class DefaultCryptoService @Inject constructor( private val getDeviceInfoTask: GetDeviceInfoTask, private val setDeviceNameTask: SetDeviceNameTask, private val uploadKeysTask: UploadKeysTask, + private val newUploadKeysTask: NewUploadKeysTask, private val loadRoomMembersTask: LoadRoomMembersTask, private val cryptoSessionInfoProvider: CryptoSessionInfoProvider, private val coroutineDispatchers: MatrixCoroutineDispatchers, @@ -337,7 +340,7 @@ internal class DefaultCryptoService @Inject constructor( uploadDeviceKeys() } - oneTimeKeysUploader.maybeUploadOneTimeKeys() + // oneTimeKeysUploader.maybeUploadOneTimeKeys() // this can throw if no backup tryOrNull { keysBackupService.checkAndStartKeysBackup() @@ -374,16 +377,7 @@ internal class DefaultCryptoService @Inject constructor( try { olmMachine = OlmMachine(userId, deviceId!!, dataDir) - Timber.v("HELLLO WORLD STARTING CRYPTO ${olmMachine?.identityKeys()}") - - // TODO sent out those requests in a sensible place. - for (request in olmMachine!!.outgoingRequests()) { - when (request) { - is Request.KeysUpload -> Timber.v("HELLO KEYS UPLOAD REQUEST ${request.body}") - is Request.KeysQuery -> Timber.v("HELLO KEYS QUERY REQUEST ${request.body}") - is Request.ToDevice -> Timber.v("HELLO TO DEVICE REQUEST ${request.body}") - } - } + Timber.v("HELLLO WORLD STARTING $dataDir CRYPTO ${olmMachine?.identityKeys()}") } catch (throwable: Throwable) { Timber.v("HELLLO WORLD FAILED CRYPTO $throwable") } @@ -444,7 +438,11 @@ internal class DefaultCryptoService @Inject constructor( * * @param syncResponse the syncResponse */ - fun onSyncCompleted(syncResponse: SyncResponse) { + suspend fun onSyncCompleted(syncResponse: SyncResponse) { + if (isStarted()) { + sendOutgoingRequests() + } + cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { runCatching { if (syncResponse.deviceLists != null) { @@ -457,7 +455,7 @@ internal class DefaultCryptoService @Inject constructor( if (isStarted()) { // Make sure we process to-device messages before generating new one-time-keys #2782 deviceListManager.refreshOutdatedDeviceLists() - oneTimeKeysUploader.maybeUploadOneTimeKeys() + // oneTimeKeysUploader.maybeUploadOneTimeKeys() incomingGossipingRequestManager.processReceivedGossipingRequests() } } @@ -939,27 +937,49 @@ internal class DefaultCryptoService @Inject constructor( } } + private suspend fun sendOutgoingRequests() { + // TODO these requests should be sent out in parallel + for (outgoingRequest in olmMachine!!.outgoingRequests()) { + when (outgoingRequest) { + is Request.KeysUpload -> { + Timber.v("HELLO UPLOADING RUSTY KEYS") + val body = MoshiProvider.providesMoshi().adapter(Map::class.java).fromJson(outgoingRequest.body)!! + val request = NewUploadKeysTask.Params(body) + + val response = newUploadKeysTask.execute(request) + val adapter = MoshiProvider.providesMoshi().adapter(KeysUploadResponse::class.java) + val json_response = adapter.toJson(response)!! + olmMachine!!.markRequestAsSent(outgoingRequest.requestId, RequestType.KEYS_UPLOAD, json_response) + Timber.v("HELLO UPLOADED KEYS $response") + } + is Request.KeysQuery -> Timber.v("HELLO KEYS QUERY REQUEST ${outgoingRequest.body}") + is Request.ToDevice -> Timber.v("HELLO TO DEVICE REQUEST ${outgoingRequest.body}") + } + } + } + /** * Upload my user's device keys. */ private suspend fun uploadDeviceKeys() { - if (cryptoStore.getDeviceKeysUploaded()) { - Timber.d("Keys already uploaded, nothing to do") - return - } - // Prepare the device keys data to send - // Sign it - val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, getMyDevice().signalableJSONDictionary()) - var rest = getMyDevice().toRest() + // sendOutgoingRequests() + // if (cryptoStore.getDeviceKeysUploaded()) { + // Timber.d("Keys already uploaded, nothing to do") + // return + // } + // // Prepare the device keys data to send + // // Sign it + // val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, getMyDevice().signalableJSONDictionary()) + // var rest = getMyDevice().toRest() - rest = rest.copy( - signatures = objectSigner.signObject(canonicalJson) - ) + // rest = rest.copy( + // signatures = objectSigner.signObject(canonicalJson) + // ) - val uploadDeviceKeysParams = UploadKeysTask.Params(rest, null) - uploadKeysTask.execute(uploadDeviceKeysParams) + // val uploadDeviceKeysParams = UploadKeysTask.Params(rest, null) + // uploadKeysTask.execute(uploadDeviceKeysParams) - cryptoStore.setDeviceKeysUploaded(true) + // cryptoStore.setDeviceKeysUploaded(true) } /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/api/CryptoApi.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/api/CryptoApi.kt index 5604e97152..104cb1e97f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/api/CryptoApi.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/api/CryptoApi.kt @@ -15,6 +15,7 @@ */ package org.matrix.android.sdk.internal.crypto.api +import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.internal.crypto.model.rest.DeleteDeviceParams import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse @@ -64,6 +65,13 @@ internal interface CryptoApi { @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "keys/upload") fun uploadKeys(@Body body: KeysUploadBody): Call + /** + * Upload device and one-time keys + * @param body the keys to be sent. + */ + @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "keys/upload") + fun newUploadKeys(@Body body: JsonDict): Call + /** * Download device keys. * Doc: https://matrix.org/docs/spec/client_server/r0.4.0.html#post-matrix-client-r0-keys-query diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadKeysTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadKeysTask.kt index eb53bbbf8d..0dbd87c537 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadKeysTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadKeysTask.kt @@ -54,3 +54,23 @@ internal class DefaultUploadKeysTask @Inject constructor( } } } + +internal interface NewUploadKeysTask : Task { + data class Params( + val body: JsonDict + ) +} + +internal class NewDefaultUploadKeysTask @Inject constructor( + private val cryptoApi: CryptoApi, + private val globalErrorReceiver: GlobalErrorReceiver +) : NewUploadKeysTask { + + override suspend fun execute(params: NewUploadKeysTask.Params): KeysUploadResponse { + Timber.i("## Uploading device keys -> $params.body") + + return executeRequest(globalErrorReceiver) { + apiCall = cryptoApi.newUploadKeys(params.body) + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/CryptoSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/CryptoSyncHandler.kt index fc476a3dd6..1e08b86d4b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/CryptoSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/CryptoSyncHandler.kt @@ -52,7 +52,7 @@ internal class CryptoSyncHandler @Inject constructor(private val cryptoService: } } - fun onSyncCompleted(syncResponse: SyncResponse) { + suspend fun onSyncCompleted(syncResponse: SyncResponse) { cryptoService.onSyncCompleted(syncResponse) }