@@ -38,7 +38,8 @@ use vodozemac::{
3838} ;
3939
4040use super :: {
41- BackedUpRoomKey , ExportedRoomKey , OutboundGroupSession , SessionCreationError , SessionKey ,
41+ inbound_group_session_sender_data:: InboundGroupSessionSenderData , BackedUpRoomKey ,
42+ ExportedRoomKey , OutboundGroupSession , SessionCreationError , SessionKey ,
4243} ;
4344use crate :: {
4445 error:: { EventError , MegolmResult } ,
@@ -123,6 +124,13 @@ pub struct InboundGroupSession {
123124 /// on how the session was received.
124125 pub ( crate ) creator_info : SessionCreatorInfo ,
125126
127+ /// Information about the sender of this session and how much we trust that
128+ /// information. Holds the information we have about the device that created
129+ /// the session, or, if we can use that device information to find the
130+ /// sender's cross-signing identity, holds the user ID and cross-signing
131+ /// key.
132+ pub ( crate ) sender_data : InboundGroupSessionSenderData ,
133+
126134 /// The Room this GroupSession belongs to
127135 pub room_id : OwnedRoomId ,
128136
@@ -191,6 +199,7 @@ impl InboundGroupSession {
191199 curve25519_key : sender_key,
192200 signing_keys : keys. into ( ) ,
193201 } ,
202+ sender_data : InboundGroupSessionSenderData :: default ( ) ,
194203 room_id : room_id. into ( ) ,
195204 imported : false ,
196205 algorithm : encryption_algorithm. into ( ) ,
@@ -243,6 +252,7 @@ impl InboundGroupSession {
243252 pickle,
244253 sender_key : self . creator_info . curve25519_key ,
245254 signing_key : ( * self . creator_info . signing_keys ) . clone ( ) ,
255+ sender_data : self . sender_data . clone ( ) ,
246256 room_id : self . room_id ( ) . to_owned ( ) ,
247257 imported : self . imported ,
248258 backed_up : self . backed_up ( ) ,
@@ -326,6 +336,7 @@ impl InboundGroupSession {
326336 curve25519_key : pickle. sender_key ,
327337 signing_keys : pickle. signing_key . into ( ) ,
328338 } ,
339+ sender_data : pickle. sender_data ,
329340 history_visibility : pickle. history_visibility . into ( ) ,
330341 first_known_index,
331342 room_id : ( * pickle. room_id ) . into ( ) ,
@@ -494,6 +505,9 @@ pub struct PickledInboundGroupSession {
494505 pub sender_key : Curve25519PublicKey ,
495506 /// The public ed25519 key of the account that sent us the session.
496507 pub signing_key : SigningKeys < DeviceKeyAlgorithm > ,
508+ /// Information on the device/sender who sent us this session
509+ #[ serde( default ) ]
510+ pub sender_data : InboundGroupSessionSenderData ,
497511 /// The id of the room that the session is used in.
498512 pub room_id : OwnedRoomId ,
499513 /// Flag remembering if the session was directly sent to us by the sender
@@ -528,6 +542,8 @@ impl TryFrom<&ExportedRoomKey> for InboundGroupSession {
528542 curve25519_key : key. sender_key ,
529543 signing_keys : key. sender_claimed_keys . to_owned ( ) . into ( ) ,
530544 } ,
545+ // TODO: in future, exported keys should contain sender data that we can use here
546+ sender_data : InboundGroupSessionSenderData :: default ( ) ,
531547 history_visibility : None . into ( ) ,
532548 first_known_index,
533549 room_id : key. room_id . to_owned ( ) ,
@@ -555,6 +571,8 @@ impl From<&ForwardedMegolmV1AesSha2Content> for InboundGroupSession {
555571 ) ] )
556572 . into ( ) ,
557573 } ,
574+ // TODO: in future, forwarded keys should contain sender data that we can use here
575+ sender_data : InboundGroupSessionSenderData :: default ( ) ,
558576 history_visibility : None . into ( ) ,
559577 first_known_index,
560578 room_id : value. room_id . to_owned ( ) ,
@@ -578,6 +596,8 @@ impl From<&ForwardedMegolmV2AesSha2Content> for InboundGroupSession {
578596 curve25519_key : value. claimed_sender_key ,
579597 signing_keys : value. claimed_signing_keys . to_owned ( ) . into ( ) ,
580598 } ,
599+ // TODO: in future, forwarded keys should contain sender data that we can use here
600+ sender_data : InboundGroupSessionSenderData :: default ( ) ,
581601 history_visibility : None . into ( ) ,
582602 first_known_index,
583603 room_id : value. room_id . to_owned ( ) ,
@@ -606,10 +626,23 @@ impl TryFrom<&DecryptedForwardedRoomKeyEvent> for InboundGroupSession {
606626#[ cfg( test) ]
607627mod tests {
608628 use matrix_sdk_test:: async_test;
609- use ruma:: { device_id, room_id, user_id, DeviceId , UserId } ;
610- use vodozemac:: { megolm:: SessionOrdering , Curve25519PublicKey } ;
611-
612- use crate :: { olm:: InboundGroupSession , Account } ;
629+ use ruma:: {
630+ device_id, events:: room:: history_visibility:: HistoryVisibility , room_id, user_id, DeviceId ,
631+ MilliSecondsSinceUnixEpoch , UInt , UserId ,
632+ } ;
633+ use vodozemac:: {
634+ megolm:: { SessionKey , SessionOrdering } ,
635+ Curve25519PublicKey , Ed25519PublicKey ,
636+ } ;
637+
638+ use crate :: {
639+ olm:: {
640+ group_sessions:: inbound_group_session_sender_data:: InboundGroupSessionSenderData ,
641+ InboundGroupSession ,
642+ } ,
643+ types:: EventEncryptionAlgorithm ,
644+ Account ,
645+ } ;
613646
614647 fn alice_id ( ) -> & ' static UserId {
615648 user_id ! ( "@alice:example.org" )
@@ -620,7 +653,8 @@ mod tests {
620653 }
621654
622655 #[ async_test]
623- async fn inbound_group_session_serialization ( ) {
656+ async fn test_can_deserialise_pickled_session_without_sender_data ( ) {
657+ // Given the raw JSON for a picked inbound group sessions
624658 let pickle = r#"
625659 {
626660 "pickle": {
@@ -657,11 +691,166 @@ mod tests {
657691 }
658692 "# ;
659693
694+ // When we deserialise it to from JSON
660695 let deserialized = serde_json:: from_str ( pickle) . unwrap ( ) ;
661696
697+ // And unpickle it
662698 let unpickled = InboundGroupSession :: from_pickle ( deserialized) . unwrap ( ) ;
663699
700+ // Then it was parsed correctly
664701 assert_eq ! ( unpickled. session_id( ) , "XbmrPa1kMwmdtNYng1B2gsfoo8UtF+NklzsTZiaVKyY" ) ;
702+
703+ // We populated the InboundGroupSession's sender_data with a default value,
704+ // with legacy_session set to true.
705+ let InboundGroupSessionSenderData :: UnknownDevice { retry_details, legacy_session } =
706+ unpickled. sender_data
707+ else {
708+ panic ! ( "Expected sender_data to be UnknownDevice!" ) ;
709+ } ;
710+ assert_eq ! ( retry_details. retry_count, 0 ) ;
711+ assert ! ( legacy_session) ;
712+ }
713+
714+ #[ async_test]
715+ async fn test_can_serialise_pickled_session_with_sender_data ( ) {
716+ // Given an InboundGroupSession
717+ let igs = InboundGroupSession :: new (
718+ Curve25519PublicKey :: from_base64 ( "AmM1DvVJarsNNXVuX7OarzfT481N37GtDwvDVF0RcR8" )
719+ . unwrap ( ) ,
720+ Ed25519PublicKey :: from_base64 ( "wTRTdz4rn4EY+68cKPzpMdQ6RAlg7T8cbTmEjaXuUww" ) . unwrap ( ) ,
721+ room_id ! ( "!test:localhost" ) ,
722+ & create_session_key ( ) ,
723+ EventEncryptionAlgorithm :: MegolmV1AesSha2 ,
724+ Some ( HistoryVisibility :: Shared ) ,
725+ )
726+ . unwrap ( ) ;
727+
728+ // When we pickle it and set its retry time to a known value
729+ let mut pickled = igs. pickle ( ) . await ;
730+
731+ let InboundGroupSessionSenderData :: UnknownDevice { retry_details, .. } =
732+ & mut pickled. sender_data
733+ else {
734+ panic ! ( "Expected sender_data to be UnknownDevice" ) ;
735+ } ;
736+ ( * retry_details) . next_retry_time_ms = MilliSecondsSinceUnixEpoch ( UInt :: new ( 1234 ) . unwrap ( ) ) ;
737+
738+ // And serialise it
739+ let serialised = serde_json:: to_string ( & pickled) . unwrap ( ) ;
740+
741+ // Then it looks as we expect
742+
743+ // (Break out this list of numbers as otherwise it bothers the json macro below)
744+ let expected_inner = vec ! [
745+ 193 , 203 , 223 , 152 , 33 , 132 , 200 , 168 , 24 , 197 , 79 , 174 , 231 , 202 , 45 , 245 , 128 , 131 ,
746+ 178 , 165 , 148 , 37 , 241 , 214 , 178 , 218 , 25 , 33 , 68 , 48 , 153 , 104 , 122 , 6 , 249 , 198 , 97 ,
747+ 226 , 214 , 75 , 64 , 128 , 25 , 138 , 98 , 90 , 138 , 93 , 52 , 206 , 174 , 3 , 84 , 149 , 101 , 140 ,
748+ 238 , 156 , 103 , 107 , 124 , 144 , 139 , 104 , 253 , 5 , 100 , 251 , 186 , 118 , 208 , 87 , 31 , 218 ,
749+ 123 , 234 , 103 , 34 , 246 , 100 , 39 , 90 , 216 , 72 , 187 , 86 , 202 , 150 , 100 , 116 , 204 , 254 ,
750+ 10 , 154 , 216 , 133 , 61 , 250 , 75 , 100 , 195 , 63 , 138 , 22 , 17 , 13 , 156 , 123 , 195 , 132 , 111 ,
751+ 95 , 250 , 24 , 236 , 0 , 246 , 93 , 230 , 100 , 211 , 165 , 211 , 190 , 181 , 87 , 42 , 181 ,
752+ ] ;
753+ assert_eq ! (
754+ serde_json:: from_str:: <serde_json:: Value >( & serialised) . unwrap( ) ,
755+ serde_json:: json!( {
756+ "pickle" : {
757+ "initial_ratchet" : {
758+ "inner" : expected_inner,
759+ "counter" : 0
760+ } ,
761+ "signing_key" : [
762+ 213 , 161 , 95 , 135 , 114 , 153 , 162 , 127 , 217 , 74 , 64 , 2 , 59 , 143 , 93 , 5 , 190 , 157 , 120 ,
763+ 80 , 89 , 8 , 87 , 129 , 115 , 148 , 104 , 144 , 152 , 186 , 178 , 109
764+ ] ,
765+ "signing_key_verified" : true ,
766+ "config" : { "version" : "V1" }
767+ } ,
768+ "sender_key" : "AmM1DvVJarsNNXVuX7OarzfT481N37GtDwvDVF0RcR8" ,
769+ "signing_key" : { "ed25519" : "wTRTdz4rn4EY+68cKPzpMdQ6RAlg7T8cbTmEjaXuUww" } ,
770+ "sender_data" : {
771+ "UnknownDevice" : {
772+ "retry_details" : {
773+ "retry_count" : 0 ,
774+ "next_retry_time_ms" : 1234
775+ } ,
776+ "legacy_session" : true
777+ }
778+ } ,
779+ "room_id" : "!test:localhost" ,
780+ "imported" : false ,
781+ "backed_up" : false ,
782+ "history_visibility" : "shared" ,
783+ "algorithm" : "m.megolm.v1.aes-sha2"
784+ } )
785+ ) ;
786+ }
787+
788+ #[ async_test]
789+ async fn test_can_deserialise_pickled_session_with_sender_data ( ) {
790+ // Given the raw JSON for a picked inbound group sessions
791+ let pickle = r#"
792+ {
793+ "pickle": {
794+ "initial_ratchet": {
795+ "inner": [ 124, 251, 213, 204, 108, 247, 54, 7, 179, 162, 15, 107, 154, 215,
796+ 220, 46, 123, 113, 120, 162, 225, 246, 237, 203, 125, 102, 190, 212,
797+ 229, 195, 136, 185, 26, 31, 77, 140, 144, 181, 152, 177, 46, 105,
798+ 202, 6, 53, 158, 157, 170, 31, 155, 130, 87, 214, 110, 143, 55, 68,
799+ 138, 41, 35, 242, 230, 194, 15, 16, 145, 116, 94, 89, 35, 79, 145,
800+ 245, 117, 204, 173, 166, 178, 49, 131, 143, 61, 61, 15, 211, 167, 17,
801+ 2, 79, 110, 149, 200, 223, 23, 185, 200, 29, 64, 55, 39, 147, 167,
802+ 205, 224, 159, 101, 218, 249, 203, 30, 175, 174, 48, 252, 40, 131,
803+ 52, 135, 91, 57, 211, 96, 105, 58, 55, 68, 250, 24 ],
804+ "counter": 0
805+ },
806+ "signing_key": [ 93, 185, 171, 61, 173, 100, 51, 9, 157, 180, 214, 39, 131, 80, 118,
807+ 130, 199, 232, 163, 197, 45, 23, 227, 100, 151, 59, 19, 102, 38,
808+ 149, 43, 38 ],
809+ "signing_key_verified": true,
810+ "config": {
811+ "version": "V1"
812+ }
813+ },
814+ "sender_key": "AmM1DvVJarsNNXVuX7OarzfT481N37GtDwvDVF0RcR8",
815+ "signing_key": {
816+ "ed25519": "wTRTdz4rn4EY+68cKPzpMdQ6RAlg7T8cbTmEjaXuUww"
817+ },
818+ "sender_data":{
819+ "UnknownDevice":{
820+ "retry_details":{
821+ "retry_count":0,
822+ "next_retry_time_ms":98765
823+ },
824+ "legacy_session":false
825+ }
826+ },
827+ "room_id": "!test:localhost",
828+ "forwarding_chains": ["tb6kQKjk+SJl2KnfQ0lKVOZl6gDFMcsb9HcUP9k/4hc"],
829+ "imported": false,
830+ "backed_up": false,
831+ "history_visibility": "shared",
832+ "algorithm": "m.megolm.v1.aes-sha2"
833+ }
834+ "# ;
835+
836+ // When we deserialise it to from JSON
837+ let deserialized = serde_json:: from_str ( pickle) . unwrap ( ) ;
838+
839+ // And unpickle it
840+ let unpickled = InboundGroupSession :: from_pickle ( deserialized) . unwrap ( ) ;
841+
842+ // Then it was parsed correctly
843+ assert_eq ! ( unpickled. session_id( ) , "XbmrPa1kMwmdtNYng1B2gsfoo8UtF+NklzsTZiaVKyY" ) ;
844+
845+ // We populated the InboundGroupSession's sender_data with a default value
846+ let InboundGroupSessionSenderData :: UnknownDevice { retry_details, legacy_session } =
847+ unpickled. sender_data
848+ else {
849+ panic ! ( "Expected sender_data to be UnknownDevice!" ) ;
850+ } ;
851+ assert_eq ! ( retry_details. retry_count, 0 ) ;
852+ assert_eq ! ( retry_details. next_retry_time_ms. 0 , UInt :: new( 98765 ) . unwrap( ) ) ;
853+ assert ! ( !legacy_session) ;
665854 }
666855
667856 #[ async_test]
@@ -685,4 +874,17 @@ mod tests {
685874
686875 assert_eq ! ( inbound. compare( & copy) . await , SessionOrdering :: Unconnected ) ;
687876 }
877+
878+ fn create_session_key ( ) -> SessionKey {
879+ SessionKey :: from_base64 (
880+ "\
881+ AgAAAADBy9+YIYTIqBjFT67nyi31gIOypZQl8day2hkhRDCZaHoG+cZh4tZLQIAZimJail0\
882+ 0zq4DVJVljO6cZ2t8kIto/QVk+7p20Fcf2nvqZyL2ZCda2Ei7VsqWZHTM/gqa2IU9+ktkwz\
883+ +KFhENnHvDhG9f+hjsAPZd5mTTpdO+tVcqtdWhX4dymaJ/2UpAAjuPXQW+nXhQWQhXgXOUa\
884+ JCYurJtvbCbqZGeDMmVIoqukBs2KugNJ6j5WlTPoeFnMl6Guy9uH2iWWxGg8ZgT2xspqVl5\
885+ CwujjC+m7Dh1toVkvu+bAw\
886+ ",
887+ )
888+ . unwrap ( )
889+ }
688890}
0 commit comments