core_crypto_keystore/
error.rs

1#[cfg(target_family = "wasm")]
2use crate::keystore_v_1_0_0;
3
4/// Error to represent when a key is not present in the KeyStore
5#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
6pub enum MissingKeyErrorKind {
7    #[error("Consumer Data")]
8    ConsumerData,
9    #[error("MLS KeyPackage")]
10    MlsKeyPackage,
11    #[error("MLS SignatureKeyPair")]
12    MlsSignatureKeyPair,
13    #[error("MLS HpkePrivateKey")]
14    MlsHpkePrivateKey,
15    #[error("MLS EncryptionKeyPair")]
16    MlsEncryptionKeyPair,
17    #[error("MLS Epoch EncryptionKeyPair")]
18    MlsEpochEncryptionKeyPair,
19    #[error("MLS PreSharedKeyBundle")]
20    MlsPskBundle,
21    #[error("MLS CredentialBundle")]
22    MlsCredential,
23    #[error("MLS Buffered Commit")]
24    MlsBufferedCommit,
25    #[error("MLS Persisted Group")]
26    PersistedMlsGroup,
27    #[error("MLS Persisted Pending Group")]
28    MlsPendingGroup,
29    #[error("MLS Pending Messages")]
30    MlsPendingMessages,
31    #[error("End-to-end identity enrollment")]
32    E2eiEnrollment,
33    #[error("OIDC refresh token")]
34    E2eiRefreshToken,
35    #[error("End-to-end identity root trust anchor CA cert")]
36    E2eiAcmeCA,
37    #[error("End-to-end identity intermediate CA cert")]
38    E2eiIntermediateCert,
39    #[error("End-to-end identity CRL")]
40    E2eiCrl,
41    #[cfg(feature = "proteus-keystore")]
42    #[error("Proteus PreKey")]
43    ProteusPrekey,
44    #[cfg(feature = "proteus-keystore")]
45    #[error("Proteus Session")]
46    ProteusSession,
47    #[cfg(feature = "proteus-keystore")]
48    #[error("Proteus Identity")]
49    ProteusIdentity,
50}
51
52/// Error type to represent various errors that can happen in the KeyStore
53#[derive(Debug, thiserror::Error)]
54pub enum CryptoKeystoreError {
55    #[error("The requested {0} is not present in the store")]
56    MissingKeyInStore(#[from] MissingKeyErrorKind),
57    #[error("The given key doesn't contain valid utf-8")]
58    KeyReprError(#[from] std::str::Utf8Error),
59    #[error("A transaction must be in progress to perform this operation.")]
60    MutatingOperationWithoutTransaction,
61    #[error("Cannot perform the operation \"{attempted_operation:?}\" while a transaction is in progress.")]
62    TransactionInProgress { attempted_operation: String },
63    #[error(transparent)]
64    TryFromSliceError(#[from] std::array::TryFromSliceError),
65    #[error("One of the Keystore locks has been poisoned")]
66    LockPoisonError,
67    #[error("The keystore has run out of keypackage bundles!")]
68    OutOfKeyPackageBundles,
69    #[error("Incorrect API usage: {0}")]
70    IncorrectApiUsage(&'static str),
71    #[error("The credential tied to this signature keypair is different from the provided one")]
72    SignatureKeyPairDoesNotBelongToCredential,
73    #[error("A uniqueness constraint has been violated")]
74    AlreadyExists,
75    #[error("The provided buffer is too big to be persisted in the store")]
76    BlobTooBig,
77    #[error("Cannot close as multiple strong refs exist")]
78    CannotClose,
79    #[error(transparent)]
80    KeyStoreValueTransformError(#[from] postcard::Error),
81    #[error(transparent)]
82    IoError(#[from] std::io::Error),
83    #[cfg(not(target_family = "wasm"))]
84    #[error(transparent)]
85    TimeError(#[from] std::time::SystemTimeError),
86    #[cfg(target_family = "wasm")]
87    #[error(transparent)]
88    ChannelError(#[from] std::sync::mpsc::TryRecvError),
89    #[cfg(target_family = "wasm")]
90    #[error("The task has been canceled")]
91    WasmExecutorError,
92    #[cfg(target_family = "wasm")]
93    #[error("aead::Error")]
94    AesGcmError,
95    #[cfg(target_family = "wasm")]
96    #[error("{0}")]
97    SerdeWasmBindgenError(String),
98    #[cfg(not(target_family = "wasm"))]
99    #[error(transparent)]
100    DbError(#[from] rusqlite::Error),
101    #[cfg(not(target_family = "wasm"))]
102    #[error(transparent)]
103    DbMigrationError(#[from] Box<refinery::Error>),
104    #[cfg(test)]
105    #[error(transparent)]
106    MlsKeyPackageIdError(#[from] openmls::prelude::KeyPackageIdError),
107    #[cfg(test)]
108    #[error(transparent)]
109    MlsExtensionError(#[from] openmls::prelude::ExtensionError),
110    #[error("Invalid database key size, expected {expected}, got {actual}")]
111    InvalidDbKeySize { expected: usize, actual: usize },
112    #[cfg(feature = "proteus-keystore")]
113    #[error("Invalid key [{key}] size, expected {expected}, got {actual}")]
114    InvalidKeySize {
115        expected: usize,
116        actual: usize,
117        key: &'static str,
118    },
119    #[cfg(feature = "proteus-keystore")]
120    #[error(transparent)]
121    ParseIntError(#[from] std::num::ParseIntError),
122    #[cfg(feature = "proteus-keystore")]
123    #[error("Could not find a free prekey id")]
124    NoFreePrekeyId,
125    #[error("{0}")]
126    MlsKeyStoreError(String),
127    #[error(transparent)]
128    HexDecodeError(#[from] hex::FromHexError),
129    #[error(transparent)]
130    FromUtf8Error(#[from] std::string::FromUtf8Error),
131    #[cfg(target_os = "ios")]
132    #[error(transparent)]
133    HexSaltDecodeError(hex::FromHexError),
134    #[cfg(target_os = "ios")]
135    #[error(transparent)]
136    SecurityFrameworkError(#[from] security_framework::base::Error),
137    #[cfg(target_family = "wasm")]
138    #[error("{0}")]
139    JsError(String),
140    #[error("Not implemented (and probably never will)")]
141    NotImplemented,
142    #[error("Failed getting current timestamp")]
143    TimestampError,
144    #[error("Could not find {0} in keystore with value {1}")]
145    NotFound(&'static str, String),
146    #[cfg(target_family = "wasm")]
147    #[error(transparent)]
148    SerdeJsonError(#[from] serde_json::Error),
149    #[cfg(target_family = "wasm")]
150    #[error(transparent)]
151    IdbError(#[from] idb::Error),
152    #[cfg(target_family = "wasm")]
153    #[error(transparent)]
154    CryptoKeystoreErrorV1_0_0(keystore_v_1_0_0::CryptoKeystoreError),
155    #[cfg(target_family = "wasm")]
156    #[error(transparent)]
157    IdbErrorCryptoKeystoreV1_0_0(idb::Error),
158    #[cfg(target_family = "wasm")]
159    #[error(transparent)]
160    RexieErrorCryptoKeystoreV1_0_0(rexie::Error),
161    #[cfg(target_family = "wasm")]
162    #[error("Migration from version {0} is not supported")]
163    MigrationNotSupported(u32),
164    #[cfg(target_family = "wasm")]
165    #[error("The migration failed.")]
166    MigrationFailed,
167}
168
169#[cfg(target_family = "wasm")]
170impl From<keystore_v_1_0_0::CryptoKeystoreError> for CryptoKeystoreError {
171    fn from(e: keystore_v_1_0_0::CryptoKeystoreError) -> Self {
172        match e {
173            keystore_v_1_0_0::CryptoKeystoreError::RexieError(rexie_error) => match rexie_error {
174                rexie::Error::IdbError(idb_error) => Self::IdbErrorCryptoKeystoreV1_0_0(idb_error),
175                _ => Self::RexieErrorCryptoKeystoreV1_0_0(rexie_error),
176            },
177            _ => Self::CryptoKeystoreErrorV1_0_0(e),
178        }
179    }
180}
181
182#[cfg(target_family = "wasm")]
183impl From<wasm_bindgen::JsValue> for CryptoKeystoreError {
184    fn from(jsv: wasm_bindgen::JsValue) -> Self {
185        Self::JsError(jsv.as_string().unwrap())
186    }
187}
188
189#[cfg(target_family = "wasm")]
190#[allow(clippy::from_over_into)]
191impl Into<wasm_bindgen::JsValue> for CryptoKeystoreError {
192    fn into(self) -> wasm_bindgen::JsValue {
193        wasm_bindgen::JsValue::from_str(&self.to_string())
194    }
195}
196
197#[cfg(target_family = "wasm")]
198impl From<serde_wasm_bindgen::Error> for CryptoKeystoreError {
199    fn from(jsv: serde_wasm_bindgen::Error) -> Self {
200        Self::SerdeWasmBindgenError(jsv.to_string())
201    }
202}
203
204#[cfg(feature = "proteus-keystore")]
205impl proteus_traits::ProteusErrorCode for CryptoKeystoreError {
206    fn code(&self) -> proteus_traits::ProteusErrorKind {
207        use proteus_traits::ProteusErrorKind;
208        match self {
209            CryptoKeystoreError::MissingKeyInStore(k) => match k {
210                MissingKeyErrorKind::ProteusPrekey => ProteusErrorKind::PreKeyNotFound,
211                MissingKeyErrorKind::ProteusSession => ProteusErrorKind::SessionStateNotFoundForTag,
212                MissingKeyErrorKind::ProteusIdentity => ProteusErrorKind::Unknown,
213                _ => unreachable!(),
214            },
215            CryptoKeystoreError::KeyReprError(_) => ProteusErrorKind::DecodeError,
216            CryptoKeystoreError::TryFromSliceError(_) => ProteusErrorKind::DecodeError,
217            CryptoKeystoreError::LockPoisonError => ProteusErrorKind::OtherSystemError,
218            CryptoKeystoreError::BlobTooBig => ProteusErrorKind::IoError,
219            CryptoKeystoreError::KeyStoreValueTransformError(_) => ProteusErrorKind::DecodeError,
220            CryptoKeystoreError::IoError(_) => ProteusErrorKind::IoError,
221            #[cfg(not(target_family = "wasm"))]
222            CryptoKeystoreError::DbError(_) => ProteusErrorKind::IoError,
223            #[cfg(not(target_family = "wasm"))]
224            CryptoKeystoreError::DbMigrationError(_) => ProteusErrorKind::IoError,
225            CryptoKeystoreError::InvalidKeySize { .. } => ProteusErrorKind::InvalidArrayLen,
226            CryptoKeystoreError::ParseIntError(_) => ProteusErrorKind::DecodeError,
227            CryptoKeystoreError::HexDecodeError(_) => ProteusErrorKind::DecodeError,
228            CryptoKeystoreError::FromUtf8Error(_) => ProteusErrorKind::DecodeError,
229            _ => unreachable!(),
230        }
231    }
232}
233
234/// A specialized Result for the KeyStore functions
235pub type CryptoKeystoreResult<T> = Result<T, CryptoKeystoreError>;