@@ -55,6 +55,7 @@ import org.matrix.android.sdk.internal.crypto.model.MXInboundMegolmSessionWrappe
5555import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper
5656import org.matrix.android.sdk.internal.crypto.model.OutboundGroupSessionWrapper
5757import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
58+ import org.matrix.android.sdk.internal.crypto.store.UserDataToStore
5859import org.matrix.android.sdk.internal.crypto.store.db.mapper.CrossSigningKeysMapper
5960import org.matrix.android.sdk.internal.crypto.store.db.mapper.MyDeviceLastSeenInfoEntityMapper
6061import org.matrix.android.sdk.internal.crypto.store.db.model.AuditTrailEntity
@@ -289,37 +290,41 @@ internal class RealmCryptoStore @Inject constructor(
289290
290291 override fun storeUserDevices (userId : String , devices : Map <String , CryptoDeviceInfo >? ) {
291292 doRealmTransaction(" storeUserDevices" , realmConfiguration) { realm ->
292- if (devices == null ) {
293- Timber .d(" Remove user $userId " )
294- // Remove the user
295- UserEntity .delete(realm, userId)
296- } else {
297- val userEntity = UserEntity .getOrCreate(realm, userId)
298- // First delete the removed devices
299- val deviceIds = devices.keys
300- userEntity.devices.toTypedArray().iterator().let {
301- while (it.hasNext()) {
302- val deviceInfoEntity = it.next()
303- if (deviceInfoEntity.deviceId !in deviceIds) {
304- Timber .d(" Remove device ${deviceInfoEntity.deviceId} of user $userId " )
305- deviceInfoEntity.deleteOnCascade()
306- }
293+ storeUserDevices(realm, userId, devices)
294+ }
295+ }
296+
297+ private fun storeUserDevices (realm : Realm , userId : String , devices : Map <String , CryptoDeviceInfo >? ) {
298+ if (devices == null ) {
299+ Timber .d(" Remove user $userId " )
300+ // Remove the user
301+ UserEntity .delete(realm, userId)
302+ } else {
303+ val userEntity = UserEntity .getOrCreate(realm, userId)
304+ // First delete the removed devices
305+ val deviceIds = devices.keys
306+ userEntity.devices.toTypedArray().iterator().let {
307+ while (it.hasNext()) {
308+ val deviceInfoEntity = it.next()
309+ if (deviceInfoEntity.deviceId !in deviceIds) {
310+ Timber .d(" Remove device ${deviceInfoEntity.deviceId} of user $userId " )
311+ deviceInfoEntity.deleteOnCascade()
307312 }
308313 }
309- // Then update existing devices or add new one
310- devices.values.forEach { cryptoDeviceInfo ->
311- val existingDeviceInfoEntity = userEntity. devices.firstOrNull { it.deviceId == cryptoDeviceInfo.deviceId }
312- if (existingDeviceInfoEntity == null ) {
313- // Add the device
314- Timber .d( " Add device ${cryptoDeviceInfo.deviceId} of user $userId " )
315- val newEntity = CryptoMapper .mapToEntity(cryptoDeviceInfo )
316- newEntity.firstTimeSeenLocalTs = clock.epochMillis( )
317- userEntity.devices.add(newEntity )
318- } else {
319- // Update the device
320- Timber .d( " Update device ${cryptoDeviceInfo.deviceId} of user $userId " )
321- CryptoMapper .updateDeviceInfoEntity(existingDeviceInfoEntity, cryptoDeviceInfo )
322- }
314+ }
315+ // Then update existing devices or add new one
316+ devices.values.forEach { cryptoDeviceInfo ->
317+ val existingDeviceInfoEntity = userEntity.devices.firstOrNull { it.deviceId == cryptoDeviceInfo.deviceId }
318+ if (existingDeviceInfoEntity == null ) {
319+ // Add the device
320+ Timber .d( " Add device ${cryptoDeviceInfo.deviceId} of user $userId " )
321+ val newEntity = CryptoMapper .mapToEntity(cryptoDeviceInfo )
322+ newEntity.firstTimeSeenLocalTs = clock.epochMillis( )
323+ userEntity.devices.add(newEntity)
324+ } else {
325+ // Update the device
326+ Timber .d( " Update device ${cryptoDeviceInfo.deviceId} of user $userId " )
327+ CryptoMapper .updateDeviceInfoEntity(existingDeviceInfoEntity, cryptoDeviceInfo)
323328 }
324329 }
325330 }
@@ -332,85 +337,95 @@ internal class RealmCryptoStore @Inject constructor(
332337 userSigningKey : CryptoCrossSigningKey ?
333338 ) {
334339 doRealmTransaction(" storeUserCrossSigningKeys" , realmConfiguration) { realm ->
335- UserEntity .getOrCreate(realm, userId)
336- .let { userEntity ->
337- if (masterKey == null || selfSigningKey == null ) {
338- // The user has disabled cross signing?
339- userEntity.crossSigningInfoEntity?.deleteOnCascade()
340- userEntity.crossSigningInfoEntity = null
341- } else {
342- var shouldResetMyDevicesLocalTrust = false
343- CrossSigningInfoEntity .getOrCreate(realm, userId).let { signingInfo ->
344- // What should we do if we detect a change of the keys?
345- val existingMaster = signingInfo.getMasterKey()
346- if (existingMaster != null && existingMaster.publicKeyBase64 == masterKey.unpaddedBase64PublicKey) {
347- crossSigningKeysMapper.update(existingMaster, masterKey)
348- } else {
349- Timber .d(" ## CrossSigning MSK change for $userId " )
350- val keyEntity = crossSigningKeysMapper.map(masterKey)
351- signingInfo.setMasterKey(keyEntity)
352- if (userId == this .userId) {
353- shouldResetMyDevicesLocalTrust = true
354- // my msk has changed! clear my private key
355- // Could we have some race here? e.g I am the one that did change the keys
356- // could i get this update to early and clear the private keys?
357- // -> initializeCrossSigning is guarding for that by storing all at once
358- realm.where<CryptoMetadataEntity >().findFirst()?.apply {
359- xSignMasterPrivateKey = null
360- }
340+ storeUserCrossSigningKeys(realm, userId, masterKey, selfSigningKey, userSigningKey)
341+ }
342+ }
343+
344+ private fun storeUserCrossSigningKeys (
345+ realm : Realm ,
346+ userId : String ,
347+ masterKey : CryptoCrossSigningKey ? ,
348+ selfSigningKey : CryptoCrossSigningKey ? ,
349+ userSigningKey : CryptoCrossSigningKey ?
350+ ) {
351+ UserEntity .getOrCreate(realm, userId)
352+ .let { userEntity ->
353+ if (masterKey == null || selfSigningKey == null ) {
354+ // The user has disabled cross signing?
355+ userEntity.crossSigningInfoEntity?.deleteOnCascade()
356+ userEntity.crossSigningInfoEntity = null
357+ } else {
358+ var shouldResetMyDevicesLocalTrust = false
359+ CrossSigningInfoEntity .getOrCreate(realm, userId).let { signingInfo ->
360+ // What should we do if we detect a change of the keys?
361+ val existingMaster = signingInfo.getMasterKey()
362+ if (existingMaster != null && existingMaster.publicKeyBase64 == masterKey.unpaddedBase64PublicKey) {
363+ crossSigningKeysMapper.update(existingMaster, masterKey)
364+ } else {
365+ Timber .d(" ## CrossSigning MSK change for $userId " )
366+ val keyEntity = crossSigningKeysMapper.map(masterKey)
367+ signingInfo.setMasterKey(keyEntity)
368+ if (userId == this .userId) {
369+ shouldResetMyDevicesLocalTrust = true
370+ // my msk has changed! clear my private key
371+ // Could we have some race here? e.g I am the one that did change the keys
372+ // could i get this update to early and clear the private keys?
373+ // -> initializeCrossSigning is guarding for that by storing all at once
374+ realm.where<CryptoMetadataEntity >().findFirst()?.apply {
375+ xSignMasterPrivateKey = null
361376 }
362377 }
378+ }
363379
364- val existingSelfSigned = signingInfo.getSelfSignedKey()
365- if (existingSelfSigned != null && existingSelfSigned.publicKeyBase64 == selfSigningKey.unpaddedBase64PublicKey) {
366- crossSigningKeysMapper.update(existingSelfSigned, selfSigningKey)
380+ val existingSelfSigned = signingInfo.getSelfSignedKey()
381+ if (existingSelfSigned != null && existingSelfSigned.publicKeyBase64 == selfSigningKey.unpaddedBase64PublicKey) {
382+ crossSigningKeysMapper.update(existingSelfSigned, selfSigningKey)
383+ } else {
384+ Timber .d(" ## CrossSigning SSK change for $userId " )
385+ val keyEntity = crossSigningKeysMapper.map(selfSigningKey)
386+ signingInfo.setSelfSignedKey(keyEntity)
387+ if (userId == this .userId) {
388+ shouldResetMyDevicesLocalTrust = true
389+ // my ssk has changed! clear my private key
390+ realm.where<CryptoMetadataEntity >().findFirst()?.apply {
391+ xSignSelfSignedPrivateKey = null
392+ }
393+ }
394+ }
395+
396+ // Only for me
397+ if (userSigningKey != null ) {
398+ val existingUSK = signingInfo.getUserSigningKey()
399+ if (existingUSK != null && existingUSK.publicKeyBase64 == userSigningKey.unpaddedBase64PublicKey) {
400+ crossSigningKeysMapper.update(existingUSK, userSigningKey)
367401 } else {
368- Timber .d(" ## CrossSigning SSK change for $userId " )
369- val keyEntity = crossSigningKeysMapper.map(selfSigningKey )
370- signingInfo.setSelfSignedKey (keyEntity)
402+ Timber .d(" ## CrossSigning USK change for $userId " )
403+ val keyEntity = crossSigningKeysMapper.map(userSigningKey )
404+ signingInfo.setUserSignedKey (keyEntity)
371405 if (userId == this .userId) {
372406 shouldResetMyDevicesLocalTrust = true
373- // my ssk has changed! clear my private key
407+ // my usk has changed! clear my private key
374408 realm.where<CryptoMetadataEntity >().findFirst()?.apply {
375- xSignSelfSignedPrivateKey = null
409+ xSignUserPrivateKey = null
376410 }
377411 }
378412 }
413+ }
379414
380- // Only for me
381- if (userSigningKey != null ) {
382- val existingUSK = signingInfo.getUserSigningKey()
383- if (existingUSK != null && existingUSK.publicKeyBase64 == userSigningKey.unpaddedBase64PublicKey) {
384- crossSigningKeysMapper.update(existingUSK, userSigningKey)
385- } else {
386- Timber .d(" ## CrossSigning USK change for $userId " )
387- val keyEntity = crossSigningKeysMapper.map(userSigningKey)
388- signingInfo.setUserSignedKey(keyEntity)
389- if (userId == this .userId) {
390- shouldResetMyDevicesLocalTrust = true
391- // my usk has changed! clear my private key
392- realm.where<CryptoMetadataEntity >().findFirst()?.apply {
393- xSignUserPrivateKey = null
394- }
415+ // When my cross signing keys are reset, we consider clearing all existing device trust
416+ if (shouldResetMyDevicesLocalTrust) {
417+ realm.where<UserEntity >()
418+ .equalTo(UserEntityFields .USER_ID , this .userId)
419+ .findFirst()
420+ ?.devices?.forEach {
421+ it?.trustLevelEntity?.crossSignedVerified = false
422+ it?.trustLevelEntity?.locallyVerified = it.deviceId == deviceId
395423 }
396- }
397- }
398-
399- // When my cross signing keys are reset, we consider clearing all existing device trust
400- if (shouldResetMyDevicesLocalTrust) {
401- realm.where<UserEntity >()
402- .equalTo(UserEntityFields .USER_ID , this .userId)
403- .findFirst()
404- ?.devices?.forEach {
405- it?.trustLevelEntity?.crossSignedVerified = false
406- it?.trustLevelEntity?.locallyVerified = it.deviceId == deviceId
407- }
408- }
409- userEntity.crossSigningInfoEntity = signingInfo
410424 }
425+ userEntity.crossSigningInfoEntity = signingInfo
411426 }
412427 }
413- }
428+ }
414429 }
415430
416431 override fun getCrossSigningPrivateKeys (): PrivateKeysInfo ? {
@@ -1831,13 +1846,24 @@ internal class RealmCryptoStore @Inject constructor(
18311846 }
18321847 doRealmTransaction(" onSyncCompleted" , realmConfiguration) { realm ->
18331848 // setShouldShareHistory
1834- aggregator.setShouldShareHistoryData.map {
1849+ aggregator.setShouldShareHistoryData.forEach {
18351850 CryptoRoomEntity .getOrCreate(realm, it.key).shouldShareHistory = it.value
18361851 }
18371852 // setShouldEncryptForInvitedMembers
1838- aggregator.setShouldEncryptForInvitedMembersData.map {
1853+ aggregator.setShouldEncryptForInvitedMembersData.forEach {
18391854 CryptoRoomEntity .getOrCreate(realm, it.key).shouldEncryptForInvitedMembers = it.value
18401855 }
18411856 }
18421857 }
1858+
1859+ override fun storeUserDataToStore (userDataToStore : UserDataToStore ) {
1860+ doRealmTransaction(" storeUserDataToStore" , realmConfiguration) { realm ->
1861+ userDataToStore.userDevices.forEach {
1862+ storeUserDevices(realm, it.key, it.value)
1863+ }
1864+ userDataToStore.userCrossSigningKeys.forEach {
1865+ storeUserCrossSigningKeys(realm, it.key, it.value.first, it.value.second, it.value.third)
1866+ }
1867+ }
1868+ }
18431869}
0 commit comments