summaryrefslogtreecommitdiffstats
path: root/vendor/der/src/error.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/der/src/error.rs')
-rw-r--r--vendor/der/src/error.rs369
1 files changed, 369 insertions, 0 deletions
diff --git a/vendor/der/src/error.rs b/vendor/der/src/error.rs
new file mode 100644
index 0000000..902863d
--- /dev/null
+++ b/vendor/der/src/error.rs
@@ -0,0 +1,369 @@
+//! Error types.
+
+pub use core::str::Utf8Error;
+
+use crate::{Length, Tag};
+use core::{convert::Infallible, fmt, num::TryFromIntError};
+
+#[cfg(feature = "oid")]
+use crate::asn1::ObjectIdentifier;
+
+#[cfg(feature = "pem")]
+use crate::pem;
+
+/// Result type.
+pub type Result<T> = core::result::Result<T, Error>;
+
+/// Error type.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct Error {
+ /// Kind of error.
+ kind: ErrorKind,
+
+ /// Position inside of message where error occurred.
+ position: Option<Length>,
+}
+
+impl Error {
+ /// Create a new [`Error`].
+ pub fn new(kind: ErrorKind, position: Length) -> Error {
+ Error {
+ kind,
+ position: Some(position),
+ }
+ }
+
+ /// Create a new [`ErrorKind::Incomplete`] for the given length.
+ ///
+ /// Computes the expected len as being one greater than `actual_len`.
+ pub fn incomplete(actual_len: Length) -> Self {
+ match actual_len + Length::ONE {
+ Ok(expected_len) => ErrorKind::Incomplete {
+ expected_len,
+ actual_len,
+ }
+ .at(actual_len),
+ Err(err) => err.kind().at(actual_len),
+ }
+ }
+
+ /// Get the [`ErrorKind`] which occurred.
+ pub fn kind(self) -> ErrorKind {
+ self.kind
+ }
+
+ /// Get the position inside of the message where the error occurred.
+ pub fn position(self) -> Option<Length> {
+ self.position
+ }
+
+ /// For errors occurring inside of a nested message, extend the position
+ /// count by the location where the nested message occurs.
+ pub(crate) fn nested(self, nested_position: Length) -> Self {
+ // TODO(tarcieri): better handle length overflows occurring in this calculation?
+ let position = (nested_position + self.position.unwrap_or_default()).ok();
+
+ Self {
+ kind: self.kind,
+ position,
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for Error {}
+
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{}", self.kind)?;
+
+ if let Some(pos) = self.position {
+ write!(f, " at DER byte {}", pos)?;
+ }
+
+ Ok(())
+ }
+}
+
+impl From<ErrorKind> for Error {
+ fn from(kind: ErrorKind) -> Error {
+ Error {
+ kind,
+ position: None,
+ }
+ }
+}
+
+impl From<Infallible> for Error {
+ fn from(_: Infallible) -> Error {
+ unreachable!()
+ }
+}
+
+impl From<TryFromIntError> for Error {
+ fn from(_: TryFromIntError) -> Error {
+ Error {
+ kind: ErrorKind::Overflow,
+ position: None,
+ }
+ }
+}
+
+impl From<Utf8Error> for Error {
+ fn from(err: Utf8Error) -> Error {
+ Error {
+ kind: ErrorKind::Utf8(err),
+ position: None,
+ }
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl From<alloc::string::FromUtf8Error> for Error {
+ fn from(err: alloc::string::FromUtf8Error) -> Error {
+ ErrorKind::Utf8(err.utf8_error()).into()
+ }
+}
+
+#[cfg(feature = "oid")]
+impl From<const_oid::Error> for Error {
+ fn from(_: const_oid::Error) -> Error {
+ ErrorKind::OidMalformed.into()
+ }
+}
+
+#[cfg(feature = "pem")]
+impl From<pem::Error> for Error {
+ fn from(err: pem::Error) -> Error {
+ ErrorKind::Pem(err).into()
+ }
+}
+
+#[cfg(feature = "std")]
+impl From<std::io::Error> for Error {
+ fn from(err: std::io::Error) -> Error {
+ match err.kind() {
+ std::io::ErrorKind::NotFound => ErrorKind::FileNotFound,
+ std::io::ErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
+ other => ErrorKind::Io(other),
+ }
+ .into()
+ }
+}
+
+#[cfg(feature = "time")]
+impl From<time::error::ComponentRange> for Error {
+ fn from(_: time::error::ComponentRange) -> Error {
+ ErrorKind::DateTime.into()
+ }
+}
+
+/// Error type.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[non_exhaustive]
+pub enum ErrorKind {
+ /// Date-and-time related errors.
+ DateTime,
+
+ /// This error indicates a previous DER parsing operation resulted in
+ /// an error and tainted the state of a `Decoder` or `Encoder`.
+ ///
+ /// Once this occurs, the overall operation has failed and cannot be
+ /// subsequently resumed.
+ Failed,
+
+ /// File not found error.
+ #[cfg(feature = "std")]
+ FileNotFound,
+
+ /// Message is incomplete and does not contain all of the expected data.
+ Incomplete {
+ /// Expected message length.
+ ///
+ /// Note that this length represents a *minimum* lower bound on how
+ /// much additional data is needed to continue parsing the message.
+ ///
+ /// It's possible upon subsequent message parsing that the parser will
+ /// discover even more data is needed.
+ expected_len: Length,
+
+ /// Actual length of the message buffer currently being processed.
+ actual_len: Length,
+ },
+
+ /// I/O errors.
+ #[cfg(feature = "std")]
+ Io(std::io::ErrorKind),
+
+ /// Indefinite length disallowed.
+ IndefiniteLength,
+
+ /// Incorrect length for a given field.
+ Length {
+ /// Tag of the value being decoded.
+ tag: Tag,
+ },
+
+ /// Message is not canonically encoded.
+ Noncanonical {
+ /// Tag of the value which is not canonically encoded.
+ tag: Tag,
+ },
+
+ /// OID is improperly encoded.
+ OidMalformed,
+
+ /// Unknown OID.
+ ///
+ /// This error is intended to be used by libraries which parse DER-based
+ /// formats which encounter unknown or unsupported OID libraries.
+ ///
+ /// It enables passing back the OID value to the caller, which allows them
+ /// to determine which OID(s) are causing the error (and then potentially
+ /// contribute upstream support for algorithms they care about).
+ #[cfg(feature = "oid")]
+ OidUnknown {
+ /// OID value that was unrecognized by a parser for a DER-based format.
+ oid: ObjectIdentifier,
+ },
+
+ /// `SET` cannot contain duplicates.
+ SetDuplicate,
+
+ /// `SET` ordering error: items not in canonical order.
+ SetOrdering,
+
+ /// Integer overflow occurred (library bug!).
+ Overflow,
+
+ /// Message is longer than this library's internal limits support.
+ Overlength,
+
+ /// PEM encoding errors.
+ #[cfg(feature = "pem")]
+ Pem(pem::Error),
+
+ /// Permission denied reading file.
+ #[cfg(feature = "std")]
+ PermissionDenied,
+
+ /// Reader does not support the requested operation.
+ Reader,
+
+ /// Unknown tag mode.
+ TagModeUnknown,
+
+ /// Invalid tag number.
+ ///
+ /// The "tag number" is the lower 5-bits of a tag's octet.
+ /// This error occurs in the case that all 5-bits are set to `1`,
+ /// which indicates a multi-byte tag which is unsupported by this library.
+ TagNumberInvalid,
+
+ /// Unexpected tag.
+ TagUnexpected {
+ /// Tag the decoder was expecting (if there is a single such tag).
+ ///
+ /// `None` if multiple tags are expected/allowed, but the `actual` tag
+ /// does not match any of them.
+ expected: Option<Tag>,
+
+ /// Actual tag encountered in the message.
+ actual: Tag,
+ },
+
+ /// Unknown/unsupported tag.
+ TagUnknown {
+ /// Raw byte value of the tag.
+ byte: u8,
+ },
+
+ /// Undecoded trailing data at end of message.
+ TrailingData {
+ /// Length of the decoded data.
+ decoded: Length,
+
+ /// Total length of the remaining data left in the buffer.
+ remaining: Length,
+ },
+
+ /// UTF-8 errors.
+ Utf8(Utf8Error),
+
+ /// Unexpected value.
+ Value {
+ /// Tag of the unexpected value.
+ tag: Tag,
+ },
+}
+
+impl ErrorKind {
+ /// Annotate an [`ErrorKind`] with context about where it occurred,
+ /// returning an error.
+ pub fn at(self, position: Length) -> Error {
+ Error::new(self, position)
+ }
+}
+
+impl fmt::Display for ErrorKind {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ ErrorKind::DateTime => write!(f, "date/time error"),
+ ErrorKind::Failed => write!(f, "operation failed"),
+ #[cfg(feature = "std")]
+ ErrorKind::FileNotFound => write!(f, "file not found"),
+ ErrorKind::Incomplete {
+ expected_len,
+ actual_len,
+ } => write!(
+ f,
+ "ASN.1 DER message is incomplete: expected {}, actual {}",
+ expected_len, actual_len
+ ),
+ #[cfg(feature = "std")]
+ ErrorKind::Io(err) => write!(f, "I/O error: {:?}", err),
+ ErrorKind::IndefiniteLength => write!(f, "indefinite length disallowed"),
+ ErrorKind::Length { tag } => write!(f, "incorrect length for {}", tag),
+ ErrorKind::Noncanonical { tag } => {
+ write!(f, "ASN.1 {} not canonically encoded as DER", tag)
+ }
+ ErrorKind::OidMalformed => write!(f, "malformed OID"),
+ #[cfg(feature = "oid")]
+ ErrorKind::OidUnknown { oid } => {
+ write!(f, "unknown/unsupported OID: {}", oid)
+ }
+ ErrorKind::SetDuplicate => write!(f, "SET OF contains duplicate"),
+ ErrorKind::SetOrdering => write!(f, "SET OF ordering error"),
+ ErrorKind::Overflow => write!(f, "integer overflow"),
+ ErrorKind::Overlength => write!(f, "ASN.1 DER message is too long"),
+ #[cfg(feature = "pem")]
+ ErrorKind::Pem(e) => write!(f, "PEM error: {}", e),
+ #[cfg(feature = "std")]
+ ErrorKind::PermissionDenied => write!(f, "permission denied"),
+ ErrorKind::Reader => write!(f, "reader does not support the requested operation"),
+ ErrorKind::TagModeUnknown => write!(f, "unknown tag mode"),
+ ErrorKind::TagNumberInvalid => write!(f, "invalid tag number"),
+ ErrorKind::TagUnexpected { expected, actual } => {
+ write!(f, "unexpected ASN.1 DER tag: ")?;
+
+ if let Some(tag) = expected {
+ write!(f, "expected {}, ", tag)?;
+ }
+
+ write!(f, "got {}", actual)
+ }
+ ErrorKind::TagUnknown { byte } => {
+ write!(f, "unknown/unsupported ASN.1 DER tag: 0x{:02x}", byte)
+ }
+ ErrorKind::TrailingData { decoded, remaining } => {
+ write!(
+ f,
+ "trailing data at end of DER message: decoded {} bytes, {} bytes remaining",
+ decoded, remaining
+ )
+ }
+ ErrorKind::Utf8(e) => write!(f, "{}", e),
+ ErrorKind::Value { tag } => write!(f, "malformed ASN.1 DER value for {}", tag),
+ }
+ }
+}