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 thiserror::Error;
6
7pub use super::mls_group::errors::*;
8use super::public_group::errors::CreationFromExternalError;
9use crate::{
10    ciphersuite::signable::SignatureError,
11    error::LibraryError,
12    extensions::errors::{ExtensionError, InvalidExtensionError},
13    framing::errors::MessageDecryptionError,
14    key_packages::errors::{KeyPackageExtensionSupportError, KeyPackageVerifyError},
15    messages::{group_info::GroupInfoError, GroupSecretsError},
16    schedule::errors::PskError,
17    treesync::errors::*,
18};
19
20/// Welcome error
21#[derive(Error, Debug, PartialEq, Clone)]
22pub enum WelcomeError<StorageError> {
23    /// See [`GroupSecretsError`] for more details.
24    #[error(transparent)]
25    GroupSecrets(#[from] GroupSecretsError),
26    /// Private part of `init_key` not found in key store.
27    #[error("Private part of `init_key` not found in key store.")]
28    PrivateInitKeyNotFound,
29    /// See [`LibraryError`] for more details.
30    #[error(transparent)]
31    LibraryError(#[from] LibraryError),
32    /// Ciphersuites in Welcome and key package bundle don't match.
33    #[error("Ciphersuites in Welcome and key package bundle don't match.")]
34    CiphersuiteMismatch,
35    /// See [`GroupInfoError`] for more details.
36    #[error(transparent)]
37    GroupInfo(#[from] GroupInfoError),
38    /// No joiner secret found in the Welcome message.
39    #[error("No joiner secret found in the Welcome message.")]
40    JoinerSecretNotFound,
41    /// No ratchet tree available to build initial tree after receiving a Welcome message.
42    #[error("No ratchet tree available to build initial tree after receiving a Welcome message.")]
43    MissingRatchetTree,
44    /// The computed confirmation tag does not match the expected one.
45    #[error("The computed confirmation tag does not match the expected one.")]
46    ConfirmationTagMismatch,
47    /// The signature on the GroupInfo is not valid.
48    #[error("The signature on the GroupInfo is not valid.")]
49    InvalidGroupInfoSignature,
50    /// We don't support the version of the group we are trying to join.
51    #[error("We don't support the version of the group we are trying to join.")]
52    UnsupportedMlsVersion,
53    /// We don't support all capabilities of the group.
54    #[error("We don't support all capabilities of the group.")]
55    UnsupportedCapability,
56    /// Sender not found in tree.
57    #[error("Sender not found in tree.")]
58    UnknownSender,
59    /// The provided message is not a Welcome message.
60    #[error("Not a Welcome message.")]
61    NotAWelcomeMessage,
62    /// Malformed Welcome message.
63    #[error("Malformed Welcome message.")]
64    MalformedWelcomeMessage,
65    /// Could not decrypt the Welcome message.
66    #[error("Could not decrypt the Welcome message.")]
67    UnableToDecrypt,
68    /// Unsupported extensions found in the KeyPackage of another member.
69    #[error("Unsupported extensions found in the KeyPackage of another member.")]
70    UnsupportedExtensions,
71    /// See [`PskError`] for more details.
72    #[error(transparent)]
73    Psk(#[from] PskError),
74    /// No matching encryption key was found in the key store.
75    #[error("No matching encryption key was found in the key store.")]
76    NoMatchingEncryptionKey,
77    /// No matching key package was found in the key store.
78    #[error("No matching key package was found in the key store.")]
79    NoMatchingKeyPackage,
80    /// This error indicates the public tree is invalid. See [`PublicTreeError`] for more details.
81    #[error(transparent)]
82    PublicTreeError(#[from] PublicTreeError),
83    /// This error indicates the public tree is invalid. See
84    /// [`CreationFromExternalError`] for more details.
85    #[error(transparent)]
86    PublicGroupError(#[from] CreationFromExternalError<StorageError>),
87    /// This error indicates the leaf node is invalid. See [`LeafNodeValidationError`] for more details.
88    #[error(transparent)]
89    LeafNodeValidation(#[from] LeafNodeValidationError),
90    /// This error indicates that an error occurred while reading or writing from/to storage.
91    #[error("An error occurred when querying storage")]
92    StorageError(StorageError),
93}
94
95/// External Commit error
96#[derive(Error, Debug, PartialEq, Clone)]
97pub enum ExternalCommitError<StorageError> {
98    /// See [`LibraryError`] for more details.
99    #[error(transparent)]
100    LibraryError(#[from] LibraryError),
101    /// No ratchet tree available to build initial tree.
102    #[error("No ratchet tree available to build initial tree.")]
103    MissingRatchetTree,
104    /// No external_pub extension available to join group by external commit.
105    #[error("No external_pub extension available to join group by external commit.")]
106    MissingExternalPub,
107    /// We don't support the ciphersuite of the group we are trying to join.
108    #[error("We don't support the ciphersuite of the group we are trying to join.")]
109    UnsupportedCiphersuite,
110    /// Sender not found in tree.
111    #[error("Sender not found in tree.")]
112    UnknownSender,
113    /// The signature over the given group info is invalid.
114    #[error("The signature over the given group info is invalid.")]
115    InvalidGroupInfoSignature,
116    /// Error creating external commit.
117    #[error("Error creating external commit.")]
118    CommitError,
119    /// This error indicates the public tree is invalid. See
120    /// [`CreationFromExternalError`] for more details.
121    #[error(transparent)]
122    PublicGroupError(#[from] CreationFromExternalError<StorageError>),
123    /// Credential is missing from external commit.
124    #[error("Credential is missing from external commit.")]
125    MissingCredential,
126    /// An erorr occurred when writing group to storage
127    #[error("An error occurred when writing group to storage.")]
128    StorageError(StorageError),
129}
130
131/// Stage Commit error
132#[derive(Error, Debug, PartialEq, Clone)]
133pub enum StageCommitError {
134    /// See [`LibraryError`] for more details.
135    #[error(transparent)]
136    LibraryError(#[from] LibraryError),
137    /// The epoch of the group context and PublicMessage didn't match.
138    #[error("The epoch of the group context and PublicMessage didn't match.")]
139    EpochMismatch,
140    /// The Commit was created by this client.
141    #[error("The Commit was created by this client.")]
142    OwnCommit,
143    /// stage_commit was called with an PublicMessage that is not a Commit.
144    #[error("stage_commit was called with an PublicMessage that is not a Commit.")]
145    WrongPlaintextContentType,
146    /// Unable to verify the leaf node signature.
147    #[error("Unable to verify the leaf node signature.")]
148    PathLeafNodeVerificationFailure,
149    /// Unable to determine commit path.
150    #[error("Unable to determine commit path.")]
151    RequiredPathNotFound,
152    /// The confirmation Tag is missing.
153    #[error("The confirmation Tag is missing.")]
154    ConfirmationTagMissing,
155    /// The confirmation tag is invalid.
156    #[error("The confirmation tag is invalid.")]
157    ConfirmationTagMismatch,
158    /// The committer can't remove themselves.
159    #[error("The committer can't remove themselves.")]
160    AttemptedSelfRemoval,
161    /// The proposal queue is missing a proposal for the commit.
162    #[error("The proposal queue is missing a proposal for the commit.")]
163    MissingProposal,
164    /// Missing own key to apply proposal.
165    #[error("Missing own key to apply proposal.")]
166    OwnKeyNotFound,
167    /// External Committer used the wrong index.
168    #[error("External Committer used the wrong index.")]
169    InconsistentSenderIndex,
170    /// The sender is of type external, which is not valid.
171    #[error("The sender is of type external, which is not valid.")]
172    SenderTypeExternal,
173    /// The sender is of type `NewMemberProposal`, which is not valid.
174    #[error("The sender is of type NewMemberProposal, which is not valid.")]
175    SenderTypeNewMemberProposal,
176    /// Too many new members: the tree is full.
177    #[error("Too many new members: the tree is full.")]
178    TooManyNewMembers,
179    /// See [`ProposalValidationError`] for more details.
180    #[error(transparent)]
181    ProposalValidationError(#[from] ProposalValidationError),
182    /// See [`PskError`] for more details.
183    #[error(transparent)]
184    PskError(#[from] PskError),
185    /// See [`ExternalCommitValidationError`] for more details.
186    #[error(transparent)]
187    ExternalCommitValidation(#[from] ExternalCommitValidationError),
188    /// See [`ApplyUpdatePathError`] for more details.
189    #[error(transparent)]
190    UpdatePathError(#[from] ApplyUpdatePathError),
191    /// Missing decryption key.
192    #[error("Missing decryption key.")]
193    MissingDecryptionKey,
194    /// See [`UpdatePathError`] for more details.
195    #[error(transparent)]
196    VerifiedUpdatePathError(#[from] UpdatePathError),
197    /// See [`GroupContextExtensionsProposalValidationError`] for more details.
198    #[error(transparent)]
199    GroupContextExtensionsProposalValidationError(
200        #[from] GroupContextExtensionsProposalValidationError,
201    ),
202    /// See [`LeafNodeValidationError`] for more details.
203    #[error(transparent)]
204    LeafNodeValidation(#[from] LeafNodeValidationError),
205}
206
207/// Create commit error
208#[derive(Error, Debug, PartialEq, Clone)]
209pub enum CreateCommitError {
210    /// See [`LibraryError`] for more details.
211    #[error(transparent)]
212    LibraryError(#[from] LibraryError),
213    /// Missing own key to apply proposal.
214    #[error("Missing own key to apply proposal.")]
215    OwnKeyNotFound,
216    /// The Commit tried to remove self from the group. This is not possible.
217    #[error("The Commit tried to remove self from the group. This is not possible.")]
218    CannotRemoveSelf,
219    /// The proposal queue is missing a proposal for the commit.
220    #[error("The proposal queue is missing a proposal for the commit.")]
221    MissingProposal,
222    /// A proposal has the wrong sender type.
223    #[error("A proposal has the wrong sender type.")]
224    WrongProposalSenderType,
225    /// See [`PskError`] for more details.
226    #[error(transparent)]
227    PskError(#[from] PskError),
228    /// See [`ProposalValidationError`] for more details.
229    #[error(transparent)]
230    ProposalValidationError(#[from] ProposalValidationError),
231    /// See [`SignatureError`] for more details.
232    #[error(transparent)]
233    SignatureError(#[from] SignatureError),
234    /// Credential is missing from external commit.
235    #[error("Credential is missing from external commit.")]
236    MissingCredential,
237    /// This error indicates the public tree is invalid. See [`PublicTreeError`] for more details.
238    #[error(transparent)]
239    PublicTreeError(#[from] PublicTreeError),
240    /// See [`InvalidExtensionError`] for more details.
241    #[error(transparent)]
242    InvalidExtensionError(#[from] InvalidExtensionError),
243    /// See [`GroupContextExtensionsProposalValidationError`] for more details.
244    #[error(transparent)]
245    GroupContextExtensionsProposalValidationError(
246        #[from] GroupContextExtensionsProposalValidationError,
247    ),
248    /// See [`TreeSyncAddLeaf`] for more details.
249    #[error(transparent)]
250    TreeSyncAddLeaf(#[from] TreeSyncAddLeaf),
251}
252
253/// Stage commit error
254#[derive(Error, Debug, PartialEq, Clone)]
255pub enum CommitBuilderStageError<StorageError> {
256    /// See [`LibraryError`] for more details.
257    #[error(transparent)]
258    LibraryError(#[from] LibraryError),
259    /// Error interacting with storage.
260    #[error("Error interacting with storage.")]
261    KeyStoreError(StorageError),
262}
263
264/// Validation error
265#[derive(Error, Debug, PartialEq, Clone)]
266pub enum ValidationError {
267    /// See [`LibraryError`] for more details.
268    #[error(transparent)]
269    LibraryError(#[from] LibraryError),
270    /// Message group ID differs from the group's group ID.
271    #[error("Message group ID differs from the group's group ID.")]
272    WrongGroupId,
273    /// Message epoch differs from the group's epoch.
274    #[error("Message epoch differs from the group's epoch.")]
275    WrongEpoch,
276    /// The PublicMessage is not a Commit despite the sender begin of type [NewMemberCommit](crate::prelude::Sender::NewMemberCommit).
277    #[error("The PublicMessage is not a Commit despite the sender begin of type NewMemberCommit.")]
278    NotACommit,
279    /// The PublicMessage is not an External Add Proposal despite the sender begin of type [NewMemberProposal](crate::prelude::Sender::NewMemberProposal).
280    #[error("The PublicMessage is not an external Add proposal despite the sender begin of type NewMemberProposal.")]
281    NotAnExternalAddProposal,
282    /// The Commit doesn't have a path despite the sender being of type NewMemberCommit.
283    #[error("The Commit doesn't have a path despite the sender being of type NewMemberCommit.")]
284    NoPath,
285    /// The PublicMessage contains an application message but was not encrypted.
286    #[error("The PublicMessage contains an application message but was not encrypted.")]
287    UnencryptedApplicationMessage,
288    /// Sender is not part of the group.
289    #[error("Sender is not part of the group.")]
290    UnknownMember,
291    /// Membership tag is missing.
292    #[error("Membership tag is missing.")]
293    MissingMembershipTag,
294    /// Membership tag is invalid.
295    #[error("Membership tag is invalid.")]
296    InvalidMembershipTag,
297    /// The confirmation tag is missing.
298    #[error("The confirmation tag is missing.")]
299    MissingConfirmationTag,
300    /// Wrong wire format.
301    #[error("Wrong wire format.")]
302    WrongWireFormat,
303    /// Verifying the signature failed.
304    #[error("Verifying the signature failed.")]
305    InvalidSignature,
306    /// An application message was sent from an external sender.
307    #[error("An application message was sent from an external sender.")]
308    NonMemberApplicationMessage,
309    /// Could not decrypt the message
310    #[error(transparent)]
311    UnableToDecrypt(#[from] MessageDecryptionError),
312    /// The message is from an epoch too far in the past.
313    #[error("The message is from an epoch too far in the past.")]
314    NoPastEpochData,
315    /// The provided external sender is not authorized to send external proposals
316    #[error("The provided external sender is not authorized to send external proposals")]
317    UnauthorizedExternalSender,
318    /// The group doesn't contain external senders extension.
319    #[error("The group doesn't contain external senders extension")]
320    NoExternalSendersExtension,
321    /// The KeyPackage could not be validated.
322    #[error(transparent)]
323    KeyPackageVerifyError(#[from] KeyPackageVerifyError),
324    /// The UpdatePath could not be validated.
325    #[error(transparent)]
326    UpdatePathError(#[from] UpdatePathError),
327    /// Invalid LeafNode signature.
328    #[error("Invalid LeafNode signature.")]
329    InvalidLeafNodeSignature,
330    /// Invalid LeafNode source type
331    #[error("Invalid LeafNode source type")]
332    InvalidLeafNodeSourceType,
333    /// Invalid sender type.
334    #[error("Invalid sender type")]
335    InvalidSenderType,
336    /// The Commit includes update proposals from the committer.
337    #[error("The Commit includes update proposals from the committer.")]
338    CommitterIncludedOwnUpdate,
339    /// The ciphersuite in the KeyPackage of the Add proposal does not match the group context.
340    #[error(
341        "The ciphersuite in the KeyPackage of the Add proposal does not match the group context."
342    )]
343    InvalidAddProposalCiphersuite,
344    /// Cannot decrypt own messages because the necessary key has been deleted according to the deletion schedule.
345    #[error("Cannot decrypt own messages.")]
346    CannotDecryptOwnMessage,
347    /// See [`ExternalCommitValidationError`] for more details.
348    #[error(transparent)]
349    ExternalCommitValidation(#[from] ExternalCommitValidationError),
350}
351
352/// Proposal validation error
353#[derive(Error, Debug, PartialEq, Clone)]
354pub enum ProposalValidationError {
355    /// See [`LibraryError`] for more details.
356    #[error(transparent)]
357    LibraryError(#[from] LibraryError),
358    /// The sender could not be matched to a member of the group.
359    #[error("The sender could not be matched to a member of the group.")]
360    UnknownMember,
361    /// Duplicate signature key in proposals and group.
362    #[error("Duplicate signature key in proposals and group.")]
363    DuplicateSignatureKey,
364    /// Duplicate encryption key in proposals and group.
365    #[error("Duplicate encryption key in proposals and group.")]
366    DuplicateEncryptionKey,
367    /// Duplicate init key in proposals.
368    #[error("Duplicate init key in proposals.")]
369    DuplicateInitKey,
370    /// The HPKE init and encryption keys are the same.
371    #[error("The HPKE init and encryption keys are the same.")]
372    InitEncryptionKeyCollision,
373    /// Duplicate remove proposals for the same member.
374    #[error("Duplicate remove proposals for the same member.")]
375    DuplicateMemberRemoval,
376    /// The remove proposal referenced a non-existing member.
377    #[error("The remove proposal referenced a non-existing member.")]
378    UnknownMemberRemoval,
379    /// Found an update from a non-member.
380    #[error("Found an update from a non-member.")]
381    UpdateFromNonMember,
382    /// The Commit includes update proposals from the committer.
383    #[error("The Commit includes update proposals from the committer.")]
384    CommitterIncludedOwnUpdate,
385    /// The capabilities of the add proposal are insufficient for this group.
386    #[error("The capabilities of the add proposal are insufficient for this group.")]
387    InsufficientCapabilities,
388    /// The add proposal's ciphersuite or protocol version do not match the ones in the group context.
389    #[error(
390        "The add proposal's ciphersuite or protocol version do not match the ones in the group context."
391    )]
392    InvalidAddProposalCiphersuiteOrVersion,
393    /// See [`PskError`] for more details.
394    #[error(transparent)]
395    Psk(#[from] PskError),
396    /// The proposal type is not supported by all group members.
397    #[error("The proposal type is not supported by all group members.")]
398    UnsupportedProposalType,
399    /// See [`LeafNodeValidationError`] for more details.
400    #[error(transparent)]
401    LeafNodeValidation(#[from] LeafNodeValidationError),
402    /// Regular Commits may not contain ExternalInit proposals, but one was found
403    #[error("Found ExternalInit proposal in regular commit")]
404    ExternalInitProposalInRegularCommit,
405}
406
407/// External Commit validaton error
408#[derive(Error, Debug, PartialEq, Clone)]
409pub enum ExternalCommitValidationError {
410    /// See [`LibraryError`] for more details.
411    #[error(transparent)]
412    LibraryError(#[from] LibraryError),
413    /// No ExternalInit proposal found.
414    #[error("No ExternalInit proposal found.")]
415    NoExternalInitProposals,
416    /// Multiple ExternalInit proposal found.
417    #[error("Multiple ExternalInit proposal found.")]
418    MultipleExternalInitProposals,
419    /// Found inline Add or Update proposals.
420    #[error("Found inline Add or Update proposals.")]
421    InvalidInlineProposals,
422    /// Found multiple inline Remove proposals.
423    #[error("Found multiple inline Remove proposals.")]
424    MultipleRemoveProposals,
425    /// Remove proposal targets the wrong group member.
426    #[error("Remove proposal targets the wrong group member.")]
427    InvalidRemoveProposal,
428    /// External Commit has to contain a path.
429    #[error("External Commit has to contain a path.")]
430    NoPath,
431    /// External commit contains referenced proposal
432    #[error("Found a referenced proposal in an External Commit.")]
433    ReferencedProposal,
434}
435
436/// Create add proposal error
437#[derive(Error, Debug, PartialEq, Clone)]
438pub enum CreateAddProposalError {
439    /// See [`LibraryError`] for more details.
440    #[error(transparent)]
441    LibraryError(#[from] LibraryError),
442    /// See [`LeafNodeValidationError`] for more details.
443    #[error(transparent)]
444    LeafNodeValidation(#[from] LeafNodeValidationError),
445}
446
447// === Crate errors ===
448
449/// Proposal queue error
450#[derive(Error, Debug, PartialEq, Clone)]
451pub(crate) enum ProposalQueueError {
452    /// See [`LibraryError`] for more details.
453    #[error(transparent)]
454    LibraryError(#[from] LibraryError),
455    /// Not all proposals in the Commit were found locally.
456    #[error("Not all proposals in the Commit were found locally.")]
457    ProposalNotFound,
458    /// Update proposal from external sender.
459    #[error("Update proposal from external sender.")]
460    UpdateFromExternalSender,
461    /// SelfRemove proposal from a non-Member.
462    #[error("SelfRemove proposal from a non-Member.")]
463    SelfRemoveFromNonMember,
464}
465
466/// Errors that can arise when creating a [`ProposalQueue`] from committed
467/// proposals.
468#[derive(Error, Debug, PartialEq, Clone)]
469pub(crate) enum FromCommittedProposalsError {
470    /// See [`LibraryError`] for more details.
471    #[error(transparent)]
472    LibraryError(#[from] LibraryError),
473    /// Not all proposals in the Commit were found locally.
474    #[error("Not all proposals in the Commit were found locally.")]
475    ProposalNotFound,
476    /// The sender of a Commit tried to remove themselves.
477    #[error("The sender of a Commit tried to remove themselves.")]
478    SelfRemoval,
479}
480
481/// Create group context ext proposal error
482#[derive(Error, Debug, PartialEq, Clone)]
483pub enum CreateGroupContextExtProposalError<StorageError> {
484    /// See [`LibraryError`] for more details.
485    #[error(transparent)]
486    LibraryError(#[from] LibraryError),
487    /// See [`KeyPackageExtensionSupportError`] for more details.
488    #[error(transparent)]
489    KeyPackageExtensionSupport(#[from] KeyPackageExtensionSupportError),
490    /// See [`ExtensionError`] for more details.
491    #[error(transparent)]
492    Extension(#[from] ExtensionError),
493    /// See [`LeafNodeValidationError`] for more details.
494    #[error(transparent)]
495    LeafNodeValidation(#[from] LeafNodeValidationError),
496    /// See [`MlsGroupStateError`] for more details.
497    #[error(transparent)]
498    MlsGroupStateError(#[from] MlsGroupStateError),
499    /// See [`CreateCommitError`] for more details.
500    #[error(transparent)]
501    CreateCommitError(#[from] CreateCommitError),
502    /// See [`CommitBuilderStageError`] for more details.
503    #[error(transparent)]
504    CommitBuilderStageError(#[from] CommitBuilderStageError<StorageError>),
505    /// Error writing updated group to storage.
506    #[error("Error writing updated group data to storage.")]
507    StorageError(StorageError),
508}
509
510/// Error merging a commit.
511#[derive(Error, Debug, PartialEq, Clone)]
512pub enum MergeCommitError<StorageError> {
513    /// See [`LibraryError`] for more details.
514    #[error(transparent)]
515    LibraryError(#[from] LibraryError),
516    /// Error writing updated group to storage.
517    #[error("Error writing updated group data to storage.")]
518    StorageError(StorageError),
519}
520
521/// Error validation a GroupContextExtensions proposal.
522#[derive(Error, Debug, PartialEq, Clone)]
523pub enum GroupContextExtensionsProposalValidationError {
524    /// Commit has more than one GroupContextExtensions proposal.
525    #[error("Commit has more than one GroupContextExtensions proposal.")]
526    TooManyGCEProposals,
527
528    /// See [`LibraryError`] for more details.
529    #[error(transparent)]
530    LibraryError(#[from] LibraryError),
531
532    /// The new extension types in required capabilties contails extensions that are not supported by all group members.
533    #[error(
534        "The new required capabilties contain extension types that are not supported by all group members."
535    )]
536    ExtensionNotSupportedByAllMembers,
537    /// Proposal changes the immutable metadata extension, which is not allowed.
538    #[error("Proposal changes the immutable metadata extension, which is not allowed.")]
539    ChangedImmutableMetadata,
540
541    /// The new extension types in required capabilties contails extensions that are not supported by all group members.
542    #[error(
543        "The new required capabilties contain extension types that are not supported by all group members."
544    )]
545    RequiredExtensionNotSupportedByAllMembers,
546
547    /// An extension in the group context extensions is not listed in the required capabilties'
548    /// extension types.
549    #[error(
550        "An extension in the group context extensions is not listed in the required capabilties' extension types."
551    )]
552    ExtensionNotInRequiredCapabilities,
553}