Skip to content

Commit afb6627

Browse files
authored
fix(crypto): Fixed a bug where room keys would be rotated unecessarily
Previously, `is_session_overshared_for_user` did not take into account that `shared_with_set` also contains withheld device IDs who explicitly have never received the session keys. This would lead to it mistakenly determining oversharing for those devices for every event being sent in the presence of blacklisted/withheld devices in the room, and rotating the group session accordingly. The fix is to correctly exclude devices with `ShareInfo::Withheld` from the enumeration. Signed-off-by: Niklas Baumstark niklas.baumstark@gmail.com
1 parent 8c3f554 commit afb6627

File tree

2 files changed

+60
-7
lines changed

2 files changed

+60
-7
lines changed

crates/matrix-sdk-crypto/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ All notable changes to this project will be documented in this file.
2020
(as per [MSC4147](https://github.com/matrix-org/matrix-spec-proposals/pull/4147)).
2121
([#4922](https://github.com/matrix-org/matrix-rust-sdk/pull/4922))
2222

23+
- Fix bug which caused room keys to be unnecessarily rotated on every send in the
24+
presence of blacklisted/withheld devices in the room.
25+
([#4954](https://github.com/matrix-org/matrix-rust-sdk/pull/4954))
26+
2327
## [0.11.0] - 2025-04-11
2428

2529
### Features

crates/matrix-sdk-crypto/src/session_manager/group_sessions/share_strategy.rs

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use tracing::{debug, instrument, trace};
2727
use super::OutboundGroupSession;
2828
use crate::{
2929
error::{OlmResult, SessionRecipientCollectionError},
30+
olm::ShareInfo,
3031
store::Store,
3132
DeviceData, EncryptionSettings, LocalTrust, OlmError, OwnUserIdentityData, UserIdentityData,
3233
};
@@ -433,7 +434,11 @@ fn is_session_overshared_for_user(
433434
};
434435

435436
// Devices that received this session
436-
let shared: BTreeSet<&DeviceId> = shared.keys().map(|d| d.as_ref()).collect();
437+
let shared: BTreeSet<&DeviceId> = shared
438+
.iter()
439+
.filter(|(_, info)| matches!(info, ShareInfo::Shared(_)))
440+
.map(|(d, _)| d.as_ref())
441+
.collect();
437442

438443
// The set difference between
439444
//
@@ -2095,9 +2100,55 @@ mod tests {
20952100
let machine = test_machine().await;
20962101
import_known_users_to_test_machine(&machine).await;
20972102

2098-
let fake_room_id = room_id!("!roomid:localhost");
20992103
let encryption_settings = all_devices_strategy_settings();
2104+
let group_session = create_test_outbound_group_session(&machine, &encryption_settings);
2105+
let sender_key = machine.identity_keys().curve25519;
2106+
2107+
group_session
2108+
.mark_shared_with(
2109+
KeyDistributionTestData::dan_id(),
2110+
KeyDistributionTestData::dan_signed_device_id(),
2111+
sender_key,
2112+
)
2113+
.await;
2114+
group_session
2115+
.mark_shared_with(
2116+
KeyDistributionTestData::dan_id(),
2117+
KeyDistributionTestData::dan_unsigned_device_id(),
2118+
sender_key,
2119+
)
2120+
.await;
2121+
2122+
// Try to share again after dan has removed one of his devices
2123+
let keys_query = KeyDistributionTestData::dan_keys_query_response_device_loggedout();
2124+
machine.mark_request_as_sent(&TransactionId::new(), &keys_query).await.unwrap();
21002125

2126+
// share again
2127+
let share_result = collect_session_recipients(
2128+
machine.store(),
2129+
vec![KeyDistributionTestData::dan_id()].into_iter(),
2130+
&encryption_settings,
2131+
&group_session,
2132+
)
2133+
.await
2134+
.unwrap();
2135+
2136+
assert!(share_result.should_rotate);
2137+
}
2138+
2139+
/// Test that the session is not rotated if a devices is removed
2140+
/// but was already withheld from receiving the session.
2141+
#[async_test]
2142+
async fn test_should_not_rotate_if_keys_were_withheld() {
2143+
let machine = test_machine().await;
2144+
import_known_users_to_test_machine(&machine).await;
2145+
2146+
let encryption_settings = all_devices_strategy_settings();
2147+
let group_session = create_test_outbound_group_session(&machine, &encryption_settings);
2148+
let fake_room_id = group_session.room_id();
2149+
2150+
// Because we don't have Olm sessions initialized, this will contain
2151+
// withheld requests for both of Dan's devices
21012152
let requests = machine
21022153
.share_room_key(
21032154
fake_room_id,
@@ -2115,13 +2166,11 @@ mod tests {
21152166
.await
21162167
.unwrap();
21172168
}
2169+
21182170
// Try to share again after dan has removed one of his devices
21192171
let keys_query = KeyDistributionTestData::dan_keys_query_response_device_loggedout();
2120-
let txn_id = TransactionId::new();
2121-
machine.mark_request_as_sent(&txn_id, &keys_query).await.unwrap();
2172+
machine.mark_request_as_sent(&TransactionId::new(), &keys_query).await.unwrap();
21222173

2123-
let group_session =
2124-
machine.store().get_outbound_group_session(fake_room_id).await.unwrap().unwrap();
21252174
// share again
21262175
let share_result = collect_session_recipients(
21272176
machine.store(),
@@ -2132,7 +2181,7 @@ mod tests {
21322181
.await
21332182
.unwrap();
21342183

2135-
assert!(share_result.should_rotate);
2184+
assert!(!share_result.should_rotate);
21362185
}
21372186

21382187
/// Common setup for tests which require a verified user to have unsigned

0 commit comments

Comments
 (0)