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`]. new(kind: ErrorKind, position: Length) -> Error29 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`. incomplete(actual_len: Length) -> Self39 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. kind(self) -> ErrorKind51 pub fn kind(self) -> ErrorKind { 52 self.kind 53 } 54 55 /// Get the position inside of the message where the error occurred. position(self) -> Option<Length>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. nested(self, nested_position: Length) -> Self62 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 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result77 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 { from(kind: ErrorKind) -> Error89 fn from(kind: ErrorKind) -> Error { 90 Error { 91 kind, 92 position: None, 93 } 94 } 95 } 96 97 impl From<Infallible> for Error { from(_: Infallible) -> Error98 fn from(_: Infallible) -> Error { 99 unreachable!() 100 } 101 } 102 103 impl From<TryFromIntError> for Error { from(_: TryFromIntError) -> Error104 fn from(_: TryFromIntError) -> Error { 105 Error { 106 kind: ErrorKind::Overflow, 107 position: None, 108 } 109 } 110 } 111 112 impl From<Utf8Error> for Error { from(err: Utf8Error) -> Error113 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 { from(err: alloc::string::FromUtf8Error) -> Error123 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 { from(_: const_oid::Error) -> Error130 fn from(_: const_oid::Error) -> Error { 131 ErrorKind::OidMalformed.into() 132 } 133 } 134 135 #[cfg(feature = "pem")] 136 impl From<pem::Error> for Error { from(err: pem::Error) -> Error137 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 { from(err: std::io::Error) -> Error144 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 { from(_: time::error::ComponentRange) -> Error156 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. at(self, position: Length) -> Error302 pub fn at(self, position: Length) -> Error { 303 Error::new(self, position) 304 } 305 } 306 307 impl fmt::Display for ErrorKind { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result308 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 } 367