asn1_rs/
error.rs

1#![allow(unknown_lints)]
2#![allow(non_local_definitions)] // false positive for displaydoc::Display: https://github.com/yaahc/displaydoc/issues/46
3
4use crate::{Class, Tag};
5use alloc::str;
6use alloc::string;
7#[cfg(not(feature = "std"))]
8use alloc::string::{String, ToString};
9use core::fmt;
10use displaydoc::Display;
11use nom::error::{ErrorKind, FromExternalError, ParseError};
12use nom::{IResult, Input};
13#[cfg(feature = "std")]
14use std::io;
15use thiserror::Error;
16
17#[derive(Clone, Copy, Debug, Display, PartialEq, Eq, Error)]
18/// Error types for DER constraints
19pub enum DerConstraint {
20    /// Indefinite length not allowed
21    IndefiniteLength,
22    /// Object must not be constructed
23    Constructed,
24    /// Object must be constructed
25    NotConstructed,
26    /// DateTime object is missing timezone
27    MissingTimeZone,
28    /// DateTime object is missing seconds
29    MissingSeconds,
30    /// Bitstring unused bits must be set to zero
31    UnusedBitsNotZero,
32    /// Boolean value must be 0x00 of 0xff
33    InvalidBoolean,
34    /// Integer must not be empty
35    IntegerEmpty,
36    /// Leading zeroes in Integer encoding
37    IntegerLeadingZeroes,
38    /// Leading 0xff in negative Integer encoding
39    IntegerLeadingFF,
40}
41
42/// The error type for operations of the [`FromBer`](crate::FromBer),
43/// [`FromDer`](crate::FromDer), and associated traits.
44#[derive(Clone, Debug, Display, PartialEq, Eq, Error)]
45pub enum Error {
46    /// BER object does not have the expected type
47    BerTypeError,
48    /// BER object does not have the expected value
49    BerValueError,
50    /// Invalid Length
51    InvalidLength,
52    /// Invalid Value when parsing object with tag {tag:?} {msg:}
53    InvalidValue { tag: Tag, msg: String },
54    /// Invalid Tag
55    InvalidTag,
56    /// Unknown tag: {0:?}
57    UnknownTag(u32),
58    /// Unexpected Tag (expected: {expected:?}, actual: {actual:?})
59    UnexpectedTag { expected: Option<Tag>, actual: Tag },
60    /// Unexpected Class (expected: {expected:?}, actual: {actual:?})
61    UnexpectedClass {
62        expected: Option<Class>,
63        actual: Class,
64    },
65
66    /// Indefinite length not allowed
67    IndefiniteLengthUnexpected,
68
69    /// DER object was expected to be constructed (and found to be primitive)
70    ConstructExpected,
71    /// DER object was expected to be primitive (and found to be constructed)
72    ConstructUnexpected,
73
74    /// Integer too large to fit requested type
75    IntegerTooLarge,
76    /// BER integer is negative, while an unsigned integer was requested
77    IntegerNegative,
78    /// BER recursive parsing reached maximum depth
79    BerMaxDepth,
80
81    /// Invalid encoding or forbidden characters in string
82    StringInvalidCharset,
83    /// Invalid Date or Time
84    InvalidDateTime,
85
86    /// DER Failed constraint: {0:?}
87    DerConstraintFailed(DerConstraint),
88
89    /// Requesting borrowed data from a temporary object
90    LifetimeError,
91    /// Feature is not yet implemented
92    Unsupported,
93
94    /// incomplete data, missing: {0:?}
95    Incomplete(nom::Needed),
96
97    /// nom error: {0:?}
98    NomError(ErrorKind),
99}
100
101#[derive(Debug, Error, PartialEq, Eq)]
102pub struct BerError<I: Input> {
103    /// Input location where error happened
104    input: I,
105    /// Error kind
106    inner_error: InnerError,
107}
108
109impl<I: Input> BerError<I> {
110    /// Build a new error
111    #[inline]
112    pub const fn new(input: I, inner: InnerError) -> Self {
113        Self {
114            input,
115            inner_error: inner,
116        }
117    }
118
119    /// Return the error location
120    pub const fn input(&self) -> &I {
121        &self.input
122    }
123
124    /// Return the error kind
125    pub fn inner(&self) -> &InnerError {
126        &self.inner_error
127    }
128
129    #[inline]
130    pub const fn nom_err(input: I, inner_error: InnerError) -> nom::Err<Self> {
131        nom::Err::Error(Self { input, inner_error })
132    }
133
134    /// convert an `InnerError` to a `nom::Err::Error(input, inner)`
135    ///
136    /// This is usefull when mapping the result of a function returning `InnerError`
137    /// inside a parser function (expecting error type `Err<Error<I>>`).
138    ///
139    /// For ex: `header.tag().assert_eq(Tag(0)).map_err(Error::convert(input))?`
140    pub fn convert(input: I) -> impl Fn(InnerError) -> nom::Err<Self>
141    where
142        I: Clone,
143    {
144        move |inner_error| Self::nom_err(input.clone(), inner_error)
145    }
146
147    /// convert an `InnerError` to a `nom::Err::Error<E>` with `e: From<Error<I>>`
148    ///
149    /// This is similar to [`Self::convert`], but with an `Into` applied to the result
150    pub fn convert_into<E: From<Self>>(input: I) -> impl Fn(InnerError) -> nom::Err<E>
151    where
152        I: Clone,
153    {
154        move |inner_error| nom::Err::Error(Self::new(input.clone(), inner_error).into())
155    }
156
157    /// Build an error from the provided invalid value
158    #[inline]
159    pub const fn invalid_value(input: I, tag: Tag, msg: String) -> Self {
160        Self::new(input, InnerError::InvalidValue { tag, msg })
161    }
162
163    // /// Build an error from the provided unexpected class
164    // #[inline]
165    // pub const fn unexpected_class(expected: Option<Class>, actual: Class) -> Self {
166    //     Self::UnexpectedClass { expected, actual }
167    // }
168
169    /// Build an error from the provided unexpected tag
170    #[inline]
171    pub const fn unexpected_tag(input: I, expected: Option<Tag>, actual: Tag) -> Self {
172        Self::new(input, InnerError::UnexpectedTag { expected, actual })
173    }
174
175    /// Build an error from the provided unexpected tag
176    #[inline]
177    pub const fn unexpected_class(input: I, expected: Option<Class>, actual: Class) -> Self {
178        Self::new(input, InnerError::UnexpectedClass { expected, actual })
179    }
180
181    /// Build an `Incomplete` error from the provided parameters
182    #[inline]
183    pub const fn incomplete(input: I, n: nom::Needed) -> Self {
184        Self {
185            input,
186            inner_error: InnerError::Incomplete(n),
187        }
188    }
189}
190
191impl<'i> BerError<crate::Input<'i>> {
192    /// Build a new `BerError` from input reference and inner error
193    pub const fn err_input<'a: 'i, 'r>(input: &'r crate::Input<'a>, inner: InnerError) -> Self {
194        BerError::new(input.const_clone(), inner)
195    }
196
197    /// Builda new `nom::Err::Error<BerError>` from input reference and inner error
198    pub const fn nom_err_input<'a: 'i, 'r>(
199        input: &'r crate::Input<'a>,
200        inner: InnerError,
201    ) -> nom::Err<Self> {
202        nom::Err::Error(BerError::new(input.const_clone(), inner))
203    }
204
205    /// Consume the error and return error location and inner error
206    pub fn consume(self) -> (crate::Input<'i>, InnerError) {
207        (self.input, self.inner_error)
208    }
209}
210
211impl<I: Input + fmt::Display> fmt::Display for BerError<I> {
212    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213        write!(f, "BerError: input={} error={}", self.input(), self.inner())
214    }
215}
216
217impl<I: Input> ParseError<I> for BerError<I> {
218    fn from_error_kind(input: I, kind: ErrorKind) -> Self {
219        Self {
220            input,
221            inner_error: InnerError::Nom(kind),
222        }
223    }
224
225    fn append(_: I, _z: ErrorKind, other: Self) -> Self {
226        // NOTE: we do not support error stacking, and just use the last one
227        other
228    }
229}
230
231impl From<Error> for BerError<crate::Input<'_>> {
232    fn from(value: Error) -> Self {
233        let inner = InnerError::from(value);
234        BerError::new(crate::Input::from_slice(&[]), inner)
235    }
236}
237
238impl<'a, 'b> From<(crate::Input<'b>, Error)> for BerError<crate::Input<'a>>
239where
240    'b: 'a,
241{
242    fn from(value: (crate::Input<'b>, Error)) -> Self {
243        Self {
244            input: value.0,
245            inner_error: InnerError::from(value.1),
246        }
247    }
248}
249
250impl<'a, 'b> From<(crate::Input<'b>, BerError<crate::Input<'b>>)> for BerError<crate::Input<'a>>
251where
252    'b: 'a,
253{
254    fn from(value: (crate::Input<'b>, BerError<crate::Input<'b>>)) -> Self {
255        // ignore new input, assume error input is already set
256        value.1
257        // Self {
258        //     input: value.0,
259        //     inner_error: value.1.inner_error,
260        // }
261    }
262}
263
264/// The error type for operations of the [`FromBer`](crate::FromBer),
265/// [`FromDer`](crate::FromDer), and associated traits.
266#[derive(Clone, Debug, Display, PartialEq, Eq, Error)]
267#[non_exhaustive]
268pub enum InnerError {
269    /// BER object does not have the expected type
270    BerTypeError,
271    /// BER object does not have the expected value
272    BerValueError,
273    /// Invalid Length
274    InvalidLength,
275    /// Invalid Value when parsing object with tag {tag:?} {msg:}
276    InvalidValue { tag: Tag, msg: String },
277    /// Invalid Tag
278    InvalidTag,
279    /// Unknown tag: {0:?}
280    UnknownTag(u32),
281    /// Unexpected Tag (expected: {expected:?}, actual: {actual:?})
282    UnexpectedTag { expected: Option<Tag>, actual: Tag },
283    /// Unexpected Class (expected: {expected:?}, actual: {actual:?})
284    UnexpectedClass {
285        expected: Option<Class>,
286        actual: Class,
287    },
288
289    /// Indefinite length not allowed
290    IndefiniteLengthUnexpected,
291
292    /// DER object was expected to be constructed (and found to be primitive)
293    ConstructExpected,
294    /// DER object was expected to be primitive (and found to be constructed)
295    ConstructUnexpected,
296
297    /// Integer too large to fit requested type
298    IntegerTooLarge,
299    /// BER integer is negative, while an unsigned integer was requested
300    IntegerNegative,
301    /// BER recursive parsing reached maximum depth
302    BerMaxDepth,
303
304    /// Invalid encoding or forbidden characters in string
305    StringInvalidCharset,
306    /// Invalid Date or Time
307    InvalidDateTime,
308
309    /// DER Failed constraint: {0:?}
310    DerConstraintFailed(DerConstraint),
311
312    /// Parse error
313    Nom(ErrorKind),
314
315    /// Requesting borrowed data from a temporary object
316    LifetimeError,
317    /// Feature is not yet implemented
318    Unsupported,
319
320    /// incomplete data, missing: {0:?}
321    Incomplete(nom::Needed),
322}
323
324impl InnerError {
325    pub fn invalid_value(tag: Tag, msg: &str) -> Self {
326        Self::InvalidValue {
327            tag,
328            msg: msg.to_string(),
329        }
330    }
331}
332
333impl From<str::Utf8Error> for InnerError {
334    fn from(_: str::Utf8Error) -> Self {
335        InnerError::StringInvalidCharset
336    }
337}
338
339impl From<string::FromUtf8Error> for InnerError {
340    fn from(_: string::FromUtf8Error) -> Self {
341        InnerError::StringInvalidCharset
342    }
343}
344
345impl From<string::FromUtf16Error> for InnerError {
346    fn from(_: string::FromUtf16Error) -> Self {
347        InnerError::StringInvalidCharset
348    }
349}
350
351impl From<Error> for InnerError {
352    fn from(value: Error) -> Self {
353        match value {
354            Error::BerTypeError => Self::BerTypeError,
355            Error::BerValueError => Self::BerValueError,
356            Error::InvalidLength => Self::InvalidLength,
357            Error::InvalidValue { tag, msg } => Self::InvalidValue { tag, msg },
358            Error::InvalidTag => Self::InvalidTag,
359            Error::UnknownTag(tag) => Self::UnknownTag(tag),
360            Error::UnexpectedTag { expected, actual } => Self::UnexpectedTag { expected, actual },
361            Error::UnexpectedClass { expected, actual } => {
362                Self::UnexpectedClass { expected, actual }
363            }
364            Error::IndefiniteLengthUnexpected => Self::IndefiniteLengthUnexpected,
365            Error::ConstructExpected => Self::ConstructExpected,
366            Error::ConstructUnexpected => Self::ConstructUnexpected,
367            Error::IntegerTooLarge => Self::IntegerTooLarge,
368            Error::IntegerNegative => Self::IntegerNegative,
369            Error::BerMaxDepth => Self::BerMaxDepth,
370            Error::StringInvalidCharset => Self::StringInvalidCharset,
371            Error::InvalidDateTime => Self::InvalidDateTime,
372            Error::DerConstraintFailed(der_constraint) => Self::DerConstraintFailed(der_constraint),
373            Error::LifetimeError => Self::LifetimeError,
374            Error::Unsupported => Self::Unsupported,
375            Error::Incomplete(needed) => Self::Incomplete(needed),
376            Error::NomError(error_kind) => Self::Nom(error_kind),
377        }
378    }
379}
380
381impl Error {
382    /// Build an error from the provided invalid value
383    #[inline]
384    pub const fn invalid_value(tag: Tag, msg: String) -> Self {
385        Self::InvalidValue { tag, msg }
386    }
387
388    /// Build an error from the provided unexpected class
389    #[inline]
390    pub const fn unexpected_class(expected: Option<Class>, actual: Class) -> Self {
391        Self::UnexpectedClass { expected, actual }
392    }
393
394    /// Build an error from the provided unexpected tag
395    #[inline]
396    pub const fn unexpected_tag(expected: Option<Tag>, actual: Tag) -> Self {
397        Self::UnexpectedTag { expected, actual }
398    }
399
400    /// Build an error from a `Nom::Err<BerError<Input>>`
401    pub fn from_nom_berr(e: nom::Err<BerError<crate::Input<'_>>>) -> Self {
402        match e {
403            nom::Err::Incomplete(n) => Self::Incomplete(n),
404            nom::Err::Error(e) | nom::Err::Failure(e) => e.inner_error.into(),
405        }
406    }
407}
408
409impl<I> ParseError<I> for Error {
410    fn from_error_kind(_input: I, kind: ErrorKind) -> Self {
411        Error::NomError(kind)
412    }
413    fn append(_input: I, kind: ErrorKind, _other: Self) -> Self {
414        Error::NomError(kind)
415    }
416}
417
418impl From<Error> for nom::Err<Error> {
419    fn from(e: Error) -> Self {
420        nom::Err::Error(e)
421    }
422}
423
424impl From<str::Utf8Error> for Error {
425    fn from(_: str::Utf8Error) -> Self {
426        Error::StringInvalidCharset
427    }
428}
429
430impl From<string::FromUtf8Error> for Error {
431    fn from(_: string::FromUtf8Error) -> Self {
432        Error::StringInvalidCharset
433    }
434}
435
436impl From<string::FromUtf16Error> for Error {
437    fn from(_: string::FromUtf16Error) -> Self {
438        Error::StringInvalidCharset
439    }
440}
441
442impl From<nom::Err<Error>> for Error {
443    fn from(e: nom::Err<Error>) -> Self {
444        match e {
445            nom::Err::Incomplete(n) => Self::Incomplete(n),
446            nom::Err::Error(e) | nom::Err::Failure(e) => e,
447        }
448    }
449}
450
451impl<I: Input> From<BerError<I>> for Error {
452    fn from(value: BerError<I>) -> Self {
453        Self::from(value.inner_error)
454    }
455}
456
457impl From<InnerError> for Error {
458    fn from(value: InnerError) -> Self {
459        match value {
460            InnerError::BerTypeError => Self::BerTypeError,
461            InnerError::BerValueError => Self::BerValueError,
462            InnerError::InvalidLength => Self::InvalidLength,
463            InnerError::InvalidValue { tag, msg } => Self::InvalidValue { tag, msg },
464            InnerError::InvalidTag => Self::InvalidTag,
465            InnerError::UnknownTag(t) => Self::UnknownTag(t),
466            InnerError::UnexpectedTag { expected, actual } => {
467                Self::UnexpectedTag { expected, actual }
468            }
469            InnerError::UnexpectedClass { expected, actual } => {
470                Self::unexpected_class(expected, actual)
471            }
472            InnerError::IndefiniteLengthUnexpected => Self::IndefiniteLengthUnexpected,
473            InnerError::ConstructExpected => Self::ConstructExpected,
474            InnerError::ConstructUnexpected => Self::ConstructUnexpected,
475            InnerError::IntegerTooLarge => Self::IntegerTooLarge,
476            InnerError::IntegerNegative => Self::IntegerNegative,
477            InnerError::BerMaxDepth => Self::BerMaxDepth,
478            InnerError::StringInvalidCharset => Self::StringInvalidCharset,
479            InnerError::InvalidDateTime => Self::InvalidDateTime,
480            InnerError::DerConstraintFailed(der_constraint) => {
481                Self::DerConstraintFailed(der_constraint)
482            }
483            InnerError::Nom(error_kind) => Self::NomError(error_kind),
484            InnerError::LifetimeError => Self::LifetimeError,
485            InnerError::Unsupported => Self::Unsupported,
486            InnerError::Incomplete(n) => Self::Incomplete(n),
487        }
488    }
489}
490
491impl<I, E> FromExternalError<I, E> for Error {
492    fn from_external_error(_input: I, kind: ErrorKind, _e: E) -> Error {
493        Error::NomError(kind)
494    }
495}
496
497/// Flatten all `nom::Err` variants error into a single error type
498pub fn from_nom_error<E, F>(e: nom::Err<E>) -> F
499where
500    F: From<E> + From<Error>,
501{
502    match e {
503        nom::Err::Error(e) | nom::Err::Failure(e) => F::from(e),
504        nom::Err::Incomplete(n) => F::from(Error::Incomplete(n)),
505    }
506}
507
508/// Flatten all `nom::Err` variants error into a single error type
509///
510/// Note: used in custom derive
511pub fn from_nom_bererror<'a, E, F>(input: crate::Input<'a>, e: nom::Err<E>) -> F
512where
513    F: Sized + From<(crate::Input<'a>, E)> + From<Error>,
514{
515    match e {
516        nom::Err::Error(e) | nom::Err::Failure(e) => F::from((input, e)),
517        nom::Err::Incomplete(n) => F::from(Error::Incomplete(n)),
518    }
519}
520
521/// Holds the result of BER/DER serialization functions
522pub type ParseResult<'a, T, E = Error> = IResult<&'a [u8], T, E>;
523
524/// A specialized `Result` type for all operations from this crate.
525pub type Result<T, E = Error> = core::result::Result<T, E>;
526
527/// The error type for serialization operations of the [`ToDer`](crate::ToDer) trait.
528#[cfg(feature = "std")]
529#[derive(Debug, Error)]
530pub enum SerializeError {
531    #[error("ASN.1 error: {0:?}")]
532    ASN1Error(#[from] Error),
533
534    #[error("Invalid Class {class:}")]
535    InvalidClass { class: u8 },
536
537    #[error("Invalid Length")]
538    InvalidLength,
539
540    #[error("I/O error: {0:?}")]
541    IOError(#[from] io::Error),
542}
543
544#[cfg(feature = "std")]
545/// Holds the result of BER/DER encoding functions
546pub type SerializeResult<T> = std::result::Result<T, SerializeError>;