core_crypto_keystore/
error.rs

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