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 close(&self) -> Result<(), Self::Error>;
428
429 async fn reopen(&self) -> Result<(), Self::Error>;
432
433 async fn get_size(&self) -> Result<Option<usize>, Self::Error>;
435}
436
437#[repr(transparent)]
438struct EraseCryptoStoreError<T>(T);
439
440#[cfg(not(tarpaulin_include))]
441impl<T: fmt::Debug> fmt::Debug for EraseCryptoStoreError<T> {
442 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
443 self.0.fmt(f)
444 }
445}
446
447#[cfg_attr(target_family = "wasm", async_trait(?Send))]
448#[cfg_attr(not(target_family = "wasm"), async_trait)]
449impl<T: CryptoStore> CryptoStore for EraseCryptoStoreError<T> {
450 type Error = CryptoStoreError;
451
452 async fn load_account(&self) -> Result<Option<Account>> {
453 self.0.load_account().await.map_err(Into::into)
454 }
455
456 async fn load_identity(&self) -> Result<Option<PrivateCrossSigningIdentity>> {
457 self.0.load_identity().await.map_err(Into::into)
458 }
459
460 async fn save_changes(&self, changes: Changes) -> Result<()> {
461 self.0.save_changes(changes).await.map_err(Into::into)
462 }
463
464 async fn save_pending_changes(&self, changes: PendingChanges) -> Result<()> {
465 self.0.save_pending_changes(changes).await.map_err(Into::into)
466 }
467
468 async fn save_inbound_group_sessions(
469 &self,
470 sessions: Vec<InboundGroupSession>,
471 backed_up_to_version: Option<&str>,
472 ) -> Result<()> {
473 self.0.save_inbound_group_sessions(sessions, backed_up_to_version).await.map_err(Into::into)
474 }
475
476 async fn get_sessions(&self, sender_key: &str) -> Result<Option<Vec<Session>>> {
477 self.0.get_sessions(sender_key).await.map_err(Into::into)
478 }
479
480 async fn get_inbound_group_session(
481 &self,
482 room_id: &RoomId,
483 session_id: &str,
484 ) -> Result<Option<InboundGroupSession>> {
485 self.0.get_inbound_group_session(room_id, session_id).await.map_err(Into::into)
486 }
487
488 async fn get_inbound_group_sessions(&self) -> Result<Vec<InboundGroupSession>> {
489 self.0.get_inbound_group_sessions().await.map_err(Into::into)
490 }
491
492 async fn get_inbound_group_sessions_by_room_id(
493 &self,
494 room_id: &RoomId,
495 ) -> Result<Vec<InboundGroupSession>> {
496 self.0.get_inbound_group_sessions_by_room_id(room_id).await.map_err(Into::into)
497 }
498
499 async fn get_inbound_group_sessions_for_device_batch(
500 &self,
501 curve_key: Curve25519PublicKey,
502 sender_data_type: SenderDataType,
503 after_session_id: Option<String>,
504 limit: usize,
505 ) -> Result<Vec<InboundGroupSession>> {
506 self.0
507 .get_inbound_group_sessions_for_device_batch(
508 curve_key,
509 sender_data_type,
510 after_session_id,
511 limit,
512 )
513 .await
514 .map_err(Into::into)
515 }
516
517 async fn inbound_group_session_counts(
518 &self,
519 backup_version: Option<&str>,
520 ) -> Result<RoomKeyCounts> {
521 self.0.inbound_group_session_counts(backup_version).await.map_err(Into::into)
522 }
523 async fn inbound_group_sessions_for_backup(
524 &self,
525 backup_version: &str,
526 limit: usize,
527 ) -> Result<Vec<InboundGroupSession>> {
528 self.0.inbound_group_sessions_for_backup(backup_version, limit).await.map_err(Into::into)
529 }
530
531 async fn mark_inbound_group_sessions_as_backed_up(
532 &self,
533 backup_version: &str,
534 room_and_session_ids: &[(&RoomId, &str)],
535 ) -> Result<()> {
536 self.0
537 .mark_inbound_group_sessions_as_backed_up(backup_version, room_and_session_ids)
538 .await
539 .map_err(Into::into)
540 }
541
542 async fn reset_backup_state(&self) -> Result<()> {
543 self.0.reset_backup_state().await.map_err(Into::into)
544 }
545
546 async fn load_backup_keys(&self) -> Result<BackupKeys> {
547 self.0.load_backup_keys().await.map_err(Into::into)
548 }
549
550 async fn load_dehydrated_device_pickle_key(&self) -> Result<Option<DehydratedDeviceKey>> {
551 self.0.load_dehydrated_device_pickle_key().await.map_err(Into::into)
552 }
553
554 async fn delete_dehydrated_device_pickle_key(&self) -> Result<(), Self::Error> {
555 self.0.delete_dehydrated_device_pickle_key().await.map_err(Into::into)
556 }
557
558 async fn get_outbound_group_session(
559 &self,
560 room_id: &RoomId,
561 ) -> Result<Option<OutboundGroupSession>> {
562 self.0.get_outbound_group_session(room_id).await.map_err(Into::into)
563 }
564
565 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>> {
566 self.0.load_tracked_users().await.map_err(Into::into)
567 }
568
569 async fn save_tracked_users(&self, users: &[(&UserId, bool)]) -> Result<()> {
570 self.0.save_tracked_users(users).await.map_err(Into::into)
571 }
572
573 async fn get_device(
574 &self,
575 user_id: &UserId,
576 device_id: &DeviceId,
577 ) -> Result<Option<DeviceData>> {
578 self.0.get_device(user_id, device_id).await.map_err(Into::into)
579 }
580
581 async fn get_user_devices(
582 &self,
583 user_id: &UserId,
584 ) -> Result<HashMap<OwnedDeviceId, DeviceData>> {
585 self.0.get_user_devices(user_id).await.map_err(Into::into)
586 }
587
588 async fn get_own_device(&self) -> Result<DeviceData> {
589 self.0.get_own_device().await.map_err(Into::into)
590 }
591
592 async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<UserIdentityData>> {
593 self.0.get_user_identity(user_id).await.map_err(Into::into)
594 }
595
596 async fn is_message_known(&self, message_hash: &OlmMessageHash) -> Result<bool> {
597 self.0.is_message_known(message_hash).await.map_err(Into::into)
598 }
599
600 async fn get_outgoing_secret_requests(
601 &self,
602 request_id: &TransactionId,
603 ) -> Result<Option<GossipRequest>> {
604 self.0.get_outgoing_secret_requests(request_id).await.map_err(Into::into)
605 }
606
607 async fn get_secret_request_by_info(
608 &self,
609 secret_info: &SecretInfo,
610 ) -> Result<Option<GossipRequest>> {
611 self.0.get_secret_request_by_info(secret_info).await.map_err(Into::into)
612 }
613
614 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>> {
615 self.0.get_unsent_secret_requests().await.map_err(Into::into)
616 }
617
618 async fn delete_outgoing_secret_requests(&self, request_id: &TransactionId) -> Result<()> {
619 self.0.delete_outgoing_secret_requests(request_id).await.map_err(Into::into)
620 }
621
622 async fn get_secrets_from_inbox(
623 &self,
624 secret_name: &SecretName,
625 ) -> Result<Vec<Zeroizing<String>>> {
626 self.0.get_secrets_from_inbox(secret_name).await.map_err(Into::into)
627 }
628
629 async fn delete_secrets_from_inbox(&self, secret_name: &SecretName) -> Result<()> {
630 self.0.delete_secrets_from_inbox(secret_name).await.map_err(Into::into)
631 }
632
633 async fn get_withheld_info(
634 &self,
635 room_id: &RoomId,
636 session_id: &str,
637 ) -> Result<Option<RoomKeyWithheldEntry>, Self::Error> {
638 self.0.get_withheld_info(room_id, session_id).await.map_err(Into::into)
639 }
640
641 async fn get_withheld_sessions_by_room_id(
642 &self,
643 room_id: &RoomId,
644 ) -> Result<Vec<RoomKeyWithheldEntry>, Self::Error> {
645 self.0.get_withheld_sessions_by_room_id(room_id).await.map_err(Into::into)
646 }
647
648 async fn get_room_settings(&self, room_id: &RoomId) -> Result<Option<RoomSettings>> {
649 self.0.get_room_settings(room_id).await.map_err(Into::into)
650 }
651
652 async fn get_received_room_key_bundle_data(
653 &self,
654 room_id: &RoomId,
655 user_id: &UserId,
656 ) -> Result<Option<StoredRoomKeyBundleData>> {
657 self.0.get_received_room_key_bundle_data(room_id, user_id).await.map_err(Into::into)
658 }
659
660 async fn has_downloaded_all_room_keys(&self, room_id: &RoomId) -> Result<bool, Self::Error> {
661 self.0.has_downloaded_all_room_keys(room_id).await.map_err(Into::into)
662 }
663
664 async fn get_pending_key_bundle_details_for_room(
665 &self,
666 room_id: &RoomId,
667 ) -> Result<Option<RoomPendingKeyBundleDetails>, Self::Error> {
668 self.0.get_pending_key_bundle_details_for_room(room_id).await.map_err(Into::into)
669 }
670
671 async fn get_all_rooms_pending_key_bundles(
672 &self,
673 ) -> Result<Vec<RoomPendingKeyBundleDetails>, Self::Error> {
674 self.0.get_all_rooms_pending_key_bundles().await.map_err(Into::into)
675 }
676
677 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>, Self::Error> {
678 self.0.get_custom_value(key).await.map_err(Into::into)
679 }
680
681 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<(), Self::Error> {
682 self.0.set_custom_value(key, value).await.map_err(Into::into)
683 }
684
685 async fn remove_custom_value(&self, key: &str) -> Result<(), Self::Error> {
686 self.0.remove_custom_value(key).await.map_err(Into::into)
687 }
688
689 async fn try_take_leased_lock(
690 &self,
691 lease_duration_ms: u32,
692 key: &str,
693 holder: &str,
694 ) -> Result<Option<CrossProcessLockGeneration>, Self::Error> {
695 self.0.try_take_leased_lock(lease_duration_ms, key, holder).await.map_err(Into::into)
696 }
697
698 async fn next_batch_token(&self) -> Result<Option<String>, Self::Error> {
699 self.0.next_batch_token().await.map_err(Into::into)
700 }
701
702 async fn close(&self) -> Result<(), Self::Error> {
703 self.0.close().await.map_err(Into::into)
704 }
705
706 async fn reopen(&self) -> Result<(), Self::Error> {
707 self.0.reopen().await.map_err(Into::into)
708 }
709
710 async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
711 self.0.get_size().await.map_err(Into::into)
712 }
713}
714
715pub type DynCryptoStore = dyn CryptoStore<Error = CryptoStoreError>;
717
718pub trait IntoCryptoStore {
724 #[doc(hidden)]
725 fn into_crypto_store(self) -> Arc<DynCryptoStore>;
726}
727
728impl<T> IntoCryptoStore for T
729where
730 T: CryptoStore + 'static,
731{
732 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
733 Arc::new(EraseCryptoStoreError(self))
734 }
735}
736
737impl<T> IntoCryptoStore for Arc<T>
740where
741 T: CryptoStore + 'static,
742{
743 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
744 let ptr: *const T = Arc::into_raw(self);
745 let ptr_erased = ptr as *const EraseCryptoStoreError<T>;
746 unsafe { Arc::from_raw(ptr_erased) }
749 }
750}
751
752impl IntoCryptoStore for Arc<DynCryptoStore> {
753 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
754 self
755 }
756}