/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 | | } |