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,
27 ProcessedToDeviceEvent, ToDeviceUnableToDecryptInfo, ToDeviceUnableToDecryptReason,
28 UnableToDecryptInfo, UnableToDecryptReason, UnsignedDecryptionResult,
29 UnsignedEventLocation, VerificationLevel, VerificationState,
30 },
31 locks::RwLock as StdRwLock,
32 BoxFuture,
33};
34use ruma::{
35 api::client::{
36 dehydrated_device::DehydratedDeviceData,
37 keys::{
38 claim_keys::v3::Request as KeysClaimRequest,
39 get_keys::v3::Response as KeysQueryResponse,
40 upload_keys::v3::{Request as UploadKeysRequest, Response as UploadKeysResponse},
41 upload_signatures::v3::Request as UploadSignaturesRequest,
42 },
43 sync::sync_events::DeviceLists,
44 },
45 assign,
46 events::{
47 secret::request::SecretName, AnyMessageLikeEvent, AnyMessageLikeEventContent,
48 AnyToDeviceEvent, MessageLikeEventContent,
49 },
50 serde::{JsonObject, Raw},
51 DeviceId, MilliSecondsSinceUnixEpoch, OneTimeKeyAlgorithm, OwnedDeviceId, OwnedDeviceKeyId,
52 OwnedTransactionId, OwnedUserId, RoomId, TransactionId, UInt, UserId,
53};
54use serde_json::{value::to_raw_value, Value};
55use tokio::sync::Mutex;
56use tracing::{
57 debug, error,
58 field::{debug, display},
59 info, instrument, trace, warn, Span,
60};
61use vodozemac::{
62 megolm::{DecryptionError, SessionOrdering},
63 Curve25519PublicKey, Ed25519Signature,
64};
65
66#[cfg(feature = "experimental-send-custom-to-device")]
67use crate::session_manager::split_devices_for_share_strategy;
68use crate::{
69 backups::{BackupMachine, MegolmV1BackupKey},
70 dehydrated_devices::{DehydratedDevices, DehydrationError},
71 error::{EventError, MegolmError, MegolmResult, OlmError, OlmResult, SetRoomSettingsError},
72 gossiping::GossipMachine,
73 identities::{user::UserIdentity, Device, IdentityManager, UserDevices},
74 olm::{
75 Account, CrossSigningStatus, EncryptionSettings, IdentityKeys, InboundGroupSession,
76 KnownSenderData, OlmDecryptionInfo, PrivateCrossSigningIdentity, SenderData,
77 SenderDataFinder, SessionType, StaticAccountData,
78 },
79 session_manager::{GroupSessionManager, SessionManager},
80 store::{
81 caches::StoreCache,
82 types::{
83 Changes, CrossSigningKeyExport, DeviceChanges, IdentityChanges, PendingChanges,
84 RoomKeyInfo, RoomSettings, StoredRoomKeyBundleData,
85 },
86 CryptoStoreWrapper, IntoCryptoStore, MemoryStore, Result as StoreResult, SecretImportError,
87 Store, StoreTransaction,
88 },
89 types::{
90 events::{
91 olm_v1::{AnyDecryptedOlmEvent, DecryptedRoomKeyBundleEvent, DecryptedRoomKeyEvent},
92 room::encrypted::{
93 EncryptedEvent, EncryptedToDeviceEvent, RoomEncryptedEventContent,
94 RoomEventEncryptionScheme, SupportedEventEncryptionSchemes,
95 ToDeviceEncryptedEventContent,
96 },
97 room_key::{MegolmV1AesSha2Content, RoomKeyContent},
98 room_key_bundle::RoomKeyBundleContent,
99 room_key_withheld::{
100 MegolmV1AesSha2WithheldContent, RoomKeyWithheldContent, RoomKeyWithheldEvent,
101 },
102 ToDeviceEvent, ToDeviceEvents,
103 },
104 requests::{
105 AnyIncomingResponse, KeysQueryRequest, OutgoingRequest, ToDeviceRequest,
106 UploadSigningKeysRequest,
107 },
108 EventEncryptionAlgorithm, Signatures,
109 },
110 utilities::timestamp_to_iso8601,
111 verification::{Verification, VerificationMachine, VerificationRequest},
112 CollectStrategy, CryptoStoreError, DecryptionSettings, DeviceData, LocalTrust,
113 RoomEventDecryptionResult, SignatureError, TrustRequirement,
114};
115
116#[derive(Clone)]
119pub struct OlmMachine {
120 pub(crate) inner: Arc<OlmMachineInner>,
121}
122
123pub struct OlmMachineInner {
124 user_id: OwnedUserId,
126 device_id: OwnedDeviceId,
128 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
133 store: Store,
137 session_manager: SessionManager,
139 pub(crate) group_session_manager: GroupSessionManager,
141 verification_machine: VerificationMachine,
144 pub(crate) key_request_machine: GossipMachine,
147 identity_manager: IdentityManager,
150 backup_machine: BackupMachine,
152}
153
154#[cfg(not(tarpaulin_include))]
155impl std::fmt::Debug for OlmMachine {
156 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
157 f.debug_struct("OlmMachine")
158 .field("user_id", &self.user_id())
159 .field("device_id", &self.device_id())
160 .finish()
161 }
162}
163
164impl OlmMachine {
165 const CURRENT_GENERATION_STORE_KEY: &'static str = "generation-counter";
166 const HAS_MIGRATED_VERIFICATION_LATCH: &'static str = "HAS_MIGRATED_VERIFICATION_LATCH";
167
168 pub async fn new(user_id: &UserId, device_id: &DeviceId) -> Self {
179 OlmMachine::with_store(user_id, device_id, MemoryStore::new(), None)
180 .await
181 .expect("Reading and writing to the memory store always succeeds")
182 }
183
184 pub(crate) async fn rehydrate(
185 &self,
186 pickle_key: &[u8; 32],
187 device_id: &DeviceId,
188 device_data: Raw<DehydratedDeviceData>,
189 ) -> Result<OlmMachine, DehydrationError> {
190 let account = Account::rehydrate(pickle_key, self.user_id(), device_id, device_data)?;
191 let static_account = account.static_data().clone();
192
193 let store =
194 Arc::new(CryptoStoreWrapper::new(self.user_id(), device_id, MemoryStore::new()));
195 let device = DeviceData::from_account(&account);
196 store.save_pending_changes(PendingChanges { account: Some(account) }).await?;
197 store
198 .save_changes(Changes {
199 devices: DeviceChanges { new: vec![device], ..Default::default() },
200 ..Default::default()
201 })
202 .await?;
203
204 let (verification_machine, store, identity_manager) =
205 Self::new_helper_prelude(store, static_account, self.store().private_identity());
206
207 Ok(Self::new_helper(
208 device_id,
209 store,
210 verification_machine,
211 identity_manager,
212 self.store().private_identity(),
213 None,
214 ))
215 }
216
217 fn new_helper_prelude(
218 store_wrapper: Arc<CryptoStoreWrapper>,
219 account: StaticAccountData,
220 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
221 ) -> (VerificationMachine, Store, IdentityManager) {
222 let verification_machine =
223 VerificationMachine::new(account.clone(), user_identity.clone(), store_wrapper.clone());
224 let store = Store::new(account, user_identity, store_wrapper, verification_machine.clone());
225
226 let identity_manager = IdentityManager::new(store.clone());
227
228 (verification_machine, store, identity_manager)
229 }
230
231 fn new_helper(
232 device_id: &DeviceId,
233 store: Store,
234 verification_machine: VerificationMachine,
235 identity_manager: IdentityManager,
236 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
237 maybe_backup_key: Option<MegolmV1BackupKey>,
238 ) -> Self {
239 let group_session_manager = GroupSessionManager::new(store.clone());
240
241 let users_for_key_claim = Arc::new(StdRwLock::new(BTreeMap::new()));
242 let key_request_machine = GossipMachine::new(
243 store.clone(),
244 identity_manager.clone(),
245 group_session_manager.session_cache(),
246 users_for_key_claim.clone(),
247 );
248
249 let session_manager =
250 SessionManager::new(users_for_key_claim, key_request_machine.clone(), store.clone());
251
252 let backup_machine = BackupMachine::new(store.clone(), maybe_backup_key);
253
254 let inner = Arc::new(OlmMachineInner {
255 user_id: store.user_id().to_owned(),
256 device_id: device_id.to_owned(),
257 user_identity,
258 store,
259 session_manager,
260 group_session_manager,
261 verification_machine,
262 key_request_machine,
263 identity_manager,
264 backup_machine,
265 });
266
267 Self { inner }
268 }
269
270 #[instrument(skip(store, custom_account), fields(ed25519_key, curve25519_key))]
295 pub async fn with_store(
296 user_id: &UserId,
297 device_id: &DeviceId,
298 store: impl IntoCryptoStore,
299 custom_account: Option<vodozemac::olm::Account>,
300 ) -> StoreResult<Self> {
301 let store = store.into_crypto_store();
302
303 let static_account = match store.load_account().await? {
304 Some(account) => {
305 if user_id != account.user_id()
306 || device_id != account.device_id()
307 || custom_account.is_some()
308 {
309 return Err(CryptoStoreError::MismatchedAccount {
310 expected: (account.user_id().to_owned(), account.device_id().to_owned()),
311 got: (user_id.to_owned(), device_id.to_owned()),
312 });
313 }
314
315 Span::current()
316 .record("ed25519_key", display(account.identity_keys().ed25519))
317 .record("curve25519_key", display(account.identity_keys().curve25519));
318 debug!("Restored an Olm account");
319
320 account.static_data().clone()
321 }
322
323 None => {
324 let account = if let Some(account) = custom_account {
325 Account::new_helper(account, user_id, device_id)
326 } else {
327 Account::with_device_id(user_id, device_id)
328 };
329
330 let static_account = account.static_data().clone();
331
332 Span::current()
333 .record("ed25519_key", display(account.identity_keys().ed25519))
334 .record("curve25519_key", display(account.identity_keys().curve25519));
335
336 let device = DeviceData::from_account(&account);
337
338 device.set_trust_state(LocalTrust::Verified);
342
343 let changes = Changes {
344 devices: DeviceChanges { new: vec![device], ..Default::default() },
345 ..Default::default()
346 };
347 store.save_changes(changes).await?;
348 store.save_pending_changes(PendingChanges { account: Some(account) }).await?;
349
350 debug!("Created a new Olm account");
351
352 static_account
353 }
354 };
355
356 let identity = match store.load_identity().await? {
357 Some(i) => {
358 let master_key = i
359 .master_public_key()
360 .await
361 .and_then(|m| m.get_first_key().map(|m| m.to_owned()));
362 debug!(?master_key, "Restored the cross signing identity");
363 i
364 }
365 None => {
366 debug!("Creating an empty cross signing identity stub");
367 PrivateCrossSigningIdentity::empty(user_id)
368 }
369 };
370
371 let saved_keys = store.load_backup_keys().await?;
376 let maybe_backup_key = saved_keys.decryption_key.and_then(|k| {
377 if let Some(version) = saved_keys.backup_version {
378 let megolm_v1_backup_key = k.megolm_v1_public_key();
379 megolm_v1_backup_key.set_version(version);
380 Some(megolm_v1_backup_key)
381 } else {
382 None
383 }
384 });
385
386 let identity = Arc::new(Mutex::new(identity));
387 let store = Arc::new(CryptoStoreWrapper::new(user_id, device_id, store));
388
389 let (verification_machine, store, identity_manager) =
390 Self::new_helper_prelude(store, static_account, identity.clone());
391
392 Self::migration_post_verified_latch_support(&store, &identity_manager).await?;
395
396 Ok(Self::new_helper(
397 device_id,
398 store,
399 verification_machine,
400 identity_manager,
401 identity,
402 maybe_backup_key,
403 ))
404 }
405
406 pub(crate) async fn migration_post_verified_latch_support(
414 store: &Store,
415 identity_manager: &IdentityManager,
416 ) -> Result<(), CryptoStoreError> {
417 let maybe_migrate_for_identity_verified_latch =
418 store.get_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH).await?.is_none();
419
420 if maybe_migrate_for_identity_verified_latch {
421 identity_manager.mark_all_tracked_users_as_dirty(store.cache().await?).await?;
422
423 store.set_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH, vec![0]).await?
424 }
425 Ok(())
426 }
427
428 pub fn store(&self) -> &Store {
430 &self.inner.store
431 }
432
433 pub fn user_id(&self) -> &UserId {
435 &self.inner.user_id
436 }
437
438 pub fn device_id(&self) -> &DeviceId {
440 &self.inner.device_id
441 }
442
443 pub fn device_creation_time(&self) -> MilliSecondsSinceUnixEpoch {
450 self.inner.store.static_account().creation_local_time()
451 }
452
453 pub fn identity_keys(&self) -> IdentityKeys {
455 let account = self.inner.store.static_account();
456 account.identity_keys()
457 }
458
459 pub async fn display_name(&self) -> StoreResult<Option<String>> {
461 self.store().device_display_name().await
462 }
463
464 pub async fn tracked_users(&self) -> StoreResult<HashSet<OwnedUserId>> {
469 let cache = self.store().cache().await?;
470 Ok(self.inner.identity_manager.key_query_manager.synced(&cache).await?.tracked_users())
471 }
472
473 #[cfg(feature = "automatic-room-key-forwarding")]
482 pub fn set_room_key_requests_enabled(&self, enable: bool) {
483 self.inner.key_request_machine.set_room_key_requests_enabled(enable)
484 }
485
486 pub fn are_room_key_requests_enabled(&self) -> bool {
491 self.inner.key_request_machine.are_room_key_requests_enabled()
492 }
493
494 #[cfg(feature = "automatic-room-key-forwarding")]
503 pub fn set_room_key_forwarding_enabled(&self, enable: bool) {
504 self.inner.key_request_machine.set_room_key_forwarding_enabled(enable)
505 }
506
507 pub fn is_room_key_forwarding_enabled(&self) -> bool {
511 self.inner.key_request_machine.is_room_key_forwarding_enabled()
512 }
513
514 pub async fn outgoing_requests(&self) -> StoreResult<Vec<OutgoingRequest>> {
522 let mut requests = Vec::new();
523
524 {
525 let store_cache = self.inner.store.cache().await?;
526 let account = store_cache.account().await?;
527 if let Some(r) = self.keys_for_upload(&account).await.map(|r| OutgoingRequest {
528 request_id: TransactionId::new(),
529 request: Arc::new(r.into()),
530 }) {
531 requests.push(r);
532 }
533 }
534
535 for request in self
536 .inner
537 .identity_manager
538 .users_for_key_query()
539 .await?
540 .into_iter()
541 .map(|(request_id, r)| OutgoingRequest { request_id, request: Arc::new(r.into()) })
542 {
543 requests.push(request);
544 }
545
546 requests.append(&mut self.inner.verification_machine.outgoing_messages());
547 requests.append(&mut self.inner.key_request_machine.outgoing_to_device_requests().await?);
548
549 Ok(requests)
550 }
551
552 pub fn query_keys_for_users<'a>(
573 &self,
574 users: impl IntoIterator<Item = &'a UserId>,
575 ) -> (OwnedTransactionId, KeysQueryRequest) {
576 self.inner.identity_manager.build_key_query_for_users(users)
577 }
578
579 pub async fn mark_request_as_sent<'a>(
589 &self,
590 request_id: &TransactionId,
591 response: impl Into<AnyIncomingResponse<'a>>,
592 ) -> OlmResult<()> {
593 match response.into() {
594 AnyIncomingResponse::KeysUpload(response) => {
595 Box::pin(self.receive_keys_upload_response(response)).await?;
596 }
597 AnyIncomingResponse::KeysQuery(response) => {
598 Box::pin(self.receive_keys_query_response(request_id, response)).await?;
599 }
600 AnyIncomingResponse::KeysClaim(response) => {
601 Box::pin(
602 self.inner.session_manager.receive_keys_claim_response(request_id, response),
603 )
604 .await?;
605 }
606 AnyIncomingResponse::ToDevice(_) => {
607 Box::pin(self.mark_to_device_request_as_sent(request_id)).await?;
608 }
609 AnyIncomingResponse::SigningKeysUpload(_) => {
610 Box::pin(self.receive_cross_signing_upload_response()).await?;
611 }
612 AnyIncomingResponse::SignatureUpload(_) => {
613 self.inner.verification_machine.mark_request_as_sent(request_id);
614 }
615 AnyIncomingResponse::RoomMessage(_) => {
616 self.inner.verification_machine.mark_request_as_sent(request_id);
617 }
618 AnyIncomingResponse::KeysBackup(_) => {
619 Box::pin(self.inner.backup_machine.mark_request_as_sent(request_id)).await?;
620 }
621 }
622
623 Ok(())
624 }
625
626 async fn receive_cross_signing_upload_response(&self) -> StoreResult<()> {
628 let identity = self.inner.user_identity.lock().await;
629 identity.mark_as_shared();
630
631 let changes = Changes { private_identity: Some(identity.clone()), ..Default::default() };
632
633 self.store().save_changes(changes).await
634 }
635
636 pub async fn bootstrap_cross_signing(
655 &self,
656 reset: bool,
657 ) -> StoreResult<CrossSigningBootstrapRequests> {
658 let identity = self.inner.user_identity.lock().await.clone();
663
664 let (upload_signing_keys_req, upload_signatures_req) = if reset || identity.is_empty().await
665 {
666 info!("Creating new cross signing identity");
667
668 let (identity, upload_signing_keys_req, upload_signatures_req) = {
669 let cache = self.inner.store.cache().await?;
670 let account = cache.account().await?;
671 account.bootstrap_cross_signing().await
672 };
673
674 let public = identity.to_public_identity().await.expect(
675 "Couldn't create a public version of the identity from a new private identity",
676 );
677
678 *self.inner.user_identity.lock().await = identity.clone();
679
680 self.store()
681 .save_changes(Changes {
682 identities: IdentityChanges { new: vec![public.into()], ..Default::default() },
683 private_identity: Some(identity),
684 ..Default::default()
685 })
686 .await?;
687
688 (upload_signing_keys_req, upload_signatures_req)
689 } else {
690 info!("Trying to upload the existing cross signing identity");
691 let upload_signing_keys_req = identity.as_upload_request().await;
692
693 let upload_signatures_req = identity
695 .sign_account(self.inner.store.static_account())
696 .await
697 .expect("Can't sign device keys");
698
699 (upload_signing_keys_req, upload_signatures_req)
700 };
701
702 let upload_keys_req =
706 self.upload_device_keys().await?.map(|(_, request)| OutgoingRequest::from(request));
707
708 Ok(CrossSigningBootstrapRequests {
709 upload_signing_keys_req,
710 upload_keys_req,
711 upload_signatures_req,
712 })
713 }
714
715 pub async fn upload_device_keys(
727 &self,
728 ) -> StoreResult<Option<(OwnedTransactionId, UploadKeysRequest)>> {
729 let cache = self.store().cache().await?;
730 let account = cache.account().await?;
731
732 Ok(self.keys_for_upload(&account).await.map(|request| (TransactionId::new(), request)))
733 }
734
735 async fn receive_keys_upload_response(&self, response: &UploadKeysResponse) -> OlmResult<()> {
742 self.inner
743 .store
744 .with_transaction(|mut tr| async {
745 let account = tr.account().await?;
746 account.receive_keys_upload_response(response)?;
747 Ok((tr, ()))
748 })
749 .await
750 }
751
752 #[instrument(skip_all)]
780 pub async fn get_missing_sessions(
781 &self,
782 users: impl Iterator<Item = &UserId>,
783 ) -> StoreResult<Option<(OwnedTransactionId, KeysClaimRequest)>> {
784 self.inner.session_manager.get_missing_sessions(users).await
785 }
786
787 async fn receive_keys_query_response(
796 &self,
797 request_id: &TransactionId,
798 response: &KeysQueryResponse,
799 ) -> OlmResult<(DeviceChanges, IdentityChanges)> {
800 self.inner.identity_manager.receive_keys_query_response(request_id, response).await
801 }
802
803 async fn keys_for_upload(&self, account: &Account) -> Option<UploadKeysRequest> {
812 let (mut device_keys, one_time_keys, fallback_keys) = account.keys_for_upload();
813
814 if let Some(device_keys) = &mut device_keys {
824 let private_identity = self.store().private_identity();
825 let guard = private_identity.lock().await;
826
827 if guard.status().await.is_complete() {
828 guard.sign_device_keys(device_keys).await.expect(
829 "We should be able to sign our device keys since we confirmed that we \
830 have a complete set of private cross-signing keys",
831 );
832 }
833 }
834
835 if device_keys.is_none() && one_time_keys.is_empty() && fallback_keys.is_empty() {
836 None
837 } else {
838 let device_keys = device_keys.map(|d| d.to_raw());
839
840 Some(assign!(UploadKeysRequest::new(), {
841 device_keys, one_time_keys, fallback_keys
842 }))
843 }
844 }
845
846 async fn decrypt_to_device_event(
869 &self,
870 transaction: &mut StoreTransaction,
871 event: &EncryptedToDeviceEvent,
872 changes: &mut Changes,
873 decryption_settings: &DecryptionSettings,
874 ) -> Result<OlmDecryptionInfo, DecryptToDeviceError> {
875 let mut decrypted = transaction
877 .account()
878 .await?
879 .decrypt_to_device_event(&self.inner.store, event, decryption_settings)
880 .await?;
881
882 self.check_to_device_event_is_not_from_dehydrated_device(&decrypted, &event.sender).await?;
884
885 self.handle_decrypted_to_device_event(transaction.cache(), &mut decrypted, changes).await?;
887
888 Ok(decrypted)
889 }
890
891 #[instrument(
892 skip_all,
893 fields(room_id = ? content.room_id, session_id)
897 )]
898 async fn handle_key(
899 &self,
900 sender_key: Curve25519PublicKey,
901 event: &DecryptedRoomKeyEvent,
902 content: &MegolmV1AesSha2Content,
903 ) -> OlmResult<Option<InboundGroupSession>> {
904 let session =
905 InboundGroupSession::from_room_key_content(sender_key, event.keys.ed25519, content);
906
907 match session {
908 Ok(mut session) => {
909 Span::current().record("session_id", session.session_id());
910
911 let sender_data =
912 SenderDataFinder::find_using_event(self.store(), sender_key, event, &session)
913 .await?;
914
915 session.sender_data = sender_data;
916
917 match self.store().compare_group_session(&session).await? {
918 SessionOrdering::Better => {
919 info!("Received a new megolm room key");
920
921 Ok(Some(session))
922 }
923 comparison_result => {
924 warn!(
925 ?comparison_result,
926 "Received a megolm room key that we already have a better version \
927 of, discarding"
928 );
929
930 Ok(None)
931 }
932 }
933 }
934 Err(e) => {
935 Span::current().record("session_id", &content.session_id);
936 warn!("Received a room key event which contained an invalid session key: {e}");
937
938 Ok(None)
939 }
940 }
941 }
942
943 #[instrument(skip_all, fields(algorithm = ?event.content.algorithm()))]
945 async fn add_room_key(
946 &self,
947 sender_key: Curve25519PublicKey,
948 event: &DecryptedRoomKeyEvent,
949 ) -> OlmResult<Option<InboundGroupSession>> {
950 match &event.content {
951 RoomKeyContent::MegolmV1AesSha2(content) => {
952 self.handle_key(sender_key, event, content).await
953 }
954 #[cfg(feature = "experimental-algorithms")]
955 RoomKeyContent::MegolmV2AesSha2(content) => {
956 self.handle_key(sender_key, event, content).await
957 }
958 RoomKeyContent::Unknown(_) => {
959 warn!("Received a room key with an unsupported algorithm");
960 Ok(None)
961 }
962 }
963 }
964
965 #[instrument()]
968 async fn receive_room_key_bundle_data(
969 &self,
970 sender_key: Curve25519PublicKey,
971 event: &DecryptedRoomKeyBundleEvent,
972 changes: &mut Changes,
973 ) -> OlmResult<()> {
974 let Some(sender_device_keys) = &event.sender_device_keys else {
975 warn!("Received a room key bundle with no sender device keys: ignoring");
976 return Ok(());
977 };
978
979 let sender_device_data =
984 DeviceData::try_from(sender_device_keys).expect("failed to verify sender device keys");
985 let sender_device = self.store().wrap_device_data(sender_device_data).await?;
986
987 changes.received_room_key_bundles.push(StoredRoomKeyBundleData {
988 sender_user: event.sender.clone(),
989 sender_data: SenderData::from_device(&sender_device),
990 sender_key,
991 bundle_data: event.content.clone(),
992 });
993 Ok(())
994 }
995
996 fn add_withheld_info(&self, changes: &mut Changes, event: &RoomKeyWithheldEvent) {
997 debug!(?event.content, "Processing `m.room_key.withheld` event");
998
999 if let RoomKeyWithheldContent::MegolmV1AesSha2(
1000 MegolmV1AesSha2WithheldContent::BlackListed(c)
1001 | MegolmV1AesSha2WithheldContent::Unverified(c),
1002 ) = &event.content
1003 {
1004 changes
1005 .withheld_session_info
1006 .entry(c.room_id.to_owned())
1007 .or_default()
1008 .insert(c.session_id.to_owned(), event.to_owned());
1009 }
1010 }
1011
1012 #[cfg(test)]
1013 pub(crate) async fn create_outbound_group_session_with_defaults_test_helper(
1014 &self,
1015 room_id: &RoomId,
1016 ) -> OlmResult<()> {
1017 let (_, session) = self
1018 .inner
1019 .group_session_manager
1020 .create_outbound_group_session(
1021 room_id,
1022 EncryptionSettings::default(),
1023 SenderData::unknown(),
1024 )
1025 .await?;
1026
1027 self.store().save_inbound_group_sessions(&[session]).await?;
1028
1029 Ok(())
1030 }
1031
1032 #[cfg(test)]
1033 #[allow(dead_code)]
1034 pub(crate) async fn create_inbound_session_test_helper(
1035 &self,
1036 room_id: &RoomId,
1037 ) -> OlmResult<InboundGroupSession> {
1038 let (_, session) = self
1039 .inner
1040 .group_session_manager
1041 .create_outbound_group_session(
1042 room_id,
1043 EncryptionSettings::default(),
1044 SenderData::unknown(),
1045 )
1046 .await?;
1047
1048 Ok(session)
1049 }
1050
1051 pub async fn encrypt_room_event(
1068 &self,
1069 room_id: &RoomId,
1070 content: impl MessageLikeEventContent,
1071 ) -> MegolmResult<Raw<RoomEncryptedEventContent>> {
1072 let event_type = content.event_type().to_string();
1073 let content = Raw::new(&content)?.cast_unchecked();
1074 self.encrypt_room_event_raw(room_id, &event_type, &content).await
1075 }
1076
1077 pub async fn encrypt_room_event_raw(
1097 &self,
1098 room_id: &RoomId,
1099 event_type: &str,
1100 content: &Raw<AnyMessageLikeEventContent>,
1101 ) -> MegolmResult<Raw<RoomEncryptedEventContent>> {
1102 self.inner.group_session_manager.encrypt(room_id, event_type, content).await
1103 }
1104
1105 pub async fn discard_room_key(&self, room_id: &RoomId) -> StoreResult<bool> {
1116 self.inner.group_session_manager.invalidate_group_session(room_id).await
1117 }
1118
1119 pub async fn share_room_key(
1139 &self,
1140 room_id: &RoomId,
1141 users: impl Iterator<Item = &UserId>,
1142 encryption_settings: impl Into<EncryptionSettings>,
1143 ) -> OlmResult<Vec<Arc<ToDeviceRequest>>> {
1144 self.inner.group_session_manager.share_room_key(room_id, users, encryption_settings).await
1145 }
1146
1147 #[cfg(feature = "experimental-send-custom-to-device")]
1161 pub async fn encrypt_content_for_devices(
1162 &self,
1163 devices: Vec<DeviceData>,
1164 event_type: &str,
1165 content: &Value,
1166 share_strategy: CollectStrategy,
1167 ) -> OlmResult<(Vec<ToDeviceRequest>, Vec<(DeviceData, WithheldCode)>)> {
1168 let mut changes = Changes::default();
1169
1170 let (allowed_devices, mut blocked_devices) =
1171 split_devices_for_share_strategy(&self.inner.store, devices, share_strategy).await?;
1172
1173 let result = self
1174 .inner
1175 .group_session_manager
1176 .encrypt_content_for_devices(allowed_devices, event_type, content.clone(), &mut changes)
1177 .await;
1178
1179 if !changes.is_empty() {
1181 let session_count = changes.sessions.len();
1182
1183 self.inner.store.save_changes(changes).await?;
1184
1185 trace!(
1186 session_count = session_count,
1187 "Stored the changed sessions after encrypting a custom to-device event"
1188 );
1189 }
1190
1191 result.map(|(to_device_requests, mut withheld)| {
1192 withheld.append(&mut blocked_devices);
1193 (to_device_requests, withheld)
1194 })
1195 }
1196 pub async fn share_room_key_bundle_data(
1201 &self,
1202 user_id: &UserId,
1203 collect_strategy: &CollectStrategy,
1204 bundle_data: RoomKeyBundleContent,
1205 ) -> OlmResult<Vec<ToDeviceRequest>> {
1206 self.inner
1207 .group_session_manager
1208 .share_room_key_bundle_data(user_id, collect_strategy, bundle_data)
1209 .await
1210 }
1211
1212 #[deprecated(note = "Use OlmMachine::receive_verification_event instead", since = "0.7.0")]
1220 pub async fn receive_unencrypted_verification_event(
1221 &self,
1222 event: &AnyMessageLikeEvent,
1223 ) -> StoreResult<()> {
1224 self.inner.verification_machine.receive_any_event(event).await
1225 }
1226
1227 pub async fn receive_verification_event(&self, event: &AnyMessageLikeEvent) -> StoreResult<()> {
1231 self.inner.verification_machine.receive_any_event(event).await
1232 }
1233
1234 #[instrument(
1240 skip_all,
1241 fields(
1242 sender_key = ?decrypted.result.sender_key,
1243 event_type = decrypted.result.event.event_type(),
1244 ),
1245 )]
1246 async fn handle_decrypted_to_device_event(
1247 &self,
1248 cache: &StoreCache,
1249 decrypted: &mut OlmDecryptionInfo,
1250 changes: &mut Changes,
1251 ) -> OlmResult<()> {
1252 debug!(
1253 sender_device_keys =
1254 ?decrypted.result.event.sender_device_keys().map(|k| (k.curve25519_key(), k.ed25519_key())).unwrap_or((None, None)),
1255 "Received a decrypted to-device event",
1256 );
1257
1258 match &*decrypted.result.event {
1259 AnyDecryptedOlmEvent::RoomKey(e) => {
1260 let session = self.add_room_key(decrypted.result.sender_key, e).await?;
1261 decrypted.inbound_group_session = session;
1262 }
1263 AnyDecryptedOlmEvent::ForwardedRoomKey(e) => {
1264 let session = self
1265 .inner
1266 .key_request_machine
1267 .receive_forwarded_room_key(decrypted.result.sender_key, e)
1268 .await?;
1269 decrypted.inbound_group_session = session;
1270 }
1271 AnyDecryptedOlmEvent::SecretSend(e) => {
1272 let name = self
1273 .inner
1274 .key_request_machine
1275 .receive_secret_event(cache, decrypted.result.sender_key, e, changes)
1276 .await?;
1277
1278 if let Ok(ToDeviceEvents::SecretSend(mut e)) =
1281 decrypted.result.raw_event.deserialize_as()
1282 {
1283 e.content.secret_name = name;
1284 decrypted.result.raw_event = Raw::from_json(to_raw_value(&e)?);
1285 }
1286 }
1287 AnyDecryptedOlmEvent::Dummy(_) => {
1288 debug!("Received an `m.dummy` event");
1289 }
1290 AnyDecryptedOlmEvent::RoomKeyBundle(e) => {
1291 debug!("Received a room key bundle event {:?}", e);
1292 self.receive_room_key_bundle_data(decrypted.result.sender_key, e, changes).await?;
1293 }
1294 AnyDecryptedOlmEvent::Custom(_) => {
1295 warn!("Received an unexpected encrypted to-device event");
1296 }
1297 }
1298
1299 Ok(())
1300 }
1301
1302 async fn handle_verification_event(&self, event: &ToDeviceEvents) {
1303 if let Err(e) = self.inner.verification_machine.receive_any_event(event).await {
1304 error!("Error handling a verification event: {e:?}");
1305 }
1306 }
1307
1308 async fn mark_to_device_request_as_sent(&self, request_id: &TransactionId) -> StoreResult<()> {
1310 self.inner.verification_machine.mark_request_as_sent(request_id);
1311 self.inner.key_request_machine.mark_outgoing_request_as_sent(request_id).await?;
1312 self.inner.group_session_manager.mark_request_as_sent(request_id).await?;
1313 self.inner.session_manager.mark_outgoing_request_as_sent(request_id);
1314 Ok(())
1315 }
1316
1317 pub fn get_verification(&self, user_id: &UserId, flow_id: &str) -> Option<Verification> {
1319 self.inner.verification_machine.get_verification(user_id, flow_id)
1320 }
1321
1322 pub fn get_verification_request(
1324 &self,
1325 user_id: &UserId,
1326 flow_id: impl AsRef<str>,
1327 ) -> Option<VerificationRequest> {
1328 self.inner.verification_machine.get_request(user_id, flow_id)
1329 }
1330
1331 pub fn get_verification_requests(&self, user_id: &UserId) -> Vec<VerificationRequest> {
1333 self.inner.verification_machine.get_requests(user_id)
1334 }
1335
1336 async fn handle_to_device_event(&self, changes: &mut Changes, event: &ToDeviceEvents) {
1341 use crate::types::events::ToDeviceEvents::*;
1342
1343 match event {
1344 RoomKeyRequest(e) => self.inner.key_request_machine.receive_incoming_key_request(e),
1350 SecretRequest(e) => self.inner.key_request_machine.receive_incoming_secret_request(e),
1351 RoomKeyWithheld(e) => self.add_withheld_info(changes, e),
1352 KeyVerificationAccept(..)
1353 | KeyVerificationCancel(..)
1354 | KeyVerificationKey(..)
1355 | KeyVerificationMac(..)
1356 | KeyVerificationRequest(..)
1357 | KeyVerificationReady(..)
1358 | KeyVerificationDone(..)
1359 | KeyVerificationStart(..) => {
1360 self.handle_verification_event(event).await;
1361 }
1362
1363 Custom(_) | Dummy(_) => {}
1365
1366 RoomEncrypted(_) => {}
1368
1369 SecretSend(_) | RoomKey(_) | ForwardedRoomKey(_) => {}
1372 }
1373 }
1374
1375 fn record_message_id(event: &Raw<AnyToDeviceEvent>) {
1376 use serde::Deserialize;
1377
1378 #[derive(Deserialize)]
1379 struct ContentStub<'a> {
1380 #[serde(borrow, rename = "org.matrix.msgid")]
1381 message_id: Option<&'a str>,
1382 }
1383 #[derive(Deserialize)]
1384 struct ToDeviceStub<'a> {
1385 sender: &'a str,
1386 #[serde(rename = "type")]
1387 event_type: &'a str,
1388 #[serde(borrow)]
1389 content: ContentStub<'a>,
1390 }
1391
1392 if let Ok(event) = event.deserialize_as_unchecked::<ToDeviceStub<'_>>() {
1393 Span::current().record("sender", event.sender);
1394 Span::current().record("event_type", event.event_type);
1395 Span::current().record("message_id", event.content.message_id);
1396 }
1397 }
1398
1399 #[instrument(skip_all, fields(sender, event_type, message_id))]
1407 async fn receive_to_device_event(
1408 &self,
1409 transaction: &mut StoreTransaction,
1410 changes: &mut Changes,
1411 raw_event: Raw<AnyToDeviceEvent>,
1412 decryption_settings: &DecryptionSettings,
1413 ) -> Option<ProcessedToDeviceEvent> {
1414 Self::record_message_id(&raw_event);
1415
1416 let event: ToDeviceEvents = match raw_event.deserialize_as() {
1417 Ok(e) => e,
1418 Err(e) => {
1419 warn!("Received an invalid to-device event: {e}");
1421 return Some(ProcessedToDeviceEvent::Invalid(raw_event));
1422 }
1423 };
1424
1425 debug!("Received a to-device event");
1426
1427 match event {
1428 ToDeviceEvents::RoomEncrypted(e) => {
1429 self.receive_encrypted_to_device_event(
1430 transaction,
1431 changes,
1432 raw_event,
1433 e,
1434 decryption_settings,
1435 )
1436 .await
1437 }
1438 e => {
1439 self.handle_to_device_event(changes, &e).await;
1440 Some(ProcessedToDeviceEvent::PlainText(raw_event))
1441 }
1442 }
1443 }
1444
1445 async fn receive_encrypted_to_device_event(
1459 &self,
1460 transaction: &mut StoreTransaction,
1461 changes: &mut Changes,
1462 mut raw_event: Raw<AnyToDeviceEvent>,
1463 e: ToDeviceEvent<ToDeviceEncryptedEventContent>,
1464 decryption_settings: &DecryptionSettings,
1465 ) -> Option<ProcessedToDeviceEvent> {
1466 let decrypted = match self
1467 .decrypt_to_device_event(transaction, &e, changes, decryption_settings)
1468 .await
1469 {
1470 Ok(decrypted) => decrypted,
1471 Err(DecryptToDeviceError::OlmError(err)) => {
1472 let reason = if let OlmError::UnverifiedSenderDevice = &err {
1473 ToDeviceUnableToDecryptReason::UnverifiedSenderDevice
1474 } else {
1475 ToDeviceUnableToDecryptReason::DecryptionFailure
1476 };
1477
1478 if let OlmError::SessionWedged(sender, curve_key) = err {
1479 if let Err(e) =
1480 self.inner.session_manager.mark_device_as_wedged(&sender, curve_key).await
1481 {
1482 error!(
1483 error = ?e,
1484 "Couldn't mark device to be unwedged",
1485 );
1486 }
1487 }
1488
1489 return Some(ProcessedToDeviceEvent::UnableToDecrypt {
1490 encrypted_event: raw_event,
1491 utd_info: ToDeviceUnableToDecryptInfo { reason },
1492 });
1493 }
1494 Err(DecryptToDeviceError::FromDehydratedDevice) => return None,
1495 };
1496
1497 match decrypted.session {
1500 SessionType::New(s) | SessionType::Existing(s) => {
1501 changes.sessions.push(s);
1502 }
1503 }
1504
1505 changes.message_hashes.push(decrypted.message_hash);
1506
1507 if let Some(group_session) = decrypted.inbound_group_session {
1508 changes.inbound_group_sessions.push(group_session);
1509 }
1510
1511 match decrypted.result.raw_event.deserialize_as() {
1512 Ok(event) => {
1513 self.handle_to_device_event(changes, &event).await;
1514
1515 raw_event = event
1516 .serialize_zeroized()
1517 .expect("Zeroizing and reserializing our events should always work")
1518 .cast();
1519 }
1520 Err(e) => {
1521 warn!("Received an invalid encrypted to-device event: {e}");
1522 raw_event = decrypted.result.raw_event;
1523 }
1524 }
1525
1526 Some(ProcessedToDeviceEvent::Decrypted {
1527 raw: raw_event,
1528 encryption_info: decrypted.result.encryption_info,
1529 })
1530 }
1531
1532 async fn check_to_device_event_is_not_from_dehydrated_device(
1535 &self,
1536 decrypted: &OlmDecryptionInfo,
1537 sender_user_id: &UserId,
1538 ) -> Result<(), DecryptToDeviceError> {
1539 if self.to_device_event_is_from_dehydrated_device(decrypted, sender_user_id).await? {
1540 warn!(
1541 sender = ?sender_user_id,
1542 session = ?decrypted.session,
1543 "Received a to-device event from a dehydrated device. This is unexpected: ignoring event"
1544 );
1545 Err(DecryptToDeviceError::FromDehydratedDevice)
1546 } else {
1547 Ok(())
1548 }
1549 }
1550
1551 async fn to_device_event_is_from_dehydrated_device(
1557 &self,
1558 decrypted: &OlmDecryptionInfo,
1559 sender_user_id: &UserId,
1560 ) -> OlmResult<bool> {
1561 if let Some(device_keys) = decrypted.result.event.sender_device_keys() {
1563 if device_keys.dehydrated.unwrap_or(false) {
1569 return Ok(true);
1570 }
1571 }
1576
1577 Ok(self
1579 .store()
1580 .get_device_from_curve_key(sender_user_id, decrypted.result.sender_key)
1581 .await?
1582 .is_some_and(|d| d.is_dehydrated()))
1583 }
1584
1585 #[instrument(skip_all)]
1603 pub async fn receive_sync_changes(
1604 &self,
1605 sync_changes: EncryptionSyncChanges<'_>,
1606 decryption_settings: &DecryptionSettings,
1607 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Vec<RoomKeyInfo>)> {
1608 let mut store_transaction = self.inner.store.transaction().await;
1609
1610 let (events, changes) = self
1611 .preprocess_sync_changes(&mut store_transaction, sync_changes, decryption_settings)
1612 .await?;
1613
1614 let room_key_updates: Vec<_> =
1617 changes.inbound_group_sessions.iter().map(RoomKeyInfo::from).collect();
1618
1619 self.store().save_changes(changes).await?;
1620 store_transaction.commit().await?;
1621
1622 Ok((events, room_key_updates))
1623 }
1624
1625 pub(crate) async fn preprocess_sync_changes(
1643 &self,
1644 transaction: &mut StoreTransaction,
1645 sync_changes: EncryptionSyncChanges<'_>,
1646 decryption_settings: &DecryptionSettings,
1647 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Changes)> {
1648 let mut events: Vec<ProcessedToDeviceEvent> = self
1650 .inner
1651 .verification_machine
1652 .garbage_collect()
1653 .iter()
1654 .map(|e| ProcessedToDeviceEvent::PlainText(e.clone()))
1658 .collect();
1659 let mut changes = Default::default();
1662
1663 {
1664 let account = transaction.account().await?;
1665 account.update_key_counts(
1666 sync_changes.one_time_keys_counts,
1667 sync_changes.unused_fallback_keys,
1668 )
1669 }
1670
1671 if let Err(e) = self
1672 .inner
1673 .identity_manager
1674 .receive_device_changes(
1675 transaction.cache(),
1676 sync_changes.changed_devices.changed.iter().map(|u| u.as_ref()),
1677 )
1678 .await
1679 {
1680 error!(error = ?e, "Error marking a tracked user as changed");
1681 }
1682
1683 for raw_event in sync_changes.to_device_events {
1684 let processed_event = Box::pin(self.receive_to_device_event(
1685 transaction,
1686 &mut changes,
1687 raw_event,
1688 decryption_settings,
1689 ))
1690 .await;
1691
1692 if let Some(processed_event) = processed_event {
1693 events.push(processed_event);
1694 }
1695 }
1696
1697 let changed_sessions = self
1698 .inner
1699 .key_request_machine
1700 .collect_incoming_key_requests(transaction.cache())
1701 .await?;
1702
1703 changes.sessions.extend(changed_sessions);
1704 changes.next_batch_token = sync_changes.next_batch_token;
1705
1706 Ok((events, changes))
1707 }
1708
1709 pub async fn request_room_key(
1726 &self,
1727 event: &Raw<EncryptedEvent>,
1728 room_id: &RoomId,
1729 ) -> MegolmResult<(Option<OutgoingRequest>, OutgoingRequest)> {
1730 let event = event.deserialize()?;
1731 self.inner.key_request_machine.request_key(room_id, &event).await
1732 }
1733
1734 async fn get_room_event_verification_state(
1747 &self,
1748 session: &InboundGroupSession,
1749 sender: &UserId,
1750 ) -> MegolmResult<(VerificationState, Option<OwnedDeviceId>)> {
1751 let sender_data = self.get_or_update_sender_data(session, sender).await?;
1752
1753 let (verification_state, device_id) = match sender_data.user_id() {
1762 Some(i) if i != sender => {
1763 (VerificationState::Unverified(VerificationLevel::MismatchedSender), None)
1764 }
1765
1766 Some(_) | None => {
1767 sender_data_to_verification_state(sender_data, session.has_been_imported())
1768 }
1769 };
1770
1771 Ok((verification_state, device_id))
1772 }
1773
1774 async fn get_or_update_sender_data(
1789 &self,
1790 session: &InboundGroupSession,
1791 sender: &UserId,
1792 ) -> MegolmResult<SenderData> {
1793 let sender_data = if session.sender_data.should_recalculate() {
1794 let calculated_sender_data = SenderDataFinder::find_using_curve_key(
1813 self.store(),
1814 session.sender_key(),
1815 sender,
1816 session,
1817 )
1818 .await?;
1819
1820 if calculated_sender_data.compare_trust_level(&session.sender_data).is_gt() {
1822 let mut new_session = session.clone();
1824 new_session.sender_data = calculated_sender_data.clone();
1825 self.store().save_inbound_group_sessions(&[new_session]).await?;
1826
1827 calculated_sender_data
1829 } else {
1830 session.sender_data.clone()
1832 }
1833 } else {
1834 session.sender_data.clone()
1835 };
1836
1837 Ok(sender_data)
1838 }
1839
1840 pub async fn query_missing_secrets_from_other_sessions(&self) -> StoreResult<bool> {
1865 let identity = self.inner.user_identity.lock().await;
1866 let mut secrets = identity.get_missing_secrets().await;
1867
1868 if self.store().load_backup_keys().await?.decryption_key.is_none() {
1869 secrets.push(SecretName::RecoveryKey);
1870 }
1871
1872 if secrets.is_empty() {
1873 debug!("No missing requests to query");
1874 return Ok(false);
1875 }
1876
1877 let secret_requests = GossipMachine::request_missing_secrets(self.user_id(), secrets);
1878
1879 let unsent_request = self.store().get_unsent_secret_requests().await?;
1881 let not_yet_requested = secret_requests
1882 .into_iter()
1883 .filter(|request| !unsent_request.iter().any(|unsent| unsent.info == request.info))
1884 .collect_vec();
1885
1886 if not_yet_requested.is_empty() {
1887 debug!("The missing secrets have already been requested");
1888 Ok(false)
1889 } else {
1890 debug!("Requesting missing secrets");
1891
1892 let changes = Changes { key_requests: not_yet_requested, ..Default::default() };
1893
1894 self.store().save_changes(changes).await?;
1895 Ok(true)
1896 }
1897 }
1898
1899 async fn get_encryption_info(
1905 &self,
1906 session: &InboundGroupSession,
1907 sender: &UserId,
1908 ) -> MegolmResult<Arc<EncryptionInfo>> {
1909 let (verification_state, device_id) =
1910 self.get_room_event_verification_state(session, sender).await?;
1911
1912 let sender = sender.to_owned();
1913
1914 Ok(Arc::new(EncryptionInfo {
1915 sender,
1916 sender_device: device_id,
1917 algorithm_info: AlgorithmInfo::MegolmV1AesSha2 {
1918 curve25519_key: session.sender_key().to_base64(),
1919 sender_claimed_keys: session
1920 .signing_keys()
1921 .iter()
1922 .map(|(k, v)| (k.to_owned(), v.to_base64()))
1923 .collect(),
1924 session_id: Some(session.session_id().to_owned()),
1925 },
1926 verification_state,
1927 }))
1928 }
1929
1930 async fn decrypt_megolm_events(
1931 &self,
1932 room_id: &RoomId,
1933 event: &EncryptedEvent,
1934 content: &SupportedEventEncryptionSchemes<'_>,
1935 decryption_settings: &DecryptionSettings,
1936 ) -> MegolmResult<(JsonObject, Arc<EncryptionInfo>)> {
1937 let session =
1938 self.get_inbound_group_session_or_error(room_id, content.session_id()).await?;
1939
1940 Span::current().record("sender_key", debug(session.sender_key()));
1946
1947 let result = session.decrypt(event).await;
1948 match result {
1949 Ok((decrypted_event, _)) => {
1950 let encryption_info = self.get_encryption_info(&session, &event.sender).await?;
1951
1952 self.check_sender_trust_requirement(
1953 &session,
1954 &encryption_info,
1955 &decryption_settings.sender_device_trust_requirement,
1956 )?;
1957
1958 Ok((decrypted_event, encryption_info))
1959 }
1960 Err(error) => Err(
1961 if let MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) = error {
1962 let withheld_code = self
1963 .inner
1964 .store
1965 .get_withheld_info(room_id, content.session_id())
1966 .await?
1967 .map(|e| e.content.withheld_code());
1968
1969 if withheld_code.is_some() {
1970 MegolmError::MissingRoomKey(withheld_code)
1972 } else {
1973 error
1974 }
1975 } else {
1976 error
1977 },
1978 ),
1979 }
1980 }
1981
1982 fn check_sender_trust_requirement(
1988 &self,
1989 session: &InboundGroupSession,
1990 encryption_info: &EncryptionInfo,
1991 trust_requirement: &TrustRequirement,
1992 ) -> MegolmResult<()> {
1993 trace!(
1994 verification_state = ?encryption_info.verification_state,
1995 ?trust_requirement, "check_sender_trust_requirement",
1996 );
1997
1998 let verification_level = match &encryption_info.verification_state {
2001 VerificationState::Verified => return Ok(()),
2002 VerificationState::Unverified(verification_level) => verification_level,
2003 };
2004
2005 let ok = match trust_requirement {
2006 TrustRequirement::Untrusted => true,
2007
2008 TrustRequirement::CrossSignedOrLegacy => {
2009 let legacy_session = match session.sender_data {
2015 SenderData::DeviceInfo { legacy_session, .. } => legacy_session,
2016 SenderData::UnknownDevice { legacy_session, .. } => legacy_session,
2017 _ => false,
2018 };
2019
2020 match (verification_level, legacy_session) {
2030 (VerificationLevel::UnverifiedIdentity, _) => true,
2032
2033 (VerificationLevel::UnsignedDevice, true) => true,
2035
2036 (VerificationLevel::None(_), true) => true,
2038
2039 (VerificationLevel::VerificationViolation, _)
2041 | (VerificationLevel::MismatchedSender, _)
2042 | (VerificationLevel::UnsignedDevice, false)
2043 | (VerificationLevel::None(_), false) => false,
2044 }
2045 }
2046
2047 TrustRequirement::CrossSigned => match verification_level {
2050 VerificationLevel::UnverifiedIdentity => true,
2051
2052 VerificationLevel::VerificationViolation
2053 | VerificationLevel::MismatchedSender
2054 | VerificationLevel::UnsignedDevice
2055 | VerificationLevel::None(_) => false,
2056 },
2057 };
2058
2059 if ok {
2060 Ok(())
2061 } else {
2062 Err(MegolmError::SenderIdentityNotTrusted(verification_level.clone()))
2063 }
2064 }
2065
2066 async fn get_inbound_group_session_or_error(
2071 &self,
2072 room_id: &RoomId,
2073 session_id: &str,
2074 ) -> MegolmResult<InboundGroupSession> {
2075 match self.store().get_inbound_group_session(room_id, session_id).await? {
2076 Some(session) => Ok(session),
2077 None => {
2078 let withheld_code = self
2079 .inner
2080 .store
2081 .get_withheld_info(room_id, session_id)
2082 .await?
2083 .map(|e| e.content.withheld_code());
2084 Err(MegolmError::MissingRoomKey(withheld_code))
2085 }
2086 }
2087 }
2088
2089 pub async fn try_decrypt_room_event(
2104 &self,
2105 raw_event: &Raw<EncryptedEvent>,
2106 room_id: &RoomId,
2107 decryption_settings: &DecryptionSettings,
2108 ) -> Result<RoomEventDecryptionResult, CryptoStoreError> {
2109 match self.decrypt_room_event_inner(raw_event, room_id, true, decryption_settings).await {
2110 Ok(decrypted) => Ok(RoomEventDecryptionResult::Decrypted(decrypted)),
2111 Err(err) => Ok(RoomEventDecryptionResult::UnableToDecrypt(megolm_error_to_utd_info(
2112 raw_event, err,
2113 )?)),
2114 }
2115 }
2116
2117 pub async fn decrypt_room_event(
2125 &self,
2126 event: &Raw<EncryptedEvent>,
2127 room_id: &RoomId,
2128 decryption_settings: &DecryptionSettings,
2129 ) -> MegolmResult<DecryptedRoomEvent> {
2130 self.decrypt_room_event_inner(event, room_id, true, decryption_settings).await
2131 }
2132
2133 #[instrument(name = "decrypt_room_event", skip_all, fields(?room_id, event_id, origin_server_ts, sender, algorithm, session_id, message_index, sender_key))]
2134 async fn decrypt_room_event_inner(
2135 &self,
2136 event: &Raw<EncryptedEvent>,
2137 room_id: &RoomId,
2138 decrypt_unsigned: bool,
2139 decryption_settings: &DecryptionSettings,
2140 ) -> MegolmResult<DecryptedRoomEvent> {
2141 let event = event.deserialize()?;
2142
2143 Span::current()
2144 .record("sender", debug(&event.sender))
2145 .record("event_id", debug(&event.event_id))
2146 .record(
2147 "origin_server_ts",
2148 timestamp_to_iso8601(event.origin_server_ts)
2149 .unwrap_or_else(|| "<out of range>".to_owned()),
2150 )
2151 .record("algorithm", debug(event.content.algorithm()));
2152
2153 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2154 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2155 Span::current().record("sender_key", debug(c.sender_key));
2156 c.into()
2157 }
2158 #[cfg(feature = "experimental-algorithms")]
2159 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2160 RoomEventEncryptionScheme::Unknown(_) => {
2161 warn!("Received an encrypted room event with an unsupported algorithm");
2162 return Err(EventError::UnsupportedAlgorithm.into());
2163 }
2164 };
2165
2166 Span::current().record("session_id", content.session_id());
2167 Span::current().record("message_index", content.message_index());
2168
2169 let result =
2170 self.decrypt_megolm_events(room_id, &event, &content, decryption_settings).await;
2171
2172 if let Err(e) = &result {
2173 #[cfg(feature = "automatic-room-key-forwarding")]
2174 match e {
2175 MegolmError::MissingRoomKey(_)
2178 | MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
2179 self.inner
2180 .key_request_machine
2181 .create_outgoing_key_request(room_id, &event)
2182 .await?;
2183 }
2184 _ => {}
2185 }
2186
2187 warn!("Failed to decrypt a room event: {e}");
2188 }
2189
2190 let (mut decrypted_event, encryption_info) = result?;
2191
2192 let mut unsigned_encryption_info = None;
2193 if decrypt_unsigned {
2194 unsigned_encryption_info = self
2196 .decrypt_unsigned_events(&mut decrypted_event, room_id, decryption_settings)
2197 .await;
2198 }
2199
2200 let event = serde_json::from_value::<Raw<AnyMessageLikeEvent>>(decrypted_event.into())?;
2201
2202 Ok(DecryptedRoomEvent { event, encryption_info, unsigned_encryption_info })
2203 }
2204
2205 async fn decrypt_unsigned_events(
2215 &self,
2216 main_event: &mut JsonObject,
2217 room_id: &RoomId,
2218 decryption_settings: &DecryptionSettings,
2219 ) -> Option<BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>> {
2220 let unsigned = main_event.get_mut("unsigned")?.as_object_mut()?;
2221 let mut unsigned_encryption_info: Option<
2222 BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>,
2223 > = None;
2224
2225 let location = UnsignedEventLocation::RelationsReplace;
2227 let replace = location.find_mut(unsigned);
2228 if let Some(decryption_result) =
2229 self.decrypt_unsigned_event(replace, room_id, decryption_settings).await
2230 {
2231 unsigned_encryption_info
2232 .get_or_insert_with(Default::default)
2233 .insert(location, decryption_result);
2234 }
2235
2236 let location = UnsignedEventLocation::RelationsThreadLatestEvent;
2239 let thread_latest_event = location.find_mut(unsigned);
2240 if let Some(decryption_result) =
2241 self.decrypt_unsigned_event(thread_latest_event, room_id, decryption_settings).await
2242 {
2243 unsigned_encryption_info
2244 .get_or_insert_with(Default::default)
2245 .insert(location, decryption_result);
2246 }
2247
2248 unsigned_encryption_info
2249 }
2250
2251 fn decrypt_unsigned_event<'a>(
2259 &'a self,
2260 event: Option<&'a mut Value>,
2261 room_id: &'a RoomId,
2262 decryption_settings: &'a DecryptionSettings,
2263 ) -> BoxFuture<'a, Option<UnsignedDecryptionResult>> {
2264 Box::pin(async move {
2265 let event = event?;
2266
2267 let is_encrypted = event
2268 .get("type")
2269 .and_then(|type_| type_.as_str())
2270 .is_some_and(|s| s == "m.room.encrypted");
2271 if !is_encrypted {
2272 return None;
2273 }
2274
2275 let raw_event = serde_json::from_value(event.clone()).ok()?;
2276 match self
2277 .decrypt_room_event_inner(&raw_event, room_id, false, decryption_settings)
2278 .await
2279 {
2280 Ok(decrypted_event) => {
2281 *event = serde_json::to_value(decrypted_event.event).ok()?;
2283 Some(UnsignedDecryptionResult::Decrypted(decrypted_event.encryption_info))
2284 }
2285 Err(err) => {
2286 let utd_info = megolm_error_to_utd_info(&raw_event, err).ok()?;
2291 Some(UnsignedDecryptionResult::UnableToDecrypt(utd_info))
2292 }
2293 }
2294 })
2295 }
2296
2297 pub async fn is_room_key_available(
2304 &self,
2305 event: &Raw<EncryptedEvent>,
2306 room_id: &RoomId,
2307 ) -> Result<bool, CryptoStoreError> {
2308 let event = event.deserialize()?;
2309
2310 let (session_id, message_index) = match &event.content.scheme {
2311 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2312 (&c.session_id, c.ciphertext.message_index())
2313 }
2314 #[cfg(feature = "experimental-algorithms")]
2315 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => {
2316 (&c.session_id, c.ciphertext.message_index())
2317 }
2318 RoomEventEncryptionScheme::Unknown(_) => {
2319 return Ok(false);
2321 }
2322 };
2323
2324 Ok(self
2327 .store()
2328 .get_inbound_group_session(room_id, session_id)
2329 .await?
2330 .filter(|s| s.first_known_index() <= message_index)
2331 .is_some())
2332 }
2333
2334 #[instrument(skip(self, event), fields(event_id, sender, session_id))]
2347 pub async fn get_room_event_encryption_info(
2348 &self,
2349 event: &Raw<EncryptedEvent>,
2350 room_id: &RoomId,
2351 ) -> MegolmResult<Arc<EncryptionInfo>> {
2352 let event = event.deserialize()?;
2353
2354 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2355 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => c.into(),
2356 #[cfg(feature = "experimental-algorithms")]
2357 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2358 RoomEventEncryptionScheme::Unknown(_) => {
2359 return Err(EventError::UnsupportedAlgorithm.into());
2360 }
2361 };
2362
2363 Span::current()
2364 .record("sender", debug(&event.sender))
2365 .record("event_id", debug(&event.event_id))
2366 .record("session_id", content.session_id());
2367
2368 self.get_session_encryption_info(room_id, content.session_id(), &event.sender).await
2369 }
2370
2371 pub async fn get_session_encryption_info(
2386 &self,
2387 room_id: &RoomId,
2388 session_id: &str,
2389 sender: &UserId,
2390 ) -> MegolmResult<Arc<EncryptionInfo>> {
2391 let session = self.get_inbound_group_session_or_error(room_id, session_id).await?;
2392 self.get_encryption_info(&session, sender).await
2393 }
2394
2395 pub async fn update_tracked_users(
2413 &self,
2414 users: impl IntoIterator<Item = &UserId>,
2415 ) -> StoreResult<()> {
2416 self.inner.identity_manager.update_tracked_users(users).await
2417 }
2418
2419 pub async fn mark_all_tracked_users_as_dirty(&self) -> StoreResult<()> {
2424 self.inner
2425 .identity_manager
2426 .mark_all_tracked_users_as_dirty(self.inner.store.cache().await?)
2427 .await
2428 }
2429
2430 async fn wait_if_user_pending(
2431 &self,
2432 user_id: &UserId,
2433 timeout: Option<Duration>,
2434 ) -> StoreResult<()> {
2435 if let Some(timeout) = timeout {
2436 let cache = self.store().cache().await?;
2437 self.inner
2438 .identity_manager
2439 .key_query_manager
2440 .wait_if_user_key_query_pending(cache, timeout, user_id)
2441 .await?;
2442 }
2443 Ok(())
2444 }
2445
2446 #[instrument(skip(self))]
2476 pub async fn get_device(
2477 &self,
2478 user_id: &UserId,
2479 device_id: &DeviceId,
2480 timeout: Option<Duration>,
2481 ) -> StoreResult<Option<Device>> {
2482 self.wait_if_user_pending(user_id, timeout).await?;
2483 self.store().get_device(user_id, device_id).await
2484 }
2485
2486 #[instrument(skip(self))]
2500 pub async fn get_identity(
2501 &self,
2502 user_id: &UserId,
2503 timeout: Option<Duration>,
2504 ) -> StoreResult<Option<UserIdentity>> {
2505 self.wait_if_user_pending(user_id, timeout).await?;
2506 self.store().get_identity(user_id).await
2507 }
2508
2509 #[instrument(skip(self))]
2536 pub async fn get_user_devices(
2537 &self,
2538 user_id: &UserId,
2539 timeout: Option<Duration>,
2540 ) -> StoreResult<UserDevices> {
2541 self.wait_if_user_pending(user_id, timeout).await?;
2542 self.store().get_user_devices(user_id).await
2543 }
2544
2545 pub async fn cross_signing_status(&self) -> CrossSigningStatus {
2550 self.inner.user_identity.lock().await.status().await
2551 }
2552
2553 pub async fn export_cross_signing_keys(&self) -> StoreResult<Option<CrossSigningKeyExport>> {
2561 let master_key = self.store().export_secret(&SecretName::CrossSigningMasterKey).await?;
2562 let self_signing_key =
2563 self.store().export_secret(&SecretName::CrossSigningSelfSigningKey).await?;
2564 let user_signing_key =
2565 self.store().export_secret(&SecretName::CrossSigningUserSigningKey).await?;
2566
2567 Ok(if master_key.is_none() && self_signing_key.is_none() && user_signing_key.is_none() {
2568 None
2569 } else {
2570 Some(CrossSigningKeyExport { master_key, self_signing_key, user_signing_key })
2571 })
2572 }
2573
2574 pub async fn import_cross_signing_keys(
2579 &self,
2580 export: CrossSigningKeyExport,
2581 ) -> Result<CrossSigningStatus, SecretImportError> {
2582 self.store().import_cross_signing_keys(export).await
2583 }
2584
2585 async fn sign_with_master_key(
2586 &self,
2587 message: &str,
2588 ) -> Result<(OwnedDeviceKeyId, Ed25519Signature), SignatureError> {
2589 let identity = &*self.inner.user_identity.lock().await;
2590 let key_id = identity.master_key_id().await.ok_or(SignatureError::MissingSigningKey)?;
2591
2592 let signature = identity.sign(message).await?;
2593
2594 Ok((key_id, signature))
2595 }
2596
2597 pub async fn sign(&self, message: &str) -> Result<Signatures, CryptoStoreError> {
2603 let mut signatures = Signatures::new();
2604
2605 {
2606 let cache = self.inner.store.cache().await?;
2607 let account = cache.account().await?;
2608 let key_id = account.signing_key_id();
2609 let signature = account.sign(message);
2610 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
2611 }
2612
2613 match self.sign_with_master_key(message).await {
2614 Ok((key_id, signature)) => {
2615 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
2616 }
2617 Err(e) => {
2618 warn!(error = ?e, "Couldn't sign the message using the cross signing master key")
2619 }
2620 }
2621
2622 Ok(signatures)
2623 }
2624
2625 pub fn backup_machine(&self) -> &BackupMachine {
2630 &self.inner.backup_machine
2631 }
2632
2633 pub async fn initialize_crypto_store_generation(
2637 &self,
2638 generation: &Mutex<Option<u64>>,
2639 ) -> StoreResult<()> {
2640 let mut gen_guard = generation.lock().await;
2643
2644 let prev_generation =
2645 self.inner.store.get_custom_value(Self::CURRENT_GENERATION_STORE_KEY).await?;
2646
2647 let gen = match prev_generation {
2648 Some(val) => {
2649 u64::from_le_bytes(val.try_into().map_err(|_| {
2652 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
2653 })?)
2654 .wrapping_add(1)
2655 }
2656 None => 0,
2657 };
2658
2659 tracing::debug!("Initialising crypto store generation at {}", gen);
2660
2661 self.inner
2662 .store
2663 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, gen.to_le_bytes().to_vec())
2664 .await?;
2665
2666 *gen_guard = Some(gen);
2667
2668 Ok(())
2669 }
2670
2671 pub async fn maintain_crypto_store_generation(
2696 &'_ self,
2697 generation: &Mutex<Option<u64>>,
2698 ) -> StoreResult<(bool, u64)> {
2699 let mut gen_guard = generation.lock().await;
2700
2701 let actual_gen = self
2707 .inner
2708 .store
2709 .get_custom_value(Self::CURRENT_GENERATION_STORE_KEY)
2710 .await?
2711 .ok_or_else(|| {
2712 CryptoStoreError::InvalidLockGeneration("counter missing in store".to_owned())
2713 })?;
2714
2715 let actual_gen =
2716 u64::from_le_bytes(actual_gen.try_into().map_err(|_| {
2717 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
2718 })?);
2719
2720 let new_gen = match gen_guard.as_ref() {
2721 Some(expected_gen) => {
2722 if actual_gen == *expected_gen {
2723 return Ok((false, actual_gen));
2724 }
2725 actual_gen.max(*expected_gen).wrapping_add(1)
2727 }
2728 None => {
2729 actual_gen.wrapping_add(1)
2732 }
2733 };
2734
2735 tracing::debug!(
2736 "Crypto store generation mismatch: previously known was {:?}, actual is {:?}, next is {}",
2737 *gen_guard,
2738 actual_gen,
2739 new_gen
2740 );
2741
2742 *gen_guard = Some(new_gen);
2744
2745 self.inner
2747 .store
2748 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, new_gen.to_le_bytes().to_vec())
2749 .await?;
2750
2751 Ok((true, new_gen))
2752 }
2753
2754 pub fn dehydrated_devices(&self) -> DehydratedDevices {
2756 DehydratedDevices { inner: self.to_owned() }
2757 }
2758
2759 pub async fn room_settings(&self, room_id: &RoomId) -> StoreResult<Option<RoomSettings>> {
2764 self.inner.store.get_room_settings(room_id).await
2767 }
2768
2769 pub async fn set_room_settings(
2780 &self,
2781 room_id: &RoomId,
2782 new_settings: &RoomSettings,
2783 ) -> Result<(), SetRoomSettingsError> {
2784 let store = &self.inner.store;
2785
2786 let _store_transaction = store.transaction().await;
2791
2792 let old_settings = store.get_room_settings(room_id).await?;
2793
2794 if let Some(old_settings) = old_settings {
2807 if old_settings != *new_settings {
2808 return Err(SetRoomSettingsError::EncryptionDowngrade);
2809 } else {
2810 return Ok(());
2812 }
2813 }
2814
2815 match new_settings.algorithm {
2817 EventEncryptionAlgorithm::MegolmV1AesSha2 => (),
2818
2819 #[cfg(feature = "experimental-algorithms")]
2820 EventEncryptionAlgorithm::MegolmV2AesSha2 => (),
2821
2822 _ => {
2823 warn!(
2824 ?room_id,
2825 "Rejecting invalid encryption algorithm {}", new_settings.algorithm
2826 );
2827 return Err(SetRoomSettingsError::InvalidSettings);
2828 }
2829 }
2830
2831 store
2833 .save_changes(Changes {
2834 room_settings: HashMap::from([(room_id.to_owned(), new_settings.clone())]),
2835 ..Default::default()
2836 })
2837 .await?;
2838
2839 Ok(())
2840 }
2841
2842 #[cfg(any(feature = "testing", test))]
2846 pub fn same_as(&self, other: &OlmMachine) -> bool {
2847 Arc::ptr_eq(&self.inner, &other.inner)
2848 }
2849
2850 #[cfg(any(feature = "testing", test))]
2852 pub async fn uploaded_key_count(&self) -> Result<u64, CryptoStoreError> {
2853 let cache = self.inner.store.cache().await?;
2854 let account = cache.account().await?;
2855 Ok(account.uploaded_key_count())
2856 }
2857
2858 #[cfg(test)]
2860 pub(crate) fn identity_manager(&self) -> &IdentityManager {
2861 &self.inner.identity_manager
2862 }
2863
2864 #[cfg(test)]
2866 pub(crate) fn key_for_has_migrated_verification_latch() -> &'static str {
2867 Self::HAS_MIGRATED_VERIFICATION_LATCH
2868 }
2869}
2870
2871fn sender_data_to_verification_state(
2872 sender_data: SenderData,
2873 session_has_been_imported: bool,
2874) -> (VerificationState, Option<OwnedDeviceId>) {
2875 match sender_data {
2876 SenderData::UnknownDevice { owner_check_failed: false, .. } => {
2877 let device_link_problem = if session_has_been_imported {
2878 DeviceLinkProblem::InsecureSource
2879 } else {
2880 DeviceLinkProblem::MissingDevice
2881 };
2882
2883 (VerificationState::Unverified(VerificationLevel::None(device_link_problem)), None)
2884 }
2885 SenderData::UnknownDevice { owner_check_failed: true, .. } => (
2886 VerificationState::Unverified(VerificationLevel::None(
2887 DeviceLinkProblem::InsecureSource,
2888 )),
2889 None,
2890 ),
2891 SenderData::DeviceInfo { device_keys, .. } => (
2892 VerificationState::Unverified(VerificationLevel::UnsignedDevice),
2893 Some(device_keys.device_id),
2894 ),
2895 SenderData::VerificationViolation(KnownSenderData { device_id, .. }) => {
2896 (VerificationState::Unverified(VerificationLevel::VerificationViolation), device_id)
2897 }
2898 SenderData::SenderUnverified(KnownSenderData { device_id, .. }) => {
2899 (VerificationState::Unverified(VerificationLevel::UnverifiedIdentity), device_id)
2900 }
2901 SenderData::SenderVerified(KnownSenderData { device_id, .. }) => {
2902 (VerificationState::Verified, device_id)
2903 }
2904 }
2905}
2906
2907#[derive(Debug, Clone)]
2910pub struct CrossSigningBootstrapRequests {
2911 pub upload_keys_req: Option<OutgoingRequest>,
2918
2919 pub upload_signing_keys_req: UploadSigningKeysRequest,
2923
2924 pub upload_signatures_req: UploadSignaturesRequest,
2929}
2930
2931#[derive(Debug)]
2934pub struct EncryptionSyncChanges<'a> {
2935 pub to_device_events: Vec<Raw<AnyToDeviceEvent>>,
2937 pub changed_devices: &'a DeviceLists,
2940 pub one_time_keys_counts: &'a BTreeMap<OneTimeKeyAlgorithm, UInt>,
2942 pub unused_fallback_keys: Option<&'a [OneTimeKeyAlgorithm]>,
2944 pub next_batch_token: Option<String>,
2946}
2947
2948fn megolm_error_to_utd_info(
2956 raw_event: &Raw<EncryptedEvent>,
2957 error: MegolmError,
2958) -> Result<UnableToDecryptInfo, CryptoStoreError> {
2959 use MegolmError::*;
2960 let reason = match error {
2961 EventError(_) => UnableToDecryptReason::MalformedEncryptedEvent,
2962 Decode(_) => UnableToDecryptReason::MalformedEncryptedEvent,
2963 MissingRoomKey(maybe_withheld) => {
2964 UnableToDecryptReason::MissingMegolmSession { withheld_code: maybe_withheld }
2965 }
2966 Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
2967 UnableToDecryptReason::UnknownMegolmMessageIndex
2968 }
2969 Decryption(_) => UnableToDecryptReason::MegolmDecryptionFailure,
2970 JsonError(_) => UnableToDecryptReason::PayloadDeserializationFailure,
2971 MismatchedIdentityKeys(_) => UnableToDecryptReason::MismatchedIdentityKeys,
2972 SenderIdentityNotTrusted(level) => UnableToDecryptReason::SenderIdentityNotTrusted(level),
2973
2974 Store(error) => Err(error)?,
2977 };
2978
2979 let session_id = raw_event.deserialize().ok().and_then(|ev| match ev.content.scheme {
2980 RoomEventEncryptionScheme::MegolmV1AesSha2(s) => Some(s.session_id),
2981 #[cfg(feature = "experimental-algorithms")]
2982 RoomEventEncryptionScheme::MegolmV2AesSha2(s) => Some(s.session_id),
2983 RoomEventEncryptionScheme::Unknown(_) => None,
2984 });
2985
2986 Ok(UnableToDecryptInfo { session_id, reason })
2987}
2988
2989#[derive(Debug, thiserror::Error)]
2999pub(crate) enum DecryptToDeviceError {
3000 #[error("An Olm error occurred meaning we failed to decrypt the event")]
3001 OlmError(#[from] OlmError),
3002
3003 #[error("The event was sent from a dehydrated device")]
3004 FromDehydratedDevice,
3005}
3006
3007impl From<CryptoStoreError> for DecryptToDeviceError {
3008 fn from(value: CryptoStoreError) -> Self {
3009 Self::OlmError(value.into())
3010 }
3011}
3012
3013#[cfg(test)]
3014impl From<DecryptToDeviceError> for OlmError {
3015 fn from(value: DecryptToDeviceError) -> Self {
3018 match value {
3019 DecryptToDeviceError::OlmError(olm_error) => olm_error,
3020 DecryptToDeviceError::FromDehydratedDevice => {
3021 panic!("Expected an OlmError but found FromDehydratedDevice")
3022 }
3023 }
3024 }
3025}
3026
3027#[cfg(test)]
3028pub(crate) mod test_helpers;
3029
3030#[cfg(test)]
3031pub(crate) mod tests;