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