1use std::{cmp::Ordering, fmt};
16
17use ruma::{DeviceId, OwnedDeviceId, OwnedUserId, UserId};
18use serde::{de, de::Visitor, Deserialize, Deserializer, Serialize};
19use vodozemac::Ed25519PublicKey;
20
21use crate::types::{serialize_ed25519_key, DeviceKeys};
22
23#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
26pub struct KnownSenderData {
27 pub user_id: OwnedUserId,
29
30 pub device_id: Option<OwnedDeviceId>,
34
35 #[serde(
37 serialize_with = "serialize_ed25519_key",
38 deserialize_with = "deserialize_sender_msk_base64_or_array"
39 )]
40 pub master_key: Box<Ed25519PublicKey>,
41}
42
43pub(crate) fn deserialize_sender_msk_base64_or_array<'de, D>(
46 de: D,
47) -> Result<Box<Ed25519PublicKey>, D::Error>
48where
49 D: Deserializer<'de>,
50{
51 struct KeyVisitor;
52
53 impl<'de> Visitor<'de> for KeyVisitor {
54 type Value = Box<Ed25519PublicKey>;
55
56 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
57 write!(formatter, "a base64 string or an array of 32 bytes")
58 }
59
60 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
61 where
62 E: de::Error,
63 {
64 let decoded = Ed25519PublicKey::from_base64(v)
65 .map_err(|_| de::Error::custom("Base64 decoding error"))?;
66 Ok(Box::new(decoded))
67 }
68
69 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
70 where
71 A: de::SeqAccess<'de>,
72 {
73 let mut buf = [0u8; Ed25519PublicKey::LENGTH];
74
75 for (i, item) in buf.iter_mut().enumerate() {
76 *item = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(i, &self))?;
77 }
78
79 let key = Ed25519PublicKey::from_slice(&buf).map_err(|e| de::Error::custom(&e))?;
80
81 Ok(Box::new(key))
82 }
83
84 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
85 where
86 E: de::Error,
87 {
88 if v.len() == Ed25519PublicKey::LENGTH {
89 let mut buf = [0u8; Ed25519PublicKey::LENGTH];
90 buf.copy_from_slice(v);
91
92 let key = Ed25519PublicKey::from_slice(&buf).map_err(|e| de::Error::custom(&e))?;
93 Ok(Box::new(key))
94 } else {
95 Err(de::Error::invalid_length(v.len(), &self))
96 }
97 }
98 }
99
100 de.deserialize_any(KeyVisitor)
101}
102
103#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
112#[serde(from = "SenderDataReader")]
113pub enum SenderData {
114 UnknownDevice {
117 legacy_session: bool,
121
122 #[serde(skip_serializing_if = "std::ops::Not::not")]
125 #[serde(default)]
126 owner_check_failed: bool,
127 },
128
129 DeviceInfo {
132 device_keys: DeviceKeys,
135
136 legacy_session: bool,
140 },
141
142 VerificationViolation(KnownSenderData),
147
148 SenderUnverified(KnownSenderData),
152
153 SenderVerified(KnownSenderData),
157}
158
159impl SenderData {
160 pub fn unknown() -> Self {
162 Self::UnknownDevice { legacy_session: false, owner_check_failed: false }
163 }
164
165 pub fn device_info(device_keys: DeviceKeys) -> Self {
167 Self::DeviceInfo { device_keys, legacy_session: false }
168 }
169
170 pub fn sender_verification_violation(
173 user_id: &UserId,
174 device_id: &DeviceId,
175 master_key: Ed25519PublicKey,
176 ) -> Self {
177 Self::VerificationViolation(KnownSenderData {
178 user_id: user_id.to_owned(),
179 device_id: Some(device_id.to_owned()),
180 master_key: Box::new(master_key),
181 })
182 }
183
184 pub fn sender_unverified(
186 user_id: &UserId,
187 device_id: &DeviceId,
188 master_key: Ed25519PublicKey,
189 ) -> Self {
190 Self::SenderUnverified(KnownSenderData {
191 user_id: user_id.to_owned(),
192 device_id: Some(device_id.to_owned()),
193 master_key: Box::new(master_key),
194 })
195 }
196
197 pub fn sender_verified(
199 user_id: &UserId,
200 device_id: &DeviceId,
201 master_key: Ed25519PublicKey,
202 ) -> Self {
203 Self::SenderVerified(KnownSenderData {
204 user_id: user_id.to_owned(),
205 device_id: Some(device_id.to_owned()),
206 master_key: Box::new(master_key),
207 })
208 }
209
210 pub fn legacy() -> Self {
216 Self::UnknownDevice { legacy_session: true, owner_check_failed: false }
217 }
218
219 pub(crate) fn compare_trust_level(&self, other: &Self) -> Ordering {
229 self.trust_number().cmp(&other.trust_number())
230 }
231
232 fn trust_number(&self) -> u8 {
236 match self {
237 SenderData::UnknownDevice { .. } => 0,
238 SenderData::DeviceInfo { .. } => 1,
239 SenderData::VerificationViolation(..) => 2,
240 SenderData::SenderUnverified(..) => 3,
241 SenderData::SenderVerified(..) => 4,
242 }
243 }
244
245 pub fn to_type(&self) -> SenderDataType {
247 match self {
248 Self::UnknownDevice { .. } => SenderDataType::UnknownDevice,
249 Self::DeviceInfo { .. } => SenderDataType::DeviceInfo,
250 Self::VerificationViolation { .. } => SenderDataType::VerificationViolation,
251 Self::SenderUnverified { .. } => SenderDataType::SenderUnverified,
252 Self::SenderVerified { .. } => SenderDataType::SenderVerified,
253 }
254 }
255}
256
257impl Default for SenderData {
263 fn default() -> Self {
264 Self::legacy()
265 }
266}
267
268#[derive(Deserialize)]
270enum SenderDataReader {
271 UnknownDevice {
272 legacy_session: bool,
273 #[serde(default)]
274 owner_check_failed: bool,
275 },
276
277 DeviceInfo {
278 device_keys: DeviceKeys,
279 legacy_session: bool,
280 },
281
282 #[serde(alias = "SenderUnverifiedButPreviouslyVerified")]
283 VerificationViolation(KnownSenderData),
284
285 SenderUnverified(KnownSenderData),
286
287 SenderVerified(KnownSenderData),
288
289 SenderKnown {
292 user_id: OwnedUserId,
293 device_id: Option<OwnedDeviceId>,
294 master_key: Box<Ed25519PublicKey>,
295 master_key_verified: bool,
296 },
297}
298
299impl From<SenderDataReader> for SenderData {
300 fn from(data: SenderDataReader) -> Self {
301 match data {
302 SenderDataReader::UnknownDevice { legacy_session, owner_check_failed } => {
303 Self::UnknownDevice { legacy_session, owner_check_failed }
304 }
305 SenderDataReader::DeviceInfo { device_keys, legacy_session } => {
306 Self::DeviceInfo { device_keys, legacy_session }
307 }
308 SenderDataReader::VerificationViolation(data) => Self::VerificationViolation(data),
309 SenderDataReader::SenderUnverified(data) => Self::SenderUnverified(data),
310 SenderDataReader::SenderVerified(data) => Self::SenderVerified(data),
311 SenderDataReader::SenderKnown {
312 user_id,
313 device_id,
314 master_key,
315 master_key_verified,
316 } => {
317 let known_sender_data = KnownSenderData { user_id, device_id, master_key };
318 if master_key_verified {
319 Self::SenderVerified(known_sender_data)
320 } else {
321 Self::SenderUnverified(known_sender_data)
322 }
323 }
324 }
325 }
326}
327
328#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
332pub enum SenderDataType {
333 UnknownDevice = 1,
335 DeviceInfo = 2,
337 VerificationViolation = 3,
339 SenderUnverified = 4,
341 SenderVerified = 5,
343}
344
345#[cfg(test)]
346mod tests {
347 use std::{cmp::Ordering, collections::BTreeMap};
348
349 use assert_matches2::assert_let;
350 use insta::assert_json_snapshot;
351 use ruma::{
352 device_id, owned_device_id, owned_user_id, user_id, DeviceKeyAlgorithm, DeviceKeyId,
353 };
354 use serde_json::json;
355 use vodozemac::{base64_decode, Curve25519PublicKey, Ed25519PublicKey};
356
357 use super::SenderData;
358 use crate::{
359 olm::{KnownSenderData, PickledInboundGroupSession},
360 types::{DeviceKey, DeviceKeys, EventEncryptionAlgorithm, Signatures},
361 };
362
363 #[test]
364 fn serializing_unknown_device_correctly_preserves_owner_check_failed_if_true() {
365 let start = SenderData::UnknownDevice { legacy_session: false, owner_check_failed: true };
367
368 let json = serde_json::to_string(&start).unwrap();
370 let end: SenderData = serde_json::from_str(&json).unwrap();
371
372 assert_let!(SenderData::UnknownDevice { owner_check_failed, .. } = &end);
374 assert!(owner_check_failed);
375
376 assert_eq!(start, end);
378 }
379
380 #[test]
381 fn serializing_unknown_device_without_failed_owner_check_excludes_it() {
382 let start = SenderData::UnknownDevice { legacy_session: false, owner_check_failed: false };
384
385 let json = serde_json::to_string(&start).unwrap();
387
388 assert!(!json.contains("owner_check_failed"), "JSON contains 'owner_check_failed'!");
390
391 let end: SenderData = serde_json::from_str(&json).unwrap();
393 assert_eq!(start, end);
394 }
395
396 #[test]
397 fn deserializing_unknown_device_with_extra_retry_info_ignores_it() {
398 let json = r#"
401 {
402 "UnknownDevice":{
403 "retry_details":{
404 "retry_count":3,
405 "next_retry_time_ms":10000
406 },
407 "legacy_session":false
408 }
409 }
410 "#;
411
412 let end: SenderData = serde_json::from_str(json).expect("Failed to parse!");
413 assert_let!(SenderData::UnknownDevice { .. } = end);
414 }
415
416 #[test]
417 fn deserializing_senderknown_without_device_id_defaults_to_none() {
418 let json = r#"
419 {
420 "SenderKnown":{
421 "user_id":"@u:s.co",
422 "master_key":[
423 150,140,249,139,141,29,63,230,179,14,213,175,176,61,11,255,
424 26,103,10,51,100,154,183,47,181,117,87,204,33,215,241,92
425 ],
426 "master_key_verified":true
427 }
428 }
429 "#;
430
431 let end: SenderData = serde_json::from_str(json).expect("Failed to parse!");
432 assert_let!(SenderData::SenderVerified { .. } = end);
433 }
434
435 #[test]
436 fn deserializing_sender_unverified_but_previously_verified_migrates_to_verification_violation()
437 {
438 let json = r#"
439 {
440 "SenderUnverifiedButPreviouslyVerified":{
441 "user_id":"@u:s.co",
442 "master_key":[
443 150,140,249,139,141,29,63,230,179,14,213,175,176,61,11,255,
444 26,103,10,51,100,154,183,47,181,117,87,204,33,215,241,92
445 ],
446 "master_key_verified":true
447 }
448 }
449 "#;
450
451 let end: SenderData = serde_json::from_str(json).expect("Failed to parse!");
452 assert_let!(SenderData::VerificationViolation(KnownSenderData { user_id, .. }) = end);
453 assert_eq!(user_id, owned_user_id!("@u:s.co"));
454 }
455
456 #[test]
457 fn deserializing_verification_violation() {
458 let json = r#"
459 {
460 "VerificationViolation":{
461 "user_id":"@u:s.co",
462 "master_key":[
463 150,140,249,139,141,29,63,230,179,14,213,175,176,61,11,255,
464 26,103,10,51,100,154,183,47,181,117,87,204,33,215,241,92
465 ],
466 "master_key_verified":true
467 }
468 }
469 "#;
470
471 let end: SenderData = serde_json::from_str(json).expect("Failed to parse!");
472 assert_let!(SenderData::VerificationViolation(KnownSenderData { user_id, .. }) = end);
473 assert_eq!(user_id, owned_user_id!("@u:s.co"));
474 }
475
476 #[test]
477 fn equal_sessions_have_same_trust_level() {
478 let unknown = SenderData::unknown();
479 let device_keys = SenderData::device_info(DeviceKeys::new(
480 owned_user_id!("@u:s.co"),
481 owned_device_id!("DEV"),
482 Vec::new(),
483 BTreeMap::new(),
484 Signatures::new(),
485 ));
486 let master_key =
487 Ed25519PublicKey::from_base64("2/5LWJMow5zhJqakV88SIc7q/1pa8fmkfgAzx72w9G4").unwrap();
488 let sender_unverified =
489 SenderData::sender_unverified(user_id!("@u:s.co"), device_id!("DEV"), master_key);
490 let sender_verified =
491 SenderData::sender_verified(user_id!("@u:s.co"), device_id!("DEV"), master_key);
492
493 assert_eq!(unknown.compare_trust_level(&unknown), Ordering::Equal);
494 assert_eq!(device_keys.compare_trust_level(&device_keys), Ordering::Equal);
495 assert_eq!(sender_unverified.compare_trust_level(&sender_unverified), Ordering::Equal);
496 assert_eq!(sender_verified.compare_trust_level(&sender_verified), Ordering::Equal);
497 }
498
499 #[test]
500 fn more_trust_data_makes_you_more_trusted() {
501 let unknown = SenderData::unknown();
502 let device_keys = SenderData::device_info(DeviceKeys::new(
503 owned_user_id!("@u:s.co"),
504 owned_device_id!("DEV"),
505 Vec::new(),
506 BTreeMap::new(),
507 Signatures::new(),
508 ));
509 let master_key =
510 Ed25519PublicKey::from_base64("2/5LWJMow5zhJqakV88SIc7q/1pa8fmkfgAzx72w9G4").unwrap();
511 let sender_verification_violation = SenderData::sender_verification_violation(
512 user_id!("@u:s.co"),
513 device_id!("DEV"),
514 master_key,
515 );
516 let sender_unverified =
517 SenderData::sender_unverified(user_id!("@u:s.co"), device_id!("DEV"), master_key);
518 let sender_verified =
519 SenderData::sender_verified(user_id!("@u:s.co"), device_id!("DEV"), master_key);
520
521 assert_eq!(unknown.compare_trust_level(&device_keys), Ordering::Less);
522 assert_eq!(unknown.compare_trust_level(&sender_verification_violation), Ordering::Less);
523 assert_eq!(unknown.compare_trust_level(&sender_unverified), Ordering::Less);
524 assert_eq!(unknown.compare_trust_level(&sender_verified), Ordering::Less);
525 assert_eq!(device_keys.compare_trust_level(&unknown), Ordering::Greater);
526 assert_eq!(sender_verification_violation.compare_trust_level(&unknown), Ordering::Greater);
527 assert_eq!(sender_unverified.compare_trust_level(&unknown), Ordering::Greater);
528 assert_eq!(sender_verified.compare_trust_level(&unknown), Ordering::Greater);
529
530 assert_eq!(device_keys.compare_trust_level(&sender_unverified), Ordering::Less);
531 assert_eq!(device_keys.compare_trust_level(&sender_verified), Ordering::Less);
532 assert_eq!(
533 sender_verification_violation.compare_trust_level(&device_keys),
534 Ordering::Greater
535 );
536 assert_eq!(sender_unverified.compare_trust_level(&device_keys), Ordering::Greater);
537 assert_eq!(sender_verified.compare_trust_level(&device_keys), Ordering::Greater);
538
539 assert_eq!(
540 sender_verification_violation.compare_trust_level(&sender_verified),
541 Ordering::Less
542 );
543 assert_eq!(
544 sender_verification_violation.compare_trust_level(&sender_unverified),
545 Ordering::Less
546 );
547 assert_eq!(sender_unverified.compare_trust_level(&sender_verified), Ordering::Less);
548 assert_eq!(sender_verified.compare_trust_level(&sender_unverified), Ordering::Greater);
549 }
550
551 #[test]
552 fn snapshot_sender_data() {
553 assert_json_snapshot!(SenderData::UnknownDevice {
554 legacy_session: false,
555 owner_check_failed: true,
556 });
557
558 assert_json_snapshot!(SenderData::UnknownDevice {
559 legacy_session: true,
560 owner_check_failed: false,
561 });
562
563 assert_json_snapshot!(SenderData::DeviceInfo {
564 device_keys: DeviceKeys::new(
565 owned_user_id!("@foo:bar.baz"),
566 owned_device_id!("DEV"),
567 vec![
568 EventEncryptionAlgorithm::MegolmV1AesSha2,
569 EventEncryptionAlgorithm::OlmV1Curve25519AesSha2
570 ],
571 BTreeMap::from_iter(vec![(
572 DeviceKeyId::from_parts(DeviceKeyAlgorithm::Ed25519, device_id!("ABCDEFGH")),
573 DeviceKey::Curve25519(Curve25519PublicKey::from_bytes([0u8; 32])),
574 )]),
575 Default::default(),
576 ),
577 legacy_session: false,
578 });
579
580 assert_json_snapshot!(SenderData::VerificationViolation(KnownSenderData {
581 user_id: owned_user_id!("@foo:bar.baz"),
582 device_id: Some(owned_device_id!("DEV")),
583 master_key: Box::new(Ed25519PublicKey::from_slice(&[0u8; 32]).unwrap()),
584 }));
585
586 assert_json_snapshot!(SenderData::SenderUnverified(KnownSenderData {
587 user_id: owned_user_id!("@foo:bar.baz"),
588 device_id: None,
589 master_key: Box::new(Ed25519PublicKey::from_slice(&[1u8; 32]).unwrap()),
590 }));
591
592 assert_json_snapshot!(SenderData::SenderVerified(KnownSenderData {
593 user_id: owned_user_id!("@foo:bar.baz"),
594 device_id: None,
595 master_key: Box::new(Ed25519PublicKey::from_slice(&[1u8; 32]).unwrap()),
596 }));
597 }
598
599 #[test]
600 fn test_sender_known_data_migration() {
601 let old_format = json!(
602 {
603 "SenderVerified": {
604 "user_id": "@foo:bar.baz",
605 "device_id": null,
606 "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]
607 }
608 });
609
610 let migrated: SenderData = serde_json::from_value(old_format).unwrap();
611
612 assert_let!(SenderData::SenderVerified(KnownSenderData { master_key, .. }) = migrated);
613
614 assert_eq!(
615 master_key.to_base64(),
616 Ed25519PublicKey::from_slice(&[0u8; 32]).unwrap().to_base64()
617 );
618 }
619
620 #[test]
621 fn test_sender_known_data_migration_with_efficient_bytes_array() {
622 const SERIALIZED_B64: &str =
628 "iaZwaWNrbGWEr2luaXRpYWxfcmF0Y2hldIKlaW5uZXLcAIABYMzfSnBRzMlPKF1uKjYbzLtkzNJ4RcylzN0HzP\
629 9DzON1Tm05zO7M2MzFQsy9Acz9zPnMqDvM4syQzNrMzxF5KzbM4sy9zPUbBWfM7m4/zJzM18zDzMESKgfMkE7M\
630 yszIHszqWjYyQURbzKTMkx7M58zANsy+AGPM2A8tbcyFYczge8ykzMFdbVxJMMyAzN8azJEXGsy8zPJazMMaP8\
631 ziDszmWwfM+My2ajLMr8y+eczTRm9TFadjb3VudGVyAKtzaWduaW5nX2tlecQgefpCr6Duu7QUWzKIeMOFmxv/\
632 NjfcsYwZz8IN2ZOhdaS0c2lnbmluZ19rZXlfdmVyaWZpZWTDpmNvbmZpZ4GndmVyc2lvbqJWMapzZW5kZXJfa2\
633 V52StoMkIySDg2ajFpYmk2SW13ak9UUkhzbTVMamtyT2kyUGtiSXVUb0w0TWtFq3NpZ25pbmdfa2V5gadlZDI1\
634 NTE52StUWHJqNS9UYXpia3Yram1CZDl4UlB4NWNVaFFzNUNnblc1Q1pNRjgvNjZzq3NlbmRlcl9kYXRhgbBTZW\
635 5kZXJVbnZlcmlmaWVkg6d1c2VyX2lks0B2YWxvdTM1Om1hdHJpeC5vcmepZGV2aWNlX2lkqkZJQlNaRlJLUE2q\
636 bWFzdGVyX2tlecQgkOp9s4ClyQujYD7rRZA8xgE6kvYlqKSNnMrQNmSrcuGncm9vbV9pZL4hRWt5VEtGdkViYl\
637 B6SmxhaUhFOm1hdHJpeC5vcmeoaW1wb3J0ZWTCqWJhY2tlZF91cMKyaGlzdG9yeV92aXNpYmlsaXR5wKlhbGdv\
638 cml0aG20bS5tZWdvbG0udjEuYWVzLXNoYTI";
639
640 let input = base64_decode(SERIALIZED_B64).unwrap();
641 let sender_data: PickledInboundGroupSession = rmp_serde::from_slice(&input)
642 .expect("Should be able to deserialize serialized inbound group session");
643
644 assert_let!(
645 SenderData::SenderUnverified(KnownSenderData { master_key, .. }) =
646 sender_data.sender_data
647 );
648
649 assert_eq!(master_key.to_base64(), "kOp9s4ClyQujYD7rRZA8xgE6kvYlqKSNnMrQNmSrcuE");
650 }
651}