1use crate::mls::conversation::config::MAX_PAST_EPOCHS;
18use crate::prelude::{E2eIdentityError, MlsCredentialType};
19
20#[cfg(all(feature = "cryptobox-migrate", target_family = "wasm"))]
21use rexie;
22
23#[derive(Debug, thiserror::Error, strum::IntoStaticStr)]
25#[cfg_attr(feature = "uniffi", derive(uniffi::Error))]
26#[cfg_attr(feature = "uniffi", uniffi(flat_error))]
27pub enum CryptoError {
28 #[error("End to end identity error")]
30 E2eiError(#[from] E2eIdentityError),
31 #[error("Couldn't find conversation")]
33 ConversationNotFound(crate::prelude::ConversationId),
34 #[error("Conversation already exists")]
36 ConversationAlreadyExists(crate::prelude::ConversationId),
37 #[error("Couldn't find client")]
39 ClientNotFound(crate::prelude::ClientId),
40 #[error("Couldn't find pending proposal {0}")]
42 PendingProposalNotFound(crate::mls::proposal::MlsProposalRef),
43 #[error("Couldn't find pending commit")]
45 PendingCommitNotFound,
46 #[error("Malformed or empty identifier found: {0}")]
48 MalformedIdentifier(&'static str),
49 #[error("The provided client signature has not been found in the keystore")]
51 ClientSignatureNotFound,
52 #[error("The keystore already contains a stored identity. Cannot create a new one!")]
54 IdentityAlreadyPresent,
55 #[error(
57 r#"The externally-generated client ID initialization cannot continue - there's no provisional keypair in-store!
58
59 Have you called `CoreCrypto::generate_raw_keypair` ?"#
60 )]
61 NoProvisionalIdentityFound,
62 #[error(
67 "Somehow CoreCrypto holds more than one MLS identity. Something might've gone very wrong with this client!"
68 )]
69 TooManyIdentitiesPresent,
70 #[error("One of the locks has been poisoned")]
72 LockPoisonError,
73 #[error("We have done something terribly wrong and it needs to be fixed")]
75 ImplementationError,
76 #[error("Tried to insert an already existing CredentialBundle")]
78 CredentialBundleConflict,
79 #[error("The consumer of this library has misused it")]
81 ConsumerError,
82 #[error(transparent)]
84 MlsProviderError(#[from] mls_crypto_provider::MlsProviderError),
85 #[error(transparent)]
87 KeyStoreError(#[from] core_crypto_keystore::CryptoKeystoreError),
88 #[error(transparent)]
90 MlsError(MlsError),
91 #[cfg(test)]
93 #[error(transparent)]
94 UuidError(#[from] uuid::Error),
95 #[error(transparent)]
97 Utf8Error(#[from] std::str::Utf8Error),
98 #[error(transparent)]
100 StringUtf8Error(#[from] std::string::FromUtf8Error),
101 #[error(transparent)]
103 ParseIntError(#[from] std::num::ParseIntError),
104 #[error(transparent)]
106 ConvertIntError(#[from] std::num::TryFromIntError),
107 #[error(transparent)]
109 HexDecodeError(#[from] hex::FromHexError),
110 #[error("Byte array supplied did not have the expected size {0}")]
112 InvalidByteArrayError(usize),
113 #[error(transparent)]
115 IoError(#[from] std::io::Error),
116 #[error("The current client id isn't authorized to perform this action")]
118 Unauthorized,
119 #[error("The callbacks needed for CoreCrypto to operate were not set")]
121 CallbacksNotSet,
122 #[error("External add proposal validation failed: only users already in the group are allowed")]
124 UnauthorizedExternalAddProposal,
125 #[error("External Commit sender was not authorized to perform such")]
127 UnauthorizedExternalCommit,
128 #[error("A supplied reference is not of the expected size: 16")]
130 InvalidHashReference,
131 #[error("Decrypted an application message from the wrong epoch")]
133 DecryptionError,
134 #[error("Incoming message is from a prior epoch")]
136 StaleMessage,
137 #[error("Incoming message is a commit for which we have not yet received all the proposals. Buffering until all proposals have arrived.")]
141 BufferedCommit,
142 #[error("Incoming message is from an epoch too far in the future to buffer.")]
144 WrongEpoch,
145 #[error("Incoming message is for a future epoch. We will buffer it until the commit for that epoch arrives")]
147 BufferedFutureMessage {
148 message_epoch: u64,
150 },
151 #[error(transparent)]
153 ProteusError(#[from] ProteusError),
154 #[error(transparent)]
156 CryptoboxMigrationError(#[from] CryptoboxMigrationError),
157 #[error("Proteus client hasn't been initialized")]
159 ProteusNotInitialized,
160 #[error("CoreCrypto hasn't been built with Proteus support enabled; The feature `{0}` isn't enabled")]
162 ProteusSupportNotEnabled(String),
163 #[error("A MLS operation was requested but MLS hasn't been initialized on this instance")]
165 MlsNotInitialized,
166 #[error("Decrypted message uses an invalid KeyPackage")]
168 InvalidKeyPackage,
169 #[error("Client presented an invalid identity")]
171 InvalidIdentity,
172 #[error("MLS Client was not initialized the right way")]
174 IdentityInitializationError,
175 #[error("The specified parent group has not been found in the keystore")]
177 ParentGroupNotFound,
178 #[error("The epoch in which message was encrypted is older than {MAX_PAST_EPOCHS}")]
180 MessageEpochTooOld,
181 #[error("End-to-end identity enrollment has not been done")]
183 E2eiEnrollmentNotDone,
184 #[error("A Credential of type {0:?} was not found locally which is very likely an implementation error")]
186 CredentialNotFound(MlsCredentialType),
187 #[error("The MLS group is in an invalid state for an unknown reason")]
189 InternalMlsError,
190 #[error("We already decrypted this message once")]
192 DuplicateMessage,
193 #[cfg(test)]
195 #[error("This method leaks entities whereas it's not supposed to")]
196 LeakEntities,
197 #[cfg(test)]
199 #[error("This method does not create new entities whereas it's supposed to")]
200 NoEntityCreated,
201 #[error("Happens when a client creates a commit, sends it to the DS which accepts it but then client \
206 clears this pending commit and creates another commit. This is triggered when the client tries to decrypt the original commit.\
207 This means something is very wrong in the client's code and has to be fixed immediately")]
208 ClearingPendingCommitError,
209 #[error("Tried to decrypt a commit created by self which is likely to have been replayed by the DS")]
211 SelfCommitIgnored,
212 #[error(
214 "You tried to join with an external commit but did not merge it yet. We will reapply this message for you when you merge your external commit"
215 )]
216 UnmergedPendingGroup,
217 #[error(transparent)]
219 X509CertDerError(#[from] x509_cert::der::Error),
220 #[error(transparent)]
222 PemError(#[from] pem::PemError),
223 #[error("Could not find domain name in the certificate")]
225 DomainNameNotFound,
226 #[error("The provided domain name and the one found in the certificate don't match")]
228 DomainNamesDontMatch,
229 #[error("A trust anchor with the provided domain name already exists in the group's context extensions")]
232 DuplicateDomainName,
233 #[error("The certificate chain is invalid or not complete")]
235 InvalidCertificateChain,
236 #[error("The update anchors parameters can't be empty")]
238 EmptyTrustAnchorUpdate,
239 #[error("The certificate chain is already in the group's context")]
241 DuplicateCertificateChain,
242 #[error("Although this Welcome seems valid, the local KeyPackage it references has already been deleted locally. Join this group with an external commit")]
247 OrphanWelcome,
248 #[error("The encountered ClientId does not match Wire's definition")]
250 InvalidClientId,
251 #[error(transparent)]
253 JsonError(#[from] serde_json::Error),
254 #[error("The received commit is deemed stale and is from an older epoch.")]
256 StaleCommit,
257 #[error("The received proposal is deemed stale and is from an older epoch.")]
259 StaleProposal,
260 #[error("The group lacks an ExternalSender extension whereas it should have at least one")]
262 MissingExternalSenderExtension,
263 #[error("Not supported for the moment")]
265 Unsupported,
266 #[error("This context has already been finished and can no longer be used.")]
268 InvalidContext,
269}
270
271impl From<MlsError> for CryptoError {
272 fn from(err: MlsError) -> Self {
273 match err {
274 MlsError::MlsAddMembersError(openmls::prelude::AddMembersError::KeyPackageVerifyError(
275 openmls::key_packages::errors::KeyPackageVerifyError::InvalidLeafNode(
276 openmls::prelude::LeafNodeValidationError::InvalidCredential(
277 openmls::credentials::errors::CredentialError::AuthenticationServiceValidationFailure(
278 openmls_traits::authentication_service::CredentialAuthenticationStatus::Invalid,
279 ),
280 ),
281 ),
282 )) => Self::InvalidIdentity,
283 e => Self::MlsError(e),
284 }
285 }
286}
287
288pub type CryptoResult<T> = Result<T, CryptoError>;
290
291impl CryptoError {
292 pub fn proteus_error_code(&self) -> Option<u16> {
294 if let Self::ProteusError(e) = self {
295 e.error_code()
296 } else {
297 None
298 }
299 }
300}
301
302#[derive(Debug, thiserror::Error, strum::IntoStaticStr)]
304pub enum MlsError {
305 #[error(transparent)]
307 MlsWelcomeError(#[from] openmls::prelude::WelcomeError<core_crypto_keystore::CryptoKeystoreError>),
308 #[error(transparent)]
310 MlsLibraryError(#[from] openmls::error::LibraryError),
311 #[error(transparent)]
313 MlsInvalidMessageError(#[from] openmls::prelude::CreateMessageError),
314 #[error(transparent)]
316 MlsEmptyInputError(#[from] openmls::prelude::EmptyInputError),
317 #[error(transparent)]
319 MlsCredentialError(#[from] openmls::prelude::CredentialError),
320 #[error(transparent)]
322 MlsNewGroupError(#[from] openmls::prelude::NewGroupError<core_crypto_keystore::CryptoKeystoreError>),
323 #[error(transparent)]
325 MlsAddMembersError(#[from] openmls::prelude::AddMembersError<core_crypto_keystore::CryptoKeystoreError>),
326 #[error(transparent)]
328 MlsRemoveMembersError(#[from] openmls::prelude::RemoveMembersError<core_crypto_keystore::CryptoKeystoreError>),
329 #[error(transparent)]
331 MlsMessageError(#[from] openmls::prelude::ProcessMessageError),
332 #[error(transparent)]
334 MlsKeyPackageBundleNewError(
335 #[from] openmls::prelude::KeyPackageNewError<core_crypto_keystore::CryptoKeystoreError>,
336 ),
337 #[error(transparent)]
339 MlsSelfUpdateError(#[from] openmls::prelude::SelfUpdateError<core_crypto_keystore::CryptoKeystoreError>),
340 #[error(transparent)]
342 MlsMlsGroupStateError(#[from] openmls::prelude::MlsGroupStateError),
343 #[error(transparent)]
345 ProposeAddMemberError(#[from] openmls::prelude::ProposeAddMemberError),
346 #[error(transparent)]
348 ProposeSelfUpdateError(#[from] openmls::prelude::ProposeSelfUpdateError<core_crypto_keystore::CryptoKeystoreError>),
349 #[error(transparent)]
351 ProposeRemoveMemberError(#[from] openmls::prelude::ProposeRemoveMemberError),
352 #[error(transparent)]
354 MlsCommitToPendingProposalsError(
355 #[from] openmls::prelude::CommitToPendingProposalsError<core_crypto_keystore::CryptoKeystoreError>,
356 ),
357 #[error(transparent)]
359 MlsExportGroupInfoError(#[from] openmls::prelude::ExportGroupInfoError),
360 #[error(transparent)]
362 MlsTlsCodecError(#[from] tls_codec::Error),
363 #[error(transparent)]
366 MlsKeystoreSerializationError(#[from] serde_json::Error),
367 #[error(transparent)]
370 MlsErrorString(#[from] openmls::error::ErrorString),
371 #[error(transparent)]
373 MlsExternalCommitError(#[from] openmls::prelude::ExternalCommitError),
374 #[error(transparent)]
376 MlsCryptoError(#[from] openmls::prelude::CryptoError),
377 #[error(transparent)]
379 MlsExportSecretError(#[from] openmls::prelude::ExportSecretError),
380 #[error(transparent)]
382 MlsMergeCommitError(#[from] openmls::prelude::MergeCommitError<core_crypto_keystore::CryptoKeystoreError>),
383 #[error(transparent)]
385 MlsKeyPackageValidationError(#[from] openmls::prelude::KeyPackageVerifyError),
386 #[error(transparent)]
388 MlsMergePendingCommitError(
389 #[from] openmls::prelude::MergePendingCommitError<core_crypto_keystore::CryptoKeystoreError>,
390 ),
391 #[error(transparent)]
393 MlsEncryptMessageError(#[from] openmls::framing::errors::MlsMessageError),
394 #[error(transparent)]
396 MlsDeleteKeyPackageError(
397 #[from] openmls::key_packages::errors::KeyPackageDeleteError<core_crypto_keystore::CryptoKeystoreError>,
398 ),
399 #[error(transparent)]
401 MlsUpdateExtensionsError(
402 #[from] openmls::prelude::UpdateExtensionsError<core_crypto_keystore::CryptoKeystoreError>,
403 ),
404 #[error(transparent)]
406 MlsLeafNodeValidationError(#[from] openmls::prelude::LeafNodeValidationError),
407 #[error(transparent)]
409 RatchetTreeError(#[from] openmls::treesync::RatchetTreeError),
410 #[error(transparent)]
412 GroupInfoError(#[from] openmls::messages::group_info::GroupInfoError),
413}
414
415#[derive(Debug, thiserror::Error, strum::IntoStaticStr)]
416pub enum ProteusError {
418 #[cfg(feature = "proteus")]
419 #[error(transparent)]
420 ProteusDecodeError(#[from] proteus_wasm::DecodeError),
422 #[cfg(feature = "proteus")]
423 #[error(transparent)]
424 ProteusEncodeError(#[from] proteus_wasm::EncodeError),
426 #[cfg(feature = "proteus")]
427 #[error(transparent)]
428 ProteusInternalError(#[from] proteus_wasm::error::ProteusError),
430 #[cfg(feature = "proteus")]
431 #[error(transparent)]
432 ProteusSessionError(#[from] proteus_wasm::session::Error<core_crypto_keystore::CryptoKeystoreError>),
434}
435
436impl ProteusError {
437 pub fn error_code(&self) -> Option<u16> {
439 cfg_if::cfg_if! {
440 if #[cfg(feature = "proteus")] {
441 use proteus_traits::{ProteusErrorCode as _, ProteusErrorKind};
442 let kind = match self {
443 ProteusError::ProteusDecodeError(e) => e.code(),
444 ProteusError::ProteusEncodeError(e) => e.code(),
445 ProteusError::ProteusSessionError(e) => e.code(),
446 ProteusError::ProteusInternalError(e) => e.code(),
447 };
448 (kind != ProteusErrorKind::None).then_some(kind as u16)
449 } else {
450 None
451 }
452 }
453 }
454}
455
456#[derive(Debug, thiserror::Error, strum::IntoStaticStr)]
457pub enum CryptoboxMigrationError {
459 #[cfg(all(feature = "cryptobox-migrate", target_family = "wasm"))]
460 #[error(transparent)]
461 RexieError(rexie::Error),
463 #[cfg(all(feature = "cryptobox-migrate", target_family = "wasm"))]
464 #[error(transparent)]
465 IdbError(idb::Error),
467 #[cfg(all(feature = "cryptobox-migrate", target_family = "wasm"))]
468 #[error(transparent)]
469 JsonParseError(#[from] serde_wasm_bindgen::Error),
471 #[cfg(all(feature = "cryptobox-migrate", target_family = "wasm"))]
472 #[error(transparent)]
473 Base64DecodeError(#[from] base64::DecodeError),
475 #[error("The targeted value does not possess the targeted key ({0})")]
476 MissingKeyInValue(String),
478 #[error("The value cannot be coerced to the {0} type")]
479 WrongValueType(String),
481 #[cfg_attr(target_family = "wasm", error("The provided path [{0}] could not be found."))]
482 #[cfg_attr(
483 not(target_family = "wasm"),
484 error("The provided path store [{0}] is either non-existent or has an incorrect shape.")
485 )]
486 ProvidedPathDoesNotExist(String),
488 #[error("The Cryptobox identity at path [{0}] could not be found.")]
489 IdentityNotFound(String),
491}
492
493#[cfg(all(feature = "cryptobox-migrate", target_family = "wasm"))]
494impl From<rexie::Error> for CryptoboxMigrationError {
495 fn from(e: rexie::Error) -> Self {
496 match e {
497 rexie::Error::IdbError(e) => Self::IdbError(e),
498 _ => Self::RexieError(e),
499 }
500 }
501}