1#[allow(unused_macros)]
32#[macro_export]
33macro_rules! cryptostore_integration_tests {
34 () => {
35 mod cryptostore_integration_tests {
36 use std::collections::{BTreeMap, HashMap};
37 use std::time::Duration;
38
39 use assert_matches::assert_matches;
40 use matrix_sdk_test::async_test;
41 use ruma::{
42 device_id, events::secret::request::SecretName, room_id, serde::Raw,
43 to_device::DeviceIdOrAllDevices, user_id, DeviceId, RoomId, TransactionId, UserId,
44 };
45 use serde_json::value::to_raw_value;
46 use serde_json::json;
47 use matrix_sdk_common::deserialized_responses::WithheldCode;
48 use $crate::{
49 olm::{
50 Account, Curve25519PublicKey, InboundGroupSession, OlmMessageHash,
51 PrivateCrossSigningIdentity, SenderData, SenderDataType, Session
52 },
53 store::{
54 BackupDecryptionKey, Changes, CryptoStore, DehydratedDeviceKey, DeviceChanges, GossipRequest,
55 IdentityChanges, PendingChanges, RoomSettings,
56 },
57 testing::{get_device, get_other_identity, get_own_identity},
58 types::{
59 events::{
60 dummy::DummyEventContent,
61 olm_v1::{DecryptedSecretSendEvent, OlmV1Keys},
62 room_key_request::MegolmV1AesSha2Content,
63 room_key_withheld::{
64 CommonWithheldCodeContent, MegolmV1AesSha2WithheldContent,
65 RoomKeyWithheldContent,
66 },
67 secret_send::SecretSendContent,
68 ToDeviceEvent,
69 },
70 requests::ToDeviceRequest,
71 DeviceKeys,
72 EventEncryptionAlgorithm,
73 },
74 vodozemac::megolm::{GroupSession, SessionConfig}, DeviceData, GossippedSecret, LocalTrust, SecretInfo,
75 TrackedUser,
76 };
77
78 use super::get_store;
79
80 fn alice_id() -> &'static UserId {
81 user_id!("@alice:example.org")
82 }
83
84 fn alice_device_id() -> &'static DeviceId {
85 device_id!("ALICEDEVICE")
86 }
87
88 fn bob_id() -> &'static UserId {
89 user_id!("@bob:example.org")
90 }
91
92 fn bob_device_id() -> &'static DeviceId {
93 device_id!("BOBDEVICE")
94 }
95
96 pub async fn get_loaded_store(name: &str) -> (Account, impl CryptoStore) {
97 let store = get_store(name, None, true).await;
98 let account = get_account();
99
100 store.save_pending_changes(PendingChanges { account: Some(account.deep_clone()), }).await.expect("Can't save account");
101
102 (account, store)
103 }
104
105 fn get_account() -> Account {
106 Account::with_device_id(alice_id(), alice_device_id())
107 }
108
109 pub(crate) async fn get_account_and_session() -> (Account, Session) {
110 let alice = Account::with_device_id(alice_id(), alice_device_id());
111 let mut bob = Account::with_device_id(bob_id(), bob_device_id());
112
113 bob.generate_one_time_keys(1);
114 let one_time_key = *bob.one_time_keys().values().next().unwrap();
115 let sender_key = bob.identity_keys().curve25519;
116 let session = alice.create_outbound_session_helper(
117 Default::default(),
118 sender_key,
119 one_time_key,
120 false,
121 alice.device_keys(),
122 );
123
124 (alice, session)
125 }
126
127 #[async_test]
128 async fn test_save_account_via_generic_save() {
129 let store = get_store("save_account_via_generic", None, true).await;
130 assert!(store.get_static_account().is_none());
131 assert!(store.load_account().await.unwrap().is_none());
132 let account = get_account();
133
134 store
135 .save_pending_changes(PendingChanges { account: Some(account) })
136 .await
137 .expect("Can't save account");
138 assert!(store.get_static_account().is_some());
139 }
140
141 #[async_test]
142 async fn test_save_account() {
143 let store = get_store("save_account", None, true).await;
144 assert!(store.get_static_account().is_none());
145 assert!(store.load_account().await.unwrap().is_none());
146 let account = get_account();
147
148 store
149 .save_pending_changes(PendingChanges { account: Some(account) })
150 .await
151 .expect("Can't save account");
152 assert!(store.get_static_account().is_some());
153 }
154
155 #[async_test]
156 async fn test_load_account() {
157 let store = get_store("load_account", None, true).await;
158 let account = get_account();
159
160 store
161 .save_pending_changes(PendingChanges { account: Some(account.deep_clone()) })
162 .await
163 .expect("Can't save account");
164
165 let loaded_account = store.load_account().await.expect("Can't load account");
166 let loaded_account = loaded_account.unwrap();
167
168 assert_eq!(account, loaded_account);
169 }
170
171 #[async_test]
172 async fn test_load_account_with_passphrase() {
173 let passphrase = Some("secret_passphrase");
174 let store = get_store("load_account_with_passphrase", passphrase, true).await;
175 let account = get_account();
176
177 store
178 .save_pending_changes(PendingChanges { account: Some(account.deep_clone()) })
179 .await
180 .expect("Can't save account");
181
182 let loaded_account = store.load_account().await.expect("Can't load account");
183 let loaded_account = loaded_account.unwrap();
184
185 assert_eq!(account, loaded_account);
186 }
187
188 #[async_test]
189 async fn test_save_and_share_account() {
190 let store = get_store("save_and_share_account", None, true).await;
191 let mut account = get_account();
192
193 store
194 .save_pending_changes(PendingChanges { account: Some(account.deep_clone()) })
195 .await
196 .expect("Can't save account");
197
198 account.mark_as_shared();
199 account.update_uploaded_key_count(50);
200
201 store
202 .save_pending_changes(PendingChanges { account: Some(account.deep_clone()) })
203 .await
204 .expect("Can't save account");
205
206 let loaded_account = store.load_account().await.expect("Can't load account");
207 let loaded_account = loaded_account.unwrap();
208
209 assert_eq!(account, loaded_account);
210 assert_eq!(account.uploaded_key_count(), loaded_account.uploaded_key_count());
211 }
212
213 #[async_test]
214 async fn test_load_sessions() {
215 let store = get_store("load_sessions", None, true).await;
216 let (account, session) = get_account_and_session().await;
217 store
218 .save_pending_changes(PendingChanges { account: Some(account.deep_clone()) })
219 .await
220 .expect("Can't save account");
221
222 let changes = Changes {
223 sessions: vec![session.clone()],
224 devices: DeviceChanges { new: vec![DeviceData::from_account(&account)], ..Default::default() },
225 ..Default::default()
226 };
227
228 store.save_changes(changes).await.unwrap();
229
230 let sessions = store
231 .get_sessions(&session.sender_key.to_base64())
232 .await
233 .expect("Can't load sessions")
234 .unwrap();
235 let loaded_session = sessions.get(0).cloned().expect("We should find the session in the store.");
236
237 assert_eq!(&session, &loaded_session, "The loaded session should be the same one we put into the store.");
238 }
239
240 #[async_test]
241 async fn test_add_and_save_session() {
242 let store_name = "add_and_save_session";
243
244 let (session_id, account, sender_key) = {
246 let store = get_store(store_name, None, true).await;
247 let (account, session) = get_account_and_session().await;
248 let sender_key = session.sender_key.to_base64();
249 let session_id = session.session_id().to_owned();
250
251 store
252 .save_pending_changes(PendingChanges {
253 account: Some(account.deep_clone()),
254 })
255 .await
256 .expect("Can't save account");
257 store
258 .save_changes(Changes {
259 devices: DeviceChanges {
260 new: vec![DeviceData::from_account(&account)],
261 ..Default::default()
262 },
263 ..Default::default()
264 })
265 .await
266 .unwrap();
267
268 let changes = Changes { sessions: vec![session.clone()], ..Default::default() };
269 store.save_changes(changes).await.unwrap();
270
271 let sessions = store.get_sessions(&sender_key).await.unwrap().unwrap();
272 let session = &sessions[0];
273
274 assert_eq!(session_id, session.session_id());
275
276 (session_id, account, sender_key)
277 };
278
279 let store = get_store(store_name, None, false).await;
281
282 let loaded_account = store.load_account().await.unwrap().unwrap();
284 assert_eq!(account, loaded_account);
285
286 let sessions = store.get_sessions(&sender_key).await.unwrap().unwrap();
287 let session = &sessions[0];
288
289 assert_eq!(session_id, session.session_id());
290 }
291
292 #[async_test]
293 async fn test_load_outbound_group_session() {
294 let dir = "load_outbound_group_session";
295 let room_id = room_id!("!test:localhost");
296
297 {
299 let (account, store) = get_loaded_store(dir.clone()).await;
300 assert!(
301 store.get_outbound_group_session(&room_id).await.unwrap().is_none(),
302 "Initially there should be no outbound group session"
303 );
304
305 let (session, _) =
306 account.create_group_session_pair_with_defaults(&room_id).await;
307
308 let user_id = user_id!("@example:localhost");
309 let request = ToDeviceRequest::new(
310 user_id,
311 DeviceIdOrAllDevices::AllDevices,
312 "m.dummy",
313 Raw::from_json(to_raw_value(&DummyEventContent::new()).unwrap()),
314 );
315
316 session.add_request(TransactionId::new(), request.into(), Default::default());
317
318 let changes = Changes {
319 outbound_group_sessions: vec![session.clone()],
320 ..Default::default()
321 };
322
323 store.save_changes(changes).await.expect("Can't save group session");
324 assert!(
325 store.get_outbound_group_session(&room_id).await.unwrap().is_some(),
326 "Sanity: after we've saved one, there should be an outbound_group_session"
327 );
328 }
329
330 let store = get_store(dir, None, false).await;
332 store.load_account().await.unwrap();
333
334 assert!(
336 store.get_outbound_group_session(&room_id).await.unwrap().is_some(),
337 "The outbound_group_session should have been loaded"
338 );
339 }
340
341 #[async_test]
343 async fn test_save_changes_save_inbound_group_session() {
344 let (account, store) = get_loaded_store("save_inbound_group_session").await;
345
346 let room_id = &room_id!("!test:localhost");
347 let (_, session) = account.create_group_session_pair_with_defaults(room_id).await;
348
349 let changes =
350 Changes { inbound_group_sessions: vec![session], ..Default::default() };
351
352 store.save_changes(changes).await.expect("Can't save group session");
353 }
354
355 #[async_test]
358 async fn test_save_inbound_group_session_from_backup() {
359 let (account, store) =
360 get_loaded_store("save_inbound_group_session_from_backup").await;
361
362 let room_id = &room_id!("!test:localhost");
363 let (_, session) = account.create_group_session_pair_with_defaults(room_id).await;
364
365 session.mark_as_backed_up();
366 store
367 .save_inbound_group_sessions(vec![session.clone()], Some(&"bkpver1"))
368 .await
369 .expect("could not save sessions");
370
371 let loaded_session = store
372 .get_inbound_group_session(&session.room_id, session.session_id())
373 .await
374 .expect("error when loading session")
375 .expect("session not found in store");
376 assert_eq!(session, loaded_session);
377 assert_eq!(store.get_inbound_group_sessions().await.unwrap().len(), 1);
378 assert_eq!(store.inbound_group_session_counts(None).await.unwrap().total, 1);
379
380 let to_back_up = store.inbound_group_sessions_for_backup("bkpver1", 1).await.unwrap();
382 assert_eq!(to_back_up.len(), 0, "backup was returned by backup query");
383 assert_eq!(
384 store.inbound_group_session_counts(Some(&"bkpver1")).await.unwrap().backed_up, 1,
385 "backed_up count",
386 );
387 }
388
389 #[ignore]
394 #[async_test]
395 async fn test_save_inbound_group_session_from_old_backup() {
396 let (account, store) =
397 get_loaded_store("save_inbound_group_session_from_old_backup").await;
398
399 let room_id = &room_id!("!test:localhost");
400 let (_, session) = account.create_group_session_pair_with_defaults(room_id).await;
401
402 session.mark_as_backed_up();
403 store
404 .save_inbound_group_sessions(vec![session.clone()], Some(&"bkpver1"))
405 .await
406 .expect("could not save sessions");
407
408 let to_back_up = store.inbound_group_sessions_for_backup("bkpver2", 1).await.unwrap();
410 assert_eq!(to_back_up, vec![session]);
411 assert_eq!(
412 store.inbound_group_session_counts(Some(&"bkpver2")).await.unwrap().backed_up, 0,
413 "backed_up count for backup version 2",
414 );
415 }
416
417 #[async_test]
420 async fn test_save_inbound_group_session_from_import() {
421 let (account, store) =
422 get_loaded_store("save_inbound_group_session_from_import").await;
423
424 let room_id = &room_id!("!test:localhost");
425 let (_, session) = account.create_group_session_pair_with_defaults(room_id).await;
426
427 store
428 .save_inbound_group_sessions(vec![session.clone()], None)
429 .await
430 .expect("could not save sessions");
431
432 let loaded_session = store
433 .get_inbound_group_session(&session.room_id, session.session_id())
434 .await
435 .expect("error when loading session")
436 .expect("session not found in store");
437 assert_eq!(session, loaded_session);
438 assert_eq!(store.get_inbound_group_sessions().await.unwrap().len(), 1);
439 assert_eq!(store.inbound_group_session_counts(None).await.unwrap().total, 1);
440 assert_eq!(store.inbound_group_session_counts(None).await.unwrap().backed_up, 0);
441
442 let to_back_up = store.inbound_group_sessions_for_backup("bkpver1", 1).await.unwrap();
444 assert_eq!(to_back_up, vec![session]);
445 }
446
447 #[async_test]
448 async fn test_mark_inbound_group_sessions_as_backed_up() {
449 let (account, store) =
451 get_loaded_store("mark_inbound_group_sessions_as_backed_up").await;
452 let room_id = &room_id!("!test:localhost");
453 let mut sessions: Vec<InboundGroupSession> = Vec::with_capacity(10);
454 for _i in 0..10 {
455 sessions.push(account.create_group_session_pair_with_defaults(room_id).await.1);
456 }
457 let changes = Changes { inbound_group_sessions: sessions.clone(), ..Default::default() };
458 store.save_changes(changes).await.expect("Can't save group session");
459 assert_eq!(store.inbound_group_sessions_for_backup("bkpver", 100).await.unwrap().len(), 10);
460
461 store.mark_inbound_group_sessions_as_backed_up("bkpver", &[
463 session_info(&sessions[1]),
464 session_info(&sessions[3]),
465 session_info(&sessions[5]),
466 session_info(&sessions[7]),
467 session_info(&sessions[9]),
468 ]).await.expect("Failed to mark sessions as backed up");
469
470 let to_back_up = store.inbound_group_sessions_for_backup("bkpver", 10).await.unwrap();
472 let needs_backing_up = |i: usize| to_back_up.iter().any(|s| s.session_id() == sessions[i].session_id());
473
474 assert!(!needs_backing_up(1));
476 assert!(!needs_backing_up(3));
477 assert!(!needs_backing_up(5));
478 assert!(!needs_backing_up(7));
479 assert!(!needs_backing_up(9));
480
481 assert!(needs_backing_up(0));
483 assert!(needs_backing_up(2));
484 assert!(needs_backing_up(4));
485 assert!(needs_backing_up(6));
486 assert!(needs_backing_up(8));
487 assert_eq!(to_back_up.len(), 5);
488 }
489
490 #[async_test]
491 async fn test_reset_inbound_group_session_for_backup() {
492 let (account, store) =
494 get_loaded_store("reset_inbound_group_session_for_backup").await;
495 let room_id = &room_id!("!test:localhost");
496 let mut sessions: Vec<InboundGroupSession> = Vec::with_capacity(10);
497 for _ in 0..10 {
498 sessions.push(account.create_group_session_pair_with_defaults(room_id).await.1);
499 }
500 let changes = Changes { inbound_group_sessions: sessions.clone(), ..Default::default() };
501 store.save_changes(changes).await.expect("Can't save group session");
502 assert_eq!(store.inbound_group_sessions_for_backup("backup_1", 100).await.unwrap().len(), 10);
503 store.mark_inbound_group_sessions_as_backed_up(
504 "backup_1",
505 &(0..10).map(|i| session_info(&sessions[i])).collect::<Vec<_>>(),
506 ).await.expect("Failed to mark sessions as backed up");
507
508 {
510 let to_back_up_old = store.inbound_group_sessions_for_backup("backup_1", 10).await.unwrap();
511 assert_eq!(to_back_up_old.len(), 0);
512 }
513
514 store.reset_backup_state().await.expect("reset failed");
517
518 let to_back_up = store.inbound_group_sessions_for_backup("backup_02", 10).await.unwrap();
520
521 let needs_backing_up = |i: usize| to_back_up.iter().any(|s| s.session_id() == sessions[i].session_id());
523 assert!(needs_backing_up(0));
524 assert!(needs_backing_up(1));
525 assert!(needs_backing_up(8));
526 assert!(needs_backing_up(9));
527 assert_eq!(to_back_up.len(), 10);
528 }
529
530 #[async_test]
531 async fn test_load_inbound_group_session() {
532 let dir = "load_inbound_group_session";
533 let (account, store) = get_loaded_store(dir).await;
534 assert_eq!(store.get_inbound_group_sessions().await.unwrap().len(), 0);
535
536 let room_id = &room_id!("!test:localhost");
537 let (_, session) = account.create_group_session_pair_with_defaults(room_id).await;
538
539 let export = session.export().await;
540
541 let session = InboundGroupSession::from_export(&export).unwrap();
542
543 let changes =
544 Changes { inbound_group_sessions: vec![session.clone()], ..Default::default() };
545
546 store.save_changes(changes).await.expect("Can't save group session");
547
548 drop(store);
549
550 let store = get_store(dir, None, false).await;
551
552 store.load_account().await.unwrap();
553
554 let loaded_session = store
555 .get_inbound_group_session(&session.room_id, session.session_id())
556 .await
557 .unwrap()
558 .unwrap();
559 assert_eq!(session, loaded_session);
560 loaded_session.export().await;
561
562 assert_eq!(store.get_inbound_group_sessions().await.unwrap().len(), 1);
563 assert_eq!(store.inbound_group_session_counts(None).await.unwrap().total, 1);
564 }
565
566 #[async_test]
567 async fn test_fetch_inbound_group_sessions_for_device() {
568 let (account, store) =
570 get_loaded_store("fetch_inbound_group_sessions_for_device").await;
571
572 let dev1 = Curve25519PublicKey::from_base64(
573 "wjLpTLRqbqBzLs63aYaEv2Boi6cFEbbM/sSRQ2oAKk4"
574 ).unwrap();
575 let dev2 = Curve25519PublicKey::from_base64(
576 "LTpv2DGMhggPAXO02+7f68CNEp6A40F0Yl8B094Y8gc"
577 ).unwrap();
578
579 let dev_1_unknown_a = create_session(&account, &dev1, SenderDataType::UnknownDevice).await;
580 let dev_1_unknown_b = create_session(&account, &dev1, SenderDataType::UnknownDevice).await;
581
582 let dev_1_keys_a = create_session(&account, &dev1, SenderDataType::DeviceInfo).await;
583 let dev_1_keys_b = create_session(&account, &dev1, SenderDataType::DeviceInfo).await;
584 let dev_1_keys_c = create_session(&account, &dev1, SenderDataType::DeviceInfo).await;
585 let dev_1_keys_d = create_session(&account, &dev1, SenderDataType::DeviceInfo).await;
586
587 let dev_2_unknown = create_session(
588 &account, &dev2, SenderDataType::UnknownDevice).await;
589
590 let dev_2_keys = create_session(
591 &account, &dev2, SenderDataType::DeviceInfo).await;
592
593 let sessions = vec![
594 dev_1_unknown_a.clone(),
595 dev_1_unknown_b.clone(),
596 dev_1_keys_a.clone(),
597 dev_1_keys_b.clone(),
598 dev_1_keys_c.clone(),
599 dev_1_keys_d.clone(),
600 dev_2_unknown.clone(),
601 dev_2_keys.clone(),
602 ];
603
604 let changes = Changes {
605 inbound_group_sessions: sessions,
606 ..Default::default()
607 };
608 store.save_changes(changes).await.expect("Can't save group session");
609
610 let sessions_1_u = store.get_inbound_group_sessions_for_device_batch(
612 dev1,
613 SenderDataType::UnknownDevice,
614 None,
615 10
616 ).await.expect("Failed to get sessions for dev1");
617
618 assert_session_lists_eq(sessions_1_u, [dev_1_unknown_a, dev_1_unknown_b], "device 1 sessions");
620
621 let sessions_2_d = store
623 .get_inbound_group_sessions_for_device_batch(dev2, SenderDataType::DeviceInfo, None, 10)
624 .await
625 .expect("Failed to get sessions for dev2");
626
627 assert_eq!(sessions_2_d, vec![dev_2_keys], "device 2 sessions");
629
630 let mut sessions_1_k = Vec::new();
633 let mut previous_last_session_id: Option<String> = None;
634 loop {
635 let mut sessions_1_k_batch = store.get_inbound_group_sessions_for_device_batch(
636 dev1,
637 SenderDataType::DeviceInfo,
638 previous_last_session_id,
639 2
640 ).await.expect("Failed to get batch 1");
641
642 let Some(last_session) = sessions_1_k_batch.last() else {
644 break;
645 };
646
647 assert_eq!(sessions_1_k_batch.len(), 2);
649
650 previous_last_session_id = Some(last_session.session_id().to_owned());
651
652 let mut last_session = last_session.clone();
654 last_session.sender_data = SenderData::unknown();
655 store.save_inbound_group_sessions(vec![last_session], None).await.unwrap();
656
657 sessions_1_k.append(&mut sessions_1_k_batch);
658 }
659
660 assert_session_lists_eq(
661 sessions_1_k,
662 [dev_1_keys_a, dev_1_keys_b, dev_1_keys_c, dev_1_keys_d],
663 "device 1 batched results"
664 );
665 }
666
667 fn assert_session_lists_eq<I, J>(actual: I, expected: J, message: &str)
673 where I: IntoIterator<Item = InboundGroupSession>, J: IntoIterator<Item = InboundGroupSession>
674 {
675 let sorter = |a: &InboundGroupSession, b: &InboundGroupSession| Ord::cmp(a.session_id(), b.session_id());
676
677 let mut actual = Vec::from_iter(actual);
678 actual.sort_unstable_by(sorter);
679 let mut expected = Vec::from_iter(expected);
680 expected.sort_unstable_by(sorter);
681 assert_eq!(actual, expected, "{}", message);
682 }
683
684 #[async_test]
685 async fn test_tracked_users() {
686 let dir = "test_tracked_users";
687 let (_account, store) = get_loaded_store(dir.clone()).await;
688
689 let alice = user_id!("@alice:example.org");
690 let bob = user_id!("@bob:example.org");
691 let candy = user_id!("@candy:example.org");
692
693 let loaded = store.load_tracked_users().await.unwrap();
694 assert!(loaded.is_empty(), "Initially there are no tracked users");
695
696 let users = vec![(alice, true), (bob, false)];
697 store.save_tracked_users(&users).await.unwrap();
698
699 let check_loaded_users = |loaded: Vec<TrackedUser>| {
700 let loaded: HashMap<_, _> =
701 loaded.into_iter().map(|u| (u.user_id.to_owned(), u)).collect();
702
703 let loaded_alice =
704 loaded.get(alice).expect("Alice should be in the store as a tracked user");
705 let loaded_bob =
706 loaded.get(bob).expect("Bob should be in the store as as tracked user");
707
708 assert!(!loaded.contains_key(candy), "Candy shouldn't be part of the store");
709 assert_eq!(loaded.len(), 2, "Candy shouldn't be part of the store");
710
711 assert!(loaded_alice.dirty, "Alice should be considered to be dirty");
712 assert!(!loaded_bob.dirty, "Bob should not be considered to be dirty");
713 };
714
715 let loaded = store.load_tracked_users().await.unwrap();
716 check_loaded_users(loaded);
717
718 drop(store);
719
720 let name = dir.clone();let store = get_store(name, None, false).await;
721 let loaded = store.load_tracked_users().await.unwrap();
722 check_loaded_users(loaded);
723 }
724
725 #[async_test]
726 async fn test_device_saving() {
727 let dir = "device_saving";
728 let (_account, store) = get_loaded_store(dir.clone()).await;
729
730 let alice_device_1 = DeviceData::from_account(&Account::with_device_id(
731 "@alice:localhost".try_into().unwrap(),
732 "FIRSTDEVICE".into(),
733 ));
734
735 let alice_device_2 = DeviceData::from_account(&Account::with_device_id(
736 "@alice:localhost".try_into().unwrap(),
737 "SECONDDEVICE".into(),
738 ));
739
740 let json = json!({
741 "algorithms": ["m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"],
742 "user_id": "@bob:localhost",
743 "device_id": "BOBDEVICE",
744 "extra_property": "somevalue",
745 "keys": {
746 "curve25519:BOBDEVICE": "n0zs7qnaPLLf/OTL+dDLcI5kaPexbUeQ8jLQ2q6sO0E",
747 "ed25519:BOBDEVICE": "RrKiu4+5EHRBWY6Qj6OtQGC0txpmEeanOz2irEZ/IN4",
748 },
749 "signatures": {
750 "@bob:localhost": {
751 "ed25519:BOBDEVICE": "9NjPewVHfB7Ah32mJ+CBx64mVoiQ8gbh+/2pc9WfAgut/H0Kqd/bbpgJq9Pn518szaXcGqEq0DxDP6CABBX8CQ",
752 },
753 },
754 });
755
756 let bob_device_1_keys: DeviceKeys = serde_json::from_value(json).unwrap();
757 let bob_device_1 = DeviceData::new(bob_device_1_keys, LocalTrust::Unset);
758
759 let changes = Changes {
760 devices: DeviceChanges {
761 new: vec![alice_device_1.clone(), alice_device_2.clone(), bob_device_1.clone()],
762 ..Default::default()
763 },
764 ..Default::default()
765 };
766
767 store.save_changes(changes).await.unwrap();
768
769 drop(store);
770
771 let store = get_store(dir, None, false).await;
772
773 store.load_account().await.unwrap();
774
775 let loaded_device = store
776 .get_device(alice_device_1.user_id(), alice_device_1.device_id())
777 .await
778 .unwrap()
779 .unwrap();
780
781 assert_eq!(alice_device_1, loaded_device);
782
783 for algorithm in loaded_device.algorithms() {
784 assert!(alice_device_1.algorithms().contains(algorithm));
785 }
786 assert_eq!(alice_device_1.algorithms().len(), loaded_device.algorithms().len());
787 assert_eq!(alice_device_1.keys(), loaded_device.keys());
788
789 let user_devices = store.get_user_devices(alice_device_1.user_id()).await.unwrap();
790 assert_eq!(user_devices.len(), 2);
791
792 let bob_device = store
793 .get_device(bob_device_1.user_id(), bob_device_1.device_id())
794 .await
795 .unwrap();
796
797 let bob_device_json = serde_json::to_value(bob_device).unwrap();
798 assert_eq!(bob_device_json["device_keys"]["extra_property"], json!("somevalue"));
799 }
800
801 #[async_test]
802 async fn test_device_deleting() {
803 let dir = "device_deleting";
804 let (_account, store) = get_loaded_store(dir.clone()).await;
805 let device = get_device();
806
807 let changes = Changes {
808 devices: DeviceChanges { changed: vec![device.clone()], ..Default::default() },
809 ..Default::default()
810 };
811
812 store.save_changes(changes).await.unwrap();
813
814 let changes = Changes {
815 devices: DeviceChanges { deleted: vec![device.clone()], ..Default::default() },
816 ..Default::default()
817 };
818
819 store.save_changes(changes).await.unwrap();
820 drop(store);
821
822 let store = get_store(dir, None, false).await;
823
824 store.load_account().await.unwrap();
825
826 let loaded_device =
827 store.get_device(device.user_id(), device.device_id()).await.unwrap();
828
829 assert!(loaded_device.is_none());
830 }
831
832 #[async_test]
833 async fn test_user_saving() {
834 let dir = "user_saving";
835
836 let user_id = user_id!("@example:localhost");
837 let device_id: &DeviceId = "WSKKLTJZCL".into();
838
839 let store = get_store(dir, None, true).await;
840
841 let account = Account::with_device_id(&user_id, device_id);
842
843 store.save_pending_changes(PendingChanges { account: Some(account), })
844 .await
845 .expect("Can't save account");
846
847 let own_identity = get_own_identity();
848
849 let changes = Changes {
850 identities: IdentityChanges {
851 changed: vec![own_identity.clone().into()],
852 ..Default::default()
853 },
854 ..Default::default()
855 };
856
857 store.save_changes(changes).await.expect("Can't save identity");
858
859 drop(store);
860
861 let store = get_store(dir, None, false).await;
862
863 store.load_account().await.unwrap();
864
865 let loaded_user =
866 store.get_user_identity(own_identity.user_id()).await.unwrap().unwrap();
867
868 assert_eq!(loaded_user.master_key(), own_identity.master_key());
869 assert_eq!(loaded_user.self_signing_key(), own_identity.self_signing_key());
870 assert_eq!(loaded_user.own().unwrap().clone(), own_identity.clone());
871
872 let other_identity = get_other_identity();
873
874 let changes = Changes {
875 identities: IdentityChanges {
876 changed: vec![other_identity.clone().into()],
877 ..Default::default()
878 },
879 ..Default::default()
880 };
881
882 store.save_changes(changes).await.unwrap();
883
884 let loaded_user =
885 store.get_user_identity(other_identity.user_id()).await.unwrap().unwrap();
886
887 assert_eq!(loaded_user.master_key(), other_identity.master_key());
888 assert_eq!(loaded_user.self_signing_key(), other_identity.self_signing_key());
889 assert_eq!(loaded_user.user_id(), other_identity.user_id());
890 assert_eq!(loaded_user.other().unwrap().clone(), other_identity);
891
892 own_identity.mark_as_verified();
893
894 let changes = Changes {
895 identities: IdentityChanges {
896 changed: vec![own_identity.into()],
897 ..Default::default()
898 },
899 ..Default::default()
900 };
901
902 store.save_changes(changes).await.unwrap();
903 let loaded_user = store.get_user_identity(&user_id).await.unwrap().unwrap();
904 assert!(loaded_user.own().unwrap().is_verified())
905 }
906
907 #[async_test]
908 async fn test_private_identity_saving() {
909 let (_, store) = get_loaded_store("private_identity_saving").await;
910 assert!(store.load_identity().await.unwrap().is_none());
911 let identity = PrivateCrossSigningIdentity::new(alice_id().to_owned());
912
913 let changes =
914 Changes { private_identity: Some(identity.clone()), ..Default::default() };
915
916 store.save_changes(changes).await.unwrap();
917 let loaded_identity = store.load_identity().await.unwrap().unwrap();
918 assert_eq!(identity.user_id(), loaded_identity.user_id());
919 }
920
921 #[async_test]
922 async fn test_olm_hash_saving() {
923 let (_, store) = get_loaded_store("olm_hash_saving").await;
924
925 let hash = OlmMessageHash {
926 sender_key: "test_sender".to_owned(),
927 hash: "test_hash".to_owned(),
928 };
929
930 let mut changes = Changes::default();
931 changes.message_hashes.push(hash.clone());
932
933 assert!(!store.is_message_known(&hash).await.unwrap());
934 store.save_changes(changes).await.unwrap();
935 assert!(store.is_message_known(&hash).await.unwrap());
936 }
937
938 #[async_test]
939 async fn test_key_request_saving() {
940 let (account, store) = get_loaded_store("key_request_saving").await;
941 let sender_key =
942 Curve25519PublicKey::from_base64("Nn0L2hkcCMFKqynTjyGsJbth7QrVmX3lbrksMkrGOAw")
943 .unwrap();
944
945 let id = TransactionId::new();
946 let info: SecretInfo = MegolmV1AesSha2Content {
947 room_id: room_id!("!test:localhost").to_owned(),
948 sender_key,
949 session_id: "test_session_id".to_owned(),
950 }
951 .into();
952
953 let request = GossipRequest {
954 request_recipient: account.user_id().to_owned(),
955 request_id: id.clone(),
956 info: info.clone(),
957 sent_out: false,
958 };
959
960 assert!(store.get_outgoing_secret_requests(&id).await.unwrap().is_none());
961
962 let mut changes = Changes::default();
963 changes.key_requests.push(request.clone());
964 store.save_changes(changes).await.unwrap();
965
966 let request = Some(request);
967
968 let stored_request = store.get_outgoing_secret_requests(&id).await.unwrap();
969 assert_eq!(request, stored_request);
970
971 let stored_request = store.get_secret_request_by_info(&info).await.unwrap();
972 assert_eq!(request, stored_request);
973 assert!(!store.get_unsent_secret_requests().await.unwrap().is_empty());
974
975 let request = GossipRequest {
976 request_recipient: account.user_id().to_owned(),
977 request_id: id.clone(),
978 info: info.clone(),
979 sent_out: true,
980 };
981
982 let mut changes = Changes::default();
983 changes.key_requests.push(request.clone());
984 store.save_changes(changes).await.unwrap();
985
986 assert!(store.get_unsent_secret_requests().await.unwrap().is_empty());
987 let stored_request = store.get_outgoing_secret_requests(&id).await.unwrap();
988 assert_eq!(Some(request), stored_request);
989
990 store.delete_outgoing_secret_requests(&id).await.unwrap();
991
992 let stored_request = store.get_outgoing_secret_requests(&id).await.unwrap();
993 assert_eq!(None, stored_request);
994
995 let stored_request = store.get_secret_request_by_info(&info).await.unwrap();
996 assert_eq!(None, stored_request);
997 assert!(store.get_unsent_secret_requests().await.unwrap().is_empty());
998 }
999
1000 #[async_test]
1001 async fn test_gossipped_secret_saving() {
1002 let (account, store) = get_loaded_store("gossipped_secret_saving").await;
1003
1004 let secret = "It is a secret to everybody";
1005
1006 let id = TransactionId::new();
1007 let info: SecretInfo = MegolmV1AesSha2Content {
1008 room_id: room_id!("!test:localhost").to_owned(),
1009 sender_key: account.identity_keys().curve25519,
1010 session_id: "test_session_id".to_owned(),
1011 }
1012 .into();
1013
1014 let gossip_request = GossipRequest {
1015 request_recipient: account.user_id().to_owned(),
1016 request_id: id.clone(),
1017 info: info.clone(),
1018 sent_out: true,
1019 };
1020
1021 let mut event = DecryptedSecretSendEvent {
1022 sender: account.user_id().to_owned(),
1023 recipient: account.user_id().to_owned(),
1024 keys: OlmV1Keys {
1025 ed25519: account.identity_keys().ed25519,
1026 },
1027 recipient_keys: OlmV1Keys {
1028 ed25519: account.identity_keys().ed25519,
1029 },
1030 sender_device_keys: None,
1031 content: SecretSendContent::new(id.to_owned(), secret.to_owned()),
1032 };
1033
1034 let value = GossippedSecret {
1035 secret_name: SecretName::RecoveryKey,
1036 gossip_request: gossip_request.to_owned(),
1037 event: event.to_owned(),
1038 };
1039
1040 assert!(
1041 store.get_secrets_from_inbox(&SecretName::RecoveryKey).await.unwrap().is_empty(),
1042 "No secret should initially be found in the store"
1043 );
1044
1045 let mut changes = Changes::default();
1046 changes.secrets.push(value);
1047 store.save_changes(changes).await.unwrap();
1048
1049 let restored = store.get_secrets_from_inbox(&SecretName::RecoveryKey).await.unwrap();
1050 let first_secret = restored.first().expect("We should have restored a secret now");
1051 assert_eq!(first_secret.event.content.secret, secret);
1052 assert_eq!(restored.len(), 1, "We should only have one secret stored for now");
1053
1054 event.content.request_id = TransactionId::new();
1055 let another_secret = GossippedSecret {
1056 secret_name: SecretName::RecoveryKey,
1057 gossip_request,
1058 event,
1059 };
1060
1061 let mut changes = Changes::default();
1062 changes.secrets.push(another_secret);
1063 store.save_changes(changes).await.unwrap();
1064
1065 let restored = store.get_secrets_from_inbox(&SecretName::RecoveryKey).await.unwrap();
1066 assert_eq!(restored.len(), 2, "We should only have two secrets stored");
1067
1068 let restored = store.get_secrets_from_inbox(&SecretName::CrossSigningMasterKey).await.unwrap();
1069 assert!(restored.is_empty(), "We should not have secrets of a different type stored");
1070
1071 store.delete_secrets_from_inbox(&SecretName::RecoveryKey).await.unwrap();
1072
1073 let restored = store.get_secrets_from_inbox(&SecretName::RecoveryKey).await.unwrap();
1074 assert!(restored.is_empty(), "We should not have any secrets after we have deleted them");
1075 }
1076
1077 #[async_test]
1078 async fn test_withheld_info_storage() {
1079 let (account, store) = get_loaded_store("withheld_info_storage").await;
1080
1081 let mut info_list: BTreeMap<_, BTreeMap<_, _>> = BTreeMap::new();
1082
1083 let user_id = account.user_id().to_owned();
1084 let room_id = room_id!("!DwLygpkclUAfQNnfva:example.com");
1085 let session_id_1 = "GBnDxGP9i3IkPsz3/ihNr6P7qjIXxSRVWZ1MYmSn09w";
1086 let session_id_2 = "IDLtnNCH2kIr3xIf1B7JFkGpQmTjyMca2jww+X6zeOE";
1087
1088 let content = RoomKeyWithheldContent::MegolmV1AesSha2(
1089 MegolmV1AesSha2WithheldContent::Unverified(
1090 CommonWithheldCodeContent::new(
1091 room_id.to_owned(),
1092 session_id_1.into(),
1093 Curve25519PublicKey::from_base64(
1094 "9n7mdWKOjr9c4NTlG6zV8dbFtNK79q9vZADoh7nMUwA",
1095 )
1096 .unwrap(),
1097 "DEVICEID".into(),
1098 )
1099 .into(),
1100 ),
1101 );
1102 let event = ToDeviceEvent::new(user_id.to_owned(), content);
1103 info_list
1104 .entry(room_id.to_owned())
1105 .or_default()
1106 .insert(session_id_1.to_owned(), event);
1107
1108 let content = RoomKeyWithheldContent::MegolmV1AesSha2(
1109 MegolmV1AesSha2WithheldContent::BlackListed(
1110 CommonWithheldCodeContent::new(
1111 room_id.to_owned(),
1112 session_id_2.into(),
1113 Curve25519PublicKey::from_base64(
1114 "9n7mdWKOjr9c4NTlG6zV8dbFtNK79q9vZADoh7nMUwA",
1115 )
1116 .unwrap(),
1117 "DEVICEID".into(),
1118 )
1119 .into(),
1120 ),
1121 );
1122 let event = ToDeviceEvent::new(user_id.to_owned(), content);
1123 info_list
1124 .entry(room_id.to_owned())
1125 .or_default()
1126 .insert(session_id_2.to_owned(), event);
1127
1128 let changes = Changes { withheld_session_info: info_list, ..Default::default() };
1129 store.save_changes(changes).await.unwrap();
1130
1131 let is_withheld = store.get_withheld_info(room_id, session_id_1).await.unwrap();
1132
1133 assert_matches!(
1134 is_withheld, Some(event)
1135 if event.content.algorithm() == EventEncryptionAlgorithm::MegolmV1AesSha2 &&
1136 event.content.withheld_code() == WithheldCode::Unverified
1137 );
1138
1139 let is_withheld = store.get_withheld_info(room_id, session_id_2).await.unwrap();
1140
1141 assert_matches!(
1142 is_withheld, Some(event)
1143 if event.content.algorithm() == EventEncryptionAlgorithm::MegolmV1AesSha2 &&
1144 event.content.withheld_code() == WithheldCode::Blacklisted
1145 );
1146
1147 let other_room_id = room_id!("!nQRyiRFuyUhXeaQfiR:example.com");
1148
1149 let is_withheld =
1150 store.get_withheld_info(other_room_id, session_id_2).await.unwrap();
1151
1152 assert!(is_withheld.is_none());
1153 }
1154
1155 #[async_test]
1156 async fn test_room_settings_saving() {
1157 let (_, store) = get_loaded_store("room_settings_saving").await;
1158
1159 let room_1 = room_id!("!test_1:localhost");
1160 let settings_1 = RoomSettings {
1161 algorithm: EventEncryptionAlgorithm::MegolmV1AesSha2,
1162 only_allow_trusted_devices: true,
1163 session_rotation_period: Some(Duration::from_secs(10)),
1164 session_rotation_period_messages: Some(123),
1165 };
1166
1167 let room_2 = room_id!("!test_2:localhost");
1168 let settings_2 = RoomSettings {
1169 algorithm: EventEncryptionAlgorithm::OlmV1Curve25519AesSha2,
1170 only_allow_trusted_devices: false,
1171 ..Default::default()
1172 };
1173
1174 let room_3 = room_id!("!test_3:localhost");
1175
1176 let changes = Changes {
1177 room_settings: HashMap::from([
1178 (room_1.into(), settings_1.clone()),
1179 (room_2.into(), settings_2.clone()),
1180 ]),
1181 ..Default::default()
1182 };
1183
1184 store.save_changes(changes).await.unwrap();
1185
1186 let loaded_settings_1 = store.get_room_settings(room_1).await.unwrap();
1187 assert_eq!(Some(settings_1), loaded_settings_1);
1188
1189 let loaded_settings_2 = store.get_room_settings(room_2).await.unwrap();
1190 assert_eq!(Some(settings_2), loaded_settings_2);
1191
1192 let loaded_settings_3 = store.get_room_settings(room_3).await.unwrap();
1193 assert_eq!(None, loaded_settings_3);
1194 }
1195
1196 #[async_test]
1197 async fn test_backup_keys_saving() {
1198 let (_account, store) = get_loaded_store("backup_keys_saving").await;
1199
1200 let restored = store.load_backup_keys().await.unwrap();
1201 assert!(restored.decryption_key.is_none(), "Initially no backup decryption key should be present");
1202
1203 let backup_decryption_key = Some(BackupDecryptionKey::new().unwrap());
1204
1205 let changes = Changes { backup_decryption_key, ..Default::default() };
1206 store.save_changes(changes).await.unwrap();
1207
1208 let restored = store.load_backup_keys().await.unwrap();
1209 assert!(restored.decryption_key.is_some(), "We should be able to restore a backup decryption key");
1210 assert!(restored.backup_version.is_none(), "The backup version should still be None");
1211
1212 let changes = Changes { backup_version: Some("some_version".to_owned()), ..Default::default() };
1213 store.save_changes(changes).await.unwrap();
1214
1215 let restored = store.load_backup_keys().await.unwrap();
1216 assert!(restored.decryption_key.is_some(), "The backup decryption key should still be known");
1217 assert!(restored.backup_version.is_some(), "The backup version should now be Some as well");
1218 }
1219
1220 #[async_test]
1221 async fn test_dehydration_pickle_key_saving() {
1222 let (_account, store) = get_loaded_store("dehydration_pickle_key_saving").await;
1223
1224 let restored = store.load_dehydrated_device_pickle_key().await.unwrap();
1225 assert!(restored.is_none(), "Initially no pickle key should be present");
1226
1227 let dehydrated_device_pickle_key = Some(DehydratedDeviceKey::new().unwrap());
1228 let exported_base64 = dehydrated_device_pickle_key.clone().unwrap().to_base64();
1229
1230 let changes = Changes { dehydrated_device_pickle_key, ..Default::default() };
1231 store.save_changes(changes).await.unwrap();
1232
1233 let restored = store.load_dehydrated_device_pickle_key().await.unwrap();
1234 assert!(restored.is_some(), "We should be able to restore a pickle key");
1235 assert_eq!(restored.unwrap().to_base64(), exported_base64);
1236
1237 let changes = Changes { dehydrated_device_pickle_key: None, ..Default::default() };
1239 store.save_changes(changes).await.unwrap();
1240
1241 let restored = store.load_dehydrated_device_pickle_key().await.unwrap();
1242 assert!(restored.is_some(), "We should be able to restore a pickle key");
1243 assert_eq!(restored.unwrap().to_base64(), exported_base64);
1244
1245 }
1246
1247 #[async_test]
1248 async fn test_delete_dehydration_pickle_key() {
1249 let (_account, store) = get_loaded_store("delete_dehydration_pickle_key").await;
1250
1251 let dehydrated_device_pickle_key = DehydratedDeviceKey::new().unwrap();
1252
1253 let changes = Changes { dehydrated_device_pickle_key: Some(dehydrated_device_pickle_key), ..Default::default() };
1254 store.save_changes(changes).await.unwrap();
1255
1256 let restored = store.load_dehydrated_device_pickle_key().await.unwrap();
1257 assert!(restored.is_some(), "We should be able to restore a pickle key");
1258
1259 store.delete_dehydrated_device_pickle_key().await.unwrap();
1260
1261 let restored = store.load_dehydrated_device_pickle_key().await.unwrap();
1262 assert!(restored.is_none(), "The previously saved key should be deleted");
1263
1264 }
1265
1266
1267 #[async_test]
1268 async fn test_custom_value_saving() {
1269 let (_, store) = get_loaded_store("custom_value_saving").await;
1270 store.set_custom_value("A", "Hello".as_bytes().to_vec()).await.unwrap();
1271
1272 let loaded_1 = store.get_custom_value("A").await.unwrap();
1273 assert_eq!(Some("Hello".as_bytes().to_vec()), loaded_1);
1274
1275 let loaded_2 = store.get_custom_value("B").await.unwrap();
1276 assert_eq!(None, loaded_2);
1277 }
1278
1279 fn session_info(session: &InboundGroupSession) -> (&RoomId, &str) {
1280 (&session.room_id(), &session.session_id())
1281 }
1282
1283 async fn create_session(
1284 account: &Account,
1285 device_curve_key: &Curve25519PublicKey,
1286 sender_data_type: SenderDataType,
1287 ) -> InboundGroupSession {
1288 let sender_data = match sender_data_type {
1289 SenderDataType::UnknownDevice => {
1290 SenderData::UnknownDevice { legacy_session: false, owner_check_failed: false }
1291 }
1292 SenderDataType::DeviceInfo => SenderData::DeviceInfo {
1293 device_keys: account.device_keys().clone(),
1294 legacy_session: false,
1295 },
1296 SenderDataType::VerificationViolation => panic!("VerificationViolation not supported"),
1297 SenderDataType::SenderUnverified=> panic!("SenderUnverified not supported"),
1298 SenderDataType::SenderVerified => panic!("SenderVerified not supported"),
1299 };
1300
1301 let session_key = GroupSession::new(SessionConfig::default()).session_key();
1302
1303 InboundGroupSession::new(
1304 device_curve_key.clone(),
1305 account.device_keys().ed25519_key().unwrap(),
1306 room_id!("!r:s.co"),
1307 &session_key,
1308 sender_data,
1309 EventEncryptionAlgorithm::MegolmV1AesSha2,
1310 None,
1311 )
1312 .unwrap()
1313 }
1314 }
1315 };
1316}
1317
1318#[allow(unused_macros)]
1319#[macro_export]
1320macro_rules! cryptostore_integration_tests_time {
1321 () => {
1322 mod cryptostore_integration_tests_time {
1323 use std::time::Duration;
1324
1325 use matrix_sdk_test::async_test;
1326 use $crate::store::CryptoStore as _;
1327
1328 use super::cryptostore_integration_tests::*;
1329
1330 #[async_test]
1331 async fn test_lease_locks() {
1332 let (_account, store) = get_loaded_store("lease_locks").await;
1333
1334 let acquired0 = store.try_take_leased_lock(0, "key", "alice").await.unwrap();
1335 assert!(acquired0);
1336
1337 let acquired2 = store.try_take_leased_lock(300, "key", "alice").await.unwrap();
1339 assert!(acquired2);
1340
1341 let acquired3 = store.try_take_leased_lock(300, "key", "alice").await.unwrap();
1343 assert!(acquired3);
1344
1345 let acquired4 = store.try_take_leased_lock(300, "key", "bob").await.unwrap();
1347 assert!(!acquired4);
1348
1349 let acquired5 = store.try_take_leased_lock(300, "key", "bob").await.unwrap();
1351 assert!(!acquired5);
1352
1353 tokio::time::sleep(Duration::from_millis(50)).await;
1355
1356 let acquired55 = store.try_take_leased_lock(300, "key", "bob").await.unwrap();
1358 assert!(!acquired55);
1359
1360 tokio::time::sleep(Duration::from_millis(250)).await;
1362
1363 let acquired6 = store.try_take_leased_lock(0, "key", "bob").await.unwrap();
1365 assert!(acquired6);
1366
1367 tokio::time::sleep(Duration::from_millis(1)).await;
1368
1369 let acquired7 = store.try_take_leased_lock(0, "key", "alice").await.unwrap();
1371 assert!(acquired7);
1372
1373 tokio::time::sleep(Duration::from_millis(1)).await;
1374
1375 let acquired8 = store.try_take_leased_lock(300, "key", "bob").await.unwrap();
1377 assert!(acquired8);
1378
1379 let acquired9 = store.try_take_leased_lock(300, "key", "alice").await.unwrap();
1381 assert!(!acquired9);
1382
1383 let acquired10 = store.try_take_leased_lock(300, "key", "bob").await.unwrap();
1385 assert!(acquired10);
1386 }
1387 }
1388 };
1389}