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_for_device_batch(
158 &self,
159 curve_key: Curve25519PublicKey,
160 sender_data_type: SenderDataType,
161 after_session_id: Option<String>,
162 limit: usize,
163 ) -> Result<Vec<InboundGroupSession>, Self::Error>;
164
165 async fn inbound_group_sessions_for_backup(
173 &self,
174 backup_version: &str,
175 limit: usize,
176 ) -> Result<Vec<InboundGroupSession>, Self::Error>;
177
178 async fn mark_inbound_group_sessions_as_backed_up(
184 &self,
185 backup_version: &str,
186 room_and_session_ids: &[(&RoomId, &str)],
187 ) -> Result<(), Self::Error>;
188
189 async fn reset_backup_state(&self) -> Result<(), Self::Error>;
198
199 async fn load_backup_keys(&self) -> Result<BackupKeys, Self::Error>;
201
202 async fn load_dehydrated_device_pickle_key(
204 &self,
205 ) -> Result<Option<DehydratedDeviceKey>, Self::Error>;
206
207 async fn delete_dehydrated_device_pickle_key(&self) -> Result<(), Self::Error>;
209
210 async fn get_outbound_group_session(
213 &self,
214 room_id: &RoomId,
215 ) -> Result<Option<OutboundGroupSession>, Self::Error>;
216
217 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>, Self::Error>;
220
221 async fn save_tracked_users(&self, users: &[(&UserId, bool)]) -> Result<(), Self::Error>;
226
227 async fn get_device(
235 &self,
236 user_id: &UserId,
237 device_id: &DeviceId,
238 ) -> Result<Option<DeviceData>, Self::Error>;
239
240 async fn get_user_devices(
246 &self,
247 user_id: &UserId,
248 ) -> Result<HashMap<OwnedDeviceId, DeviceData>, Self::Error>;
249
250 async fn get_own_device(&self) -> Result<DeviceData, Self::Error>;
255
256 async fn get_user_identity(
262 &self,
263 user_id: &UserId,
264 ) -> Result<Option<UserIdentityData>, Self::Error>;
265
266 async fn is_message_known(&self, message_hash: &OlmMessageHash) -> Result<bool, Self::Error>;
268
269 async fn get_outgoing_secret_requests(
277 &self,
278 request_id: &TransactionId,
279 ) -> Result<Option<GossipRequest>, Self::Error>;
280
281 async fn get_secret_request_by_info(
288 &self,
289 secret_info: &SecretInfo,
290 ) -> Result<Option<GossipRequest>, Self::Error>;
291
292 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>, Self::Error>;
294
295 async fn delete_outgoing_secret_requests(
303 &self,
304 request_id: &TransactionId,
305 ) -> Result<(), Self::Error>;
306
307 async fn get_secrets_from_inbox(
310 &self,
311 secret_name: &SecretName,
312 ) -> Result<Vec<GossippedSecret>, Self::Error>;
313
314 async fn delete_secrets_from_inbox(&self, secret_name: &SecretName) -> Result<(), Self::Error>;
317
318 async fn get_room_settings(
325 &self,
326 room_id: &RoomId,
327 ) -> Result<Option<RoomSettings>, Self::Error>;
328
329 async fn get_received_room_key_bundle_data(
332 &self,
333 room_id: &RoomId,
334 user_id: &UserId,
335 ) -> Result<Option<StoredRoomKeyBundleData>, Self::Error>;
336
337 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>, Self::Error>;
343
344 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<(), Self::Error>;
352
353 async fn remove_custom_value(&self, key: &str) -> Result<(), Self::Error>;
359
360 async fn try_take_leased_lock(
372 &self,
373 lease_duration_ms: u32,
374 key: &str,
375 holder: &str,
376 ) -> Result<bool, Self::Error>;
377
378 async fn next_batch_token(&self) -> Result<Option<String>, Self::Error>;
380}
381
382#[repr(transparent)]
383struct EraseCryptoStoreError<T>(T);
384
385#[cfg(not(tarpaulin_include))]
386impl<T: fmt::Debug> fmt::Debug for EraseCryptoStoreError<T> {
387 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
388 self.0.fmt(f)
389 }
390}
391
392#[cfg_attr(target_family = "wasm", async_trait(?Send))]
393#[cfg_attr(not(target_family = "wasm"), async_trait)]
394impl<T: CryptoStore> CryptoStore for EraseCryptoStoreError<T> {
395 type Error = CryptoStoreError;
396
397 async fn load_account(&self) -> Result<Option<Account>> {
398 self.0.load_account().await.map_err(Into::into)
399 }
400
401 async fn load_identity(&self) -> Result<Option<PrivateCrossSigningIdentity>> {
402 self.0.load_identity().await.map_err(Into::into)
403 }
404
405 async fn save_changes(&self, changes: Changes) -> Result<()> {
406 self.0.save_changes(changes).await.map_err(Into::into)
407 }
408
409 async fn save_pending_changes(&self, changes: PendingChanges) -> Result<()> {
410 self.0.save_pending_changes(changes).await.map_err(Into::into)
411 }
412
413 async fn save_inbound_group_sessions(
414 &self,
415 sessions: Vec<InboundGroupSession>,
416 backed_up_to_version: Option<&str>,
417 ) -> Result<()> {
418 self.0.save_inbound_group_sessions(sessions, backed_up_to_version).await.map_err(Into::into)
419 }
420
421 async fn get_sessions(&self, sender_key: &str) -> Result<Option<Vec<Session>>> {
422 self.0.get_sessions(sender_key).await.map_err(Into::into)
423 }
424
425 async fn get_inbound_group_session(
426 &self,
427 room_id: &RoomId,
428 session_id: &str,
429 ) -> Result<Option<InboundGroupSession>> {
430 self.0.get_inbound_group_session(room_id, session_id).await.map_err(Into::into)
431 }
432
433 async fn get_inbound_group_sessions(&self) -> Result<Vec<InboundGroupSession>> {
434 self.0.get_inbound_group_sessions().await.map_err(Into::into)
435 }
436
437 async fn get_inbound_group_sessions_for_device_batch(
438 &self,
439 curve_key: Curve25519PublicKey,
440 sender_data_type: SenderDataType,
441 after_session_id: Option<String>,
442 limit: usize,
443 ) -> Result<Vec<InboundGroupSession>> {
444 self.0
445 .get_inbound_group_sessions_for_device_batch(
446 curve_key,
447 sender_data_type,
448 after_session_id,
449 limit,
450 )
451 .await
452 .map_err(Into::into)
453 }
454
455 async fn inbound_group_session_counts(
456 &self,
457 backup_version: Option<&str>,
458 ) -> Result<RoomKeyCounts> {
459 self.0.inbound_group_session_counts(backup_version).await.map_err(Into::into)
460 }
461 async fn inbound_group_sessions_for_backup(
462 &self,
463 backup_version: &str,
464 limit: usize,
465 ) -> Result<Vec<InboundGroupSession>> {
466 self.0.inbound_group_sessions_for_backup(backup_version, limit).await.map_err(Into::into)
467 }
468
469 async fn mark_inbound_group_sessions_as_backed_up(
470 &self,
471 backup_version: &str,
472 room_and_session_ids: &[(&RoomId, &str)],
473 ) -> Result<()> {
474 self.0
475 .mark_inbound_group_sessions_as_backed_up(backup_version, room_and_session_ids)
476 .await
477 .map_err(Into::into)
478 }
479
480 async fn reset_backup_state(&self) -> Result<()> {
481 self.0.reset_backup_state().await.map_err(Into::into)
482 }
483
484 async fn load_backup_keys(&self) -> Result<BackupKeys> {
485 self.0.load_backup_keys().await.map_err(Into::into)
486 }
487
488 async fn load_dehydrated_device_pickle_key(&self) -> Result<Option<DehydratedDeviceKey>> {
489 self.0.load_dehydrated_device_pickle_key().await.map_err(Into::into)
490 }
491
492 async fn delete_dehydrated_device_pickle_key(&self) -> Result<(), Self::Error> {
493 self.0.delete_dehydrated_device_pickle_key().await.map_err(Into::into)
494 }
495
496 async fn get_outbound_group_session(
497 &self,
498 room_id: &RoomId,
499 ) -> Result<Option<OutboundGroupSession>> {
500 self.0.get_outbound_group_session(room_id).await.map_err(Into::into)
501 }
502
503 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>> {
504 self.0.load_tracked_users().await.map_err(Into::into)
505 }
506
507 async fn save_tracked_users(&self, users: &[(&UserId, bool)]) -> Result<()> {
508 self.0.save_tracked_users(users).await.map_err(Into::into)
509 }
510
511 async fn get_device(
512 &self,
513 user_id: &UserId,
514 device_id: &DeviceId,
515 ) -> Result<Option<DeviceData>> {
516 self.0.get_device(user_id, device_id).await.map_err(Into::into)
517 }
518
519 async fn get_user_devices(
520 &self,
521 user_id: &UserId,
522 ) -> Result<HashMap<OwnedDeviceId, DeviceData>> {
523 self.0.get_user_devices(user_id).await.map_err(Into::into)
524 }
525
526 async fn get_own_device(&self) -> Result<DeviceData> {
527 self.0.get_own_device().await.map_err(Into::into)
528 }
529
530 async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<UserIdentityData>> {
531 self.0.get_user_identity(user_id).await.map_err(Into::into)
532 }
533
534 async fn is_message_known(&self, message_hash: &OlmMessageHash) -> Result<bool> {
535 self.0.is_message_known(message_hash).await.map_err(Into::into)
536 }
537
538 async fn get_outgoing_secret_requests(
539 &self,
540 request_id: &TransactionId,
541 ) -> Result<Option<GossipRequest>> {
542 self.0.get_outgoing_secret_requests(request_id).await.map_err(Into::into)
543 }
544
545 async fn get_secret_request_by_info(
546 &self,
547 secret_info: &SecretInfo,
548 ) -> Result<Option<GossipRequest>> {
549 self.0.get_secret_request_by_info(secret_info).await.map_err(Into::into)
550 }
551
552 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>> {
553 self.0.get_unsent_secret_requests().await.map_err(Into::into)
554 }
555
556 async fn delete_outgoing_secret_requests(&self, request_id: &TransactionId) -> Result<()> {
557 self.0.delete_outgoing_secret_requests(request_id).await.map_err(Into::into)
558 }
559
560 async fn get_secrets_from_inbox(
561 &self,
562 secret_name: &SecretName,
563 ) -> Result<Vec<GossippedSecret>> {
564 self.0.get_secrets_from_inbox(secret_name).await.map_err(Into::into)
565 }
566
567 async fn delete_secrets_from_inbox(&self, secret_name: &SecretName) -> Result<()> {
568 self.0.delete_secrets_from_inbox(secret_name).await.map_err(Into::into)
569 }
570
571 async fn get_withheld_info(
572 &self,
573 room_id: &RoomId,
574 session_id: &str,
575 ) -> Result<Option<RoomKeyWithheldEvent>, Self::Error> {
576 self.0.get_withheld_info(room_id, session_id).await.map_err(Into::into)
577 }
578
579 async fn get_room_settings(&self, room_id: &RoomId) -> Result<Option<RoomSettings>> {
580 self.0.get_room_settings(room_id).await.map_err(Into::into)
581 }
582
583 async fn get_received_room_key_bundle_data(
584 &self,
585 room_id: &RoomId,
586 user_id: &UserId,
587 ) -> Result<Option<StoredRoomKeyBundleData>> {
588 self.0.get_received_room_key_bundle_data(room_id, user_id).await.map_err(Into::into)
589 }
590
591 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>, Self::Error> {
592 self.0.get_custom_value(key).await.map_err(Into::into)
593 }
594
595 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<(), Self::Error> {
596 self.0.set_custom_value(key, value).await.map_err(Into::into)
597 }
598
599 async fn remove_custom_value(&self, key: &str) -> Result<(), Self::Error> {
600 self.0.remove_custom_value(key).await.map_err(Into::into)
601 }
602
603 async fn try_take_leased_lock(
604 &self,
605 lease_duration_ms: u32,
606 key: &str,
607 holder: &str,
608 ) -> Result<bool, Self::Error> {
609 self.0.try_take_leased_lock(lease_duration_ms, key, holder).await.map_err(Into::into)
610 }
611
612 async fn next_batch_token(&self) -> Result<Option<String>, Self::Error> {
613 self.0.next_batch_token().await.map_err(Into::into)
614 }
615}
616
617pub type DynCryptoStore = dyn CryptoStore<Error = CryptoStoreError>;
619
620pub trait IntoCryptoStore {
626 #[doc(hidden)]
627 fn into_crypto_store(self) -> Arc<DynCryptoStore>;
628}
629
630impl<T> IntoCryptoStore for T
631where
632 T: CryptoStore + 'static,
633{
634 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
635 Arc::new(EraseCryptoStoreError(self))
636 }
637}
638
639impl<T> IntoCryptoStore for Arc<T>
642where
643 T: CryptoStore + 'static,
644{
645 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
646 let ptr: *const T = Arc::into_raw(self);
647 let ptr_erased = ptr as *const EraseCryptoStoreError<T>;
648 unsafe { Arc::from_raw(ptr_erased) }
651 }
652}
653
654impl IntoCryptoStore for Arc<DynCryptoStore> {
655 fn into_crypto_store(self) -> Arc<DynCryptoStore> {
656 self
657 }
658}