Make outbound key sharing strategy configurable.

This commit is contained in:
Onuray Sahin 2021-02-04 11:47:24 +03:00 committed by Benoit Marty
parent d504a1f266
commit ae648c3e11
12 changed files with 101 additions and 9 deletions

View file

@ -41,6 +41,7 @@ Improvements 🙌:
- Improve room profile UX
- Upgrade Jitsi library from 2.9.3 to 3.1.0
- a11y improvements
- Pre-share session keys when opening a room or start typing (#2771)
Bugfix 🐛:
- VoIP : fix audio devices output

View file

@ -17,6 +17,7 @@
package org.matrix.android.sdk.api
import org.matrix.android.sdk.api.crypto.MXCryptoConfig
import org.matrix.android.sdk.api.crypto.OutboundSessionKeySharingStrategy
import java.net.Proxy
data class MatrixConfiguration(
@ -40,6 +41,7 @@ data class MatrixConfiguration(
* True to advertise support for call transfers to other parties on Matrix calls.
*/
val supportsCallTransfer: Boolean = false
val outboundSessionKeySharingStrategy: OutboundSessionKeySharingStrategy = OutboundSessionKeySharingStrategy.WhenSendingEvent
) {
/**

View file

@ -0,0 +1,34 @@
/*
* Copyright 2020 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.api.crypto
enum class OutboundSessionKeySharingStrategy {
/**
* Keys will be sent for the first time when the first message is sent
*/
WhenSendingEvent,
/**
* Keys will be sent for the first time when the timeline displayed
*/
WhenEnteringRoom,
/**
* Keys will be sent for the first time when a typing started
*/
WhenTyping
}

View file

@ -156,4 +156,6 @@ interface CryptoService {
fun getWithHeldMegolmSession(roomId: String, sessionId: String): RoomKeyWithHeldContent?
fun logDbUsageInfo()
fun ensureOutboundSession(roomId: String)
}

View file

@ -1290,6 +1290,21 @@ internal class DefaultCryptoService @Inject constructor(
cryptoStore.logDbUsageInfo()
}
override fun ensureOutboundSession(roomId: String) {
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
roomEncryptorsStore
.get(roomId)
?.let {
getEncryptionAlgorithm(roomId)?.let { safeAlgorithm ->
val userIds = getRoomUserIds(roomId)
if (setEncryptionInRoom(roomId, safeAlgorithm, false, userIds)) {
roomEncryptorsStore.get(roomId)?.ensureOutboundSession(getRoomUserIds(roomId))
}
}
}
}
}
/* ==========================================================================================
* For test only
* ========================================================================================== */

View file

@ -62,4 +62,11 @@ internal interface IMXEncrypting {
userId: String,
deviceId: String,
senderKey: String): Boolean
/**
* Ensure the outbound session
*
* @param usersInRoom the users in the room
*/
suspend fun ensureOutboundSession(usersInRoom: List<String>)
}

View file

@ -137,11 +137,10 @@ internal class MXMegolmEncryption(
return MXOutboundSessionInfo(sessionId, SharedWithHelper(roomId, sessionId, cryptoStore))
}
/**
* Ensure the outbound session
*
* @param devicesInRoom the devices list
*/
override suspend fun ensureOutboundSession(usersInRoom: List<String>) {
getDevicesInRoom(usersInRoom).allowedDevices
}
private suspend fun ensureOutboundSession(devicesInRoom: MXUsersDevicesMap<CryptoDeviceInfo>): MXOutboundSessionInfo {
Timber.v("## CRYPTO | ensureOutboundSession start")
var session = outboundSession

View file

@ -85,4 +85,8 @@ internal class MXOlmEncryption(
// No need for olm
return false
}
override suspend fun ensureOutboundSession(usersInRoom: List<String>) {
// NOOP
}
}

View file

@ -24,9 +24,13 @@ import io.realm.RealmQuery
import io.realm.RealmResults
import io.realm.Sort
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.MatrixConfiguration
import org.matrix.android.sdk.api.NoOpMatrixCallback
import org.matrix.android.sdk.api.crypto.OutboundSessionKeySharingStrategy
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.RelationType
import org.matrix.android.sdk.api.session.events.model.toModel
@ -80,8 +84,11 @@ internal class DefaultTimeline(
private val timelineInput: TimelineInput,
private val eventDecryptor: TimelineEventDecryptor,
private val realmSessionProvider: RealmSessionProvider,
private val loadRoomMembersTask: LoadRoomMembersTask
) : Timeline,
private val loadRoomMembersTask: LoadRoomMembersTask,
private val session: Session,
private val matrixConfiguration: MatrixConfiguration,
private val cryptoService: CryptoService
) : Timeline,
TimelineHiddenReadReceipts.Delegate,
TimelineInput.Listener {
@ -188,6 +195,11 @@ internal class DefaultTimeline(
}
.executeBy(taskExecutor)
if (session.getRoom(roomId)?.isEncrypted().orFalse()
&& matrixConfiguration.outboundSessionKeySharingStrategy == OutboundSessionKeySharingStrategy.WhenEnteringRoom) {
cryptoService.ensureOutboundSession(roomId)
}
isReady.set(true)
}
}

View file

@ -21,6 +21,11 @@ import org.matrix.android.sdk.internal.network.executeRequest
import org.matrix.android.sdk.internal.session.room.RoomAPI
import org.matrix.android.sdk.internal.task.Task
import kotlinx.coroutines.delay
import org.matrix.android.sdk.api.MatrixConfiguration
import org.matrix.android.sdk.api.crypto.OutboundSessionKeySharingStrategy
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
import javax.inject.Inject
@ -38,12 +43,21 @@ internal interface SendTypingTask : Task<SendTypingTask.Params, Unit> {
internal class DefaultSendTypingTask @Inject constructor(
private val roomAPI: RoomAPI,
@UserId private val userId: String,
private val globalErrorReceiver: GlobalErrorReceiver
private val globalErrorReceiver: GlobalErrorReceiver,
private val matrixConfiguration: MatrixConfiguration,
private val session: Session,
private val cryptoService: CryptoService
) : SendTypingTask {
override suspend fun execute(params: SendTypingTask.Params) {
delay(params.delay ?: -1)
if (params.isTyping
&& session.getRoom(params.roomId)?.isEncrypted().orFalse()
&& matrixConfiguration.outboundSessionKeySharingStrategy == OutboundSessionKeySharingStrategy.WhenTyping) {
cryptoService.ensureOutboundSession(params.roomId)
}
executeRequest<Unit>(globalErrorReceiver) {
apiCall = roomAPI.sendTypingState(
params.roomId,

View file

@ -136,6 +136,8 @@ android {
buildConfigField "String", "BUILD_NUMBER", "\"${buildNumber}\""
resValue "string", "build_number", "\"${buildNumber}\""
buildConfigField "org.matrix.android.sdk.api.crypto.OutboundSessionKeySharingStrategy", "OutboundSessionKeySharingStrategy", "org.matrix.android.sdk.api.crypto.OutboundSessionKeySharingStrategy.WhenTyping"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// Keep abiFilter for the universalApk

View file

@ -205,7 +205,7 @@ class VectorApplication :
}
}
override fun providesMatrixConfiguration() = MatrixConfiguration(BuildConfig.FLAVOR_DESCRIPTION)
override fun providesMatrixConfiguration() = MatrixConfiguration(applicationFlavor = BuildConfig.FLAVOR_DESCRIPTION, outboundSessionKeySharingStrategy = BuildConfig.OutboundSessionKeySharingStrategy)
override fun getWorkManagerConfiguration(): WorkConfiguration {
return WorkConfiguration.Builder()