use core::fmt;
use core::ops::ControlFlow;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum Error {
BadDer,
BadDerTime,
CaUsedAsEndEntity,
CertExpired,
CertNotValidForName,
CertNotValidYet,
CertRevoked,
EndEntityUsedAsCa,
ExtensionValueInvalid,
InvalidCertValidity,
InvalidCrlNumber,
InvalidNetworkMaskConstraint,
InvalidSerialNumber,
InvalidCrlSignatureForPublicKey,
InvalidSignatureForPublicKey,
IssuerNotCrlSigner,
MalformedDnsIdentifier,
MalformedExtensions,
MalformedNameConstraint,
MaximumNameConstraintComparisonsExceeded,
MaximumPathBuildCallsExceeded,
MaximumPathDepthExceeded,
MaximumSignatureChecksExceeded,
NameConstraintViolation,
PathLenConstraintViolated,
RequiredEkuNotFound,
SignatureAlgorithmMismatch,
UnknownIssuer,
UnsupportedCertVersion,
UnsupportedCriticalExtension,
UnsupportedCrlVersion,
UnsupportedDeltaCrl,
UnsupportedIndirectCrl,
UnsupportedRevocationReason,
UnsupportedCrlSignatureAlgorithm,
UnsupportedSignatureAlgorithm,
UnsupportedCrlSignatureAlgorithmForPublicKey,
UnsupportedSignatureAlgorithmForPublicKey,
}
impl Error {
pub(crate) fn most_specific(self, new: Error) -> Error {
if self.rank() >= new.rank() {
self
} else {
new
}
}
#[allow(clippy::as_conversions)] pub(crate) fn rank(&self) -> u32 {
match &self {
Error::CertNotValidYet | Error::CertExpired => 290,
Error::CertNotValidForName => 280,
Error::CertRevoked => 270,
Error::InvalidCrlSignatureForPublicKey | Error::InvalidSignatureForPublicKey => 260,
Error::SignatureAlgorithmMismatch => 250,
Error::RequiredEkuNotFound => 240,
Error::NameConstraintViolation => 230,
Error::PathLenConstraintViolated => 220,
Error::CaUsedAsEndEntity | Error::EndEntityUsedAsCa => 210,
Error::IssuerNotCrlSigner => 200,
Error::InvalidCertValidity => 190,
Error::InvalidNetworkMaskConstraint => 180,
Error::InvalidSerialNumber => 170,
Error::InvalidCrlNumber => 160,
Error::UnsupportedCrlSignatureAlgorithmForPublicKey
| Error::UnsupportedSignatureAlgorithmForPublicKey => 150,
Error::UnsupportedCrlSignatureAlgorithm | Error::UnsupportedSignatureAlgorithm => 140,
Error::UnsupportedCriticalExtension => 130,
Error::UnsupportedCertVersion => 130,
Error::UnsupportedCrlVersion => 120,
Error::UnsupportedDeltaCrl => 110,
Error::UnsupportedIndirectCrl => 100,
Error::UnsupportedRevocationReason => 90,
Error::MaximumPathDepthExceeded => 61,
Error::MalformedDnsIdentifier => 60,
Error::MalformedNameConstraint => 50,
Error::MalformedExtensions => 40,
Error::ExtensionValueInvalid => 30,
Error::BadDerTime => 20,
Error::BadDer => 10,
Error::MaximumSignatureChecksExceeded => 0,
Error::MaximumPathBuildCallsExceeded => 0,
Error::MaximumNameConstraintComparisonsExceeded => 0,
Error::UnknownIssuer => 0,
}
}
#[inline]
pub(crate) fn is_fatal(&self) -> bool {
matches!(
self,
Error::MaximumSignatureChecksExceeded
| Error::MaximumPathBuildCallsExceeded
| Error::MaximumNameConstraintComparisonsExceeded
)
}
}
impl From<Error> for ControlFlow<Error, Error> {
fn from(value: Error) -> Self {
match value {
err if err.is_fatal() => Self::Break(err),
err => Self::Continue(err),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl ::std::error::Error for Error {}
impl From<untrusted::EndOfInput> for Error {
fn from(_: untrusted::EndOfInput) -> Self {
Error::BadDer
}
}