1use std::{collections::HashMap, fmt, sync::Arc};
16
17use async_trait::async_trait;
18use matrix_sdk_common::AsyncTraitDeps;
19use ruma::{
20 events::secret::request::SecretName, DeviceId, OwnedDeviceId, RoomId, TransactionId, UserId,
21};
22use vodozemac::Curve25519PublicKey;
23
24use super::{
25 types::{
26 BackupKeys, Changes, DehydratedDeviceKey, PendingChanges, RoomKeyCounts, RoomSettings,
27 StoredRoomKeyBundleData, TrackedUser,
28 },
29 CryptoStoreError, Result,
30};
31#[cfg(doc)]
32use crate::olm::SenderData;
33use crate::{
34 olm::{
35 InboundGroupSession, OlmMessageHash, OutboundGroupSession, PrivateCrossSigningIdentity,
36 SenderDataType, Session,
37 },
38 types::events::room_key_withheld::RoomKeyWithheldEvent,
39 Account, DeviceData, GossipRequest, GossippedSecret, SecretInfo, UserIdentityData,
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<RoomKeyWithheldEvent>, Self::Error>;
120
121 async fn get_inbound_group_sessions(&self) -> Result<Vec<InboundGroupSession>, Self::Error>;
123
124 async fn inbound_group_session_counts(
127 &self,
128 backup_version: Option<&str>,
129 ) -> Result<RoomKeyCounts, Self::Error>;
130
131 async fn get_inbound_group_sessions_by_room_id(
136 &self,
137 room_id: &RoomId,
138 ) -> Result<Vec<InboundGroupSession>, Self::Error>;
139
140 async fn get_inbound_group_sessions_for_device_batch(
167 &self,
168 curve_key: Curve25519PublicKey,
169 sender_data_type: SenderDataType,
170 after_session_id: Option<String>,
171 limit: usize,
172 ) -> Result<Vec<InboundGroupSession>, Self::Error>;
173
174 async fn inbound_group_sessions_for_backup(
182 &self,
183 backup_version: &str,
184 limit: usize,
185 ) -> Result<Vec<InboundGroupSession>, Self::Error>;
186
187 async fn mark_inbound_group_sessions_as_backed_up(
193 &self,
194 backup_version: &str,
195 room_and_session_ids: &[(&RoomId, &str)],
196 ) -> Result<(), Self::Error>;
197
198 async fn reset_backup_state(&self) -> Result<(), Self::Error>;
207
208 async fn load_backup_keys(&self) -> Result<BackupKeys, Self::Error>;
210
211 async fn load_dehydrated_device_pickle_key(
213 &self,
214 ) -> Result<Option<DehydratedDeviceKey>, Self::Error>;
215
216 async fn delete_dehydrated_device_pickle_key(&self) -> Result<(), Self::Error>;
218
219 async fn get_outbound_group_session(
222 &self,
223 room_id: &RoomId,
224 ) -> Result<Option<OutboundGroupSession>, Self::Error>;
225
226 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>, Self::Error>;
229
230 async fn save_tracked_users(&self, users: &[(&UserId, bool)]) -> Result<(), Self::Error>;
235
236 async fn get_device(
244 &self,
245 user_id: &UserId,
246 device_id: &DeviceId,
247 ) -> Result<Option<DeviceData>, Self::Error>;
248
249 async fn get_user_devices(
255 &self,
256 user_id: &UserId,
257 ) -> Result<HashMap<OwnedDeviceId, DeviceData>, Self::Error>;
258
259 async fn get_own_device(&self) -> Result<DeviceData, Self::Error>;
264
265 async fn get_user_identity(
271 &self,
272 user_id: &UserId,
273 ) -> Result<Option<UserIdentityData>, Self::Error>;
274
275 async fn is_message_known(&self, message_hash: &OlmMessageHash) -> Result<bool, Self::Error>;
277
278 async fn get_outgoing_secret_requests(
286 &self,
287 request_id: &TransactionId,
288 ) -> Result<Option<GossipRequest>, Self::Error>;
289
290 async fn get_secret_request_by_info(
297 &self,
298 secret_info: &SecretInfo,
299 ) -> Result<Option<GossipRequest>, Self::Error>;
300
301 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>, Self::Error>;
303
304 async fn delete_outgoing_secret_requests(
312 &self,
313 request_id: &TransactionId,
314 ) -> Result<(), Self::Error>;
315
316 async fn get_secrets_from_inbox(
319 &self,
320 secret_name: &SecretName,
321 ) -> Result<Vec<GossippedSecret>, Self::Error>;
322
323 async fn delete_secrets_from_inbox(&self, secret_name: &SecretName) -> Result<(), Self::Error>;
326
327 async fn get_room_settings(
334 &self,
335 room_id: &RoomId,
336 ) -> Result<Option<RoomSettings>, Self::Error>;
337
338 async fn get_received_room_key_bundle_data(
341 &self,
342 room_id: &RoomId,
343 user_id: &UserId,
344 ) -> Result<Option<StoredRoomKeyBundleData>, Self::Error>;
345
346 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>, Self::Error>;
352
353 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<(), Self::Error>;
361
362 async fn remove_custom_value(&self, key: &str) -> Result<(), Self::Error>;
368
369 async fn try_take_leased_lock(
381 &self,
382 lease_duration_ms: u32,
383 key: &str,
384 holder: &str,
385 ) -> Result<bool, Self::Error>;
386
387 async fn next_batch_token(&self) -> Result<Option<String>, Self::Error>;
389}
390
391#[repr(transparent)]
392struct EraseCryptoStoreError<T>(T);
393
394#[cfg(not(tarpaulin_include))]
395impl<T: fmt::Debug> fmt::Debug for EraseCryptoStoreError<T> {
396 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
397 self.0.fmt(f)
398 }
399}
400
401#[cfg_attr(target_family = "wasm", async_trait(?Send))]
402#[cfg_attr(not(target_family = "wasm"), async_trait)]
403impl<T: CryptoStore> CryptoStore for EraseCryptoStoreError<T> {
404 type Error = CryptoStoreError;
405
406 async fn load_account(&self) -> Result<Option<Account>> {
407 self.0.load_account().await.map_err(Into::into)
408 }
409
410 async fn load_identity(&self) -> Result<Option<PrivateCrossSigningIdentity>> {
411 self.0.load_identity().await.map_err(Into::into)
412 }
413
414 async fn save_changes(&self, changes: Changes) -> Result<()> {
415 self.0.save_changes(changes).await.map_err(Into::into)
416 }
417
418 async fn save_pending_changes(&self, changes: PendingChanges) -> Result<()> {
419 self.0.save_pending_changes(changes).await.map_err(Into::into)
420 }
421
422 async fn save_inbound_group_sessions(
423 &self,
424 sessions: Vec<InboundGroupSession>,
425 backed_up_to_version: Option<&str>,
426 ) -> Result<()> {
427 self.0.save_inbound_group_sessions(sessions, backed_up_to_version).await.map_err(Into::into)
428 }
429
430 async fn get_sessions(&self, sender_key: &str) -> Result<Option<Vec<Session>>> {
431 self.0.get_sessions(sender_key).await.map_err(Into::into)
432 }
433
434 async fn get_inbound_group_session(
435 &self,
436 room_id: &RoomId,
437 session_id: &str,
438 ) -> Result<Option<InboundGroupSession>> {
439 self.0.get_inbound_group_session(room_id, session_id).await.map_err(Into::into)
440 }
441
442 async fn get_inbound_group_sessions(&self) -> Result<Vec<InboundGroupSession>> {
443 self.0.get_inbound_group_sessions().await.map_err(Into::into)
444 }
445
446 async fn get_inbound_group_sessions_by_room_id(
447 &self,
448 room_id: &RoomId,
449 ) -> Result<Vec<InboundGroupSession>> {
450 self.0.get_inbound_group_sessions_by_room_id(room_id).await.map_err(Into::into)
451 }
452
453 async fn get_inbound_group_sessions_for_device_batch(
454 &self,
455 curve_key: Curve25519PublicKey,
456 sender_data_type: SenderDataType,
457 after_session_id: Option<String>,
458 limit: usize,
459 ) -> Result<Vec<InboundGroupSession>> {
460 self.0
461 .get_inbound_group_sessions_for_device_batch(
462 curve_key,
463 sender_data_type,
464 after_session_id,
465 limit,
466 )
467 .await
468 .map_err(Into::into)
469 }
470
471 async fn inbound_group_session_counts(
472 &self,
473 backup_version: Option<&str>,
474 ) -> Result<RoomKeyCounts> {
475 self.0.inbound_group_session_counts(backup_version).await.map_err(Into::into)
476 }
477 async fn inbound_group_sessions_for_backup(
478 &self,
479 backup_version: &str,
480 limit: usize,
481 ) -> Result<Vec<InboundGroupSession>> {
482 self.0.inbound_group_sessions_for_backup(backup_version, limit).await.map_err(Into::into)
483 }
484
485 async fn mark_inbound_group_sessions_as_backed_up(
486 &self,
487 backup_version: &str,
488 room_and_session_ids: &[(&RoomId, &str)],
489 ) -> Result<()> {
490 self.0
491 .mark_inbound_group_sessions_as_backed_up(backup_version, room_and_session_ids)
492 .await
493 .map_err(Into::into)
494 }
495
496 async fn reset_backup_state(&self) -> Result<()> {
497 self.0.reset_backup_state().await.map_err(Into::into)
498 }
499
500 async fn load_backup_keys(&self) -> Result<BackupKeys> {
501 self.0.load_backup_keys().await.map_err(Into::into)
502 }
503
504 async fn load_dehydrated_device_pickle_key(&self) -> Result<Option<DehydratedDeviceKey>> {
505 self.0.load_dehydrated_device_pickle_key().await.map_err(Into::into)
506 }
507
508 async fn delete_dehydrated_device_pickle_key(&self) -> Result<(), Self::Error> {
509 self.0.delete_dehydrated_device_pickle_key().await.map_err(Into::into)
510 }
511
512 async fn get_outbound_group_session(
513 &self,
514 room_id: &RoomId,
515 ) -> Result<Option<OutboundGroupSession>> {
516 self.0.get_outbound_group_session(room_id).await.map_err(Into::into)
517 }
518
519 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>> {
520 self.0.load_tracked_users().await.map_err(Into::into)
521 }
522
523 async fn save_tracked_users(&self, users: &[(&UserId, bool)]) -> Result<()> {
524 self.0.save_tracked_users(users).await.map_err(Into::into)
525 }
526
527 async fn get_device(
528 &self,
529 user_id: &UserId,
530 device_id: &DeviceId,
531 ) -> Result<Option<DeviceData>> {
532 self.0.get_device(user_id, device_id).await.map_err(Into::into)
533 }
534
535 async fn get_user_devices(
536 &self,
537 user_id: &UserId,
538 ) -> Result<HashMap<OwnedDeviceId, DeviceData>> {
539 self.0.get_user_devices(user_id).await.map_err(Into::into)
540 }
541
542 async fn get_own_device(&self) -> Result<DeviceData> {
543 self.0.get_own_device().await.map_err(Into::into)
544 }
545
546 async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<UserIdentityData>> {
547 self.0.get_user_identity(user_id).await.map_err(Into::into)
548 }
549
550 async fn is_message_known(&self, message_hash: &OlmMessageHash) -> Result<bool> {
551 self.0.is_message_known(message_hash).await.map_err(Into::into)
552 }
553
554 async fn get_outgoing_secret_requests(
555 &self,
556 request_id: &TransactionId,
557 ) -> Result<Option<GossipRequest>> {
558 self.0.get_outgoing_secret_requests(request_id).await.map_err(Into::into)
559 }
560
561 async fn get_secret_request_by_info(
562 &self,
563 secret_info: &SecretInfo,
564 ) -> Result<Option<GossipRequest>> {
565 self.0.get_secret_request_by_info(secret_info).await.map_err(Into::into)
566 }
567
568 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>> {
569 self.0.get_unsent_secret_requests().await.map_err(Into::into)
570 }
571
572 async fn delete_outgoing_secret_requests(&self, request_id: &TransactionId) -> Result<()> {
573 self.0.delete_outgoing_secret_requests(request_id).await.map_err(Into::into)
574 }
575
576 async fn get_secrets_from_inbox(
577 &self,
578 secret_name: &SecretName,
579 ) -> Result<Vec<GossippedSecret>> {
580 self.0.get_secrets_from_inbox(secret_name).await.map_err(Into::into)
581 }
582
583 async fn delete_secrets_from_inbox(&self, secret_name: &SecretName) -> Result<()> {
584 self.0.delete_secrets_from_inbox(secret_name).await.map_err(Into::into)
585 }
586
587 async fn get_withheld_info(
588 &self,
589 room_id: &RoomId,
590 session_id: &str,
591 ) -> Result<Option<RoomKeyWithheldEvent>, Self::Error> {
592 self.0.get_withheld_info(room_id, session_id).await.map_err(Into::into)
593 }
594
595 async fn get_room_settings(&self, room_id: &RoomId) -> Result<Option<RoomSettings>> {
596 self.0.get_room_settings(room_id).await.map_err(Into::into)
597 }
598
599 async fn get_received_room_key_bundle_data(
600 &self,
601 room_id: &RoomId,
602 user_id: &UserId,
603 ) -> Result<Option<StoredRoomKeyBundleData>> {
604 self.0.get_received_room_key_bundle_data(room_id, user_id).await.map_err(Into::into)
605 }
606
607 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>, Self::Error> {
608 self.0.get_custom_value(key).await.map_err(Into::into)
609 }
610
611 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<(), Self::Error> {
612 self.0.set_custom_value(key, value).await.map_err(Into::into)
613 }
614
615 async fn remove_custom_value(&self, key: &str) -> Result<(), Self::Error> {
616 self.0.remove_custom_value(key).await.map_err(Into::into)
617 }
618
619 async fn try_take_leased_lock(
620 &self,
621 lease_duration_ms: u32,
622 key: &str,
623 holder: &str,
624 ) -> Result<bool, Self::Error> {
625 self.0.try_take_leased_lock(lease_duration_ms, key, holder).await.map_err(Into::into)
626 }
627
628 async fn next_batch_token(&self) -> Result<Option<String>, Self::Error> {
629 self.0.next_batch_token().await.map_err(Into::into)
630 }
631}
632
633pub type DynCryptoStore = dyn CryptoStore<Error = CryptoStoreError>;
635
636pub trait IntoCryptoStore {
642 #[doc(hidden)]
643 fn into_crypto_store(self) -> Arc<DynCryptoStore>;
644}
645
646impl<T> IntoCryptoStore for T
647where
648 T: CryptoStore + 'static,
649{
650 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
651 Arc::new(EraseCryptoStoreError(self))
652 }
653}
654
655impl<T> IntoCryptoStore for Arc<T>
658where
659 T: CryptoStore + 'static,
660{
661 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
662 let ptr: *const T = Arc::into_raw(self);
663 let ptr_erased = ptr as *const EraseCryptoStoreError<T>;
664 unsafe { Arc::from_raw(ptr_erased) }
667 }
668}
669
670impl IntoCryptoStore for Arc<DynCryptoStore> {
671 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
672 self
673 }
674}