1use thiserror::Error;
6
7#[cfg(feature = "extensions-draft-08")]
8use super::public_group::errors::ApplyAppDataUpdateError;
9
10pub use super::mls_group::errors::*;
11use super::public_group::errors::CreationFromExternalError;
12use crate::{
13 ciphersuite::signable::SignatureError,
14 error::LibraryError,
15 extensions::errors::{ExtensionError, InvalidExtensionError},
16 framing::errors::MessageDecryptionError,
17 group::commit_builder::external_commits::ExternalCommitBuilderError,
18 key_packages::errors::{KeyPackageExtensionSupportError, KeyPackageVerifyError},
19 messages::{group_info::GroupInfoError, GroupSecretsError},
20 prelude::ExtensionType,
21 schedule::{errors::PskError, PreSharedKeyId},
22 treesync::errors::*,
23};
24
25#[cfg(doc)]
26use crate::{group::GroupId, treesync::LeafNodeParameters};
27
28#[derive(Error, Debug, PartialEq, Clone)]
30pub enum WelcomeError<StorageError> {
31 #[error(transparent)]
33 GroupSecrets(#[from] GroupSecretsError),
34 #[error("Private part of `init_key` not found in key store.")]
36 PrivateInitKeyNotFound,
37 #[error(transparent)]
39 LibraryError(#[from] LibraryError),
40 #[error("Ciphersuites in Welcome and key package bundle don't match.")]
42 CiphersuiteMismatch,
43 #[error(transparent)]
45 GroupInfo(#[from] GroupInfoError),
46 #[error("No joiner secret found in the Welcome message.")]
48 JoinerSecretNotFound,
49 #[error("No ratchet tree available to build initial tree after receiving a Welcome message.")]
51 MissingRatchetTree,
52 #[error("The computed confirmation tag does not match the expected one.")]
54 ConfirmationTagMismatch,
55 #[error("The signature on the GroupInfo is not valid.")]
57 InvalidGroupInfoSignature,
58 #[error("We don't support the version of the group we are trying to join.")]
60 UnsupportedMlsVersion,
61 #[error("We don't support all capabilities of the group.")]
63 UnsupportedCapability,
64 #[error("Sender not found in tree.")]
66 UnknownSender,
67 #[error("Not a Welcome message.")]
69 NotAWelcomeMessage,
70 #[error("Malformed Welcome message.")]
72 MalformedWelcomeMessage,
73 #[error("Could not decrypt the Welcome message.")]
75 UnableToDecrypt,
76 #[error("Unsupported extensions found in the GroupContext or KeyPackage of another member.")]
78 UnsupportedExtensions,
79 #[error(transparent)]
81 Psk(#[from] PskError),
82 #[error("No matching encryption key was found in the key store.")]
84 NoMatchingEncryptionKey,
85 #[error("No matching key package was found in the key store.")]
87 NoMatchingKeyPackage,
88 #[error(transparent)]
90 PublicTreeError(#[from] PublicTreeError),
91 #[error(transparent)]
94 PublicGroupError(#[from] CreationFromExternalError<StorageError>),
95 #[error(transparent)]
97 LeafNodeValidation(#[from] LeafNodeValidationError),
98 #[error("An error occurred when querying storage")]
100 StorageError(StorageError),
101 #[error("A group with this [`GroupId`] already exists.")]
103 GroupAlreadyExists,
104}
105
106#[derive(Error, Debug, PartialEq, Clone)]
108pub enum ExternalCommitError<StorageError> {
109 #[error(transparent)]
111 LibraryError(#[from] LibraryError),
112 #[error("No ratchet tree available to build initial tree.")]
114 MissingRatchetTree,
115 #[error("No external_pub extension available to join group by external commit.")]
117 MissingExternalPub,
118 #[error("We don't support the ciphersuite of the group we are trying to join.")]
120 UnsupportedCiphersuite,
121 #[error("Sender not found in tree.")]
123 UnknownSender,
124 #[error("The signature over the given group info is invalid.")]
126 InvalidGroupInfoSignature,
127 #[error("Error creating external commit.")]
129 CommitError(#[from] CreateCommitError),
130 #[error(transparent)]
133 PublicGroupError(#[from] CreationFromExternalError<StorageError>),
134 #[error("Credential is missing from external commit.")]
136 MissingCredential,
137 #[error("An error occurred when writing group to storage.")]
139 StorageError(StorageError),
140}
141
142impl<StorageError> From<ExternalCommitBuilderError<StorageError>>
143 for ExternalCommitError<StorageError>
144{
145 fn from(error: ExternalCommitBuilderError<StorageError>) -> Self {
146 match error {
147 ExternalCommitBuilderError::LibraryError(library_error) => {
148 ExternalCommitError::LibraryError(library_error)
149 }
150 ExternalCommitBuilderError::MissingRatchetTree => {
151 ExternalCommitError::MissingRatchetTree
152 }
153 ExternalCommitBuilderError::MissingExternalPub => {
154 ExternalCommitError::MissingExternalPub
155 }
156 ExternalCommitBuilderError::UnsupportedCiphersuite => {
157 ExternalCommitError::UnsupportedCiphersuite
158 }
159 ExternalCommitBuilderError::PublicGroupError(creation_from_external_error) => {
160 ExternalCommitError::PublicGroupError(creation_from_external_error)
161 }
162 ExternalCommitBuilderError::StorageError(error) => {
163 ExternalCommitError::StorageError(error)
164 }
165 ExternalCommitBuilderError::InvalidProposal(e) => {
168 log::error!("Error validating proposal in external commit: {e}");
169 ExternalCommitError::LibraryError(LibraryError::custom(
170 "Error creating external commit",
171 ))
172 }
173 }
174 }
175}
176
177impl<StorageError> From<ExternalCommitBuilderFinalizeError<StorageError>>
178 for ExternalCommitError<StorageError>
179{
180 fn from(error: ExternalCommitBuilderFinalizeError<StorageError>) -> Self {
181 match error {
182 ExternalCommitBuilderFinalizeError::LibraryError(library_error) => {
183 ExternalCommitError::LibraryError(library_error)
184 }
185 ExternalCommitBuilderFinalizeError::StorageError(error) => {
186 ExternalCommitError::StorageError(error)
187 }
188 ExternalCommitBuilderFinalizeError::MergeCommitError(e) => {
189 log::error!("Error merging external commit: {e}");
190 ExternalCommitError::LibraryError(LibraryError::custom(
193 "Error merging external commit",
194 ))
195 }
196 }
197 }
198}
199
200#[derive(Error, Debug, PartialEq, Clone)]
202pub enum StageCommitError {
203 #[error(transparent)]
205 LibraryError(#[from] LibraryError),
206 #[error("The epoch of the group context and PublicMessage didn't match.")]
208 EpochMismatch,
209 #[error("The Commit was created by this client.")]
211 OwnCommit,
212 #[error("stage_commit was called with an PublicMessage that is not a Commit.")]
214 WrongPlaintextContentType,
215 #[error("Unable to verify the leaf node signature.")]
217 PathLeafNodeVerificationFailure,
218 #[error("Unable to determine commit path.")]
220 RequiredPathNotFound,
221 #[error("The confirmation Tag is missing.")]
223 ConfirmationTagMissing,
224 #[error("The confirmation tag is invalid.")]
226 ConfirmationTagMismatch,
227 #[error("The committer can't remove themselves.")]
229 AttemptedSelfRemoval,
230 #[error("The proposal queue is missing a proposal for the commit.")]
232 MissingProposal,
233 #[error("Missing own key to apply proposal.")]
235 OwnKeyNotFound,
236 #[error("External Committer used the wrong index.")]
238 InconsistentSenderIndex,
239 #[error("The sender is of type external, which is not valid.")]
241 SenderTypeExternal,
242 #[error("The sender is of type NewMemberProposal, which is not valid.")]
244 SenderTypeNewMemberProposal,
245 #[error("Too many new members: the tree is full.")]
247 TooManyNewMembers,
248 #[error(transparent)]
250 ProposalValidationError(#[from] ProposalValidationError),
251 #[error(transparent)]
253 PskError(#[from] PskError),
254 #[error(transparent)]
256 ExternalCommitValidation(#[from] ExternalCommitValidationError),
257 #[error(transparent)]
259 UpdatePathError(#[from] ApplyUpdatePathError),
260 #[error("Missing decryption key.")]
262 MissingDecryptionKey,
263 #[error(transparent)]
265 VerifiedUpdatePathError(#[from] UpdatePathError),
266 #[error(transparent)]
268 GroupContextExtensionsProposalValidationError(
269 #[from] GroupContextExtensionsProposalValidationError,
270 ),
271 #[cfg(feature = "extensions-draft-08")]
272 #[error(transparent)]
274 AppDataUpdateValidationError(#[from] AppDataUpdateValidationError),
275 #[error(transparent)]
277 LeafNodeValidation(#[from] LeafNodeValidationError),
278 #[cfg(feature = "extensions-draft-08")]
280 #[error(transparent)]
281 ApplyAppDataUpdateError(#[from] ApplyAppDataUpdateError),
282 #[error("Duplicate PSK proposal with PSK ID {0:?}.")]
284 DuplicatePskId(PreSharedKeyId),
285}
286
287#[derive(Error, Debug, PartialEq, Clone)]
289pub enum CreateCommitError {
290 #[error(transparent)]
292 LibraryError(#[from] LibraryError),
293 #[error("Missing own key to apply proposal.")]
295 OwnKeyNotFound,
296 #[error("The Commit tried to remove self from the group. This is not possible.")]
298 CannotRemoveSelf,
299 #[error("The proposal queue is missing a proposal for the commit.")]
301 MissingProposal,
302 #[error("A proposal has the wrong sender type.")]
304 WrongProposalSenderType,
305 #[error(transparent)]
307 PskError(#[from] PskError),
308 #[error(transparent)]
310 ProposalValidationError(#[from] ProposalValidationError),
311 #[error(transparent)]
313 SignatureError(#[from] SignatureError),
314 #[error("Credential is missing from external commit.")]
316 MissingCredential,
317 #[error(transparent)]
319 PublicTreeError(#[from] PublicTreeError),
320 #[error(transparent)]
322 InvalidExtensionError(#[from] InvalidExtensionError),
323 #[cfg(feature = "extensions-draft-08")]
324 #[error(transparent)]
326 AppDataUpdateValidationError(#[from] AppDataUpdateValidationError),
327 #[error(transparent)]
329 GroupContextExtensionsProposalValidationError(
330 #[from] GroupContextExtensionsProposalValidationError,
331 ),
332 #[error(transparent)]
334 TreeSyncAddLeaf(#[from] TreeSyncAddLeaf),
335 #[error("Invalid LeafNodeParameters. CredentialWithKey can't be set with new signer.")]
337 InvalidLeafNodeParameters,
338 #[error("Invalid external commit.")]
340 InvalidExternalCommit(#[from] ExternalCommitValidationError),
341 #[cfg(feature = "extensions-draft-08")]
343 #[error(transparent)]
344 ApplyAppDataUpdateError(#[from] ApplyAppDataUpdateError),
345 #[error(transparent)]
347 LeafNodeValidation(#[from] LeafNodeValidationError),
348}
349
350#[derive(Error, Debug, PartialEq, Clone)]
352pub enum CommitBuilderStageError<StorageError> {
353 #[error(transparent)]
355 LibraryError(#[from] LibraryError),
356 #[error("Error interacting with storage.")]
358 KeyStoreError(StorageError),
359}
360
361#[derive(Error, Debug, PartialEq, Clone)]
363pub enum ExternalCommitBuilderFinalizeError<StorageError> {
364 #[error(transparent)]
366 LibraryError(#[from] LibraryError),
367 #[error("Error interacting with storage.")]
369 StorageError(StorageError),
370 #[error("Error merging external commit.")]
372 MergeCommitError(#[from] MergePendingCommitError<StorageError>),
373}
374
375#[derive(Error, Debug, PartialEq, Clone)]
377pub enum ValidationError {
378 #[error(transparent)]
380 LibraryError(#[from] LibraryError),
381 #[error("Message group ID differs from the group's group ID.")]
383 WrongGroupId,
384 #[error("Message epoch differs from the group's epoch.")]
386 WrongEpoch,
387 #[error("The PublicMessage is not a Commit despite the sender begin of type NewMemberCommit.")]
389 NotACommit,
390 #[error("The PublicMessage is not an external Add proposal despite the sender begin of type NewMemberProposal.")]
392 NotAnExternalAddProposal,
393 #[error("The Commit doesn't have a path despite the sender being of type NewMemberCommit.")]
395 NoPath,
396 #[error("The PublicMessage contains an application message but was not encrypted.")]
398 UnencryptedApplicationMessage,
399 #[error("Sender is not part of the group.")]
401 UnknownMember,
402 #[error("Membership tag is missing.")]
404 MissingMembershipTag,
405 #[error("Membership tag is invalid.")]
407 InvalidMembershipTag,
408 #[error("The confirmation tag is missing.")]
410 MissingConfirmationTag,
411 #[error("Wrong wire format.")]
413 WrongWireFormat,
414 #[error("Verifying the signature failed.")]
416 InvalidSignature,
417 #[error("An application message was sent from an external sender.")]
419 NonMemberApplicationMessage,
420 #[error(transparent)]
422 UnableToDecrypt(#[from] MessageDecryptionError),
423 #[error("The message is from an epoch too far in the past.")]
425 NoPastEpochData,
426 #[error("The provided external sender is not authorized to send external proposals")]
428 UnauthorizedExternalSender,
429 #[error("The group doesn't contain external senders extension")]
431 NoExternalSendersExtension,
432 #[error(transparent)]
434 KeyPackageVerifyError(#[from] KeyPackageVerifyError),
435 #[error(transparent)]
437 UpdatePathError(#[from] UpdatePathError),
438 #[error("Invalid LeafNode signature.")]
440 InvalidLeafNodeSignature,
441 #[error("Invalid LeafNode source type")]
443 InvalidLeafNodeSourceType,
444 #[error("Invalid sender type")]
446 InvalidSenderType,
447 #[error("The Commit includes update proposals from the committer.")]
449 CommitterIncludedOwnUpdate,
450 #[error(
452 "The ciphersuite in the KeyPackage of the Add proposal does not match the group context."
453 )]
454 InvalidAddProposalCiphersuite,
455 #[cfg(not(feature = "virtual-clients-draft"))]
456 #[error("Cannot decrypt own messages.")]
458 CannotDecryptOwnMessage,
459 #[error(transparent)]
461 ExternalCommitValidation(#[from] ExternalCommitValidationError),
462 #[error("Invalid extension")]
464 InvalidExtension(#[from] InvalidExtensionError),
465}
466
467#[derive(Error, Debug, PartialEq, Clone)]
469pub enum ProposalValidationError {
470 #[error(transparent)]
472 LibraryError(#[from] LibraryError),
473 #[error("The sender could not be matched to a member of the group.")]
475 UnknownMember,
476 #[error("Duplicate signature key in proposals and group.")]
478 DuplicateSignatureKey,
479 #[error("Duplicate encryption key in proposals and group.")]
481 DuplicateEncryptionKey,
482 #[error("Duplicate init key in proposals.")]
484 DuplicateInitKey,
485 #[error("The HPKE init and encryption keys are the same.")]
487 InitEncryptionKeyCollision,
488 #[error("Duplicate remove proposals for the same member.")]
490 DuplicateMemberRemoval,
491 #[error("The remove proposal referenced a non-existing member.")]
493 UnknownMemberRemoval,
494 #[error("Found an update from a non-member.")]
496 UpdateFromNonMember,
497 #[error("The Commit includes update proposals from the committer.")]
499 CommitterIncludedOwnUpdate,
500 #[error("The capabilities of the add proposal are insufficient for this group.")]
502 InsufficientCapabilities,
503 #[error(
505 "The add proposal's ciphersuite or protocol version do not match the ones in the group context."
506 )]
507 InvalidAddProposalCiphersuiteOrVersion,
508 #[error(transparent)]
510 Psk(#[from] PskError),
511 #[error("The proposal type is not supported by all group members.")]
513 UnsupportedProposalType,
514 #[error(transparent)]
516 LeafNodeValidation(#[from] LeafNodeValidationError),
517 #[error("Found ExternalInit proposal in regular commit")]
519 ExternalInitProposalInRegularCommit,
520}
521
522#[derive(Error, Debug, PartialEq, Clone)]
524pub enum ExternalCommitValidationError {
525 #[error(transparent)]
527 LibraryError(#[from] LibraryError),
528 #[error("No ExternalInit proposal found.")]
530 NoExternalInitProposals,
531 #[error("Multiple ExternalInit proposal found.")]
533 MultipleExternalInitProposals,
534 #[error("Found inline Add or Update proposals.")]
536 InvalidInlineProposals,
537 #[error("Found multiple inline Remove proposals.")]
539 MultipleRemoveProposals,
540 #[error("Remove proposal targets the wrong group member.")]
542 InvalidRemoveProposal,
543 #[error("External Commit has to contain a path.")]
545 NoPath,
546 #[error("Found a referenced proposal in an External Commit.")]
548 ReferencedProposal,
549 #[error("External committer's leaf node does not support all group context extensions.")]
551 UnsupportedGroupContextExtensions,
552}
553
554#[derive(Error, Debug, PartialEq, Clone)]
556pub enum CreateAddProposalError {
557 #[error(transparent)]
559 LibraryError(#[from] LibraryError),
560 #[error(transparent)]
562 LeafNodeValidation(#[from] LeafNodeValidationError),
563}
564
565#[derive(Error, Debug, PartialEq, Clone)]
569pub(crate) enum ProposalQueueError {
570 #[error(transparent)]
572 LibraryError(#[from] LibraryError),
573 #[error("Not all proposals in the Commit were found locally.")]
575 ProposalNotFound,
576 #[error("Update proposal from external sender.")]
578 UpdateFromExternalSender,
579 #[error("SelfRemove proposal from a non-Member.")]
581 SelfRemoveFromNonMember,
582}
583
584#[derive(Error, Debug, PartialEq, Clone)]
587pub(crate) enum FromCommittedProposalsError {
588 #[error(transparent)]
590 LibraryError(#[from] LibraryError),
591 #[error("Not all proposals in the Commit were found locally.")]
593 ProposalNotFound,
594 #[error("The sender of a Commit tried to remove themselves.")]
596 SelfRemoval,
597 #[error("Commit contains two PSK proposals the PSK ID {0:?}.")]
599 DuplicatePskId(PreSharedKeyId),
600}
601
602#[derive(Error, Debug, PartialEq, Clone)]
604pub enum CreateGroupContextExtProposalError<StorageError> {
605 #[error(transparent)]
607 LibraryError(#[from] LibraryError),
608 #[error(transparent)]
610 KeyPackageExtensionSupport(#[from] KeyPackageExtensionSupportError),
611 #[error(transparent)]
613 Extension(#[from] ExtensionError),
614 #[error(transparent)]
616 LeafNodeValidation(#[from] LeafNodeValidationError),
617 #[error(transparent)]
619 MlsGroupStateError(#[from] MlsGroupStateError),
620 #[error(transparent)]
622 CreateCommitError(#[from] CreateCommitError),
623 #[error(transparent)]
625 CommitBuilderStageError(#[from] CommitBuilderStageError<StorageError>),
626 #[error("Error writing updated group data to storage.")]
628 StorageError(StorageError),
629 #[error(transparent)]
631 InvalidExtensionError(#[from] InvalidExtensionError),
632}
633
634#[derive(Error, Debug, PartialEq, Clone)]
636pub enum MergeCommitError<StorageError> {
637 #[error(transparent)]
639 LibraryError(#[from] LibraryError),
640 #[error("Error writing updated group data to storage.")]
642 StorageError(StorageError),
643}
644
645#[cfg(feature = "extensions-draft-08")]
646#[derive(Error, Debug, PartialEq, Clone)]
648pub enum AppDataUpdateValidationError {
649 #[error("AppDataUpdate proposals occur before GroupContextExtensions proposals.")]
653 IncorrectOrder,
654 #[error("Attempted to update the AppDataDictionary in the GroupContextExtensions proposal directly.")]
658 CannotUpdateDictionaryDirectly,
659 #[error("More than one AppDataUpdate proposal per ComponentId had a Remove operation.")]
663 MoreThanOneRemovePerComponentId,
664 #[error("Proposals for a ComponentId had both Remove and Update operations.")]
668 CombinedRemoveAndUpdateOperations,
669 #[error("Proposals for a ComponentId had a Remove for a nonexistent component.")]
673 CannotRemoveNonexistentComponent,
674}
675
676#[derive(Error, Debug, PartialEq, Clone)]
678pub enum GroupContextExtensionsProposalValidationError {
679 #[error("Commit has more than one GroupContextExtensions proposal.")]
681 TooManyGCEProposals,
682
683 #[error(transparent)]
685 LibraryError(#[from] LibraryError),
686
687 #[error(
689 "The new required capabilties contain extension types that are not supported by all group members."
690 )]
691 ExtensionNotSupportedByAllMembers,
692 #[error("Proposal changes the immutable metadata extension, which is not allowed.")]
694 ChangedImmutableMetadata,
695
696 #[error(
698 "The new required capabilties contain extension types that are not supported by all group members."
699 )]
700 RequiredExtensionNotSupportedByAllMembers,
701
702 #[error(
705 "An extension in the group context extensions is not listed in the required capabilties' extension types."
706 )]
707 ExtensionNotInRequiredCapabilities,
708
709 #[error("Expected valid `Extension` for `GroupContextExtension`, got `{wrong:?}`")]
711 InvalidExtensionTypeError {
712 wrong: ExtensionType,
714 },
715}