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-push-secrets")]
70use crate::error::SecretPushError;
71#[cfg(feature = "experimental-send-custom-to-device")]
72use crate::session_manager::split_devices_for_share_strategy;
73use crate::{
74 CollectStrategy, CryptoStoreError, DecryptionSettings, DeviceData, LocalTrust,
75 RoomEventDecryptionResult, SignatureError, TrustRequirement,
76 backups::{BackupMachine, MegolmV1BackupKey},
77 dehydrated_devices::{DehydratedDevices, DehydrationError},
78 error::{EventError, MegolmError, MegolmResult, OlmError, OlmResult, SetRoomSettingsError},
79 gossiping::GossipMachine,
80 identities::{Device, IdentityManager, UserDevices, user::UserIdentity},
81 olm::{
82 Account, CrossSigningStatus, EncryptionSettings, IdentityKeys, InboundGroupSession,
83 KnownSenderData, OlmDecryptionInfo, PrivateCrossSigningIdentity, SenderData,
84 SenderDataFinder, SessionType, StaticAccountData,
85 },
86 session_manager::{GroupSessionManager, SessionManager},
87 store::{
88 CryptoStoreWrapper, IntoCryptoStore, MemoryStore, Result as StoreResult, SecretImportError,
89 Store, StoreTransaction,
90 caches::StoreCache,
91 types::{
92 Changes, CrossSigningKeyExport, DeviceChanges, IdentityChanges, PendingChanges,
93 RoomKeyInfo, RoomSettings, StoredRoomKeyBundleData,
94 },
95 },
96 types::{
97 EventEncryptionAlgorithm, Signatures,
98 events::{
99 ToDeviceEvent, ToDeviceEvents,
100 olm_v1::{AnyDecryptedOlmEvent, DecryptedRoomKeyBundleEvent, DecryptedRoomKeyEvent},
101 room::encrypted::{
102 EncryptedEvent, EncryptedToDeviceEvent, RoomEncryptedEventContent,
103 RoomEventEncryptionScheme, SupportedEventEncryptionSchemes,
104 ToDeviceEncryptedEventContent,
105 },
106 room_key::{MegolmV1AesSha2Content, RoomKeyContent},
107 room_key_bundle::RoomKeyBundleContent,
108 room_key_withheld::{
109 MegolmV1AesSha2WithheldContent, RoomKeyWithheldContent, RoomKeyWithheldEvent,
110 },
111 },
112 requests::{
113 AnyIncomingResponse, KeysQueryRequest, OutgoingRequest, ToDeviceRequest,
114 UploadSigningKeysRequest,
115 },
116 },
117 utilities::timestamp_to_iso8601,
118 verification::{Verification, VerificationMachine, VerificationRequest},
119};
120
121#[derive(Debug, Serialize)]
122pub struct RawEncryptionResult {
124 pub content: Raw<RoomEncryptedEventContent>,
126 pub encryption_info: EncryptionInfo,
128}
129
130#[derive(Clone)]
133pub struct OlmMachine {
134 pub(crate) inner: Arc<OlmMachineInner>,
135}
136
137pub struct OlmMachineInner {
138 user_id: OwnedUserId,
140 device_id: OwnedDeviceId,
142 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
147 store: Store,
151 session_manager: SessionManager,
153 pub(crate) group_session_manager: GroupSessionManager,
155 verification_machine: VerificationMachine,
158 pub(crate) key_request_machine: GossipMachine,
161 identity_manager: IdentityManager,
164 backup_machine: BackupMachine,
166}
167
168#[cfg(not(tarpaulin_include))]
169impl std::fmt::Debug for OlmMachine {
170 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171 f.debug_struct("OlmMachine")
172 .field("user_id", &self.user_id())
173 .field("device_id", &self.device_id())
174 .finish()
175 }
176}
177
178impl OlmMachine {
179 const CURRENT_GENERATION_STORE_KEY: &'static str = "generation-counter";
180 const HAS_MIGRATED_VERIFICATION_LATCH: &'static str = "HAS_MIGRATED_VERIFICATION_LATCH";
181
182 pub async fn new(user_id: &UserId, device_id: &DeviceId) -> Self {
193 OlmMachine::with_store(user_id, device_id, MemoryStore::new(), None)
194 .await
195 .expect("Reading and writing to the memory store always succeeds")
196 }
197
198 pub(crate) async fn rehydrate(
199 &self,
200 pickle_key: &[u8; 32],
201 device_id: &DeviceId,
202 device_data: Raw<DehydratedDeviceData>,
203 ) -> Result<OlmMachine, DehydrationError> {
204 let account = Account::rehydrate(pickle_key, self.user_id(), device_id, device_data)?;
205 let static_account = account.static_data().clone();
206
207 let store =
208 Arc::new(CryptoStoreWrapper::new(self.user_id(), device_id, MemoryStore::new()));
209 let device = DeviceData::from_account(&account);
210 store.save_pending_changes(PendingChanges { account: Some(account) }).await?;
211 store
212 .save_changes(Changes {
213 devices: DeviceChanges { new: vec![device], ..Default::default() },
214 ..Default::default()
215 })
216 .await?;
217
218 let (verification_machine, store, identity_manager) =
219 Self::new_helper_prelude(store, static_account, self.store().private_identity());
220
221 Ok(Self::new_helper(
222 device_id,
223 store,
224 verification_machine,
225 identity_manager,
226 self.store().private_identity(),
227 None,
228 ))
229 }
230
231 fn new_helper_prelude(
232 store_wrapper: Arc<CryptoStoreWrapper>,
233 account: StaticAccountData,
234 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
235 ) -> (VerificationMachine, Store, IdentityManager) {
236 let verification_machine =
237 VerificationMachine::new(account.clone(), user_identity.clone(), store_wrapper.clone());
238 let store = Store::new(account, user_identity, store_wrapper, verification_machine.clone());
239
240 let identity_manager = IdentityManager::new(store.clone());
241
242 (verification_machine, store, identity_manager)
243 }
244
245 fn new_helper(
246 device_id: &DeviceId,
247 store: Store,
248 verification_machine: VerificationMachine,
249 identity_manager: IdentityManager,
250 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
251 maybe_backup_key: Option<MegolmV1BackupKey>,
252 ) -> Self {
253 let group_session_manager = GroupSessionManager::new(store.clone());
254
255 let users_for_key_claim = Arc::new(StdRwLock::new(BTreeMap::new()));
256 let key_request_machine = GossipMachine::new(
257 store.clone(),
258 identity_manager.clone(),
259 group_session_manager.session_cache(),
260 users_for_key_claim.clone(),
261 );
262
263 let session_manager =
264 SessionManager::new(users_for_key_claim, key_request_machine.clone(), store.clone());
265
266 let backup_machine = BackupMachine::new(store.clone(), maybe_backup_key);
267
268 let inner = Arc::new(OlmMachineInner {
269 user_id: store.user_id().to_owned(),
270 device_id: device_id.to_owned(),
271 user_identity,
272 store,
273 session_manager,
274 group_session_manager,
275 verification_machine,
276 key_request_machine,
277 identity_manager,
278 backup_machine,
279 });
280
281 Self { inner }
282 }
283
284 #[instrument(skip(store, custom_account), fields(ed25519_key, curve25519_key))]
309 pub async fn with_store(
310 user_id: &UserId,
311 device_id: &DeviceId,
312 store: impl IntoCryptoStore,
313 custom_account: Option<vodozemac::olm::Account>,
314 ) -> StoreResult<Self> {
315 let store = store.into_crypto_store();
316
317 let static_account = match store.load_account().await? {
318 Some(account) => {
319 if user_id != account.user_id()
320 || device_id != account.device_id()
321 || custom_account.is_some()
322 {
323 return Err(CryptoStoreError::MismatchedAccount {
324 expected: (account.user_id().to_owned(), account.device_id().to_owned()),
325 got: (user_id.to_owned(), device_id.to_owned()),
326 });
327 }
328
329 Span::current()
330 .record("ed25519_key", display(account.identity_keys().ed25519))
331 .record("curve25519_key", display(account.identity_keys().curve25519));
332 debug!("Restored an Olm account");
333
334 account.static_data().clone()
335 }
336
337 None => {
338 let account = if let Some(account) = custom_account {
339 Account::new_helper(account, user_id, device_id)
340 } else {
341 Account::with_device_id(user_id, device_id)
342 };
343
344 let static_account = account.static_data().clone();
345
346 Span::current()
347 .record("ed25519_key", display(account.identity_keys().ed25519))
348 .record("curve25519_key", display(account.identity_keys().curve25519));
349
350 let device = DeviceData::from_account(&account);
351
352 device.set_trust_state(LocalTrust::Verified);
356
357 let changes = Changes {
358 devices: DeviceChanges { new: vec![device], ..Default::default() },
359 ..Default::default()
360 };
361 store.save_changes(changes).await?;
362 store.save_pending_changes(PendingChanges { account: Some(account) }).await?;
363
364 debug!("Created a new Olm account");
365
366 static_account
367 }
368 };
369
370 let identity = match store.load_identity().await? {
371 Some(i) => {
372 let master_key = i
373 .master_public_key()
374 .await
375 .and_then(|m| m.get_first_key().map(|m| m.to_owned()));
376 debug!(?master_key, "Restored the cross signing identity");
377 i
378 }
379 None => {
380 debug!("Creating an empty cross signing identity stub");
381 PrivateCrossSigningIdentity::empty(user_id)
382 }
383 };
384
385 let saved_keys = store.load_backup_keys().await?;
390 let maybe_backup_key = saved_keys.decryption_key.and_then(|k| {
391 if let Some(version) = saved_keys.backup_version {
392 let megolm_v1_backup_key = k.megolm_v1_public_key();
393 megolm_v1_backup_key.set_version(version);
394 Some(megolm_v1_backup_key)
395 } else {
396 None
397 }
398 });
399
400 let identity = Arc::new(Mutex::new(identity));
401 let store = Arc::new(CryptoStoreWrapper::new(user_id, device_id, store));
402
403 let (verification_machine, store, identity_manager) =
404 Self::new_helper_prelude(store, static_account, identity.clone());
405
406 Self::migration_post_verified_latch_support(&store, &identity_manager).await?;
409
410 Ok(Self::new_helper(
411 device_id,
412 store,
413 verification_machine,
414 identity_manager,
415 identity,
416 maybe_backup_key,
417 ))
418 }
419
420 pub(crate) async fn migration_post_verified_latch_support(
428 store: &Store,
429 identity_manager: &IdentityManager,
430 ) -> Result<(), CryptoStoreError> {
431 let maybe_migrate_for_identity_verified_latch =
432 store.get_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH).await?.is_none();
433
434 if maybe_migrate_for_identity_verified_latch {
435 identity_manager.mark_all_tracked_users_as_dirty(store.cache().await?).await?;
436
437 store.set_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH, vec![0]).await?
438 }
439 Ok(())
440 }
441
442 pub fn store(&self) -> &Store {
444 &self.inner.store
445 }
446
447 pub fn user_id(&self) -> &UserId {
449 &self.inner.user_id
450 }
451
452 pub fn device_id(&self) -> &DeviceId {
454 &self.inner.device_id
455 }
456
457 pub fn device_creation_time(&self) -> MilliSecondsSinceUnixEpoch {
464 self.inner.store.static_account().creation_local_time()
465 }
466
467 pub fn identity_keys(&self) -> IdentityKeys {
469 let account = self.inner.store.static_account();
470 account.identity_keys()
471 }
472
473 pub async fn display_name(&self) -> StoreResult<Option<String>> {
475 self.store().device_display_name().await
476 }
477
478 pub async fn tracked_users(&self) -> StoreResult<HashSet<OwnedUserId>> {
483 let cache = self.store().cache().await?;
484 Ok(self.inner.identity_manager.key_query_manager.synced(&cache).await?.tracked_users())
485 }
486
487 #[cfg(feature = "automatic-room-key-forwarding")]
496 pub fn set_room_key_requests_enabled(&self, enable: bool) {
497 self.inner.key_request_machine.set_room_key_requests_enabled(enable)
498 }
499
500 pub fn are_room_key_requests_enabled(&self) -> bool {
505 self.inner.key_request_machine.are_room_key_requests_enabled()
506 }
507
508 #[cfg(feature = "automatic-room-key-forwarding")]
517 pub fn set_room_key_forwarding_enabled(&self, enable: bool) {
518 self.inner.key_request_machine.set_room_key_forwarding_enabled(enable)
519 }
520
521 pub fn is_room_key_forwarding_enabled(&self) -> bool {
525 self.inner.key_request_machine.is_room_key_forwarding_enabled()
526 }
527
528 pub async fn outgoing_requests(&self) -> StoreResult<Vec<OutgoingRequest>> {
536 let mut requests = Vec::new();
537
538 {
539 let store_cache = self.inner.store.cache().await?;
540 let account = store_cache.account().await?;
541 if let Some(r) = self.keys_for_upload(&account).await.map(|r| OutgoingRequest {
542 request_id: TransactionId::new(),
543 request: Arc::new(r.into()),
544 }) {
545 requests.push(r);
546 }
547 }
548
549 for request in self
550 .inner
551 .identity_manager
552 .users_for_key_query()
553 .await?
554 .into_iter()
555 .map(|(request_id, r)| OutgoingRequest { request_id, request: Arc::new(r.into()) })
556 {
557 requests.push(request);
558 }
559
560 requests.append(&mut self.inner.verification_machine.outgoing_messages());
561 requests.append(&mut self.inner.key_request_machine.outgoing_to_device_requests().await?);
562
563 Ok(requests)
564 }
565
566 pub fn query_keys_for_users<'a>(
587 &self,
588 users: impl IntoIterator<Item = &'a UserId>,
589 ) -> (OwnedTransactionId, KeysQueryRequest) {
590 self.inner.identity_manager.build_key_query_for_users(users)
591 }
592
593 pub async fn mark_request_as_sent<'a>(
603 &self,
604 request_id: &TransactionId,
605 response: impl Into<AnyIncomingResponse<'a>>,
606 ) -> OlmResult<()> {
607 match response.into() {
608 AnyIncomingResponse::KeysUpload(response) => {
609 Box::pin(self.receive_keys_upload_response(response)).await?;
610 }
611 AnyIncomingResponse::KeysQuery(response) => {
612 Box::pin(self.receive_keys_query_response(request_id, response)).await?;
613 }
614 AnyIncomingResponse::KeysClaim(response) => {
615 Box::pin(
616 self.inner.session_manager.receive_keys_claim_response(request_id, response),
617 )
618 .await?;
619 }
620 AnyIncomingResponse::ToDevice(_) => {
621 Box::pin(self.mark_to_device_request_as_sent(request_id)).await?;
622 }
623 AnyIncomingResponse::SigningKeysUpload(_) => {
624 Box::pin(self.receive_cross_signing_upload_response()).await?;
625 }
626 AnyIncomingResponse::SignatureUpload(_) => {
627 self.inner.verification_machine.mark_request_as_sent(request_id);
628 }
629 AnyIncomingResponse::RoomMessage(_) => {
630 self.inner.verification_machine.mark_request_as_sent(request_id);
631 }
632 AnyIncomingResponse::KeysBackup(_) => {
633 Box::pin(self.inner.backup_machine.mark_request_as_sent(request_id)).await?;
634 }
635 }
636
637 Ok(())
638 }
639
640 async fn receive_cross_signing_upload_response(&self) -> StoreResult<()> {
642 let identity = self.inner.user_identity.lock().await;
643 identity.mark_as_shared();
644
645 let changes = Changes { private_identity: Some(identity.clone()), ..Default::default() };
646
647 self.store().save_changes(changes).await
648 }
649
650 pub async fn bootstrap_cross_signing(
669 &self,
670 reset: bool,
671 ) -> StoreResult<CrossSigningBootstrapRequests> {
672 let identity = self.inner.user_identity.lock().await.clone();
677
678 let (upload_signing_keys_req, upload_signatures_req) = if reset || identity.is_empty().await
679 {
680 info!("Creating new cross signing identity");
681
682 let (identity, upload_signing_keys_req, upload_signatures_req) = {
683 let cache = self.inner.store.cache().await?;
684 let account = cache.account().await?;
685 account.bootstrap_cross_signing().await
686 };
687
688 let public = identity.to_public_identity().await.expect(
689 "Couldn't create a public version of the identity from a new private identity",
690 );
691
692 *self.inner.user_identity.lock().await = identity.clone();
693
694 self.store()
695 .save_changes(Changes {
696 identities: IdentityChanges { new: vec![public.into()], ..Default::default() },
697 private_identity: Some(identity),
698 ..Default::default()
699 })
700 .await?;
701
702 (upload_signing_keys_req, upload_signatures_req)
703 } else {
704 info!("Trying to upload the existing cross signing identity");
705 let upload_signing_keys_req = identity.as_upload_request().await;
706
707 let upload_signatures_req = identity
709 .sign_account(self.inner.store.static_account())
710 .await
711 .expect("Can't sign device keys");
712
713 (upload_signing_keys_req, upload_signatures_req)
714 };
715
716 let upload_keys_req =
720 self.upload_device_keys().await?.map(|(_, request)| OutgoingRequest::from(request));
721
722 Ok(CrossSigningBootstrapRequests {
723 upload_signing_keys_req,
724 upload_keys_req,
725 upload_signatures_req,
726 })
727 }
728
729 pub async fn upload_device_keys(
741 &self,
742 ) -> StoreResult<Option<(OwnedTransactionId, UploadKeysRequest)>> {
743 let cache = self.store().cache().await?;
744 let account = cache.account().await?;
745
746 Ok(self.keys_for_upload(&account).await.map(|request| (TransactionId::new(), request)))
747 }
748
749 async fn receive_keys_upload_response(&self, response: &UploadKeysResponse) -> OlmResult<()> {
756 self.inner
757 .store
758 .with_transaction(async |tr| {
759 let account = tr.account().await?;
760 account.receive_keys_upload_response(response)?;
761 Ok(())
762 })
763 .await
764 }
765
766 #[instrument(skip_all)]
794 pub async fn get_missing_sessions(
795 &self,
796 users: impl Iterator<Item = &UserId>,
797 ) -> StoreResult<Option<(OwnedTransactionId, KeysClaimRequest)>> {
798 self.inner.session_manager.get_missing_sessions(users).await
799 }
800
801 async fn receive_keys_query_response(
810 &self,
811 request_id: &TransactionId,
812 response: &KeysQueryResponse,
813 ) -> OlmResult<(DeviceChanges, IdentityChanges)> {
814 self.inner.identity_manager.receive_keys_query_response(request_id, response).await
815 }
816
817 async fn keys_for_upload(&self, account: &Account) -> Option<UploadKeysRequest> {
826 let (mut device_keys, one_time_keys, fallback_keys) = account.keys_for_upload();
827
828 if let Some(device_keys) = &mut device_keys {
838 let private_identity = self.store().private_identity();
839 let guard = private_identity.lock().await;
840
841 if guard.status().await.is_complete() {
842 guard.sign_device_keys(device_keys).await.expect(
843 "We should be able to sign our device keys since we confirmed that we \
844 have a complete set of private cross-signing keys",
845 );
846 }
847 }
848
849 if device_keys.is_none() && one_time_keys.is_empty() && fallback_keys.is_empty() {
850 None
851 } else {
852 let device_keys = device_keys.map(|d| d.to_raw());
853
854 Some(assign!(UploadKeysRequest::new(), {
855 device_keys, one_time_keys, fallback_keys
856 }))
857 }
858 }
859
860 async fn decrypt_to_device_event(
883 &self,
884 transaction: &mut StoreTransaction,
885 event: &EncryptedToDeviceEvent,
886 changes: &mut Changes,
887 decryption_settings: &DecryptionSettings,
888 ) -> Result<OlmDecryptionInfo, DecryptToDeviceError> {
889 let mut decrypted = transaction
891 .account()
892 .await?
893 .decrypt_to_device_event(&self.inner.store, event, decryption_settings)
894 .await?;
895
896 self.check_to_device_event_is_not_from_dehydrated_device(&decrypted, &event.sender).await?;
898
899 self.handle_decrypted_to_device_event(transaction.cache(), &mut decrypted, changes).await?;
901
902 Ok(decrypted)
903 }
904
905 #[instrument(
906 skip_all,
907 fields(room_id = ? content.room_id, session_id, message_index, shared_history = content.shared_history)
911 )]
912 async fn handle_key(
913 &self,
914 sender_key: Curve25519PublicKey,
915 event: &DecryptedRoomKeyEvent,
916 content: &MegolmV1AesSha2Content,
917 ) -> OlmResult<Option<InboundGroupSession>> {
918 let session =
919 InboundGroupSession::from_room_key_content(sender_key, event.keys.ed25519, content);
920
921 match session {
922 Ok(mut session) => {
923 Span::current().record("session_id", session.session_id());
924 Span::current().record("message_index", session.first_known_index());
925
926 let sender_data =
927 SenderDataFinder::find_using_event(self.store(), sender_key, event, &session)
928 .await?;
929 session.sender_data = sender_data;
930
931 Ok(self.store().merge_received_group_session(session).await?)
932 }
933 Err(e) => {
934 Span::current().record("session_id", &content.session_id);
935 warn!("Received a room key event which contained an invalid session key: {e}");
936
937 Ok(None)
938 }
939 }
940 }
941
942 #[instrument(skip_all, fields(algorithm = ?event.content.algorithm()))]
944 async fn add_room_key(
945 &self,
946 sender_key: Curve25519PublicKey,
947 event: &DecryptedRoomKeyEvent,
948 ) -> OlmResult<Option<InboundGroupSession>> {
949 match &event.content {
950 RoomKeyContent::MegolmV1AesSha2(content) => {
951 self.handle_key(sender_key, event, content).await
952 }
953 #[cfg(feature = "experimental-algorithms")]
954 RoomKeyContent::MegolmV2AesSha2(content) => {
955 self.handle_key(sender_key, event, content).await
956 }
957 RoomKeyContent::Unknown(_) => {
958 warn!("Received a room key with an unsupported algorithm");
959 Ok(None)
960 }
961 }
962 }
963
964 #[instrument()]
966 async fn receive_room_key_bundle_data(
967 &self,
968 sender_key: Curve25519PublicKey,
969 event: &DecryptedRoomKeyBundleEvent,
970 changes: &mut Changes,
971 ) -> OlmResult<()> {
972 let Some(sender_device_keys) = &event.sender_device_keys else {
973 warn!("Received a room key bundle with no sender device keys: ignoring");
974 return Ok(());
975 };
976
977 let sender_device_data =
982 DeviceData::try_from(sender_device_keys).expect("failed to verify sender device keys");
983 let sender_device = self.store().wrap_device_data(sender_device_data).await?;
984
985 changes.received_room_key_bundles.push(StoredRoomKeyBundleData {
986 sender_user: event.sender.clone(),
987 sender_data: SenderData::from_device(&sender_device),
988 sender_key,
989 bundle_data: event.content.clone(),
990 });
991 Ok(())
992 }
993
994 fn add_withheld_info(&self, changes: &mut Changes, event: &RoomKeyWithheldEvent) {
995 debug!(?event.content, "Processing `m.room_key.withheld` event");
996
997 if let RoomKeyWithheldContent::MegolmV1AesSha2(
998 MegolmV1AesSha2WithheldContent::BlackListed(c)
999 | MegolmV1AesSha2WithheldContent::Unverified(c)
1000 | MegolmV1AesSha2WithheldContent::Unauthorised(c)
1001 | MegolmV1AesSha2WithheldContent::Unavailable(c),
1002 ) = &event.content
1003 {
1004 changes
1005 .withheld_session_info
1006 .entry(c.room_id.to_owned())
1007 .or_default()
1008 .insert(c.session_id.to_owned(), event.to_owned().into());
1009 }
1010 }
1011
1012 #[cfg(test)]
1013 pub(crate) async fn create_outbound_group_session_with_defaults_test_helper(
1014 &self,
1015 room_id: &RoomId,
1016 ) -> OlmResult<()> {
1017 let (_, session) = self
1018 .inner
1019 .group_session_manager
1020 .create_outbound_group_session(
1021 room_id,
1022 EncryptionSettings::default(),
1023 SenderData::unknown(),
1024 )
1025 .await?;
1026
1027 self.store().save_inbound_group_sessions(&[session]).await?;
1028
1029 Ok(())
1030 }
1031
1032 #[cfg(test)]
1033 #[allow(dead_code)]
1034 pub(crate) async fn create_inbound_session_test_helper(
1035 &self,
1036 room_id: &RoomId,
1037 ) -> OlmResult<InboundGroupSession> {
1038 let (_, session) = self
1039 .inner
1040 .group_session_manager
1041 .create_outbound_group_session(
1042 room_id,
1043 EncryptionSettings::default(),
1044 SenderData::unknown(),
1045 )
1046 .await?;
1047
1048 Ok(session)
1049 }
1050
1051 pub async fn encrypt_room_event(
1068 &self,
1069 room_id: &RoomId,
1070 content: impl MessageLikeEventContent,
1071 ) -> MegolmResult<RawEncryptionResult> {
1072 let event_type = content.event_type().to_string();
1073 let content = Raw::new(&content)?.cast_unchecked();
1074 self.encrypt_room_event_raw(room_id, &event_type, &content).await
1075 }
1076
1077 pub async fn encrypt_room_event_raw(
1097 &self,
1098 room_id: &RoomId,
1099 event_type: &str,
1100 content: &Raw<AnyMessageLikeEventContent>,
1101 ) -> MegolmResult<RawEncryptionResult> {
1102 self.inner.group_session_manager.encrypt(room_id, event_type, content).await.map(|result| {
1103 RawEncryptionResult {
1104 content: result.content,
1105 encryption_info: self
1106 .own_encryption_info(result.algorithm, result.session_id.to_string()),
1107 }
1108 })
1109 }
1110
1111 fn own_encryption_info(
1112 &self,
1113 algorithm: EventEncryptionAlgorithm,
1114 session_id: String,
1115 ) -> EncryptionInfo {
1116 let identity_keys = self.identity_keys();
1117
1118 let algorithm_info = match algorithm {
1119 EventEncryptionAlgorithm::MegolmV1AesSha2 => AlgorithmInfo::MegolmV1AesSha2 {
1120 curve25519_key: identity_keys.curve25519.to_base64(),
1121 sender_claimed_keys: BTreeMap::from([(
1122 DeviceKeyAlgorithm::Ed25519,
1123 identity_keys.ed25519.to_base64(),
1124 )]),
1125 session_id: Some(session_id),
1126 },
1127 EventEncryptionAlgorithm::OlmV1Curve25519AesSha2 => {
1128 AlgorithmInfo::OlmV1Curve25519AesSha2 {
1129 curve25519_public_key_base64: identity_keys.curve25519.to_base64(),
1130 }
1131 }
1132 _ => unreachable!(
1133 "Only MegolmV1AesSha2 and OlmV1Curve25519AesSha2 are supported on this level"
1134 ),
1135 };
1136
1137 EncryptionInfo {
1138 sender: self.inner.user_id.clone(),
1139 sender_device: Some(self.inner.device_id.clone()),
1140 forwarder: None,
1141 algorithm_info,
1142 verification_state: VerificationState::Verified,
1143 }
1144 }
1145
1146 #[cfg(feature = "experimental-encrypted-state-events")]
1158 pub async fn encrypt_state_event<C, K>(
1159 &self,
1160 room_id: &RoomId,
1161 content: C,
1162 state_key: K,
1163 ) -> MegolmResult<Raw<RoomEncryptedEventContent>>
1164 where
1165 C: StateEventContent,
1166 C::StateKey: Borrow<K>,
1167 K: AsRef<str>,
1168 {
1169 let event_type = content.event_type().to_string();
1170 let content = Raw::new(&content)?.cast_unchecked();
1171 self.encrypt_state_event_raw(room_id, &event_type, state_key.as_ref(), &content).await
1172 }
1173
1174 #[cfg(feature = "experimental-encrypted-state-events")]
1193 pub async fn encrypt_state_event_raw(
1194 &self,
1195 room_id: &RoomId,
1196 event_type: &str,
1197 state_key: &str,
1198 content: &Raw<AnyStateEventContent>,
1199 ) -> MegolmResult<Raw<RoomEncryptedEventContent>> {
1200 self.inner
1201 .group_session_manager
1202 .encrypt_state(room_id, event_type, state_key, content)
1203 .await
1204 }
1205
1206 pub async fn discard_room_key(&self, room_id: &RoomId) -> StoreResult<bool> {
1217 self.inner.group_session_manager.invalidate_group_session(room_id).await
1218 }
1219
1220 pub async fn share_room_key(
1240 &self,
1241 room_id: &RoomId,
1242 users: impl Iterator<Item = &UserId>,
1243 encryption_settings: impl Into<EncryptionSettings>,
1244 ) -> OlmResult<Vec<Arc<ToDeviceRequest>>> {
1245 self.inner.group_session_manager.share_room_key(room_id, users, encryption_settings).await
1246 }
1247
1248 #[cfg(feature = "experimental-send-custom-to-device")]
1262 pub async fn encrypt_content_for_devices(
1263 &self,
1264 devices: Vec<DeviceData>,
1265 event_type: &str,
1266 content: &Value,
1267 share_strategy: CollectStrategy,
1268 ) -> OlmResult<(Vec<ToDeviceRequest>, Vec<(DeviceData, WithheldCode)>)> {
1269 let mut changes = Changes::default();
1270
1271 let (allowed_devices, mut blocked_devices) =
1272 split_devices_for_share_strategy(&self.inner.store, devices, share_strategy).await?;
1273
1274 let result = self
1275 .inner
1276 .group_session_manager
1277 .encrypt_content_for_devices(allowed_devices, event_type, content.clone(), &mut changes)
1278 .await;
1279
1280 if !changes.is_empty() {
1282 let session_count = changes.sessions.len();
1283
1284 self.inner.store.save_changes(changes).await?;
1285
1286 trace!(
1287 session_count = session_count,
1288 "Stored the changed sessions after encrypting a custom to-device event"
1289 );
1290 }
1291
1292 result.map(|(to_device_requests, mut withheld)| {
1293 withheld.append(&mut blocked_devices);
1294 (to_device_requests, withheld)
1295 })
1296 }
1297 pub async fn share_room_key_bundle_data(
1302 &self,
1303 user_id: &UserId,
1304 collect_strategy: &CollectStrategy,
1305 bundle_data: RoomKeyBundleContent,
1306 ) -> OlmResult<Vec<ToDeviceRequest>> {
1307 self.inner
1308 .group_session_manager
1309 .share_room_key_bundle_data(user_id, collect_strategy, bundle_data)
1310 .await
1311 }
1312
1313 #[deprecated(note = "Use OlmMachine::receive_verification_event instead", since = "0.7.0")]
1321 pub async fn receive_unencrypted_verification_event(
1322 &self,
1323 event: &AnyMessageLikeEvent,
1324 ) -> StoreResult<()> {
1325 self.inner.verification_machine.receive_any_event(event).await
1326 }
1327
1328 pub async fn receive_verification_event(&self, event: &AnyMessageLikeEvent) -> StoreResult<()> {
1341 self.inner.verification_machine.receive_any_event(event).await
1342 }
1343
1344 #[instrument(
1350 skip_all,
1351 fields(
1352 sender_key = ?decrypted.result.sender_key,
1353 event_type = decrypted.result.event.event_type(),
1354 ),
1355 )]
1356 async fn handle_decrypted_to_device_event(
1357 &self,
1358 cache: &StoreCache,
1359 decrypted: &mut OlmDecryptionInfo,
1360 changes: &mut Changes,
1361 ) -> OlmResult<()> {
1362 debug!(
1363 sender_device_keys =
1364 ?decrypted.result.event.sender_device_keys().map(|k| (k.curve25519_key(), k.ed25519_key())).unwrap_or((None, None)),
1365 "Received a decrypted to-device event",
1366 );
1367
1368 match &*decrypted.result.event {
1369 AnyDecryptedOlmEvent::RoomKey(e) => {
1370 let session = self.add_room_key(decrypted.result.sender_key, e).await?;
1371 decrypted.inbound_group_session = session;
1372 }
1373 AnyDecryptedOlmEvent::ForwardedRoomKey(e) => {
1374 let session = self
1375 .inner
1376 .key_request_machine
1377 .receive_forwarded_room_key(decrypted.result.sender_key, e)
1378 .await?;
1379 decrypted.inbound_group_session = session;
1380 }
1381 AnyDecryptedOlmEvent::SecretSend(e) => {
1382 let name = self
1383 .inner
1384 .key_request_machine
1385 .receive_secret_event(cache, decrypted.result.sender_key, e, changes)
1386 .await?;
1387
1388 if let Ok(ToDeviceEvents::SecretSend(mut e)) =
1391 decrypted.result.raw_event.deserialize_as()
1392 {
1393 e.content.secret_name = name;
1394 decrypted.result.raw_event = Raw::from_json(to_raw_value(&e)?);
1395 }
1396
1397 if enabled!(tracing::Level::DEBUG) {
1398 let cross_signing_status = self.cross_signing_status().await;
1399 let backup_enabled = self.backup_machine().enabled().await;
1400 debug!(
1401 ?cross_signing_status,
1402 backup_enabled, "Status after receiving secret event"
1403 );
1404 }
1405 }
1406 AnyDecryptedOlmEvent::Dummy(_) => {
1407 debug!("Received an `m.dummy` event");
1408 }
1409 AnyDecryptedOlmEvent::RoomKeyBundle(e) => {
1410 debug!("Received a room key bundle event {:?}", e);
1411 self.receive_room_key_bundle_data(decrypted.result.sender_key, e, changes).await?;
1412 }
1413 #[cfg(feature = "experimental-push-secrets")]
1414 AnyDecryptedOlmEvent::SecretPush(e) => {
1415 self.inner
1416 .key_request_machine
1417 .receive_secret_push_event(&decrypted.result.sender_key, e, changes)
1418 .await?;
1419 }
1420 AnyDecryptedOlmEvent::Custom(_) => {
1421 warn!("Received an unexpected encrypted to-device event");
1422 }
1423 }
1424
1425 Ok(())
1426 }
1427
1428 async fn handle_verification_event(&self, event: &ToDeviceEvents) {
1429 if let Err(e) = self.inner.verification_machine.receive_any_event(event).await {
1430 error!("Error handling a verification event: {e:?}");
1431 }
1432 }
1433
1434 async fn mark_to_device_request_as_sent(&self, request_id: &TransactionId) -> StoreResult<()> {
1436 self.inner.verification_machine.mark_request_as_sent(request_id);
1437 self.inner.key_request_machine.mark_outgoing_request_as_sent(request_id).await?;
1438 self.inner.group_session_manager.mark_request_as_sent(request_id).await?;
1439 self.inner.session_manager.mark_outgoing_request_as_sent(request_id);
1440 Ok(())
1441 }
1442
1443 pub fn get_verification(&self, user_id: &UserId, flow_id: &str) -> Option<Verification> {
1445 self.inner.verification_machine.get_verification(user_id, flow_id)
1446 }
1447
1448 pub fn get_verification_request(
1450 &self,
1451 user_id: &UserId,
1452 flow_id: impl AsRef<str>,
1453 ) -> Option<VerificationRequest> {
1454 self.inner.verification_machine.get_request(user_id, flow_id)
1455 }
1456
1457 pub fn get_verification_requests(&self, user_id: &UserId) -> Vec<VerificationRequest> {
1459 self.inner.verification_machine.get_requests(user_id)
1460 }
1461
1462 async fn handle_to_device_event(&self, changes: &mut Changes, event: &ToDeviceEvents) {
1467 use crate::types::events::ToDeviceEvents::*;
1468
1469 match event {
1470 RoomKeyRequest(e) => self.inner.key_request_machine.receive_incoming_key_request(e),
1476 SecretRequest(e) => self.inner.key_request_machine.receive_incoming_secret_request(e),
1477 RoomKeyWithheld(e) => self.add_withheld_info(changes, e),
1478 KeyVerificationAccept(..)
1479 | KeyVerificationCancel(..)
1480 | KeyVerificationKey(..)
1481 | KeyVerificationMac(..)
1482 | KeyVerificationRequest(..)
1483 | KeyVerificationReady(..)
1484 | KeyVerificationDone(..)
1485 | KeyVerificationStart(..) => {
1486 self.handle_verification_event(event).await;
1487 }
1488
1489 Custom(_) | Dummy(_) => {}
1491
1492 RoomEncrypted(_) => {}
1494
1495 SecretSend(_) | RoomKey(_) | ForwardedRoomKey(_) => {}
1498 }
1499 }
1500
1501 fn record_message_id(event: &Raw<AnyToDeviceEvent>) {
1502 use serde::Deserialize;
1503
1504 #[derive(Deserialize)]
1505 struct ContentStub<'a> {
1506 #[serde(borrow, rename = "org.matrix.msgid")]
1507 message_id: Option<&'a str>,
1508 }
1509 #[derive(Deserialize)]
1510 struct ToDeviceStub<'a> {
1511 sender: &'a str,
1512 #[serde(rename = "type")]
1513 event_type: &'a str,
1514 #[serde(borrow)]
1515 content: ContentStub<'a>,
1516 }
1517
1518 if let Ok(event) = event.deserialize_as_unchecked::<ToDeviceStub<'_>>() {
1519 Span::current().record("sender", event.sender);
1520 Span::current().record("event_type", event.event_type);
1521 Span::current().record("message_id", event.content.message_id);
1522 }
1523 }
1524
1525 #[instrument(skip_all, fields(sender, event_type, message_id))]
1533 async fn receive_to_device_event(
1534 &self,
1535 transaction: &mut StoreTransaction,
1536 changes: &mut Changes,
1537 raw_event: Raw<AnyToDeviceEvent>,
1538 decryption_settings: &DecryptionSettings,
1539 ) -> Option<ProcessedToDeviceEvent> {
1540 Self::record_message_id(&raw_event);
1541
1542 let event: ToDeviceEvents = match raw_event.deserialize_as() {
1543 Ok(e) => e,
1544 Err(e) => {
1545 warn!("Received an invalid to-device event: {e}");
1547 return Some(ProcessedToDeviceEvent::Invalid(raw_event));
1548 }
1549 };
1550
1551 debug!("Received a to-device event");
1552
1553 match event {
1554 ToDeviceEvents::RoomEncrypted(e) => {
1555 self.receive_encrypted_to_device_event(
1556 transaction,
1557 changes,
1558 raw_event,
1559 e,
1560 decryption_settings,
1561 )
1562 .await
1563 }
1564 e => {
1565 self.handle_to_device_event(changes, &e).await;
1566 Some(ProcessedToDeviceEvent::PlainText(raw_event))
1567 }
1568 }
1569 }
1570
1571 async fn receive_encrypted_to_device_event(
1585 &self,
1586 transaction: &mut StoreTransaction,
1587 changes: &mut Changes,
1588 mut raw_event: Raw<AnyToDeviceEvent>,
1589 e: ToDeviceEvent<ToDeviceEncryptedEventContent>,
1590 decryption_settings: &DecryptionSettings,
1591 ) -> Option<ProcessedToDeviceEvent> {
1592 let decrypted = match self
1593 .decrypt_to_device_event(transaction, &e, changes, decryption_settings)
1594 .await
1595 {
1596 Ok(decrypted) => decrypted,
1597 Err(DecryptToDeviceError::OlmError(err)) => {
1598 let reason = if let OlmError::UnverifiedSenderDevice = &err {
1599 ToDeviceUnableToDecryptReason::UnverifiedSenderDevice
1600 } else {
1601 ToDeviceUnableToDecryptReason::DecryptionFailure
1602 };
1603
1604 if let OlmError::SessionWedged(sender, curve_key) = err
1605 && let Err(e) =
1606 self.inner.session_manager.mark_device_as_wedged(&sender, curve_key).await
1607 {
1608 error!(
1609 error = ?e,
1610 "Couldn't mark device to be unwedged",
1611 );
1612 }
1613
1614 return Some(ProcessedToDeviceEvent::UnableToDecrypt {
1615 encrypted_event: raw_event,
1616 utd_info: ToDeviceUnableToDecryptInfo { reason },
1617 });
1618 }
1619 Err(DecryptToDeviceError::FromDehydratedDevice) => return None,
1620 };
1621
1622 match decrypted.session {
1625 SessionType::New(s) | SessionType::Existing(s) => {
1626 changes.sessions.push(s);
1627 }
1628 }
1629
1630 changes.message_hashes.push(decrypted.message_hash);
1631
1632 if let Some(group_session) = decrypted.inbound_group_session {
1633 changes.inbound_group_sessions.push(group_session);
1634 }
1635
1636 match decrypted.result.raw_event.deserialize_as() {
1637 Ok(event) => {
1638 self.handle_to_device_event(changes, &event).await;
1639
1640 raw_event = event
1641 .serialize_zeroized()
1642 .expect("Zeroizing and reserializing our events should always work")
1643 .cast();
1644 }
1645 Err(e) => {
1646 warn!("Received an invalid encrypted to-device event: {e}");
1647 raw_event = decrypted.result.raw_event;
1648 }
1649 }
1650
1651 Some(ProcessedToDeviceEvent::Decrypted {
1652 raw: raw_event,
1653 encryption_info: decrypted.result.encryption_info,
1654 })
1655 }
1656
1657 async fn check_to_device_event_is_not_from_dehydrated_device(
1660 &self,
1661 decrypted: &OlmDecryptionInfo,
1662 sender_user_id: &UserId,
1663 ) -> Result<(), DecryptToDeviceError> {
1664 if self.to_device_event_is_from_dehydrated_device(decrypted, sender_user_id).await? {
1665 warn!(
1666 sender = ?sender_user_id,
1667 session = ?decrypted.session,
1668 "Received a to-device event from a dehydrated device. This is unexpected: ignoring event"
1669 );
1670 Err(DecryptToDeviceError::FromDehydratedDevice)
1671 } else {
1672 Ok(())
1673 }
1674 }
1675
1676 async fn to_device_event_is_from_dehydrated_device(
1682 &self,
1683 decrypted: &OlmDecryptionInfo,
1684 sender_user_id: &UserId,
1685 ) -> OlmResult<bool> {
1686 if let Some(device_keys) = decrypted.result.event.sender_device_keys() {
1688 if device_keys.dehydrated.unwrap_or(false) {
1694 return Ok(true);
1695 }
1696 }
1701
1702 Ok(self
1704 .store()
1705 .get_device_from_curve_key(sender_user_id, decrypted.result.sender_key)
1706 .await?
1707 .is_some_and(|d| d.is_dehydrated()))
1708 }
1709
1710 #[instrument(skip_all)]
1728 pub async fn receive_sync_changes(
1729 &self,
1730 sync_changes: EncryptionSyncChanges<'_>,
1731 decryption_settings: &DecryptionSettings,
1732 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Vec<RoomKeyInfo>)> {
1733 let mut store_transaction = self.inner.store.transaction().await;
1734
1735 let (events, changes) = self
1736 .preprocess_sync_changes(&mut store_transaction, sync_changes, decryption_settings)
1737 .await?;
1738
1739 let room_key_updates: Vec<_> =
1742 changes.inbound_group_sessions.iter().map(RoomKeyInfo::from).collect();
1743
1744 self.store().save_changes(changes).await?;
1745 store_transaction.commit().await?;
1746
1747 Ok((events, room_key_updates))
1748 }
1749
1750 pub(crate) async fn preprocess_sync_changes(
1768 &self,
1769 transaction: &mut StoreTransaction,
1770 sync_changes: EncryptionSyncChanges<'_>,
1771 decryption_settings: &DecryptionSettings,
1772 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Changes)> {
1773 let mut events: Vec<ProcessedToDeviceEvent> = self
1775 .inner
1776 .verification_machine
1777 .garbage_collect()
1778 .iter()
1779 .map(|e| ProcessedToDeviceEvent::PlainText(e.clone()))
1783 .collect();
1784 let mut changes = Default::default();
1787
1788 {
1789 let account = transaction.account().await?;
1790 account.update_key_counts(
1791 sync_changes.one_time_keys_counts,
1792 sync_changes.unused_fallback_keys,
1793 )
1794 }
1795
1796 if let Err(e) = self
1797 .inner
1798 .identity_manager
1799 .receive_device_changes(
1800 transaction.cache(),
1801 sync_changes.changed_devices.changed.iter().map(|u| u.as_ref()),
1802 )
1803 .await
1804 {
1805 error!(error = ?e, "Error marking a tracked user as changed");
1806 }
1807
1808 for raw_event in sync_changes.to_device_events {
1809 let processed_event = Box::pin(self.receive_to_device_event(
1810 transaction,
1811 &mut changes,
1812 raw_event,
1813 decryption_settings,
1814 ))
1815 .await;
1816
1817 if let Some(processed_event) = processed_event {
1818 events.push(processed_event);
1819 }
1820 }
1821
1822 let changed_sessions = self
1823 .inner
1824 .key_request_machine
1825 .collect_incoming_key_requests(transaction.cache())
1826 .await?;
1827
1828 changes.sessions.extend(changed_sessions);
1829 changes.next_batch_token = sync_changes.next_batch_token;
1830
1831 Ok((events, changes))
1832 }
1833
1834 pub async fn request_room_key(
1851 &self,
1852 event: &Raw<EncryptedEvent>,
1853 room_id: &RoomId,
1854 ) -> MegolmResult<(Option<OutgoingRequest>, OutgoingRequest)> {
1855 let event = event.deserialize()?;
1856 self.inner.key_request_machine.request_key(room_id, &event).await
1857 }
1858
1859 async fn get_room_event_verification_state(
1872 &self,
1873 session: &InboundGroupSession,
1874 sender: &UserId,
1875 ) -> MegolmResult<(VerificationState, Option<OwnedDeviceId>)> {
1876 let sender_data = self.get_or_update_sender_data(session, sender).await?;
1877
1878 let (verification_state, device_id) = match sender_data.user_id() {
1887 Some(i) if i != sender => {
1888 (VerificationState::Unverified(VerificationLevel::MismatchedSender), None)
1889 }
1890
1891 Some(_) | None => {
1892 sender_data_to_verification_state(sender_data, session.has_been_imported())
1893 }
1894 };
1895
1896 Ok((verification_state, device_id))
1897 }
1898
1899 async fn get_or_update_sender_data(
1914 &self,
1915 session: &InboundGroupSession,
1916 sender: &UserId,
1917 ) -> MegolmResult<SenderData> {
1918 let sender_data = if session.sender_data.should_recalculate() {
1919 let calculated_sender_data = SenderDataFinder::find_using_curve_key(
1938 self.store(),
1939 session.sender_key(),
1940 sender,
1941 session,
1942 )
1943 .await?;
1944
1945 if calculated_sender_data.compare_trust_level(&session.sender_data).is_gt() {
1947 let mut new_session = session.clone();
1949 new_session.sender_data = calculated_sender_data.clone();
1950 self.store().save_inbound_group_sessions(&[new_session]).await?;
1951
1952 calculated_sender_data
1954 } else {
1955 session.sender_data.clone()
1957 }
1958 } else {
1959 session.sender_data.clone()
1960 };
1961
1962 Ok(sender_data)
1963 }
1964
1965 pub async fn query_missing_secrets_from_other_sessions(&self) -> StoreResult<bool> {
1990 let identity = self.inner.user_identity.lock().await;
1991 let mut secrets = identity.get_missing_secrets().await;
1992
1993 if self.store().load_backup_keys().await?.decryption_key.is_none() {
1994 secrets.push(SecretName::RecoveryKey);
1995 }
1996
1997 if secrets.is_empty() {
1998 debug!("No missing requests to query");
1999 return Ok(false);
2000 }
2001
2002 let secret_requests = GossipMachine::request_missing_secrets(self.user_id(), secrets);
2003
2004 let unsent_request = self.store().get_unsent_secret_requests().await?;
2006 let not_yet_requested = secret_requests
2007 .into_iter()
2008 .filter(|request| !unsent_request.iter().any(|unsent| unsent.info == request.info))
2009 .collect_vec();
2010
2011 if not_yet_requested.is_empty() {
2012 debug!("The missing secrets have already been requested");
2013 Ok(false)
2014 } else {
2015 debug!("Requesting missing secrets");
2016
2017 let changes = Changes { key_requests: not_yet_requested, ..Default::default() };
2018
2019 self.store().save_changes(changes).await?;
2020 Ok(true)
2021 }
2022 }
2023
2024 #[cfg(feature = "experimental-push-secrets")]
2032 pub async fn push_secret_to_verified_devices(
2033 &self,
2034 secret_name: SecretName,
2035 ) -> Result<HashMap<OwnedDeviceId, OlmError>, SecretPushError> {
2036 self.inner.key_request_machine.push_secret_to_verified_devices(secret_name).await
2037 }
2038
2039 async fn get_encryption_info(
2045 &self,
2046 session: &InboundGroupSession,
2047 sender: &UserId,
2048 ) -> MegolmResult<Arc<EncryptionInfo>> {
2049 let (verification_state, device_id) =
2050 self.get_room_event_verification_state(session, sender).await?;
2051
2052 Ok(Arc::new(EncryptionInfo {
2053 sender: sender.to_owned(),
2054 sender_device: device_id,
2055 forwarder: session.forwarder_data.as_ref().and_then(|data| {
2056 data.device_id().map(|device_id| ForwarderInfo {
2060 device_id: device_id.to_owned(),
2061 user_id: data.user_id().to_owned(),
2062 })
2063 }),
2064 algorithm_info: AlgorithmInfo::MegolmV1AesSha2 {
2065 curve25519_key: session.sender_key().to_base64(),
2066 sender_claimed_keys: session
2067 .signing_keys()
2068 .iter()
2069 .map(|(k, v)| (k.to_owned(), v.to_base64()))
2070 .collect(),
2071 session_id: Some(session.session_id().to_owned()),
2072 },
2073 verification_state,
2074 }))
2075 }
2076
2077 async fn decrypt_megolm_events(
2078 &self,
2079 room_id: &RoomId,
2080 event: &EncryptedEvent,
2081 content: &SupportedEventEncryptionSchemes<'_>,
2082 decryption_settings: &DecryptionSettings,
2083 ) -> MegolmResult<(JsonObject, Arc<EncryptionInfo>)> {
2084 let session =
2085 self.get_inbound_group_session_or_error(room_id, content.session_id()).await?;
2086
2087 Span::current().record("sender_key", debug(session.sender_key()));
2093
2094 let result = session.decrypt(event).await;
2095 match result {
2096 Ok((decrypted_event, _)) => {
2097 let encryption_info = self.get_encryption_info(&session, &event.sender).await?;
2098
2099 self.check_sender_trust_requirement(
2100 &session,
2101 &encryption_info,
2102 &decryption_settings.sender_device_trust_requirement,
2103 )?;
2104
2105 Ok((decrypted_event, encryption_info))
2106 }
2107 Err(error) => Err(
2108 if let MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) = error {
2109 let withheld_code = self
2110 .inner
2111 .store
2112 .get_withheld_info(room_id, content.session_id())
2113 .await?
2114 .map(|e| e.content.withheld_code());
2115
2116 if withheld_code.is_some() {
2117 MegolmError::MissingRoomKey(withheld_code)
2119 } else {
2120 error
2121 }
2122 } else {
2123 error
2124 },
2125 ),
2126 }
2127 }
2128
2129 fn check_sender_trust_requirement(
2135 &self,
2136 session: &InboundGroupSession,
2137 encryption_info: &EncryptionInfo,
2138 trust_requirement: &TrustRequirement,
2139 ) -> MegolmResult<()> {
2140 trace!(
2141 verification_state = ?encryption_info.verification_state,
2142 ?trust_requirement, "check_sender_trust_requirement",
2143 );
2144
2145 let verification_level = match &encryption_info.verification_state {
2148 VerificationState::Verified => return Ok(()),
2149 VerificationState::Unverified(verification_level) => verification_level,
2150 };
2151
2152 let ok = match trust_requirement {
2153 TrustRequirement::Untrusted => true,
2154
2155 TrustRequirement::CrossSignedOrLegacy => {
2156 let legacy_session = match session.sender_data {
2162 SenderData::DeviceInfo { legacy_session, .. } => legacy_session,
2163 SenderData::UnknownDevice { legacy_session, .. } => legacy_session,
2164 _ => false,
2165 };
2166
2167 match (verification_level, legacy_session) {
2177 (VerificationLevel::UnverifiedIdentity, _) => true,
2179
2180 (VerificationLevel::UnsignedDevice, true) => true,
2182
2183 (VerificationLevel::None(_), true) => true,
2185
2186 (VerificationLevel::VerificationViolation, _)
2188 | (VerificationLevel::MismatchedSender, _)
2189 | (VerificationLevel::UnsignedDevice, false)
2190 | (VerificationLevel::None(_), false) => false,
2191 }
2192 }
2193
2194 TrustRequirement::CrossSigned => match verification_level {
2197 VerificationLevel::UnverifiedIdentity => true,
2198
2199 VerificationLevel::VerificationViolation
2200 | VerificationLevel::MismatchedSender
2201 | VerificationLevel::UnsignedDevice
2202 | VerificationLevel::None(_) => false,
2203 },
2204 };
2205
2206 if ok {
2207 Ok(())
2208 } else {
2209 Err(MegolmError::SenderIdentityNotTrusted(verification_level.clone()))
2210 }
2211 }
2212
2213 async fn get_inbound_group_session_or_error(
2218 &self,
2219 room_id: &RoomId,
2220 session_id: &str,
2221 ) -> MegolmResult<InboundGroupSession> {
2222 match self.store().get_inbound_group_session(room_id, session_id).await? {
2223 Some(session) => Ok(session),
2224 None => {
2225 let withheld_code = self
2226 .inner
2227 .store
2228 .get_withheld_info(room_id, session_id)
2229 .await?
2230 .map(|e| e.content.withheld_code());
2231 Err(MegolmError::MissingRoomKey(withheld_code))
2232 }
2233 }
2234 }
2235
2236 pub async fn try_decrypt_room_event(
2251 &self,
2252 raw_event: &Raw<EncryptedEvent>,
2253 room_id: &RoomId,
2254 decryption_settings: &DecryptionSettings,
2255 ) -> Result<RoomEventDecryptionResult, CryptoStoreError> {
2256 match self.decrypt_room_event_inner(raw_event, room_id, true, decryption_settings).await {
2257 Ok(decrypted) => Ok(RoomEventDecryptionResult::Decrypted(decrypted)),
2258 Err(err) => Ok(RoomEventDecryptionResult::UnableToDecrypt(megolm_error_to_utd_info(
2259 raw_event, err,
2260 )?)),
2261 }
2262 }
2263
2264 pub async fn decrypt_room_event(
2272 &self,
2273 event: &Raw<EncryptedEvent>,
2274 room_id: &RoomId,
2275 decryption_settings: &DecryptionSettings,
2276 ) -> MegolmResult<DecryptedRoomEvent> {
2277 self.decrypt_room_event_inner(event, room_id, true, decryption_settings).await
2278 }
2279
2280 #[instrument(name = "decrypt_room_event", skip_all, fields(?room_id, event_id, origin_server_ts, sender, algorithm, session_id, message_index, sender_key))]
2281 async fn decrypt_room_event_inner(
2282 &self,
2283 event: &Raw<EncryptedEvent>,
2284 room_id: &RoomId,
2285 decrypt_unsigned: bool,
2286 decryption_settings: &DecryptionSettings,
2287 ) -> MegolmResult<DecryptedRoomEvent> {
2288 let _timer = timer!(tracing::Level::TRACE, "_method");
2289
2290 let event = event.deserialize()?;
2291
2292 Span::current()
2293 .record("sender", debug(&event.sender))
2294 .record("event_id", debug(&event.event_id))
2295 .record(
2296 "origin_server_ts",
2297 timestamp_to_iso8601(event.origin_server_ts)
2298 .unwrap_or_else(|| "<out of range>".to_owned()),
2299 )
2300 .record("algorithm", debug(event.content.algorithm()));
2301
2302 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2303 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2304 Span::current().record("sender_key", debug(c.sender_key));
2305 c.into()
2306 }
2307 #[cfg(feature = "experimental-algorithms")]
2308 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2309 RoomEventEncryptionScheme::Unknown(_) => {
2310 warn!("Received an encrypted room event with an unsupported algorithm");
2311 return Err(EventError::UnsupportedAlgorithm.into());
2312 }
2313 };
2314
2315 Span::current().record("session_id", content.session_id());
2316 Span::current().record("message_index", content.message_index());
2317
2318 let result =
2319 self.decrypt_megolm_events(room_id, &event, &content, decryption_settings).await;
2320
2321 if let Err(e) = &result {
2322 #[cfg(feature = "automatic-room-key-forwarding")]
2323 match e {
2324 MegolmError::MissingRoomKey(_)
2327 | MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
2328 self.inner
2329 .key_request_machine
2330 .create_outgoing_key_request(room_id, &event)
2331 .await?;
2332 }
2333 _ => {}
2334 }
2335
2336 warn!("Failed to decrypt a room event: {e}");
2337 }
2338
2339 let (mut decrypted_event, encryption_info) = result?;
2340
2341 let mut unsigned_encryption_info = None;
2342 if decrypt_unsigned {
2343 unsigned_encryption_info = self
2345 .decrypt_unsigned_events(&mut decrypted_event, room_id, decryption_settings)
2346 .await;
2347 }
2348
2349 let decrypted_event =
2350 serde_json::from_value::<Raw<AnyTimelineEvent>>(decrypted_event.into())?;
2351
2352 #[cfg(feature = "experimental-encrypted-state-events")]
2353 self.verify_packed_state_key(&event, &decrypted_event)?;
2354
2355 Ok(DecryptedRoomEvent { event: decrypted_event, encryption_info, unsigned_encryption_info })
2356 }
2357
2358 #[cfg(feature = "experimental-encrypted-state-events")]
2375 fn verify_packed_state_key(
2376 &self,
2377 original: &EncryptedEvent,
2378 decrypted: &Raw<AnyTimelineEvent>,
2379 ) -> MegolmResult<()> {
2380 use serde::Deserialize;
2381
2382 #[derive(Deserialize)]
2384 struct PayloadDeserializationHelper {
2385 state_key: Option<String>,
2386 #[serde(rename = "type")]
2387 event_type: String,
2388 }
2389
2390 let PayloadDeserializationHelper {
2392 state_key: inner_state_key,
2393 event_type: inner_event_type,
2394 } = decrypted
2395 .deserialize_as_unchecked()
2396 .map_err(|_| MegolmError::StateKeyVerificationFailed)?;
2397
2398 let (raw_state_key, inner_state_key) = match (&original.state_key, &inner_state_key) {
2400 (Some(raw_state_key), Some(inner_state_key)) => (raw_state_key, inner_state_key),
2401 (None, None) => return Ok(()),
2402 _ => return Err(MegolmError::StateKeyVerificationFailed),
2403 };
2404
2405 let (outer_event_type, outer_state_key) =
2407 raw_state_key.split_once(":").ok_or(MegolmError::StateKeyVerificationFailed)?;
2408
2409 if outer_event_type != inner_event_type {
2411 return Err(MegolmError::StateKeyVerificationFailed);
2412 }
2413
2414 if outer_state_key != inner_state_key {
2416 return Err(MegolmError::StateKeyVerificationFailed);
2417 }
2418 Ok(())
2419 }
2420
2421 async fn decrypt_unsigned_events(
2431 &self,
2432 main_event: &mut JsonObject,
2433 room_id: &RoomId,
2434 decryption_settings: &DecryptionSettings,
2435 ) -> Option<BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>> {
2436 let unsigned = main_event.get_mut("unsigned")?.as_object_mut()?;
2437 let mut unsigned_encryption_info: Option<
2438 BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>,
2439 > = None;
2440
2441 let location = UnsignedEventLocation::RelationsReplace;
2443 let replace = location.find_mut(unsigned);
2444 if let Some(decryption_result) =
2445 self.decrypt_unsigned_event(replace, room_id, decryption_settings).await
2446 {
2447 unsigned_encryption_info
2448 .get_or_insert_with(Default::default)
2449 .insert(location, decryption_result);
2450 }
2451
2452 let location = UnsignedEventLocation::RelationsThreadLatestEvent;
2455 let thread_latest_event = location.find_mut(unsigned);
2456 if let Some(decryption_result) =
2457 self.decrypt_unsigned_event(thread_latest_event, room_id, decryption_settings).await
2458 {
2459 unsigned_encryption_info
2460 .get_or_insert_with(Default::default)
2461 .insert(location, decryption_result);
2462 }
2463
2464 unsigned_encryption_info
2465 }
2466
2467 fn decrypt_unsigned_event<'a>(
2475 &'a self,
2476 event: Option<&'a mut Value>,
2477 room_id: &'a RoomId,
2478 decryption_settings: &'a DecryptionSettings,
2479 ) -> BoxFuture<'a, Option<UnsignedDecryptionResult>> {
2480 Box::pin(async move {
2481 let event = event?;
2482
2483 let is_encrypted = event
2484 .get("type")
2485 .and_then(|type_| type_.as_str())
2486 .is_some_and(|s| s == "m.room.encrypted");
2487 if !is_encrypted {
2488 return None;
2489 }
2490
2491 let raw_event = serde_json::from_value(event.clone()).ok()?;
2492 match self
2493 .decrypt_room_event_inner(&raw_event, room_id, false, decryption_settings)
2494 .await
2495 {
2496 Ok(decrypted_event) => {
2497 *event = serde_json::to_value(decrypted_event.event).ok()?;
2499 Some(UnsignedDecryptionResult::Decrypted(decrypted_event.encryption_info))
2500 }
2501 Err(err) => {
2502 let utd_info = megolm_error_to_utd_info(&raw_event, err).ok()?;
2507 Some(UnsignedDecryptionResult::UnableToDecrypt(utd_info))
2508 }
2509 }
2510 })
2511 }
2512
2513 pub async fn is_room_key_available(
2520 &self,
2521 event: &Raw<EncryptedEvent>,
2522 room_id: &RoomId,
2523 ) -> Result<bool, CryptoStoreError> {
2524 let event = event.deserialize()?;
2525
2526 let (session_id, message_index) = match &event.content.scheme {
2527 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2528 (&c.session_id, c.ciphertext.message_index())
2529 }
2530 #[cfg(feature = "experimental-algorithms")]
2531 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => {
2532 (&c.session_id, c.ciphertext.message_index())
2533 }
2534 RoomEventEncryptionScheme::Unknown(_) => {
2535 return Ok(false);
2537 }
2538 };
2539
2540 Ok(self
2543 .store()
2544 .get_inbound_group_session(room_id, session_id)
2545 .await?
2546 .filter(|s| s.first_known_index() <= message_index)
2547 .is_some())
2548 }
2549
2550 #[instrument(skip(self, event), fields(event_id, sender, session_id))]
2563 pub async fn get_room_event_encryption_info(
2564 &self,
2565 event: &Raw<EncryptedEvent>,
2566 room_id: &RoomId,
2567 ) -> MegolmResult<Arc<EncryptionInfo>> {
2568 let event = event.deserialize()?;
2569
2570 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2571 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => c.into(),
2572 #[cfg(feature = "experimental-algorithms")]
2573 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2574 RoomEventEncryptionScheme::Unknown(_) => {
2575 return Err(EventError::UnsupportedAlgorithm.into());
2576 }
2577 };
2578
2579 Span::current()
2580 .record("sender", debug(&event.sender))
2581 .record("event_id", debug(&event.event_id))
2582 .record("session_id", content.session_id());
2583
2584 self.get_session_encryption_info(room_id, content.session_id(), &event.sender).await
2585 }
2586
2587 pub async fn get_session_encryption_info(
2602 &self,
2603 room_id: &RoomId,
2604 session_id: &str,
2605 sender: &UserId,
2606 ) -> MegolmResult<Arc<EncryptionInfo>> {
2607 let session = self.get_inbound_group_session_or_error(room_id, session_id).await?;
2608 self.get_encryption_info(&session, sender).await
2609 }
2610
2611 pub async fn update_tracked_users(
2629 &self,
2630 users: impl IntoIterator<Item = &UserId>,
2631 ) -> StoreResult<()> {
2632 self.inner.identity_manager.update_tracked_users(users).await
2633 }
2634
2635 pub async fn mark_all_tracked_users_as_dirty(&self) -> StoreResult<()> {
2640 self.inner
2641 .identity_manager
2642 .mark_all_tracked_users_as_dirty(self.inner.store.cache().await?)
2643 .await
2644 }
2645
2646 async fn wait_if_user_pending(
2647 &self,
2648 user_id: &UserId,
2649 timeout: Option<Duration>,
2650 ) -> StoreResult<()> {
2651 if let Some(timeout) = timeout {
2652 let cache = self.store().cache().await?;
2653 self.inner
2654 .identity_manager
2655 .key_query_manager
2656 .wait_if_user_key_query_pending(cache, timeout, user_id)
2657 .await?;
2658 }
2659 Ok(())
2660 }
2661
2662 #[instrument(skip(self))]
2692 pub async fn get_device(
2693 &self,
2694 user_id: &UserId,
2695 device_id: &DeviceId,
2696 timeout: Option<Duration>,
2697 ) -> StoreResult<Option<Device>> {
2698 self.wait_if_user_pending(user_id, timeout).await?;
2699 self.store().get_device(user_id, device_id).await
2700 }
2701
2702 #[instrument(skip(self))]
2716 pub async fn get_identity(
2717 &self,
2718 user_id: &UserId,
2719 timeout: Option<Duration>,
2720 ) -> StoreResult<Option<UserIdentity>> {
2721 self.wait_if_user_pending(user_id, timeout).await?;
2722 self.store().get_identity(user_id).await
2723 }
2724
2725 #[instrument(skip(self))]
2752 pub async fn get_user_devices(
2753 &self,
2754 user_id: &UserId,
2755 timeout: Option<Duration>,
2756 ) -> StoreResult<UserDevices> {
2757 self.wait_if_user_pending(user_id, timeout).await?;
2758 self.store().get_user_devices(user_id).await
2759 }
2760
2761 pub async fn cross_signing_status(&self) -> CrossSigningStatus {
2766 self.inner.user_identity.lock().await.status().await
2767 }
2768
2769 pub async fn export_cross_signing_keys(&self) -> StoreResult<Option<CrossSigningKeyExport>> {
2777 let master_key = self.store().export_secret(&SecretName::CrossSigningMasterKey).await?;
2778 let self_signing_key =
2779 self.store().export_secret(&SecretName::CrossSigningSelfSigningKey).await?;
2780 let user_signing_key =
2781 self.store().export_secret(&SecretName::CrossSigningUserSigningKey).await?;
2782
2783 Ok(if master_key.is_none() && self_signing_key.is_none() && user_signing_key.is_none() {
2784 None
2785 } else {
2786 Some(CrossSigningKeyExport { master_key, self_signing_key, user_signing_key })
2787 })
2788 }
2789
2790 pub async fn import_cross_signing_keys(
2795 &self,
2796 export: CrossSigningKeyExport,
2797 ) -> Result<CrossSigningStatus, SecretImportError> {
2798 self.store().import_cross_signing_keys(export).await
2799 }
2800
2801 async fn sign_with_master_key(
2802 &self,
2803 message: &str,
2804 ) -> Result<(OwnedDeviceKeyId, Ed25519Signature), SignatureError> {
2805 let identity = &*self.inner.user_identity.lock().await;
2806 let key_id = identity.master_key_id().await.ok_or(SignatureError::MissingSigningKey)?;
2807
2808 let signature = identity.sign(message).await?;
2809
2810 Ok((key_id, signature))
2811 }
2812
2813 pub async fn sign(&self, message: &str) -> Result<Signatures, CryptoStoreError> {
2819 let mut signatures = Signatures::new();
2820
2821 {
2822 let cache = self.inner.store.cache().await?;
2823 let account = cache.account().await?;
2824 let key_id = account.signing_key_id();
2825 let signature = account.sign(message);
2826 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
2827 }
2828
2829 match self.sign_with_master_key(message).await {
2830 Ok((key_id, signature)) => {
2831 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
2832 }
2833 Err(e) => {
2834 warn!(error = ?e, "Couldn't sign the message using the cross signing master key")
2835 }
2836 }
2837
2838 Ok(signatures)
2839 }
2840
2841 pub fn backup_machine(&self) -> &BackupMachine {
2846 &self.inner.backup_machine
2847 }
2848
2849 pub async fn initialize_crypto_store_generation(
2853 &self,
2854 generation: &Mutex<Option<u64>>,
2855 ) -> StoreResult<()> {
2856 let mut gen_guard = generation.lock().await;
2859
2860 let prev_generation =
2861 self.inner.store.get_custom_value(Self::CURRENT_GENERATION_STORE_KEY).await?;
2862
2863 let generation = match prev_generation {
2864 Some(val) => {
2865 u64::from_le_bytes(val.try_into().map_err(|_| {
2868 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
2869 })?)
2870 .wrapping_add(1)
2871 }
2872 None => 0,
2873 };
2874
2875 tracing::debug!("Initialising crypto store generation at {generation}");
2876
2877 self.inner
2878 .store
2879 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, generation.to_le_bytes().to_vec())
2880 .await?;
2881
2882 *gen_guard = Some(generation);
2883
2884 Ok(())
2885 }
2886
2887 pub async fn maintain_crypto_store_generation(
2912 &'_ self,
2913 generation: &Mutex<Option<u64>>,
2914 ) -> StoreResult<(bool, u64)> {
2915 let mut gen_guard = generation.lock().await;
2916
2917 let actual_gen = self
2923 .inner
2924 .store
2925 .get_custom_value(Self::CURRENT_GENERATION_STORE_KEY)
2926 .await?
2927 .ok_or_else(|| {
2928 CryptoStoreError::InvalidLockGeneration("counter missing in store".to_owned())
2929 })?;
2930
2931 let actual_gen =
2932 u64::from_le_bytes(actual_gen.try_into().map_err(|_| {
2933 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
2934 })?);
2935
2936 let new_gen = match gen_guard.as_ref() {
2937 Some(expected_gen) => {
2938 if actual_gen == *expected_gen {
2939 return Ok((false, actual_gen));
2940 }
2941 actual_gen.max(*expected_gen).wrapping_add(1)
2943 }
2944 None => {
2945 actual_gen.wrapping_add(1)
2948 }
2949 };
2950
2951 tracing::debug!(
2952 "Crypto store generation mismatch: previously known was {:?}, actual is {:?}, next is {}",
2953 *gen_guard,
2954 actual_gen,
2955 new_gen
2956 );
2957
2958 *gen_guard = Some(new_gen);
2960
2961 self.inner
2963 .store
2964 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, new_gen.to_le_bytes().to_vec())
2965 .await?;
2966
2967 Ok((true, new_gen))
2968 }
2969
2970 pub fn dehydrated_devices(&self) -> DehydratedDevices {
2972 DehydratedDevices { inner: self.to_owned() }
2973 }
2974
2975 pub async fn room_settings(&self, room_id: &RoomId) -> StoreResult<Option<RoomSettings>> {
2980 self.inner.store.get_room_settings(room_id).await
2983 }
2984
2985 pub async fn set_room_settings(
2996 &self,
2997 room_id: &RoomId,
2998 new_settings: &RoomSettings,
2999 ) -> Result<(), SetRoomSettingsError> {
3000 let store = &self.inner.store;
3001
3002 let _store_transaction = store.transaction().await;
3007
3008 let old_settings = store.get_room_settings(room_id).await?;
3009
3010 if let Some(old_settings) = old_settings {
3023 if old_settings != *new_settings {
3024 return Err(SetRoomSettingsError::EncryptionDowngrade);
3025 } else {
3026 return Ok(());
3028 }
3029 }
3030
3031 match new_settings.algorithm {
3033 EventEncryptionAlgorithm::MegolmV1AesSha2 => (),
3034
3035 #[cfg(feature = "experimental-algorithms")]
3036 EventEncryptionAlgorithm::MegolmV2AesSha2 => (),
3037
3038 _ => {
3039 warn!(
3040 ?room_id,
3041 "Rejecting invalid encryption algorithm {}", new_settings.algorithm
3042 );
3043 return Err(SetRoomSettingsError::InvalidSettings);
3044 }
3045 }
3046
3047 store
3049 .save_changes(Changes {
3050 room_settings: HashMap::from([(room_id.to_owned(), new_settings.clone())]),
3051 ..Default::default()
3052 })
3053 .await?;
3054
3055 Ok(())
3056 }
3057
3058 #[cfg(any(feature = "testing", test))]
3062 pub fn same_as(&self, other: &OlmMachine) -> bool {
3063 Arc::ptr_eq(&self.inner, &other.inner)
3064 }
3065
3066 #[cfg(any(feature = "testing", test))]
3068 pub async fn uploaded_key_count(&self) -> Result<u64, CryptoStoreError> {
3069 let cache = self.inner.store.cache().await?;
3070 let account = cache.account().await?;
3071 Ok(account.uploaded_key_count())
3072 }
3073
3074 #[cfg(test)]
3076 pub(crate) fn identity_manager(&self) -> &IdentityManager {
3077 &self.inner.identity_manager
3078 }
3079
3080 #[cfg(test)]
3082 pub(crate) fn key_for_has_migrated_verification_latch() -> &'static str {
3083 Self::HAS_MIGRATED_VERIFICATION_LATCH
3084 }
3085}
3086
3087fn sender_data_to_verification_state(
3088 sender_data: SenderData,
3089 session_has_been_imported: bool,
3090) -> (VerificationState, Option<OwnedDeviceId>) {
3091 match sender_data {
3092 SenderData::UnknownDevice { owner_check_failed: false, .. } => {
3093 let device_link_problem = if session_has_been_imported {
3094 DeviceLinkProblem::InsecureSource
3095 } else {
3096 DeviceLinkProblem::MissingDevice
3097 };
3098
3099 (VerificationState::Unverified(VerificationLevel::None(device_link_problem)), None)
3100 }
3101 SenderData::UnknownDevice { owner_check_failed: true, .. } => (
3102 VerificationState::Unverified(VerificationLevel::None(
3103 DeviceLinkProblem::InsecureSource,
3104 )),
3105 None,
3106 ),
3107 SenderData::DeviceInfo { device_keys, .. } => (
3108 VerificationState::Unverified(VerificationLevel::UnsignedDevice),
3109 Some(device_keys.device_id),
3110 ),
3111 SenderData::VerificationViolation(KnownSenderData { device_id, .. }) => {
3112 (VerificationState::Unverified(VerificationLevel::VerificationViolation), device_id)
3113 }
3114 SenderData::SenderUnverified(KnownSenderData { device_id, .. }) => {
3115 (VerificationState::Unverified(VerificationLevel::UnverifiedIdentity), device_id)
3116 }
3117 SenderData::SenderVerified(KnownSenderData { device_id, .. }) => {
3118 (VerificationState::Verified, device_id)
3119 }
3120 }
3121}
3122
3123#[derive(Debug, Clone)]
3126pub struct CrossSigningBootstrapRequests {
3127 pub upload_keys_req: Option<OutgoingRequest>,
3134
3135 pub upload_signing_keys_req: UploadSigningKeysRequest,
3139
3140 pub upload_signatures_req: UploadSignaturesRequest,
3145}
3146
3147#[derive(Debug)]
3150pub struct EncryptionSyncChanges<'a> {
3151 pub to_device_events: Vec<Raw<AnyToDeviceEvent>>,
3153 pub changed_devices: &'a DeviceLists,
3156 pub one_time_keys_counts: &'a BTreeMap<OneTimeKeyAlgorithm, UInt>,
3158 pub unused_fallback_keys: Option<&'a [OneTimeKeyAlgorithm]>,
3160 pub next_batch_token: Option<String>,
3162}
3163
3164fn megolm_error_to_utd_info(
3172 raw_event: &Raw<EncryptedEvent>,
3173 error: MegolmError,
3174) -> Result<UnableToDecryptInfo, CryptoStoreError> {
3175 use MegolmError::*;
3176 let reason = match error {
3177 EventError(_) => UnableToDecryptReason::MalformedEncryptedEvent,
3178 Decode(_) => UnableToDecryptReason::MalformedEncryptedEvent,
3179 MissingRoomKey(maybe_withheld) => {
3180 UnableToDecryptReason::MissingMegolmSession { withheld_code: maybe_withheld }
3181 }
3182 Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
3183 UnableToDecryptReason::UnknownMegolmMessageIndex
3184 }
3185 Decryption(_) => UnableToDecryptReason::MegolmDecryptionFailure,
3186 JsonError(_) => UnableToDecryptReason::PayloadDeserializationFailure,
3187 MismatchedIdentityKeys(_) => UnableToDecryptReason::MismatchedIdentityKeys,
3188 SenderIdentityNotTrusted(level) => UnableToDecryptReason::SenderIdentityNotTrusted(level),
3189 #[cfg(feature = "experimental-encrypted-state-events")]
3190 StateKeyVerificationFailed => UnableToDecryptReason::StateKeyVerificationFailed,
3191
3192 Store(error) => Err(error)?,
3195 };
3196
3197 let session_id = raw_event.deserialize().ok().and_then(|ev| match ev.content.scheme {
3198 RoomEventEncryptionScheme::MegolmV1AesSha2(s) => Some(s.session_id),
3199 #[cfg(feature = "experimental-algorithms")]
3200 RoomEventEncryptionScheme::MegolmV2AesSha2(s) => Some(s.session_id),
3201 RoomEventEncryptionScheme::Unknown(_) => None,
3202 });
3203
3204 Ok(UnableToDecryptInfo { session_id, reason })
3205}
3206
3207#[derive(Debug, thiserror::Error)]
3217pub(crate) enum DecryptToDeviceError {
3218 #[error("An Olm error occurred meaning we failed to decrypt the event")]
3219 OlmError(#[from] OlmError),
3220
3221 #[error("The event was sent from a dehydrated device")]
3222 FromDehydratedDevice,
3223}
3224
3225impl From<CryptoStoreError> for DecryptToDeviceError {
3226 fn from(value: CryptoStoreError) -> Self {
3227 Self::OlmError(value.into())
3228 }
3229}
3230
3231#[cfg(test)]
3232impl From<DecryptToDeviceError> for OlmError {
3233 fn from(value: DecryptToDeviceError) -> Self {
3236 match value {
3237 DecryptToDeviceError::OlmError(olm_error) => olm_error,
3238 DecryptToDeviceError::FromDehydratedDevice => {
3239 panic!("Expected an OlmError but found FromDehydratedDevice")
3240 }
3241 }
3242 }
3243}
3244
3245#[cfg(test)]
3246pub(crate) mod test_helpers;
3247
3248#[cfg(test)]
3249pub(crate) mod tests;