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::{
66 megolm::{DecryptionError, SessionOrdering},
67 Curve25519PublicKey, Ed25519Signature,
68};
69
70#[cfg(feature = "experimental-send-custom-to-device")]
71use crate::session_manager::split_devices_for_share_strategy;
72use crate::{
73 backups::{BackupMachine, MegolmV1BackupKey},
74 dehydrated_devices::{DehydratedDevices, DehydrationError},
75 error::{EventError, MegolmError, MegolmResult, OlmError, OlmResult, SetRoomSettingsError},
76 gossiping::GossipMachine,
77 identities::{user::UserIdentity, Device, IdentityManager, UserDevices},
78 olm::{
79 Account, CrossSigningStatus, EncryptionSettings, IdentityKeys, InboundGroupSession,
80 KnownSenderData, OlmDecryptionInfo, PrivateCrossSigningIdentity, SenderData,
81 SenderDataFinder, SessionType, StaticAccountData,
82 },
83 session_manager::{GroupSessionManager, SessionManager},
84 store::{
85 caches::StoreCache,
86 types::{
87 Changes, CrossSigningKeyExport, DeviceChanges, IdentityChanges, PendingChanges,
88 RoomKeyInfo, RoomSettings, StoredRoomKeyBundleData,
89 },
90 CryptoStoreWrapper, IntoCryptoStore, MemoryStore, Result as StoreResult, SecretImportError,
91 Store, StoreTransaction,
92 },
93 types::{
94 events::{
95 olm_v1::{AnyDecryptedOlmEvent, DecryptedRoomKeyBundleEvent, DecryptedRoomKeyEvent},
96 room::encrypted::{
97 EncryptedEvent, EncryptedToDeviceEvent, RoomEncryptedEventContent,
98 RoomEventEncryptionScheme, SupportedEventEncryptionSchemes,
99 ToDeviceEncryptedEventContent,
100 },
101 room_key::{MegolmV1AesSha2Content, RoomKeyContent},
102 room_key_bundle::RoomKeyBundleContent,
103 room_key_withheld::{
104 MegolmV1AesSha2WithheldContent, RoomKeyWithheldContent, RoomKeyWithheldEvent,
105 },
106 ToDeviceEvent, ToDeviceEvents,
107 },
108 requests::{
109 AnyIncomingResponse, KeysQueryRequest, OutgoingRequest, ToDeviceRequest,
110 UploadSigningKeysRequest,
111 },
112 EventEncryptionAlgorithm, Signatures,
113 },
114 utilities::timestamp_to_iso8601,
115 verification::{Verification, VerificationMachine, VerificationRequest},
116 CollectStrategy, CryptoStoreError, DecryptionSettings, DeviceData, LocalTrust,
117 RoomEventDecryptionResult, SignatureError, TrustRequirement,
118};
119
120#[derive(Clone)]
123pub struct OlmMachine {
124 pub(crate) inner: Arc<OlmMachineInner>,
125}
126
127pub struct OlmMachineInner {
128 user_id: OwnedUserId,
130 device_id: OwnedDeviceId,
132 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
137 store: Store,
141 session_manager: SessionManager,
143 pub(crate) group_session_manager: GroupSessionManager,
145 verification_machine: VerificationMachine,
148 pub(crate) key_request_machine: GossipMachine,
151 identity_manager: IdentityManager,
154 backup_machine: BackupMachine,
156}
157
158#[cfg(not(tarpaulin_include))]
159impl std::fmt::Debug for OlmMachine {
160 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161 f.debug_struct("OlmMachine")
162 .field("user_id", &self.user_id())
163 .field("device_id", &self.device_id())
164 .finish()
165 }
166}
167
168impl OlmMachine {
169 const CURRENT_GENERATION_STORE_KEY: &'static str = "generation-counter";
170 const HAS_MIGRATED_VERIFICATION_LATCH: &'static str = "HAS_MIGRATED_VERIFICATION_LATCH";
171
172 pub async fn new(user_id: &UserId, device_id: &DeviceId) -> Self {
183 OlmMachine::with_store(user_id, device_id, MemoryStore::new(), None)
184 .await
185 .expect("Reading and writing to the memory store always succeeds")
186 }
187
188 pub(crate) async fn rehydrate(
189 &self,
190 pickle_key: &[u8; 32],
191 device_id: &DeviceId,
192 device_data: Raw<DehydratedDeviceData>,
193 ) -> Result<OlmMachine, DehydrationError> {
194 let account = Account::rehydrate(pickle_key, self.user_id(), device_id, device_data)?;
195 let static_account = account.static_data().clone();
196
197 let store =
198 Arc::new(CryptoStoreWrapper::new(self.user_id(), device_id, MemoryStore::new()));
199 let device = DeviceData::from_account(&account);
200 store.save_pending_changes(PendingChanges { account: Some(account) }).await?;
201 store
202 .save_changes(Changes {
203 devices: DeviceChanges { new: vec![device], ..Default::default() },
204 ..Default::default()
205 })
206 .await?;
207
208 let (verification_machine, store, identity_manager) =
209 Self::new_helper_prelude(store, static_account, self.store().private_identity());
210
211 Ok(Self::new_helper(
212 device_id,
213 store,
214 verification_machine,
215 identity_manager,
216 self.store().private_identity(),
217 None,
218 ))
219 }
220
221 fn new_helper_prelude(
222 store_wrapper: Arc<CryptoStoreWrapper>,
223 account: StaticAccountData,
224 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
225 ) -> (VerificationMachine, Store, IdentityManager) {
226 let verification_machine =
227 VerificationMachine::new(account.clone(), user_identity.clone(), store_wrapper.clone());
228 let store = Store::new(account, user_identity, store_wrapper, verification_machine.clone());
229
230 let identity_manager = IdentityManager::new(store.clone());
231
232 (verification_machine, store, identity_manager)
233 }
234
235 fn new_helper(
236 device_id: &DeviceId,
237 store: Store,
238 verification_machine: VerificationMachine,
239 identity_manager: IdentityManager,
240 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
241 maybe_backup_key: Option<MegolmV1BackupKey>,
242 ) -> Self {
243 let group_session_manager = GroupSessionManager::new(store.clone());
244
245 let users_for_key_claim = Arc::new(StdRwLock::new(BTreeMap::new()));
246 let key_request_machine = GossipMachine::new(
247 store.clone(),
248 identity_manager.clone(),
249 group_session_manager.session_cache(),
250 users_for_key_claim.clone(),
251 );
252
253 let session_manager =
254 SessionManager::new(users_for_key_claim, key_request_machine.clone(), store.clone());
255
256 let backup_machine = BackupMachine::new(store.clone(), maybe_backup_key);
257
258 let inner = Arc::new(OlmMachineInner {
259 user_id: store.user_id().to_owned(),
260 device_id: device_id.to_owned(),
261 user_identity,
262 store,
263 session_manager,
264 group_session_manager,
265 verification_machine,
266 key_request_machine,
267 identity_manager,
268 backup_machine,
269 });
270
271 Self { inner }
272 }
273
274 #[instrument(skip(store, custom_account), fields(ed25519_key, curve25519_key))]
299 pub async fn with_store(
300 user_id: &UserId,
301 device_id: &DeviceId,
302 store: impl IntoCryptoStore,
303 custom_account: Option<vodozemac::olm::Account>,
304 ) -> StoreResult<Self> {
305 let store = store.into_crypto_store();
306
307 let static_account = match store.load_account().await? {
308 Some(account) => {
309 if user_id != account.user_id()
310 || device_id != account.device_id()
311 || custom_account.is_some()
312 {
313 return Err(CryptoStoreError::MismatchedAccount {
314 expected: (account.user_id().to_owned(), account.device_id().to_owned()),
315 got: (user_id.to_owned(), device_id.to_owned()),
316 });
317 }
318
319 Span::current()
320 .record("ed25519_key", display(account.identity_keys().ed25519))
321 .record("curve25519_key", display(account.identity_keys().curve25519));
322 debug!("Restored an Olm account");
323
324 account.static_data().clone()
325 }
326
327 None => {
328 let account = if let Some(account) = custom_account {
329 Account::new_helper(account, user_id, device_id)
330 } else {
331 Account::with_device_id(user_id, device_id)
332 };
333
334 let static_account = account.static_data().clone();
335
336 Span::current()
337 .record("ed25519_key", display(account.identity_keys().ed25519))
338 .record("curve25519_key", display(account.identity_keys().curve25519));
339
340 let device = DeviceData::from_account(&account);
341
342 device.set_trust_state(LocalTrust::Verified);
346
347 let changes = Changes {
348 devices: DeviceChanges { new: vec![device], ..Default::default() },
349 ..Default::default()
350 };
351 store.save_changes(changes).await?;
352 store.save_pending_changes(PendingChanges { account: Some(account) }).await?;
353
354 debug!("Created a new Olm account");
355
356 static_account
357 }
358 };
359
360 let identity = match store.load_identity().await? {
361 Some(i) => {
362 let master_key = i
363 .master_public_key()
364 .await
365 .and_then(|m| m.get_first_key().map(|m| m.to_owned()));
366 debug!(?master_key, "Restored the cross signing identity");
367 i
368 }
369 None => {
370 debug!("Creating an empty cross signing identity stub");
371 PrivateCrossSigningIdentity::empty(user_id)
372 }
373 };
374
375 let saved_keys = store.load_backup_keys().await?;
380 let maybe_backup_key = saved_keys.decryption_key.and_then(|k| {
381 if let Some(version) = saved_keys.backup_version {
382 let megolm_v1_backup_key = k.megolm_v1_public_key();
383 megolm_v1_backup_key.set_version(version);
384 Some(megolm_v1_backup_key)
385 } else {
386 None
387 }
388 });
389
390 let identity = Arc::new(Mutex::new(identity));
391 let store = Arc::new(CryptoStoreWrapper::new(user_id, device_id, store));
392
393 let (verification_machine, store, identity_manager) =
394 Self::new_helper_prelude(store, static_account, identity.clone());
395
396 Self::migration_post_verified_latch_support(&store, &identity_manager).await?;
399
400 Ok(Self::new_helper(
401 device_id,
402 store,
403 verification_machine,
404 identity_manager,
405 identity,
406 maybe_backup_key,
407 ))
408 }
409
410 pub(crate) async fn migration_post_verified_latch_support(
418 store: &Store,
419 identity_manager: &IdentityManager,
420 ) -> Result<(), CryptoStoreError> {
421 let maybe_migrate_for_identity_verified_latch =
422 store.get_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH).await?.is_none();
423
424 if maybe_migrate_for_identity_verified_latch {
425 identity_manager.mark_all_tracked_users_as_dirty(store.cache().await?).await?;
426
427 store.set_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH, vec![0]).await?
428 }
429 Ok(())
430 }
431
432 pub fn store(&self) -> &Store {
434 &self.inner.store
435 }
436
437 pub fn user_id(&self) -> &UserId {
439 &self.inner.user_id
440 }
441
442 pub fn device_id(&self) -> &DeviceId {
444 &self.inner.device_id
445 }
446
447 pub fn device_creation_time(&self) -> MilliSecondsSinceUnixEpoch {
454 self.inner.store.static_account().creation_local_time()
455 }
456
457 pub fn identity_keys(&self) -> IdentityKeys {
459 let account = self.inner.store.static_account();
460 account.identity_keys()
461 }
462
463 pub async fn display_name(&self) -> StoreResult<Option<String>> {
465 self.store().device_display_name().await
466 }
467
468 pub async fn tracked_users(&self) -> StoreResult<HashSet<OwnedUserId>> {
473 let cache = self.store().cache().await?;
474 Ok(self.inner.identity_manager.key_query_manager.synced(&cache).await?.tracked_users())
475 }
476
477 #[cfg(feature = "automatic-room-key-forwarding")]
486 pub fn set_room_key_requests_enabled(&self, enable: bool) {
487 self.inner.key_request_machine.set_room_key_requests_enabled(enable)
488 }
489
490 pub fn are_room_key_requests_enabled(&self) -> bool {
495 self.inner.key_request_machine.are_room_key_requests_enabled()
496 }
497
498 #[cfg(feature = "automatic-room-key-forwarding")]
507 pub fn set_room_key_forwarding_enabled(&self, enable: bool) {
508 self.inner.key_request_machine.set_room_key_forwarding_enabled(enable)
509 }
510
511 pub fn is_room_key_forwarding_enabled(&self) -> bool {
515 self.inner.key_request_machine.is_room_key_forwarding_enabled()
516 }
517
518 pub async fn outgoing_requests(&self) -> StoreResult<Vec<OutgoingRequest>> {
526 let mut requests = Vec::new();
527
528 {
529 let store_cache = self.inner.store.cache().await?;
530 let account = store_cache.account().await?;
531 if let Some(r) = self.keys_for_upload(&account).await.map(|r| OutgoingRequest {
532 request_id: TransactionId::new(),
533 request: Arc::new(r.into()),
534 }) {
535 requests.push(r);
536 }
537 }
538
539 for request in self
540 .inner
541 .identity_manager
542 .users_for_key_query()
543 .await?
544 .into_iter()
545 .map(|(request_id, r)| OutgoingRequest { request_id, request: Arc::new(r.into()) })
546 {
547 requests.push(request);
548 }
549
550 requests.append(&mut self.inner.verification_machine.outgoing_messages());
551 requests.append(&mut self.inner.key_request_machine.outgoing_to_device_requests().await?);
552
553 Ok(requests)
554 }
555
556 pub fn query_keys_for_users<'a>(
577 &self,
578 users: impl IntoIterator<Item = &'a UserId>,
579 ) -> (OwnedTransactionId, KeysQueryRequest) {
580 self.inner.identity_manager.build_key_query_for_users(users)
581 }
582
583 pub async fn mark_request_as_sent<'a>(
593 &self,
594 request_id: &TransactionId,
595 response: impl Into<AnyIncomingResponse<'a>>,
596 ) -> OlmResult<()> {
597 match response.into() {
598 AnyIncomingResponse::KeysUpload(response) => {
599 Box::pin(self.receive_keys_upload_response(response)).await?;
600 }
601 AnyIncomingResponse::KeysQuery(response) => {
602 Box::pin(self.receive_keys_query_response(request_id, response)).await?;
603 }
604 AnyIncomingResponse::KeysClaim(response) => {
605 Box::pin(
606 self.inner.session_manager.receive_keys_claim_response(request_id, response),
607 )
608 .await?;
609 }
610 AnyIncomingResponse::ToDevice(_) => {
611 Box::pin(self.mark_to_device_request_as_sent(request_id)).await?;
612 }
613 AnyIncomingResponse::SigningKeysUpload(_) => {
614 Box::pin(self.receive_cross_signing_upload_response()).await?;
615 }
616 AnyIncomingResponse::SignatureUpload(_) => {
617 self.inner.verification_machine.mark_request_as_sent(request_id);
618 }
619 AnyIncomingResponse::RoomMessage(_) => {
620 self.inner.verification_machine.mark_request_as_sent(request_id);
621 }
622 AnyIncomingResponse::KeysBackup(_) => {
623 Box::pin(self.inner.backup_machine.mark_request_as_sent(request_id)).await?;
624 }
625 }
626
627 Ok(())
628 }
629
630 async fn receive_cross_signing_upload_response(&self) -> StoreResult<()> {
632 let identity = self.inner.user_identity.lock().await;
633 identity.mark_as_shared();
634
635 let changes = Changes { private_identity: Some(identity.clone()), ..Default::default() };
636
637 self.store().save_changes(changes).await
638 }
639
640 pub async fn bootstrap_cross_signing(
659 &self,
660 reset: bool,
661 ) -> StoreResult<CrossSigningBootstrapRequests> {
662 let identity = self.inner.user_identity.lock().await.clone();
667
668 let (upload_signing_keys_req, upload_signatures_req) = if reset || identity.is_empty().await
669 {
670 info!("Creating new cross signing identity");
671
672 let (identity, upload_signing_keys_req, upload_signatures_req) = {
673 let cache = self.inner.store.cache().await?;
674 let account = cache.account().await?;
675 account.bootstrap_cross_signing().await
676 };
677
678 let public = identity.to_public_identity().await.expect(
679 "Couldn't create a public version of the identity from a new private identity",
680 );
681
682 *self.inner.user_identity.lock().await = identity.clone();
683
684 self.store()
685 .save_changes(Changes {
686 identities: IdentityChanges { new: vec![public.into()], ..Default::default() },
687 private_identity: Some(identity),
688 ..Default::default()
689 })
690 .await?;
691
692 (upload_signing_keys_req, upload_signatures_req)
693 } else {
694 info!("Trying to upload the existing cross signing identity");
695 let upload_signing_keys_req = identity.as_upload_request().await;
696
697 let upload_signatures_req = identity
699 .sign_account(self.inner.store.static_account())
700 .await
701 .expect("Can't sign device keys");
702
703 (upload_signing_keys_req, upload_signatures_req)
704 };
705
706 let upload_keys_req =
710 self.upload_device_keys().await?.map(|(_, request)| OutgoingRequest::from(request));
711
712 Ok(CrossSigningBootstrapRequests {
713 upload_signing_keys_req,
714 upload_keys_req,
715 upload_signatures_req,
716 })
717 }
718
719 pub async fn upload_device_keys(
731 &self,
732 ) -> StoreResult<Option<(OwnedTransactionId, UploadKeysRequest)>> {
733 let cache = self.store().cache().await?;
734 let account = cache.account().await?;
735
736 Ok(self.keys_for_upload(&account).await.map(|request| (TransactionId::new(), request)))
737 }
738
739 async fn receive_keys_upload_response(&self, response: &UploadKeysResponse) -> OlmResult<()> {
746 self.inner
747 .store
748 .with_transaction(|mut tr| async {
749 let account = tr.account().await?;
750 account.receive_keys_upload_response(response)?;
751 Ok((tr, ()))
752 })
753 .await
754 }
755
756 #[instrument(skip_all)]
784 pub async fn get_missing_sessions(
785 &self,
786 users: impl Iterator<Item = &UserId>,
787 ) -> StoreResult<Option<(OwnedTransactionId, KeysClaimRequest)>> {
788 self.inner.session_manager.get_missing_sessions(users).await
789 }
790
791 async fn receive_keys_query_response(
800 &self,
801 request_id: &TransactionId,
802 response: &KeysQueryResponse,
803 ) -> OlmResult<(DeviceChanges, IdentityChanges)> {
804 self.inner.identity_manager.receive_keys_query_response(request_id, response).await
805 }
806
807 async fn keys_for_upload(&self, account: &Account) -> Option<UploadKeysRequest> {
816 let (mut device_keys, one_time_keys, fallback_keys) = account.keys_for_upload();
817
818 if let Some(device_keys) = &mut device_keys {
828 let private_identity = self.store().private_identity();
829 let guard = private_identity.lock().await;
830
831 if guard.status().await.is_complete() {
832 guard.sign_device_keys(device_keys).await.expect(
833 "We should be able to sign our device keys since we confirmed that we \
834 have a complete set of private cross-signing keys",
835 );
836 }
837 }
838
839 if device_keys.is_none() && one_time_keys.is_empty() && fallback_keys.is_empty() {
840 None
841 } else {
842 let device_keys = device_keys.map(|d| d.to_raw());
843
844 Some(assign!(UploadKeysRequest::new(), {
845 device_keys, one_time_keys, fallback_keys
846 }))
847 }
848 }
849
850 async fn decrypt_to_device_event(
873 &self,
874 transaction: &mut StoreTransaction,
875 event: &EncryptedToDeviceEvent,
876 changes: &mut Changes,
877 decryption_settings: &DecryptionSettings,
878 ) -> Result<OlmDecryptionInfo, DecryptToDeviceError> {
879 let mut decrypted = transaction
881 .account()
882 .await?
883 .decrypt_to_device_event(&self.inner.store, event, decryption_settings)
884 .await?;
885
886 self.check_to_device_event_is_not_from_dehydrated_device(&decrypted, &event.sender).await?;
888
889 self.handle_decrypted_to_device_event(transaction.cache(), &mut decrypted, changes).await?;
891
892 Ok(decrypted)
893 }
894
895 #[instrument(
896 skip_all,
897 fields(room_id = ? content.room_id, session_id, message_index, shared_history = content.shared_history)
901 )]
902 async fn handle_key(
903 &self,
904 sender_key: Curve25519PublicKey,
905 event: &DecryptedRoomKeyEvent,
906 content: &MegolmV1AesSha2Content,
907 ) -> OlmResult<Option<InboundGroupSession>> {
908 let session =
909 InboundGroupSession::from_room_key_content(sender_key, event.keys.ed25519, content);
910
911 match session {
912 Ok(mut session) => {
913 Span::current().record("session_id", session.session_id());
914 Span::current().record("message_index", session.first_known_index());
915
916 let sender_data =
917 SenderDataFinder::find_using_event(self.store(), sender_key, event, &session)
918 .await?;
919
920 session.sender_data = sender_data;
921
922 match self.store().compare_group_session(&session).await? {
923 SessionOrdering::Better => {
924 info!("Received a new megolm room key");
925
926 Ok(Some(session))
927 }
928 comparison_result => {
929 warn!(
930 ?comparison_result,
931 "Received a megolm room key that we already have a better version \
932 of, discarding"
933 );
934
935 Ok(None)
936 }
937 }
938 }
939 Err(e) => {
940 Span::current().record("session_id", &content.session_id);
941 warn!("Received a room key event which contained an invalid session key: {e}");
942
943 Ok(None)
944 }
945 }
946 }
947
948 #[instrument(skip_all, fields(algorithm = ?event.content.algorithm()))]
950 async fn add_room_key(
951 &self,
952 sender_key: Curve25519PublicKey,
953 event: &DecryptedRoomKeyEvent,
954 ) -> OlmResult<Option<InboundGroupSession>> {
955 match &event.content {
956 RoomKeyContent::MegolmV1AesSha2(content) => {
957 self.handle_key(sender_key, event, content).await
958 }
959 #[cfg(feature = "experimental-algorithms")]
960 RoomKeyContent::MegolmV2AesSha2(content) => {
961 self.handle_key(sender_key, event, content).await
962 }
963 RoomKeyContent::Unknown(_) => {
964 warn!("Received a room key with an unsupported algorithm");
965 Ok(None)
966 }
967 }
968 }
969
970 #[instrument()]
973 async fn receive_room_key_bundle_data(
974 &self,
975 sender_key: Curve25519PublicKey,
976 event: &DecryptedRoomKeyBundleEvent,
977 changes: &mut Changes,
978 ) -> OlmResult<()> {
979 let Some(sender_device_keys) = &event.sender_device_keys else {
980 warn!("Received a room key bundle with no sender device keys: ignoring");
981 return Ok(());
982 };
983
984 let sender_device_data =
989 DeviceData::try_from(sender_device_keys).expect("failed to verify sender device keys");
990 let sender_device = self.store().wrap_device_data(sender_device_data).await?;
991
992 changes.received_room_key_bundles.push(StoredRoomKeyBundleData {
993 sender_user: event.sender.clone(),
994 sender_data: SenderData::from_device(&sender_device),
995 sender_key,
996 bundle_data: event.content.clone(),
997 });
998 Ok(())
999 }
1000
1001 fn add_withheld_info(&self, changes: &mut Changes, event: &RoomKeyWithheldEvent) {
1002 debug!(?event.content, "Processing `m.room_key.withheld` event");
1003
1004 if let RoomKeyWithheldContent::MegolmV1AesSha2(
1005 MegolmV1AesSha2WithheldContent::BlackListed(c)
1006 | MegolmV1AesSha2WithheldContent::Unverified(c)
1007 | MegolmV1AesSha2WithheldContent::Unauthorised(c)
1008 | MegolmV1AesSha2WithheldContent::Unavailable(c),
1009 ) = &event.content
1010 {
1011 changes
1012 .withheld_session_info
1013 .entry(c.room_id.to_owned())
1014 .or_default()
1015 .insert(c.session_id.to_owned(), event.to_owned().into());
1016 }
1017 }
1018
1019 #[cfg(test)]
1020 pub(crate) async fn create_outbound_group_session_with_defaults_test_helper(
1021 &self,
1022 room_id: &RoomId,
1023 ) -> OlmResult<()> {
1024 let (_, session) = self
1025 .inner
1026 .group_session_manager
1027 .create_outbound_group_session(
1028 room_id,
1029 EncryptionSettings::default(),
1030 SenderData::unknown(),
1031 )
1032 .await?;
1033
1034 self.store().save_inbound_group_sessions(&[session]).await?;
1035
1036 Ok(())
1037 }
1038
1039 #[cfg(test)]
1040 #[allow(dead_code)]
1041 pub(crate) async fn create_inbound_session_test_helper(
1042 &self,
1043 room_id: &RoomId,
1044 ) -> OlmResult<InboundGroupSession> {
1045 let (_, session) = self
1046 .inner
1047 .group_session_manager
1048 .create_outbound_group_session(
1049 room_id,
1050 EncryptionSettings::default(),
1051 SenderData::unknown(),
1052 )
1053 .await?;
1054
1055 Ok(session)
1056 }
1057
1058 pub async fn encrypt_room_event(
1075 &self,
1076 room_id: &RoomId,
1077 content: impl MessageLikeEventContent,
1078 ) -> MegolmResult<Raw<RoomEncryptedEventContent>> {
1079 let event_type = content.event_type().to_string();
1080 let content = Raw::new(&content)?.cast_unchecked();
1081 self.encrypt_room_event_raw(room_id, &event_type, &content).await
1082 }
1083
1084 pub async fn encrypt_room_event_raw(
1104 &self,
1105 room_id: &RoomId,
1106 event_type: &str,
1107 content: &Raw<AnyMessageLikeEventContent>,
1108 ) -> MegolmResult<Raw<RoomEncryptedEventContent>> {
1109 self.inner.group_session_manager.encrypt(room_id, event_type, content).await
1110 }
1111
1112 #[cfg(feature = "experimental-encrypted-state-events")]
1124 pub async fn encrypt_state_event<C, K>(
1125 &self,
1126 room_id: &RoomId,
1127 content: C,
1128 state_key: K,
1129 ) -> MegolmResult<Raw<RoomEncryptedEventContent>>
1130 where
1131 C: StateEventContent,
1132 C::StateKey: Borrow<K>,
1133 K: AsRef<str>,
1134 {
1135 let event_type = content.event_type().to_string();
1136 let content = Raw::new(&content)?.cast_unchecked();
1137 self.encrypt_state_event_raw(room_id, &event_type, state_key.as_ref(), &content).await
1138 }
1139
1140 #[cfg(feature = "experimental-encrypted-state-events")]
1159 pub async fn encrypt_state_event_raw(
1160 &self,
1161 room_id: &RoomId,
1162 event_type: &str,
1163 state_key: &str,
1164 content: &Raw<AnyStateEventContent>,
1165 ) -> MegolmResult<Raw<RoomEncryptedEventContent>> {
1166 self.inner
1167 .group_session_manager
1168 .encrypt_state(room_id, event_type, state_key, content)
1169 .await
1170 }
1171
1172 pub async fn discard_room_key(&self, room_id: &RoomId) -> StoreResult<bool> {
1183 self.inner.group_session_manager.invalidate_group_session(room_id).await
1184 }
1185
1186 pub async fn share_room_key(
1206 &self,
1207 room_id: &RoomId,
1208 users: impl Iterator<Item = &UserId>,
1209 encryption_settings: impl Into<EncryptionSettings>,
1210 ) -> OlmResult<Vec<Arc<ToDeviceRequest>>> {
1211 self.inner.group_session_manager.share_room_key(room_id, users, encryption_settings).await
1212 }
1213
1214 #[cfg(feature = "experimental-send-custom-to-device")]
1228 pub async fn encrypt_content_for_devices(
1229 &self,
1230 devices: Vec<DeviceData>,
1231 event_type: &str,
1232 content: &Value,
1233 share_strategy: CollectStrategy,
1234 ) -> OlmResult<(Vec<ToDeviceRequest>, Vec<(DeviceData, WithheldCode)>)> {
1235 let mut changes = Changes::default();
1236
1237 let (allowed_devices, mut blocked_devices) =
1238 split_devices_for_share_strategy(&self.inner.store, devices, share_strategy).await?;
1239
1240 let result = self
1241 .inner
1242 .group_session_manager
1243 .encrypt_content_for_devices(allowed_devices, event_type, content.clone(), &mut changes)
1244 .await;
1245
1246 if !changes.is_empty() {
1248 let session_count = changes.sessions.len();
1249
1250 self.inner.store.save_changes(changes).await?;
1251
1252 trace!(
1253 session_count = session_count,
1254 "Stored the changed sessions after encrypting a custom to-device event"
1255 );
1256 }
1257
1258 result.map(|(to_device_requests, mut withheld)| {
1259 withheld.append(&mut blocked_devices);
1260 (to_device_requests, withheld)
1261 })
1262 }
1263 pub async fn share_room_key_bundle_data(
1268 &self,
1269 user_id: &UserId,
1270 collect_strategy: &CollectStrategy,
1271 bundle_data: RoomKeyBundleContent,
1272 ) -> OlmResult<Vec<ToDeviceRequest>> {
1273 self.inner
1274 .group_session_manager
1275 .share_room_key_bundle_data(user_id, collect_strategy, bundle_data)
1276 .await
1277 }
1278
1279 #[deprecated(note = "Use OlmMachine::receive_verification_event instead", since = "0.7.0")]
1287 pub async fn receive_unencrypted_verification_event(
1288 &self,
1289 event: &AnyMessageLikeEvent,
1290 ) -> StoreResult<()> {
1291 self.inner.verification_machine.receive_any_event(event).await
1292 }
1293
1294 pub async fn receive_verification_event(&self, event: &AnyMessageLikeEvent) -> StoreResult<()> {
1307 self.inner.verification_machine.receive_any_event(event).await
1308 }
1309
1310 #[instrument(
1316 skip_all,
1317 fields(
1318 sender_key = ?decrypted.result.sender_key,
1319 event_type = decrypted.result.event.event_type(),
1320 ),
1321 )]
1322 async fn handle_decrypted_to_device_event(
1323 &self,
1324 cache: &StoreCache,
1325 decrypted: &mut OlmDecryptionInfo,
1326 changes: &mut Changes,
1327 ) -> OlmResult<()> {
1328 debug!(
1329 sender_device_keys =
1330 ?decrypted.result.event.sender_device_keys().map(|k| (k.curve25519_key(), k.ed25519_key())).unwrap_or((None, None)),
1331 "Received a decrypted to-device event",
1332 );
1333
1334 match &*decrypted.result.event {
1335 AnyDecryptedOlmEvent::RoomKey(e) => {
1336 let session = self.add_room_key(decrypted.result.sender_key, e).await?;
1337 decrypted.inbound_group_session = session;
1338 }
1339 AnyDecryptedOlmEvent::ForwardedRoomKey(e) => {
1340 let session = self
1341 .inner
1342 .key_request_machine
1343 .receive_forwarded_room_key(decrypted.result.sender_key, e)
1344 .await?;
1345 decrypted.inbound_group_session = session;
1346 }
1347 AnyDecryptedOlmEvent::SecretSend(e) => {
1348 let name = self
1349 .inner
1350 .key_request_machine
1351 .receive_secret_event(cache, decrypted.result.sender_key, e, changes)
1352 .await?;
1353
1354 if let Ok(ToDeviceEvents::SecretSend(mut e)) =
1357 decrypted.result.raw_event.deserialize_as()
1358 {
1359 e.content.secret_name = name;
1360 decrypted.result.raw_event = Raw::from_json(to_raw_value(&e)?);
1361 }
1362 }
1363 AnyDecryptedOlmEvent::Dummy(_) => {
1364 debug!("Received an `m.dummy` event");
1365 }
1366 AnyDecryptedOlmEvent::RoomKeyBundle(e) => {
1367 debug!("Received a room key bundle event {:?}", e);
1368 self.receive_room_key_bundle_data(decrypted.result.sender_key, e, changes).await?;
1369 }
1370 AnyDecryptedOlmEvent::Custom(_) => {
1371 warn!("Received an unexpected encrypted to-device event");
1372 }
1373 }
1374
1375 Ok(())
1376 }
1377
1378 async fn handle_verification_event(&self, event: &ToDeviceEvents) {
1379 if let Err(e) = self.inner.verification_machine.receive_any_event(event).await {
1380 error!("Error handling a verification event: {e:?}");
1381 }
1382 }
1383
1384 async fn mark_to_device_request_as_sent(&self, request_id: &TransactionId) -> StoreResult<()> {
1386 self.inner.verification_machine.mark_request_as_sent(request_id);
1387 self.inner.key_request_machine.mark_outgoing_request_as_sent(request_id).await?;
1388 self.inner.group_session_manager.mark_request_as_sent(request_id).await?;
1389 self.inner.session_manager.mark_outgoing_request_as_sent(request_id);
1390 Ok(())
1391 }
1392
1393 pub fn get_verification(&self, user_id: &UserId, flow_id: &str) -> Option<Verification> {
1395 self.inner.verification_machine.get_verification(user_id, flow_id)
1396 }
1397
1398 pub fn get_verification_request(
1400 &self,
1401 user_id: &UserId,
1402 flow_id: impl AsRef<str>,
1403 ) -> Option<VerificationRequest> {
1404 self.inner.verification_machine.get_request(user_id, flow_id)
1405 }
1406
1407 pub fn get_verification_requests(&self, user_id: &UserId) -> Vec<VerificationRequest> {
1409 self.inner.verification_machine.get_requests(user_id)
1410 }
1411
1412 async fn handle_to_device_event(&self, changes: &mut Changes, event: &ToDeviceEvents) {
1417 use crate::types::events::ToDeviceEvents::*;
1418
1419 match event {
1420 RoomKeyRequest(e) => self.inner.key_request_machine.receive_incoming_key_request(e),
1426 SecretRequest(e) => self.inner.key_request_machine.receive_incoming_secret_request(e),
1427 RoomKeyWithheld(e) => self.add_withheld_info(changes, e),
1428 KeyVerificationAccept(..)
1429 | KeyVerificationCancel(..)
1430 | KeyVerificationKey(..)
1431 | KeyVerificationMac(..)
1432 | KeyVerificationRequest(..)
1433 | KeyVerificationReady(..)
1434 | KeyVerificationDone(..)
1435 | KeyVerificationStart(..) => {
1436 self.handle_verification_event(event).await;
1437 }
1438
1439 Custom(_) | Dummy(_) => {}
1441
1442 RoomEncrypted(_) => {}
1444
1445 SecretSend(_) | RoomKey(_) | ForwardedRoomKey(_) => {}
1448 }
1449 }
1450
1451 fn record_message_id(event: &Raw<AnyToDeviceEvent>) {
1452 use serde::Deserialize;
1453
1454 #[derive(Deserialize)]
1455 struct ContentStub<'a> {
1456 #[serde(borrow, rename = "org.matrix.msgid")]
1457 message_id: Option<&'a str>,
1458 }
1459 #[derive(Deserialize)]
1460 struct ToDeviceStub<'a> {
1461 sender: &'a str,
1462 #[serde(rename = "type")]
1463 event_type: &'a str,
1464 #[serde(borrow)]
1465 content: ContentStub<'a>,
1466 }
1467
1468 if let Ok(event) = event.deserialize_as_unchecked::<ToDeviceStub<'_>>() {
1469 Span::current().record("sender", event.sender);
1470 Span::current().record("event_type", event.event_type);
1471 Span::current().record("message_id", event.content.message_id);
1472 }
1473 }
1474
1475 #[instrument(skip_all, fields(sender, event_type, message_id))]
1483 async fn receive_to_device_event(
1484 &self,
1485 transaction: &mut StoreTransaction,
1486 changes: &mut Changes,
1487 raw_event: Raw<AnyToDeviceEvent>,
1488 decryption_settings: &DecryptionSettings,
1489 ) -> Option<ProcessedToDeviceEvent> {
1490 Self::record_message_id(&raw_event);
1491
1492 let event: ToDeviceEvents = match raw_event.deserialize_as() {
1493 Ok(e) => e,
1494 Err(e) => {
1495 warn!("Received an invalid to-device event: {e}");
1497 return Some(ProcessedToDeviceEvent::Invalid(raw_event));
1498 }
1499 };
1500
1501 debug!("Received a to-device event");
1502
1503 match event {
1504 ToDeviceEvents::RoomEncrypted(e) => {
1505 self.receive_encrypted_to_device_event(
1506 transaction,
1507 changes,
1508 raw_event,
1509 e,
1510 decryption_settings,
1511 )
1512 .await
1513 }
1514 e => {
1515 self.handle_to_device_event(changes, &e).await;
1516 Some(ProcessedToDeviceEvent::PlainText(raw_event))
1517 }
1518 }
1519 }
1520
1521 async fn receive_encrypted_to_device_event(
1535 &self,
1536 transaction: &mut StoreTransaction,
1537 changes: &mut Changes,
1538 mut raw_event: Raw<AnyToDeviceEvent>,
1539 e: ToDeviceEvent<ToDeviceEncryptedEventContent>,
1540 decryption_settings: &DecryptionSettings,
1541 ) -> Option<ProcessedToDeviceEvent> {
1542 let decrypted = match self
1543 .decrypt_to_device_event(transaction, &e, changes, decryption_settings)
1544 .await
1545 {
1546 Ok(decrypted) => decrypted,
1547 Err(DecryptToDeviceError::OlmError(err)) => {
1548 let reason = if let OlmError::UnverifiedSenderDevice = &err {
1549 ToDeviceUnableToDecryptReason::UnverifiedSenderDevice
1550 } else {
1551 ToDeviceUnableToDecryptReason::DecryptionFailure
1552 };
1553
1554 if let OlmError::SessionWedged(sender, curve_key) = err {
1555 if let Err(e) =
1556 self.inner.session_manager.mark_device_as_wedged(&sender, curve_key).await
1557 {
1558 error!(
1559 error = ?e,
1560 "Couldn't mark device to be unwedged",
1561 );
1562 }
1563 }
1564
1565 return Some(ProcessedToDeviceEvent::UnableToDecrypt {
1566 encrypted_event: raw_event,
1567 utd_info: ToDeviceUnableToDecryptInfo { reason },
1568 });
1569 }
1570 Err(DecryptToDeviceError::FromDehydratedDevice) => return None,
1571 };
1572
1573 match decrypted.session {
1576 SessionType::New(s) | SessionType::Existing(s) => {
1577 changes.sessions.push(s);
1578 }
1579 }
1580
1581 changes.message_hashes.push(decrypted.message_hash);
1582
1583 if let Some(group_session) = decrypted.inbound_group_session {
1584 changes.inbound_group_sessions.push(group_session);
1585 }
1586
1587 match decrypted.result.raw_event.deserialize_as() {
1588 Ok(event) => {
1589 self.handle_to_device_event(changes, &event).await;
1590
1591 raw_event = event
1592 .serialize_zeroized()
1593 .expect("Zeroizing and reserializing our events should always work")
1594 .cast();
1595 }
1596 Err(e) => {
1597 warn!("Received an invalid encrypted to-device event: {e}");
1598 raw_event = decrypted.result.raw_event;
1599 }
1600 }
1601
1602 Some(ProcessedToDeviceEvent::Decrypted {
1603 raw: raw_event,
1604 encryption_info: decrypted.result.encryption_info,
1605 })
1606 }
1607
1608 async fn check_to_device_event_is_not_from_dehydrated_device(
1611 &self,
1612 decrypted: &OlmDecryptionInfo,
1613 sender_user_id: &UserId,
1614 ) -> Result<(), DecryptToDeviceError> {
1615 if self.to_device_event_is_from_dehydrated_device(decrypted, sender_user_id).await? {
1616 warn!(
1617 sender = ?sender_user_id,
1618 session = ?decrypted.session,
1619 "Received a to-device event from a dehydrated device. This is unexpected: ignoring event"
1620 );
1621 Err(DecryptToDeviceError::FromDehydratedDevice)
1622 } else {
1623 Ok(())
1624 }
1625 }
1626
1627 async fn to_device_event_is_from_dehydrated_device(
1633 &self,
1634 decrypted: &OlmDecryptionInfo,
1635 sender_user_id: &UserId,
1636 ) -> OlmResult<bool> {
1637 if let Some(device_keys) = decrypted.result.event.sender_device_keys() {
1639 if device_keys.dehydrated.unwrap_or(false) {
1645 return Ok(true);
1646 }
1647 }
1652
1653 Ok(self
1655 .store()
1656 .get_device_from_curve_key(sender_user_id, decrypted.result.sender_key)
1657 .await?
1658 .is_some_and(|d| d.is_dehydrated()))
1659 }
1660
1661 #[instrument(skip_all)]
1679 pub async fn receive_sync_changes(
1680 &self,
1681 sync_changes: EncryptionSyncChanges<'_>,
1682 decryption_settings: &DecryptionSettings,
1683 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Vec<RoomKeyInfo>)> {
1684 let mut store_transaction = self.inner.store.transaction().await;
1685
1686 let (events, changes) = self
1687 .preprocess_sync_changes(&mut store_transaction, sync_changes, decryption_settings)
1688 .await?;
1689
1690 let room_key_updates: Vec<_> =
1693 changes.inbound_group_sessions.iter().map(RoomKeyInfo::from).collect();
1694
1695 self.store().save_changes(changes).await?;
1696 store_transaction.commit().await?;
1697
1698 Ok((events, room_key_updates))
1699 }
1700
1701 pub(crate) async fn preprocess_sync_changes(
1719 &self,
1720 transaction: &mut StoreTransaction,
1721 sync_changes: EncryptionSyncChanges<'_>,
1722 decryption_settings: &DecryptionSettings,
1723 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Changes)> {
1724 let mut events: Vec<ProcessedToDeviceEvent> = self
1726 .inner
1727 .verification_machine
1728 .garbage_collect()
1729 .iter()
1730 .map(|e| ProcessedToDeviceEvent::PlainText(e.clone()))
1734 .collect();
1735 let mut changes = Default::default();
1738
1739 {
1740 let account = transaction.account().await?;
1741 account.update_key_counts(
1742 sync_changes.one_time_keys_counts,
1743 sync_changes.unused_fallback_keys,
1744 )
1745 }
1746
1747 if let Err(e) = self
1748 .inner
1749 .identity_manager
1750 .receive_device_changes(
1751 transaction.cache(),
1752 sync_changes.changed_devices.changed.iter().map(|u| u.as_ref()),
1753 )
1754 .await
1755 {
1756 error!(error = ?e, "Error marking a tracked user as changed");
1757 }
1758
1759 for raw_event in sync_changes.to_device_events {
1760 let processed_event = Box::pin(self.receive_to_device_event(
1761 transaction,
1762 &mut changes,
1763 raw_event,
1764 decryption_settings,
1765 ))
1766 .await;
1767
1768 if let Some(processed_event) = processed_event {
1769 events.push(processed_event);
1770 }
1771 }
1772
1773 let changed_sessions = self
1774 .inner
1775 .key_request_machine
1776 .collect_incoming_key_requests(transaction.cache())
1777 .await?;
1778
1779 changes.sessions.extend(changed_sessions);
1780 changes.next_batch_token = sync_changes.next_batch_token;
1781
1782 Ok((events, changes))
1783 }
1784
1785 pub async fn request_room_key(
1802 &self,
1803 event: &Raw<EncryptedEvent>,
1804 room_id: &RoomId,
1805 ) -> MegolmResult<(Option<OutgoingRequest>, OutgoingRequest)> {
1806 let event = event.deserialize()?;
1807 self.inner.key_request_machine.request_key(room_id, &event).await
1808 }
1809
1810 async fn get_room_event_verification_state(
1823 &self,
1824 session: &InboundGroupSession,
1825 sender: &UserId,
1826 ) -> MegolmResult<(VerificationState, Option<OwnedDeviceId>)> {
1827 let sender_data = self.get_or_update_sender_data(session, sender).await?;
1828
1829 let (verification_state, device_id) = match sender_data.user_id() {
1838 Some(i) if i != sender => {
1839 (VerificationState::Unverified(VerificationLevel::MismatchedSender), None)
1840 }
1841
1842 Some(_) | None => {
1843 sender_data_to_verification_state(sender_data, session.has_been_imported())
1844 }
1845 };
1846
1847 Ok((verification_state, device_id))
1848 }
1849
1850 async fn get_or_update_sender_data(
1865 &self,
1866 session: &InboundGroupSession,
1867 sender: &UserId,
1868 ) -> MegolmResult<SenderData> {
1869 let sender_data = if session.sender_data.should_recalculate() {
1870 let calculated_sender_data = SenderDataFinder::find_using_curve_key(
1889 self.store(),
1890 session.sender_key(),
1891 sender,
1892 session,
1893 )
1894 .await?;
1895
1896 if calculated_sender_data.compare_trust_level(&session.sender_data).is_gt() {
1898 let mut new_session = session.clone();
1900 new_session.sender_data = calculated_sender_data.clone();
1901 self.store().save_inbound_group_sessions(&[new_session]).await?;
1902
1903 calculated_sender_data
1905 } else {
1906 session.sender_data.clone()
1908 }
1909 } else {
1910 session.sender_data.clone()
1911 };
1912
1913 Ok(sender_data)
1914 }
1915
1916 pub async fn query_missing_secrets_from_other_sessions(&self) -> StoreResult<bool> {
1941 let identity = self.inner.user_identity.lock().await;
1942 let mut secrets = identity.get_missing_secrets().await;
1943
1944 if self.store().load_backup_keys().await?.decryption_key.is_none() {
1945 secrets.push(SecretName::RecoveryKey);
1946 }
1947
1948 if secrets.is_empty() {
1949 debug!("No missing requests to query");
1950 return Ok(false);
1951 }
1952
1953 let secret_requests = GossipMachine::request_missing_secrets(self.user_id(), secrets);
1954
1955 let unsent_request = self.store().get_unsent_secret_requests().await?;
1957 let not_yet_requested = secret_requests
1958 .into_iter()
1959 .filter(|request| !unsent_request.iter().any(|unsent| unsent.info == request.info))
1960 .collect_vec();
1961
1962 if not_yet_requested.is_empty() {
1963 debug!("The missing secrets have already been requested");
1964 Ok(false)
1965 } else {
1966 debug!("Requesting missing secrets");
1967
1968 let changes = Changes { key_requests: not_yet_requested, ..Default::default() };
1969
1970 self.store().save_changes(changes).await?;
1971 Ok(true)
1972 }
1973 }
1974
1975 async fn get_encryption_info(
1981 &self,
1982 session: &InboundGroupSession,
1983 sender: &UserId,
1984 ) -> MegolmResult<Arc<EncryptionInfo>> {
1985 let (verification_state, device_id) =
1986 self.get_room_event_verification_state(session, sender).await?;
1987
1988 let sender = sender.to_owned();
1989
1990 Ok(Arc::new(EncryptionInfo {
1991 sender,
1992 sender_device: device_id,
1993 algorithm_info: AlgorithmInfo::MegolmV1AesSha2 {
1994 curve25519_key: session.sender_key().to_base64(),
1995 sender_claimed_keys: session
1996 .signing_keys()
1997 .iter()
1998 .map(|(k, v)| (k.to_owned(), v.to_base64()))
1999 .collect(),
2000 session_id: Some(session.session_id().to_owned()),
2001 },
2002 verification_state,
2003 }))
2004 }
2005
2006 async fn decrypt_megolm_events(
2007 &self,
2008 room_id: &RoomId,
2009 event: &EncryptedEvent,
2010 content: &SupportedEventEncryptionSchemes<'_>,
2011 decryption_settings: &DecryptionSettings,
2012 ) -> MegolmResult<(JsonObject, Arc<EncryptionInfo>)> {
2013 let session =
2014 self.get_inbound_group_session_or_error(room_id, content.session_id()).await?;
2015
2016 Span::current().record("sender_key", debug(session.sender_key()));
2022
2023 let result = session.decrypt(event).await;
2024 match result {
2025 Ok((decrypted_event, _)) => {
2026 let encryption_info = self.get_encryption_info(&session, &event.sender).await?;
2027
2028 self.check_sender_trust_requirement(
2029 &session,
2030 &encryption_info,
2031 &decryption_settings.sender_device_trust_requirement,
2032 )?;
2033
2034 Ok((decrypted_event, encryption_info))
2035 }
2036 Err(error) => Err(
2037 if let MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) = error {
2038 let withheld_code = self
2039 .inner
2040 .store
2041 .get_withheld_info(room_id, content.session_id())
2042 .await?
2043 .map(|e| e.content.withheld_code());
2044
2045 if withheld_code.is_some() {
2046 MegolmError::MissingRoomKey(withheld_code)
2048 } else {
2049 error
2050 }
2051 } else {
2052 error
2053 },
2054 ),
2055 }
2056 }
2057
2058 fn check_sender_trust_requirement(
2064 &self,
2065 session: &InboundGroupSession,
2066 encryption_info: &EncryptionInfo,
2067 trust_requirement: &TrustRequirement,
2068 ) -> MegolmResult<()> {
2069 trace!(
2070 verification_state = ?encryption_info.verification_state,
2071 ?trust_requirement, "check_sender_trust_requirement",
2072 );
2073
2074 let verification_level = match &encryption_info.verification_state {
2077 VerificationState::Verified => return Ok(()),
2078 VerificationState::Unverified(verification_level) => verification_level,
2079 };
2080
2081 let ok = match trust_requirement {
2082 TrustRequirement::Untrusted => true,
2083
2084 TrustRequirement::CrossSignedOrLegacy => {
2085 let legacy_session = match session.sender_data {
2091 SenderData::DeviceInfo { legacy_session, .. } => legacy_session,
2092 SenderData::UnknownDevice { legacy_session, .. } => legacy_session,
2093 _ => false,
2094 };
2095
2096 match (verification_level, legacy_session) {
2106 (VerificationLevel::UnverifiedIdentity, _) => true,
2108
2109 (VerificationLevel::UnsignedDevice, true) => true,
2111
2112 (VerificationLevel::None(_), true) => true,
2114
2115 (VerificationLevel::VerificationViolation, _)
2117 | (VerificationLevel::MismatchedSender, _)
2118 | (VerificationLevel::UnsignedDevice, false)
2119 | (VerificationLevel::None(_), false) => false,
2120 }
2121 }
2122
2123 TrustRequirement::CrossSigned => match verification_level {
2126 VerificationLevel::UnverifiedIdentity => true,
2127
2128 VerificationLevel::VerificationViolation
2129 | VerificationLevel::MismatchedSender
2130 | VerificationLevel::UnsignedDevice
2131 | VerificationLevel::None(_) => false,
2132 },
2133 };
2134
2135 if ok {
2136 Ok(())
2137 } else {
2138 Err(MegolmError::SenderIdentityNotTrusted(verification_level.clone()))
2139 }
2140 }
2141
2142 async fn get_inbound_group_session_or_error(
2147 &self,
2148 room_id: &RoomId,
2149 session_id: &str,
2150 ) -> MegolmResult<InboundGroupSession> {
2151 match self.store().get_inbound_group_session(room_id, session_id).await? {
2152 Some(session) => Ok(session),
2153 None => {
2154 let withheld_code = self
2155 .inner
2156 .store
2157 .get_withheld_info(room_id, session_id)
2158 .await?
2159 .map(|e| e.content.withheld_code());
2160 Err(MegolmError::MissingRoomKey(withheld_code))
2161 }
2162 }
2163 }
2164
2165 pub async fn try_decrypt_room_event(
2180 &self,
2181 raw_event: &Raw<EncryptedEvent>,
2182 room_id: &RoomId,
2183 decryption_settings: &DecryptionSettings,
2184 ) -> Result<RoomEventDecryptionResult, CryptoStoreError> {
2185 match self.decrypt_room_event_inner(raw_event, room_id, true, decryption_settings).await {
2186 Ok(decrypted) => Ok(RoomEventDecryptionResult::Decrypted(decrypted)),
2187 Err(err) => Ok(RoomEventDecryptionResult::UnableToDecrypt(megolm_error_to_utd_info(
2188 raw_event, err,
2189 )?)),
2190 }
2191 }
2192
2193 pub async fn decrypt_room_event(
2201 &self,
2202 event: &Raw<EncryptedEvent>,
2203 room_id: &RoomId,
2204 decryption_settings: &DecryptionSettings,
2205 ) -> MegolmResult<DecryptedRoomEvent> {
2206 self.decrypt_room_event_inner(event, room_id, true, decryption_settings).await
2207 }
2208
2209 #[instrument(name = "decrypt_room_event", skip_all, fields(?room_id, event_id, origin_server_ts, sender, algorithm, session_id, message_index, sender_key))]
2210 async fn decrypt_room_event_inner(
2211 &self,
2212 event: &Raw<EncryptedEvent>,
2213 room_id: &RoomId,
2214 decrypt_unsigned: bool,
2215 decryption_settings: &DecryptionSettings,
2216 ) -> MegolmResult<DecryptedRoomEvent> {
2217 let _timer = timer!(tracing::Level::TRACE, "_method");
2218
2219 let event = event.deserialize()?;
2220
2221 Span::current()
2222 .record("sender", debug(&event.sender))
2223 .record("event_id", debug(&event.event_id))
2224 .record(
2225 "origin_server_ts",
2226 timestamp_to_iso8601(event.origin_server_ts)
2227 .unwrap_or_else(|| "<out of range>".to_owned()),
2228 )
2229 .record("algorithm", debug(event.content.algorithm()));
2230
2231 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2232 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2233 Span::current().record("sender_key", debug(c.sender_key));
2234 c.into()
2235 }
2236 #[cfg(feature = "experimental-algorithms")]
2237 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2238 RoomEventEncryptionScheme::Unknown(_) => {
2239 warn!("Received an encrypted room event with an unsupported algorithm");
2240 return Err(EventError::UnsupportedAlgorithm.into());
2241 }
2242 };
2243
2244 Span::current().record("session_id", content.session_id());
2245 Span::current().record("message_index", content.message_index());
2246
2247 let result =
2248 self.decrypt_megolm_events(room_id, &event, &content, decryption_settings).await;
2249
2250 if let Err(e) = &result {
2251 #[cfg(feature = "automatic-room-key-forwarding")]
2252 match e {
2253 MegolmError::MissingRoomKey(_)
2256 | MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
2257 self.inner
2258 .key_request_machine
2259 .create_outgoing_key_request(room_id, &event)
2260 .await?;
2261 }
2262 _ => {}
2263 }
2264
2265 warn!("Failed to decrypt a room event: {e}");
2266 }
2267
2268 let (mut decrypted_event, encryption_info) = result?;
2269
2270 let mut unsigned_encryption_info = None;
2271 if decrypt_unsigned {
2272 unsigned_encryption_info = self
2274 .decrypt_unsigned_events(&mut decrypted_event, room_id, decryption_settings)
2275 .await;
2276 }
2277
2278 let decrypted_event =
2279 serde_json::from_value::<Raw<AnyTimelineEvent>>(decrypted_event.into())?;
2280
2281 #[cfg(feature = "experimental-encrypted-state-events")]
2282 self.verify_packed_state_key(&event, &decrypted_event)?;
2283
2284 Ok(DecryptedRoomEvent { event: decrypted_event, encryption_info, unsigned_encryption_info })
2285 }
2286
2287 #[cfg(feature = "experimental-encrypted-state-events")]
2304 fn verify_packed_state_key(
2305 &self,
2306 original: &EncryptedEvent,
2307 decrypted: &Raw<AnyTimelineEvent>,
2308 ) -> MegolmResult<()> {
2309 use serde::Deserialize;
2310
2311 #[derive(Deserialize)]
2313 struct PayloadDeserializationHelper {
2314 state_key: Option<String>,
2315 #[serde(rename = "type")]
2316 event_type: String,
2317 }
2318
2319 let PayloadDeserializationHelper {
2321 state_key: inner_state_key,
2322 event_type: inner_event_type,
2323 } = decrypted
2324 .deserialize_as_unchecked()
2325 .map_err(|_| MegolmError::StateKeyVerificationFailed)?;
2326
2327 let (raw_state_key, inner_state_key) = match (&original.state_key, &inner_state_key) {
2329 (Some(raw_state_key), Some(inner_state_key)) => (raw_state_key, inner_state_key),
2330 (None, None) => return Ok(()),
2331 _ => return Err(MegolmError::StateKeyVerificationFailed),
2332 };
2333
2334 let (outer_event_type, outer_state_key) =
2336 raw_state_key.split_once(":").ok_or(MegolmError::StateKeyVerificationFailed)?;
2337
2338 if outer_event_type != inner_event_type {
2340 return Err(MegolmError::StateKeyVerificationFailed);
2341 }
2342
2343 if outer_state_key != inner_state_key {
2345 return Err(MegolmError::StateKeyVerificationFailed);
2346 }
2347 Ok(())
2348 }
2349
2350 async fn decrypt_unsigned_events(
2360 &self,
2361 main_event: &mut JsonObject,
2362 room_id: &RoomId,
2363 decryption_settings: &DecryptionSettings,
2364 ) -> Option<BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>> {
2365 let unsigned = main_event.get_mut("unsigned")?.as_object_mut()?;
2366 let mut unsigned_encryption_info: Option<
2367 BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>,
2368 > = None;
2369
2370 let location = UnsignedEventLocation::RelationsReplace;
2372 let replace = location.find_mut(unsigned);
2373 if let Some(decryption_result) =
2374 self.decrypt_unsigned_event(replace, room_id, decryption_settings).await
2375 {
2376 unsigned_encryption_info
2377 .get_or_insert_with(Default::default)
2378 .insert(location, decryption_result);
2379 }
2380
2381 let location = UnsignedEventLocation::RelationsThreadLatestEvent;
2384 let thread_latest_event = location.find_mut(unsigned);
2385 if let Some(decryption_result) =
2386 self.decrypt_unsigned_event(thread_latest_event, room_id, decryption_settings).await
2387 {
2388 unsigned_encryption_info
2389 .get_or_insert_with(Default::default)
2390 .insert(location, decryption_result);
2391 }
2392
2393 unsigned_encryption_info
2394 }
2395
2396 fn decrypt_unsigned_event<'a>(
2404 &'a self,
2405 event: Option<&'a mut Value>,
2406 room_id: &'a RoomId,
2407 decryption_settings: &'a DecryptionSettings,
2408 ) -> BoxFuture<'a, Option<UnsignedDecryptionResult>> {
2409 Box::pin(async move {
2410 let event = event?;
2411
2412 let is_encrypted = event
2413 .get("type")
2414 .and_then(|type_| type_.as_str())
2415 .is_some_and(|s| s == "m.room.encrypted");
2416 if !is_encrypted {
2417 return None;
2418 }
2419
2420 let raw_event = serde_json::from_value(event.clone()).ok()?;
2421 match self
2422 .decrypt_room_event_inner(&raw_event, room_id, false, decryption_settings)
2423 .await
2424 {
2425 Ok(decrypted_event) => {
2426 *event = serde_json::to_value(decrypted_event.event).ok()?;
2428 Some(UnsignedDecryptionResult::Decrypted(decrypted_event.encryption_info))
2429 }
2430 Err(err) => {
2431 let utd_info = megolm_error_to_utd_info(&raw_event, err).ok()?;
2436 Some(UnsignedDecryptionResult::UnableToDecrypt(utd_info))
2437 }
2438 }
2439 })
2440 }
2441
2442 pub async fn is_room_key_available(
2449 &self,
2450 event: &Raw<EncryptedEvent>,
2451 room_id: &RoomId,
2452 ) -> Result<bool, CryptoStoreError> {
2453 let event = event.deserialize()?;
2454
2455 let (session_id, message_index) = match &event.content.scheme {
2456 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2457 (&c.session_id, c.ciphertext.message_index())
2458 }
2459 #[cfg(feature = "experimental-algorithms")]
2460 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => {
2461 (&c.session_id, c.ciphertext.message_index())
2462 }
2463 RoomEventEncryptionScheme::Unknown(_) => {
2464 return Ok(false);
2466 }
2467 };
2468
2469 Ok(self
2472 .store()
2473 .get_inbound_group_session(room_id, session_id)
2474 .await?
2475 .filter(|s| s.first_known_index() <= message_index)
2476 .is_some())
2477 }
2478
2479 #[instrument(skip(self, event), fields(event_id, sender, session_id))]
2492 pub async fn get_room_event_encryption_info(
2493 &self,
2494 event: &Raw<EncryptedEvent>,
2495 room_id: &RoomId,
2496 ) -> MegolmResult<Arc<EncryptionInfo>> {
2497 let event = event.deserialize()?;
2498
2499 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2500 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => c.into(),
2501 #[cfg(feature = "experimental-algorithms")]
2502 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2503 RoomEventEncryptionScheme::Unknown(_) => {
2504 return Err(EventError::UnsupportedAlgorithm.into());
2505 }
2506 };
2507
2508 Span::current()
2509 .record("sender", debug(&event.sender))
2510 .record("event_id", debug(&event.event_id))
2511 .record("session_id", content.session_id());
2512
2513 self.get_session_encryption_info(room_id, content.session_id(), &event.sender).await
2514 }
2515
2516 pub async fn get_session_encryption_info(
2531 &self,
2532 room_id: &RoomId,
2533 session_id: &str,
2534 sender: &UserId,
2535 ) -> MegolmResult<Arc<EncryptionInfo>> {
2536 let session = self.get_inbound_group_session_or_error(room_id, session_id).await?;
2537 self.get_encryption_info(&session, sender).await
2538 }
2539
2540 pub async fn update_tracked_users(
2558 &self,
2559 users: impl IntoIterator<Item = &UserId>,
2560 ) -> StoreResult<()> {
2561 self.inner.identity_manager.update_tracked_users(users).await
2562 }
2563
2564 pub async fn mark_all_tracked_users_as_dirty(&self) -> StoreResult<()> {
2569 self.inner
2570 .identity_manager
2571 .mark_all_tracked_users_as_dirty(self.inner.store.cache().await?)
2572 .await
2573 }
2574
2575 async fn wait_if_user_pending(
2576 &self,
2577 user_id: &UserId,
2578 timeout: Option<Duration>,
2579 ) -> StoreResult<()> {
2580 if let Some(timeout) = timeout {
2581 let cache = self.store().cache().await?;
2582 self.inner
2583 .identity_manager
2584 .key_query_manager
2585 .wait_if_user_key_query_pending(cache, timeout, user_id)
2586 .await?;
2587 }
2588 Ok(())
2589 }
2590
2591 #[instrument(skip(self))]
2621 pub async fn get_device(
2622 &self,
2623 user_id: &UserId,
2624 device_id: &DeviceId,
2625 timeout: Option<Duration>,
2626 ) -> StoreResult<Option<Device>> {
2627 self.wait_if_user_pending(user_id, timeout).await?;
2628 self.store().get_device(user_id, device_id).await
2629 }
2630
2631 #[instrument(skip(self))]
2645 pub async fn get_identity(
2646 &self,
2647 user_id: &UserId,
2648 timeout: Option<Duration>,
2649 ) -> StoreResult<Option<UserIdentity>> {
2650 self.wait_if_user_pending(user_id, timeout).await?;
2651 self.store().get_identity(user_id).await
2652 }
2653
2654 #[instrument(skip(self))]
2681 pub async fn get_user_devices(
2682 &self,
2683 user_id: &UserId,
2684 timeout: Option<Duration>,
2685 ) -> StoreResult<UserDevices> {
2686 self.wait_if_user_pending(user_id, timeout).await?;
2687 self.store().get_user_devices(user_id).await
2688 }
2689
2690 pub async fn cross_signing_status(&self) -> CrossSigningStatus {
2695 self.inner.user_identity.lock().await.status().await
2696 }
2697
2698 pub async fn export_cross_signing_keys(&self) -> StoreResult<Option<CrossSigningKeyExport>> {
2706 let master_key = self.store().export_secret(&SecretName::CrossSigningMasterKey).await?;
2707 let self_signing_key =
2708 self.store().export_secret(&SecretName::CrossSigningSelfSigningKey).await?;
2709 let user_signing_key =
2710 self.store().export_secret(&SecretName::CrossSigningUserSigningKey).await?;
2711
2712 Ok(if master_key.is_none() && self_signing_key.is_none() && user_signing_key.is_none() {
2713 None
2714 } else {
2715 Some(CrossSigningKeyExport { master_key, self_signing_key, user_signing_key })
2716 })
2717 }
2718
2719 pub async fn import_cross_signing_keys(
2724 &self,
2725 export: CrossSigningKeyExport,
2726 ) -> Result<CrossSigningStatus, SecretImportError> {
2727 self.store().import_cross_signing_keys(export).await
2728 }
2729
2730 async fn sign_with_master_key(
2731 &self,
2732 message: &str,
2733 ) -> Result<(OwnedDeviceKeyId, Ed25519Signature), SignatureError> {
2734 let identity = &*self.inner.user_identity.lock().await;
2735 let key_id = identity.master_key_id().await.ok_or(SignatureError::MissingSigningKey)?;
2736
2737 let signature = identity.sign(message).await?;
2738
2739 Ok((key_id, signature))
2740 }
2741
2742 pub async fn sign(&self, message: &str) -> Result<Signatures, CryptoStoreError> {
2748 let mut signatures = Signatures::new();
2749
2750 {
2751 let cache = self.inner.store.cache().await?;
2752 let account = cache.account().await?;
2753 let key_id = account.signing_key_id();
2754 let signature = account.sign(message);
2755 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
2756 }
2757
2758 match self.sign_with_master_key(message).await {
2759 Ok((key_id, signature)) => {
2760 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
2761 }
2762 Err(e) => {
2763 warn!(error = ?e, "Couldn't sign the message using the cross signing master key")
2764 }
2765 }
2766
2767 Ok(signatures)
2768 }
2769
2770 pub fn backup_machine(&self) -> &BackupMachine {
2775 &self.inner.backup_machine
2776 }
2777
2778 pub async fn initialize_crypto_store_generation(
2782 &self,
2783 generation: &Mutex<Option<u64>>,
2784 ) -> StoreResult<()> {
2785 let mut gen_guard = generation.lock().await;
2788
2789 let prev_generation =
2790 self.inner.store.get_custom_value(Self::CURRENT_GENERATION_STORE_KEY).await?;
2791
2792 let gen = match prev_generation {
2793 Some(val) => {
2794 u64::from_le_bytes(val.try_into().map_err(|_| {
2797 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
2798 })?)
2799 .wrapping_add(1)
2800 }
2801 None => 0,
2802 };
2803
2804 tracing::debug!("Initialising crypto store generation at {}", gen);
2805
2806 self.inner
2807 .store
2808 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, gen.to_le_bytes().to_vec())
2809 .await?;
2810
2811 *gen_guard = Some(gen);
2812
2813 Ok(())
2814 }
2815
2816 pub async fn maintain_crypto_store_generation(
2841 &'_ self,
2842 generation: &Mutex<Option<u64>>,
2843 ) -> StoreResult<(bool, u64)> {
2844 let mut gen_guard = generation.lock().await;
2845
2846 let actual_gen = self
2852 .inner
2853 .store
2854 .get_custom_value(Self::CURRENT_GENERATION_STORE_KEY)
2855 .await?
2856 .ok_or_else(|| {
2857 CryptoStoreError::InvalidLockGeneration("counter missing in store".to_owned())
2858 })?;
2859
2860 let actual_gen =
2861 u64::from_le_bytes(actual_gen.try_into().map_err(|_| {
2862 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
2863 })?);
2864
2865 let new_gen = match gen_guard.as_ref() {
2866 Some(expected_gen) => {
2867 if actual_gen == *expected_gen {
2868 return Ok((false, actual_gen));
2869 }
2870 actual_gen.max(*expected_gen).wrapping_add(1)
2872 }
2873 None => {
2874 actual_gen.wrapping_add(1)
2877 }
2878 };
2879
2880 tracing::debug!(
2881 "Crypto store generation mismatch: previously known was {:?}, actual is {:?}, next is {}",
2882 *gen_guard,
2883 actual_gen,
2884 new_gen
2885 );
2886
2887 *gen_guard = Some(new_gen);
2889
2890 self.inner
2892 .store
2893 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, new_gen.to_le_bytes().to_vec())
2894 .await?;
2895
2896 Ok((true, new_gen))
2897 }
2898
2899 pub fn dehydrated_devices(&self) -> DehydratedDevices {
2901 DehydratedDevices { inner: self.to_owned() }
2902 }
2903
2904 pub async fn room_settings(&self, room_id: &RoomId) -> StoreResult<Option<RoomSettings>> {
2909 self.inner.store.get_room_settings(room_id).await
2912 }
2913
2914 pub async fn set_room_settings(
2925 &self,
2926 room_id: &RoomId,
2927 new_settings: &RoomSettings,
2928 ) -> Result<(), SetRoomSettingsError> {
2929 let store = &self.inner.store;
2930
2931 let _store_transaction = store.transaction().await;
2936
2937 let old_settings = store.get_room_settings(room_id).await?;
2938
2939 if let Some(old_settings) = old_settings {
2952 if old_settings != *new_settings {
2953 return Err(SetRoomSettingsError::EncryptionDowngrade);
2954 } else {
2955 return Ok(());
2957 }
2958 }
2959
2960 match new_settings.algorithm {
2962 EventEncryptionAlgorithm::MegolmV1AesSha2 => (),
2963
2964 #[cfg(feature = "experimental-algorithms")]
2965 EventEncryptionAlgorithm::MegolmV2AesSha2 => (),
2966
2967 _ => {
2968 warn!(
2969 ?room_id,
2970 "Rejecting invalid encryption algorithm {}", new_settings.algorithm
2971 );
2972 return Err(SetRoomSettingsError::InvalidSettings);
2973 }
2974 }
2975
2976 store
2978 .save_changes(Changes {
2979 room_settings: HashMap::from([(room_id.to_owned(), new_settings.clone())]),
2980 ..Default::default()
2981 })
2982 .await?;
2983
2984 Ok(())
2985 }
2986
2987 #[cfg(any(feature = "testing", test))]
2991 pub fn same_as(&self, other: &OlmMachine) -> bool {
2992 Arc::ptr_eq(&self.inner, &other.inner)
2993 }
2994
2995 #[cfg(any(feature = "testing", test))]
2997 pub async fn uploaded_key_count(&self) -> Result<u64, CryptoStoreError> {
2998 let cache = self.inner.store.cache().await?;
2999 let account = cache.account().await?;
3000 Ok(account.uploaded_key_count())
3001 }
3002
3003 #[cfg(test)]
3005 pub(crate) fn identity_manager(&self) -> &IdentityManager {
3006 &self.inner.identity_manager
3007 }
3008
3009 #[cfg(test)]
3011 pub(crate) fn key_for_has_migrated_verification_latch() -> &'static str {
3012 Self::HAS_MIGRATED_VERIFICATION_LATCH
3013 }
3014}
3015
3016fn sender_data_to_verification_state(
3017 sender_data: SenderData,
3018 session_has_been_imported: bool,
3019) -> (VerificationState, Option<OwnedDeviceId>) {
3020 match sender_data {
3021 SenderData::UnknownDevice { owner_check_failed: false, .. } => {
3022 let device_link_problem = if session_has_been_imported {
3023 DeviceLinkProblem::InsecureSource
3024 } else {
3025 DeviceLinkProblem::MissingDevice
3026 };
3027
3028 (VerificationState::Unverified(VerificationLevel::None(device_link_problem)), None)
3029 }
3030 SenderData::UnknownDevice { owner_check_failed: true, .. } => (
3031 VerificationState::Unverified(VerificationLevel::None(
3032 DeviceLinkProblem::InsecureSource,
3033 )),
3034 None,
3035 ),
3036 SenderData::DeviceInfo { device_keys, .. } => (
3037 VerificationState::Unverified(VerificationLevel::UnsignedDevice),
3038 Some(device_keys.device_id),
3039 ),
3040 SenderData::VerificationViolation(KnownSenderData { device_id, .. }) => {
3041 (VerificationState::Unverified(VerificationLevel::VerificationViolation), device_id)
3042 }
3043 SenderData::SenderUnverified(KnownSenderData { device_id, .. }) => {
3044 (VerificationState::Unverified(VerificationLevel::UnverifiedIdentity), device_id)
3045 }
3046 SenderData::SenderVerified(KnownSenderData { device_id, .. }) => {
3047 (VerificationState::Verified, device_id)
3048 }
3049 }
3050}
3051
3052#[derive(Debug, Clone)]
3055pub struct CrossSigningBootstrapRequests {
3056 pub upload_keys_req: Option<OutgoingRequest>,
3063
3064 pub upload_signing_keys_req: UploadSigningKeysRequest,
3068
3069 pub upload_signatures_req: UploadSignaturesRequest,
3074}
3075
3076#[derive(Debug)]
3079pub struct EncryptionSyncChanges<'a> {
3080 pub to_device_events: Vec<Raw<AnyToDeviceEvent>>,
3082 pub changed_devices: &'a DeviceLists,
3085 pub one_time_keys_counts: &'a BTreeMap<OneTimeKeyAlgorithm, UInt>,
3087 pub unused_fallback_keys: Option<&'a [OneTimeKeyAlgorithm]>,
3089 pub next_batch_token: Option<String>,
3091}
3092
3093fn megolm_error_to_utd_info(
3101 raw_event: &Raw<EncryptedEvent>,
3102 error: MegolmError,
3103) -> Result<UnableToDecryptInfo, CryptoStoreError> {
3104 use MegolmError::*;
3105 let reason = match error {
3106 EventError(_) => UnableToDecryptReason::MalformedEncryptedEvent,
3107 Decode(_) => UnableToDecryptReason::MalformedEncryptedEvent,
3108 MissingRoomKey(maybe_withheld) => {
3109 UnableToDecryptReason::MissingMegolmSession { withheld_code: maybe_withheld }
3110 }
3111 Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
3112 UnableToDecryptReason::UnknownMegolmMessageIndex
3113 }
3114 Decryption(_) => UnableToDecryptReason::MegolmDecryptionFailure,
3115 JsonError(_) => UnableToDecryptReason::PayloadDeserializationFailure,
3116 MismatchedIdentityKeys(_) => UnableToDecryptReason::MismatchedIdentityKeys,
3117 SenderIdentityNotTrusted(level) => UnableToDecryptReason::SenderIdentityNotTrusted(level),
3118 #[cfg(feature = "experimental-encrypted-state-events")]
3119 StateKeyVerificationFailed => UnableToDecryptReason::StateKeyVerificationFailed,
3120
3121 Store(error) => Err(error)?,
3124 };
3125
3126 let session_id = raw_event.deserialize().ok().and_then(|ev| match ev.content.scheme {
3127 RoomEventEncryptionScheme::MegolmV1AesSha2(s) => Some(s.session_id),
3128 #[cfg(feature = "experimental-algorithms")]
3129 RoomEventEncryptionScheme::MegolmV2AesSha2(s) => Some(s.session_id),
3130 RoomEventEncryptionScheme::Unknown(_) => None,
3131 });
3132
3133 Ok(UnableToDecryptInfo { session_id, reason })
3134}
3135
3136#[derive(Debug, thiserror::Error)]
3146pub(crate) enum DecryptToDeviceError {
3147 #[error("An Olm error occurred meaning we failed to decrypt the event")]
3148 OlmError(#[from] OlmError),
3149
3150 #[error("The event was sent from a dehydrated device")]
3151 FromDehydratedDevice,
3152}
3153
3154impl From<CryptoStoreError> for DecryptToDeviceError {
3155 fn from(value: CryptoStoreError) -> Self {
3156 Self::OlmError(value.into())
3157 }
3158}
3159
3160#[cfg(test)]
3161impl From<DecryptToDeviceError> for OlmError {
3162 fn from(value: DecryptToDeviceError) -> Self {
3165 match value {
3166 DecryptToDeviceError::OlmError(olm_error) => olm_error,
3167 DecryptToDeviceError::FromDehydratedDevice => {
3168 panic!("Expected an OlmError but found FromDehydratedDevice")
3169 }
3170 }
3171 }
3172}
3173
3174#[cfg(test)]
3175pub(crate) mod test_helpers;
3176
3177#[cfg(test)]
3178pub(crate) mod tests;