Skip to main content

matrix_sdk_crypto_ffi/
error.rs

1#![allow(missing_docs)]
2
3use matrix_sdk_crypto::{
4    KeyExportError, MegolmError, OlmError, SecretImportError as RustSecretImportError,
5    SignatureError as InnerSignatureError,
6    store::{CryptoStoreError as InnerStoreError, DehydrationError as InnerDehydrationError},
7};
8use matrix_sdk_sqlite::OpenStoreError;
9use ruma::{IdParseError, OwnedUserId};
10
11#[derive(Debug, thiserror::Error, uniffi::Error)]
12#[uniffi(flat_error)]
13pub enum KeyImportError {
14    #[error(transparent)]
15    Export(#[from] KeyExportError),
16    #[error(transparent)]
17    CryptoStore(#[from] InnerStoreError),
18    #[error(transparent)]
19    Json(#[from] serde_json::Error),
20}
21
22#[derive(Debug, thiserror::Error, uniffi::Error)]
23#[uniffi(flat_error)]
24pub enum SecretImportError {
25    #[error(transparent)]
26    CryptoStore(#[from] InnerStoreError),
27    #[error(transparent)]
28    Import(#[from] RustSecretImportError),
29}
30
31#[derive(Debug, thiserror::Error, uniffi::Error)]
32#[uniffi(flat_error)]
33pub enum SignatureError {
34    #[error(transparent)]
35    Signature(#[from] InnerSignatureError),
36    #[error(transparent)]
37    Identifier(#[from] IdParseError),
38    #[error(transparent)]
39    CryptoStore(#[from] InnerStoreError),
40    #[error("Unknown device {0} {1}")]
41    UnknownDevice(OwnedUserId, String),
42    #[error("Unknown user identity {0}")]
43    UnknownUserIdentity(String),
44}
45
46#[derive(Debug, thiserror::Error, uniffi::Error)]
47#[uniffi(flat_error)]
48pub enum CryptoStoreError {
49    #[error("Failed to open the store")]
50    OpenStore(#[from] OpenStoreError),
51    #[error(transparent)]
52    CryptoStore(#[from] InnerStoreError),
53    #[error(transparent)]
54    OlmError(#[from] OlmError),
55    #[error(transparent)]
56    Serialization(#[from] serde_json::Error),
57    #[error("The given string is not a valid user ID: source {0}, error {1}")]
58    InvalidUserId(String, IdParseError),
59    #[error(transparent)]
60    Identifier(#[from] IdParseError),
61    #[error(transparent)]
62    DehydrationError(#[from] InnerDehydrationError),
63}
64
65#[derive(Debug, thiserror::Error, uniffi::Error)]
66pub enum DecryptionError {
67    #[error("serialization error: {error}")]
68    Serialization { error: String },
69    #[error("identifier parsing error: {error}")]
70    Identifier { error: String },
71    #[error("megolm error: {error}")]
72    Megolm { error: String },
73    #[error("missing room key: {error}")]
74    MissingRoomKey { error: String, withheld_code: Option<String> },
75    #[error("store error: {error}")]
76    Store { error: String },
77}
78
79#[derive(Debug, thiserror::Error, uniffi::Error)]
80pub enum BootstrapCrossSigningError {
81    #[error(transparent)]
82    CryptoStore(CryptoStoreError),
83    #[error(transparent)]
84    Signature(SignatureError),
85}
86
87/// Error describing what went wrong when exporting a [`SecretsBundle`].
88///
89/// The [`SecretsBundle`] can only be exported if we have all cross-signing
90/// private keys in the store.
91#[derive(Debug, thiserror::Error, uniffi::Error)]
92pub enum SecretsBundleExportError {
93    /// The store itself had an error.
94    #[error(transparent)]
95    CryptoStore(CryptoStoreError),
96    /// We're missing one or more cross-signing keys.
97    #[error("The store doesn't contain all the cross-signing keys")]
98    MissingCrossSigningKeys,
99    /// We have a backup key stored, but we don't know the version of the
100    /// backup.
101    #[error("The store contains a backup key, but no backup version")]
102    MissingBackupVersion,
103    #[error("serialization error: {error}")]
104    Serialization { error: String },
105}
106
107impl From<matrix_sdk_crypto::store::SecretsBundleExportError> for SecretsBundleExportError {
108    fn from(value: matrix_sdk_crypto::store::SecretsBundleExportError) -> Self {
109        match value {
110            matrix_sdk_crypto::store::SecretsBundleExportError::Store(e) => {
111                Self::CryptoStore(e.into())
112            }
113            matrix_sdk_crypto::store::SecretsBundleExportError::MissingCrossSigningKey(_)
114            | matrix_sdk_crypto::store::SecretsBundleExportError::MissingCrossSigningKeys => {
115                Self::MissingCrossSigningKeys
116            }
117            matrix_sdk_crypto::store::SecretsBundleExportError::MissingBackupVersion => {
118                Self::MissingBackupVersion
119            }
120        }
121    }
122}
123
124impl From<serde_json::Error> for SecretsBundleExportError {
125    fn from(err: serde_json::Error) -> Self {
126        Self::Serialization { error: err.to_string() }
127    }
128}
129
130impl From<MegolmError> for DecryptionError {
131    fn from(value: MegolmError) -> Self {
132        match &value {
133            MegolmError::MissingRoomKey(withheld_code) => Self::MissingRoomKey {
134                error: value.to_string(),
135                withheld_code: withheld_code.as_ref().map(|w| w.as_str().to_owned()),
136            },
137            _ => Self::Megolm { error: value.to_string() },
138        }
139    }
140}
141
142impl From<serde_json::Error> for DecryptionError {
143    fn from(err: serde_json::Error) -> Self {
144        Self::Serialization { error: err.to_string() }
145    }
146}
147
148impl From<IdParseError> for DecryptionError {
149    fn from(err: IdParseError) -> Self {
150        Self::Identifier { error: err.to_string() }
151    }
152}
153
154impl From<InnerStoreError> for DecryptionError {
155    fn from(err: InnerStoreError) -> Self {
156        Self::Store { error: err.to_string() }
157    }
158}
159
160impl From<matrix_sdk_crypto::BootstrapCrossSigningError> for BootstrapCrossSigningError {
161    fn from(err: matrix_sdk_crypto::BootstrapCrossSigningError) -> Self {
162        use matrix_sdk_crypto::BootstrapCrossSigningError as BCSE;
163        match err {
164            BCSE::CryptoStore(e) => Self::CryptoStore(e.into()),
165            BCSE::Signature(e) => Self::Signature(e.into()),
166        }
167    }
168}
169
170#[cfg(test)]
171mod tests {
172    use assert_matches2::assert_let;
173    use matrix_sdk_crypto::MegolmError;
174
175    use super::DecryptionError;
176
177    #[test]
178    fn test_withheld_error_mapping() {
179        use matrix_sdk_common::deserialized_responses::WithheldCode;
180
181        let inner_error = MegolmError::MissingRoomKey(Some(WithheldCode::Unverified));
182
183        let binding_error: DecryptionError = inner_error.into();
184
185        assert_let!(
186            DecryptionError::MissingRoomKey { error: _, withheld_code: Some(code) } = binding_error
187        );
188        assert_eq!("m.unverified", code)
189    }
190}