1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
//! TreeSync errors
//!
//! This module exposes [`ApplyUpdatePathError`] and [`PublicTreeError`].

use thiserror::Error;

use super::*;
use crate::{
    binary_tree::MlsBinaryTreeDiffError, ciphersuite::signable::SignatureError, error::LibraryError,
};

// === Public errors ===

/// Public tree error
#[derive(Error, Debug, PartialEq, Eq, Clone)]
pub enum PublicTreeError {
    /// See [`LibraryError`] for more details.
    #[error(transparent)]
    LibraryError(#[from] LibraryError),
    /// The derived public key doesn't match the one in the tree.
    #[error("The derived public key doesn't match the one in the tree.")]
    PublicKeyMismatch,
    /// Found two KeyPackages with the same public key.
    #[error("Found two KeyPackages with the same public key.")]
    DuplicateKeyPackage,
    /// Couldn't find our own key package in this tree.
    #[error("Couldn't find our own key package in this tree.")]
    MissingKeyPackage,
    /// The tree is malformed.
    #[error("The tree is malformed.")]
    MalformedTree,
    /// A parent hash was invalid.
    #[error("A parent hash was invalid.")]
    InvalidParentHash,
    /// An update failed because the provided credential has a different identity than the one in the leaf node.
    #[error("An update failed because the provided credential has a different identity than the one in the leaf node.")]
    IdentityMismatch,
    /// See [`SignatureError`] for more details.
    #[error(transparent)]
    SignatureError(#[from] SignatureError),
}

/// Apply update path error
#[derive(Error, Debug, PartialEq, Clone)]
pub enum ApplyUpdatePathError {
    /// See [`LibraryError`] for more details.
    #[error(transparent)]
    LibraryError(#[from] LibraryError),
    /// The length of the received update path and that of the sender's direct path do not match.
    #[error(
        "The length of the received update path and that of the sender's direct path do not match."
    )]
    PathLengthMismatch,
    /// The received update path and the derived nodes are not identical.
    #[error("The received update path and the derived nodes are not identical.")]
    PathMismatch,
    /// The parent hash of the ney key package is invalid.
    #[error("The parent hash of the ney key package is invalid.")]
    ParentHashMismatch,
    /// The parent hash of the ney key package is missing.
    #[error("The parent hash of the ney key package is missing.")]
    MissingParentHash,
    /// Unable to decrypt the path node.
    #[error("Unable to decrypt the path node.")]
    UnableToDecrypt,
    /// Unable to find sender in tree.
    #[error("Unable to find sender in tree.")]
    MissingSender,
    /// Tree is already at maximum size.
    #[error("Tree is already at maximum size.")]
    TreeFull,
    /// External Committer used the wrong index.
    #[error("External Committer used the wrong index.")]
    InconsistentSenderIndex,
}

// === Crate errors ===

// TODO: This will go away in #819 again.
// `UnsupportedExtension` is only used in tests for now
#[allow(dead_code)]
/// TreeSync error
#[derive(Error, Debug, PartialEq, Clone)]
pub(crate) enum TreeSyncError {
    /// See [`LibraryError`] for more details.
    #[error(transparent)]
    LibraryError(#[from] LibraryError),
    /// A requested leaf is not in the tree.
    #[error("The leaf does not exist in the tree.")]
    LeafNotInTree,
    /// See [`TreeSyncSetPathError`] for more details.
    #[error(transparent)]
    SetPathError(#[from] DerivePathError),
    /// See [`MlsBinaryTreeError`] for more details.
    #[error(transparent)]
    BinaryTreeError(#[from] MlsBinaryTreeError),
    /// See [`TreeSyncDiffError`] for more details.
    #[error(transparent)]
    TreeSyncDiffError(#[from] TreeSyncDiffError),
    /// See [`PathSecretError`] for more details.
    #[error(transparent)]
    DerivationError(#[from] PathSecretError),

    /// See [`CryptoError`] for more details.
    #[error(transparent)]
    CryptoError(#[from] CryptoError),
    /// An extension type is not supported by a leaf in the tree.
    #[error("An extension type is not supported by a leaf in the tree.")]
    UnsupportedExtension,
    /// A capability is not supported by a leaf in the tree.
    #[error("A capability is not supported by a leaf in the tree.")]
    UnsupportedCapabilities,
    /// A proposal is not supported by a leaf in the tree.
    #[error("A proposal is not supported by a leaf in the tree.")]
    UnsupportedProposal,
}

/// Derive path error
#[derive(Error, Debug, PartialEq, Clone)]
pub(crate) enum DerivePathError {
    /// See [`LibraryError`] for more details.
    #[error(transparent)]
    LibraryError(#[from] LibraryError),
    /// The derived public key doesn't match the one in the tree.
    #[error("The derived public key doesn't match the one in the tree.")]
    PublicKeyMismatch,
}

/// TreeSync set path error
#[derive(Error, Debug, PartialEq, Clone)]
pub(crate) enum TreeSyncAddLeaf {
    /// See [`LibraryError`] for more details.
    #[error(transparent)]
    LibraryError(#[from] LibraryError),
    /// The tree is full, we cannot add any more leaves.
    #[error("The tree is full, we cannot add any more leaves.")]
    TreeFull,
}

/// TreeSync from nodes error
#[derive(Error, Debug, PartialEq, Clone)]
pub enum TreeSyncFromNodesError {
    /// See [`LibraryError`] for more details.
    #[error(transparent)]
    LibraryError(#[from] LibraryError),
    /// See [`PublicTreeError`] for more details.
    #[error(transparent)]
    PublicTreeError(#[from] PublicTreeError),
    /// See [`RatchetTreeError`] for more details.
    #[error(transparent)]
    RatchetTreeError(#[from] RatchetTreeError),
}

/// TreeSync parent hash error
#[derive(Error, Debug, PartialEq, Clone)]
pub(crate) enum TreeSyncParentHashError {
    /// See [`LibraryError`] for more details.
    #[error(transparent)]
    LibraryError(#[from] LibraryError),
    /// Parent hash mismatch.
    #[error("Parent hash mismatch.")]
    InvalidParentHash,
}

/// TreeSync parent hash error
#[derive(Error, Debug, PartialEq, Clone)]
pub(crate) enum TreeSyncDiffError {
    /// See [`LibraryError`] for more details.
    #[error(transparent)]
    LibraryError(#[from] LibraryError),
    #[error(
        "Couldn't find a fitting private key in the filtered resolution of the given leaf index."
    )]
    NoPrivateKeyFound,
    /// See [`MlsBinaryTreeDiffError`] for more details.
    #[error(transparent)]
    TreeDiffError(#[from] MlsBinaryTreeDiffError),
    /// See [`PathSecretError`] for more details.
    #[error(transparent)]
    DerivationError(#[from] PathSecretError),
    /// See [`MlsBinaryTreeError`] for more details.
    #[error(transparent)]
    CreationError(#[from] MlsBinaryTreeError),
}

/// TreeKem error
#[derive(Error, Debug, PartialEq, Clone)]
#[allow(clippy::enum_variant_names)]
pub(crate) enum TreeKemError {
    /// See [`LibraryError`] for more details.
    #[error(transparent)]
    LibraryError(#[from] LibraryError),
    /// See [`TreeSyncError`] for more details.
    #[error(transparent)]
    TreeSyncError(#[from] TreeSyncError),
    /// See [`TreeSyncDiffError`] for more details.
    #[error(transparent)]
    TreeSyncDiffError(#[from] TreeSyncDiffError),
    /// See [`PathSecretError`] for more details.
    #[error(transparent)]
    PathSecretError(#[from] PathSecretError),
}

/// Errors that can happen during leaf node validation.
#[derive(Clone, Debug, Error, Eq, PartialEq)]
pub enum LeafNodeValidationError {
    /// Lifetime is not acceptable.
    #[error("Lifetime is not acceptable.")]
    Lifetime(LifetimeError),
    /// Extensions are not acceptable.
    #[error("Extensions are not acceptable.")]
    UnsupportedExtensions,
    /// Proposals are not acceptable.
    #[error("Proposals are not acceptable.")]
    UnsupportedProposals,
    /// Credentials are not acceptable.
    #[error("Credentials are not acceptable.")]
    UnsupportedCredentials,
    /// The leaf node's credential type is not listed in the leaf node's capabilities."
    #[error("The leaf node's credential type is not listed in the leaf node's capabilities.")]
    CredentialNotInCapabilities,
    /// The leaf node's extension types are not (all) listed in the leaf node's capabilities.
    #[error(
        "The leaf node's extension types are not (all) listed in the leaf node's capabilities."
    )]
    ExtensionsNotInCapabilities,
    /// The leaf node's signature key is already used in the group.
    #[error("The leaf node's signature key is already used in the group.")]
    SignatureKeyAlreadyInUse,
    /// The leaf node's encryption key is already used in the group.
    #[error("The leaf node's encryption key is already used in the group.")]
    EncryptionKeyAlreadyInUse,
    /// The leaf node source is invalid in the given context.
    #[error("The leaf node source is invalid in the given context.")]
    InvalidLeafNodeSource,
    /// The leaf node credential is not supported by all members in the group.
    #[error("The leaf node credential is not supported by all members in the group.")]
    LeafNodeCredentialNotSupportedByMember,
    /// The credential used by a member is not supported by this leaf node.
    #[error("The credential used by a member is not supported by this leaf node.")]
    MemberCredentialNotSupportedByLeafNode,
}

/// Errors that can happen during lifetime validation.
#[derive(Clone, Debug, Error, Eq, PartialEq)]
pub enum LifetimeError {
    /// Lifetime range is too wide.
    #[error("Lifetime range is too wide.")]
    RangeTooBig,
    /// Lifetime doesn't cover current time.
    #[error("Lifetime doesn't cover current time.")]
    NotCurrent,
}

/// Errors that can happen during path validation.
#[derive(Debug, Clone, PartialEq, Eq, Error)]
pub enum UpdatePathError {
    /// The update path contains an invalid type of leaf node.
    #[error("The update path contains an invalid type of leaf node.")]
    InvalidType,
    /// See [`SignatureError`] for more details.
    #[error(transparent)]
    SignatureError(#[from] SignatureError),
}