Skip to main content

openmls/group/
errors.rs

1//! # MLS group errors
2//!
3//! This module contains errors that originate at lower levels and are partially re-exported in errors thrown by functions of the `MlsGroup` API.
4
5use openmls_traits::types::Ciphersuite;
6use thiserror::Error;
7
8#[cfg(feature = "extensions-draft")]
9use super::public_group::errors::ApplyAppDataUpdateError;
10
11pub use super::mls_group::errors::*;
12use super::public_group::errors::CreationFromExternalError;
13use crate::{
14    ciphersuite::signable::SignatureError,
15    error::LibraryError,
16    extensions::errors::{ExtensionError, InvalidExtensionError},
17    framing::errors::MessageDecryptionError,
18    group::commit_builder::external_commits::ExternalCommitBuilderError,
19    key_packages::errors::{KeyPackageExtensionSupportError, KeyPackageVerifyError},
20    messages::{group_info::GroupInfoError, GroupSecretsError},
21    prelude::ExtensionType,
22    schedule::{
23        errors::{KeyScheduleError, PskError},
24        PreSharedKeyId,
25    },
26    treesync::errors::*,
27};
28
29#[cfg(doc)]
30use crate::{group::GroupId, treesync::LeafNodeParameters};
31
32/// Welcome error
33#[derive(Error, Debug, PartialEq, Clone)]
34pub enum WelcomeError<StorageError> {
35    /// See [`GroupSecretsError`] for more details.
36    #[error(transparent)]
37    GroupSecrets(#[from] GroupSecretsError),
38    /// Private part of `init_key` not found in key store.
39    #[error("Private part of `init_key` not found in key store.")]
40    PrivateInitKeyNotFound,
41    /// See [`LibraryError`] for more details.
42    #[error(transparent)]
43    LibraryError(#[from] LibraryError),
44    /// Ciphersuites in Welcome and key package bundle don't match.
45    #[error("Ciphersuites in Welcome and key package bundle don't match.")]
46    CiphersuiteMismatch,
47    /// See [`GroupInfoError`] for more details.
48    #[error(transparent)]
49    GroupInfo(#[from] GroupInfoError),
50    /// No joiner secret found in the Welcome message.
51    #[error("No joiner secret found in the Welcome message.")]
52    JoinerSecretNotFound,
53    /// No ratchet tree available to build initial tree after receiving a Welcome message.
54    #[error("No ratchet tree available to build initial tree after receiving a Welcome message.")]
55    MissingRatchetTree,
56    /// The computed confirmation tag does not match the expected one.
57    #[error("The computed confirmation tag does not match the expected one.")]
58    ConfirmationTagMismatch,
59    /// The signature on the GroupInfo is not valid.
60    #[error("The signature on the GroupInfo is not valid.")]
61    InvalidGroupInfoSignature,
62    /// We don't support the version of the group we are trying to join.
63    #[error("We don't support the version of the group we are trying to join.")]
64    UnsupportedMlsVersion,
65    /// We don't support all capabilities of the group.
66    #[error("We don't support all capabilities of the group.")]
67    UnsupportedCapability,
68    /// The crypto provider doesn't support the ciphersuite of the group we are trying to join.
69    #[error("Ciphersuite {0:?} of the group we are trying to join is not supported by the crypto provider.")]
70    UnsupportedCiphersuite(Ciphersuite),
71    /// Sender not found in tree.
72    #[error("Sender not found in tree.")]
73    UnknownSender,
74    /// The provided message is not a Welcome message.
75    #[error("Not a Welcome message.")]
76    NotAWelcomeMessage,
77    /// Malformed Welcome message.
78    #[error("Malformed Welcome message.")]
79    MalformedWelcomeMessage,
80    /// Could not decrypt the Welcome message.
81    #[error("Could not decrypt the Welcome message.")]
82    UnableToDecrypt,
83    /// Unsupported extensions found in the GroupContext or KeyPackage of another member.
84    #[error("Unsupported extensions found in the GroupContext or KeyPackage of another member.")]
85    UnsupportedExtensions,
86    /// See [`PskError`] for more details.
87    #[error(transparent)]
88    Psk(#[from] PskError),
89    /// No matching encryption key was found in the key store.
90    #[error("No matching encryption key was found in the key store.")]
91    NoMatchingEncryptionKey,
92    /// No matching key package was found in the key store.
93    #[error("No matching key package was found in the key store.")]
94    NoMatchingKeyPackage,
95    /// This error indicates the public tree is invalid. See [`PublicTreeError`] for more details.
96    #[error(transparent)]
97    PublicTreeError(#[from] PublicTreeError),
98    /// This error indicates the public tree is invalid. See
99    /// [`CreationFromExternalError`] for more details.
100    #[error(transparent)]
101    PublicGroupError(#[from] CreationFromExternalError<StorageError>),
102    /// This error indicates the leaf node is invalid. See [`LeafNodeValidationError`] for more details.
103    #[error(transparent)]
104    LeafNodeValidation(#[from] LeafNodeValidationError),
105    /// This error indicates that an error occurred while reading or writing from/to storage.
106    #[error("An error occurred when querying storage")]
107    StorageError(StorageError),
108    /// A group with this [`GroupId`] already exists.
109    #[error("A group with this [`GroupId`] already exists.")]
110    GroupAlreadyExists,
111    /// A virtual-clients error occurred while deriving or validating the
112    /// virtual client's join material.
113    #[cfg(feature = "virtual-clients-draft")]
114    #[error(transparent)]
115    VirtualClientsError(#[from] crate::components::vc_derivation_info::VirtualClientsError),
116    /// This error indicates that computing the key schedule failed
117    #[error(transparent)]
118    KeySchedule(#[from] KeyScheduleError),
119}
120
121/// External Commit error
122#[derive(Error, Debug, PartialEq, Clone)]
123pub enum ExternalCommitError<StorageError> {
124    /// See [`LibraryError`] for more details.
125    #[error(transparent)]
126    LibraryError(#[from] LibraryError),
127    /// No ratchet tree available to build initial tree.
128    #[error("No ratchet tree available to build initial tree.")]
129    MissingRatchetTree,
130    /// No external_pub extension available to join group by external commit.
131    #[error("No external_pub extension available to join group by external commit.")]
132    MissingExternalPub,
133    /// We don't support the ciphersuite of the group we are trying to join.
134    #[error("Ciphersuite {0:?} of the group we are trying to join is not supported by the crypto provider.")]
135    UnsupportedCiphersuite(Ciphersuite),
136    /// Sender not found in tree.
137    #[error("Sender not found in tree.")]
138    UnknownSender,
139    /// The signature over the given group info is invalid.
140    #[error("The signature over the given group info is invalid.")]
141    InvalidGroupInfoSignature,
142    /// Error creating external commit.
143    #[error("Error creating external commit.")]
144    CommitError(#[from] CreateCommitError),
145    /// This error indicates the public tree is invalid. See
146    /// [`CreationFromExternalError`] for more details.
147    #[error(transparent)]
148    PublicGroupError(#[from] CreationFromExternalError<StorageError>),
149    /// Credential is missing from external commit.
150    #[error("Credential is missing from external commit.")]
151    MissingCredential,
152    /// An erorr occurred when writing group to storage
153    #[error("An error occurred when writing group to storage.")]
154    StorageError(StorageError),
155}
156
157impl<StorageError> From<ExternalCommitBuilderError<StorageError>>
158    for ExternalCommitError<StorageError>
159{
160    fn from(error: ExternalCommitBuilderError<StorageError>) -> Self {
161        match error {
162            ExternalCommitBuilderError::LibraryError(library_error) => {
163                ExternalCommitError::LibraryError(library_error)
164            }
165            ExternalCommitBuilderError::MissingRatchetTree => {
166                ExternalCommitError::MissingRatchetTree
167            }
168            ExternalCommitBuilderError::MissingExternalPub => {
169                ExternalCommitError::MissingExternalPub
170            }
171            ExternalCommitBuilderError::UnsupportedCiphersuite(ciphersuite) => {
172                ExternalCommitError::UnsupportedCiphersuite(ciphersuite)
173            }
174            ExternalCommitBuilderError::PublicGroupError(creation_from_external_error) => {
175                ExternalCommitError::PublicGroupError(creation_from_external_error)
176            }
177            ExternalCommitBuilderError::StorageError(error) => {
178                ExternalCommitError::StorageError(error)
179            }
180            // These should not happen since `join_by_external_commit` doesn't
181            // take proposals as input.
182            ExternalCommitBuilderError::InvalidProposal(e) => {
183                log::error!("Error validating proposal in external commit: {e}");
184                ExternalCommitError::LibraryError(LibraryError::custom(
185                    "Error creating external commit",
186                ))
187            }
188        }
189    }
190}
191
192/// Error joining a higher-level group as a virtual client's sibling emulator
193/// by processing another sibling's external commit
194/// ([`MlsGroup::vc_join_via_sibling_external_commit`]).
195///
196/// [`MlsGroup::vc_join_via_sibling_external_commit`]: crate::group::MlsGroup::vc_join_via_sibling_external_commit
197#[cfg(feature = "virtual-clients-draft")]
198#[derive(Error, Debug)]
199pub enum VcExternalCommitJoinError<StorageError> {
200    /// See [`LibraryError`] for more details.
201    #[error(transparent)]
202    LibraryError(#[from] LibraryError),
203    /// No ratchet tree available to build the prior-epoch public group.
204    #[error("No ratchet tree available to build the prior-epoch public group.")]
205    MissingRatchetTree,
206    /// The prior-epoch public tree is invalid. See [`CreationFromExternalError`].
207    #[error(transparent)]
208    PublicGroupError(#[from] CreationFromExternalError<StorageError>),
209    /// The external commit could not be parsed or verified.
210    #[error(transparent)]
211    ProcessMessageError(#[from] ProcessMessageError<StorageError>),
212    /// Staging the external commit failed.
213    #[error(transparent)]
214    StageCommitError(#[from] StageCommitError),
215    /// Merging the external commit failed.
216    #[error(transparent)]
217    MergeCommitError(#[from] MergeCommitError<StorageError>),
218    /// The message is not an external commit (`Sender::NewMemberCommit` with a
219    /// Commit body).
220    #[error("The message is not an external commit.")]
221    NotAnExternalCommit,
222    /// The external commit's leaf carries no virtual-clients derivation info,
223    /// so a sibling cannot reconstruct the joining state from it.
224    #[error("The external commit carries no virtual-clients derivation info.")]
225    MissingDerivationInfo,
226    /// The derivation info references a different emulation epoch than the one
227    /// supplied.
228    #[error("The external commit references a different emulation epoch.")]
229    EpochIdMismatch,
230    /// A virtual-clients processing error occurred.
231    #[error(transparent)]
232    VirtualClientsError(#[from] crate::components::vc_derivation_info::VirtualClientsError),
233    /// An error occurred when writing the group to storage.
234    #[error("An error occurred when writing the group to storage.")]
235    StorageError(StorageError),
236}
237
238/// Error bootstrapping a virtual client's sibling emulator into a higher-level
239/// group the virtual client created, by processing the creator's initial group
240/// creation material ([`MlsGroup::vc_join_at_creation`]).
241///
242/// [`MlsGroup::vc_join_at_creation`]: crate::group::MlsGroup::vc_join_at_creation
243#[cfg(feature = "virtual-clients-draft")]
244#[derive(Error, Debug)]
245pub enum VcGroupCreationJoinError<StorageError> {
246    /// See [`LibraryError`] for more details.
247    #[error(transparent)]
248    LibraryError(#[from] LibraryError),
249    /// No ratchet tree available to build the created group's public tree.
250    #[error("No ratchet tree available to build the created group's public tree.")]
251    MissingRatchetTree,
252    /// The created group's public tree is invalid. See
253    /// [`CreationFromExternalError`].
254    #[error(transparent)]
255    PublicGroupError(#[from] CreationFromExternalError<StorageError>),
256    /// The ratchet tree does not consist of exactly the creator's leaf.
257    #[error("The ratchet tree does not consist of exactly the creator's leaf.")]
258    NotASingleLeafTree,
259    /// The creator leaf carries no virtual-clients derivation info.
260    #[error("The creator leaf carries no virtual-clients derivation info.")]
261    MissingDerivationInfo,
262    /// The derivation info references a different emulation epoch than the one
263    /// supplied.
264    #[error("The creator leaf references a different emulation epoch.")]
265    EpochIdMismatch,
266    /// The creator leaf is not `key_package`-sourced, so it is not a virtual
267    /// client's group-creation leaf.
268    #[error("The creator leaf is not key_package-sourced.")]
269    CreatorLeafNotKeyPackageSourced,
270    /// The leaf key material derived from the operation secret does not match
271    /// the creator leaf, so this is not a genuine sibling-created group.
272    #[error("The derived leaf key material does not match the creator leaf.")]
273    LeafKeyMismatch,
274    /// The GroupInfo could not be verified against the reconstructed epoch
275    /// state, so the reconstruction did not reproduce the creator's secrets.
276    #[error("The GroupInfo could not be verified against the reconstructed epoch state.")]
277    ConfirmationTagMismatch,
278    /// A virtual-clients processing error occurred.
279    #[error(transparent)]
280    VirtualClientsError(#[from] crate::components::vc_derivation_info::VirtualClientsError),
281    /// An error occurred when writing the group to storage.
282    #[error("An error occurred when writing the group to storage.")]
283    StorageError(StorageError),
284}
285
286impl<StorageError> From<ExternalCommitBuilderFinalizeError<StorageError>>
287    for ExternalCommitError<StorageError>
288{
289    fn from(error: ExternalCommitBuilderFinalizeError<StorageError>) -> Self {
290        match error {
291            ExternalCommitBuilderFinalizeError::LibraryError(library_error) => {
292                ExternalCommitError::LibraryError(library_error)
293            }
294            ExternalCommitBuilderFinalizeError::StorageError(error) => {
295                ExternalCommitError::StorageError(error)
296            }
297            ExternalCommitBuilderFinalizeError::MergeCommitError(e) => {
298                log::error!("Error merging external commit: {e}");
299                // This shouldn't happen, since we merge our own external
300                // commit.
301                ExternalCommitError::LibraryError(LibraryError::custom(
302                    "Error merging external commit",
303                ))
304            }
305        }
306    }
307}
308
309/// Stage Commit error
310#[derive(Error, Debug, PartialEq, Clone)]
311pub enum StageCommitError {
312    /// Virtual clients error.
313    #[cfg(feature = "virtual-clients-draft")]
314    #[error(transparent)]
315    VirtualClientsError(#[from] crate::components::vc_derivation_info::VirtualClientsError),
316    /// See [`LibraryError`] for more details.
317    #[error(transparent)]
318    LibraryError(#[from] LibraryError),
319    /// The epoch of the group context and PublicMessage didn't match.
320    #[error("The epoch of the group context and PublicMessage didn't match.")]
321    EpochMismatch,
322    /// The Commit was created by this client but does not match the pending commit.
323    #[error("The Commit was created by this client but does not match the pending commit.")]
324    OwnCommitMismatch,
325    /// stage_commit was called with an PublicMessage that is not a Commit.
326    #[error("stage_commit was called with an PublicMessage that is not a Commit.")]
327    WrongPlaintextContentType,
328    /// Unable to verify the leaf node signature.
329    #[error("Unable to verify the leaf node signature.")]
330    PathLeafNodeVerificationFailure,
331    /// Unable to determine commit path.
332    #[error("Unable to determine commit path.")]
333    RequiredPathNotFound,
334    /// The confirmation Tag is missing.
335    #[error("The confirmation Tag is missing.")]
336    ConfirmationTagMissing,
337    /// The confirmation tag is invalid.
338    #[error("The confirmation tag is invalid.")]
339    ConfirmationTagMismatch,
340    /// The committer can't remove themselves.
341    #[error("The committer can't remove themselves.")]
342    AttemptedSelfRemoval,
343    /// The proposal queue is missing a proposal for the commit.
344    #[error("The proposal queue is missing a proposal for the commit.")]
345    MissingProposal,
346    /// Missing own key to apply proposal.
347    #[error("Missing own key to apply proposal.")]
348    OwnKeyNotFound,
349    /// External Committer used the wrong index.
350    #[error("External Committer used the wrong index.")]
351    InconsistentSenderIndex,
352    /// The sender is of type external, which is not valid.
353    #[error("The sender is of type external, which is not valid.")]
354    SenderTypeExternal,
355    /// The sender is of type `NewMemberProposal`, which is not valid.
356    #[error("The sender is of type NewMemberProposal, which is not valid.")]
357    SenderTypeNewMemberProposal,
358    /// Too many new members: the tree is full.
359    #[error("Too many new members: the tree is full.")]
360    TooManyNewMembers,
361    /// See [`ProposalValidationError`] for more details.
362    #[error(transparent)]
363    ProposalValidationError(#[from] ProposalValidationError),
364    /// See [`PskError`] for more details.
365    #[error(transparent)]
366    PskError(#[from] PskError),
367    /// See [`ExternalCommitValidationError`] for more details.
368    #[error(transparent)]
369    ExternalCommitValidation(#[from] ExternalCommitValidationError),
370    /// See [`ApplyUpdatePathError`] for more details.
371    #[error(transparent)]
372    UpdatePathError(#[from] ApplyUpdatePathError),
373    /// Missing decryption key.
374    #[error("Missing decryption key.")]
375    MissingDecryptionKey,
376    /// See [`UpdatePathError`] for more details.
377    #[error(transparent)]
378    VerifiedUpdatePathError(#[from] UpdatePathError),
379    /// See [`GroupContextExtensionsProposalValidationError`] for more details.
380    #[error(transparent)]
381    GroupContextExtensionsProposalValidationError(
382        #[from] GroupContextExtensionsProposalValidationError,
383    ),
384    #[cfg(feature = "extensions-draft")]
385    /// See [`AppDataUpdateValidationError`] for more details.
386    #[error(transparent)]
387    AppDataUpdateValidationError(#[from] AppDataUpdateValidationError),
388    /// See [`LeafNodeValidationError`] for more details.
389    #[error(transparent)]
390    LeafNodeValidation(#[from] LeafNodeValidationError),
391    /// See [`ApplyAppDataUpdateError`] for more details.
392    #[cfg(feature = "extensions-draft")]
393    #[error(transparent)]
394    ApplyAppDataUpdateError(#[from] ApplyAppDataUpdateError),
395    /// Duplicate PSK Proposal.
396    #[error("Duplicate PSK proposal with PSK ID {0:?}.")]
397    DuplicatePskId(PreSharedKeyId),
398}
399
400/// Create commit error
401#[derive(Error, Debug, PartialEq, Clone)]
402pub enum CreateCommitError {
403    /// See [`LibraryError`] for more details.
404    #[error(transparent)]
405    LibraryError(#[from] LibraryError),
406    /// Virtual-clients error.
407    #[cfg(feature = "virtual-clients-draft")]
408    #[error(transparent)]
409    VirtualClientsError(#[from] crate::components::vc_derivation_info::VirtualClientsError),
410    /// Missing own key to apply proposal.
411    #[error("Missing own key to apply proposal.")]
412    OwnKeyNotFound,
413    /// The Commit tried to remove self from the group. This is not possible.
414    #[error("The Commit tried to remove self from the group. This is not possible.")]
415    CannotRemoveSelf,
416    /// The proposal queue is missing a proposal for the commit.
417    #[error("The proposal queue is missing a proposal for the commit.")]
418    MissingProposal,
419    /// A proposal has the wrong sender type.
420    #[error("A proposal has the wrong sender type.")]
421    WrongProposalSenderType,
422    /// See [`PskError`] for more details.
423    #[error(transparent)]
424    PskError(#[from] PskError),
425    /// See [`ProposalValidationError`] for more details.
426    #[error(transparent)]
427    ProposalValidationError(#[from] ProposalValidationError),
428    /// See [`SignatureError`] for more details.
429    #[error(transparent)]
430    SignatureError(#[from] SignatureError),
431    /// Credential is missing from external commit.
432    #[error("Credential is missing from external commit.")]
433    MissingCredential,
434    /// This error indicates the public tree is invalid. See [`PublicTreeError`] for more details.
435    #[error(transparent)]
436    PublicTreeError(#[from] PublicTreeError),
437    /// See [`InvalidExtensionError`] for more details.
438    #[error(transparent)]
439    InvalidExtensionError(#[from] InvalidExtensionError),
440    #[cfg(feature = "extensions-draft")]
441    /// See [`AppDataUpdateValidationError`] for more details.
442    #[error(transparent)]
443    AppDataUpdateValidationError(#[from] AppDataUpdateValidationError),
444    /// See [`GroupContextExtensionsProposalValidationError`] for more details.
445    #[error(transparent)]
446    GroupContextExtensionsProposalValidationError(
447        #[from] GroupContextExtensionsProposalValidationError,
448    ),
449    /// See [`TreeSyncAddLeaf`] for more details.
450    #[error(transparent)]
451    TreeSyncAddLeaf(#[from] TreeSyncAddLeaf),
452    /// Invalid [`LeafNodeParameters`]. `[CredentialWithKey]` can't be set with new signer.
453    #[error("Invalid LeafNodeParameters. CredentialWithKey can't be set with new signer.")]
454    InvalidLeafNodeParameters,
455    /// Invalid external commit.
456    #[error("Invalid external commit.")]
457    InvalidExternalCommit(#[from] ExternalCommitValidationError),
458    /// See [`ApplyAppDataUpdateError`] for more details.
459    #[cfg(feature = "extensions-draft")]
460    #[error(transparent)]
461    ApplyAppDataUpdateError(#[from] ApplyAppDataUpdateError),
462    /// See [`LeafNodeValidationError`] for more details.
463    #[error(transparent)]
464    LeafNodeValidation(#[from] LeafNodeValidationError),
465}
466
467/// Stage commit error
468#[derive(Error, Debug, PartialEq, Clone)]
469pub enum CommitBuilderStageError<StorageError> {
470    /// See [`LibraryError`] for more details.
471    #[error(transparent)]
472    LibraryError(#[from] LibraryError),
473    /// Error interacting with storage.
474    #[error("Error interacting with storage.")]
475    KeyStoreError(StorageError),
476}
477
478/// Stage commit error
479#[derive(Error, Debug, PartialEq, Clone)]
480pub enum ExternalCommitBuilderFinalizeError<StorageError> {
481    /// See [`LibraryError`] for more details.
482    #[error(transparent)]
483    LibraryError(#[from] LibraryError),
484    /// Error interacting with storage.
485    #[error("Error interacting with storage.")]
486    StorageError(StorageError),
487    /// Error merging external commit.
488    #[error("Error merging external commit.")]
489    MergeCommitError(#[from] MergePendingCommitError<StorageError>),
490}
491
492/// Validation error
493#[derive(Error, Debug, PartialEq, Clone)]
494pub enum ValidationError {
495    /// See [`LibraryError`] for more details.
496    #[error(transparent)]
497    LibraryError(#[from] LibraryError),
498    /// Message group ID differs from the group's group ID.
499    #[error("Message group ID differs from the group's group ID.")]
500    WrongGroupId,
501    /// Message epoch differs from the group's epoch.
502    #[error("Message epoch differs from the group's epoch.")]
503    WrongEpoch,
504    /// The PublicMessage is not a Commit despite the sender begin of type [NewMemberCommit](crate::prelude::Sender::NewMemberCommit).
505    #[error("The PublicMessage is not a Commit despite the sender begin of type NewMemberCommit.")]
506    NotACommit,
507    /// The PublicMessage is not an External Add Proposal despite the sender begin of type [NewMemberProposal](crate::prelude::Sender::NewMemberProposal).
508    #[error("The PublicMessage is not an external Add proposal despite the sender begin of type NewMemberProposal.")]
509    NotAnExternalAddProposal,
510    /// The Commit doesn't have a path despite the sender being of type NewMemberCommit.
511    #[error("The Commit doesn't have a path despite the sender being of type NewMemberCommit.")]
512    NoPath,
513    /// The PublicMessage contains an application message but was not encrypted.
514    #[error("The PublicMessage contains an application message but was not encrypted.")]
515    UnencryptedApplicationMessage,
516    /// Sender is not part of the group.
517    #[error("Sender is not part of the group.")]
518    UnknownMember,
519    /// Membership tag is missing.
520    #[error("Membership tag is missing.")]
521    MissingMembershipTag,
522    /// Membership tag is invalid.
523    #[error("Membership tag is invalid.")]
524    InvalidMembershipTag,
525    /// The confirmation tag is missing.
526    #[error("The confirmation tag is missing.")]
527    MissingConfirmationTag,
528    /// Wrong wire format.
529    #[error("Wrong wire format.")]
530    WrongWireFormat,
531    /// Verifying the signature failed.
532    #[error("Verifying the signature failed.")]
533    InvalidSignature,
534    /// An application message was sent from an external sender.
535    #[error("An application message was sent from an external sender.")]
536    NonMemberApplicationMessage,
537    /// Could not decrypt the message
538    #[error(transparent)]
539    UnableToDecrypt(#[from] MessageDecryptionError),
540    /// The message is from an epoch too far in the past.
541    #[error("The message is from an epoch too far in the past.")]
542    NoPastEpochData,
543    /// The provided external sender is not authorized to send external proposals
544    #[error("The provided external sender is not authorized to send external proposals")]
545    UnauthorizedExternalSender,
546    /// The group doesn't contain external senders extension.
547    #[error("The group doesn't contain external senders extension")]
548    NoExternalSendersExtension,
549    /// The KeyPackage could not be validated.
550    #[error(transparent)]
551    KeyPackageVerifyError(#[from] KeyPackageVerifyError),
552    /// The UpdatePath could not be validated.
553    #[error(transparent)]
554    UpdatePathError(#[from] UpdatePathError),
555    /// Invalid LeafNode signature.
556    #[error("Invalid LeafNode signature.")]
557    InvalidLeafNodeSignature,
558    /// Invalid LeafNode source type
559    #[error("Invalid LeafNode source type")]
560    InvalidLeafNodeSourceType,
561    /// Invalid sender type.
562    #[error("Invalid sender type")]
563    InvalidSenderType,
564    /// The Commit includes update proposals from the committer.
565    #[error("The Commit includes update proposals from the committer.")]
566    CommitterIncludedOwnUpdate,
567    /// The ciphersuite in the KeyPackage of the Add proposal does not match the group context.
568    #[error(
569        "The ciphersuite in the KeyPackage of the Add proposal does not match the group context."
570    )]
571    InvalidAddProposalCiphersuite,
572    /// See [`ExternalCommitValidationError`] for more details.
573    #[error(transparent)]
574    ExternalCommitValidation(#[from] ExternalCommitValidationError),
575    /// See [`InvalidExtensionError`]
576    #[error("Invalid extension")]
577    InvalidExtension(#[from] InvalidExtensionError),
578}
579
580/// Proposal validation error
581#[derive(Error, Debug, PartialEq, Clone)]
582pub enum ProposalValidationError {
583    /// See [`LibraryError`] for more details.
584    #[error(transparent)]
585    LibraryError(#[from] LibraryError),
586    /// The sender could not be matched to a member of the group.
587    #[error("The sender could not be matched to a member of the group.")]
588    UnknownMember,
589    /// Duplicate signature key in proposals and group.
590    #[error("Duplicate signature key in proposals and group.")]
591    DuplicateSignatureKey,
592    /// Duplicate encryption key in proposals and group.
593    #[error("Duplicate encryption key in proposals and group.")]
594    DuplicateEncryptionKey,
595    /// Duplicate init key in proposals.
596    #[error("Duplicate init key in proposals.")]
597    DuplicateInitKey,
598    /// The HPKE init and encryption keys are the same.
599    #[error("The HPKE init and encryption keys are the same.")]
600    InitEncryptionKeyCollision,
601    /// Duplicate remove proposals for the same member.
602    #[error("Duplicate remove proposals for the same member.")]
603    DuplicateMemberRemoval,
604    /// The remove proposal referenced a non-existing member.
605    #[error("The remove proposal referenced a non-existing member.")]
606    UnknownMemberRemoval,
607    /// Found an update from a non-member.
608    #[error("Found an update from a non-member.")]
609    UpdateFromNonMember,
610    /// The Commit includes update proposals from the committer.
611    #[error("The Commit includes update proposals from the committer.")]
612    CommitterIncludedOwnUpdate,
613    /// The capabilities of the add proposal are insufficient for this group.
614    #[error("The capabilities of the add proposal are insufficient for this group.")]
615    InsufficientCapabilities,
616    /// The add proposal's ciphersuite or protocol version do not match the ones in the group context.
617    #[error(
618        "The add proposal's ciphersuite or protocol version do not match the ones in the group context."
619    )]
620    InvalidAddProposalCiphersuiteOrVersion,
621    /// See [`PskError`] for more details.
622    #[error(transparent)]
623    Psk(#[from] PskError),
624    /// The proposal type is not supported by all group members.
625    #[error("The proposal type is not supported by all group members.")]
626    UnsupportedProposalType,
627    /// See [`LeafNodeValidationError`] for more details.
628    #[error(transparent)]
629    LeafNodeValidation(#[from] LeafNodeValidationError),
630    /// Regular Commits may not contain ExternalInit proposals, but one was found
631    #[error("Found ExternalInit proposal in regular commit")]
632    ExternalInitProposalInRegularCommit,
633}
634
635/// External Commit validaton error
636#[derive(Error, Debug, PartialEq, Clone)]
637pub enum ExternalCommitValidationError {
638    /// See [`LibraryError`] for more details.
639    #[error(transparent)]
640    LibraryError(#[from] LibraryError),
641    /// No ExternalInit proposal found.
642    #[error("No ExternalInit proposal found.")]
643    NoExternalInitProposals,
644    /// Multiple ExternalInit proposal found.
645    #[error("Multiple ExternalInit proposal found.")]
646    MultipleExternalInitProposals,
647    /// Found inline Add or Update proposals.
648    #[error("Found inline Add or Update proposals.")]
649    InvalidInlineProposals,
650    /// Found multiple inline Remove proposals.
651    #[error("Found multiple inline Remove proposals.")]
652    MultipleRemoveProposals,
653    /// Remove proposal targets the wrong group member.
654    #[error("Remove proposal targets the wrong group member.")]
655    InvalidRemoveProposal,
656    /// External Commit has to contain a path.
657    #[error("External Commit has to contain a path.")]
658    NoPath,
659    /// External commit contains referenced proposal
660    #[error("Found a referenced proposal in an External Commit.")]
661    ReferencedProposal,
662    /// External committer's leaf node does not support all group context extensions.
663    #[error("External committer's leaf node does not support all group context extensions.")]
664    UnsupportedGroupContextExtensions,
665}
666
667/// Create add proposal error
668#[derive(Error, Debug, PartialEq, Clone)]
669pub enum CreateAddProposalError {
670    /// See [`LibraryError`] for more details.
671    #[error(transparent)]
672    LibraryError(#[from] LibraryError),
673    /// See [`LeafNodeValidationError`] for more details.
674    #[error(transparent)]
675    LeafNodeValidation(#[from] LeafNodeValidationError),
676}
677
678// === Crate errors ===
679
680/// Proposal queue error
681#[derive(Error, Debug, PartialEq, Clone)]
682pub(crate) enum ProposalQueueError {
683    /// See [`LibraryError`] for more details.
684    #[error(transparent)]
685    LibraryError(#[from] LibraryError),
686    /// Not all proposals in the Commit were found locally.
687    #[error("Not all proposals in the Commit were found locally.")]
688    ProposalNotFound,
689    /// Update proposal from external sender.
690    #[error("Update proposal from external sender.")]
691    UpdateFromExternalSender,
692    /// SelfRemove proposal from a non-Member.
693    #[error("SelfRemove proposal from a non-Member.")]
694    SelfRemoveFromNonMember,
695}
696
697/// Errors that can arise when creating a [`ProposalQueue`] from committed
698/// proposals.
699#[derive(Error, Debug, PartialEq, Clone)]
700pub(crate) enum FromCommittedProposalsError {
701    /// See [`LibraryError`] for more details.
702    #[error(transparent)]
703    LibraryError(#[from] LibraryError),
704    /// Not all proposals in the Commit were found locally.
705    #[error("Not all proposals in the Commit were found locally.")]
706    ProposalNotFound,
707    /// The sender of a Commit tried to remove themselves.
708    #[error("The sender of a Commit tried to remove themselves.")]
709    SelfRemoval,
710    /// Commit contains two PSK proposals with the same PSK ID.
711    #[error("Commit contains two PSK proposals the PSK ID {0:?}.")]
712    DuplicatePskId(PreSharedKeyId),
713}
714
715/// Create group context ext proposal error
716#[derive(Error, Debug, PartialEq, Clone)]
717pub enum CreateGroupContextExtProposalError<StorageError> {
718    /// See [`LibraryError`] for more details.
719    #[error(transparent)]
720    LibraryError(#[from] LibraryError),
721    /// See [`KeyPackageExtensionSupportError`] for more details.
722    #[error(transparent)]
723    KeyPackageExtensionSupport(#[from] KeyPackageExtensionSupportError),
724    /// See [`ExtensionError`] for more details.
725    #[error(transparent)]
726    Extension(#[from] ExtensionError),
727    /// See [`LeafNodeValidationError`] for more details.
728    #[error(transparent)]
729    LeafNodeValidation(#[from] LeafNodeValidationError),
730    /// See [`MlsGroupStateError`] for more details.
731    #[error(transparent)]
732    MlsGroupStateError(#[from] MlsGroupStateError),
733    /// See [`CreateCommitError`] for more details.
734    #[error(transparent)]
735    CreateCommitError(#[from] CreateCommitError),
736    /// See [`CommitBuilderStageError`] for more details.
737    #[error(transparent)]
738    CommitBuilderStageError(#[from] CommitBuilderStageError<StorageError>),
739    /// Error writing updated group to storage.
740    #[error("Error writing updated group data to storage.")]
741    StorageError(StorageError),
742    /// Error validating the extensions
743    #[error(transparent)]
744    InvalidExtensionError(#[from] InvalidExtensionError),
745}
746
747/// Error merging a commit.
748#[derive(Error, Debug, PartialEq, Clone)]
749pub enum MergeCommitError<StorageError> {
750    /// See [`LibraryError`] for more details.
751    #[error(transparent)]
752    LibraryError(#[from] LibraryError),
753    /// Error writing updated group to storage.
754    #[error("Error writing updated group data to storage.")]
755    StorageError(StorageError),
756}
757
758#[cfg(feature = "extensions-draft")]
759/// Error validating an AppDataUpdate proposal.
760#[derive(Error, Debug, PartialEq, Clone)]
761pub enum AppDataUpdateValidationError {
762    /// [`AppDataUpdateProposal`](crate::messages::proposals::AppDataUpdateProposal)s
763    /// occur before
764    /// [`GroupContextExtensionsProposal`](crate::messages::proposals::GroupContextExtensionProposal)s.
765    #[error("AppDataUpdate proposals occur before GroupContextExtensions proposals.")]
766    IncorrectOrder,
767    /// Attempted to update the [`AppDataDictionary`](crate::extensions::AppDataDictionary)
768    /// in the
769    /// [`GroupContextExtensionsProposal`](crate::messages::proposals::GroupContextExtensionProposal) directly.
770    #[error("Attempted to update the AppDataDictionary in the GroupContextExtensions proposal directly.")]
771    CannotUpdateDictionaryDirectly,
772    /// More than one [`AppDataUpdate]` proposal per [`ComponentId`] had a Remove operation.
773    ///
774    /// [`ComponentId`]: crate::component::ComponentId
775    #[error("More than one AppDataUpdate proposal per ComponentId had a Remove operation.")]
776    MoreThanOneRemovePerComponentId,
777    /// Proposals for a [`ComponentId`] had both Remove and Update operations.
778    ///
779    /// [`ComponentId`]: crate::component::ComponentId
780    #[error("Proposals for a ComponentId had both Remove and Update operations.")]
781    CombinedRemoveAndUpdateOperations,
782    /// Proposals for a [`ComponentId`] had a Remove for a nonexistent component.
783    ///
784    /// [`ComponentId`]: crate::component::ComponentId
785    #[error("Proposals for a ComponentId had a Remove for a nonexistent component.")]
786    CannotRemoveNonexistentComponent,
787}
788
789/// Error validation a GroupContextExtensions proposal.
790#[derive(Error, Debug, PartialEq, Clone)]
791pub enum GroupContextExtensionsProposalValidationError {
792    /// Commit has more than one GroupContextExtensions proposal.
793    #[error("Commit has more than one GroupContextExtensions proposal.")]
794    TooManyGCEProposals,
795
796    /// See [`LibraryError`] for more details.
797    #[error(transparent)]
798    LibraryError(#[from] LibraryError),
799
800    /// The new extension types in required capabilties contails extensions that are not supported by all group members.
801    #[error(
802        "The new required capabilties contain extension types that are not supported by all group members."
803    )]
804    ExtensionNotSupportedByAllMembers,
805    /// Proposal changes the immutable metadata extension, which is not allowed.
806    #[error("Proposal changes the immutable metadata extension, which is not allowed.")]
807    ChangedImmutableMetadata,
808
809    /// The new extension types in required capabilties contails extensions that are not supported by all group members.
810    #[error(
811        "The new required capabilties contain extension types that are not supported by all group members."
812    )]
813    RequiredExtensionNotSupportedByAllMembers,
814
815    /// An extension in the group context extensions is not listed in the required capabilties'
816    /// extension types.
817    #[error(
818        "An extension in the group context extensions is not listed in the required capabilties' extension types."
819    )]
820    ExtensionNotInRequiredCapabilities,
821
822    /// An extension with a type that is not valid in the group context
823    #[error("Expected valid `Extension` for `GroupContextExtension`, got `{wrong:?}`")]
824    InvalidExtensionTypeError {
825        /// found invalid type
826        wrong: ExtensionType,
827    },
828}