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,
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, 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 algorithm_info,
1140 verification_state: VerificationState::Verified,
1141 }
1142 }
1143
1144 #[cfg(feature = "experimental-encrypted-state-events")]
1156 pub async fn encrypt_state_event<C, K>(
1157 &self,
1158 room_id: &RoomId,
1159 content: C,
1160 state_key: K,
1161 ) -> MegolmResult<Raw<RoomEncryptedEventContent>>
1162 where
1163 C: StateEventContent,
1164 C::StateKey: Borrow<K>,
1165 K: AsRef<str>,
1166 {
1167 let event_type = content.event_type().to_string();
1168 let content = Raw::new(&content)?.cast_unchecked();
1169 self.encrypt_state_event_raw(room_id, &event_type, state_key.as_ref(), &content).await
1170 }
1171
1172 #[cfg(feature = "experimental-encrypted-state-events")]
1191 pub async fn encrypt_state_event_raw(
1192 &self,
1193 room_id: &RoomId,
1194 event_type: &str,
1195 state_key: &str,
1196 content: &Raw<AnyStateEventContent>,
1197 ) -> MegolmResult<Raw<RoomEncryptedEventContent>> {
1198 self.inner
1199 .group_session_manager
1200 .encrypt_state(room_id, event_type, state_key, content)
1201 .await
1202 }
1203
1204 pub async fn discard_room_key(&self, room_id: &RoomId) -> StoreResult<bool> {
1215 self.inner.group_session_manager.invalidate_group_session(room_id).await
1216 }
1217
1218 pub async fn share_room_key(
1238 &self,
1239 room_id: &RoomId,
1240 users: impl Iterator<Item = &UserId>,
1241 encryption_settings: impl Into<EncryptionSettings>,
1242 ) -> OlmResult<Vec<Arc<ToDeviceRequest>>> {
1243 self.inner.group_session_manager.share_room_key(room_id, users, encryption_settings).await
1244 }
1245
1246 #[cfg(feature = "experimental-send-custom-to-device")]
1260 pub async fn encrypt_content_for_devices(
1261 &self,
1262 devices: Vec<DeviceData>,
1263 event_type: &str,
1264 content: &Value,
1265 share_strategy: CollectStrategy,
1266 ) -> OlmResult<(Vec<ToDeviceRequest>, Vec<(DeviceData, WithheldCode)>)> {
1267 let mut changes = Changes::default();
1268
1269 let (allowed_devices, mut blocked_devices) =
1270 split_devices_for_share_strategy(&self.inner.store, devices, share_strategy).await?;
1271
1272 let result = self
1273 .inner
1274 .group_session_manager
1275 .encrypt_content_for_devices(allowed_devices, event_type, content.clone(), &mut changes)
1276 .await;
1277
1278 if !changes.is_empty() {
1280 let session_count = changes.sessions.len();
1281
1282 self.inner.store.save_changes(changes).await?;
1283
1284 trace!(
1285 session_count = session_count,
1286 "Stored the changed sessions after encrypting a custom to-device event"
1287 );
1288 }
1289
1290 result.map(|(to_device_requests, mut withheld)| {
1291 withheld.append(&mut blocked_devices);
1292 (to_device_requests, withheld)
1293 })
1294 }
1295 pub async fn share_room_key_bundle_data(
1300 &self,
1301 user_id: &UserId,
1302 collect_strategy: &CollectStrategy,
1303 bundle_data: RoomKeyBundleContent,
1304 ) -> OlmResult<Vec<ToDeviceRequest>> {
1305 self.inner
1306 .group_session_manager
1307 .share_room_key_bundle_data(user_id, collect_strategy, bundle_data)
1308 .await
1309 }
1310
1311 #[deprecated(note = "Use OlmMachine::receive_verification_event instead", since = "0.7.0")]
1319 pub async fn receive_unencrypted_verification_event(
1320 &self,
1321 event: &AnyMessageLikeEvent,
1322 ) -> StoreResult<()> {
1323 self.inner.verification_machine.receive_any_event(event).await
1324 }
1325
1326 pub async fn receive_verification_event(&self, event: &AnyMessageLikeEvent) -> StoreResult<()> {
1339 self.inner.verification_machine.receive_any_event(event).await
1340 }
1341
1342 #[instrument(
1348 skip_all,
1349 fields(
1350 sender_key = ?decrypted.result.sender_key,
1351 event_type = decrypted.result.event.event_type(),
1352 ),
1353 )]
1354 async fn handle_decrypted_to_device_event(
1355 &self,
1356 cache: &StoreCache,
1357 decrypted: &mut OlmDecryptionInfo,
1358 changes: &mut Changes,
1359 ) -> OlmResult<()> {
1360 debug!(
1361 sender_device_keys =
1362 ?decrypted.result.event.sender_device_keys().map(|k| (k.curve25519_key(), k.ed25519_key())).unwrap_or((None, None)),
1363 "Received a decrypted to-device event",
1364 );
1365
1366 match &*decrypted.result.event {
1367 AnyDecryptedOlmEvent::RoomKey(e) => {
1368 let session = self.add_room_key(decrypted.result.sender_key, e).await?;
1369 decrypted.inbound_group_session = session;
1370 }
1371 AnyDecryptedOlmEvent::ForwardedRoomKey(e) => {
1372 let session = self
1373 .inner
1374 .key_request_machine
1375 .receive_forwarded_room_key(decrypted.result.sender_key, e)
1376 .await?;
1377 decrypted.inbound_group_session = session;
1378 }
1379 AnyDecryptedOlmEvent::SecretSend(e) => {
1380 let name = self
1381 .inner
1382 .key_request_machine
1383 .receive_secret_event(cache, decrypted.result.sender_key, e, changes)
1384 .await?;
1385
1386 if let Ok(ToDeviceEvents::SecretSend(mut e)) =
1389 decrypted.result.raw_event.deserialize_as()
1390 {
1391 e.content.secret_name = name;
1392 decrypted.result.raw_event = Raw::from_json(to_raw_value(&e)?);
1393 }
1394 }
1395 AnyDecryptedOlmEvent::Dummy(_) => {
1396 debug!("Received an `m.dummy` event");
1397 }
1398 AnyDecryptedOlmEvent::RoomKeyBundle(e) => {
1399 debug!("Received a room key bundle event {:?}", e);
1400 self.receive_room_key_bundle_data(decrypted.result.sender_key, e, changes).await?;
1401 }
1402 AnyDecryptedOlmEvent::Custom(_) => {
1403 warn!("Received an unexpected encrypted to-device event");
1404 }
1405 }
1406
1407 Ok(())
1408 }
1409
1410 async fn handle_verification_event(&self, event: &ToDeviceEvents) {
1411 if let Err(e) = self.inner.verification_machine.receive_any_event(event).await {
1412 error!("Error handling a verification event: {e:?}");
1413 }
1414 }
1415
1416 async fn mark_to_device_request_as_sent(&self, request_id: &TransactionId) -> StoreResult<()> {
1418 self.inner.verification_machine.mark_request_as_sent(request_id);
1419 self.inner.key_request_machine.mark_outgoing_request_as_sent(request_id).await?;
1420 self.inner.group_session_manager.mark_request_as_sent(request_id).await?;
1421 self.inner.session_manager.mark_outgoing_request_as_sent(request_id);
1422 Ok(())
1423 }
1424
1425 pub fn get_verification(&self, user_id: &UserId, flow_id: &str) -> Option<Verification> {
1427 self.inner.verification_machine.get_verification(user_id, flow_id)
1428 }
1429
1430 pub fn get_verification_request(
1432 &self,
1433 user_id: &UserId,
1434 flow_id: impl AsRef<str>,
1435 ) -> Option<VerificationRequest> {
1436 self.inner.verification_machine.get_request(user_id, flow_id)
1437 }
1438
1439 pub fn get_verification_requests(&self, user_id: &UserId) -> Vec<VerificationRequest> {
1441 self.inner.verification_machine.get_requests(user_id)
1442 }
1443
1444 async fn handle_to_device_event(&self, changes: &mut Changes, event: &ToDeviceEvents) {
1449 use crate::types::events::ToDeviceEvents::*;
1450
1451 match event {
1452 RoomKeyRequest(e) => self.inner.key_request_machine.receive_incoming_key_request(e),
1458 SecretRequest(e) => self.inner.key_request_machine.receive_incoming_secret_request(e),
1459 RoomKeyWithheld(e) => self.add_withheld_info(changes, e),
1460 KeyVerificationAccept(..)
1461 | KeyVerificationCancel(..)
1462 | KeyVerificationKey(..)
1463 | KeyVerificationMac(..)
1464 | KeyVerificationRequest(..)
1465 | KeyVerificationReady(..)
1466 | KeyVerificationDone(..)
1467 | KeyVerificationStart(..) => {
1468 self.handle_verification_event(event).await;
1469 }
1470
1471 Custom(_) | Dummy(_) => {}
1473
1474 RoomEncrypted(_) => {}
1476
1477 SecretSend(_) | RoomKey(_) | ForwardedRoomKey(_) => {}
1480 }
1481 }
1482
1483 fn record_message_id(event: &Raw<AnyToDeviceEvent>) {
1484 use serde::Deserialize;
1485
1486 #[derive(Deserialize)]
1487 struct ContentStub<'a> {
1488 #[serde(borrow, rename = "org.matrix.msgid")]
1489 message_id: Option<&'a str>,
1490 }
1491 #[derive(Deserialize)]
1492 struct ToDeviceStub<'a> {
1493 sender: &'a str,
1494 #[serde(rename = "type")]
1495 event_type: &'a str,
1496 #[serde(borrow)]
1497 content: ContentStub<'a>,
1498 }
1499
1500 if let Ok(event) = event.deserialize_as_unchecked::<ToDeviceStub<'_>>() {
1501 Span::current().record("sender", event.sender);
1502 Span::current().record("event_type", event.event_type);
1503 Span::current().record("message_id", event.content.message_id);
1504 }
1505 }
1506
1507 #[instrument(skip_all, fields(sender, event_type, message_id))]
1515 async fn receive_to_device_event(
1516 &self,
1517 transaction: &mut StoreTransaction,
1518 changes: &mut Changes,
1519 raw_event: Raw<AnyToDeviceEvent>,
1520 decryption_settings: &DecryptionSettings,
1521 ) -> Option<ProcessedToDeviceEvent> {
1522 Self::record_message_id(&raw_event);
1523
1524 let event: ToDeviceEvents = match raw_event.deserialize_as() {
1525 Ok(e) => e,
1526 Err(e) => {
1527 warn!("Received an invalid to-device event: {e}");
1529 return Some(ProcessedToDeviceEvent::Invalid(raw_event));
1530 }
1531 };
1532
1533 debug!("Received a to-device event");
1534
1535 match event {
1536 ToDeviceEvents::RoomEncrypted(e) => {
1537 self.receive_encrypted_to_device_event(
1538 transaction,
1539 changes,
1540 raw_event,
1541 e,
1542 decryption_settings,
1543 )
1544 .await
1545 }
1546 e => {
1547 self.handle_to_device_event(changes, &e).await;
1548 Some(ProcessedToDeviceEvent::PlainText(raw_event))
1549 }
1550 }
1551 }
1552
1553 async fn receive_encrypted_to_device_event(
1567 &self,
1568 transaction: &mut StoreTransaction,
1569 changes: &mut Changes,
1570 mut raw_event: Raw<AnyToDeviceEvent>,
1571 e: ToDeviceEvent<ToDeviceEncryptedEventContent>,
1572 decryption_settings: &DecryptionSettings,
1573 ) -> Option<ProcessedToDeviceEvent> {
1574 let decrypted = match self
1575 .decrypt_to_device_event(transaction, &e, changes, decryption_settings)
1576 .await
1577 {
1578 Ok(decrypted) => decrypted,
1579 Err(DecryptToDeviceError::OlmError(err)) => {
1580 let reason = if let OlmError::UnverifiedSenderDevice = &err {
1581 ToDeviceUnableToDecryptReason::UnverifiedSenderDevice
1582 } else {
1583 ToDeviceUnableToDecryptReason::DecryptionFailure
1584 };
1585
1586 if let OlmError::SessionWedged(sender, curve_key) = err
1587 && let Err(e) =
1588 self.inner.session_manager.mark_device_as_wedged(&sender, curve_key).await
1589 {
1590 error!(
1591 error = ?e,
1592 "Couldn't mark device to be unwedged",
1593 );
1594 }
1595
1596 return Some(ProcessedToDeviceEvent::UnableToDecrypt {
1597 encrypted_event: raw_event,
1598 utd_info: ToDeviceUnableToDecryptInfo { reason },
1599 });
1600 }
1601 Err(DecryptToDeviceError::FromDehydratedDevice) => return None,
1602 };
1603
1604 match decrypted.session {
1607 SessionType::New(s) | SessionType::Existing(s) => {
1608 changes.sessions.push(s);
1609 }
1610 }
1611
1612 changes.message_hashes.push(decrypted.message_hash);
1613
1614 if let Some(group_session) = decrypted.inbound_group_session {
1615 changes.inbound_group_sessions.push(group_session);
1616 }
1617
1618 match decrypted.result.raw_event.deserialize_as() {
1619 Ok(event) => {
1620 self.handle_to_device_event(changes, &event).await;
1621
1622 raw_event = event
1623 .serialize_zeroized()
1624 .expect("Zeroizing and reserializing our events should always work")
1625 .cast();
1626 }
1627 Err(e) => {
1628 warn!("Received an invalid encrypted to-device event: {e}");
1629 raw_event = decrypted.result.raw_event;
1630 }
1631 }
1632
1633 Some(ProcessedToDeviceEvent::Decrypted {
1634 raw: raw_event,
1635 encryption_info: decrypted.result.encryption_info,
1636 })
1637 }
1638
1639 async fn check_to_device_event_is_not_from_dehydrated_device(
1642 &self,
1643 decrypted: &OlmDecryptionInfo,
1644 sender_user_id: &UserId,
1645 ) -> Result<(), DecryptToDeviceError> {
1646 if self.to_device_event_is_from_dehydrated_device(decrypted, sender_user_id).await? {
1647 warn!(
1648 sender = ?sender_user_id,
1649 session = ?decrypted.session,
1650 "Received a to-device event from a dehydrated device. This is unexpected: ignoring event"
1651 );
1652 Err(DecryptToDeviceError::FromDehydratedDevice)
1653 } else {
1654 Ok(())
1655 }
1656 }
1657
1658 async fn to_device_event_is_from_dehydrated_device(
1664 &self,
1665 decrypted: &OlmDecryptionInfo,
1666 sender_user_id: &UserId,
1667 ) -> OlmResult<bool> {
1668 if let Some(device_keys) = decrypted.result.event.sender_device_keys() {
1670 if device_keys.dehydrated.unwrap_or(false) {
1676 return Ok(true);
1677 }
1678 }
1683
1684 Ok(self
1686 .store()
1687 .get_device_from_curve_key(sender_user_id, decrypted.result.sender_key)
1688 .await?
1689 .is_some_and(|d| d.is_dehydrated()))
1690 }
1691
1692 #[instrument(skip_all)]
1710 pub async fn receive_sync_changes(
1711 &self,
1712 sync_changes: EncryptionSyncChanges<'_>,
1713 decryption_settings: &DecryptionSettings,
1714 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Vec<RoomKeyInfo>)> {
1715 let mut store_transaction = self.inner.store.transaction().await;
1716
1717 let (events, changes) = self
1718 .preprocess_sync_changes(&mut store_transaction, sync_changes, decryption_settings)
1719 .await?;
1720
1721 let room_key_updates: Vec<_> =
1724 changes.inbound_group_sessions.iter().map(RoomKeyInfo::from).collect();
1725
1726 self.store().save_changes(changes).await?;
1727 store_transaction.commit().await?;
1728
1729 Ok((events, room_key_updates))
1730 }
1731
1732 pub(crate) async fn preprocess_sync_changes(
1750 &self,
1751 transaction: &mut StoreTransaction,
1752 sync_changes: EncryptionSyncChanges<'_>,
1753 decryption_settings: &DecryptionSettings,
1754 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Changes)> {
1755 let mut events: Vec<ProcessedToDeviceEvent> = self
1757 .inner
1758 .verification_machine
1759 .garbage_collect()
1760 .iter()
1761 .map(|e| ProcessedToDeviceEvent::PlainText(e.clone()))
1765 .collect();
1766 let mut changes = Default::default();
1769
1770 {
1771 let account = transaction.account().await?;
1772 account.update_key_counts(
1773 sync_changes.one_time_keys_counts,
1774 sync_changes.unused_fallback_keys,
1775 )
1776 }
1777
1778 if let Err(e) = self
1779 .inner
1780 .identity_manager
1781 .receive_device_changes(
1782 transaction.cache(),
1783 sync_changes.changed_devices.changed.iter().map(|u| u.as_ref()),
1784 )
1785 .await
1786 {
1787 error!(error = ?e, "Error marking a tracked user as changed");
1788 }
1789
1790 for raw_event in sync_changes.to_device_events {
1791 let processed_event = Box::pin(self.receive_to_device_event(
1792 transaction,
1793 &mut changes,
1794 raw_event,
1795 decryption_settings,
1796 ))
1797 .await;
1798
1799 if let Some(processed_event) = processed_event {
1800 events.push(processed_event);
1801 }
1802 }
1803
1804 let changed_sessions = self
1805 .inner
1806 .key_request_machine
1807 .collect_incoming_key_requests(transaction.cache())
1808 .await?;
1809
1810 changes.sessions.extend(changed_sessions);
1811 changes.next_batch_token = sync_changes.next_batch_token;
1812
1813 Ok((events, changes))
1814 }
1815
1816 pub async fn request_room_key(
1833 &self,
1834 event: &Raw<EncryptedEvent>,
1835 room_id: &RoomId,
1836 ) -> MegolmResult<(Option<OutgoingRequest>, OutgoingRequest)> {
1837 let event = event.deserialize()?;
1838 self.inner.key_request_machine.request_key(room_id, &event).await
1839 }
1840
1841 async fn get_room_event_verification_state(
1854 &self,
1855 session: &InboundGroupSession,
1856 sender: &UserId,
1857 ) -> MegolmResult<(VerificationState, Option<OwnedDeviceId>)> {
1858 let sender_data = self.get_or_update_sender_data(session, sender).await?;
1859
1860 let (verification_state, device_id) = match sender_data.user_id() {
1869 Some(i) if i != sender => {
1870 (VerificationState::Unverified(VerificationLevel::MismatchedSender), None)
1871 }
1872
1873 Some(_) | None => {
1874 sender_data_to_verification_state(sender_data, session.has_been_imported())
1875 }
1876 };
1877
1878 Ok((verification_state, device_id))
1879 }
1880
1881 async fn get_or_update_sender_data(
1896 &self,
1897 session: &InboundGroupSession,
1898 sender: &UserId,
1899 ) -> MegolmResult<SenderData> {
1900 let sender_data = if session.sender_data.should_recalculate() {
1901 let calculated_sender_data = SenderDataFinder::find_using_curve_key(
1920 self.store(),
1921 session.sender_key(),
1922 sender,
1923 session,
1924 )
1925 .await?;
1926
1927 if calculated_sender_data.compare_trust_level(&session.sender_data).is_gt() {
1929 let mut new_session = session.clone();
1931 new_session.sender_data = calculated_sender_data.clone();
1932 self.store().save_inbound_group_sessions(&[new_session]).await?;
1933
1934 calculated_sender_data
1936 } else {
1937 session.sender_data.clone()
1939 }
1940 } else {
1941 session.sender_data.clone()
1942 };
1943
1944 Ok(sender_data)
1945 }
1946
1947 pub async fn query_missing_secrets_from_other_sessions(&self) -> StoreResult<bool> {
1972 let identity = self.inner.user_identity.lock().await;
1973 let mut secrets = identity.get_missing_secrets().await;
1974
1975 if self.store().load_backup_keys().await?.decryption_key.is_none() {
1976 secrets.push(SecretName::RecoveryKey);
1977 }
1978
1979 if secrets.is_empty() {
1980 debug!("No missing requests to query");
1981 return Ok(false);
1982 }
1983
1984 let secret_requests = GossipMachine::request_missing_secrets(self.user_id(), secrets);
1985
1986 let unsent_request = self.store().get_unsent_secret_requests().await?;
1988 let not_yet_requested = secret_requests
1989 .into_iter()
1990 .filter(|request| !unsent_request.iter().any(|unsent| unsent.info == request.info))
1991 .collect_vec();
1992
1993 if not_yet_requested.is_empty() {
1994 debug!("The missing secrets have already been requested");
1995 Ok(false)
1996 } else {
1997 debug!("Requesting missing secrets");
1998
1999 let changes = Changes { key_requests: not_yet_requested, ..Default::default() };
2000
2001 self.store().save_changes(changes).await?;
2002 Ok(true)
2003 }
2004 }
2005
2006 async fn get_encryption_info(
2012 &self,
2013 session: &InboundGroupSession,
2014 sender: &UserId,
2015 ) -> MegolmResult<Arc<EncryptionInfo>> {
2016 let (verification_state, device_id) =
2017 self.get_room_event_verification_state(session, sender).await?;
2018
2019 let sender = sender.to_owned();
2020
2021 Ok(Arc::new(EncryptionInfo {
2022 sender,
2023 sender_device: device_id,
2024 algorithm_info: AlgorithmInfo::MegolmV1AesSha2 {
2025 curve25519_key: session.sender_key().to_base64(),
2026 sender_claimed_keys: session
2027 .signing_keys()
2028 .iter()
2029 .map(|(k, v)| (k.to_owned(), v.to_base64()))
2030 .collect(),
2031 session_id: Some(session.session_id().to_owned()),
2032 },
2033 verification_state,
2034 }))
2035 }
2036
2037 async fn decrypt_megolm_events(
2038 &self,
2039 room_id: &RoomId,
2040 event: &EncryptedEvent,
2041 content: &SupportedEventEncryptionSchemes<'_>,
2042 decryption_settings: &DecryptionSettings,
2043 ) -> MegolmResult<(JsonObject, Arc<EncryptionInfo>)> {
2044 let session =
2045 self.get_inbound_group_session_or_error(room_id, content.session_id()).await?;
2046
2047 Span::current().record("sender_key", debug(session.sender_key()));
2053
2054 let result = session.decrypt(event).await;
2055 match result {
2056 Ok((decrypted_event, _)) => {
2057 let encryption_info = self.get_encryption_info(&session, &event.sender).await?;
2058
2059 self.check_sender_trust_requirement(
2060 &session,
2061 &encryption_info,
2062 &decryption_settings.sender_device_trust_requirement,
2063 )?;
2064
2065 Ok((decrypted_event, encryption_info))
2066 }
2067 Err(error) => Err(
2068 if let MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) = error {
2069 let withheld_code = self
2070 .inner
2071 .store
2072 .get_withheld_info(room_id, content.session_id())
2073 .await?
2074 .map(|e| e.content.withheld_code());
2075
2076 if withheld_code.is_some() {
2077 MegolmError::MissingRoomKey(withheld_code)
2079 } else {
2080 error
2081 }
2082 } else {
2083 error
2084 },
2085 ),
2086 }
2087 }
2088
2089 fn check_sender_trust_requirement(
2095 &self,
2096 session: &InboundGroupSession,
2097 encryption_info: &EncryptionInfo,
2098 trust_requirement: &TrustRequirement,
2099 ) -> MegolmResult<()> {
2100 trace!(
2101 verification_state = ?encryption_info.verification_state,
2102 ?trust_requirement, "check_sender_trust_requirement",
2103 );
2104
2105 let verification_level = match &encryption_info.verification_state {
2108 VerificationState::Verified => return Ok(()),
2109 VerificationState::Unverified(verification_level) => verification_level,
2110 };
2111
2112 let ok = match trust_requirement {
2113 TrustRequirement::Untrusted => true,
2114
2115 TrustRequirement::CrossSignedOrLegacy => {
2116 let legacy_session = match session.sender_data {
2122 SenderData::DeviceInfo { legacy_session, .. } => legacy_session,
2123 SenderData::UnknownDevice { legacy_session, .. } => legacy_session,
2124 _ => false,
2125 };
2126
2127 match (verification_level, legacy_session) {
2137 (VerificationLevel::UnverifiedIdentity, _) => true,
2139
2140 (VerificationLevel::UnsignedDevice, true) => true,
2142
2143 (VerificationLevel::None(_), true) => true,
2145
2146 (VerificationLevel::VerificationViolation, _)
2148 | (VerificationLevel::MismatchedSender, _)
2149 | (VerificationLevel::UnsignedDevice, false)
2150 | (VerificationLevel::None(_), false) => false,
2151 }
2152 }
2153
2154 TrustRequirement::CrossSigned => match verification_level {
2157 VerificationLevel::UnverifiedIdentity => true,
2158
2159 VerificationLevel::VerificationViolation
2160 | VerificationLevel::MismatchedSender
2161 | VerificationLevel::UnsignedDevice
2162 | VerificationLevel::None(_) => false,
2163 },
2164 };
2165
2166 if ok {
2167 Ok(())
2168 } else {
2169 Err(MegolmError::SenderIdentityNotTrusted(verification_level.clone()))
2170 }
2171 }
2172
2173 async fn get_inbound_group_session_or_error(
2178 &self,
2179 room_id: &RoomId,
2180 session_id: &str,
2181 ) -> MegolmResult<InboundGroupSession> {
2182 match self.store().get_inbound_group_session(room_id, session_id).await? {
2183 Some(session) => Ok(session),
2184 None => {
2185 let withheld_code = self
2186 .inner
2187 .store
2188 .get_withheld_info(room_id, session_id)
2189 .await?
2190 .map(|e| e.content.withheld_code());
2191 Err(MegolmError::MissingRoomKey(withheld_code))
2192 }
2193 }
2194 }
2195
2196 pub async fn try_decrypt_room_event(
2211 &self,
2212 raw_event: &Raw<EncryptedEvent>,
2213 room_id: &RoomId,
2214 decryption_settings: &DecryptionSettings,
2215 ) -> Result<RoomEventDecryptionResult, CryptoStoreError> {
2216 match self.decrypt_room_event_inner(raw_event, room_id, true, decryption_settings).await {
2217 Ok(decrypted) => Ok(RoomEventDecryptionResult::Decrypted(decrypted)),
2218 Err(err) => Ok(RoomEventDecryptionResult::UnableToDecrypt(megolm_error_to_utd_info(
2219 raw_event, err,
2220 )?)),
2221 }
2222 }
2223
2224 pub async fn decrypt_room_event(
2232 &self,
2233 event: &Raw<EncryptedEvent>,
2234 room_id: &RoomId,
2235 decryption_settings: &DecryptionSettings,
2236 ) -> MegolmResult<DecryptedRoomEvent> {
2237 self.decrypt_room_event_inner(event, room_id, true, decryption_settings).await
2238 }
2239
2240 #[instrument(name = "decrypt_room_event", skip_all, fields(?room_id, event_id, origin_server_ts, sender, algorithm, session_id, message_index, sender_key))]
2241 async fn decrypt_room_event_inner(
2242 &self,
2243 event: &Raw<EncryptedEvent>,
2244 room_id: &RoomId,
2245 decrypt_unsigned: bool,
2246 decryption_settings: &DecryptionSettings,
2247 ) -> MegolmResult<DecryptedRoomEvent> {
2248 let _timer = timer!(tracing::Level::TRACE, "_method");
2249
2250 let event = event.deserialize()?;
2251
2252 Span::current()
2253 .record("sender", debug(&event.sender))
2254 .record("event_id", debug(&event.event_id))
2255 .record(
2256 "origin_server_ts",
2257 timestamp_to_iso8601(event.origin_server_ts)
2258 .unwrap_or_else(|| "<out of range>".to_owned()),
2259 )
2260 .record("algorithm", debug(event.content.algorithm()));
2261
2262 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2263 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2264 Span::current().record("sender_key", debug(c.sender_key));
2265 c.into()
2266 }
2267 #[cfg(feature = "experimental-algorithms")]
2268 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2269 RoomEventEncryptionScheme::Unknown(_) => {
2270 warn!("Received an encrypted room event with an unsupported algorithm");
2271 return Err(EventError::UnsupportedAlgorithm.into());
2272 }
2273 };
2274
2275 Span::current().record("session_id", content.session_id());
2276 Span::current().record("message_index", content.message_index());
2277
2278 let result =
2279 self.decrypt_megolm_events(room_id, &event, &content, decryption_settings).await;
2280
2281 if let Err(e) = &result {
2282 #[cfg(feature = "automatic-room-key-forwarding")]
2283 match e {
2284 MegolmError::MissingRoomKey(_)
2287 | MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
2288 self.inner
2289 .key_request_machine
2290 .create_outgoing_key_request(room_id, &event)
2291 .await?;
2292 }
2293 _ => {}
2294 }
2295
2296 warn!("Failed to decrypt a room event: {e}");
2297 }
2298
2299 let (mut decrypted_event, encryption_info) = result?;
2300
2301 let mut unsigned_encryption_info = None;
2302 if decrypt_unsigned {
2303 unsigned_encryption_info = self
2305 .decrypt_unsigned_events(&mut decrypted_event, room_id, decryption_settings)
2306 .await;
2307 }
2308
2309 let decrypted_event =
2310 serde_json::from_value::<Raw<AnyTimelineEvent>>(decrypted_event.into())?;
2311
2312 #[cfg(feature = "experimental-encrypted-state-events")]
2313 self.verify_packed_state_key(&event, &decrypted_event)?;
2314
2315 Ok(DecryptedRoomEvent { event: decrypted_event, encryption_info, unsigned_encryption_info })
2316 }
2317
2318 #[cfg(feature = "experimental-encrypted-state-events")]
2335 fn verify_packed_state_key(
2336 &self,
2337 original: &EncryptedEvent,
2338 decrypted: &Raw<AnyTimelineEvent>,
2339 ) -> MegolmResult<()> {
2340 use serde::Deserialize;
2341
2342 #[derive(Deserialize)]
2344 struct PayloadDeserializationHelper {
2345 state_key: Option<String>,
2346 #[serde(rename = "type")]
2347 event_type: String,
2348 }
2349
2350 let PayloadDeserializationHelper {
2352 state_key: inner_state_key,
2353 event_type: inner_event_type,
2354 } = decrypted
2355 .deserialize_as_unchecked()
2356 .map_err(|_| MegolmError::StateKeyVerificationFailed)?;
2357
2358 let (raw_state_key, inner_state_key) = match (&original.state_key, &inner_state_key) {
2360 (Some(raw_state_key), Some(inner_state_key)) => (raw_state_key, inner_state_key),
2361 (None, None) => return Ok(()),
2362 _ => return Err(MegolmError::StateKeyVerificationFailed),
2363 };
2364
2365 let (outer_event_type, outer_state_key) =
2367 raw_state_key.split_once(":").ok_or(MegolmError::StateKeyVerificationFailed)?;
2368
2369 if outer_event_type != inner_event_type {
2371 return Err(MegolmError::StateKeyVerificationFailed);
2372 }
2373
2374 if outer_state_key != inner_state_key {
2376 return Err(MegolmError::StateKeyVerificationFailed);
2377 }
2378 Ok(())
2379 }
2380
2381 async fn decrypt_unsigned_events(
2391 &self,
2392 main_event: &mut JsonObject,
2393 room_id: &RoomId,
2394 decryption_settings: &DecryptionSettings,
2395 ) -> Option<BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>> {
2396 let unsigned = main_event.get_mut("unsigned")?.as_object_mut()?;
2397 let mut unsigned_encryption_info: Option<
2398 BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>,
2399 > = None;
2400
2401 let location = UnsignedEventLocation::RelationsReplace;
2403 let replace = location.find_mut(unsigned);
2404 if let Some(decryption_result) =
2405 self.decrypt_unsigned_event(replace, room_id, decryption_settings).await
2406 {
2407 unsigned_encryption_info
2408 .get_or_insert_with(Default::default)
2409 .insert(location, decryption_result);
2410 }
2411
2412 let location = UnsignedEventLocation::RelationsThreadLatestEvent;
2415 let thread_latest_event = location.find_mut(unsigned);
2416 if let Some(decryption_result) =
2417 self.decrypt_unsigned_event(thread_latest_event, room_id, decryption_settings).await
2418 {
2419 unsigned_encryption_info
2420 .get_or_insert_with(Default::default)
2421 .insert(location, decryption_result);
2422 }
2423
2424 unsigned_encryption_info
2425 }
2426
2427 fn decrypt_unsigned_event<'a>(
2435 &'a self,
2436 event: Option<&'a mut Value>,
2437 room_id: &'a RoomId,
2438 decryption_settings: &'a DecryptionSettings,
2439 ) -> BoxFuture<'a, Option<UnsignedDecryptionResult>> {
2440 Box::pin(async move {
2441 let event = event?;
2442
2443 let is_encrypted = event
2444 .get("type")
2445 .and_then(|type_| type_.as_str())
2446 .is_some_and(|s| s == "m.room.encrypted");
2447 if !is_encrypted {
2448 return None;
2449 }
2450
2451 let raw_event = serde_json::from_value(event.clone()).ok()?;
2452 match self
2453 .decrypt_room_event_inner(&raw_event, room_id, false, decryption_settings)
2454 .await
2455 {
2456 Ok(decrypted_event) => {
2457 *event = serde_json::to_value(decrypted_event.event).ok()?;
2459 Some(UnsignedDecryptionResult::Decrypted(decrypted_event.encryption_info))
2460 }
2461 Err(err) => {
2462 let utd_info = megolm_error_to_utd_info(&raw_event, err).ok()?;
2467 Some(UnsignedDecryptionResult::UnableToDecrypt(utd_info))
2468 }
2469 }
2470 })
2471 }
2472
2473 pub async fn is_room_key_available(
2480 &self,
2481 event: &Raw<EncryptedEvent>,
2482 room_id: &RoomId,
2483 ) -> Result<bool, CryptoStoreError> {
2484 let event = event.deserialize()?;
2485
2486 let (session_id, message_index) = match &event.content.scheme {
2487 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2488 (&c.session_id, c.ciphertext.message_index())
2489 }
2490 #[cfg(feature = "experimental-algorithms")]
2491 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => {
2492 (&c.session_id, c.ciphertext.message_index())
2493 }
2494 RoomEventEncryptionScheme::Unknown(_) => {
2495 return Ok(false);
2497 }
2498 };
2499
2500 Ok(self
2503 .store()
2504 .get_inbound_group_session(room_id, session_id)
2505 .await?
2506 .filter(|s| s.first_known_index() <= message_index)
2507 .is_some())
2508 }
2509
2510 #[instrument(skip(self, event), fields(event_id, sender, session_id))]
2523 pub async fn get_room_event_encryption_info(
2524 &self,
2525 event: &Raw<EncryptedEvent>,
2526 room_id: &RoomId,
2527 ) -> MegolmResult<Arc<EncryptionInfo>> {
2528 let event = event.deserialize()?;
2529
2530 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2531 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => c.into(),
2532 #[cfg(feature = "experimental-algorithms")]
2533 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2534 RoomEventEncryptionScheme::Unknown(_) => {
2535 return Err(EventError::UnsupportedAlgorithm.into());
2536 }
2537 };
2538
2539 Span::current()
2540 .record("sender", debug(&event.sender))
2541 .record("event_id", debug(&event.event_id))
2542 .record("session_id", content.session_id());
2543
2544 self.get_session_encryption_info(room_id, content.session_id(), &event.sender).await
2545 }
2546
2547 pub async fn get_session_encryption_info(
2562 &self,
2563 room_id: &RoomId,
2564 session_id: &str,
2565 sender: &UserId,
2566 ) -> MegolmResult<Arc<EncryptionInfo>> {
2567 let session = self.get_inbound_group_session_or_error(room_id, session_id).await?;
2568 self.get_encryption_info(&session, sender).await
2569 }
2570
2571 pub async fn update_tracked_users(
2589 &self,
2590 users: impl IntoIterator<Item = &UserId>,
2591 ) -> StoreResult<()> {
2592 self.inner.identity_manager.update_tracked_users(users).await
2593 }
2594
2595 pub async fn mark_all_tracked_users_as_dirty(&self) -> StoreResult<()> {
2600 self.inner
2601 .identity_manager
2602 .mark_all_tracked_users_as_dirty(self.inner.store.cache().await?)
2603 .await
2604 }
2605
2606 async fn wait_if_user_pending(
2607 &self,
2608 user_id: &UserId,
2609 timeout: Option<Duration>,
2610 ) -> StoreResult<()> {
2611 if let Some(timeout) = timeout {
2612 let cache = self.store().cache().await?;
2613 self.inner
2614 .identity_manager
2615 .key_query_manager
2616 .wait_if_user_key_query_pending(cache, timeout, user_id)
2617 .await?;
2618 }
2619 Ok(())
2620 }
2621
2622 #[instrument(skip(self))]
2652 pub async fn get_device(
2653 &self,
2654 user_id: &UserId,
2655 device_id: &DeviceId,
2656 timeout: Option<Duration>,
2657 ) -> StoreResult<Option<Device>> {
2658 self.wait_if_user_pending(user_id, timeout).await?;
2659 self.store().get_device(user_id, device_id).await
2660 }
2661
2662 #[instrument(skip(self))]
2676 pub async fn get_identity(
2677 &self,
2678 user_id: &UserId,
2679 timeout: Option<Duration>,
2680 ) -> StoreResult<Option<UserIdentity>> {
2681 self.wait_if_user_pending(user_id, timeout).await?;
2682 self.store().get_identity(user_id).await
2683 }
2684
2685 #[instrument(skip(self))]
2712 pub async fn get_user_devices(
2713 &self,
2714 user_id: &UserId,
2715 timeout: Option<Duration>,
2716 ) -> StoreResult<UserDevices> {
2717 self.wait_if_user_pending(user_id, timeout).await?;
2718 self.store().get_user_devices(user_id).await
2719 }
2720
2721 pub async fn cross_signing_status(&self) -> CrossSigningStatus {
2726 self.inner.user_identity.lock().await.status().await
2727 }
2728
2729 pub async fn export_cross_signing_keys(&self) -> StoreResult<Option<CrossSigningKeyExport>> {
2737 let master_key = self.store().export_secret(&SecretName::CrossSigningMasterKey).await?;
2738 let self_signing_key =
2739 self.store().export_secret(&SecretName::CrossSigningSelfSigningKey).await?;
2740 let user_signing_key =
2741 self.store().export_secret(&SecretName::CrossSigningUserSigningKey).await?;
2742
2743 Ok(if master_key.is_none() && self_signing_key.is_none() && user_signing_key.is_none() {
2744 None
2745 } else {
2746 Some(CrossSigningKeyExport { master_key, self_signing_key, user_signing_key })
2747 })
2748 }
2749
2750 pub async fn import_cross_signing_keys(
2755 &self,
2756 export: CrossSigningKeyExport,
2757 ) -> Result<CrossSigningStatus, SecretImportError> {
2758 self.store().import_cross_signing_keys(export).await
2759 }
2760
2761 async fn sign_with_master_key(
2762 &self,
2763 message: &str,
2764 ) -> Result<(OwnedDeviceKeyId, Ed25519Signature), SignatureError> {
2765 let identity = &*self.inner.user_identity.lock().await;
2766 let key_id = identity.master_key_id().await.ok_or(SignatureError::MissingSigningKey)?;
2767
2768 let signature = identity.sign(message).await?;
2769
2770 Ok((key_id, signature))
2771 }
2772
2773 pub async fn sign(&self, message: &str) -> Result<Signatures, CryptoStoreError> {
2779 let mut signatures = Signatures::new();
2780
2781 {
2782 let cache = self.inner.store.cache().await?;
2783 let account = cache.account().await?;
2784 let key_id = account.signing_key_id();
2785 let signature = account.sign(message);
2786 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
2787 }
2788
2789 match self.sign_with_master_key(message).await {
2790 Ok((key_id, signature)) => {
2791 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
2792 }
2793 Err(e) => {
2794 warn!(error = ?e, "Couldn't sign the message using the cross signing master key")
2795 }
2796 }
2797
2798 Ok(signatures)
2799 }
2800
2801 pub fn backup_machine(&self) -> &BackupMachine {
2806 &self.inner.backup_machine
2807 }
2808
2809 pub async fn initialize_crypto_store_generation(
2813 &self,
2814 generation: &Mutex<Option<u64>>,
2815 ) -> StoreResult<()> {
2816 let mut gen_guard = generation.lock().await;
2819
2820 let prev_generation =
2821 self.inner.store.get_custom_value(Self::CURRENT_GENERATION_STORE_KEY).await?;
2822
2823 let generation = match prev_generation {
2824 Some(val) => {
2825 u64::from_le_bytes(val.try_into().map_err(|_| {
2828 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
2829 })?)
2830 .wrapping_add(1)
2831 }
2832 None => 0,
2833 };
2834
2835 tracing::debug!("Initialising crypto store generation at {generation}");
2836
2837 self.inner
2838 .store
2839 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, generation.to_le_bytes().to_vec())
2840 .await?;
2841
2842 *gen_guard = Some(generation);
2843
2844 Ok(())
2845 }
2846
2847 pub async fn maintain_crypto_store_generation(
2872 &'_ self,
2873 generation: &Mutex<Option<u64>>,
2874 ) -> StoreResult<(bool, u64)> {
2875 let mut gen_guard = generation.lock().await;
2876
2877 let actual_gen = self
2883 .inner
2884 .store
2885 .get_custom_value(Self::CURRENT_GENERATION_STORE_KEY)
2886 .await?
2887 .ok_or_else(|| {
2888 CryptoStoreError::InvalidLockGeneration("counter missing in store".to_owned())
2889 })?;
2890
2891 let actual_gen =
2892 u64::from_le_bytes(actual_gen.try_into().map_err(|_| {
2893 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
2894 })?);
2895
2896 let new_gen = match gen_guard.as_ref() {
2897 Some(expected_gen) => {
2898 if actual_gen == *expected_gen {
2899 return Ok((false, actual_gen));
2900 }
2901 actual_gen.max(*expected_gen).wrapping_add(1)
2903 }
2904 None => {
2905 actual_gen.wrapping_add(1)
2908 }
2909 };
2910
2911 tracing::debug!(
2912 "Crypto store generation mismatch: previously known was {:?}, actual is {:?}, next is {}",
2913 *gen_guard,
2914 actual_gen,
2915 new_gen
2916 );
2917
2918 *gen_guard = Some(new_gen);
2920
2921 self.inner
2923 .store
2924 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, new_gen.to_le_bytes().to_vec())
2925 .await?;
2926
2927 Ok((true, new_gen))
2928 }
2929
2930 pub fn dehydrated_devices(&self) -> DehydratedDevices {
2932 DehydratedDevices { inner: self.to_owned() }
2933 }
2934
2935 pub async fn room_settings(&self, room_id: &RoomId) -> StoreResult<Option<RoomSettings>> {
2940 self.inner.store.get_room_settings(room_id).await
2943 }
2944
2945 pub async fn set_room_settings(
2956 &self,
2957 room_id: &RoomId,
2958 new_settings: &RoomSettings,
2959 ) -> Result<(), SetRoomSettingsError> {
2960 let store = &self.inner.store;
2961
2962 let _store_transaction = store.transaction().await;
2967
2968 let old_settings = store.get_room_settings(room_id).await?;
2969
2970 if let Some(old_settings) = old_settings {
2983 if old_settings != *new_settings {
2984 return Err(SetRoomSettingsError::EncryptionDowngrade);
2985 } else {
2986 return Ok(());
2988 }
2989 }
2990
2991 match new_settings.algorithm {
2993 EventEncryptionAlgorithm::MegolmV1AesSha2 => (),
2994
2995 #[cfg(feature = "experimental-algorithms")]
2996 EventEncryptionAlgorithm::MegolmV2AesSha2 => (),
2997
2998 _ => {
2999 warn!(
3000 ?room_id,
3001 "Rejecting invalid encryption algorithm {}", new_settings.algorithm
3002 );
3003 return Err(SetRoomSettingsError::InvalidSettings);
3004 }
3005 }
3006
3007 store
3009 .save_changes(Changes {
3010 room_settings: HashMap::from([(room_id.to_owned(), new_settings.clone())]),
3011 ..Default::default()
3012 })
3013 .await?;
3014
3015 Ok(())
3016 }
3017
3018 #[cfg(any(feature = "testing", test))]
3022 pub fn same_as(&self, other: &OlmMachine) -> bool {
3023 Arc::ptr_eq(&self.inner, &other.inner)
3024 }
3025
3026 #[cfg(any(feature = "testing", test))]
3028 pub async fn uploaded_key_count(&self) -> Result<u64, CryptoStoreError> {
3029 let cache = self.inner.store.cache().await?;
3030 let account = cache.account().await?;
3031 Ok(account.uploaded_key_count())
3032 }
3033
3034 #[cfg(test)]
3036 pub(crate) fn identity_manager(&self) -> &IdentityManager {
3037 &self.inner.identity_manager
3038 }
3039
3040 #[cfg(test)]
3042 pub(crate) fn key_for_has_migrated_verification_latch() -> &'static str {
3043 Self::HAS_MIGRATED_VERIFICATION_LATCH
3044 }
3045}
3046
3047fn sender_data_to_verification_state(
3048 sender_data: SenderData,
3049 session_has_been_imported: bool,
3050) -> (VerificationState, Option<OwnedDeviceId>) {
3051 match sender_data {
3052 SenderData::UnknownDevice { owner_check_failed: false, .. } => {
3053 let device_link_problem = if session_has_been_imported {
3054 DeviceLinkProblem::InsecureSource
3055 } else {
3056 DeviceLinkProblem::MissingDevice
3057 };
3058
3059 (VerificationState::Unverified(VerificationLevel::None(device_link_problem)), None)
3060 }
3061 SenderData::UnknownDevice { owner_check_failed: true, .. } => (
3062 VerificationState::Unverified(VerificationLevel::None(
3063 DeviceLinkProblem::InsecureSource,
3064 )),
3065 None,
3066 ),
3067 SenderData::DeviceInfo { device_keys, .. } => (
3068 VerificationState::Unverified(VerificationLevel::UnsignedDevice),
3069 Some(device_keys.device_id),
3070 ),
3071 SenderData::VerificationViolation(KnownSenderData { device_id, .. }) => {
3072 (VerificationState::Unverified(VerificationLevel::VerificationViolation), device_id)
3073 }
3074 SenderData::SenderUnverified(KnownSenderData { device_id, .. }) => {
3075 (VerificationState::Unverified(VerificationLevel::UnverifiedIdentity), device_id)
3076 }
3077 SenderData::SenderVerified(KnownSenderData { device_id, .. }) => {
3078 (VerificationState::Verified, device_id)
3079 }
3080 }
3081}
3082
3083#[derive(Debug, Clone)]
3086pub struct CrossSigningBootstrapRequests {
3087 pub upload_keys_req: Option<OutgoingRequest>,
3094
3095 pub upload_signing_keys_req: UploadSigningKeysRequest,
3099
3100 pub upload_signatures_req: UploadSignaturesRequest,
3105}
3106
3107#[derive(Debug)]
3110pub struct EncryptionSyncChanges<'a> {
3111 pub to_device_events: Vec<Raw<AnyToDeviceEvent>>,
3113 pub changed_devices: &'a DeviceLists,
3116 pub one_time_keys_counts: &'a BTreeMap<OneTimeKeyAlgorithm, UInt>,
3118 pub unused_fallback_keys: Option<&'a [OneTimeKeyAlgorithm]>,
3120 pub next_batch_token: Option<String>,
3122}
3123
3124fn megolm_error_to_utd_info(
3132 raw_event: &Raw<EncryptedEvent>,
3133 error: MegolmError,
3134) -> Result<UnableToDecryptInfo, CryptoStoreError> {
3135 use MegolmError::*;
3136 let reason = match error {
3137 EventError(_) => UnableToDecryptReason::MalformedEncryptedEvent,
3138 Decode(_) => UnableToDecryptReason::MalformedEncryptedEvent,
3139 MissingRoomKey(maybe_withheld) => {
3140 UnableToDecryptReason::MissingMegolmSession { withheld_code: maybe_withheld }
3141 }
3142 Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
3143 UnableToDecryptReason::UnknownMegolmMessageIndex
3144 }
3145 Decryption(_) => UnableToDecryptReason::MegolmDecryptionFailure,
3146 JsonError(_) => UnableToDecryptReason::PayloadDeserializationFailure,
3147 MismatchedIdentityKeys(_) => UnableToDecryptReason::MismatchedIdentityKeys,
3148 SenderIdentityNotTrusted(level) => UnableToDecryptReason::SenderIdentityNotTrusted(level),
3149 #[cfg(feature = "experimental-encrypted-state-events")]
3150 StateKeyVerificationFailed => UnableToDecryptReason::StateKeyVerificationFailed,
3151
3152 Store(error) => Err(error)?,
3155 };
3156
3157 let session_id = raw_event.deserialize().ok().and_then(|ev| match ev.content.scheme {
3158 RoomEventEncryptionScheme::MegolmV1AesSha2(s) => Some(s.session_id),
3159 #[cfg(feature = "experimental-algorithms")]
3160 RoomEventEncryptionScheme::MegolmV2AesSha2(s) => Some(s.session_id),
3161 RoomEventEncryptionScheme::Unknown(_) => None,
3162 });
3163
3164 Ok(UnableToDecryptInfo { session_id, reason })
3165}
3166
3167#[derive(Debug, thiserror::Error)]
3177pub(crate) enum DecryptToDeviceError {
3178 #[error("An Olm error occurred meaning we failed to decrypt the event")]
3179 OlmError(#[from] OlmError),
3180
3181 #[error("The event was sent from a dehydrated device")]
3182 FromDehydratedDevice,
3183}
3184
3185impl From<CryptoStoreError> for DecryptToDeviceError {
3186 fn from(value: CryptoStoreError) -> Self {
3187 Self::OlmError(value.into())
3188 }
3189}
3190
3191#[cfg(test)]
3192impl From<DecryptToDeviceError> for OlmError {
3193 fn from(value: DecryptToDeviceError) -> Self {
3196 match value {
3197 DecryptToDeviceError::OlmError(olm_error) => olm_error,
3198 DecryptToDeviceError::FromDehydratedDevice => {
3199 panic!("Expected an OlmError but found FromDehydratedDevice")
3200 }
3201 }
3202 }
3203}
3204
3205#[cfg(test)]
3206pub(crate) mod test_helpers;
3207
3208#[cfg(test)]
3209pub(crate) mod tests;