matrix_sdk_crypto/olm/group_sessions/
sender_data_finder.rs

1// Copyright 2024 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 ruma::UserId;
16use tracing::error;
17use vodozemac::Curve25519PublicKey;
18
19use super::{InboundGroupSession, KnownSenderData, SenderData};
20use crate::{
21    error::MismatchedIdentityKeysError, store::Store, types::events::olm_v1::DecryptedRoomKeyEvent,
22    CryptoStoreError, Device, DeviceData, MegolmError, OlmError, SignatureError,
23};
24
25/// Temporary struct that is used to look up [`SenderData`] based on the
26/// information supplied in
27/// [`crate::types::events::olm_v1::DecryptedRoomKeyEvent`].
28///
29/// # Algorithm
30///
31/// When we receive a to-device message establishing a megolm session (i.e. when
32/// [`crate::machine::OlmMachine::add_room_key`] is called):
33///
34/// ┌───────────────────────────────────────────────────────────────────┐
35/// │ A (start - we have a to-device message containing a room key)     │
36/// └───────────────────────────────────────────────────────────────────┘
37///                                     │
38///   __________________________________▼______________________________
39///  ╱                                                                 ╲
40/// ╱ Does the to-device message contain the device_keys property from  ╲yes
41/// ╲ MSC4147?                                                          ╱ │
42///  ╲_________________________________________________________________╱  │
43///                                     │ no                              │
44///                                     ▼                                 │
45/// ┌───────────────────────────────────────────────────────────────────┐ │
46/// │ B (there are no device keys in the to-device message)             │ │
47/// │                                                                   │ │
48/// │ We need to find the device details.                               │ │
49/// └───────────────────────────────────────────────────────────────────┘ │
50///                                     │                                 │
51///   __________________________________▼______________________________   │
52///  ╱                                                                 ╲  │
53/// ╱ Does the store contain a device whose curve key matches the       ╲ ▼
54/// ╲ sender of the to-device message?                                  ╱yes
55///  ╲_________________________________________________________________╱  │
56///                                     │ no                              │
57///                                     ▼                                 │
58/// ╭───────────────────────────────────────────────────────────────────╮ │
59/// │ C (we don't know the sending device)                              │ │
60/// │                                                                   │ │
61/// │ Give up: we have no sender info for this room key.                │ │
62/// ╰───────────────────────────────────────────────────────────────────╯ │
63///                                     ┌─────────────────────────────────┘
64///                                     ▼
65/// ┌───────────────────────────────────────────────────────────────────┐
66/// │ D (we have the device)                                            │
67/// └───────────────────────────────────────────────────────────────────┘
68///                                     │
69///   __________________________________▼______________________________
70///  ╱                                                                 ╲
71/// ╱ Is the session owned by the device?                               ╲yes
72/// ╲___________________________________________________________________╱ │
73///                                     │ no                              │
74///                                     ▼                                 │
75/// ╭───────────────────────────────────────────────────────────────────╮ │
76/// │ E (the device does not own the session)                           │ │
77/// │                                                                   │ │
78/// │ Give up: something is wrong with the session.                     │ │
79/// ╰───────────────────────────────────────────────────────────────────╯ │
80///                                     ┌─────────────────────────────────┘
81///   __________________________________▼______________________________
82///  ╱                                                                 ╲
83/// ╱ Is the device cross-signed by the sender?                         ╲yes
84/// ╲___________________________________________________________________╱ │
85///                                     │ no                              │
86///                                     ▼                                 │
87/// ┌───────────────────────────────────────────────────────────────────┐ │
88/// │ F (we have device keys, but they are not signed by the sender)    │ │
89/// │                                                                   │ │
90/// │ Store the device with the session, in case we can confirm it      │ │
91/// │ later.                                                            │ │
92/// ╰───────────────────────────────────────────────────────────────────╯ │
93///                                     ┌─────────────────────────────────┘
94///                                     ▼
95/// ┌───────────────────────────────────────────────────────────────────┐
96/// │ G (device is cross-signed by the sender)                          │
97/// └───────────────────────────────────────────────────────────────────┘
98///                                     │
99///   __________________________________▼______________________________
100///  ╱                                                                 ╲
101/// ╱ Does the cross-signing key match that used                        ╲yes
102/// ╲ to sign the device?                                               ╱ │
103///  ╲_________________________________________________________________╱  │
104///                                     │ no                              │
105///                                     ▼                                 │
106/// ╭───────────────────────────────────────────────────────────────────╮ │
107/// │ Store the device with the session, in case we get the             │ │
108/// │ right cross-signing key later.                                    │ │
109/// ╰───────────────────────────────────────────────────────────────────╯ │
110///                                     ┌─────────────────────────────────┘
111///                                     ▼
112/// ┌───────────────────────────────────────────────────────────────────┐
113/// │ H (cross-signing key matches that used to sign the device!)       │
114/// │                                                                   │
115/// │ Look up the user_id and master_key for the user sending the       │
116/// │ to-device message.                                                │
117/// │                                                                   │
118/// │ Decide the master_key trust level based on whether we have        │
119/// │ verified this user.                                               │
120/// │                                                                   │
121/// │ Store this information with the session.                          │
122/// ╰───────────────────────────────────────────────────────────────────╯
123///
124/// Note: the sender data may become out-of-date if we later verify the user. We
125/// have no plans to update it if so.
126pub(crate) struct SenderDataFinder<'a> {
127    store: &'a Store,
128    session: &'a InboundGroupSession,
129}
130
131impl<'a> SenderDataFinder<'a> {
132    /// Find the device associated with the to-device message used to
133    /// create the InboundGroupSession we are about to create, and decide
134    /// whether we trust the sender.
135    pub(crate) async fn find_using_event(
136        store: &'a Store,
137        sender_curve_key: Curve25519PublicKey,
138        room_key_event: &'a DecryptedRoomKeyEvent,
139        session: &'a InboundGroupSession,
140    ) -> Result<SenderData, SessionDeviceKeysCheckError> {
141        let finder = Self { store, session };
142        finder.have_event(sender_curve_key, room_key_event).await
143    }
144
145    /// Use the supplied device data to decide whether we trust the sender.
146    pub(crate) async fn find_using_device_data(
147        store: &'a Store,
148        device_data: DeviceData,
149        session: &'a InboundGroupSession,
150    ) -> Result<SenderData, SessionDeviceCheckError> {
151        let finder = Self { store, session };
152        finder.have_device_data(device_data).await
153    }
154
155    /// Find the device using the curve key provided, and decide whether we
156    /// trust the sender.
157    pub(crate) async fn find_using_curve_key(
158        store: &'a Store,
159        sender_curve_key: Curve25519PublicKey,
160        sender_user_id: &'a UserId,
161        session: &'a InboundGroupSession,
162    ) -> Result<SenderData, SessionDeviceCheckError> {
163        let finder = Self { store, session };
164        finder.search_for_device(sender_curve_key, sender_user_id).await
165    }
166
167    /// Step A (start - we have a to-device message containing a room key)
168    async fn have_event(
169        &self,
170        sender_curve_key: Curve25519PublicKey,
171        room_key_event: &'a DecryptedRoomKeyEvent,
172    ) -> Result<SenderData, SessionDeviceKeysCheckError> {
173        // Does the to-device message contain the device_keys property from MSC4147?
174        if let Some(sender_device_keys) = &room_key_event.sender_device_keys {
175            // Yes: use the device keys to continue.
176
177            // Validate the signature of the DeviceKeys supplied.
178            let sender_device_data = DeviceData::try_from(sender_device_keys)?;
179            Ok(self.have_device_data(sender_device_data).await?)
180        } else {
181            // No: look for the device in the store
182            Ok(self.search_for_device(sender_curve_key, &room_key_event.sender).await?)
183        }
184    }
185
186    /// Step B (there are no device keys in the to-device message)
187    async fn search_for_device(
188        &self,
189        sender_curve_key: Curve25519PublicKey,
190        sender_user_id: &UserId,
191    ) -> Result<SenderData, SessionDeviceCheckError> {
192        // Does the locally-cached (in the store) devices list contain a device with the
193        // curve key of the sender of the to-device message?
194        if let Some(sender_device) =
195            self.store.get_device_from_curve_key(sender_user_id, sender_curve_key).await?
196        {
197            // Yes: use the device to continue
198            self.have_device(sender_device)
199        } else {
200            // Step C (we don't know the sending device)
201            //
202            // We have no device data for this session so we can't continue in the "fast
203            // lane" (blocking sync).
204            let sender_data = SenderData::UnknownDevice {
205                // This is not a legacy session since we did attempt to look
206                // up its sender data at the time of reception.
207                legacy_session: false,
208                owner_check_failed: false,
209            };
210            Ok(sender_data)
211        }
212    }
213
214    async fn have_device_data(
215        &self,
216        sender_device_data: DeviceData,
217    ) -> Result<SenderData, SessionDeviceCheckError> {
218        let sender_device = self.store.wrap_device_data(sender_device_data).await?;
219        self.have_device(sender_device)
220    }
221
222    /// Step D (we have a device)
223    ///
224    /// Returns Err if the device does not own the session.
225    fn have_device(&self, sender_device: Device) -> Result<SenderData, SessionDeviceCheckError> {
226        // Is the session owned by the device?
227        let device_is_owner = sender_device.is_owner_of_session(self.session)?;
228
229        // Is the device cross-signed?
230        // Does the cross-signing key match that used to sign the device?
231        // And is the signature in the device valid?
232        let cross_signed = sender_device.is_cross_signed_by_owner();
233
234        Ok(match (device_is_owner, cross_signed) {
235            (true, true) => self.device_is_cross_signed_by_sender(sender_device),
236            (true, false) => {
237                // F (we have device keys, but they are not signed by the sender)
238                SenderData::device_info(sender_device.as_device_keys().clone())
239            }
240            (false, _) => {
241                // Step E (the device does not own the session)
242                // Give up: something is wrong with the session.
243                SenderData::UnknownDevice { legacy_session: false, owner_check_failed: true }
244            }
245        })
246    }
247
248    /// Step G (device is cross-signed by the sender)
249    fn device_is_cross_signed_by_sender(&self, sender_device: Device) -> SenderData {
250        // H (cross-signing key matches that used to sign the device!)
251        let user_id = sender_device.user_id().to_owned();
252        let device_id = Some(sender_device.device_id().to_owned());
253
254        let master_key = sender_device
255            .device_owner_identity
256            .as_ref()
257            .and_then(|i| i.master_key().get_first_key());
258
259        if let Some(master_key) = master_key {
260            // We have user_id and master_key for the user sending the to-device message.
261            let master_key = Box::new(master_key);
262            let known_sender_data = KnownSenderData { user_id, device_id, master_key };
263            if sender_device.is_cross_signing_trusted() {
264                SenderData::SenderVerified(known_sender_data)
265            } else if sender_device
266                .device_owner_identity
267                .expect("User with master key must have identity")
268                .was_previously_verified()
269            {
270                SenderData::VerificationViolation(known_sender_data)
271            } else {
272                SenderData::SenderUnverified(known_sender_data)
273            }
274        } else {
275            // Surprisingly, there was no key in the MasterPubkey. We did not expect this:
276            // treat it as if the device was not signed by this master key.
277            //
278            error!("MasterPubkey for user {user_id} does not contain any keys!",);
279            SenderData::device_info(sender_device.as_device_keys().clone())
280        }
281    }
282}
283
284#[derive(Debug)]
285pub(crate) enum SessionDeviceCheckError {
286    CryptoStoreError(CryptoStoreError),
287    MismatchedIdentityKeys(MismatchedIdentityKeysError),
288}
289
290impl From<CryptoStoreError> for SessionDeviceCheckError {
291    fn from(e: CryptoStoreError) -> Self {
292        Self::CryptoStoreError(e)
293    }
294}
295
296impl From<MismatchedIdentityKeysError> for SessionDeviceCheckError {
297    fn from(e: MismatchedIdentityKeysError) -> Self {
298        Self::MismatchedIdentityKeys(e)
299    }
300}
301
302impl From<SessionDeviceCheckError> for OlmError {
303    fn from(e: SessionDeviceCheckError) -> Self {
304        match e {
305            SessionDeviceCheckError::CryptoStoreError(e) => e.into(),
306            SessionDeviceCheckError::MismatchedIdentityKeys(e) => {
307                OlmError::SessionCreation(e.into())
308            }
309        }
310    }
311}
312
313impl From<SessionDeviceCheckError> for MegolmError {
314    fn from(e: SessionDeviceCheckError) -> Self {
315        match e {
316            SessionDeviceCheckError::CryptoStoreError(e) => e.into(),
317            SessionDeviceCheckError::MismatchedIdentityKeys(e) => e.into(),
318        }
319    }
320}
321
322#[derive(Debug)]
323pub(crate) enum SessionDeviceKeysCheckError {
324    CryptoStoreError(CryptoStoreError),
325    MismatchedIdentityKeys(MismatchedIdentityKeysError),
326    SignatureError(SignatureError),
327}
328
329impl From<CryptoStoreError> for SessionDeviceKeysCheckError {
330    fn from(e: CryptoStoreError) -> Self {
331        Self::CryptoStoreError(e)
332    }
333}
334
335impl From<MismatchedIdentityKeysError> for SessionDeviceKeysCheckError {
336    fn from(e: MismatchedIdentityKeysError) -> Self {
337        Self::MismatchedIdentityKeys(e)
338    }
339}
340
341impl From<SignatureError> for SessionDeviceKeysCheckError {
342    fn from(e: SignatureError) -> Self {
343        Self::SignatureError(e)
344    }
345}
346
347impl From<SessionDeviceCheckError> for SessionDeviceKeysCheckError {
348    fn from(e: SessionDeviceCheckError) -> Self {
349        match e {
350            SessionDeviceCheckError::CryptoStoreError(e) => Self::CryptoStoreError(e),
351            SessionDeviceCheckError::MismatchedIdentityKeys(e) => Self::MismatchedIdentityKeys(e),
352        }
353    }
354}
355
356impl From<SessionDeviceKeysCheckError> for OlmError {
357    fn from(e: SessionDeviceKeysCheckError) -> Self {
358        match e {
359            SessionDeviceKeysCheckError::CryptoStoreError(e) => e.into(),
360            SessionDeviceKeysCheckError::MismatchedIdentityKeys(e) => {
361                OlmError::SessionCreation(e.into())
362            }
363            SessionDeviceKeysCheckError::SignatureError(e) => OlmError::SessionCreation(e.into()),
364        }
365    }
366}
367
368#[cfg(test)]
369mod tests {
370    use std::{ops::Deref as _, sync::Arc};
371
372    use assert_matches2::assert_let;
373    use matrix_sdk_test::async_test;
374    use ruma::{device_id, room_id, user_id, DeviceId, OwnedUserId, RoomId, UserId};
375    use tokio::sync::Mutex;
376    use vodozemac::{megolm::SessionKey, Curve25519PublicKey, Ed25519PublicKey};
377
378    use super::SenderDataFinder;
379    use crate::{
380        error::MismatchedIdentityKeysError,
381        olm::{
382            group_sessions::sender_data_finder::SessionDeviceKeysCheckError, InboundGroupSession,
383            KnownSenderData, PrivateCrossSigningIdentity, SenderData,
384        },
385        store::{Changes, CryptoStoreWrapper, MemoryStore, Store},
386        types::{
387            events::{
388                olm_v1::DecryptedRoomKeyEvent,
389                room_key::{MegolmV1AesSha2Content, RoomKeyContent},
390            },
391            EventEncryptionAlgorithm,
392        },
393        verification::VerificationMachine,
394        Account, Device, DeviceData, OtherUserIdentityData, OwnUserIdentityData, UserIdentityData,
395    };
396
397    impl<'a> SenderDataFinder<'a> {
398        fn new(store: &'a Store, session: &'a InboundGroupSession) -> Self {
399            Self { store, session }
400        }
401    }
402
403    #[async_test]
404    async fn test_providing_no_device_data_returns_sender_data_with_no_device_info() {
405        // Given that the device is not in the store and the initial event has no device
406        // info
407        let setup = TestSetup::new(TestOptions::new()).await;
408        let finder = SenderDataFinder::new(&setup.store, &setup.session);
409
410        // When we try to find sender data
411        let sender_data = finder
412            .have_event(setup.sender_device_curve_key(), &setup.room_key_event)
413            .await
414            .unwrap();
415
416        // Then we get back no useful information at all
417        assert_let!(SenderData::UnknownDevice { legacy_session, owner_check_failed } = sender_data);
418
419        assert!(!legacy_session);
420        assert!(!owner_check_failed);
421    }
422
423    #[async_test]
424    async fn test_if_the_todevice_event_contains_device_info_it_is_captured() {
425        // Given that the signed device keys are in the event
426        let setup =
427            TestSetup::new(TestOptions::new().device_is_signed().event_contains_device_keys())
428                .await;
429        let finder = SenderDataFinder::new(&setup.store, &setup.session);
430
431        // When we try to find sender data
432        let sender_data = finder
433            .have_event(setup.sender_device_curve_key(), &setup.room_key_event)
434            .await
435            .unwrap();
436
437        // Then we get back the device keys that were in the event
438        assert_let!(SenderData::DeviceInfo { device_keys, legacy_session } = sender_data);
439        assert_eq!(&device_keys, setup.sender_device.as_device_keys());
440        assert!(!legacy_session);
441    }
442
443    #[async_test]
444    async fn test_picks_up_device_info_from_the_store_if_missing_from_the_todevice_event() {
445        // Given that the device keys are not in the event but the device is in the
446        // store
447        let setup =
448            TestSetup::new(TestOptions::new().store_contains_device().device_is_signed()).await;
449        let finder = SenderDataFinder::new(&setup.store, &setup.session);
450
451        // When we try to find sender data
452        let sender_data = finder
453            .have_event(setup.sender_device_curve_key(), &setup.room_key_event)
454            .await
455            .unwrap();
456
457        // Then we get back the device keys that were in the store
458        assert_let!(SenderData::DeviceInfo { device_keys, legacy_session } = sender_data);
459        assert_eq!(&device_keys, setup.sender_device.as_device_keys());
460        assert!(!legacy_session);
461    }
462
463    #[async_test]
464    async fn test_adds_device_info_even_if_it_is_not_signed() {
465        // Given that the the device is in the store
466        // But it is not signed
467        let setup = TestSetup::new(TestOptions::new().store_contains_device()).await;
468        let finder = SenderDataFinder::new(&setup.store, &setup.session);
469
470        // When we try to find sender data
471        let sender_data = finder
472            .have_event(setup.sender_device_curve_key(), &setup.room_key_event)
473            .await
474            .unwrap();
475
476        // Then we store the device info even though it is useless, in case we want to
477        // check it matches up later.
478        assert_let!(SenderData::DeviceInfo { device_keys, legacy_session } = sender_data);
479        assert_eq!(&device_keys, setup.sender_device.as_device_keys());
480        assert!(!legacy_session);
481    }
482
483    #[async_test]
484    async fn test_adds_sender_data_for_own_verified_device_and_user_using_device_from_store() {
485        // Given the device is in the store, and we sent the event
486        let setup = TestSetup::new(
487            TestOptions::new()
488                .store_contains_device()
489                .store_contains_sender_identity()
490                .device_is_signed()
491                .sender_is_ourself(),
492        )
493        .await;
494        let finder = SenderDataFinder::new(&setup.store, &setup.session);
495
496        // When we try to find sender data
497        let sender_data = finder
498            .have_event(setup.sender_device_curve_key(), &setup.room_key_event)
499            .await
500            .unwrap();
501
502        // Then we get back the information about the sender
503        assert_let!(
504            SenderData::SenderUnverified(KnownSenderData { user_id, device_id, master_key }) =
505                sender_data
506        );
507        assert_eq!(user_id, setup.sender.user_id);
508        assert_eq!(device_id.unwrap(), setup.sender_device.device_id());
509        assert_eq!(*master_key, setup.sender_master_key());
510    }
511
512    #[async_test]
513    async fn test_adds_sender_data_for_other_verified_device_and_user_using_device_from_store() {
514        // Given the device is in the store, and someone else sent the event
515        let setup = TestSetup::new(
516            TestOptions::new()
517                .store_contains_device()
518                .store_contains_sender_identity()
519                .device_is_signed(),
520        )
521        .await;
522        let finder = SenderDataFinder::new(&setup.store, &setup.session);
523
524        // When we try to find sender data
525        let sender_data = finder
526            .have_event(setup.sender_device_curve_key(), &setup.room_key_event)
527            .await
528            .unwrap();
529
530        // Then we get back the information about the sender
531        assert_let!(
532            SenderData::SenderUnverified(KnownSenderData { user_id, device_id, master_key }) =
533                sender_data
534        );
535        assert_eq!(user_id, setup.sender.user_id);
536        assert_eq!(device_id.unwrap(), setup.sender_device.device_id());
537        assert_eq!(*master_key, setup.sender_master_key());
538    }
539
540    #[async_test]
541    async fn test_adds_sender_data_for_own_device_and_user_using_device_from_event() {
542        // Given the device keys are in the event, and we sent the event
543        let setup = TestSetup::new(
544            TestOptions::new()
545                .store_contains_sender_identity()
546                .device_is_signed()
547                .event_contains_device_keys()
548                .sender_is_ourself(),
549        )
550        .await;
551        let finder = SenderDataFinder::new(&setup.store, &setup.session);
552
553        // When we try to find sender data
554        let sender_data = finder
555            .have_event(setup.sender_device_curve_key(), &setup.room_key_event)
556            .await
557            .unwrap();
558
559        // Then we get back the information about the sender
560        assert_let!(
561            SenderData::SenderUnverified(KnownSenderData { user_id, device_id, master_key }) =
562                sender_data
563        );
564        assert_eq!(user_id, setup.sender.user_id);
565        assert_eq!(device_id.unwrap(), setup.sender_device.device_id());
566        assert_eq!(*master_key, setup.sender_master_key());
567    }
568
569    #[async_test]
570    async fn test_adds_sender_data_for_other_verified_device_and_user_using_device_from_event() {
571        // Given the device keys are in the event, and someone else sent the event
572        let setup = TestSetup::new(
573            TestOptions::new()
574                .store_contains_sender_identity()
575                .device_is_signed()
576                .event_contains_device_keys(),
577        )
578        .await;
579        let finder = SenderDataFinder::new(&setup.store, &setup.session);
580
581        // When we try to find sender data
582        let sender_data = finder
583            .have_event(setup.sender_device_curve_key(), &setup.room_key_event)
584            .await
585            .unwrap();
586
587        // Then we get back the information about the sender
588        assert_let!(
589            SenderData::SenderUnverified(KnownSenderData { user_id, device_id, master_key }) =
590                sender_data
591        );
592        assert_eq!(user_id, setup.sender.user_id);
593        assert_eq!(device_id.unwrap(), setup.sender_device.device_id());
594        assert_eq!(*master_key, setup.sender_master_key());
595    }
596
597    #[async_test]
598    async fn test_if_session_signing_does_not_match_device_return_an_error() {
599        // Given everything is the same as the above test
600        // except the session is not owned by the device
601        let setup = TestSetup::new(
602            TestOptions::new()
603                .store_contains_sender_identity()
604                .device_is_signed()
605                .event_contains_device_keys()
606                .session_signing_key_differs_from_device(),
607        )
608        .await;
609        let finder = SenderDataFinder::new(&setup.store, &setup.session);
610
611        // When we try to find sender data
612        assert_let!(
613            Err(e) =
614                finder.have_event(setup.sender_device_curve_key(), &setup.room_key_event).await
615        );
616
617        assert_let!(SessionDeviceKeysCheckError::MismatchedIdentityKeys(e) = e);
618
619        let key_ed25519 =
620            Box::new(setup.session.signing_keys().iter().next().unwrap().1.ed25519().unwrap());
621        let key_curve25519 = Box::new(setup.session.sender_key());
622
623        let device_ed25519 = setup.sender_device.ed25519_key().map(Box::new);
624        let device_curve25519 = Some(Box::new(setup.sender_device_curve_key()));
625
626        assert_eq!(
627            e,
628            MismatchedIdentityKeysError {
629                key_ed25519,
630                device_ed25519,
631                key_curve25519,
632                device_curve25519
633            }
634        );
635    }
636
637    #[async_test]
638    async fn test_does_not_add_sender_data_for_a_device_missing_keys() {
639        // Given everything is the same as the successful test
640        // except the device does not own the session because
641        // it is imported.
642        let setup = TestSetup::new(
643            TestOptions::new()
644                .store_contains_sender_identity()
645                .session_is_imported()
646                .event_contains_device_keys(),
647        )
648        .await;
649        let finder = SenderDataFinder::new(&setup.store, &setup.session);
650
651        // When we try to find sender data
652        let sender_data = finder
653            .have_event(setup.sender_device_curve_key(), &setup.room_key_event)
654            .await
655            .unwrap();
656
657        // Then we fail to find useful sender data
658        assert_let!(SenderData::UnknownDevice { legacy_session, owner_check_failed } = sender_data);
659        assert!(!legacy_session);
660
661        // And report that the owner_check_failed
662        assert!(owner_check_failed);
663    }
664
665    #[async_test]
666    async fn test_notes_master_key_is_verified_for_own_identity() {
667        // Given we can find the device, and we sent the event, and we are verified
668        let setup = TestSetup::new(
669            TestOptions::new()
670                .store_contains_device()
671                .store_contains_sender_identity()
672                .device_is_signed()
673                .event_contains_device_keys()
674                .sender_is_ourself()
675                .sender_is_verified(),
676        )
677        .await;
678        let finder = SenderDataFinder::new(&setup.store, &setup.session);
679
680        // When we try to find sender data
681        let sender_data = finder
682            .have_event(setup.sender_device_curve_key(), &setup.room_key_event)
683            .await
684            .unwrap();
685
686        // Then we get back the information about the sender
687        assert_let!(
688            SenderData::SenderVerified(KnownSenderData { user_id, device_id, master_key }) =
689                sender_data
690        );
691        assert_eq!(user_id, setup.sender.user_id);
692        assert_eq!(device_id.unwrap(), setup.sender_device.device_id());
693        assert_eq!(*master_key, setup.sender_master_key());
694    }
695
696    #[async_test]
697    async fn test_notes_master_key_is_verified_for_other_identity() {
698        // Given we can find the device, and someone else sent the event
699        // And the sender is verified
700        let setup = TestSetup::new(
701            TestOptions::new()
702                .store_contains_device()
703                .store_contains_sender_identity()
704                .device_is_signed()
705                .event_contains_device_keys()
706                .sender_is_verified(),
707        )
708        .await;
709        let finder = SenderDataFinder::new(&setup.store, &setup.session);
710
711        // When we try to find sender data
712        let sender_data = finder
713            .have_event(setup.sender_device_curve_key(), &setup.room_key_event)
714            .await
715            .unwrap();
716
717        // Then we get back the information about the sender
718        assert_let!(
719            SenderData::SenderVerified(KnownSenderData { user_id, device_id, master_key }) =
720                sender_data
721        );
722        assert_eq!(user_id, setup.sender.user_id);
723        assert_eq!(device_id.unwrap(), setup.sender_device.device_id());
724        assert_eq!(*master_key, setup.sender_master_key());
725    }
726
727    #[async_test]
728    async fn test_can_add_user_sender_data_based_on_a_provided_device() {
729        // Given the device is not in the store or the event
730        let setup =
731            TestSetup::new(TestOptions::new().store_contains_sender_identity().device_is_signed())
732                .await;
733        let finder = SenderDataFinder::new(&setup.store, &setup.session);
734
735        // When we supply the device keys directly while asking for the sender data
736        let sender_data = finder.have_device_data(setup.sender_device.inner.clone()).await.unwrap();
737
738        // Then it is found using the device we supplied
739        assert_let!(
740            SenderData::SenderUnverified(KnownSenderData { user_id, device_id, master_key }) =
741                sender_data
742        );
743        assert_eq!(user_id, setup.sender.user_id);
744        assert_eq!(device_id.unwrap(), setup.sender_device.device_id());
745        assert_eq!(*master_key, setup.sender_master_key());
746    }
747
748    struct TestOptions {
749        store_contains_device: bool,
750        store_contains_sender_identity: bool,
751        device_is_signed: bool,
752        event_contains_device_keys: bool,
753        sender_is_ourself: bool,
754        sender_is_verified: bool,
755        session_signing_key_differs_from_device: bool,
756        session_is_imported: bool,
757    }
758
759    impl TestOptions {
760        fn new() -> Self {
761            Self {
762                store_contains_device: false,
763                store_contains_sender_identity: false,
764                device_is_signed: false,
765                event_contains_device_keys: false,
766                sender_is_ourself: false,
767                sender_is_verified: false,
768                session_signing_key_differs_from_device: false,
769                session_is_imported: false,
770            }
771        }
772
773        fn store_contains_device(mut self) -> Self {
774            self.store_contains_device = true;
775            self
776        }
777
778        fn store_contains_sender_identity(mut self) -> Self {
779            self.store_contains_sender_identity = true;
780            self
781        }
782
783        fn device_is_signed(mut self) -> Self {
784            self.device_is_signed = true;
785            self
786        }
787
788        fn event_contains_device_keys(mut self) -> Self {
789            self.event_contains_device_keys = true;
790            self
791        }
792
793        fn sender_is_ourself(mut self) -> Self {
794            self.sender_is_ourself = true;
795            self
796        }
797
798        fn sender_is_verified(mut self) -> Self {
799            self.sender_is_verified = true;
800            self
801        }
802
803        fn session_signing_key_differs_from_device(mut self) -> Self {
804            self.session_signing_key_differs_from_device = true;
805            self
806        }
807
808        fn session_is_imported(mut self) -> Self {
809            self.session_is_imported = true;
810            self
811        }
812    }
813
814    struct TestSetup {
815        sender: TestUser,
816        sender_device: Device,
817        store: Store,
818        room_key_event: DecryptedRoomKeyEvent,
819        session: InboundGroupSession,
820    }
821
822    impl TestSetup {
823        async fn new(options: TestOptions) -> Self {
824            let me = TestUser::own().await;
825            let sender = TestUser::other(&me, &options).await;
826
827            let sender_device = if options.device_is_signed {
828                create_signed_device(&sender.account, &*sender.private_identity.lock().await).await
829            } else {
830                create_unsigned_device(&sender.account)
831            };
832
833            let store = create_store(&me);
834
835            save_to_store(&store, &me, &sender, &sender_device, &options).await;
836
837            let room_id = room_id!("!r:s.co");
838            let session_key = create_session_key();
839
840            let room_key_event = create_room_key_event(
841                &sender.user_id,
842                &me.user_id,
843                &sender_device,
844                room_id,
845                &session_key,
846                &options,
847            );
848
849            let signing_key = if options.session_signing_key_differs_from_device {
850                Ed25519PublicKey::from_base64("2/5LWJMow5zhJqakV88SIc7q/1pa8fmkfgAzx72w9G4")
851                    .unwrap()
852            } else {
853                sender_device.inner.ed25519_key().unwrap()
854            };
855
856            let mut session = InboundGroupSession::new(
857                sender_device.inner.curve25519_key().unwrap(),
858                signing_key,
859                room_id,
860                &session_key,
861                SenderData::unknown(),
862                EventEncryptionAlgorithm::MegolmV1AesSha2,
863                None,
864            )
865            .unwrap();
866            if options.session_is_imported {
867                session.mark_as_imported();
868            }
869
870            Self { sender, sender_device, store, room_key_event, session }
871        }
872
873        fn sender_device_curve_key(&self) -> Curve25519PublicKey {
874            self.sender_device.curve25519_key().unwrap()
875        }
876
877        fn sender_master_key(&self) -> Ed25519PublicKey {
878            self.sender.user_identity.master_key().get_first_key().unwrap()
879        }
880    }
881
882    fn create_store(me: &TestUser) -> Store {
883        let store_wrapper = Arc::new(CryptoStoreWrapper::new(
884            &me.user_id,
885            me.account.device_id(),
886            MemoryStore::new(),
887        ));
888
889        let verification_machine = VerificationMachine::new(
890            me.account.deref().clone(),
891            Arc::clone(&me.private_identity),
892            Arc::clone(&store_wrapper),
893        );
894
895        Store::new(
896            me.account.static_data.clone(),
897            Arc::clone(&me.private_identity),
898            store_wrapper,
899            verification_machine,
900        )
901    }
902
903    async fn save_to_store(
904        store: &Store,
905        me: &TestUser,
906        sender: &TestUser,
907        sender_device: &Device,
908        options: &TestOptions,
909    ) {
910        let mut changes = Changes::default();
911
912        // If the device should exist in the store, add it
913        if options.store_contains_device {
914            changes.devices.new.push(sender_device.inner.clone())
915        }
916
917        // Add the sender identity to the store
918        if options.store_contains_sender_identity {
919            changes.identities.new.push(sender.user_identity.clone());
920        }
921
922        // If it's different from the sender, add our identity too
923        if !options.sender_is_ourself {
924            changes.identities.new.push(me.user_identity.clone());
925        }
926
927        store.save_changes(changes).await.unwrap();
928    }
929
930    struct TestUser {
931        user_id: OwnedUserId,
932        account: Account,
933        private_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
934        user_identity: UserIdentityData,
935    }
936
937    impl TestUser {
938        async fn new(
939            user_id: &UserId,
940            device_id: &DeviceId,
941            is_me: bool,
942            is_verified: bool,
943            signer: Option<&TestUser>,
944        ) -> Self {
945            let account = Account::with_device_id(user_id, device_id);
946            let user_id = user_id.to_owned();
947            let private_identity = Arc::new(Mutex::new(create_private_identity(&account).await));
948
949            let user_identity =
950                create_user_identity(&*private_identity.lock().await, is_me, is_verified, signer)
951                    .await;
952
953            Self { user_id, account, private_identity, user_identity }
954        }
955
956        async fn own() -> Self {
957            Self::new(user_id!("@myself:s.co"), device_id!("OWNDEVICEID"), true, true, None).await
958        }
959
960        async fn other(me: &TestUser, options: &TestOptions) -> Self {
961            let user_id =
962                if options.sender_is_ourself { &me.user_id } else { user_id!("@other:s.co") };
963
964            Self::new(
965                user_id,
966                device_id!("SENDERDEVICEID"),
967                options.sender_is_ourself,
968                options.sender_is_verified,
969                Some(me),
970            )
971            .await
972        }
973    }
974
975    async fn create_user_identity(
976        private_identity: &PrivateCrossSigningIdentity,
977        is_me: bool,
978        is_verified: bool,
979        signer: Option<&TestUser>,
980    ) -> UserIdentityData {
981        if is_me {
982            let own_user_identity = OwnUserIdentityData::from_private(private_identity).await;
983
984            if is_verified {
985                own_user_identity.mark_as_verified();
986            }
987
988            UserIdentityData::Own(own_user_identity)
989        } else {
990            let mut other_user_identity =
991                OtherUserIdentityData::from_private(private_identity).await;
992
993            if is_verified {
994                sign_other_identity(signer, &mut other_user_identity).await;
995            }
996
997            UserIdentityData::Other(other_user_identity)
998        }
999    }
1000
1001    async fn sign_other_identity(
1002        signer: Option<&TestUser>,
1003        other_user_identity: &mut OtherUserIdentityData,
1004    ) {
1005        if let Some(signer) = signer {
1006            let signer_private_identity = signer.private_identity.lock().await;
1007
1008            let user_signing = signer_private_identity.user_signing_key.lock().await;
1009
1010            let user_signing = user_signing.as_ref().unwrap();
1011            let master = user_signing.sign_user(&*other_user_identity).unwrap();
1012            other_user_identity.master_key = Arc::new(master.try_into().unwrap());
1013
1014            user_signing.public_key().verify_master_key(other_user_identity.master_key()).unwrap();
1015        } else {
1016            panic!("You must provide a `signer` if you want an Other to be verified!");
1017        }
1018    }
1019
1020    async fn create_private_identity(account: &Account) -> PrivateCrossSigningIdentity {
1021        PrivateCrossSigningIdentity::with_account(account).await.0
1022    }
1023
1024    async fn create_signed_device(
1025        account: &Account,
1026        private_identity: &PrivateCrossSigningIdentity,
1027    ) -> Device {
1028        let mut read_only_device = DeviceData::from_account(account);
1029
1030        let self_signing = private_identity.self_signing_key.lock().await;
1031        let self_signing = self_signing.as_ref().unwrap();
1032
1033        let mut device_keys = read_only_device.as_device_keys().to_owned();
1034        self_signing.sign_device(&mut device_keys).unwrap();
1035        read_only_device.update_device(&device_keys).unwrap();
1036
1037        wrap_device(account, read_only_device)
1038    }
1039
1040    fn create_unsigned_device(account: &Account) -> Device {
1041        wrap_device(account, DeviceData::from_account(account))
1042    }
1043
1044    fn wrap_device(account: &Account, read_only_device: DeviceData) -> Device {
1045        Device {
1046            inner: read_only_device,
1047            verification_machine: VerificationMachine::new(
1048                account.deref().clone(),
1049                Arc::new(Mutex::new(PrivateCrossSigningIdentity::new(
1050                    account.user_id().to_owned(),
1051                ))),
1052                Arc::new(CryptoStoreWrapper::new(
1053                    account.user_id(),
1054                    account.device_id(),
1055                    MemoryStore::new(),
1056                )),
1057            ),
1058            own_identity: None,
1059            device_owner_identity: None,
1060        }
1061    }
1062
1063    fn create_room_key_event(
1064        sender: &UserId,
1065        receiver: &UserId,
1066        sender_device: &Device,
1067        room_id: &RoomId,
1068        session_key: &SessionKey,
1069        options: &TestOptions,
1070    ) -> DecryptedRoomKeyEvent {
1071        let device = if options.event_contains_device_keys {
1072            Some(sender_device.as_device_keys().clone())
1073        } else {
1074            None
1075        };
1076
1077        DecryptedRoomKeyEvent::new(
1078            sender,
1079            receiver,
1080            Ed25519PublicKey::from_base64("loz5i40dP+azDtWvsD0L/xpnCjNkmrcvtXVXzCHX8Vw").unwrap(),
1081            device,
1082            RoomKeyContent::MegolmV1AesSha2(Box::new(MegolmV1AesSha2Content::new(
1083                room_id.to_owned(),
1084                "mysession".to_owned(),
1085                clone_session_key(session_key),
1086            ))),
1087        )
1088    }
1089
1090    fn create_session_key() -> SessionKey {
1091        SessionKey::from_base64(
1092            "\
1093            AgAAAADBy9+YIYTIqBjFT67nyi31gIOypZQl8day2hkhRDCZaHoG+cZh4tZLQIAZimJail0\
1094            0zq4DVJVljO6cZ2t8kIto/QVk+7p20Fcf2nvqZyL2ZCda2Ei7VsqWZHTM/gqa2IU9+ktkwz\
1095            +KFhENnHvDhG9f+hjsAPZd5mTTpdO+tVcqtdWhX4dymaJ/2UpAAjuPXQW+nXhQWQhXgXOUa\
1096            JCYurJtvbCbqZGeDMmVIoqukBs2KugNJ6j5WlTPoeFnMl6Guy9uH2iWWxGg8ZgT2xspqVl5\
1097            CwujjC+m7Dh1toVkvu+bAw\
1098            ",
1099        )
1100        .unwrap()
1101    }
1102
1103    fn clone_session_key(session_key: &SessionKey) -> SessionKey {
1104        SessionKey::from_base64(&session_key.to_base64()).unwrap()
1105    }
1106}