• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
178     FileNotFound,
179 
180     /// Message is incomplete and does not contain all of the expected data.
181     Incomplete {
182         /// Expected message length.
183         ///
184         /// Note that this length represents a *minimum* lower bound on how
185         /// much additional data is needed to continue parsing the message.
186         ///
187         /// It's possible upon subsequent message parsing that the parser will
188         /// discover even more data is needed.
189         expected_len: Length,
190 
191         /// Actual length of the message buffer currently being processed.
192         actual_len: Length,
193     },
194 
195     /// I/O errors.
196     #[cfg(feature = "std")]
197     #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
198     Io(std::io::ErrorKind),
199 
200     /// Incorrect length for a given field.
201     Length {
202         /// Tag of the value being decoded.
203         tag: Tag,
204     },
205 
206     /// Message is not canonically encoded.
207     Noncanonical {
208         /// Tag of the value which is not canonically encoded.
209         tag: Tag,
210     },
211 
212     /// OID is improperly encoded.
213     OidMalformed,
214 
215     /// Unknown OID.
216     ///
217     /// This error is intended to be used by libraries which parse DER-based
218     /// formats which encounter unknown or unsupported OID libraries.
219     ///
220     /// It enables passing back the OID value to the caller, which allows them
221     /// to determine which OID(s) are causing the error (and then potentially
222     /// contribute upstream support for algorithms they care about).
223     #[cfg(feature = "oid")]
224     #[cfg_attr(docsrs, doc(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` ordering error: items not in canonical order.
231     SetOrdering,
232 
233     /// Integer overflow occurred (library bug!).
234     Overflow,
235 
236     /// Message is longer than this library's internal limits support.
237     Overlength,
238 
239     /// PEM encoding errors.
240     #[cfg(feature = "pem")]
241     #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
242     Pem(pem::Error),
243 
244     /// Permission denied reading file.
245     #[cfg(feature = "std")]
246     #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
247     PermissionDenied,
248 
249     /// Reader does not support the requested operation.
250     Reader,
251 
252     /// Unknown tag mode.
253     TagModeUnknown,
254 
255     /// Invalid tag number.
256     ///
257     /// The "tag number" is the lower 5-bits of a tag's octet.
258     /// This error occurs in the case that all 5-bits are set to `1`,
259     /// which indicates a multi-byte tag which is unsupported by this library.
260     TagNumberInvalid,
261 
262     /// Unexpected tag.
263     TagUnexpected {
264         /// Tag the decoder was expecting (if there is a single such tag).
265         ///
266         /// `None` if multiple tags are expected/allowed, but the `actual` tag
267         /// does not match any of them.
268         expected: Option<Tag>,
269 
270         /// Actual tag encountered in the message.
271         actual: Tag,
272     },
273 
274     /// Unknown/unsupported tag.
275     TagUnknown {
276         /// Raw byte value of the tag.
277         byte: u8,
278     },
279 
280     /// Undecoded trailing data at end of message.
281     TrailingData {
282         /// Length of the decoded data.
283         decoded: Length,
284 
285         /// Total length of the remaining data left in the buffer.
286         remaining: Length,
287     },
288 
289     /// UTF-8 errors.
290     Utf8(Utf8Error),
291 
292     /// Unexpected value.
293     Value {
294         /// Tag of the unexpected value.
295         tag: Tag,
296     },
297 }
298 
299 impl ErrorKind {
300     /// Annotate an [`ErrorKind`] with context about where it occurred,
301     /// returning an error.
at(self, position: Length) -> Error302     pub fn at(self, position: Length) -> Error {
303         Error::new(self, position)
304     }
305 }
306 
307 impl fmt::Display for ErrorKind {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result308     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
309         match self {
310             ErrorKind::DateTime => write!(f, "date/time error"),
311             ErrorKind::Failed => write!(f, "operation failed"),
312             #[cfg(feature = "std")]
313             ErrorKind::FileNotFound => write!(f, "file not found"),
314             ErrorKind::Incomplete {
315                 expected_len,
316                 actual_len,
317             } => write!(
318                 f,
319                 "ASN.1 DER message is incomplete: expected {}, actual {}",
320                 expected_len, actual_len
321             ),
322             #[cfg(feature = "std")]
323             ErrorKind::Io(err) => write!(f, "I/O error: {:?}", err),
324             ErrorKind::Length { tag } => write!(f, "incorrect length for {}", tag),
325             ErrorKind::Noncanonical { tag } => {
326                 write!(f, "ASN.1 {} not canonically encoded as DER", tag)
327             }
328             ErrorKind::OidMalformed => write!(f, "malformed OID"),
329             #[cfg(feature = "oid")]
330             ErrorKind::OidUnknown { oid } => {
331                 write!(f, "unknown/unsupported OID: {}", oid)
332             }
333             ErrorKind::SetOrdering => write!(f, "SET OF ordering error"),
334             ErrorKind::Overflow => write!(f, "integer overflow"),
335             ErrorKind::Overlength => write!(f, "ASN.1 DER message is too long"),
336             #[cfg(feature = "pem")]
337             ErrorKind::Pem(e) => write!(f, "PEM error: {}", e),
338             #[cfg(feature = "std")]
339             ErrorKind::PermissionDenied => write!(f, "permission denied"),
340             ErrorKind::Reader => write!(f, "reader does not support the requested operation"),
341             ErrorKind::TagModeUnknown => write!(f, "unknown tag mode"),
342             ErrorKind::TagNumberInvalid => write!(f, "invalid tag number"),
343             ErrorKind::TagUnexpected { expected, actual } => {
344                 write!(f, "unexpected ASN.1 DER tag: ")?;
345 
346                 if let Some(tag) = expected {
347                     write!(f, "expected {}, ", tag)?;
348                 }
349 
350                 write!(f, "got {}", actual)
351             }
352             ErrorKind::TagUnknown { byte } => {
353                 write!(f, "unknown/unsupported ASN.1 DER tag: 0x{:02x}", byte)
354             }
355             ErrorKind::TrailingData { decoded, remaining } => {
356                 write!(
357                     f,
358                     "trailing data at end of DER message: decoded {} bytes, {} bytes remaining",
359                     decoded, remaining
360                 )
361             }
362             ErrorKind::Utf8(e) => write!(f, "{}", e),
363             ErrorKind::Value { tag } => write!(f, "malformed ASN.1 DER value for {}", tag),
364         }
365     }
366 }
367