core_crypto_keystore/
error.rs

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