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;
9use displaydoc::Display;
10use nom::error::{ErrorKind, FromExternalError, ParseError};
11use nom::IResult;
12#[cfg(feature = "std")]
13use std::io;
14#[cfg(feature = "std")]
15use thiserror::Error;
16
17#[cfg(feature = "std")]
18impl std::error::Error for DerConstraint {}
19
20#[derive(Clone, Copy, Debug, Display, PartialEq, Eq)]
21/// Error types for DER constraints
22pub enum DerConstraint {
23    /// Indefinite length not allowed
24    IndefiniteLength,
25    /// Object must not be constructed
26    Constructed,
27    /// Object must be constructed
28    NotConstructed,
29    /// DateTime object is missing timezone
30    MissingTimeZone,
31    /// DateTime object is missing seconds
32    MissingSeconds,
33    /// Bitstring unused bits must be set to zero
34    UnusedBitsNotZero,
35    /// Boolean value must be 0x00 of 0xff
36    InvalidBoolean,
37    /// Integer must not be empty
38    IntegerEmpty,
39    /// Leading zeroes in Integer encoding
40    IntegerLeadingZeroes,
41    /// Leading 0xff in negative Integer encoding
42    IntegerLeadingFF,
43}
44
45// XXX
46// thiserror does not work in no_std
47// see https://github.com/dtolnay/thiserror/pull/64
48
49#[cfg(feature = "std")]
50impl std::error::Error for Error {}
51
52/// The error type for operations of the [`FromBer`](crate::FromBer),
53/// [`FromDer`](crate::FromDer), and associated traits.
54#[derive(Clone, Debug, Display, PartialEq, Eq)]
55// #[cfg_attr(feature = "std", derive(Error))]
56pub enum Error {
57    /// BER object does not have the expected type
58    BerTypeError,
59    /// BER object does not have the expected value
60    BerValueError,
61    /// Invalid Length
62    InvalidLength,
63    /// Invalid Value when parsing object with tag {tag:?} {msg:}
64    InvalidValue { tag: Tag, msg: String },
65    /// Invalid Tag
66    InvalidTag,
67    /// Unknown tag: {0:?}
68    UnknownTag(u32),
69    /// Unexpected Tag (expected: {expected:?}, actual: {actual:?})
70    UnexpectedTag { expected: Option<Tag>, actual: Tag },
71    /// Unexpected Class (expected: {expected:?}, actual: {actual:?})
72    UnexpectedClass {
73        expected: Option<Class>,
74        actual: Class,
75    },
76
77    /// Indefinite length not allowed
78    IndefiniteLengthUnexpected,
79
80    /// DER object was expected to be constructed (and found to be primitive)
81    ConstructExpected,
82    /// DER object was expected to be primitive (and found to be constructed)
83    ConstructUnexpected,
84
85    /// Integer too large to fit requested type
86    IntegerTooLarge,
87    /// BER integer is negative, while an unsigned integer was requested
88    IntegerNegative,
89    /// BER recursive parsing reached maximum depth
90    BerMaxDepth,
91
92    /// Invalid encoding or forbidden characters in string
93    StringInvalidCharset,
94    /// Invalid Date or Time
95    InvalidDateTime,
96
97    /// DER Failed constraint: {0:?}
98    DerConstraintFailed(DerConstraint),
99
100    /// Requesting borrowed data from a temporary object
101    LifetimeError,
102    /// Feature is not yet implemented
103    Unsupported,
104
105    /// incomplete data, missing: {0:?}
106    Incomplete(nom::Needed),
107
108    /// nom error: {0:?}
109    NomError(ErrorKind),
110}
111
112impl Error {
113    /// Build an error from the provided invalid value
114    #[inline]
115    pub const fn invalid_value(tag: Tag, msg: String) -> Self {
116        Self::InvalidValue { tag, msg }
117    }
118
119    /// Build an error from the provided unexpected class
120    #[inline]
121    pub const fn unexpected_class(expected: Option<Class>, actual: Class) -> Self {
122        Self::UnexpectedClass { expected, actual }
123    }
124
125    /// Build an error from the provided unexpected tag
126    #[inline]
127    pub const fn unexpected_tag(expected: Option<Tag>, actual: Tag) -> Self {
128        Self::UnexpectedTag { expected, actual }
129    }
130}
131
132impl<'a> ParseError<&'a [u8]> for Error {
133    fn from_error_kind(_input: &'a [u8], kind: ErrorKind) -> Self {
134        Error::NomError(kind)
135    }
136    fn append(_input: &'a [u8], kind: ErrorKind, _other: Self) -> Self {
137        Error::NomError(kind)
138    }
139}
140
141impl From<Error> for nom::Err<Error> {
142    fn from(e: Error) -> Self {
143        nom::Err::Error(e)
144    }
145}
146
147impl From<str::Utf8Error> for Error {
148    fn from(_: str::Utf8Error) -> Self {
149        Error::StringInvalidCharset
150    }
151}
152
153impl From<string::FromUtf8Error> for Error {
154    fn from(_: string::FromUtf8Error) -> Self {
155        Error::StringInvalidCharset
156    }
157}
158
159impl From<string::FromUtf16Error> for Error {
160    fn from(_: string::FromUtf16Error) -> Self {
161        Error::StringInvalidCharset
162    }
163}
164
165impl From<nom::Err<Error>> for Error {
166    fn from(e: nom::Err<Error>) -> Self {
167        match e {
168            nom::Err::Incomplete(n) => Self::Incomplete(n),
169            nom::Err::Error(e) | nom::Err::Failure(e) => e,
170        }
171    }
172}
173
174impl<I, E> FromExternalError<I, E> for Error {
175    fn from_external_error(_input: I, kind: ErrorKind, _e: E) -> Error {
176        Error::NomError(kind)
177    }
178}
179
180/// Flatten all `nom::Err` variants error into a single error type
181pub fn from_nom_error<E, F>(e: nom::Err<E>) -> F
182where
183    F: From<E> + From<Error>,
184{
185    match e {
186        nom::Err::Error(e) | nom::Err::Failure(e) => F::from(e),
187        nom::Err::Incomplete(n) => F::from(Error::Incomplete(n)),
188    }
189}
190
191/// Holds the result of BER/DER serialization functions
192pub type ParseResult<'a, T, E = Error> = IResult<&'a [u8], T, E>;
193
194/// A specialized `Result` type for all operations from this crate.
195pub type Result<T, E = Error> = core::result::Result<T, E>;
196
197/// The error type for serialization operations of the [`ToDer`](crate::ToDer) trait.
198#[cfg(feature = "std")]
199#[derive(Debug, Error)]
200pub enum SerializeError {
201    #[error("ASN.1 error: {0:?}")]
202    ASN1Error(#[from] Error),
203
204    #[error("Invalid Class {class:}")]
205    InvalidClass { class: u8 },
206
207    #[error("Invalid Length")]
208    InvalidLength,
209
210    #[error("I/O error: {0:?}")]
211    IOError(#[from] io::Error),
212}
213
214#[cfg(feature = "std")]
215/// Holds the result of BER/DER encoding functions
216pub type SerializeResult<T> = std::result::Result<T, SerializeError>;