Skip to content

Commit d53fe25

Browse files
committed
crypto: Fetch immediately-available sender data when we receive a room key
1 parent 03dc672 commit d53fe25

File tree

11 files changed

+418
-46
lines changed

11 files changed

+418
-46
lines changed

bindings/matrix-sdk-crypto-ffi/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub use logger::{set_logger, Logger};
3131
pub use machine::{KeyRequestPair, OlmMachine, SignatureVerification};
3232
use matrix_sdk_common::deserialized_responses::ShieldState as RustShieldState;
3333
use matrix_sdk_crypto::{
34-
olm::{IdentityKeys, InboundGroupSession, Session},
34+
olm::{IdentityKeys, InboundGroupSession, SenderData, Session},
3535
store::{Changes, CryptoStore, PendingChanges, RoomSettings as RustRoomSettings},
3636
types::{EventEncryptionAlgorithm as RustEventEncryptionAlgorithm, SigningKey},
3737
EncryptionSettings as RustEncryptionSettings,
@@ -471,6 +471,7 @@ fn collect_sessions(
471471
Ok((algorithm, key))
472472
})
473473
.collect::<anyhow::Result<_>>()?,
474+
sender_data: SenderData::new(), // TODO: what should happen here?
474475
room_id: RoomId::parse(session.room_id)?,
475476
imported: session.imported,
476477
backed_up: session.backed_up,

crates/matrix-sdk-crypto/src/machine.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ use crate::{
6363
identities::{user::UserIdentities, Device, IdentityManager, UserDevices},
6464
olm::{
6565
Account, CrossSigningStatus, EncryptionSettings, IdentityKeys, InboundGroupSession,
66-
OlmDecryptionInfo, PrivateCrossSigningIdentity, SessionType, StaticAccountData,
66+
OlmDecryptionInfo, PrivateCrossSigningIdentity, SenderDataFinder, SessionType,
67+
StaticAccountData,
6768
},
6869
requests::{IncomingResponse, OutgoingRequest, UploadSigningKeysRequest},
6970
session_manager::{GroupSessionManager, SessionManager},
@@ -806,11 +807,14 @@ impl OlmMachine {
806807
event: &DecryptedRoomKeyEvent,
807808
content: &MegolmV1AesSha2Content,
808809
) -> OlmResult<Option<InboundGroupSession>> {
810+
let sender_data = SenderDataFinder::find(self, sender_key, event, content).await?;
811+
809812
let session = InboundGroupSession::new(
810813
sender_key,
811814
event.keys.ed25519,
812815
&content.room_id,
813816
&content.session_key,
817+
sender_data,
814818
event.content.algorithm(),
815819
None,
816820
);
@@ -2263,7 +2267,8 @@ pub(crate) mod tests {
22632267
error::{EventError, SetRoomSettingsError},
22642268
machine::{EncryptionSyncChanges, OlmMachine},
22652269
olm::{
2266-
BackedUpRoomKey, ExportedRoomKey, InboundGroupSession, OutboundGroupSession, VerifyJson,
2270+
BackedUpRoomKey, ExportedRoomKey, InboundGroupSession, OutboundGroupSession,
2271+
SenderData, VerifyJson,
22672272
},
22682273
store::{BackupDecryptionKey, Changes, CryptoStore, MemoryStore, RoomSettings},
22692274
types::{
@@ -3556,6 +3561,7 @@ pub(crate) mod tests {
35563561
Ed25519PublicKey::from_base64("loz5i40dP+azDtWvsD0L/xpnCjNkmrcvtXVXzCHX8Vw").unwrap(),
35573562
fake_room_id,
35583563
&olm,
3564+
SenderData::new(),
35593565
EventEncryptionAlgorithm::MegolmV1AesSha2,
35603566
None,
35613567
)
@@ -3573,6 +3579,7 @@ pub(crate) mod tests {
35733579
Ed25519PublicKey::from_base64("48f3WQAMGwYLBg5M5qUhqnEVA8yeibjZpPsShoWMFT8").unwrap(),
35743580
fake_room_id,
35753581
&olm,
3582+
SenderData::new(),
35763583
EventEncryptionAlgorithm::MegolmV1AesSha2,
35773584
None,
35783585
)

crates/matrix-sdk-crypto/src/olm/account.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ use crate::{
6161
dehydrated_devices::DehydrationError,
6262
error::{EventError, OlmResult, SessionCreationError},
6363
identities::ReadOnlyDevice,
64+
olm::SenderData,
6465
requests::UploadSigningKeysRequest,
6566
store::{Changes, Store},
6667
types::{
@@ -220,6 +221,7 @@ impl StaticAccountData {
220221
signing_key,
221222
room_id,
222223
&outbound.session_key().await,
224+
SenderData::new(), // TODO: provide sender data about ourself
223225
algorithm,
224226
Some(visibility),
225227
)?;

crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ use vodozemac::{
3838
};
3939

4040
use super::{
41-
inbound_group_session_sender_data::InboundGroupSessionSenderData, BackedUpRoomKey,
42-
ExportedRoomKey, OutboundGroupSession, SessionCreationError, SessionKey,
41+
BackedUpRoomKey, ExportedRoomKey, OutboundGroupSession, SenderData, SessionCreationError,
42+
SessionKey,
4343
};
4444
use crate::{
4545
error::{EventError, MegolmResult},
@@ -129,7 +129,7 @@ pub struct InboundGroupSession {
129129
/// the session, or, if we can use that device information to find the
130130
/// sender's cross-signing identity, holds the user ID and cross-signing
131131
/// key.
132-
pub(crate) sender_data: InboundGroupSessionSenderData,
132+
pub(crate) sender_data: SenderData,
133133

134134
/// The Room this GroupSession belongs to
135135
pub room_id: OwnedRoomId,
@@ -173,11 +173,15 @@ impl InboundGroupSession {
173173
///
174174
/// * `session_key` - The private session key that is used to decrypt
175175
/// messages.
176+
///
177+
/// * `sender_data` - Information about the sender of the to-device
178+
/// message that established this session.
176179
pub fn new(
177180
sender_key: Curve25519PublicKey,
178181
signing_key: Ed25519PublicKey,
179182
room_id: &RoomId,
180183
session_key: &SessionKey,
184+
sender_data: SenderData,
181185
encryption_algorithm: EventEncryptionAlgorithm,
182186
history_visibility: Option<HistoryVisibility>,
183187
) -> Result<Self, SessionCreationError> {
@@ -199,7 +203,7 @@ impl InboundGroupSession {
199203
curve25519_key: sender_key,
200204
signing_keys: keys.into(),
201205
},
202-
sender_data: InboundGroupSessionSenderData::default(),
206+
sender_data,
203207
room_id: room_id.into(),
204208
imported: false,
205209
algorithm: encryption_algorithm.into(),
@@ -507,7 +511,7 @@ pub struct PickledInboundGroupSession {
507511
pub signing_key: SigningKeys<DeviceKeyAlgorithm>,
508512
/// Information on the device/sender who sent us this session
509513
#[serde(default)]
510-
pub sender_data: InboundGroupSessionSenderData,
514+
pub sender_data: SenderData,
511515
/// The id of the room that the session is used in.
512516
pub room_id: OwnedRoomId,
513517
/// Flag remembering if the session was directly sent to us by the sender
@@ -543,7 +547,7 @@ impl TryFrom<&ExportedRoomKey> for InboundGroupSession {
543547
signing_keys: key.sender_claimed_keys.to_owned().into(),
544548
},
545549
// TODO: in future, exported keys should contain sender data that we can use here
546-
sender_data: InboundGroupSessionSenderData::default(),
550+
sender_data: SenderData::default(),
547551
history_visibility: None.into(),
548552
first_known_index,
549553
room_id: key.room_id.to_owned(),
@@ -572,7 +576,7 @@ impl From<&ForwardedMegolmV1AesSha2Content> for InboundGroupSession {
572576
.into(),
573577
},
574578
// TODO: in future, forwarded keys should contain sender data that we can use here
575-
sender_data: InboundGroupSessionSenderData::default(),
579+
sender_data: SenderData::default(),
576580
history_visibility: None.into(),
577581
first_known_index,
578582
room_id: value.room_id.to_owned(),
@@ -597,7 +601,7 @@ impl From<&ForwardedMegolmV2AesSha2Content> for InboundGroupSession {
597601
signing_keys: value.claimed_signing_keys.to_owned().into(),
598602
},
599603
// TODO: in future, forwarded keys should contain sender data that we can use here
600-
sender_data: InboundGroupSessionSenderData::default(),
604+
sender_data: SenderData::default(),
601605
history_visibility: None.into(),
602606
first_known_index,
603607
room_id: value.room_id.to_owned(),
@@ -628,18 +632,15 @@ mod tests {
628632
use matrix_sdk_test::async_test;
629633
use ruma::{
630634
device_id, events::room::history_visibility::HistoryVisibility, room_id, user_id, DeviceId,
631-
MilliSecondsSinceUnixEpoch, UInt, UserId,
635+
UInt, UserId,
632636
};
633637
use vodozemac::{
634638
megolm::{SessionKey, SessionOrdering},
635639
Curve25519PublicKey, Ed25519PublicKey,
636640
};
637641

638642
use crate::{
639-
olm::{
640-
group_sessions::inbound_group_session_sender_data::InboundGroupSessionSenderData,
641-
InboundGroupSession,
642-
},
643+
olm::{InboundGroupSession, SenderData, SenderDataRetryDetails},
643644
types::EventEncryptionAlgorithm,
644645
Account,
645646
};
@@ -702,8 +703,7 @@ mod tests {
702703

703704
// We populated the InboundGroupSession's sender_data with a default value,
704705
// with legacy_session set to true.
705-
let InboundGroupSessionSenderData::UnknownDevice { retry_details, legacy_session } =
706-
unpickled.sender_data
706+
let SenderData::UnknownDevice { retry_details, legacy_session } = unpickled.sender_data
707707
else {
708708
panic!("Expected sender_data to be UnknownDevice!");
709709
};
@@ -720,20 +720,14 @@ mod tests {
720720
Ed25519PublicKey::from_base64("wTRTdz4rn4EY+68cKPzpMdQ6RAlg7T8cbTmEjaXuUww").unwrap(),
721721
room_id!("!test:localhost"),
722722
&create_session_key(),
723+
SenderData::unknown(SenderDataRetryDetails::new(5, 1234)),
723724
EventEncryptionAlgorithm::MegolmV1AesSha2,
724725
Some(HistoryVisibility::Shared),
725726
)
726727
.unwrap();
727728

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());
729+
// When we pickle it
730+
let pickled = igs.pickle().await;
737731

738732
// And serialise it
739733
let serialised = serde_json::to_string(&pickled).unwrap();
@@ -770,7 +764,7 @@ mod tests {
770764
"sender_data":{
771765
"UnknownDevice":{
772766
"retry_details":{
773-
"retry_count":0,
767+
"retry_count":5,
774768
"next_retry_time_ms":1234
775769
},
776770
"legacy_session":true
@@ -843,8 +837,7 @@ mod tests {
843837
assert_eq!(unpickled.session_id(), "XbmrPa1kMwmdtNYng1B2gsfoo8UtF+NklzsTZiaVKyY");
844838

845839
// We populated the InboundGroupSession's sender_data with a default value
846-
let InboundGroupSessionSenderData::UnknownDevice { retry_details, legacy_session } =
847-
unpickled.sender_data
840+
let SenderData::UnknownDevice { retry_details, legacy_session } = unpickled.sender_data
848841
else {
849842
panic!("Expected sender_data to be UnknownDevice!");
850843
};

crates/matrix-sdk-crypto/src/olm/group_sessions/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,17 @@ use ruma::{DeviceKeyAlgorithm, OwnedRoomId};
1616
use serde::{Deserialize, Serialize};
1717

1818
mod inbound;
19-
mod inbound_group_session_sender_data;
2019
mod outbound;
20+
mod sender_data;
21+
mod sender_data_finder;
2122

2223
pub use inbound::{InboundGroupSession, PickledInboundGroupSession};
2324
pub(crate) use outbound::ShareState;
2425
pub use outbound::{
2526
EncryptionSettings, OutboundGroupSession, PickledOutboundGroupSession, ShareInfo,
2627
};
28+
pub use sender_data::{SenderData, SenderDataRetryDetails};
29+
pub(crate) use sender_data_finder::SenderDataFinder;
2730
use thiserror::Error;
2831
pub use vodozemac::megolm::{ExportedSessionKey, SessionKey};
2932
use vodozemac::{megolm::SessionKeyDecodeError, Curve25519PublicKey};

crates/matrix-sdk-crypto/src/olm/group_sessions/outbound.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,7 @@ impl OutboundGroupSession {
513513
self.room_id().to_owned(),
514514
self.session_id().to_owned(),
515515
session_key,
516+
None, // AJB
516517
)
517518
.into(),
518519
)
Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ use crate::types::DeviceKeys;
2424
/// state when we get the device info. Finally, if we can look up the sender
2525
/// using the device info, the session can be moved into `SenderKnown` state.
2626
#[derive(Clone, Debug, Deserialize, Serialize)]
27-
pub enum InboundGroupSessionSenderData {
27+
pub enum SenderData {
2828
/// We have not yet found the (signed) device info for the sending device
2929
UnknownDevice {
3030
// TODO: we may need to handle unsigned and unknown devices separately, which
3131
// probably necessitates a flag here
3232
/// When we will next try again to find device info for this session,
3333
/// and how many times we have tried
34-
retry_details: RetryDetails,
34+
retry_details: SenderDataRetryDetails,
3535

3636
/// Was this session created before we started collecting trust
3737
/// information about sessions? If so, we may choose to display its
@@ -47,7 +47,7 @@ pub enum InboundGroupSessionSenderData {
4747
device_keys: DeviceKeys,
4848
/// When we will next try again to find a cross-signing key that signed
4949
/// the device information, and how many times we have tried.
50-
retry_details: RetryDetails,
50+
retry_details: SenderDataRetryDetails,
5151

5252
/// Was this session created before we started collecting trust
5353
/// information about sessions? If so, we may choose to display its
@@ -72,29 +72,74 @@ pub enum InboundGroupSessionSenderData {
7272
},
7373
}
7474

75+
impl SenderData {
76+
/// Create a [`SenderData`] which contains no device info and will be
77+
/// retried soon.
78+
pub fn new() -> Self {
79+
Self::UnknownDevice {
80+
retry_details: SenderDataRetryDetails::retry_soon(),
81+
// TODO: when we have implemented all of SenderDataFinder,
82+
// legacy_session should be set to false, but for now we leave
83+
// it as true because we might lose device info while
84+
// this code is still in transition.
85+
legacy_session: true,
86+
}
87+
}
88+
89+
/// Create a [`SenderData`] which has the legacy flag set. Caution: messages
90+
/// within sessions with this flag will be displayed in some contexts,
91+
/// even when we are unable to verify the sender.
92+
///
93+
/// The returned struct contains no device info, and will be retried soon.
94+
pub(crate) fn legacy() -> Self {
95+
Self::UnknownDevice {
96+
retry_details: SenderDataRetryDetails::retry_soon(),
97+
legacy_session: true,
98+
}
99+
}
100+
101+
#[cfg(test)]
102+
pub(crate) fn unknown(retry_details: SenderDataRetryDetails) -> Self {
103+
Self::UnknownDevice { retry_details, legacy_session: false }
104+
}
105+
}
106+
107+
/// Used when deserialising and the sender_data property is missing.
75108
/// If we are deserialising an InboundGroupSession session with missing
76109
/// sender_data, this must be a legacy session (i.e. it was created before we
77110
/// started tracking sender data). We set its legacy flag to true, and set it up
78111
/// to be retried soon, so we can populate it with trust information if it is
79112
/// available.
80-
impl Default for InboundGroupSessionSenderData {
113+
impl Default for SenderData {
81114
fn default() -> Self {
82-
Self::UnknownDevice { retry_details: RetryDetails::retry_soon(), legacy_session: true }
115+
Self::legacy()
83116
}
84117
}
85118

86119
/// Tracking information about when we need to try again fetching device or
87120
/// user information, and how many times we have already tried.
88121
#[derive(Clone, Debug, Deserialize, Serialize)]
89-
pub struct RetryDetails {
90-
pub retry_count: u8,
91-
pub next_retry_time_ms: MilliSecondsSinceUnixEpoch,
122+
pub struct SenderDataRetryDetails {
123+
retry_count: u8,
124+
next_retry_time_ms: MilliSecondsSinceUnixEpoch,
92125
}
93126

94-
impl RetryDetails {
127+
impl SenderDataRetryDetails {
95128
/// Create a new RetryDetails with a retry count of zero, and retry time of
96129
/// now.
97130
pub(crate) fn retry_soon() -> Self {
98131
Self { retry_count: 0, next_retry_time_ms: MilliSecondsSinceUnixEpoch::now() }
99132
}
133+
134+
#[cfg(test)]
135+
pub(crate) fn new(retry_count: u8, next_retry_time_ms: u64) -> Self {
136+
use ruma::UInt;
137+
138+
Self {
139+
retry_count,
140+
next_retry_time_ms: MilliSecondsSinceUnixEpoch(
141+
UInt::try_from(next_retry_time_ms).unwrap_or(UInt::from(0u8)),
142+
),
143+
}
144+
}
100145
}

0 commit comments

Comments
 (0)