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, DynCryptoStore, IntoCryptoStore, MemoryStore, Result as StoreResult,
89 SecretImportError, 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
130pub struct OlmMachineBuilder {
132 user_id: OwnedUserId,
134
135 device_id: OwnedDeviceId,
137
138 store: Option<Arc<DynCryptoStore>>,
141
142 custom_account: Option<vodozemac::olm::Account>,
145}
146
147impl OlmMachineBuilder {
148 pub fn new(user_id: &UserId, device_id: &DeviceId) -> Self {
151 Self {
152 user_id: user_id.to_owned(),
153 device_id: device_id.to_owned(),
154 store: None,
155 custom_account: None,
156 }
157 }
158
159 pub fn with_crypto_store(mut self, store: impl IntoCryptoStore) -> Self {
167 self.store = Some(store.into_crypto_store());
168 self
169 }
170
171 pub fn with_custom_account(mut self, custom_account: Option<vodozemac::olm::Account>) -> Self {
181 self.custom_account = custom_account;
182 self
183 }
184
185 pub async fn build(self) -> Result<OlmMachine, CryptoStoreError> {
192 OlmMachine::from_builder(self).await
193 }
194}
195
196impl std::fmt::Debug for OlmMachineBuilder {
197 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
198 f.debug_struct("OlmMachineBuilder")
199 .field("user_id", &self.user_id)
200 .field("device_id", &self.device_id)
201 .finish_non_exhaustive()
202 }
203}
204
205#[derive(Clone)]
208pub struct OlmMachine {
209 pub(crate) inner: Arc<OlmMachineInner>,
210}
211
212pub struct OlmMachineInner {
213 user_id: OwnedUserId,
215 device_id: OwnedDeviceId,
217 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
222 store: Store,
226 session_manager: SessionManager,
228 pub(crate) group_session_manager: GroupSessionManager,
230 verification_machine: VerificationMachine,
233 pub(crate) key_request_machine: GossipMachine,
236 identity_manager: IdentityManager,
239 backup_machine: BackupMachine,
241}
242
243#[cfg(not(tarpaulin_include))]
244impl std::fmt::Debug for OlmMachine {
245 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
246 f.debug_struct("OlmMachine")
247 .field("user_id", &self.user_id())
248 .field("device_id", &self.device_id())
249 .finish()
250 }
251}
252
253impl OlmMachine {
254 const CURRENT_GENERATION_STORE_KEY: &'static str = "generation-counter";
255 const HAS_MIGRATED_VERIFICATION_LATCH: &'static str = "HAS_MIGRATED_VERIFICATION_LATCH";
256
257 pub async fn new(user_id: &UserId, device_id: &DeviceId) -> Self {
268 OlmMachineBuilder::new(user_id, device_id)
269 .build()
270 .await
271 .expect("Reading and writing to the memory store always succeeds")
272 }
273
274 pub(crate) async fn rehydrate(
275 &self,
276 pickle_key: &[u8; 32],
277 device_id: &DeviceId,
278 device_data: Raw<DehydratedDeviceData>,
279 ) -> Result<OlmMachine, DehydrationError> {
280 let account = Account::rehydrate(pickle_key, self.user_id(), device_id, device_data)?;
281 let static_account = account.static_data().clone();
282
283 let store =
284 Arc::new(CryptoStoreWrapper::new(self.user_id(), device_id, MemoryStore::new()));
285 let device = DeviceData::from_account(&account);
286 store.save_pending_changes(PendingChanges { account: Some(account) }).await?;
287 store
288 .save_changes(Changes {
289 devices: DeviceChanges { new: vec![device], ..Default::default() },
290 ..Default::default()
291 })
292 .await?;
293
294 let (verification_machine, store, identity_manager) =
295 Self::new_helper_prelude(store, static_account, self.store().private_identity());
296
297 Ok(Self::new_helper(
298 device_id,
299 store,
300 verification_machine,
301 identity_manager,
302 self.store().private_identity(),
303 None,
304 ))
305 }
306
307 fn new_helper_prelude(
308 store_wrapper: Arc<CryptoStoreWrapper>,
309 account: StaticAccountData,
310 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
311 ) -> (VerificationMachine, Store, IdentityManager) {
312 let verification_machine =
313 VerificationMachine::new(account.clone(), user_identity.clone(), store_wrapper.clone());
314 let store = Store::new(account, user_identity, store_wrapper, verification_machine.clone());
315
316 let identity_manager = IdentityManager::new(store.clone());
317
318 (verification_machine, store, identity_manager)
319 }
320
321 fn new_helper(
322 device_id: &DeviceId,
323 store: Store,
324 verification_machine: VerificationMachine,
325 identity_manager: IdentityManager,
326 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
327 maybe_backup_key: Option<MegolmV1BackupKey>,
328 ) -> Self {
329 let group_session_manager = GroupSessionManager::new(store.clone());
330
331 let users_for_key_claim = Arc::new(StdRwLock::new(BTreeMap::new()));
332 let key_request_machine = GossipMachine::new(
333 store.clone(),
334 identity_manager.clone(),
335 group_session_manager.session_cache(),
336 users_for_key_claim.clone(),
337 );
338
339 let session_manager =
340 SessionManager::new(users_for_key_claim, key_request_machine.clone(), store.clone());
341
342 let backup_machine = BackupMachine::new(store.clone(), maybe_backup_key);
343
344 let inner = Arc::new(OlmMachineInner {
345 user_id: store.user_id().to_owned(),
346 device_id: device_id.to_owned(),
347 user_identity,
348 store,
349 session_manager,
350 group_session_manager,
351 verification_machine,
352 key_request_machine,
353 identity_manager,
354 backup_machine,
355 });
356
357 Self { inner }
358 }
359
360 #[instrument(skip(builder), fields(user_id, device_id, ed25519_key, curve25519_key))]
361 pub(crate) async fn from_builder(builder: OlmMachineBuilder) -> StoreResult<Self> {
362 let OlmMachineBuilder { user_id, device_id, store, custom_account } = builder;
363
364 let store = store.unwrap_or_else(|| MemoryStore::new().into_crypto_store());
365
366 let static_account = match store.load_account().await? {
367 Some(account) => {
368 if user_id != account.user_id()
369 || device_id != account.device_id()
370 || custom_account.is_some()
371 {
372 return Err(CryptoStoreError::MismatchedAccount {
373 expected: (account.user_id().to_owned(), account.device_id().to_owned()),
374 got: (user_id.to_owned(), device_id.to_owned()),
375 });
376 }
377
378 Span::current()
379 .record("ed25519_key", display(account.identity_keys().ed25519))
380 .record("curve25519_key", display(account.identity_keys().curve25519));
381 debug!("Restored an Olm account");
382
383 account.static_data().clone()
384 }
385
386 None => {
387 let account = if let Some(account) = custom_account {
388 Account::new_helper(account, &user_id, &device_id)
389 } else {
390 Account::with_device_id(&user_id, &device_id)
391 };
392
393 let static_account = account.static_data().clone();
394
395 Span::current()
396 .record("ed25519_key", display(account.identity_keys().ed25519))
397 .record("curve25519_key", display(account.identity_keys().curve25519));
398
399 let device = DeviceData::from_account(&account);
400
401 device.set_trust_state(LocalTrust::Verified);
405
406 let changes = Changes {
407 devices: DeviceChanges { new: vec![device], ..Default::default() },
408 ..Default::default()
409 };
410 store.save_changes(changes).await?;
411 store.save_pending_changes(PendingChanges { account: Some(account) }).await?;
412
413 debug!("Created a new Olm account");
414
415 static_account
416 }
417 };
418
419 let identity = match store.load_identity().await? {
420 Some(i) => {
421 let master_key = i
422 .master_public_key()
423 .await
424 .and_then(|m| m.get_first_key().map(|m| m.to_owned()));
425 debug!(?master_key, "Restored the cross signing identity");
426 i
427 }
428 None => {
429 debug!("Creating an empty cross signing identity stub");
430 PrivateCrossSigningIdentity::empty(&user_id)
431 }
432 };
433
434 let saved_keys = store.load_backup_keys().await?;
439 let maybe_backup_key = saved_keys.decryption_key.and_then(|k| {
440 if let Some(version) = saved_keys.backup_version {
441 let megolm_v1_backup_key = k.megolm_v1_public_key();
442 megolm_v1_backup_key.set_version(version);
443 Some(megolm_v1_backup_key)
444 } else {
445 None
446 }
447 });
448
449 let identity = Arc::new(Mutex::new(identity));
450 let store = Arc::new(CryptoStoreWrapper::new(&user_id, &device_id, store));
451
452 let (verification_machine, store, identity_manager) =
453 Self::new_helper_prelude(store, static_account, identity.clone());
454
455 Self::migration_post_verified_latch_support(&store, &identity_manager).await?;
458
459 Ok(Self::new_helper(
460 &device_id,
461 store,
462 verification_machine,
463 identity_manager,
464 identity,
465 maybe_backup_key,
466 ))
467 }
468
469 pub(crate) async fn migration_post_verified_latch_support(
477 store: &Store,
478 identity_manager: &IdentityManager,
479 ) -> Result<(), CryptoStoreError> {
480 let maybe_migrate_for_identity_verified_latch =
481 store.get_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH).await?.is_none();
482
483 if maybe_migrate_for_identity_verified_latch {
484 identity_manager.mark_all_tracked_users_as_dirty(store.cache().await?).await?;
485
486 store.set_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH, vec![0]).await?
487 }
488 Ok(())
489 }
490
491 pub fn store(&self) -> &Store {
493 &self.inner.store
494 }
495
496 pub fn user_id(&self) -> &UserId {
498 &self.inner.user_id
499 }
500
501 pub fn device_id(&self) -> &DeviceId {
503 &self.inner.device_id
504 }
505
506 pub fn device_creation_time(&self) -> MilliSecondsSinceUnixEpoch {
513 self.inner.store.static_account().creation_local_time()
514 }
515
516 pub fn identity_keys(&self) -> IdentityKeys {
518 let account = self.inner.store.static_account();
519 account.identity_keys()
520 }
521
522 pub async fn display_name(&self) -> StoreResult<Option<String>> {
524 self.store().device_display_name().await
525 }
526
527 pub async fn tracked_users(&self) -> StoreResult<HashSet<OwnedUserId>> {
532 let cache = self.store().cache().await?;
533 Ok(self.inner.identity_manager.key_query_manager.synced(&cache).await?.tracked_users())
534 }
535
536 #[cfg(feature = "automatic-room-key-forwarding")]
545 pub fn set_room_key_requests_enabled(&self, enable: bool) {
546 self.inner.key_request_machine.set_room_key_requests_enabled(enable)
547 }
548
549 pub fn are_room_key_requests_enabled(&self) -> bool {
554 self.inner.key_request_machine.are_room_key_requests_enabled()
555 }
556
557 #[cfg(feature = "automatic-room-key-forwarding")]
566 pub fn set_room_key_forwarding_enabled(&self, enable: bool) {
567 self.inner.key_request_machine.set_room_key_forwarding_enabled(enable)
568 }
569
570 pub fn is_room_key_forwarding_enabled(&self) -> bool {
574 self.inner.key_request_machine.is_room_key_forwarding_enabled()
575 }
576
577 pub async fn outgoing_requests(&self) -> StoreResult<Vec<OutgoingRequest>> {
585 let mut requests = Vec::new();
586
587 {
588 let store_cache = self.inner.store.cache().await?;
589 let account = store_cache.account().await?;
590 if let Some(r) = self.keys_for_upload(&account).await.map(|r| OutgoingRequest {
591 request_id: TransactionId::new(),
592 request: Arc::new(r.into()),
593 }) {
594 requests.push(r);
595 }
596 }
597
598 for request in self
599 .inner
600 .identity_manager
601 .users_for_key_query()
602 .await?
603 .into_iter()
604 .map(|(request_id, r)| OutgoingRequest { request_id, request: Arc::new(r.into()) })
605 {
606 requests.push(request);
607 }
608
609 requests.append(&mut self.inner.verification_machine.outgoing_messages());
610 requests.append(&mut self.inner.key_request_machine.outgoing_to_device_requests().await?);
611
612 Ok(requests)
613 }
614
615 pub fn query_keys_for_users<'a>(
636 &self,
637 users: impl IntoIterator<Item = &'a UserId>,
638 ) -> (OwnedTransactionId, KeysQueryRequest) {
639 self.inner.identity_manager.build_key_query_for_users(users)
640 }
641
642 pub async fn mark_request_as_sent<'a>(
652 &self,
653 request_id: &TransactionId,
654 response: impl Into<AnyIncomingResponse<'a>>,
655 ) -> OlmResult<()> {
656 match response.into() {
657 AnyIncomingResponse::KeysUpload(response) => {
658 Box::pin(self.receive_keys_upload_response(response)).await?;
659 }
660 AnyIncomingResponse::KeysQuery(response) => {
661 Box::pin(self.receive_keys_query_response(request_id, response)).await?;
662 }
663 AnyIncomingResponse::KeysClaim(response) => {
664 Box::pin(
665 self.inner.session_manager.receive_keys_claim_response(request_id, response),
666 )
667 .await?;
668 }
669 AnyIncomingResponse::ToDevice(_) => {
670 Box::pin(self.mark_to_device_request_as_sent(request_id)).await?;
671 }
672 AnyIncomingResponse::SigningKeysUpload(_) => {
673 Box::pin(self.receive_cross_signing_upload_response()).await?;
674 }
675 AnyIncomingResponse::SignatureUpload(_) => {
676 self.inner.verification_machine.mark_request_as_sent(request_id);
677 }
678 AnyIncomingResponse::RoomMessage(_) => {
679 self.inner.verification_machine.mark_request_as_sent(request_id);
680 }
681 AnyIncomingResponse::KeysBackup(_) => {
682 Box::pin(self.inner.backup_machine.mark_request_as_sent(request_id)).await?;
683 }
684 }
685
686 Ok(())
687 }
688
689 async fn receive_cross_signing_upload_response(&self) -> StoreResult<()> {
691 let identity = self.inner.user_identity.lock().await;
692 identity.mark_as_shared();
693
694 let changes = Changes { private_identity: Some(identity.clone()), ..Default::default() };
695
696 self.store().save_changes(changes).await
697 }
698
699 pub async fn bootstrap_cross_signing(
718 &self,
719 reset: bool,
720 ) -> StoreResult<CrossSigningBootstrapRequests> {
721 let identity = self.inner.user_identity.lock().await.clone();
726
727 let (upload_signing_keys_req, upload_signatures_req) = if reset || identity.is_empty().await
728 {
729 info!("Creating new cross signing identity");
730
731 let (identity, upload_signing_keys_req, upload_signatures_req) = {
732 let cache = self.inner.store.cache().await?;
733 let account = cache.account().await?;
734 account.bootstrap_cross_signing().await
735 };
736
737 let public = identity.to_public_identity().await.expect(
738 "Couldn't create a public version of the identity from a new private identity",
739 );
740
741 *self.inner.user_identity.lock().await = identity.clone();
742
743 self.store()
744 .save_changes(Changes {
745 identities: IdentityChanges { new: vec![public.into()], ..Default::default() },
746 private_identity: Some(identity),
747 ..Default::default()
748 })
749 .await?;
750
751 (upload_signing_keys_req, upload_signatures_req)
752 } else {
753 info!("Trying to upload the existing cross signing identity");
754 let upload_signing_keys_req = identity.as_upload_request().await;
755
756 let upload_signatures_req = identity
758 .sign_account(self.inner.store.static_account())
759 .await
760 .expect("Can't sign device keys");
761
762 (upload_signing_keys_req, upload_signatures_req)
763 };
764
765 let upload_keys_req =
769 self.upload_device_keys().await?.map(|(_, request)| OutgoingRequest::from(request));
770
771 Ok(CrossSigningBootstrapRequests {
772 upload_signing_keys_req,
773 upload_keys_req,
774 upload_signatures_req,
775 })
776 }
777
778 pub async fn upload_device_keys(
790 &self,
791 ) -> StoreResult<Option<(OwnedTransactionId, UploadKeysRequest)>> {
792 let cache = self.store().cache().await?;
793 let account = cache.account().await?;
794
795 Ok(self.keys_for_upload(&account).await.map(|request| (TransactionId::new(), request)))
796 }
797
798 async fn receive_keys_upload_response(&self, response: &UploadKeysResponse) -> OlmResult<()> {
805 self.inner
806 .store
807 .with_transaction(async |tr| {
808 let account = tr.account().await?;
809 account.receive_keys_upload_response(response)?;
810 Ok(())
811 })
812 .await
813 }
814
815 #[instrument(skip_all)]
843 pub async fn get_missing_sessions(
844 &self,
845 users: impl Iterator<Item = &UserId>,
846 ) -> StoreResult<Option<(OwnedTransactionId, KeysClaimRequest)>> {
847 self.inner.session_manager.get_missing_sessions(users).await
848 }
849
850 async fn receive_keys_query_response(
859 &self,
860 request_id: &TransactionId,
861 response: &KeysQueryResponse,
862 ) -> OlmResult<(DeviceChanges, IdentityChanges)> {
863 self.inner.identity_manager.receive_keys_query_response(request_id, response).await
864 }
865
866 async fn keys_for_upload(&self, account: &Account) -> Option<UploadKeysRequest> {
875 let (mut device_keys, one_time_keys, fallback_keys) = account.keys_for_upload();
876
877 if let Some(device_keys) = &mut device_keys {
887 let private_identity = self.store().private_identity();
888 let guard = private_identity.lock().await;
889
890 if guard.status().await.is_complete() {
891 guard.sign_device_keys(device_keys).await.expect(
892 "We should be able to sign our device keys since we confirmed that we \
893 have a complete set of private cross-signing keys",
894 );
895 }
896 }
897
898 if device_keys.is_none() && one_time_keys.is_empty() && fallback_keys.is_empty() {
899 None
900 } else {
901 let device_keys = device_keys.map(|d| d.to_raw());
902
903 Some(assign!(UploadKeysRequest::new(), {
904 device_keys, one_time_keys, fallback_keys
905 }))
906 }
907 }
908
909 async fn decrypt_to_device_event(
932 &self,
933 transaction: &mut StoreTransaction,
934 event: &EncryptedToDeviceEvent,
935 changes: &mut Changes,
936 decryption_settings: &DecryptionSettings,
937 ) -> Result<OlmDecryptionInfo, DecryptToDeviceError> {
938 let mut decrypted = transaction
940 .account()
941 .await?
942 .decrypt_to_device_event(&self.inner.store, event, decryption_settings)
943 .await?;
944
945 self.check_to_device_event_is_not_from_dehydrated_device(&decrypted, &event.sender).await?;
947
948 self.handle_decrypted_to_device_event(transaction.cache(), &mut decrypted, changes).await?;
950
951 Ok(decrypted)
952 }
953
954 #[instrument(
955 skip_all,
956 fields(room_id = ? content.room_id, session_id, message_index, shared_history = content.shared_history)
960 )]
961 async fn handle_key(
962 &self,
963 sender_key: Curve25519PublicKey,
964 event: &DecryptedRoomKeyEvent,
965 content: &MegolmV1AesSha2Content,
966 ) -> OlmResult<Option<InboundGroupSession>> {
967 let session =
968 InboundGroupSession::from_room_key_content(sender_key, event.keys.ed25519, content);
969
970 match session {
971 Ok(mut session) => {
972 Span::current().record("session_id", session.session_id());
973 Span::current().record("message_index", session.first_known_index());
974
975 let sender_data =
976 SenderDataFinder::find_using_event(self.store(), sender_key, event, &session)
977 .await?;
978 session.sender_data = sender_data;
979
980 Ok(self.store().merge_received_group_session(session).await?)
981 }
982 Err(e) => {
983 Span::current().record("session_id", &content.session_id);
984 warn!("Received a room key event which contained an invalid session key: {e}");
985
986 Ok(None)
987 }
988 }
989 }
990
991 #[instrument(skip_all, fields(algorithm = ?event.content.algorithm()))]
993 async fn add_room_key(
994 &self,
995 sender_key: Curve25519PublicKey,
996 event: &DecryptedRoomKeyEvent,
997 ) -> OlmResult<Option<InboundGroupSession>> {
998 match &event.content {
999 RoomKeyContent::MegolmV1AesSha2(content) => {
1000 self.handle_key(sender_key, event, content).await
1001 }
1002 #[cfg(feature = "experimental-algorithms")]
1003 RoomKeyContent::MegolmV2AesSha2(content) => {
1004 self.handle_key(sender_key, event, content).await
1005 }
1006 RoomKeyContent::Unknown(_) => {
1007 warn!("Received a room key with an unsupported algorithm");
1008 Ok(None)
1009 }
1010 }
1011 }
1012
1013 #[instrument()]
1015 async fn receive_room_key_bundle_data(
1016 &self,
1017 sender_key: Curve25519PublicKey,
1018 event: &DecryptedRoomKeyBundleEvent,
1019 changes: &mut Changes,
1020 ) -> OlmResult<()> {
1021 let Some(sender_device_keys) = &event.sender_device_keys else {
1022 warn!("Received a room key bundle with no sender device keys: ignoring");
1023 return Ok(());
1024 };
1025
1026 let sender_device_data =
1031 DeviceData::try_from(sender_device_keys).expect("failed to verify sender device keys");
1032 let sender_device = self.store().wrap_device_data(sender_device_data).await?;
1033
1034 changes.received_room_key_bundles.push(StoredRoomKeyBundleData {
1035 sender_user: event.sender.clone(),
1036 sender_data: SenderData::from_device(&sender_device),
1037 sender_key,
1038 bundle_data: event.content.clone(),
1039 });
1040 Ok(())
1041 }
1042
1043 fn add_withheld_info(&self, changes: &mut Changes, event: &RoomKeyWithheldEvent) {
1044 debug!(?event.content, "Processing `m.room_key.withheld` event");
1045
1046 if let RoomKeyWithheldContent::MegolmV1AesSha2(
1047 MegolmV1AesSha2WithheldContent::BlackListed(c)
1048 | MegolmV1AesSha2WithheldContent::Unverified(c)
1049 | MegolmV1AesSha2WithheldContent::Unauthorised(c)
1050 | MegolmV1AesSha2WithheldContent::Unavailable(c),
1051 ) = &event.content
1052 {
1053 changes
1054 .withheld_session_info
1055 .entry(c.room_id.to_owned())
1056 .or_default()
1057 .insert(c.session_id.to_owned(), event.to_owned().into());
1058 }
1059 }
1060
1061 #[cfg(test)]
1062 pub(crate) async fn create_outbound_group_session_with_defaults_test_helper(
1063 &self,
1064 room_id: &RoomId,
1065 ) -> OlmResult<()> {
1066 let (_, session) = self
1067 .inner
1068 .group_session_manager
1069 .create_outbound_group_session(
1070 room_id,
1071 EncryptionSettings::default(),
1072 SenderData::unknown(),
1073 )
1074 .await?;
1075
1076 self.store().save_inbound_group_sessions(&[session]).await?;
1077
1078 Ok(())
1079 }
1080
1081 #[cfg(test)]
1082 #[allow(dead_code)]
1083 pub(crate) async fn create_inbound_session_test_helper(
1084 &self,
1085 room_id: &RoomId,
1086 ) -> OlmResult<InboundGroupSession> {
1087 let (_, session) = self
1088 .inner
1089 .group_session_manager
1090 .create_outbound_group_session(
1091 room_id,
1092 EncryptionSettings::default(),
1093 SenderData::unknown(),
1094 )
1095 .await?;
1096
1097 Ok(session)
1098 }
1099
1100 pub async fn encrypt_room_event(
1117 &self,
1118 room_id: &RoomId,
1119 content: impl MessageLikeEventContent,
1120 ) -> MegolmResult<RawEncryptionResult> {
1121 let event_type = content.event_type().to_string();
1122 let content = Raw::new(&content)?.cast_unchecked();
1123 self.encrypt_room_event_raw(room_id, &event_type, &content).await
1124 }
1125
1126 pub async fn encrypt_room_event_raw(
1146 &self,
1147 room_id: &RoomId,
1148 event_type: &str,
1149 content: &Raw<AnyMessageLikeEventContent>,
1150 ) -> MegolmResult<RawEncryptionResult> {
1151 self.inner.group_session_manager.encrypt(room_id, event_type, content).await.map(|result| {
1152 RawEncryptionResult {
1153 content: result.content,
1154 encryption_info: self
1155 .own_encryption_info(result.algorithm, result.session_id.to_string()),
1156 }
1157 })
1158 }
1159
1160 fn own_encryption_info(
1161 &self,
1162 algorithm: EventEncryptionAlgorithm,
1163 session_id: String,
1164 ) -> EncryptionInfo {
1165 let identity_keys = self.identity_keys();
1166
1167 let algorithm_info = match algorithm {
1168 EventEncryptionAlgorithm::MegolmV1AesSha2 => AlgorithmInfo::MegolmV1AesSha2 {
1169 curve25519_key: identity_keys.curve25519.to_base64(),
1170 sender_claimed_keys: BTreeMap::from([(
1171 DeviceKeyAlgorithm::Ed25519,
1172 identity_keys.ed25519.to_base64(),
1173 )]),
1174 session_id: Some(session_id),
1175 },
1176 EventEncryptionAlgorithm::OlmV1Curve25519AesSha2 => {
1177 AlgorithmInfo::OlmV1Curve25519AesSha2 {
1178 curve25519_public_key_base64: identity_keys.curve25519.to_base64(),
1179 }
1180 }
1181 _ => unreachable!(
1182 "Only MegolmV1AesSha2 and OlmV1Curve25519AesSha2 are supported on this level"
1183 ),
1184 };
1185
1186 EncryptionInfo {
1187 sender: self.inner.user_id.clone(),
1188 sender_device: Some(self.inner.device_id.clone()),
1189 forwarder: None,
1190 algorithm_info,
1191 verification_state: VerificationState::Verified,
1192 }
1193 }
1194
1195 #[cfg(feature = "experimental-encrypted-state-events")]
1207 pub async fn encrypt_state_event<C, K>(
1208 &self,
1209 room_id: &RoomId,
1210 content: C,
1211 state_key: K,
1212 ) -> MegolmResult<Raw<RoomEncryptedEventContent>>
1213 where
1214 C: StateEventContent,
1215 C::StateKey: Borrow<K>,
1216 K: AsRef<str>,
1217 {
1218 let event_type = content.event_type().to_string();
1219 let content = Raw::new(&content)?.cast_unchecked();
1220 self.encrypt_state_event_raw(room_id, &event_type, state_key.as_ref(), &content).await
1221 }
1222
1223 #[cfg(feature = "experimental-encrypted-state-events")]
1242 pub async fn encrypt_state_event_raw(
1243 &self,
1244 room_id: &RoomId,
1245 event_type: &str,
1246 state_key: &str,
1247 content: &Raw<AnyStateEventContent>,
1248 ) -> MegolmResult<Raw<RoomEncryptedEventContent>> {
1249 self.inner
1250 .group_session_manager
1251 .encrypt_state(room_id, event_type, state_key, content)
1252 .await
1253 }
1254
1255 pub async fn discard_room_key(&self, room_id: &RoomId) -> StoreResult<bool> {
1266 self.inner.group_session_manager.invalidate_group_session(room_id).await
1267 }
1268
1269 pub async fn share_room_key(
1289 &self,
1290 room_id: &RoomId,
1291 users: impl Iterator<Item = &UserId>,
1292 encryption_settings: impl Into<EncryptionSettings>,
1293 ) -> OlmResult<Vec<Arc<ToDeviceRequest>>> {
1294 self.inner.group_session_manager.share_room_key(room_id, users, encryption_settings).await
1295 }
1296
1297 #[cfg(feature = "experimental-send-custom-to-device")]
1311 pub async fn encrypt_content_for_devices(
1312 &self,
1313 devices: Vec<DeviceData>,
1314 event_type: &str,
1315 content: &Value,
1316 share_strategy: CollectStrategy,
1317 ) -> OlmResult<(Vec<ToDeviceRequest>, Vec<(DeviceData, WithheldCode)>)> {
1318 let mut changes = Changes::default();
1319
1320 let (allowed_devices, mut blocked_devices) =
1321 split_devices_for_share_strategy(&self.inner.store, devices, share_strategy).await?;
1322
1323 let result = self
1324 .inner
1325 .group_session_manager
1326 .encrypt_content_for_devices(allowed_devices, event_type, content.clone(), &mut changes)
1327 .await;
1328
1329 if !changes.is_empty() {
1331 let session_count = changes.sessions.len();
1332
1333 self.inner.store.save_changes(changes).await?;
1334
1335 trace!(
1336 session_count = session_count,
1337 "Stored the changed sessions after encrypting a custom to-device event"
1338 );
1339 }
1340
1341 result.map(|(to_device_requests, mut withheld)| {
1342 withheld.append(&mut blocked_devices);
1343 (to_device_requests, withheld)
1344 })
1345 }
1346 pub async fn share_room_key_bundle_data(
1351 &self,
1352 user_id: &UserId,
1353 collect_strategy: &CollectStrategy,
1354 bundle_data: RoomKeyBundleContent,
1355 ) -> OlmResult<Vec<ToDeviceRequest>> {
1356 self.inner
1357 .group_session_manager
1358 .share_room_key_bundle_data(user_id, collect_strategy, bundle_data)
1359 .await
1360 }
1361
1362 #[deprecated(note = "Use OlmMachine::receive_verification_event instead", since = "0.7.0")]
1370 pub async fn receive_unencrypted_verification_event(
1371 &self,
1372 event: &AnyMessageLikeEvent,
1373 ) -> StoreResult<()> {
1374 self.inner.verification_machine.receive_any_event(event).await
1375 }
1376
1377 pub async fn receive_verification_event(&self, event: &AnyMessageLikeEvent) -> StoreResult<()> {
1390 self.inner.verification_machine.receive_any_event(event).await
1391 }
1392
1393 #[instrument(
1399 skip_all,
1400 fields(
1401 sender_key = ?decrypted.result.sender_key,
1402 event_type = decrypted.result.event.event_type(),
1403 ),
1404 )]
1405 async fn handle_decrypted_to_device_event(
1406 &self,
1407 cache: &StoreCache,
1408 decrypted: &mut OlmDecryptionInfo,
1409 changes: &mut Changes,
1410 ) -> OlmResult<()> {
1411 debug!(
1412 sender_device_keys =
1413 ?decrypted.result.event.sender_device_keys().map(|k| (k.curve25519_key(), k.ed25519_key())).unwrap_or((None, None)),
1414 "Received a decrypted to-device event",
1415 );
1416
1417 match &*decrypted.result.event {
1418 AnyDecryptedOlmEvent::RoomKey(e) => {
1419 let session = self.add_room_key(decrypted.result.sender_key, e).await?;
1420 decrypted.inbound_group_session = session;
1421 }
1422 AnyDecryptedOlmEvent::ForwardedRoomKey(e) => {
1423 let session = self
1424 .inner
1425 .key_request_machine
1426 .receive_forwarded_room_key(decrypted.result.sender_key, e)
1427 .await?;
1428 decrypted.inbound_group_session = session;
1429 }
1430 AnyDecryptedOlmEvent::SecretSend(e) => {
1431 let name = self
1432 .inner
1433 .key_request_machine
1434 .receive_secret_event(cache, decrypted.result.sender_key, e, changes)
1435 .await?;
1436
1437 if let Ok(ToDeviceEvents::SecretSend(mut e)) =
1440 decrypted.result.raw_event.deserialize_as()
1441 {
1442 e.content.secret_name = name;
1443 decrypted.result.raw_event = Raw::from_json(to_raw_value(&e)?);
1444 }
1445
1446 if enabled!(tracing::Level::DEBUG) {
1447 let cross_signing_status = self.cross_signing_status().await;
1448 let backup_enabled = self.backup_machine().enabled().await;
1449 debug!(
1450 ?cross_signing_status,
1451 backup_enabled, "Status after receiving secret event"
1452 );
1453 }
1454 }
1455 AnyDecryptedOlmEvent::Dummy(_) => {
1456 debug!("Received an `m.dummy` event");
1457 }
1458 AnyDecryptedOlmEvent::RoomKeyBundle(e) => {
1459 debug!("Received a room key bundle event {:?}", e);
1460 self.receive_room_key_bundle_data(decrypted.result.sender_key, e, changes).await?;
1461 }
1462 #[cfg(feature = "experimental-push-secrets")]
1463 AnyDecryptedOlmEvent::SecretPush(e) => {
1464 self.inner
1465 .key_request_machine
1466 .receive_secret_push_event(&decrypted.result.sender_key, e, changes)
1467 .await?;
1468 }
1469 AnyDecryptedOlmEvent::Custom(_) => {
1470 warn!("Received an unexpected encrypted to-device event");
1471 }
1472 }
1473
1474 Ok(())
1475 }
1476
1477 async fn handle_verification_event(&self, event: &ToDeviceEvents) {
1478 if let Err(e) = self.inner.verification_machine.receive_any_event(event).await {
1479 error!("Error handling a verification event: {e:?}");
1480 }
1481 }
1482
1483 async fn mark_to_device_request_as_sent(&self, request_id: &TransactionId) -> StoreResult<()> {
1485 self.inner.verification_machine.mark_request_as_sent(request_id);
1486 self.inner.key_request_machine.mark_outgoing_request_as_sent(request_id).await?;
1487 self.inner.group_session_manager.mark_request_as_sent(request_id).await?;
1488 self.inner.session_manager.mark_outgoing_request_as_sent(request_id);
1489 Ok(())
1490 }
1491
1492 pub fn get_verification(&self, user_id: &UserId, flow_id: &str) -> Option<Verification> {
1494 self.inner.verification_machine.get_verification(user_id, flow_id)
1495 }
1496
1497 pub fn get_verification_request(
1499 &self,
1500 user_id: &UserId,
1501 flow_id: impl AsRef<str>,
1502 ) -> Option<VerificationRequest> {
1503 self.inner.verification_machine.get_request(user_id, flow_id)
1504 }
1505
1506 pub fn get_verification_requests(&self, user_id: &UserId) -> Vec<VerificationRequest> {
1508 self.inner.verification_machine.get_requests(user_id)
1509 }
1510
1511 async fn handle_to_device_event(&self, changes: &mut Changes, event: &ToDeviceEvents) {
1516 use crate::types::events::ToDeviceEvents::*;
1517
1518 match event {
1519 RoomKeyRequest(e) => self.inner.key_request_machine.receive_incoming_key_request(e),
1525 SecretRequest(e) => self.inner.key_request_machine.receive_incoming_secret_request(e),
1526 RoomKeyWithheld(e) => self.add_withheld_info(changes, e),
1527 KeyVerificationAccept(..)
1528 | KeyVerificationCancel(..)
1529 | KeyVerificationKey(..)
1530 | KeyVerificationMac(..)
1531 | KeyVerificationRequest(..)
1532 | KeyVerificationReady(..)
1533 | KeyVerificationDone(..)
1534 | KeyVerificationStart(..) => {
1535 self.handle_verification_event(event).await;
1536 }
1537
1538 Custom(_) | Dummy(_) => {}
1540
1541 RoomEncrypted(_) => {}
1543
1544 SecretSend(_) | RoomKey(_) | ForwardedRoomKey(_) => {}
1547 }
1548 }
1549
1550 fn record_message_id(event: &Raw<AnyToDeviceEvent>) {
1551 use serde::Deserialize;
1552
1553 #[derive(Deserialize)]
1554 struct ContentStub<'a> {
1555 #[serde(borrow, rename = "org.matrix.msgid")]
1556 message_id: Option<&'a str>,
1557 }
1558 #[derive(Deserialize)]
1559 struct ToDeviceStub<'a> {
1560 sender: &'a str,
1561 #[serde(rename = "type")]
1562 event_type: &'a str,
1563 #[serde(borrow)]
1564 content: ContentStub<'a>,
1565 }
1566
1567 if let Ok(event) = event.deserialize_as_unchecked::<ToDeviceStub<'_>>() {
1568 Span::current().record("sender", event.sender);
1569 Span::current().record("event_type", event.event_type);
1570 Span::current().record("message_id", event.content.message_id);
1571 }
1572 }
1573
1574 #[instrument(skip_all, fields(sender, event_type, message_id))]
1582 async fn receive_to_device_event(
1583 &self,
1584 transaction: &mut StoreTransaction,
1585 changes: &mut Changes,
1586 raw_event: Raw<AnyToDeviceEvent>,
1587 decryption_settings: &DecryptionSettings,
1588 ) -> Option<ProcessedToDeviceEvent> {
1589 Self::record_message_id(&raw_event);
1590
1591 let event: ToDeviceEvents = match raw_event.deserialize_as() {
1592 Ok(e) => e,
1593 Err(e) => {
1594 warn!("Received an invalid to-device event: {e}");
1596 return Some(ProcessedToDeviceEvent::Invalid(raw_event));
1597 }
1598 };
1599
1600 debug!("Received a to-device event");
1601
1602 match event {
1603 ToDeviceEvents::RoomEncrypted(e) => {
1604 self.receive_encrypted_to_device_event(
1605 transaction,
1606 changes,
1607 raw_event,
1608 e,
1609 decryption_settings,
1610 )
1611 .await
1612 }
1613 e => {
1614 self.handle_to_device_event(changes, &e).await;
1615 Some(ProcessedToDeviceEvent::PlainText(raw_event))
1616 }
1617 }
1618 }
1619
1620 async fn receive_encrypted_to_device_event(
1634 &self,
1635 transaction: &mut StoreTransaction,
1636 changes: &mut Changes,
1637 mut raw_event: Raw<AnyToDeviceEvent>,
1638 e: ToDeviceEvent<ToDeviceEncryptedEventContent>,
1639 decryption_settings: &DecryptionSettings,
1640 ) -> Option<ProcessedToDeviceEvent> {
1641 let decrypted = match self
1642 .decrypt_to_device_event(transaction, &e, changes, decryption_settings)
1643 .await
1644 {
1645 Ok(decrypted) => decrypted,
1646 Err(DecryptToDeviceError::OlmError(err)) => {
1647 let reason = if let OlmError::UnverifiedSenderDevice = &err {
1648 ToDeviceUnableToDecryptReason::UnverifiedSenderDevice
1649 } else {
1650 ToDeviceUnableToDecryptReason::DecryptionFailure
1651 };
1652
1653 if let OlmError::SessionWedged(sender, curve_key) = err
1654 && let Err(e) =
1655 self.inner.session_manager.mark_device_as_wedged(&sender, curve_key).await
1656 {
1657 error!(
1658 error = ?e,
1659 "Couldn't mark device to be unwedged",
1660 );
1661 }
1662
1663 return Some(ProcessedToDeviceEvent::UnableToDecrypt {
1664 encrypted_event: raw_event,
1665 utd_info: ToDeviceUnableToDecryptInfo { reason },
1666 });
1667 }
1668 Err(DecryptToDeviceError::FromDehydratedDevice) => return None,
1669 };
1670
1671 match decrypted.session {
1674 SessionType::New(s) | SessionType::Existing(s) => {
1675 changes.sessions.push(s);
1676 }
1677 }
1678
1679 changes.message_hashes.push(decrypted.message_hash);
1680
1681 if let Some(group_session) = decrypted.inbound_group_session {
1682 changes.inbound_group_sessions.push(group_session);
1683 }
1684
1685 match decrypted.result.raw_event.deserialize_as() {
1686 Ok(event) => {
1687 self.handle_to_device_event(changes, &event).await;
1688
1689 raw_event = event
1690 .serialize_zeroized()
1691 .expect("Zeroizing and reserializing our events should always work")
1692 .cast();
1693 }
1694 Err(e) => {
1695 warn!("Received an invalid encrypted to-device event: {e}");
1696 raw_event = decrypted.result.raw_event;
1697 }
1698 }
1699
1700 Some(ProcessedToDeviceEvent::Decrypted {
1701 raw: raw_event,
1702 encryption_info: decrypted.result.encryption_info,
1703 })
1704 }
1705
1706 async fn check_to_device_event_is_not_from_dehydrated_device(
1709 &self,
1710 decrypted: &OlmDecryptionInfo,
1711 sender_user_id: &UserId,
1712 ) -> Result<(), DecryptToDeviceError> {
1713 if self.to_device_event_is_from_dehydrated_device(decrypted, sender_user_id).await? {
1714 warn!(
1715 sender = ?sender_user_id,
1716 session = ?decrypted.session,
1717 "Received a to-device event from a dehydrated device. This is unexpected: ignoring event"
1718 );
1719 Err(DecryptToDeviceError::FromDehydratedDevice)
1720 } else {
1721 Ok(())
1722 }
1723 }
1724
1725 async fn to_device_event_is_from_dehydrated_device(
1731 &self,
1732 decrypted: &OlmDecryptionInfo,
1733 sender_user_id: &UserId,
1734 ) -> OlmResult<bool> {
1735 if let Some(device_keys) = decrypted.result.event.sender_device_keys() {
1737 if device_keys.dehydrated.unwrap_or(false) {
1743 return Ok(true);
1744 }
1745 }
1750
1751 Ok(self
1753 .store()
1754 .get_device_from_curve_key(sender_user_id, decrypted.result.sender_key)
1755 .await?
1756 .is_some_and(|d| d.is_dehydrated()))
1757 }
1758
1759 #[instrument(skip_all)]
1777 pub async fn receive_sync_changes(
1778 &self,
1779 sync_changes: EncryptionSyncChanges<'_>,
1780 decryption_settings: &DecryptionSettings,
1781 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Vec<RoomKeyInfo>)> {
1782 let mut store_transaction = self.inner.store.transaction().await;
1783
1784 let (events, changes) = self
1785 .preprocess_sync_changes(&mut store_transaction, sync_changes, decryption_settings)
1786 .await?;
1787
1788 let room_key_updates: Vec<_> =
1791 changes.inbound_group_sessions.iter().map(RoomKeyInfo::from).collect();
1792
1793 self.store().save_changes(changes).await?;
1794 store_transaction.commit().await?;
1795
1796 Ok((events, room_key_updates))
1797 }
1798
1799 pub(crate) async fn preprocess_sync_changes(
1817 &self,
1818 transaction: &mut StoreTransaction,
1819 sync_changes: EncryptionSyncChanges<'_>,
1820 decryption_settings: &DecryptionSettings,
1821 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Changes)> {
1822 let mut events: Vec<ProcessedToDeviceEvent> = self
1824 .inner
1825 .verification_machine
1826 .garbage_collect()
1827 .iter()
1828 .map(|e| ProcessedToDeviceEvent::PlainText(e.clone()))
1832 .collect();
1833 let mut changes = Default::default();
1836
1837 {
1838 let account = transaction.account().await?;
1839 account.update_key_counts(
1840 sync_changes.one_time_keys_counts,
1841 sync_changes.unused_fallback_keys,
1842 )
1843 }
1844
1845 if let Err(e) = self
1846 .inner
1847 .identity_manager
1848 .receive_device_changes(
1849 transaction.cache(),
1850 sync_changes.changed_devices.changed.iter().map(|u| u.as_ref()),
1851 )
1852 .await
1853 {
1854 error!(error = ?e, "Error marking a tracked user as changed");
1855 }
1856
1857 for raw_event in sync_changes.to_device_events {
1858 let processed_event = Box::pin(self.receive_to_device_event(
1859 transaction,
1860 &mut changes,
1861 raw_event,
1862 decryption_settings,
1863 ))
1864 .await;
1865
1866 if let Some(processed_event) = processed_event {
1867 events.push(processed_event);
1868 }
1869 }
1870
1871 let changed_sessions = self
1872 .inner
1873 .key_request_machine
1874 .collect_incoming_key_requests(transaction.cache())
1875 .await?;
1876
1877 changes.sessions.extend(changed_sessions);
1878 changes.next_batch_token = sync_changes.next_batch_token;
1879
1880 Ok((events, changes))
1881 }
1882
1883 pub async fn request_room_key(
1900 &self,
1901 event: &Raw<EncryptedEvent>,
1902 room_id: &RoomId,
1903 ) -> MegolmResult<(Option<OutgoingRequest>, OutgoingRequest)> {
1904 let event = event.deserialize()?;
1905 self.inner.key_request_machine.request_key(room_id, &event).await
1906 }
1907
1908 async fn get_room_event_verification_state(
1921 &self,
1922 session: &InboundGroupSession,
1923 sender: &UserId,
1924 ) -> MegolmResult<(VerificationState, Option<OwnedDeviceId>)> {
1925 let sender_data = self.get_or_update_sender_data(session, sender).await?;
1926
1927 let (verification_state, device_id) = match sender_data.user_id() {
1936 Some(i) if i != sender => {
1937 (VerificationState::Unverified(VerificationLevel::MismatchedSender), None)
1938 }
1939
1940 Some(_) | None => {
1941 sender_data_to_verification_state(sender_data, session.has_been_imported())
1942 }
1943 };
1944
1945 Ok((verification_state, device_id))
1946 }
1947
1948 async fn get_or_update_sender_data(
1963 &self,
1964 session: &InboundGroupSession,
1965 sender: &UserId,
1966 ) -> MegolmResult<SenderData> {
1967 let sender_data = if session.sender_data.should_recalculate() {
1968 let calculated_sender_data = SenderDataFinder::find_using_curve_key(
1987 self.store(),
1988 session.sender_key(),
1989 sender,
1990 session,
1991 )
1992 .await?;
1993
1994 if calculated_sender_data.compare_trust_level(&session.sender_data).is_gt() {
1996 let mut new_session = session.clone();
1998 new_session.sender_data = calculated_sender_data.clone();
1999 self.store().save_inbound_group_sessions(&[new_session]).await?;
2000
2001 calculated_sender_data
2003 } else {
2004 session.sender_data.clone()
2006 }
2007 } else {
2008 session.sender_data.clone()
2009 };
2010
2011 Ok(sender_data)
2012 }
2013
2014 pub async fn query_missing_secrets_from_other_sessions(&self) -> StoreResult<bool> {
2039 let identity = self.inner.user_identity.lock().await;
2040 let mut secrets = identity.get_missing_secrets().await;
2041
2042 if self.store().load_backup_keys().await?.decryption_key.is_none() {
2043 secrets.push(SecretName::RecoveryKey);
2044 }
2045
2046 if secrets.is_empty() {
2047 debug!("No missing requests to query");
2048 return Ok(false);
2049 }
2050
2051 let secret_requests = GossipMachine::request_missing_secrets(self.user_id(), secrets);
2052
2053 let unsent_request = self.store().get_unsent_secret_requests().await?;
2055 let not_yet_requested = secret_requests
2056 .into_iter()
2057 .filter(|request| !unsent_request.iter().any(|unsent| unsent.info == request.info))
2058 .collect_vec();
2059
2060 if not_yet_requested.is_empty() {
2061 debug!("The missing secrets have already been requested");
2062 Ok(false)
2063 } else {
2064 debug!("Requesting missing secrets");
2065
2066 let changes = Changes { key_requests: not_yet_requested, ..Default::default() };
2067
2068 self.store().save_changes(changes).await?;
2069 Ok(true)
2070 }
2071 }
2072
2073 #[cfg(feature = "experimental-push-secrets")]
2081 pub async fn push_secret_to_verified_devices(
2082 &self,
2083 secret_name: SecretName,
2084 ) -> Result<HashMap<OwnedDeviceId, OlmError>, SecretPushError> {
2085 self.inner.key_request_machine.push_secret_to_verified_devices(secret_name).await
2086 }
2087
2088 async fn get_encryption_info(
2094 &self,
2095 session: &InboundGroupSession,
2096 sender: &UserId,
2097 ) -> MegolmResult<Arc<EncryptionInfo>> {
2098 let (verification_state, device_id) =
2099 self.get_room_event_verification_state(session, sender).await?;
2100
2101 Ok(Arc::new(EncryptionInfo {
2102 sender: sender.to_owned(),
2103 sender_device: device_id,
2104 forwarder: session.forwarder_data.as_ref().and_then(|data| {
2105 data.device_id().map(|device_id| ForwarderInfo {
2109 device_id: device_id.to_owned(),
2110 user_id: data.user_id().to_owned(),
2111 })
2112 }),
2113 algorithm_info: AlgorithmInfo::MegolmV1AesSha2 {
2114 curve25519_key: session.sender_key().to_base64(),
2115 sender_claimed_keys: session
2116 .signing_keys()
2117 .iter()
2118 .map(|(k, v)| (k.to_owned(), v.to_base64()))
2119 .collect(),
2120 session_id: Some(session.session_id().to_owned()),
2121 },
2122 verification_state,
2123 }))
2124 }
2125
2126 async fn decrypt_megolm_events(
2127 &self,
2128 room_id: &RoomId,
2129 event: &EncryptedEvent,
2130 content: &SupportedEventEncryptionSchemes<'_>,
2131 decryption_settings: &DecryptionSettings,
2132 ) -> MegolmResult<(JsonObject, Arc<EncryptionInfo>)> {
2133 let session =
2134 self.get_inbound_group_session_or_error(room_id, content.session_id()).await?;
2135
2136 Span::current().record("sender_key", debug(session.sender_key()));
2142
2143 let result = session.decrypt(event).await;
2144 match result {
2145 Ok((decrypted_event, _)) => {
2146 let encryption_info = self.get_encryption_info(&session, &event.sender).await?;
2147
2148 self.check_sender_trust_requirement(
2149 &session,
2150 &encryption_info,
2151 &decryption_settings.sender_device_trust_requirement,
2152 )?;
2153
2154 Ok((decrypted_event, encryption_info))
2155 }
2156 Err(error) => Err(
2157 if let MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) = error {
2158 let withheld_code = self
2159 .inner
2160 .store
2161 .get_withheld_info(room_id, content.session_id())
2162 .await?
2163 .map(|e| e.content.withheld_code());
2164
2165 if withheld_code.is_some() {
2166 MegolmError::MissingRoomKey(withheld_code)
2168 } else {
2169 error
2170 }
2171 } else {
2172 error
2173 },
2174 ),
2175 }
2176 }
2177
2178 fn check_sender_trust_requirement(
2184 &self,
2185 session: &InboundGroupSession,
2186 encryption_info: &EncryptionInfo,
2187 trust_requirement: &TrustRequirement,
2188 ) -> MegolmResult<()> {
2189 trace!(
2190 verification_state = ?encryption_info.verification_state,
2191 ?trust_requirement, "check_sender_trust_requirement",
2192 );
2193
2194 let verification_level = match &encryption_info.verification_state {
2197 VerificationState::Verified => return Ok(()),
2198 VerificationState::Unverified(verification_level) => verification_level,
2199 };
2200
2201 let ok = match trust_requirement {
2202 TrustRequirement::Untrusted => true,
2203
2204 TrustRequirement::CrossSignedOrLegacy => {
2205 let legacy_session = match session.sender_data {
2211 SenderData::DeviceInfo { legacy_session, .. } => legacy_session,
2212 SenderData::UnknownDevice { legacy_session, .. } => legacy_session,
2213 _ => false,
2214 };
2215
2216 match (verification_level, legacy_session) {
2226 (VerificationLevel::UnverifiedIdentity, _) => true,
2228
2229 (VerificationLevel::UnsignedDevice, true) => true,
2231
2232 (VerificationLevel::None(_), true) => true,
2234
2235 (VerificationLevel::VerificationViolation, _)
2237 | (VerificationLevel::MismatchedSender, _)
2238 | (VerificationLevel::UnsignedDevice, false)
2239 | (VerificationLevel::None(_), false) => false,
2240 }
2241 }
2242
2243 TrustRequirement::CrossSigned => match verification_level {
2246 VerificationLevel::UnverifiedIdentity => true,
2247
2248 VerificationLevel::VerificationViolation
2249 | VerificationLevel::MismatchedSender
2250 | VerificationLevel::UnsignedDevice
2251 | VerificationLevel::None(_) => false,
2252 },
2253 };
2254
2255 if ok {
2256 Ok(())
2257 } else {
2258 Err(MegolmError::SenderIdentityNotTrusted(verification_level.clone()))
2259 }
2260 }
2261
2262 async fn get_inbound_group_session_or_error(
2267 &self,
2268 room_id: &RoomId,
2269 session_id: &str,
2270 ) -> MegolmResult<InboundGroupSession> {
2271 match self.store().get_inbound_group_session(room_id, session_id).await? {
2272 Some(session) => Ok(session),
2273 None => {
2274 let withheld_code = self
2275 .inner
2276 .store
2277 .get_withheld_info(room_id, session_id)
2278 .await?
2279 .map(|e| e.content.withheld_code());
2280 Err(MegolmError::MissingRoomKey(withheld_code))
2281 }
2282 }
2283 }
2284
2285 pub async fn try_decrypt_room_event(
2300 &self,
2301 raw_event: &Raw<EncryptedEvent>,
2302 room_id: &RoomId,
2303 decryption_settings: &DecryptionSettings,
2304 ) -> Result<RoomEventDecryptionResult, CryptoStoreError> {
2305 match self.decrypt_room_event_inner(raw_event, room_id, true, decryption_settings).await {
2306 Ok(decrypted) => Ok(RoomEventDecryptionResult::Decrypted(decrypted)),
2307 Err(err) => Ok(RoomEventDecryptionResult::UnableToDecrypt(megolm_error_to_utd_info(
2308 raw_event, err,
2309 )?)),
2310 }
2311 }
2312
2313 pub async fn decrypt_room_event(
2321 &self,
2322 event: &Raw<EncryptedEvent>,
2323 room_id: &RoomId,
2324 decryption_settings: &DecryptionSettings,
2325 ) -> MegolmResult<DecryptedRoomEvent> {
2326 self.decrypt_room_event_inner(event, room_id, true, decryption_settings).await
2327 }
2328
2329 #[instrument(name = "decrypt_room_event", skip_all, fields(?room_id, event_id, origin_server_ts, sender, algorithm, session_id, message_index, sender_key))]
2330 async fn decrypt_room_event_inner(
2331 &self,
2332 event: &Raw<EncryptedEvent>,
2333 room_id: &RoomId,
2334 decrypt_unsigned: bool,
2335 decryption_settings: &DecryptionSettings,
2336 ) -> MegolmResult<DecryptedRoomEvent> {
2337 let _timer = timer!(tracing::Level::TRACE, "_method");
2338
2339 let event = event.deserialize()?;
2340
2341 Span::current()
2342 .record("sender", debug(&event.sender))
2343 .record("event_id", debug(&event.event_id))
2344 .record(
2345 "origin_server_ts",
2346 timestamp_to_iso8601(event.origin_server_ts)
2347 .unwrap_or_else(|| "<out of range>".to_owned()),
2348 )
2349 .record("algorithm", debug(event.content.algorithm()));
2350
2351 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2352 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2353 Span::current().record("sender_key", debug(c.sender_key));
2354 c.into()
2355 }
2356 #[cfg(feature = "experimental-algorithms")]
2357 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2358 RoomEventEncryptionScheme::Unknown(_) => {
2359 warn!("Received an encrypted room event with an unsupported algorithm");
2360 return Err(EventError::UnsupportedAlgorithm.into());
2361 }
2362 };
2363
2364 Span::current().record("session_id", content.session_id());
2365 Span::current().record("message_index", content.message_index());
2366
2367 let result =
2368 self.decrypt_megolm_events(room_id, &event, &content, decryption_settings).await;
2369
2370 if let Err(e) = &result {
2371 #[cfg(feature = "automatic-room-key-forwarding")]
2372 match e {
2373 MegolmError::MissingRoomKey(_)
2376 | MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
2377 self.inner
2378 .key_request_machine
2379 .create_outgoing_key_request(room_id, &event)
2380 .await?;
2381 }
2382 _ => {}
2383 }
2384
2385 warn!("Failed to decrypt a room event: {e}");
2386 }
2387
2388 let (mut decrypted_event, encryption_info) = result?;
2389
2390 let mut unsigned_encryption_info = None;
2391 if decrypt_unsigned {
2392 unsigned_encryption_info = self
2394 .decrypt_unsigned_events(&mut decrypted_event, room_id, decryption_settings)
2395 .await;
2396 }
2397
2398 let decrypted_event =
2399 serde_json::from_value::<Raw<AnyTimelineEvent>>(decrypted_event.into())?;
2400
2401 #[cfg(feature = "experimental-encrypted-state-events")]
2402 self.verify_packed_state_key(&event, &decrypted_event)?;
2403
2404 Ok(DecryptedRoomEvent { event: decrypted_event, encryption_info, unsigned_encryption_info })
2405 }
2406
2407 #[cfg(feature = "experimental-encrypted-state-events")]
2424 fn verify_packed_state_key(
2425 &self,
2426 original: &EncryptedEvent,
2427 decrypted: &Raw<AnyTimelineEvent>,
2428 ) -> MegolmResult<()> {
2429 use serde::Deserialize;
2430
2431 #[derive(Deserialize)]
2433 struct PayloadDeserializationHelper {
2434 state_key: Option<String>,
2435 #[serde(rename = "type")]
2436 event_type: String,
2437 }
2438
2439 let PayloadDeserializationHelper {
2441 state_key: inner_state_key,
2442 event_type: inner_event_type,
2443 } = decrypted
2444 .deserialize_as_unchecked()
2445 .map_err(|_| MegolmError::StateKeyVerificationFailed)?;
2446
2447 let (raw_state_key, inner_state_key) = match (&original.state_key, &inner_state_key) {
2449 (Some(raw_state_key), Some(inner_state_key)) => (raw_state_key, inner_state_key),
2450 (None, None) => return Ok(()),
2451 _ => return Err(MegolmError::StateKeyVerificationFailed),
2452 };
2453
2454 let (outer_event_type, outer_state_key) =
2456 raw_state_key.split_once(":").ok_or(MegolmError::StateKeyVerificationFailed)?;
2457
2458 if outer_event_type != inner_event_type {
2460 return Err(MegolmError::StateKeyVerificationFailed);
2461 }
2462
2463 if outer_state_key != inner_state_key {
2465 return Err(MegolmError::StateKeyVerificationFailed);
2466 }
2467 Ok(())
2468 }
2469
2470 async fn decrypt_unsigned_events(
2480 &self,
2481 main_event: &mut JsonObject,
2482 room_id: &RoomId,
2483 decryption_settings: &DecryptionSettings,
2484 ) -> Option<BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>> {
2485 let unsigned = main_event.get_mut("unsigned")?.as_object_mut()?;
2486 let mut unsigned_encryption_info: Option<
2487 BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>,
2488 > = None;
2489
2490 let location = UnsignedEventLocation::RelationsReplace;
2492 let replace = location.find_mut(unsigned);
2493 if let Some(decryption_result) =
2494 self.decrypt_unsigned_event(replace, room_id, decryption_settings).await
2495 {
2496 unsigned_encryption_info
2497 .get_or_insert_with(Default::default)
2498 .insert(location, decryption_result);
2499 }
2500
2501 let location = UnsignedEventLocation::RelationsThreadLatestEvent;
2504 let thread_latest_event = location.find_mut(unsigned);
2505 if let Some(decryption_result) =
2506 self.decrypt_unsigned_event(thread_latest_event, room_id, decryption_settings).await
2507 {
2508 unsigned_encryption_info
2509 .get_or_insert_with(Default::default)
2510 .insert(location, decryption_result);
2511 }
2512
2513 unsigned_encryption_info
2514 }
2515
2516 fn decrypt_unsigned_event<'a>(
2524 &'a self,
2525 event: Option<&'a mut Value>,
2526 room_id: &'a RoomId,
2527 decryption_settings: &'a DecryptionSettings,
2528 ) -> BoxFuture<'a, Option<UnsignedDecryptionResult>> {
2529 Box::pin(async move {
2530 let event = event?;
2531
2532 let is_encrypted = event
2533 .get("type")
2534 .and_then(|type_| type_.as_str())
2535 .is_some_and(|s| s == "m.room.encrypted");
2536 if !is_encrypted {
2537 return None;
2538 }
2539
2540 let raw_event = serde_json::from_value(event.clone()).ok()?;
2541 match self
2542 .decrypt_room_event_inner(&raw_event, room_id, false, decryption_settings)
2543 .await
2544 {
2545 Ok(decrypted_event) => {
2546 *event = serde_json::to_value(decrypted_event.event).ok()?;
2548 Some(UnsignedDecryptionResult::Decrypted(decrypted_event.encryption_info))
2549 }
2550 Err(err) => {
2551 let utd_info = megolm_error_to_utd_info(&raw_event, err).ok()?;
2556 Some(UnsignedDecryptionResult::UnableToDecrypt(utd_info))
2557 }
2558 }
2559 })
2560 }
2561
2562 pub async fn is_room_key_available(
2569 &self,
2570 event: &Raw<EncryptedEvent>,
2571 room_id: &RoomId,
2572 ) -> Result<bool, CryptoStoreError> {
2573 let event = event.deserialize()?;
2574
2575 let (session_id, message_index) = match &event.content.scheme {
2576 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2577 (&c.session_id, c.ciphertext.message_index())
2578 }
2579 #[cfg(feature = "experimental-algorithms")]
2580 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => {
2581 (&c.session_id, c.ciphertext.message_index())
2582 }
2583 RoomEventEncryptionScheme::Unknown(_) => {
2584 return Ok(false);
2586 }
2587 };
2588
2589 Ok(self
2592 .store()
2593 .get_inbound_group_session(room_id, session_id)
2594 .await?
2595 .filter(|s| s.first_known_index() <= message_index)
2596 .is_some())
2597 }
2598
2599 #[instrument(skip(self, event), fields(event_id, sender, session_id))]
2612 pub async fn get_room_event_encryption_info(
2613 &self,
2614 event: &Raw<EncryptedEvent>,
2615 room_id: &RoomId,
2616 ) -> MegolmResult<Arc<EncryptionInfo>> {
2617 let event = event.deserialize()?;
2618
2619 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2620 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => c.into(),
2621 #[cfg(feature = "experimental-algorithms")]
2622 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2623 RoomEventEncryptionScheme::Unknown(_) => {
2624 return Err(EventError::UnsupportedAlgorithm.into());
2625 }
2626 };
2627
2628 Span::current()
2629 .record("sender", debug(&event.sender))
2630 .record("event_id", debug(&event.event_id))
2631 .record("session_id", content.session_id());
2632
2633 self.get_session_encryption_info(room_id, content.session_id(), &event.sender).await
2634 }
2635
2636 pub async fn get_session_encryption_info(
2651 &self,
2652 room_id: &RoomId,
2653 session_id: &str,
2654 sender: &UserId,
2655 ) -> MegolmResult<Arc<EncryptionInfo>> {
2656 let session = self.get_inbound_group_session_or_error(room_id, session_id).await?;
2657 self.get_encryption_info(&session, sender).await
2658 }
2659
2660 pub async fn update_tracked_users(
2678 &self,
2679 users: impl IntoIterator<Item = &UserId>,
2680 ) -> StoreResult<()> {
2681 self.inner.identity_manager.update_tracked_users(users).await
2682 }
2683
2684 pub async fn mark_all_tracked_users_as_dirty(&self) -> StoreResult<()> {
2689 self.inner
2690 .identity_manager
2691 .mark_all_tracked_users_as_dirty(self.inner.store.cache().await?)
2692 .await
2693 }
2694
2695 async fn wait_if_user_pending(
2696 &self,
2697 user_id: &UserId,
2698 timeout: Option<Duration>,
2699 ) -> StoreResult<()> {
2700 if let Some(timeout) = timeout {
2701 let cache = self.store().cache().await?;
2702 self.inner
2703 .identity_manager
2704 .key_query_manager
2705 .wait_if_user_key_query_pending(cache, timeout, user_id)
2706 .await?;
2707 }
2708 Ok(())
2709 }
2710
2711 #[instrument(skip(self))]
2741 pub async fn get_device(
2742 &self,
2743 user_id: &UserId,
2744 device_id: &DeviceId,
2745 timeout: Option<Duration>,
2746 ) -> StoreResult<Option<Device>> {
2747 self.wait_if_user_pending(user_id, timeout).await?;
2748 self.store().get_device(user_id, device_id).await
2749 }
2750
2751 #[instrument(skip(self))]
2765 pub async fn get_identity(
2766 &self,
2767 user_id: &UserId,
2768 timeout: Option<Duration>,
2769 ) -> StoreResult<Option<UserIdentity>> {
2770 self.wait_if_user_pending(user_id, timeout).await?;
2771 self.store().get_identity(user_id).await
2772 }
2773
2774 #[instrument(skip(self))]
2801 pub async fn get_user_devices(
2802 &self,
2803 user_id: &UserId,
2804 timeout: Option<Duration>,
2805 ) -> StoreResult<UserDevices> {
2806 self.wait_if_user_pending(user_id, timeout).await?;
2807 self.store().get_user_devices(user_id).await
2808 }
2809
2810 pub async fn cross_signing_status(&self) -> CrossSigningStatus {
2815 self.inner.user_identity.lock().await.status().await
2816 }
2817
2818 pub async fn export_cross_signing_keys(&self) -> StoreResult<Option<CrossSigningKeyExport>> {
2826 let master_key = self.store().export_secret(&SecretName::CrossSigningMasterKey).await?;
2827 let self_signing_key =
2828 self.store().export_secret(&SecretName::CrossSigningSelfSigningKey).await?;
2829 let user_signing_key =
2830 self.store().export_secret(&SecretName::CrossSigningUserSigningKey).await?;
2831
2832 Ok(if master_key.is_none() && self_signing_key.is_none() && user_signing_key.is_none() {
2833 None
2834 } else {
2835 Some(CrossSigningKeyExport { master_key, self_signing_key, user_signing_key })
2836 })
2837 }
2838
2839 pub async fn import_cross_signing_keys(
2844 &self,
2845 export: CrossSigningKeyExport,
2846 ) -> Result<CrossSigningStatus, SecretImportError> {
2847 self.store().import_cross_signing_keys(export).await
2848 }
2849
2850 async fn sign_with_master_key(
2851 &self,
2852 message: &str,
2853 ) -> Result<(OwnedDeviceKeyId, Ed25519Signature), SignatureError> {
2854 let identity = &*self.inner.user_identity.lock().await;
2855 let key_id = identity.master_key_id().await.ok_or(SignatureError::MissingSigningKey)?;
2856
2857 let signature = identity.sign(message).await?;
2858
2859 Ok((key_id, signature))
2860 }
2861
2862 pub async fn sign(&self, message: &str) -> Result<Signatures, CryptoStoreError> {
2868 let mut signatures = Signatures::new();
2869
2870 {
2871 let cache = self.inner.store.cache().await?;
2872 let account = cache.account().await?;
2873 let key_id = account.signing_key_id();
2874 let signature = account.sign(message);
2875 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
2876 }
2877
2878 match self.sign_with_master_key(message).await {
2879 Ok((key_id, signature)) => {
2880 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
2881 }
2882 Err(e) => {
2883 warn!(error = ?e, "Couldn't sign the message using the cross signing master key")
2884 }
2885 }
2886
2887 Ok(signatures)
2888 }
2889
2890 pub fn backup_machine(&self) -> &BackupMachine {
2895 &self.inner.backup_machine
2896 }
2897
2898 pub async fn initialize_crypto_store_generation(
2902 &self,
2903 generation: &Mutex<Option<u64>>,
2904 ) -> StoreResult<()> {
2905 let mut gen_guard = generation.lock().await;
2908
2909 let prev_generation =
2910 self.inner.store.get_custom_value(Self::CURRENT_GENERATION_STORE_KEY).await?;
2911
2912 let generation = match prev_generation {
2913 Some(val) => {
2914 u64::from_le_bytes(val.try_into().map_err(|_| {
2917 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
2918 })?)
2919 .wrapping_add(1)
2920 }
2921 None => 0,
2922 };
2923
2924 tracing::debug!("Initialising crypto store generation at {generation}");
2925
2926 self.inner
2927 .store
2928 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, generation.to_le_bytes().to_vec())
2929 .await?;
2930
2931 *gen_guard = Some(generation);
2932
2933 Ok(())
2934 }
2935
2936 pub async fn maintain_crypto_store_generation(
2961 &'_ self,
2962 generation: &Mutex<Option<u64>>,
2963 ) -> StoreResult<(bool, u64)> {
2964 let mut gen_guard = generation.lock().await;
2965
2966 let actual_gen = self
2972 .inner
2973 .store
2974 .get_custom_value(Self::CURRENT_GENERATION_STORE_KEY)
2975 .await?
2976 .ok_or_else(|| {
2977 CryptoStoreError::InvalidLockGeneration("counter missing in store".to_owned())
2978 })?;
2979
2980 let actual_gen =
2981 u64::from_le_bytes(actual_gen.try_into().map_err(|_| {
2982 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
2983 })?);
2984
2985 let new_gen = match gen_guard.as_ref() {
2986 Some(expected_gen) => {
2987 if actual_gen == *expected_gen {
2988 return Ok((false, actual_gen));
2989 }
2990 actual_gen.max(*expected_gen).wrapping_add(1)
2992 }
2993 None => {
2994 actual_gen.wrapping_add(1)
2997 }
2998 };
2999
3000 tracing::debug!(
3001 "Crypto store generation mismatch: previously known was {:?}, actual is {:?}, next is {}",
3002 *gen_guard,
3003 actual_gen,
3004 new_gen
3005 );
3006
3007 *gen_guard = Some(new_gen);
3009
3010 self.inner
3012 .store
3013 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, new_gen.to_le_bytes().to_vec())
3014 .await?;
3015
3016 Ok((true, new_gen))
3017 }
3018
3019 pub fn dehydrated_devices(&self) -> DehydratedDevices {
3021 DehydratedDevices { inner: self.to_owned() }
3022 }
3023
3024 pub async fn room_settings(&self, room_id: &RoomId) -> StoreResult<Option<RoomSettings>> {
3029 self.inner.store.get_room_settings(room_id).await
3032 }
3033
3034 pub async fn set_room_settings(
3045 &self,
3046 room_id: &RoomId,
3047 new_settings: &RoomSettings,
3048 ) -> Result<(), SetRoomSettingsError> {
3049 let store = &self.inner.store;
3050
3051 let _store_transaction = store.transaction().await;
3056
3057 let old_settings = store.get_room_settings(room_id).await?;
3058
3059 if let Some(old_settings) = old_settings {
3072 if old_settings != *new_settings {
3073 return Err(SetRoomSettingsError::EncryptionDowngrade);
3074 } else {
3075 return Ok(());
3077 }
3078 }
3079
3080 match new_settings.algorithm {
3082 EventEncryptionAlgorithm::MegolmV1AesSha2 => (),
3083
3084 #[cfg(feature = "experimental-algorithms")]
3085 EventEncryptionAlgorithm::MegolmV2AesSha2 => (),
3086
3087 _ => {
3088 warn!(
3089 ?room_id,
3090 "Rejecting invalid encryption algorithm {}", new_settings.algorithm
3091 );
3092 return Err(SetRoomSettingsError::InvalidSettings);
3093 }
3094 }
3095
3096 store
3098 .save_changes(Changes {
3099 room_settings: HashMap::from([(room_id.to_owned(), new_settings.clone())]),
3100 ..Default::default()
3101 })
3102 .await?;
3103
3104 Ok(())
3105 }
3106
3107 #[cfg(any(feature = "testing", test))]
3111 pub fn same_as(&self, other: &OlmMachine) -> bool {
3112 Arc::ptr_eq(&self.inner, &other.inner)
3113 }
3114
3115 #[cfg(any(feature = "testing", test))]
3117 pub async fn uploaded_key_count(&self) -> Result<u64, CryptoStoreError> {
3118 let cache = self.inner.store.cache().await?;
3119 let account = cache.account().await?;
3120 Ok(account.uploaded_key_count())
3121 }
3122
3123 #[cfg(test)]
3125 pub(crate) fn identity_manager(&self) -> &IdentityManager {
3126 &self.inner.identity_manager
3127 }
3128
3129 #[cfg(test)]
3131 pub(crate) fn key_for_has_migrated_verification_latch() -> &'static str {
3132 Self::HAS_MIGRATED_VERIFICATION_LATCH
3133 }
3134}
3135
3136fn sender_data_to_verification_state(
3137 sender_data: SenderData,
3138 session_has_been_imported: bool,
3139) -> (VerificationState, Option<OwnedDeviceId>) {
3140 match sender_data {
3141 SenderData::UnknownDevice { owner_check_failed: false, .. } => {
3142 let device_link_problem = if session_has_been_imported {
3143 DeviceLinkProblem::InsecureSource
3144 } else {
3145 DeviceLinkProblem::MissingDevice
3146 };
3147
3148 (VerificationState::Unverified(VerificationLevel::None(device_link_problem)), None)
3149 }
3150 SenderData::UnknownDevice { owner_check_failed: true, .. } => (
3151 VerificationState::Unverified(VerificationLevel::None(
3152 DeviceLinkProblem::InsecureSource,
3153 )),
3154 None,
3155 ),
3156 SenderData::DeviceInfo { device_keys, .. } => (
3157 VerificationState::Unverified(VerificationLevel::UnsignedDevice),
3158 Some(device_keys.device_id),
3159 ),
3160 SenderData::VerificationViolation(KnownSenderData { device_id, .. }) => {
3161 (VerificationState::Unverified(VerificationLevel::VerificationViolation), device_id)
3162 }
3163 SenderData::SenderUnverified(KnownSenderData { device_id, .. }) => {
3164 (VerificationState::Unverified(VerificationLevel::UnverifiedIdentity), device_id)
3165 }
3166 SenderData::SenderVerified(KnownSenderData { device_id, .. }) => {
3167 (VerificationState::Verified, device_id)
3168 }
3169 }
3170}
3171
3172#[derive(Debug, Clone)]
3175pub struct CrossSigningBootstrapRequests {
3176 pub upload_keys_req: Option<OutgoingRequest>,
3183
3184 pub upload_signing_keys_req: UploadSigningKeysRequest,
3188
3189 pub upload_signatures_req: UploadSignaturesRequest,
3194}
3195
3196#[derive(Debug)]
3199pub struct EncryptionSyncChanges<'a> {
3200 pub to_device_events: Vec<Raw<AnyToDeviceEvent>>,
3202 pub changed_devices: &'a DeviceLists,
3205 pub one_time_keys_counts: &'a BTreeMap<OneTimeKeyAlgorithm, UInt>,
3207 pub unused_fallback_keys: Option<&'a [OneTimeKeyAlgorithm]>,
3209 pub next_batch_token: Option<String>,
3211}
3212
3213fn megolm_error_to_utd_info(
3221 raw_event: &Raw<EncryptedEvent>,
3222 error: MegolmError,
3223) -> Result<UnableToDecryptInfo, CryptoStoreError> {
3224 use MegolmError::*;
3225 let reason = match error {
3226 EventError(_) => UnableToDecryptReason::MalformedEncryptedEvent,
3227 Decode(_) => UnableToDecryptReason::MalformedEncryptedEvent,
3228 MissingRoomKey(maybe_withheld) => {
3229 UnableToDecryptReason::MissingMegolmSession { withheld_code: maybe_withheld }
3230 }
3231 Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
3232 UnableToDecryptReason::UnknownMegolmMessageIndex
3233 }
3234 Decryption(_) => UnableToDecryptReason::MegolmDecryptionFailure,
3235 JsonError(_) => UnableToDecryptReason::PayloadDeserializationFailure,
3236 MismatchedIdentityKeys(_) => UnableToDecryptReason::MismatchedIdentityKeys,
3237 SenderIdentityNotTrusted(level) => UnableToDecryptReason::SenderIdentityNotTrusted(level),
3238 #[cfg(feature = "experimental-encrypted-state-events")]
3239 StateKeyVerificationFailed => UnableToDecryptReason::StateKeyVerificationFailed,
3240
3241 Store(error) => Err(error)?,
3244 };
3245
3246 let session_id = raw_event.deserialize().ok().and_then(|ev| match ev.content.scheme {
3247 RoomEventEncryptionScheme::MegolmV1AesSha2(s) => Some(s.session_id),
3248 #[cfg(feature = "experimental-algorithms")]
3249 RoomEventEncryptionScheme::MegolmV2AesSha2(s) => Some(s.session_id),
3250 RoomEventEncryptionScheme::Unknown(_) => None,
3251 });
3252
3253 Ok(UnableToDecryptInfo { session_id, reason })
3254}
3255
3256#[derive(Debug, thiserror::Error)]
3266pub(crate) enum DecryptToDeviceError {
3267 #[error("An Olm error occurred meaning we failed to decrypt the event")]
3268 OlmError(#[from] OlmError),
3269
3270 #[error("The event was sent from a dehydrated device")]
3271 FromDehydratedDevice,
3272}
3273
3274impl From<CryptoStoreError> for DecryptToDeviceError {
3275 fn from(value: CryptoStoreError) -> Self {
3276 Self::OlmError(value.into())
3277 }
3278}
3279
3280#[cfg(test)]
3281impl From<DecryptToDeviceError> for OlmError {
3282 fn from(value: DecryptToDeviceError) -> Self {
3285 match value {
3286 DecryptToDeviceError::OlmError(olm_error) => olm_error,
3287 DecryptToDeviceError::FromDehydratedDevice => {
3288 panic!("Expected an OlmError but found FromDehydratedDevice")
3289 }
3290 }
3291 }
3292}
3293
3294#[cfg(test)]
3295pub(crate) mod test_helpers;
3296
3297#[cfg(test)]
3298pub(crate) mod tests;