Skip to main content

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