@@ -16,9 +16,13 @@ use std::{cmp::Ordering, fmt};
16
16
17
17
use ruma:: { DeviceId , OwnedDeviceId , OwnedUserId , UserId } ;
18
18
use serde:: { de, de:: Visitor , Deserialize , Deserializer , Serialize } ;
19
+ use tracing:: error;
19
20
use vodozemac:: Ed25519PublicKey ;
20
21
21
- use crate :: types:: { serialize_ed25519_key, DeviceKeys } ;
22
+ use crate :: {
23
+ types:: { serialize_ed25519_key, DeviceKeys } ,
24
+ Device ,
25
+ } ;
22
26
23
27
/// Information about the sender of a megolm session where we know the
24
28
/// cross-signing identity of the sender.
@@ -216,6 +220,58 @@ impl SenderData {
216
220
Self :: UnknownDevice { legacy_session : true , owner_check_failed : false }
217
221
}
218
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
+
219
275
/// Returns `Greater` if this `SenderData` represents a greater level of
220
276
/// trust than the supplied one, `Equal` if they have the same level, and
221
277
/// `Less` if the supplied one has a greater level of trust.
@@ -344,10 +400,11 @@ pub enum SenderDataType {
344
400
345
401
#[ cfg( test) ]
346
402
mod tests {
347
- use std:: { cmp:: Ordering , collections:: BTreeMap } ;
403
+ use std:: { cmp:: Ordering , collections:: BTreeMap , ops :: Deref } ;
348
404
349
405
use assert_matches2:: assert_let;
350
406
use insta:: assert_json_snapshot;
407
+ use matrix_sdk_test:: async_test;
351
408
use ruma:: {
352
409
device_id, owned_device_id, owned_user_id, user_id, DeviceKeyAlgorithm , DeviceKeyId ,
353
410
} ;
@@ -356,8 +413,13 @@ mod tests {
356
413
357
414
use super :: SenderData ;
358
415
use crate :: {
359
- olm:: { KnownSenderData , PickledInboundGroupSession } ,
416
+ machine:: test_helpers:: {
417
+ create_signed_device_of_unverified_user, create_signed_device_of_verified_user,
418
+ create_unsigned_device,
419
+ } ,
420
+ olm:: { KnownSenderData , PickledInboundGroupSession , PrivateCrossSigningIdentity } ,
360
421
types:: { DeviceKey , DeviceKeys , EventEncryptionAlgorithm , Signatures } ,
422
+ Account ,
361
423
} ;
362
424
363
425
#[ test]
@@ -648,4 +710,108 @@ mod tests {
648
710
649
711
assert_eq ! ( master_key. to_base64( ) , "kOp9s4ClyQujYD7rRZA8xgE6kvYlqKSNnMrQNmSrcuE" ) ;
650
712
}
713
+
714
+ #[ async_test]
715
+ async fn test_from_device_for_unsigned_device ( ) {
716
+ let bob_account =
717
+ Account :: with_device_id ( user_id ! ( "@bob:example.com" ) , device_id ! ( "BOB_DEVICE" ) ) ;
718
+ let bob_device = create_unsigned_device ( bob_account. device_keys ( ) ) ;
719
+
720
+ let sender_data = SenderData :: from_device ( & bob_device) ;
721
+
722
+ assert_eq ! (
723
+ sender_data,
724
+ SenderData :: DeviceInfo {
725
+ device_keys: bob_device. device_keys. deref( ) . clone( ) ,
726
+ legacy_session: false
727
+ }
728
+ ) ;
729
+ }
730
+
731
+ #[ async_test]
732
+ async fn test_from_device_for_unverified_user ( ) {
733
+ let bob_identity =
734
+ PrivateCrossSigningIdentity :: new ( user_id ! ( "@bob:example.com" ) . to_owned ( ) ) ;
735
+ let bob_account =
736
+ Account :: with_device_id ( user_id ! ( "@bob:example.com" ) , device_id ! ( "BOB_DEVICE" ) ) ;
737
+ let bob_device = create_signed_device_of_unverified_user (
738
+ bob_account. device_keys ( ) . clone ( ) ,
739
+ & bob_identity,
740
+ )
741
+ . await ;
742
+
743
+ let sender_data = SenderData :: from_device ( & bob_device) ;
744
+
745
+ assert_eq ! (
746
+ sender_data,
747
+ SenderData :: SenderUnverified ( KnownSenderData {
748
+ user_id: bob_account. user_id( ) . to_owned( ) ,
749
+ device_id: Some ( bob_account. device_id( ) . to_owned( ) ) ,
750
+ master_key: Box :: new(
751
+ bob_identity. master_public_key( ) . await . unwrap( ) . get_first_key( ) . unwrap( )
752
+ ) ,
753
+ } )
754
+ ) ;
755
+ }
756
+
757
+ #[ async_test]
758
+ async fn test_from_device_for_verified_user ( ) {
759
+ let alice_account =
760
+ Account :: with_device_id ( user_id ! ( "@alice:example.com" ) , device_id ! ( "ALICE_DEVICE" ) ) ;
761
+ let alice_identity = PrivateCrossSigningIdentity :: with_account ( & alice_account) . await . 0 ;
762
+
763
+ let bob_identity =
764
+ PrivateCrossSigningIdentity :: new ( user_id ! ( "@bob:example.com" ) . to_owned ( ) ) ;
765
+ let bob_account =
766
+ Account :: with_device_id ( user_id ! ( "@bob:example.com" ) , device_id ! ( "BOB_DEVICE" ) ) ;
767
+ let bob_device = create_signed_device_of_verified_user (
768
+ bob_account. device_keys ( ) . clone ( ) ,
769
+ & bob_identity,
770
+ & alice_identity,
771
+ )
772
+ . await ;
773
+
774
+ let sender_data = SenderData :: from_device ( & bob_device) ;
775
+
776
+ assert_eq ! (
777
+ sender_data,
778
+ SenderData :: SenderVerified ( KnownSenderData {
779
+ user_id: bob_account. user_id( ) . to_owned( ) ,
780
+ device_id: Some ( bob_account. device_id( ) . to_owned( ) ) ,
781
+ master_key: Box :: new(
782
+ bob_identity. master_public_key( ) . await . unwrap( ) . get_first_key( ) . unwrap( )
783
+ ) ,
784
+ } )
785
+ ) ;
786
+ }
787
+
788
+ #[ async_test]
789
+ async fn test_from_device_for_verification_violation_user ( ) {
790
+ let bob_identity =
791
+ PrivateCrossSigningIdentity :: new ( user_id ! ( "@bob:example.com" ) . to_owned ( ) ) ;
792
+ let bob_account =
793
+ Account :: with_device_id ( user_id ! ( "@bob:example.com" ) , device_id ! ( "BOB_DEVICE" ) ) ;
794
+ let bob_device =
795
+ create_signed_device_of_unverified_user ( bob_account. device_keys ( ) , & bob_identity) . await ;
796
+ bob_device
797
+ . device_owner_identity
798
+ . as_ref ( )
799
+ . unwrap ( )
800
+ . other ( )
801
+ . unwrap ( )
802
+ . mark_as_previously_verified ( ) ;
803
+
804
+ let sender_data = SenderData :: from_device ( & bob_device) ;
805
+
806
+ assert_eq ! (
807
+ sender_data,
808
+ SenderData :: VerificationViolation ( KnownSenderData {
809
+ user_id: bob_account. user_id( ) . to_owned( ) ,
810
+ device_id: Some ( bob_account. device_id( ) . to_owned( ) ) ,
811
+ master_key: Box :: new(
812
+ bob_identity. master_public_key( ) . await . unwrap( ) . get_first_key( ) . unwrap( )
813
+ ) ,
814
+ } )
815
+ ) ;
816
+ }
651
817
}
0 commit comments