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 BackupKeys, Changes, CryptoStoreError, DehydratedDeviceKey, PendingChanges, Result,
26 RoomKeyCounts, RoomSettings, StoredRoomKeyBundleData,
27};
28#[cfg(doc)]
29use crate::olm::SenderData;
30use crate::{
31 olm::{
32 InboundGroupSession, OlmMessageHash, OutboundGroupSession, PrivateCrossSigningIdentity,
33 SenderDataType, Session,
34 },
35 types::events::room_key_withheld::RoomKeyWithheldEvent,
36 Account, DeviceData, GossipRequest, GossippedSecret, SecretInfo, TrackedUser, UserIdentityData,
37};
38
39#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
42#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
43pub trait CryptoStore: AsyncTraitDeps {
44 type Error: fmt::Debug + Into<CryptoStoreError>;
46
47 async fn load_account(&self) -> Result<Option<Account>, Self::Error>;
49
50 async fn load_identity(&self) -> Result<Option<PrivateCrossSigningIdentity>, Self::Error>;
52
53 async fn save_changes(&self, changes: Changes) -> Result<(), Self::Error>;
59
60 async fn save_pending_changes(&self, changes: PendingChanges) -> Result<(), Self::Error>;
69
70 async fn save_inbound_group_sessions(
81 &self,
82 sessions: Vec<InboundGroupSession>,
83 backed_up_to_version: Option<&str>,
84 ) -> Result<(), Self::Error>;
85
86 async fn get_sessions(&self, sender_key: &str) -> Result<Option<Vec<Session>>, Self::Error>;
92
93 async fn get_inbound_group_session(
102 &self,
103 room_id: &RoomId,
104 session_id: &str,
105 ) -> Result<Option<InboundGroupSession>, Self::Error>;
106
107 async fn get_withheld_info(
113 &self,
114 room_id: &RoomId,
115 session_id: &str,
116 ) -> Result<Option<RoomKeyWithheldEvent>, Self::Error>;
117
118 async fn get_inbound_group_sessions(&self) -> Result<Vec<InboundGroupSession>, Self::Error>;
120
121 async fn inbound_group_session_counts(
124 &self,
125 backup_version: Option<&str>,
126 ) -> Result<RoomKeyCounts, Self::Error>;
127
128 async fn get_inbound_group_sessions_for_device_batch(
155 &self,
156 curve_key: Curve25519PublicKey,
157 sender_data_type: SenderDataType,
158 after_session_id: Option<String>,
159 limit: usize,
160 ) -> Result<Vec<InboundGroupSession>, Self::Error>;
161
162 async fn inbound_group_sessions_for_backup(
170 &self,
171 backup_version: &str,
172 limit: usize,
173 ) -> Result<Vec<InboundGroupSession>, Self::Error>;
174
175 async fn mark_inbound_group_sessions_as_backed_up(
181 &self,
182 backup_version: &str,
183 room_and_session_ids: &[(&RoomId, &str)],
184 ) -> Result<(), Self::Error>;
185
186 async fn reset_backup_state(&self) -> Result<(), Self::Error>;
195
196 async fn load_backup_keys(&self) -> Result<BackupKeys, Self::Error>;
198
199 async fn load_dehydrated_device_pickle_key(
201 &self,
202 ) -> Result<Option<DehydratedDeviceKey>, Self::Error>;
203
204 async fn delete_dehydrated_device_pickle_key(&self) -> Result<(), Self::Error>;
206
207 async fn get_outbound_group_session(
210 &self,
211 room_id: &RoomId,
212 ) -> Result<Option<OutboundGroupSession>, Self::Error>;
213
214 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>, Self::Error>;
217
218 async fn save_tracked_users(&self, users: &[(&UserId, bool)]) -> Result<(), Self::Error>;
223
224 async fn get_device(
232 &self,
233 user_id: &UserId,
234 device_id: &DeviceId,
235 ) -> Result<Option<DeviceData>, Self::Error>;
236
237 async fn get_user_devices(
243 &self,
244 user_id: &UserId,
245 ) -> Result<HashMap<OwnedDeviceId, DeviceData>, Self::Error>;
246
247 async fn get_own_device(&self) -> Result<DeviceData, Self::Error>;
252
253 async fn get_user_identity(
259 &self,
260 user_id: &UserId,
261 ) -> Result<Option<UserIdentityData>, Self::Error>;
262
263 async fn is_message_known(&self, message_hash: &OlmMessageHash) -> Result<bool, Self::Error>;
265
266 async fn get_outgoing_secret_requests(
274 &self,
275 request_id: &TransactionId,
276 ) -> Result<Option<GossipRequest>, Self::Error>;
277
278 async fn get_secret_request_by_info(
285 &self,
286 secret_info: &SecretInfo,
287 ) -> Result<Option<GossipRequest>, Self::Error>;
288
289 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>, Self::Error>;
291
292 async fn delete_outgoing_secret_requests(
300 &self,
301 request_id: &TransactionId,
302 ) -> Result<(), Self::Error>;
303
304 async fn get_secrets_from_inbox(
307 &self,
308 secret_name: &SecretName,
309 ) -> Result<Vec<GossippedSecret>, Self::Error>;
310
311 async fn delete_secrets_from_inbox(&self, secret_name: &SecretName) -> Result<(), Self::Error>;
314
315 async fn get_room_settings(
322 &self,
323 room_id: &RoomId,
324 ) -> Result<Option<RoomSettings>, Self::Error>;
325
326 async fn get_received_room_key_bundle_data(
329 &self,
330 room_id: &RoomId,
331 user_id: &UserId,
332 ) -> Result<Option<StoredRoomKeyBundleData>, Self::Error>;
333
334 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>, Self::Error>;
340
341 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<(), Self::Error>;
349
350 async fn remove_custom_value(&self, key: &str) -> Result<(), Self::Error>;
356
357 async fn try_take_leased_lock(
369 &self,
370 lease_duration_ms: u32,
371 key: &str,
372 holder: &str,
373 ) -> Result<bool, Self::Error>;
374
375 async fn next_batch_token(&self) -> Result<Option<String>, Self::Error>;
377}
378
379#[repr(transparent)]
380struct EraseCryptoStoreError<T>(T);
381
382#[cfg(not(tarpaulin_include))]
383impl<T: fmt::Debug> fmt::Debug for EraseCryptoStoreError<T> {
384 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
385 self.0.fmt(f)
386 }
387}
388
389#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
390#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
391impl<T: CryptoStore> CryptoStore for EraseCryptoStoreError<T> {
392 type Error = CryptoStoreError;
393
394 async fn load_account(&self) -> Result<Option<Account>> {
395 self.0.load_account().await.map_err(Into::into)
396 }
397
398 async fn load_identity(&self) -> Result<Option<PrivateCrossSigningIdentity>> {
399 self.0.load_identity().await.map_err(Into::into)
400 }
401
402 async fn save_changes(&self, changes: Changes) -> Result<()> {
403 self.0.save_changes(changes).await.map_err(Into::into)
404 }
405
406 async fn save_pending_changes(&self, changes: PendingChanges) -> Result<()> {
407 self.0.save_pending_changes(changes).await.map_err(Into::into)
408 }
409
410 async fn save_inbound_group_sessions(
411 &self,
412 sessions: Vec<InboundGroupSession>,
413 backed_up_to_version: Option<&str>,
414 ) -> Result<()> {
415 self.0.save_inbound_group_sessions(sessions, backed_up_to_version).await.map_err(Into::into)
416 }
417
418 async fn get_sessions(&self, sender_key: &str) -> Result<Option<Vec<Session>>> {
419 self.0.get_sessions(sender_key).await.map_err(Into::into)
420 }
421
422 async fn get_inbound_group_session(
423 &self,
424 room_id: &RoomId,
425 session_id: &str,
426 ) -> Result<Option<InboundGroupSession>> {
427 self.0.get_inbound_group_session(room_id, session_id).await.map_err(Into::into)
428 }
429
430 async fn get_inbound_group_sessions(&self) -> Result<Vec<InboundGroupSession>> {
431 self.0.get_inbound_group_sessions().await.map_err(Into::into)
432 }
433
434 async fn get_inbound_group_sessions_for_device_batch(
435 &self,
436 curve_key: Curve25519PublicKey,
437 sender_data_type: SenderDataType,
438 after_session_id: Option<String>,
439 limit: usize,
440 ) -> Result<Vec<InboundGroupSession>> {
441 self.0
442 .get_inbound_group_sessions_for_device_batch(
443 curve_key,
444 sender_data_type,
445 after_session_id,
446 limit,
447 )
448 .await
449 .map_err(Into::into)
450 }
451
452 async fn inbound_group_session_counts(
453 &self,
454 backup_version: Option<&str>,
455 ) -> Result<RoomKeyCounts> {
456 self.0.inbound_group_session_counts(backup_version).await.map_err(Into::into)
457 }
458 async fn inbound_group_sessions_for_backup(
459 &self,
460 backup_version: &str,
461 limit: usize,
462 ) -> Result<Vec<InboundGroupSession>> {
463 self.0.inbound_group_sessions_for_backup(backup_version, limit).await.map_err(Into::into)
464 }
465
466 async fn mark_inbound_group_sessions_as_backed_up(
467 &self,
468 backup_version: &str,
469 room_and_session_ids: &[(&RoomId, &str)],
470 ) -> Result<()> {
471 self.0
472 .mark_inbound_group_sessions_as_backed_up(backup_version, room_and_session_ids)
473 .await
474 .map_err(Into::into)
475 }
476
477 async fn reset_backup_state(&self) -> Result<()> {
478 self.0.reset_backup_state().await.map_err(Into::into)
479 }
480
481 async fn load_backup_keys(&self) -> Result<BackupKeys> {
482 self.0.load_backup_keys().await.map_err(Into::into)
483 }
484
485 async fn load_dehydrated_device_pickle_key(&self) -> Result<Option<DehydratedDeviceKey>> {
486 self.0.load_dehydrated_device_pickle_key().await.map_err(Into::into)
487 }
488
489 async fn delete_dehydrated_device_pickle_key(&self) -> Result<(), Self::Error> {
490 self.0.delete_dehydrated_device_pickle_key().await.map_err(Into::into)
491 }
492
493 async fn get_outbound_group_session(
494 &self,
495 room_id: &RoomId,
496 ) -> Result<Option<OutboundGroupSession>> {
497 self.0.get_outbound_group_session(room_id).await.map_err(Into::into)
498 }
499
500 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>> {
501 self.0.load_tracked_users().await.map_err(Into::into)
502 }
503
504 async fn save_tracked_users(&self, users: &[(&UserId, bool)]) -> Result<()> {
505 self.0.save_tracked_users(users).await.map_err(Into::into)
506 }
507
508 async fn get_device(
509 &self,
510 user_id: &UserId,
511 device_id: &DeviceId,
512 ) -> Result<Option<DeviceData>> {
513 self.0.get_device(user_id, device_id).await.map_err(Into::into)
514 }
515
516 async fn get_user_devices(
517 &self,
518 user_id: &UserId,
519 ) -> Result<HashMap<OwnedDeviceId, DeviceData>> {
520 self.0.get_user_devices(user_id).await.map_err(Into::into)
521 }
522
523 async fn get_own_device(&self) -> Result<DeviceData> {
524 self.0.get_own_device().await.map_err(Into::into)
525 }
526
527 async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<UserIdentityData>> {
528 self.0.get_user_identity(user_id).await.map_err(Into::into)
529 }
530
531 async fn is_message_known(&self, message_hash: &OlmMessageHash) -> Result<bool> {
532 self.0.is_message_known(message_hash).await.map_err(Into::into)
533 }
534
535 async fn get_outgoing_secret_requests(
536 &self,
537 request_id: &TransactionId,
538 ) -> Result<Option<GossipRequest>> {
539 self.0.get_outgoing_secret_requests(request_id).await.map_err(Into::into)
540 }
541
542 async fn get_secret_request_by_info(
543 &self,
544 secret_info: &SecretInfo,
545 ) -> Result<Option<GossipRequest>> {
546 self.0.get_secret_request_by_info(secret_info).await.map_err(Into::into)
547 }
548
549 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>> {
550 self.0.get_unsent_secret_requests().await.map_err(Into::into)
551 }
552
553 async fn delete_outgoing_secret_requests(&self, request_id: &TransactionId) -> Result<()> {
554 self.0.delete_outgoing_secret_requests(request_id).await.map_err(Into::into)
555 }
556
557 async fn get_secrets_from_inbox(
558 &self,
559 secret_name: &SecretName,
560 ) -> Result<Vec<GossippedSecret>> {
561 self.0.get_secrets_from_inbox(secret_name).await.map_err(Into::into)
562 }
563
564 async fn delete_secrets_from_inbox(&self, secret_name: &SecretName) -> Result<()> {
565 self.0.delete_secrets_from_inbox(secret_name).await.map_err(Into::into)
566 }
567
568 async fn get_withheld_info(
569 &self,
570 room_id: &RoomId,
571 session_id: &str,
572 ) -> Result<Option<RoomKeyWithheldEvent>, Self::Error> {
573 self.0.get_withheld_info(room_id, session_id).await.map_err(Into::into)
574 }
575
576 async fn get_room_settings(&self, room_id: &RoomId) -> Result<Option<RoomSettings>> {
577 self.0.get_room_settings(room_id).await.map_err(Into::into)
578 }
579
580 async fn get_received_room_key_bundle_data(
581 &self,
582 room_id: &RoomId,
583 user_id: &UserId,
584 ) -> Result<Option<StoredRoomKeyBundleData>> {
585 self.0.get_received_room_key_bundle_data(room_id, user_id).await.map_err(Into::into)
586 }
587
588 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>, Self::Error> {
589 self.0.get_custom_value(key).await.map_err(Into::into)
590 }
591
592 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<(), Self::Error> {
593 self.0.set_custom_value(key, value).await.map_err(Into::into)
594 }
595
596 async fn remove_custom_value(&self, key: &str) -> Result<(), Self::Error> {
597 self.0.remove_custom_value(key).await.map_err(Into::into)
598 }
599
600 async fn try_take_leased_lock(
601 &self,
602 lease_duration_ms: u32,
603 key: &str,
604 holder: &str,
605 ) -> Result<bool, Self::Error> {
606 self.0.try_take_leased_lock(lease_duration_ms, key, holder).await.map_err(Into::into)
607 }
608
609 async fn next_batch_token(&self) -> Result<Option<String>, Self::Error> {
610 self.0.next_batch_token().await.map_err(Into::into)
611 }
612}
613
614pub type DynCryptoStore = dyn CryptoStore<Error = CryptoStoreError>;
616
617pub trait IntoCryptoStore {
623 #[doc(hidden)]
624 fn into_crypto_store(self) -> Arc<DynCryptoStore>;
625}
626
627impl<T> IntoCryptoStore for T
628where
629 T: CryptoStore + 'static,
630{
631 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
632 Arc::new(EraseCryptoStoreError(self))
633 }
634}
635
636impl<T> IntoCryptoStore for Arc<T>
639where
640 T: CryptoStore + 'static,
641{
642 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
643 let ptr: *const T = Arc::into_raw(self);
644 let ptr_erased = ptr as *const EraseCryptoStoreError<T>;
645 unsafe { Arc::from_raw(ptr_erased) }
648 }
649}
650
651impl IntoCryptoStore for Arc<DynCryptoStore> {
652 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
653 self
654 }
655}