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 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. at(self, position: Length) -> Error303 pub fn at(self, position: Length) -> Error { 304 Error::new(self, position) 305 } 306 } 307 308 impl fmt::Display for ErrorKind { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result309 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 } 370