webauthn_rp

WebAuthn Level 3 RP library.
git clone https://git.philomathiclife.com/repos/webauthn_rp
Log | Files | Refs | README

error.rs (31467B)


      1 #[cfg(feature = "serde_relaxed")]
      2 use super::super::SerdeJsonErr;
      3 #[cfg(doc)]
      4 use super::{
      5     super::super::{
      6         RegisteredCredential,
      7         request::{
      8             BackupReq, CredentialMediationRequirement, UserVerificationRequirement,
      9             register::{
     10                 AuthenticatorAttachmentReq, AuthenticatorSelectionCriteria,
     11                 CredentialCreationOptions, Extension, PublicKeyCredentialCreationOptions,
     12                 RegistrationServerState, RegistrationVerificationOptions,
     13             },
     14         },
     15     },
     16     Aaguid, Attestation, AttestationObject, AttestedCredentialData, AuthenticatorAttachment,
     17     AuthenticatorAttestation, AuthenticatorData, AuthenticatorExtensionOutput, Backup,
     18     ClientExtensionsOutputs, CollectedClientData, CompressedP256PubKey, CompressedP384PubKey,
     19     Ed25519PubKey, Ed25519Signature, Flag, MAX_RSA_N_BITS, MIN_RSA_E, MIN_RSA_N_BITS, Metadata,
     20     PackedAttestation, RsaPubKey, UncompressedP256PubKey, UncompressedP384PubKey,
     21     UncompressedPubKey,
     22 };
     23 use super::{
     24     super::{
     25         super::{CredentialErr, request::register::CredProtect},
     26         AuthRespErr, AuthenticatorDataErr as AuthDataErr, CeremonyErr,
     27         error::{CollectedClientDataErr, CredentialIdErr},
     28     },
     29     CredentialProtectionPolicy, FourToSixtyThree,
     30 };
     31 use core::{
     32     convert::Infallible,
     33     error::Error,
     34     fmt::{self, Display, Formatter},
     35 };
     36 /// Error returned from [`Ed25519PubKey::try_from`] when the `slice` is not 32-bytes in length.
     37 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
     38 pub struct Ed25519PubKeyErr;
     39 impl Display for Ed25519PubKeyErr {
     40     #[inline]
     41     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
     42         f.write_str("the Ed25519 public key is not 32-bytes in length")
     43     }
     44 }
     45 impl Error for Ed25519PubKeyErr {}
     46 /// Error returned from [`UncompressedP256PubKey::try_from`].
     47 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
     48 pub enum UncompressedP256PubKeyErr {
     49     /// Variant returned when the x-coordinate is not 32-bytes in length.
     50     X,
     51     /// Variant returned when the y-coordinate is not 32-bytes in length.
     52     Y,
     53 }
     54 impl Display for UncompressedP256PubKeyErr {
     55     #[inline]
     56     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
     57         f.write_str(match *self {
     58             Self::X => "the P-256 public key x-coordinate is not 32-bytes in length",
     59             Self::Y => "the P-256 public key y-coordinate is not 32-bytes in length",
     60         })
     61     }
     62 }
     63 impl Error for UncompressedP256PubKeyErr {}
     64 /// Error returned from [`CompressedP256PubKey::try_from`] when the x-coordinate
     65 /// is not exactly 32 bytes in length.
     66 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
     67 pub struct CompressedP256PubKeyErr;
     68 impl Display for CompressedP256PubKeyErr {
     69     #[inline]
     70     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
     71         f.write_str("the compressed P-256 public key x-coordinate is not 32-bytes in length")
     72     }
     73 }
     74 impl Error for CompressedP256PubKeyErr {}
     75 /// Error returned from [`UncompressedP384PubKey::try_from`].
     76 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
     77 pub enum UncompressedP384PubKeyErr {
     78     /// Variant returned when the x-coordinate is not 48-bytes in length.
     79     X,
     80     /// Variant returned when the y-coordinate is not 48-bytes in length.
     81     Y,
     82 }
     83 impl Display for UncompressedP384PubKeyErr {
     84     #[inline]
     85     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
     86         f.write_str(match *self {
     87             Self::X => "the P-384 public key x-coordinate is not 48-bytes in length",
     88             Self::Y => "the P-384 public key y-coordinate is not 48-bytes in length",
     89         })
     90     }
     91 }
     92 impl Error for UncompressedP384PubKeyErr {}
     93 /// Error returned from [`CompressedP384PubKey::try_from`] when the x-coordinate
     94 /// is not exactly 48 bytes in length.
     95 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
     96 pub struct CompressedP384PubKeyErr;
     97 impl Display for CompressedP384PubKeyErr {
     98     #[inline]
     99     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    100         f.write_str("the compressed P-384 public key x-coordinate is not 48-bytes in length")
    101     }
    102 }
    103 impl Error for CompressedP384PubKeyErr {}
    104 /// Error returned from [`RsaPubKey::try_from`].
    105 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    106 pub enum RsaPubKeyErr {
    107     /// Variant returned when the modulus has a leading 0.
    108     NLeading0,
    109     /// Variant returned when the modulus has fewer than [`MIN_RSA_N_BITS`] or more than
    110     /// [`MAX_RSA_N_BITS`].
    111     NSize,
    112     /// Variant returned when the modulus is even.
    113     NEven,
    114     /// Variant returned when the exponent is less than [`MIN_RSA_E`].
    115     ESize,
    116     /// Variant returned when the exponent is even.
    117     EEven,
    118 }
    119 impl Display for RsaPubKeyErr {
    120     #[inline]
    121     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    122         f.write_str(match *self {
    123             Self::NLeading0 => "the RSA public key modulus had a leading 0",
    124             Self::NSize => {
    125                 "the RSA public key modulus was less than 2048 bits or greater than 16384"
    126             }
    127             Self::NEven => "the RSA public key modulus was even",
    128             Self::ESize => "the RSA public key exponent was less than 3",
    129             Self::EEven => "the RSA public key exponent was even",
    130         })
    131     }
    132 }
    133 impl Error for RsaPubKeyErr {}
    134 /// Error returned when an alleged public key is not valid.
    135 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    136 pub enum PubKeyErr {
    137     /// Error when [`Ed25519PubKey`] is not valid.
    138     ///
    139     /// Note this means the underlying point is either not on the curve or is an element
    140     /// of the small-order subgroup.
    141     Ed25519,
    142     /// Error when [`UncompressedP256PubKey`] or [`CompressedP256PubKey`] is not valid.
    143     P256,
    144     /// Error when [`UncompressedP384PubKey`] or [`CompressedP384PubKey`] is not valid.
    145     P384,
    146 }
    147 impl Display for PubKeyErr {
    148     #[inline]
    149     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    150         f.write_str(match *self {
    151             Self::Ed25519 => "Ed25519 public key is invalid",
    152             Self::P256 => "P-256 public key is invalid",
    153             Self::P384 => "P-384 public key is invalid",
    154         })
    155     }
    156 }
    157 impl Error for PubKeyErr {}
    158 /// Error returned from [`Ed25519Signature::try_from`].
    159 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    160 pub struct Ed25519SignatureErr;
    161 impl Display for Ed25519SignatureErr {
    162     #[inline]
    163     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    164         f.write_str("the Ed25519 signature is not 64-bytes in length")
    165     }
    166 }
    167 impl Error for Ed25519SignatureErr {}
    168 /// Error returned from [`Aaguid::try_from`] when the slice is not exactly
    169 /// 16-bytes in length.
    170 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    171 pub struct AaguidErr;
    172 impl Display for AaguidErr {
    173     #[inline]
    174     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    175         f.write_str("the AAGUID is not 16-bytes in length")
    176     }
    177 }
    178 impl Error for AaguidErr {}
    179 /// Error returned in [`AuthenticatorDataErr::AuthenticatorExtension`].
    180 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    181 pub enum AuthenticatorExtensionOutputErr {
    182     /// The `slice` had an invalid length.
    183     Len,
    184     /// The first byte did not represent a map of one, two, or three key pairs.
    185     CborHeader,
    186     /// `credProtect` had an invalid value.
    187     CredProtectValue,
    188     /// `hmac-secret` had an invalid value.
    189     HmacSecretValue,
    190     /// `minPinLength` had an invalid value.
    191     MinPinLengthValue,
    192     /// `hmac-secret-mc` was not a byte string with additional info 24.
    193     HmacSecretMcType,
    194     /// `hmac-secret-mc` was not a byte string of length 48 or 80.
    195     HmacSecretMcValue,
    196     /// Fewer extensions existed than expected.
    197     Missing,
    198 }
    199 impl Display for AuthenticatorExtensionOutputErr {
    200     #[inline]
    201     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    202         f.write_str(match *self {
    203             Self::Len => "CBOR authenticator extensions had an invalid length",
    204             Self::CborHeader => "CBOR authenticator extensions did not represent a map of one, two, or three key pairs",
    205             Self::CredProtectValue => "CBOR authenticator extension 'credProtect' had an invalid value",
    206             Self::HmacSecretValue => "CBOR authenticator extension 'hmac-secret' had an invalid value",
    207             Self::MinPinLengthValue => "CBOR authenticator extension 'minPinLength' had an invalid value",
    208             Self::HmacSecretMcType => "CBOR authenticator extension 'hmac-secret-mc' was not a byte string with additional info 24",
    209             Self::HmacSecretMcValue => "CBOR authenticator extension 'hmac-secret-mc' was not a byte string of length 48 or 80",
    210             Self::Missing => "CBOR authenticator extensions had fewer extensions than expected",
    211         })
    212     }
    213 }
    214 impl Error for AuthenticatorExtensionOutputErr {}
    215 /// Error returned in [`AttestedCredentialDataErr::CoseKey`].
    216 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    217 pub enum CoseKeyErr {
    218     /// The `slice` had an invalid length.
    219     Len,
    220     /// The COSE Key type was not `OKP`, `EC2`, or `RSA`.
    221     CoseKeyType,
    222     /// The `slice` was malformed and did not conform to an Ed25519 public key encoded as a COSE Key per
    223     /// [RFC 9052](https://www.rfc-editor.org/rfc/rfc9052) and [RFC 9053](https://www.rfc-editor.org/rfc/rfc9053).
    224     Ed25519CoseEncoding,
    225     /// The `slice` was malformed and did not conform to an ECDSA public key based on curve P-256 and SHA-256
    226     /// encoded as a COSE Key per [RFC 9052](https://www.rfc-editor.org/rfc/rfc9052) and
    227     /// [RFC 9053](https://www.rfc-editor.org/rfc/rfc9053).
    228     P256CoseEncoding,
    229     /// The `slice` was malformed and did not conform to an ECDSA public key based on curve P-384 and SHA-384
    230     /// encoded as a COSE Key per [RFC 9052](https://www.rfc-editor.org/rfc/rfc9052) and
    231     /// [RFC 9053](https://www.rfc-editor.org/rfc/rfc9053).
    232     P384CoseEncoding,
    233     /// The `slice` was malformed and did not conform to an RSASSA-PKCS1-v1.5 public key using SHA-256 encoded as a
    234     /// COSE Key per [RFC 8230](https://www.rfc-editor.org/rfc/rfc8230.html).
    235     RsaCoseEncoding,
    236     /// The RSA public key exponent is too large.
    237     RsaExponentTooLarge,
    238     /// The RSA public key was invalid.
    239     RsaPubKey(RsaPubKeyErr),
    240 }
    241 impl Display for CoseKeyErr {
    242     #[inline]
    243     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    244         match *self {
    245             Self::Len => f.write_str("COSE key data had an invalid length"),
    246             Self::CoseKeyType => f.write_str("COSE key type was not 'OKP', 'EC2', or 'RSA'"),
    247             Self::Ed25519CoseEncoding => f.write_str("Ed25519 COSE key was not encoded correctly"),
    248             Self::P256CoseEncoding => {
    249                 f.write_str("ECDSA with P-256 and SHA-256 COSE key was not encoded correctly")
    250             }
    251             Self::P384CoseEncoding => {
    252                 f.write_str("ECDSA with P-384 and SHA-384 COSE key was not encoded correctly")
    253             }
    254             Self::RsaCoseEncoding => {
    255                 f.write_str("RSASSA-PKCS1-v1.5 using SHA-256 COSE key was not encoded correctly")
    256             }
    257             Self::RsaExponentTooLarge => f.write_str("RSA public key exponent is too large"),
    258             Self::RsaPubKey(err) => err.fmt(f),
    259         }
    260     }
    261 }
    262 impl Error for CoseKeyErr {}
    263 /// Error returned in [`AuthenticatorDataErr::AttestedCredential`].
    264 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    265 pub enum AttestedCredentialDataErr {
    266     /// The `slice` had an invalid length.
    267     Len,
    268     /// Error when the claimed credential ID length is not valid.
    269     CredentialId(CredentialIdErr),
    270     /// Error related to the credential public key.
    271     CoseKey(CoseKeyErr),
    272 }
    273 impl Display for AttestedCredentialDataErr {
    274     #[inline]
    275     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    276         match *self {
    277             Self::Len => f.write_str("attested credential data had an invalid length"),
    278             Self::CredentialId(err) => err.fmt(f),
    279             Self::CoseKey(err) => err.fmt(f),
    280         }
    281     }
    282 }
    283 impl Error for AttestedCredentialDataErr {}
    284 /// Error returned from [`AuthenticatorData::try_from`].
    285 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    286 pub enum AuthenticatorDataErr {
    287     /// The `slice` had an invalid length.
    288     Len,
    289     /// Bit 1 in [`flags`](https://www.w3.org/TR/webauthn-3/#authdata-flags) is not 0.
    290     FlagsBit1Not0,
    291     /// Bit 5 in [`flags`](https://www.w3.org/TR/webauthn-3/#authdata-flags) is not 0.
    292     FlagsBit5Not0,
    293     /// [AT](https://www.w3.org/TR/webauthn-3/#authdata-flags-at) bit was 0.
    294     AttestedCredentialDataNotIncluded,
    295     /// [BE](https://www.w3.org/TR/webauthn-3/#authdata-flags-be) and
    296     /// [BS](https://www.w3.org/TR/webauthn-3/#authdata-flags-bs) bits were 0 and 1 respectively.
    297     BackupWithoutEligibility,
    298     /// Error returned when [`AttestedCredentialData`] is malformed.
    299     AttestedCredential(AttestedCredentialDataErr),
    300     /// Error returned when [`AuthenticatorExtensionOutput`] is malformed.
    301     AuthenticatorExtension(AuthenticatorExtensionOutputErr),
    302     /// [ED](https://www.w3.org/TR/webauthn-3/#authdata-flags-ed) bit was 0, but
    303     /// [`extensions`](https://www.w3.org/TR/webauthn-3/#authdata-extensions) existed.
    304     NoExtensionBitWithData,
    305     /// [ED](https://www.w3.org/TR/webauthn-3/#authdata-flags-ed) bit was 1, but
    306     /// [`extensions`](https://www.w3.org/TR/webauthn-3/#authdata-extensions) did not exist.
    307     ExtensionBitWithoutData,
    308     /// There was data remaining that could not be deserialized.
    309     TrailingData,
    310 }
    311 impl Display for AuthenticatorDataErr {
    312     #[inline]
    313     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    314         match *self {
    315             Self::Len => AuthDataErr::<
    316                 Infallible,
    317                 AttestedCredentialDataErr,
    318                 AuthenticatorExtensionOutputErr,
    319             >::Len
    320                 .fmt(f),
    321             Self::FlagsBit1Not0 => AuthDataErr::<
    322                 Infallible,
    323                 AttestedCredentialDataErr,
    324                 AuthenticatorExtensionOutputErr,
    325             >::FlagsBit1Not0
    326                 .fmt(f),
    327             Self::FlagsBit5Not0 => AuthDataErr::<
    328                 Infallible,
    329                 AttestedCredentialDataErr,
    330                 AuthenticatorExtensionOutputErr,
    331             >::FlagsBit5Not0
    332                 .fmt(f),
    333             Self::AttestedCredentialDataNotIncluded => {
    334                 f.write_str("attested credential data was not included")
    335             }
    336             Self::BackupWithoutEligibility => AuthDataErr::<
    337                 Infallible,
    338                 AttestedCredentialDataErr,
    339                 AuthenticatorExtensionOutputErr,
    340             >::BackupWithoutEligibility
    341                 .fmt(f),
    342             Self::AttestedCredential(err) => err.fmt(f),
    343             Self::AuthenticatorExtension(err) => err.fmt(f),
    344             Self::NoExtensionBitWithData => AuthDataErr::<
    345                 Infallible,
    346                 AttestedCredentialDataErr,
    347                 AuthenticatorExtensionOutputErr,
    348             >::NoExtensionBitWithData
    349                 .fmt(f),
    350             Self::ExtensionBitWithoutData => AuthDataErr::<
    351                 Infallible,
    352                 AttestedCredentialDataErr,
    353                 AuthenticatorExtensionOutputErr,
    354             >::ExtensionBitWithoutData
    355                 .fmt(f),
    356             Self::TrailingData => AuthDataErr::<
    357                 Infallible,
    358                 AttestedCredentialDataErr,
    359                 AuthenticatorExtensionOutputErr,
    360             >::TrailingData
    361                 .fmt(f),
    362         }
    363     }
    364 }
    365 impl Error for AuthenticatorDataErr {}
    366 /// Error returned in [`AttestationObjectErr::Attestation`].
    367 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    368 pub enum AttestationErr {
    369     /// The `slice` had an invalid length.
    370     Len,
    371     /// The attestation format does not exist.
    372     MissingFormat,
    373     /// The attestation format is not supported.
    374     UnsupportedFormat,
    375     /// The attestation statement does not exist.
    376     MissingStatement,
    377     /// [None](https://www.w3.org/TR/webauthn-3/#sctn-none-attestation) has the wrong format.
    378     NoneFormat,
    379     /// [Packed](https://www.w3.org/TR/webauthn-3/#sctn-packed-attestation) was not a map of two or three key-value pairs.
    380     PackedFormat,
    381     /// [Packed](https://www.w3.org/TR/webauthn-3/#sctn-packed-attestation) did not have an algorithm.
    382     PackedFormatMissingAlg,
    383     /// [Packed](https://www.w3.org/TR/webauthn-3/#sctn-packed-attestation) had an unsupported algorithm.
    384     PackedFormatUnsupportedAlg,
    385     /// [Packed](https://www.w3.org/TR/webauthn-3/#sctn-packed-attestation) did not have a signature.
    386     PackedFormatMissingSig,
    387     /// [Packed](https://www.w3.org/TR/webauthn-3/#sctn-packed-attestation) Ed25519 signature CBOR was invalid.
    388     PackedFormatCborEd25519Signature,
    389     /// [Packed](https://www.w3.org/TR/webauthn-3/#sctn-packed-attestation) P-256 signature CBOR was invalid.
    390     PackedFormatCborP256Signature,
    391     /// [Packed](https://www.w3.org/TR/webauthn-3/#sctn-packed-attestation) P-256 signature was invalid.
    392     PackedFormatP256,
    393     /// [Packed](https://www.w3.org/TR/webauthn-3/#sctn-packed-attestation) P-384 signature CBOR was invalid.
    394     PackedFormatCborP384Signature,
    395     /// [Packed](https://www.w3.org/TR/webauthn-3/#sctn-packed-attestation) P-384 signature was invalid.
    396     PackedFormatP384,
    397     /// [Packed](https://www.w3.org/TR/webauthn-3/#sctn-packed-attestation) RS256 signature CBOR was invalid.
    398     PackedFormatCborRs256Signature,
    399     /// [Packed](https://www.w3.org/TR/webauthn-3/#sctn-packed-attestation) RS256 signature was invalid.
    400     PackedFormatRs256,
    401 }
    402 impl Display for AttestationErr {
    403     #[inline]
    404     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    405         f.write_str(match *self {
    406             Self::Len => "CBOR attestation had an invalid length",
    407             Self::MissingFormat => "CBOR attestation did not have an attestation format",
    408             Self::UnsupportedFormat => "CBOR attestation format is not supported",
    409             Self::MissingStatement => "CBOR attestation did not have an attestation statement",
    410             Self::NoneFormat => "CBOR attestation had the wrong format for the none attestation",
    411             Self::PackedFormat => "CBOR attestation had the wrong number of key-value pairs for the packed attestation",
    412             Self::PackedFormatMissingAlg => "CBOR attestation did not have an algorithm for the packed attestation",
    413             Self::PackedFormatUnsupportedAlg => "CBOR attestation had an unsupported algorithm for the packed attestation",
    414             Self::PackedFormatMissingSig => "CBOR attestation did not have a signature for the packed attestation",
    415             Self::PackedFormatCborEd25519Signature => "CBOR attestation Ed25519 signature had the wrong CBOR format for the packed attestation",
    416             Self::PackedFormatCborP256Signature => "CBOR attestation P-256 signature had the wrong CBOR format for the packed attestation",
    417             Self::PackedFormatP256 => "CBOR attestation P-256 signature was invalid for the packed attestation",
    418             Self::PackedFormatCborP384Signature => "CBOR attestation P-384 signature had the wrong CBOR format for the packed attestation",
    419             Self::PackedFormatP384 => "CBOR attestation P-384 signature was invalid for the packed attestation",
    420             Self::PackedFormatCborRs256Signature => "CBOR attestation RS256 signature had the wrong CBOR format for the packed attestation",
    421             Self::PackedFormatRs256 => "CBOR attestation RS256 signature was invalid for the packed attestation",
    422         })
    423     }
    424 }
    425 impl Error for AttestationErr {}
    426 /// Error returned by [`AttestationObject::try_from`].
    427 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    428 pub enum AttestationObjectErr {
    429     /// The `slice` had an invalid length.
    430     Len,
    431     /// The `slice` was not a CBOR map with three key-value pairs.
    432     NotAMapOf3,
    433     /// Error when [`PackedAttestation::signature`] does not match the type of
    434     /// [`AttestedCredentialData::credential_public_key`] when self attestation
    435     /// is used.
    436     SelfAttestationAlgorithmMismatch,
    437     /// The third key was not "authData".
    438     MissingAuthData,
    439     /// `authData` did not have a byte string data type.
    440     AuthDataType,
    441     /// `authData` length with additional info 24 or 25 did not have a conforming length.
    442     AuthDataLenInfo,
    443     /// Error related to the encoding of [`Attestation`].
    444     Attestation(AttestationErr),
    445     /// [`AuthenticatorData`] length did not match the length encoded in the CBOR data.
    446     CborAuthDataLenMismatch,
    447     /// Error from [`AuthenticatorData::try_from`].
    448     AuthData(AuthenticatorDataErr),
    449 }
    450 impl Display for AttestationObjectErr {
    451     #[inline]
    452     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    453         match *self {
    454             Self::Len => f.write_str("CBOR attestation object had an invalid length"),
    455             Self::NotAMapOf3 => {
    456                 f.write_str("CBOR attestation object was not a map of three key-value pairs")
    457             }
    458             Self::MissingAuthData => {
    459                 f.write_str("CBOR attestation object did not have 'authData' as its third key")
    460             }
    461             Self::AuthDataType => {
    462                 f.write_str("CBOR attestation object authenticator data invalid type")
    463             }
    464             Self::AuthDataLenInfo => f.write_str(
    465                 "CBOR attestation object authenticator data had an invalid encoded length",
    466             ),
    467             Self::Attestation(err) => err.fmt(f),
    468             Self::CborAuthDataLenMismatch => f.write_str(
    469                 "CBOR attestation object authenticator data length did not match the CBOR value",
    470             ),
    471             Self::AuthData(err) => err.fmt(f),
    472             Self::SelfAttestationAlgorithmMismatch => f.write_str("CBOR attestation object packed attestation contained a self attestation whose format did not match the type of the public key"),
    473         }
    474     }
    475 }
    476 impl Error for AttestationObjectErr {}
    477 /// Error in [`RegCeremonyErr::Extension`].
    478 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    479 pub enum ExtensionErr {
    480     /// [`ClientExtensionsOutputs::cred_props`] was sent from the client but was not supposed to be.
    481     ForbiddenCredProps,
    482     /// [`ClientExtensionsOutputs::prf`] was sent from the client but was not supposed to be.
    483     ForbiddenPrf,
    484     /// [`AuthenticatorExtensionOutput::cred_protect`] was sent from the client but was not supposed to be.
    485     ForbiddenCredProtect,
    486     /// [`AuthenticatorExtensionOutput::hmac_secret`] was sent from the client but was not supposed to be.
    487     ForbiddenHmacSecret,
    488     /// [`AuthenticatorExtensionOutput::min_pin_length`] was sent from the client but was not supposed to be.
    489     ForbiddenMinPinLength,
    490     /// [`Extension::cred_props`] was requested, but the required response was not sent back.
    491     MissingCredProps,
    492     /// [`Extension::prf`] was requested, but the required response was not sent back.
    493     MissingPrf,
    494     /// [`Extension::cred_protect`] was requested, but the required response was not sent back.
    495     MissingCredProtect,
    496     /// [`Extension::min_pin_length`] was requested, but the required response was not sent back.
    497     MissingMinPinLength,
    498     /// [`Extension::cred_protect`] was requested with the first policy, but the second policy was sent back.
    499     InvalidCredProtectValue(CredProtect, CredentialProtectionPolicy),
    500     /// [`Extension::prf`] was requested, but
    501     /// [`enabled`](https://www.w3.org/TR/webauthn-3/#dom-authenticationextensionsprfoutputs-enabled) was `false`.
    502     InvalidPrfValue,
    503     /// [`Extension::prf`] was requested, but
    504     /// [`hmac-secret`](https://fidoalliance.org/specs/fido-v2.2-rd-20230321/fido-client-to-authenticator-protocol-v2.2-rd-20230321.html#sctn-hmac-secret-extension)
    505     /// was `false`.
    506     InvalidHmacSecretValue,
    507     /// [`Extension::min_pin_length`] was requested, but
    508     /// [`minPinLength`](https://fidoalliance.org/specs/fido-v2.2-rd-20230321/fido-client-to-authenticator-protocol-v2.2-rd-20230321.html#sctn-minpinlength-extension)
    509     /// was sent set to the second value which is strictly less than the required first value.
    510     InvalidMinPinLength(FourToSixtyThree, FourToSixtyThree),
    511 }
    512 impl Display for ExtensionErr {
    513     #[inline]
    514     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    515         match *self {
    516             Self::ForbiddenCredProps => {
    517                 f.write_str("credProps was sent from the client, but it is not allowed")
    518             }
    519             Self::ForbiddenPrf => {
    520                 f.write_str("prf info was sent from the client, but it is not allowed")
    521             }
    522             Self::ForbiddenCredProtect => {
    523                 f.write_str("credProtect was sent from the client, but it is not allowed")
    524             }
    525             Self::ForbiddenHmacSecret => {
    526                 f.write_str("hmac-secret info was sent from the client, but it is not allowed")
    527             }
    528             Self::ForbiddenMinPinLength => {
    529                 f.write_str("minPinLength info was sent from the client, but it is not allowed")
    530             }
    531             Self::MissingCredProps => f.write_str("credProps was not sent from the client"),
    532             Self::MissingPrf => f.write_str("prf was not sent from the client"),
    533             Self::MissingCredProtect => f.write_str("credProtect was not sent from the client"),
    534             Self::MissingMinPinLength => f.write_str("minPinLength was not sent from the client"),
    535             Self::InvalidCredProtectValue(sent, rec) => write!(
    536                 f,
    537                 "credProtect was sent with {sent}, but {rec} was received",
    538             ),
    539             Self::InvalidPrfValue => f.write_str("prf was false"),
    540             Self::InvalidHmacSecretValue => f.write_str("hmac-secret was false"),
    541             Self::InvalidMinPinLength(sent, rec) => write!(
    542                 f,
    543                 "minPinLength was sent, but {rec} is strictly smaller than the required {sent}"
    544             ),
    545         }
    546     }
    547 }
    548 impl Error for ExtensionErr {}
    549 /// Error returned by [`RegistrationServerState::verify`].
    550 #[derive(Debug)]
    551 pub enum RegCeremonyErr {
    552     /// [`PublicKeyCredentialCreationOptions::timeout`] was exceeded.
    553     Timeout,
    554     /// [`AuthenticatorAttestation::client_data_json`] could not be parsed by
    555     /// [`CollectedClientData::from_client_data_json`].
    556     CollectedClientData(CollectedClientDataErr),
    557     /// [`AuthenticatorAttestation::client_data_json`] could not be parsed by
    558     /// [`CollectedClientData::from_client_data_json_relaxed`].
    559     #[cfg_attr(docsrs, doc(cfg(feature = "serde_relaxed")))]
    560     #[cfg(feature = "serde_relaxed")]
    561     CollectedClientDataRelaxed(SerdeJsonErr),
    562     /// [`AuthenticatorAttestation::attestation_object`] could not be parsed into
    563     /// [`AttestationObject`].
    564     AttestationObject(AttestationObjectErr),
    565     /// [`UncompressedPubKey`] was not valid.
    566     PubKey(PubKeyErr),
    567     /// [`PackedAttestation::signature`] was not valid.
    568     AttestationSignature,
    569     /// [`CollectedClientData::origin`] does not match one of the values in
    570     /// [`RegistrationVerificationOptions::allowed_origins`].
    571     OriginMismatch,
    572     /// [`CollectedClientData::cross_origin`] was `true`, but
    573     /// [`RegistrationVerificationOptions::allowed_top_origins`] was `None`.
    574     CrossOrigin,
    575     /// [`CollectedClientData::top_origin`] does not match one of the values in
    576     /// [`RegistrationVerificationOptions::allowed_top_origins`].
    577     TopOriginMismatch,
    578     /// [`PublicKeyCredentialCreationOptions::challenge`] and [`CollectedClientData::challenge`] don't match.
    579     ChallengeMismatch,
    580     /// The SHA-256 hash of [`PublicKeyCredentialCreationOptions::rp_id`] does not match [`AuthenticatorData::rp_id_hash`].
    581     RpIdHashMismatch,
    582     /// [`Flag::user_present`] was `false` despite [`CredentialCreationOptions::mediation`]
    583     /// being something other than [`CredentialMediationRequirement::Conditional`].
    584     UserNotPresent,
    585     /// [`AuthenticatorSelectionCriteria::user_verification`] was set to [`UserVerificationRequirement::Required`],
    586     /// but [`Flag::user_verified`] was `false`.
    587     UserNotVerified,
    588     /// [`Backup::NotEligible`] was not sent back despite [`BackupReq::NotEligible`].
    589     BackupEligible,
    590     /// [`Backup::NotEligible`] was sent back despite [`BackupReq::Eligible`].
    591     BackupNotEligible,
    592     /// [`Backup::Eligible`] was not sent back despite [`BackupReq::EligibleNotExists`].
    593     BackupExists,
    594     /// [`Backup::Exists`] was not sent back despite [`BackupReq::Exists`].
    595     BackupDoesNotExist,
    596     /// [`AuthenticatorAttachment`] was not sent back despite being required.
    597     MissingAuthenticatorAttachment,
    598     /// [`AuthenticatorAttachmentReq::Platform`] or [`AuthenticatorAttachmentReq::CrossPlatform`] was sent
    599     /// but [`AuthenticatorAttachment`] was not the same.
    600     AuthenticatorAttachmentMismatch,
    601     /// Variant returned when there is an issue with [`Extension`]s.
    602     Extension(ExtensionErr),
    603     /// [`PublicKeyCredentialCreationOptions::pub_key_cred_params`] does not contain an algorithm associated with
    604     /// [`AttestedCredentialData::credential_public_key`].
    605     PublicKeyAlgorithmMismatch,
    606     /// Variant returned when [`RegisteredCredential`] cannot be created due to invalid state.
    607     Credential(CredentialErr),
    608 }
    609 impl Display for RegCeremonyErr {
    610     #[inline]
    611     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    612         match *self {
    613             Self::Timeout => CeremonyErr::<AttestationObjectErr>::Timeout.fmt(f),
    614             Self::CollectedClientData(ref err) => write!(f, "clientDataJSON could not be parsed: {err}"),
    615             #[cfg(feature = "serde_relaxed")]
    616             Self::CollectedClientDataRelaxed(ref err) => write!(f, "clientDataJSON could not be parsed: {err}"),
    617             Self::AttestationObject(err) => err.fmt(f),
    618             Self::PubKey(err) => err.fmt(f),
    619             Self::AttestationSignature => AuthRespErr::<AttestationObjectErr>::Signature.fmt(f),
    620             Self::OriginMismatch => CeremonyErr::<AttestationObjectErr>::OriginMismatch.fmt(f),
    621             Self::CrossOrigin => CeremonyErr::<AttestationObjectErr>::CrossOrigin.fmt(f),
    622             Self::TopOriginMismatch => CeremonyErr::<AttestationObjectErr>::TopOriginMismatch.fmt(f),
    623             Self::BackupEligible => CeremonyErr::<AttestationObjectErr>::BackupEligible.fmt(f),
    624             Self::BackupNotEligible => CeremonyErr::<AttestationObjectErr>::BackupNotEligible.fmt(f),
    625             Self::BackupExists => CeremonyErr::<AttestationObjectErr>::BackupExists.fmt(f),
    626             Self::BackupDoesNotExist => CeremonyErr::<AttestationObjectErr>::BackupDoesNotExist.fmt(f),
    627             Self::ChallengeMismatch => CeremonyErr::<AttestationObjectErr>::ChallengeMismatch.fmt(f),
    628             Self::RpIdHashMismatch => CeremonyErr::<AttestationObjectErr>::RpIdHashMismatch.fmt(f),
    629             Self::UserNotPresent => f.write_str("user was not present despite mediation not being conditional"),
    630             Self::UserNotVerified => CeremonyErr::<AttestationObjectErr>::UserNotVerified.fmt(f),
    631             Self::MissingAuthenticatorAttachment => f.write_str("the authenticator attachment modality was not sent despite being required"),
    632             Self::AuthenticatorAttachmentMismatch => f.write_str("the kind of authenticator requested (e.g., platform) was not used"),
    633             Self::Extension(ext) => ext.fmt(f),
    634             Self::PublicKeyAlgorithmMismatch => f.write_str(
    635                 "the allowed public key algorithms does not contain the algorithm sent from the client",
    636             ),
    637             Self::Credential(err) => err.fmt(f),
    638         }
    639     }
    640 }
    641 impl Error for RegCeremonyErr {}