1use std::{
16 collections::{BTreeMap, BTreeSet, HashMap, HashSet},
17 ops::Deref,
18 sync::Arc,
19 time::Duration,
20};
21
22use futures_util::future::join_all;
23use itertools::Itertools;
24use matrix_sdk_common::{executor::spawn, failures_cache::FailuresCache};
25#[cfg(feature = "experimental-x509-identity-verification")]
26use ruma::api::client::keys::upload_signatures::v3::Request as SignatureUploadRequest;
27use ruma::{
28 OwnedDeviceId, OwnedServerName, OwnedTransactionId, OwnedUserId, ServerName, TransactionId,
29 UserId, api::client::keys::get_keys::v3::Response as KeysQueryResponse, serde::Raw,
30};
31use tokio::sync::Mutex;
32use tracing::{Level, debug, enabled, info, instrument, trace, warn};
33
34#[cfg(feature = "experimental-x509-identity-verification")]
35use crate::types::requests::OutgoingRequest;
36use crate::{
37 CryptoStoreError, LocalTrust, OwnUserIdentity, SignatureError, UserIdentity,
38 error::OlmResult,
39 identities::{DeviceData, OtherUserIdentityData, OwnUserIdentityData, UserIdentityData},
40 olm::{
41 InboundGroupSession, PrivateCrossSigningIdentity, SenderDataFinder, SenderDataType,
42 sender_data_finder::SessionDeviceCheckError,
43 },
44 store::{
45 KeyQueryManager, Result as StoreResult, Store,
46 caches::{SequenceNumber, StoreCache, StoreCacheGuard},
47 types::{Changes, DeviceChanges, IdentityChanges, UserKeyQueryResult},
48 },
49 types::{
50 CrossSigningKey, DeviceKeys, MasterPubkey, SelfSigningPubkey, UserSigningPubkey,
51 requests::KeysQueryRequest,
52 },
53};
54
55enum DeviceChange {
56 New(DeviceData),
57 Updated(DeviceData),
58 None,
59}
60
61enum IdentityUpdateResult {
66 Updated(UserIdentityData),
67 Unchanged(UserIdentityData),
68}
69
70#[cfg(feature = "experimental-x509-identity-verification")]
73#[derive(Debug)]
74enum X509SignatureUploadRequest {
75 Unknown,
77 None,
79 Some(OutgoingRequest),
81}
82
83#[cfg(feature = "experimental-x509-identity-verification")]
84impl X509SignatureUploadRequest {
85 fn is_unknown(&self) -> bool {
86 matches!(self, Self::Unknown)
87 }
88}
89
90#[cfg(feature = "experimental-x509-identity-verification")]
91impl From<Option<SignatureUploadRequest>> for X509SignatureUploadRequest {
92 fn from(request: Option<SignatureUploadRequest>) -> Self {
93 match request {
94 None => Self::None,
95 Some(request) => Self::Some(request.into()),
96 }
97 }
98}
99
100#[derive(Debug, Clone)]
101pub(crate) struct IdentityManager {
102 failures: FailuresCache<OwnedServerName>,
107 store: Store,
108
109 pub(crate) key_query_manager: Arc<KeyQueryManager>,
110
111 keys_query_request_details: Arc<Mutex<Option<KeysQueryRequestDetails>>>,
113
114 #[cfg(feature = "experimental-x509-identity-verification")]
120 x509_signature_upload_request: Arc<Mutex<X509SignatureUploadRequest>>,
121}
122
123#[derive(Debug, Clone, Default)]
125struct KeysQueryRequestDetails {
126 sequence_number: SequenceNumber,
129
130 request_ids: HashSet<OwnedTransactionId>,
134}
135
136struct KeySetInfo {
138 user_id: OwnedUserId,
139 master_key: MasterPubkey,
140 self_signing: SelfSigningPubkey,
141}
142
143impl IdentityManager {
144 const MAX_KEY_QUERY_USERS: usize = 250;
145
146 pub fn new(store: Store) -> Self {
147 let keys_query_request_details = Mutex::new(None);
148
149 IdentityManager {
150 store,
151 key_query_manager: Default::default(),
152 failures: Default::default(),
153 keys_query_request_details: keys_query_request_details.into(),
154 #[cfg(feature = "experimental-x509-identity-verification")]
155 x509_signature_upload_request: Arc::new(Mutex::new(
156 X509SignatureUploadRequest::Unknown,
157 )),
158 }
159 }
160
161 fn user_id(&self) -> &UserId {
162 &self.store.static_account().user_id
163 }
164
165 pub async fn receive_keys_query_response(
177 &self,
178 request_id: &TransactionId,
179 response: &KeysQueryResponse,
180 ) -> OlmResult<(DeviceChanges, IdentityChanges)> {
181 debug!(
182 ?request_id,
183 users = ?response.device_keys.keys().collect::<BTreeSet<_>>(),
184 failures = ?response.failures,
185 "Handling a `/keys/query` response"
186 );
187
188 let failed_servers = response
192 .failures
193 .keys()
194 .filter_map(|k| ServerName::parse(k).ok())
195 .filter(|s| s != self.user_id().server_name());
196 let successful_servers = response.device_keys.keys().map(|u| u.server_name());
197
198 self.failures.extend(failed_servers);
203 self.failures.remove(successful_servers);
204
205 let devices = self.handle_devices_from_key_query(response.device_keys.clone()).await?;
206 let (identities, cross_signing_identity) = self.handle_cross_signing_keys(response).await?;
207
208 let changes = Changes {
209 identities: identities.clone(),
210 devices: devices.clone(),
211 private_identity: cross_signing_identity,
212 ..Default::default()
213 };
214
215 self.store.save_changes(changes).await?;
216
217 self.update_sender_data_from_device_changes(&devices).await?;
234
235 let sequence_number = {
239 let mut request_details = self.keys_query_request_details.lock().await;
240
241 request_details.as_mut().and_then(|details| {
242 if details.request_ids.remove(request_id) {
243 Some(details.sequence_number)
244 } else {
245 None
246 }
247 })
248 };
249
250 if let Some(sequence_number) = sequence_number {
251 let cache = self.store.cache().await?;
252 self.key_query_manager
253 .synced(&cache)
254 .await?
255 .mark_tracked_users_as_up_to_date(
256 response.device_keys.keys().map(Deref::deref),
257 sequence_number,
258 )
259 .await?;
260 }
261
262 if enabled!(Level::DEBUG) {
263 debug_log_keys_query_response(&devices, &identities, request_id);
264 }
265
266 Ok((devices, identities))
267 }
268
269 async fn update_or_create_device(
270 store: Store,
271 device_keys: DeviceKeys,
272 ) -> StoreResult<DeviceChange> {
273 let old_device =
274 store.get_device_data(&device_keys.user_id, &device_keys.device_id).await?;
275
276 if let Some(mut device) = old_device {
277 match device.update_device(&device_keys) {
278 Err(e) => {
279 warn!(
280 user_id = ?device.user_id(),
281 device_id = ?device.device_id(),
282 error = ?e,
283 "Rejecting device update",
284 );
285 Ok(DeviceChange::None)
286 }
287 Ok(true) => Ok(DeviceChange::Updated(device)),
288 Ok(false) => Ok(DeviceChange::None),
289 }
290 } else {
291 match DeviceData::try_from(&device_keys) {
292 Ok(d) => {
293 if d.user_id() == store.user_id() && d.device_id() == store.device_id() {
297 let local_device_keys = store.static_account().unsigned_device_keys();
298
299 if d.keys() == &local_device_keys.keys {
300 d.set_trust_state(LocalTrust::Verified);
301
302 trace!(
303 user_id = ?d.user_id(),
304 device_id = ?d.device_id(),
305 keys = ?d.keys(),
306 "Adding our own device to the device store, \
307 marking it as locally verified",
308 );
309
310 Ok(DeviceChange::New(d))
311 } else {
312 Ok(DeviceChange::None)
313 }
314 } else {
315 trace!(
316 user_id = ?d.user_id(),
317 device_id = ?d.device_id(),
318 keys = ?d.keys(),
319 "Adding a new device to the device store",
320 );
321
322 Ok(DeviceChange::New(d))
323 }
324 }
325 Err(e) => {
326 warn!(
327 user_id = ?device_keys.user_id,
328 device_id = ?device_keys.device_id,
329 error = ?e,
330 "Rejecting a previously unseen device",
331 );
332
333 Ok(DeviceChange::None)
334 }
335 }
336 }
337 }
338
339 async fn update_user_devices(
340 store: Store,
341 user_id: OwnedUserId,
342 device_map: BTreeMap<OwnedDeviceId, Raw<ruma::encryption::DeviceKeys>>,
343 ) -> StoreResult<DeviceChanges> {
344 let own_device_id = store.static_account().device_id().to_owned();
345
346 let mut changes = DeviceChanges::default();
347
348 let current_devices: HashSet<OwnedDeviceId> = device_map.keys().cloned().collect();
349
350 let tasks = device_map.into_iter().filter_map(|(device_id, device_keys)| match device_keys
351 .deserialize_as::<DeviceKeys>(
352 ) {
353 Ok(device_keys) => {
354 if user_id != device_keys.user_id || device_id != device_keys.device_id {
355 warn!(
356 ?user_id,
357 ?device_id,
358 device_key_user = ?device_keys.user_id,
359 device_key_device_id = ?device_keys.device_id,
360 "Mismatch in the device keys payload",
361 );
362 None
363 } else {
364 Some(spawn(Self::update_or_create_device(store.clone(), device_keys)))
365 }
366 }
367 Err(e) => {
368 warn!(
369 ?user_id, ?device_id, error = ?e,
370 "Device keys failed to deserialize",
371 );
372 None
373 }
374 });
375
376 let results = join_all(tasks).await;
377
378 for device in results {
379 let device = device.expect("Creating or updating a device panicked")?;
380
381 match device {
382 DeviceChange::New(d) => changes.new.push(d),
383 DeviceChange::Updated(d) => changes.changed.push(d),
384 DeviceChange::None => (),
385 }
386 }
387
388 let current_devices: HashSet<&OwnedDeviceId> = current_devices.iter().collect();
389 let stored_devices = store.get_device_data_for_user(&user_id).await?;
390 let stored_devices_set: HashSet<&OwnedDeviceId> = stored_devices.keys().collect();
391 let deleted_devices_set = stored_devices_set.difference(¤t_devices);
392
393 let own_user_id = store.static_account().user_id();
394 for device_id in deleted_devices_set {
395 if user_id == *own_user_id && *device_id == &own_device_id {
396 let identity_keys = store.static_account().identity_keys();
397
398 warn!(
399 user_id = ?own_user_id,
400 device_id = ?own_device_id,
401 curve25519_key = ?identity_keys.curve25519,
402 ed25519_key = ?identity_keys.ed25519,
403 "Our own device might have been deleted"
404 );
405 } else if let Some(device) = stored_devices.get(*device_id) {
406 device.mark_as_deleted();
407 changes.deleted.push(device.clone());
408 }
409 }
410
411 Ok(changes)
412 }
413
414 async fn handle_devices_from_key_query(
424 &self,
425 device_keys_map: BTreeMap<
426 OwnedUserId,
427 BTreeMap<OwnedDeviceId, Raw<ruma::encryption::DeviceKeys>>,
428 >,
429 ) -> StoreResult<DeviceChanges> {
430 let mut changes = DeviceChanges::default();
431
432 let tasks = device_keys_map.into_iter().map(|(user_id, device_keys_map)| {
433 spawn(Self::update_user_devices(self.store.clone(), user_id, device_keys_map))
434 });
435
436 let results = join_all(tasks).await;
437
438 for result in results {
439 let change_fragment = result.expect("Panic while updating user devices")?;
440
441 changes.extend(change_fragment);
442 }
443
444 Ok(changes)
445 }
446
447 async fn check_private_identity(
465 &self,
466 identity: &OwnUserIdentityData,
467 ) -> Option<PrivateCrossSigningIdentity> {
468 let private_identity = self.store.private_identity();
469 let private_identity = private_identity.lock().await;
470 let result = private_identity.clear_if_differs(identity).await;
471
472 if result.any_differ() {
473 info!(cleared = ?result, "Removed some or all of our private cross signing keys");
474 Some((*private_identity).clone())
475 } else {
476 if private_identity.has_master_key().await && !identity.is_verified() {
483 trace!("Marked our own identity as verified");
484 identity.mark_as_verified()
485 }
486 #[cfg(feature = "experimental-x509-identity-verification")]
487 {
488 *self.x509_signature_upload_request.lock().await =
490 identity.refresh_x509_signature(&self.store).await.unwrap_or(None).into();
491 }
492
493 None
494 }
495 }
496
497 async fn handle_changed_identity(
528 &self,
529 response: &KeysQueryResponse,
530 maybe_verified_own_identity: Option<&OwnUserIdentity>,
531 master_key: MasterPubkey,
532 self_signing: SelfSigningPubkey,
533 i: UserIdentityData,
534 changed_private_identity: &mut Option<PrivateCrossSigningIdentity>,
535 ) -> Result<IdentityUpdateResult, SignatureError> {
536 match i {
537 UserIdentityData::Own(mut identity) => {
538 let user_signing = self.get_user_signing_key_from_response(response)?;
539 let has_changed = identity.update(master_key, self_signing, user_signing)?;
540 *changed_private_identity = self.check_private_identity(&identity).await;
541 if has_changed {
542 Ok(IdentityUpdateResult::Updated(identity.into()))
543 } else {
544 Ok(IdentityUpdateResult::Unchanged(identity.into()))
545 }
546 }
547 UserIdentityData::Other(mut identity) => {
548 let has_changed = identity.update(
549 master_key,
550 self_signing,
551 maybe_verified_own_identity.map(|o| o.user_signing_key()),
552 )?;
553
554 if has_changed {
555 Ok(IdentityUpdateResult::Updated(identity.into()))
556 } else {
557 Ok(IdentityUpdateResult::Unchanged(identity.into()))
558 }
559 }
560 }
561 }
562
563 async fn handle_new_identity(
592 &self,
593 response: &KeysQueryResponse,
594 maybe_verified_own_identity: Option<&OwnUserIdentity>,
595 master_key: MasterPubkey,
596 self_signing: SelfSigningPubkey,
597 changed_private_identity: &mut Option<PrivateCrossSigningIdentity>,
598 ) -> Result<UserIdentityData, SignatureError> {
599 if master_key.user_id() == self.user_id() {
600 let user_signing = self.get_user_signing_key_from_response(response)?;
602 let identity = OwnUserIdentityData::new(master_key, self_signing, user_signing)?;
603 *changed_private_identity = self.check_private_identity(&identity).await;
604 Ok(identity.into())
605 } else {
606 let identity = OtherUserIdentityData::new(master_key, self_signing)?;
608 let is_verified = maybe_verified_own_identity
609 .is_some_and(|own_user_identity| own_user_identity.is_identity_signed(&identity));
610 if is_verified {
611 identity.mark_as_previously_verified();
612 }
613
614 Ok(identity.into())
615 }
616 }
617
618 fn get_minimal_set_of_keys(
639 master_key: &Raw<CrossSigningKey>,
640 response: &KeysQueryResponse,
641 ) -> Option<(MasterPubkey, SelfSigningPubkey)> {
642 match master_key.deserialize_as_unchecked::<MasterPubkey>() {
643 Ok(master_key) => {
644 if let Some(self_signing) = response
645 .self_signing_keys
646 .get(master_key.user_id())
647 .and_then(|k| k.deserialize_as_unchecked::<SelfSigningPubkey>().ok())
648 {
649 Some((master_key, self_signing))
650 } else {
651 warn!(
652 "A user identity didn't contain a self signing pubkey or the key was invalid"
653 );
654 None
655 }
656 }
657 Err(e) => {
658 warn!(
659 error = ?e,
660 "Couldn't update or create new user identity"
661 );
662 None
663 }
664 }
665 }
666
667 fn get_user_signing_key_from_response(
678 &self,
679 response: &KeysQueryResponse,
680 ) -> Result<UserSigningPubkey, SignatureError> {
681 let Some(user_signing) = response
682 .user_signing_keys
683 .get(self.user_id())
684 .and_then(|k| k.deserialize_as_unchecked::<UserSigningPubkey>().ok())
685 else {
686 warn!(
687 "User identity for our own user didn't contain a user signing pubkey or the key \
688 isn't valid",
689 );
690 return Err(SignatureError::MissingSigningKey);
691 };
692
693 if user_signing.user_id() != self.user_id() {
694 warn!(
695 expected = ?self.user_id(),
696 got = ?user_signing.user_id(),
697 "User ID mismatch in our user-signing key",
698 );
699 return Err(SignatureError::UserIdMismatch);
700 }
701
702 Ok(user_signing)
703 }
704
705 #[instrument(skip_all, fields(user_id))]
723 async fn update_or_create_identity(
724 &self,
725 response: &KeysQueryResponse,
726 changes: &mut IdentityChanges,
727 changed_private_identity: &mut Option<PrivateCrossSigningIdentity>,
728 maybe_verified_own_identity: Option<&OwnUserIdentity>,
729 key_set_info: KeySetInfo,
730 ) -> StoreResult<()> {
731 let KeySetInfo { user_id, master_key, self_signing } = key_set_info;
732 if master_key.user_id() != user_id || self_signing.user_id() != user_id {
733 warn!(?user_id, "User ID mismatch in one of the cross signing keys");
734 } else if let Some(i) = self.store.get_user_identity(&user_id).await? {
735 match self
737 .handle_changed_identity(
738 response,
739 maybe_verified_own_identity,
740 master_key,
741 self_signing,
742 i,
743 changed_private_identity,
744 )
745 .await
746 {
747 Ok(IdentityUpdateResult::Updated(identity)) => {
748 trace!(?identity, "Updated a user identity");
749 changes.changed.push(identity);
750 }
751 Ok(IdentityUpdateResult::Unchanged(identity)) => {
752 trace!(?identity, "Received an unchanged user identity");
753 changes.unchanged.push(identity);
754 }
755 Err(e) => {
756 warn!(error = ?e, "Couldn't update an existing user identity");
757 }
758 }
759 } else {
760 match self
762 .handle_new_identity(
763 response,
764 maybe_verified_own_identity,
765 master_key,
766 self_signing,
767 changed_private_identity,
768 )
769 .await
770 {
771 Ok(identity) => {
772 trace!(?identity, "Created new user identity");
773 changes.new.push(identity);
774 }
775 Err(e) => {
776 warn!(error = ?e, "Couldn't create new user identity");
777 }
778 }
779 }
780
781 Ok(())
782 }
783
784 async fn handle_cross_signing_keys(
800 &self,
801 response: &KeysQueryResponse,
802 ) -> StoreResult<(IdentityChanges, Option<PrivateCrossSigningIdentity>)> {
803 let mut changes = IdentityChanges::default();
804 let mut changed_identity = None;
805
806 let maybe_own_verified_identity = self
809 .store
810 .get_identity(self.user_id())
811 .await?
812 .and_then(UserIdentity::own)
813 .filter(|own| own.is_verified());
814
815 for (user_id, master_key) in &response.master_keys {
816 let Some((master_key, self_signing)) =
819 Self::get_minimal_set_of_keys(master_key.cast_ref(), response)
820 else {
821 continue;
822 };
823
824 let key_set_info = KeySetInfo { user_id: user_id.clone(), master_key, self_signing };
825
826 self.update_or_create_identity(
827 response,
828 &mut changes,
829 &mut changed_identity,
830 maybe_own_verified_identity.as_ref(),
831 key_set_info,
832 )
833 .await?;
834 }
835
836 Ok((changes, changed_identity))
837 }
838
839 pub(crate) fn build_key_query_for_users<'a>(
857 &self,
858 users: impl IntoIterator<Item = &'a UserId>,
859 ) -> (OwnedTransactionId, KeysQueryRequest) {
860 (TransactionId::new(), KeysQueryRequest::new(users.into_iter().map(|u| u.to_owned())))
869 }
870
871 #[cfg(feature = "experimental-x509-identity-verification")]
878 pub(crate) async fn get_x509_signature_upload_request(&self) -> Option<OutgoingRequest> {
879 let mut upload_request = self.x509_signature_upload_request.lock().await;
880 if upload_request.is_unknown() {
881 if let Some(identity) = self
884 .store
885 .get_user_identity(self.user_id())
886 .await
887 .unwrap_or(None)
888 .and_then(UserIdentityData::into_own)
889 {
890 *upload_request =
891 identity.refresh_x509_signature(&self.store).await.unwrap_or(None).into();
892 }
893 }
894 match &*upload_request {
895 X509SignatureUploadRequest::Some(request) => Some(request.clone()),
896 _ => None,
897 }
898 }
899
900 #[cfg(feature = "experimental-x509-identity-verification")]
902 pub(crate) async fn mark_x509_signature_request_as_sent(&self, request_id: &TransactionId) {
903 let mut x509_signature_upload_request = self.x509_signature_upload_request.lock().await;
904
905 if let X509SignatureUploadRequest::Some(request) = &*x509_signature_upload_request
906 && request.request_id() == request_id
907 {
908 *x509_signature_upload_request = X509SignatureUploadRequest::None;
909 }
910 }
911
912 pub async fn users_for_key_query(
923 &self,
924 ) -> StoreResult<BTreeMap<OwnedTransactionId, KeysQueryRequest>> {
925 *self.keys_query_request_details.lock().await = None;
927
928 let (users, sequence_number) = {
934 let cache = self.store.cache().await?;
935 let key_query_manager = self.key_query_manager.synced(&cache).await?;
936
937 let (users, sequence_number) = key_query_manager.users_for_key_query().await;
938
939 if users.is_empty() && !key_query_manager.tracked_users().contains(self.user_id()) {
940 key_query_manager.mark_user_as_changed(self.user_id()).await?;
941 key_query_manager.users_for_key_query().await
942 } else {
943 (users, sequence_number)
944 }
945 };
946
947 if users.is_empty() {
948 Ok(BTreeMap::new())
949 } else {
950 let users = users.into_iter().filter(|u| !self.failures.contains(u.server_name()));
955
956 let requests: BTreeMap<_, _> = users
964 .chunks(Self::MAX_KEY_QUERY_USERS)
965 .into_iter()
966 .map(|user_chunk| {
967 let request_id = TransactionId::new();
968 let request = KeysQueryRequest::new(user_chunk);
969
970 debug!(?request_id, users = ?request.device_keys.keys(), "Created a /keys/query request");
971
972 (request_id, request)
973 })
974 .collect();
975
976 let request_ids = requests.keys().cloned().collect();
980 let request_details = KeysQueryRequestDetails { sequence_number, request_ids };
981
982 *self.keys_query_request_details.lock().await = Some(request_details);
983
984 Ok(requests)
985 }
986 }
987
988 pub async fn receive_device_changes(
996 &self,
997 cache: &StoreCache,
998 users: impl Iterator<Item = &UserId>,
999 ) -> StoreResult<()> {
1000 self.key_query_manager.synced(cache).await?.mark_tracked_users_as_changed(users).await
1001 }
1002
1003 pub async fn update_tracked_users(
1005 &self,
1006 users: impl IntoIterator<Item = &UserId>,
1007 ) -> StoreResult<()> {
1008 let cache = self.store.cache().await?;
1009 self.key_query_manager.synced(&cache).await?.update_tracked_users(users.into_iter()).await
1010 }
1011
1012 pub async fn get_user_devices_for_encryption(
1020 &self,
1021 users: impl Iterator<Item = &UserId>,
1022 ) -> StoreResult<HashMap<OwnedUserId, HashMap<OwnedDeviceId, DeviceData>>> {
1023 const KEYS_QUERY_WAIT_TIME: Duration = Duration::from_secs(5);
1025
1026 let mut devices_by_user = HashMap::new();
1027 let mut users_with_no_devices_on_failed_servers = Vec::new();
1028 let mut users_with_no_devices_on_unfailed_servers = Vec::new();
1029
1030 for user_id in users {
1031 let devices = self.store.get_device_data_for_user_filtered(user_id).await?;
1033
1034 if !devices.is_empty() {
1042 devices_by_user.insert(user_id.to_owned(), devices);
1052 continue;
1053 }
1054
1055 if self.failures.contains(user_id.server_name()) {
1068 users_with_no_devices_on_failed_servers.push(user_id);
1069 continue;
1070 }
1071
1072 users_with_no_devices_on_unfailed_servers.push(user_id);
1073 }
1074
1075 if !users_with_no_devices_on_failed_servers.is_empty() {
1076 info!(
1077 ?users_with_no_devices_on_failed_servers,
1078 "Not waiting for `/keys/query` for users whose server has previously failed"
1079 );
1080 }
1081
1082 if !users_with_no_devices_on_unfailed_servers.is_empty() {
1083 let results = join_all(
1091 users_with_no_devices_on_unfailed_servers
1092 .into_iter()
1093 .map(|user_id| self.get_updated_keys_for_user(KEYS_QUERY_WAIT_TIME, user_id)),
1094 )
1095 .await;
1096
1097 let mut updated_users = Vec::new();
1099 for result in results {
1100 if let Some((user_id, updated_devices)) = result? {
1101 devices_by_user.insert(user_id.to_owned(), updated_devices);
1102 updated_users.push(user_id);
1103 }
1104 }
1105
1106 if !updated_users.is_empty() {
1107 info!(
1108 ?updated_users,
1109 "Waited for `/keys/query` to complete for users who have no devices"
1110 );
1111 }
1112 }
1113
1114 Ok(devices_by_user)
1115 }
1116
1117 #[allow(clippy::type_complexity)]
1123 #[instrument(skip(self))]
1124 async fn get_updated_keys_for_user<'a>(
1125 &self,
1126 timeout_duration: Duration,
1127 user_id: &'a UserId,
1128 ) -> Result<Option<(&'a UserId, HashMap<OwnedDeviceId, DeviceData>)>, CryptoStoreError> {
1129 let cache = self.store.cache().await?;
1130 match self
1131 .key_query_manager
1132 .wait_if_user_key_query_pending(cache, timeout_duration, user_id)
1133 .await?
1134 {
1135 UserKeyQueryResult::WasPending => {
1136 Ok(Some((user_id, self.store.get_device_data_for_user_filtered(user_id).await?)))
1137 }
1138 _ => Ok(None),
1139 }
1140 }
1141
1142 async fn update_sender_data_from_device_changes(
1146 &self,
1147 device_changes: &DeviceChanges,
1148 ) -> Result<(), CryptoStoreError> {
1149 for device in device_changes.new.iter().chain(device_changes.changed.iter()) {
1150 self.update_sender_data_for_sessions_for_device(device, SenderDataType::UnknownDevice)
1159 .await?;
1160
1161 let device_owner_identity = self.store.get_user_identity(device.user_id()).await?;
1171 if device_owner_identity.is_some_and(|id| device.is_cross_signed_by_owner(&id)) {
1172 self.update_sender_data_for_sessions_for_device(device, SenderDataType::DeviceInfo)
1173 .await?;
1174 }
1175 }
1176
1177 Ok(())
1178 }
1179
1180 #[instrument(skip(self))]
1183 async fn update_sender_data_for_sessions_for_device(
1184 &self,
1185 device: &DeviceData,
1186 sender_data_type: SenderDataType,
1187 ) -> Result<(), CryptoStoreError> {
1188 const IGS_BATCH_SIZE: usize = 50;
1189
1190 let Some(curve_key) = device.curve25519_key() else { return Ok(()) };
1191
1192 let mut last_session_id: Option<String> = None;
1193 loop {
1194 let mut sessions = self
1195 .store
1196 .get_inbound_group_sessions_for_device_batch(
1197 curve_key,
1198 sender_data_type,
1199 last_session_id,
1200 IGS_BATCH_SIZE,
1201 )
1202 .await?;
1203
1204 if sessions.is_empty() {
1205 return Ok(());
1207 }
1208
1209 last_session_id = None;
1210 for session in &mut sessions {
1211 last_session_id = Some(session.session_id().to_owned());
1212 self.update_sender_data_for_session(session, device).await?;
1213 }
1214 self.store.save_inbound_group_sessions(&sessions).await?;
1215 }
1216 }
1217
1218 #[instrument(skip(self, device, session), fields(session_id = session.session_id()))]
1221 async fn update_sender_data_for_session(
1222 &self,
1223 session: &mut InboundGroupSession,
1224 device: &DeviceData,
1225 ) -> Result<(), CryptoStoreError> {
1226 match SenderDataFinder::find_using_device_data(&self.store, device.clone(), session).await {
1227 Ok(sender_data) => {
1228 debug!("Updating existing InboundGroupSession with new SenderData {sender_data:?}");
1229 session.sender_data = sender_data;
1230 }
1231 Err(SessionDeviceCheckError::CryptoStoreError(e)) => {
1232 return Err(e);
1233 }
1234 Err(SessionDeviceCheckError::MismatchedIdentityKeys(e)) => {
1235 warn!(
1236 ?session,
1237 ?device,
1238 "cannot update existing InboundGroupSession due to ownership error: {e}",
1239 );
1240 }
1241 }
1242
1243 Ok(())
1244 }
1245
1246 pub(crate) async fn mark_all_tracked_users_as_dirty(
1251 &self,
1252 store_cache: StoreCacheGuard,
1253 ) -> StoreResult<()> {
1254 let store_wrapper = store_cache.store_wrapper();
1255 let tracked_users = store_wrapper.load_tracked_users().await?;
1256
1257 self.key_query_manager
1258 .synced(&store_cache)
1259 .await?
1260 .mark_tracked_users_as_changed(
1261 tracked_users.iter().map(|tracked_user| tracked_user.user_id.as_ref()),
1262 )
1263 .await?;
1264
1265 Ok(())
1266 }
1267}
1268
1269fn debug_log_keys_query_response(
1272 devices: &DeviceChanges,
1273 identities: &IdentityChanges,
1274 request_id: &TransactionId,
1275) {
1276 #[allow(unknown_lints, clippy::unwrap_or_default)] let changed_devices = devices.changed.iter().fold(BTreeMap::new(), |mut acc, d| {
1278 acc.entry(d.user_id()).or_insert_with(BTreeSet::new).insert(d.device_id());
1279 acc
1280 });
1281
1282 #[allow(unknown_lints, clippy::unwrap_or_default)] let new_devices = devices.new.iter().fold(BTreeMap::new(), |mut acc, d| {
1284 acc.entry(d.user_id()).or_insert_with(BTreeSet::new).insert(d.device_id());
1285 acc
1286 });
1287
1288 #[allow(unknown_lints, clippy::unwrap_or_default)] let deleted_devices = devices.deleted.iter().fold(BTreeMap::new(), |mut acc, d| {
1290 acc.entry(d.user_id()).or_insert_with(BTreeSet::new).insert(d.device_id());
1291 acc
1292 });
1293
1294 let new_identities = identities.new.iter().map(|i| i.user_id()).collect::<BTreeSet<_>>();
1295 let changed_identities =
1296 identities.changed.iter().map(|i| i.user_id()).collect::<BTreeSet<_>>();
1297
1298 debug!(
1299 ?request_id,
1300 ?new_devices,
1301 ?changed_devices,
1302 ?deleted_devices,
1303 ?new_identities,
1304 ?changed_identities,
1305 "Finished handling of the `/keys/query` response"
1306 );
1307}
1308
1309#[cfg(any(test, feature = "testing"))]
1310#[allow(dead_code)]
1311pub(crate) mod testing {
1312 use std::sync::Arc;
1313
1314 use matrix_sdk_test::ruma_response_from_json;
1315 use ruma::{
1316 DeviceId, UserId, api::client::keys::get_keys::v3::Response as KeyQueryResponse, device_id,
1317 user_id,
1318 };
1319 use serde_json::json;
1320 use tokio::sync::Mutex;
1321
1322 use crate::{
1323 identities::IdentityManager,
1324 olm::{Account, PrivateCrossSigningIdentity},
1325 store::{CryptoStoreWrapper, MemoryStore, Store, types::PendingChanges},
1326 types::{DeviceKeys, requests::UploadSigningKeysRequest},
1327 verification::VerificationMachine,
1328 };
1329
1330 pub fn user_id() -> &'static UserId {
1331 user_id!("@example:localhost")
1332 }
1333
1334 pub fn other_user_id() -> &'static UserId {
1335 user_id!("@example2:localhost")
1336 }
1337
1338 pub fn device_id() -> &'static DeviceId {
1339 device_id!("WSKKLTJZCL")
1340 }
1341
1342 pub(crate) async fn manager_test_helper(
1343 user_id: &UserId,
1344 device_id: &DeviceId,
1345 ) -> IdentityManager {
1346 let identity = PrivateCrossSigningIdentity::new(user_id.into());
1347 let identity = Arc::new(Mutex::new(identity));
1348 let user_id = user_id.to_owned();
1349 let account = Account::with_device_id(&user_id, device_id);
1350 let static_account = account.static_data().clone();
1351 let store = Arc::new(CryptoStoreWrapper::new(&user_id, device_id, MemoryStore::new()));
1352 let verification =
1353 VerificationMachine::new(static_account.clone(), identity.clone(), store.clone());
1354 let store = Store::new(static_account, identity, store, verification);
1355 store.save_pending_changes(PendingChanges { account: Some(account) }).await.unwrap();
1356 IdentityManager::new(store)
1357 }
1358
1359 pub fn other_key_query() -> KeyQueryResponse {
1360 let data = &json!({
1361 "device_keys": {
1362 "@example2:localhost": {
1363 "SKISMLNIMH": {
1364 "algorithms": ["m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"],
1365 "device_id": "SKISMLNIMH",
1366 "keys": {
1367 "curve25519:SKISMLNIMH": "qO9xFazIcW8dE0oqHGMojGgJwbBpMOhGnIfJy2pzvmI",
1368 "ed25519:SKISMLNIMH": "y3wV3AoyIGREqrJJVH8DkQtlwHBUxoZ9ApP76kFgXQ8"
1369 },
1370 "signatures": {
1371 "@example2:localhost": {
1372 "ed25519:SKISMLNIMH": "YwbT35rbjKoYFZVU1tQP8MsL06+znVNhNzUMPt6jTEYRBFoC4GDq9hQEJBiFSq37r1jvLMteggVAWw37fs1yBA",
1373 "ed25519:ZtFrSkJ1qB8Jph/ql9Eo/lKpIYCzwvKAKXfkaS4XZNc": "PWuuTE/aTkp1EJQkPHhRx2BxbF+wjMIDFxDRp7JAerlMkDsNFUTfRRusl6vqROPU36cl+yY8oeJTZGFkU6+pBQ"
1374 }
1375 },
1376 "user_id": "@example2:localhost",
1377 "unsigned": {
1378 "device_display_name": "Riot Desktop (Linux)"
1379 }
1380 }
1381 }
1382 },
1383 "failures": {},
1384 "master_keys": {
1385 "@example2:localhost": {
1386 "user_id": "@example2:localhost",
1387 "usage": ["master"],
1388 "keys": {
1389 "ed25519:kC/HmRYw4HNqUp/i4BkwYENrf+hd9tvdB7A1YOf5+Do": "kC/HmRYw4HNqUp/i4BkwYENrf+hd9tvdB7A1YOf5+Do"
1390 },
1391 "signatures": {
1392 "@example2:localhost": {
1393 "ed25519:SKISMLNIMH": "KdUZqzt8VScGNtufuQ8lOf25byYLWIhmUYpPENdmM8nsldexD7vj+Sxoo7PknnTX/BL9h2N7uBq0JuykjunCAw"
1394 }
1395 }
1396 }
1397 },
1398 "self_signing_keys": {
1399 "@example2:localhost": {
1400 "user_id": "@example2:localhost",
1401 "usage": ["self_signing"],
1402 "keys": {
1403 "ed25519:ZtFrSkJ1qB8Jph/ql9Eo/lKpIYCzwvKAKXfkaS4XZNc": "ZtFrSkJ1qB8Jph/ql9Eo/lKpIYCzwvKAKXfkaS4XZNc"
1404 },
1405 "signatures": {
1406 "@example2:localhost": {
1407 "ed25519:kC/HmRYw4HNqUp/i4BkwYENrf+hd9tvdB7A1YOf5+Do": "W/O8BnmiUETPpH02mwYaBgvvgF/atXnusmpSTJZeUSH/vHg66xiZOhveQDG4cwaW8iMa+t9N4h1DWnRoHB4mCQ"
1408 }
1409 }
1410 }
1411 },
1412 "user_signing_keys": {}
1413 });
1414 ruma_response_from_json(data)
1415 }
1416
1417 pub fn other_key_query_cross_signed() -> KeyQueryResponse {
1421 let data = json!({
1422 "device_keys": {
1423 "@example2:localhost": {
1424 "SKISMLNIMH": {
1425 "algorithms": ["m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"],
1426 "device_id": "SKISMLNIMH",
1427 "keys": {
1428 "curve25519:SKISMLNIMH": "qO9xFazIcW8dE0oqHGMojGgJwbBpMOhGnIfJy2pzvmI",
1429 "ed25519:SKISMLNIMH": "y3wV3AoyIGREqrJJVH8DkQtlwHBUxoZ9ApP76kFgXQ8"
1430 },
1431 "signatures": {
1432 "@example2:localhost": {
1433 "ed25519:SKISMLNIMH": "YwbT35rbjKoYFZVU1tQP8MsL06+znVNhNzUMPt6jTEYRBFoC4GDq9hQEJBiFSq37r1jvLMteggVAWw37fs1yBA",
1434 "ed25519:ZtFrSkJ1qB8Jph/ql9Eo/lKpIYCzwvKAKXfkaS4XZNc": "PWuuTE/aTkp1EJQkPHhRx2BxbF+wjMIDFxDRp7JAerlMkDsNFUTfRRusl6vqROPU36cl+yY8oeJTZGFkU6+pBQ"
1435 }
1436 },
1437 "user_id": "@example2:localhost",
1438 "unsigned": {
1439 "device_display_name": "Riot Desktop (Linux)"
1440 }
1441 }
1442 }
1443 },
1444 "failures": {},
1445 "master_keys": {
1446 "@example2:localhost": {
1447 "user_id": "@example2:localhost",
1448 "usage": ["master"],
1449 "keys": {
1450 "ed25519:kC/HmRYw4HNqUp/i4BkwYENrf+hd9tvdB7A1YOf5+Do": "kC/HmRYw4HNqUp/i4BkwYENrf+hd9tvdB7A1YOf5+Do"
1451 },
1452 "signatures": {
1453 "@example2:localhost": {
1454 "ed25519:SKISMLNIMH": "KdUZqzt8VScGNtufuQ8lOf25byYLWIhmUYpPENdmM8nsldexD7vj+Sxoo7PknnTX/BL9h2N7uBq0JuykjunCAw"
1455 },
1456 "@alice:localhost": {
1458 "ed25519:DU9z4gBFKFKCk7a13sW9wjT0Iyg7Hqv5f0BPM7DEhPo": "NotAValidSignature+GNtufuQ8lOf25byYLWIhmUYpPENdmM8nsldexD7vj+Sxoo7PknnTX/BL9h2N7uBq0JuykjunCAw"
1459 }
1460 }
1461 }
1462 },
1463 "self_signing_keys": {
1464 "@example2:localhost": {
1465 "user_id": "@example2:localhost",
1466 "usage": ["self_signing"],
1467 "keys": {
1468 "ed25519:ZtFrSkJ1qB8Jph/ql9Eo/lKpIYCzwvKAKXfkaS4XZNc": "ZtFrSkJ1qB8Jph/ql9Eo/lKpIYCzwvKAKXfkaS4XZNc"
1469 },
1470 "signatures": {
1471 "@example2:localhost": {
1472 "ed25519:kC/HmRYw4HNqUp/i4BkwYENrf+hd9tvdB7A1YOf5+Do": "W/O8BnmiUETPpH02mwYaBgvvgF/atXnusmpSTJZeUSH/vHg66xiZOhveQDG4cwaW8iMa+t9N4h1DWnRoHB4mCQ"
1473 }
1474 }
1475 }
1476 },
1477 "user_signing_keys": {}
1478 });
1479 ruma_response_from_json(&data)
1480 }
1481
1482 pub fn own_key_query_with_user_id(user_id: &UserId) -> KeyQueryResponse {
1484 let data = json!({
1485 "device_keys": {
1486 user_id: {
1487 "WSKKLTJZCL": {
1488 "algorithms": [
1489 "m.olm.v1.curve25519-aes-sha2",
1490 "m.megolm.v1.aes-sha2"
1491 ],
1492 "device_id": "WSKKLTJZCL",
1493 "keys": {
1494 "curve25519:WSKKLTJZCL": "wnip2tbJBJxrFayC88NNJpm61TeSNgYcqBH4T9yEDhU",
1495 "ed25519:WSKKLTJZCL": "lQ+eshkhgKoo+qp9Qgnj3OX5PBoWMU5M9zbuEevwYqE"
1496 },
1497 "signatures": {
1498 user_id: {
1499 "ed25519:WSKKLTJZCL": "SKpIUnq7QK0xleav0PrIQyKjVm+TgZr7Yi8cKjLeZDtkgyToE2d4/e3Aj79dqOlLB92jFVE4d1cM/Ry04wFwCA",
1500 "ed25519:0C8lCBxrvrv/O7BQfsKnkYogHZX3zAgw3RfJuyiq210": "9UGu1iC5YhFCdELGfB29YaV+QE0t/X5UDSsPf4QcdZyXIwyp9zBbHX2lh9vWudNQ+akZpaq7ZRaaM+4TCnw/Ag"
1501 }
1502 },
1503 "user_id": user_id,
1504 "unsigned": {
1505 "device_display_name": "Cross signing capable"
1506 }
1507 },
1508 "LVWOVGOXME": {
1509 "algorithms": [
1510 "m.olm.v1.curve25519-aes-sha2",
1511 "m.megolm.v1.aes-sha2"
1512 ],
1513 "device_id": "LVWOVGOXME",
1514 "keys": {
1515 "curve25519:LVWOVGOXME": "KMfWKUhnDW1D11hNzATs/Ax1FQRsJxKCWzq0NyGtIiI",
1516 "ed25519:LVWOVGOXME": "k+NC3L7CBD6fBClcHBrKLOkqCyGNSKhWXiH5Q2STRnA"
1517 },
1518 "signatures": {
1519 user_id: {
1520 "ed25519:LVWOVGOXME": "39Ir5Bttpc5+bQwzLj7rkjm5E5/cp/JTbMJ/t0enj6J5w9MXVBFOUqqM2hpaRaRwILMMpwYbJ8IOGjl0Y/MGAw"
1521 }
1522 },
1523 "user_id": user_id,
1524 "unsigned": {
1525 "device_display_name": "Non-cross signing"
1526 }
1527 }
1528 }
1529 },
1530 "failures": {},
1531 "master_keys": {
1532 user_id: {
1533 "user_id": user_id,
1534 "usage": [
1535 "master"
1536 ],
1537 "keys": {
1538 "ed25519:rJ2TAGkEOP6dX41Ksll6cl8K3J48l8s/59zaXyvl2p0": "rJ2TAGkEOP6dX41Ksll6cl8K3J48l8s/59zaXyvl2p0"
1539 },
1540 "signatures": {
1541 user_id: {
1542 "ed25519:WSKKLTJZCL": "ZzJp1wtmRdykXAUEItEjNiFlBrxx8L6/Vaen9am8AuGwlxxJtOkuY4m+4MPLvDPOgavKHLsrRuNLAfCeakMlCQ"
1543 }
1544 }
1545 }
1546 },
1547 "self_signing_keys": {
1548 user_id: {
1549 "user_id": user_id,
1550 "usage": [
1551 "self_signing"
1552 ],
1553 "keys": {
1554 "ed25519:0C8lCBxrvrv/O7BQfsKnkYogHZX3zAgw3RfJuyiq210": "0C8lCBxrvrv/O7BQfsKnkYogHZX3zAgw3RfJuyiq210"
1555 },
1556 "signatures": {
1557 user_id: {
1558 "ed25519:rJ2TAGkEOP6dX41Ksll6cl8K3J48l8s/59zaXyvl2p0": "AC7oDUW4rUhtInwb4lAoBJ0wAuu4a5k+8e34B5+NKsDB8HXRwgVwUWN/MRWc/sJgtSbVlhzqS9THEmQQ1C51Bw"
1559 }
1560 }
1561 }
1562 },
1563 "user_signing_keys": {
1564 user_id: {
1565 "user_id": user_id,
1566 "usage": [
1567 "user_signing"
1568 ],
1569 "keys": {
1570 "ed25519:DU9z4gBFKFKCk7a13sW9wjT0Iyg7Hqv5f0BPM7DEhPo": "DU9z4gBFKFKCk7a13sW9wjT0Iyg7Hqv5f0BPM7DEhPo"
1571 },
1572 "signatures": {
1573 user_id: {
1574 "ed25519:rJ2TAGkEOP6dX41Ksll6cl8K3J48l8s/59zaXyvl2p0": "C4L2sx9frGqj8w41KyynHGqwUbbwBYRZpYCB+6QWnvQFA5Oi/1PJj8w5anwzEsoO0TWmLYmf7FXuAGewanOWDg"
1575 }
1576 }
1577 }
1578 }
1579 });
1580 ruma_response_from_json(&data)
1581 }
1582
1583 pub fn own_key_query() -> KeyQueryResponse {
1584 own_key_query_with_user_id(user_id())
1585 }
1586
1587 pub fn key_query(
1588 identity: UploadSigningKeysRequest,
1589 device_keys: DeviceKeys,
1590 ) -> KeyQueryResponse {
1591 let json = json!({
1592 "device_keys": {
1593 "@example:localhost": {
1594 device_keys.device_id.to_string(): device_keys
1595 }
1596 },
1597 "failures": {},
1598 "master_keys": {
1599 "@example:localhost": identity.master_key
1600 },
1601 "self_signing_keys": {
1602 "@example:localhost": identity.self_signing_key
1603 },
1604 "user_signing_keys": {
1605 "@example:localhost": identity.user_signing_key
1606 },
1607 }
1608 );
1609
1610 ruma_response_from_json(&json)
1611 }
1612}
1613
1614#[cfg(test)]
1615pub(crate) mod tests {
1616 use std::ops::Deref;
1617 #[cfg(feature = "experimental-x509-identity-verification")]
1618 use std::sync::Arc;
1619
1620 use futures_util::pin_mut;
1621 use matrix_sdk_test::{async_test, ruma_response_from_json, test_json};
1622 use ruma::{
1623 TransactionId, api::client::keys::get_keys::v3::Response as KeysQueryResponse, device_id,
1624 user_id,
1625 };
1626 use serde_json::json;
1627 use stream_assert::{assert_closed, assert_pending, assert_ready};
1628 #[cfg(feature = "experimental-x509-identity-verification")]
1629 use tokio::sync::Mutex;
1630
1631 #[cfg(feature = "experimental-x509-identity-verification")]
1632 use super::IdentityManager;
1633 use super::testing::{
1634 device_id, key_query, manager_test_helper, other_key_query, other_user_id, user_id,
1635 };
1636 #[cfg(feature = "experimental-x509-identity-verification")]
1637 use crate::olm::Account;
1638 use crate::{
1639 CrossSigningKeyExport, OlmMachine,
1640 identities::manager::testing::{other_key_query_cross_signed, own_key_query},
1641 olm::PrivateCrossSigningIdentity,
1642 store::types::Changes,
1643 };
1644
1645 fn key_query_with_failures() -> KeysQueryResponse {
1646 let response = json!({
1647 "device_keys": {
1648 },
1649 "failures": {
1650 "example.org": {
1651 "errcode": "M_RESOURCE_LIMIT_EXCEEDED",
1652 "error": "Not yet ready to retry",
1653 }
1654 }
1655 });
1656
1657 ruma_response_from_json(&response)
1658 }
1659
1660 #[async_test]
1661 async fn test_tracked_users() {
1662 let manager = manager_test_helper(user_id(), device_id()).await;
1663 let alice = user_id!("@alice:example.org");
1664
1665 let cache = manager.store.cache().await.unwrap();
1666 let key_query_manager = manager.key_query_manager.synced(&cache).await.unwrap();
1667
1668 assert!(key_query_manager.tracked_users().is_empty(), "No users are initially tracked");
1669
1670 manager.receive_device_changes(&cache, [alice].iter().map(Deref::deref)).await.unwrap();
1671
1672 assert!(
1673 !key_query_manager.tracked_users().contains(alice),
1674 "Receiving a device changes update for a user we don't track does nothing"
1675 );
1676
1677 assert!(
1678 !key_query_manager.users_for_key_query().await.0.contains(alice),
1679 "The user we don't track doesn't end up in the `/keys/query` request"
1680 );
1681 }
1682
1683 #[async_test]
1684 async fn test_manager_creation() {
1685 let manager = manager_test_helper(user_id(), device_id()).await;
1686 let cache = manager.store.cache().await.unwrap();
1687 assert!(manager.key_query_manager.synced(&cache).await.unwrap().tracked_users().is_empty())
1688 }
1689
1690 #[async_test]
1691 async fn test_manager_key_query_response() {
1692 let manager = manager_test_helper(user_id(), device_id()).await;
1693 let other_user = other_user_id();
1694 let devices = manager.store.get_user_devices(other_user).await.unwrap();
1695 assert_eq!(devices.devices().count(), 0);
1696
1697 manager
1698 .receive_keys_query_response(&TransactionId::new(), &other_key_query())
1699 .await
1700 .unwrap();
1701
1702 let devices = manager.store.get_user_devices(other_user).await.unwrap();
1703 assert_eq!(devices.devices().count(), 1);
1704
1705 let device = manager
1706 .store
1707 .get_device_data(other_user, device_id!("SKISMLNIMH"))
1708 .await
1709 .unwrap()
1710 .unwrap();
1711 let identity = manager.store.get_user_identity(other_user).await.unwrap().unwrap();
1712 let identity = identity.other().unwrap();
1713
1714 assert!(identity.is_device_signed(&device));
1715 }
1716
1717 #[async_test]
1718 async fn test_manager_own_key_query_response() {
1719 let manager = manager_test_helper(user_id(), device_id()).await;
1720 let our_user = user_id();
1721 let devices = manager.store.get_user_devices(our_user).await.unwrap();
1722 assert_eq!(devices.devices().count(), 0);
1723
1724 let private_identity = manager.store.private_identity();
1725 let private_identity = private_identity.lock().await;
1726 let identity_request = private_identity.as_upload_request().await;
1727 drop(private_identity);
1728
1729 let device_keys =
1730 manager.store.cache().await.unwrap().account().await.unwrap().device_keys();
1731 manager
1732 .receive_keys_query_response(
1733 &TransactionId::new(),
1734 &key_query(identity_request, device_keys),
1735 )
1736 .await
1737 .unwrap();
1738
1739 let identity = manager
1740 .store
1741 .get_user_identity(our_user)
1742 .await
1743 .unwrap()
1744 .expect("missing user identity");
1745 let identity = identity.own().expect("missing own identity");
1746 assert!(identity.is_verified());
1747
1748 let devices = manager.store.get_user_devices(our_user).await.unwrap();
1749 assert_eq!(devices.devices().count(), 1);
1750
1751 let device = manager.store.get_device_data(our_user, device_id()).await.unwrap();
1752
1753 assert!(device.is_some());
1754 }
1755
1756 #[async_test]
1757 async fn test_private_identity_invalidation_after_public_keys_change() {
1758 let user_id = user_id!("@example1:localhost");
1759 let manager = manager_test_helper(user_id, "DEVICEID".into()).await;
1760
1761 let identity_request = {
1762 let private_identity = manager.store.private_identity();
1763 let private_identity = private_identity.lock().await;
1764 private_identity.as_upload_request().await
1765 };
1766 let device_keys = manager.store.static_account().unsigned_device_keys();
1767
1768 let response = json!({
1769 "device_keys": {
1770 user_id: {
1771 device_keys.device_id.to_string(): device_keys
1772 }
1773 },
1774 "master_keys": {
1775 user_id: identity_request.master_key,
1776 },
1777 "self_signing_keys": {
1778 user_id: identity_request.self_signing_key,
1779 },
1780 "user_signing_keys": {
1781 user_id: identity_request.user_signing_key,
1782 }
1783 });
1784
1785 let response = ruma_response_from_json(&response);
1786 manager.receive_keys_query_response(&TransactionId::new(), &response).await.unwrap();
1787
1788 let identity = manager.store.get_user_identity(user_id).await.unwrap().unwrap();
1789 let identity = identity.own().unwrap();
1790 assert!(identity.is_verified());
1791
1792 let identity_request = {
1793 let private_identity = PrivateCrossSigningIdentity::new(user_id.into());
1794 private_identity.as_upload_request().await
1795 };
1796
1797 let response = json!({
1798 "master_keys": {
1799 user_id: identity_request.master_key,
1800 "@example2:localhost": {
1801 "user_id": "@example2:localhost",
1802 "usage": ["master"],
1803 "keys": {
1804 "ed25519:kC/HmRYw4HNqUp/i4BkwYENrf+hd9tvdB7A1YOf5+Do": "kC/HmRYw4HNqUp/i4BkwYENrf+hd9tvdB7A1YOf5+Do"
1805 },
1806 "signatures": {
1807 "@example2:localhost": {
1808 "ed25519:SKISMLNIMH": "KdUZqzt8VScGNtufuQ8lOf25byYLWIhmUYpPENdmM8nsldexD7vj+Sxoo7PknnTX/BL9h2N7uBq0JuykjunCAw"
1809 }
1810 }
1811 },
1812 },
1813 "self_signing_keys": {
1814 user_id: identity_request.self_signing_key,
1815 "@example2:localhost": {
1816 "user_id": "@example2:localhost",
1817 "usage": ["self_signing"],
1818 "keys": {
1819 "ed25519:ZtFrSkJ1qB8Jph/ql9Eo/lKpIYCzwvKAKXfkaS4XZNc": "ZtFrSkJ1qB8Jph/ql9Eo/lKpIYCzwvKAKXfkaS4XZNc"
1820 },
1821 "signatures": {
1822 "@example2:localhost": {
1823 "ed25519:kC/HmRYw4HNqUp/i4BkwYENrf+hd9tvdB7A1YOf5+Do": "W/O8BnmiUETPpH02mwYaBgvvgF/atXnusmpSTJZeUSH/vHg66xiZOhveQDG4cwaW8iMa+t9N4h1DWnRoHB4mCQ"
1824 }
1825 }
1826 }
1827 },
1828 "user_signing_keys": {
1829 user_id: identity_request.user_signing_key,
1830 }
1831 });
1832
1833 let response = ruma_response_from_json(&response);
1834 let (_, private_identity) = manager.handle_cross_signing_keys(&response).await.unwrap();
1835
1836 assert!(private_identity.is_some());
1837 let private_identity = manager.store.private_identity();
1838 assert!(private_identity.lock().await.is_empty().await);
1839 }
1840
1841 #[async_test]
1842 async fn test_no_tracked_users_key_query_request() {
1843 let manager = manager_test_helper(user_id(), device_id()).await;
1844
1845 let cache = manager.store.cache().await.unwrap();
1846 assert!(
1847 manager.key_query_manager.synced(&cache).await.unwrap().tracked_users().is_empty(),
1848 "No users are initially tracked"
1849 );
1850
1851 let requests = manager.users_for_key_query().await.unwrap();
1852 assert!(!requests.is_empty(), "We query the keys for our own user");
1853
1854 assert!(
1855 manager
1856 .key_query_manager
1857 .synced(&cache)
1858 .await
1859 .unwrap()
1860 .tracked_users()
1861 .contains(manager.user_id()),
1862 "Our own user is now tracked"
1863 );
1864 }
1865
1866 #[async_test]
1870 async fn test_invalidation_race_handling() {
1871 let manager = manager_test_helper(user_id(), device_id()).await;
1872 let alice = other_user_id();
1873 manager.update_tracked_users([alice]).await.unwrap();
1874
1875 let (reqid, req) = manager.users_for_key_query().await.unwrap().pop_first().unwrap();
1877 assert!(req.device_keys.contains_key(alice));
1878
1879 {
1881 let cache = manager.store.cache().await.unwrap();
1882 manager.receive_device_changes(&cache, [alice].into_iter()).await.unwrap();
1883 }
1884
1885 manager.receive_keys_query_response(&reqid, &other_key_query()).await.unwrap();
1887
1888 let (reqid, req) = manager.users_for_key_query().await.unwrap().pop_first().unwrap();
1890 assert!(req.device_keys.contains_key(alice));
1891
1892 manager.receive_keys_query_response(&reqid, &other_key_query()).await.unwrap();
1894
1895 let queries = manager.users_for_key_query().await.unwrap();
1897 assert!(!queries.iter().any(|(_, r)| r.device_keys.contains_key(alice)));
1898 }
1899
1900 #[async_test]
1901 async fn test_failure_handling() {
1902 let manager = manager_test_helper(user_id(), device_id()).await;
1903 let alice = user_id!("@alice:example.org");
1904
1905 {
1906 let cache = manager.store.cache().await.unwrap();
1907 let key_query_manager = manager.key_query_manager.synced(&cache).await.unwrap();
1908 assert!(key_query_manager.tracked_users().is_empty(), "No users are initially tracked");
1909
1910 key_query_manager.mark_user_as_changed(alice).await.unwrap();
1911
1912 assert!(
1913 key_query_manager.tracked_users().contains(alice),
1914 "Alice is tracked after being marked as tracked"
1915 );
1916 }
1917
1918 let (reqid, req) = manager.users_for_key_query().await.unwrap().pop_first().unwrap();
1919 assert!(req.device_keys.contains_key(alice));
1920
1921 let response = key_query_with_failures();
1923 manager.receive_keys_query_response(&reqid, &response).await.unwrap();
1924 assert!(manager.failures.contains(alice.server_name()));
1925 assert!(
1926 !manager
1927 .users_for_key_query()
1928 .await
1929 .unwrap()
1930 .iter()
1931 .any(|(_, r)| r.device_keys.contains_key(alice))
1932 );
1933
1934 manager.failures.remove([alice.server_name().to_owned()].iter());
1936 assert!(
1937 manager
1938 .users_for_key_query()
1939 .await
1940 .unwrap()
1941 .iter()
1942 .any(|(_, r)| r.device_keys.contains_key(alice))
1943 );
1944 }
1945
1946 #[async_test]
1947 async fn test_out_of_band_key_query() {
1948 let manager = manager_test_helper(user_id(), device_id()).await;
1950 let (reqid, req) = manager.build_key_query_for_users(vec![user_id()]);
1951 assert!(req.device_keys.contains_key(user_id()));
1952
1953 let (device_changes, identity_changes) =
1955 manager.receive_keys_query_response(&reqid, &own_key_query()).await.unwrap();
1956 assert_eq!(device_changes.new.len(), 1);
1957 assert_eq!(device_changes.new[0].device_id(), "LVWOVGOXME");
1958 assert_eq!(identity_changes.new.len(), 1);
1959 assert_eq!(identity_changes.new[0].user_id(), user_id());
1960
1961 let devices = manager.store.get_user_devices(user_id()).await.unwrap();
1962 assert_eq!(devices.devices().count(), 1);
1963 assert_eq!(devices.devices().next().unwrap().device_id(), "LVWOVGOXME");
1964 }
1965
1966 #[async_test]
1967 async fn test_invalid_key_response() {
1968 let my_user_id = user_id();
1969 let my_device_id = device_id();
1970 let manager = manager_test_helper(my_user_id, my_device_id).await;
1971
1972 let (reqid, _) = manager.build_key_query_for_users(vec![user_id()]);
1974 let (device_changes, identity_changes) =
1975 manager.receive_keys_query_response(&reqid, &own_key_query()).await.unwrap();
1976 assert_eq!(device_changes.new.len(), 1);
1977 let test_device_id = device_changes.new.first().unwrap().device_id().to_owned();
1978 let changes =
1979 Changes { devices: device_changes, identities: identity_changes, ..Changes::default() };
1980 manager.store.save_changes(changes).await.unwrap();
1981
1982 let (reqid, _) = manager.build_key_query_for_users(vec![my_user_id]);
1984 let response = ruma_response_from_json(&json!({
1985 "device_keys": {
1986 my_user_id: {
1987 test_device_id.as_str(): {
1988 "algorithms": [
1989 "m.olm.v1.curve25519-aes-sha2",
1990 ],
1991 "device_id": test_device_id.as_str(),
1992 "keys": {
1993 format!("curve25519:{}", test_device_id): "wnip2tbJBJxrFayC88NNJpm61TeSNgYcqBH4T9yEDhU",
1994 format!("ed25519:{}", test_device_id): "lQ+eshkhgKoo+qp9Qgnj3OX5PBoWMU5M9zbuEevwYqE"
1995 },
1996 "signatures": {
1997 my_user_id: {
1998 format!("ed25519:{}", test_device_id): "imadethisup",
2000 }
2001 },
2002 "user_id": my_user_id,
2003 }
2004 }
2005 }
2006 }));
2007
2008 let (device_changes, identity_changes) =
2009 manager.receive_keys_query_response(&reqid, &response).await.unwrap();
2010
2011 assert_eq!(device_changes.new.len(), 0);
2013 assert_eq!(device_changes.changed.len(), 0);
2014 assert_eq!(device_changes.deleted.len(), 0);
2015 assert_eq!(identity_changes.new.len(), 0);
2016
2017 let device =
2019 manager.store.get_user_devices(my_user_id).await.unwrap().get(&test_device_id).unwrap();
2020 assert_eq!(device.algorithms().len(), 2);
2021 }
2022
2023 #[async_test]
2024 async fn test_devices_stream() {
2025 let manager = manager_test_helper(user_id(), device_id()).await;
2026 let (request_id, _) = manager.build_key_query_for_users(vec![user_id()]);
2027
2028 let stream = manager.store.devices_stream();
2029 pin_mut!(stream);
2030
2031 manager.receive_keys_query_response(&request_id, &own_key_query()).await.unwrap();
2032
2033 let update = assert_ready!(stream);
2034 assert!(!update.new.is_empty(), "The device update should contain some devices");
2035 }
2036
2037 #[async_test]
2038 async fn test_identities_stream() {
2039 let manager = manager_test_helper(user_id(), device_id()).await;
2040 let (request_id, _) = manager.build_key_query_for_users(vec![user_id()]);
2041
2042 let stream = manager.store.user_identities_stream();
2043 pin_mut!(stream);
2044
2045 manager.receive_keys_query_response(&request_id, &own_key_query()).await.unwrap();
2046
2047 let update = assert_ready!(stream);
2048 assert!(!update.new.is_empty(), "The identities update should contain some identities");
2049 }
2050
2051 #[async_test]
2052 async fn test_identities_stream_raw() {
2053 let mut manager = Some(manager_test_helper(user_id(), device_id()).await);
2054 let (request_id, _) = manager.as_ref().unwrap().build_key_query_for_users(vec![user_id()]);
2055
2056 let stream = manager.as_ref().unwrap().store.identities_stream_raw();
2057 pin_mut!(stream);
2058
2059 manager
2060 .as_ref()
2061 .unwrap()
2062 .receive_keys_query_response(&request_id, &own_key_query())
2063 .await
2064 .unwrap();
2065
2066 let (identity_update, _) = assert_ready!(stream);
2067 assert_eq!(identity_update.new.len(), 1);
2068 assert_eq!(identity_update.changed.len(), 0);
2069 assert_eq!(identity_update.unchanged.len(), 0);
2070 assert_eq!(identity_update.new[0].user_id(), user_id());
2071
2072 assert_pending!(stream);
2073
2074 let (new_request_id, _) =
2075 manager.as_ref().unwrap().build_key_query_for_users(vec![user_id()]);
2076
2077 manager
2080 .as_ref()
2081 .unwrap()
2082 .receive_keys_query_response(&new_request_id, &own_key_query())
2083 .await
2084 .unwrap();
2085
2086 assert_pending!(stream);
2087
2088 manager.take();
2090 assert_closed!(stream);
2091 }
2092
2093 #[async_test]
2094 async fn test_identities_stream_raw_signature_update() {
2095 let mut manager = Some(manager_test_helper(user_id(), device_id()).await);
2096 let (request_id, _) =
2097 manager.as_ref().unwrap().build_key_query_for_users(vec![other_user_id()]);
2098
2099 let stream = manager.as_ref().unwrap().store.identities_stream_raw();
2100 pin_mut!(stream);
2101
2102 manager
2103 .as_ref()
2104 .unwrap()
2105 .receive_keys_query_response(&request_id, &other_key_query())
2106 .await
2107 .unwrap();
2108
2109 let (identity_update, _) = assert_ready!(stream);
2110 assert_eq!(identity_update.new.len(), 1);
2111 assert_eq!(identity_update.changed.len(), 0);
2112 assert_eq!(identity_update.unchanged.len(), 0);
2113 assert_eq!(identity_update.new[0].user_id(), other_user_id());
2114
2115 let initial_msk = identity_update.new[0].master_key().clone();
2116
2117 let (new_request_id, _) =
2118 manager.as_ref().unwrap().build_key_query_for_users(vec![user_id()]);
2119 manager
2121 .as_ref()
2122 .unwrap()
2123 .receive_keys_query_response(&new_request_id, &other_key_query_cross_signed())
2124 .await
2125 .unwrap();
2126
2127 let (identity_update_2, _) = assert_ready!(stream);
2128 assert_eq!(identity_update_2.new.len(), 0);
2129 assert_eq!(identity_update_2.changed.len(), 1);
2130 assert_eq!(identity_update_2.unchanged.len(), 0);
2131
2132 let updated_msk = identity_update_2.changed[0].master_key().clone();
2133
2134 assert_eq!(initial_msk, updated_msk);
2136
2137 assert_pending!(stream);
2138
2139 manager.take();
2140 }
2141
2142 #[async_test]
2143 async fn test_key_query_with_unknown_properties() {
2144 let manager = manager_test_helper(user_id(), device_id()).await;
2145 let other_user = user_id!("@example:localhost");
2146 let devices = manager.store.get_user_devices(other_user).await.unwrap();
2147 assert_eq!(devices.devices().count(), 0);
2148
2149 let response = json!({
2150 "device_keys": {
2151 "@example:localhost": {
2152 "OBEBOSKTBE": {
2153 "algorithms": ["m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"],
2154 "user_id": "@example:localhost",
2155 "device_id": "OBEBOSKTBE",
2156 "extra_property": "somevalue",
2157 "keys": {
2158 "curve25519:OBEBOSKTBE": "ECrdZebl0DskwbkxoztsiKPb6ivu7M2qQ70BFWwre3w",
2159 "ed25519:OBEBOSKTBE": "hFWo+pG6TVWNzq/ZubUQVL5Ardu9rqHxpKkCbf1/KiA"
2160 },
2161 "signatures": {
2162 "@example:localhost": {
2163 "ed25519:OBEBOSKTBE": "6vyYUgX+IoT1x6Mvf0g/GEPVb2UI3brfL7WZ75WZ81sH4FBFgAzkkuGpw9suGLKXnlEdLH0suBzaT4esVhFDCw",
2164 },
2165 },
2166 },
2167 },
2168 },
2169 });
2170
2171 let response = ruma_response_from_json(&response);
2172 manager.receive_keys_query_response(&TransactionId::new(), &response).await.unwrap();
2173
2174 let devices = manager.store.get_user_devices(other_user).await.unwrap();
2175 assert_eq!(devices.devices().count(), 1);
2176
2177 manager.store.get_device_data(other_user, device_id!("OBEBOSKTBE")).await.unwrap().unwrap();
2178 }
2179
2180 #[async_test]
2181 async fn test_manager_identity_updates() {
2182 use test_json::keys_query_sets::IdentityChangeDataSet as DataSet;
2183
2184 let manager = manager_test_helper(user_id(), device_id()).await;
2185 let other_user = DataSet::user_id();
2186 let devices = manager.store.get_user_devices(other_user).await.unwrap();
2187 assert_eq!(devices.devices().count(), 0);
2188
2189 let identity = manager.store.get_user_identity(other_user).await.unwrap();
2190 assert!(identity.is_none());
2191
2192 manager
2193 .receive_keys_query_response(
2194 &TransactionId::new(),
2195 &DataSet::key_query_with_identity_a(),
2196 )
2197 .await
2198 .unwrap();
2199
2200 let identity = manager.store.get_user_identity(other_user).await.unwrap().unwrap();
2201 let other_identity = identity.other().unwrap();
2202
2203 assert!(!other_identity.has_pin_violation());
2206 let first_device =
2207 manager.store.get_device_data(other_user, DataSet::device_a()).await.unwrap().unwrap();
2208 assert!(first_device.is_cross_signed_by_owner(&identity));
2209
2210 manager
2212 .receive_keys_query_response(
2213 &TransactionId::new(),
2214 &DataSet::key_query_with_identity_b(),
2215 )
2216 .await
2217 .unwrap();
2218
2219 let identity = manager.store.get_user_identity(other_user).await.unwrap().unwrap();
2220 let other_identity = identity.other().unwrap();
2221
2222 assert!(other_identity.has_pin_violation());
2225
2226 let second_device =
2227 manager.store.get_device_data(other_user, DataSet::device_b()).await.unwrap().unwrap();
2228
2229 assert!(second_device.is_cross_signed_by_owner(&identity));
2231
2232 let first_device =
2234 manager.store.get_device_data(other_user, DataSet::device_a()).await.unwrap().unwrap();
2235 assert!(!first_device.is_cross_signed_by_owner(&identity));
2236
2237 let remember_previous_identity = other_identity.clone();
2238 manager
2243 .receive_keys_query_response(
2244 &TransactionId::new(),
2245 &DataSet::key_query_with_identity_no_identity(),
2246 )
2247 .await
2248 .unwrap();
2249
2250 let identity = manager.store.get_user_identity(other_user).await.unwrap().unwrap();
2251 let other_identity = identity.other().unwrap();
2252
2253 assert_eq!(other_identity, &remember_previous_identity);
2254 assert!(other_identity.has_pin_violation());
2255 }
2256
2257 #[async_test]
2258 async fn test_manager_resolve_identity_pin_violation() {
2259 use test_json::keys_query_sets::IdentityChangeDataSet as DataSet;
2260
2261 let manager = manager_test_helper(user_id(), device_id()).await;
2262 let other_user = DataSet::user_id();
2263
2264 manager
2265 .receive_keys_query_response(
2266 &TransactionId::new(),
2267 &DataSet::key_query_with_identity_a(),
2268 )
2269 .await
2270 .unwrap();
2271
2272 manager
2274 .receive_keys_query_response(
2275 &TransactionId::new(),
2276 &DataSet::key_query_with_identity_b(),
2277 )
2278 .await
2279 .unwrap();
2280
2281 let identity = manager.store.get_user_identity(other_user).await.unwrap().unwrap();
2282 let other_identity = identity.other().unwrap();
2283
2284 assert!(other_identity.has_pin_violation());
2286
2287 other_identity.pin();
2289
2290 assert!(!other_identity.has_pin_violation());
2291 }
2292
2293 async fn common_verified_identity_changes_machine_setup() -> OlmMachine {
2296 use test_json::keys_query_sets::VerificationViolationTestData as DataSet;
2297
2298 let machine = OlmMachine::new(DataSet::own_id(), device_id!("LOCAL")).await;
2299
2300 let keys_query = DataSet::own_keys_query_response_1();
2301 let txn_id = TransactionId::new();
2302 machine.mark_request_as_sent(&txn_id, &keys_query).await.unwrap();
2303
2304 machine
2305 .import_cross_signing_keys(CrossSigningKeyExport {
2306 master_key: DataSet::MASTER_KEY_PRIVATE_EXPORT.to_owned().into(),
2307 self_signing_key: DataSet::SELF_SIGNING_KEY_PRIVATE_EXPORT.to_owned().into(),
2308 user_signing_key: DataSet::USER_SIGNING_KEY_PRIVATE_EXPORT.to_owned().into(),
2309 })
2310 .await
2311 .unwrap();
2312 machine
2313 }
2314 #[async_test]
2315 async fn test_manager_verified_latch_setup_on_new_identities() {
2316 use test_json::keys_query_sets::VerificationViolationTestData as DataSet;
2317
2318 let machine = common_verified_identity_changes_machine_setup().await;
2319
2320 let keys_query = DataSet::bob_keys_query_response_signed();
2324 let txn_id = TransactionId::new();
2325 machine.mark_request_as_sent(&txn_id, &keys_query).await.unwrap();
2326
2327 let own_identity =
2328 machine.get_identity(DataSet::own_id(), None).await.unwrap().unwrap().own().unwrap();
2329 assert!(own_identity.is_verified());
2331
2332 let bob_identity =
2333 machine.get_identity(DataSet::bob_id(), None).await.unwrap().unwrap().other().unwrap();
2334 assert!(bob_identity.was_previously_verified());
2336 assert!(bob_identity.is_verified());
2338
2339 let keys_query = DataSet::bob_keys_query_response_rotated();
2343 let txn_id = TransactionId::new();
2344 machine.mark_request_as_sent(&txn_id, &keys_query).await.unwrap();
2345
2346 let bob_identity =
2347 machine.get_identity(DataSet::bob_id(), None).await.unwrap().unwrap().other().unwrap();
2348 assert!(!bob_identity.is_verified());
2350 assert!(bob_identity.was_previously_verified());
2352 let bob_device = machine
2355 .get_device(DataSet::bob_id(), DataSet::bob_device_2_id(), None)
2356 .await
2357 .unwrap()
2358 .unwrap();
2359 assert!(bob_identity.is_device_signed(&bob_device));
2360 assert!(bob_identity.has_pin_violation());
2362 bob_identity.pin_current_master_key().await.unwrap();
2364 assert!(!bob_identity.has_pin_violation());
2365 let has_latch_violation =
2366 bob_identity.was_previously_verified() && !bob_identity.is_verified();
2367 assert!(has_latch_violation);
2368 }
2369
2370 #[async_test]
2371 async fn test_manager_verified_identity_changes_setup_on_updated_identities() {
2372 use test_json::keys_query_sets::VerificationViolationTestData as DataSet;
2373
2374 let machine = common_verified_identity_changes_machine_setup().await;
2375
2376 let keys_query = DataSet::carol_keys_query_response_unsigned();
2380 let txn_id = TransactionId::new();
2381 machine.mark_request_as_sent(&txn_id, &keys_query).await.unwrap();
2382
2383 let carol_identity =
2384 machine.get_identity(DataSet::carol_id(), None).await.unwrap().unwrap();
2385 assert!(!carol_identity.is_verified());
2387 assert!(!carol_identity.was_previously_verified());
2389
2390 let keys_query = DataSet::carol_keys_query_response_signed();
2393 let txn_id = TransactionId::new();
2394 machine.mark_request_as_sent(&txn_id, &keys_query).await.unwrap();
2395
2396 let carol_identity = machine
2397 .get_identity(DataSet::carol_id(), None)
2398 .await
2399 .unwrap()
2400 .unwrap()
2401 .other()
2402 .unwrap();
2403 assert!(carol_identity.is_verified());
2404 assert!(carol_identity.was_previously_verified());
2406 assert!(!carol_identity.has_pin_violation());
2408 }
2409
2410 async fn common_verified_identity_changes_own_trust_change_machine_setup() -> OlmMachine {
2414 use test_json::keys_query_sets::VerificationViolationTestData as DataSet;
2415
2416 let machine = OlmMachine::new(DataSet::own_id(), device_id!("LOCAL")).await;
2418
2419 let keys_query = DataSet::own_keys_query_response_1();
2420 let txn_id = TransactionId::new();
2421 machine.mark_request_as_sent(&txn_id, &keys_query).await.unwrap();
2422
2423 let own_identity =
2425 machine.get_identity(DataSet::own_id(), None).await.unwrap().unwrap().own().unwrap();
2426 assert!(!own_identity.is_verified());
2427
2428 let keys_query = DataSet::own_keys_query_response_1();
2429 let txn_id = TransactionId::new();
2430 machine.mark_request_as_sent(&txn_id, &keys_query).await.unwrap();
2431
2432 let keys_query = DataSet::bob_keys_query_response_signed();
2434 let txn_id = TransactionId::new();
2435 machine.mark_request_as_sent(&txn_id, &keys_query).await.unwrap();
2436
2437 let keys_query = DataSet::carol_keys_query_response_signed();
2438 let txn_id = TransactionId::new();
2439 machine.mark_request_as_sent(&txn_id, &keys_query).await.unwrap();
2440
2441 machine.update_tracked_users(vec![DataSet::bob_id(), DataSet::carol_id()]).await.unwrap();
2442
2443 machine
2444 }
2445
2446 #[async_test]
2447 async fn test_manager_verified_identity_changes_setup_on_own_identity_trust_change() {
2448 use test_json::keys_query_sets::VerificationViolationTestData as DataSet;
2449 let machine = common_verified_identity_changes_own_trust_change_machine_setup().await;
2450
2451 let own_identity =
2452 machine.get_identity(DataSet::own_id(), None).await.unwrap().unwrap().own().unwrap();
2453
2454 let bob_identity = machine.get_identity(DataSet::bob_id(), None).await.unwrap().unwrap();
2455 assert!(!bob_identity.was_previously_verified());
2457 assert!(own_identity.is_identity_signed(&bob_identity.other().unwrap()));
2458
2459 let carol_identity =
2460 machine.get_identity(DataSet::carol_id(), None).await.unwrap().unwrap();
2461 assert!(!carol_identity.was_previously_verified());
2463 assert!(own_identity.is_identity_signed(&carol_identity.other().unwrap()));
2464
2465 let _ = own_identity.verify().await;
2467
2468 let own_identity = machine.get_identity(DataSet::own_id(), None).await.unwrap().unwrap();
2469 assert!(own_identity.is_verified());
2470
2471 let carol_identity =
2472 machine.get_identity(DataSet::carol_id(), None).await.unwrap().unwrap();
2473 assert!(carol_identity.is_verified());
2474 assert!(carol_identity.was_previously_verified());
2476
2477 let bob_identity = machine.get_identity(DataSet::bob_id(), None).await.unwrap().unwrap();
2478 assert!(bob_identity.is_verified());
2479 assert!(bob_identity.was_previously_verified());
2481 }
2482
2483 #[async_test]
2484 async fn test_manager_verified_identity_change_setup_on_import_secrets() {
2485 use test_json::keys_query_sets::VerificationViolationTestData as DataSet;
2486 let machine = common_verified_identity_changes_own_trust_change_machine_setup().await;
2487
2488 let own_identity =
2489 machine.get_identity(DataSet::own_id(), None).await.unwrap().unwrap().own().unwrap();
2490
2491 let bob_identity =
2492 machine.get_identity(DataSet::bob_id(), None).await.unwrap().unwrap().other().unwrap();
2493 assert!(own_identity.is_identity_signed(&bob_identity));
2495 assert!(!bob_identity.was_previously_verified());
2496
2497 let carol_identity = machine
2498 .get_identity(DataSet::carol_id(), None)
2499 .await
2500 .unwrap()
2501 .unwrap()
2502 .other()
2503 .unwrap();
2504 assert!(own_identity.is_identity_signed(&carol_identity));
2506 assert!(!carol_identity.was_previously_verified());
2507
2508 machine
2510 .import_cross_signing_keys(CrossSigningKeyExport {
2511 master_key: DataSet::MASTER_KEY_PRIVATE_EXPORT.to_owned().into(),
2512 self_signing_key: DataSet::SELF_SIGNING_KEY_PRIVATE_EXPORT.to_owned().into(),
2513 user_signing_key: DataSet::USER_SIGNING_KEY_PRIVATE_EXPORT.to_owned().into(),
2514 })
2515 .await
2516 .unwrap();
2517
2518 let own_identity = machine.get_identity(DataSet::own_id(), None).await.unwrap().unwrap();
2519 assert!(own_identity.is_verified());
2520
2521 let carol_identity =
2522 machine.get_identity(DataSet::carol_id(), None).await.unwrap().unwrap();
2523 assert!(carol_identity.is_verified());
2524 assert!(carol_identity.was_previously_verified());
2526
2527 let bob_identity = machine.get_identity(DataSet::bob_id(), None).await.unwrap().unwrap();
2528 assert!(bob_identity.is_verified());
2529 assert!(bob_identity.was_previously_verified());
2531 }
2532
2533 mod update_sender_data {
2534 use assert_matches::assert_matches;
2535 use matrix_sdk_test::async_test;
2536 use ruma::room_id;
2537
2538 use super::{device_id, manager_test_helper};
2539 use crate::{
2540 Account, DeviceData, EncryptionSettings,
2541 identities::manager::testing::{other_user_id, user_id},
2542 olm::{InboundGroupSession, SenderData},
2543 store::types::{Changes, DeviceChanges},
2544 };
2545
2546 #[async_test]
2547 async fn test_adds_device_info_to_existing_sessions() {
2548 let manager = manager_test_helper(user_id(), device_id()).await;
2549
2550 let account1 = Account::new(user_id());
2552 let account2 = Account::new(other_user_id());
2553
2554 let mut account1_sessions = Vec::new();
2555 for _ in 0..60 {
2556 account1_sessions.push(create_inbound_group_session(&account1).await);
2557 }
2558 let mut account2_sessions = Vec::new();
2559 for _ in 0..60 {
2560 account2_sessions.push(create_inbound_group_session(&account2).await);
2561 }
2562 manager
2563 .store
2564 .save_changes(Changes {
2565 inbound_group_sessions: [account1_sessions.clone(), account2_sessions.clone()]
2566 .concat(),
2567 ..Default::default()
2568 })
2569 .await
2570 .unwrap();
2571
2572 let device_data = DeviceData::from_account(&account1);
2574 manager
2575 .update_sender_data_from_device_changes(&DeviceChanges {
2576 changed: vec![device_data],
2577 ..Default::default()
2578 })
2579 .await
2580 .unwrap();
2581
2582 for session in account1_sessions {
2584 let updated = manager
2585 .store
2586 .get_inbound_group_session(session.room_id(), session.session_id())
2587 .await
2588 .unwrap()
2589 .expect("Could not find session after update");
2590 assert_matches!(
2591 updated.sender_data,
2592 SenderData::DeviceInfo { .. },
2593 "incorrect sender data for session {}",
2594 session.session_id()
2595 );
2596 }
2597
2598 for session in account2_sessions {
2600 let updated = manager
2601 .store
2602 .get_inbound_group_session(session.room_id(), session.session_id())
2603 .await
2604 .unwrap()
2605 .expect("Could not find session after update");
2606 assert_matches!(updated.sender_data, SenderData::UnknownDevice { .. });
2607 }
2608 }
2609
2610 async fn create_inbound_group_session(account: &Account) -> InboundGroupSession {
2612 let (_, igs) = account
2613 .create_group_session_pair(
2614 room_id!("!test:room"),
2615 EncryptionSettings::default(),
2616 SenderData::unknown(),
2617 )
2618 .await
2619 .unwrap();
2620 igs
2621 }
2622 }
2623
2624 #[async_test]
2625 #[cfg(feature = "experimental-x509-identity-verification")]
2626 async fn test_refresh_x509_signature_after_keys_query() {
2627 let user_id = user_id!("@example1:localhost");
2630 let device_id = device_id!("DEVICEID");
2631
2632 let (x509_signer_old, x509_signer_current, x509_signer_new) =
2635 crate::x509::tests::signers_with_different_validity();
2636
2637 let manager = {
2639 let account = Account::with_device_id(&user_id, device_id);
2640 let identity =
2641 PrivateCrossSigningIdentity::for_account(&account, Some(&x509_signer_current))
2642 .await
2643 .unwrap();
2644 manager_with_private_identity_and_x509(identity, account, x509_signer_current.clone())
2645 .await
2646 };
2647
2648 assert!(manager.get_x509_signature_upload_request().await.is_none());
2649
2650 let private_identity = manager.store.private_identity();
2651 let master_key =
2652 private_identity.lock().await.master_public_key().await.unwrap().as_ref().clone();
2653 let identity_request = {
2654 let private_identity = manager.store.private_identity();
2655 let private_identity = private_identity.lock().await;
2656 private_identity.as_upload_request().await
2657 };
2658 let device_keys = manager.store.static_account().unsigned_device_keys();
2659
2660 let make_response = async move |x509_signer: &crate::x509::X509Signer| {
2663 let mut master_key = master_key.clone();
2664 x509_signer.sign_cross_signing_key(user_id, &mut master_key).await.unwrap();
2665
2666 let response = json!({
2667 "device_keys": {
2668 user_id: {
2669 device_keys.device_id.to_string(): device_keys
2670 }
2671 },
2672 "master_keys": {
2673 user_id: master_key,
2674 },
2675 "self_signing_keys": {
2676 user_id: identity_request.self_signing_key,
2677 },
2678 "user_signing_keys": {
2679 user_id: identity_request.user_signing_key,
2680 }
2681 });
2682
2683 ruma_response_from_json(&response)
2684 };
2685
2686 let response = make_response(&x509_signer_old).await;
2689 manager.receive_keys_query_response(&TransactionId::new(), &response).await.unwrap();
2690 assert!(manager.get_x509_signature_upload_request().await.is_some());
2691
2692 let response = make_response(&x509_signer_current).await;
2695 manager.receive_keys_query_response(&TransactionId::new(), &response).await.unwrap();
2696 assert!(manager.get_x509_signature_upload_request().await.is_none());
2697
2698 let response = make_response(&x509_signer_new).await;
2701 manager.receive_keys_query_response(&TransactionId::new(), &response).await.unwrap();
2702 assert!(manager.get_x509_signature_upload_request().await.is_none());
2703 }
2704
2705 #[async_test]
2706 #[cfg(feature = "experimental-x509-identity-verification")]
2707 async fn test_refresh_x509_signature_on_startup() {
2708 let user_id = user_id!("@example1:localhost");
2711 let device_id = device_id!("DEVICEID");
2712
2713 let (x509_signer_old, x509_signer_current, x509_signer_new) =
2716 crate::x509::tests::signers_with_different_validity();
2717
2718 let account = Account::with_device_id(&user_id, device_id);
2720 let identity =
2721 PrivateCrossSigningIdentity::for_account(&account, Some(&x509_signer_current))
2722 .await
2723 .unwrap();
2724
2725 let manager_old = manager_with_private_identity_and_x509(
2728 identity.clone(),
2729 account.deep_clone(),
2730 x509_signer_old,
2731 )
2732 .await;
2733 assert!(manager_old.get_x509_signature_upload_request().await.is_none());
2734
2735 let manager_current = manager_with_private_identity_and_x509(
2738 identity.clone(),
2739 account.deep_clone(),
2740 x509_signer_current,
2741 )
2742 .await;
2743 assert!(manager_current.get_x509_signature_upload_request().await.is_none());
2744
2745 let manager_new = manager_with_private_identity_and_x509(
2748 identity.clone(),
2749 account.deep_clone(),
2750 x509_signer_new,
2751 )
2752 .await;
2753 assert!(manager_new.get_x509_signature_upload_request().await.is_some());
2754 }
2755
2756 #[cfg(feature = "experimental-x509-identity-verification")]
2757 async fn manager_with_private_identity_and_x509(
2758 identity: PrivateCrossSigningIdentity,
2759 account: Account,
2760 x509_signer: crate::x509::X509Signer,
2761 ) -> IdentityManager {
2762 use crate::{
2763 store::{
2764 CryptoStoreWrapper, MemoryStore, Store,
2765 types::{Changes, IdentityChanges, PendingChanges},
2766 },
2767 verification::VerificationMachine,
2768 };
2769
2770 let user_identity_data = identity.to_public_identity().await.unwrap();
2771 let identity = Arc::new(Mutex::new(identity));
2772 let static_account = account.static_data().clone();
2773 let store = Arc::new(CryptoStoreWrapper::new(
2774 account.user_id(),
2775 account.device_id(),
2776 MemoryStore::new(),
2777 ));
2778 let verification =
2779 VerificationMachine::new(static_account.clone(), identity.clone(), store.clone());
2780 let store = Store::new_with_x509(
2781 static_account,
2782 identity,
2783 store,
2784 verification,
2785 None,
2786 Some(x509_signer),
2787 );
2788 store
2789 .save_changes(Changes {
2790 identities: IdentityChanges {
2791 new: vec![user_identity_data.into()],
2792 ..Default::default()
2793 },
2794 ..Default::default()
2795 })
2796 .await
2797 .unwrap();
2798 store.save_pending_changes(PendingChanges { account: Some(account) }).await.unwrap();
2799 IdentityManager::new(store)
2800 }
2801}