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

Update/Revise SDK to implement reference flowchart for key sharing/forwarding + use backup #5559

Merged
merged 29 commits into from
May 11, 2022
Merged
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9177cb1
Refactor key and secret request managers
BillCarsonFr Mar 14, 2022
9747eb2
Add share test + fix
BillCarsonFr Mar 16, 2022
b1db6ca
fix db migration
BillCarsonFr Mar 16, 2022
ae6df46
Add incoming key forward trail
BillCarsonFr Mar 16, 2022
6a509ce
fix unused var
BillCarsonFr Mar 17, 2022
1d948d6
Add option to disable key gossip, clear key request on trust change
BillCarsonFr Mar 18, 2022
81b114f
Add change log + quick quality fix
BillCarsonFr Mar 21, 2022
cc10749
Fix database migration
BillCarsonFr Mar 21, 2022
88cf1a5
Fix unneeded re-uploade of key got from backup
BillCarsonFr Mar 29, 2022
54fb4ae
proper initial withheld support
BillCarsonFr Apr 12, 2022
f9dd3b9
Stop using workers for interactive verification
BillCarsonFr Apr 15, 2022
a60171c
Reactivate withheld and verification tests
BillCarsonFr Apr 15, 2022
3f5f2dc
Fix tests
BillCarsonFr Apr 15, 2022
631ea50
Move some crypto classes to API + cleaning
BillCarsonFr Apr 15, 2022
effbc47
FIx unit test compilation
BillCarsonFr Apr 20, 2022
885f836
Cleaning, review
BillCarsonFr Apr 20, 2022
058d2e6
Fix: ignore key request form self devices
BillCarsonFr Apr 22, 2022
9385d19
Fix trail display (from instead of to for incoming types)
BillCarsonFr Apr 22, 2022
eaf1044
Cleaning, code review
BillCarsonFr Apr 25, 2022
012dfeb
Change log for SDK apis
BillCarsonFr Apr 25, 2022
728faae
Fix missing mapper for incoming key forward trail
BillCarsonFr Apr 26, 2022
8920ed3
Code review
BillCarsonFr Apr 27, 2022
23f32aa
Merge branch 'develop' into feature/bca/crypto_better_key_share
BillCarsonFr Apr 27, 2022
0f06368
Code review
BillCarsonFr Apr 28, 2022
de580cc
Fix make verif scope as a child of crypto scope
BillCarsonFr Apr 29, 2022
12ab478
Merge branch 'develop' into feature/bca/crypto_better_key_share
BillCarsonFr May 10, 2022
546d6fe
post merge fix
BillCarsonFr May 11, 2022
992f477
use clock time instead of system
BillCarsonFr May 11, 2022
3948f26
fix method visibility
BillCarsonFr May 11, 2022
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
Original file line number Diff line number Diff line change
@@ -35,6 +35,7 @@ import org.matrix.android.sdk.api.session.crypto.model.RoomKeyShareRequest
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.util.fromBase64
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
@@ -68,6 +69,7 @@ internal class OutgoingKeyRequestManager @Inject constructor(
private val cryptoConfig: MXCryptoConfig,
private val inboundGroupSessionStore: InboundGroupSessionStore,
private val sendToDeviceTask: DefaultSendToDeviceTask,
private val deviceListManager: DeviceListManager,
private val perSessionBackupQueryRateLimiter: PerSessionBackupQueryRateLimiter) {

private val dispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
@@ -215,6 +217,41 @@ internal class OutgoingKeyRequestManager @Inject constructor(
outgoingRequestScope.launch {
sequencer.post {
Timber.tag(loggerTag.value).d("Withheld received for $sessionId from ${event.senderId}|$fromDevice")
Timber.tag(loggerTag.value).v("Withheld content ${event.getClearContent()}")

// We want to store withheld code from the sender of the message (owner of the megolm session), not from
// other devices that might gossip the key. If not the initial reason might be overridden
// by a request to one of our session.
event.getClearContent().toModel<RoomKeyWithHeldContent>()?.let { withheld ->
withContext(coroutineDispatchers.crypto) {
tryOrNull {
deviceListManager.downloadKeys(listOf(event.senderId ?: ""), false)
}
cryptoStore.getUserDeviceList(event.senderId ?: "")
.also { devices ->
Timber.tag(loggerTag.value).v("Withheld Devices for ${event.senderId} are ${devices.orEmpty().joinToString { it.identityKey() ?: "" }}")
}
?.firstOrNull {
it.identityKey() == senderKey
}
}.also {
Timber.tag(loggerTag.value).v("Withheld device for sender key $senderKey is from ${it?.shortDebugString()}")
}?.let {
if (it.userId == event.senderId) {
if (fromDevice != null) {
if (it.deviceId == fromDevice) {
Timber.tag(loggerTag.value).v("Storing sender Withheld code ${withheld.code} for ${withheld.sessionId}")
cryptoStore.addWithHeldMegolmSession(withheld)
}
} else {
Timber.tag(loggerTag.value).v("Storing sender Withheld code ${withheld.code} for ${withheld.sessionId}")
cryptoStore.addWithHeldMegolmSession(withheld)
}
}
}
}

// Here we store the replies from a given request
cryptoStore.updateOutgoingRoomKeyReply(
roomId = roomId,
sessionId = sessionId,
Original file line number Diff line number Diff line change
@@ -102,9 +102,20 @@ internal class MXMegolmDecryption(
if (throwable is MXCryptoError.OlmError) {
// TODO Check the value of .message
if (throwable.olmException.message == "UNKNOWN_MESSAGE_INDEX") {
// So we know that session, but it's ratcheted and we can't decrypt at that index

if (requestKeysOnFail) {
requestKeysForEvent(event)
}
// Check if partially withheld
val withHeldInfo = cryptoStore.getWithHeldMegolmSession(event.roomId, encryptedEventContent.sessionId)
if (withHeldInfo != null) {
// Encapsulate as withHeld exception
throw MXCryptoError.Base(MXCryptoError.ErrorType.KEYS_WITHHELD,
withHeldInfo.code?.value ?: "",
withHeldInfo.reason)
}

throw MXCryptoError.Base(
MXCryptoError.ErrorType.UNKNOWN_MESSAGE_INDEX,
"UNKNOWN_MESSAGE_INDEX",
@@ -121,6 +132,18 @@ internal class MXMegolmDecryption(
}
if (throwable is MXCryptoError.Base) {
if (throwable.errorType == MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID) {
// Check if it was withheld by sender to enrich error code
val withHeldInfo = cryptoStore.getWithHeldMegolmSession(event.roomId, encryptedEventContent.sessionId)
if (withHeldInfo != null) {
if (requestKeysOnFail) {
requestKeysForEvent(event)
}
// Encapsulate as withHeld exception
throw MXCryptoError.Base(MXCryptoError.ErrorType.KEYS_WITHHELD,
withHeldInfo.code?.value ?: "",
withHeldInfo.reason)
}

if (requestKeysOnFail) {
requestKeysForEvent(event)
}
Original file line number Diff line number Diff line change
@@ -328,7 +328,8 @@ internal class MXMegolmEncryption(
senderKey = senderKey,
algorithm = MXCRYPTO_ALGORITHM_MEGOLM,
sessionId = sessionId,
codeString = code.value
codeString = code.value,
fromDevice = myDeviceId
)
val params = SendToDeviceTask.Params(
EventType.ROOM_KEY_WITHHELD,
Original file line number Diff line number Diff line change
@@ -271,12 +271,13 @@ internal class RealmCryptoStore @Inject constructor(
}

override fun deviceWithIdentityKey(identityKey: String): CryptoDeviceInfo? {
return doWithRealm(realmConfiguration) {
it.where<DeviceInfoEntity>()
.equalTo(DeviceInfoEntityFields.IDENTITY_KEY, identityKey)
.findFirst()
?.let { deviceInfo ->
CryptoMapper.mapToModel(deviceInfo)
return doWithRealm(realmConfiguration) { realm ->
realm.where<DeviceInfoEntity>()
.contains(DeviceInfoEntityFields.KEYS_MAP_JSON, identityKey)
.findAll()
.mapNotNull { CryptoMapper.mapToModel(it) }
.firstOrNull {
it.identityKey() == identityKey
}
}
}