Skip to main content

paysec_keyblock/tr31_2018/
error.rs

1use std::error::Error;
2use std::fmt::{Display, Formatter};
3use std::num::ParseIntError;
4
5/// Errors produced while constructing or parsing a TR-31 payload.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum PayloadError {
8    /// The cipher block length must be greater than zero.
9    InvalidCipherBlockLength,
10
11    /// The calculated payload length is invalid.
12    InvalidTotalPayloadLength,
13
14    /// The protected key is too large for the TR-31 16-bit key-length field.
15    KeyTooLong { max: usize, actual: usize },
16
17    /// The supplied random seed does not contain enough bytes for padding.
18    RandomSeedTooShort { required: usize, actual: usize },
19
20    /// The payload does not contain the two-byte key-length field.
21    PayloadTooShort { minimum: usize, actual: usize },
22
23    /// The payload does not contain as many key bytes as its length field
24    /// declares.
25    PayloadTooShortForKey { required: usize, actual: usize },
26}
27
28impl Display for PayloadError {
29    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
30        match self {
31            Self::InvalidCipherBlockLength => write!(
32                f,
33                "ERROR TR-31 PAYLOAD: Cipher block length must be greater than zero"
34            ),
35
36            Self::InvalidTotalPayloadLength => {
37                write!(f, "ERROR TR-31 PAYLOAD: Invalid total payload length")
38            }
39
40            Self::KeyTooLong { .. } => write!(
41                f,
42                "ERROR TR-31 PAYLOAD: Key length exceeds maximum representable length"
43            ),
44
45            Self::RandomSeedTooShort { .. } => write!(
46                f,
47                "ERROR TR-31 PAYLOAD: The provided random seed is too short for the padding requirement"
48            ),
49
50            Self::PayloadTooShort { .. } => write!(
51                f,
52                "ERROR TR-31 PAYLOAD: Payload too short to contain valid key length"
53            ),
54
55            Self::PayloadTooShortForKey { .. } => write!(
56                f,
57                "ERROR TR-31 PAYLOAD: Payload too short for the specified key length"
58            ),
59        }
60    }
61}
62
63impl Error for PayloadError {}
64
65/// Errors produced while constructing, parsing, or serializing TR-31
66/// optional blocks.
67#[derive(Debug)]
68pub enum OptBlockError {
69    /// The supplied optional-block string does not contain the minimum
70    /// ID and length fields.
71    StringTooShort { minimum: usize, actual: usize },
72
73    /// Optional blocks are defined using ASCII data and cannot safely be
74    /// parsed from arbitrary UTF-8 strings.
75    NonAsciiInput,
76
77    /// An extended-length optional block must contain at least 256 bytes.
78    ExtendedLengthStringTooShort { minimum: usize, actual: usize },
79
80    /// The encoded optional-block length exceeds the available input.
81    StringTooShortForLength { required: usize, actual: usize },
82
83    /// An optional block has not been initialized sufficiently for export.
84    Uninitialized { length: usize },
85
86    /// The optional-block identifier is not supported.
87    InvalidId(String),
88
89    /// Data was assigned before an optional-block identifier.
90    IdNotSet,
91
92    /// Optional-block data contains non-ASCII characters.
93    NonAsciiData(String),
94
95    /// The complete optional block exceeds the maximum representable size.
96    BlockTooLong { maximum: usize, actual: usize },
97
98    /// A normal length field must consist of exactly two hexadecimal
99    /// characters.
100    InvalidLengthFieldWidth { value: String, expected: usize },
101
102    /// A normal length field is not valid hexadecimal.
103    InvalidLengthFieldHex {
104        value: String,
105        source: ParseIntError,
106    },
107
108    /// A normal optional-block length cannot be smaller than four bytes.
109    LengthFieldTooSmall { minimum: usize, actual: usize },
110
111    /// An extended length field must consist of exactly six characters.
112    InvalidExtendedLengthField(String),
113
114    /// The first two characters of the extended length field must encode
115    /// the supported length-of-length value.
116    InvalidLengthOfLengthField(String),
117
118    /// The extended block length is not valid hexadecimal.
119    InvalidExtendedLengthHex {
120        value: String,
121        source: ParseIntError,
122    },
123
124    /// Extended encoding may only be used for block lengths greater than
125    /// 255 bytes.
126    ExtendedLengthTooSmall { value: String },
127}
128
129impl Display for OptBlockError {
130    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
131        match self {
132            Self::StringTooShort { .. } => write!(
133                f,
134                "ERROR TR-31 OPT BLOCK: String too short. Expected at least 4 characters"
135            ),
136
137            Self::NonAsciiInput => write!(
138                f,
139                "ERROR TR-31 OPT BLOCK: Input contains non ASCII characters"
140            ),
141
142            Self::ExtendedLengthStringTooShort { .. } => write!(
143                f,
144                "ERROR TR-31 OPT BLOCK: String containing extended length too short. Expected at least 256 characters"
145            ),
146
147            Self::StringTooShortForLength { required, .. } => write!(
148                f,
149                "ERROR TR-31 OPT BLOCK: String too short for given length. Expected at least {} characters.",
150                required
151            ),
152
153            Self::Uninitialized { .. } => write!(
154                f,
155                "ERROR TR-31 OPT BLOCK: Length must be greater than 4, indicating uninitialized OptBlock"
156            ),
157
158            Self::InvalidId(id) => write!(f, "ERROR TR-31 OPT BLOCK: Invalid ID: {}", id),
159
160            Self::IdNotSet => write!(
161                f,
162                "ERROR TR-31 OPT BLOCK: ID not set (has to be set before data)"
163            ),
164
165            Self::NonAsciiData(data) => write!(
166                f,
167                "ERROR TR-31 OPT BLOCK: Data has non ASCII characters: {}",
168                data
169            ),
170
171            Self::BlockTooLong { actual, .. } => write!(
172                f,
173                "ERROR TR-31 OPT BLOCK: Block size '{}' is too long (must be max. 65535)",
174                actual
175            ),
176
177            Self::InvalidLengthFieldWidth { value, .. } => write!(
178                f,
179                "ERROR TR-31 OPT BLOCK: Invalid length field: Expected a string with 2 characters, found '{}'",
180                value
181            ),
182
183            Self::InvalidLengthFieldHex { value, .. } => write!(
184                f,
185                "ERROR TR-31 OPT BLOCK: Invalid length field: '{}' is not a valid hexadecimal number",
186                value
187            ),
188
189            Self::LengthFieldTooSmall { actual, .. } => write!(
190                f,
191                "ERROR TR-31 OPT BLOCK: Invalid length field: value {} is too small (must be at least 4)",
192                actual
193            ),
194
195            Self::InvalidExtendedLengthField(value) => write!(
196                f,
197                "ERROR TR-31 OPT BLOCK: Invalid extended length field: {}",
198                value
199            ),
200
201            Self::InvalidLengthOfLengthField(value) => write!(
202                f,
203                "ERROR TR-31 OPT BLOCK: Invalid length of length field: {}",
204                value
205            ),
206
207            Self::InvalidExtendedLengthHex { source, .. } => {
208                // Preserve the previous behavior of exposing the underlying
209                // hexadecimal parser message.
210                Display::fmt(source, f)
211            }
212
213            Self::ExtendedLengthTooSmall { value } => write!(
214                f,
215                "ERROR TR-31 OPT BLOCK: Extended length is not greater than 255: {}",
216                value
217            ),
218        }
219    }
220}
221
222impl Error for OptBlockError {
223    fn source(&self) -> Option<&(dyn Error + 'static)> {
224        match self {
225            Self::InvalidLengthFieldHex { source, .. }
226            | Self::InvalidExtendedLengthHex { source, .. } => Some(source),
227
228            _ => None,
229        }
230    }
231}
232
233/// Errors produced while constructing, parsing, validating, or serializing
234/// a TR-31 key block header.
235#[derive(Debug)]
236pub enum KeyBlockHeaderError {
237    InvalidDataLength {
238        minimum: usize,
239        actual: usize,
240    },
241
242    NonAsciiHeader,
243
244    InvalidKeyBlockLength,
245
246    InvalidNumberOfOptionalBlocks,
247
248    InvalidHeaderLengthWithOptionalBlocks {
249        minimum: usize,
250        actual: usize,
251    },
252
253    InvalidVersionId(String),
254
255    InvalidKeyUsage(String),
256
257    InvalidAlgorithm(String),
258
259    InvalidModeOfUse(String),
260
261    InvalidKeyVersionNumberLength(String),
262
263    InvalidKeyVersionNumberEncoding(String),
264
265    InvalidExportability(String),
266
267    TooManyOptionalBlocks {
268        maximum: u8,
269        actual: u8,
270    },
271
272    InvalidReservedField(String),
273
274    ExportFailedEmptyFields,
275
276    /// Error propagated directly from optional-block processing.
277    OptionalBlock(OptBlockError),
278
279    /// Optional-block error specifically encountered while parsing a header.
280    FailedToParseOptionalBlocks(OptBlockError),
281}
282
283impl Display for KeyBlockHeaderError {
284    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
285        match self {
286            Self::InvalidDataLength { .. } => write!(f, "ERROR TR-31 HEADER: Invalid data length"),
287
288            Self::NonAsciiHeader => write!(
289                f,
290                "ERROR TR-31 HEADER: Header contains non ASCII characters"
291            ),
292
293            Self::InvalidKeyBlockLength => {
294                write!(f, "ERROR TR-31 HEADER: Invalid key block length")
295            }
296
297            Self::InvalidNumberOfOptionalBlocks => {
298                write!(f, "ERROR TR-31 HEADER: Invalid number of optional blocks")
299            }
300
301            Self::InvalidHeaderLengthWithOptionalBlocks { .. } => write!(
302                f,
303                "ERROR TR-31 HEADER: Invalid header length containing optional blocks"
304            ),
305
306            Self::InvalidVersionId(value) => {
307                write!(f, "ERROR TR-31 HEADER: Invalid version ID: {}", value)
308            }
309
310            Self::InvalidKeyUsage(value) => {
311                write!(f, "ERROR TR-31 HEADER: Invalid key usage: {}", value)
312            }
313
314            Self::InvalidAlgorithm(value) => {
315                write!(f, "ERROR TR-31 HEADER: Invalid algorithm: {}", value)
316            }
317
318            Self::InvalidModeOfUse(value) => {
319                write!(f, "ERROR TR-31 HEADER: Invalid mode of use: {}", value)
320            }
321
322            Self::InvalidKeyVersionNumberLength(value) => write!(
323                f,
324                "ERROR TR-31 HEADER: Key version number must consist of 2 ASCII characters: {}",
325                value
326            ),
327
328            Self::InvalidKeyVersionNumberEncoding(value) => write!(
329                f,
330                "ERROR TR-31 HEADER: Key version number must consist of ASCII characters: {}",
331                value
332            ),
333
334            Self::InvalidExportability(value) => {
335                write!(f, "ERROR TR-31 HEADER: Invalid exportability: {}", value)
336            }
337
338            Self::TooManyOptionalBlocks { .. } => write!(
339                f,
340                "ERROR TR-31 HEADER: Number of opt blocks value is too large"
341            ),
342
343            Self::InvalidReservedField(value) => write!(
344                f,
345                "ERROR TR-31 HEADER: Invalid value for reserved field: {}",
346                value
347            ),
348
349            Self::ExportFailedEmptyFields => write!(
350                f,
351                "ERROR TR-31 HEADER: Export failed due to empty field(s) or zero length"
352            ),
353
354            Self::OptionalBlock(error) => Display::fmt(error, f),
355
356            Self::FailedToParseOptionalBlocks(error) => write!(
357                f,
358                "ERROR TR-31 HEADER: Failed to parse optional blocks: {}",
359                error
360            ),
361        }
362    }
363}
364
365impl Error for KeyBlockHeaderError {
366    fn source(&self) -> Option<&(dyn Error + 'static)> {
367        match self {
368            Self::OptionalBlock(error) | Self::FailedToParseOptionalBlocks(error) => Some(error),
369
370            _ => None,
371        }
372    }
373}
374
375impl From<OptBlockError> for KeyBlockHeaderError {
376    fn from(error: OptBlockError) -> Self {
377        Self::OptionalBlock(error)
378    }
379}
380
381/// Errors produced by TR-31 key block processing.
382#[derive(Debug)]
383pub enum Tr31Error {
384    /// The requested key block version is not supported by this
385    /// implementation.
386    UnsupportedVersion(String),
387
388    /// The complete key block length is not aligned to the cipher block size.
389    TotalBlockLengthNotMultiple {
390        block_length: usize,
391        actual: usize,
392    },
393
394    /// The actual key block length differs from the value encoded in the
395    /// header.
396    KeyBlockLengthMismatch {
397        expected: usize,
398        actual: usize,
399    },
400
401    /// The key block is shorter than the minimum valid version D block.
402    KeyBlockBelowMinimum {
403        minimum: usize,
404        actual: usize,
405    },
406
407    /// The decoded MAC does not have the required length.
408    InvalidMacLength {
409        expected: usize,
410        actual: usize,
411    },
412
413    /// Key block authentication failed.
414    MacVerificationFailed,
415
416    /// Header processing failed.
417    Header(KeyBlockHeaderError),
418
419    /// Payload processing failed.
420    Payload(PayloadError),
421
422    /// Hexadecimal decoding failed.
423    Hex(hex::FromHexError),
424
425    KeyBlockLengthTooLarge {
426        maximum: usize,
427        actual: usize,
428    },
429}
430
431impl Display for Tr31Error {
432    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
433        match self {
434            Self::UnsupportedVersion(version) => write!(
435                f,
436                "ERROR TR-31: Key block version not supported by implementation: {}",
437                version
438            ),
439
440            Self::TotalBlockLengthNotMultiple { block_length, .. } => write!(
441                f,
442                "ERROR TR-31: Total block length is not a multiple of block length: {}",
443                block_length
444            ),
445
446            Self::KeyBlockLengthMismatch { .. } => write!(
447                f,
448                "ERROR TR-31: Key block length does not match its length in the header"
449            ),
450
451            Self::KeyBlockBelowMinimum { .. } => write!(
452                f,
453                "ERROR TR-31: Key block length is below minimum required length"
454            ),
455
456            Self::InvalidMacLength { expected, actual } => write!(
457                f,
458                "ERROR TR-31: Invalid MAC length: expected {} bytes, found {}",
459                expected, actual
460            ),
461
462            Self::MacVerificationFailed => write!(f, "ERROR TR-31: MAC check failed"),
463
464            Self::Header(error) => Display::fmt(error, f),
465
466            Self::Payload(error) => Display::fmt(error, f),
467
468            Self::Hex(error) => Display::fmt(error, f),
469
470            Self::KeyBlockLengthTooLarge { maximum, actual } => write!(
471                f,
472                "ERROR TR-31: Key block length exceeds maximum: maximum {}, actual {}",
473                maximum, actual
474            ),
475        }
476    }
477}
478
479impl Error for Tr31Error {
480    fn source(&self) -> Option<&(dyn Error + 'static)> {
481        match self {
482            Self::Header(error) => Some(error),
483            Self::Payload(error) => Some(error),
484            Self::Hex(error) => Some(error),
485
486            _ => None,
487        }
488    }
489}
490
491impl From<KeyBlockHeaderError> for Tr31Error {
492    fn from(error: KeyBlockHeaderError) -> Self {
493        Self::Header(error)
494    }
495}
496
497impl From<PayloadError> for Tr31Error {
498    fn from(error: PayloadError) -> Self {
499        Self::Payload(error)
500    }
501}
502
503impl From<hex::FromHexError> for Tr31Error {
504    fn from(error: hex::FromHexError) -> Self {
505        Self::Hex(error)
506    }
507}
508
509/// Error returned by TR-31 operations that may invoke a cryptographic
510/// provider.
511#[derive(Debug)]
512pub enum Tr31CryptoError<E> {
513    /// TR-31 parsing, validation, or formatting failed.
514    Tr31(Tr31Error),
515
516    /// The cryptographic provider reported an error.
517    Crypto(E),
518}
519
520impl<E> Display for Tr31CryptoError<E>
521where
522    E: Display,
523{
524    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
525        match self {
526            Self::Tr31(error) => Display::fmt(error, f),
527
528            Self::Crypto(error) => Display::fmt(error, f),
529        }
530    }
531}
532
533impl<E> Error for Tr31CryptoError<E>
534where
535    E: Error + 'static,
536{
537    fn source(&self) -> Option<&(dyn Error + 'static)> {
538        match self {
539            Self::Tr31(error) => Some(error),
540            Self::Crypto(error) => Some(error),
541        }
542    }
543}
544
545impl<E> From<Tr31Error> for Tr31CryptoError<E> {
546    fn from(error: Tr31Error) -> Self {
547        Self::Tr31(error)
548    }
549}
550
551impl<E> From<KeyBlockHeaderError> for Tr31CryptoError<E> {
552    fn from(error: KeyBlockHeaderError) -> Self {
553        Self::Tr31(Tr31Error::Header(error))
554    }
555}
556
557impl<E> From<PayloadError> for Tr31CryptoError<E> {
558    fn from(error: PayloadError) -> Self {
559        Self::Tr31(Tr31Error::Payload(error))
560    }
561}
562
563impl<E> From<hex::FromHexError> for Tr31CryptoError<E> {
564    fn from(error: hex::FromHexError) -> Self {
565        Self::Tr31(Tr31Error::Hex(error))
566    }
567}