@@ -34,7 +34,7 @@ use matrix_sdk_common::{
34
34
BoxFuture ,
35
35
} ;
36
36
#[ cfg( feature = "experimental-encrypted-state-events" ) ]
37
- use ruma:: events:: { AnyStateEventContent , StateEventContent } ;
37
+ use ruma:: events:: { AnyStateEvent , AnyStateEventContent , StateEventContent } ;
38
38
use ruma:: {
39
39
api:: client:: {
40
40
dehydrated_device:: DehydratedDeviceData ,
@@ -2259,9 +2259,62 @@ impl OlmMachine {
2259
2259
. await ;
2260
2260
}
2261
2261
2262
- let event = serde_json:: from_value :: < Raw < AnyTimelineEvent > > ( decrypted_event. into ( ) ) ?;
2262
+ let decrypted_event =
2263
+ serde_json:: from_value :: < Raw < AnyTimelineEvent > > ( decrypted_event. into ( ) ) ?;
2263
2264
2264
- Ok ( DecryptedRoomEvent { event, encryption_info, unsigned_encryption_info } )
2265
+ #[ cfg( feature = "experimental-encrypted-state-events" ) ]
2266
+ self . verify_packed_state_key ( & event, & decrypted_event) ?;
2267
+
2268
+ Ok ( DecryptedRoomEvent { event : decrypted_event, encryption_info, unsigned_encryption_info } )
2269
+ }
2270
+
2271
+ /// If the passed event is a state event, verify its outer packed state key
2272
+ /// matches the inner state key once unpacked.
2273
+ ///
2274
+ /// * `original` - The original encrypted event received over the wire.
2275
+ /// * `decrypted` - The decrypted event.
2276
+ ///
2277
+ /// # Errors
2278
+ ///
2279
+ /// Returns an error if
2280
+ ///
2281
+ /// * The original event's state key failed to unpack;
2282
+ /// * The decrypted event could not be deserialised;
2283
+ /// * The unpacked event type does not match the type of the decrypted
2284
+ /// event;
2285
+ /// * The unpacked event state key does not match the state key of the
2286
+ /// decrypted event.
2287
+ #[ cfg( feature = "experimental-encrypted-state-events" ) ]
2288
+ pub fn verify_packed_state_key (
2289
+ & self ,
2290
+ original : & EncryptedEvent ,
2291
+ decrypted : & Raw < AnyTimelineEvent > ,
2292
+ ) -> MegolmResult < ( ) > {
2293
+ // We only need to verify state events.
2294
+ let Some ( raw_state_key) = & original. state_key else { return Ok ( ( ) ) } ;
2295
+
2296
+ // Unpack event type and state key from the raw state key.
2297
+ let ( outer_event_type, outer_state_key) =
2298
+ raw_state_key. split_once ( ":" ) . ok_or ( MegolmError :: StateKeyVerificationFailed ) ?;
2299
+
2300
+ // Deserialize the decrypted event.
2301
+ let AnyTimelineEvent :: State ( inner) =
2302
+ decrypted. deserialize ( ) . map_err ( MegolmError :: JsonError ) ?
2303
+ else {
2304
+ return Err ( MegolmError :: StateKeyVerificationFailed ) ;
2305
+ } ;
2306
+
2307
+ // Check event types match, discard if not.
2308
+ let inner_event_type = inner. event_type ( ) . to_string ( ) ;
2309
+ if outer_event_type != inner_event_type {
2310
+ return Err ( MegolmError :: StateKeyVerificationFailed ) ;
2311
+ }
2312
+
2313
+ // Check state keys match, discard if not.
2314
+ if outer_state_key != inner. state_key ( ) {
2315
+ return Err ( MegolmError :: StateKeyVerificationFailed ) ;
2316
+ }
2317
+ Ok ( ( ) )
2265
2318
}
2266
2319
2267
2320
/// Try to decrypt the events bundled in the `unsigned` object of the given
@@ -3032,6 +3085,8 @@ fn megolm_error_to_utd_info(
3032
3085
JsonError ( _) => UnableToDecryptReason :: PayloadDeserializationFailure ,
3033
3086
MismatchedIdentityKeys ( _) => UnableToDecryptReason :: MismatchedIdentityKeys ,
3034
3087
SenderIdentityNotTrusted ( level) => UnableToDecryptReason :: SenderIdentityNotTrusted ( level) ,
3088
+ #[ cfg( feature = "experimental-encrypted-state-events" ) ]
3089
+ StateKeyVerificationFailed => UnableToDecryptReason :: StateKeyVerificationFailed ,
3035
3090
3036
3091
// Pass through crypto store errors, which indicate a problem with our
3037
3092
// application, rather than a UTD.
0 commit comments