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 #[cfg(target_os = "unknown")]
100 #[error("CoreCrypto 10.x databases are unsupported and must be discarded")]
101 CoreCrypto10DatabaseUnsupported,
102 #[error("The migration failed: {0}")]
103 MigrationFailed(String),
104 #[cfg(target_os = "unknown")]
105 #[error("{context}")]
106 OpfsError {
107 context: &'static str,
108 #[source]
109 error: rsqlite_vfs::VfsError,
110 },
111 #[error("The database includes migrations newer than this version of CC knows about")]
112 DatabaseFromTheFuture,
113}
114
115impl CryptoKeystoreError {
116 pub(crate) fn map_already_exists(table_name: &'static str) -> impl FnOnce(rusqlite::Error) -> Self {
122 move |err| {
123 if let rusqlite::Error::SqliteFailure(inner, _) = err
124 && matches!(
125 inner.extended_code,
126 rusqlite::ffi::SQLITE_CONSTRAINT_UNIQUE | rusqlite::ffi::SQLITE_CONSTRAINT_PRIMARYKEY
127 )
128 {
129 Self::AlreadyExists(table_name)
130 } else {
131 err.into()
132 }
133 }
134 }
135
136 #[cfg(target_os = "unknown")]
137 pub(crate) fn opfs(context: &'static str) -> impl FnOnce(rsqlite_vfs::VfsError) -> Self {
138 move |error| Self::OpfsError { context, error }
139 }
140}
141
142#[cfg(target_os = "unknown")]
143#[expect(clippy::from_over_into)]
144impl Into<wasm_bindgen::JsValue> for CryptoKeystoreError {
145 fn into(self) -> wasm_bindgen::JsValue {
146 wasm_bindgen::JsValue::from_str(&self.to_string())
147 }
148}
149
150#[cfg(target_os = "unknown")]
151impl From<serde_wasm_bindgen::Error> for CryptoKeystoreError {
152 fn from(jsv: serde_wasm_bindgen::Error) -> Self {
153 Self::SerdeWasmBindgenError(jsv.to_string())
154 }
155}
156
157#[cfg(feature = "proteus-keystore")]
158impl proteus_traits::ProteusErrorCode for CryptoKeystoreError {
159 fn code(&self) -> proteus_traits::ProteusErrorKind {
160 use proteus_traits::ProteusErrorKind;
161 match self {
162 CryptoKeystoreError::KeyReprError(_) => ProteusErrorKind::DecodeError,
163 CryptoKeystoreError::TryFromSliceError(_) => ProteusErrorKind::DecodeError,
164 CryptoKeystoreError::LockPoisonError => ProteusErrorKind::OtherSystemError,
165 CryptoKeystoreError::BlobTooBig => ProteusErrorKind::IoError,
166 CryptoKeystoreError::KeyStoreValueTransformError(_) => ProteusErrorKind::DecodeError,
167 CryptoKeystoreError::IoError(_) => ProteusErrorKind::IoError,
168 CryptoKeystoreError::DbError(_) => ProteusErrorKind::IoError,
169 CryptoKeystoreError::DbMigrationError(_) => ProteusErrorKind::IoError,
170 CryptoKeystoreError::InvalidKeySize { .. } => ProteusErrorKind::InvalidArrayLen,
171 CryptoKeystoreError::ParseIntError(_) => ProteusErrorKind::DecodeError,
172 CryptoKeystoreError::HexDecodeError(_) => ProteusErrorKind::DecodeError,
173 CryptoKeystoreError::FromUtf8Error(_) => ProteusErrorKind::DecodeError,
174 _ => unreachable!(),
175 }
176 }
177}
178
179pub type CryptoKeystoreResult<T> = Result<T, CryptoKeystoreError>;