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