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 #[error("Cannot decrypt own messages.")]
457 CannotDecryptOwnMessage,
458 #[error(transparent)]
460 ExternalCommitValidation(#[from] ExternalCommitValidationError),
461 #[error("Invalid extension")]
463 InvalidExtension(#[from] InvalidExtensionError),
464}
465
466#[derive(Error, Debug, PartialEq, Clone)]
468pub enum ProposalValidationError {
469 #[error(transparent)]
471 LibraryError(#[from] LibraryError),
472 #[error("The sender could not be matched to a member of the group.")]
474 UnknownMember,
475 #[error("Duplicate signature key in proposals and group.")]
477 DuplicateSignatureKey,
478 #[error("Duplicate encryption key in proposals and group.")]
480 DuplicateEncryptionKey,
481 #[error("Duplicate init key in proposals.")]
483 DuplicateInitKey,
484 #[error("The HPKE init and encryption keys are the same.")]
486 InitEncryptionKeyCollision,
487 #[error("Duplicate remove proposals for the same member.")]
489 DuplicateMemberRemoval,
490 #[error("The remove proposal referenced a non-existing member.")]
492 UnknownMemberRemoval,
493 #[error("Found an update from a non-member.")]
495 UpdateFromNonMember,
496 #[error("The Commit includes update proposals from the committer.")]
498 CommitterIncludedOwnUpdate,
499 #[error("The capabilities of the add proposal are insufficient for this group.")]
501 InsufficientCapabilities,
502 #[error(
504 "The add proposal's ciphersuite or protocol version do not match the ones in the group context."
505 )]
506 InvalidAddProposalCiphersuiteOrVersion,
507 #[error(transparent)]
509 Psk(#[from] PskError),
510 #[error("The proposal type is not supported by all group members.")]
512 UnsupportedProposalType,
513 #[error(transparent)]
515 LeafNodeValidation(#[from] LeafNodeValidationError),
516 #[error("Found ExternalInit proposal in regular commit")]
518 ExternalInitProposalInRegularCommit,
519}
520
521#[derive(Error, Debug, PartialEq, Clone)]
523pub enum ExternalCommitValidationError {
524 #[error(transparent)]
526 LibraryError(#[from] LibraryError),
527 #[error("No ExternalInit proposal found.")]
529 NoExternalInitProposals,
530 #[error("Multiple ExternalInit proposal found.")]
532 MultipleExternalInitProposals,
533 #[error("Found inline Add or Update proposals.")]
535 InvalidInlineProposals,
536 #[error("Found multiple inline Remove proposals.")]
538 MultipleRemoveProposals,
539 #[error("Remove proposal targets the wrong group member.")]
541 InvalidRemoveProposal,
542 #[error("External Commit has to contain a path.")]
544 NoPath,
545 #[error("Found a referenced proposal in an External Commit.")]
547 ReferencedProposal,
548 #[error("External committer's leaf node does not support all group context extensions.")]
550 UnsupportedGroupContextExtensions,
551}
552
553#[derive(Error, Debug, PartialEq, Clone)]
555pub enum CreateAddProposalError {
556 #[error(transparent)]
558 LibraryError(#[from] LibraryError),
559 #[error(transparent)]
561 LeafNodeValidation(#[from] LeafNodeValidationError),
562}
563
564#[derive(Error, Debug, PartialEq, Clone)]
568pub(crate) enum ProposalQueueError {
569 #[error(transparent)]
571 LibraryError(#[from] LibraryError),
572 #[error("Not all proposals in the Commit were found locally.")]
574 ProposalNotFound,
575 #[error("Update proposal from external sender.")]
577 UpdateFromExternalSender,
578 #[error("SelfRemove proposal from a non-Member.")]
580 SelfRemoveFromNonMember,
581}
582
583#[derive(Error, Debug, PartialEq, Clone)]
586pub(crate) enum FromCommittedProposalsError {
587 #[error(transparent)]
589 LibraryError(#[from] LibraryError),
590 #[error("Not all proposals in the Commit were found locally.")]
592 ProposalNotFound,
593 #[error("The sender of a Commit tried to remove themselves.")]
595 SelfRemoval,
596 #[error("Commit contains two PSK proposals the PSK ID {0:?}.")]
598 DuplicatePskId(PreSharedKeyId),
599}
600
601#[derive(Error, Debug, PartialEq, Clone)]
603pub enum CreateGroupContextExtProposalError<StorageError> {
604 #[error(transparent)]
606 LibraryError(#[from] LibraryError),
607 #[error(transparent)]
609 KeyPackageExtensionSupport(#[from] KeyPackageExtensionSupportError),
610 #[error(transparent)]
612 Extension(#[from] ExtensionError),
613 #[error(transparent)]
615 LeafNodeValidation(#[from] LeafNodeValidationError),
616 #[error(transparent)]
618 MlsGroupStateError(#[from] MlsGroupStateError),
619 #[error(transparent)]
621 CreateCommitError(#[from] CreateCommitError),
622 #[error(transparent)]
624 CommitBuilderStageError(#[from] CommitBuilderStageError<StorageError>),
625 #[error("Error writing updated group data to storage.")]
627 StorageError(StorageError),
628 #[error(transparent)]
630 InvalidExtensionError(#[from] InvalidExtensionError),
631}
632
633#[derive(Error, Debug, PartialEq, Clone)]
635pub enum MergeCommitError<StorageError> {
636 #[error(transparent)]
638 LibraryError(#[from] LibraryError),
639 #[error("Error writing updated group data to storage.")]
641 StorageError(StorageError),
642}
643
644#[cfg(feature = "extensions-draft-08")]
645#[derive(Error, Debug, PartialEq, Clone)]
647pub enum AppDataUpdateValidationError {
648 #[error("AppDataUpdate proposals occur before GroupContextExtensions proposals.")]
652 IncorrectOrder,
653 #[error("Attempted to update the AppDataDictionary in the GroupContextExtensions proposal directly.")]
657 CannotUpdateDictionaryDirectly,
658 #[error("More than one AppDataUpdate proposal per ComponentId had a Remove operation.")]
662 MoreThanOneRemovePerComponentId,
663 #[error("Proposals for a ComponentId had both Remove and Update operations.")]
667 CombinedRemoveAndUpdateOperations,
668 #[error("Proposals for a ComponentId had a Remove for a nonexistent component.")]
672 CannotRemoveNonexistentComponent,
673}
674
675#[derive(Error, Debug, PartialEq, Clone)]
677pub enum GroupContextExtensionsProposalValidationError {
678 #[error("Commit has more than one GroupContextExtensions proposal.")]
680 TooManyGCEProposals,
681
682 #[error(transparent)]
684 LibraryError(#[from] LibraryError),
685
686 #[error(
688 "The new required capabilties contain extension types that are not supported by all group members."
689 )]
690 ExtensionNotSupportedByAllMembers,
691 #[error("Proposal changes the immutable metadata extension, which is not allowed.")]
693 ChangedImmutableMetadata,
694
695 #[error(
697 "The new required capabilties contain extension types that are not supported by all group members."
698 )]
699 RequiredExtensionNotSupportedByAllMembers,
700
701 #[error(
704 "An extension in the group context extensions is not listed in the required capabilties' extension types."
705 )]
706 ExtensionNotInRequiredCapabilities,
707
708 #[error("Expected valid `Extension` for `GroupContextExtension`, got `{wrong:?}`")]
710 InvalidExtensionTypeError {
711 wrong: ExtensionType,
713 },
714}