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