1#[cfg(feature = "experimental-encrypted-state-events")]
16use std::borrow::Borrow;
17use std::{
18 collections::{BTreeMap, HashMap, HashSet},
19 sync::Arc,
20 time::Duration,
21};
22
23use itertools::Itertools;
24#[cfg(feature = "experimental-send-custom-to-device")]
25use matrix_sdk_common::deserialized_responses::WithheldCode;
26use matrix_sdk_common::{
27 deserialized_responses::{
28 AlgorithmInfo, DecryptedRoomEvent, DeviceLinkProblem, EncryptionInfo,
29 ProcessedToDeviceEvent, ToDeviceUnableToDecryptInfo, ToDeviceUnableToDecryptReason,
30 UnableToDecryptInfo, UnableToDecryptReason, UnsignedDecryptionResult,
31 UnsignedEventLocation, VerificationLevel, VerificationState,
32 },
33 locks::RwLock as StdRwLock,
34 timer, BoxFuture,
35};
36#[cfg(feature = "experimental-encrypted-state-events")]
37use ruma::events::{AnyStateEventContent, StateEventContent};
38use ruma::{
39 api::client::{
40 dehydrated_device::DehydratedDeviceData,
41 keys::{
42 claim_keys::v3::Request as KeysClaimRequest,
43 get_keys::v3::Response as KeysQueryResponse,
44 upload_keys::v3::{Request as UploadKeysRequest, Response as UploadKeysResponse},
45 upload_signatures::v3::Request as UploadSignaturesRequest,
46 },
47 sync::sync_events::DeviceLists,
48 },
49 assign,
50 events::{
51 secret::request::SecretName, AnyMessageLikeEvent, AnyMessageLikeEventContent,
52 AnyTimelineEvent, AnyToDeviceEvent, MessageLikeEventContent,
53 },
54 serde::{JsonObject, Raw},
55 DeviceId, MilliSecondsSinceUnixEpoch, OneTimeKeyAlgorithm, OwnedDeviceId, OwnedDeviceKeyId,
56 OwnedTransactionId, OwnedUserId, RoomId, TransactionId, UInt, UserId,
57};
58use serde_json::{value::to_raw_value, Value};
59use tokio::sync::Mutex;
60use tracing::{
61 debug, error,
62 field::{debug, display},
63 info, instrument, trace, warn, Span,
64};
65use vodozemac::{megolm::DecryptionError, Curve25519PublicKey, Ed25519Signature};
66
67#[cfg(feature = "experimental-send-custom-to-device")]
68use crate::session_manager::split_devices_for_share_strategy;
69use crate::{
70 backups::{BackupMachine, MegolmV1BackupKey},
71 dehydrated_devices::{DehydratedDevices, DehydrationError},
72 error::{EventError, MegolmError, MegolmResult, OlmError, OlmResult, SetRoomSettingsError},
73 gossiping::GossipMachine,
74 identities::{user::UserIdentity, Device, IdentityManager, UserDevices},
75 olm::{
76 Account, CrossSigningStatus, EncryptionSettings, IdentityKeys, InboundGroupSession,
77 KnownSenderData, OlmDecryptionInfo, PrivateCrossSigningIdentity, SenderData,
78 SenderDataFinder, SessionType, StaticAccountData,
79 },
80 session_manager::{GroupSessionManager, SessionManager},
81 store::{
82 caches::StoreCache,
83 types::{
84 Changes, CrossSigningKeyExport, DeviceChanges, IdentityChanges, PendingChanges,
85 RoomKeyInfo, RoomSettings, StoredRoomKeyBundleData,
86 },
87 CryptoStoreWrapper, IntoCryptoStore, MemoryStore, Result as StoreResult, SecretImportError,
88 Store, StoreTransaction,
89 },
90 types::{
91 events::{
92 olm_v1::{AnyDecryptedOlmEvent, DecryptedRoomKeyBundleEvent, DecryptedRoomKeyEvent},
93 room::encrypted::{
94 EncryptedEvent, EncryptedToDeviceEvent, RoomEncryptedEventContent,
95 RoomEventEncryptionScheme, SupportedEventEncryptionSchemes,
96 ToDeviceEncryptedEventContent,
97 },
98 room_key::{MegolmV1AesSha2Content, RoomKeyContent},
99 room_key_bundle::RoomKeyBundleContent,
100 room_key_withheld::{
101 MegolmV1AesSha2WithheldContent, RoomKeyWithheldContent, RoomKeyWithheldEvent,
102 },
103 ToDeviceEvent, ToDeviceEvents,
104 },
105 requests::{
106 AnyIncomingResponse, KeysQueryRequest, OutgoingRequest, ToDeviceRequest,
107 UploadSigningKeysRequest,
108 },
109 EventEncryptionAlgorithm, Signatures,
110 },
111 utilities::timestamp_to_iso8601,
112 verification::{Verification, VerificationMachine, VerificationRequest},
113 CollectStrategy, CryptoStoreError, DecryptionSettings, DeviceData, LocalTrust,
114 RoomEventDecryptionResult, SignatureError, TrustRequirement,
115};
116
117#[derive(Clone)]
120pub struct OlmMachine {
121 pub(crate) inner: Arc<OlmMachineInner>,
122}
123
124pub struct OlmMachineInner {
125 user_id: OwnedUserId,
127 device_id: OwnedDeviceId,
129 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
134 store: Store,
138 session_manager: SessionManager,
140 pub(crate) group_session_manager: GroupSessionManager,
142 verification_machine: VerificationMachine,
145 pub(crate) key_request_machine: GossipMachine,
148 identity_manager: IdentityManager,
151 backup_machine: BackupMachine,
153}
154
155#[cfg(not(tarpaulin_include))]
156impl std::fmt::Debug for OlmMachine {
157 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
158 f.debug_struct("OlmMachine")
159 .field("user_id", &self.user_id())
160 .field("device_id", &self.device_id())
161 .finish()
162 }
163}
164
165impl OlmMachine {
166 const CURRENT_GENERATION_STORE_KEY: &'static str = "generation-counter";
167 const HAS_MIGRATED_VERIFICATION_LATCH: &'static str = "HAS_MIGRATED_VERIFICATION_LATCH";
168
169 pub async fn new(user_id: &UserId, device_id: &DeviceId) -> Self {
180 OlmMachine::with_store(user_id, device_id, MemoryStore::new(), None)
181 .await
182 .expect("Reading and writing to the memory store always succeeds")
183 }
184
185 pub(crate) async fn rehydrate(
186 &self,
187 pickle_key: &[u8; 32],
188 device_id: &DeviceId,
189 device_data: Raw<DehydratedDeviceData>,
190 ) -> Result<OlmMachine, DehydrationError> {
191 let account = Account::rehydrate(pickle_key, self.user_id(), device_id, device_data)?;
192 let static_account = account.static_data().clone();
193
194 let store =
195 Arc::new(CryptoStoreWrapper::new(self.user_id(), device_id, MemoryStore::new()));
196 let device = DeviceData::from_account(&account);
197 store.save_pending_changes(PendingChanges { account: Some(account) }).await?;
198 store
199 .save_changes(Changes {
200 devices: DeviceChanges { new: vec![device], ..Default::default() },
201 ..Default::default()
202 })
203 .await?;
204
205 let (verification_machine, store, identity_manager) =
206 Self::new_helper_prelude(store, static_account, self.store().private_identity());
207
208 Ok(Self::new_helper(
209 device_id,
210 store,
211 verification_machine,
212 identity_manager,
213 self.store().private_identity(),
214 None,
215 ))
216 }
217
218 fn new_helper_prelude(
219 store_wrapper: Arc<CryptoStoreWrapper>,
220 account: StaticAccountData,
221 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
222 ) -> (VerificationMachine, Store, IdentityManager) {
223 let verification_machine =
224 VerificationMachine::new(account.clone(), user_identity.clone(), store_wrapper.clone());
225 let store = Store::new(account, user_identity, store_wrapper, verification_machine.clone());
226
227 let identity_manager = IdentityManager::new(store.clone());
228
229 (verification_machine, store, identity_manager)
230 }
231
232 fn new_helper(
233 device_id: &DeviceId,
234 store: Store,
235 verification_machine: VerificationMachine,
236 identity_manager: IdentityManager,
237 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
238 maybe_backup_key: Option<MegolmV1BackupKey>,
239 ) -> Self {
240 let group_session_manager = GroupSessionManager::new(store.clone());
241
242 let users_for_key_claim = Arc::new(StdRwLock::new(BTreeMap::new()));
243 let key_request_machine = GossipMachine::new(
244 store.clone(),
245 identity_manager.clone(),
246 group_session_manager.session_cache(),
247 users_for_key_claim.clone(),
248 );
249
250 let session_manager =
251 SessionManager::new(users_for_key_claim, key_request_machine.clone(), store.clone());
252
253 let backup_machine = BackupMachine::new(store.clone(), maybe_backup_key);
254
255 let inner = Arc::new(OlmMachineInner {
256 user_id: store.user_id().to_owned(),
257 device_id: device_id.to_owned(),
258 user_identity,
259 store,
260 session_manager,
261 group_session_manager,
262 verification_machine,
263 key_request_machine,
264 identity_manager,
265 backup_machine,
266 });
267
268 Self { inner }
269 }
270
271 #[instrument(skip(store, custom_account), fields(ed25519_key, curve25519_key))]
296 pub async fn with_store(
297 user_id: &UserId,
298 device_id: &DeviceId,
299 store: impl IntoCryptoStore,
300 custom_account: Option<vodozemac::olm::Account>,
301 ) -> StoreResult<Self> {
302 let store = store.into_crypto_store();
303
304 let static_account = match store.load_account().await? {
305 Some(account) => {
306 if user_id != account.user_id()
307 || device_id != account.device_id()
308 || custom_account.is_some()
309 {
310 return Err(CryptoStoreError::MismatchedAccount {
311 expected: (account.user_id().to_owned(), account.device_id().to_owned()),
312 got: (user_id.to_owned(), device_id.to_owned()),
313 });
314 }
315
316 Span::current()
317 .record("ed25519_key", display(account.identity_keys().ed25519))
318 .record("curve25519_key", display(account.identity_keys().curve25519));
319 debug!("Restored an Olm account");
320
321 account.static_data().clone()
322 }
323
324 None => {
325 let account = if let Some(account) = custom_account {
326 Account::new_helper(account, user_id, device_id)
327 } else {
328 Account::with_device_id(user_id, device_id)
329 };
330
331 let static_account = account.static_data().clone();
332
333 Span::current()
334 .record("ed25519_key", display(account.identity_keys().ed25519))
335 .record("curve25519_key", display(account.identity_keys().curve25519));
336
337 let device = DeviceData::from_account(&account);
338
339 device.set_trust_state(LocalTrust::Verified);
343
344 let changes = Changes {
345 devices: DeviceChanges { new: vec![device], ..Default::default() },
346 ..Default::default()
347 };
348 store.save_changes(changes).await?;
349 store.save_pending_changes(PendingChanges { account: Some(account) }).await?;
350
351 debug!("Created a new Olm account");
352
353 static_account
354 }
355 };
356
357 let identity = match store.load_identity().await? {
358 Some(i) => {
359 let master_key = i
360 .master_public_key()
361 .await
362 .and_then(|m| m.get_first_key().map(|m| m.to_owned()));
363 debug!(?master_key, "Restored the cross signing identity");
364 i
365 }
366 None => {
367 debug!("Creating an empty cross signing identity stub");
368 PrivateCrossSigningIdentity::empty(user_id)
369 }
370 };
371
372 let saved_keys = store.load_backup_keys().await?;
377 let maybe_backup_key = saved_keys.decryption_key.and_then(|k| {
378 if let Some(version) = saved_keys.backup_version {
379 let megolm_v1_backup_key = k.megolm_v1_public_key();
380 megolm_v1_backup_key.set_version(version);
381 Some(megolm_v1_backup_key)
382 } else {
383 None
384 }
385 });
386
387 let identity = Arc::new(Mutex::new(identity));
388 let store = Arc::new(CryptoStoreWrapper::new(user_id, device_id, store));
389
390 let (verification_machine, store, identity_manager) =
391 Self::new_helper_prelude(store, static_account, identity.clone());
392
393 Self::migration_post_verified_latch_support(&store, &identity_manager).await?;
396
397 Ok(Self::new_helper(
398 device_id,
399 store,
400 verification_machine,
401 identity_manager,
402 identity,
403 maybe_backup_key,
404 ))
405 }
406
407 pub(crate) async fn migration_post_verified_latch_support(
415 store: &Store,
416 identity_manager: &IdentityManager,
417 ) -> Result<(), CryptoStoreError> {
418 let maybe_migrate_for_identity_verified_latch =
419 store.get_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH).await?.is_none();
420
421 if maybe_migrate_for_identity_verified_latch {
422 identity_manager.mark_all_tracked_users_as_dirty(store.cache().await?).await?;
423
424 store.set_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH, vec![0]).await?
425 }
426 Ok(())
427 }
428
429 pub fn store(&self) -> &Store {
431 &self.inner.store
432 }
433
434 pub fn user_id(&self) -> &UserId {
436 &self.inner.user_id
437 }
438
439 pub fn device_id(&self) -> &DeviceId {
441 &self.inner.device_id
442 }
443
444 pub fn device_creation_time(&self) -> MilliSecondsSinceUnixEpoch {
451 self.inner.store.static_account().creation_local_time()
452 }
453
454 pub fn identity_keys(&self) -> IdentityKeys {
456 let account = self.inner.store.static_account();
457 account.identity_keys()
458 }
459
460 pub async fn display_name(&self) -> StoreResult<Option<String>> {
462 self.store().device_display_name().await
463 }
464
465 pub async fn tracked_users(&self) -> StoreResult<HashSet<OwnedUserId>> {
470 let cache = self.store().cache().await?;
471 Ok(self.inner.identity_manager.key_query_manager.synced(&cache).await?.tracked_users())
472 }
473
474 #[cfg(feature = "automatic-room-key-forwarding")]
483 pub fn set_room_key_requests_enabled(&self, enable: bool) {
484 self.inner.key_request_machine.set_room_key_requests_enabled(enable)
485 }
486
487 pub fn are_room_key_requests_enabled(&self) -> bool {
492 self.inner.key_request_machine.are_room_key_requests_enabled()
493 }
494
495 #[cfg(feature = "automatic-room-key-forwarding")]
504 pub fn set_room_key_forwarding_enabled(&self, enable: bool) {
505 self.inner.key_request_machine.set_room_key_forwarding_enabled(enable)
506 }
507
508 pub fn is_room_key_forwarding_enabled(&self) -> bool {
512 self.inner.key_request_machine.is_room_key_forwarding_enabled()
513 }
514
515 pub async fn outgoing_requests(&self) -> StoreResult<Vec<OutgoingRequest>> {
523 let mut requests = Vec::new();
524
525 {
526 let store_cache = self.inner.store.cache().await?;
527 let account = store_cache.account().await?;
528 if let Some(r) = self.keys_for_upload(&account).await.map(|r| OutgoingRequest {
529 request_id: TransactionId::new(),
530 request: Arc::new(r.into()),
531 }) {
532 requests.push(r);
533 }
534 }
535
536 for request in self
537 .inner
538 .identity_manager
539 .users_for_key_query()
540 .await?
541 .into_iter()
542 .map(|(request_id, r)| OutgoingRequest { request_id, request: Arc::new(r.into()) })
543 {
544 requests.push(request);
545 }
546
547 requests.append(&mut self.inner.verification_machine.outgoing_messages());
548 requests.append(&mut self.inner.key_request_machine.outgoing_to_device_requests().await?);
549
550 Ok(requests)
551 }
552
553 pub fn query_keys_for_users<'a>(
574 &self,
575 users: impl IntoIterator<Item = &'a UserId>,
576 ) -> (OwnedTransactionId, KeysQueryRequest) {
577 self.inner.identity_manager.build_key_query_for_users(users)
578 }
579
580 pub async fn mark_request_as_sent<'a>(
590 &self,
591 request_id: &TransactionId,
592 response: impl Into<AnyIncomingResponse<'a>>,
593 ) -> OlmResult<()> {
594 match response.into() {
595 AnyIncomingResponse::KeysUpload(response) => {
596 Box::pin(self.receive_keys_upload_response(response)).await?;
597 }
598 AnyIncomingResponse::KeysQuery(response) => {
599 Box::pin(self.receive_keys_query_response(request_id, response)).await?;
600 }
601 AnyIncomingResponse::KeysClaim(response) => {
602 Box::pin(
603 self.inner.session_manager.receive_keys_claim_response(request_id, response),
604 )
605 .await?;
606 }
607 AnyIncomingResponse::ToDevice(_) => {
608 Box::pin(self.mark_to_device_request_as_sent(request_id)).await?;
609 }
610 AnyIncomingResponse::SigningKeysUpload(_) => {
611 Box::pin(self.receive_cross_signing_upload_response()).await?;
612 }
613 AnyIncomingResponse::SignatureUpload(_) => {
614 self.inner.verification_machine.mark_request_as_sent(request_id);
615 }
616 AnyIncomingResponse::RoomMessage(_) => {
617 self.inner.verification_machine.mark_request_as_sent(request_id);
618 }
619 AnyIncomingResponse::KeysBackup(_) => {
620 Box::pin(self.inner.backup_machine.mark_request_as_sent(request_id)).await?;
621 }
622 }
623
624 Ok(())
625 }
626
627 async fn receive_cross_signing_upload_response(&self) -> StoreResult<()> {
629 let identity = self.inner.user_identity.lock().await;
630 identity.mark_as_shared();
631
632 let changes = Changes { private_identity: Some(identity.clone()), ..Default::default() };
633
634 self.store().save_changes(changes).await
635 }
636
637 pub async fn bootstrap_cross_signing(
656 &self,
657 reset: bool,
658 ) -> StoreResult<CrossSigningBootstrapRequests> {
659 let identity = self.inner.user_identity.lock().await.clone();
664
665 let (upload_signing_keys_req, upload_signatures_req) = if reset || identity.is_empty().await
666 {
667 info!("Creating new cross signing identity");
668
669 let (identity, upload_signing_keys_req, upload_signatures_req) = {
670 let cache = self.inner.store.cache().await?;
671 let account = cache.account().await?;
672 account.bootstrap_cross_signing().await
673 };
674
675 let public = identity.to_public_identity().await.expect(
676 "Couldn't create a public version of the identity from a new private identity",
677 );
678
679 *self.inner.user_identity.lock().await = identity.clone();
680
681 self.store()
682 .save_changes(Changes {
683 identities: IdentityChanges { new: vec![public.into()], ..Default::default() },
684 private_identity: Some(identity),
685 ..Default::default()
686 })
687 .await?;
688
689 (upload_signing_keys_req, upload_signatures_req)
690 } else {
691 info!("Trying to upload the existing cross signing identity");
692 let upload_signing_keys_req = identity.as_upload_request().await;
693
694 let upload_signatures_req = identity
696 .sign_account(self.inner.store.static_account())
697 .await
698 .expect("Can't sign device keys");
699
700 (upload_signing_keys_req, upload_signatures_req)
701 };
702
703 let upload_keys_req =
707 self.upload_device_keys().await?.map(|(_, request)| OutgoingRequest::from(request));
708
709 Ok(CrossSigningBootstrapRequests {
710 upload_signing_keys_req,
711 upload_keys_req,
712 upload_signatures_req,
713 })
714 }
715
716 pub async fn upload_device_keys(
728 &self,
729 ) -> StoreResult<Option<(OwnedTransactionId, UploadKeysRequest)>> {
730 let cache = self.store().cache().await?;
731 let account = cache.account().await?;
732
733 Ok(self.keys_for_upload(&account).await.map(|request| (TransactionId::new(), request)))
734 }
735
736 async fn receive_keys_upload_response(&self, response: &UploadKeysResponse) -> OlmResult<()> {
743 self.inner
744 .store
745 .with_transaction(|mut tr| async {
746 let account = tr.account().await?;
747 account.receive_keys_upload_response(response)?;
748 Ok((tr, ()))
749 })
750 .await
751 }
752
753 #[instrument(skip_all)]
781 pub async fn get_missing_sessions(
782 &self,
783 users: impl Iterator<Item = &UserId>,
784 ) -> StoreResult<Option<(OwnedTransactionId, KeysClaimRequest)>> {
785 self.inner.session_manager.get_missing_sessions(users).await
786 }
787
788 async fn receive_keys_query_response(
797 &self,
798 request_id: &TransactionId,
799 response: &KeysQueryResponse,
800 ) -> OlmResult<(DeviceChanges, IdentityChanges)> {
801 self.inner.identity_manager.receive_keys_query_response(request_id, response).await
802 }
803
804 async fn keys_for_upload(&self, account: &Account) -> Option<UploadKeysRequest> {
813 let (mut device_keys, one_time_keys, fallback_keys) = account.keys_for_upload();
814
815 if let Some(device_keys) = &mut device_keys {
825 let private_identity = self.store().private_identity();
826 let guard = private_identity.lock().await;
827
828 if guard.status().await.is_complete() {
829 guard.sign_device_keys(device_keys).await.expect(
830 "We should be able to sign our device keys since we confirmed that we \
831 have a complete set of private cross-signing keys",
832 );
833 }
834 }
835
836 if device_keys.is_none() && one_time_keys.is_empty() && fallback_keys.is_empty() {
837 None
838 } else {
839 let device_keys = device_keys.map(|d| d.to_raw());
840
841 Some(assign!(UploadKeysRequest::new(), {
842 device_keys, one_time_keys, fallback_keys
843 }))
844 }
845 }
846
847 async fn decrypt_to_device_event(
870 &self,
871 transaction: &mut StoreTransaction,
872 event: &EncryptedToDeviceEvent,
873 changes: &mut Changes,
874 decryption_settings: &DecryptionSettings,
875 ) -> Result<OlmDecryptionInfo, DecryptToDeviceError> {
876 let mut decrypted = transaction
878 .account()
879 .await?
880 .decrypt_to_device_event(&self.inner.store, event, decryption_settings)
881 .await?;
882
883 self.check_to_device_event_is_not_from_dehydrated_device(&decrypted, &event.sender).await?;
885
886 self.handle_decrypted_to_device_event(transaction.cache(), &mut decrypted, changes).await?;
888
889 Ok(decrypted)
890 }
891
892 #[instrument(
893 skip_all,
894 fields(room_id = ? content.room_id, session_id, message_index, shared_history = content.shared_history)
898 )]
899 async fn handle_key(
900 &self,
901 sender_key: Curve25519PublicKey,
902 event: &DecryptedRoomKeyEvent,
903 content: &MegolmV1AesSha2Content,
904 ) -> OlmResult<Option<InboundGroupSession>> {
905 let session =
906 InboundGroupSession::from_room_key_content(sender_key, event.keys.ed25519, content);
907
908 match session {
909 Ok(mut session) => {
910 Span::current().record("session_id", session.session_id());
911 Span::current().record("message_index", session.first_known_index());
912
913 let sender_data =
914 SenderDataFinder::find_using_event(self.store(), sender_key, event, &session)
915 .await?;
916 session.sender_data = sender_data;
917
918 Ok(self.store().merge_received_group_session(session).await?)
919 }
920 Err(e) => {
921 Span::current().record("session_id", &content.session_id);
922 warn!("Received a room key event which contained an invalid session key: {e}");
923
924 Ok(None)
925 }
926 }
927 }
928
929 #[instrument(skip_all, fields(algorithm = ?event.content.algorithm()))]
931 async fn add_room_key(
932 &self,
933 sender_key: Curve25519PublicKey,
934 event: &DecryptedRoomKeyEvent,
935 ) -> OlmResult<Option<InboundGroupSession>> {
936 match &event.content {
937 RoomKeyContent::MegolmV1AesSha2(content) => {
938 self.handle_key(sender_key, event, content).await
939 }
940 #[cfg(feature = "experimental-algorithms")]
941 RoomKeyContent::MegolmV2AesSha2(content) => {
942 self.handle_key(sender_key, event, content).await
943 }
944 RoomKeyContent::Unknown(_) => {
945 warn!("Received a room key with an unsupported algorithm");
946 Ok(None)
947 }
948 }
949 }
950
951 #[instrument()]
954 async fn receive_room_key_bundle_data(
955 &self,
956 sender_key: Curve25519PublicKey,
957 event: &DecryptedRoomKeyBundleEvent,
958 changes: &mut Changes,
959 ) -> OlmResult<()> {
960 let Some(sender_device_keys) = &event.sender_device_keys else {
961 warn!("Received a room key bundle with no sender device keys: ignoring");
962 return Ok(());
963 };
964
965 let sender_device_data =
970 DeviceData::try_from(sender_device_keys).expect("failed to verify sender device keys");
971 let sender_device = self.store().wrap_device_data(sender_device_data).await?;
972
973 changes.received_room_key_bundles.push(StoredRoomKeyBundleData {
974 sender_user: event.sender.clone(),
975 sender_data: SenderData::from_device(&sender_device),
976 sender_key,
977 bundle_data: event.content.clone(),
978 });
979 Ok(())
980 }
981
982 fn add_withheld_info(&self, changes: &mut Changes, event: &RoomKeyWithheldEvent) {
983 debug!(?event.content, "Processing `m.room_key.withheld` event");
984
985 if let RoomKeyWithheldContent::MegolmV1AesSha2(
986 MegolmV1AesSha2WithheldContent::BlackListed(c)
987 | MegolmV1AesSha2WithheldContent::Unverified(c)
988 | MegolmV1AesSha2WithheldContent::Unauthorised(c)
989 | MegolmV1AesSha2WithheldContent::Unavailable(c),
990 ) = &event.content
991 {
992 changes
993 .withheld_session_info
994 .entry(c.room_id.to_owned())
995 .or_default()
996 .insert(c.session_id.to_owned(), event.to_owned().into());
997 }
998 }
999
1000 #[cfg(test)]
1001 pub(crate) async fn create_outbound_group_session_with_defaults_test_helper(
1002 &self,
1003 room_id: &RoomId,
1004 ) -> OlmResult<()> {
1005 let (_, session) = self
1006 .inner
1007 .group_session_manager
1008 .create_outbound_group_session(
1009 room_id,
1010 EncryptionSettings::default(),
1011 SenderData::unknown(),
1012 )
1013 .await?;
1014
1015 self.store().save_inbound_group_sessions(&[session]).await?;
1016
1017 Ok(())
1018 }
1019
1020 #[cfg(test)]
1021 #[allow(dead_code)]
1022 pub(crate) async fn create_inbound_session_test_helper(
1023 &self,
1024 room_id: &RoomId,
1025 ) -> OlmResult<InboundGroupSession> {
1026 let (_, session) = self
1027 .inner
1028 .group_session_manager
1029 .create_outbound_group_session(
1030 room_id,
1031 EncryptionSettings::default(),
1032 SenderData::unknown(),
1033 )
1034 .await?;
1035
1036 Ok(session)
1037 }
1038
1039 pub async fn encrypt_room_event(
1056 &self,
1057 room_id: &RoomId,
1058 content: impl MessageLikeEventContent,
1059 ) -> MegolmResult<Raw<RoomEncryptedEventContent>> {
1060 let event_type = content.event_type().to_string();
1061 let content = Raw::new(&content)?.cast_unchecked();
1062 self.encrypt_room_event_raw(room_id, &event_type, &content).await
1063 }
1064
1065 pub async fn encrypt_room_event_raw(
1085 &self,
1086 room_id: &RoomId,
1087 event_type: &str,
1088 content: &Raw<AnyMessageLikeEventContent>,
1089 ) -> MegolmResult<Raw<RoomEncryptedEventContent>> {
1090 self.inner.group_session_manager.encrypt(room_id, event_type, content).await
1091 }
1092
1093 #[cfg(feature = "experimental-encrypted-state-events")]
1105 pub async fn encrypt_state_event<C, K>(
1106 &self,
1107 room_id: &RoomId,
1108 content: C,
1109 state_key: K,
1110 ) -> MegolmResult<Raw<RoomEncryptedEventContent>>
1111 where
1112 C: StateEventContent,
1113 C::StateKey: Borrow<K>,
1114 K: AsRef<str>,
1115 {
1116 let event_type = content.event_type().to_string();
1117 let content = Raw::new(&content)?.cast_unchecked();
1118 self.encrypt_state_event_raw(room_id, &event_type, state_key.as_ref(), &content).await
1119 }
1120
1121 #[cfg(feature = "experimental-encrypted-state-events")]
1140 pub async fn encrypt_state_event_raw(
1141 &self,
1142 room_id: &RoomId,
1143 event_type: &str,
1144 state_key: &str,
1145 content: &Raw<AnyStateEventContent>,
1146 ) -> MegolmResult<Raw<RoomEncryptedEventContent>> {
1147 self.inner
1148 .group_session_manager
1149 .encrypt_state(room_id, event_type, state_key, content)
1150 .await
1151 }
1152
1153 pub async fn discard_room_key(&self, room_id: &RoomId) -> StoreResult<bool> {
1164 self.inner.group_session_manager.invalidate_group_session(room_id).await
1165 }
1166
1167 pub async fn share_room_key(
1187 &self,
1188 room_id: &RoomId,
1189 users: impl Iterator<Item = &UserId>,
1190 encryption_settings: impl Into<EncryptionSettings>,
1191 ) -> OlmResult<Vec<Arc<ToDeviceRequest>>> {
1192 self.inner.group_session_manager.share_room_key(room_id, users, encryption_settings).await
1193 }
1194
1195 #[cfg(feature = "experimental-send-custom-to-device")]
1209 pub async fn encrypt_content_for_devices(
1210 &self,
1211 devices: Vec<DeviceData>,
1212 event_type: &str,
1213 content: &Value,
1214 share_strategy: CollectStrategy,
1215 ) -> OlmResult<(Vec<ToDeviceRequest>, Vec<(DeviceData, WithheldCode)>)> {
1216 let mut changes = Changes::default();
1217
1218 let (allowed_devices, mut blocked_devices) =
1219 split_devices_for_share_strategy(&self.inner.store, devices, share_strategy).await?;
1220
1221 let result = self
1222 .inner
1223 .group_session_manager
1224 .encrypt_content_for_devices(allowed_devices, event_type, content.clone(), &mut changes)
1225 .await;
1226
1227 if !changes.is_empty() {
1229 let session_count = changes.sessions.len();
1230
1231 self.inner.store.save_changes(changes).await?;
1232
1233 trace!(
1234 session_count = session_count,
1235 "Stored the changed sessions after encrypting a custom to-device event"
1236 );
1237 }
1238
1239 result.map(|(to_device_requests, mut withheld)| {
1240 withheld.append(&mut blocked_devices);
1241 (to_device_requests, withheld)
1242 })
1243 }
1244 pub async fn share_room_key_bundle_data(
1249 &self,
1250 user_id: &UserId,
1251 collect_strategy: &CollectStrategy,
1252 bundle_data: RoomKeyBundleContent,
1253 ) -> OlmResult<Vec<ToDeviceRequest>> {
1254 self.inner
1255 .group_session_manager
1256 .share_room_key_bundle_data(user_id, collect_strategy, bundle_data)
1257 .await
1258 }
1259
1260 #[deprecated(note = "Use OlmMachine::receive_verification_event instead", since = "0.7.0")]
1268 pub async fn receive_unencrypted_verification_event(
1269 &self,
1270 event: &AnyMessageLikeEvent,
1271 ) -> StoreResult<()> {
1272 self.inner.verification_machine.receive_any_event(event).await
1273 }
1274
1275 pub async fn receive_verification_event(&self, event: &AnyMessageLikeEvent) -> StoreResult<()> {
1288 self.inner.verification_machine.receive_any_event(event).await
1289 }
1290
1291 #[instrument(
1297 skip_all,
1298 fields(
1299 sender_key = ?decrypted.result.sender_key,
1300 event_type = decrypted.result.event.event_type(),
1301 ),
1302 )]
1303 async fn handle_decrypted_to_device_event(
1304 &self,
1305 cache: &StoreCache,
1306 decrypted: &mut OlmDecryptionInfo,
1307 changes: &mut Changes,
1308 ) -> OlmResult<()> {
1309 debug!(
1310 sender_device_keys =
1311 ?decrypted.result.event.sender_device_keys().map(|k| (k.curve25519_key(), k.ed25519_key())).unwrap_or((None, None)),
1312 "Received a decrypted to-device event",
1313 );
1314
1315 match &*decrypted.result.event {
1316 AnyDecryptedOlmEvent::RoomKey(e) => {
1317 let session = self.add_room_key(decrypted.result.sender_key, e).await?;
1318 decrypted.inbound_group_session = session;
1319 }
1320 AnyDecryptedOlmEvent::ForwardedRoomKey(e) => {
1321 let session = self
1322 .inner
1323 .key_request_machine
1324 .receive_forwarded_room_key(decrypted.result.sender_key, e)
1325 .await?;
1326 decrypted.inbound_group_session = session;
1327 }
1328 AnyDecryptedOlmEvent::SecretSend(e) => {
1329 let name = self
1330 .inner
1331 .key_request_machine
1332 .receive_secret_event(cache, decrypted.result.sender_key, e, changes)
1333 .await?;
1334
1335 if let Ok(ToDeviceEvents::SecretSend(mut e)) =
1338 decrypted.result.raw_event.deserialize_as()
1339 {
1340 e.content.secret_name = name;
1341 decrypted.result.raw_event = Raw::from_json(to_raw_value(&e)?);
1342 }
1343 }
1344 AnyDecryptedOlmEvent::Dummy(_) => {
1345 debug!("Received an `m.dummy` event");
1346 }
1347 AnyDecryptedOlmEvent::RoomKeyBundle(e) => {
1348 debug!("Received a room key bundle event {:?}", e);
1349 self.receive_room_key_bundle_data(decrypted.result.sender_key, e, changes).await?;
1350 }
1351 AnyDecryptedOlmEvent::Custom(_) => {
1352 warn!("Received an unexpected encrypted to-device event");
1353 }
1354 }
1355
1356 Ok(())
1357 }
1358
1359 async fn handle_verification_event(&self, event: &ToDeviceEvents) {
1360 if let Err(e) = self.inner.verification_machine.receive_any_event(event).await {
1361 error!("Error handling a verification event: {e:?}");
1362 }
1363 }
1364
1365 async fn mark_to_device_request_as_sent(&self, request_id: &TransactionId) -> StoreResult<()> {
1367 self.inner.verification_machine.mark_request_as_sent(request_id);
1368 self.inner.key_request_machine.mark_outgoing_request_as_sent(request_id).await?;
1369 self.inner.group_session_manager.mark_request_as_sent(request_id).await?;
1370 self.inner.session_manager.mark_outgoing_request_as_sent(request_id);
1371 Ok(())
1372 }
1373
1374 pub fn get_verification(&self, user_id: &UserId, flow_id: &str) -> Option<Verification> {
1376 self.inner.verification_machine.get_verification(user_id, flow_id)
1377 }
1378
1379 pub fn get_verification_request(
1381 &self,
1382 user_id: &UserId,
1383 flow_id: impl AsRef<str>,
1384 ) -> Option<VerificationRequest> {
1385 self.inner.verification_machine.get_request(user_id, flow_id)
1386 }
1387
1388 pub fn get_verification_requests(&self, user_id: &UserId) -> Vec<VerificationRequest> {
1390 self.inner.verification_machine.get_requests(user_id)
1391 }
1392
1393 async fn handle_to_device_event(&self, changes: &mut Changes, event: &ToDeviceEvents) {
1398 use crate::types::events::ToDeviceEvents::*;
1399
1400 match event {
1401 RoomKeyRequest(e) => self.inner.key_request_machine.receive_incoming_key_request(e),
1407 SecretRequest(e) => self.inner.key_request_machine.receive_incoming_secret_request(e),
1408 RoomKeyWithheld(e) => self.add_withheld_info(changes, e),
1409 KeyVerificationAccept(..)
1410 | KeyVerificationCancel(..)
1411 | KeyVerificationKey(..)
1412 | KeyVerificationMac(..)
1413 | KeyVerificationRequest(..)
1414 | KeyVerificationReady(..)
1415 | KeyVerificationDone(..)
1416 | KeyVerificationStart(..) => {
1417 self.handle_verification_event(event).await;
1418 }
1419
1420 Custom(_) | Dummy(_) => {}
1422
1423 RoomEncrypted(_) => {}
1425
1426 SecretSend(_) | RoomKey(_) | ForwardedRoomKey(_) => {}
1429 }
1430 }
1431
1432 fn record_message_id(event: &Raw<AnyToDeviceEvent>) {
1433 use serde::Deserialize;
1434
1435 #[derive(Deserialize)]
1436 struct ContentStub<'a> {
1437 #[serde(borrow, rename = "org.matrix.msgid")]
1438 message_id: Option<&'a str>,
1439 }
1440 #[derive(Deserialize)]
1441 struct ToDeviceStub<'a> {
1442 sender: &'a str,
1443 #[serde(rename = "type")]
1444 event_type: &'a str,
1445 #[serde(borrow)]
1446 content: ContentStub<'a>,
1447 }
1448
1449 if let Ok(event) = event.deserialize_as_unchecked::<ToDeviceStub<'_>>() {
1450 Span::current().record("sender", event.sender);
1451 Span::current().record("event_type", event.event_type);
1452 Span::current().record("message_id", event.content.message_id);
1453 }
1454 }
1455
1456 #[instrument(skip_all, fields(sender, event_type, message_id))]
1464 async fn receive_to_device_event(
1465 &self,
1466 transaction: &mut StoreTransaction,
1467 changes: &mut Changes,
1468 raw_event: Raw<AnyToDeviceEvent>,
1469 decryption_settings: &DecryptionSettings,
1470 ) -> Option<ProcessedToDeviceEvent> {
1471 Self::record_message_id(&raw_event);
1472
1473 let event: ToDeviceEvents = match raw_event.deserialize_as() {
1474 Ok(e) => e,
1475 Err(e) => {
1476 warn!("Received an invalid to-device event: {e}");
1478 return Some(ProcessedToDeviceEvent::Invalid(raw_event));
1479 }
1480 };
1481
1482 debug!("Received a to-device event");
1483
1484 match event {
1485 ToDeviceEvents::RoomEncrypted(e) => {
1486 self.receive_encrypted_to_device_event(
1487 transaction,
1488 changes,
1489 raw_event,
1490 e,
1491 decryption_settings,
1492 )
1493 .await
1494 }
1495 e => {
1496 self.handle_to_device_event(changes, &e).await;
1497 Some(ProcessedToDeviceEvent::PlainText(raw_event))
1498 }
1499 }
1500 }
1501
1502 async fn receive_encrypted_to_device_event(
1516 &self,
1517 transaction: &mut StoreTransaction,
1518 changes: &mut Changes,
1519 mut raw_event: Raw<AnyToDeviceEvent>,
1520 e: ToDeviceEvent<ToDeviceEncryptedEventContent>,
1521 decryption_settings: &DecryptionSettings,
1522 ) -> Option<ProcessedToDeviceEvent> {
1523 let decrypted = match self
1524 .decrypt_to_device_event(transaction, &e, changes, decryption_settings)
1525 .await
1526 {
1527 Ok(decrypted) => decrypted,
1528 Err(DecryptToDeviceError::OlmError(err)) => {
1529 let reason = if let OlmError::UnverifiedSenderDevice = &err {
1530 ToDeviceUnableToDecryptReason::UnverifiedSenderDevice
1531 } else {
1532 ToDeviceUnableToDecryptReason::DecryptionFailure
1533 };
1534
1535 if let OlmError::SessionWedged(sender, curve_key) = err {
1536 if let Err(e) =
1537 self.inner.session_manager.mark_device_as_wedged(&sender, curve_key).await
1538 {
1539 error!(
1540 error = ?e,
1541 "Couldn't mark device to be unwedged",
1542 );
1543 }
1544 }
1545
1546 return Some(ProcessedToDeviceEvent::UnableToDecrypt {
1547 encrypted_event: raw_event,
1548 utd_info: ToDeviceUnableToDecryptInfo { reason },
1549 });
1550 }
1551 Err(DecryptToDeviceError::FromDehydratedDevice) => return None,
1552 };
1553
1554 match decrypted.session {
1557 SessionType::New(s) | SessionType::Existing(s) => {
1558 changes.sessions.push(s);
1559 }
1560 }
1561
1562 changes.message_hashes.push(decrypted.message_hash);
1563
1564 if let Some(group_session) = decrypted.inbound_group_session {
1565 changes.inbound_group_sessions.push(group_session);
1566 }
1567
1568 match decrypted.result.raw_event.deserialize_as() {
1569 Ok(event) => {
1570 self.handle_to_device_event(changes, &event).await;
1571
1572 raw_event = event
1573 .serialize_zeroized()
1574 .expect("Zeroizing and reserializing our events should always work")
1575 .cast();
1576 }
1577 Err(e) => {
1578 warn!("Received an invalid encrypted to-device event: {e}");
1579 raw_event = decrypted.result.raw_event;
1580 }
1581 }
1582
1583 Some(ProcessedToDeviceEvent::Decrypted {
1584 raw: raw_event,
1585 encryption_info: decrypted.result.encryption_info,
1586 })
1587 }
1588
1589 async fn check_to_device_event_is_not_from_dehydrated_device(
1592 &self,
1593 decrypted: &OlmDecryptionInfo,
1594 sender_user_id: &UserId,
1595 ) -> Result<(), DecryptToDeviceError> {
1596 if self.to_device_event_is_from_dehydrated_device(decrypted, sender_user_id).await? {
1597 warn!(
1598 sender = ?sender_user_id,
1599 session = ?decrypted.session,
1600 "Received a to-device event from a dehydrated device. This is unexpected: ignoring event"
1601 );
1602 Err(DecryptToDeviceError::FromDehydratedDevice)
1603 } else {
1604 Ok(())
1605 }
1606 }
1607
1608 async fn to_device_event_is_from_dehydrated_device(
1614 &self,
1615 decrypted: &OlmDecryptionInfo,
1616 sender_user_id: &UserId,
1617 ) -> OlmResult<bool> {
1618 if let Some(device_keys) = decrypted.result.event.sender_device_keys() {
1620 if device_keys.dehydrated.unwrap_or(false) {
1626 return Ok(true);
1627 }
1628 }
1633
1634 Ok(self
1636 .store()
1637 .get_device_from_curve_key(sender_user_id, decrypted.result.sender_key)
1638 .await?
1639 .is_some_and(|d| d.is_dehydrated()))
1640 }
1641
1642 #[instrument(skip_all)]
1660 pub async fn receive_sync_changes(
1661 &self,
1662 sync_changes: EncryptionSyncChanges<'_>,
1663 decryption_settings: &DecryptionSettings,
1664 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Vec<RoomKeyInfo>)> {
1665 let mut store_transaction = self.inner.store.transaction().await;
1666
1667 let (events, changes) = self
1668 .preprocess_sync_changes(&mut store_transaction, sync_changes, decryption_settings)
1669 .await?;
1670
1671 let room_key_updates: Vec<_> =
1674 changes.inbound_group_sessions.iter().map(RoomKeyInfo::from).collect();
1675
1676 self.store().save_changes(changes).await?;
1677 store_transaction.commit().await?;
1678
1679 Ok((events, room_key_updates))
1680 }
1681
1682 pub(crate) async fn preprocess_sync_changes(
1700 &self,
1701 transaction: &mut StoreTransaction,
1702 sync_changes: EncryptionSyncChanges<'_>,
1703 decryption_settings: &DecryptionSettings,
1704 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Changes)> {
1705 let mut events: Vec<ProcessedToDeviceEvent> = self
1707 .inner
1708 .verification_machine
1709 .garbage_collect()
1710 .iter()
1711 .map(|e| ProcessedToDeviceEvent::PlainText(e.clone()))
1715 .collect();
1716 let mut changes = Default::default();
1719
1720 {
1721 let account = transaction.account().await?;
1722 account.update_key_counts(
1723 sync_changes.one_time_keys_counts,
1724 sync_changes.unused_fallback_keys,
1725 )
1726 }
1727
1728 if let Err(e) = self
1729 .inner
1730 .identity_manager
1731 .receive_device_changes(
1732 transaction.cache(),
1733 sync_changes.changed_devices.changed.iter().map(|u| u.as_ref()),
1734 )
1735 .await
1736 {
1737 error!(error = ?e, "Error marking a tracked user as changed");
1738 }
1739
1740 for raw_event in sync_changes.to_device_events {
1741 let processed_event = Box::pin(self.receive_to_device_event(
1742 transaction,
1743 &mut changes,
1744 raw_event,
1745 decryption_settings,
1746 ))
1747 .await;
1748
1749 if let Some(processed_event) = processed_event {
1750 events.push(processed_event);
1751 }
1752 }
1753
1754 let changed_sessions = self
1755 .inner
1756 .key_request_machine
1757 .collect_incoming_key_requests(transaction.cache())
1758 .await?;
1759
1760 changes.sessions.extend(changed_sessions);
1761 changes.next_batch_token = sync_changes.next_batch_token;
1762
1763 Ok((events, changes))
1764 }
1765
1766 pub async fn request_room_key(
1783 &self,
1784 event: &Raw<EncryptedEvent>,
1785 room_id: &RoomId,
1786 ) -> MegolmResult<(Option<OutgoingRequest>, OutgoingRequest)> {
1787 let event = event.deserialize()?;
1788 self.inner.key_request_machine.request_key(room_id, &event).await
1789 }
1790
1791 async fn get_room_event_verification_state(
1804 &self,
1805 session: &InboundGroupSession,
1806 sender: &UserId,
1807 ) -> MegolmResult<(VerificationState, Option<OwnedDeviceId>)> {
1808 let sender_data = self.get_or_update_sender_data(session, sender).await?;
1809
1810 let (verification_state, device_id) = match sender_data.user_id() {
1819 Some(i) if i != sender => {
1820 (VerificationState::Unverified(VerificationLevel::MismatchedSender), None)
1821 }
1822
1823 Some(_) | None => {
1824 sender_data_to_verification_state(sender_data, session.has_been_imported())
1825 }
1826 };
1827
1828 Ok((verification_state, device_id))
1829 }
1830
1831 async fn get_or_update_sender_data(
1846 &self,
1847 session: &InboundGroupSession,
1848 sender: &UserId,
1849 ) -> MegolmResult<SenderData> {
1850 let sender_data = if session.sender_data.should_recalculate() {
1851 let calculated_sender_data = SenderDataFinder::find_using_curve_key(
1870 self.store(),
1871 session.sender_key(),
1872 sender,
1873 session,
1874 )
1875 .await?;
1876
1877 if calculated_sender_data.compare_trust_level(&session.sender_data).is_gt() {
1879 let mut new_session = session.clone();
1881 new_session.sender_data = calculated_sender_data.clone();
1882 self.store().save_inbound_group_sessions(&[new_session]).await?;
1883
1884 calculated_sender_data
1886 } else {
1887 session.sender_data.clone()
1889 }
1890 } else {
1891 session.sender_data.clone()
1892 };
1893
1894 Ok(sender_data)
1895 }
1896
1897 pub async fn query_missing_secrets_from_other_sessions(&self) -> StoreResult<bool> {
1922 let identity = self.inner.user_identity.lock().await;
1923 let mut secrets = identity.get_missing_secrets().await;
1924
1925 if self.store().load_backup_keys().await?.decryption_key.is_none() {
1926 secrets.push(SecretName::RecoveryKey);
1927 }
1928
1929 if secrets.is_empty() {
1930 debug!("No missing requests to query");
1931 return Ok(false);
1932 }
1933
1934 let secret_requests = GossipMachine::request_missing_secrets(self.user_id(), secrets);
1935
1936 let unsent_request = self.store().get_unsent_secret_requests().await?;
1938 let not_yet_requested = secret_requests
1939 .into_iter()
1940 .filter(|request| !unsent_request.iter().any(|unsent| unsent.info == request.info))
1941 .collect_vec();
1942
1943 if not_yet_requested.is_empty() {
1944 debug!("The missing secrets have already been requested");
1945 Ok(false)
1946 } else {
1947 debug!("Requesting missing secrets");
1948
1949 let changes = Changes { key_requests: not_yet_requested, ..Default::default() };
1950
1951 self.store().save_changes(changes).await?;
1952 Ok(true)
1953 }
1954 }
1955
1956 async fn get_encryption_info(
1962 &self,
1963 session: &InboundGroupSession,
1964 sender: &UserId,
1965 ) -> MegolmResult<Arc<EncryptionInfo>> {
1966 let (verification_state, device_id) =
1967 self.get_room_event_verification_state(session, sender).await?;
1968
1969 let sender = sender.to_owned();
1970
1971 Ok(Arc::new(EncryptionInfo {
1972 sender,
1973 sender_device: device_id,
1974 algorithm_info: AlgorithmInfo::MegolmV1AesSha2 {
1975 curve25519_key: session.sender_key().to_base64(),
1976 sender_claimed_keys: session
1977 .signing_keys()
1978 .iter()
1979 .map(|(k, v)| (k.to_owned(), v.to_base64()))
1980 .collect(),
1981 session_id: Some(session.session_id().to_owned()),
1982 },
1983 verification_state,
1984 }))
1985 }
1986
1987 async fn decrypt_megolm_events(
1988 &self,
1989 room_id: &RoomId,
1990 event: &EncryptedEvent,
1991 content: &SupportedEventEncryptionSchemes<'_>,
1992 decryption_settings: &DecryptionSettings,
1993 ) -> MegolmResult<(JsonObject, Arc<EncryptionInfo>)> {
1994 let session =
1995 self.get_inbound_group_session_or_error(room_id, content.session_id()).await?;
1996
1997 Span::current().record("sender_key", debug(session.sender_key()));
2003
2004 let result = session.decrypt(event).await;
2005 match result {
2006 Ok((decrypted_event, _)) => {
2007 let encryption_info = self.get_encryption_info(&session, &event.sender).await?;
2008
2009 self.check_sender_trust_requirement(
2010 &session,
2011 &encryption_info,
2012 &decryption_settings.sender_device_trust_requirement,
2013 )?;
2014
2015 Ok((decrypted_event, encryption_info))
2016 }
2017 Err(error) => Err(
2018 if let MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) = error {
2019 let withheld_code = self
2020 .inner
2021 .store
2022 .get_withheld_info(room_id, content.session_id())
2023 .await?
2024 .map(|e| e.content.withheld_code());
2025
2026 if withheld_code.is_some() {
2027 MegolmError::MissingRoomKey(withheld_code)
2029 } else {
2030 error
2031 }
2032 } else {
2033 error
2034 },
2035 ),
2036 }
2037 }
2038
2039 fn check_sender_trust_requirement(
2045 &self,
2046 session: &InboundGroupSession,
2047 encryption_info: &EncryptionInfo,
2048 trust_requirement: &TrustRequirement,
2049 ) -> MegolmResult<()> {
2050 trace!(
2051 verification_state = ?encryption_info.verification_state,
2052 ?trust_requirement, "check_sender_trust_requirement",
2053 );
2054
2055 let verification_level = match &encryption_info.verification_state {
2058 VerificationState::Verified => return Ok(()),
2059 VerificationState::Unverified(verification_level) => verification_level,
2060 };
2061
2062 let ok = match trust_requirement {
2063 TrustRequirement::Untrusted => true,
2064
2065 TrustRequirement::CrossSignedOrLegacy => {
2066 let legacy_session = match session.sender_data {
2072 SenderData::DeviceInfo { legacy_session, .. } => legacy_session,
2073 SenderData::UnknownDevice { legacy_session, .. } => legacy_session,
2074 _ => false,
2075 };
2076
2077 match (verification_level, legacy_session) {
2087 (VerificationLevel::UnverifiedIdentity, _) => true,
2089
2090 (VerificationLevel::UnsignedDevice, true) => true,
2092
2093 (VerificationLevel::None(_), true) => true,
2095
2096 (VerificationLevel::VerificationViolation, _)
2098 | (VerificationLevel::MismatchedSender, _)
2099 | (VerificationLevel::UnsignedDevice, false)
2100 | (VerificationLevel::None(_), false) => false,
2101 }
2102 }
2103
2104 TrustRequirement::CrossSigned => match verification_level {
2107 VerificationLevel::UnverifiedIdentity => true,
2108
2109 VerificationLevel::VerificationViolation
2110 | VerificationLevel::MismatchedSender
2111 | VerificationLevel::UnsignedDevice
2112 | VerificationLevel::None(_) => false,
2113 },
2114 };
2115
2116 if ok {
2117 Ok(())
2118 } else {
2119 Err(MegolmError::SenderIdentityNotTrusted(verification_level.clone()))
2120 }
2121 }
2122
2123 async fn get_inbound_group_session_or_error(
2128 &self,
2129 room_id: &RoomId,
2130 session_id: &str,
2131 ) -> MegolmResult<InboundGroupSession> {
2132 match self.store().get_inbound_group_session(room_id, session_id).await? {
2133 Some(session) => Ok(session),
2134 None => {
2135 let withheld_code = self
2136 .inner
2137 .store
2138 .get_withheld_info(room_id, session_id)
2139 .await?
2140 .map(|e| e.content.withheld_code());
2141 Err(MegolmError::MissingRoomKey(withheld_code))
2142 }
2143 }
2144 }
2145
2146 pub async fn try_decrypt_room_event(
2161 &self,
2162 raw_event: &Raw<EncryptedEvent>,
2163 room_id: &RoomId,
2164 decryption_settings: &DecryptionSettings,
2165 ) -> Result<RoomEventDecryptionResult, CryptoStoreError> {
2166 match self.decrypt_room_event_inner(raw_event, room_id, true, decryption_settings).await {
2167 Ok(decrypted) => Ok(RoomEventDecryptionResult::Decrypted(decrypted)),
2168 Err(err) => Ok(RoomEventDecryptionResult::UnableToDecrypt(megolm_error_to_utd_info(
2169 raw_event, err,
2170 )?)),
2171 }
2172 }
2173
2174 pub async fn decrypt_room_event(
2182 &self,
2183 event: &Raw<EncryptedEvent>,
2184 room_id: &RoomId,
2185 decryption_settings: &DecryptionSettings,
2186 ) -> MegolmResult<DecryptedRoomEvent> {
2187 self.decrypt_room_event_inner(event, room_id, true, decryption_settings).await
2188 }
2189
2190 #[instrument(name = "decrypt_room_event", skip_all, fields(?room_id, event_id, origin_server_ts, sender, algorithm, session_id, message_index, sender_key))]
2191 async fn decrypt_room_event_inner(
2192 &self,
2193 event: &Raw<EncryptedEvent>,
2194 room_id: &RoomId,
2195 decrypt_unsigned: bool,
2196 decryption_settings: &DecryptionSettings,
2197 ) -> MegolmResult<DecryptedRoomEvent> {
2198 let _timer = timer!(tracing::Level::TRACE, "_method");
2199
2200 let event = event.deserialize()?;
2201
2202 Span::current()
2203 .record("sender", debug(&event.sender))
2204 .record("event_id", debug(&event.event_id))
2205 .record(
2206 "origin_server_ts",
2207 timestamp_to_iso8601(event.origin_server_ts)
2208 .unwrap_or_else(|| "<out of range>".to_owned()),
2209 )
2210 .record("algorithm", debug(event.content.algorithm()));
2211
2212 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2213 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2214 Span::current().record("sender_key", debug(c.sender_key));
2215 c.into()
2216 }
2217 #[cfg(feature = "experimental-algorithms")]
2218 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2219 RoomEventEncryptionScheme::Unknown(_) => {
2220 warn!("Received an encrypted room event with an unsupported algorithm");
2221 return Err(EventError::UnsupportedAlgorithm.into());
2222 }
2223 };
2224
2225 Span::current().record("session_id", content.session_id());
2226 Span::current().record("message_index", content.message_index());
2227
2228 let result =
2229 self.decrypt_megolm_events(room_id, &event, &content, decryption_settings).await;
2230
2231 if let Err(e) = &result {
2232 #[cfg(feature = "automatic-room-key-forwarding")]
2233 match e {
2234 MegolmError::MissingRoomKey(_)
2237 | MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
2238 self.inner
2239 .key_request_machine
2240 .create_outgoing_key_request(room_id, &event)
2241 .await?;
2242 }
2243 _ => {}
2244 }
2245
2246 warn!("Failed to decrypt a room event: {e}");
2247 }
2248
2249 let (mut decrypted_event, encryption_info) = result?;
2250
2251 let mut unsigned_encryption_info = None;
2252 if decrypt_unsigned {
2253 unsigned_encryption_info = self
2255 .decrypt_unsigned_events(&mut decrypted_event, room_id, decryption_settings)
2256 .await;
2257 }
2258
2259 let decrypted_event =
2260 serde_json::from_value::<Raw<AnyTimelineEvent>>(decrypted_event.into())?;
2261
2262 #[cfg(feature = "experimental-encrypted-state-events")]
2263 self.verify_packed_state_key(&event, &decrypted_event)?;
2264
2265 Ok(DecryptedRoomEvent { event: decrypted_event, encryption_info, unsigned_encryption_info })
2266 }
2267
2268 #[cfg(feature = "experimental-encrypted-state-events")]
2285 fn verify_packed_state_key(
2286 &self,
2287 original: &EncryptedEvent,
2288 decrypted: &Raw<AnyTimelineEvent>,
2289 ) -> MegolmResult<()> {
2290 use serde::Deserialize;
2291
2292 #[derive(Deserialize)]
2294 struct PayloadDeserializationHelper {
2295 state_key: Option<String>,
2296 #[serde(rename = "type")]
2297 event_type: String,
2298 }
2299
2300 let PayloadDeserializationHelper {
2302 state_key: inner_state_key,
2303 event_type: inner_event_type,
2304 } = decrypted
2305 .deserialize_as_unchecked()
2306 .map_err(|_| MegolmError::StateKeyVerificationFailed)?;
2307
2308 let (raw_state_key, inner_state_key) = match (&original.state_key, &inner_state_key) {
2310 (Some(raw_state_key), Some(inner_state_key)) => (raw_state_key, inner_state_key),
2311 (None, None) => return Ok(()),
2312 _ => return Err(MegolmError::StateKeyVerificationFailed),
2313 };
2314
2315 let (outer_event_type, outer_state_key) =
2317 raw_state_key.split_once(":").ok_or(MegolmError::StateKeyVerificationFailed)?;
2318
2319 if outer_event_type != inner_event_type {
2321 return Err(MegolmError::StateKeyVerificationFailed);
2322 }
2323
2324 if outer_state_key != inner_state_key {
2326 return Err(MegolmError::StateKeyVerificationFailed);
2327 }
2328 Ok(())
2329 }
2330
2331 async fn decrypt_unsigned_events(
2341 &self,
2342 main_event: &mut JsonObject,
2343 room_id: &RoomId,
2344 decryption_settings: &DecryptionSettings,
2345 ) -> Option<BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>> {
2346 let unsigned = main_event.get_mut("unsigned")?.as_object_mut()?;
2347 let mut unsigned_encryption_info: Option<
2348 BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>,
2349 > = None;
2350
2351 let location = UnsignedEventLocation::RelationsReplace;
2353 let replace = location.find_mut(unsigned);
2354 if let Some(decryption_result) =
2355 self.decrypt_unsigned_event(replace, room_id, decryption_settings).await
2356 {
2357 unsigned_encryption_info
2358 .get_or_insert_with(Default::default)
2359 .insert(location, decryption_result);
2360 }
2361
2362 let location = UnsignedEventLocation::RelationsThreadLatestEvent;
2365 let thread_latest_event = location.find_mut(unsigned);
2366 if let Some(decryption_result) =
2367 self.decrypt_unsigned_event(thread_latest_event, room_id, decryption_settings).await
2368 {
2369 unsigned_encryption_info
2370 .get_or_insert_with(Default::default)
2371 .insert(location, decryption_result);
2372 }
2373
2374 unsigned_encryption_info
2375 }
2376
2377 fn decrypt_unsigned_event<'a>(
2385 &'a self,
2386 event: Option<&'a mut Value>,
2387 room_id: &'a RoomId,
2388 decryption_settings: &'a DecryptionSettings,
2389 ) -> BoxFuture<'a, Option<UnsignedDecryptionResult>> {
2390 Box::pin(async move {
2391 let event = event?;
2392
2393 let is_encrypted = event
2394 .get("type")
2395 .and_then(|type_| type_.as_str())
2396 .is_some_and(|s| s == "m.room.encrypted");
2397 if !is_encrypted {
2398 return None;
2399 }
2400
2401 let raw_event = serde_json::from_value(event.clone()).ok()?;
2402 match self
2403 .decrypt_room_event_inner(&raw_event, room_id, false, decryption_settings)
2404 .await
2405 {
2406 Ok(decrypted_event) => {
2407 *event = serde_json::to_value(decrypted_event.event).ok()?;
2409 Some(UnsignedDecryptionResult::Decrypted(decrypted_event.encryption_info))
2410 }
2411 Err(err) => {
2412 let utd_info = megolm_error_to_utd_info(&raw_event, err).ok()?;
2417 Some(UnsignedDecryptionResult::UnableToDecrypt(utd_info))
2418 }
2419 }
2420 })
2421 }
2422
2423 pub async fn is_room_key_available(
2430 &self,
2431 event: &Raw<EncryptedEvent>,
2432 room_id: &RoomId,
2433 ) -> Result<bool, CryptoStoreError> {
2434 let event = event.deserialize()?;
2435
2436 let (session_id, message_index) = match &event.content.scheme {
2437 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2438 (&c.session_id, c.ciphertext.message_index())
2439 }
2440 #[cfg(feature = "experimental-algorithms")]
2441 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => {
2442 (&c.session_id, c.ciphertext.message_index())
2443 }
2444 RoomEventEncryptionScheme::Unknown(_) => {
2445 return Ok(false);
2447 }
2448 };
2449
2450 Ok(self
2453 .store()
2454 .get_inbound_group_session(room_id, session_id)
2455 .await?
2456 .filter(|s| s.first_known_index() <= message_index)
2457 .is_some())
2458 }
2459
2460 #[instrument(skip(self, event), fields(event_id, sender, session_id))]
2473 pub async fn get_room_event_encryption_info(
2474 &self,
2475 event: &Raw<EncryptedEvent>,
2476 room_id: &RoomId,
2477 ) -> MegolmResult<Arc<EncryptionInfo>> {
2478 let event = event.deserialize()?;
2479
2480 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2481 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => c.into(),
2482 #[cfg(feature = "experimental-algorithms")]
2483 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2484 RoomEventEncryptionScheme::Unknown(_) => {
2485 return Err(EventError::UnsupportedAlgorithm.into());
2486 }
2487 };
2488
2489 Span::current()
2490 .record("sender", debug(&event.sender))
2491 .record("event_id", debug(&event.event_id))
2492 .record("session_id", content.session_id());
2493
2494 self.get_session_encryption_info(room_id, content.session_id(), &event.sender).await
2495 }
2496
2497 pub async fn get_session_encryption_info(
2512 &self,
2513 room_id: &RoomId,
2514 session_id: &str,
2515 sender: &UserId,
2516 ) -> MegolmResult<Arc<EncryptionInfo>> {
2517 let session = self.get_inbound_group_session_or_error(room_id, session_id).await?;
2518 self.get_encryption_info(&session, sender).await
2519 }
2520
2521 pub async fn update_tracked_users(
2539 &self,
2540 users: impl IntoIterator<Item = &UserId>,
2541 ) -> StoreResult<()> {
2542 self.inner.identity_manager.update_tracked_users(users).await
2543 }
2544
2545 pub async fn mark_all_tracked_users_as_dirty(&self) -> StoreResult<()> {
2550 self.inner
2551 .identity_manager
2552 .mark_all_tracked_users_as_dirty(self.inner.store.cache().await?)
2553 .await
2554 }
2555
2556 async fn wait_if_user_pending(
2557 &self,
2558 user_id: &UserId,
2559 timeout: Option<Duration>,
2560 ) -> StoreResult<()> {
2561 if let Some(timeout) = timeout {
2562 let cache = self.store().cache().await?;
2563 self.inner
2564 .identity_manager
2565 .key_query_manager
2566 .wait_if_user_key_query_pending(cache, timeout, user_id)
2567 .await?;
2568 }
2569 Ok(())
2570 }
2571
2572 #[instrument(skip(self))]
2602 pub async fn get_device(
2603 &self,
2604 user_id: &UserId,
2605 device_id: &DeviceId,
2606 timeout: Option<Duration>,
2607 ) -> StoreResult<Option<Device>> {
2608 self.wait_if_user_pending(user_id, timeout).await?;
2609 self.store().get_device(user_id, device_id).await
2610 }
2611
2612 #[instrument(skip(self))]
2626 pub async fn get_identity(
2627 &self,
2628 user_id: &UserId,
2629 timeout: Option<Duration>,
2630 ) -> StoreResult<Option<UserIdentity>> {
2631 self.wait_if_user_pending(user_id, timeout).await?;
2632 self.store().get_identity(user_id).await
2633 }
2634
2635 #[instrument(skip(self))]
2662 pub async fn get_user_devices(
2663 &self,
2664 user_id: &UserId,
2665 timeout: Option<Duration>,
2666 ) -> StoreResult<UserDevices> {
2667 self.wait_if_user_pending(user_id, timeout).await?;
2668 self.store().get_user_devices(user_id).await
2669 }
2670
2671 pub async fn cross_signing_status(&self) -> CrossSigningStatus {
2676 self.inner.user_identity.lock().await.status().await
2677 }
2678
2679 pub async fn export_cross_signing_keys(&self) -> StoreResult<Option<CrossSigningKeyExport>> {
2687 let master_key = self.store().export_secret(&SecretName::CrossSigningMasterKey).await?;
2688 let self_signing_key =
2689 self.store().export_secret(&SecretName::CrossSigningSelfSigningKey).await?;
2690 let user_signing_key =
2691 self.store().export_secret(&SecretName::CrossSigningUserSigningKey).await?;
2692
2693 Ok(if master_key.is_none() && self_signing_key.is_none() && user_signing_key.is_none() {
2694 None
2695 } else {
2696 Some(CrossSigningKeyExport { master_key, self_signing_key, user_signing_key })
2697 })
2698 }
2699
2700 pub async fn import_cross_signing_keys(
2705 &self,
2706 export: CrossSigningKeyExport,
2707 ) -> Result<CrossSigningStatus, SecretImportError> {
2708 self.store().import_cross_signing_keys(export).await
2709 }
2710
2711 async fn sign_with_master_key(
2712 &self,
2713 message: &str,
2714 ) -> Result<(OwnedDeviceKeyId, Ed25519Signature), SignatureError> {
2715 let identity = &*self.inner.user_identity.lock().await;
2716 let key_id = identity.master_key_id().await.ok_or(SignatureError::MissingSigningKey)?;
2717
2718 let signature = identity.sign(message).await?;
2719
2720 Ok((key_id, signature))
2721 }
2722
2723 pub async fn sign(&self, message: &str) -> Result<Signatures, CryptoStoreError> {
2729 let mut signatures = Signatures::new();
2730
2731 {
2732 let cache = self.inner.store.cache().await?;
2733 let account = cache.account().await?;
2734 let key_id = account.signing_key_id();
2735 let signature = account.sign(message);
2736 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
2737 }
2738
2739 match self.sign_with_master_key(message).await {
2740 Ok((key_id, signature)) => {
2741 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
2742 }
2743 Err(e) => {
2744 warn!(error = ?e, "Couldn't sign the message using the cross signing master key")
2745 }
2746 }
2747
2748 Ok(signatures)
2749 }
2750
2751 pub fn backup_machine(&self) -> &BackupMachine {
2756 &self.inner.backup_machine
2757 }
2758
2759 pub async fn initialize_crypto_store_generation(
2763 &self,
2764 generation: &Mutex<Option<u64>>,
2765 ) -> StoreResult<()> {
2766 let mut gen_guard = generation.lock().await;
2769
2770 let prev_generation =
2771 self.inner.store.get_custom_value(Self::CURRENT_GENERATION_STORE_KEY).await?;
2772
2773 let gen = match prev_generation {
2774 Some(val) => {
2775 u64::from_le_bytes(val.try_into().map_err(|_| {
2778 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
2779 })?)
2780 .wrapping_add(1)
2781 }
2782 None => 0,
2783 };
2784
2785 tracing::debug!("Initialising crypto store generation at {}", gen);
2786
2787 self.inner
2788 .store
2789 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, gen.to_le_bytes().to_vec())
2790 .await?;
2791
2792 *gen_guard = Some(gen);
2793
2794 Ok(())
2795 }
2796
2797 pub async fn maintain_crypto_store_generation(
2822 &'_ self,
2823 generation: &Mutex<Option<u64>>,
2824 ) -> StoreResult<(bool, u64)> {
2825 let mut gen_guard = generation.lock().await;
2826
2827 let actual_gen = self
2833 .inner
2834 .store
2835 .get_custom_value(Self::CURRENT_GENERATION_STORE_KEY)
2836 .await?
2837 .ok_or_else(|| {
2838 CryptoStoreError::InvalidLockGeneration("counter missing in store".to_owned())
2839 })?;
2840
2841 let actual_gen =
2842 u64::from_le_bytes(actual_gen.try_into().map_err(|_| {
2843 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
2844 })?);
2845
2846 let new_gen = match gen_guard.as_ref() {
2847 Some(expected_gen) => {
2848 if actual_gen == *expected_gen {
2849 return Ok((false, actual_gen));
2850 }
2851 actual_gen.max(*expected_gen).wrapping_add(1)
2853 }
2854 None => {
2855 actual_gen.wrapping_add(1)
2858 }
2859 };
2860
2861 tracing::debug!(
2862 "Crypto store generation mismatch: previously known was {:?}, actual is {:?}, next is {}",
2863 *gen_guard,
2864 actual_gen,
2865 new_gen
2866 );
2867
2868 *gen_guard = Some(new_gen);
2870
2871 self.inner
2873 .store
2874 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, new_gen.to_le_bytes().to_vec())
2875 .await?;
2876
2877 Ok((true, new_gen))
2878 }
2879
2880 pub fn dehydrated_devices(&self) -> DehydratedDevices {
2882 DehydratedDevices { inner: self.to_owned() }
2883 }
2884
2885 pub async fn room_settings(&self, room_id: &RoomId) -> StoreResult<Option<RoomSettings>> {
2890 self.inner.store.get_room_settings(room_id).await
2893 }
2894
2895 pub async fn set_room_settings(
2906 &self,
2907 room_id: &RoomId,
2908 new_settings: &RoomSettings,
2909 ) -> Result<(), SetRoomSettingsError> {
2910 let store = &self.inner.store;
2911
2912 let _store_transaction = store.transaction().await;
2917
2918 let old_settings = store.get_room_settings(room_id).await?;
2919
2920 if let Some(old_settings) = old_settings {
2933 if old_settings != *new_settings {
2934 return Err(SetRoomSettingsError::EncryptionDowngrade);
2935 } else {
2936 return Ok(());
2938 }
2939 }
2940
2941 match new_settings.algorithm {
2943 EventEncryptionAlgorithm::MegolmV1AesSha2 => (),
2944
2945 #[cfg(feature = "experimental-algorithms")]
2946 EventEncryptionAlgorithm::MegolmV2AesSha2 => (),
2947
2948 _ => {
2949 warn!(
2950 ?room_id,
2951 "Rejecting invalid encryption algorithm {}", new_settings.algorithm
2952 );
2953 return Err(SetRoomSettingsError::InvalidSettings);
2954 }
2955 }
2956
2957 store
2959 .save_changes(Changes {
2960 room_settings: HashMap::from([(room_id.to_owned(), new_settings.clone())]),
2961 ..Default::default()
2962 })
2963 .await?;
2964
2965 Ok(())
2966 }
2967
2968 #[cfg(any(feature = "testing", test))]
2972 pub fn same_as(&self, other: &OlmMachine) -> bool {
2973 Arc::ptr_eq(&self.inner, &other.inner)
2974 }
2975
2976 #[cfg(any(feature = "testing", test))]
2978 pub async fn uploaded_key_count(&self) -> Result<u64, CryptoStoreError> {
2979 let cache = self.inner.store.cache().await?;
2980 let account = cache.account().await?;
2981 Ok(account.uploaded_key_count())
2982 }
2983
2984 #[cfg(test)]
2986 pub(crate) fn identity_manager(&self) -> &IdentityManager {
2987 &self.inner.identity_manager
2988 }
2989
2990 #[cfg(test)]
2992 pub(crate) fn key_for_has_migrated_verification_latch() -> &'static str {
2993 Self::HAS_MIGRATED_VERIFICATION_LATCH
2994 }
2995}
2996
2997fn sender_data_to_verification_state(
2998 sender_data: SenderData,
2999 session_has_been_imported: bool,
3000) -> (VerificationState, Option<OwnedDeviceId>) {
3001 match sender_data {
3002 SenderData::UnknownDevice { owner_check_failed: false, .. } => {
3003 let device_link_problem = if session_has_been_imported {
3004 DeviceLinkProblem::InsecureSource
3005 } else {
3006 DeviceLinkProblem::MissingDevice
3007 };
3008
3009 (VerificationState::Unverified(VerificationLevel::None(device_link_problem)), None)
3010 }
3011 SenderData::UnknownDevice { owner_check_failed: true, .. } => (
3012 VerificationState::Unverified(VerificationLevel::None(
3013 DeviceLinkProblem::InsecureSource,
3014 )),
3015 None,
3016 ),
3017 SenderData::DeviceInfo { device_keys, .. } => (
3018 VerificationState::Unverified(VerificationLevel::UnsignedDevice),
3019 Some(device_keys.device_id),
3020 ),
3021 SenderData::VerificationViolation(KnownSenderData { device_id, .. }) => {
3022 (VerificationState::Unverified(VerificationLevel::VerificationViolation), device_id)
3023 }
3024 SenderData::SenderUnverified(KnownSenderData { device_id, .. }) => {
3025 (VerificationState::Unverified(VerificationLevel::UnverifiedIdentity), device_id)
3026 }
3027 SenderData::SenderVerified(KnownSenderData { device_id, .. }) => {
3028 (VerificationState::Verified, device_id)
3029 }
3030 }
3031}
3032
3033#[derive(Debug, Clone)]
3036pub struct CrossSigningBootstrapRequests {
3037 pub upload_keys_req: Option<OutgoingRequest>,
3044
3045 pub upload_signing_keys_req: UploadSigningKeysRequest,
3049
3050 pub upload_signatures_req: UploadSignaturesRequest,
3055}
3056
3057#[derive(Debug)]
3060pub struct EncryptionSyncChanges<'a> {
3061 pub to_device_events: Vec<Raw<AnyToDeviceEvent>>,
3063 pub changed_devices: &'a DeviceLists,
3066 pub one_time_keys_counts: &'a BTreeMap<OneTimeKeyAlgorithm, UInt>,
3068 pub unused_fallback_keys: Option<&'a [OneTimeKeyAlgorithm]>,
3070 pub next_batch_token: Option<String>,
3072}
3073
3074fn megolm_error_to_utd_info(
3082 raw_event: &Raw<EncryptedEvent>,
3083 error: MegolmError,
3084) -> Result<UnableToDecryptInfo, CryptoStoreError> {
3085 use MegolmError::*;
3086 let reason = match error {
3087 EventError(_) => UnableToDecryptReason::MalformedEncryptedEvent,
3088 Decode(_) => UnableToDecryptReason::MalformedEncryptedEvent,
3089 MissingRoomKey(maybe_withheld) => {
3090 UnableToDecryptReason::MissingMegolmSession { withheld_code: maybe_withheld }
3091 }
3092 Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
3093 UnableToDecryptReason::UnknownMegolmMessageIndex
3094 }
3095 Decryption(_) => UnableToDecryptReason::MegolmDecryptionFailure,
3096 JsonError(_) => UnableToDecryptReason::PayloadDeserializationFailure,
3097 MismatchedIdentityKeys(_) => UnableToDecryptReason::MismatchedIdentityKeys,
3098 SenderIdentityNotTrusted(level) => UnableToDecryptReason::SenderIdentityNotTrusted(level),
3099 #[cfg(feature = "experimental-encrypted-state-events")]
3100 StateKeyVerificationFailed => UnableToDecryptReason::StateKeyVerificationFailed,
3101
3102 Store(error) => Err(error)?,
3105 };
3106
3107 let session_id = raw_event.deserialize().ok().and_then(|ev| match ev.content.scheme {
3108 RoomEventEncryptionScheme::MegolmV1AesSha2(s) => Some(s.session_id),
3109 #[cfg(feature = "experimental-algorithms")]
3110 RoomEventEncryptionScheme::MegolmV2AesSha2(s) => Some(s.session_id),
3111 RoomEventEncryptionScheme::Unknown(_) => None,
3112 });
3113
3114 Ok(UnableToDecryptInfo { session_id, reason })
3115}
3116
3117#[derive(Debug, thiserror::Error)]
3127pub(crate) enum DecryptToDeviceError {
3128 #[error("An Olm error occurred meaning we failed to decrypt the event")]
3129 OlmError(#[from] OlmError),
3130
3131 #[error("The event was sent from a dehydrated device")]
3132 FromDehydratedDevice,
3133}
3134
3135impl From<CryptoStoreError> for DecryptToDeviceError {
3136 fn from(value: CryptoStoreError) -> Self {
3137 Self::OlmError(value.into())
3138 }
3139}
3140
3141#[cfg(test)]
3142impl From<DecryptToDeviceError> for OlmError {
3143 fn from(value: DecryptToDeviceError) -> Self {
3146 match value {
3147 DecryptToDeviceError::OlmError(olm_error) => olm_error,
3148 DecryptToDeviceError::FromDehydratedDevice => {
3149 panic!("Expected an OlmError but found FromDehydratedDevice")
3150 }
3151 }
3152 }
3153}
3154
3155#[cfg(test)]
3156pub(crate) mod test_helpers;
3157
3158#[cfg(test)]
3159pub(crate) mod tests;