Skip to main content

matrix_sdk_crypto/identities/
manager.rs

1// Copyright 2020 The Matrix.org Foundation C.I.C.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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
61/// This enum helps us to distinguish between the changed and unchanged
62/// identity case.
63/// An unchanged identity means same cross signing keys as well as same
64/// set of signatures on the master key.
65enum IdentityUpdateResult {
66    Updated(UserIdentityData),
67    Unchanged(UserIdentityData),
68}
69
70/// This enum tracks the status of the outgoing X.509 signature upload request,
71/// if any.
72#[cfg(feature = "experimental-x509-identity-verification")]
73#[derive(Debug)]
74enum X509SignatureUploadRequest {
75    /// We have not yet checked if we need to upload a new signature.
76    Unknown,
77    /// We do not need to upload a new signature.
78    None,
79    /// We have a new signature to upload.
80    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    /// Servers that have previously appeared in the `failures` section of a
103    /// `/keys/query` response.
104    ///
105    /// See also [`crate::session_manager::SessionManager::failures`].
106    failures: FailuresCache<OwnedServerName>,
107    store: Store,
108
109    pub(crate) key_query_manager: Arc<KeyQueryManager>,
110
111    /// Details of the current "in-flight" key query request, if any
112    keys_query_request_details: Arc<Mutex<Option<KeysQueryRequestDetails>>>,
113
114    /// The current X.509 signature re-upload request, if any.
115    ///
116    /// We check whether we need to re-sign when
117    /// `get_x509_signature_upload_request` is first called, or when we receive
118    /// a master signing key from a `/keys/query` request.
119    #[cfg(feature = "experimental-x509-identity-verification")]
120    x509_signature_upload_request: Arc<Mutex<X509SignatureUploadRequest>>,
121}
122
123/// Details of an in-flight key query request
124#[derive(Debug, Clone, Default)]
125struct KeysQueryRequestDetails {
126    /// The sequence number, to be passed to
127    /// `Store.mark_tracked_users_as_up_to_date`.
128    sequence_number: SequenceNumber,
129
130    /// A single batch of queries returned by the Store is broken up into one or
131    /// more actual KeysQueryRequests, each with their own request id. We
132    /// record the outstanding request ids here.
133    request_ids: HashSet<OwnedTransactionId>,
134}
135
136// Helper type to handle key query response
137struct 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    /// Receive a successful `/keys/query` response.
166    ///
167    /// Returns a list of devices newly discovered devices and devices that
168    /// changed.
169    ///
170    /// # Arguments
171    ///
172    /// * `request_id` - The request_id returned by `users_for_key_query` or
173    ///   `build_key_query_for_users`
174    /// * `response` - The response of the `/keys/query` request that the client
175    ///   performed.
176    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        // Parse the strings into server names and filter out our own server. We should
189        // never get failures from our own server but let's remove it as a
190        // precaution anyways.
191        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        // Append the new failed servers and remove any successful servers. We
199        // need to explicitly remove the successful servers because the cache
200        // doesn't automatically remove entries that elapse. Instead, the effect
201        // is that elapsed servers will be retried and their delays incremented.
202        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        // Update the sender data on any existing inbound group sessions based on the
218        // changes in this response.
219        //
220        // `update_sender_data_from_device_changes` relies on being able to look up the
221        // user identities from the store, so this has to happen *after* the
222        // changes from `handle_cross_signing_keys` are saved.
223        //
224        // Note: it might be possible for this to race against session creation. If a
225        // new session is received at the same time as a `/keys/query` response is being
226        // processed, it could be saved without up-to-date sender data, but it might be
227        // saved too late for it to be picked up by
228        // `update_sender_data_from_device_changes`. However, this should be rare,
229        // since, in general, /sync responses which might create a new session
230        // are not processed at the same time as /keys/query responses (assuming
231        // that the application does not call `OlmMachine::receive_sync_changes`
232        // at the same time as `OlmMachine::mark_request_as_sent`).
233        self.update_sender_data_from_device_changes(&devices).await?;
234
235        // if this request is one of those we expected to be in flight, pass the
236        // sequence number back to the store so that it can mark devices up to
237        // date
238        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 this is our own device, check that the server isn't
294                    // lying about our keys, also mark the device as locally
295                    // trusted.
296                    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(&current_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    /// Handle the device keys part of a key query response.
415    ///
416    /// # Arguments
417    ///
418    /// * `device_keys_map` - A map holding the device keys of the users for
419    ///   which the key query was done.
420    ///
421    /// Returns a list of devices that changed. Changed here means either
422    /// they are new, one of their properties has changed or they got deleted.
423    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    /// Check if the given public identity matches our stored private one.
448    ///
449    /// If they don't match, this is an indication that our identity has been
450    /// rotated. In this case we return `Some(cleared_private_identity)`,
451    /// where `cleared_private_identity` is our currently-stored
452    /// private identity with the conflicting keys removed.
453    ///
454    /// Otherwise, assuming we do have a private master cross-signing key, we
455    /// mark the public identity as verified.
456    ///
457    /// # Returns
458    ///
459    /// If the private identity needs updating (because it does not match the
460    /// public keys), the updated private identity (which will need to be
461    /// persisted).
462    ///
463    /// Otherwise, `None`.
464    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 the master key didn't rotate above (`clear_if_differs`),
477            // then this means that the public part and the private parts of
478            // the master key match. We previously did a signature check, so
479            // this means that the private part of the master key has signed
480            // the identity. We can safely mark the public part of the
481            // identity as verified.
482            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                // Check if we need to re-sign our identity with the X.509 signer.
489                *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    /// Process an identity received in a `/keys/query` response that we
498    /// previously knew about.
499    ///
500    /// If the identity is our own, we will look for a user-signing key; if one
501    /// is not found, an error is returned. Otherwise, we then compare the
502    /// received public identity against our stored private identity;
503    /// if they match, the returned public identity is marked as verified and
504    /// `*changed_private_identity` is set to `None`. If they do *not* match,
505    /// it is an indication that our identity has been rotated, and
506    /// `*changed_private_identity` is set to our currently-stored private
507    /// identity with the conflicting keys removed (which will need to be
508    /// persisted).
509    ///
510    /// Whether the identity is our own or that of another, we check whether
511    /// there has been any change to the cross-signing keys, and classify
512    /// the result into [`IdentityUpdateResult::Updated`] or
513    /// [`IdentityUpdateResult::Unchanged`].
514    ///
515    /// # Arguments
516    ///
517    /// * `response` - The entire `/keys/query` response.
518    /// * `master_key` - The public master cross-signing key from the
519    ///   `/keys/query` response.
520    /// * `self_signing` - The public self-signing key from the `/keys/query`
521    ///   response.
522    /// * `i` - The existing identity for this user.
523    /// * `changed_private_identity` - Output parameter. Unchanged if the
524    ///   identity is that of another user. If it is our own, set to `None` or
525    ///   `Some` depending on whether our stored private identity needs
526    ///   updating. See above for more detail.
527    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    /// Process an identity received in a `/keys/query` response that we didn't
564    /// previously know about.
565    ///
566    /// If the identity is our own, we will look for a user-signing key, and if
567    /// it is present and correct, all three keys will be returned in the
568    /// `IdentityChange` result; otherwise, an error is returned. We will also
569    /// compare the received public identity against our stored private
570    /// identity; if they match, the returned public identity is marked as
571    /// verified and `*changed_private_identity` is set to `None`. If they do
572    /// *not* match, it is an indication that our identity has been rotated,
573    /// and `*changed_private_identity` is set to our currently-stored
574    /// private identity with the conflicting keys removed (which will need
575    /// to be persisted).
576    ///
577    /// If the identity is that of another user, we just parse the keys into the
578    /// `IdentityChange` result, since all other checks have already been done.
579    ///
580    /// # Arguments
581    ///
582    /// * `response` - The entire `/keys/query` response.
583    /// * `master_key` - The public master cross-signing key from the
584    ///   `/keys/query` response.
585    /// * `self_signing` - The public self-signing key from the `/keys/query`
586    ///   response.
587    /// * `changed_private_identity` - Output parameter. Unchanged if the
588    ///   identity is that of another user. If it is our own, set to `None` or
589    ///   `Some` depending on whether our stored private identity needs
590    ///   updating. See above for more detail.
591    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            // Own identity
601            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            // First time seen, create the identity. The current MSK will be pinned.
607            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    /// Try to deserialize the master key and self-signing key of an
619    /// identity from a `/keys/query` response.
620    ///
621    /// Each user identity *must* at least contain a master and self-signing
622    /// key, and this function deserializes them. (Our own identity, in addition
623    /// to those two, also contains a user-signing key, but that is not
624    /// extracted here; see
625    /// [`IdentityManager::get_user_signing_key_from_response`])
626    ///
627    /// # Arguments
628    ///
629    ///  * `master_key` - The master key for a particular user from a
630    ///    `/keys/query` response.
631    ///  * `response` - The entire `/keys/query` response.
632    ///
633    /// # Returns
634    ///
635    /// `None` if the self-signing key couldn't be found in the response, or the
636    /// one of the keys couldn't be deserialized. Else, the deserialized
637    /// public keys.
638    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    /// Try to deserialize the our user-signing key from a `/keys/query`
668    /// response.
669    ///
670    /// If a `/keys/query` response includes our own cross-signing keys, then it
671    /// should include our user-signing key. This method attempts to
672    /// extract, deserialize, and check the key from the response.
673    ///
674    /// # Arguments
675    ///
676    /// * `response` - the entire `/keys/query` response.
677    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    /// Process the cross-signing keys for a particular identity from a
706    /// `/keys/query` response.
707    ///
708    /// Checks that the keys are consistent, verifies the updates, and produces
709    /// a list of changes to be stored.
710    ///
711    /// # Arguments
712    ///
713    /// * `response` - The entire `/keys/query` response.
714    /// * `changes` - The identity results so far, which we will add to.
715    /// * `changed_identity` - Output parameter: Unchanged if the identity is
716    ///   that of another user. If it is our own, set to `None` or `Some`
717    ///   depending on whether our stored private identity needs updating.
718    /// * `maybe_verified_own_identity` - Own verified identity if any to check
719    ///   verification status of updated identity.
720    /// * `key_set_info` - The identity info as returned by the `/keys/query`
721    ///   response.
722    #[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            // an identity we knew about before, which is being updated
736            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            // an identity we did not know about before
761            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    /// Handle the cross signing keys part of a key query response.
785    ///
786    /// # Arguments
787    ///
788    /// * `response` - The `/keys/query` response.
789    ///
790    /// # Returns
791    ///
792    /// The processed results, to be saved to the datastore, comprising:
793    ///
794    ///  * A list of public identities that were received, categorised as "new",
795    ///    "changed" or "unchanged".
796    ///
797    ///  * If our own identity was updated and did not match our private
798    ///    identity, an update to that private identity. Otherwise, `None`.
799    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        // We want to check if the updated/new other identities are trusted by us or
807        // not. This is based on the current verified state of the own identity.
808        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            // Get the master and self-signing key for each identity; those are required for
817            // every user identity type. If we don't have those we skip over.
818            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    /// Generate an "out-of-band" key query request for the given set of users.
840    ///
841    /// Unlike the regular key query requests returned by `users_for_key_query`,
842    /// there can be several of these in flight at once. This can be useful
843    /// if we need results to be as up-to-date as possible.
844    ///
845    /// Once the request has been made, the response can be fed back into the
846    /// IdentityManager and store by calling `receive_keys_query_response`.
847    ///
848    /// # Arguments
849    ///
850    /// * `users` - list of users whose keys should be queried
851    ///
852    /// # Returns
853    ///
854    /// A tuple containing the request ID for the request, and the request
855    /// itself.
856    pub(crate) fn build_key_query_for_users<'a>(
857        &self,
858        users: impl IntoIterator<Item = &'a UserId>,
859    ) -> (OwnedTransactionId, KeysQueryRequest) {
860        // Since this is an "out-of-band" request, we just make up a transaction ID and
861        // do not store the details in `self.keys_query_request_details`.
862        //
863        // `receive_keys_query_response` will process the response as normal, except
864        // that it will not mark the users as "up-to-date".
865
866        // We assume that there aren't too many users here; if we find a usecase that
867        // requires lots of users to be up-to-date we may need to rethink this.
868        (TransactionId::new(), KeysQueryRequest::new(users.into_iter().map(|u| u.to_owned())))
869    }
870
871    /// Return the current signature upload request, if any, needed for updating
872    /// the X.509 signature.
873    ///
874    /// We re-sign our master cross-signing key with X.509 if our signer has a
875    /// later validity period than the current signature on our master
876    /// cross-signing key.
877    #[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            // We haven't yet checked if our identity needs re-signing, so check
882            // it now and remember the result.
883            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    /// Mark the outgoing X.509 signature upload request as sent.
901    #[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    /// Get a list of key query requests needed.
913    ///
914    /// # Returns
915    ///
916    /// A map of a request ID to the `/keys/query` request.
917    ///
918    /// The response of a successful key query requests needs to be passed to
919    /// the [`OlmMachine`] with the [`receive_keys_query_response`].
920    ///
921    /// [`receive_keys_query_response`]: Self::receive_keys_query_response
922    pub async fn users_for_key_query(
923        &self,
924    ) -> StoreResult<BTreeMap<OwnedTransactionId, KeysQueryRequest>> {
925        // Forget about any previous key queries in flight.
926        *self.keys_query_request_details.lock().await = None;
927
928        // We always want to track our own user, but in case we aren't in an encrypted
929        // room yet, we won't be tracking ourselves yet. This ensures we are always
930        // tracking ourselves.
931        //
932        // The check for emptiness is done first for performance.
933        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's remove users that are part of the `FailuresCache`. The cache, which is
951            // a TTL cache, remembers users for which a previous `/key/query` request has
952            // failed. We don't retry a `/keys/query` for such users for a
953            // certain amount of time.
954            let users = users.into_iter().filter(|u| !self.failures.contains(u.server_name()));
955
956            // We don't want to create a single `/keys/query` request with an infinite
957            // amount of users. Some servers will likely bail out after a
958            // certain amount of users and the responses will be large. In the
959            // case of a transmission error, we'll have to retransmit the large
960            // response.
961            //
962            // Convert the set of users into multiple /keys/query requests.
963            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            // Collect the request IDs, these will be used later in the
977            // `receive_keys_query_response()` method to figure out if the user can be
978            // marked as up-to-date/non-dirty.
979            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    /// Receive the list of users that contained changed devices from the
989    /// `/sync` response.
990    ///
991    /// This will queue up the given user for a key query.
992    ///
993    /// Note: The user already needs to be tracked for it to be queued up for a
994    /// key query.
995    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    /// See the docs for [`OlmMachine::update_tracked_users()`].
1004    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    /// Retrieve a list of a user's current devices, so we can encrypt a message
1013    /// to them.
1014    ///
1015    /// If we have not yet seen any devices for the user, and their device list
1016    /// has been marked as outdated, then we wait for the `/keys/query` request
1017    /// to complete. This helps ensure that we attempt at least once to fetch a
1018    /// user's devices before encrypting to them.
1019    pub async fn get_user_devices_for_encryption(
1020        &self,
1021        users: impl Iterator<Item = &UserId>,
1022    ) -> StoreResult<HashMap<OwnedUserId, HashMap<OwnedDeviceId, DeviceData>>> {
1023        // How long we wait for /keys/query to complete.
1024        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            // First of all, check the store for this user.
1032            let devices = self.store.get_device_data_for_user_filtered(user_id).await?;
1033
1034            // Now, look for users who have no devices at all.
1035            //
1036            // If a user has no devices at all, that implies we have never (successfully)
1037            // done a `/keys/query` for them; we wait for one to complete if it is
1038            // in flight. (Of course, the user might genuinely have no devices, but
1039            // that's fine, it just means we redundantly grab the cache guard and
1040            // check the pending-query flag.)
1041            if !devices.is_empty() {
1042                // This user has at least one known device.
1043                //
1044                // The device list may also be outdated in this case; but in this
1045                // situation, we are racing between sending a message and retrieving their
1046                // device list. That's an inherently racy situation and there is no real
1047                // benefit to waiting for the `/keys/query` request to complete. So we don't
1048                // bother.
1049                //
1050                // We just add their devices to the result and carry on.
1051                devices_by_user.insert(user_id.to_owned(), devices);
1052                continue;
1053            }
1054
1055            // *However*, if the user's server is currently subject to a backoff due to
1056            // previous failures, then `users_for_key_query` won't attempt to query
1057            // for the user's devices, so there's no point waiting.
1058            //
1059            // XXX: this is racy. It's possible that:
1060            //  * `failures` included the user's server when `users_for_key_query` was
1061            //    called, so the user was not returned in the `KeyQueryRequest`, and:
1062            //  * The backoff has now expired.
1063            //
1064            // In that case, we'll end up waiting for the *next* `users_for_key_query` call,
1065            // which might not be for 30 seconds or so. (And by then, it might be `failed`
1066            // again.)
1067            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            // For each user with no devices, fire off a task to wait for a `/keys/query`
1084            // result if one is pending.
1085            //
1086            // We don't actually update the `devices_by_user` map here since that could
1087            // require concurrent access to it. Instead each task returns a
1088            // `(OwnedUserId, HashMap)` pair (or rather, an `Option` of one) so that we can
1089            // add the results to the map.
1090            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            // Once all the tasks have completed, process the results.
1098            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    /// Helper for get_user_devices_for_encryption.
1118    ///
1119    /// Waits for any pending `/keys/query` for the given user. If one was
1120    /// pending, reloads the device list and returns `Some(user_id,
1121    /// device_list)`. If no request was pending, returns `None`.
1122    #[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    /// Given a list of changed devices, update any [`InboundGroupSession`]s
1143    /// which were sent from those devices and which do not have complete
1144    /// sender data.
1145    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            // 1. Look for InboundGroupSessions from the device whose sender_data is
1151            //    UnknownDevice. For such sessions, we now have the device, and can update
1152            //    the sender_data accordingly.
1153            //
1154            // In theory, we only need to do this for new devices. In practice, I'm a bit
1155            // worried about races leading us to getting stuck in the
1156            // UnknownDevice state, so we'll paper over that by doing this check
1157            // on device updates too.
1158            self.update_sender_data_for_sessions_for_device(device, SenderDataType::UnknownDevice)
1159                .await?;
1160
1161            // 2. If, and only if, the device is now correctly cross-signed (ie,
1162            //    device.is_cross_signed_by_owner() is true, and we have the master
1163            //    cross-signing key for the owner), look for InboundGroupSessions from the
1164            //    device whose sender_data is DeviceInfo. We can also update the sender_data
1165            //    for these sessions.
1166            //
1167            // In theory, we can skip a couple of steps of the SenderDataFinder algorithm,
1168            // because we're doing the cross-signing check here. In practice,
1169            // it's *way* easier just to use the same logic.
1170            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    /// Given a device, look for [`InboundGroupSession`]s whose sender data is
1181    /// in the given state, and update it.
1182    #[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                // end of the session list
1206                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    /// Update the sender data on the given inbound group session, using the
1219    /// given device data.
1220    #[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    /// Mark all tracked users as dirty.
1247    ///
1248    /// All users *whose device lists we are tracking* are flagged as needing a
1249    /// key query. Users whose devices we are not tracking are ignored.
1250    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
1269/// Log information about what changed after processing a /keys/query response.
1270/// Only does anything if the DEBUG log level is enabled.
1271fn debug_log_keys_query_response(
1272    devices: &DeviceChanges,
1273    identities: &IdentityChanges,
1274    request_id: &TransactionId,
1275) {
1276    #[allow(unknown_lints, clippy::unwrap_or_default)] // false positive
1277    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)] // false positive
1283    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)] // false positive
1289    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    // An updated version of `other_key_query` featuring an additional signature on
1418    // the master key *Note*: The added signature is actually not valid, but a
1419    // valid signature  is not required for our test.
1420    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                        // This is the added signature from alice USK compared to `other_key_query`. Note that actual signature is not valid.
1457                        "@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    /// Mocked response to a /keys/query request.
1483    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    /// If a user is invalidated while a /keys/query request is in flight, that
1867    /// user is not removed from the list of outdated users when the
1868    /// response is received
1869    #[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        // alice should be in the list of key queries
1876        let (reqid, req) = manager.users_for_key_query().await.unwrap().pop_first().unwrap();
1877        assert!(req.device_keys.contains_key(alice));
1878
1879        // another invalidation turns up
1880        {
1881            let cache = manager.store.cache().await.unwrap();
1882            manager.receive_device_changes(&cache, [alice].into_iter()).await.unwrap();
1883        }
1884
1885        // the response from the query arrives
1886        manager.receive_keys_query_response(&reqid, &other_key_query()).await.unwrap();
1887
1888        // alice should *still* be in the list of key queries
1889        let (reqid, req) = manager.users_for_key_query().await.unwrap().pop_first().unwrap();
1890        assert!(req.device_keys.contains_key(alice));
1891
1892        // another key query response
1893        manager.receive_keys_query_response(&reqid, &other_key_query()).await.unwrap();
1894
1895        // finally alice should not be in the list
1896        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        // a failure should stop us querying for the user's keys.
1922        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        // clearing the failure flag should make the user reappear in the query list.
1935        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        // build the request
1949        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        // make up a response and check it is processed
1954        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        // First of all, populate the store with good data
1973        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        // Now provide an invalid update
1983        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                                // Not a valid signature.
1999                                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        // The result should be empty
2012        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        // And the device should not have been updated.
2018        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        // A second `/keys/query` response with the same result shouldn't fire a change
2078        // notification: the identity and device should be unchanged.
2079        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        // dropping the manager (and hence dropping the store) should close the stream
2089        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        // There is a new signature on the msk, should trigger a change
2120        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        // Identity has a change (new signature) but it's the same msk
2135        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        // We should now have an identity for the user but no pin violation
2204        // (pinned master key is the current one)
2205        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        // We receive a new keys update for that user, with a new identity
2211        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        // The previous known identity has been replaced, there should be a pin
2223        // violation
2224        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        // There is a new device signed by the new identity
2230        assert!(second_device.is_cross_signed_by_owner(&identity));
2231
2232        // The first device should not be signed by the new identity
2233        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        // We receive updated keys for that user, with no identity anymore.
2239        // Notice that there is no server API to delete identity, but we want to
2240        // test here that a home server cannot clear the identity and
2241        // subsequently serve a new one which would get automatically approved.
2242        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        // We receive a new keys update for that user, with a new identity
2273        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        // We have a new identity now, so there should be a pin violation
2285        assert!(other_identity.has_pin_violation());
2286
2287        // Resolve the violation by pinning the new identity
2288        other_identity.pin();
2289
2290        assert!(!other_identity.has_pin_violation());
2291    }
2292
2293    // Set up a machine do initial own key query and import cross-signing secret to
2294    // make the current session verified.
2295    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        // ######
2321        // First test: Assert that the latch is properly set on new identities
2322        // ######
2323        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        // For sanity check that own identity is trusted
2330        assert!(own_identity.is_verified());
2331
2332        let bob_identity =
2333            machine.get_identity(DataSet::bob_id(), None).await.unwrap().unwrap().other().unwrap();
2334        // The verified latch should be true
2335        assert!(bob_identity.was_previously_verified());
2336        // And bob is verified
2337        assert!(bob_identity.is_verified());
2338
2339        // ######
2340        // Second test: Assert that the local latch stays on if the identity is rotated
2341        // ######
2342        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        // Bob is not verified anymore
2349        assert!(!bob_identity.is_verified());
2350        // The verified latch should still be true
2351        assert!(bob_identity.was_previously_verified());
2352        // Bob device_2 is self-signed even if there is this verification latch
2353        // violation
2354        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        // there is also a pin violation
2361        assert!(bob_identity.has_pin_violation());
2362        // Fixing the pin violation won't fix the verification latch violation
2363        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        // ######
2377        // Get the Carol identity for the first time
2378        // ######
2379        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        // The identity is not verified
2386        assert!(!carol_identity.is_verified());
2387        // The verified latch is off
2388        assert!(!carol_identity.was_previously_verified());
2389
2390        // Carol is verified, likely from another session. Ensure the latch is updated
2391        // when the key query response is processed
2392        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        // This should have updated the latch
2405        assert!(carol_identity.was_previously_verified());
2406        // It is the same identity, it's just signed now so no pin violation
2407        assert!(!carol_identity.has_pin_violation());
2408    }
2409
2410    // Set up a machine do initial own key query.
2411    // The cross signing secrets are not yet uploaded.
2412    // Then query keys for carol and bob (both signed by own identity)
2413    async fn common_verified_identity_changes_own_trust_change_machine_setup() -> OlmMachine {
2414        use test_json::keys_query_sets::VerificationViolationTestData as DataSet;
2415
2416        // Start on a non-verified session
2417        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        // For sanity check that own identity is not trusted
2424        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        // Get Bob and Carol already signed
2433        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        // Bob is verified by our identity but our own identity is not yet trusted
2456        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        // Carol is verified by our identity but our own identity is not yet trusted
2462        assert!(!carol_identity.was_previously_verified());
2463        assert!(own_identity.is_identity_signed(&carol_identity.other().unwrap()));
2464
2465        // Marking our own identity as trusted should update the existing identities
2466        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        // The latch should be set now
2475        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        // The latch should be set now
2480        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        // Carol is verified by our identity but our own identity is not yet trusted
2494        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        // Carol is verified by our identity but our own identity is not yet trusted
2505        assert!(own_identity.is_identity_signed(&carol_identity));
2506        assert!(!carol_identity.was_previously_verified());
2507
2508        // Marking our own identity as trusted should update the existing identities
2509        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        // The latch should be set now
2525        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        // The latch should be set now
2530        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            // Given that we have lots of sessions in the store, from each of two devices
2551            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            // When we get an update for one device
2573            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            // Then those sessions should be updated
2583            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            // ... and those from the other account should not
2599            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        /// Create an InboundGroupSession sent from the given account
2611        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        // Test that we check the X.509 signature on our identity to see if it
2628        // needs re-signing when it is received from a `/keys/query` response.
2629        let user_id = user_id!("@example1:localhost");
2630        let device_id = device_id!("DEVICEID");
2631
2632        // We create three signers with different validity dates: an "old"
2633        // signer, a "current" signer, and a "new" signer.
2634        let (x509_signer_old, x509_signer_current, x509_signer_new) =
2635            crate::x509::tests::signers_with_different_validity();
2636
2637        // We create an `IdentityManager` that uses the "current" X.509 signer
2638        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        // Make a `/keys/query` response where the master key is signed by the
2661        // given X.509 signer.
2662        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        // We receive a master key signed by the old signer.  In this case, we
2687        // should re-sign the key, since our signer has a newer validity period.
2688        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        // We receive a master key signed by the same signer, so we don't need
2693        // to re-sign.
2694        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        // We receive a master key signed by a newer signer, so we don't need to
2699        // re-sign.
2700        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        // Test that we check if we need to re-sign our master key with X.509
2709        // without having a `/keys/query` response.
2710        let user_id = user_id!("@example1:localhost");
2711        let device_id = device_id!("DEVICEID");
2712
2713        // We create three signers with different validity dates: an "old"
2714        // signer, a "current" signer, and a "new" signer.
2715        let (x509_signer_old, x509_signer_current, x509_signer_new) =
2716            crate::x509::tests::signers_with_different_validity();
2717
2718        // We create a cross-signing identity signed with the current signer.
2719        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        // If we have an identity manager with an old signer, then it won't try
2726        // to re-sign the master key.
2727        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        // If we have an identity manager with the same signer, then it won't try
2736        // to re-sign the master key.
2737        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        // If we have an identity manager with a new signer, then it will
2746        // re-sign the master key.
2747        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}