Skip to main content

der/
error.rs

1//! Error types.
2
3pub use core::str::Utf8Error;
4
5use crate::{Length, Tag};
6use core::{convert::Infallible, fmt, num::TryFromIntError};
7
8#[cfg(feature = "oid")]
9use crate::asn1::ObjectIdentifier;
10
11#[cfg(feature = "pem")]
12use crate::pem;
13
14#[cfg(doc)]
15use crate::{Reader, Writer};
16
17/// Result type.
18pub type Result<T> = core::result::Result<T, Error>;
19
20/// Error type.
21///
22/// ## Example
23/// ```
24/// use der::{Decode, ErrorKind, Reader};
25///
26/// struct MyDecodable;
27///
28/// impl<'a> Decode<'a> for MyDecodable {
29///     type Error = der::Error;
30///
31///     fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Self, der::Error> {
32///         Err(reader.error(ErrorKind::OidMalformed))
33///     }
34/// }
35/// ```
36#[derive(Copy, Clone, Debug, Eq, PartialEq)]
37pub struct Error {
38    /// Kind of error.
39    kind: ErrorKind,
40
41    /// Position inside of message where error occurred.
42    position: Option<Length>,
43}
44
45impl Error {
46    /// Create a new [`Error`].
47    #[must_use]
48    pub const fn new(kind: ErrorKind, position: Length) -> Error {
49        Error {
50            kind,
51            position: Some(position),
52        }
53    }
54    /// Create a new [`Error`], without known position.
55    pub(crate) const fn from_kind(kind: ErrorKind) -> Error {
56        Error {
57            kind,
58            position: None,
59        }
60    }
61
62    /// Create a new [`ErrorKind::Incomplete`] for the given length.
63    ///
64    /// Computes the expected len as being one greater than `actual_len`.
65    #[must_use]
66    pub fn incomplete(actual_len: Length) -> Self {
67        match actual_len + Length::ONE {
68            Ok(expected_len) => ErrorKind::Incomplete {
69                expected_len,
70                actual_len,
71            }
72            .at(actual_len),
73            Err(err) => err.kind().at(actual_len),
74        }
75    }
76
77    /// Get the [`ErrorKind`] which occurred.
78    #[must_use]
79    pub fn kind(self) -> ErrorKind {
80        self.kind
81    }
82
83    /// Get the position inside of the message where the error occurred.
84    #[must_use]
85    pub fn position(self) -> Option<Length> {
86        self.position
87    }
88
89    /// For errors occurring inside of a nested message, extend the position
90    /// count by the location where the nested message occurs.
91    pub(crate) fn nested(self, nested_position: Length) -> Self {
92        // TODO(tarcieri): better handle length overflows occurring in this calculation?
93        let position = (nested_position + self.position.unwrap_or_default()).ok();
94
95        Self {
96            kind: self.kind,
97            position,
98        }
99    }
100}
101
102impl core::error::Error for Error {}
103
104impl fmt::Display for Error {
105    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106        write!(f, "{}", self.kind)?;
107
108        if let Some(pos) = self.position {
109            write!(f, " at DER byte {pos}")?;
110        }
111
112        Ok(())
113    }
114}
115
116impl From<ErrorKind> for Error {
117    fn from(kind: ErrorKind) -> Error {
118        Error::from_kind(kind)
119    }
120}
121
122impl From<Infallible> for Error {
123    fn from(_: Infallible) -> Error {
124        unreachable!()
125    }
126}
127
128impl From<TryFromIntError> for Error {
129    fn from(_: TryFromIntError) -> Error {
130        Error {
131            kind: ErrorKind::Overflow,
132            position: None,
133        }
134    }
135}
136
137impl From<Utf8Error> for Error {
138    fn from(err: Utf8Error) -> Error {
139        Error {
140            kind: ErrorKind::Utf8(err),
141            position: None,
142        }
143    }
144}
145
146#[cfg(feature = "alloc")]
147impl From<alloc::string::FromUtf8Error> for Error {
148    fn from(err: alloc::string::FromUtf8Error) -> Error {
149        ErrorKind::Utf8(err.utf8_error()).into()
150    }
151}
152
153#[cfg(feature = "oid")]
154impl From<const_oid::Error> for Error {
155    fn from(_: const_oid::Error) -> Error {
156        ErrorKind::OidMalformed.into()
157    }
158}
159
160#[cfg(feature = "pem")]
161impl From<pem::Error> for Error {
162    fn from(err: pem::Error) -> Error {
163        ErrorKind::Pem(err).into()
164    }
165}
166
167#[cfg(feature = "std")]
168impl From<std::io::Error> for Error {
169    fn from(err: std::io::Error) -> Error {
170        match err.kind() {
171            std::io::ErrorKind::NotFound => ErrorKind::FileNotFound,
172            std::io::ErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
173            other => ErrorKind::Io(other),
174        }
175        .into()
176    }
177}
178
179#[cfg(feature = "time")]
180impl From<time::error::ComponentRange> for Error {
181    fn from(_: time::error::ComponentRange) -> Error {
182        ErrorKind::DateTime.into()
183    }
184}
185
186/// Error type.
187///
188/// # Example
189/// ```
190/// use der::{asn1::OctetStringRef, Decode, ErrorKind};
191///
192/// let err = <&OctetStringRef>::from_der(&[0x04, 0x80, 0x00]).unwrap_err();
193///
194/// assert_eq!(err.kind(), ErrorKind::IndefiniteLength);
195/// ```
196#[derive(Copy, Clone, Debug, Eq, PartialEq)]
197#[non_exhaustive]
198pub enum ErrorKind {
199    /// Date-and-time related errors.
200    DateTime,
201
202    /// Invalid encoding rules.
203    EncodingRules,
204
205    /// This error indicates a previous DER parsing operation resulted in
206    /// an error and tainted the state of a [`Reader`] or [`Writer`].
207    ///
208    /// Once this occurs, the overall operation has failed and cannot be
209    /// subsequently resumed.
210    Failed,
211
212    /// File not found error.
213    #[cfg(feature = "std")]
214    FileNotFound,
215
216    /// Message is incomplete and does not contain all of the expected data.
217    Incomplete {
218        /// Expected message length.
219        ///
220        /// Note that this length represents a *minimum* lower bound on how
221        /// much additional data is needed to continue parsing the message.
222        ///
223        /// It's possible upon subsequent message parsing that the parser will
224        /// discover even more data is needed.
225        expected_len: Length,
226
227        /// Actual length of the message buffer currently being processed.
228        actual_len: Length,
229    },
230
231    /// I/O errors.
232    #[cfg(feature = "std")]
233    Io(std::io::ErrorKind),
234
235    /// Indefinite length invalid (disallowed in DER or malformed when decoding BER)
236    IndefiniteLength,
237
238    /// Incorrect length for a given field.
239    Length {
240        /// Tag of the value being decoded.
241        tag: Tag,
242    },
243
244    /// Too many nested productions (i.e. TLV-in-TLV) encountered.
245    NestingDepth,
246
247    /// Message is not canonically encoded.
248    Noncanonical {
249        /// Tag of the value which is not canonically encoded.
250        tag: Tag,
251    },
252
253    /// OID is improperly encoded.
254    OidMalformed,
255
256    /// Unknown OID.
257    ///
258    /// This error is intended to be used by libraries which parse DER-based
259    /// formats which encounter unknown or unsupported OID libraries.
260    ///
261    /// It enables passing back the OID value to the caller, which allows them
262    /// to determine which OID(s) are causing the error (and then potentially
263    /// contribute upstream support for algorithms they care about).
264    #[cfg(feature = "oid")]
265    OidUnknown {
266        /// OID value that was unrecognized by a parser for a DER-based format.
267        oid: ObjectIdentifier,
268    },
269
270    /// `SET` cannot contain duplicates.
271    // TODO(tarcieri): remove this in the next breaking release
272    #[deprecated(
273        since = "0.8.1",
274        note = "per X.680, 27.3 NOTE 3 duplicates are allowed"
275    )]
276    SetDuplicate,
277
278    /// `SET` ordering error: items not in canonical order.
279    SetOrdering,
280
281    /// Integer overflow occurred (library bug!).
282    Overflow,
283
284    /// Message is longer than this library's internal limits support.
285    Overlength,
286
287    /// PEM encoding errors.
288    #[cfg(feature = "pem")]
289    Pem(pem::Error),
290
291    /// Permission denied reading file.
292    #[cfg(feature = "std")]
293    PermissionDenied,
294
295    /// Reader does not support the requested operation.
296    Reader,
297
298    /// Unknown tag mode.
299    TagModeUnknown,
300
301    /// Invalid tag number.
302    ///
303    /// The "tag number" is the lower 5-bits of a tag's octet.
304    /// This error occurs in the case that all 5-bits are set to `1`,
305    /// which indicates a multi-byte tag which is unsupported by this library.
306    TagNumberInvalid,
307
308    /// Unexpected tag.
309    TagUnexpected {
310        /// Tag the decoder was expecting (if there is a single such tag).
311        ///
312        /// `None` if multiple tags are expected/allowed, but the `actual` tag
313        /// does not match any of them.
314        expected: Option<Tag>,
315
316        /// Actual tag encountered in the message.
317        actual: Tag,
318    },
319
320    /// Unknown/unsupported tag.
321    TagUnknown {
322        /// Raw byte value of the tag.
323        byte: u8,
324    },
325
326    /// Undecoded trailing data at end of message.
327    TrailingData {
328        /// Length of the decoded data.
329        decoded: Length,
330
331        /// Total length of the remaining data left in the buffer.
332        remaining: Length,
333    },
334
335    /// UTF-8 errors.
336    Utf8(Utf8Error),
337
338    /// Unexpected value.
339    Value {
340        /// Tag of the unexpected value.
341        tag: Tag,
342    },
343}
344
345impl ErrorKind {
346    /// Annotate an [`ErrorKind`] with context about where it occurred,
347    /// returning an error.
348    #[must_use]
349    pub fn at(self, position: Length) -> Error {
350        Error::new(self, position)
351    }
352
353    /// Convert to an error, omitting position information.
354    #[must_use]
355    pub fn to_error(self) -> Error {
356        Error::from_kind(self)
357    }
358}
359
360impl fmt::Display for ErrorKind {
361    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
362        match self {
363            ErrorKind::DateTime => write!(f, "date/time error"),
364            ErrorKind::EncodingRules => write!(f, "invalid encoding rules"),
365            ErrorKind::Failed => write!(f, "operation failed"),
366            #[cfg(feature = "std")]
367            ErrorKind::FileNotFound => write!(f, "file not found"),
368            ErrorKind::Incomplete {
369                expected_len,
370                actual_len,
371            } => write!(
372                f,
373                "ASN.1 DER message is incomplete: expected {expected_len}, actual {actual_len}"
374            ),
375            #[cfg(feature = "std")]
376            ErrorKind::Io(err) => write!(f, "I/O error: {err:?}"),
377            ErrorKind::IndefiniteLength => write!(f, "indefinite length disallowed/malformed"),
378            ErrorKind::Length { tag } => write!(f, "incorrect length for {tag}"),
379            ErrorKind::NestingDepth => write!(f, "too many nested productions encountered"),
380            ErrorKind::Noncanonical { tag } => {
381                write!(f, "ASN.1 {tag} not canonically encoded as DER")
382            }
383            ErrorKind::OidMalformed => write!(f, "malformed OID"),
384            #[cfg(feature = "oid")]
385            ErrorKind::OidUnknown { oid } => {
386                write!(f, "unknown/unsupported OID: {oid}")
387            }
388            #[allow(deprecated)]
389            ErrorKind::SetDuplicate => write!(f, "SET OF contains duplicate"),
390            ErrorKind::SetOrdering => write!(f, "SET OF ordering error"),
391            ErrorKind::Overflow => write!(f, "integer overflow"),
392            ErrorKind::Overlength => write!(f, "ASN.1 DER message is too long"),
393            #[cfg(feature = "pem")]
394            ErrorKind::Pem(e) => write!(f, "PEM error: {e}"),
395            #[cfg(feature = "std")]
396            ErrorKind::PermissionDenied => write!(f, "permission denied"),
397            ErrorKind::Reader => write!(f, "reader does not support the requested operation"),
398            ErrorKind::TagModeUnknown => write!(f, "unknown tag mode"),
399            ErrorKind::TagNumberInvalid => write!(f, "invalid tag number"),
400            ErrorKind::TagUnexpected { expected, actual } => {
401                write!(f, "unexpected ASN.1 DER tag: ")?;
402
403                if let Some(tag) = expected {
404                    write!(f, "expected {tag}, ")?;
405                }
406
407                write!(f, "got {actual}")
408            }
409            ErrorKind::TagUnknown { byte } => {
410                write!(f, "unknown/unsupported ASN.1 DER tag: 0x{byte:02x}")
411            }
412            ErrorKind::TrailingData { decoded, remaining } => {
413                write!(
414                    f,
415                    "trailing data at end of DER message: decoded {decoded} bytes, {remaining} bytes remaining"
416                )
417            }
418            ErrorKind::Utf8(e) => write!(f, "{e}"),
419            ErrorKind::Value { tag } => write!(f, "malformed ASN.1 DER value for {tag}"),
420        }
421    }
422}