Skip to main content

passless_rs/storage/
mod.rs

1//! Storage implementations for credentials
2//!
3//! This module provides storage backends for FIDO2 credentials.
4
5pub mod credential;
6pub mod index;
7pub mod local;
8pub mod pass;
9mod pass_refresh;
10pub mod rp_id;
11#[cfg(feature = "tpm")]
12pub mod tpm;
13
14// Internal credential type with controlled serialization
15#[allow(unused_imports)]
16pub(crate) use credential::Credential;
17pub use local::LocalStorageAdapter;
18pub use pass_refresh::PassStorageAdapter;
19pub use rp_id::ValidatedRpId;
20#[cfg(feature = "tpm")]
21pub use tpm::TpmStorageAdapter;
22
23use soft_fido2::Result;
24
25/// Filter criteria for reading credentials
26#[derive(Debug, Clone)]
27pub enum CredentialFilter {
28    /// No filter - return all credentials
29    None,
30    /// Filter by credential ID
31    #[allow(dead_code)]
32    ById(Vec<u8>),
33    /// Filter by relying party ID
34    ByRp(String),
35    /// Filter by relying party ID hash
36    #[allow(dead_code)]
37    ByHash([u8; 32]),
38}
39
40/// Trait defining the storage interface for credentials
41///
42/// Any storage backend must implement this trait.
43pub trait CredentialStorage: Send + Sync {
44    /// Start a new iteration and return the first matching credential
45    fn read_first(&mut self, filter: CredentialFilter) -> Result<soft_fido2::Credential>;
46
47    /// Continue the current iteration and return the next credential
48    fn read_next(&mut self) -> Result<soft_fido2::Credential>;
49
50    /// Read a specific credential by ID and RP
51    fn read(&mut self, id: &[u8]) -> Result<soft_fido2::Credential>;
52
53    /// Store a new credential
54    fn write(&mut self, cred: soft_fido2::CredentialRef) -> Result<()>;
55
56    /// Delete a credential by ID
57    fn delete(&mut self, id: &[u8]) -> Result<()>;
58
59    /// Count total number of stored credentials
60    fn count_credentials(&self) -> usize;
61
62    /// Check if user verification should be disabled for this backend
63    ///
64    /// Some backends (like pass) don't support user verification.
65    /// The default implementation returns false (UV enabled).
66    ///
67    /// # Returns
68    ///
69    /// true if UV should be disabled, false otherwise
70    fn disable_user_verification(&self) -> bool {
71        false
72    }
73
74    /// Cleanup expired cache entries (if caching is supported)
75    ///
76    /// This method should be called periodically to ensure cached credentials
77    /// don't remain in memory beyond their TTL, even when idle.
78    ///
79    /// Default implementation does nothing (for backends without caching).
80    ///
81    /// # Security
82    ///
83    /// Important for security: ensures sensitive data is removed promptly.
84    fn cleanup_expired_cache(&mut self) {
85        // Default: no-op for backends that don't cache
86    }
87}
88
89impl CredentialStorage for Box<dyn CredentialStorage> {
90    fn read_first(&mut self, filter: CredentialFilter) -> Result<soft_fido2::Credential> {
91        (**self).read_first(filter)
92    }
93
94    fn read_next(&mut self) -> Result<soft_fido2::Credential> {
95        (**self).read_next()
96    }
97
98    fn read(&mut self, id: &[u8]) -> Result<soft_fido2::Credential> {
99        (**self).read(id)
100    }
101
102    fn write(&mut self, cred: soft_fido2::CredentialRef) -> Result<()> {
103        (**self).write(cred)
104    }
105
106    fn delete(&mut self, id: &[u8]) -> Result<()> {
107        (**self).delete(id)
108    }
109
110    fn count_credentials(&self) -> usize {
111        (**self).count_credentials()
112    }
113
114    fn disable_user_verification(&self) -> bool {
115        (**self).disable_user_verification()
116    }
117
118    fn cleanup_expired_cache(&mut self) {
119        (**self).cleanup_expired_cache()
120    }
121}