1pub use core::str::Utf8Error;
4
5use crate::{Length, Tag};
6use core::{convert::Infallible, fmt};
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(self) -> Option<usize> {
38 self.kind().incomplete()
39 }
40
41 pub fn kind(self) -> ErrorKind {
43 self.kind
44 }
45
46 pub fn position(self) -> Option<Length> {
48 self.position
49 }
50
51 pub(crate) fn nested(self, nested_position: Length) -> Self {
54 let position = (nested_position + self.position.unwrap_or_default()).ok();
56
57 Self {
58 kind: self.kind,
59 position,
60 }
61 }
62}
63
64#[cfg(feature = "std")]
65impl std::error::Error for Error {}
66
67impl fmt::Display for Error {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 write!(f, "{}", self.kind)?;
70
71 if let Some(pos) = self.position {
72 write!(f, " at DER byte {}", pos)?;
73 }
74
75 Ok(())
76 }
77}
78
79impl From<ErrorKind> for Error {
80 fn from(kind: ErrorKind) -> Error {
81 Error {
82 kind,
83 position: None,
84 }
85 }
86}
87
88impl From<Infallible> for Error {
89 fn from(_: Infallible) -> Error {
90 unreachable!()
91 }
92}
93
94impl From<Utf8Error> for Error {
95 fn from(err: Utf8Error) -> Error {
96 Error {
97 kind: ErrorKind::Utf8(err),
98 position: None,
99 }
100 }
101}
102
103#[cfg(feature = "oid")]
104impl From<const_oid::Error> for Error {
105 fn from(_: const_oid::Error) -> Error {
106 ErrorKind::OidMalformed.into()
107 }
108}
109
110#[cfg(feature = "pem")]
111impl From<pem::Error> for Error {
112 fn from(err: pem::Error) -> Error {
113 ErrorKind::Pem(err).into()
114 }
115}
116
117#[cfg(feature = "std")]
118impl From<std::io::Error> for Error {
119 fn from(err: std::io::Error) -> Error {
120 match err.kind() {
121 std::io::ErrorKind::NotFound => ErrorKind::FileNotFound,
122 std::io::ErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
123 other => ErrorKind::Io(other),
124 }
125 .into()
126 }
127}
128
129#[cfg(feature = "time")]
130impl From<time::error::ComponentRange> for Error {
131 fn from(_: time::error::ComponentRange) -> Error {
132 ErrorKind::DateTime.into()
133 }
134}
135#[derive(Copy, Clone, Debug, Eq, PartialEq)]
137#[non_exhaustive]
138pub enum ErrorKind {
139 DateTime,
141
142 Failed,
148
149 #[cfg(feature = "std")]
151 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
152 FileNotFound,
153
154 Incomplete {
156 expected_len: Length,
164
165 actual_len: Length,
167 },
168
169 #[cfg(feature = "std")]
171 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
172 Io(std::io::ErrorKind),
173
174 Length {
176 tag: Tag,
178 },
179
180 Noncanonical {
182 tag: Tag,
184 },
185
186 OidMalformed,
188
189 #[cfg(feature = "oid")]
198 #[cfg_attr(docsrs, doc(cfg(feature = "oid")))]
199 OidUnknown {
200 oid: ObjectIdentifier,
202 },
203
204 SetOrdering,
206
207 Overflow,
209
210 Overlength,
212
213 #[cfg(feature = "pem")]
215 #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
216 Pem(pem::Error),
217
218 #[cfg(feature = "std")]
220 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
221 PermissionDenied,
222
223 TagModeUnknown,
225
226 TagNumberInvalid,
232
233 TagUnexpected {
235 expected: Option<Tag>,
240
241 actual: Tag,
243 },
244
245 TagUnknown {
247 byte: u8,
249 },
250
251 TrailingData {
253 decoded: Length,
255
256 remaining: Length,
258 },
259
260 Utf8(Utf8Error),
262
263 Value {
265 tag: Tag,
267 },
268}
269
270impl ErrorKind {
271 pub fn at(self, position: Length) -> Error {
274 Error::new(self, position)
275 }
276
277 pub fn incomplete(self) -> Option<usize> {
279 match self {
280 ErrorKind::Incomplete { expected_len, .. } => usize::try_from(expected_len).ok(),
281 _ => None,
282 }
283 }
284}
285
286impl fmt::Display for ErrorKind {
287 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
288 match self {
289 ErrorKind::DateTime => write!(f, "date/time error"),
290 ErrorKind::Failed => write!(f, "operation failed"),
291 #[cfg(feature = "std")]
292 ErrorKind::FileNotFound => f.write_str("file not found"),
293 ErrorKind::Incomplete {
294 expected_len,
295 actual_len,
296 } => write!(
297 f,
298 "ASN.1 DER message is incomplete: expected {}, actual {}",
299 expected_len, actual_len
300 ),
301 #[cfg(feature = "std")]
302 ErrorKind::Io(err) => write!(f, "I/O error: {:?}", err),
303 ErrorKind::Length { tag } => write!(f, "incorrect length for {}", tag),
304 ErrorKind::Noncanonical { tag } => {
305 write!(f, "ASN.1 {} not canonically encoded as DER", tag)
306 }
307 ErrorKind::OidMalformed => write!(f, "malformed OID"),
308 #[cfg(feature = "oid")]
309 ErrorKind::OidUnknown { oid } => {
310 write!(f, "unknown/unsupported OID: {}", oid)
311 }
312 ErrorKind::SetOrdering => write!(f, "ordering error"),
313 ErrorKind::Overflow => write!(f, "integer overflow"),
314 ErrorKind::Overlength => write!(f, "ASN.1 DER message is too long"),
315 #[cfg(feature = "pem")]
316 ErrorKind::Pem(e) => write!(f, "PEM error: {}", e),
317 #[cfg(feature = "std")]
318 ErrorKind::PermissionDenied => f.write_str("permission denied"),
319 ErrorKind::TagModeUnknown => write!(f, "unknown tag mode"),
320 ErrorKind::TagNumberInvalid => write!(f, "invalid tag number"),
321 ErrorKind::TagUnexpected { expected, actual } => {
322 write!(f, "unexpected ASN.1 DER tag: ")?;
323
324 if let Some(tag) = expected {
325 write!(f, "expected {}, ", tag)?;
326 }
327
328 write!(f, "got {}", actual)
329 }
330 ErrorKind::TagUnknown { byte } => {
331 write!(f, "unknown/unsupported ASN.1 DER tag: 0x{:02x}", byte)
332 }
333 ErrorKind::TrailingData { decoded, remaining } => {
334 write!(
335 f,
336 "trailing data at end of DER message: decoded {} bytes, {} bytes remaining",
337 decoded, remaining
338 )
339 }
340 ErrorKind::Utf8(e) => write!(f, "{}", e),
341 ErrorKind::Value { tag } => write!(f, "malformed ASN.1 DER value for {}", tag),
342 }
343 }
344}