core_crypto_keystore/
error.rs

1/// Error type to represent various errors that can happen in the KeyStore
2#[derive(Debug, thiserror::Error)]
3pub enum CryptoKeystoreError {
4    #[error("The given key doesn't contain valid utf-8")]
5    KeyReprError(#[from] std::str::Utf8Error),
6    #[error("A transaction must be in progress to perform this operation.")]
7    MutatingOperationWithoutTransaction,
8    #[error("Cannot perform the operation \"{attempted_operation:?}\" while a transaction is in progress.")]
9    TransactionInProgress { attempted_operation: String },
10    #[error(transparent)]
11    TryFromSliceError(#[from] std::array::TryFromSliceError),
12    #[error("One of the Keystore locks has been poisoned")]
13    LockPoisonError,
14    #[error("The keystore has run out of keypackage bundles!")]
15    OutOfKeyPackageBundles,
16    #[error("Incorrect API usage: {0}")]
17    IncorrectApiUsage(&'static str),
18    #[error("The credential tied to this signature keypair is different from the provided one")]
19    SignatureKeyPairDoesNotBelongToCredential,
20    #[error("The uniqueness constraint has been violated for {0}")]
21    AlreadyExists(&'static str),
22    #[error("The provided buffer is too big to be persisted in the store")]
23    BlobTooBig,
24    #[error("This database connection has been closed")]
25    Closed,
26    #[error(transparent)]
27    KeyStoreValueTransformError(#[from] postcard::Error),
28    #[error(transparent)]
29    IoError(#[from] std::io::Error),
30    #[cfg(not(target_os = "unknown"))]
31    #[error(transparent)]
32    TimeError(#[from] std::time::SystemTimeError),
33    #[cfg(target_os = "unknown")]
34    #[error(transparent)]
35    ChannelError(#[from] std::sync::mpsc::TryRecvError),
36    #[cfg(target_os = "unknown")]
37    #[error("The task has been canceled")]
38    WasmExecutorError,
39    #[error("aead::Error: {0}")]
40    AesGcmError(&'static str),
41    #[cfg(target_os = "unknown")]
42    #[error("{0}")]
43    SerdeWasmBindgenError(String),
44    #[error(transparent)]
45    DbError(#[from] rusqlite::Error),
46    #[error(transparent)]
47    DbMigrationError(#[from] Box<refinery::Error>),
48    #[cfg(test)]
49    #[error(transparent)]
50    MlsKeyPackageIdError(#[from] openmls::prelude::KeyPackageIdError),
51    #[cfg(test)]
52    #[error(transparent)]
53    MlsExtensionError(#[from] openmls::prelude::ExtensionError),
54    #[error("Invalid database key size, expected {expected}, got {actual}")]
55    InvalidDbKeySize { expected: usize, actual: usize },
56    #[cfg(feature = "proteus-keystore")]
57    #[error("Invalid key [{key}] size, expected {expected}, got {actual}")]
58    InvalidKeySize {
59        expected: usize,
60        actual: usize,
61        key: &'static str,
62    },
63    #[cfg(feature = "proteus-keystore")]
64    #[error(transparent)]
65    ParseIntError(#[from] std::num::ParseIntError),
66    #[cfg(feature = "proteus-keystore")]
67    #[error("Could not find a free prekey id")]
68    NoFreePrekeyId,
69    #[error("{0}")]
70    MlsKeyStoreError(String),
71    #[error(transparent)]
72    HexDecodeError(#[from] hex::FromHexError),
73    #[error(transparent)]
74    FromUtf8Error(#[from] std::string::FromUtf8Error),
75    #[cfg(target_os = "ios")]
76    #[error(transparent)]
77    HexSaltDecodeError(hex::FromHexError),
78    #[cfg(target_os = "ios")]
79    #[error(transparent)]
80    SecurityFrameworkError(#[from] security_framework::base::Error),
81    #[cfg(target_os = "unknown")]
82    #[error("{0}")]
83    JsError(String),
84    #[error("Not implemented (and probably never will)")]
85    NotImplemented,
86    #[error("Failed getting current timestamp")]
87    TimestampError,
88    #[error("Could not find {0} in keystore with value {1}")]
89    NotFound(&'static str, String),
90    #[error(transparent)]
91    SerdeJsonError(#[from] serde_json::Error),
92    #[cfg(target_os = "unknown")]
93    #[error(transparent)]
94    IdbError(#[from] idb::Error),
95    #[cfg(target_os = "unknown")]
96    #[error(transparent)]
97    IdbErrorCryptoKeystoreV1_0_0(idb::Error),
98    #[cfg(target_os = "unknown")]
99    #[error("Migration from version {0} is not supported")]
100    MigrationNotSupported(u32),
101    #[error("The migration failed: {0}")]
102    MigrationFailed(String),
103    #[error("the provided bytes could not be interpreted as the primary key of {0}")]
104    InvalidPrimaryKeyBytes(&'static str),
105    #[error("the collection name {0} is unknown and could not be found")]
106    UnknownCollectionName(&'static str),
107    #[cfg(target_os = "unknown")]
108    #[error("{context}")]
109    RelaxedIdbError {
110        context: &'static str,
111        #[source]
112        error: sqlite_wasm_vfs::relaxed_idb::RelaxedIdbError,
113    },
114}
115
116impl CryptoKeystoreError {
117    #[cfg(target_os = "unknown")]
118    pub(crate) fn relaxed_idb(
119        context: &'static str,
120    ) -> impl FnOnce(sqlite_wasm_vfs::relaxed_idb::RelaxedIdbError) -> Self {
121        move |error| Self::RelaxedIdbError { context, error }
122    }
123}
124
125#[cfg(target_os = "unknown")]
126impl From<wasm_bindgen::JsValue> for CryptoKeystoreError {
127    fn from(jsv: wasm_bindgen::JsValue) -> Self {
128        Self::JsError(jsv.as_string().unwrap())
129    }
130}
131
132#[cfg(target_os = "unknown")]
133#[allow(clippy::from_over_into)]
134impl Into<wasm_bindgen::JsValue> for CryptoKeystoreError {
135    fn into(self) -> wasm_bindgen::JsValue {
136        wasm_bindgen::JsValue::from_str(&self.to_string())
137    }
138}
139
140#[cfg(target_os = "unknown")]
141impl From<serde_wasm_bindgen::Error> for CryptoKeystoreError {
142    fn from(jsv: serde_wasm_bindgen::Error) -> Self {
143        Self::SerdeWasmBindgenError(jsv.to_string())
144    }
145}
146
147#[cfg(feature = "proteus-keystore")]
148impl proteus_traits::ProteusErrorCode for CryptoKeystoreError {
149    fn code(&self) -> proteus_traits::ProteusErrorKind {
150        use proteus_traits::ProteusErrorKind;
151        match self {
152            CryptoKeystoreError::KeyReprError(_) => ProteusErrorKind::DecodeError,
153            CryptoKeystoreError::TryFromSliceError(_) => ProteusErrorKind::DecodeError,
154            CryptoKeystoreError::LockPoisonError => ProteusErrorKind::OtherSystemError,
155            CryptoKeystoreError::BlobTooBig => ProteusErrorKind::IoError,
156            CryptoKeystoreError::KeyStoreValueTransformError(_) => ProteusErrorKind::DecodeError,
157            CryptoKeystoreError::IoError(_) => ProteusErrorKind::IoError,
158            #[cfg(not(target_os = "unknown"))]
159            CryptoKeystoreError::DbError(_) => ProteusErrorKind::IoError,
160            #[cfg(not(target_os = "unknown"))]
161            CryptoKeystoreError::DbMigrationError(_) => ProteusErrorKind::IoError,
162            CryptoKeystoreError::InvalidKeySize { .. } => ProteusErrorKind::InvalidArrayLen,
163            CryptoKeystoreError::ParseIntError(_) => ProteusErrorKind::DecodeError,
164            CryptoKeystoreError::HexDecodeError(_) => ProteusErrorKind::DecodeError,
165            CryptoKeystoreError::FromUtf8Error(_) => ProteusErrorKind::DecodeError,
166            _ => unreachable!(),
167        }
168    }
169}
170
171/// A specialized Result for the KeyStore functions
172pub type CryptoKeystoreResult<T> = Result<T, CryptoKeystoreError>;