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>;
73
74 async fn save_inbound_group_sessions(
85 &self,
86 sessions: Vec<InboundGroupSession>,
87 backed_up_to_version: Option<&str>,
88 ) -> Result<(), Self::Error>;
89
90 async fn get_sessions(&self, sender_key: &str) -> Result<Option<Vec<Session>>, Self::Error>;
96
97 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(
117 &self,
118 room_id: &RoomId,
119 session_id: &str,
120 ) -> Result<Option<RoomKeyWithheldEntry>, Self::Error>;
121
122 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(
150 &self,
151 room_id: &RoomId,
152 ) -> Result<Vec<InboundGroupSession>, Self::Error>;
153
154 async fn get_inbound_group_sessions_for_device_batch(
181 &self,
182 curve_key: Curve25519PublicKey,
183 sender_data_type: SenderDataType,
184 after_session_id: Option<String>,
185 limit: usize,
186 ) -> Result<Vec<InboundGroupSession>, Self::Error>;
187
188 async fn inbound_group_sessions_for_backup(
196 &self,
197 backup_version: &str,
198 limit: usize,
199 ) -> Result<Vec<InboundGroupSession>, Self::Error>;
200
201 async fn mark_inbound_group_sessions_as_backed_up(
207 &self,
208 backup_version: &str,
209 room_and_session_ids: &[(&RoomId, &str)],
210 ) -> Result<(), Self::Error>;
211
212 async fn reset_backup_state(&self) -> Result<(), Self::Error>;
221
222 async fn load_backup_keys(&self) -> Result<BackupKeys, Self::Error>;
224
225 async fn load_dehydrated_device_pickle_key(
227 &self,
228 ) -> Result<Option<DehydratedDeviceKey>, Self::Error>;
229
230 async fn delete_dehydrated_device_pickle_key(&self) -> Result<(), Self::Error>;
232
233 async fn get_outbound_group_session(
236 &self,
237 room_id: &RoomId,
238 ) -> Result<Option<OutboundGroupSession>, Self::Error>;
239
240 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>, Self::Error>;
243
244 async fn save_tracked_users(&self, users: &[(&UserId, bool)]) -> Result<(), Self::Error>;
249
250 async fn get_device(
258 &self,
259 user_id: &UserId,
260 device_id: &DeviceId,
261 ) -> Result<Option<DeviceData>, Self::Error>;
262
263 async fn get_user_devices(
269 &self,
270 user_id: &UserId,
271 ) -> Result<HashMap<OwnedDeviceId, DeviceData>, Self::Error>;
272
273 async fn get_own_device(&self) -> Result<DeviceData, Self::Error>;
278
279 async fn get_user_identity(
285 &self,
286 user_id: &UserId,
287 ) -> Result<Option<UserIdentityData>, Self::Error>;
288
289 async fn is_message_known(&self, message_hash: &OlmMessageHash) -> Result<bool, Self::Error>;
291
292 async fn get_outgoing_secret_requests(
300 &self,
301 request_id: &TransactionId,
302 ) -> Result<Option<GossipRequest>, Self::Error>;
303
304 async fn get_secret_request_by_info(
311 &self,
312 secret_info: &SecretInfo,
313 ) -> Result<Option<GossipRequest>, Self::Error>;
314
315 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>, Self::Error>;
317
318 async fn delete_outgoing_secret_requests(
326 &self,
327 request_id: &TransactionId,
328 ) -> Result<(), Self::Error>;
329
330 async fn get_secrets_from_inbox(
333 &self,
334 secret_name: &SecretName,
335 ) -> Result<Vec<Zeroizing<String>>, Self::Error>;
336
337 async fn delete_secrets_from_inbox(&self, secret_name: &SecretName) -> Result<(), Self::Error>;
340
341 async fn get_room_settings(
348 &self,
349 room_id: &RoomId,
350 ) -> Result<Option<RoomSettings>, Self::Error>;
351
352 async fn get_received_room_key_bundle_data(
355 &self,
356 room_id: &RoomId,
357 user_id: &UserId,
358 ) -> Result<Option<StoredRoomKeyBundleData>, Self::Error>;
359
360 async fn get_pending_key_bundle_details_for_room(
363 &self,
364 room_id: &RoomId,
365 ) -> Result<Option<RoomPendingKeyBundleDetails>, Self::Error>;
366
367 async fn get_all_rooms_pending_key_bundles(
370 &self,
371 ) -> Result<Vec<RoomPendingKeyBundleDetails>, Self::Error>;
372
373 async fn has_downloaded_all_room_keys(&self, room_id: &RoomId) -> Result<bool, Self::Error>;
376
377 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>, Self::Error>;
383
384 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<(), Self::Error>;
392
393 async fn remove_custom_value(&self, key: &str) -> Result<(), Self::Error>;
399
400 async fn try_take_leased_lock(
412 &self,
413 lease_duration_ms: u32,
414 key: &str,
415 holder: &str,
416 ) -> Result<Option<CrossProcessLockGeneration>, Self::Error>;
417
418 async fn next_batch_token(&self) -> Result<Option<String>, Self::Error>;
420
421 async fn get_size(&self) -> Result<Option<usize>, Self::Error>;
423}
424
425#[repr(transparent)]
426struct EraseCryptoStoreError<T>(T);
427
428#[cfg(not(tarpaulin_include))]
429impl<T: fmt::Debug> fmt::Debug for EraseCryptoStoreError<T> {
430 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
431 self.0.fmt(f)
432 }
433}
434
435#[cfg_attr(target_family = "wasm", async_trait(?Send))]
436#[cfg_attr(not(target_family = "wasm"), async_trait)]
437impl<T: CryptoStore> CryptoStore for EraseCryptoStoreError<T> {
438 type Error = CryptoStoreError;
439
440 async fn load_account(&self) -> Result<Option<Account>> {
441 self.0.load_account().await.map_err(Into::into)
442 }
443
444 async fn load_identity(&self) -> Result<Option<PrivateCrossSigningIdentity>> {
445 self.0.load_identity().await.map_err(Into::into)
446 }
447
448 async fn save_changes(&self, changes: Changes) -> Result<()> {
449 self.0.save_changes(changes).await.map_err(Into::into)
450 }
451
452 async fn save_pending_changes(&self, changes: PendingChanges) -> Result<()> {
453 self.0.save_pending_changes(changes).await.map_err(Into::into)
454 }
455
456 async fn save_inbound_group_sessions(
457 &self,
458 sessions: Vec<InboundGroupSession>,
459 backed_up_to_version: Option<&str>,
460 ) -> Result<()> {
461 self.0.save_inbound_group_sessions(sessions, backed_up_to_version).await.map_err(Into::into)
462 }
463
464 async fn get_sessions(&self, sender_key: &str) -> Result<Option<Vec<Session>>> {
465 self.0.get_sessions(sender_key).await.map_err(Into::into)
466 }
467
468 async fn get_inbound_group_session(
469 &self,
470 room_id: &RoomId,
471 session_id: &str,
472 ) -> Result<Option<InboundGroupSession>> {
473 self.0.get_inbound_group_session(room_id, session_id).await.map_err(Into::into)
474 }
475
476 async fn get_inbound_group_sessions(&self) -> Result<Vec<InboundGroupSession>> {
477 self.0.get_inbound_group_sessions().await.map_err(Into::into)
478 }
479
480 async fn get_inbound_group_sessions_by_room_id(
481 &self,
482 room_id: &RoomId,
483 ) -> Result<Vec<InboundGroupSession>> {
484 self.0.get_inbound_group_sessions_by_room_id(room_id).await.map_err(Into::into)
485 }
486
487 async fn get_inbound_group_sessions_for_device_batch(
488 &self,
489 curve_key: Curve25519PublicKey,
490 sender_data_type: SenderDataType,
491 after_session_id: Option<String>,
492 limit: usize,
493 ) -> Result<Vec<InboundGroupSession>> {
494 self.0
495 .get_inbound_group_sessions_for_device_batch(
496 curve_key,
497 sender_data_type,
498 after_session_id,
499 limit,
500 )
501 .await
502 .map_err(Into::into)
503 }
504
505 async fn inbound_group_session_counts(
506 &self,
507 backup_version: Option<&str>,
508 ) -> Result<RoomKeyCounts> {
509 self.0.inbound_group_session_counts(backup_version).await.map_err(Into::into)
510 }
511 async fn inbound_group_sessions_for_backup(
512 &self,
513 backup_version: &str,
514 limit: usize,
515 ) -> Result<Vec<InboundGroupSession>> {
516 self.0.inbound_group_sessions_for_backup(backup_version, limit).await.map_err(Into::into)
517 }
518
519 async fn mark_inbound_group_sessions_as_backed_up(
520 &self,
521 backup_version: &str,
522 room_and_session_ids: &[(&RoomId, &str)],
523 ) -> Result<()> {
524 self.0
525 .mark_inbound_group_sessions_as_backed_up(backup_version, room_and_session_ids)
526 .await
527 .map_err(Into::into)
528 }
529
530 async fn reset_backup_state(&self) -> Result<()> {
531 self.0.reset_backup_state().await.map_err(Into::into)
532 }
533
534 async fn load_backup_keys(&self) -> Result<BackupKeys> {
535 self.0.load_backup_keys().await.map_err(Into::into)
536 }
537
538 async fn load_dehydrated_device_pickle_key(&self) -> Result<Option<DehydratedDeviceKey>> {
539 self.0.load_dehydrated_device_pickle_key().await.map_err(Into::into)
540 }
541
542 async fn delete_dehydrated_device_pickle_key(&self) -> Result<(), Self::Error> {
543 self.0.delete_dehydrated_device_pickle_key().await.map_err(Into::into)
544 }
545
546 async fn get_outbound_group_session(
547 &self,
548 room_id: &RoomId,
549 ) -> Result<Option<OutboundGroupSession>> {
550 self.0.get_outbound_group_session(room_id).await.map_err(Into::into)
551 }
552
553 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>> {
554 self.0.load_tracked_users().await.map_err(Into::into)
555 }
556
557 async fn save_tracked_users(&self, users: &[(&UserId, bool)]) -> Result<()> {
558 self.0.save_tracked_users(users).await.map_err(Into::into)
559 }
560
561 async fn get_device(
562 &self,
563 user_id: &UserId,
564 device_id: &DeviceId,
565 ) -> Result<Option<DeviceData>> {
566 self.0.get_device(user_id, device_id).await.map_err(Into::into)
567 }
568
569 async fn get_user_devices(
570 &self,
571 user_id: &UserId,
572 ) -> Result<HashMap<OwnedDeviceId, DeviceData>> {
573 self.0.get_user_devices(user_id).await.map_err(Into::into)
574 }
575
576 async fn get_own_device(&self) -> Result<DeviceData> {
577 self.0.get_own_device().await.map_err(Into::into)
578 }
579
580 async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<UserIdentityData>> {
581 self.0.get_user_identity(user_id).await.map_err(Into::into)
582 }
583
584 async fn is_message_known(&self, message_hash: &OlmMessageHash) -> Result<bool> {
585 self.0.is_message_known(message_hash).await.map_err(Into::into)
586 }
587
588 async fn get_outgoing_secret_requests(
589 &self,
590 request_id: &TransactionId,
591 ) -> Result<Option<GossipRequest>> {
592 self.0.get_outgoing_secret_requests(request_id).await.map_err(Into::into)
593 }
594
595 async fn get_secret_request_by_info(
596 &self,
597 secret_info: &SecretInfo,
598 ) -> Result<Option<GossipRequest>> {
599 self.0.get_secret_request_by_info(secret_info).await.map_err(Into::into)
600 }
601
602 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>> {
603 self.0.get_unsent_secret_requests().await.map_err(Into::into)
604 }
605
606 async fn delete_outgoing_secret_requests(&self, request_id: &TransactionId) -> Result<()> {
607 self.0.delete_outgoing_secret_requests(request_id).await.map_err(Into::into)
608 }
609
610 async fn get_secrets_from_inbox(
611 &self,
612 secret_name: &SecretName,
613 ) -> Result<Vec<Zeroizing<String>>> {
614 self.0.get_secrets_from_inbox(secret_name).await.map_err(Into::into)
615 }
616
617 async fn delete_secrets_from_inbox(&self, secret_name: &SecretName) -> Result<()> {
618 self.0.delete_secrets_from_inbox(secret_name).await.map_err(Into::into)
619 }
620
621 async fn get_withheld_info(
622 &self,
623 room_id: &RoomId,
624 session_id: &str,
625 ) -> Result<Option<RoomKeyWithheldEntry>, Self::Error> {
626 self.0.get_withheld_info(room_id, session_id).await.map_err(Into::into)
627 }
628
629 async fn get_withheld_sessions_by_room_id(
630 &self,
631 room_id: &RoomId,
632 ) -> Result<Vec<RoomKeyWithheldEntry>, Self::Error> {
633 self.0.get_withheld_sessions_by_room_id(room_id).await.map_err(Into::into)
634 }
635
636 async fn get_room_settings(&self, room_id: &RoomId) -> Result<Option<RoomSettings>> {
637 self.0.get_room_settings(room_id).await.map_err(Into::into)
638 }
639
640 async fn get_received_room_key_bundle_data(
641 &self,
642 room_id: &RoomId,
643 user_id: &UserId,
644 ) -> Result<Option<StoredRoomKeyBundleData>> {
645 self.0.get_received_room_key_bundle_data(room_id, user_id).await.map_err(Into::into)
646 }
647
648 async fn has_downloaded_all_room_keys(&self, room_id: &RoomId) -> Result<bool, Self::Error> {
649 self.0.has_downloaded_all_room_keys(room_id).await.map_err(Into::into)
650 }
651
652 async fn get_pending_key_bundle_details_for_room(
653 &self,
654 room_id: &RoomId,
655 ) -> Result<Option<RoomPendingKeyBundleDetails>, Self::Error> {
656 self.0.get_pending_key_bundle_details_for_room(room_id).await.map_err(Into::into)
657 }
658
659 async fn get_all_rooms_pending_key_bundles(
660 &self,
661 ) -> Result<Vec<RoomPendingKeyBundleDetails>, Self::Error> {
662 self.0.get_all_rooms_pending_key_bundles().await.map_err(Into::into)
663 }
664
665 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>, Self::Error> {
666 self.0.get_custom_value(key).await.map_err(Into::into)
667 }
668
669 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<(), Self::Error> {
670 self.0.set_custom_value(key, value).await.map_err(Into::into)
671 }
672
673 async fn remove_custom_value(&self, key: &str) -> Result<(), Self::Error> {
674 self.0.remove_custom_value(key).await.map_err(Into::into)
675 }
676
677 async fn try_take_leased_lock(
678 &self,
679 lease_duration_ms: u32,
680 key: &str,
681 holder: &str,
682 ) -> Result<Option<CrossProcessLockGeneration>, Self::Error> {
683 self.0.try_take_leased_lock(lease_duration_ms, key, holder).await.map_err(Into::into)
684 }
685
686 async fn next_batch_token(&self) -> Result<Option<String>, Self::Error> {
687 self.0.next_batch_token().await.map_err(Into::into)
688 }
689
690 async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
691 self.0.get_size().await.map_err(Into::into)
692 }
693}
694
695pub type DynCryptoStore = dyn CryptoStore<Error = CryptoStoreError>;
697
698pub trait IntoCryptoStore {
704 #[doc(hidden)]
705 fn into_crypto_store(self) -> Arc<DynCryptoStore>;
706}
707
708impl<T> IntoCryptoStore for T
709where
710 T: CryptoStore + 'static,
711{
712 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
713 Arc::new(EraseCryptoStoreError(self))
714 }
715}
716
717impl<T> IntoCryptoStore for Arc<T>
720where
721 T: CryptoStore + 'static,
722{
723 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
724 let ptr: *const T = Arc::into_raw(self);
725 let ptr_erased = ptr as *const EraseCryptoStoreError<T>;
726 unsafe { Arc::from_raw(ptr_erased) }
729 }
730}
731
732impl IntoCryptoStore for Arc<DynCryptoStore> {
733 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
734 self
735 }
736}