diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/CryptoConstants.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/CryptoConstants.kt
index 37b9ac379e..aced0ca3a2 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/CryptoConstants.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/CryptoConstants.kt
@@ -42,3 +42,6 @@ const val SSSS_ALGORITHM_AES_HMAC_SHA2 = "m.secret_storage.v1.aes-hmac-sha2"
 // TODO Refacto: use this constants everywhere
 const val ed25519 = "ed25519"
 const val curve25519 = "curve25519"
+
+const val MEGOLM_DEFAULT_ROTATION_MSGS = 100L
+const val MEGOLM_DEFAULT_ROTATION_PERIOD_MS = 7 * 24 * 3600 * 1000L
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/CryptoRoomInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/CryptoRoomInfo.kt
new file mode 100644
index 0000000000..51cd811150
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/CryptoRoomInfo.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2023 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.session.crypto.model
+
+data class CryptoRoomInfo(
+        val algorithm: String,
+        val shouldEncryptForInvitedMembers: Boolean,
+        val blacklistUnverifiedDevices: Boolean,
+        // Determines whether or not room history should be shared on new member invites
+        val shouldShareHistory: Boolean,
+        // This is specific to megolm but not sure how to model it better
+        // a security to ensure that a room will never revert to not encrypted
+        // even if a new state event with empty encryption, or state is reset somehow
+        val wasEncryptedOnce: Boolean,
+        // How long the session should be used before changing it. 604800000 (a week) is the recommended default.
+        val rotationPeriodMs: Long,
+        // How many messages should be sent before changing the session. 100 is the recommended default.
+        val rotationPeriodMsgs: Long,
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt
index 881b456c48..a13c15bd1a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt
@@ -28,11 +28,13 @@ 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
@@ -284,6 +286,9 @@ internal interface IMXCryptoStore {
      */
     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).
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt
index c3dfffb181..30a33c8810 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt
@@ -40,6 +40,7 @@ import org.matrix.android.sdk.api.session.crypto.keysbackup.BackupUtils
 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.ForwardInfo
 import org.matrix.android.sdk.api.session.crypto.model.IncomingKeyRequestInfo
@@ -48,6 +49,7 @@ 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.crypto.model.WithheldInfo
 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
@@ -58,6 +60,7 @@ import org.matrix.android.sdk.internal.crypto.model.OutboundGroupSessionWrapper
 import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
 import org.matrix.android.sdk.internal.crypto.store.UserDataToStore
 import org.matrix.android.sdk.internal.crypto.store.db.mapper.CrossSigningKeysMapper
+import org.matrix.android.sdk.internal.crypto.store.db.mapper.CryptoRoomInfoMapper
 import org.matrix.android.sdk.internal.crypto.store.db.mapper.MyDeviceLastSeenInfoEntityMapper
 import org.matrix.android.sdk.internal.crypto.store.db.model.AuditTrailEntity
 import org.matrix.android.sdk.internal.crypto.store.db.model.AuditTrailEntityFields
@@ -714,6 +717,30 @@ internal class RealmCryptoStore @Inject constructor(
         }
     }
 
+    override fun getRoomCryptoInfo(roomId: String): CryptoRoomInfo? {
+        return doWithRealm(realmConfiguration) { realm ->
+            CryptoRoomEntity.getById(realm, roomId)?.let {
+                CryptoRoomInfoMapper.map(it)
+            }
+        }
+    }
+
+    override fun setAlgorithmInfo(roomId: String, encryption: EncryptionEventContent?) {
+        doRealmTransaction("setAlgorithmInfo", realmConfiguration) {
+            CryptoRoomEntity.getOrCreate(it, roomId).let { entity ->
+                entity.algorithm = encryption?.algorithm
+                // store anyway the new algorithm, but mark the room
+                // as having been encrypted once whatever, this can never
+                // go back to false
+                if (encryption?.algorithm == MXCRYPTO_ALGORITHM_MEGOLM) {
+                    entity.wasEncryptedOnce = true
+                    entity.rotationPeriodMs = encryption.rotationPeriodMs
+                    entity.rotationPeriodMsgs = encryption.rotationPeriodMsgs
+                }
+            }
+        }
+    }
+
     override fun roomWasOnceEncrypted(roomId: String): Boolean {
         return doWithRealm(realmConfiguration) {
             CryptoRoomEntity.getById(it, roomId)?.wasEncryptedOnce ?: false
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt
index 9129453c8a..c1aeff368f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt
@@ -37,6 +37,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo
 import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo018
 import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo019
 import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo020
+import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo021
 import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration
 import org.matrix.android.sdk.internal.util.time.Clock
 import javax.inject.Inject
@@ -51,7 +52,7 @@ internal class RealmCryptoStoreMigration @Inject constructor(
         private val clock: Clock,
 ) : MatrixRealmMigration(
         dbName = "Crypto",
-        schemaVersion = 20L,
+        schemaVersion = 21L,
 ) {
     /**
      * Forces all RealmCryptoStoreMigration instances to be equal.
@@ -81,5 +82,6 @@ internal class RealmCryptoStoreMigration @Inject constructor(
         if (oldVersion < 18) MigrateCryptoTo018(realm).perform()
         if (oldVersion < 19) MigrateCryptoTo019(realm).perform()
         if (oldVersion < 20) MigrateCryptoTo020(realm).perform()
+        if (oldVersion < 21) MigrateCryptoTo021(realm).perform()
     }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/CryptoRoomInfoMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/CryptoRoomInfoMapper.kt
new file mode 100644
index 0000000000..ef4d30ad42
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/CryptoRoomInfoMapper.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2023 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.internal.crypto.store.db.mapper
+
+import org.matrix.android.sdk.api.crypto.MEGOLM_DEFAULT_ROTATION_MSGS
+import org.matrix.android.sdk.api.crypto.MEGOLM_DEFAULT_ROTATION_PERIOD_MS
+import org.matrix.android.sdk.api.session.crypto.model.CryptoRoomInfo
+import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntity
+
+internal object CryptoRoomInfoMapper {
+
+    fun map(entity: CryptoRoomEntity): CryptoRoomInfo? {
+        val algorithm = entity.algorithm ?: return null
+        return CryptoRoomInfo(
+                algorithm = algorithm,
+                shouldEncryptForInvitedMembers = entity.shouldEncryptForInvitedMembers ?: false,
+                blacklistUnverifiedDevices = entity.blacklistUnverifiedDevices,
+                shouldShareHistory = entity.shouldShareHistory,
+                wasEncryptedOnce = entity.wasEncryptedOnce ?: false,
+                rotationPeriodMsgs = entity.rotationPeriodMsgs ?: MEGOLM_DEFAULT_ROTATION_MSGS,
+                rotationPeriodMs = entity.rotationPeriodMs ?: MEGOLM_DEFAULT_ROTATION_PERIOD_MS
+        )
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo021.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo021.kt
new file mode 100644
index 0000000000..7284d9df50
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo021.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2023 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.internal.crypto.store.db.migration
+
+import io.realm.DynamicRealm
+import org.matrix.android.sdk.api.crypto.MEGOLM_DEFAULT_ROTATION_MSGS
+import org.matrix.android.sdk.api.crypto.MEGOLM_DEFAULT_ROTATION_PERIOD_MS
+import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntityFields
+import org.matrix.android.sdk.internal.util.database.RealmMigrator
+
+/**
+ * This migration stores the rotation parameters for megolm oubound sessions
+ */
+internal class MigrateCryptoTo021(realm: DynamicRealm) : RealmMigrator(realm, 21) {
+
+    override fun doMigrate(realm: DynamicRealm) {
+        realm.schema.get("CryptoRoomEntity")
+                ?.addField(CryptoRoomEntityFields.ROTATION_PERIOD_MS, Long::class.java)
+                ?.setNullable(CryptoRoomEntityFields.ROTATION_PERIOD_MS, true)
+                ?.addField(CryptoRoomEntityFields.ROTATION_PERIOD_MSGS, Long::class.java)
+                ?.setNullable(CryptoRoomEntityFields.ROTATION_PERIOD_MSGS, true)
+                ?.transform {
+                    // As a migration we set the default (will be on par with existing code)
+                    // A clear cache will have the correct values.
+                    it.setLong(CryptoRoomEntityFields.ROTATION_PERIOD_MS, MEGOLM_DEFAULT_ROTATION_PERIOD_MS)
+                    it.setLong(CryptoRoomEntityFields.ROTATION_PERIOD_MSGS, MEGOLM_DEFAULT_ROTATION_MSGS)
+                }
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoRoomEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoRoomEntity.kt
index be57586163..dce47860c7 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoRoomEntity.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoRoomEntity.kt
@@ -32,7 +32,12 @@ internal open class CryptoRoomEntity(
         var outboundSessionInfo: OutboundGroupSessionInfoEntity? = null,
         // a security to ensure that a room will never revert to not encrypted
         // even if a new state event with empty encryption, or state is reset somehow
-        var wasEncryptedOnce: Boolean? = false
+        var wasEncryptedOnce: Boolean? = false,
+
+        // How long the session should be used before changing it. 604800000 (a week) is the recommended default.
+        var rotationPeriodMs: Long? = null,
+        // How many messages should be sent before changing the session. 100 is the recommended default.
+        var rotationPeriodMsgs: Long? = null,
 ) :
         RealmObject() {
 
diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/PrepareToEncryptUseCase.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/PrepareToEncryptUseCase.kt
index 92fdebf5bd..bd55257a44 100644
--- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/PrepareToEncryptUseCase.kt
+++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/PrepareToEncryptUseCase.kt
@@ -23,6 +23,7 @@ import kotlinx.coroutines.sync.Mutex
 import kotlinx.coroutines.sync.withLock
 import kotlinx.coroutines.withContext
 import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
+import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
 import org.matrix.android.sdk.api.logger.LoggerTag
 import org.matrix.android.sdk.api.session.crypto.MXCryptoError
 import org.matrix.android.sdk.internal.crypto.keysbackup.RustKeyBackupService
@@ -49,7 +50,8 @@ internal class PrepareToEncryptUseCase @Inject constructor(
         private val getRoomUserIds: GetRoomUserIdsUseCase,
         private val requestSender: RequestSender,
         private val loadRoomMembersTask: LoadRoomMembersTask,
-        private val keysBackupService: RustKeyBackupService
+        private val keysBackupService: RustKeyBackupService,
+        private val shouldEncryptForInvitedMembers: ShouldEncryptForInvitedMembersUseCase,
 ) {
 
     private val keyClaimLock: Mutex = Mutex()
@@ -87,17 +89,20 @@ internal class PrepareToEncryptUseCase @Inject constructor(
         val keyShareLock = roomKeyShareLocks.getOrPut(roomId) { Mutex() }
         var sharedKey = false
 
-        cryptoStore.getBlockUnverifiedDevices(roomId)
-        cryptoStore.shouldShareHistory(roomId)
+        val info = cryptoStore.getRoomCryptoInfo(roomId)
+                ?: throw java.lang.IllegalArgumentException("Encryption not configured in this room")
+        // how to react if this is null??
+        if (info.algorithm != MXCRYPTO_ALGORITHM_MEGOLM) {
+            throw java.lang.IllegalArgumentException("Unsupported algorithm ${info.algorithm}")
+        }
         val settings = EncryptionSettings(
                 algorithm = EventEncryptionAlgorithm.MEGOLM_V1_AES_SHA2,
-                onlyAllowTrustedDevices = cryptoStore.getBlockUnverifiedDevices(roomId),
-                // TODO should take that from m.room.encryption event
-                rotationPeriod = (7 * 24 * 3600 * 1000).toULong(),
-                rotationPeriodMsgs = 100UL,
-                historyVisibility = if (cryptoStore.shouldShareHistory(roomId)) {
+                onlyAllowTrustedDevices = info.blacklistUnverifiedDevices,
+                rotationPeriod = info.rotationPeriodMs.toULong(),
+                rotationPeriodMsgs = info.rotationPeriodMsgs.toULong(),
+                historyVisibility = if (info.shouldShareHistory) {
                     HistoryVisibility.SHARED
-                } else if (cryptoStore.shouldEncryptForInvitedMembers(roomId)) {
+                } else if (shouldEncryptForInvitedMembers.invoke(roomId)) {
                     HistoryVisibility.INVITED
                 } else {
                     HistoryVisibility.JOINED
diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt
index c5cf779f93..693ea14ba2 100755
--- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt
+++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt
@@ -57,6 +57,7 @@ import org.matrix.android.sdk.api.session.crypto.model.TrailType
 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.session.events.model.EventType
+import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
 import org.matrix.android.sdk.api.session.events.model.content.RoomKeyContent
 import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent
 import org.matrix.android.sdk.api.session.events.model.content.SecretSendEventContent
@@ -384,12 +385,13 @@ internal class RustCryptoService @Inject constructor(
      */
     private suspend fun setEncryptionInRoom(
             roomId: String,
-            algorithm: String?,
+            info: EncryptionEventContent?,
             membersId: List<String>
     ): Boolean {
         // If we already have encryption in this room, we should ignore this event
         // (for now at least. Maybe we should alert the user somehow?)
         val existingAlgorithm = cryptoStore.getRoomAlgorithm(roomId)
+        val algorithm = info?.algorithm
 
         if (!existingAlgorithm.isNullOrEmpty() && existingAlgorithm != algorithm) {
             Timber.tag(loggerTag.value).e("setEncryptionInRoom() : Ignoring m.room.encryption event which requests a change of config in $roomId")
@@ -397,7 +399,7 @@ internal class RustCryptoService @Inject constructor(
         }
 
         // TODO CHECK WITH VALERE
-        cryptoStore.storeRoomAlgorithm(roomId, algorithm)
+        cryptoStore.setAlgorithmInfo(roomId, info)
 
         if (algorithm != MXCRYPTO_ALGORITHM_MEGOLM) {
             Timber.tag(loggerTag.value).e("## CRYPTO | setEncryptionInRoom() : Unable to encrypt room $roomId with $algorithm")
@@ -508,7 +510,7 @@ internal class RustCryptoService @Inject constructor(
 //                Timber.e(throwable, "## CRYPTO | onRoomEncryptionEvent ERROR FAILED TO SETUP CRYPTO ")
 //            } finally {
             val userIds = getRoomUserIds(roomId)
-            setEncryptionInRoom(roomId, event.content?.get("algorithm")?.toString(), userIds)
+            setEncryptionInRoom(roomId, event.content?.toModel<EncryptionEventContent>(), userIds)
 //            }
 //        }
     }