1pub use core::str::Utf8Error;
4
5use crate::{Length, Tag};
6use core::{convert::Infallible, fmt, num::TryFromIntError};
7
8#[cfg(feature = "oid")]
9use crate::asn1::ObjectIdentifier;
10
11#[cfg(feature = "pem")]
12use crate::pem;
13
14pub type Result<T> = core::result::Result<T, Error>;
16
17#[derive(Copy, Clone, Debug, Eq, PartialEq)]
19pub struct Error {
20 kind: ErrorKind,
22
23 position: Option<Length>,
25}
26
27impl Error {
28 pub fn new(kind: ErrorKind, position: Length) -> Error {
30 Error {
31 kind,
32 position: Some(position),
33 }
34 }
35
36 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 pub fn kind(self) -> ErrorKind {
52 self.kind
53 }
54
55 pub fn position(self) -> Option<Length> {
57 self.position
58 }
59
60 pub(crate) fn nested(self, nested_position: Length) -> Self {
63 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")]
74impl std::error::Error for Error {}
75
76impl 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
88impl From<ErrorKind> for Error {
89 fn from(kind: ErrorKind) -> Error {
90 Error {
91 kind,
92 position: None,
93 }
94 }
95}
96
97impl From<Infallible> for Error {
98 fn from(_: Infallible) -> Error {
99 unreachable!()
100 }
101}
102
103impl From<TryFromIntError> for Error {
104 fn from(_: TryFromIntError) -> Error {
105 Error {
106 kind: ErrorKind::Overflow,
107 position: None,
108 }
109 }
110}
111
112impl 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")]
122impl 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")]
129impl From<const_oid::Error> for Error {
130 fn from(_: const_oid::Error) -> Error {
131 ErrorKind::OidMalformed.into()
132 }
133}
134
135#[cfg(feature = "pem")]
136impl From<pem::Error> for Error {
137 fn from(err: pem::Error) -> Error {
138 ErrorKind::Pem(err).into()
139 }
140}
141
142#[cfg(feature = "std")]
143impl 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")]
155impl From<time::error::ComponentRange> for Error {
156 fn from(_: time::error::ComponentRange) -> Error {
157 ErrorKind::DateTime.into()
158 }
159}
160
161#[derive(Copy, Clone, Debug, Eq, PartialEq)]
163#[non_exhaustive]
164pub enum ErrorKind {
165 DateTime,
167
168 Failed,
174
175 #[cfg(feature = "std")]
177 FileNotFound,
178
179 Incomplete {
181 expected_len: Length,
189
190 actual_len: Length,
192 },
193
194 #[cfg(feature = "std")]
196 Io(std::io::ErrorKind),
197
198 IndefiniteLength,
200
201 Length {
203 tag: Tag,
205 },
206
207 Noncanonical {
209 tag: Tag,
211 },
212
213 OidMalformed,
215
216 #[cfg(feature = "oid")]
225 OidUnknown {
226 oid: ObjectIdentifier,
228 },
229
230 SetDuplicate,
232
233 SetOrdering,
235
236 Overflow,
238
239 Overlength,
241
242 #[cfg(feature = "pem")]
244 Pem(pem::Error),
245
246 #[cfg(feature = "std")]
248 PermissionDenied,
249
250 Reader,
252
253 TagModeUnknown,
255
256 TagNumberInvalid,
262
263 TagUnexpected {
265 expected: Option<Tag>,
270
271 actual: Tag,
273 },
274
275 TagUnknown {
277 byte: u8,
279 },
280
281 TrailingData {
283 decoded: Length,
285
286 remaining: Length,
288 },
289
290 Utf8(Utf8Error),
292
293 Value {
295 tag: Tag,
297 },
298}
299
300impl ErrorKind {
301 pub fn at(self, position: Length) -> Error {
304 Error::new(self, position)
305 }
306}
307
308impl fmt::Display for ErrorKind {
309 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}