]> git.proxmox.com Git - rustc.git/blob - vendor/der/src/error.rs
New upstream version 1.70.0+dfsg2
[rustc.git] / vendor / der / src / error.rs
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 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`.
39 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.
51 pub fn kind(self) -> ErrorKind {
52 self.kind
53 }
54
55 /// Get the position inside of the message where the error occurred.
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.
62 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 {
77 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 {
89 fn from(kind: ErrorKind) -> Error {
90 Error {
91 kind,
92 position: None,
93 }
94 }
95 }
96
97 impl From<Infallible> for Error {
98 fn from(_: Infallible) -> Error {
99 unreachable!()
100 }
101 }
102
103 impl From<TryFromIntError> for Error {
104 fn from(_: TryFromIntError) -> Error {
105 Error {
106 kind: ErrorKind::Overflow,
107 position: None,
108 }
109 }
110 }
111
112 impl From<Utf8Error> for Error {
113 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 {
123 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 {
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 #[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.
302 pub fn at(self, position: Length) -> Error {
303 Error::new(self, position)
304 }
305 }
306
307 impl fmt::Display for ErrorKind {
308 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 }