/rust/registry/src/index.crates.io-1949cf8c6b5b557f/der-0.7.10/src/error.rs
Line  | Count  | Source  | 
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`].  | 
29  | 0  |     pub fn new(kind: ErrorKind, position: Length) -> Error { | 
30  | 0  |         Error { | 
31  | 0  |             kind,  | 
32  | 0  |             position: Some(position),  | 
33  | 0  |         }  | 
34  | 0  |     }  | 
35  |  |  | 
36  |  |     /// Create a new [`ErrorKind::Incomplete`] for the given length.  | 
37  |  |     ///  | 
38  |  |     /// Computes the expected len as being one greater than `actual_len`.  | 
39  | 0  |     pub fn incomplete(actual_len: Length) -> Self { | 
40  | 0  |         match actual_len + Length::ONE { | 
41  | 0  |             Ok(expected_len) => ErrorKind::Incomplete { | 
42  | 0  |                 expected_len,  | 
43  | 0  |                 actual_len,  | 
44  | 0  |             }  | 
45  | 0  |             .at(actual_len),  | 
46  | 0  |             Err(err) => err.kind().at(actual_len),  | 
47  |  |         }  | 
48  | 0  |     }  | 
49  |  |  | 
50  |  |     /// Get the [`ErrorKind`] which occurred.  | 
51  | 0  |     pub fn kind(self) -> ErrorKind { | 
52  | 0  |         self.kind  | 
53  | 0  |     }  | 
54  |  |  | 
55  |  |     /// Get the position inside of the message where the error occurred.  | 
56  | 0  |     pub fn position(self) -> Option<Length> { | 
57  | 0  |         self.position  | 
58  | 0  |     }  | 
59  |  |  | 
60  |  |     /// For errors occurring inside of a nested message, extend the position  | 
61  |  |     /// count by the location where the nested message occurs.  | 
62  | 0  |     pub(crate) fn nested(self, nested_position: Length) -> Self { | 
63  |  |         // TODO(tarcieri): better handle length overflows occurring in this calculation?  | 
64  | 0  |         let position = (nested_position + self.position.unwrap_or_default()).ok();  | 
65  |  |  | 
66  | 0  |         Self { | 
67  | 0  |             kind: self.kind,  | 
68  | 0  |             position,  | 
69  | 0  |         }  | 
70  | 0  |     }  | 
71  |  | }  | 
72  |  |  | 
73  |  | #[cfg(feature = "std")]  | 
74  |  | impl std::error::Error for Error {} | 
75  |  |  | 
76  |  | impl fmt::Display for Error { | 
77  | 0  |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
78  | 0  |         write!(f, "{}", self.kind)?; | 
79  |  |  | 
80  | 0  |         if let Some(pos) = self.position { | 
81  | 0  |             write!(f, " at DER byte {}", pos)?; | 
82  | 0  |         }  | 
83  |  |  | 
84  | 0  |         Ok(())  | 
85  | 0  |     }  | 
86  |  | }  | 
87  |  |  | 
88  |  | impl From<ErrorKind> for Error { | 
89  | 0  |     fn from(kind: ErrorKind) -> Error { | 
90  | 0  |         Error { | 
91  | 0  |             kind,  | 
92  | 0  |             position: None,  | 
93  | 0  |         }  | 
94  | 0  |     }  | 
95  |  | }  | 
96  |  |  | 
97  |  | impl From<Infallible> for Error { | 
98  | 0  |     fn from(_: Infallible) -> Error { | 
99  | 0  |         unreachable!()  | 
100  |  |     }  | 
101  |  | }  | 
102  |  |  | 
103  |  | impl From<TryFromIntError> for Error { | 
104  | 0  |     fn from(_: TryFromIntError) -> Error { | 
105  | 0  |         Error { | 
106  | 0  |             kind: ErrorKind::Overflow,  | 
107  | 0  |             position: None,  | 
108  | 0  |         }  | 
109  | 0  |     }  | 
110  |  | }  | 
111  |  |  | 
112  |  | impl From<Utf8Error> for Error { | 
113  | 0  |     fn from(err: Utf8Error) -> Error { | 
114  | 0  |         Error { | 
115  | 0  |             kind: ErrorKind::Utf8(err),  | 
116  | 0  |             position: None,  | 
117  | 0  |         }  | 
118  | 0  |     }  | 
119  |  | }  | 
120  |  |  | 
121  |  | #[cfg(feature = "alloc")]  | 
122  |  | impl From<alloc::string::FromUtf8Error> for Error { | 
123  | 0  |     fn from(err: alloc::string::FromUtf8Error) -> Error { | 
124  | 0  |         ErrorKind::Utf8(err.utf8_error()).into()  | 
125  | 0  |     }  | 
126  |  | }  | 
127  |  |  | 
128  |  | #[cfg(feature = "oid")]  | 
129  |  | impl From<const_oid::Error> for Error { | 
130  |  |     fn from(_: const_oid::Error) -> Error { | 
131  |  |         ErrorKind::OidMalformed.into()  | 
132  |  |     }  | 
133  |  | }  | 
134  |  |  | 
135  |  | #[cfg(feature = "pem")]  | 
136  |  | impl From<pem::Error> for Error { | 
137  |  |     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 { | 
144  |  |     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 { | 
156  |  |     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.  | 
303  | 0  |     pub fn at(self, position: Length) -> Error { | 
304  | 0  |         Error::new(self, position)  | 
305  | 0  |     }  | 
306  |  | }  | 
307  |  |  | 
308  |  | impl fmt::Display for ErrorKind { | 
309  | 0  |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
310  | 0  |         match self { | 
311  | 0  |             ErrorKind::DateTime => write!(f, "date/time error"),  | 
312  | 0  |             ErrorKind::Failed => write!(f, "operation failed"),  | 
313  |  |             #[cfg(feature = "std")]  | 
314  |  |             ErrorKind::FileNotFound => write!(f, "file not found"),  | 
315  |  |             ErrorKind::Incomplete { | 
316  | 0  |                 expected_len,  | 
317  | 0  |                 actual_len,  | 
318  | 0  |             } => write!(  | 
319  | 0  |                 f,  | 
320  | 0  |                 "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  | 0  |             ErrorKind::IndefiniteLength => write!(f, "indefinite length disallowed"),  | 
326  | 0  |             ErrorKind::Length { tag } => write!(f, "incorrect length for {}", tag), | 
327  | 0  |             ErrorKind::Noncanonical { tag } => { | 
328  | 0  |                 write!(f, "ASN.1 {} not canonically encoded as DER", tag) | 
329  |  |             }  | 
330  | 0  |             ErrorKind::OidMalformed => write!(f, "malformed OID"),  | 
331  |  |             #[cfg(feature = "oid")]  | 
332  |  |             ErrorKind::OidUnknown { oid } => { | 
333  |  |                 write!(f, "unknown/unsupported OID: {}", oid) | 
334  |  |             }  | 
335  | 0  |             ErrorKind::SetDuplicate => write!(f, "SET OF contains duplicate"),  | 
336  | 0  |             ErrorKind::SetOrdering => write!(f, "SET OF ordering error"),  | 
337  | 0  |             ErrorKind::Overflow => write!(f, "integer overflow"),  | 
338  | 0  |             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  | 0  |             ErrorKind::Reader => write!(f, "reader does not support the requested operation"),  | 
344  | 0  |             ErrorKind::TagModeUnknown => write!(f, "unknown tag mode"),  | 
345  | 0  |             ErrorKind::TagNumberInvalid => write!(f, "invalid tag number"),  | 
346  | 0  |             ErrorKind::TagUnexpected { expected, actual } => { | 
347  | 0  |                 write!(f, "unexpected ASN.1 DER tag: ")?;  | 
348  |  |  | 
349  | 0  |                 if let Some(tag) = expected { | 
350  | 0  |                     write!(f, "expected {}, ", tag)?; | 
351  | 0  |                 }  | 
352  |  |  | 
353  | 0  |                 write!(f, "got {}", actual) | 
354  |  |             }  | 
355  | 0  |             ErrorKind::TagUnknown { byte } => { | 
356  | 0  |                 write!(f, "unknown/unsupported ASN.1 DER tag: 0x{:02x}", byte) | 
357  |  |             }  | 
358  | 0  |             ErrorKind::TrailingData { decoded, remaining } => { | 
359  | 0  |                 write!(  | 
360  | 0  |                     f,  | 
361  | 0  |                     "trailing data at end of DER message: decoded {} bytes, {} bytes remaining", | 
362  |  |                     decoded, remaining  | 
363  |  |                 )  | 
364  |  |             }  | 
365  | 0  |             ErrorKind::Utf8(e) => write!(f, "{}", e), | 
366  | 0  |             ErrorKind::Value { tag } => write!(f, "malformed ASN.1 DER value for {}", tag), | 
367  |  |         }  | 
368  | 0  |     }  | 
369  |  | }  |