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
//! Error structs
use crate::ArchiveEntryId;
use crate::entry::EntryName;
use std::error;
use std::fmt;
use std::io;
#[non_exhaustive]
#[derive(Debug)]
pub enum Error {
/// IO Error (not enough data, etc.)
IOError(io::Error),
/// Wrong magic, must be "MLAFAAA"
WrongMagic,
/// Unsupported version, must be 2
UnsupportedVersion,
/// Supplied key is not in the expected format
InvalidKeyFormat,
/// Wrong `BlockSubFile` magic has been encountered. Is the deserializion
/// starting at the beginning of a block?
WrongBlockSubFileType,
/// An error has occurred while converting into UTF8. This error could
/// happens while parsing the entry data name
UTF8ConversionError(std::string::FromUtf8Error),
/// `EntryNames` have a limited size `ENTRY_NAME_MAX_SIZE`
EntryNameTooLong,
/// The writer state is not in the expected state for the current operation
WrongArchiveWriterState {
current_state: String,
expected_state: String,
},
/// Should never happens: an internal assumptions no more hold
AssertionError(String),
/// The reader state is not in the expected state for the current operation
WrongReaderState(String),
/// The writer state is not in the expected state for the current operation
WrongWriterState(String),
/// Error with the inner random generator
RandError,
/// A Private Key is required to decrypt the encrypted cipher key
PrivateKeyNeeded,
/// Deserialization error. May happens when starting from a wrong offset /
/// version mismatch
DeserializationError,
/// Serialization error. May happens on I/O errors
SerializationError,
/// Missing metadata (usually means the footer has not been correctly read,
/// a `clean-truncated` operation might be needed)
MissingMetadata,
/// Error returned on API call with incorrect argument
BadAPIArgument(String),
/// End of stream reached, no more data should be expected
EndOfStream,
/// An error happens in the configuration
ConfigError(ConfigError),
/// `EntryName` already used
DuplicateEntryName,
/// Wrong tag while decrypting authenticated data
AuthenticatedDecryptionWrongTag,
/// Unable to expand while using the HKDF
HKDFInvalidKeyLength,
/// Error during HPKE computation
HPKEError,
/// Invalid last tag
InvalidLastTag,
/// User asked for encryption but archive was not marked as encrypted
EncryptionAskedButNotMarkedPresent,
/// MLA archive must be terminated by EMLAAAAA
WrongEndMagic,
// Cannot validate any signature
NoValidSignatureFound,
// Signature verification was asked but no signature layer was found
SignatureVerificationAskedButNoSignatureLayerFound,
// MissingEndOfEncryptedInnerLayerMagic
MissingEndOfEncryptedInnerLayerMagic,
// TruncatedTag
TruncatedTag,
// UnknownTagPosition
UnknownTagPosition,
// Arbitrary String error
Other(String),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// For now, use the debug derived version
write!(f, "{self:?}")
}
}
impl From<io::Error> for Error {
fn from(error: io::Error) -> Self {
Error::IOError(error)
}
}
impl From<std::string::FromUtf8Error> for Error {
fn from(error: std::string::FromUtf8Error) -> Self {
Error::UTF8ConversionError(error)
}
}
impl From<Error> for io::Error {
fn from(error: Error) -> Self {
io::Error::other(format!("{error}"))
}
}
impl From<ConfigError> for Error {
fn from(error: ConfigError) -> Self {
match error {
ConfigError::PrivateKeyNotSet => Error::PrivateKeyNeeded,
_ => Error::ConfigError(error),
}
}
}
impl error::Error for Error {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match &self {
Error::IOError(err) => Some(err),
Error::UTF8ConversionError(err) => Some(err),
Error::ConfigError(err) => Some(err),
_ => None,
}
}
}
#[non_exhaustive]
#[derive(Debug)]
pub enum TruncatedReadError {
/// Everything ends correctly
NoError,
/// An unexpected EOF occurs while getting the next block
UnexpectedEOFOnNextBlock,
/// An IO error occurs while reading the next block
IOErrorOnNextBlock(io::Error),
/// A Error occurs while reading the next block
ErrorOnNextBlock(Error),
/// An error occurs in the middle of a file
ErrorInFile(io::Error, String),
/// A file ID is being reused
ArchiveEntryIDReuse(ArchiveEntryId),
/// An entry name is being reused
EntryNameReuse(String),
/// Data for a file already closed
ArchiveEntryIDAlreadyClosed(ArchiveEntryId),
/// Content for an unknown file
ContentForUnknownFile(ArchiveEntryId),
/// Termination of an unknwown file
EOFForUnknownFile(ArchiveEntryId),
/// Wraps an already existing error and indicates which files are not
/// finished (a file can be finished but uncompleted)
UnfinishedEntries {
names: Vec<EntryName>,
stopping_error: Box<TruncatedReadError>,
},
/// End of original archive reached - this is the best case
EndOfOriginalArchiveData,
/// Error in the `TruncatedReader` internal state
TruncatedReadInternalError,
/// The file's hash does not correspond to the expected one
HashDiffers {
expected: Vec<u8>,
obtained: Vec<u8>,
},
}
impl fmt::Display for TruncatedReadError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// For now, use the debug derived version
write!(f, "{self:?}")
}
}
impl error::Error for TruncatedReadError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match &self {
TruncatedReadError::IOErrorOnNextBlock(err) => Some(err),
TruncatedReadError::ErrorOnNextBlock(err) => Some(err),
TruncatedReadError::ErrorInFile(err, _path) => Some(err),
_ => None,
}
}
}
#[non_exhaustive]
#[derive(Debug)]
pub enum ConfigError {
IncoherentPersistentConfig,
// Compression specifics
CompressionLevelOutOfRange,
// Encryption specifics
/// No recipients provided, encryption can't continue
NoRecipients,
/// Internal state has not yet been created. A call to `to_persistent` might be missing
EncryptionKeyIsMissing,
PrivateKeyNotSet,
PrivateKeyNotFound,
MLKEMComputationError,
DHKEMComputationError,
KeyCommitmentComputationError,
/// The encrypted key commitment does not correspond to the key commitment chain
KeyCommitmentCheckingError,
/// Error while wrapping or unwrapping the encryption key
KeyWrappingComputationError,
}
impl fmt::Display for ConfigError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// For now, use the debug derived version
write!(f, "{self:?}")
}
}
impl error::Error for ConfigError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
None
}
}