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