1use std::{collections::HashMap, fmt, sync::Arc};
16
17use async_trait::async_trait;
18use matrix_sdk_common::{AsyncTraitDeps, cross_process_lock::CrossProcessLockGeneration};
19use ruma::{
20 DeviceId, OwnedDeviceId, RoomId, TransactionId, UserId, events::secret::request::SecretName,
21};
22use vodozemac::Curve25519PublicKey;
23
24use super::{
25 CryptoStoreError, Result,
26 types::{
27 BackupKeys, Changes, DehydratedDeviceKey, PendingChanges, RoomKeyCounts, RoomSettings,
28 StoredRoomKeyBundleData, TrackedUser,
29 },
30};
31#[cfg(doc)]
32use crate::olm::SenderData;
33use crate::{
34 Account, DeviceData, GossipRequest, GossippedSecret, SecretInfo, UserIdentityData,
35 olm::{
36 InboundGroupSession, OlmMessageHash, OutboundGroupSession, PrivateCrossSigningIdentity,
37 SenderDataType, Session,
38 },
39 store::types::{RoomKeyWithheldEntry, RoomPendingKeyBundleDetails},
40};
41
42#[cfg_attr(target_family = "wasm", async_trait(?Send))]
45#[cfg_attr(not(target_family = "wasm"), async_trait)]
46pub trait CryptoStore: AsyncTraitDeps {
47 type Error: fmt::Debug + Into<CryptoStoreError>;
49
50 async fn load_account(&self) -> Result<Option<Account>, Self::Error>;
52
53 async fn load_identity(&self) -> Result<Option<PrivateCrossSigningIdentity>, Self::Error>;
55
56 async fn save_changes(&self, changes: Changes) -> Result<(), Self::Error>;
62
63 async fn save_pending_changes(&self, changes: PendingChanges) -> Result<(), Self::Error>;
72
73 async fn save_inbound_group_sessions(
84 &self,
85 sessions: Vec<InboundGroupSession>,
86 backed_up_to_version: Option<&str>,
87 ) -> Result<(), Self::Error>;
88
89 async fn get_sessions(&self, sender_key: &str) -> Result<Option<Vec<Session>>, Self::Error>;
95
96 async fn get_inbound_group_session(
105 &self,
106 room_id: &RoomId,
107 session_id: &str,
108 ) -> Result<Option<InboundGroupSession>, Self::Error>;
109
110 async fn get_withheld_info(
116 &self,
117 room_id: &RoomId,
118 session_id: &str,
119 ) -> Result<Option<RoomKeyWithheldEntry>, Self::Error>;
120
121 async fn get_withheld_sessions_by_room_id(
130 &self,
131 room_id: &RoomId,
132 ) -> Result<Vec<RoomKeyWithheldEntry>, Self::Error>;
133
134 async fn get_inbound_group_sessions(&self) -> Result<Vec<InboundGroupSession>, Self::Error>;
136
137 async fn inbound_group_session_counts(
140 &self,
141 backup_version: Option<&str>,
142 ) -> Result<RoomKeyCounts, Self::Error>;
143
144 async fn get_inbound_group_sessions_by_room_id(
149 &self,
150 room_id: &RoomId,
151 ) -> Result<Vec<InboundGroupSession>, Self::Error>;
152
153 async fn get_inbound_group_sessions_for_device_batch(
180 &self,
181 curve_key: Curve25519PublicKey,
182 sender_data_type: SenderDataType,
183 after_session_id: Option<String>,
184 limit: usize,
185 ) -> Result<Vec<InboundGroupSession>, Self::Error>;
186
187 async fn inbound_group_sessions_for_backup(
195 &self,
196 backup_version: &str,
197 limit: usize,
198 ) -> Result<Vec<InboundGroupSession>, Self::Error>;
199
200 async fn mark_inbound_group_sessions_as_backed_up(
206 &self,
207 backup_version: &str,
208 room_and_session_ids: &[(&RoomId, &str)],
209 ) -> Result<(), Self::Error>;
210
211 async fn reset_backup_state(&self) -> Result<(), Self::Error>;
220
221 async fn load_backup_keys(&self) -> Result<BackupKeys, Self::Error>;
223
224 async fn load_dehydrated_device_pickle_key(
226 &self,
227 ) -> Result<Option<DehydratedDeviceKey>, Self::Error>;
228
229 async fn delete_dehydrated_device_pickle_key(&self) -> Result<(), Self::Error>;
231
232 async fn get_outbound_group_session(
235 &self,
236 room_id: &RoomId,
237 ) -> Result<Option<OutboundGroupSession>, Self::Error>;
238
239 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>, Self::Error>;
242
243 async fn save_tracked_users(&self, users: &[(&UserId, bool)]) -> Result<(), Self::Error>;
248
249 async fn get_device(
257 &self,
258 user_id: &UserId,
259 device_id: &DeviceId,
260 ) -> Result<Option<DeviceData>, Self::Error>;
261
262 async fn get_user_devices(
268 &self,
269 user_id: &UserId,
270 ) -> Result<HashMap<OwnedDeviceId, DeviceData>, Self::Error>;
271
272 async fn get_own_device(&self) -> Result<DeviceData, Self::Error>;
277
278 async fn get_user_identity(
284 &self,
285 user_id: &UserId,
286 ) -> Result<Option<UserIdentityData>, Self::Error>;
287
288 async fn is_message_known(&self, message_hash: &OlmMessageHash) -> Result<bool, Self::Error>;
290
291 async fn get_outgoing_secret_requests(
299 &self,
300 request_id: &TransactionId,
301 ) -> Result<Option<GossipRequest>, Self::Error>;
302
303 async fn get_secret_request_by_info(
310 &self,
311 secret_info: &SecretInfo,
312 ) -> Result<Option<GossipRequest>, Self::Error>;
313
314 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>, Self::Error>;
316
317 async fn delete_outgoing_secret_requests(
325 &self,
326 request_id: &TransactionId,
327 ) -> Result<(), Self::Error>;
328
329 async fn get_secrets_from_inbox(
332 &self,
333 secret_name: &SecretName,
334 ) -> Result<Vec<GossippedSecret>, Self::Error>;
335
336 async fn delete_secrets_from_inbox(&self, secret_name: &SecretName) -> Result<(), Self::Error>;
339
340 async fn get_room_settings(
347 &self,
348 room_id: &RoomId,
349 ) -> Result<Option<RoomSettings>, Self::Error>;
350
351 async fn get_received_room_key_bundle_data(
354 &self,
355 room_id: &RoomId,
356 user_id: &UserId,
357 ) -> Result<Option<StoredRoomKeyBundleData>, Self::Error>;
358
359 async fn get_pending_key_bundle_details_for_room(
362 &self,
363 room_id: &RoomId,
364 ) -> Result<Option<RoomPendingKeyBundleDetails>, Self::Error>;
365
366 async fn get_all_rooms_pending_key_bundles(
369 &self,
370 ) -> Result<Vec<RoomPendingKeyBundleDetails>, Self::Error>;
371
372 async fn has_downloaded_all_room_keys(&self, room_id: &RoomId) -> Result<bool, Self::Error>;
375
376 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>, Self::Error>;
382
383 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<(), Self::Error>;
391
392 async fn remove_custom_value(&self, key: &str) -> Result<(), Self::Error>;
398
399 async fn try_take_leased_lock(
411 &self,
412 lease_duration_ms: u32,
413 key: &str,
414 holder: &str,
415 ) -> Result<Option<CrossProcessLockGeneration>, Self::Error>;
416
417 async fn next_batch_token(&self) -> Result<Option<String>, Self::Error>;
419
420 async fn get_size(&self) -> Result<Option<usize>, Self::Error>;
422}
423
424#[repr(transparent)]
425struct EraseCryptoStoreError<T>(T);
426
427#[cfg(not(tarpaulin_include))]
428impl<T: fmt::Debug> fmt::Debug for EraseCryptoStoreError<T> {
429 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
430 self.0.fmt(f)
431 }
432}
433
434#[cfg_attr(target_family = "wasm", async_trait(?Send))]
435#[cfg_attr(not(target_family = "wasm"), async_trait)]
436impl<T: CryptoStore> CryptoStore for EraseCryptoStoreError<T> {
437 type Error = CryptoStoreError;
438
439 async fn load_account(&self) -> Result<Option<Account>> {
440 self.0.load_account().await.map_err(Into::into)
441 }
442
443 async fn load_identity(&self) -> Result<Option<PrivateCrossSigningIdentity>> {
444 self.0.load_identity().await.map_err(Into::into)
445 }
446
447 async fn save_changes(&self, changes: Changes) -> Result<()> {
448 self.0.save_changes(changes).await.map_err(Into::into)
449 }
450
451 async fn save_pending_changes(&self, changes: PendingChanges) -> Result<()> {
452 self.0.save_pending_changes(changes).await.map_err(Into::into)
453 }
454
455 async fn save_inbound_group_sessions(
456 &self,
457 sessions: Vec<InboundGroupSession>,
458 backed_up_to_version: Option<&str>,
459 ) -> Result<()> {
460 self.0.save_inbound_group_sessions(sessions, backed_up_to_version).await.map_err(Into::into)
461 }
462
463 async fn get_sessions(&self, sender_key: &str) -> Result<Option<Vec<Session>>> {
464 self.0.get_sessions(sender_key).await.map_err(Into::into)
465 }
466
467 async fn get_inbound_group_session(
468 &self,
469 room_id: &RoomId,
470 session_id: &str,
471 ) -> Result<Option<InboundGroupSession>> {
472 self.0.get_inbound_group_session(room_id, session_id).await.map_err(Into::into)
473 }
474
475 async fn get_inbound_group_sessions(&self) -> Result<Vec<InboundGroupSession>> {
476 self.0.get_inbound_group_sessions().await.map_err(Into::into)
477 }
478
479 async fn get_inbound_group_sessions_by_room_id(
480 &self,
481 room_id: &RoomId,
482 ) -> Result<Vec<InboundGroupSession>> {
483 self.0.get_inbound_group_sessions_by_room_id(room_id).await.map_err(Into::into)
484 }
485
486 async fn get_inbound_group_sessions_for_device_batch(
487 &self,
488 curve_key: Curve25519PublicKey,
489 sender_data_type: SenderDataType,
490 after_session_id: Option<String>,
491 limit: usize,
492 ) -> Result<Vec<InboundGroupSession>> {
493 self.0
494 .get_inbound_group_sessions_for_device_batch(
495 curve_key,
496 sender_data_type,
497 after_session_id,
498 limit,
499 )
500 .await
501 .map_err(Into::into)
502 }
503
504 async fn inbound_group_session_counts(
505 &self,
506 backup_version: Option<&str>,
507 ) -> Result<RoomKeyCounts> {
508 self.0.inbound_group_session_counts(backup_version).await.map_err(Into::into)
509 }
510 async fn inbound_group_sessions_for_backup(
511 &self,
512 backup_version: &str,
513 limit: usize,
514 ) -> Result<Vec<InboundGroupSession>> {
515 self.0.inbound_group_sessions_for_backup(backup_version, limit).await.map_err(Into::into)
516 }
517
518 async fn mark_inbound_group_sessions_as_backed_up(
519 &self,
520 backup_version: &str,
521 room_and_session_ids: &[(&RoomId, &str)],
522 ) -> Result<()> {
523 self.0
524 .mark_inbound_group_sessions_as_backed_up(backup_version, room_and_session_ids)
525 .await
526 .map_err(Into::into)
527 }
528
529 async fn reset_backup_state(&self) -> Result<()> {
530 self.0.reset_backup_state().await.map_err(Into::into)
531 }
532
533 async fn load_backup_keys(&self) -> Result<BackupKeys> {
534 self.0.load_backup_keys().await.map_err(Into::into)
535 }
536
537 async fn load_dehydrated_device_pickle_key(&self) -> Result<Option<DehydratedDeviceKey>> {
538 self.0.load_dehydrated_device_pickle_key().await.map_err(Into::into)
539 }
540
541 async fn delete_dehydrated_device_pickle_key(&self) -> Result<(), Self::Error> {
542 self.0.delete_dehydrated_device_pickle_key().await.map_err(Into::into)
543 }
544
545 async fn get_outbound_group_session(
546 &self,
547 room_id: &RoomId,
548 ) -> Result<Option<OutboundGroupSession>> {
549 self.0.get_outbound_group_session(room_id).await.map_err(Into::into)
550 }
551
552 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>> {
553 self.0.load_tracked_users().await.map_err(Into::into)
554 }
555
556 async fn save_tracked_users(&self, users: &[(&UserId, bool)]) -> Result<()> {
557 self.0.save_tracked_users(users).await.map_err(Into::into)
558 }
559
560 async fn get_device(
561 &self,
562 user_id: &UserId,
563 device_id: &DeviceId,
564 ) -> Result<Option<DeviceData>> {
565 self.0.get_device(user_id, device_id).await.map_err(Into::into)
566 }
567
568 async fn get_user_devices(
569 &self,
570 user_id: &UserId,
571 ) -> Result<HashMap<OwnedDeviceId, DeviceData>> {
572 self.0.get_user_devices(user_id).await.map_err(Into::into)
573 }
574
575 async fn get_own_device(&self) -> Result<DeviceData> {
576 self.0.get_own_device().await.map_err(Into::into)
577 }
578
579 async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<UserIdentityData>> {
580 self.0.get_user_identity(user_id).await.map_err(Into::into)
581 }
582
583 async fn is_message_known(&self, message_hash: &OlmMessageHash) -> Result<bool> {
584 self.0.is_message_known(message_hash).await.map_err(Into::into)
585 }
586
587 async fn get_outgoing_secret_requests(
588 &self,
589 request_id: &TransactionId,
590 ) -> Result<Option<GossipRequest>> {
591 self.0.get_outgoing_secret_requests(request_id).await.map_err(Into::into)
592 }
593
594 async fn get_secret_request_by_info(
595 &self,
596 secret_info: &SecretInfo,
597 ) -> Result<Option<GossipRequest>> {
598 self.0.get_secret_request_by_info(secret_info).await.map_err(Into::into)
599 }
600
601 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>> {
602 self.0.get_unsent_secret_requests().await.map_err(Into::into)
603 }
604
605 async fn delete_outgoing_secret_requests(&self, request_id: &TransactionId) -> Result<()> {
606 self.0.delete_outgoing_secret_requests(request_id).await.map_err(Into::into)
607 }
608
609 async fn get_secrets_from_inbox(
610 &self,
611 secret_name: &SecretName,
612 ) -> Result<Vec<GossippedSecret>> {
613 self.0.get_secrets_from_inbox(secret_name).await.map_err(Into::into)
614 }
615
616 async fn delete_secrets_from_inbox(&self, secret_name: &SecretName) -> Result<()> {
617 self.0.delete_secrets_from_inbox(secret_name).await.map_err(Into::into)
618 }
619
620 async fn get_withheld_info(
621 &self,
622 room_id: &RoomId,
623 session_id: &str,
624 ) -> Result<Option<RoomKeyWithheldEntry>, Self::Error> {
625 self.0.get_withheld_info(room_id, session_id).await.map_err(Into::into)
626 }
627
628 async fn get_withheld_sessions_by_room_id(
629 &self,
630 room_id: &RoomId,
631 ) -> Result<Vec<RoomKeyWithheldEntry>, Self::Error> {
632 self.0.get_withheld_sessions_by_room_id(room_id).await.map_err(Into::into)
633 }
634
635 async fn get_room_settings(&self, room_id: &RoomId) -> Result<Option<RoomSettings>> {
636 self.0.get_room_settings(room_id).await.map_err(Into::into)
637 }
638
639 async fn get_received_room_key_bundle_data(
640 &self,
641 room_id: &RoomId,
642 user_id: &UserId,
643 ) -> Result<Option<StoredRoomKeyBundleData>> {
644 self.0.get_received_room_key_bundle_data(room_id, user_id).await.map_err(Into::into)
645 }
646
647 async fn has_downloaded_all_room_keys(&self, room_id: &RoomId) -> Result<bool, Self::Error> {
648 self.0.has_downloaded_all_room_keys(room_id).await.map_err(Into::into)
649 }
650
651 async fn get_pending_key_bundle_details_for_room(
652 &self,
653 room_id: &RoomId,
654 ) -> Result<Option<RoomPendingKeyBundleDetails>, Self::Error> {
655 self.0.get_pending_key_bundle_details_for_room(room_id).await.map_err(Into::into)
656 }
657
658 async fn get_all_rooms_pending_key_bundles(
659 &self,
660 ) -> Result<Vec<RoomPendingKeyBundleDetails>, Self::Error> {
661 self.0.get_all_rooms_pending_key_bundles().await.map_err(Into::into)
662 }
663
664 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>, Self::Error> {
665 self.0.get_custom_value(key).await.map_err(Into::into)
666 }
667
668 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<(), Self::Error> {
669 self.0.set_custom_value(key, value).await.map_err(Into::into)
670 }
671
672 async fn remove_custom_value(&self, key: &str) -> Result<(), Self::Error> {
673 self.0.remove_custom_value(key).await.map_err(Into::into)
674 }
675
676 async fn try_take_leased_lock(
677 &self,
678 lease_duration_ms: u32,
679 key: &str,
680 holder: &str,
681 ) -> Result<Option<CrossProcessLockGeneration>, Self::Error> {
682 self.0.try_take_leased_lock(lease_duration_ms, key, holder).await.map_err(Into::into)
683 }
684
685 async fn next_batch_token(&self) -> Result<Option<String>, Self::Error> {
686 self.0.next_batch_token().await.map_err(Into::into)
687 }
688
689 async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
690 self.0.get_size().await.map_err(Into::into)
691 }
692}
693
694pub type DynCryptoStore = dyn CryptoStore<Error = CryptoStoreError>;
696
697pub trait IntoCryptoStore {
703 #[doc(hidden)]
704 fn into_crypto_store(self) -> Arc<DynCryptoStore>;
705}
706
707impl<T> IntoCryptoStore for T
708where
709 T: CryptoStore + 'static,
710{
711 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
712 Arc::new(EraseCryptoStoreError(self))
713 }
714}
715
716impl<T> IntoCryptoStore for Arc<T>
719where
720 T: CryptoStore + 'static,
721{
722 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
723 let ptr: *const T = Arc::into_raw(self);
724 let ptr_erased = ptr as *const EraseCryptoStoreError<T>;
725 unsafe { Arc::from_raw(ptr_erased) }
728 }
729}
730
731impl IntoCryptoStore for Arc<DynCryptoStore> {
732 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
733 self
734 }
735}