1
#![allow(unknown_lints)]
2
#![allow(non_local_definitions)] // false positive for displaydoc::Display: https://github.com/yaahc/displaydoc/issues/46
3

            
4
use crate::{Class, Tag};
5
use alloc::str;
6
use alloc::string;
7
#[cfg(not(feature = "std"))]
8
use alloc::string::String;
9
use displaydoc::Display;
10
use nom::error::{ErrorKind, FromExternalError, ParseError};
11
use nom::IResult;
12
#[cfg(feature = "std")]
13
use std::io;
14
#[cfg(feature = "std")]
15
use thiserror::Error;
16

            
17
#[cfg(feature = "std")]
18
impl std::error::Error for DerConstraint {}
19

            
20
#[derive(Clone, Copy, Debug, Display, PartialEq, Eq)]
21
/// Error types for DER constraints
22
pub 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")]
50
impl 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))]
56
pub 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

            
112
impl 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

            
132
impl<'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

            
141
impl From<Error> for nom::Err<Error> {
142
    fn from(e: Error) -> Self {
143
        nom::Err::Error(e)
144
    }
145
}
146

            
147
impl From<str::Utf8Error> for Error {
148
    fn from(_: str::Utf8Error) -> Self {
149
        Error::StringInvalidCharset
150
    }
151
}
152

            
153
impl From<string::FromUtf8Error> for Error {
154
    fn from(_: string::FromUtf8Error) -> Self {
155
        Error::StringInvalidCharset
156
    }
157
}
158

            
159
impl From<string::FromUtf16Error> for Error {
160
    fn from(_: string::FromUtf16Error) -> Self {
161
        Error::StringInvalidCharset
162
    }
163
}
164

            
165
impl 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

            
174
impl<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
181
pub fn from_nom_error<E, F>(e: nom::Err<E>) -> F
182
where
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
192
pub type ParseResult<'a, T, E = Error> = IResult<&'a [u8], T, E>;
193

            
194
/// A specialized `Result` type for all operations from this crate.
195
pub 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)]
200
pub 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
216
pub type SerializeResult<T> = std::result::Result<T, SerializeError>;