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;
23use zeroize::Zeroizing;
24
25use super::{
26 CryptoStoreError, Result,
27 types::{
28 BackupKeys, Changes, DehydratedDeviceKey, PendingChanges, RoomKeyCounts, RoomSettings,
29 StoredRoomKeyBundleData, TrackedUser,
30 },
31};
32#[cfg(doc)]
33use crate::olm::SenderData;
34use crate::{
35 Account, DeviceData, GossipRequest, SecretInfo, UserIdentityData,
36 olm::{
37 InboundGroupSession, OlmMessageHash, OutboundGroupSession, PrivateCrossSigningIdentity,
38 SenderDataType, Session,
39 },
40 store::types::{RoomKeyWithheldEntry, RoomPendingKeyBundleDetails},
41};
42
43#[cfg_attr(target_family = "wasm", async_trait(?Send))]
46#[cfg_attr(not(target_family = "wasm"), async_trait)]
47pub trait CryptoStore: AsyncTraitDeps {
48 type Error: fmt::Debug + Into<CryptoStoreError>;
50
51 async fn load_account(&self) -> Result<Option<Account>, Self::Error>;
53
54 async fn load_identity(&self) -> Result<Option<PrivateCrossSigningIdentity>, Self::Error>;
56
57 async fn save_changes(&self, changes: Changes) -> Result<(), Self::Error>;
63
64 async fn save_pending_changes(&self, changes: PendingChanges) -> Result<(), Self::Error>;
74
75 async fn save_inbound_group_sessions(
86 &self,
87 sessions: Vec<InboundGroupSession>,
88 backed_up_to_version: Option<&str>,
89 ) -> Result<(), Self::Error>;
90
91 async fn get_sessions(&self, sender_key: &str) -> Result<Option<Vec<Session>>, Self::Error>;
97
98 async fn get_inbound_group_session(
106 &self,
107 room_id: &RoomId,
108 session_id: &str,
109 ) -> Result<Option<InboundGroupSession>, Self::Error>;
110
111 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(
131 &self,
132 room_id: &RoomId,
133 ) -> Result<Vec<RoomKeyWithheldEntry>, Self::Error>;
134
135 async fn get_inbound_group_sessions(&self) -> Result<Vec<InboundGroupSession>, Self::Error>;
137
138 async fn inbound_group_session_counts(
141 &self,
142 backup_version: Option<&str>,
143 ) -> Result<RoomKeyCounts, Self::Error>;
144
145 async fn get_inbound_group_sessions_by_room_id(
151 &self,
152 room_id: &RoomId,
153 ) -> Result<Vec<InboundGroupSession>, Self::Error>;
154
155 async fn get_inbound_group_sessions_for_device_batch(
182 &self,
183 curve_key: Curve25519PublicKey,
184 sender_data_type: SenderDataType,
185 after_session_id: Option<String>,
186 limit: usize,
187 ) -> Result<Vec<InboundGroupSession>, Self::Error>;
188
189 async fn inbound_group_sessions_for_backup(
197 &self,
198 backup_version: &str,
199 limit: usize,
200 ) -> Result<Vec<InboundGroupSession>, Self::Error>;
201
202 async fn mark_inbound_group_sessions_as_backed_up(
208 &self,
209 backup_version: &str,
210 room_and_session_ids: &[(&RoomId, &str)],
211 ) -> Result<(), Self::Error>;
212
213 async fn reset_backup_state(&self) -> Result<(), Self::Error>;
222
223 async fn load_backup_keys(&self) -> Result<BackupKeys, Self::Error>;
225
226 async fn load_dehydrated_device_pickle_key(
228 &self,
229 ) -> Result<Option<DehydratedDeviceKey>, Self::Error>;
230
231 async fn delete_dehydrated_device_pickle_key(&self) -> Result<(), Self::Error>;
233
234 async fn get_outbound_group_session(
237 &self,
238 room_id: &RoomId,
239 ) -> Result<Option<OutboundGroupSession>, Self::Error>;
240
241 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>, Self::Error>;
244
245 async fn save_tracked_users(&self, users: &[(&UserId, bool)]) -> Result<(), Self::Error>;
250
251 async fn get_device(
259 &self,
260 user_id: &UserId,
261 device_id: &DeviceId,
262 ) -> Result<Option<DeviceData>, Self::Error>;
263
264 async fn get_user_devices(
270 &self,
271 user_id: &UserId,
272 ) -> Result<HashMap<OwnedDeviceId, DeviceData>, Self::Error>;
273
274 async fn get_own_device(&self) -> Result<DeviceData, Self::Error>;
279
280 async fn get_user_identity(
286 &self,
287 user_id: &UserId,
288 ) -> Result<Option<UserIdentityData>, Self::Error>;
289
290 async fn is_message_known(&self, message_hash: &OlmMessageHash) -> Result<bool, Self::Error>;
292
293 async fn get_outgoing_secret_requests(
301 &self,
302 request_id: &TransactionId,
303 ) -> Result<Option<GossipRequest>, Self::Error>;
304
305 async fn get_secret_request_by_info(
312 &self,
313 secret_info: &SecretInfo,
314 ) -> Result<Option<GossipRequest>, Self::Error>;
315
316 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>, Self::Error>;
318
319 async fn delete_outgoing_secret_requests(
327 &self,
328 request_id: &TransactionId,
329 ) -> Result<(), Self::Error>;
330
331 async fn get_secrets_from_inbox(
334 &self,
335 secret_name: &SecretName,
336 ) -> Result<Vec<Zeroizing<String>>, Self::Error>;
337
338 async fn delete_secrets_from_inbox(&self, secret_name: &SecretName) -> Result<(), Self::Error>;
341
342 async fn get_room_settings(
349 &self,
350 room_id: &RoomId,
351 ) -> Result<Option<RoomSettings>, Self::Error>;
352
353 async fn get_received_room_key_bundle_data(
356 &self,
357 room_id: &RoomId,
358 user_id: &UserId,
359 ) -> Result<Option<StoredRoomKeyBundleData>, Self::Error>;
360
361 async fn get_pending_key_bundle_details_for_room(
364 &self,
365 room_id: &RoomId,
366 ) -> Result<Option<RoomPendingKeyBundleDetails>, Self::Error>;
367
368 async fn get_all_rooms_pending_key_bundles(
371 &self,
372 ) -> Result<Vec<RoomPendingKeyBundleDetails>, Self::Error>;
373
374 async fn has_downloaded_all_room_keys(&self, room_id: &RoomId) -> Result<bool, Self::Error>;
377
378 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>, Self::Error>;
384
385 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<(), Self::Error>;
393
394 async fn remove_custom_value(&self, key: &str) -> Result<(), Self::Error>;
400
401 async fn try_take_leased_lock(
413 &self,
414 lease_duration_ms: u32,
415 key: &str,
416 holder: &str,
417 ) -> Result<Option<CrossProcessLockGeneration>, Self::Error>;
418
419 async fn next_batch_token(&self) -> Result<Option<String>, Self::Error>;
421
422 async fn delete_next_batch_token(&self) -> Result<(), Self::Error>;
425
426 async fn close(&self) -> Result<(), Self::Error>;
432
433 async fn reopen(&self) -> Result<(), Self::Error>;
436
437 async fn get_size(&self) -> Result<Option<usize>, Self::Error>;
439}
440
441#[repr(transparent)]
442struct EraseCryptoStoreError<T>(T);
443
444#[cfg(not(tarpaulin_include))]
445impl<T: fmt::Debug> fmt::Debug for EraseCryptoStoreError<T> {
446 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
447 self.0.fmt(f)
448 }
449}
450
451#[cfg_attr(target_family = "wasm", async_trait(?Send))]
452#[cfg_attr(not(target_family = "wasm"), async_trait)]
453impl<T: CryptoStore> CryptoStore for EraseCryptoStoreError<T> {
454 type Error = CryptoStoreError;
455
456 async fn load_account(&self) -> Result<Option<Account>> {
457 self.0.load_account().await.map_err(Into::into)
458 }
459
460 async fn load_identity(&self) -> Result<Option<PrivateCrossSigningIdentity>> {
461 self.0.load_identity().await.map_err(Into::into)
462 }
463
464 async fn save_changes(&self, changes: Changes) -> Result<()> {
465 self.0.save_changes(changes).await.map_err(Into::into)
466 }
467
468 async fn save_pending_changes(&self, changes: PendingChanges) -> Result<()> {
469 self.0.save_pending_changes(changes).await.map_err(Into::into)
470 }
471
472 async fn save_inbound_group_sessions(
473 &self,
474 sessions: Vec<InboundGroupSession>,
475 backed_up_to_version: Option<&str>,
476 ) -> Result<()> {
477 self.0.save_inbound_group_sessions(sessions, backed_up_to_version).await.map_err(Into::into)
478 }
479
480 async fn get_sessions(&self, sender_key: &str) -> Result<Option<Vec<Session>>> {
481 self.0.get_sessions(sender_key).await.map_err(Into::into)
482 }
483
484 async fn get_inbound_group_session(
485 &self,
486 room_id: &RoomId,
487 session_id: &str,
488 ) -> Result<Option<InboundGroupSession>> {
489 self.0.get_inbound_group_session(room_id, session_id).await.map_err(Into::into)
490 }
491
492 async fn get_inbound_group_sessions(&self) -> Result<Vec<InboundGroupSession>> {
493 self.0.get_inbound_group_sessions().await.map_err(Into::into)
494 }
495
496 async fn get_inbound_group_sessions_by_room_id(
497 &self,
498 room_id: &RoomId,
499 ) -> Result<Vec<InboundGroupSession>> {
500 self.0.get_inbound_group_sessions_by_room_id(room_id).await.map_err(Into::into)
501 }
502
503 async fn get_inbound_group_sessions_for_device_batch(
504 &self,
505 curve_key: Curve25519PublicKey,
506 sender_data_type: SenderDataType,
507 after_session_id: Option<String>,
508 limit: usize,
509 ) -> Result<Vec<InboundGroupSession>> {
510 self.0
511 .get_inbound_group_sessions_for_device_batch(
512 curve_key,
513 sender_data_type,
514 after_session_id,
515 limit,
516 )
517 .await
518 .map_err(Into::into)
519 }
520
521 async fn inbound_group_session_counts(
522 &self,
523 backup_version: Option<&str>,
524 ) -> Result<RoomKeyCounts> {
525 self.0.inbound_group_session_counts(backup_version).await.map_err(Into::into)
526 }
527 async fn inbound_group_sessions_for_backup(
528 &self,
529 backup_version: &str,
530 limit: usize,
531 ) -> Result<Vec<InboundGroupSession>> {
532 self.0.inbound_group_sessions_for_backup(backup_version, limit).await.map_err(Into::into)
533 }
534
535 async fn mark_inbound_group_sessions_as_backed_up(
536 &self,
537 backup_version: &str,
538 room_and_session_ids: &[(&RoomId, &str)],
539 ) -> Result<()> {
540 self.0
541 .mark_inbound_group_sessions_as_backed_up(backup_version, room_and_session_ids)
542 .await
543 .map_err(Into::into)
544 }
545
546 async fn reset_backup_state(&self) -> Result<()> {
547 self.0.reset_backup_state().await.map_err(Into::into)
548 }
549
550 async fn load_backup_keys(&self) -> Result<BackupKeys> {
551 self.0.load_backup_keys().await.map_err(Into::into)
552 }
553
554 async fn load_dehydrated_device_pickle_key(&self) -> Result<Option<DehydratedDeviceKey>> {
555 self.0.load_dehydrated_device_pickle_key().await.map_err(Into::into)
556 }
557
558 async fn delete_dehydrated_device_pickle_key(&self) -> Result<(), Self::Error> {
559 self.0.delete_dehydrated_device_pickle_key().await.map_err(Into::into)
560 }
561
562 async fn get_outbound_group_session(
563 &self,
564 room_id: &RoomId,
565 ) -> Result<Option<OutboundGroupSession>> {
566 self.0.get_outbound_group_session(room_id).await.map_err(Into::into)
567 }
568
569 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>> {
570 self.0.load_tracked_users().await.map_err(Into::into)
571 }
572
573 async fn save_tracked_users(&self, users: &[(&UserId, bool)]) -> Result<()> {
574 self.0.save_tracked_users(users).await.map_err(Into::into)
575 }
576
577 async fn get_device(
578 &self,
579 user_id: &UserId,
580 device_id: &DeviceId,
581 ) -> Result<Option<DeviceData>> {
582 self.0.get_device(user_id, device_id).await.map_err(Into::into)
583 }
584
585 async fn get_user_devices(
586 &self,
587 user_id: &UserId,
588 ) -> Result<HashMap<OwnedDeviceId, DeviceData>> {
589 self.0.get_user_devices(user_id).await.map_err(Into::into)
590 }
591
592 async fn get_own_device(&self) -> Result<DeviceData> {
593 self.0.get_own_device().await.map_err(Into::into)
594 }
595
596 async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<UserIdentityData>> {
597 self.0.get_user_identity(user_id).await.map_err(Into::into)
598 }
599
600 async fn is_message_known(&self, message_hash: &OlmMessageHash) -> Result<bool> {
601 self.0.is_message_known(message_hash).await.map_err(Into::into)
602 }
603
604 async fn get_outgoing_secret_requests(
605 &self,
606 request_id: &TransactionId,
607 ) -> Result<Option<GossipRequest>> {
608 self.0.get_outgoing_secret_requests(request_id).await.map_err(Into::into)
609 }
610
611 async fn get_secret_request_by_info(
612 &self,
613 secret_info: &SecretInfo,
614 ) -> Result<Option<GossipRequest>> {
615 self.0.get_secret_request_by_info(secret_info).await.map_err(Into::into)
616 }
617
618 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>> {
619 self.0.get_unsent_secret_requests().await.map_err(Into::into)
620 }
621
622 async fn delete_outgoing_secret_requests(&self, request_id: &TransactionId) -> Result<()> {
623 self.0.delete_outgoing_secret_requests(request_id).await.map_err(Into::into)
624 }
625
626 async fn get_secrets_from_inbox(
627 &self,
628 secret_name: &SecretName,
629 ) -> Result<Vec<Zeroizing<String>>> {
630 self.0.get_secrets_from_inbox(secret_name).await.map_err(Into::into)
631 }
632
633 async fn delete_secrets_from_inbox(&self, secret_name: &SecretName) -> Result<()> {
634 self.0.delete_secrets_from_inbox(secret_name).await.map_err(Into::into)
635 }
636
637 async fn get_withheld_info(
638 &self,
639 room_id: &RoomId,
640 session_id: &str,
641 ) -> Result<Option<RoomKeyWithheldEntry>, Self::Error> {
642 self.0.get_withheld_info(room_id, session_id).await.map_err(Into::into)
643 }
644
645 async fn get_withheld_sessions_by_room_id(
646 &self,
647 room_id: &RoomId,
648 ) -> Result<Vec<RoomKeyWithheldEntry>, Self::Error> {
649 self.0.get_withheld_sessions_by_room_id(room_id).await.map_err(Into::into)
650 }
651
652 async fn get_room_settings(&self, room_id: &RoomId) -> Result<Option<RoomSettings>> {
653 self.0.get_room_settings(room_id).await.map_err(Into::into)
654 }
655
656 async fn get_received_room_key_bundle_data(
657 &self,
658 room_id: &RoomId,
659 user_id: &UserId,
660 ) -> Result<Option<StoredRoomKeyBundleData>> {
661 self.0.get_received_room_key_bundle_data(room_id, user_id).await.map_err(Into::into)
662 }
663
664 async fn has_downloaded_all_room_keys(&self, room_id: &RoomId) -> Result<bool, Self::Error> {
665 self.0.has_downloaded_all_room_keys(room_id).await.map_err(Into::into)
666 }
667
668 async fn get_pending_key_bundle_details_for_room(
669 &self,
670 room_id: &RoomId,
671 ) -> Result<Option<RoomPendingKeyBundleDetails>, Self::Error> {
672 self.0.get_pending_key_bundle_details_for_room(room_id).await.map_err(Into::into)
673 }
674
675 async fn get_all_rooms_pending_key_bundles(
676 &self,
677 ) -> Result<Vec<RoomPendingKeyBundleDetails>, Self::Error> {
678 self.0.get_all_rooms_pending_key_bundles().await.map_err(Into::into)
679 }
680
681 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>, Self::Error> {
682 self.0.get_custom_value(key).await.map_err(Into::into)
683 }
684
685 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<(), Self::Error> {
686 self.0.set_custom_value(key, value).await.map_err(Into::into)
687 }
688
689 async fn remove_custom_value(&self, key: &str) -> Result<(), Self::Error> {
690 self.0.remove_custom_value(key).await.map_err(Into::into)
691 }
692
693 async fn try_take_leased_lock(
694 &self,
695 lease_duration_ms: u32,
696 key: &str,
697 holder: &str,
698 ) -> Result<Option<CrossProcessLockGeneration>, Self::Error> {
699 self.0.try_take_leased_lock(lease_duration_ms, key, holder).await.map_err(Into::into)
700 }
701
702 async fn next_batch_token(&self) -> Result<Option<String>, Self::Error> {
703 self.0.next_batch_token().await.map_err(Into::into)
704 }
705
706 async fn delete_next_batch_token(&self) -> Result<(), Self::Error> {
707 self.0.delete_next_batch_token().await.map_err(Into::into)
708 }
709
710 async fn close(&self) -> Result<(), Self::Error> {
711 self.0.close().await.map_err(Into::into)
712 }
713
714 async fn reopen(&self) -> Result<(), Self::Error> {
715 self.0.reopen().await.map_err(Into::into)
716 }
717
718 async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
719 self.0.get_size().await.map_err(Into::into)
720 }
721}
722
723pub type DynCryptoStore = dyn CryptoStore<Error = CryptoStoreError>;
725
726pub trait IntoCryptoStore {
732 #[doc(hidden)]
733 fn into_crypto_store(self) -> Arc<DynCryptoStore>;
734}
735
736impl<T> IntoCryptoStore for T
737where
738 T: CryptoStore + 'static,
739{
740 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
741 Arc::new(EraseCryptoStoreError(self))
742 }
743}
744
745impl<T> IntoCryptoStore for Arc<T>
748where
749 T: CryptoStore + 'static,
750{
751 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
752 let ptr: *const T = Arc::into_raw(self);
753 let ptr_erased = ptr as *const EraseCryptoStoreError<T>;
754 unsafe { Arc::from_raw(ptr_erased) }
757 }
758}
759
760impl IntoCryptoStore for Arc<DynCryptoStore> {
761 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
762 self
763 }
764}