Skip to content

Commit

Permalink
Merge pull request #296 from luki-ev/synodim-merge-upstream
Browse files Browse the repository at this point in the history
Merge upstream v1.6.2
  • Loading branch information
dontub authored Sep 16, 2023
2 parents fbb2129 + 1ab6765 commit 43c6415
Show file tree
Hide file tree
Showing 59 changed files with 849 additions and 277 deletions.
20 changes: 20 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
Changes in Element v1.6.2 (2023-06-02)
======================================

Features ✨
----------
- **Element Android is now using the Crypto Rust SDK**. Migration of user's data should be done at first launch after application upgrade. ([#8390](https://github.com/vector-im/element-android/issues/8390))
- Marks WebP files as Animated and allows them to play ([#8120](https://github.com/vector-im/element-android/issues/8120))
- Updates to protocol used for Sign in with QR code ([#8299](https://github.com/vector-im/element-android/issues/8299))
- Updated rust crypto SDK to version 0.3.9 ([#8488](https://github.com/vector-im/element-android/issues/8488))

Bugfixes 🐛
----------
- Fix: Allow users to sign out even if the sign out request fails. ([#4855](https://github.com/vector-im/element-android/issues/4855))
- fix: Make some crypto calls suspendable to avoid reported ANR ([#8482](https://github.com/vector-im/element-android/issues/8482))

Other changes
-------------
- Refactoring: Extract a new interface for common access to crypto store between kotlin and rust crypto ([#8470](https://github.com/vector-im/element-android/issues/8470))


Changes in Element v1.6.1 (2023-05-25)
======================================

Expand Down
2 changes: 1 addition & 1 deletion dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ ext.libs = [
'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines"
],
androidx : [
'activity' : "androidx.activity:activity-ktx:1.7.1",
'activity' : "androidx.activity:activity-ktx:1.7.2",
'appCompat' : "androidx.appcompat:appcompat:1.6.1",
'biometric' : "androidx.biometric:biometric:1.1.0",
'core' : "androidx.core:core-ktx:1.10.1",
Expand Down
2 changes: 2 additions & 0 deletions fastlane/metadata/android/en-US/changelogs/40106020.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Main changes in this version: Element Android is now using the Crypto Rust SDK.
Full changelog: https://github.com/vector-im/element-android/releases
3 changes: 3 additions & 0 deletions library/ui-strings/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,9 @@
<string name="backup">Back up</string>
<string name="sign_out_bottom_sheet_will_lose_secure_messages">You’ll lose access to your encrypted messages unless you back up your keys before signing out.</string>

<string name="sign_out_failed_dialog_message">Cannot reach the homeserver. If you sign out anyway, this device will not be erased from your device list, you may want to remove it using another client.</string>
<string name="sign_out_anyway">Sign out anyway</string>

<!-- splash screen accessibility -->
<string name="loading">Loading…</string>

Expand Down
6 changes: 3 additions & 3 deletions matrix-sdk-android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ android {
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'

buildConfigField "String", "SDK_VERSION", "\"1.6.1\""
buildConfigField "String", "SDK_VERSION", "\"1.6.2\""

buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\""
Expand Down Expand Up @@ -216,8 +216,8 @@ dependencies {

implementation libs.google.phonenumber

rustCryptoImplementation("org.matrix.rustcomponents:crypto-android:0.3.7")
// rustCryptoApi project(":library:rustCrypto")
rustCryptoImplementation("org.matrix.rustcomponents:crypto-android:0.3.9")
// rustCryptoApi project(":library:rustCrypto")

testImplementation libs.tests.junit
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreRoomSessionD
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreRoomSessionsDataTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreSessionsDataTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.UpdateKeysBackupVersionTask
import org.matrix.android.sdk.internal.crypto.store.IMXCommonCryptoStore
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStore
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreMigration
Expand Down Expand Up @@ -254,6 +255,9 @@ internal abstract class CryptoModule {
@Binds
abstract fun bindCryptoStore(store: RealmCryptoStore): IMXCryptoStore

@Binds
abstract fun bindCommonCryptoStore(store: RealmCryptoStore): IMXCommonCryptoStore

@Binds
abstract fun bindSendEventTask(task: DefaultSendEventTask): SendEventTask

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ internal class DefaultCryptoService @Inject constructor(
return if (longFormat) olmManager.getDetailedVersion(context) else olmManager.version
}

override fun getMyCryptoDevice(): CryptoDeviceInfo {
override suspend fun getMyCryptoDevice(): CryptoDeviceInfo {
return myDeviceInfoHolder.get().myDevice
}

Expand Down Expand Up @@ -506,10 +506,7 @@ internal class DefaultCryptoService @Inject constructor(
null
} else {
withContext(coroutineDispatchers.io) {
cryptoStore.deviceWithIdentityKey(senderKey).takeIf {
// check that the claimed user id matches
it?.userId == userId
}
cryptoStore.deviceWithIdentityKey(userId, senderKey)
}
}
}
Expand Down Expand Up @@ -539,7 +536,7 @@ internal class DefaultCryptoService @Inject constructor(
// .executeBy(taskExecutor)
// }

override fun getCryptoDeviceInfo(userId: String): List<CryptoDeviceInfo> {
override suspend fun getCryptoDeviceInfo(userId: String): List<CryptoDeviceInfo> {
return cryptoStore.getUserDeviceList(userId).orEmpty()
}
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,24 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.UserIdentity
import org.matrix.android.sdk.api.session.crypto.keysbackup.SavedKeyBackupKeyInfo
import org.matrix.android.sdk.api.session.crypto.model.AuditTrail
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
import org.matrix.android.sdk.api.session.crypto.model.CryptoRoomInfo
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody
import org.matrix.android.sdk.api.session.crypto.model.TrailType
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent
import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode
import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.internal.crypto.model.MXInboundMegolmSessionWrapper
import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper
import org.matrix.android.sdk.internal.crypto.model.OutboundGroupSessionWrapper
import org.matrix.android.sdk.internal.crypto.store.db.CryptoStoreAggregator
import org.matrix.android.sdk.internal.crypto.store.db.model.KeysBackupDataEntity
import org.matrix.olm.OlmAccount
import org.matrix.olm.OlmOutboundGroupSession

/**
* The crypto data store.
*/
internal interface IMXCryptoStore {
internal interface IMXCryptoStore : IMXCommonCryptoStore {

/**
* @return the device id
Expand Down Expand Up @@ -78,21 +74,6 @@ internal interface IMXCryptoStore {
*/
fun getInboundGroupSessions(roomId: String): List<MXInboundMegolmSessionWrapper>

/**
* @return true to unilaterally blacklist all unverified devices.
*/
fun getGlobalBlacklistUnverifiedDevices(): Boolean

/**
* Set the global override for whether the client should ever send encrypted
* messages to unverified devices.
* If false, it can still be overridden per-room.
* If true, it overrides the per-room settings.
*
* @param block true to unilaterally blacklist all
*/
fun setGlobalBlacklistUnverifiedDevices(block: Boolean)

/**
* Enable or disable key gossiping.
* Default is true.
Expand Down Expand Up @@ -123,28 +104,6 @@ internal interface IMXCryptoStore {
*/
fun getRoomsListBlacklistUnverifiedDevices(): List<String>

/**
* A live status regarding sharing keys for unverified devices in this room.
*
* @return Live status
*/
fun getLiveBlockUnverifiedDevices(roomId: String): LiveData<Boolean>

/**
* Tell if unverified devices should be blacklisted when sending keys.
*
* @return true if should not send keys to unverified devices
*/
fun getBlockUnverifiedDevices(roomId: String): Boolean

/**
* Define if encryption keys should be sent to unverified devices in this room.
*
* @param roomId the roomId
* @param block if true will not send keys to unverified devices
*/
fun blockUnverifiedDevicesInRoom(roomId: String, block: Boolean)

/**
* Get the current keys backup version.
*/
Expand Down Expand Up @@ -186,16 +145,6 @@ internal interface IMXCryptoStore {
*/
fun deleteStore()

/**
* open any existing crypto store.
*/
fun open()

/**
* Close the store.
*/
fun close()

/**
* Store the device id.
*
Expand Down Expand Up @@ -262,14 +211,6 @@ internal interface IMXCryptoStore {

fun getLiveDeviceWithId(deviceId: String): LiveData<Optional<CryptoDeviceInfo>>

fun getMyDevicesInfo(): List<DeviceInfo>

fun getLiveMyDevicesInfo(): LiveData<List<DeviceInfo>>

fun getLiveMyDevicesInfo(deviceId: String): LiveData<Optional<DeviceInfo>>

fun saveMyDevicesInfo(info: List<DeviceInfo>)

/**
* Store the crypto algorithm for a room.
*
Expand All @@ -278,47 +219,8 @@ internal interface IMXCryptoStore {
*/
fun storeRoomAlgorithm(roomId: String, algorithm: String?)

/**
* Provides the algorithm used in a dedicated room.
*
* @param roomId the room id
* @return the algorithm, null is the room is not encrypted
*/
fun getRoomAlgorithm(roomId: String): String?

fun getRoomCryptoInfo(roomId: String): CryptoRoomInfo?
fun setAlgorithmInfo(roomId: String, encryption: EncryptionEventContent?)

/**
* This is a bit different than isRoomEncrypted.
* A room is encrypted when there is a m.room.encryption state event in the room (malformed/invalid or not).
* But the crypto layer has additional guaranty to ensure that encryption would never been reverted.
* It's defensive coding out of precaution (if ever state is reset).
*/
fun roomWasOnceEncrypted(roomId: String): Boolean

fun shouldEncryptForInvitedMembers(roomId: String): Boolean

/**
* Sets a boolean flag that will determine whether or not this device should encrypt Events for
* invited members.
*
* @param roomId the room id
* @param shouldEncryptForInvitedMembers The boolean flag
*/
fun setShouldEncryptForInvitedMembers(roomId: String, shouldEncryptForInvitedMembers: Boolean)

fun shouldShareHistory(roomId: String): Boolean

/**
* Sets a boolean flag that will determine whether or not room history (existing inbound sessions)
* will be shared to new user invites.
*
* @param roomId the room id
* @param shouldShareHistory The boolean flag
*/
fun setShouldShareHistory(roomId: String, shouldShareHistory: Boolean)

/**
* Store a session between the logged-in user and another device.
*
Expand Down Expand Up @@ -361,15 +263,6 @@ internal interface IMXCryptoStore {
*/
fun storeInboundGroupSessions(sessions: List<MXInboundMegolmSessionWrapper>)

/**
* Retrieve an inbound group session.
*
* @param sessionId the session identifier.
* @param senderKey the base64-encoded curve25519 key of the sender.
* @return an inbound group session.
*/
fun getInboundGroupSession(sessionId: String, senderKey: String): MXInboundMegolmSessionWrapper?

/**
* Retrieve an inbound group session, filtering shared history.
*
Expand Down Expand Up @@ -552,7 +445,6 @@ internal interface IMXCryptoStore {
// fun getCrossSigningPrivateKeysFlow(): Flow<Optional<PrivateKeysInfo>>

fun getGlobalCryptoConfig(): GlobalCryptoConfig
fun getLiveGlobalCryptoConfig(): LiveData<GlobalCryptoConfig>

fun saveBackupRecoveryKey(recoveryKey: String?, version: String?)
fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo?
Expand Down Expand Up @@ -597,14 +489,8 @@ internal interface IMXCryptoStore {

fun setDeviceKeysUploaded(uploaded: Boolean)
fun areDeviceKeysUploaded(): Boolean
fun tidyUpDataBase()
fun getOutgoingRoomKeyRequests(inStates: Set<OutgoingRoomKeyRequestState>): List<OutgoingKeyRequest>

/**
* Store a bunch of data collected during a sync response treatment. @See [CryptoStoreAggregator].
*/
fun storeData(cryptoStoreAggregator: CryptoStoreAggregator)

/**
* Store a bunch of data related to the users. @See [UserDataToStore].
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,19 @@ internal class RealmCryptoStore @Inject constructor(
}
}

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

override fun storeUserDevices(userId: String, devices: Map<String, CryptoDeviceInfo>?) {
doRealmTransaction("storeUserDevices", realmConfiguration) { realm ->
storeUserDevices(realm, userId, devices)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ interface CryptoService {

suspend fun getUserDevices(userId: String): List<CryptoDeviceInfo>

fun getMyCryptoDevice(): CryptoDeviceInfo
suspend fun getMyCryptoDevice(): CryptoDeviceInfo

fun getGlobalBlacklistUnverifiedDevices(): Boolean

Expand Down Expand Up @@ -130,7 +130,7 @@ interface CryptoService {

suspend fun getCryptoDeviceInfo(userId: String, deviceId: String?): CryptoDeviceInfo?

fun getCryptoDeviceInfo(userId: String): List<CryptoDeviceInfo>
suspend fun getCryptoDeviceInfo(userId: String): List<CryptoDeviceInfo>

// fun getCryptoDeviceInfoFlow(userId: String): Flow<List<CryptoDeviceInfo>>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ interface SignOutService {
/**
* Sign out, and release the session, clear all the session data, including crypto data.
* @param signOutFromHomeserver true if the sign out request has to be done
* @param ignoreServerRequestError true to ignore server error if any
*/
suspend fun signOut(signOutFromHomeserver: Boolean)
suspend fun signOut(signOutFromHomeserver: Boolean, ignoreServerRequestError: Boolean = false)
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ object MimeTypes {
const val BadJpg = "image/jpg"
const val Jpeg = "image/jpeg"
const val Gif = "image/gif"
const val Webp = "image/webp"

const val Ogg = "audio/ogg"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,9 @@ internal class DefaultAuthenticationService @Inject constructor(
val oidcCompatibilityFlow = loginFlowResponse.flows.orEmpty().firstOrNull { it.type == "m.login.sso" && it.delegatedOidcCompatibilty == true }
val flows = if (oidcCompatibilityFlow != null) listOf(oidcCompatibilityFlow) else loginFlowResponse.flows

val supportsGetLoginTokenFlow = loginFlowResponse.flows.orEmpty().firstOrNull { it.type == "m.login.token" && it.getLoginToken == true } != null

@Suppress("DEPRECATION")
return LoginFlowResult(
supportedLoginTypes = flows.orEmpty().mapNotNull { it.type },
ssoIdentityProviders = flows.orEmpty().firstOrNull { it.type == LoginFlowTypes.SSO }?.ssoIdentityProvider,
Expand All @@ -309,7 +312,7 @@ internal class DefaultAuthenticationService @Inject constructor(
isOutdatedHomeserver = !versions.isSupportedBySdk(),
hasOidcCompatibilityFlow = oidcCompatibilityFlow != null,
isLogoutDevicesSupported = versions.doesServerSupportLogoutDevices(),
isLoginWithQrSupported = versions.doesServerSupportQrCodeLogin(),
isLoginWithQrSupported = supportsGetLoginTokenFlow || versions.doesServerSupportQrCodeLogin(),
)
}

Expand Down
Loading

0 comments on commit 43c6415

Please sign in to comment.