1use std::{
16 collections::{BTreeMap, HashMap, HashSet},
17 sync::Arc,
18 time::Duration,
19};
20
21use itertools::Itertools;
22#[cfg(feature = "experimental-send-custom-to-device")]
23use matrix_sdk_common::deserialized_responses::WithheldCode;
24use matrix_sdk_common::{
25 deserialized_responses::{
26 AlgorithmInfo, DecryptedRoomEvent, DeviceLinkProblem, EncryptionInfo, UnableToDecryptInfo,
27 UnableToDecryptReason, UnsignedDecryptionResult, UnsignedEventLocation, VerificationLevel,
28 VerificationState,
29 },
30 locks::RwLock as StdRwLock,
31 BoxFuture,
32};
33use ruma::{
34 api::client::{
35 dehydrated_device::DehydratedDeviceData,
36 keys::{
37 claim_keys::v3::Request as KeysClaimRequest,
38 get_keys::v3::Response as KeysQueryResponse,
39 upload_keys::v3::{Request as UploadKeysRequest, Response as UploadKeysResponse},
40 upload_signatures::v3::Request as UploadSignaturesRequest,
41 },
42 sync::sync_events::DeviceLists,
43 },
44 assign,
45 events::{
46 secret::request::SecretName, AnyMessageLikeEvent, AnyMessageLikeEventContent,
47 AnyToDeviceEvent, MessageLikeEventContent,
48 },
49 serde::{JsonObject, Raw},
50 DeviceId, MilliSecondsSinceUnixEpoch, OneTimeKeyAlgorithm, OwnedDeviceId, OwnedDeviceKeyId,
51 OwnedTransactionId, OwnedUserId, RoomId, TransactionId, UInt, UserId,
52};
53use serde_json::{value::to_raw_value, Value};
54use tokio::sync::Mutex;
55use tracing::{
56 debug, error,
57 field::{debug, display},
58 info, instrument, trace, warn, Span,
59};
60use vodozemac::{
61 megolm::{DecryptionError, SessionOrdering},
62 Curve25519PublicKey, Ed25519Signature,
63};
64
65use crate::{
66 backups::{BackupMachine, MegolmV1BackupKey},
67 dehydrated_devices::{DehydratedDevices, DehydrationError},
68 error::{EventError, MegolmError, MegolmResult, OlmError, OlmResult, SetRoomSettingsError},
69 gossiping::GossipMachine,
70 identities::{user::UserIdentity, Device, IdentityManager, UserDevices},
71 olm::{
72 Account, CrossSigningStatus, EncryptionSettings, IdentityKeys, InboundGroupSession,
73 KnownSenderData, OlmDecryptionInfo, PrivateCrossSigningIdentity, SenderData,
74 SenderDataFinder, SessionType, StaticAccountData,
75 },
76 session_manager::{GroupSessionManager, SessionManager},
77 store::{
78 Changes, CryptoStoreWrapper, DeviceChanges, IdentityChanges, IntoCryptoStore, MemoryStore,
79 PendingChanges, Result as StoreResult, RoomKeyInfo, RoomSettings, SecretImportError, Store,
80 StoreCache, StoreTransaction, StoredRoomKeyBundleData,
81 },
82 types::{
83 events::{
84 olm_v1::{AnyDecryptedOlmEvent, DecryptedRoomKeyBundleEvent, DecryptedRoomKeyEvent},
85 room::encrypted::{
86 EncryptedEvent, EncryptedToDeviceEvent, RoomEncryptedEventContent,
87 RoomEventEncryptionScheme, SupportedEventEncryptionSchemes,
88 },
89 room_key::{MegolmV1AesSha2Content, RoomKeyContent},
90 room_key_bundle::RoomKeyBundleContent,
91 room_key_withheld::{
92 MegolmV1AesSha2WithheldContent, RoomKeyWithheldContent, RoomKeyWithheldEvent,
93 },
94 ToDeviceEvents,
95 },
96 requests::{
97 AnyIncomingResponse, KeysQueryRequest, OutgoingRequest, ToDeviceRequest,
98 UploadSigningKeysRequest,
99 },
100 EventEncryptionAlgorithm, ProcessedToDeviceEvent, Signatures,
101 },
102 utilities::timestamp_to_iso8601,
103 verification::{Verification, VerificationMachine, VerificationRequest},
104 CollectStrategy, CrossSigningKeyExport, CryptoStoreError, DecryptionSettings, DeviceData,
105 LocalTrust, RoomEventDecryptionResult, SignatureError, TrustRequirement,
106};
107
108#[derive(Clone)]
111pub struct OlmMachine {
112 pub(crate) inner: Arc<OlmMachineInner>,
113}
114
115pub struct OlmMachineInner {
116 user_id: OwnedUserId,
118 device_id: OwnedDeviceId,
120 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
125 store: Store,
129 session_manager: SessionManager,
131 pub(crate) group_session_manager: GroupSessionManager,
133 verification_machine: VerificationMachine,
136 pub(crate) key_request_machine: GossipMachine,
139 identity_manager: IdentityManager,
142 backup_machine: BackupMachine,
144}
145
146#[cfg(not(tarpaulin_include))]
147impl std::fmt::Debug for OlmMachine {
148 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149 f.debug_struct("OlmMachine")
150 .field("user_id", &self.user_id())
151 .field("device_id", &self.device_id())
152 .finish()
153 }
154}
155
156impl OlmMachine {
157 const CURRENT_GENERATION_STORE_KEY: &'static str = "generation-counter";
158 const HAS_MIGRATED_VERIFICATION_LATCH: &'static str = "HAS_MIGRATED_VERIFICATION_LATCH";
159
160 pub async fn new(user_id: &UserId, device_id: &DeviceId) -> Self {
171 OlmMachine::with_store(user_id, device_id, MemoryStore::new(), None)
172 .await
173 .expect("Reading and writing to the memory store always succeeds")
174 }
175
176 pub(crate) async fn rehydrate(
177 &self,
178 pickle_key: &[u8; 32],
179 device_id: &DeviceId,
180 device_data: Raw<DehydratedDeviceData>,
181 ) -> Result<OlmMachine, DehydrationError> {
182 let account = Account::rehydrate(pickle_key, self.user_id(), device_id, device_data)?;
183 let static_account = account.static_data().clone();
184
185 let store =
186 Arc::new(CryptoStoreWrapper::new(self.user_id(), device_id, MemoryStore::new()));
187 let device = DeviceData::from_account(&account);
188 store.save_pending_changes(PendingChanges { account: Some(account) }).await?;
189 store
190 .save_changes(Changes {
191 devices: DeviceChanges { new: vec![device], ..Default::default() },
192 ..Default::default()
193 })
194 .await?;
195
196 let (verification_machine, store, identity_manager) =
197 Self::new_helper_prelude(store, static_account, self.store().private_identity());
198
199 Ok(Self::new_helper(
200 device_id,
201 store,
202 verification_machine,
203 identity_manager,
204 self.store().private_identity(),
205 None,
206 ))
207 }
208
209 fn new_helper_prelude(
210 store_wrapper: Arc<CryptoStoreWrapper>,
211 account: StaticAccountData,
212 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
213 ) -> (VerificationMachine, Store, IdentityManager) {
214 let verification_machine =
215 VerificationMachine::new(account.clone(), user_identity.clone(), store_wrapper.clone());
216 let store = Store::new(account, user_identity, store_wrapper, verification_machine.clone());
217
218 let identity_manager = IdentityManager::new(store.clone());
219
220 (verification_machine, store, identity_manager)
221 }
222
223 fn new_helper(
224 device_id: &DeviceId,
225 store: Store,
226 verification_machine: VerificationMachine,
227 identity_manager: IdentityManager,
228 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
229 maybe_backup_key: Option<MegolmV1BackupKey>,
230 ) -> Self {
231 let group_session_manager = GroupSessionManager::new(store.clone());
232
233 let users_for_key_claim = Arc::new(StdRwLock::new(BTreeMap::new()));
234 let key_request_machine = GossipMachine::new(
235 store.clone(),
236 identity_manager.clone(),
237 group_session_manager.session_cache(),
238 users_for_key_claim.clone(),
239 );
240
241 let session_manager =
242 SessionManager::new(users_for_key_claim, key_request_machine.clone(), store.clone());
243
244 let backup_machine = BackupMachine::new(store.clone(), maybe_backup_key);
245
246 let inner = Arc::new(OlmMachineInner {
247 user_id: store.user_id().to_owned(),
248 device_id: device_id.to_owned(),
249 user_identity,
250 store,
251 session_manager,
252 group_session_manager,
253 verification_machine,
254 key_request_machine,
255 identity_manager,
256 backup_machine,
257 });
258
259 Self { inner }
260 }
261
262 #[instrument(skip(store, custom_account), fields(ed25519_key, curve25519_key))]
290 pub async fn with_store(
291 user_id: &UserId,
292 device_id: &DeviceId,
293 store: impl IntoCryptoStore,
294 custom_account: Option<vodozemac::olm::Account>,
295 ) -> StoreResult<Self> {
296 let store = store.into_crypto_store();
297
298 let static_account = match store.load_account().await? {
299 Some(account) => {
300 if user_id != account.user_id()
301 || device_id != account.device_id()
302 || custom_account.is_some()
303 {
304 return Err(CryptoStoreError::MismatchedAccount {
305 expected: (account.user_id().to_owned(), account.device_id().to_owned()),
306 got: (user_id.to_owned(), device_id.to_owned()),
307 });
308 }
309
310 Span::current()
311 .record("ed25519_key", display(account.identity_keys().ed25519))
312 .record("curve25519_key", display(account.identity_keys().curve25519));
313 debug!("Restored an Olm account");
314
315 account.static_data().clone()
316 }
317
318 None => {
319 let account = if let Some(account) = custom_account {
320 Account::new_helper(account, user_id, device_id)
321 } else {
322 Account::with_device_id(user_id, device_id)
323 };
324
325 let static_account = account.static_data().clone();
326
327 Span::current()
328 .record("ed25519_key", display(account.identity_keys().ed25519))
329 .record("curve25519_key", display(account.identity_keys().curve25519));
330
331 let device = DeviceData::from_account(&account);
332
333 device.set_trust_state(LocalTrust::Verified);
337
338 let changes = Changes {
339 devices: DeviceChanges { new: vec![device], ..Default::default() },
340 ..Default::default()
341 };
342 store.save_changes(changes).await?;
343 store.save_pending_changes(PendingChanges { account: Some(account) }).await?;
344
345 debug!("Created a new Olm account");
346
347 static_account
348 }
349 };
350
351 let identity = match store.load_identity().await? {
352 Some(i) => {
353 let master_key = i
354 .master_public_key()
355 .await
356 .and_then(|m| m.get_first_key().map(|m| m.to_owned()));
357 debug!(?master_key, "Restored the cross signing identity");
358 i
359 }
360 None => {
361 debug!("Creating an empty cross signing identity stub");
362 PrivateCrossSigningIdentity::empty(user_id)
363 }
364 };
365
366 let saved_keys = store.load_backup_keys().await?;
371 let maybe_backup_key = saved_keys.decryption_key.and_then(|k| {
372 if let Some(version) = saved_keys.backup_version {
373 let megolm_v1_backup_key = k.megolm_v1_public_key();
374 megolm_v1_backup_key.set_version(version);
375 Some(megolm_v1_backup_key)
376 } else {
377 None
378 }
379 });
380
381 let identity = Arc::new(Mutex::new(identity));
382 let store = Arc::new(CryptoStoreWrapper::new(user_id, device_id, store));
383
384 let (verification_machine, store, identity_manager) =
385 Self::new_helper_prelude(store, static_account, identity.clone());
386
387 Self::migration_post_verified_latch_support(&store, &identity_manager).await?;
390
391 Ok(Self::new_helper(
392 device_id,
393 store,
394 verification_machine,
395 identity_manager,
396 identity,
397 maybe_backup_key,
398 ))
399 }
400
401 pub(crate) async fn migration_post_verified_latch_support(
409 store: &Store,
410 identity_manager: &IdentityManager,
411 ) -> Result<(), CryptoStoreError> {
412 let maybe_migrate_for_identity_verified_latch =
413 store.get_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH).await?.is_none();
414
415 if maybe_migrate_for_identity_verified_latch {
416 identity_manager.mark_all_tracked_users_as_dirty(store.cache().await?).await?;
417
418 store.set_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH, vec![0]).await?
419 }
420 Ok(())
421 }
422
423 pub fn store(&self) -> &Store {
425 &self.inner.store
426 }
427
428 pub fn user_id(&self) -> &UserId {
430 &self.inner.user_id
431 }
432
433 pub fn device_id(&self) -> &DeviceId {
435 &self.inner.device_id
436 }
437
438 pub fn device_creation_time(&self) -> MilliSecondsSinceUnixEpoch {
445 self.inner.store.static_account().creation_local_time()
446 }
447
448 pub fn identity_keys(&self) -> IdentityKeys {
450 let account = self.inner.store.static_account();
451 account.identity_keys()
452 }
453
454 pub async fn display_name(&self) -> StoreResult<Option<String>> {
456 self.store().device_display_name().await
457 }
458
459 pub async fn tracked_users(&self) -> StoreResult<HashSet<OwnedUserId>> {
464 let cache = self.store().cache().await?;
465 Ok(self.inner.identity_manager.key_query_manager.synced(&cache).await?.tracked_users())
466 }
467
468 #[cfg(feature = "automatic-room-key-forwarding")]
477 pub fn set_room_key_requests_enabled(&self, enable: bool) {
478 self.inner.key_request_machine.set_room_key_requests_enabled(enable)
479 }
480
481 pub fn are_room_key_requests_enabled(&self) -> bool {
486 self.inner.key_request_machine.are_room_key_requests_enabled()
487 }
488
489 #[cfg(feature = "automatic-room-key-forwarding")]
498 pub fn set_room_key_forwarding_enabled(&self, enable: bool) {
499 self.inner.key_request_machine.set_room_key_forwarding_enabled(enable)
500 }
501
502 pub fn is_room_key_forwarding_enabled(&self) -> bool {
506 self.inner.key_request_machine.is_room_key_forwarding_enabled()
507 }
508
509 pub async fn outgoing_requests(&self) -> StoreResult<Vec<OutgoingRequest>> {
517 let mut requests = Vec::new();
518
519 {
520 let store_cache = self.inner.store.cache().await?;
521 let account = store_cache.account().await?;
522 if let Some(r) = self.keys_for_upload(&account).await.map(|r| OutgoingRequest {
523 request_id: TransactionId::new(),
524 request: Arc::new(r.into()),
525 }) {
526 requests.push(r);
527 }
528 }
529
530 for request in self
531 .inner
532 .identity_manager
533 .users_for_key_query()
534 .await?
535 .into_iter()
536 .map(|(request_id, r)| OutgoingRequest { request_id, request: Arc::new(r.into()) })
537 {
538 requests.push(request);
539 }
540
541 requests.append(&mut self.inner.verification_machine.outgoing_messages());
542 requests.append(&mut self.inner.key_request_machine.outgoing_to_device_requests().await?);
543
544 Ok(requests)
545 }
546
547 pub fn query_keys_for_users<'a>(
568 &self,
569 users: impl IntoIterator<Item = &'a UserId>,
570 ) -> (OwnedTransactionId, KeysQueryRequest) {
571 self.inner.identity_manager.build_key_query_for_users(users)
572 }
573
574 pub async fn mark_request_as_sent<'a>(
584 &self,
585 request_id: &TransactionId,
586 response: impl Into<AnyIncomingResponse<'a>>,
587 ) -> OlmResult<()> {
588 match response.into() {
589 AnyIncomingResponse::KeysUpload(response) => {
590 Box::pin(self.receive_keys_upload_response(response)).await?;
591 }
592 AnyIncomingResponse::KeysQuery(response) => {
593 Box::pin(self.receive_keys_query_response(request_id, response)).await?;
594 }
595 AnyIncomingResponse::KeysClaim(response) => {
596 Box::pin(
597 self.inner.session_manager.receive_keys_claim_response(request_id, response),
598 )
599 .await?;
600 }
601 AnyIncomingResponse::ToDevice(_) => {
602 Box::pin(self.mark_to_device_request_as_sent(request_id)).await?;
603 }
604 AnyIncomingResponse::SigningKeysUpload(_) => {
605 Box::pin(self.receive_cross_signing_upload_response()).await?;
606 }
607 AnyIncomingResponse::SignatureUpload(_) => {
608 self.inner.verification_machine.mark_request_as_sent(request_id);
609 }
610 AnyIncomingResponse::RoomMessage(_) => {
611 self.inner.verification_machine.mark_request_as_sent(request_id);
612 }
613 AnyIncomingResponse::KeysBackup(_) => {
614 Box::pin(self.inner.backup_machine.mark_request_as_sent(request_id)).await?;
615 }
616 };
617
618 Ok(())
619 }
620
621 async fn receive_cross_signing_upload_response(&self) -> StoreResult<()> {
623 let identity = self.inner.user_identity.lock().await;
624 identity.mark_as_shared();
625
626 let changes = Changes { private_identity: Some(identity.clone()), ..Default::default() };
627
628 self.store().save_changes(changes).await
629 }
630
631 pub async fn bootstrap_cross_signing(
650 &self,
651 reset: bool,
652 ) -> StoreResult<CrossSigningBootstrapRequests> {
653 let identity = self.inner.user_identity.lock().await.clone();
658
659 let (upload_signing_keys_req, upload_signatures_req) = if reset || identity.is_empty().await
660 {
661 info!("Creating new cross signing identity");
662
663 let (identity, upload_signing_keys_req, upload_signatures_req) = {
664 let cache = self.inner.store.cache().await?;
665 let account = cache.account().await?;
666 account.bootstrap_cross_signing().await
667 };
668
669 let public = identity.to_public_identity().await.expect(
670 "Couldn't create a public version of the identity from a new private identity",
671 );
672
673 *self.inner.user_identity.lock().await = identity.clone();
674
675 self.store()
676 .save_changes(Changes {
677 identities: IdentityChanges { new: vec![public.into()], ..Default::default() },
678 private_identity: Some(identity),
679 ..Default::default()
680 })
681 .await?;
682
683 (upload_signing_keys_req, upload_signatures_req)
684 } else {
685 info!("Trying to upload the existing cross signing identity");
686 let upload_signing_keys_req = identity.as_upload_request().await;
687
688 let upload_signatures_req = identity
690 .sign_account(self.inner.store.static_account())
691 .await
692 .expect("Can't sign device keys");
693
694 (upload_signing_keys_req, upload_signatures_req)
695 };
696
697 let upload_keys_req =
701 self.upload_device_keys().await?.map(|(_, request)| OutgoingRequest::from(request));
702
703 Ok(CrossSigningBootstrapRequests {
704 upload_signing_keys_req,
705 upload_keys_req,
706 upload_signatures_req,
707 })
708 }
709
710 pub async fn upload_device_keys(
722 &self,
723 ) -> StoreResult<Option<(OwnedTransactionId, UploadKeysRequest)>> {
724 let cache = self.store().cache().await?;
725 let account = cache.account().await?;
726
727 Ok(self.keys_for_upload(&account).await.map(|request| (TransactionId::new(), request)))
728 }
729
730 async fn receive_keys_upload_response(&self, response: &UploadKeysResponse) -> OlmResult<()> {
737 self.inner
738 .store
739 .with_transaction(|mut tr| async {
740 let account = tr.account().await?;
741 account.receive_keys_upload_response(response)?;
742 Ok((tr, ()))
743 })
744 .await
745 }
746
747 #[instrument(skip_all)]
775 pub async fn get_missing_sessions(
776 &self,
777 users: impl Iterator<Item = &UserId>,
778 ) -> StoreResult<Option<(OwnedTransactionId, KeysClaimRequest)>> {
779 self.inner.session_manager.get_missing_sessions(users).await
780 }
781
782 async fn receive_keys_query_response(
791 &self,
792 request_id: &TransactionId,
793 response: &KeysQueryResponse,
794 ) -> OlmResult<(DeviceChanges, IdentityChanges)> {
795 self.inner.identity_manager.receive_keys_query_response(request_id, response).await
796 }
797
798 async fn keys_for_upload(&self, account: &Account) -> Option<UploadKeysRequest> {
807 let (mut device_keys, one_time_keys, fallback_keys) = account.keys_for_upload();
808
809 if let Some(device_keys) = &mut device_keys {
819 let private_identity = self.store().private_identity();
820 let guard = private_identity.lock().await;
821
822 if guard.status().await.is_complete() {
823 guard.sign_device_keys(device_keys).await.expect(
824 "We should be able to sign our device keys since we confirmed that we \
825 have a complete set of private cross-signing keys",
826 );
827 }
828 }
829
830 if device_keys.is_none() && one_time_keys.is_empty() && fallback_keys.is_empty() {
831 None
832 } else {
833 let device_keys = device_keys.map(|d| d.to_raw());
834
835 Some(assign!(UploadKeysRequest::new(), {
836 device_keys, one_time_keys, fallback_keys
837 }))
838 }
839 }
840
841 async fn decrypt_to_device_event(
850 &self,
851 transaction: &mut StoreTransaction,
852 event: &EncryptedToDeviceEvent,
853 changes: &mut Changes,
854 ) -> OlmResult<OlmDecryptionInfo> {
855 let mut decrypted =
856 transaction.account().await?.decrypt_to_device_event(&self.inner.store, event).await?;
857
858 if !self.to_device_event_is_from_dehydrated_device(&decrypted, &event.sender).await? {
861 self.handle_decrypted_to_device_event(transaction.cache(), &mut decrypted, changes)
864 .await?;
865 }
866
867 Ok(decrypted)
868 }
869
870 #[instrument(
871 skip_all,
872 fields(room_id = ? content.room_id, session_id)
876 )]
877 async fn handle_key(
878 &self,
879 sender_key: Curve25519PublicKey,
880 event: &DecryptedRoomKeyEvent,
881 content: &MegolmV1AesSha2Content,
882 ) -> OlmResult<Option<InboundGroupSession>> {
883 let session =
884 InboundGroupSession::from_room_key_content(sender_key, event.keys.ed25519, content);
885
886 match session {
887 Ok(mut session) => {
888 Span::current().record("session_id", session.session_id());
889
890 let sender_data =
891 SenderDataFinder::find_using_event(self.store(), sender_key, event, &session)
892 .await?;
893
894 session.sender_data = sender_data;
895
896 match self.store().compare_group_session(&session).await? {
897 SessionOrdering::Better => {
898 info!("Received a new megolm room key");
899
900 Ok(Some(session))
901 }
902 comparison_result => {
903 warn!(
904 ?comparison_result,
905 "Received a megolm room key that we already have a better version \
906 of, discarding"
907 );
908
909 Ok(None)
910 }
911 }
912 }
913 Err(e) => {
914 Span::current().record("session_id", &content.session_id);
915 warn!("Received a room key event which contained an invalid session key: {e}");
916
917 Ok(None)
918 }
919 }
920 }
921
922 #[instrument(skip_all, fields(algorithm = ?event.content.algorithm()))]
924 async fn add_room_key(
925 &self,
926 sender_key: Curve25519PublicKey,
927 event: &DecryptedRoomKeyEvent,
928 ) -> OlmResult<Option<InboundGroupSession>> {
929 match &event.content {
930 RoomKeyContent::MegolmV1AesSha2(content) => {
931 self.handle_key(sender_key, event, content).await
932 }
933 #[cfg(feature = "experimental-algorithms")]
934 RoomKeyContent::MegolmV2AesSha2(content) => {
935 self.handle_key(sender_key, event, content).await
936 }
937 RoomKeyContent::Unknown(_) => {
938 warn!("Received a room key with an unsupported algorithm");
939 Ok(None)
940 }
941 }
942 }
943
944 #[instrument()]
947 async fn receive_room_key_bundle_data(
948 &self,
949 event: &DecryptedRoomKeyBundleEvent,
950 changes: &mut Changes,
951 ) -> OlmResult<()> {
952 let Some(sender_device_keys) = &event.sender_device_keys else {
953 warn!("Received a room key bundle with no sender device keys: ignoring");
954 return Ok(());
955 };
956
957 let sender_device_data =
962 DeviceData::try_from(sender_device_keys).expect("failed to verify sender device keys");
963 let sender_device = self.store().wrap_device_data(sender_device_data).await?;
964
965 changes.received_room_key_bundles.push(StoredRoomKeyBundleData {
966 sender_user: event.sender.clone(),
967 sender_data: SenderData::from_device(&sender_device),
968 bundle_data: event.content.clone(),
969 });
970 Ok(())
971 }
972
973 fn add_withheld_info(&self, changes: &mut Changes, event: &RoomKeyWithheldEvent) {
974 debug!(?event.content, "Processing `m.room_key.withheld` event");
975
976 if let RoomKeyWithheldContent::MegolmV1AesSha2(
977 MegolmV1AesSha2WithheldContent::BlackListed(c)
978 | MegolmV1AesSha2WithheldContent::Unverified(c),
979 ) = &event.content
980 {
981 changes
982 .withheld_session_info
983 .entry(c.room_id.to_owned())
984 .or_default()
985 .insert(c.session_id.to_owned(), event.to_owned());
986 }
987 }
988
989 #[cfg(test)]
990 pub(crate) async fn create_outbound_group_session_with_defaults_test_helper(
991 &self,
992 room_id: &RoomId,
993 ) -> OlmResult<()> {
994 let (_, session) = self
995 .inner
996 .group_session_manager
997 .create_outbound_group_session(
998 room_id,
999 EncryptionSettings::default(),
1000 SenderData::unknown(),
1001 )
1002 .await?;
1003
1004 self.store().save_inbound_group_sessions(&[session]).await?;
1005
1006 Ok(())
1007 }
1008
1009 #[cfg(test)]
1010 #[allow(dead_code)]
1011 pub(crate) async fn create_inbound_session_test_helper(
1012 &self,
1013 room_id: &RoomId,
1014 ) -> OlmResult<InboundGroupSession> {
1015 let (_, session) = self
1016 .inner
1017 .group_session_manager
1018 .create_outbound_group_session(
1019 room_id,
1020 EncryptionSettings::default(),
1021 SenderData::unknown(),
1022 )
1023 .await?;
1024
1025 Ok(session)
1026 }
1027
1028 pub async fn encrypt_room_event(
1045 &self,
1046 room_id: &RoomId,
1047 content: impl MessageLikeEventContent,
1048 ) -> MegolmResult<Raw<RoomEncryptedEventContent>> {
1049 let event_type = content.event_type().to_string();
1050 let content = Raw::new(&content)?.cast();
1051 self.encrypt_room_event_raw(room_id, &event_type, &content).await
1052 }
1053
1054 pub async fn encrypt_room_event_raw(
1074 &self,
1075 room_id: &RoomId,
1076 event_type: &str,
1077 content: &Raw<AnyMessageLikeEventContent>,
1078 ) -> MegolmResult<Raw<RoomEncryptedEventContent>> {
1079 self.inner.group_session_manager.encrypt(room_id, event_type, content).await
1080 }
1081
1082 pub async fn discard_room_key(&self, room_id: &RoomId) -> StoreResult<bool> {
1093 self.inner.group_session_manager.invalidate_group_session(room_id).await
1094 }
1095
1096 pub async fn share_room_key(
1116 &self,
1117 room_id: &RoomId,
1118 users: impl Iterator<Item = &UserId>,
1119 encryption_settings: impl Into<EncryptionSettings>,
1120 ) -> OlmResult<Vec<Arc<ToDeviceRequest>>> {
1121 self.inner.group_session_manager.share_room_key(room_id, users, encryption_settings).await
1122 }
1123
1124 #[cfg(feature = "experimental-send-custom-to-device")]
1138 pub async fn encrypt_content_for_devices(
1139 &self,
1140 devices: Vec<DeviceData>,
1141 event_type: &str,
1142 content: &Value,
1143 ) -> OlmResult<(Vec<ToDeviceRequest>, Vec<(DeviceData, WithheldCode)>)> {
1144 let mut changes = Changes::default();
1147
1148 let result = self
1149 .inner
1150 .group_session_manager
1151 .encrypt_content_for_devices(devices, event_type, content.clone(), &mut changes)
1152 .await;
1153
1154 if !changes.is_empty() {
1156 let session_count = changes.sessions.len();
1157
1158 self.inner.store.save_changes(changes).await?;
1159
1160 trace!(
1161 session_count = session_count,
1162 "Stored the changed sessions after encrypting a custom to-device event"
1163 );
1164 }
1165
1166 result
1167 }
1168 pub async fn share_room_key_bundle_data(
1173 &self,
1174 user_id: &UserId,
1175 collect_strategy: &CollectStrategy,
1176 bundle_data: RoomKeyBundleContent,
1177 ) -> OlmResult<Vec<ToDeviceRequest>> {
1178 self.inner
1179 .group_session_manager
1180 .share_room_key_bundle_data(user_id, collect_strategy, bundle_data)
1181 .await
1182 }
1183
1184 #[deprecated(note = "Use OlmMachine::receive_verification_event instead", since = "0.7.0")]
1192 pub async fn receive_unencrypted_verification_event(
1193 &self,
1194 event: &AnyMessageLikeEvent,
1195 ) -> StoreResult<()> {
1196 self.inner.verification_machine.receive_any_event(event).await
1197 }
1198
1199 pub async fn receive_verification_event(&self, event: &AnyMessageLikeEvent) -> StoreResult<()> {
1203 self.inner.verification_machine.receive_any_event(event).await
1204 }
1205
1206 #[instrument(
1212 skip_all,
1213 fields(
1214 sender_key = ?decrypted.result.sender_key,
1215 event_type = decrypted.result.event.event_type(),
1216 ),
1217 )]
1218 async fn handle_decrypted_to_device_event(
1219 &self,
1220 cache: &StoreCache,
1221 decrypted: &mut OlmDecryptionInfo,
1222 changes: &mut Changes,
1223 ) -> OlmResult<()> {
1224 debug!(
1225 sender_device_keys =
1226 ?decrypted.result.event.sender_device_keys().map(|k| (k.curve25519_key(), k.ed25519_key())).unwrap_or((None, None)),
1227 "Received a decrypted to-device event",
1228 );
1229
1230 match &*decrypted.result.event {
1231 AnyDecryptedOlmEvent::RoomKey(e) => {
1232 let session = self.add_room_key(decrypted.result.sender_key, e).await?;
1233 decrypted.inbound_group_session = session;
1234 }
1235 AnyDecryptedOlmEvent::ForwardedRoomKey(e) => {
1236 let session = self
1237 .inner
1238 .key_request_machine
1239 .receive_forwarded_room_key(decrypted.result.sender_key, e)
1240 .await?;
1241 decrypted.inbound_group_session = session;
1242 }
1243 AnyDecryptedOlmEvent::SecretSend(e) => {
1244 let name = self
1245 .inner
1246 .key_request_machine
1247 .receive_secret_event(cache, decrypted.result.sender_key, e, changes)
1248 .await?;
1249
1250 if let Ok(ToDeviceEvents::SecretSend(mut e)) =
1253 decrypted.result.raw_event.deserialize_as()
1254 {
1255 e.content.secret_name = name;
1256 decrypted.result.raw_event = Raw::from_json(to_raw_value(&e)?);
1257 }
1258 }
1259 AnyDecryptedOlmEvent::Dummy(_) => {
1260 debug!("Received an `m.dummy` event");
1261 }
1262 AnyDecryptedOlmEvent::RoomKeyBundle(e) => {
1263 debug!("Received a room key bundle event {:?}", e);
1264 self.receive_room_key_bundle_data(e, changes).await?;
1265 }
1266 AnyDecryptedOlmEvent::Custom(_) => {
1267 warn!("Received an unexpected encrypted to-device event");
1268 }
1269 }
1270
1271 Ok(())
1272 }
1273
1274 async fn handle_verification_event(&self, event: &ToDeviceEvents) {
1275 if let Err(e) = self.inner.verification_machine.receive_any_event(event).await {
1276 error!("Error handling a verification event: {e:?}");
1277 }
1278 }
1279
1280 async fn mark_to_device_request_as_sent(&self, request_id: &TransactionId) -> StoreResult<()> {
1282 self.inner.verification_machine.mark_request_as_sent(request_id);
1283 self.inner.key_request_machine.mark_outgoing_request_as_sent(request_id).await?;
1284 self.inner.group_session_manager.mark_request_as_sent(request_id).await?;
1285 self.inner.session_manager.mark_outgoing_request_as_sent(request_id);
1286 Ok(())
1287 }
1288
1289 pub fn get_verification(&self, user_id: &UserId, flow_id: &str) -> Option<Verification> {
1291 self.inner.verification_machine.get_verification(user_id, flow_id)
1292 }
1293
1294 pub fn get_verification_request(
1296 &self,
1297 user_id: &UserId,
1298 flow_id: impl AsRef<str>,
1299 ) -> Option<VerificationRequest> {
1300 self.inner.verification_machine.get_request(user_id, flow_id)
1301 }
1302
1303 pub fn get_verification_requests(&self, user_id: &UserId) -> Vec<VerificationRequest> {
1305 self.inner.verification_machine.get_requests(user_id)
1306 }
1307
1308 async fn handle_to_device_event(&self, changes: &mut Changes, event: &ToDeviceEvents) {
1309 use crate::types::events::ToDeviceEvents::*;
1310
1311 match event {
1312 RoomKeyRequest(e) => self.inner.key_request_machine.receive_incoming_key_request(e),
1313 SecretRequest(e) => self.inner.key_request_machine.receive_incoming_secret_request(e),
1314 RoomKeyWithheld(e) => self.add_withheld_info(changes, e),
1315 KeyVerificationAccept(..)
1316 | KeyVerificationCancel(..)
1317 | KeyVerificationKey(..)
1318 | KeyVerificationMac(..)
1319 | KeyVerificationRequest(..)
1320 | KeyVerificationReady(..)
1321 | KeyVerificationDone(..)
1322 | KeyVerificationStart(..) => {
1323 self.handle_verification_event(event).await;
1324 }
1325 Dummy(_) | RoomKey(_) | ForwardedRoomKey(_) | RoomEncrypted(_) => {}
1326 _ => {}
1327 }
1328 }
1329
1330 fn record_message_id(event: &Raw<AnyToDeviceEvent>) {
1331 use serde::Deserialize;
1332
1333 #[derive(Deserialize)]
1334 struct ContentStub<'a> {
1335 #[serde(borrow, rename = "org.matrix.msgid")]
1336 message_id: Option<&'a str>,
1337 }
1338
1339 #[derive(Deserialize)]
1340 struct ToDeviceStub<'a> {
1341 sender: &'a str,
1342 #[serde(rename = "type")]
1343 event_type: &'a str,
1344 #[serde(borrow)]
1345 content: ContentStub<'a>,
1346 }
1347
1348 if let Ok(event) = event.deserialize_as::<ToDeviceStub<'_>>() {
1349 Span::current().record("sender", event.sender);
1350 Span::current().record("event_type", event.event_type);
1351 Span::current().record("message_id", event.content.message_id);
1352 }
1353 }
1354
1355 #[instrument(skip_all, fields(sender, event_type, message_id))]
1363 async fn receive_to_device_event(
1364 &self,
1365 transaction: &mut StoreTransaction,
1366 changes: &mut Changes,
1367 mut raw_event: Raw<AnyToDeviceEvent>,
1368 ) -> Option<ProcessedToDeviceEvent> {
1369 Self::record_message_id(&raw_event);
1370
1371 let event: ToDeviceEvents = match raw_event.deserialize_as() {
1372 Ok(e) => e,
1373 Err(e) => {
1374 warn!("Received an invalid to-device event: {e}");
1376 return Some(ProcessedToDeviceEvent::Invalid(raw_event));
1377 }
1378 };
1379
1380 debug!("Received a to-device event");
1381
1382 match event {
1383 ToDeviceEvents::RoomEncrypted(e) => {
1384 let decrypted = match self.decrypt_to_device_event(transaction, &e, changes).await {
1385 Ok(e) => e,
1386 Err(err) => {
1387 if let OlmError::SessionWedged(sender, curve_key) = err {
1388 if let Err(e) = self
1389 .inner
1390 .session_manager
1391 .mark_device_as_wedged(&sender, curve_key)
1392 .await
1393 {
1394 error!(
1395 error = ?e,
1396 "Couldn't mark device from to be unwedged",
1397 );
1398 }
1399 }
1400
1401 return Some(ProcessedToDeviceEvent::UnableToDecrypt(raw_event));
1402 }
1403 };
1404
1405 match self.to_device_event_is_from_dehydrated_device(&decrypted, &e.sender).await {
1408 Ok(true) => {
1409 warn!(
1410 sender = ?e.sender,
1411 session = ?decrypted.session,
1412 "Received a to-device event from a dehydrated device. This is unexpected: ignoring event"
1413 );
1414 return None;
1415 }
1416 Ok(false) => {}
1417 Err(err) => {
1418 error!(
1419 error = ?err,
1420 "Couldn't check whether event is from dehydrated device",
1421 );
1422 }
1423 }
1424
1425 match decrypted.session {
1428 SessionType::New(s) | SessionType::Existing(s) => {
1429 changes.sessions.push(s);
1430 }
1431 }
1432
1433 changes.message_hashes.push(decrypted.message_hash);
1434
1435 if let Some(group_session) = decrypted.inbound_group_session {
1436 changes.inbound_group_sessions.push(group_session);
1437 }
1438
1439 match decrypted.result.raw_event.deserialize_as() {
1440 Ok(event) => {
1441 self.handle_to_device_event(changes, &event).await;
1442
1443 raw_event = event
1444 .serialize_zeroized()
1445 .expect("Zeroizing and reserializing our events should always work")
1446 .cast();
1447 }
1448 Err(e) => {
1449 warn!("Received an invalid encrypted to-device event: {e}");
1450 raw_event = decrypted.result.raw_event;
1451 }
1452 }
1453
1454 Some(ProcessedToDeviceEvent::Decrypted {
1455 raw: raw_event,
1456 encryption_info: decrypted.result.encryption_info,
1457 })
1458 }
1459
1460 e => {
1461 self.handle_to_device_event(changes, &e).await;
1462 Some(ProcessedToDeviceEvent::PlainText(raw_event))
1463 }
1464 }
1465 }
1466
1467 async fn to_device_event_is_from_dehydrated_device(
1473 &self,
1474 decrypted: &OlmDecryptionInfo,
1475 sender_user_id: &UserId,
1476 ) -> OlmResult<bool> {
1477 if let Some(device_keys) = decrypted.result.event.sender_device_keys() {
1479 if device_keys.dehydrated.unwrap_or(false) {
1485 return Ok(true);
1486 }
1487 }
1492
1493 Ok(self
1495 .store()
1496 .get_device_from_curve_key(sender_user_id, decrypted.result.sender_key)
1497 .await?
1498 .is_some_and(|d| d.is_dehydrated()))
1499 }
1500
1501 #[instrument(skip_all)]
1519 pub async fn receive_sync_changes(
1520 &self,
1521 sync_changes: EncryptionSyncChanges<'_>,
1522 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Vec<RoomKeyInfo>)> {
1523 let mut store_transaction = self.inner.store.transaction().await;
1524
1525 let (events, changes) =
1526 self.preprocess_sync_changes(&mut store_transaction, sync_changes).await?;
1527
1528 let room_key_updates: Vec<_> =
1531 changes.inbound_group_sessions.iter().map(RoomKeyInfo::from).collect();
1532
1533 self.store().save_changes(changes).await?;
1534 store_transaction.commit().await?;
1535
1536 Ok((events, room_key_updates))
1537 }
1538
1539 pub(crate) async fn preprocess_sync_changes(
1548 &self,
1549 transaction: &mut StoreTransaction,
1550 sync_changes: EncryptionSyncChanges<'_>,
1551 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Changes)> {
1552 let mut events: Vec<ProcessedToDeviceEvent> = self
1554 .inner
1555 .verification_machine
1556 .garbage_collect()
1557 .iter()
1558 .map(|e| ProcessedToDeviceEvent::PlainText(e.clone()))
1562 .collect();
1563 let mut changes = Default::default();
1566
1567 {
1568 let account = transaction.account().await?;
1569 account.update_key_counts(
1570 sync_changes.one_time_keys_counts,
1571 sync_changes.unused_fallback_keys,
1572 )
1573 }
1574
1575 if let Err(e) = self
1576 .inner
1577 .identity_manager
1578 .receive_device_changes(
1579 transaction.cache(),
1580 sync_changes.changed_devices.changed.iter().map(|u| u.as_ref()),
1581 )
1582 .await
1583 {
1584 error!(error = ?e, "Error marking a tracked user as changed");
1585 }
1586
1587 for raw_event in sync_changes.to_device_events {
1588 let raw_event =
1589 Box::pin(self.receive_to_device_event(transaction, &mut changes, raw_event)).await;
1590
1591 if let Some(raw_event) = raw_event {
1592 events.push(raw_event);
1593 }
1594 }
1595
1596 let changed_sessions = self
1597 .inner
1598 .key_request_machine
1599 .collect_incoming_key_requests(transaction.cache())
1600 .await?;
1601
1602 changes.sessions.extend(changed_sessions);
1603 changes.next_batch_token = sync_changes.next_batch_token;
1604
1605 Ok((events, changes))
1606 }
1607
1608 pub async fn request_room_key(
1625 &self,
1626 event: &Raw<EncryptedEvent>,
1627 room_id: &RoomId,
1628 ) -> MegolmResult<(Option<OutgoingRequest>, OutgoingRequest)> {
1629 let event = event.deserialize()?;
1630 self.inner.key_request_machine.request_key(room_id, &event).await
1631 }
1632
1633 async fn get_room_event_verification_state(
1646 &self,
1647 session: &InboundGroupSession,
1648 sender: &UserId,
1649 ) -> MegolmResult<(VerificationState, Option<OwnedDeviceId>)> {
1650 let sender_data = self.get_or_update_sender_data(session, sender).await?;
1651
1652 let (verification_state, device_id) = match sender_data.user_id() {
1661 Some(i) if i != sender => {
1662 (
1665 VerificationState::Unverified(VerificationLevel::None(
1666 DeviceLinkProblem::MissingDevice,
1667 )),
1668 None,
1669 )
1670 }
1671
1672 Some(_) | None => {
1673 sender_data_to_verification_state(sender_data, session.has_been_imported())
1674 }
1675 };
1676
1677 Ok((verification_state, device_id))
1678 }
1679
1680 async fn get_or_update_sender_data(
1695 &self,
1696 session: &InboundGroupSession,
1697 sender: &UserId,
1698 ) -> MegolmResult<SenderData> {
1699 fn should_recalculate_sender_data(sender_data: &SenderData) -> bool {
1710 matches!(
1711 sender_data,
1712 SenderData::UnknownDevice { .. }
1713 | SenderData::DeviceInfo { .. }
1714 | SenderData::VerificationViolation { .. }
1715 )
1716 }
1717
1718 let sender_data = if should_recalculate_sender_data(&session.sender_data) {
1719 let calculated_sender_data = SenderDataFinder::find_using_curve_key(
1738 self.store(),
1739 session.sender_key(),
1740 sender,
1741 session,
1742 )
1743 .await?;
1744
1745 if calculated_sender_data.compare_trust_level(&session.sender_data).is_gt() {
1747 let mut new_session = session.clone();
1749 new_session.sender_data = calculated_sender_data.clone();
1750 self.store().save_inbound_group_sessions(&[new_session]).await?;
1751
1752 calculated_sender_data
1754 } else {
1755 session.sender_data.clone()
1757 }
1758 } else {
1759 session.sender_data.clone()
1760 };
1761
1762 Ok(sender_data)
1763 }
1764
1765 pub async fn query_missing_secrets_from_other_sessions(&self) -> StoreResult<bool> {
1790 let identity = self.inner.user_identity.lock().await;
1791 let mut secrets = identity.get_missing_secrets().await;
1792
1793 if self.store().load_backup_keys().await?.decryption_key.is_none() {
1794 secrets.push(SecretName::RecoveryKey);
1795 }
1796
1797 if secrets.is_empty() {
1798 debug!("No missing requests to query");
1799 return Ok(false);
1800 }
1801
1802 let secret_requests = GossipMachine::request_missing_secrets(self.user_id(), secrets);
1803
1804 let unsent_request = self.store().get_unsent_secret_requests().await?;
1806 let not_yet_requested = secret_requests
1807 .into_iter()
1808 .filter(|request| !unsent_request.iter().any(|unsent| unsent.info == request.info))
1809 .collect_vec();
1810
1811 if not_yet_requested.is_empty() {
1812 debug!("The missing secrets have already been requested");
1813 Ok(false)
1814 } else {
1815 debug!("Requesting missing secrets");
1816
1817 let changes = Changes { key_requests: not_yet_requested, ..Default::default() };
1818
1819 self.store().save_changes(changes).await?;
1820 Ok(true)
1821 }
1822 }
1823
1824 async fn get_encryption_info(
1830 &self,
1831 session: &InboundGroupSession,
1832 sender: &UserId,
1833 ) -> MegolmResult<Arc<EncryptionInfo>> {
1834 let (verification_state, device_id) =
1835 self.get_room_event_verification_state(session, sender).await?;
1836
1837 let sender = sender.to_owned();
1838
1839 Ok(Arc::new(EncryptionInfo {
1840 sender,
1841 sender_device: device_id,
1842 algorithm_info: AlgorithmInfo::MegolmV1AesSha2 {
1843 curve25519_key: session.sender_key().to_base64(),
1844 sender_claimed_keys: session
1845 .signing_keys()
1846 .iter()
1847 .map(|(k, v)| (k.to_owned(), v.to_base64()))
1848 .collect(),
1849 session_id: Some(session.session_id().to_owned()),
1850 },
1851 verification_state,
1852 }))
1853 }
1854
1855 async fn decrypt_megolm_events(
1856 &self,
1857 room_id: &RoomId,
1858 event: &EncryptedEvent,
1859 content: &SupportedEventEncryptionSchemes<'_>,
1860 decryption_settings: &DecryptionSettings,
1861 ) -> MegolmResult<(JsonObject, Arc<EncryptionInfo>)> {
1862 let session =
1863 self.get_inbound_group_session_or_error(room_id, content.session_id()).await?;
1864
1865 Span::current().record("sender_key", debug(session.sender_key()));
1871
1872 let result = session.decrypt(event).await;
1873 match result {
1874 Ok((decrypted_event, _)) => {
1875 let encryption_info = self.get_encryption_info(&session, &event.sender).await?;
1876
1877 self.check_sender_trust_requirement(
1878 &session,
1879 &encryption_info,
1880 &decryption_settings.sender_device_trust_requirement,
1881 )?;
1882
1883 Ok((decrypted_event, encryption_info))
1884 }
1885 Err(error) => Err(
1886 if let MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) = error {
1887 let withheld_code = self
1888 .inner
1889 .store
1890 .get_withheld_info(room_id, content.session_id())
1891 .await?
1892 .map(|e| e.content.withheld_code());
1893
1894 if withheld_code.is_some() {
1895 MegolmError::MissingRoomKey(withheld_code)
1897 } else {
1898 error
1899 }
1900 } else {
1901 error
1902 },
1903 ),
1904 }
1905 }
1906
1907 fn check_sender_trust_requirement(
1913 &self,
1914 session: &InboundGroupSession,
1915 encryption_info: &EncryptionInfo,
1916 trust_requirement: &TrustRequirement,
1917 ) -> MegolmResult<()> {
1918 trace!(
1919 verification_state = ?encryption_info.verification_state,
1920 ?trust_requirement, "check_sender_trust_requirement",
1921 );
1922
1923 let verification_level = match &encryption_info.verification_state {
1926 VerificationState::Verified => return Ok(()),
1927 VerificationState::Unverified(verification_level) => verification_level,
1928 };
1929
1930 let ok = match trust_requirement {
1931 TrustRequirement::Untrusted => true,
1932
1933 TrustRequirement::CrossSignedOrLegacy => {
1934 let legacy_session = match session.sender_data {
1940 SenderData::DeviceInfo { legacy_session, .. } => legacy_session,
1941 SenderData::UnknownDevice { legacy_session, .. } => legacy_session,
1942 _ => false,
1943 };
1944
1945 match (verification_level, legacy_session) {
1955 (VerificationLevel::UnverifiedIdentity, _) => true,
1957
1958 (VerificationLevel::UnsignedDevice, true) => true,
1960
1961 (VerificationLevel::None(_), true) => true,
1963
1964 (VerificationLevel::VerificationViolation, _)
1966 | (VerificationLevel::UnsignedDevice, false)
1967 | (VerificationLevel::None(_), false) => false,
1968 }
1969 }
1970
1971 TrustRequirement::CrossSigned => match verification_level {
1974 VerificationLevel::UnverifiedIdentity => true,
1975
1976 VerificationLevel::VerificationViolation
1977 | VerificationLevel::UnsignedDevice
1978 | VerificationLevel::None(_) => false,
1979 },
1980 };
1981
1982 if ok {
1983 Ok(())
1984 } else {
1985 Err(MegolmError::SenderIdentityNotTrusted(verification_level.clone()))
1986 }
1987 }
1988
1989 async fn get_inbound_group_session_or_error(
1994 &self,
1995 room_id: &RoomId,
1996 session_id: &str,
1997 ) -> MegolmResult<InboundGroupSession> {
1998 match self.store().get_inbound_group_session(room_id, session_id).await? {
1999 Some(session) => Ok(session),
2000 None => {
2001 let withheld_code = self
2002 .inner
2003 .store
2004 .get_withheld_info(room_id, session_id)
2005 .await?
2006 .map(|e| e.content.withheld_code());
2007 Err(MegolmError::MissingRoomKey(withheld_code))
2008 }
2009 }
2010 }
2011
2012 pub async fn try_decrypt_room_event(
2027 &self,
2028 raw_event: &Raw<EncryptedEvent>,
2029 room_id: &RoomId,
2030 decryption_settings: &DecryptionSettings,
2031 ) -> Result<RoomEventDecryptionResult, CryptoStoreError> {
2032 match self.decrypt_room_event_inner(raw_event, room_id, true, decryption_settings).await {
2033 Ok(decrypted) => Ok(RoomEventDecryptionResult::Decrypted(decrypted)),
2034 Err(err) => Ok(RoomEventDecryptionResult::UnableToDecrypt(megolm_error_to_utd_info(
2035 raw_event, err,
2036 )?)),
2037 }
2038 }
2039
2040 pub async fn decrypt_room_event(
2048 &self,
2049 event: &Raw<EncryptedEvent>,
2050 room_id: &RoomId,
2051 decryption_settings: &DecryptionSettings,
2052 ) -> MegolmResult<DecryptedRoomEvent> {
2053 self.decrypt_room_event_inner(event, room_id, true, decryption_settings).await
2054 }
2055
2056 #[instrument(name = "decrypt_room_event", skip_all, fields(?room_id, event_id, origin_server_ts, sender, algorithm, session_id, message_index, sender_key))]
2057 async fn decrypt_room_event_inner(
2058 &self,
2059 event: &Raw<EncryptedEvent>,
2060 room_id: &RoomId,
2061 decrypt_unsigned: bool,
2062 decryption_settings: &DecryptionSettings,
2063 ) -> MegolmResult<DecryptedRoomEvent> {
2064 let event = event.deserialize()?;
2065
2066 Span::current()
2067 .record("sender", debug(&event.sender))
2068 .record("event_id", debug(&event.event_id))
2069 .record(
2070 "origin_server_ts",
2071 timestamp_to_iso8601(event.origin_server_ts)
2072 .unwrap_or_else(|| "<out of range>".to_owned()),
2073 )
2074 .record("algorithm", debug(event.content.algorithm()));
2075
2076 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2077 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2078 Span::current().record("sender_key", debug(c.sender_key));
2079 c.into()
2080 }
2081 #[cfg(feature = "experimental-algorithms")]
2082 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2083 RoomEventEncryptionScheme::Unknown(_) => {
2084 warn!("Received an encrypted room event with an unsupported algorithm");
2085 return Err(EventError::UnsupportedAlgorithm.into());
2086 }
2087 };
2088
2089 Span::current().record("session_id", content.session_id());
2090 Span::current().record("message_index", content.message_index());
2091
2092 let result =
2093 self.decrypt_megolm_events(room_id, &event, &content, decryption_settings).await;
2094
2095 if let Err(e) = &result {
2096 #[cfg(feature = "automatic-room-key-forwarding")]
2097 match e {
2098 MegolmError::MissingRoomKey(_)
2101 | MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
2102 self.inner
2103 .key_request_machine
2104 .create_outgoing_key_request(room_id, &event)
2105 .await?;
2106 }
2107 _ => {}
2108 }
2109
2110 warn!("Failed to decrypt a room event: {e}");
2111 }
2112
2113 let (mut decrypted_event, encryption_info) = result?;
2114
2115 let mut unsigned_encryption_info = None;
2116 if decrypt_unsigned {
2117 unsigned_encryption_info = self
2119 .decrypt_unsigned_events(&mut decrypted_event, room_id, decryption_settings)
2120 .await;
2121 }
2122
2123 let event = serde_json::from_value::<Raw<AnyMessageLikeEvent>>(decrypted_event.into())?;
2124
2125 Ok(DecryptedRoomEvent { event, encryption_info, unsigned_encryption_info })
2126 }
2127
2128 async fn decrypt_unsigned_events(
2138 &self,
2139 main_event: &mut JsonObject,
2140 room_id: &RoomId,
2141 decryption_settings: &DecryptionSettings,
2142 ) -> Option<BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>> {
2143 let unsigned = main_event.get_mut("unsigned")?.as_object_mut()?;
2144 let mut unsigned_encryption_info: Option<
2145 BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>,
2146 > = None;
2147
2148 let location = UnsignedEventLocation::RelationsReplace;
2150 let replace = location.find_mut(unsigned);
2151 if let Some(decryption_result) =
2152 self.decrypt_unsigned_event(replace, room_id, decryption_settings).await
2153 {
2154 unsigned_encryption_info
2155 .get_or_insert_with(Default::default)
2156 .insert(location, decryption_result);
2157 }
2158
2159 let location = UnsignedEventLocation::RelationsThreadLatestEvent;
2162 let thread_latest_event = location.find_mut(unsigned);
2163 if let Some(decryption_result) =
2164 self.decrypt_unsigned_event(thread_latest_event, room_id, decryption_settings).await
2165 {
2166 unsigned_encryption_info
2167 .get_or_insert_with(Default::default)
2168 .insert(location, decryption_result);
2169 }
2170
2171 unsigned_encryption_info
2172 }
2173
2174 fn decrypt_unsigned_event<'a>(
2182 &'a self,
2183 event: Option<&'a mut Value>,
2184 room_id: &'a RoomId,
2185 decryption_settings: &'a DecryptionSettings,
2186 ) -> BoxFuture<'a, Option<UnsignedDecryptionResult>> {
2187 Box::pin(async move {
2188 let event = event?;
2189
2190 let is_encrypted = event
2191 .get("type")
2192 .and_then(|type_| type_.as_str())
2193 .is_some_and(|s| s == "m.room.encrypted");
2194 if !is_encrypted {
2195 return None;
2196 }
2197
2198 let raw_event = serde_json::from_value(event.clone()).ok()?;
2199 match self
2200 .decrypt_room_event_inner(&raw_event, room_id, false, decryption_settings)
2201 .await
2202 {
2203 Ok(decrypted_event) => {
2204 *event = serde_json::to_value(decrypted_event.event).ok()?;
2206 Some(UnsignedDecryptionResult::Decrypted(decrypted_event.encryption_info))
2207 }
2208 Err(err) => {
2209 let utd_info = megolm_error_to_utd_info(&raw_event, err).ok()?;
2214 Some(UnsignedDecryptionResult::UnableToDecrypt(utd_info))
2215 }
2216 }
2217 })
2218 }
2219
2220 pub async fn is_room_key_available(
2227 &self,
2228 event: &Raw<EncryptedEvent>,
2229 room_id: &RoomId,
2230 ) -> Result<bool, CryptoStoreError> {
2231 let event = event.deserialize()?;
2232
2233 let (session_id, message_index) = match &event.content.scheme {
2234 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2235 (&c.session_id, c.ciphertext.message_index())
2236 }
2237 #[cfg(feature = "experimental-algorithms")]
2238 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => {
2239 (&c.session_id, c.ciphertext.message_index())
2240 }
2241 RoomEventEncryptionScheme::Unknown(_) => {
2242 return Ok(false);
2244 }
2245 };
2246
2247 Ok(self
2250 .store()
2251 .get_inbound_group_session(room_id, session_id)
2252 .await?
2253 .filter(|s| s.first_known_index() <= message_index)
2254 .is_some())
2255 }
2256
2257 pub async fn get_room_event_encryption_info(
2270 &self,
2271 event: &Raw<EncryptedEvent>,
2272 room_id: &RoomId,
2273 ) -> MegolmResult<Arc<EncryptionInfo>> {
2274 let event = event.deserialize()?;
2275
2276 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2277 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => c.into(),
2278 #[cfg(feature = "experimental-algorithms")]
2279 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2280 RoomEventEncryptionScheme::Unknown(_) => {
2281 return Err(EventError::UnsupportedAlgorithm.into());
2282 }
2283 };
2284
2285 self.get_session_encryption_info(room_id, content.session_id(), &event.sender).await
2286 }
2287
2288 pub async fn get_session_encryption_info(
2303 &self,
2304 room_id: &RoomId,
2305 session_id: &str,
2306 sender: &UserId,
2307 ) -> MegolmResult<Arc<EncryptionInfo>> {
2308 let session = self.get_inbound_group_session_or_error(room_id, session_id).await?;
2309 self.get_encryption_info(&session, sender).await
2310 }
2311
2312 pub async fn update_tracked_users(
2330 &self,
2331 users: impl IntoIterator<Item = &UserId>,
2332 ) -> StoreResult<()> {
2333 self.inner.identity_manager.update_tracked_users(users).await
2334 }
2335
2336 pub async fn mark_all_tracked_users_as_dirty(&self) -> StoreResult<()> {
2341 self.inner
2342 .identity_manager
2343 .mark_all_tracked_users_as_dirty(self.inner.store.cache().await?)
2344 .await
2345 }
2346
2347 async fn wait_if_user_pending(
2348 &self,
2349 user_id: &UserId,
2350 timeout: Option<Duration>,
2351 ) -> StoreResult<()> {
2352 if let Some(timeout) = timeout {
2353 let cache = self.store().cache().await?;
2354 self.inner
2355 .identity_manager
2356 .key_query_manager
2357 .wait_if_user_key_query_pending(cache, timeout, user_id)
2358 .await?;
2359 }
2360 Ok(())
2361 }
2362
2363 #[instrument(skip(self))]
2393 pub async fn get_device(
2394 &self,
2395 user_id: &UserId,
2396 device_id: &DeviceId,
2397 timeout: Option<Duration>,
2398 ) -> StoreResult<Option<Device>> {
2399 self.wait_if_user_pending(user_id, timeout).await?;
2400 self.store().get_device(user_id, device_id).await
2401 }
2402
2403 #[instrument(skip(self))]
2417 pub async fn get_identity(
2418 &self,
2419 user_id: &UserId,
2420 timeout: Option<Duration>,
2421 ) -> StoreResult<Option<UserIdentity>> {
2422 self.wait_if_user_pending(user_id, timeout).await?;
2423 self.store().get_identity(user_id).await
2424 }
2425
2426 #[instrument(skip(self))]
2453 pub async fn get_user_devices(
2454 &self,
2455 user_id: &UserId,
2456 timeout: Option<Duration>,
2457 ) -> StoreResult<UserDevices> {
2458 self.wait_if_user_pending(user_id, timeout).await?;
2459 self.store().get_user_devices(user_id).await
2460 }
2461
2462 pub async fn cross_signing_status(&self) -> CrossSigningStatus {
2467 self.inner.user_identity.lock().await.status().await
2468 }
2469
2470 pub async fn export_cross_signing_keys(&self) -> StoreResult<Option<CrossSigningKeyExport>> {
2478 let master_key = self.store().export_secret(&SecretName::CrossSigningMasterKey).await?;
2479 let self_signing_key =
2480 self.store().export_secret(&SecretName::CrossSigningSelfSigningKey).await?;
2481 let user_signing_key =
2482 self.store().export_secret(&SecretName::CrossSigningUserSigningKey).await?;
2483
2484 Ok(if master_key.is_none() && self_signing_key.is_none() && user_signing_key.is_none() {
2485 None
2486 } else {
2487 Some(CrossSigningKeyExport { master_key, self_signing_key, user_signing_key })
2488 })
2489 }
2490
2491 pub async fn import_cross_signing_keys(
2496 &self,
2497 export: CrossSigningKeyExport,
2498 ) -> Result<CrossSigningStatus, SecretImportError> {
2499 self.store().import_cross_signing_keys(export).await
2500 }
2501
2502 async fn sign_with_master_key(
2503 &self,
2504 message: &str,
2505 ) -> Result<(OwnedDeviceKeyId, Ed25519Signature), SignatureError> {
2506 let identity = &*self.inner.user_identity.lock().await;
2507 let key_id = identity.master_key_id().await.ok_or(SignatureError::MissingSigningKey)?;
2508
2509 let signature = identity.sign(message).await?;
2510
2511 Ok((key_id, signature))
2512 }
2513
2514 pub async fn sign(&self, message: &str) -> Result<Signatures, CryptoStoreError> {
2520 let mut signatures = Signatures::new();
2521
2522 {
2523 let cache = self.inner.store.cache().await?;
2524 let account = cache.account().await?;
2525 let key_id = account.signing_key_id();
2526 let signature = account.sign(message);
2527 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
2528 }
2529
2530 match self.sign_with_master_key(message).await {
2531 Ok((key_id, signature)) => {
2532 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
2533 }
2534 Err(e) => {
2535 warn!(error = ?e, "Couldn't sign the message using the cross signing master key")
2536 }
2537 }
2538
2539 Ok(signatures)
2540 }
2541
2542 pub fn backup_machine(&self) -> &BackupMachine {
2547 &self.inner.backup_machine
2548 }
2549
2550 pub async fn initialize_crypto_store_generation(
2554 &self,
2555 generation: &Mutex<Option<u64>>,
2556 ) -> StoreResult<()> {
2557 let mut gen_guard = generation.lock().await;
2560
2561 let prev_generation =
2562 self.inner.store.get_custom_value(Self::CURRENT_GENERATION_STORE_KEY).await?;
2563
2564 let gen = match prev_generation {
2565 Some(val) => {
2566 u64::from_le_bytes(val.try_into().map_err(|_| {
2569 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
2570 })?)
2571 .wrapping_add(1)
2572 }
2573 None => 0,
2574 };
2575
2576 tracing::debug!("Initialising crypto store generation at {}", gen);
2577
2578 self.inner
2579 .store
2580 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, gen.to_le_bytes().to_vec())
2581 .await?;
2582
2583 *gen_guard = Some(gen);
2584
2585 Ok(())
2586 }
2587
2588 pub async fn maintain_crypto_store_generation(
2613 &'_ self,
2614 generation: &Mutex<Option<u64>>,
2615 ) -> StoreResult<(bool, u64)> {
2616 let mut gen_guard = generation.lock().await;
2617
2618 let actual_gen = self
2624 .inner
2625 .store
2626 .get_custom_value(Self::CURRENT_GENERATION_STORE_KEY)
2627 .await?
2628 .ok_or_else(|| {
2629 CryptoStoreError::InvalidLockGeneration("counter missing in store".to_owned())
2630 })?;
2631
2632 let actual_gen =
2633 u64::from_le_bytes(actual_gen.try_into().map_err(|_| {
2634 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
2635 })?);
2636
2637 let new_gen = match gen_guard.as_ref() {
2638 Some(expected_gen) => {
2639 if actual_gen == *expected_gen {
2640 return Ok((false, actual_gen));
2641 }
2642 actual_gen.max(*expected_gen).wrapping_add(1)
2644 }
2645 None => {
2646 actual_gen.wrapping_add(1)
2649 }
2650 };
2651
2652 tracing::debug!(
2653 "Crypto store generation mismatch: previously known was {:?}, actual is {:?}, next is {}",
2654 *gen_guard,
2655 actual_gen,
2656 new_gen
2657 );
2658
2659 *gen_guard = Some(new_gen);
2661
2662 self.inner
2664 .store
2665 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, new_gen.to_le_bytes().to_vec())
2666 .await?;
2667
2668 Ok((true, new_gen))
2669 }
2670
2671 pub fn dehydrated_devices(&self) -> DehydratedDevices {
2673 DehydratedDevices { inner: self.to_owned() }
2674 }
2675
2676 pub async fn room_settings(&self, room_id: &RoomId) -> StoreResult<Option<RoomSettings>> {
2681 self.inner.store.get_room_settings(room_id).await
2684 }
2685
2686 pub async fn set_room_settings(
2697 &self,
2698 room_id: &RoomId,
2699 new_settings: &RoomSettings,
2700 ) -> Result<(), SetRoomSettingsError> {
2701 let store = &self.inner.store;
2702
2703 let _store_transaction = store.transaction().await;
2708
2709 let old_settings = store.get_room_settings(room_id).await?;
2710
2711 if let Some(old_settings) = old_settings {
2724 if old_settings != *new_settings {
2725 return Err(SetRoomSettingsError::EncryptionDowngrade);
2726 } else {
2727 return Ok(());
2729 }
2730 }
2731
2732 match new_settings.algorithm {
2734 EventEncryptionAlgorithm::MegolmV1AesSha2 => (),
2735
2736 #[cfg(feature = "experimental-algorithms")]
2737 EventEncryptionAlgorithm::MegolmV2AesSha2 => (),
2738
2739 _ => {
2740 warn!(
2741 ?room_id,
2742 "Rejecting invalid encryption algorithm {}", new_settings.algorithm
2743 );
2744 return Err(SetRoomSettingsError::InvalidSettings);
2745 }
2746 }
2747
2748 store
2750 .save_changes(Changes {
2751 room_settings: HashMap::from([(room_id.to_owned(), new_settings.clone())]),
2752 ..Default::default()
2753 })
2754 .await?;
2755
2756 Ok(())
2757 }
2758
2759 #[cfg(any(feature = "testing", test))]
2763 pub fn same_as(&self, other: &OlmMachine) -> bool {
2764 Arc::ptr_eq(&self.inner, &other.inner)
2765 }
2766
2767 #[cfg(any(feature = "testing", test))]
2769 pub async fn uploaded_key_count(&self) -> Result<u64, CryptoStoreError> {
2770 let cache = self.inner.store.cache().await?;
2771 let account = cache.account().await?;
2772 Ok(account.uploaded_key_count())
2773 }
2774
2775 #[cfg(test)]
2777 pub(crate) fn identity_manager(&self) -> &IdentityManager {
2778 &self.inner.identity_manager
2779 }
2780
2781 #[cfg(test)]
2783 pub(crate) fn key_for_has_migrated_verification_latch() -> &'static str {
2784 Self::HAS_MIGRATED_VERIFICATION_LATCH
2785 }
2786}
2787
2788fn sender_data_to_verification_state(
2789 sender_data: SenderData,
2790 session_has_been_imported: bool,
2791) -> (VerificationState, Option<OwnedDeviceId>) {
2792 match sender_data {
2793 SenderData::UnknownDevice { owner_check_failed: false, .. } => {
2794 let device_link_problem = if session_has_been_imported {
2795 DeviceLinkProblem::InsecureSource
2796 } else {
2797 DeviceLinkProblem::MissingDevice
2798 };
2799
2800 (VerificationState::Unverified(VerificationLevel::None(device_link_problem)), None)
2801 }
2802 SenderData::UnknownDevice { owner_check_failed: true, .. } => (
2803 VerificationState::Unverified(VerificationLevel::None(
2804 DeviceLinkProblem::InsecureSource,
2805 )),
2806 None,
2807 ),
2808 SenderData::DeviceInfo { device_keys, .. } => (
2809 VerificationState::Unverified(VerificationLevel::UnsignedDevice),
2810 Some(device_keys.device_id),
2811 ),
2812 SenderData::VerificationViolation(KnownSenderData { device_id, .. }) => {
2813 (VerificationState::Unverified(VerificationLevel::VerificationViolation), device_id)
2814 }
2815 SenderData::SenderUnverified(KnownSenderData { device_id, .. }) => {
2816 (VerificationState::Unverified(VerificationLevel::UnverifiedIdentity), device_id)
2817 }
2818 SenderData::SenderVerified(KnownSenderData { device_id, .. }) => {
2819 (VerificationState::Verified, device_id)
2820 }
2821 }
2822}
2823
2824#[derive(Debug, Clone)]
2827pub struct CrossSigningBootstrapRequests {
2828 pub upload_keys_req: Option<OutgoingRequest>,
2835
2836 pub upload_signing_keys_req: UploadSigningKeysRequest,
2840
2841 pub upload_signatures_req: UploadSignaturesRequest,
2846}
2847
2848#[derive(Debug)]
2851pub struct EncryptionSyncChanges<'a> {
2852 pub to_device_events: Vec<Raw<AnyToDeviceEvent>>,
2854 pub changed_devices: &'a DeviceLists,
2857 pub one_time_keys_counts: &'a BTreeMap<OneTimeKeyAlgorithm, UInt>,
2859 pub unused_fallback_keys: Option<&'a [OneTimeKeyAlgorithm]>,
2861 pub next_batch_token: Option<String>,
2863}
2864
2865fn megolm_error_to_utd_info(
2873 raw_event: &Raw<EncryptedEvent>,
2874 error: MegolmError,
2875) -> Result<UnableToDecryptInfo, CryptoStoreError> {
2876 use MegolmError::*;
2877 let reason = match error {
2878 EventError(_) => UnableToDecryptReason::MalformedEncryptedEvent,
2879 Decode(_) => UnableToDecryptReason::MalformedEncryptedEvent,
2880 MissingRoomKey(maybe_withheld) => {
2881 UnableToDecryptReason::MissingMegolmSession { withheld_code: maybe_withheld }
2882 }
2883 Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
2884 UnableToDecryptReason::UnknownMegolmMessageIndex
2885 }
2886 Decryption(_) => UnableToDecryptReason::MegolmDecryptionFailure,
2887 JsonError(_) => UnableToDecryptReason::PayloadDeserializationFailure,
2888 MismatchedIdentityKeys(_) => UnableToDecryptReason::MismatchedIdentityKeys,
2889 SenderIdentityNotTrusted(level) => UnableToDecryptReason::SenderIdentityNotTrusted(level),
2890
2891 Store(error) => Err(error)?,
2894 };
2895
2896 let session_id = raw_event.deserialize().ok().and_then(|ev| match ev.content.scheme {
2897 RoomEventEncryptionScheme::MegolmV1AesSha2(s) => Some(s.session_id),
2898 #[cfg(feature = "experimental-algorithms")]
2899 RoomEventEncryptionScheme::MegolmV2AesSha2(s) => Some(s.session_id),
2900 RoomEventEncryptionScheme::Unknown(_) => None,
2901 });
2902
2903 Ok(UnableToDecryptInfo { session_id, reason })
2904}
2905
2906#[cfg(test)]
2907pub(crate) mod test_helpers;
2908
2909#[cfg(test)]
2910pub(crate) mod tests;