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 BoxFuture,
28 deserialized_responses::{
29 AlgorithmInfo, DecryptedRoomEvent, DeviceLinkProblem, EncryptionInfo, ForwarderInfo,
30 ProcessedToDeviceEvent, ToDeviceUnableToDecryptInfo, ToDeviceUnableToDecryptReason,
31 UnableToDecryptInfo, UnableToDecryptReason, UnsignedDecryptionResult,
32 UnsignedEventLocation, VerificationLevel, VerificationState,
33 },
34 locks::RwLock as StdRwLock,
35 timer,
36};
37#[cfg(feature = "experimental-encrypted-state-events")]
38use ruma::events::{AnyStateEventContent, StateEventContent};
39use ruma::{
40 DeviceId, DeviceKeyAlgorithm, MilliSecondsSinceUnixEpoch, OneTimeKeyAlgorithm, OwnedDeviceId,
41 OwnedDeviceKeyId, OwnedTransactionId, OwnedUserId, RoomId, TransactionId, UInt, UserId,
42 api::client::{
43 dehydrated_device::DehydratedDeviceData,
44 keys::{
45 claim_keys::v3::Request as KeysClaimRequest,
46 get_keys::v3::Response as KeysQueryResponse,
47 upload_keys::v3::{Request as UploadKeysRequest, Response as UploadKeysResponse},
48 upload_signatures::v3::Request as UploadSignaturesRequest,
49 },
50 sync::sync_events::DeviceLists,
51 },
52 assign,
53 events::{
54 AnyMessageLikeEvent, AnyMessageLikeEventContent, AnyTimelineEvent, AnyToDeviceEvent,
55 MessageLikeEventContent, secret::request::SecretName,
56 },
57 serde::{JsonObject, Raw},
58};
59use serde::Serialize;
60use serde_json::{Value, value::to_raw_value};
61use tokio::sync::Mutex;
62use tracing::{
63 Span, debug, enabled, error,
64 field::{debug, display},
65 info, instrument, trace, warn,
66};
67use vodozemac::{Curve25519PublicKey, Ed25519Signature, megolm::DecryptionError};
68
69#[cfg(feature = "experimental-send-custom-to-device")]
70use crate::session_manager::split_devices_for_share_strategy;
71use crate::{
72 CollectStrategy, CryptoStoreError, DecryptionSettings, DeviceData, LocalTrust,
73 RoomEventDecryptionResult, SignatureError, TrustRequirement,
74 backups::{BackupMachine, MegolmV1BackupKey},
75 dehydrated_devices::{DehydratedDevices, DehydrationError},
76 error::{EventError, MegolmError, MegolmResult, OlmError, OlmResult, SetRoomSettingsError},
77 gossiping::GossipMachine,
78 identities::{Device, IdentityManager, UserDevices, user::UserIdentity},
79 olm::{
80 Account, CrossSigningStatus, EncryptionSettings, IdentityKeys, InboundGroupSession,
81 KnownSenderData, OlmDecryptionInfo, PrivateCrossSigningIdentity, SenderData,
82 SenderDataFinder, SessionType, StaticAccountData,
83 },
84 session_manager::{GroupSessionManager, SessionManager},
85 store::{
86 CryptoStoreWrapper, IntoCryptoStore, MemoryStore, Result as StoreResult, SecretImportError,
87 Store, StoreTransaction,
88 caches::StoreCache,
89 types::{
90 Changes, CrossSigningKeyExport, DeviceChanges, IdentityChanges, PendingChanges,
91 RoomKeyInfo, RoomSettings, StoredRoomKeyBundleData,
92 },
93 },
94 types::{
95 EventEncryptionAlgorithm, Signatures,
96 events::{
97 ToDeviceEvent, ToDeviceEvents,
98 olm_v1::{AnyDecryptedOlmEvent, DecryptedRoomKeyBundleEvent, DecryptedRoomKeyEvent},
99 room::encrypted::{
100 EncryptedEvent, EncryptedToDeviceEvent, RoomEncryptedEventContent,
101 RoomEventEncryptionScheme, SupportedEventEncryptionSchemes,
102 ToDeviceEncryptedEventContent,
103 },
104 room_key::{MegolmV1AesSha2Content, RoomKeyContent},
105 room_key_bundle::RoomKeyBundleContent,
106 room_key_withheld::{
107 MegolmV1AesSha2WithheldContent, RoomKeyWithheldContent, RoomKeyWithheldEvent,
108 },
109 },
110 requests::{
111 AnyIncomingResponse, KeysQueryRequest, OutgoingRequest, ToDeviceRequest,
112 UploadSigningKeysRequest,
113 },
114 },
115 utilities::timestamp_to_iso8601,
116 verification::{Verification, VerificationMachine, VerificationRequest},
117};
118
119#[derive(Debug, Serialize)]
120pub struct RawEncryptionResult {
122 pub content: Raw<RoomEncryptedEventContent>,
124 pub encryption_info: EncryptionInfo,
126}
127
128#[derive(Clone)]
131pub struct OlmMachine {
132 pub(crate) inner: Arc<OlmMachineInner>,
133}
134
135pub struct OlmMachineInner {
136 user_id: OwnedUserId,
138 device_id: OwnedDeviceId,
140 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
145 store: Store,
149 session_manager: SessionManager,
151 pub(crate) group_session_manager: GroupSessionManager,
153 verification_machine: VerificationMachine,
156 pub(crate) key_request_machine: GossipMachine,
159 identity_manager: IdentityManager,
162 backup_machine: BackupMachine,
164}
165
166#[cfg(not(tarpaulin_include))]
167impl std::fmt::Debug for OlmMachine {
168 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
169 f.debug_struct("OlmMachine")
170 .field("user_id", &self.user_id())
171 .field("device_id", &self.device_id())
172 .finish()
173 }
174}
175
176impl OlmMachine {
177 const CURRENT_GENERATION_STORE_KEY: &'static str = "generation-counter";
178 const HAS_MIGRATED_VERIFICATION_LATCH: &'static str = "HAS_MIGRATED_VERIFICATION_LATCH";
179
180 pub async fn new(user_id: &UserId, device_id: &DeviceId) -> Self {
191 OlmMachine::with_store(user_id, device_id, MemoryStore::new(), None)
192 .await
193 .expect("Reading and writing to the memory store always succeeds")
194 }
195
196 pub(crate) async fn rehydrate(
197 &self,
198 pickle_key: &[u8; 32],
199 device_id: &DeviceId,
200 device_data: Raw<DehydratedDeviceData>,
201 ) -> Result<OlmMachine, DehydrationError> {
202 let account = Account::rehydrate(pickle_key, self.user_id(), device_id, device_data)?;
203 let static_account = account.static_data().clone();
204
205 let store =
206 Arc::new(CryptoStoreWrapper::new(self.user_id(), device_id, MemoryStore::new()));
207 let device = DeviceData::from_account(&account);
208 store.save_pending_changes(PendingChanges { account: Some(account) }).await?;
209 store
210 .save_changes(Changes {
211 devices: DeviceChanges { new: vec![device], ..Default::default() },
212 ..Default::default()
213 })
214 .await?;
215
216 let (verification_machine, store, identity_manager) =
217 Self::new_helper_prelude(store, static_account, self.store().private_identity());
218
219 Ok(Self::new_helper(
220 device_id,
221 store,
222 verification_machine,
223 identity_manager,
224 self.store().private_identity(),
225 None,
226 ))
227 }
228
229 fn new_helper_prelude(
230 store_wrapper: Arc<CryptoStoreWrapper>,
231 account: StaticAccountData,
232 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
233 ) -> (VerificationMachine, Store, IdentityManager) {
234 let verification_machine =
235 VerificationMachine::new(account.clone(), user_identity.clone(), store_wrapper.clone());
236 let store = Store::new(account, user_identity, store_wrapper, verification_machine.clone());
237
238 let identity_manager = IdentityManager::new(store.clone());
239
240 (verification_machine, store, identity_manager)
241 }
242
243 fn new_helper(
244 device_id: &DeviceId,
245 store: Store,
246 verification_machine: VerificationMachine,
247 identity_manager: IdentityManager,
248 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
249 maybe_backup_key: Option<MegolmV1BackupKey>,
250 ) -> Self {
251 let group_session_manager = GroupSessionManager::new(store.clone());
252
253 let users_for_key_claim = Arc::new(StdRwLock::new(BTreeMap::new()));
254 let key_request_machine = GossipMachine::new(
255 store.clone(),
256 identity_manager.clone(),
257 group_session_manager.session_cache(),
258 users_for_key_claim.clone(),
259 );
260
261 let session_manager =
262 SessionManager::new(users_for_key_claim, key_request_machine.clone(), store.clone());
263
264 let backup_machine = BackupMachine::new(store.clone(), maybe_backup_key);
265
266 let inner = Arc::new(OlmMachineInner {
267 user_id: store.user_id().to_owned(),
268 device_id: device_id.to_owned(),
269 user_identity,
270 store,
271 session_manager,
272 group_session_manager,
273 verification_machine,
274 key_request_machine,
275 identity_manager,
276 backup_machine,
277 });
278
279 Self { inner }
280 }
281
282 #[instrument(skip(store, custom_account), fields(ed25519_key, curve25519_key))]
307 pub async fn with_store(
308 user_id: &UserId,
309 device_id: &DeviceId,
310 store: impl IntoCryptoStore,
311 custom_account: Option<vodozemac::olm::Account>,
312 ) -> StoreResult<Self> {
313 let store = store.into_crypto_store();
314
315 let static_account = match store.load_account().await? {
316 Some(account) => {
317 if user_id != account.user_id()
318 || device_id != account.device_id()
319 || custom_account.is_some()
320 {
321 return Err(CryptoStoreError::MismatchedAccount {
322 expected: (account.user_id().to_owned(), account.device_id().to_owned()),
323 got: (user_id.to_owned(), device_id.to_owned()),
324 });
325 }
326
327 Span::current()
328 .record("ed25519_key", display(account.identity_keys().ed25519))
329 .record("curve25519_key", display(account.identity_keys().curve25519));
330 debug!("Restored an Olm account");
331
332 account.static_data().clone()
333 }
334
335 None => {
336 let account = if let Some(account) = custom_account {
337 Account::new_helper(account, user_id, device_id)
338 } else {
339 Account::with_device_id(user_id, device_id)
340 };
341
342 let static_account = account.static_data().clone();
343
344 Span::current()
345 .record("ed25519_key", display(account.identity_keys().ed25519))
346 .record("curve25519_key", display(account.identity_keys().curve25519));
347
348 let device = DeviceData::from_account(&account);
349
350 device.set_trust_state(LocalTrust::Verified);
354
355 let changes = Changes {
356 devices: DeviceChanges { new: vec![device], ..Default::default() },
357 ..Default::default()
358 };
359 store.save_changes(changes).await?;
360 store.save_pending_changes(PendingChanges { account: Some(account) }).await?;
361
362 debug!("Created a new Olm account");
363
364 static_account
365 }
366 };
367
368 let identity = match store.load_identity().await? {
369 Some(i) => {
370 let master_key = i
371 .master_public_key()
372 .await
373 .and_then(|m| m.get_first_key().map(|m| m.to_owned()));
374 debug!(?master_key, "Restored the cross signing identity");
375 i
376 }
377 None => {
378 debug!("Creating an empty cross signing identity stub");
379 PrivateCrossSigningIdentity::empty(user_id)
380 }
381 };
382
383 let saved_keys = store.load_backup_keys().await?;
388 let maybe_backup_key = saved_keys.decryption_key.and_then(|k| {
389 if let Some(version) = saved_keys.backup_version {
390 let megolm_v1_backup_key = k.megolm_v1_public_key();
391 megolm_v1_backup_key.set_version(version);
392 Some(megolm_v1_backup_key)
393 } else {
394 None
395 }
396 });
397
398 let identity = Arc::new(Mutex::new(identity));
399 let store = Arc::new(CryptoStoreWrapper::new(user_id, device_id, store));
400
401 let (verification_machine, store, identity_manager) =
402 Self::new_helper_prelude(store, static_account, identity.clone());
403
404 Self::migration_post_verified_latch_support(&store, &identity_manager).await?;
407
408 Ok(Self::new_helper(
409 device_id,
410 store,
411 verification_machine,
412 identity_manager,
413 identity,
414 maybe_backup_key,
415 ))
416 }
417
418 pub(crate) async fn migration_post_verified_latch_support(
426 store: &Store,
427 identity_manager: &IdentityManager,
428 ) -> Result<(), CryptoStoreError> {
429 let maybe_migrate_for_identity_verified_latch =
430 store.get_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH).await?.is_none();
431
432 if maybe_migrate_for_identity_verified_latch {
433 identity_manager.mark_all_tracked_users_as_dirty(store.cache().await?).await?;
434
435 store.set_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH, vec![0]).await?
436 }
437 Ok(())
438 }
439
440 pub fn store(&self) -> &Store {
442 &self.inner.store
443 }
444
445 pub fn user_id(&self) -> &UserId {
447 &self.inner.user_id
448 }
449
450 pub fn device_id(&self) -> &DeviceId {
452 &self.inner.device_id
453 }
454
455 pub fn device_creation_time(&self) -> MilliSecondsSinceUnixEpoch {
462 self.inner.store.static_account().creation_local_time()
463 }
464
465 pub fn identity_keys(&self) -> IdentityKeys {
467 let account = self.inner.store.static_account();
468 account.identity_keys()
469 }
470
471 pub async fn display_name(&self) -> StoreResult<Option<String>> {
473 self.store().device_display_name().await
474 }
475
476 pub async fn tracked_users(&self) -> StoreResult<HashSet<OwnedUserId>> {
481 let cache = self.store().cache().await?;
482 Ok(self.inner.identity_manager.key_query_manager.synced(&cache).await?.tracked_users())
483 }
484
485 #[cfg(feature = "automatic-room-key-forwarding")]
494 pub fn set_room_key_requests_enabled(&self, enable: bool) {
495 self.inner.key_request_machine.set_room_key_requests_enabled(enable)
496 }
497
498 pub fn are_room_key_requests_enabled(&self) -> bool {
503 self.inner.key_request_machine.are_room_key_requests_enabled()
504 }
505
506 #[cfg(feature = "automatic-room-key-forwarding")]
515 pub fn set_room_key_forwarding_enabled(&self, enable: bool) {
516 self.inner.key_request_machine.set_room_key_forwarding_enabled(enable)
517 }
518
519 pub fn is_room_key_forwarding_enabled(&self) -> bool {
523 self.inner.key_request_machine.is_room_key_forwarding_enabled()
524 }
525
526 pub async fn outgoing_requests(&self) -> StoreResult<Vec<OutgoingRequest>> {
534 let mut requests = Vec::new();
535
536 {
537 let store_cache = self.inner.store.cache().await?;
538 let account = store_cache.account().await?;
539 if let Some(r) = self.keys_for_upload(&account).await.map(|r| OutgoingRequest {
540 request_id: TransactionId::new(),
541 request: Arc::new(r.into()),
542 }) {
543 requests.push(r);
544 }
545 }
546
547 for request in self
548 .inner
549 .identity_manager
550 .users_for_key_query()
551 .await?
552 .into_iter()
553 .map(|(request_id, r)| OutgoingRequest { request_id, request: Arc::new(r.into()) })
554 {
555 requests.push(request);
556 }
557
558 requests.append(&mut self.inner.verification_machine.outgoing_messages());
559 requests.append(&mut self.inner.key_request_machine.outgoing_to_device_requests().await?);
560
561 Ok(requests)
562 }
563
564 pub fn query_keys_for_users<'a>(
585 &self,
586 users: impl IntoIterator<Item = &'a UserId>,
587 ) -> (OwnedTransactionId, KeysQueryRequest) {
588 self.inner.identity_manager.build_key_query_for_users(users)
589 }
590
591 pub async fn mark_request_as_sent<'a>(
601 &self,
602 request_id: &TransactionId,
603 response: impl Into<AnyIncomingResponse<'a>>,
604 ) -> OlmResult<()> {
605 match response.into() {
606 AnyIncomingResponse::KeysUpload(response) => {
607 Box::pin(self.receive_keys_upload_response(response)).await?;
608 }
609 AnyIncomingResponse::KeysQuery(response) => {
610 Box::pin(self.receive_keys_query_response(request_id, response)).await?;
611 }
612 AnyIncomingResponse::KeysClaim(response) => {
613 Box::pin(
614 self.inner.session_manager.receive_keys_claim_response(request_id, response),
615 )
616 .await?;
617 }
618 AnyIncomingResponse::ToDevice(_) => {
619 Box::pin(self.mark_to_device_request_as_sent(request_id)).await?;
620 }
621 AnyIncomingResponse::SigningKeysUpload(_) => {
622 Box::pin(self.receive_cross_signing_upload_response()).await?;
623 }
624 AnyIncomingResponse::SignatureUpload(_) => {
625 self.inner.verification_machine.mark_request_as_sent(request_id);
626 }
627 AnyIncomingResponse::RoomMessage(_) => {
628 self.inner.verification_machine.mark_request_as_sent(request_id);
629 }
630 AnyIncomingResponse::KeysBackup(_) => {
631 Box::pin(self.inner.backup_machine.mark_request_as_sent(request_id)).await?;
632 }
633 }
634
635 Ok(())
636 }
637
638 async fn receive_cross_signing_upload_response(&self) -> StoreResult<()> {
640 let identity = self.inner.user_identity.lock().await;
641 identity.mark_as_shared();
642
643 let changes = Changes { private_identity: Some(identity.clone()), ..Default::default() };
644
645 self.store().save_changes(changes).await
646 }
647
648 pub async fn bootstrap_cross_signing(
667 &self,
668 reset: bool,
669 ) -> StoreResult<CrossSigningBootstrapRequests> {
670 let identity = self.inner.user_identity.lock().await.clone();
675
676 let (upload_signing_keys_req, upload_signatures_req) = if reset || identity.is_empty().await
677 {
678 info!("Creating new cross signing identity");
679
680 let (identity, upload_signing_keys_req, upload_signatures_req) = {
681 let cache = self.inner.store.cache().await?;
682 let account = cache.account().await?;
683 account.bootstrap_cross_signing().await
684 };
685
686 let public = identity.to_public_identity().await.expect(
687 "Couldn't create a public version of the identity from a new private identity",
688 );
689
690 *self.inner.user_identity.lock().await = identity.clone();
691
692 self.store()
693 .save_changes(Changes {
694 identities: IdentityChanges { new: vec![public.into()], ..Default::default() },
695 private_identity: Some(identity),
696 ..Default::default()
697 })
698 .await?;
699
700 (upload_signing_keys_req, upload_signatures_req)
701 } else {
702 info!("Trying to upload the existing cross signing identity");
703 let upload_signing_keys_req = identity.as_upload_request().await;
704
705 let upload_signatures_req = identity
707 .sign_account(self.inner.store.static_account())
708 .await
709 .expect("Can't sign device keys");
710
711 (upload_signing_keys_req, upload_signatures_req)
712 };
713
714 let upload_keys_req =
718 self.upload_device_keys().await?.map(|(_, request)| OutgoingRequest::from(request));
719
720 Ok(CrossSigningBootstrapRequests {
721 upload_signing_keys_req,
722 upload_keys_req,
723 upload_signatures_req,
724 })
725 }
726
727 pub async fn upload_device_keys(
739 &self,
740 ) -> StoreResult<Option<(OwnedTransactionId, UploadKeysRequest)>> {
741 let cache = self.store().cache().await?;
742 let account = cache.account().await?;
743
744 Ok(self.keys_for_upload(&account).await.map(|request| (TransactionId::new(), request)))
745 }
746
747 async fn receive_keys_upload_response(&self, response: &UploadKeysResponse) -> OlmResult<()> {
754 self.inner
755 .store
756 .with_transaction(|mut tr| async {
757 let account = tr.account().await?;
758 account.receive_keys_upload_response(response)?;
759 Ok((tr, ()))
760 })
761 .await
762 }
763
764 #[instrument(skip_all)]
792 pub async fn get_missing_sessions(
793 &self,
794 users: impl Iterator<Item = &UserId>,
795 ) -> StoreResult<Option<(OwnedTransactionId, KeysClaimRequest)>> {
796 self.inner.session_manager.get_missing_sessions(users).await
797 }
798
799 async fn receive_keys_query_response(
808 &self,
809 request_id: &TransactionId,
810 response: &KeysQueryResponse,
811 ) -> OlmResult<(DeviceChanges, IdentityChanges)> {
812 self.inner.identity_manager.receive_keys_query_response(request_id, response).await
813 }
814
815 async fn keys_for_upload(&self, account: &Account) -> Option<UploadKeysRequest> {
824 let (mut device_keys, one_time_keys, fallback_keys) = account.keys_for_upload();
825
826 if let Some(device_keys) = &mut device_keys {
836 let private_identity = self.store().private_identity();
837 let guard = private_identity.lock().await;
838
839 if guard.status().await.is_complete() {
840 guard.sign_device_keys(device_keys).await.expect(
841 "We should be able to sign our device keys since we confirmed that we \
842 have a complete set of private cross-signing keys",
843 );
844 }
845 }
846
847 if device_keys.is_none() && one_time_keys.is_empty() && fallback_keys.is_empty() {
848 None
849 } else {
850 let device_keys = device_keys.map(|d| d.to_raw());
851
852 Some(assign!(UploadKeysRequest::new(), {
853 device_keys, one_time_keys, fallback_keys
854 }))
855 }
856 }
857
858 async fn decrypt_to_device_event(
881 &self,
882 transaction: &mut StoreTransaction,
883 event: &EncryptedToDeviceEvent,
884 changes: &mut Changes,
885 decryption_settings: &DecryptionSettings,
886 ) -> Result<OlmDecryptionInfo, DecryptToDeviceError> {
887 let mut decrypted = transaction
889 .account()
890 .await?
891 .decrypt_to_device_event(&self.inner.store, event, decryption_settings)
892 .await?;
893
894 self.check_to_device_event_is_not_from_dehydrated_device(&decrypted, &event.sender).await?;
896
897 self.handle_decrypted_to_device_event(transaction.cache(), &mut decrypted, changes).await?;
899
900 Ok(decrypted)
901 }
902
903 #[instrument(
904 skip_all,
905 fields(room_id = ? content.room_id, session_id, message_index, shared_history = content.shared_history)
909 )]
910 async fn handle_key(
911 &self,
912 sender_key: Curve25519PublicKey,
913 event: &DecryptedRoomKeyEvent,
914 content: &MegolmV1AesSha2Content,
915 ) -> OlmResult<Option<InboundGroupSession>> {
916 let session =
917 InboundGroupSession::from_room_key_content(sender_key, event.keys.ed25519, content);
918
919 match session {
920 Ok(mut session) => {
921 Span::current().record("session_id", session.session_id());
922 Span::current().record("message_index", session.first_known_index());
923
924 let sender_data =
925 SenderDataFinder::find_using_event(self.store(), sender_key, event, &session)
926 .await?;
927 session.sender_data = sender_data;
928
929 Ok(self.store().merge_received_group_session(session).await?)
930 }
931 Err(e) => {
932 Span::current().record("session_id", &content.session_id);
933 warn!("Received a room key event which contained an invalid session key: {e}");
934
935 Ok(None)
936 }
937 }
938 }
939
940 #[instrument(skip_all, fields(algorithm = ?event.content.algorithm()))]
942 async fn add_room_key(
943 &self,
944 sender_key: Curve25519PublicKey,
945 event: &DecryptedRoomKeyEvent,
946 ) -> OlmResult<Option<InboundGroupSession>> {
947 match &event.content {
948 RoomKeyContent::MegolmV1AesSha2(content) => {
949 self.handle_key(sender_key, event, content).await
950 }
951 #[cfg(feature = "experimental-algorithms")]
952 RoomKeyContent::MegolmV2AesSha2(content) => {
953 self.handle_key(sender_key, event, content).await
954 }
955 RoomKeyContent::Unknown(_) => {
956 warn!("Received a room key with an unsupported algorithm");
957 Ok(None)
958 }
959 }
960 }
961
962 #[instrument()]
965 async fn receive_room_key_bundle_data(
966 &self,
967 sender_key: Curve25519PublicKey,
968 event: &DecryptedRoomKeyBundleEvent,
969 changes: &mut Changes,
970 ) -> OlmResult<()> {
971 let Some(sender_device_keys) = &event.sender_device_keys else {
972 warn!("Received a room key bundle with no sender device keys: ignoring");
973 return Ok(());
974 };
975
976 let sender_device_data =
981 DeviceData::try_from(sender_device_keys).expect("failed to verify sender device keys");
982 let sender_device = self.store().wrap_device_data(sender_device_data).await?;
983
984 changes.received_room_key_bundles.push(StoredRoomKeyBundleData {
985 sender_user: event.sender.clone(),
986 sender_data: SenderData::from_device(&sender_device),
987 sender_key,
988 bundle_data: event.content.clone(),
989 });
990 Ok(())
991 }
992
993 fn add_withheld_info(&self, changes: &mut Changes, event: &RoomKeyWithheldEvent) {
994 debug!(?event.content, "Processing `m.room_key.withheld` event");
995
996 if let RoomKeyWithheldContent::MegolmV1AesSha2(
997 MegolmV1AesSha2WithheldContent::BlackListed(c)
998 | MegolmV1AesSha2WithheldContent::Unverified(c)
999 | MegolmV1AesSha2WithheldContent::Unauthorised(c)
1000 | MegolmV1AesSha2WithheldContent::Unavailable(c),
1001 ) = &event.content
1002 {
1003 changes
1004 .withheld_session_info
1005 .entry(c.room_id.to_owned())
1006 .or_default()
1007 .insert(c.session_id.to_owned(), event.to_owned().into());
1008 }
1009 }
1010
1011 #[cfg(test)]
1012 pub(crate) async fn create_outbound_group_session_with_defaults_test_helper(
1013 &self,
1014 room_id: &RoomId,
1015 ) -> OlmResult<()> {
1016 let (_, session) = self
1017 .inner
1018 .group_session_manager
1019 .create_outbound_group_session(
1020 room_id,
1021 EncryptionSettings::default(),
1022 SenderData::unknown(),
1023 )
1024 .await?;
1025
1026 self.store().save_inbound_group_sessions(&[session]).await?;
1027
1028 Ok(())
1029 }
1030
1031 #[cfg(test)]
1032 #[allow(dead_code)]
1033 pub(crate) async fn create_inbound_session_test_helper(
1034 &self,
1035 room_id: &RoomId,
1036 ) -> OlmResult<InboundGroupSession> {
1037 let (_, session) = self
1038 .inner
1039 .group_session_manager
1040 .create_outbound_group_session(
1041 room_id,
1042 EncryptionSettings::default(),
1043 SenderData::unknown(),
1044 )
1045 .await?;
1046
1047 Ok(session)
1048 }
1049
1050 pub async fn encrypt_room_event(
1067 &self,
1068 room_id: &RoomId,
1069 content: impl MessageLikeEventContent,
1070 ) -> MegolmResult<RawEncryptionResult> {
1071 let event_type = content.event_type().to_string();
1072 let content = Raw::new(&content)?.cast_unchecked();
1073 self.encrypt_room_event_raw(room_id, &event_type, &content).await
1074 }
1075
1076 pub async fn encrypt_room_event_raw(
1096 &self,
1097 room_id: &RoomId,
1098 event_type: &str,
1099 content: &Raw<AnyMessageLikeEventContent>,
1100 ) -> MegolmResult<RawEncryptionResult> {
1101 self.inner.group_session_manager.encrypt(room_id, event_type, content).await.map(|result| {
1102 RawEncryptionResult {
1103 content: result.content,
1104 encryption_info: self
1105 .own_encryption_info(result.algorithm, result.session_id.to_string()),
1106 }
1107 })
1108 }
1109
1110 fn own_encryption_info(
1111 &self,
1112 algorithm: EventEncryptionAlgorithm,
1113 session_id: String,
1114 ) -> EncryptionInfo {
1115 let identity_keys = self.identity_keys();
1116
1117 let algorithm_info = match algorithm {
1118 EventEncryptionAlgorithm::MegolmV1AesSha2 => AlgorithmInfo::MegolmV1AesSha2 {
1119 curve25519_key: identity_keys.curve25519.to_base64(),
1120 sender_claimed_keys: BTreeMap::from([(
1121 DeviceKeyAlgorithm::Ed25519,
1122 identity_keys.ed25519.to_base64(),
1123 )]),
1124 session_id: Some(session_id),
1125 },
1126 EventEncryptionAlgorithm::OlmV1Curve25519AesSha2 => {
1127 AlgorithmInfo::OlmV1Curve25519AesSha2 {
1128 curve25519_public_key_base64: identity_keys.curve25519.to_base64(),
1129 }
1130 }
1131 _ => unreachable!(
1132 "Only MegolmV1AesSha2 and OlmV1Curve25519AesSha2 are supported on this level"
1133 ),
1134 };
1135
1136 EncryptionInfo {
1137 sender: self.inner.user_id.clone(),
1138 sender_device: Some(self.inner.device_id.clone()),
1139 forwarder: None,
1140 algorithm_info,
1141 verification_state: VerificationState::Verified,
1142 }
1143 }
1144
1145 #[cfg(feature = "experimental-encrypted-state-events")]
1157 pub async fn encrypt_state_event<C, K>(
1158 &self,
1159 room_id: &RoomId,
1160 content: C,
1161 state_key: K,
1162 ) -> MegolmResult<Raw<RoomEncryptedEventContent>>
1163 where
1164 C: StateEventContent,
1165 C::StateKey: Borrow<K>,
1166 K: AsRef<str>,
1167 {
1168 let event_type = content.event_type().to_string();
1169 let content = Raw::new(&content)?.cast_unchecked();
1170 self.encrypt_state_event_raw(room_id, &event_type, state_key.as_ref(), &content).await
1171 }
1172
1173 #[cfg(feature = "experimental-encrypted-state-events")]
1192 pub async fn encrypt_state_event_raw(
1193 &self,
1194 room_id: &RoomId,
1195 event_type: &str,
1196 state_key: &str,
1197 content: &Raw<AnyStateEventContent>,
1198 ) -> MegolmResult<Raw<RoomEncryptedEventContent>> {
1199 self.inner
1200 .group_session_manager
1201 .encrypt_state(room_id, event_type, state_key, content)
1202 .await
1203 }
1204
1205 pub async fn discard_room_key(&self, room_id: &RoomId) -> StoreResult<bool> {
1216 self.inner.group_session_manager.invalidate_group_session(room_id).await
1217 }
1218
1219 pub async fn share_room_key(
1239 &self,
1240 room_id: &RoomId,
1241 users: impl Iterator<Item = &UserId>,
1242 encryption_settings: impl Into<EncryptionSettings>,
1243 ) -> OlmResult<Vec<Arc<ToDeviceRequest>>> {
1244 self.inner.group_session_manager.share_room_key(room_id, users, encryption_settings).await
1245 }
1246
1247 #[cfg(feature = "experimental-send-custom-to-device")]
1261 pub async fn encrypt_content_for_devices(
1262 &self,
1263 devices: Vec<DeviceData>,
1264 event_type: &str,
1265 content: &Value,
1266 share_strategy: CollectStrategy,
1267 ) -> OlmResult<(Vec<ToDeviceRequest>, Vec<(DeviceData, WithheldCode)>)> {
1268 let mut changes = Changes::default();
1269
1270 let (allowed_devices, mut blocked_devices) =
1271 split_devices_for_share_strategy(&self.inner.store, devices, share_strategy).await?;
1272
1273 let result = self
1274 .inner
1275 .group_session_manager
1276 .encrypt_content_for_devices(allowed_devices, event_type, content.clone(), &mut changes)
1277 .await;
1278
1279 if !changes.is_empty() {
1281 let session_count = changes.sessions.len();
1282
1283 self.inner.store.save_changes(changes).await?;
1284
1285 trace!(
1286 session_count = session_count,
1287 "Stored the changed sessions after encrypting a custom to-device event"
1288 );
1289 }
1290
1291 result.map(|(to_device_requests, mut withheld)| {
1292 withheld.append(&mut blocked_devices);
1293 (to_device_requests, withheld)
1294 })
1295 }
1296 pub async fn share_room_key_bundle_data(
1301 &self,
1302 user_id: &UserId,
1303 collect_strategy: &CollectStrategy,
1304 bundle_data: RoomKeyBundleContent,
1305 ) -> OlmResult<Vec<ToDeviceRequest>> {
1306 self.inner
1307 .group_session_manager
1308 .share_room_key_bundle_data(user_id, collect_strategy, bundle_data)
1309 .await
1310 }
1311
1312 #[deprecated(note = "Use OlmMachine::receive_verification_event instead", since = "0.7.0")]
1320 pub async fn receive_unencrypted_verification_event(
1321 &self,
1322 event: &AnyMessageLikeEvent,
1323 ) -> StoreResult<()> {
1324 self.inner.verification_machine.receive_any_event(event).await
1325 }
1326
1327 pub async fn receive_verification_event(&self, event: &AnyMessageLikeEvent) -> StoreResult<()> {
1340 self.inner.verification_machine.receive_any_event(event).await
1341 }
1342
1343 #[instrument(
1349 skip_all,
1350 fields(
1351 sender_key = ?decrypted.result.sender_key,
1352 event_type = decrypted.result.event.event_type(),
1353 ),
1354 )]
1355 async fn handle_decrypted_to_device_event(
1356 &self,
1357 cache: &StoreCache,
1358 decrypted: &mut OlmDecryptionInfo,
1359 changes: &mut Changes,
1360 ) -> OlmResult<()> {
1361 debug!(
1362 sender_device_keys =
1363 ?decrypted.result.event.sender_device_keys().map(|k| (k.curve25519_key(), k.ed25519_key())).unwrap_or((None, None)),
1364 "Received a decrypted to-device event",
1365 );
1366
1367 match &*decrypted.result.event {
1368 AnyDecryptedOlmEvent::RoomKey(e) => {
1369 let session = self.add_room_key(decrypted.result.sender_key, e).await?;
1370 decrypted.inbound_group_session = session;
1371 }
1372 AnyDecryptedOlmEvent::ForwardedRoomKey(e) => {
1373 let session = self
1374 .inner
1375 .key_request_machine
1376 .receive_forwarded_room_key(decrypted.result.sender_key, e)
1377 .await?;
1378 decrypted.inbound_group_session = session;
1379 }
1380 AnyDecryptedOlmEvent::SecretSend(e) => {
1381 let name = self
1382 .inner
1383 .key_request_machine
1384 .receive_secret_event(cache, decrypted.result.sender_key, e, changes)
1385 .await?;
1386
1387 if let Ok(ToDeviceEvents::SecretSend(mut e)) =
1390 decrypted.result.raw_event.deserialize_as()
1391 {
1392 e.content.secret_name = name;
1393 decrypted.result.raw_event = Raw::from_json(to_raw_value(&e)?);
1394 }
1395
1396 if enabled!(tracing::Level::DEBUG) {
1397 let cross_signing_status = self.cross_signing_status().await;
1398 let backup_enabled = self.backup_machine().enabled().await;
1399 debug!(
1400 ?cross_signing_status,
1401 backup_enabled, "Status after receiving secret event"
1402 );
1403 }
1404 }
1405 AnyDecryptedOlmEvent::Dummy(_) => {
1406 debug!("Received an `m.dummy` event");
1407 }
1408 AnyDecryptedOlmEvent::RoomKeyBundle(e) => {
1409 debug!("Received a room key bundle event {:?}", e);
1410 self.receive_room_key_bundle_data(decrypted.result.sender_key, e, changes).await?;
1411 }
1412 AnyDecryptedOlmEvent::Custom(_) => {
1413 warn!("Received an unexpected encrypted to-device event");
1414 }
1415 }
1416
1417 Ok(())
1418 }
1419
1420 async fn handle_verification_event(&self, event: &ToDeviceEvents) {
1421 if let Err(e) = self.inner.verification_machine.receive_any_event(event).await {
1422 error!("Error handling a verification event: {e:?}");
1423 }
1424 }
1425
1426 async fn mark_to_device_request_as_sent(&self, request_id: &TransactionId) -> StoreResult<()> {
1428 self.inner.verification_machine.mark_request_as_sent(request_id);
1429 self.inner.key_request_machine.mark_outgoing_request_as_sent(request_id).await?;
1430 self.inner.group_session_manager.mark_request_as_sent(request_id).await?;
1431 self.inner.session_manager.mark_outgoing_request_as_sent(request_id);
1432 Ok(())
1433 }
1434
1435 pub fn get_verification(&self, user_id: &UserId, flow_id: &str) -> Option<Verification> {
1437 self.inner.verification_machine.get_verification(user_id, flow_id)
1438 }
1439
1440 pub fn get_verification_request(
1442 &self,
1443 user_id: &UserId,
1444 flow_id: impl AsRef<str>,
1445 ) -> Option<VerificationRequest> {
1446 self.inner.verification_machine.get_request(user_id, flow_id)
1447 }
1448
1449 pub fn get_verification_requests(&self, user_id: &UserId) -> Vec<VerificationRequest> {
1451 self.inner.verification_machine.get_requests(user_id)
1452 }
1453
1454 async fn handle_to_device_event(&self, changes: &mut Changes, event: &ToDeviceEvents) {
1459 use crate::types::events::ToDeviceEvents::*;
1460
1461 match event {
1462 RoomKeyRequest(e) => self.inner.key_request_machine.receive_incoming_key_request(e),
1468 SecretRequest(e) => self.inner.key_request_machine.receive_incoming_secret_request(e),
1469 RoomKeyWithheld(e) => self.add_withheld_info(changes, e),
1470 KeyVerificationAccept(..)
1471 | KeyVerificationCancel(..)
1472 | KeyVerificationKey(..)
1473 | KeyVerificationMac(..)
1474 | KeyVerificationRequest(..)
1475 | KeyVerificationReady(..)
1476 | KeyVerificationDone(..)
1477 | KeyVerificationStart(..) => {
1478 self.handle_verification_event(event).await;
1479 }
1480
1481 Custom(_) | Dummy(_) => {}
1483
1484 RoomEncrypted(_) => {}
1486
1487 SecretSend(_) | RoomKey(_) | ForwardedRoomKey(_) => {}
1490 }
1491 }
1492
1493 fn record_message_id(event: &Raw<AnyToDeviceEvent>) {
1494 use serde::Deserialize;
1495
1496 #[derive(Deserialize)]
1497 struct ContentStub<'a> {
1498 #[serde(borrow, rename = "org.matrix.msgid")]
1499 message_id: Option<&'a str>,
1500 }
1501 #[derive(Deserialize)]
1502 struct ToDeviceStub<'a> {
1503 sender: &'a str,
1504 #[serde(rename = "type")]
1505 event_type: &'a str,
1506 #[serde(borrow)]
1507 content: ContentStub<'a>,
1508 }
1509
1510 if let Ok(event) = event.deserialize_as_unchecked::<ToDeviceStub<'_>>() {
1511 Span::current().record("sender", event.sender);
1512 Span::current().record("event_type", event.event_type);
1513 Span::current().record("message_id", event.content.message_id);
1514 }
1515 }
1516
1517 #[instrument(skip_all, fields(sender, event_type, message_id))]
1525 async fn receive_to_device_event(
1526 &self,
1527 transaction: &mut StoreTransaction,
1528 changes: &mut Changes,
1529 raw_event: Raw<AnyToDeviceEvent>,
1530 decryption_settings: &DecryptionSettings,
1531 ) -> Option<ProcessedToDeviceEvent> {
1532 Self::record_message_id(&raw_event);
1533
1534 let event: ToDeviceEvents = match raw_event.deserialize_as() {
1535 Ok(e) => e,
1536 Err(e) => {
1537 warn!("Received an invalid to-device event: {e}");
1539 return Some(ProcessedToDeviceEvent::Invalid(raw_event));
1540 }
1541 };
1542
1543 debug!("Received a to-device event");
1544
1545 match event {
1546 ToDeviceEvents::RoomEncrypted(e) => {
1547 self.receive_encrypted_to_device_event(
1548 transaction,
1549 changes,
1550 raw_event,
1551 e,
1552 decryption_settings,
1553 )
1554 .await
1555 }
1556 e => {
1557 self.handle_to_device_event(changes, &e).await;
1558 Some(ProcessedToDeviceEvent::PlainText(raw_event))
1559 }
1560 }
1561 }
1562
1563 async fn receive_encrypted_to_device_event(
1577 &self,
1578 transaction: &mut StoreTransaction,
1579 changes: &mut Changes,
1580 mut raw_event: Raw<AnyToDeviceEvent>,
1581 e: ToDeviceEvent<ToDeviceEncryptedEventContent>,
1582 decryption_settings: &DecryptionSettings,
1583 ) -> Option<ProcessedToDeviceEvent> {
1584 let decrypted = match self
1585 .decrypt_to_device_event(transaction, &e, changes, decryption_settings)
1586 .await
1587 {
1588 Ok(decrypted) => decrypted,
1589 Err(DecryptToDeviceError::OlmError(err)) => {
1590 let reason = if let OlmError::UnverifiedSenderDevice = &err {
1591 ToDeviceUnableToDecryptReason::UnverifiedSenderDevice
1592 } else {
1593 ToDeviceUnableToDecryptReason::DecryptionFailure
1594 };
1595
1596 if let OlmError::SessionWedged(sender, curve_key) = err
1597 && let Err(e) =
1598 self.inner.session_manager.mark_device_as_wedged(&sender, curve_key).await
1599 {
1600 error!(
1601 error = ?e,
1602 "Couldn't mark device to be unwedged",
1603 );
1604 }
1605
1606 return Some(ProcessedToDeviceEvent::UnableToDecrypt {
1607 encrypted_event: raw_event,
1608 utd_info: ToDeviceUnableToDecryptInfo { reason },
1609 });
1610 }
1611 Err(DecryptToDeviceError::FromDehydratedDevice) => return None,
1612 };
1613
1614 match decrypted.session {
1617 SessionType::New(s) | SessionType::Existing(s) => {
1618 changes.sessions.push(s);
1619 }
1620 }
1621
1622 changes.message_hashes.push(decrypted.message_hash);
1623
1624 if let Some(group_session) = decrypted.inbound_group_session {
1625 changes.inbound_group_sessions.push(group_session);
1626 }
1627
1628 match decrypted.result.raw_event.deserialize_as() {
1629 Ok(event) => {
1630 self.handle_to_device_event(changes, &event).await;
1631
1632 raw_event = event
1633 .serialize_zeroized()
1634 .expect("Zeroizing and reserializing our events should always work")
1635 .cast();
1636 }
1637 Err(e) => {
1638 warn!("Received an invalid encrypted to-device event: {e}");
1639 raw_event = decrypted.result.raw_event;
1640 }
1641 }
1642
1643 Some(ProcessedToDeviceEvent::Decrypted {
1644 raw: raw_event,
1645 encryption_info: decrypted.result.encryption_info,
1646 })
1647 }
1648
1649 async fn check_to_device_event_is_not_from_dehydrated_device(
1652 &self,
1653 decrypted: &OlmDecryptionInfo,
1654 sender_user_id: &UserId,
1655 ) -> Result<(), DecryptToDeviceError> {
1656 if self.to_device_event_is_from_dehydrated_device(decrypted, sender_user_id).await? {
1657 warn!(
1658 sender = ?sender_user_id,
1659 session = ?decrypted.session,
1660 "Received a to-device event from a dehydrated device. This is unexpected: ignoring event"
1661 );
1662 Err(DecryptToDeviceError::FromDehydratedDevice)
1663 } else {
1664 Ok(())
1665 }
1666 }
1667
1668 async fn to_device_event_is_from_dehydrated_device(
1674 &self,
1675 decrypted: &OlmDecryptionInfo,
1676 sender_user_id: &UserId,
1677 ) -> OlmResult<bool> {
1678 if let Some(device_keys) = decrypted.result.event.sender_device_keys() {
1680 if device_keys.dehydrated.unwrap_or(false) {
1686 return Ok(true);
1687 }
1688 }
1693
1694 Ok(self
1696 .store()
1697 .get_device_from_curve_key(sender_user_id, decrypted.result.sender_key)
1698 .await?
1699 .is_some_and(|d| d.is_dehydrated()))
1700 }
1701
1702 #[instrument(skip_all)]
1720 pub async fn receive_sync_changes(
1721 &self,
1722 sync_changes: EncryptionSyncChanges<'_>,
1723 decryption_settings: &DecryptionSettings,
1724 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Vec<RoomKeyInfo>)> {
1725 let mut store_transaction = self.inner.store.transaction().await;
1726
1727 let (events, changes) = self
1728 .preprocess_sync_changes(&mut store_transaction, sync_changes, decryption_settings)
1729 .await?;
1730
1731 let room_key_updates: Vec<_> =
1734 changes.inbound_group_sessions.iter().map(RoomKeyInfo::from).collect();
1735
1736 self.store().save_changes(changes).await?;
1737 store_transaction.commit().await?;
1738
1739 Ok((events, room_key_updates))
1740 }
1741
1742 pub(crate) async fn preprocess_sync_changes(
1760 &self,
1761 transaction: &mut StoreTransaction,
1762 sync_changes: EncryptionSyncChanges<'_>,
1763 decryption_settings: &DecryptionSettings,
1764 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Changes)> {
1765 let mut events: Vec<ProcessedToDeviceEvent> = self
1767 .inner
1768 .verification_machine
1769 .garbage_collect()
1770 .iter()
1771 .map(|e| ProcessedToDeviceEvent::PlainText(e.clone()))
1775 .collect();
1776 let mut changes = Default::default();
1779
1780 {
1781 let account = transaction.account().await?;
1782 account.update_key_counts(
1783 sync_changes.one_time_keys_counts,
1784 sync_changes.unused_fallback_keys,
1785 )
1786 }
1787
1788 if let Err(e) = self
1789 .inner
1790 .identity_manager
1791 .receive_device_changes(
1792 transaction.cache(),
1793 sync_changes.changed_devices.changed.iter().map(|u| u.as_ref()),
1794 )
1795 .await
1796 {
1797 error!(error = ?e, "Error marking a tracked user as changed");
1798 }
1799
1800 for raw_event in sync_changes.to_device_events {
1801 let processed_event = Box::pin(self.receive_to_device_event(
1802 transaction,
1803 &mut changes,
1804 raw_event,
1805 decryption_settings,
1806 ))
1807 .await;
1808
1809 if let Some(processed_event) = processed_event {
1810 events.push(processed_event);
1811 }
1812 }
1813
1814 let changed_sessions = self
1815 .inner
1816 .key_request_machine
1817 .collect_incoming_key_requests(transaction.cache())
1818 .await?;
1819
1820 changes.sessions.extend(changed_sessions);
1821 changes.next_batch_token = sync_changes.next_batch_token;
1822
1823 Ok((events, changes))
1824 }
1825
1826 pub async fn request_room_key(
1843 &self,
1844 event: &Raw<EncryptedEvent>,
1845 room_id: &RoomId,
1846 ) -> MegolmResult<(Option<OutgoingRequest>, OutgoingRequest)> {
1847 let event = event.deserialize()?;
1848 self.inner.key_request_machine.request_key(room_id, &event).await
1849 }
1850
1851 async fn get_room_event_verification_state(
1864 &self,
1865 session: &InboundGroupSession,
1866 sender: &UserId,
1867 ) -> MegolmResult<(VerificationState, Option<OwnedDeviceId>)> {
1868 let sender_data = self.get_or_update_sender_data(session, sender).await?;
1869
1870 let (verification_state, device_id) = match sender_data.user_id() {
1879 Some(i) if i != sender => {
1880 (VerificationState::Unverified(VerificationLevel::MismatchedSender), None)
1881 }
1882
1883 Some(_) | None => {
1884 sender_data_to_verification_state(sender_data, session.has_been_imported())
1885 }
1886 };
1887
1888 Ok((verification_state, device_id))
1889 }
1890
1891 async fn get_or_update_sender_data(
1906 &self,
1907 session: &InboundGroupSession,
1908 sender: &UserId,
1909 ) -> MegolmResult<SenderData> {
1910 let sender_data = if session.sender_data.should_recalculate() {
1911 let calculated_sender_data = SenderDataFinder::find_using_curve_key(
1930 self.store(),
1931 session.sender_key(),
1932 sender,
1933 session,
1934 )
1935 .await?;
1936
1937 if calculated_sender_data.compare_trust_level(&session.sender_data).is_gt() {
1939 let mut new_session = session.clone();
1941 new_session.sender_data = calculated_sender_data.clone();
1942 self.store().save_inbound_group_sessions(&[new_session]).await?;
1943
1944 calculated_sender_data
1946 } else {
1947 session.sender_data.clone()
1949 }
1950 } else {
1951 session.sender_data.clone()
1952 };
1953
1954 Ok(sender_data)
1955 }
1956
1957 pub async fn query_missing_secrets_from_other_sessions(&self) -> StoreResult<bool> {
1982 let identity = self.inner.user_identity.lock().await;
1983 let mut secrets = identity.get_missing_secrets().await;
1984
1985 if self.store().load_backup_keys().await?.decryption_key.is_none() {
1986 secrets.push(SecretName::RecoveryKey);
1987 }
1988
1989 if secrets.is_empty() {
1990 debug!("No missing requests to query");
1991 return Ok(false);
1992 }
1993
1994 let secret_requests = GossipMachine::request_missing_secrets(self.user_id(), secrets);
1995
1996 let unsent_request = self.store().get_unsent_secret_requests().await?;
1998 let not_yet_requested = secret_requests
1999 .into_iter()
2000 .filter(|request| !unsent_request.iter().any(|unsent| unsent.info == request.info))
2001 .collect_vec();
2002
2003 if not_yet_requested.is_empty() {
2004 debug!("The missing secrets have already been requested");
2005 Ok(false)
2006 } else {
2007 debug!("Requesting missing secrets");
2008
2009 let changes = Changes { key_requests: not_yet_requested, ..Default::default() };
2010
2011 self.store().save_changes(changes).await?;
2012 Ok(true)
2013 }
2014 }
2015
2016 async fn get_encryption_info(
2022 &self,
2023 session: &InboundGroupSession,
2024 sender: &UserId,
2025 ) -> MegolmResult<Arc<EncryptionInfo>> {
2026 let (verification_state, device_id) =
2027 self.get_room_event_verification_state(session, sender).await?;
2028
2029 Ok(Arc::new(EncryptionInfo {
2030 sender: sender.to_owned(),
2031 sender_device: device_id,
2032 forwarder: session.forwarder_data.as_ref().and_then(|data| {
2033 data.device_id().map(|device_id| ForwarderInfo {
2037 device_id: device_id.to_owned(),
2038 user_id: data.user_id().to_owned(),
2039 })
2040 }),
2041 algorithm_info: AlgorithmInfo::MegolmV1AesSha2 {
2042 curve25519_key: session.sender_key().to_base64(),
2043 sender_claimed_keys: session
2044 .signing_keys()
2045 .iter()
2046 .map(|(k, v)| (k.to_owned(), v.to_base64()))
2047 .collect(),
2048 session_id: Some(session.session_id().to_owned()),
2049 },
2050 verification_state,
2051 }))
2052 }
2053
2054 async fn decrypt_megolm_events(
2055 &self,
2056 room_id: &RoomId,
2057 event: &EncryptedEvent,
2058 content: &SupportedEventEncryptionSchemes<'_>,
2059 decryption_settings: &DecryptionSettings,
2060 ) -> MegolmResult<(JsonObject, Arc<EncryptionInfo>)> {
2061 let session =
2062 self.get_inbound_group_session_or_error(room_id, content.session_id()).await?;
2063
2064 Span::current().record("sender_key", debug(session.sender_key()));
2070
2071 let result = session.decrypt(event).await;
2072 match result {
2073 Ok((decrypted_event, _)) => {
2074 let encryption_info = self.get_encryption_info(&session, &event.sender).await?;
2075
2076 self.check_sender_trust_requirement(
2077 &session,
2078 &encryption_info,
2079 &decryption_settings.sender_device_trust_requirement,
2080 )?;
2081
2082 Ok((decrypted_event, encryption_info))
2083 }
2084 Err(error) => Err(
2085 if let MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) = error {
2086 let withheld_code = self
2087 .inner
2088 .store
2089 .get_withheld_info(room_id, content.session_id())
2090 .await?
2091 .map(|e| e.content.withheld_code());
2092
2093 if withheld_code.is_some() {
2094 MegolmError::MissingRoomKey(withheld_code)
2096 } else {
2097 error
2098 }
2099 } else {
2100 error
2101 },
2102 ),
2103 }
2104 }
2105
2106 fn check_sender_trust_requirement(
2112 &self,
2113 session: &InboundGroupSession,
2114 encryption_info: &EncryptionInfo,
2115 trust_requirement: &TrustRequirement,
2116 ) -> MegolmResult<()> {
2117 trace!(
2118 verification_state = ?encryption_info.verification_state,
2119 ?trust_requirement, "check_sender_trust_requirement",
2120 );
2121
2122 let verification_level = match &encryption_info.verification_state {
2125 VerificationState::Verified => return Ok(()),
2126 VerificationState::Unverified(verification_level) => verification_level,
2127 };
2128
2129 let ok = match trust_requirement {
2130 TrustRequirement::Untrusted => true,
2131
2132 TrustRequirement::CrossSignedOrLegacy => {
2133 let legacy_session = match session.sender_data {
2139 SenderData::DeviceInfo { legacy_session, .. } => legacy_session,
2140 SenderData::UnknownDevice { legacy_session, .. } => legacy_session,
2141 _ => false,
2142 };
2143
2144 match (verification_level, legacy_session) {
2154 (VerificationLevel::UnverifiedIdentity, _) => true,
2156
2157 (VerificationLevel::UnsignedDevice, true) => true,
2159
2160 (VerificationLevel::None(_), true) => true,
2162
2163 (VerificationLevel::VerificationViolation, _)
2165 | (VerificationLevel::MismatchedSender, _)
2166 | (VerificationLevel::UnsignedDevice, false)
2167 | (VerificationLevel::None(_), false) => false,
2168 }
2169 }
2170
2171 TrustRequirement::CrossSigned => match verification_level {
2174 VerificationLevel::UnverifiedIdentity => true,
2175
2176 VerificationLevel::VerificationViolation
2177 | VerificationLevel::MismatchedSender
2178 | VerificationLevel::UnsignedDevice
2179 | VerificationLevel::None(_) => false,
2180 },
2181 };
2182
2183 if ok {
2184 Ok(())
2185 } else {
2186 Err(MegolmError::SenderIdentityNotTrusted(verification_level.clone()))
2187 }
2188 }
2189
2190 async fn get_inbound_group_session_or_error(
2195 &self,
2196 room_id: &RoomId,
2197 session_id: &str,
2198 ) -> MegolmResult<InboundGroupSession> {
2199 match self.store().get_inbound_group_session(room_id, session_id).await? {
2200 Some(session) => Ok(session),
2201 None => {
2202 let withheld_code = self
2203 .inner
2204 .store
2205 .get_withheld_info(room_id, session_id)
2206 .await?
2207 .map(|e| e.content.withheld_code());
2208 Err(MegolmError::MissingRoomKey(withheld_code))
2209 }
2210 }
2211 }
2212
2213 pub async fn try_decrypt_room_event(
2228 &self,
2229 raw_event: &Raw<EncryptedEvent>,
2230 room_id: &RoomId,
2231 decryption_settings: &DecryptionSettings,
2232 ) -> Result<RoomEventDecryptionResult, CryptoStoreError> {
2233 match self.decrypt_room_event_inner(raw_event, room_id, true, decryption_settings).await {
2234 Ok(decrypted) => Ok(RoomEventDecryptionResult::Decrypted(decrypted)),
2235 Err(err) => Ok(RoomEventDecryptionResult::UnableToDecrypt(megolm_error_to_utd_info(
2236 raw_event, err,
2237 )?)),
2238 }
2239 }
2240
2241 pub async fn decrypt_room_event(
2249 &self,
2250 event: &Raw<EncryptedEvent>,
2251 room_id: &RoomId,
2252 decryption_settings: &DecryptionSettings,
2253 ) -> MegolmResult<DecryptedRoomEvent> {
2254 self.decrypt_room_event_inner(event, room_id, true, decryption_settings).await
2255 }
2256
2257 #[instrument(name = "decrypt_room_event", skip_all, fields(?room_id, event_id, origin_server_ts, sender, algorithm, session_id, message_index, sender_key))]
2258 async fn decrypt_room_event_inner(
2259 &self,
2260 event: &Raw<EncryptedEvent>,
2261 room_id: &RoomId,
2262 decrypt_unsigned: bool,
2263 decryption_settings: &DecryptionSettings,
2264 ) -> MegolmResult<DecryptedRoomEvent> {
2265 let _timer = timer!(tracing::Level::TRACE, "_method");
2266
2267 let event = event.deserialize()?;
2268
2269 Span::current()
2270 .record("sender", debug(&event.sender))
2271 .record("event_id", debug(&event.event_id))
2272 .record(
2273 "origin_server_ts",
2274 timestamp_to_iso8601(event.origin_server_ts)
2275 .unwrap_or_else(|| "<out of range>".to_owned()),
2276 )
2277 .record("algorithm", debug(event.content.algorithm()));
2278
2279 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2280 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2281 Span::current().record("sender_key", debug(c.sender_key));
2282 c.into()
2283 }
2284 #[cfg(feature = "experimental-algorithms")]
2285 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2286 RoomEventEncryptionScheme::Unknown(_) => {
2287 warn!("Received an encrypted room event with an unsupported algorithm");
2288 return Err(EventError::UnsupportedAlgorithm.into());
2289 }
2290 };
2291
2292 Span::current().record("session_id", content.session_id());
2293 Span::current().record("message_index", content.message_index());
2294
2295 let result =
2296 self.decrypt_megolm_events(room_id, &event, &content, decryption_settings).await;
2297
2298 if let Err(e) = &result {
2299 #[cfg(feature = "automatic-room-key-forwarding")]
2300 match e {
2301 MegolmError::MissingRoomKey(_)
2304 | MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
2305 self.inner
2306 .key_request_machine
2307 .create_outgoing_key_request(room_id, &event)
2308 .await?;
2309 }
2310 _ => {}
2311 }
2312
2313 warn!("Failed to decrypt a room event: {e}");
2314 }
2315
2316 let (mut decrypted_event, encryption_info) = result?;
2317
2318 let mut unsigned_encryption_info = None;
2319 if decrypt_unsigned {
2320 unsigned_encryption_info = self
2322 .decrypt_unsigned_events(&mut decrypted_event, room_id, decryption_settings)
2323 .await;
2324 }
2325
2326 let decrypted_event =
2327 serde_json::from_value::<Raw<AnyTimelineEvent>>(decrypted_event.into())?;
2328
2329 #[cfg(feature = "experimental-encrypted-state-events")]
2330 self.verify_packed_state_key(&event, &decrypted_event)?;
2331
2332 Ok(DecryptedRoomEvent { event: decrypted_event, encryption_info, unsigned_encryption_info })
2333 }
2334
2335 #[cfg(feature = "experimental-encrypted-state-events")]
2352 fn verify_packed_state_key(
2353 &self,
2354 original: &EncryptedEvent,
2355 decrypted: &Raw<AnyTimelineEvent>,
2356 ) -> MegolmResult<()> {
2357 use serde::Deserialize;
2358
2359 #[derive(Deserialize)]
2361 struct PayloadDeserializationHelper {
2362 state_key: Option<String>,
2363 #[serde(rename = "type")]
2364 event_type: String,
2365 }
2366
2367 let PayloadDeserializationHelper {
2369 state_key: inner_state_key,
2370 event_type: inner_event_type,
2371 } = decrypted
2372 .deserialize_as_unchecked()
2373 .map_err(|_| MegolmError::StateKeyVerificationFailed)?;
2374
2375 let (raw_state_key, inner_state_key) = match (&original.state_key, &inner_state_key) {
2377 (Some(raw_state_key), Some(inner_state_key)) => (raw_state_key, inner_state_key),
2378 (None, None) => return Ok(()),
2379 _ => return Err(MegolmError::StateKeyVerificationFailed),
2380 };
2381
2382 let (outer_event_type, outer_state_key) =
2384 raw_state_key.split_once(":").ok_or(MegolmError::StateKeyVerificationFailed)?;
2385
2386 if outer_event_type != inner_event_type {
2388 return Err(MegolmError::StateKeyVerificationFailed);
2389 }
2390
2391 if outer_state_key != inner_state_key {
2393 return Err(MegolmError::StateKeyVerificationFailed);
2394 }
2395 Ok(())
2396 }
2397
2398 async fn decrypt_unsigned_events(
2408 &self,
2409 main_event: &mut JsonObject,
2410 room_id: &RoomId,
2411 decryption_settings: &DecryptionSettings,
2412 ) -> Option<BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>> {
2413 let unsigned = main_event.get_mut("unsigned")?.as_object_mut()?;
2414 let mut unsigned_encryption_info: Option<
2415 BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>,
2416 > = None;
2417
2418 let location = UnsignedEventLocation::RelationsReplace;
2420 let replace = location.find_mut(unsigned);
2421 if let Some(decryption_result) =
2422 self.decrypt_unsigned_event(replace, room_id, decryption_settings).await
2423 {
2424 unsigned_encryption_info
2425 .get_or_insert_with(Default::default)
2426 .insert(location, decryption_result);
2427 }
2428
2429 let location = UnsignedEventLocation::RelationsThreadLatestEvent;
2432 let thread_latest_event = location.find_mut(unsigned);
2433 if let Some(decryption_result) =
2434 self.decrypt_unsigned_event(thread_latest_event, room_id, decryption_settings).await
2435 {
2436 unsigned_encryption_info
2437 .get_or_insert_with(Default::default)
2438 .insert(location, decryption_result);
2439 }
2440
2441 unsigned_encryption_info
2442 }
2443
2444 fn decrypt_unsigned_event<'a>(
2452 &'a self,
2453 event: Option<&'a mut Value>,
2454 room_id: &'a RoomId,
2455 decryption_settings: &'a DecryptionSettings,
2456 ) -> BoxFuture<'a, Option<UnsignedDecryptionResult>> {
2457 Box::pin(async move {
2458 let event = event?;
2459
2460 let is_encrypted = event
2461 .get("type")
2462 .and_then(|type_| type_.as_str())
2463 .is_some_and(|s| s == "m.room.encrypted");
2464 if !is_encrypted {
2465 return None;
2466 }
2467
2468 let raw_event = serde_json::from_value(event.clone()).ok()?;
2469 match self
2470 .decrypt_room_event_inner(&raw_event, room_id, false, decryption_settings)
2471 .await
2472 {
2473 Ok(decrypted_event) => {
2474 *event = serde_json::to_value(decrypted_event.event).ok()?;
2476 Some(UnsignedDecryptionResult::Decrypted(decrypted_event.encryption_info))
2477 }
2478 Err(err) => {
2479 let utd_info = megolm_error_to_utd_info(&raw_event, err).ok()?;
2484 Some(UnsignedDecryptionResult::UnableToDecrypt(utd_info))
2485 }
2486 }
2487 })
2488 }
2489
2490 pub async fn is_room_key_available(
2497 &self,
2498 event: &Raw<EncryptedEvent>,
2499 room_id: &RoomId,
2500 ) -> Result<bool, CryptoStoreError> {
2501 let event = event.deserialize()?;
2502
2503 let (session_id, message_index) = match &event.content.scheme {
2504 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2505 (&c.session_id, c.ciphertext.message_index())
2506 }
2507 #[cfg(feature = "experimental-algorithms")]
2508 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => {
2509 (&c.session_id, c.ciphertext.message_index())
2510 }
2511 RoomEventEncryptionScheme::Unknown(_) => {
2512 return Ok(false);
2514 }
2515 };
2516
2517 Ok(self
2520 .store()
2521 .get_inbound_group_session(room_id, session_id)
2522 .await?
2523 .filter(|s| s.first_known_index() <= message_index)
2524 .is_some())
2525 }
2526
2527 #[instrument(skip(self, event), fields(event_id, sender, session_id))]
2540 pub async fn get_room_event_encryption_info(
2541 &self,
2542 event: &Raw<EncryptedEvent>,
2543 room_id: &RoomId,
2544 ) -> MegolmResult<Arc<EncryptionInfo>> {
2545 let event = event.deserialize()?;
2546
2547 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2548 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => c.into(),
2549 #[cfg(feature = "experimental-algorithms")]
2550 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2551 RoomEventEncryptionScheme::Unknown(_) => {
2552 return Err(EventError::UnsupportedAlgorithm.into());
2553 }
2554 };
2555
2556 Span::current()
2557 .record("sender", debug(&event.sender))
2558 .record("event_id", debug(&event.event_id))
2559 .record("session_id", content.session_id());
2560
2561 self.get_session_encryption_info(room_id, content.session_id(), &event.sender).await
2562 }
2563
2564 pub async fn get_session_encryption_info(
2579 &self,
2580 room_id: &RoomId,
2581 session_id: &str,
2582 sender: &UserId,
2583 ) -> MegolmResult<Arc<EncryptionInfo>> {
2584 let session = self.get_inbound_group_session_or_error(room_id, session_id).await?;
2585 self.get_encryption_info(&session, sender).await
2586 }
2587
2588 pub async fn update_tracked_users(
2606 &self,
2607 users: impl IntoIterator<Item = &UserId>,
2608 ) -> StoreResult<()> {
2609 self.inner.identity_manager.update_tracked_users(users).await
2610 }
2611
2612 pub async fn mark_all_tracked_users_as_dirty(&self) -> StoreResult<()> {
2617 self.inner
2618 .identity_manager
2619 .mark_all_tracked_users_as_dirty(self.inner.store.cache().await?)
2620 .await
2621 }
2622
2623 async fn wait_if_user_pending(
2624 &self,
2625 user_id: &UserId,
2626 timeout: Option<Duration>,
2627 ) -> StoreResult<()> {
2628 if let Some(timeout) = timeout {
2629 let cache = self.store().cache().await?;
2630 self.inner
2631 .identity_manager
2632 .key_query_manager
2633 .wait_if_user_key_query_pending(cache, timeout, user_id)
2634 .await?;
2635 }
2636 Ok(())
2637 }
2638
2639 #[instrument(skip(self))]
2669 pub async fn get_device(
2670 &self,
2671 user_id: &UserId,
2672 device_id: &DeviceId,
2673 timeout: Option<Duration>,
2674 ) -> StoreResult<Option<Device>> {
2675 self.wait_if_user_pending(user_id, timeout).await?;
2676 self.store().get_device(user_id, device_id).await
2677 }
2678
2679 #[instrument(skip(self))]
2693 pub async fn get_identity(
2694 &self,
2695 user_id: &UserId,
2696 timeout: Option<Duration>,
2697 ) -> StoreResult<Option<UserIdentity>> {
2698 self.wait_if_user_pending(user_id, timeout).await?;
2699 self.store().get_identity(user_id).await
2700 }
2701
2702 #[instrument(skip(self))]
2729 pub async fn get_user_devices(
2730 &self,
2731 user_id: &UserId,
2732 timeout: Option<Duration>,
2733 ) -> StoreResult<UserDevices> {
2734 self.wait_if_user_pending(user_id, timeout).await?;
2735 self.store().get_user_devices(user_id).await
2736 }
2737
2738 pub async fn cross_signing_status(&self) -> CrossSigningStatus {
2743 self.inner.user_identity.lock().await.status().await
2744 }
2745
2746 pub async fn export_cross_signing_keys(&self) -> StoreResult<Option<CrossSigningKeyExport>> {
2754 let master_key = self.store().export_secret(&SecretName::CrossSigningMasterKey).await?;
2755 let self_signing_key =
2756 self.store().export_secret(&SecretName::CrossSigningSelfSigningKey).await?;
2757 let user_signing_key =
2758 self.store().export_secret(&SecretName::CrossSigningUserSigningKey).await?;
2759
2760 Ok(if master_key.is_none() && self_signing_key.is_none() && user_signing_key.is_none() {
2761 None
2762 } else {
2763 Some(CrossSigningKeyExport { master_key, self_signing_key, user_signing_key })
2764 })
2765 }
2766
2767 pub async fn import_cross_signing_keys(
2772 &self,
2773 export: CrossSigningKeyExport,
2774 ) -> Result<CrossSigningStatus, SecretImportError> {
2775 self.store().import_cross_signing_keys(export).await
2776 }
2777
2778 async fn sign_with_master_key(
2779 &self,
2780 message: &str,
2781 ) -> Result<(OwnedDeviceKeyId, Ed25519Signature), SignatureError> {
2782 let identity = &*self.inner.user_identity.lock().await;
2783 let key_id = identity.master_key_id().await.ok_or(SignatureError::MissingSigningKey)?;
2784
2785 let signature = identity.sign(message).await?;
2786
2787 Ok((key_id, signature))
2788 }
2789
2790 pub async fn sign(&self, message: &str) -> Result<Signatures, CryptoStoreError> {
2796 let mut signatures = Signatures::new();
2797
2798 {
2799 let cache = self.inner.store.cache().await?;
2800 let account = cache.account().await?;
2801 let key_id = account.signing_key_id();
2802 let signature = account.sign(message);
2803 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
2804 }
2805
2806 match self.sign_with_master_key(message).await {
2807 Ok((key_id, signature)) => {
2808 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
2809 }
2810 Err(e) => {
2811 warn!(error = ?e, "Couldn't sign the message using the cross signing master key")
2812 }
2813 }
2814
2815 Ok(signatures)
2816 }
2817
2818 pub fn backup_machine(&self) -> &BackupMachine {
2823 &self.inner.backup_machine
2824 }
2825
2826 pub async fn initialize_crypto_store_generation(
2830 &self,
2831 generation: &Mutex<Option<u64>>,
2832 ) -> StoreResult<()> {
2833 let mut gen_guard = generation.lock().await;
2836
2837 let prev_generation =
2838 self.inner.store.get_custom_value(Self::CURRENT_GENERATION_STORE_KEY).await?;
2839
2840 let generation = match prev_generation {
2841 Some(val) => {
2842 u64::from_le_bytes(val.try_into().map_err(|_| {
2845 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
2846 })?)
2847 .wrapping_add(1)
2848 }
2849 None => 0,
2850 };
2851
2852 tracing::debug!("Initialising crypto store generation at {generation}");
2853
2854 self.inner
2855 .store
2856 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, generation.to_le_bytes().to_vec())
2857 .await?;
2858
2859 *gen_guard = Some(generation);
2860
2861 Ok(())
2862 }
2863
2864 pub async fn maintain_crypto_store_generation(
2889 &'_ self,
2890 generation: &Mutex<Option<u64>>,
2891 ) -> StoreResult<(bool, u64)> {
2892 let mut gen_guard = generation.lock().await;
2893
2894 let actual_gen = self
2900 .inner
2901 .store
2902 .get_custom_value(Self::CURRENT_GENERATION_STORE_KEY)
2903 .await?
2904 .ok_or_else(|| {
2905 CryptoStoreError::InvalidLockGeneration("counter missing in store".to_owned())
2906 })?;
2907
2908 let actual_gen =
2909 u64::from_le_bytes(actual_gen.try_into().map_err(|_| {
2910 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
2911 })?);
2912
2913 let new_gen = match gen_guard.as_ref() {
2914 Some(expected_gen) => {
2915 if actual_gen == *expected_gen {
2916 return Ok((false, actual_gen));
2917 }
2918 actual_gen.max(*expected_gen).wrapping_add(1)
2920 }
2921 None => {
2922 actual_gen.wrapping_add(1)
2925 }
2926 };
2927
2928 tracing::debug!(
2929 "Crypto store generation mismatch: previously known was {:?}, actual is {:?}, next is {}",
2930 *gen_guard,
2931 actual_gen,
2932 new_gen
2933 );
2934
2935 *gen_guard = Some(new_gen);
2937
2938 self.inner
2940 .store
2941 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, new_gen.to_le_bytes().to_vec())
2942 .await?;
2943
2944 Ok((true, new_gen))
2945 }
2946
2947 pub fn dehydrated_devices(&self) -> DehydratedDevices {
2949 DehydratedDevices { inner: self.to_owned() }
2950 }
2951
2952 pub async fn room_settings(&self, room_id: &RoomId) -> StoreResult<Option<RoomSettings>> {
2957 self.inner.store.get_room_settings(room_id).await
2960 }
2961
2962 pub async fn set_room_settings(
2973 &self,
2974 room_id: &RoomId,
2975 new_settings: &RoomSettings,
2976 ) -> Result<(), SetRoomSettingsError> {
2977 let store = &self.inner.store;
2978
2979 let _store_transaction = store.transaction().await;
2984
2985 let old_settings = store.get_room_settings(room_id).await?;
2986
2987 if let Some(old_settings) = old_settings {
3000 if old_settings != *new_settings {
3001 return Err(SetRoomSettingsError::EncryptionDowngrade);
3002 } else {
3003 return Ok(());
3005 }
3006 }
3007
3008 match new_settings.algorithm {
3010 EventEncryptionAlgorithm::MegolmV1AesSha2 => (),
3011
3012 #[cfg(feature = "experimental-algorithms")]
3013 EventEncryptionAlgorithm::MegolmV2AesSha2 => (),
3014
3015 _ => {
3016 warn!(
3017 ?room_id,
3018 "Rejecting invalid encryption algorithm {}", new_settings.algorithm
3019 );
3020 return Err(SetRoomSettingsError::InvalidSettings);
3021 }
3022 }
3023
3024 store
3026 .save_changes(Changes {
3027 room_settings: HashMap::from([(room_id.to_owned(), new_settings.clone())]),
3028 ..Default::default()
3029 })
3030 .await?;
3031
3032 Ok(())
3033 }
3034
3035 #[cfg(any(feature = "testing", test))]
3039 pub fn same_as(&self, other: &OlmMachine) -> bool {
3040 Arc::ptr_eq(&self.inner, &other.inner)
3041 }
3042
3043 #[cfg(any(feature = "testing", test))]
3045 pub async fn uploaded_key_count(&self) -> Result<u64, CryptoStoreError> {
3046 let cache = self.inner.store.cache().await?;
3047 let account = cache.account().await?;
3048 Ok(account.uploaded_key_count())
3049 }
3050
3051 #[cfg(test)]
3053 pub(crate) fn identity_manager(&self) -> &IdentityManager {
3054 &self.inner.identity_manager
3055 }
3056
3057 #[cfg(test)]
3059 pub(crate) fn key_for_has_migrated_verification_latch() -> &'static str {
3060 Self::HAS_MIGRATED_VERIFICATION_LATCH
3061 }
3062}
3063
3064fn sender_data_to_verification_state(
3065 sender_data: SenderData,
3066 session_has_been_imported: bool,
3067) -> (VerificationState, Option<OwnedDeviceId>) {
3068 match sender_data {
3069 SenderData::UnknownDevice { owner_check_failed: false, .. } => {
3070 let device_link_problem = if session_has_been_imported {
3071 DeviceLinkProblem::InsecureSource
3072 } else {
3073 DeviceLinkProblem::MissingDevice
3074 };
3075
3076 (VerificationState::Unverified(VerificationLevel::None(device_link_problem)), None)
3077 }
3078 SenderData::UnknownDevice { owner_check_failed: true, .. } => (
3079 VerificationState::Unverified(VerificationLevel::None(
3080 DeviceLinkProblem::InsecureSource,
3081 )),
3082 None,
3083 ),
3084 SenderData::DeviceInfo { device_keys, .. } => (
3085 VerificationState::Unverified(VerificationLevel::UnsignedDevice),
3086 Some(device_keys.device_id),
3087 ),
3088 SenderData::VerificationViolation(KnownSenderData { device_id, .. }) => {
3089 (VerificationState::Unverified(VerificationLevel::VerificationViolation), device_id)
3090 }
3091 SenderData::SenderUnverified(KnownSenderData { device_id, .. }) => {
3092 (VerificationState::Unverified(VerificationLevel::UnverifiedIdentity), device_id)
3093 }
3094 SenderData::SenderVerified(KnownSenderData { device_id, .. }) => {
3095 (VerificationState::Verified, device_id)
3096 }
3097 }
3098}
3099
3100#[derive(Debug, Clone)]
3103pub struct CrossSigningBootstrapRequests {
3104 pub upload_keys_req: Option<OutgoingRequest>,
3111
3112 pub upload_signing_keys_req: UploadSigningKeysRequest,
3116
3117 pub upload_signatures_req: UploadSignaturesRequest,
3122}
3123
3124#[derive(Debug)]
3127pub struct EncryptionSyncChanges<'a> {
3128 pub to_device_events: Vec<Raw<AnyToDeviceEvent>>,
3130 pub changed_devices: &'a DeviceLists,
3133 pub one_time_keys_counts: &'a BTreeMap<OneTimeKeyAlgorithm, UInt>,
3135 pub unused_fallback_keys: Option<&'a [OneTimeKeyAlgorithm]>,
3137 pub next_batch_token: Option<String>,
3139}
3140
3141fn megolm_error_to_utd_info(
3149 raw_event: &Raw<EncryptedEvent>,
3150 error: MegolmError,
3151) -> Result<UnableToDecryptInfo, CryptoStoreError> {
3152 use MegolmError::*;
3153 let reason = match error {
3154 EventError(_) => UnableToDecryptReason::MalformedEncryptedEvent,
3155 Decode(_) => UnableToDecryptReason::MalformedEncryptedEvent,
3156 MissingRoomKey(maybe_withheld) => {
3157 UnableToDecryptReason::MissingMegolmSession { withheld_code: maybe_withheld }
3158 }
3159 Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
3160 UnableToDecryptReason::UnknownMegolmMessageIndex
3161 }
3162 Decryption(_) => UnableToDecryptReason::MegolmDecryptionFailure,
3163 JsonError(_) => UnableToDecryptReason::PayloadDeserializationFailure,
3164 MismatchedIdentityKeys(_) => UnableToDecryptReason::MismatchedIdentityKeys,
3165 SenderIdentityNotTrusted(level) => UnableToDecryptReason::SenderIdentityNotTrusted(level),
3166 #[cfg(feature = "experimental-encrypted-state-events")]
3167 StateKeyVerificationFailed => UnableToDecryptReason::StateKeyVerificationFailed,
3168
3169 Store(error) => Err(error)?,
3172 };
3173
3174 let session_id = raw_event.deserialize().ok().and_then(|ev| match ev.content.scheme {
3175 RoomEventEncryptionScheme::MegolmV1AesSha2(s) => Some(s.session_id),
3176 #[cfg(feature = "experimental-algorithms")]
3177 RoomEventEncryptionScheme::MegolmV2AesSha2(s) => Some(s.session_id),
3178 RoomEventEncryptionScheme::Unknown(_) => None,
3179 });
3180
3181 Ok(UnableToDecryptInfo { session_id, reason })
3182}
3183
3184#[derive(Debug, thiserror::Error)]
3194pub(crate) enum DecryptToDeviceError {
3195 #[error("An Olm error occurred meaning we failed to decrypt the event")]
3196 OlmError(#[from] OlmError),
3197
3198 #[error("The event was sent from a dehydrated device")]
3199 FromDehydratedDevice,
3200}
3201
3202impl From<CryptoStoreError> for DecryptToDeviceError {
3203 fn from(value: CryptoStoreError) -> Self {
3204 Self::OlmError(value.into())
3205 }
3206}
3207
3208#[cfg(test)]
3209impl From<DecryptToDeviceError> for OlmError {
3210 fn from(value: DecryptToDeviceError) -> Self {
3213 match value {
3214 DecryptToDeviceError::OlmError(olm_error) => olm_error,
3215 DecryptToDeviceError::FromDehydratedDevice => {
3216 panic!("Expected an OlmError but found FromDehydratedDevice")
3217 }
3218 }
3219 }
3220}
3221
3222#[cfg(test)]
3223pub(crate) mod test_helpers;
3224
3225#[cfg(test)]
3226pub(crate) mod tests;