Skip to main content

matrix_sdk_crypto/olm/group_sessions/
sender_data.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 std::{cmp::Ordering, fmt};
16
17use ruma::{DeviceId, OwnedDeviceId, OwnedUserId, UserId};
18use serde::{Deserialize, Deserializer, Serialize, de, de::Visitor};
19use tracing::error;
20use vodozemac::Ed25519PublicKey;
21
22use crate::{
23    Device,
24    types::{DeviceKeys, serialize_ed25519_key},
25};
26
27/// Information about the sender of a megolm session where we know the
28/// cross-signing identity of the sender.
29#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
30pub struct KnownSenderData {
31    /// The user ID of the user who established this session.
32    pub user_id: OwnedUserId,
33
34    /// The device ID of the device that send the session. This is an `Option`
35    /// for backwards compatibility, but we should always populate it on
36    /// creation.
37    pub device_id: Option<OwnedDeviceId>,
38
39    /// The cross-signing key of the user who established this session.
40    #[serde(
41        serialize_with = "serialize_ed25519_key",
42        deserialize_with = "deserialize_sender_msk_base64_or_array"
43    )]
44    pub master_key: Box<Ed25519PublicKey>,
45}
46
47/// In an initial version the master key was serialized as an array of number,
48/// it is now exported in base64. This code adds backward compatibility.
49pub(crate) fn deserialize_sender_msk_base64_or_array<'de, D>(
50    de: D,
51) -> Result<Box<Ed25519PublicKey>, D::Error>
52where
53    D: Deserializer<'de>,
54{
55    struct KeyVisitor;
56
57    impl<'de> Visitor<'de> for KeyVisitor {
58        type Value = Box<Ed25519PublicKey>;
59
60        fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
61            write!(formatter, "a base64 string or an array of 32 bytes")
62        }
63
64        fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
65        where
66            E: de::Error,
67        {
68            let decoded = Ed25519PublicKey::from_base64(v)
69                .map_err(|_| de::Error::custom("Base64 decoding error"))?;
70            Ok(Box::new(decoded))
71        }
72
73        fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
74        where
75            A: de::SeqAccess<'de>,
76        {
77            let mut buf = [0u8; Ed25519PublicKey::LENGTH];
78
79            for (i, item) in buf.iter_mut().enumerate() {
80                *item = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(i, &self))?;
81            }
82
83            let key = Ed25519PublicKey::from_slice(&buf).map_err(|e| de::Error::custom(&e))?;
84
85            Ok(Box::new(key))
86        }
87
88        fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
89        where
90            E: de::Error,
91        {
92            if v.len() == Ed25519PublicKey::LENGTH {
93                let mut buf = [0u8; Ed25519PublicKey::LENGTH];
94                buf.copy_from_slice(v);
95
96                let key = Ed25519PublicKey::from_slice(&buf).map_err(|e| de::Error::custom(&e))?;
97                Ok(Box::new(key))
98            } else {
99                Err(de::Error::invalid_length(v.len(), &self))
100            }
101        }
102    }
103
104    de.deserialize_any(KeyVisitor)
105}
106
107/// Information on the device and user that sent the megolm session data to us
108///
109/// Sessions start off in `UnknownDevice` state, and progress into `DeviceInfo`
110/// state when we get the device info. Finally, if we can look up the sender
111/// using the device info, the session can be moved into
112/// `VerificationViolation`, `SenderUnverified`, or `SenderVerified` state,
113/// depending on the verification status of the user. If the user's verification
114/// state changes, the state may change accordingly.
115#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
116#[serde(from = "SenderDataReader")]
117pub enum SenderData {
118    /// We have not yet found the (signed) device info for the sending device,
119    /// or we did find a device but it does not own the session.
120    UnknownDevice {
121        /// Was this session created before we started collecting trust
122        /// information about sessions? If so, we may choose to display its
123        /// messages even though trust info is missing.
124        legacy_session: bool,
125
126        /// If true, we found the device but it was not the owner of the
127        /// session. If false, we could not find the device.
128        #[serde(skip_serializing_if = "std::ops::Not::not")]
129        #[serde(default)]
130        owner_check_failed: bool,
131    },
132
133    /// We have the signed device info for the sending device, but not yet the
134    /// cross-signing key that it was signed with.
135    DeviceInfo {
136        /// Information about the device that sent the to-device message
137        /// creating this session.
138        device_keys: DeviceKeys,
139
140        /// Was this session created before we started collecting trust
141        /// information about sessions? If so, we may choose to display its
142        /// messages even though trust info is missing.
143        legacy_session: bool,
144    },
145
146    /// We have found proof that this user, with this cross-signing key, sent
147    /// the to-device message that established this session, but we have not yet
148    /// verified the cross-signing key, and we had verified a previous
149    /// cross-signing key for this user.
150    VerificationViolation(KnownSenderData),
151
152    /// We have found proof that this user, with this cross-signing key, sent
153    /// the to-device message that established this session, but we have not yet
154    /// verified the cross-signing key.
155    SenderUnverified(KnownSenderData),
156
157    /// We have found proof that this user, with this cross-signing key, sent
158    /// the to-device message that established this session, and we have
159    /// verified the cross-signing key.
160    SenderVerified(KnownSenderData),
161}
162
163impl SenderData {
164    /// Whether we should recalculate the Megolm sender's data, given the
165    /// current sender data. We only want to recalculate if it might increase
166    /// trust and allow us to decrypt messages that we otherwise might refuse to
167    /// decrypt.
168    ///
169    /// We recalculate for all states except:
170    ///
171    /// - SenderUnverified: the sender is trusted enough that we will decrypt
172    ///   their messages in all cases, or
173    /// - SenderVerified: the sender is the most trusted they can be.
174    pub fn should_recalculate(&self) -> bool {
175        matches!(
176            self,
177            SenderData::UnknownDevice { .. }
178                | SenderData::DeviceInfo { .. }
179                | SenderData::VerificationViolation { .. }
180        )
181    }
182
183    /// Create a [`SenderData`] which contains no device info.
184    pub fn unknown() -> Self {
185        Self::UnknownDevice { legacy_session: false, owner_check_failed: false }
186    }
187
188    /// Create a [`SenderData`] which contains device info.
189    pub fn device_info(device_keys: DeviceKeys) -> Self {
190        Self::DeviceInfo { device_keys, legacy_session: false }
191    }
192
193    /// Create a [`SenderData`] with a known but unverified sender, where the
194    /// sender was previously verified.
195    pub fn sender_verification_violation(
196        user_id: &UserId,
197        device_id: &DeviceId,
198        master_key: Ed25519PublicKey,
199    ) -> Self {
200        Self::VerificationViolation(KnownSenderData {
201            user_id: user_id.to_owned(),
202            device_id: Some(device_id.to_owned()),
203            master_key: Box::new(master_key),
204        })
205    }
206
207    /// Create a [`SenderData`] with a known but unverified sender.
208    pub fn sender_unverified(
209        user_id: &UserId,
210        device_id: &DeviceId,
211        master_key: Ed25519PublicKey,
212    ) -> Self {
213        Self::SenderUnverified(KnownSenderData {
214            user_id: user_id.to_owned(),
215            device_id: Some(device_id.to_owned()),
216            master_key: Box::new(master_key),
217        })
218    }
219
220    /// Create a [`SenderData`] with a verified sender.
221    pub fn sender_verified(
222        user_id: &UserId,
223        device_id: &DeviceId,
224        master_key: Ed25519PublicKey,
225    ) -> Self {
226        Self::SenderVerified(KnownSenderData {
227            user_id: user_id.to_owned(),
228            device_id: Some(device_id.to_owned()),
229            master_key: Box::new(master_key),
230        })
231    }
232
233    /// Create a [`SenderData`] which has the legacy flag set. Caution: messages
234    /// within sessions with this flag will be displayed in some contexts, even
235    /// when we are unable to verify the sender.
236    ///
237    /// The returned struct contains no device info.
238    pub fn legacy() -> Self {
239        Self::UnknownDevice { legacy_session: true, owner_check_failed: false }
240    }
241
242    /// Create a [`SenderData`] representing the current verification state of
243    /// the given device.
244    ///
245    /// Depending on whether the device is correctly cross-signed or not, and
246    /// whether the user has been verified or not, this can return
247    /// [`SenderData::DeviceInfo`], [`SenderData::VerificationViolation`],
248    /// [`SenderData::SenderUnverified`] or [`SenderData::SenderVerified`]
249    pub fn from_device(sender_device: &Device) -> Self {
250        // Is the device cross-signed? Does the cross-signing key match that
251        // used to sign the device? And is the signature in the device valid?
252        let cross_signed = sender_device.is_cross_signed_by_owner();
253
254        if cross_signed {
255            SenderData::from_cross_signed_device(sender_device)
256        } else {
257            // We have device keys, but they are not signed by the sender
258            SenderData::device_info(sender_device.as_device_keys().clone())
259        }
260    }
261
262    fn from_cross_signed_device(sender_device: &Device) -> Self {
263        let user_id = sender_device.user_id().to_owned();
264        let device_id = Some(sender_device.device_id().to_owned());
265
266        let device_owner = sender_device.device_owner_identity.as_ref();
267        let master_key = device_owner.and_then(|i| i.master_key().get_first_key());
268
269        match (device_owner, master_key) {
270            (Some(device_owner), Some(master_key)) => {
271                // We have user_id and master_key for the user sending the
272                // to-device message.
273                let master_key = Box::new(master_key);
274                let known_sender_data = KnownSenderData { user_id, device_id, master_key };
275                if sender_device.is_cross_signing_trusted() {
276                    Self::SenderVerified(known_sender_data)
277                } else if device_owner.was_previously_verified() {
278                    Self::VerificationViolation(known_sender_data)
279                } else {
280                    Self::SenderUnverified(known_sender_data)
281                }
282            }
283
284            (_, _) => {
285                // Surprisingly, there was no key in the MasterPubkey. We did
286                // not expect this: treat it as if the device was not signed by
287                // this master key.
288                error!("MasterPubkey for user {user_id} does not contain any keys!");
289                Self::device_info(sender_device.as_device_keys().clone())
290            }
291        }
292    }
293
294    /// Returns `Greater` if this `SenderData` represents a greater level of
295    /// trust than the supplied one, `Equal` if they have the same level, and
296    /// `Less` if the supplied one has a greater level of trust.
297    ///
298    /// So calling this method on a `SenderKnown` or `DeviceInfo` `SenderData`
299    /// would return `Greater` if passed an `UnknownDevice` as its argument, and
300    /// a `SenderKnown` with `master_key_verified == true` would return
301    /// `Greater` if passed a `SenderKnown` with `master_key_verified == false`.
302    pub(crate) fn compare_trust_level(&self, other: &Self) -> Ordering {
303        self.trust_number().cmp(&other.trust_number())
304    }
305
306    /// Internal function to give a numeric value of how much trust this
307    /// `SenderData` represents. Used to make the implementation of
308    /// compare_trust_level simpler.
309    fn trust_number(&self) -> u8 {
310        match self {
311            SenderData::UnknownDevice { .. } => 0,
312            SenderData::DeviceInfo { .. } => 1,
313            SenderData::VerificationViolation(..) => 2,
314            SenderData::SenderUnverified(..) => 3,
315            SenderData::SenderVerified(..) => 4,
316        }
317    }
318
319    /// Return our type as a [`SenderDataType`].
320    pub fn to_type(&self) -> SenderDataType {
321        match self {
322            Self::UnknownDevice { .. } => SenderDataType::UnknownDevice,
323            Self::DeviceInfo { .. } => SenderDataType::DeviceInfo,
324            Self::VerificationViolation { .. } => SenderDataType::VerificationViolation,
325            Self::SenderUnverified { .. } => SenderDataType::SenderUnverified,
326            Self::SenderVerified { .. } => SenderDataType::SenderVerified,
327        }
328    }
329
330    /// Return our best guess of the owner of the associated megolm session.
331    ///
332    /// For `SenderData::UnknownDevice`, we don't record any information about
333    /// the owner of the sender, so returns `None`.
334    pub(crate) fn user_id(&self) -> Option<OwnedUserId> {
335        match &self {
336            SenderData::UnknownDevice { .. } => None,
337            SenderData::DeviceInfo { device_keys, .. } => Some(device_keys.user_id.clone()),
338            SenderData::VerificationViolation(known_sender_data) => {
339                Some(known_sender_data.user_id.clone())
340            }
341            SenderData::SenderUnverified(known_sender_data) => {
342                Some(known_sender_data.user_id.clone())
343            }
344            SenderData::SenderVerified(known_sender_data) => {
345                Some(known_sender_data.user_id.clone())
346            }
347        }
348    }
349}
350
351/// Used when deserialising and the sender_data property is missing. If we are
352/// deserialising an InboundGroupSession session with missing sender_data, this
353/// must be a legacy session (i.e. it was created before we started tracking
354/// sender data). We set its legacy flag to true, so we can populate it with
355/// trust information if it is available later.
356impl Default for SenderData {
357    fn default() -> Self {
358        Self::legacy()
359    }
360}
361
362/// Deserialisation type, to handle conversion from older formats
363#[derive(Deserialize)]
364enum SenderDataReader {
365    UnknownDevice {
366        legacy_session: bool,
367        #[serde(default)]
368        owner_check_failed: bool,
369    },
370
371    DeviceInfo {
372        device_keys: DeviceKeys,
373        legacy_session: bool,
374    },
375
376    #[serde(alias = "SenderUnverifiedButPreviouslyVerified")]
377    VerificationViolation(KnownSenderData),
378
379    SenderUnverified(KnownSenderData),
380
381    SenderVerified(KnownSenderData),
382
383    // If we read this older variant, it gets changed to SenderUnverified or
384    // SenderVerified, depending on the master_key_verified flag.
385    SenderKnown {
386        user_id: OwnedUserId,
387        device_id: Option<OwnedDeviceId>,
388        master_key: Box<Ed25519PublicKey>,
389        master_key_verified: bool,
390    },
391}
392
393impl From<SenderDataReader> for SenderData {
394    fn from(data: SenderDataReader) -> Self {
395        match data {
396            SenderDataReader::UnknownDevice { legacy_session, owner_check_failed } => {
397                Self::UnknownDevice { legacy_session, owner_check_failed }
398            }
399            SenderDataReader::DeviceInfo { device_keys, legacy_session } => {
400                Self::DeviceInfo { device_keys, legacy_session }
401            }
402            SenderDataReader::VerificationViolation(data) => Self::VerificationViolation(data),
403            SenderDataReader::SenderUnverified(data) => Self::SenderUnverified(data),
404            SenderDataReader::SenderVerified(data) => Self::SenderVerified(data),
405            SenderDataReader::SenderKnown {
406                user_id,
407                device_id,
408                master_key,
409                master_key_verified,
410            } => {
411                let known_sender_data = KnownSenderData { user_id, device_id, master_key };
412                if master_key_verified {
413                    Self::SenderVerified(known_sender_data)
414                } else {
415                    Self::SenderUnverified(known_sender_data)
416                }
417            }
418        }
419    }
420}
421
422/// Used when serializing [`crate::olm::group_sessions::InboundGroupSession`]s.
423/// We want just the type of the session's [`SenderData`] to be queryable, so we
424/// store the type as a separate column/property in the database.
425#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
426pub enum SenderDataType {
427    /// The [`SenderData`] is of type `UnknownDevice`.
428    UnknownDevice = 1,
429    /// The [`SenderData`] is of type `DeviceInfo`.
430    DeviceInfo = 2,
431    /// The [`SenderData`] is of type `VerificationViolation`.
432    VerificationViolation = 3,
433    /// The [`SenderData`] is of type `SenderUnverified`.
434    SenderUnverified = 4,
435    /// The [`SenderData`] is of type `SenderVerified`.
436    SenderVerified = 5,
437}
438
439#[cfg(test)]
440mod tests {
441    use std::{cmp::Ordering, collections::BTreeMap, ops::Deref};
442
443    use insta::assert_json_snapshot;
444    use matrix_sdk_test::async_test;
445    use ruma::{
446        DeviceKeyAlgorithm, DeviceKeyId, device_id, owned_device_id, owned_user_id, user_id,
447    };
448    use serde_json::json;
449    use strass::assert_let;
450    use vodozemac::{Curve25519PublicKey, Ed25519PublicKey, base64_decode};
451
452    use super::SenderData;
453    use crate::{
454        Account,
455        machine::test_helpers::{
456            create_signed_device_of_unverified_user, create_signed_device_of_verified_user,
457            create_unsigned_device,
458        },
459        olm::{KnownSenderData, PickledInboundGroupSession, PrivateCrossSigningIdentity},
460        types::{DeviceKey, DeviceKeys, EventEncryptionAlgorithm, Signatures},
461    };
462
463    #[test]
464    fn serializing_unknown_device_correctly_preserves_owner_check_failed_if_true() {
465        // Given an unknown device SenderData with failed owner check
466        let start = SenderData::UnknownDevice { legacy_session: false, owner_check_failed: true };
467
468        // When we round-trip it to JSON and back
469        let json = serde_json::to_string(&start).unwrap();
470        let end: SenderData = serde_json::from_str(&json).unwrap();
471
472        // Then the failed owner check flag is preserved
473        assert_let!(SenderData::UnknownDevice { owner_check_failed, .. } = &end);
474        assert!(owner_check_failed);
475
476        // And for good measure, everything is preserved
477        assert_eq!(start, end);
478    }
479
480    #[test]
481    fn serializing_unknown_device_without_failed_owner_check_excludes_it() {
482        // Given an unknown device SenderData with owner_check_failed==false
483        let start = SenderData::UnknownDevice { legacy_session: false, owner_check_failed: false };
484
485        // When we write it to JSON
486        let json = serde_json::to_string(&start).unwrap();
487
488        // Then the JSON does not mention `owner_check_failed`
489        assert!(!json.contains("owner_check_failed"), "JSON contains 'owner_check_failed'!");
490
491        // And for good measure, it round-trips fully
492        let end: SenderData = serde_json::from_str(&json).unwrap();
493        assert_eq!(start, end);
494    }
495
496    #[test]
497    fn deserializing_unknown_device_with_extra_retry_info_ignores_it() {
498        // Previously, SenderData contained `retry_details` but it is no longer
499        // needed - just check that we are able to deserialize even if it is
500        // present.
501        let json = r#"
502            {
503                "UnknownDevice":{
504                    "retry_details":{
505                        "retry_count":3,
506                        "next_retry_time_ms":10000
507                    },
508                    "legacy_session":false
509                }
510            }
511            "#;
512
513        let end: SenderData = serde_json::from_str(json).expect("Failed to parse!");
514        assert_let!(SenderData::UnknownDevice { .. } = end);
515    }
516
517    #[test]
518    fn deserializing_senderknown_without_device_id_defaults_to_none() {
519        let json = r#"
520            {
521                "SenderKnown":{
522                    "user_id":"@u:s.co",
523                    "master_key":[
524                        150,140,249,139,141,29,63,230,179,14,213,175,176,61,11,255,
525                        26,103,10,51,100,154,183,47,181,117,87,204,33,215,241,92
526                    ],
527                    "master_key_verified":true
528                }
529            }
530            "#;
531
532        let end: SenderData = serde_json::from_str(json).expect("Failed to parse!");
533        assert_let!(SenderData::SenderVerified { .. } = end);
534    }
535
536    #[test]
537    fn deserializing_sender_unverified_but_previously_verified_migrates_to_verification_violation()
538    {
539        let json = r#"
540            {
541                "SenderUnverifiedButPreviouslyVerified":{
542                    "user_id":"@u:s.co",
543                    "master_key":[
544                        150,140,249,139,141,29,63,230,179,14,213,175,176,61,11,255,
545                        26,103,10,51,100,154,183,47,181,117,87,204,33,215,241,92
546                    ],
547                    "master_key_verified":true
548                }
549            }
550            "#;
551
552        let end: SenderData = serde_json::from_str(json).expect("Failed to parse!");
553        assert_let!(SenderData::VerificationViolation(KnownSenderData { user_id, .. }) = end);
554        assert_eq!(user_id, "@u:s.co");
555    }
556
557    #[test]
558    fn deserializing_verification_violation() {
559        let json = r#"
560            {
561                "VerificationViolation":{
562                    "user_id":"@u:s.co",
563                    "master_key":[
564                        150,140,249,139,141,29,63,230,179,14,213,175,176,61,11,255,
565                        26,103,10,51,100,154,183,47,181,117,87,204,33,215,241,92
566                    ],
567                    "master_key_verified":true
568                }
569            }
570            "#;
571
572        let end: SenderData = serde_json::from_str(json).expect("Failed to parse!");
573        assert_let!(SenderData::VerificationViolation(KnownSenderData { user_id, .. }) = end);
574        assert_eq!(user_id, "@u:s.co");
575    }
576
577    #[test]
578    fn equal_sessions_have_same_trust_level() {
579        let unknown = SenderData::unknown();
580        let device_keys = SenderData::device_info(DeviceKeys::new(
581            owned_user_id!("@u:s.co"),
582            owned_device_id!("DEV"),
583            Vec::new(),
584            BTreeMap::new(),
585            Signatures::new(),
586        ));
587        let master_key =
588            Ed25519PublicKey::from_base64("2/5LWJMow5zhJqakV88SIc7q/1pa8fmkfgAzx72w9G4").unwrap();
589        let sender_unverified =
590            SenderData::sender_unverified(user_id!("@u:s.co"), device_id!("DEV"), master_key);
591        let sender_verified =
592            SenderData::sender_verified(user_id!("@u:s.co"), device_id!("DEV"), master_key);
593
594        assert_eq!(unknown.compare_trust_level(&unknown), Ordering::Equal);
595        assert_eq!(device_keys.compare_trust_level(&device_keys), Ordering::Equal);
596        assert_eq!(sender_unverified.compare_trust_level(&sender_unverified), Ordering::Equal);
597        assert_eq!(sender_verified.compare_trust_level(&sender_verified), Ordering::Equal);
598    }
599
600    #[test]
601    fn more_trust_data_makes_you_more_trusted() {
602        let unknown = SenderData::unknown();
603        let device_keys = SenderData::device_info(DeviceKeys::new(
604            owned_user_id!("@u:s.co"),
605            owned_device_id!("DEV"),
606            Vec::new(),
607            BTreeMap::new(),
608            Signatures::new(),
609        ));
610        let master_key =
611            Ed25519PublicKey::from_base64("2/5LWJMow5zhJqakV88SIc7q/1pa8fmkfgAzx72w9G4").unwrap();
612        let sender_verification_violation = SenderData::sender_verification_violation(
613            user_id!("@u:s.co"),
614            device_id!("DEV"),
615            master_key,
616        );
617        let sender_unverified =
618            SenderData::sender_unverified(user_id!("@u:s.co"), device_id!("DEV"), master_key);
619        let sender_verified =
620            SenderData::sender_verified(user_id!("@u:s.co"), device_id!("DEV"), master_key);
621
622        assert_eq!(unknown.compare_trust_level(&device_keys), Ordering::Less);
623        assert_eq!(unknown.compare_trust_level(&sender_verification_violation), Ordering::Less);
624        assert_eq!(unknown.compare_trust_level(&sender_unverified), Ordering::Less);
625        assert_eq!(unknown.compare_trust_level(&sender_verified), Ordering::Less);
626        assert_eq!(device_keys.compare_trust_level(&unknown), Ordering::Greater);
627        assert_eq!(sender_verification_violation.compare_trust_level(&unknown), Ordering::Greater);
628        assert_eq!(sender_unverified.compare_trust_level(&unknown), Ordering::Greater);
629        assert_eq!(sender_verified.compare_trust_level(&unknown), Ordering::Greater);
630
631        assert_eq!(device_keys.compare_trust_level(&sender_unverified), Ordering::Less);
632        assert_eq!(device_keys.compare_trust_level(&sender_verified), Ordering::Less);
633        assert_eq!(
634            sender_verification_violation.compare_trust_level(&device_keys),
635            Ordering::Greater
636        );
637        assert_eq!(sender_unverified.compare_trust_level(&device_keys), Ordering::Greater);
638        assert_eq!(sender_verified.compare_trust_level(&device_keys), Ordering::Greater);
639
640        assert_eq!(
641            sender_verification_violation.compare_trust_level(&sender_verified),
642            Ordering::Less
643        );
644        assert_eq!(
645            sender_verification_violation.compare_trust_level(&sender_unverified),
646            Ordering::Less
647        );
648        assert_eq!(sender_unverified.compare_trust_level(&sender_verified), Ordering::Less);
649        assert_eq!(sender_verified.compare_trust_level(&sender_unverified), Ordering::Greater);
650    }
651
652    #[test]
653    fn snapshot_sender_data() {
654        assert_json_snapshot!(SenderData::UnknownDevice {
655            legacy_session: false,
656            owner_check_failed: true,
657        });
658
659        assert_json_snapshot!(SenderData::UnknownDevice {
660            legacy_session: true,
661            owner_check_failed: false,
662        });
663
664        assert_json_snapshot!(SenderData::DeviceInfo {
665            device_keys: DeviceKeys::new(
666                owned_user_id!("@foo:bar.baz"),
667                owned_device_id!("DEV"),
668                vec![
669                    EventEncryptionAlgorithm::MegolmV1AesSha2,
670                    EventEncryptionAlgorithm::OlmV1Curve25519AesSha2
671                ],
672                BTreeMap::from_iter(vec![(
673                    DeviceKeyId::from_parts(DeviceKeyAlgorithm::Ed25519, device_id!("ABCDEFGH")),
674                    DeviceKey::Curve25519(Curve25519PublicKey::from_bytes([0u8; 32])),
675                )]),
676                Default::default(),
677            ),
678            legacy_session: false,
679        });
680
681        assert_json_snapshot!(SenderData::VerificationViolation(KnownSenderData {
682            user_id: owned_user_id!("@foo:bar.baz"),
683            device_id: Some(owned_device_id!("DEV")),
684            master_key: Box::new(Ed25519PublicKey::from_slice(&[0u8; 32]).unwrap()),
685        }));
686
687        assert_json_snapshot!(SenderData::SenderUnverified(KnownSenderData {
688            user_id: owned_user_id!("@foo:bar.baz"),
689            device_id: None,
690            master_key: Box::new(Ed25519PublicKey::from_slice(&[1u8; 32]).unwrap()),
691        }));
692
693        assert_json_snapshot!(SenderData::SenderVerified(KnownSenderData {
694            user_id: owned_user_id!("@foo:bar.baz"),
695            device_id: None,
696            master_key: Box::new(Ed25519PublicKey::from_slice(&[1u8; 32]).unwrap()),
697        }));
698    }
699
700    #[test]
701    fn test_sender_known_data_migration() {
702        let old_format = json!(
703        {
704            "SenderVerified": {
705                "user_id": "@foo:bar.baz",
706                "device_id": null,
707                "master_key": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
708            }
709        });
710
711        let migrated: SenderData = serde_json::from_value(old_format).unwrap();
712
713        assert_let!(SenderData::SenderVerified(KnownSenderData { master_key, .. }) = migrated);
714
715        assert_eq!(
716            master_key.to_base64(),
717            Ed25519PublicKey::from_slice(&[0u8; 32]).unwrap().to_base64()
718        );
719    }
720
721    #[test]
722    fn test_sender_known_data_migration_with_efficient_bytes_array() {
723        // This is an serialized PickledInboundGroupSession as rmp_serde will
724        // generate.
725        //
726        // This export usse a more efficient serialization format for bytes.
727        // This was exported when the `KnownSenderData` master_key was
728        // serialized as an byte array instead of a base64 encoded string.
729        const SERIALIZED_B64: &str = "\
730            iaZwaWNrbGWEr2luaXRpYWxfcmF0Y2hldIKlaW5uZXLcAIABYMzfSnBRzMlPKF1uKjYbzLtkzNJ4RcylzN0HzP\
731            9DzON1Tm05zO7M2MzFQsy9Acz9zPnMqDvM4syQzNrMzxF5KzbM4sy9zPUbBWfM7m4/zJzM18zDzMESKgfMkE7M\
732            yszIHszqWjYyQURbzKTMkx7M58zANsy+AGPM2A8tbcyFYczge8ykzMFdbVxJMMyAzN8azJEXGsy8zPJazMMaP8\
733            ziDszmWwfM+My2ajLMr8y+eczTRm9TFadjb3VudGVyAKtzaWduaW5nX2tlecQgefpCr6Duu7QUWzKIeMOFmxv/\
734            NjfcsYwZz8IN2ZOhdaS0c2lnbmluZ19rZXlfdmVyaWZpZWTDpmNvbmZpZ4GndmVyc2lvbqJWMapzZW5kZXJfa2\
735            V52StoMkIySDg2ajFpYmk2SW13ak9UUkhzbTVMamtyT2kyUGtiSXVUb0w0TWtFq3NpZ25pbmdfa2V5gadlZDI1\
736            NTE52StUWHJqNS9UYXpia3Yram1CZDl4UlB4NWNVaFFzNUNnblc1Q1pNRjgvNjZzq3NlbmRlcl9kYXRhgbBTZW\
737            5kZXJVbnZlcmlmaWVkg6d1c2VyX2lks0B2YWxvdTM1Om1hdHJpeC5vcmepZGV2aWNlX2lkqkZJQlNaRlJLUE2q\
738            bWFzdGVyX2tlecQgkOp9s4ClyQujYD7rRZA8xgE6kvYlqKSNnMrQNmSrcuGncm9vbV9pZL4hRWt5VEtGdkViYl\
739            B6SmxhaUhFOm1hdHJpeC5vcmeoaW1wb3J0ZWTCqWJhY2tlZF91cMKyaGlzdG9yeV92aXNpYmlsaXR5wKlhbGdv\
740            cml0aG20bS5tZWdvbG0udjEuYWVzLXNoYTI";
741
742        let input = base64_decode(SERIALIZED_B64).unwrap();
743        let sender_data: PickledInboundGroupSession = rmp_serde::from_slice(&input)
744            .expect("Should be able to deserialize serialized inbound group session");
745
746        assert_let!(
747            SenderData::SenderUnverified(KnownSenderData { master_key, .. }) =
748                sender_data.sender_data
749        );
750
751        assert_eq!(master_key.to_base64(), "kOp9s4ClyQujYD7rRZA8xgE6kvYlqKSNnMrQNmSrcuE");
752    }
753
754    #[async_test]
755    async fn test_from_device_for_unsigned_device() {
756        let bob_account =
757            Account::with_device_id(user_id!("@bob:example.com"), device_id!("BOB_DEVICE"));
758        let bob_device = create_unsigned_device(bob_account.device_keys());
759
760        let sender_data = SenderData::from_device(&bob_device);
761
762        assert_eq!(
763            sender_data,
764            SenderData::DeviceInfo {
765                device_keys: bob_device.device_keys.deref().clone(),
766                legacy_session: false
767            }
768        );
769    }
770
771    #[async_test]
772    async fn test_from_device_for_unverified_user() {
773        let bob_identity = PrivateCrossSigningIdentity::new(owned_user_id!("@bob:example.com"));
774        let bob_account =
775            Account::with_device_id(user_id!("@bob:example.com"), device_id!("BOB_DEVICE"));
776        let bob_device = create_signed_device_of_unverified_user(
777            bob_account.device_keys().clone(),
778            &bob_identity,
779        )
780        .await;
781
782        let sender_data = SenderData::from_device(&bob_device);
783
784        assert_eq!(
785            sender_data,
786            SenderData::SenderUnverified(KnownSenderData {
787                user_id: bob_account.user_id().to_owned(),
788                device_id: Some(bob_account.device_id().to_owned()),
789                master_key: Box::new(
790                    bob_identity.master_public_key().await.unwrap().get_first_key().unwrap()
791                ),
792            })
793        );
794    }
795
796    #[async_test]
797    async fn test_from_device_for_verified_user() {
798        let alice_account =
799            Account::with_device_id(user_id!("@alice:example.com"), device_id!("ALICE_DEVICE"));
800        let alice_identity = PrivateCrossSigningIdentity::for_account(
801            &alice_account,
802            #[cfg(feature = "experimental-x509-identity-verification")]
803            None,
804        )
805        .await
806        .unwrap();
807
808        let bob_identity = PrivateCrossSigningIdentity::new(owned_user_id!("@bob:example.com"));
809        let bob_account =
810            Account::with_device_id(user_id!("@bob:example.com"), device_id!("BOB_DEVICE"));
811        let bob_device = create_signed_device_of_verified_user(
812            bob_account.device_keys().clone(),
813            &bob_identity,
814            &alice_identity,
815        )
816        .await;
817
818        let sender_data = SenderData::from_device(&bob_device);
819
820        assert_eq!(
821            sender_data,
822            SenderData::SenderVerified(KnownSenderData {
823                user_id: bob_account.user_id().to_owned(),
824                device_id: Some(bob_account.device_id().to_owned()),
825                master_key: Box::new(
826                    bob_identity.master_public_key().await.unwrap().get_first_key().unwrap()
827                ),
828            })
829        );
830    }
831
832    #[async_test]
833    async fn test_from_device_for_verification_violation_user() {
834        let bob_identity = PrivateCrossSigningIdentity::new(owned_user_id!("@bob:example.com"));
835        let bob_account =
836            Account::with_device_id(user_id!("@bob:example.com"), device_id!("BOB_DEVICE"));
837        let bob_device =
838            create_signed_device_of_unverified_user(bob_account.device_keys(), &bob_identity).await;
839        bob_device
840            .device_owner_identity
841            .as_ref()
842            .unwrap()
843            .other()
844            .unwrap()
845            .mark_as_previously_verified();
846
847        let sender_data = SenderData::from_device(&bob_device);
848
849        assert_eq!(
850            sender_data,
851            SenderData::VerificationViolation(KnownSenderData {
852                user_id: bob_account.user_id().to_owned(),
853                device_id: Some(bob_account.device_id().to_owned()),
854                master_key: Box::new(
855                    bob_identity.master_public_key().await.unwrap().get_first_key().unwrap()
856                ),
857            })
858        );
859    }
860}