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;
73#[cfg(feature = "experimental-x509-identity-verification")]
74use crate::x509::{RawX509Signer, RawX509Verifier, X509Signer, X509Verifier};
75use crate::{
76 CollectStrategy, CryptoStoreError, DecryptionSettings, DeviceData, LocalTrust,
77 RoomEventDecryptionResult, SignatureError, TrustRequirement,
78 backups::{BackupMachine, MegolmV1BackupKey},
79 dehydrated_devices::{DehydratedDevices, DehydrationError},
80 error::{EventError, MegolmError, MegolmResult, OlmError, OlmResult, SetRoomSettingsError},
81 gossiping::GossipMachine,
82 identities::{Device, IdentityManager, UserDevices, user::UserIdentity},
83 olm::{
84 Account, CrossSigningStatus, EncryptionSettings, IdentityKeys, InboundGroupSession,
85 KnownSenderData, OlmDecryptionInfo, PrivateCrossSigningIdentity, SenderData,
86 SenderDataFinder, SessionType, StaticAccountData,
87 },
88 session_manager::{GroupSessionManager, SessionManager},
89 store::{
90 CryptoStoreWrapper, DynCryptoStore, IntoCryptoStore, MemoryStore, Result as StoreResult,
91 SecretImportError, Store, StoreTransaction,
92 caches::StoreCache,
93 types::{
94 Changes, CrossSigningKeyExport, DeviceChanges, IdentityChanges, PendingChanges,
95 RoomKeyInfo, RoomSettings, StoredRoomKeyBundleData,
96 },
97 },
98 types::{
99 EventEncryptionAlgorithm, Signatures,
100 events::{
101 ToDeviceEvent, ToDeviceEvents,
102 olm_v1::{AnyDecryptedOlmEvent, DecryptedRoomKeyBundleEvent, DecryptedRoomKeyEvent},
103 room::encrypted::{
104 EncryptedEvent, EncryptedToDeviceEvent, RoomEncryptedEventContent,
105 RoomEventEncryptionScheme, SupportedEventEncryptionSchemes,
106 ToDeviceEncryptedEventContent,
107 },
108 room_key::{MegolmV1AesSha2Content, RoomKeyContent},
109 room_key_bundle::RoomKeyBundleContent,
110 room_key_withheld::{
111 MegolmV1AesSha2WithheldContent, RoomKeyWithheldContent, RoomKeyWithheldEvent,
112 },
113 },
114 requests::{
115 AnyIncomingResponse, KeysQueryRequest, OutgoingRequest, ToDeviceRequest,
116 UploadSigningKeysRequest,
117 },
118 },
119 utilities::timestamp_to_iso8601,
120 verification::{Verification, VerificationMachine, VerificationRequest},
121};
122
123#[derive(Debug, Serialize)]
124pub struct RawEncryptionResult {
126 pub content: Raw<RoomEncryptedEventContent>,
128 pub encryption_info: EncryptionInfo,
130}
131
132pub struct OlmMachineBuilder {
134 user_id: OwnedUserId,
136
137 device_id: OwnedDeviceId,
139
140 store: Option<Arc<DynCryptoStore>>,
143
144 custom_account: Option<vodozemac::olm::Account>,
147
148 #[cfg(feature = "experimental-x509-identity-verification")]
150 x509_verifier: Option<X509Verifier>,
151
152 #[cfg(feature = "experimental-x509-identity-verification")]
154 x509_signer: Option<X509Signer>,
155}
156
157impl OlmMachineBuilder {
158 pub fn new(user_id: &UserId, device_id: &DeviceId) -> Self {
161 Self {
162 user_id: user_id.to_owned(),
163 device_id: device_id.to_owned(),
164 store: None,
165 custom_account: None,
166 #[cfg(feature = "experimental-x509-identity-verification")]
167 x509_verifier: None,
168 #[cfg(feature = "experimental-x509-identity-verification")]
169 x509_signer: None,
170 }
171 }
172
173 pub fn with_crypto_store(mut self, store: impl IntoCryptoStore) -> Self {
181 self.store = Some(store.into_crypto_store());
182 self
183 }
184
185 pub fn with_custom_account(mut self, custom_account: Option<vodozemac::olm::Account>) -> Self {
195 self.custom_account = custom_account;
196 self
197 }
198
199 #[cfg(feature = "experimental-x509-identity-verification")]
202 pub fn with_x509_verifier(mut self, x509_verifier: Option<Arc<dyn RawX509Verifier>>) -> Self {
203 self.x509_verifier = x509_verifier.map(X509Verifier::new);
204 self
205 }
206
207 #[cfg(feature = "experimental-x509-identity-verification")]
210 pub fn with_x509_signer(mut self, x509_signer: Option<Arc<dyn RawX509Signer>>) -> Self {
211 self.x509_signer = x509_signer.map(X509Signer::new);
212 self
213 }
214
215 pub async fn build(self) -> Result<OlmMachine, CryptoStoreError> {
222 OlmMachine::from_builder(self).await
223 }
224}
225
226impl std::fmt::Debug for OlmMachineBuilder {
227 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
228 f.debug_struct("OlmMachineBuilder")
229 .field("user_id", &self.user_id)
230 .field("device_id", &self.device_id)
231 .finish_non_exhaustive()
232 }
233}
234
235#[derive(Clone)]
238pub struct OlmMachine {
239 pub(crate) inner: Arc<OlmMachineInner>,
240}
241
242pub struct OlmMachineInner {
243 user_id: OwnedUserId,
245 device_id: OwnedDeviceId,
247 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
251 store: Store,
254 session_manager: SessionManager,
256 pub(crate) group_session_manager: GroupSessionManager,
258 verification_machine: VerificationMachine,
261 pub(crate) key_request_machine: GossipMachine,
264 identity_manager: IdentityManager,
267 backup_machine: BackupMachine,
269}
270
271#[cfg(not(tarpaulin_include))]
272impl std::fmt::Debug for OlmMachine {
273 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
274 f.debug_struct("OlmMachine")
275 .field("user_id", &self.user_id())
276 .field("device_id", &self.device_id())
277 .finish()
278 }
279}
280
281impl OlmMachine {
282 const CURRENT_GENERATION_STORE_KEY: &'static str = "generation-counter";
283 const HAS_MIGRATED_VERIFICATION_LATCH: &'static str = "HAS_MIGRATED_VERIFICATION_LATCH";
284
285 pub async fn new(user_id: &UserId, device_id: &DeviceId) -> Self {
295 OlmMachineBuilder::new(user_id, device_id)
296 .build()
297 .await
298 .expect("Reading and writing to the memory store always succeeds")
299 }
300
301 pub(crate) async fn rehydrate(
302 &self,
303 pickle_key: &[u8; 32],
304 device_id: &DeviceId,
305 device_data: Raw<DehydratedDeviceData>,
306 ) -> Result<OlmMachine, DehydrationError> {
307 let account = Account::rehydrate(pickle_key, self.user_id(), device_id, device_data)?;
308 let static_account = account.static_data().clone();
309
310 let store =
311 Arc::new(CryptoStoreWrapper::new(self.user_id(), device_id, MemoryStore::new()));
312 let device = DeviceData::from_account(&account);
313 store.save_pending_changes(PendingChanges { account: Some(account) }).await?;
314 store
315 .save_changes(Changes {
316 devices: DeviceChanges { new: vec![device], ..Default::default() },
317 ..Default::default()
318 })
319 .await?;
320
321 let (verification_machine, store, identity_manager) = Self::new_helper_prelude(
322 store,
323 static_account,
324 self.store().private_identity(),
325 #[cfg(feature = "experimental-x509-identity-verification")]
326 self.store().x509_verifier().cloned(),
327 #[cfg(feature = "experimental-x509-identity-verification")]
328 self.store().x509_signer().cloned(),
329 );
330
331 Ok(Self::new_helper(
332 device_id,
333 store,
334 verification_machine,
335 identity_manager,
336 self.store().private_identity(),
337 None,
338 ))
339 }
340
341 fn new_helper_prelude(
342 store_wrapper: Arc<CryptoStoreWrapper>,
343 account: StaticAccountData,
344 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
345 #[cfg(feature = "experimental-x509-identity-verification")] x509_verifier: Option<
346 X509Verifier,
347 >,
348 #[cfg(feature = "experimental-x509-identity-verification")] x509_signer: Option<X509Signer>,
349 ) -> (VerificationMachine, Store, IdentityManager) {
350 let verification_machine =
351 VerificationMachine::new(account.clone(), user_identity.clone(), store_wrapper.clone());
352
353 let store = Store::new_with_x509(
354 account,
355 user_identity,
356 store_wrapper,
357 verification_machine.clone(),
358 #[cfg(feature = "experimental-x509-identity-verification")]
359 x509_verifier,
360 #[cfg(feature = "experimental-x509-identity-verification")]
361 x509_signer,
362 );
363
364 let identity_manager = IdentityManager::new(store.clone());
365
366 (verification_machine, store, identity_manager)
367 }
368
369 fn new_helper(
370 device_id: &DeviceId,
371 store: Store,
372 verification_machine: VerificationMachine,
373 identity_manager: IdentityManager,
374 user_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
375 maybe_backup_key: Option<MegolmV1BackupKey>,
376 ) -> Self {
377 let group_session_manager = GroupSessionManager::new(store.clone());
378
379 let users_for_key_claim = Arc::new(StdRwLock::new(BTreeMap::new()));
380 let key_request_machine = GossipMachine::new(
381 store.clone(),
382 identity_manager.clone(),
383 group_session_manager.session_cache(),
384 users_for_key_claim.clone(),
385 );
386
387 let session_manager =
388 SessionManager::new(users_for_key_claim, key_request_machine.clone(), store.clone());
389
390 let backup_machine = BackupMachine::new(store.clone(), maybe_backup_key);
391
392 let inner = Arc::new(OlmMachineInner {
393 user_id: store.user_id().to_owned(),
394 device_id: device_id.to_owned(),
395 user_identity,
396 store,
397 session_manager,
398 group_session_manager,
399 verification_machine,
400 key_request_machine,
401 identity_manager,
402 backup_machine,
403 });
404
405 Self { inner }
406 }
407
408 #[instrument(skip(builder), fields(user_id, device_id, ed25519_key, curve25519_key))]
409 pub(crate) async fn from_builder(builder: OlmMachineBuilder) -> StoreResult<Self> {
410 let OlmMachineBuilder {
411 user_id,
412 device_id,
413 store,
414 custom_account,
415 #[cfg(feature = "experimental-x509-identity-verification")]
416 x509_verifier,
417 #[cfg(feature = "experimental-x509-identity-verification")]
418 x509_signer,
419 } = builder;
420
421 Span::current()
422 .record("user_id", display(&user_id))
423 .record("device_id", display(&device_id));
424
425 let store = store.unwrap_or_else(|| MemoryStore::new().into_crypto_store());
426
427 let static_account = match store.load_account().await? {
428 Some(account) => {
429 if user_id != account.user_id()
430 || device_id != account.device_id()
431 || custom_account.is_some()
432 {
433 return Err(CryptoStoreError::MismatchedAccount {
434 expected: (account.user_id().to_owned(), account.device_id().to_owned()),
435 got: (user_id.to_owned(), device_id.to_owned()),
436 });
437 }
438
439 Span::current()
440 .record("ed25519_key", display(account.identity_keys().ed25519))
441 .record("curve25519_key", display(account.identity_keys().curve25519));
442 debug!("Restored an Olm account");
443
444 account.static_data().clone()
445 }
446
447 None => {
448 let account = if let Some(account) = custom_account {
449 Account::new_helper(account, &user_id, &device_id)
450 } else {
451 Account::with_device_id(&user_id, &device_id)
452 };
453
454 let static_account = account.static_data().clone();
455
456 Span::current()
457 .record("ed25519_key", display(account.identity_keys().ed25519))
458 .record("curve25519_key", display(account.identity_keys().curve25519));
459
460 let device = DeviceData::from_account(&account);
461
462 device.set_trust_state(LocalTrust::Verified);
466
467 let changes = Changes {
468 devices: DeviceChanges { new: vec![device], ..Default::default() },
469 ..Default::default()
470 };
471 store.save_changes(changes).await?;
472 store.save_pending_changes(PendingChanges { account: Some(account) }).await?;
473
474 debug!("Created a new Olm account");
475
476 static_account
477 }
478 };
479
480 let identity = match store.load_identity().await? {
481 Some(i) => {
482 let master_key = i
483 .master_public_key()
484 .await
485 .and_then(|m| m.get_first_key().map(|m| m.to_owned()));
486 debug!(?master_key, "Restored the cross signing identity");
487 i
488 }
489 None => {
490 debug!("Creating an empty cross signing identity stub");
491 PrivateCrossSigningIdentity::empty(&user_id)
492 }
493 };
494
495 let saved_keys = store.load_backup_keys().await?;
500 let maybe_backup_key = saved_keys.decryption_key.and_then(|k| {
501 if let Some(version) = saved_keys.backup_version {
502 let megolm_v1_backup_key = k.megolm_v1_public_key();
503 megolm_v1_backup_key.set_version(version);
504 Some(megolm_v1_backup_key)
505 } else {
506 None
507 }
508 });
509
510 let identity = Arc::new(Mutex::new(identity));
511 let store = Arc::new(CryptoStoreWrapper::new(&user_id, &device_id, store));
512
513 let (verification_machine, store, identity_manager) = Self::new_helper_prelude(
514 store,
515 static_account,
516 identity.clone(),
517 #[cfg(feature = "experimental-x509-identity-verification")]
518 x509_verifier,
519 #[cfg(feature = "experimental-x509-identity-verification")]
520 x509_signer,
521 );
522
523 Self::migration_post_verified_latch_support(&store, &identity_manager).await?;
526
527 Ok(Self::new_helper(
528 &device_id,
529 store,
530 verification_machine,
531 identity_manager,
532 identity,
533 maybe_backup_key,
534 ))
535 }
536
537 pub(crate) async fn migration_post_verified_latch_support(
544 store: &Store,
545 identity_manager: &IdentityManager,
546 ) -> Result<(), CryptoStoreError> {
547 let maybe_migrate_for_identity_verified_latch =
548 store.get_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH).await?.is_none();
549
550 if maybe_migrate_for_identity_verified_latch {
551 identity_manager.mark_all_tracked_users_as_dirty(store.cache().await?).await?;
552
553 store.set_custom_value(Self::HAS_MIGRATED_VERIFICATION_LATCH, vec![0]).await?
554 }
555 Ok(())
556 }
557
558 pub fn store(&self) -> &Store {
560 &self.inner.store
561 }
562
563 pub fn user_id(&self) -> &UserId {
565 &self.inner.user_id
566 }
567
568 pub fn device_id(&self) -> &DeviceId {
570 &self.inner.device_id
571 }
572
573 pub fn device_creation_time(&self) -> MilliSecondsSinceUnixEpoch {
580 self.inner.store.static_account().creation_local_time()
581 }
582
583 pub fn identity_keys(&self) -> IdentityKeys {
585 let account = self.inner.store.static_account();
586 account.identity_keys()
587 }
588
589 pub async fn display_name(&self) -> StoreResult<Option<String>> {
591 self.store().device_display_name().await
592 }
593
594 pub async fn tracked_users(&self) -> StoreResult<HashSet<OwnedUserId>> {
599 let cache = self.store().cache().await?;
600 Ok(self.inner.identity_manager.key_query_manager.synced(&cache).await?.tracked_users())
601 }
602
603 #[cfg(feature = "automatic-room-key-forwarding")]
611 pub fn set_room_key_requests_enabled(&self, enable: bool) {
612 self.inner.key_request_machine.set_room_key_requests_enabled(enable)
613 }
614
615 pub fn are_room_key_requests_enabled(&self) -> bool {
620 self.inner.key_request_machine.are_room_key_requests_enabled()
621 }
622
623 #[cfg(feature = "automatic-room-key-forwarding")]
632 pub fn set_room_key_forwarding_enabled(&self, enable: bool) {
633 self.inner.key_request_machine.set_room_key_forwarding_enabled(enable)
634 }
635
636 pub fn is_room_key_forwarding_enabled(&self) -> bool {
640 self.inner.key_request_machine.is_room_key_forwarding_enabled()
641 }
642
643 pub async fn outgoing_requests(&self) -> StoreResult<Vec<OutgoingRequest>> {
651 let mut requests = Vec::new();
652
653 {
654 let store_cache = self.inner.store.cache().await?;
655 let account = store_cache.account().await?;
656 if let Some(r) = self.keys_for_upload(&account).await.map(|r| OutgoingRequest {
657 request_id: TransactionId::new(),
658 request: Arc::new(r.into()),
659 }) {
660 requests.push(r);
661 }
662 }
663
664 for request in self
665 .inner
666 .identity_manager
667 .users_for_key_query()
668 .await?
669 .into_iter()
670 .map(|(request_id, r)| OutgoingRequest { request_id, request: Arc::new(r.into()) })
671 {
672 requests.push(request);
673 }
674
675 requests.append(&mut self.inner.verification_machine.outgoing_messages());
676 requests.append(&mut self.inner.key_request_machine.outgoing_to_device_requests().await?);
677
678 #[cfg(feature = "experimental-x509-identity-verification")]
679 if let Some(signature_upload_request) =
680 self.inner.identity_manager.get_x509_signature_upload_request().await
681 {
682 requests.push(signature_upload_request);
683 }
684
685 Ok(requests)
686 }
687
688 pub fn query_keys_for_users<'a>(
709 &self,
710 users: impl IntoIterator<Item = &'a UserId>,
711 ) -> (OwnedTransactionId, KeysQueryRequest) {
712 self.inner.identity_manager.build_key_query_for_users(users)
713 }
714
715 pub async fn mark_request_as_sent<'a>(
725 &self,
726 request_id: &TransactionId,
727 response: impl Into<AnyIncomingResponse<'a>>,
728 ) -> OlmResult<()> {
729 match response.into() {
730 AnyIncomingResponse::KeysUpload(response) => {
731 Box::pin(self.receive_keys_upload_response(response)).await?;
732 }
733 AnyIncomingResponse::KeysQuery(response) => {
734 Box::pin(self.receive_keys_query_response(request_id, response)).await?;
735 }
736 AnyIncomingResponse::KeysClaim(response) => {
737 Box::pin(
738 self.inner.session_manager.receive_keys_claim_response(request_id, response),
739 )
740 .await?;
741 }
742 AnyIncomingResponse::ToDevice(_) => {
743 Box::pin(self.mark_to_device_request_as_sent(request_id)).await?;
744 }
745 AnyIncomingResponse::SigningKeysUpload(_) => {
746 Box::pin(self.receive_cross_signing_upload_response()).await?;
747 }
748 AnyIncomingResponse::SignatureUpload(_) => {
749 self.inner.verification_machine.mark_request_as_sent(request_id);
750 self.inner.key_request_machine.mark_outgoing_request_as_sent(request_id).await?;
751 #[cfg(feature = "experimental-x509-identity-verification")]
752 self.inner.identity_manager.mark_x509_signature_request_as_sent(request_id).await;
753 }
754 AnyIncomingResponse::RoomMessage(_) => {
755 self.inner.verification_machine.mark_request_as_sent(request_id);
756 }
757 AnyIncomingResponse::KeysBackup(_) => {
758 Box::pin(self.inner.backup_machine.mark_request_as_sent(request_id)).await?;
759 }
760 }
761
762 Ok(())
763 }
764
765 async fn receive_cross_signing_upload_response(&self) -> StoreResult<()> {
767 let identity = self.inner.user_identity.lock().await;
768 identity.mark_as_shared();
769
770 let changes = Changes { private_identity: Some(identity.clone()), ..Default::default() };
771
772 self.store().save_changes(changes).await
773 }
774
775 pub async fn bootstrap_cross_signing(
794 &self,
795 reset: bool,
796 ) -> Result<CrossSigningBootstrapRequests, BootstrapCrossSigningError> {
797 let identity = self.inner.user_identity.lock().await.clone();
802
803 let (upload_signing_keys_req, upload_signatures_req) = if reset || identity.is_empty().await
804 {
805 info!("Creating new cross signing identity");
806
807 let (identity, upload_signing_keys_req, upload_signatures_req) = {
808 let cache = self.inner.store.cache().await?;
809 let account = cache.account().await?;
810 account
811 .bootstrap_cross_signing(
812 #[cfg(feature = "experimental-x509-identity-verification")]
813 self.inner.store.x509_signer().map(|s| s.raw()),
814 )
815 .await?
816 };
817
818 let public = identity.to_public_identity().await.expect(
819 "Couldn't create a public version of the identity from a new private identity",
820 );
821
822 *self.inner.user_identity.lock().await = identity.clone();
823
824 self.store()
825 .save_changes(Changes {
826 identities: IdentityChanges { new: vec![public.into()], ..Default::default() },
827 private_identity: Some(identity),
828 ..Default::default()
829 })
830 .await?;
831
832 (upload_signing_keys_req, upload_signatures_req)
833 } else {
834 info!("Trying to upload the existing cross signing identity");
835 let upload_signing_keys_req = identity.as_upload_request().await;
836
837 let upload_signatures_req = identity
839 .sign_account(self.inner.store.static_account())
840 .await
841 .expect("Can't sign device keys");
842
843 (upload_signing_keys_req, upload_signatures_req)
844 };
845
846 let upload_keys_req =
850 self.upload_device_keys().await?.map(|(_, request)| OutgoingRequest::from(request));
851
852 Ok(CrossSigningBootstrapRequests {
853 upload_signing_keys_req,
854 upload_keys_req,
855 upload_signatures_req,
856 })
857 }
858
859 pub async fn upload_device_keys(
871 &self,
872 ) -> StoreResult<Option<(OwnedTransactionId, UploadKeysRequest)>> {
873 let cache = self.store().cache().await?;
874 let account = cache.account().await?;
875
876 Ok(self.keys_for_upload(&account).await.map(|request| (TransactionId::new(), request)))
877 }
878
879 async fn receive_keys_upload_response(&self, response: &UploadKeysResponse) -> OlmResult<()> {
886 self.inner
887 .store
888 .with_transaction(async |tr| {
889 let account = tr.account().await?;
890 account.receive_keys_upload_response(response)?;
891 Ok(())
892 })
893 .await
894 }
895
896 #[instrument(skip_all)]
924 pub async fn get_missing_sessions(
925 &self,
926 users: impl Iterator<Item = &UserId>,
927 ) -> StoreResult<Option<(OwnedTransactionId, KeysClaimRequest)>> {
928 self.inner.session_manager.get_missing_sessions(users).await
929 }
930
931 async fn receive_keys_query_response(
940 &self,
941 request_id: &TransactionId,
942 response: &KeysQueryResponse,
943 ) -> OlmResult<(DeviceChanges, IdentityChanges)> {
944 self.inner.identity_manager.receive_keys_query_response(request_id, response).await
945 }
946
947 async fn keys_for_upload(&self, account: &Account) -> Option<UploadKeysRequest> {
956 let (mut device_keys, one_time_keys, fallback_keys) = account.keys_for_upload();
957
958 if let Some(device_keys) = &mut device_keys {
968 let private_identity = self.store().private_identity();
969 let guard = private_identity.lock().await;
970
971 if guard.status().await.is_complete() {
972 guard.sign_device_keys(device_keys).await.expect(
973 "We should be able to sign our device keys since we confirmed that we \
974 have a complete set of private cross-signing keys",
975 );
976 }
977 }
978
979 if device_keys.is_none() && one_time_keys.is_empty() && fallback_keys.is_empty() {
980 None
981 } else {
982 let device_keys = device_keys.map(|d| d.to_raw());
983
984 Some(assign!(UploadKeysRequest::new(), {
985 device_keys, one_time_keys, fallback_keys
986 }))
987 }
988 }
989
990 async fn decrypt_to_device_event(
1013 &self,
1014 transaction: &mut StoreTransaction,
1015 event: &EncryptedToDeviceEvent,
1016 changes: &mut Changes,
1017 decryption_settings: &DecryptionSettings,
1018 ) -> Result<OlmDecryptionInfo, DecryptToDeviceError> {
1019 let mut decrypted = transaction
1021 .account()
1022 .await?
1023 .decrypt_to_device_event(&self.inner.store, event, decryption_settings)
1024 .await?;
1025
1026 self.check_to_device_event_is_not_from_dehydrated_device(&decrypted, &event.sender).await?;
1028
1029 self.handle_decrypted_to_device_event(transaction.cache(), &mut decrypted, changes).await?;
1032
1033 Ok(decrypted)
1034 }
1035
1036 #[instrument(
1037 skip_all,
1038 fields(room_id = ? content.room_id, session_id, message_index, shared_history = content.shared_history)
1042 )]
1043 async fn handle_key(
1044 &self,
1045 sender_key: Curve25519PublicKey,
1046 event: &DecryptedRoomKeyEvent,
1047 content: &MegolmV1AesSha2Content,
1048 ) -> OlmResult<Option<InboundGroupSession>> {
1049 let session =
1050 InboundGroupSession::from_room_key_content(sender_key, event.keys.ed25519, content);
1051
1052 match session {
1053 Ok(mut session) => {
1054 Span::current().record("session_id", session.session_id());
1055 Span::current().record("message_index", session.first_known_index());
1056
1057 let sender_data =
1058 SenderDataFinder::find_using_event(self.store(), sender_key, event, &session)
1059 .await?;
1060 session.sender_data = sender_data;
1061
1062 Ok(self.store().merge_received_group_session(session).await?)
1063 }
1064 Err(e) => {
1065 Span::current().record("session_id", &content.session_id);
1066 warn!("Received a room key event which contained an invalid session key: {e}");
1067
1068 Ok(None)
1069 }
1070 }
1071 }
1072
1073 #[instrument(skip_all, fields(algorithm = ?event.content.algorithm()))]
1075 async fn add_room_key(
1076 &self,
1077 sender_key: Curve25519PublicKey,
1078 event: &DecryptedRoomKeyEvent,
1079 ) -> OlmResult<Option<InboundGroupSession>> {
1080 match &event.content {
1081 RoomKeyContent::MegolmV1AesSha2(content) => {
1082 self.handle_key(sender_key, event, content).await
1083 }
1084 #[cfg(feature = "experimental-algorithms")]
1085 RoomKeyContent::MegolmV2AesSha2(content) => {
1086 self.handle_key(sender_key, event, content).await
1087 }
1088 RoomKeyContent::Unknown(_) => {
1089 warn!("Received a room key with an unsupported algorithm");
1090 Ok(None)
1091 }
1092 }
1093 }
1094
1095 #[instrument()]
1097 async fn receive_room_key_bundle_data(
1098 &self,
1099 sender_key: Curve25519PublicKey,
1100 event: &DecryptedRoomKeyBundleEvent,
1101 changes: &mut Changes,
1102 ) -> OlmResult<()> {
1103 let Some(sender_device_keys) = &event.sender_device_keys else {
1104 warn!("Received a room key bundle with no sender device keys: ignoring");
1105 return Ok(());
1106 };
1107
1108 let sender_device_data =
1113 DeviceData::try_from(sender_device_keys).expect("failed to verify sender device keys");
1114 let sender_device = self.store().wrap_device_data(sender_device_data).await?;
1115
1116 changes.received_room_key_bundles.push(StoredRoomKeyBundleData {
1117 sender_user: event.sender.clone(),
1118 sender_data: SenderData::from_device(&sender_device),
1119 sender_key,
1120 bundle_data: event.content.clone(),
1121 });
1122 Ok(())
1123 }
1124
1125 fn add_withheld_info(&self, changes: &mut Changes, event: &RoomKeyWithheldEvent) {
1126 debug!(?event.content, "Processing `m.room_key.withheld` event");
1127
1128 if let RoomKeyWithheldContent::MegolmV1AesSha2(
1129 MegolmV1AesSha2WithheldContent::BlackListed(c)
1130 | MegolmV1AesSha2WithheldContent::Unverified(c)
1131 | MegolmV1AesSha2WithheldContent::Unauthorised(c)
1132 | MegolmV1AesSha2WithheldContent::Unavailable(c),
1133 ) = &event.content
1134 {
1135 changes
1136 .withheld_session_info
1137 .entry(c.room_id.to_owned())
1138 .or_default()
1139 .insert(c.session_id.to_owned(), event.to_owned().into());
1140 }
1141 }
1142
1143 #[cfg(test)]
1144 pub(crate) async fn create_outbound_group_session_with_defaults_test_helper(
1145 &self,
1146 room_id: &RoomId,
1147 ) -> OlmResult<()> {
1148 let (_, session) = self
1149 .inner
1150 .group_session_manager
1151 .create_outbound_group_session(
1152 room_id,
1153 EncryptionSettings::default(),
1154 SenderData::unknown(),
1155 )
1156 .await?;
1157
1158 self.store().save_inbound_group_sessions(&[session]).await?;
1159
1160 Ok(())
1161 }
1162
1163 #[cfg(test)]
1164 #[allow(dead_code)]
1165 pub(crate) async fn create_inbound_session_test_helper(
1166 &self,
1167 room_id: &RoomId,
1168 ) -> OlmResult<InboundGroupSession> {
1169 let (_, session) = self
1170 .inner
1171 .group_session_manager
1172 .create_outbound_group_session(
1173 room_id,
1174 EncryptionSettings::default(),
1175 SenderData::unknown(),
1176 )
1177 .await?;
1178
1179 Ok(session)
1180 }
1181
1182 pub async fn encrypt_room_event(
1199 &self,
1200 room_id: &RoomId,
1201 content: impl MessageLikeEventContent,
1202 ) -> MegolmResult<RawEncryptionResult> {
1203 let event_type = content.event_type().to_string();
1204 let content = Raw::new(&content)?.cast_unchecked();
1205 self.encrypt_room_event_raw(room_id, &event_type, &content).await
1206 }
1207
1208 pub async fn encrypt_room_event_raw(
1228 &self,
1229 room_id: &RoomId,
1230 event_type: &str,
1231 content: &Raw<AnyMessageLikeEventContent>,
1232 ) -> MegolmResult<RawEncryptionResult> {
1233 self.inner.group_session_manager.encrypt(room_id, event_type, content).await.map(|result| {
1234 RawEncryptionResult {
1235 content: result.content,
1236 encryption_info: self
1237 .own_encryption_info(result.algorithm, result.session_id.to_string()),
1238 }
1239 })
1240 }
1241
1242 fn own_encryption_info(
1243 &self,
1244 algorithm: EventEncryptionAlgorithm,
1245 session_id: String,
1246 ) -> EncryptionInfo {
1247 let identity_keys = self.identity_keys();
1248
1249 let algorithm_info = match algorithm {
1250 EventEncryptionAlgorithm::MegolmV1AesSha2 => AlgorithmInfo::MegolmV1AesSha2 {
1251 curve25519_key: identity_keys.curve25519.to_base64(),
1252 sender_claimed_keys: BTreeMap::from([(
1253 DeviceKeyAlgorithm::Ed25519,
1254 identity_keys.ed25519.to_base64(),
1255 )]),
1256 session_id: Some(session_id),
1257 },
1258 EventEncryptionAlgorithm::OlmV1Curve25519AesSha2 => {
1259 AlgorithmInfo::OlmV1Curve25519AesSha2 {
1260 curve25519_public_key_base64: identity_keys.curve25519.to_base64(),
1261 }
1262 }
1263 _ => unreachable!(
1264 "Only MegolmV1AesSha2 and OlmV1Curve25519AesSha2 are supported on this level"
1265 ),
1266 };
1267
1268 EncryptionInfo {
1269 sender: self.inner.user_id.clone(),
1270 sender_device: Some(self.inner.device_id.clone()),
1271 forwarder: None,
1272 algorithm_info,
1273 verification_state: VerificationState::Verified,
1274 }
1275 }
1276
1277 #[cfg(feature = "experimental-encrypted-state-events")]
1289 pub async fn encrypt_state_event<C, K>(
1290 &self,
1291 room_id: &RoomId,
1292 content: C,
1293 state_key: K,
1294 ) -> MegolmResult<Raw<RoomEncryptedEventContent>>
1295 where
1296 C: StateEventContent,
1297 C::StateKey: Borrow<K>,
1298 K: AsRef<str>,
1299 {
1300 let event_type = content.event_type().to_string();
1301 let content = Raw::new(&content)?.cast_unchecked();
1302 self.encrypt_state_event_raw(room_id, &event_type, state_key.as_ref(), &content).await
1303 }
1304
1305 #[cfg(feature = "experimental-encrypted-state-events")]
1322 pub async fn encrypt_state_event_raw(
1323 &self,
1324 room_id: &RoomId,
1325 event_type: &str,
1326 state_key: &str,
1327 content: &Raw<AnyStateEventContent>,
1328 ) -> MegolmResult<Raw<RoomEncryptedEventContent>> {
1329 self.inner
1330 .group_session_manager
1331 .encrypt_state(room_id, event_type, state_key, content)
1332 .await
1333 }
1334
1335 pub async fn discard_room_key(&self, room_id: &RoomId) -> StoreResult<bool> {
1346 self.inner.group_session_manager.invalidate_group_session(room_id).await
1347 }
1348
1349 pub async fn share_room_key(
1368 &self,
1369 room_id: &RoomId,
1370 users: impl Iterator<Item = &UserId>,
1371 encryption_settings: impl Into<EncryptionSettings>,
1372 ) -> OlmResult<Vec<Arc<ToDeviceRequest>>> {
1373 self.inner.group_session_manager.share_room_key(room_id, users, encryption_settings).await
1374 }
1375
1376 #[cfg(feature = "experimental-send-custom-to-device")]
1389 pub async fn encrypt_content_for_devices(
1390 &self,
1391 devices: Vec<DeviceData>,
1392 event_type: &str,
1393 content: &Value,
1394 share_strategy: CollectStrategy,
1395 ) -> OlmResult<(Vec<ToDeviceRequest>, Vec<(DeviceData, WithheldCode)>)> {
1396 let mut changes = Changes::default();
1397
1398 let (allowed_devices, mut blocked_devices) =
1399 split_devices_for_share_strategy(&self.inner.store, devices, share_strategy).await?;
1400
1401 let result = self
1402 .inner
1403 .group_session_manager
1404 .encrypt_content_for_devices(allowed_devices, event_type, content.clone(), &mut changes)
1405 .await;
1406
1407 if !changes.is_empty() {
1409 let session_count = changes.sessions.len();
1410
1411 self.inner.store.save_changes(changes).await?;
1412
1413 trace!(
1414 session_count = session_count,
1415 "Stored the changed sessions after encrypting a custom to-device event"
1416 );
1417 }
1418
1419 result.map(|(to_device_requests, mut withheld)| {
1420 withheld.append(&mut blocked_devices);
1421 (to_device_requests, withheld)
1422 })
1423 }
1424 pub async fn share_room_key_bundle_data(
1429 &self,
1430 user_id: &UserId,
1431 collect_strategy: &CollectStrategy,
1432 bundle_data: RoomKeyBundleContent,
1433 ) -> OlmResult<Vec<ToDeviceRequest>> {
1434 self.inner
1435 .group_session_manager
1436 .share_room_key_bundle_data(user_id, collect_strategy, bundle_data)
1437 .await
1438 }
1439
1440 #[deprecated(note = "Use OlmMachine::receive_verification_event instead", since = "0.7.0")]
1448 pub async fn receive_unencrypted_verification_event(
1449 &self,
1450 event: &AnyMessageLikeEvent,
1451 ) -> StoreResult<()> {
1452 self.inner.verification_machine.receive_any_event(event).await
1453 }
1454
1455 pub async fn receive_verification_event(&self, event: &AnyMessageLikeEvent) -> StoreResult<()> {
1468 self.inner.verification_machine.receive_any_event(event).await
1469 }
1470
1471 #[instrument(
1477 skip_all,
1478 fields(
1479 sender_key = ?decrypted.result.sender_key,
1480 event_type = decrypted.result.event.event_type(),
1481 ),
1482 )]
1483 async fn handle_decrypted_to_device_event(
1484 &self,
1485 cache: &StoreCache,
1486 decrypted: &mut OlmDecryptionInfo,
1487 changes: &mut Changes,
1488 ) -> OlmResult<()> {
1489 debug!(
1490 sender_device_keys =
1491 ?decrypted.result.event.sender_device_keys().map(|k| (k.curve25519_key(), k.ed25519_key())).unwrap_or((None, None)),
1492 "Received a decrypted to-device event",
1493 );
1494
1495 match &*decrypted.result.event {
1496 AnyDecryptedOlmEvent::RoomKey(e) => {
1497 let session = self.add_room_key(decrypted.result.sender_key, e).await?;
1498 decrypted.inbound_group_session = session;
1499 }
1500 AnyDecryptedOlmEvent::ForwardedRoomKey(e) => {
1501 let session = self
1502 .inner
1503 .key_request_machine
1504 .receive_forwarded_room_key(decrypted.result.sender_key, e)
1505 .await?;
1506 decrypted.inbound_group_session = session;
1507 }
1508 AnyDecryptedOlmEvent::SecretSend(e) => {
1509 let name = self
1510 .inner
1511 .key_request_machine
1512 .receive_secret_event(cache, decrypted.result.sender_key, e, changes)
1513 .await?;
1514
1515 if let Ok(ToDeviceEvents::SecretSend(mut e)) =
1518 decrypted.result.raw_event.deserialize_as()
1519 {
1520 e.content.secret_name = name;
1521 decrypted.result.raw_event = Raw::from_json(to_raw_value(&e)?);
1522 }
1523
1524 if enabled!(tracing::Level::DEBUG) {
1525 let cross_signing_status = self.cross_signing_status().await;
1526 let backup_enabled = self.backup_machine().enabled().await;
1527 debug!(
1528 ?cross_signing_status,
1529 backup_enabled, "Status after receiving secret event"
1530 );
1531 }
1532 }
1533 AnyDecryptedOlmEvent::Dummy(_) => {
1534 debug!("Received an `m.dummy` event");
1535 }
1536 AnyDecryptedOlmEvent::RoomKeyBundle(e) => {
1537 debug!("Received a room key bundle event {:?}", e);
1538 self.receive_room_key_bundle_data(decrypted.result.sender_key, e, changes).await?;
1539 }
1540 #[cfg(feature = "experimental-push-secrets")]
1541 AnyDecryptedOlmEvent::SecretPush(e) => {
1542 self.inner
1543 .key_request_machine
1544 .receive_secret_push_event(&decrypted.result.sender_key, e, changes)
1545 .await?;
1546 }
1547 AnyDecryptedOlmEvent::Custom(_) => {
1548 warn!("Received an unexpected encrypted to-device event");
1549 }
1550 }
1551
1552 Ok(())
1553 }
1554
1555 async fn handle_verification_event(&self, event: &ToDeviceEvents) {
1556 if let Err(e) = self.inner.verification_machine.receive_any_event(event).await {
1557 error!("Error handling a verification event: {e:?}");
1558 }
1559 }
1560
1561 async fn mark_to_device_request_as_sent(&self, request_id: &TransactionId) -> StoreResult<()> {
1563 self.inner.verification_machine.mark_request_as_sent(request_id);
1564 self.inner.key_request_machine.mark_outgoing_request_as_sent(request_id).await?;
1565 self.inner.group_session_manager.mark_request_as_sent(request_id).await?;
1566 self.inner.session_manager.mark_outgoing_request_as_sent(request_id);
1567 Ok(())
1568 }
1569
1570 pub fn get_verification(&self, user_id: &UserId, flow_id: &str) -> Option<Verification> {
1572 self.inner.verification_machine.get_verification(user_id, flow_id)
1573 }
1574
1575 pub fn get_verification_request(
1577 &self,
1578 user_id: &UserId,
1579 flow_id: impl AsRef<str>,
1580 ) -> Option<VerificationRequest> {
1581 self.inner.verification_machine.get_request(user_id, flow_id)
1582 }
1583
1584 pub fn get_verification_requests(&self, user_id: &UserId) -> Vec<VerificationRequest> {
1586 self.inner.verification_machine.get_requests(user_id)
1587 }
1588
1589 async fn handle_to_device_event(&self, changes: &mut Changes, event: &ToDeviceEvents) {
1594 use crate::types::events::ToDeviceEvents::*;
1595
1596 match event {
1597 RoomKeyRequest(e) => self.inner.key_request_machine.receive_incoming_key_request(e),
1603 SecretRequest(e) => self.inner.key_request_machine.receive_incoming_secret_request(e),
1604 RoomKeyWithheld(e) => self.add_withheld_info(changes, e),
1605 KeyVerificationAccept(..)
1606 | KeyVerificationCancel(..)
1607 | KeyVerificationKey(..)
1608 | KeyVerificationMac(..)
1609 | KeyVerificationRequest(..)
1610 | KeyVerificationReady(..)
1611 | KeyVerificationDone(..)
1612 | KeyVerificationStart(..) => {
1613 self.handle_verification_event(event).await;
1614 }
1615
1616 Custom(_) | Dummy(_) => {}
1618
1619 RoomEncrypted(_) => {}
1621
1622 SecretSend(_) | RoomKey(_) | ForwardedRoomKey(_) => {}
1625 }
1626 }
1627
1628 fn record_message_id(event: &Raw<AnyToDeviceEvent>) {
1629 use serde::Deserialize;
1630
1631 #[derive(Deserialize)]
1632 struct ContentStub<'a> {
1633 #[serde(borrow, rename = "org.matrix.msgid")]
1634 message_id: Option<&'a str>,
1635 }
1636 #[derive(Deserialize)]
1637 struct ToDeviceStub<'a> {
1638 sender: &'a str,
1639 #[serde(rename = "type")]
1640 event_type: &'a str,
1641 #[serde(borrow)]
1642 content: ContentStub<'a>,
1643 }
1644
1645 if let Ok(event) = event.deserialize_as_unchecked::<ToDeviceStub<'_>>() {
1646 Span::current().record("sender", event.sender);
1647 Span::current().record("event_type", event.event_type);
1648 Span::current().record("message_id", event.content.message_id);
1649 }
1650 }
1651
1652 #[instrument(skip_all, fields(sender, event_type, message_id))]
1660 async fn receive_to_device_event(
1661 &self,
1662 transaction: &mut StoreTransaction,
1663 changes: &mut Changes,
1664 raw_event: Raw<AnyToDeviceEvent>,
1665 decryption_settings: &DecryptionSettings,
1666 ) -> Option<ProcessedToDeviceEvent> {
1667 Self::record_message_id(&raw_event);
1668
1669 let event: ToDeviceEvents = match raw_event.deserialize_as() {
1670 Ok(e) => e,
1671 Err(e) => {
1672 warn!("Received an invalid to-device event: {e}");
1674 return Some(ProcessedToDeviceEvent::Invalid(raw_event));
1675 }
1676 };
1677
1678 debug!("Received a to-device event");
1679
1680 match event {
1681 ToDeviceEvents::RoomEncrypted(e) => {
1682 self.receive_encrypted_to_device_event(
1683 transaction,
1684 changes,
1685 raw_event,
1686 e,
1687 decryption_settings,
1688 )
1689 .await
1690 }
1691 e => {
1692 self.handle_to_device_event(changes, &e).await;
1693 Some(ProcessedToDeviceEvent::PlainText(raw_event))
1694 }
1695 }
1696 }
1697
1698 async fn receive_encrypted_to_device_event(
1712 &self,
1713 transaction: &mut StoreTransaction,
1714 changes: &mut Changes,
1715 mut raw_event: Raw<AnyToDeviceEvent>,
1716 e: ToDeviceEvent<ToDeviceEncryptedEventContent>,
1717 decryption_settings: &DecryptionSettings,
1718 ) -> Option<ProcessedToDeviceEvent> {
1719 let decrypted = match self
1720 .decrypt_to_device_event(transaction, &e, changes, decryption_settings)
1721 .await
1722 {
1723 Ok(decrypted) => decrypted,
1724 Err(DecryptToDeviceError::OlmError(err)) => {
1725 let reason = if let OlmError::UnverifiedSenderDevice = &err {
1726 ToDeviceUnableToDecryptReason::UnverifiedSenderDevice
1727 } else {
1728 ToDeviceUnableToDecryptReason::DecryptionFailure
1729 };
1730
1731 if let OlmError::SessionWedged(sender, curve_key) = err
1732 && let Err(e) =
1733 self.inner.session_manager.mark_device_as_wedged(&sender, curve_key).await
1734 {
1735 error!(
1736 error = ?e,
1737 "Couldn't mark device to be unwedged",
1738 );
1739 }
1740
1741 return Some(ProcessedToDeviceEvent::UnableToDecrypt {
1742 encrypted_event: raw_event,
1743 utd_info: ToDeviceUnableToDecryptInfo { reason },
1744 });
1745 }
1746 Err(DecryptToDeviceError::FromDehydratedDevice) => return None,
1747 };
1748
1749 match decrypted.session {
1751 SessionType::New(s) | SessionType::Existing(s) => {
1752 changes.sessions.push(s);
1753 }
1754 }
1755
1756 changes.message_hashes.push(decrypted.message_hash);
1757
1758 if let Some(group_session) = decrypted.inbound_group_session {
1759 changes.inbound_group_sessions.push(group_session);
1760 }
1761
1762 match decrypted.result.raw_event.deserialize_as() {
1763 Ok(event) => {
1764 self.handle_to_device_event(changes, &event).await;
1765
1766 raw_event = event
1767 .serialize_zeroized()
1768 .expect("Zeroizing and reserializing our events should always work")
1769 .cast();
1770 }
1771 Err(e) => {
1772 warn!("Received an invalid encrypted to-device event: {e}");
1773 raw_event = decrypted.result.raw_event;
1774 }
1775 }
1776
1777 Some(ProcessedToDeviceEvent::Decrypted {
1778 raw: raw_event,
1779 encryption_info: decrypted.result.encryption_info,
1780 })
1781 }
1782
1783 async fn check_to_device_event_is_not_from_dehydrated_device(
1786 &self,
1787 decrypted: &OlmDecryptionInfo,
1788 sender_user_id: &UserId,
1789 ) -> Result<(), DecryptToDeviceError> {
1790 if self.to_device_event_is_from_dehydrated_device(decrypted, sender_user_id).await? {
1791 warn!(
1792 sender = ?sender_user_id,
1793 session = ?decrypted.session,
1794 "Received a to-device event from a dehydrated device. This is unexpected: ignoring event"
1795 );
1796 Err(DecryptToDeviceError::FromDehydratedDevice)
1797 } else {
1798 Ok(())
1799 }
1800 }
1801
1802 async fn to_device_event_is_from_dehydrated_device(
1808 &self,
1809 decrypted: &OlmDecryptionInfo,
1810 sender_user_id: &UserId,
1811 ) -> OlmResult<bool> {
1812 if let Some(device_keys) = decrypted.result.event.sender_device_keys() {
1814 if device_keys.dehydrated.unwrap_or(false) {
1820 return Ok(true);
1821 }
1822 }
1827
1828 Ok(self
1830 .store()
1831 .get_device_from_curve_key(sender_user_id, decrypted.result.sender_key)
1832 .await?
1833 .is_some_and(|d| d.is_dehydrated()))
1834 }
1835
1836 #[instrument(skip_all)]
1856 pub async fn receive_sync_changes(
1857 &self,
1858 sync_changes: EncryptionSyncChanges<'_>,
1859 decryption_settings: &DecryptionSettings,
1860 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Vec<RoomKeyInfo>)> {
1861 self.receive_sync_changes_impl(sync_changes, decryption_settings, true).await
1862 }
1863
1864 #[instrument(skip_all)]
1884 pub async fn receive_sync_changes_msc4186(
1885 &self,
1886 sync_changes: EncryptionSyncChanges<'_>,
1887 decryption_settings: &DecryptionSettings,
1888 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Vec<RoomKeyInfo>)> {
1889 self.receive_sync_changes_impl(sync_changes, decryption_settings, false).await
1890 }
1891
1892 async fn receive_sync_changes_impl(
1902 &self,
1903 sync_changes: EncryptionSyncChanges<'_>,
1904 decryption_settings: &DecryptionSettings,
1905 is_missing_count_zero: bool,
1906 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Vec<RoomKeyInfo>)> {
1907 let mut store_transaction = self.inner.store.transaction().await;
1908
1909 {
1910 let account = store_transaction.account().await?;
1911 account.update_key_counts(
1912 sync_changes.one_time_keys_counts,
1913 sync_changes.unused_fallback_keys,
1914 is_missing_count_zero,
1915 )
1916 }
1917
1918 let (events, changes) = self
1919 .preprocess_sync_changes(&mut store_transaction, sync_changes, decryption_settings)
1920 .await?;
1921
1922 let room_key_updates: Vec<_> =
1925 changes.inbound_group_sessions.iter().map(RoomKeyInfo::from).collect();
1926
1927 self.store().save_changes(changes).await?;
1928 store_transaction.commit().await?;
1929
1930 Ok((events, room_key_updates))
1931 }
1932
1933 pub(crate) async fn preprocess_sync_changes(
1951 &self,
1952 transaction: &mut StoreTransaction,
1953 sync_changes: EncryptionSyncChanges<'_>,
1954 decryption_settings: &DecryptionSettings,
1955 ) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Changes)> {
1956 let mut events: Vec<ProcessedToDeviceEvent> = self
1958 .inner
1959 .verification_machine
1960 .garbage_collect()
1961 .iter()
1962 .map(|e| ProcessedToDeviceEvent::PlainText(e.clone()))
1966 .collect();
1967 let mut changes = Default::default();
1970
1971 if let Err(e) = self
1972 .inner
1973 .identity_manager
1974 .receive_device_changes(
1975 transaction.cache(),
1976 sync_changes.changed_devices.changed.iter().map(|u| u.as_ref()),
1977 )
1978 .await
1979 {
1980 error!(error = ?e, "Error marking a tracked user as changed");
1981 }
1982
1983 for raw_event in sync_changes.to_device_events {
1984 let processed_event = Box::pin(self.receive_to_device_event(
1985 transaction,
1986 &mut changes,
1987 raw_event,
1988 decryption_settings,
1989 ))
1990 .await;
1991
1992 if let Some(processed_event) = processed_event {
1993 events.push(processed_event);
1994 }
1995 }
1996
1997 let changed_sessions = self
1998 .inner
1999 .key_request_machine
2000 .collect_incoming_key_requests(transaction.cache())
2001 .await?;
2002
2003 changes.sessions.extend(changed_sessions);
2004 changes.next_batch_token = sync_changes.next_batch_token;
2005
2006 Ok((events, changes))
2007 }
2008
2009 pub async fn request_room_key(
2024 &self,
2025 event: &Raw<EncryptedEvent>,
2026 room_id: &RoomId,
2027 ) -> MegolmResult<(Option<OutgoingRequest>, OutgoingRequest)> {
2028 let event = event.deserialize()?;
2029 self.inner.key_request_machine.request_key(room_id, &event).await
2030 }
2031
2032 async fn get_room_event_verification_state(
2045 &self,
2046 session: &InboundGroupSession,
2047 sender: &UserId,
2048 ) -> MegolmResult<(VerificationState, Option<OwnedDeviceId>)> {
2049 let sender_data = self.get_or_update_sender_data(session, sender).await?;
2050
2051 let (verification_state, device_id) = match sender_data.user_id() {
2060 Some(i) if i != sender => {
2061 (VerificationState::Unverified(VerificationLevel::MismatchedSender), None)
2062 }
2063
2064 Some(_) | None => {
2065 sender_data_to_verification_state(sender_data, session.has_been_imported())
2066 }
2067 };
2068
2069 Ok((verification_state, device_id))
2070 }
2071
2072 async fn get_or_update_sender_data(
2087 &self,
2088 session: &InboundGroupSession,
2089 sender: &UserId,
2090 ) -> MegolmResult<SenderData> {
2091 let sender_data = if session.sender_data.should_recalculate() {
2092 let calculated_sender_data = SenderDataFinder::find_using_curve_key(
2113 self.store(),
2114 session.sender_key(),
2115 sender,
2116 session,
2117 )
2118 .await?;
2119
2120 if calculated_sender_data.compare_trust_level(&session.sender_data).is_gt() {
2122 let mut new_session = session.clone();
2124 new_session.sender_data = calculated_sender_data.clone();
2125 self.store().save_inbound_group_sessions(&[new_session]).await?;
2126
2127 calculated_sender_data
2129 } else {
2130 session.sender_data.clone()
2132 }
2133 } else {
2134 session.sender_data.clone()
2135 };
2136
2137 Ok(sender_data)
2138 }
2139
2140 pub async fn query_missing_secrets_from_other_sessions(&self) -> StoreResult<bool> {
2165 let identity = self.inner.user_identity.lock().await;
2166 let mut secrets = identity.get_missing_secrets().await;
2167
2168 if self.store().load_backup_keys().await?.decryption_key.is_none() {
2169 secrets.push(SecretName::RecoveryKey);
2170 }
2171
2172 if secrets.is_empty() {
2173 debug!("No missing requests to query");
2174 return Ok(false);
2175 }
2176
2177 let secret_requests = GossipMachine::request_missing_secrets(self.user_id(), secrets);
2178
2179 let unsent_request = self.store().get_unsent_secret_requests().await?;
2181 let not_yet_requested = secret_requests
2182 .into_iter()
2183 .filter(|request| !unsent_request.iter().any(|unsent| unsent.info == request.info))
2184 .collect_vec();
2185
2186 if not_yet_requested.is_empty() {
2187 debug!("The missing secrets have already been requested");
2188 Ok(false)
2189 } else {
2190 debug!("Requesting missing secrets");
2191
2192 let changes = Changes { key_requests: not_yet_requested, ..Default::default() };
2193
2194 self.store().save_changes(changes).await?;
2195 Ok(true)
2196 }
2197 }
2198
2199 #[cfg(feature = "experimental-push-secrets")]
2207 pub async fn push_secret_to_verified_devices(
2208 &self,
2209 secret_name: SecretName,
2210 ) -> Result<HashMap<OwnedDeviceId, OlmError>, SecretPushError> {
2211 self.inner.key_request_machine.push_secret_to_verified_devices(secret_name).await
2212 }
2213
2214 async fn get_encryption_info(
2220 &self,
2221 session: &InboundGroupSession,
2222 sender: &UserId,
2223 ) -> MegolmResult<Arc<EncryptionInfo>> {
2224 let (verification_state, device_id) =
2225 self.get_room_event_verification_state(session, sender).await?;
2226
2227 Ok(Arc::new(EncryptionInfo {
2228 sender: sender.to_owned(),
2229 sender_device: device_id,
2230 forwarder: session.forwarder_data.as_ref().and_then(|data| {
2231 data.device_id().map(|device_id| ForwarderInfo {
2236 device_id: device_id.to_owned(),
2237 user_id: data.user_id().to_owned(),
2238 })
2239 }),
2240 algorithm_info: AlgorithmInfo::MegolmV1AesSha2 {
2241 curve25519_key: session.sender_key().to_base64(),
2242 sender_claimed_keys: session
2243 .signing_keys()
2244 .iter()
2245 .map(|(k, v)| (k.to_owned(), v.to_base64()))
2246 .collect(),
2247 session_id: Some(session.session_id().to_owned()),
2248 },
2249 verification_state,
2250 }))
2251 }
2252
2253 async fn decrypt_megolm_events(
2254 &self,
2255 room_id: &RoomId,
2256 event: &EncryptedEvent,
2257 content: &SupportedEventEncryptionSchemes<'_>,
2258 decryption_settings: &DecryptionSettings,
2259 ) -> MegolmResult<(JsonObject, Arc<EncryptionInfo>)> {
2260 let session =
2261 self.get_inbound_group_session_or_error(room_id, content.session_id()).await?;
2262
2263 Span::current().record("sender_key", debug(session.sender_key()));
2269
2270 let result = session.decrypt(event).await;
2271 match result {
2272 Ok((decrypted_event, _)) => {
2273 let encryption_info = self.get_encryption_info(&session, &event.sender).await?;
2274
2275 self.check_sender_trust_requirement(
2276 &session,
2277 &encryption_info,
2278 &decryption_settings.sender_device_trust_requirement,
2279 )?;
2280
2281 Ok((decrypted_event, encryption_info))
2282 }
2283 Err(error) => Err(
2284 if let MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) = error {
2285 let withheld_code = self
2286 .inner
2287 .store
2288 .get_withheld_info(room_id, content.session_id())
2289 .await?
2290 .map(|e| e.content.withheld_code());
2291
2292 if withheld_code.is_some() {
2293 MegolmError::MissingRoomKey(withheld_code)
2296 } else {
2297 error
2298 }
2299 } else {
2300 error
2301 },
2302 ),
2303 }
2304 }
2305
2306 fn check_sender_trust_requirement(
2312 &self,
2313 session: &InboundGroupSession,
2314 encryption_info: &EncryptionInfo,
2315 trust_requirement: &TrustRequirement,
2316 ) -> MegolmResult<()> {
2317 trace!(
2318 verification_state = ?encryption_info.verification_state,
2319 ?trust_requirement, "check_sender_trust_requirement",
2320 );
2321
2322 let verification_level = match &encryption_info.verification_state {
2325 VerificationState::Verified => return Ok(()),
2326 VerificationState::Unverified(verification_level) => verification_level,
2327 };
2328
2329 let ok = match trust_requirement {
2330 TrustRequirement::Untrusted => true,
2331
2332 TrustRequirement::CrossSignedOrLegacy => {
2333 let legacy_session = match session.sender_data {
2340 SenderData::DeviceInfo { legacy_session, .. } => legacy_session,
2341 SenderData::UnknownDevice { legacy_session, .. } => legacy_session,
2342 _ => false,
2343 };
2344
2345 match (verification_level, legacy_session) {
2355 (VerificationLevel::UnverifiedIdentity, _) => true,
2357
2358 (VerificationLevel::UnsignedDevice, true) => true,
2360
2361 (VerificationLevel::None(_), true) => true,
2363
2364 (VerificationLevel::VerificationViolation, _)
2366 | (VerificationLevel::MismatchedSender, _)
2367 | (VerificationLevel::UnsignedDevice, false)
2368 | (VerificationLevel::None(_), false) => false,
2369 }
2370 }
2371
2372 TrustRequirement::CrossSigned => match verification_level {
2376 VerificationLevel::UnverifiedIdentity => true,
2377
2378 VerificationLevel::VerificationViolation
2379 | VerificationLevel::MismatchedSender
2380 | VerificationLevel::UnsignedDevice
2381 | VerificationLevel::None(_) => false,
2382 },
2383 };
2384
2385 if ok {
2386 Ok(())
2387 } else {
2388 Err(MegolmError::SenderIdentityNotTrusted(verification_level.clone()))
2389 }
2390 }
2391
2392 async fn get_inbound_group_session_or_error(
2397 &self,
2398 room_id: &RoomId,
2399 session_id: &str,
2400 ) -> MegolmResult<InboundGroupSession> {
2401 match self.store().get_inbound_group_session(room_id, session_id).await? {
2402 Some(session) => Ok(session),
2403 None => {
2404 let withheld_code = self
2405 .inner
2406 .store
2407 .get_withheld_info(room_id, session_id)
2408 .await?
2409 .map(|e| e.content.withheld_code());
2410 Err(MegolmError::MissingRoomKey(withheld_code))
2411 }
2412 }
2413 }
2414
2415 pub async fn try_decrypt_room_event(
2429 &self,
2430 raw_event: &Raw<EncryptedEvent>,
2431 room_id: &RoomId,
2432 decryption_settings: &DecryptionSettings,
2433 ) -> Result<RoomEventDecryptionResult, CryptoStoreError> {
2434 match self.decrypt_room_event_inner(raw_event, room_id, true, decryption_settings).await {
2435 Ok(decrypted) => Ok(RoomEventDecryptionResult::Decrypted(decrypted)),
2436 Err(err) => Ok(RoomEventDecryptionResult::UnableToDecrypt(megolm_error_to_utd_info(
2437 raw_event, err,
2438 )?)),
2439 }
2440 }
2441
2442 pub async fn decrypt_room_event(
2450 &self,
2451 event: &Raw<EncryptedEvent>,
2452 room_id: &RoomId,
2453 decryption_settings: &DecryptionSettings,
2454 ) -> MegolmResult<DecryptedRoomEvent> {
2455 self.decrypt_room_event_inner(event, room_id, true, decryption_settings).await
2456 }
2457
2458 #[instrument(name = "decrypt_room_event", skip_all, fields(?room_id, event_id, origin_server_ts, sender, algorithm, session_id, message_index, sender_key))]
2459 async fn decrypt_room_event_inner(
2460 &self,
2461 event: &Raw<EncryptedEvent>,
2462 room_id: &RoomId,
2463 decrypt_unsigned: bool,
2464 decryption_settings: &DecryptionSettings,
2465 ) -> MegolmResult<DecryptedRoomEvent> {
2466 let _timer = timer!(tracing::Level::TRACE, "_method");
2467
2468 let event = event.deserialize()?;
2469
2470 Span::current()
2471 .record("sender", debug(&event.sender))
2472 .record("event_id", debug(&event.event_id))
2473 .record(
2474 "origin_server_ts",
2475 timestamp_to_iso8601(event.origin_server_ts)
2476 .unwrap_or_else(|| "<out of range>".to_owned()),
2477 )
2478 .record("algorithm", debug(event.content.algorithm()));
2479
2480 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2481 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2482 Span::current().record("sender_key", debug(c.sender_key));
2483 c.into()
2484 }
2485 #[cfg(feature = "experimental-algorithms")]
2486 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2487 RoomEventEncryptionScheme::Unknown(_) => {
2488 warn!("Received an encrypted room event with an unsupported algorithm");
2489 return Err(EventError::UnsupportedAlgorithm.into());
2490 }
2491 };
2492
2493 Span::current().record("session_id", content.session_id());
2494 Span::current().record("message_index", content.message_index());
2495
2496 let result =
2497 self.decrypt_megolm_events(room_id, &event, &content, decryption_settings).await;
2498
2499 if let Err(e) = &result {
2500 #[cfg(feature = "automatic-room-key-forwarding")]
2501 match e {
2502 MegolmError::MissingRoomKey(_)
2505 | MegolmError::Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
2506 self.inner
2507 .key_request_machine
2508 .create_outgoing_key_request(room_id, &event)
2509 .await?;
2510 }
2511 _ => {}
2512 }
2513
2514 warn!("Failed to decrypt a room event: {e}");
2515 }
2516
2517 let (mut decrypted_event, encryption_info) = result?;
2518
2519 let mut unsigned_encryption_info = None;
2520 if decrypt_unsigned {
2521 unsigned_encryption_info = self
2523 .decrypt_unsigned_events(&mut decrypted_event, room_id, decryption_settings)
2524 .await;
2525 }
2526
2527 let decrypted_event =
2528 serde_json::from_value::<Raw<AnyTimelineEvent>>(decrypted_event.into())?;
2529
2530 #[cfg(feature = "experimental-encrypted-state-events")]
2531 self.verify_packed_state_key(&event, &decrypted_event)?;
2532
2533 Ok(DecryptedRoomEvent { event: decrypted_event, encryption_info, unsigned_encryption_info })
2534 }
2535
2536 #[cfg(feature = "experimental-encrypted-state-events")]
2553 fn verify_packed_state_key(
2554 &self,
2555 original: &EncryptedEvent,
2556 decrypted: &Raw<AnyTimelineEvent>,
2557 ) -> MegolmResult<()> {
2558 use serde::Deserialize;
2559
2560 #[derive(Deserialize)]
2562 struct PayloadDeserializationHelper {
2563 state_key: Option<String>,
2564 #[serde(rename = "type")]
2565 event_type: String,
2566 }
2567
2568 let PayloadDeserializationHelper {
2570 state_key: inner_state_key,
2571 event_type: inner_event_type,
2572 } = decrypted
2573 .deserialize_as_unchecked()
2574 .map_err(|_| MegolmError::StateKeyVerificationFailed)?;
2575
2576 let (raw_state_key, inner_state_key) = match (&original.state_key, &inner_state_key) {
2579 (Some(raw_state_key), Some(inner_state_key)) => (raw_state_key, inner_state_key),
2580 (None, None) => return Ok(()),
2581 _ => return Err(MegolmError::StateKeyVerificationFailed),
2582 };
2583
2584 let (outer_event_type, outer_state_key) =
2586 raw_state_key.split_once(":").ok_or(MegolmError::StateKeyVerificationFailed)?;
2587
2588 if outer_event_type != inner_event_type {
2590 return Err(MegolmError::StateKeyVerificationFailed);
2591 }
2592
2593 if outer_state_key != inner_state_key {
2595 return Err(MegolmError::StateKeyVerificationFailed);
2596 }
2597 Ok(())
2598 }
2599
2600 async fn decrypt_unsigned_events(
2610 &self,
2611 main_event: &mut JsonObject,
2612 room_id: &RoomId,
2613 decryption_settings: &DecryptionSettings,
2614 ) -> Option<BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>> {
2615 let unsigned = main_event.get_mut("unsigned")?.as_object_mut()?;
2616 let mut unsigned_encryption_info: Option<
2617 BTreeMap<UnsignedEventLocation, UnsignedDecryptionResult>,
2618 > = None;
2619
2620 let location = UnsignedEventLocation::RelationsReplace;
2622 let replace = location.find_mut(unsigned);
2623 if let Some(decryption_result) =
2624 self.decrypt_unsigned_event(replace, room_id, decryption_settings).await
2625 {
2626 unsigned_encryption_info
2627 .get_or_insert_with(Default::default)
2628 .insert(location, decryption_result);
2629 }
2630
2631 let location = UnsignedEventLocation::RelationsThreadLatestEvent;
2634 let thread_latest_event = location.find_mut(unsigned);
2635 if let Some(decryption_result) =
2636 self.decrypt_unsigned_event(thread_latest_event, room_id, decryption_settings).await
2637 {
2638 unsigned_encryption_info
2639 .get_or_insert_with(Default::default)
2640 .insert(location, decryption_result);
2641 }
2642
2643 unsigned_encryption_info
2644 }
2645
2646 fn decrypt_unsigned_event<'a>(
2654 &'a self,
2655 event: Option<&'a mut Value>,
2656 room_id: &'a RoomId,
2657 decryption_settings: &'a DecryptionSettings,
2658 ) -> BoxFuture<'a, Option<UnsignedDecryptionResult>> {
2659 Box::pin(async move {
2660 let event = event?;
2661
2662 let is_encrypted = event
2663 .get("type")
2664 .and_then(|type_| type_.as_str())
2665 .is_some_and(|s| s == "m.room.encrypted");
2666 if !is_encrypted {
2667 return None;
2668 }
2669
2670 let raw_event = serde_json::from_value(event.clone()).ok()?;
2671 match self
2672 .decrypt_room_event_inner(&raw_event, room_id, false, decryption_settings)
2673 .await
2674 {
2675 Ok(decrypted_event) => {
2676 *event = serde_json::to_value(decrypted_event.event).ok()?;
2678 Some(UnsignedDecryptionResult::Decrypted(decrypted_event.encryption_info))
2679 }
2680 Err(err) => {
2681 let utd_info = megolm_error_to_utd_info(&raw_event, err).ok()?;
2687 Some(UnsignedDecryptionResult::UnableToDecrypt(utd_info))
2688 }
2689 }
2690 })
2691 }
2692
2693 pub async fn is_room_key_available(
2700 &self,
2701 event: &Raw<EncryptedEvent>,
2702 room_id: &RoomId,
2703 ) -> Result<bool, CryptoStoreError> {
2704 let event = event.deserialize()?;
2705
2706 let (session_id, message_index) = match &event.content.scheme {
2707 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => {
2708 (&c.session_id, c.ciphertext.message_index())
2709 }
2710 #[cfg(feature = "experimental-algorithms")]
2711 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => {
2712 (&c.session_id, c.ciphertext.message_index())
2713 }
2714 RoomEventEncryptionScheme::Unknown(_) => {
2715 return Ok(false);
2718 }
2719 };
2720
2721 Ok(self
2724 .store()
2725 .get_inbound_group_session(room_id, session_id)
2726 .await?
2727 .filter(|s| s.first_known_index() <= message_index)
2728 .is_some())
2729 }
2730
2731 #[instrument(skip(self, event), fields(event_id, sender, session_id))]
2744 pub async fn get_room_event_encryption_info(
2745 &self,
2746 event: &Raw<EncryptedEvent>,
2747 room_id: &RoomId,
2748 ) -> MegolmResult<Arc<EncryptionInfo>> {
2749 let event = event.deserialize()?;
2750
2751 let content: SupportedEventEncryptionSchemes<'_> = match &event.content.scheme {
2752 RoomEventEncryptionScheme::MegolmV1AesSha2(c) => c.into(),
2753 #[cfg(feature = "experimental-algorithms")]
2754 RoomEventEncryptionScheme::MegolmV2AesSha2(c) => c.into(),
2755 RoomEventEncryptionScheme::Unknown(_) => {
2756 return Err(EventError::UnsupportedAlgorithm.into());
2757 }
2758 };
2759
2760 Span::current()
2761 .record("sender", debug(&event.sender))
2762 .record("event_id", debug(&event.event_id))
2763 .record("session_id", content.session_id());
2764
2765 self.get_session_encryption_info(room_id, content.session_id(), &event.sender).await
2766 }
2767
2768 pub async fn get_session_encryption_info(
2783 &self,
2784 room_id: &RoomId,
2785 session_id: &str,
2786 sender: &UserId,
2787 ) -> MegolmResult<Arc<EncryptionInfo>> {
2788 let session = self.get_inbound_group_session_or_error(room_id, session_id).await?;
2789 self.get_encryption_info(&session, sender).await
2790 }
2791
2792 pub async fn update_tracked_users(
2810 &self,
2811 users: impl IntoIterator<Item = &UserId>,
2812 ) -> StoreResult<()> {
2813 self.inner.identity_manager.update_tracked_users(users).await
2814 }
2815
2816 pub async fn mark_all_tracked_users_as_dirty(&self) -> StoreResult<()> {
2821 self.inner
2822 .identity_manager
2823 .mark_all_tracked_users_as_dirty(self.inner.store.cache().await?)
2824 .await
2825 }
2826
2827 async fn wait_if_user_pending(
2828 &self,
2829 user_id: &UserId,
2830 timeout: Option<Duration>,
2831 ) -> StoreResult<()> {
2832 if let Some(timeout) = timeout {
2833 let cache = self.store().cache().await?;
2834 self.inner
2835 .identity_manager
2836 .key_query_manager
2837 .wait_if_user_key_query_pending(cache, timeout, user_id)
2838 .await?;
2839 }
2840 Ok(())
2841 }
2842
2843 #[instrument(skip(self))]
2871 pub async fn get_device(
2872 &self,
2873 user_id: &UserId,
2874 device_id: &DeviceId,
2875 timeout: Option<Duration>,
2876 ) -> StoreResult<Option<Device>> {
2877 self.wait_if_user_pending(user_id, timeout).await?;
2878 self.store().get_device(user_id, device_id).await
2879 }
2880
2881 #[instrument(skip(self))]
2894 pub async fn get_identity(
2895 &self,
2896 user_id: &UserId,
2897 timeout: Option<Duration>,
2898 ) -> StoreResult<Option<UserIdentity>> {
2899 self.wait_if_user_pending(user_id, timeout).await?;
2900 self.store().get_identity(user_id).await
2901 }
2902
2903 #[instrument(skip(self))]
2929 pub async fn get_user_devices(
2930 &self,
2931 user_id: &UserId,
2932 timeout: Option<Duration>,
2933 ) -> StoreResult<UserDevices> {
2934 self.wait_if_user_pending(user_id, timeout).await?;
2935 self.store().get_user_devices(user_id).await
2936 }
2937
2938 pub async fn cross_signing_status(&self) -> CrossSigningStatus {
2943 self.inner.user_identity.lock().await.status().await
2944 }
2945
2946 pub async fn export_cross_signing_keys(&self) -> StoreResult<Option<CrossSigningKeyExport>> {
2954 let master_key = self.store().export_secret(&SecretName::CrossSigningMasterKey).await?;
2955 let self_signing_key =
2956 self.store().export_secret(&SecretName::CrossSigningSelfSigningKey).await?;
2957 let user_signing_key =
2958 self.store().export_secret(&SecretName::CrossSigningUserSigningKey).await?;
2959
2960 Ok(if master_key.is_none() && self_signing_key.is_none() && user_signing_key.is_none() {
2961 None
2962 } else {
2963 Some(CrossSigningKeyExport { master_key, self_signing_key, user_signing_key })
2964 })
2965 }
2966
2967 pub async fn import_cross_signing_keys(
2972 &self,
2973 export: CrossSigningKeyExport,
2974 ) -> Result<CrossSigningStatus, SecretImportError> {
2975 self.store().import_cross_signing_keys(export).await
2976 }
2977
2978 async fn sign_with_master_key(
2979 &self,
2980 message: &str,
2981 ) -> Result<(OwnedDeviceKeyId, Ed25519Signature), SignatureError> {
2982 let identity = &*self.inner.user_identity.lock().await;
2983 let key_id = identity.master_key_id().await.ok_or(SignatureError::MissingSigningKey)?;
2984
2985 let signature = identity.sign(message).await?;
2986
2987 Ok((key_id, signature))
2988 }
2989
2990 pub async fn sign(&self, message: &str) -> Result<Signatures, CryptoStoreError> {
2996 let mut signatures = Signatures::new();
2997
2998 {
2999 let cache = self.inner.store.cache().await?;
3000 let account = cache.account().await?;
3001 let key_id = account.signing_key_id();
3002 let signature = account.sign(message);
3003 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
3004 }
3005
3006 match self.sign_with_master_key(message).await {
3007 Ok((key_id, signature)) => {
3008 signatures.add_signature(self.user_id().to_owned(), key_id, signature);
3009 }
3010 Err(e) => {
3011 warn!(error = ?e, "Couldn't sign the message using the cross signing master key")
3012 }
3013 }
3014
3015 Ok(signatures)
3016 }
3017
3018 pub fn backup_machine(&self) -> &BackupMachine {
3023 &self.inner.backup_machine
3024 }
3025
3026 pub async fn initialize_crypto_store_generation(
3030 &self,
3031 generation: &Mutex<Option<u64>>,
3032 ) -> StoreResult<()> {
3033 let mut gen_guard = generation.lock().await;
3036
3037 let prev_generation =
3038 self.inner.store.get_custom_value(Self::CURRENT_GENERATION_STORE_KEY).await?;
3039
3040 let generation = match prev_generation {
3041 Some(val) => {
3042 u64::from_le_bytes(val.try_into().map_err(|_| {
3046 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
3047 })?)
3048 .wrapping_add(1)
3049 }
3050 None => 0,
3051 };
3052
3053 tracing::debug!("Initialising crypto store generation at {generation}");
3054
3055 self.inner
3056 .store
3057 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, generation.to_le_bytes().to_vec())
3058 .await?;
3059
3060 *gen_guard = Some(generation);
3061
3062 Ok(())
3063 }
3064
3065 pub async fn maintain_crypto_store_generation(
3090 &'_ self,
3091 generation: &Mutex<Option<u64>>,
3092 ) -> StoreResult<(bool, u64)> {
3093 let mut gen_guard = generation.lock().await;
3094
3095 let actual_gen = self
3102 .inner
3103 .store
3104 .get_custom_value(Self::CURRENT_GENERATION_STORE_KEY)
3105 .await?
3106 .ok_or_else(|| {
3107 CryptoStoreError::InvalidLockGeneration("counter missing in store".to_owned())
3108 })?;
3109
3110 let actual_gen =
3111 u64::from_le_bytes(actual_gen.try_into().map_err(|_| {
3112 CryptoStoreError::InvalidLockGeneration("invalid format".to_owned())
3113 })?);
3114
3115 let new_gen = match gen_guard.as_ref() {
3116 Some(expected_gen) => {
3117 if actual_gen == *expected_gen {
3118 return Ok((false, actual_gen));
3119 }
3120 actual_gen.max(*expected_gen).wrapping_add(1)
3122 }
3123 None => {
3124 actual_gen.wrapping_add(1)
3128 }
3129 };
3130
3131 tracing::debug!(
3132 "Crypto store generation mismatch: previously known was {:?}, actual is {:?}, next is {}",
3133 *gen_guard,
3134 actual_gen,
3135 new_gen
3136 );
3137
3138 *gen_guard = Some(new_gen);
3140
3141 self.inner
3143 .store
3144 .set_custom_value(Self::CURRENT_GENERATION_STORE_KEY, new_gen.to_le_bytes().to_vec())
3145 .await?;
3146
3147 Ok((true, new_gen))
3148 }
3149
3150 pub fn dehydrated_devices(&self) -> DehydratedDevices {
3152 DehydratedDevices { inner: self.to_owned() }
3153 }
3154
3155 pub async fn room_settings(&self, room_id: &RoomId) -> StoreResult<Option<RoomSettings>> {
3160 self.inner.store.get_room_settings(room_id).await
3163 }
3164
3165 pub async fn set_room_settings(
3176 &self,
3177 room_id: &RoomId,
3178 new_settings: &RoomSettings,
3179 ) -> Result<(), SetRoomSettingsError> {
3180 let store = &self.inner.store;
3181
3182 let _store_transaction = store.transaction().await;
3187
3188 let old_settings = store.get_room_settings(room_id).await?;
3189
3190 if let Some(old_settings) = old_settings {
3205 if old_settings != *new_settings {
3206 return Err(SetRoomSettingsError::EncryptionDowngrade);
3207 } else {
3208 return Ok(());
3210 }
3211 }
3212
3213 match new_settings.algorithm {
3215 EventEncryptionAlgorithm::MegolmV1AesSha2 => (),
3216
3217 #[cfg(feature = "experimental-algorithms")]
3218 EventEncryptionAlgorithm::MegolmV2AesSha2 => (),
3219
3220 _ => {
3221 warn!(
3222 ?room_id,
3223 "Rejecting invalid encryption algorithm {}", new_settings.algorithm
3224 );
3225 return Err(SetRoomSettingsError::InvalidSettings);
3226 }
3227 }
3228
3229 store
3231 .save_changes(Changes {
3232 room_settings: HashMap::from([(room_id.to_owned(), new_settings.clone())]),
3233 ..Default::default()
3234 })
3235 .await?;
3236
3237 Ok(())
3238 }
3239
3240 #[cfg(any(feature = "testing", test))]
3244 pub fn same_as(&self, other: &OlmMachine) -> bool {
3245 Arc::ptr_eq(&self.inner, &other.inner)
3246 }
3247
3248 #[cfg(any(feature = "testing", test))]
3250 pub async fn uploaded_key_count(&self) -> Result<u64, CryptoStoreError> {
3251 let cache = self.inner.store.cache().await?;
3252 let account = cache.account().await?;
3253 Ok(account.uploaded_key_count())
3254 }
3255
3256 #[cfg(test)]
3258 pub(crate) fn identity_manager(&self) -> &IdentityManager {
3259 &self.inner.identity_manager
3260 }
3261
3262 #[cfg(test)]
3264 pub(crate) fn key_for_has_migrated_verification_latch() -> &'static str {
3265 Self::HAS_MIGRATED_VERIFICATION_LATCH
3266 }
3267}
3268
3269fn sender_data_to_verification_state(
3270 sender_data: SenderData,
3271 session_has_been_imported: bool,
3272) -> (VerificationState, Option<OwnedDeviceId>) {
3273 match sender_data {
3274 SenderData::UnknownDevice { owner_check_failed: false, .. } => {
3275 let device_link_problem = if session_has_been_imported {
3276 DeviceLinkProblem::InsecureSource
3277 } else {
3278 DeviceLinkProblem::MissingDevice
3279 };
3280
3281 (VerificationState::Unverified(VerificationLevel::None(device_link_problem)), None)
3282 }
3283 SenderData::UnknownDevice { owner_check_failed: true, .. } => (
3284 VerificationState::Unverified(VerificationLevel::None(
3285 DeviceLinkProblem::InsecureSource,
3286 )),
3287 None,
3288 ),
3289 SenderData::DeviceInfo { device_keys, .. } => (
3290 VerificationState::Unverified(VerificationLevel::UnsignedDevice),
3291 Some(device_keys.device_id),
3292 ),
3293 SenderData::VerificationViolation(KnownSenderData { device_id, .. }) => {
3294 (VerificationState::Unverified(VerificationLevel::VerificationViolation), device_id)
3295 }
3296 SenderData::SenderUnverified(KnownSenderData { device_id, .. }) => {
3297 (VerificationState::Unverified(VerificationLevel::UnverifiedIdentity), device_id)
3298 }
3299 SenderData::SenderVerified(KnownSenderData { device_id, .. }) => {
3300 (VerificationState::Verified, device_id)
3301 }
3302 }
3303}
3304
3305#[derive(Debug, Clone)]
3308pub struct CrossSigningBootstrapRequests {
3309 pub upload_keys_req: Option<OutgoingRequest>,
3316
3317 pub upload_signing_keys_req: UploadSigningKeysRequest,
3321
3322 pub upload_signatures_req: UploadSignaturesRequest,
3327}
3328
3329#[derive(Debug, thiserror::Error)]
3335pub enum BootstrapCrossSigningError {
3336 #[error(transparent)]
3338 CryptoStore(#[from] CryptoStoreError),
3339
3340 #[error(transparent)]
3342 Signature(#[from] SignatureError),
3343}
3344
3345#[derive(Debug)]
3348pub struct EncryptionSyncChanges<'a> {
3349 pub to_device_events: Vec<Raw<AnyToDeviceEvent>>,
3351 pub changed_devices: &'a DeviceLists,
3354 pub one_time_keys_counts: &'a BTreeMap<OneTimeKeyAlgorithm, UInt>,
3356 pub unused_fallback_keys: Option<&'a [OneTimeKeyAlgorithm]>,
3358 pub next_batch_token: Option<String>,
3360}
3361
3362fn megolm_error_to_utd_info(
3370 raw_event: &Raw<EncryptedEvent>,
3371 error: MegolmError,
3372) -> Result<UnableToDecryptInfo, CryptoStoreError> {
3373 use MegolmError::*;
3374 let reason = match error {
3375 EventError(_) => UnableToDecryptReason::MalformedEncryptedEvent,
3376 Decode(_) => UnableToDecryptReason::MalformedEncryptedEvent,
3377 MissingRoomKey(maybe_withheld) => {
3378 UnableToDecryptReason::MissingMegolmSession { withheld_code: maybe_withheld }
3379 }
3380 Decryption(DecryptionError::UnknownMessageIndex(_, _)) => {
3381 UnableToDecryptReason::UnknownMegolmMessageIndex
3382 }
3383 Decryption(_) => UnableToDecryptReason::MegolmDecryptionFailure,
3384 JsonError(_) => UnableToDecryptReason::PayloadDeserializationFailure,
3385 MismatchedIdentityKeys(_) => UnableToDecryptReason::MismatchedIdentityKeys,
3386 SenderIdentityNotTrusted(level) => UnableToDecryptReason::SenderIdentityNotTrusted(level),
3387 #[cfg(feature = "experimental-encrypted-state-events")]
3388 StateKeyVerificationFailed => UnableToDecryptReason::StateKeyVerificationFailed,
3389
3390 Store(error) => Err(error)?,
3393 };
3394
3395 let session_id = raw_event.deserialize().ok().and_then(|ev| match ev.content.scheme {
3396 RoomEventEncryptionScheme::MegolmV1AesSha2(s) => Some(s.session_id),
3397 #[cfg(feature = "experimental-algorithms")]
3398 RoomEventEncryptionScheme::MegolmV2AesSha2(s) => Some(s.session_id),
3399 RoomEventEncryptionScheme::Unknown(_) => None,
3400 });
3401
3402 Ok(UnableToDecryptInfo { session_id, reason })
3403}
3404
3405#[derive(Debug, thiserror::Error)]
3414pub(crate) enum DecryptToDeviceError {
3415 #[error("An Olm error occurred meaning we failed to decrypt the event")]
3416 OlmError(#[from] OlmError),
3417
3418 #[error("The event was sent from a dehydrated device")]
3419 FromDehydratedDevice,
3420}
3421
3422impl From<CryptoStoreError> for DecryptToDeviceError {
3423 fn from(value: CryptoStoreError) -> Self {
3424 Self::OlmError(value.into())
3425 }
3426}
3427
3428#[cfg(test)]
3429impl From<DecryptToDeviceError> for OlmError {
3430 fn from(value: DecryptToDeviceError) -> Self {
3433 match value {
3434 DecryptToDeviceError::OlmError(olm_error) => olm_error,
3435 DecryptToDeviceError::FromDehydratedDevice => {
3436 panic!("Expected an OlmError but found FromDehydratedDevice")
3437 }
3438 }
3439 }
3440}
3441
3442#[cfg(test)]
3443pub(crate) mod test_helpers;
3444
3445#[cfg(test)]
3446pub(crate) mod tests;