crypto: Move most of the getters of verification objecs into the olm machine

This commit is contained in:
Damir Jelić 2021-07-21 16:25:28 +02:00
parent 38ce3ebed7
commit cbed5be810
3 changed files with 96 additions and 82 deletions

View File

@ -392,7 +392,7 @@ internal class DefaultCryptoService @Inject constructor(
try {
setRustLogger()
val machine = OlmMachine(userId, deviceId!!, dataDir, deviceObserver)
val machine = OlmMachine(userId, deviceId!!, dataDir, deviceObserver, sender)
olmMachine = machine
verificationService = RustVerificationService(machine, this.sender)
Timber.v(
@ -482,7 +482,7 @@ internal class DefaultCryptoService @Inject constructor(
override fun getDeviceInfo(userId: String, deviceId: String?): CryptoDeviceInfo? {
return if (userId.isNotEmpty() && !deviceId.isNullOrEmpty()) {
runBlocking {
this@DefaultCryptoService.olmMachine?.getDevice(userId, deviceId)
this@DefaultCryptoService.olmMachine?.getCryptoDeviceInfo(userId, deviceId)
}
} else {
null

View File

@ -26,6 +26,8 @@ import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.listeners.ProgressListener
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.util.JsonDict
@ -49,8 +51,7 @@ import uniffi.olm.OlmMachine as InnerMachine
import uniffi.olm.ProgressListener as RustProgressListener
import uniffi.olm.Request
import uniffi.olm.RequestType
import uniffi.olm.Verification
import uniffi.olm.VerificationRequest
import uniffi.olm.Verification as InnerVerification
import uniffi.olm.setLogger
class CryptoLogger : Logger {
@ -122,10 +123,12 @@ internal class OlmMachine(
user_id: String,
device_id: String,
path: File,
deviceObserver: DeviceUpdateObserver
deviceObserver: DeviceUpdateObserver,
private val requestSender: RequestSender,
) {
private val inner: InnerMachine = InnerMachine(user_id, device_id, path.toString())
private val deviceUpdateObserver = deviceObserver
internal val verificationListeners = ArrayList<VerificationService.Listener>()
/** Get our own user ID. */
fun userId(): String {
@ -429,17 +432,26 @@ internal class OlmMachine(
* @return The Device if it found one.
*/
@Throws(CryptoStoreErrorException::class)
suspend fun getDevice(userId: String, deviceId: String): CryptoDeviceInfo? =
withContext(Dispatchers.IO) {
// Our own device isn't part of our store on the rust side, return it
// using our ownDevice method
if (userId == userId() && deviceId == deviceId()) {
ownDevice()
} else {
val device = inner.getDevice(userId, deviceId)
if (device != null) toCryptoDeviceInfo(device) else null
}
}
suspend fun getCryptoDeviceInfo(userId: String, deviceId: String): CryptoDeviceInfo? {
return if (userId == userId() && deviceId == deviceId()) {
// Our own device isn't part of our store on the Rust side, return it
// using our ownDevice method
ownDevice()
} else {
val device = getRawDevice(userId, deviceId) ?: return null
toCryptoDeviceInfo(device)
}
}
private suspend fun getRawDevice(userId: String, deviceId: String): InnerDevice? =
withContext(Dispatchers.IO) {
inner.getDevice(userId, deviceId)
}
suspend fun getDevice(userId: String, deviceId: String): Device? {
val device = this.getRawDevice(userId, deviceId) ?: return null
return Device(this.inner, device, this.requestSender, this.verificationListeners)
}
/**
* Get all devices of an user.
@ -546,19 +558,58 @@ internal class OlmMachine(
* @return The list of VerificationRequests that we share with the given user
*/
fun getVerificationRequests(userId: String): List<VerificationRequest> {
return this.inner.getVerificationRequests(userId)
return this.inner.getVerificationRequests(userId).map {
VerificationRequest(
this.inner,
it,
this.requestSender,
this.verificationListeners,
)
}
}
/** Get a verification request for the given user with the given flow ID */
fun getVerificationRequest(userId: String, flowId: String): VerificationRequest? {
return this.inner.getVerificationRequest(userId, flowId)
val request = this.inner.getVerificationRequest(userId, flowId)
return if (request != null) {
VerificationRequest(
this.inner,
request,
requestSender,
this.verificationListeners,
)
} else {
null
}
}
/** Get an active verification for the given user and given flow ID
*
* This can return a SAS verification or a QR code verification
*/
fun getVerification(userId: String, flowId: String): Verification? {
return this.inner.getVerification(userId, flowId)
fun getVerification(userId: String, flowId: String): VerificationTransaction? {
return when (val verification = this.inner.getVerification(userId, flowId)) {
is uniffi.olm.Verification.QrCodeV1 -> {
val request = this.getVerificationRequest(userId, flowId) ?: return null
QrCodeVerification(inner, request, verification.qrcode, requestSender, verificationListeners)
}
is uniffi.olm.Verification.SasV1 -> {
SasVerification(inner, verification.sas, requestSender, verificationListeners)
}
null -> {
// This branch exists because scanning a QR code is tied to the QrCodeVerification,
// i.e. instead of branching into a scanned QR code verification from the verification request,
// like it's done for SAS verifications, the public API expects us to create an empty dummy
// QrCodeVerification object that gets populated once a QR code is scanned.
val request = getVerificationRequest(userId, flowId) ?: return null
if (request.canScanQrCodes()) {
QrCodeVerification(inner, request, null, requestSender, verificationListeners)
} else {
null
}
}
}
}
}

View File

@ -20,9 +20,7 @@ import android.os.Handler
import android.os.Looper
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
@ -34,7 +32,6 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageRelationCont
import org.matrix.android.sdk.api.session.room.model.message.MessageType
import org.matrix.android.sdk.internal.crypto.Device
import org.matrix.android.sdk.internal.crypto.OlmMachine
import org.matrix.android.sdk.internal.crypto.QrCodeVerification
import org.matrix.android.sdk.internal.crypto.RequestSender
import org.matrix.android.sdk.internal.crypto.SasVerification
import org.matrix.android.sdk.internal.crypto.VerificationRequest
@ -43,14 +40,15 @@ import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_RECIPROCATE
import org.matrix.android.sdk.internal.crypto.model.rest.toValue
import timber.log.Timber
import uniffi.olm.Verification
/** A helper class to deserialize to-device `m.key.verification.*` events to fetch the transaction id out */
@JsonClass(generateAdapter = true)
internal data class ToDeviceVerificationEvent(
@Json(name = "sender") val sender: String?,
@Json(name = "transaction_id") val transactionId: String,
)
/** Helper method to fetch the unique ID of the verification event */
private fun getFlowId(event: Event): String? {
return if (event.eventId != null) {
val relatesTo = event.content.toModel<MessageRelationContent>()?.relatesTo
@ -61,6 +59,7 @@ private fun getFlowId(event: Event): String? {
}
}
/** Convert a list of VerificationMethod into a list of strings that can be passed to the Rust side */
internal fun prepareMethods(methods: List<VerificationMethod>): List<String> {
val stringMethods: MutableList<String> = methods.map { it.toValue() }.toMutableList()
@ -77,23 +76,22 @@ internal class RustVerificationService(
private val requestSender: RequestSender,
) : VerificationService {
private val uiHandler = Handler(Looper.getMainLooper())
private var listeners = ArrayList<VerificationService.Listener>()
override fun addListener(listener: VerificationService.Listener) {
uiHandler.post {
if (!listeners.contains(listener)) {
listeners.add(listener)
if (!this.olmMachine.verificationListeners.contains(listener)) {
this.olmMachine.verificationListeners.add(listener)
}
}
}
override fun removeListener(listener: VerificationService.Listener) {
uiHandler.post { listeners.remove(listener) }
uiHandler.post { this.olmMachine.verificationListeners.remove(listener) }
}
private fun dispatchTxAdded(tx: VerificationTransaction) {
uiHandler.post {
listeners.forEach {
this.olmMachine.verificationListeners.forEach {
try {
it.transactionCreated(tx)
} catch (e: Throwable) {
@ -105,7 +103,7 @@ internal class RustVerificationService(
private fun dispatchTxUpdated(tx: VerificationTransaction) {
uiHandler.post {
listeners.forEach {
this.olmMachine.verificationListeners.forEach {
try {
it.transactionUpdated(tx)
} catch (e: Throwable) {
@ -118,7 +116,7 @@ internal class RustVerificationService(
private fun dispatchRequestAdded(tx: PendingVerificationRequest) {
Timber.v("## SAS dispatchRequestAdded txId:${tx.transactionId} $tx")
uiHandler.post {
listeners.forEach {
this.olmMachine.verificationListeners.forEach {
try {
it.verificationRequestCreated(tx)
} catch (e: Throwable) {
@ -188,30 +186,11 @@ internal class RustVerificationService(
}
private fun getVerificationRequest(otherUserId: String, transactionId: String): VerificationRequest? {
val request = this.olmMachine.getVerificationRequest(otherUserId, transactionId)
return if (request != null) {
VerificationRequest(
this.olmMachine.inner(),
request,
requestSender,
listeners,
)
} else {
null
}
return this.olmMachine.getVerificationRequest(otherUserId, transactionId)
}
private suspend fun getDevice(userId: String, deviceID: String): Device? {
val device = withContext(Dispatchers.IO) {
olmMachine.inner().getDevice(userId, deviceID)
}
return if (device != null) {
Device(this.olmMachine.inner(), device, this.requestSender, this.listeners)
} else {
null
}
return this.olmMachine.getDevice(userId, deviceID)
}
override fun markedLocallyAsManuallyVerified(userId: String, deviceID: String) {
@ -230,40 +209,14 @@ internal class RustVerificationService(
otherUserId: String,
tid: String,
): VerificationTransaction? {
return when (val verification = this.olmMachine.getVerification(otherUserId, tid)) {
is Verification.QrCodeV1 -> {
val request = getVerificationRequest(otherUserId, tid) ?: return null
QrCodeVerification(this.olmMachine.inner(), request, verification.qrcode, this.requestSender, this.listeners)
}
is Verification.SasV1 -> {
SasVerification(this.olmMachine.inner(), verification.sas, this.requestSender, this.listeners)
}
null -> {
// This branch exists because scanning a QR code is tied to the QrCodeVerification,
// i.e. instead of branching into a scanned QR code verification from the verification request,
// like it's done for SAS verifications, the public API expects us to create an empty dummy
// QrCodeVerification object that gets populated once a QR code is scanned.
val request = getVerificationRequest(otherUserId, tid) ?: return null
if (request.canScanQrCodes()) {
QrCodeVerification(this.olmMachine.inner(), request, null, this.requestSender, this.listeners)
} else {
null
}
}
}
return this.olmMachine.getVerification(otherUserId, tid)
}
override fun getExistingVerificationRequests(
otherUserId: String
): List<PendingVerificationRequest> {
return this.olmMachine.getVerificationRequests(otherUserId).map {
VerificationRequest(
this.olmMachine.inner(),
it,
this.requestSender,
this.listeners,
).toPendingVerificationRequest()
it.toPendingVerificationRequest()
}
}
@ -314,7 +267,12 @@ internal class RustVerificationService(
requestSender.sendVerificationRequest(result!!.request)
}
return VerificationRequest(this.olmMachine.inner(), result!!.verification, this.requestSender, this.listeners).toPendingVerificationRequest()
return VerificationRequest(
this.olmMachine.inner(),
result!!.verification,
this.requestSender,
this.olmMachine.verificationListeners
).toPendingVerificationRequest()
}
override fun requestKeyVerificationInDMs(
@ -332,7 +290,12 @@ internal class RustVerificationService(
}
val innerRequest = this.olmMachine.inner().requestVerification(otherUserId, roomId, eventID, stringMethods)!!
return VerificationRequest(this.olmMachine.inner(), innerRequest, this.requestSender, this.listeners).toPendingVerificationRequest()
return VerificationRequest(
this.olmMachine.inner(),
innerRequest,
this.requestSender,
this.olmMachine.verificationListeners
).toPendingVerificationRequest()
}
override fun readyPendingVerification(