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    StoredKeypackage,
8    #[error("MLS SignatureKeyPair")]
9    StoredSignatureKeypair,
10    #[error("MLS HpkePrivateKey")]
11    StoredHpkePrivateKey,
12    #[error("MLS EncryptionKeyPair")]
13    StoredEncryptionKeyPair,
14    #[error("MLS Epoch EncryptionKeyPair")]
15    StoredEpochEncryptionKeypair,
16    #[error("MLS PreSharedKeyBundle")]
17    StoredPskBundle,
18    #[error("MLS Credential")]
19    StoredCredential,
20    #[error("MLS Buffered Commit")]
21    StoredBufferedCommit,
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    StoredE2eiEnrollment,
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("This database connection has been closed")]
75    Closed,
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    #[error("aead::Error")]
90    AesGcmError,
91    #[cfg(target_family = "wasm")]
92    #[error("{0}")]
93    SerdeWasmBindgenError(String),
94    #[cfg(not(target_family = "wasm"))]
95    #[error(transparent)]
96    DbError(#[from] rusqlite::Error),
97    #[cfg(not(target_family = "wasm"))]
98    #[error(transparent)]
99    DbMigrationError(#[from] Box<refinery::Error>),
100    #[cfg(test)]
101    #[error(transparent)]
102    MlsKeyPackageIdError(#[from] openmls::prelude::KeyPackageIdError),
103    #[cfg(test)]
104    #[error(transparent)]
105    MlsExtensionError(#[from] openmls::prelude::ExtensionError),
106    #[error("Invalid database key size, expected {expected}, got {actual}")]
107    InvalidDbKeySize { expected: usize, actual: usize },
108    #[cfg(feature = "proteus-keystore")]
109    #[error("Invalid key [{key}] size, expected {expected}, got {actual}")]
110    InvalidKeySize {
111        expected: usize,
112        actual: usize,
113        key: &'static str,
114    },
115    #[cfg(feature = "proteus-keystore")]
116    #[error(transparent)]
117    ParseIntError(#[from] std::num::ParseIntError),
118    #[cfg(feature = "proteus-keystore")]
119    #[error("Could not find a free prekey id")]
120    NoFreePrekeyId,
121    #[error("{0}")]
122    MlsKeyStoreError(String),
123    #[error(transparent)]
124    HexDecodeError(#[from] hex::FromHexError),
125    #[error(transparent)]
126    FromUtf8Error(#[from] std::string::FromUtf8Error),
127    #[cfg(target_os = "ios")]
128    #[error(transparent)]
129    HexSaltDecodeError(hex::FromHexError),
130    #[cfg(target_os = "ios")]
131    #[error(transparent)]
132    SecurityFrameworkError(#[from] security_framework::base::Error),
133    #[cfg(target_family = "wasm")]
134    #[error("{0}")]
135    JsError(String),
136    #[error("Not implemented (and probably never will)")]
137    NotImplemented,
138    #[error("Failed getting current timestamp")]
139    TimestampError,
140    #[error("Could not find {0} in keystore with value {1}")]
141    NotFound(&'static str, String),
142    #[error(transparent)]
143    SerdeJsonError(#[from] serde_json::Error),
144    #[cfg(target_family = "wasm")]
145    #[error(transparent)]
146    IdbError(#[from] idb::Error),
147    #[cfg(target_family = "wasm")]
148    #[error(transparent)]
149    IdbErrorCryptoKeystoreV1_0_0(idb::Error),
150    #[cfg(target_family = "wasm")]
151    #[error("Migration from version {0} is not supported")]
152    MigrationNotSupported(u32),
153    #[error("The migration failed: {0}")]
154    MigrationFailed(String),
155    #[error("the provided bytes could not be interpreted as the primary key of {0}")]
156    InvalidPrimaryKeyBytes(&'static str),
157    #[error("the collection name {0} is unknown and could not be found")]
158    UnknownCollectionName(&'static str),
159}
160
161#[cfg(target_family = "wasm")]
162impl From<wasm_bindgen::JsValue> for CryptoKeystoreError {
163    fn from(jsv: wasm_bindgen::JsValue) -> Self {
164        Self::JsError(jsv.as_string().unwrap())
165    }
166}
167
168#[cfg(target_family = "wasm")]
169#[allow(clippy::from_over_into)]
170impl Into<wasm_bindgen::JsValue> for CryptoKeystoreError {
171    fn into(self) -> wasm_bindgen::JsValue {
172        wasm_bindgen::JsValue::from_str(&self.to_string())
173    }
174}
175
176#[cfg(target_family = "wasm")]
177impl From<serde_wasm_bindgen::Error> for CryptoKeystoreError {
178    fn from(jsv: serde_wasm_bindgen::Error) -> Self {
179        Self::SerdeWasmBindgenError(jsv.to_string())
180    }
181}
182
183#[cfg(feature = "proteus-keystore")]
184impl proteus_traits::ProteusErrorCode for CryptoKeystoreError {
185    fn code(&self) -> proteus_traits::ProteusErrorKind {
186        use proteus_traits::ProteusErrorKind;
187        match self {
188            CryptoKeystoreError::MissingKeyInStore(k) => match k {
189                MissingKeyErrorKind::ProteusPrekey => ProteusErrorKind::PreKeyNotFound,
190                MissingKeyErrorKind::ProteusSession => ProteusErrorKind::SessionStateNotFoundForTag,
191                MissingKeyErrorKind::ProteusIdentity => ProteusErrorKind::Unknown,
192                _ => unreachable!(),
193            },
194            CryptoKeystoreError::KeyReprError(_) => ProteusErrorKind::DecodeError,
195            CryptoKeystoreError::TryFromSliceError(_) => ProteusErrorKind::DecodeError,
196            CryptoKeystoreError::LockPoisonError => ProteusErrorKind::OtherSystemError,
197            CryptoKeystoreError::BlobTooBig => ProteusErrorKind::IoError,
198            CryptoKeystoreError::KeyStoreValueTransformError(_) => ProteusErrorKind::DecodeError,
199            CryptoKeystoreError::IoError(_) => ProteusErrorKind::IoError,
200            #[cfg(not(target_family = "wasm"))]
201            CryptoKeystoreError::DbError(_) => ProteusErrorKind::IoError,
202            #[cfg(not(target_family = "wasm"))]
203            CryptoKeystoreError::DbMigrationError(_) => ProteusErrorKind::IoError,
204            CryptoKeystoreError::InvalidKeySize { .. } => ProteusErrorKind::InvalidArrayLen,
205            CryptoKeystoreError::ParseIntError(_) => ProteusErrorKind::DecodeError,
206            CryptoKeystoreError::HexDecodeError(_) => ProteusErrorKind::DecodeError,
207            CryptoKeystoreError::FromUtf8Error(_) => ProteusErrorKind::DecodeError,
208            _ => unreachable!(),
209        }
210    }
211}
212
213/// A specialized Result for the KeyStore functions
214pub type CryptoKeystoreResult<T> = Result<T, CryptoKeystoreError>;