Skip to content

Commit

Permalink
crypto: Verified identity changes - Migration of existing data
Browse files Browse the repository at this point in the history
  • Loading branch information
BillCarsonFr committed Aug 2, 2024
1 parent ce9e0f9 commit 3218831
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 8 deletions.
5 changes: 2 additions & 3 deletions crates/matrix-sdk-crypto/src/identities/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,6 @@ impl TryFrom<OtherUserIdentityDataSerializer> for OtherUserIdentityData {
self_signing_key: Arc::new(v0.self_signing_key),
// We migrate by pinning the current master key
pinned_master_key: Arc::new(RwLock::new(v0.master_key)),
// TODO Migration
verified_latch: Arc::new(false.into()),
})
}
Expand All @@ -505,7 +504,8 @@ impl TryFrom<OtherUserIdentityDataSerializer> for OtherUserIdentityData {
master_key: Arc::new(v1.master_key.clone()),
self_signing_key: Arc::new(v1.self_signing_key),
pinned_master_key: Arc::new(RwLock::new(v1.pinned_master_key)),
// TODO Migration
// Put it to false. There will be a migration to mark all users as dirty, so we
// will receive an update for the identity that will correctly set up the value.
verified_latch: Arc::new(false.into()),
})
}
Expand All @@ -516,7 +516,6 @@ impl TryFrom<OtherUserIdentityDataSerializer> for OtherUserIdentityData {
master_key: Arc::new(v2.master_key.clone()),
self_signing_key: Arc::new(v2.self_signing_key),
pinned_master_key: Arc::new(RwLock::new(v2.pinned_master_key)),
// TODO Migration
verified_latch: Arc::new(v2.verified_latch.into()),
})
}
Expand Down
77 changes: 72 additions & 5 deletions crates/matrix-sdk-crypto/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ impl std::fmt::Debug for OlmMachine {

impl OlmMachine {
const CURRENT_GENERATION_STORE_KEY: &'static str = "generation-counter";
const HAS_MIGRATED_VERIFICATION_LATCH: &'static str = "HAS_MIGRATED_VERIFICATION_LATCH";

/// Create a new memory based OlmMachine.
///
Expand Down Expand Up @@ -357,9 +358,40 @@ impl OlmMachine {

let identity = Arc::new(Mutex::new(identity));
let store = Arc::new(CryptoStoreWrapper::new(user_id, store));

// FIXME: We might want in the future a more generic high-level data migration
// mechanism (at the store wrapper layer).
Self::migration_post_verified_latch_support(&store).await?;

Ok(OlmMachine::new_helper(device_id, store, static_account, identity, maybe_backup_key))
}

// The sdk now support verified identity change detection.
// This introduces a new local flag (`verified_latch` on
// `OtherUserIdentityData`). In order to ensure that this flag is up-to-date and
// for the sake of simplicity we force a re-download of tracked users by marking
// them as dirty.
//
// pub(crate) visibility for testing.
pub(crate) async fn migration_post_verified_latch_support(
store: &CryptoStoreWrapper,
) -> Result<(), CryptoStoreError> {
let maybe_migrate_for_identity_verified_latch =
store.get_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH).await?.is_none();
if maybe_migrate_for_identity_verified_latch {
// We want to mark all tracked users as dirty to ensure the verified latch is
// set up correctly.
let tracked_user = store.load_tracked_users().await?;
let mut store_updates = Vec::with_capacity(tracked_user.len());
tracked_user.iter().for_each(|tu| {
store_updates.push((tu.user_id.as_ref(), true));
});
store.save_tracked_users(&store_updates).await?;
store.set_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH, vec![0]).await?
}
Ok(())
}

/// Get the crypto store associated with this `OlmMachine` instance.
pub fn store(&self) -> &Store {
&self.inner.store
Expand Down Expand Up @@ -804,11 +836,11 @@ impl OlmMachine {
}

#[instrument(
skip_all,
// This function is only ever called by add_room_key via
// handle_decrypted_to_device_event, so sender, sender_key, and algorithm are
// already recorded.
fields(room_id = ?content.room_id, session_id)
skip_all,
// This function is only ever called by add_room_key via
// handle_decrypted_to_device_event, so sender, sender_key, and algorithm are
// already recorded.
fields(room_id = ? content.room_id, session_id)
)]
async fn handle_key(
&self,
Expand Down Expand Up @@ -4947,4 +4979,39 @@ pub(crate) mod tests {
.unwrap();
assert_matches!(thread_encryption_result, UnsignedDecryptionResult::Decrypted(_));
}

#[async_test]
async fn test_verified_latch_migration() {
let store = MemoryStore::new();
let account = vodozemac::olm::Account::new();

// put some tracked users
let bob_id = user_id!("@bob:localhost");
let carol_id = user_id!("@carol:localhost");

// Mark them as not dirty
let to_track_not_dirty = vec![(bob_id, false), (carol_id, false)];
store.save_tracked_users(&to_track_not_dirty).await.unwrap();

let alice = OlmMachine::with_store(user_id(), alice_device_id(), store, Some(account))
.await
.unwrap();

// A migration should have occurred and all users should be marked as dirty
alice.store().load_tracked_users().await.unwrap().iter().for_each(|tu| {
assert!(tu.dirty);
});

// Ensure it does so only once
alice.store().save_tracked_users(&to_track_not_dirty).await.unwrap();

OlmMachine::migration_post_verified_latch_support(alice.store().crypto_store().as_ref())
.await
.unwrap();

// Migration already done, so user should not be marked as dirty
alice.store().load_tracked_users().await.unwrap().iter().for_each(|tu| {
assert!(!tu.dirty);
});
}
}

0 comments on commit 3218831

Please sign in to comment.