@@ -77,8 +77,8 @@ use crate::{
77
77
Session , StaticAccountData ,
78
78
} ,
79
79
types:: {
80
- BackupSecrets , CrossSigningSecrets , MegolmBackupV1Curve25519AesSha2Secrets , RoomKeyExport ,
81
- SecretsBundle ,
80
+ events :: room_key_withheld :: MegolmV1AesSha2WithheldContent , BackupSecrets ,
81
+ CrossSigningSecrets , MegolmBackupV1Curve25519AesSha2Secrets , RoomKeyExport , SecretsBundle ,
82
82
} ,
83
83
verification:: VerificationMachine ,
84
84
CrossSigningStatus , OwnUserIdentityData , RoomKeyImportResult ,
@@ -1632,12 +1632,11 @@ impl Store {
1632
1632
1633
1633
tracing:: Span :: current ( ) . record ( "sender_data" , tracing:: field:: debug ( & sender_data) ) ;
1634
1634
1635
- match sender_data {
1635
+ match & sender_data {
1636
1636
SenderData :: UnknownDevice { .. }
1637
1637
| SenderData :: VerificationViolation ( _)
1638
1638
| SenderData :: DeviceInfo { .. } => {
1639
1639
warn ! ( "Not accepting a historic room key bundle due to insufficient trust in the sender" ) ;
1640
- Ok ( ( ) )
1641
1640
}
1642
1641
SenderData :: SenderUnverified ( _) | SenderData :: SenderVerified ( _) => {
1643
1642
let ( good, bad) : ( Vec < _ > , Vec < _ > ) = bundle. room_keys . iter ( ) . partition_map ( |key| {
@@ -1681,10 +1680,28 @@ impl Store {
1681
1680
self . import_sessions_impl ( good, None , progress_listener) . await ?;
1682
1681
}
1683
1682
}
1683
+ }
1684
+ }
1684
1685
1685
- Ok ( ( ) )
1686
+ let mut changes = Changes :: default ( ) ;
1687
+ for withheld in & bundle. withheld {
1688
+ if let RoomKeyWithheldContent :: MegolmV1AesSha2 (
1689
+ MegolmV1AesSha2WithheldContent :: BlackListed ( c)
1690
+ | MegolmV1AesSha2WithheldContent :: Unverified ( c)
1691
+ | MegolmV1AesSha2WithheldContent :: Unauthorised ( c)
1692
+ | MegolmV1AesSha2WithheldContent :: Unavailable ( c) ,
1693
+ ) = withheld
1694
+ {
1695
+ changes
1696
+ . withheld_session_info
1697
+ . entry ( c. room_id . to_owned ( ) )
1698
+ . or_default ( )
1699
+ . insert ( c. session_id . to_owned ( ) , withheld. to_owned ( ) . into ( ) ) ;
1686
1700
}
1687
1701
}
1702
+ self . save_changes ( changes) . await ?;
1703
+
1704
+ Ok ( ( ) )
1688
1705
}
1689
1706
}
1690
1707
@@ -1717,17 +1734,32 @@ impl matrix_sdk_common::cross_process_lock::TryLock for LockableCryptoStore {
1717
1734
mod tests {
1718
1735
use std:: pin:: pin;
1719
1736
1737
+ use assert_matches2:: assert_matches;
1720
1738
use futures_util:: StreamExt ;
1721
1739
use insta:: { _macro_support:: Content , assert_json_snapshot, internals:: ContentPath } ;
1722
1740
use matrix_sdk_test:: async_test;
1723
- use ruma:: { device_id, room_id, user_id, RoomId } ;
1741
+ use ruma:: {
1742
+ device_id,
1743
+ events:: room:: { EncryptedFileInit , JsonWebKeyInit } ,
1744
+ owned_mxc_uri, room_id,
1745
+ serde:: Base64 ,
1746
+ user_id, RoomId ,
1747
+ } ;
1724
1748
use vodozemac:: megolm:: SessionKey ;
1725
1749
1726
1750
use crate :: {
1727
1751
machine:: test_helpers:: get_machine_pair,
1728
1752
olm:: { InboundGroupSession , SenderData } ,
1729
- store:: types:: DehydratedDeviceKey ,
1730
- types:: EventEncryptionAlgorithm ,
1753
+ store:: types:: { DehydratedDeviceKey , StoredRoomKeyBundleData } ,
1754
+ types:: {
1755
+ events:: {
1756
+ room_key_bundle:: RoomKeyBundleContent ,
1757
+ room_key_withheld:: {
1758
+ MegolmV1AesSha2WithheldContent , RoomKeyWithheldContent , RoomKeyWithheldEntry ,
1759
+ } ,
1760
+ } ,
1761
+ EventEncryptionAlgorithm ,
1762
+ } ,
1731
1763
OlmMachine ,
1732
1764
} ;
1733
1765
@@ -1969,6 +2001,90 @@ mod tests {
1969
2001
} ) ;
1970
2002
}
1971
2003
2004
+ #[ async_test]
2005
+ async fn test_receive_room_key_bundle ( ) {
2006
+ let alice = OlmMachine :: new ( user_id ! ( "@a:s.co" ) , device_id ! ( "ALICE" ) ) . await ;
2007
+ let alice_key = alice. identity_keys ( ) . curve25519 ;
2008
+ let bob = OlmMachine :: new ( user_id ! ( "@b:s.co" ) , device_id ! ( "BOB" ) ) . await ;
2009
+
2010
+ let room_id = room_id ! ( "!room1:localhost" ) ;
2011
+
2012
+ let session_key1 = "AgAAAAC2XHVzsMBKs4QCRElJ92CJKyGtknCSC8HY7cQ7UYwndMKLQAejXLh5UA0l6s736mgctcUMNvELScUWrObdflrHo+vth/gWreXOaCnaSxmyjjKErQwyIYTkUfqbHy40RJfEesLwnN23on9XAkch/iy8R2+Jz7B8zfG01f2Ow2SxPQFnAndcO1ZSD2GmXgedy6n4B20MWI1jGP2wiexOWbFSya8DO/VxC9m5+/mF+WwYqdpKn9g4Y05Yw4uz7cdjTc3rXm7xK+8E7hI//5QD1nHPvuKYbjjM9u2JSL+Bzp61Cw" ;
2013
+ let session_key2 = "AgAAAAC1BXreFTUQQSBGekTEuYxhdytRKyv4JgDGcG+VOBYdPNGgs807SdibCGJky4lJ3I+7ZDGHoUzZPZP/4ogGu4kxni0PWdtWuN7+5zsuamgoFF/BkaGeUUGv6kgIkx8pyPpM5SASTUEP9bN2loDSpUPYwfiIqz74DgC4WQ4435sTBctYvKz8n+TDJwdLXpyT6zKljuqADAioud+s/iqx9LYn9HpbBfezZcvbg67GtE113pLrvde3IcPI5s6dNHK2onGO2B2eoaobcen18bbEDnlUGPeIivArLya7Da6us14jBQ" ;
2014
+
2015
+ let sessions = [
2016
+ create_inbound_group_session_with_visibility (
2017
+ & alice,
2018
+ room_id,
2019
+ & SessionKey :: from_base64 ( session_key1) . unwrap ( ) ,
2020
+ true ,
2021
+ ) ,
2022
+ create_inbound_group_session_with_visibility (
2023
+ & alice,
2024
+ room_id,
2025
+ & SessionKey :: from_base64 ( session_key2) . unwrap ( ) ,
2026
+ false ,
2027
+ ) ,
2028
+ ] ;
2029
+
2030
+ alice. store ( ) . save_inbound_group_sessions ( & sessions) . await . unwrap ( ) ;
2031
+ let bundle = alice. store ( ) . build_room_key_bundle ( room_id) . await . unwrap ( ) ;
2032
+
2033
+ bob. store ( )
2034
+ . receive_room_key_bundle (
2035
+ & StoredRoomKeyBundleData {
2036
+ sender_user : alice. user_id ( ) . to_owned ( ) ,
2037
+ sender_key : alice_key. clone ( ) ,
2038
+ sender_data : SenderData :: sender_verified (
2039
+ alice. user_id ( ) ,
2040
+ device_id ! ( "ALICE" ) ,
2041
+ alice. identity_keys ( ) . ed25519 ,
2042
+ ) ,
2043
+
2044
+ bundle_data : RoomKeyBundleContent {
2045
+ room_id : room_id. to_owned ( ) ,
2046
+ // This isn't used at all in the method call, so we can fill it with
2047
+ // garbage.
2048
+ file : EncryptedFileInit {
2049
+ url : owned_mxc_uri ! ( "mxc://example.com/0" ) ,
2050
+ key : JsonWebKeyInit {
2051
+ kty : "oct" . to_string ( ) ,
2052
+ key_ops : vec ! [ "encrypt" . to_string( ) , "decrypt" . to_string( ) ] ,
2053
+ alg : "A256CTR." . to_string ( ) ,
2054
+ k : Base64 :: new ( vec ! [ 0u8 ; 128 ] ) ,
2055
+ ext : true ,
2056
+ }
2057
+ . into ( ) ,
2058
+ iv : Base64 :: new ( vec ! [ 0u8 ; 128 ] ) ,
2059
+ hashes : vec ! [ ( "sha256" . to_string( ) , Base64 :: new( vec![ 0u8 ; 128 ] ) ) ]
2060
+ . into_iter ( )
2061
+ . collect ( ) ,
2062
+ v : "v2" . to_string ( ) ,
2063
+ }
2064
+ . into ( ) ,
2065
+ } ,
2066
+ } ,
2067
+ bundle,
2068
+ |_, _| { } ,
2069
+ )
2070
+ . await
2071
+ . unwrap ( ) ;
2072
+
2073
+ // The room key should be imported successfully
2074
+ let imported_sessions =
2075
+ bob. store ( ) . get_inbound_group_sessions_by_room_id ( room_id) . await . unwrap ( ) ;
2076
+
2077
+ assert_eq ! ( imported_sessions. len( ) , 1 ) ;
2078
+ assert_eq ! ( imported_sessions[ 0 ] . room_id( ) , room_id) ;
2079
+
2080
+ assert_matches ! (
2081
+ bob. store( ) . get_withheld_info( room_id, sessions[ 1 ] . session_id( ) ) . await . unwrap( ) ,
2082
+ Some ( RoomKeyWithheldEntry :: Bundle ( RoomKeyWithheldContent :: MegolmV1AesSha2 (
2083
+ MegolmV1AesSha2WithheldContent :: Unauthorised ( _)
2084
+ ) ) )
2085
+ ) ;
2086
+ }
2087
+
1972
2088
/// Create an inbound Megolm session for the given room.
1973
2089
///
1974
2090
/// `olm_machine` is used to set the `sender_key` and `signing_key`
0 commit comments