error.rs (17015B)
1 #[cfg(feature = "serde_relaxed")] 2 use super::super::SerdeJsonErr; 3 use super::super::{ 4 super::CredentialId, AuthRespErr, AuthenticatorDataErr as AuthDataErr, CeremonyErr, 5 CollectedClientDataErr, PubKeyErr, RpId, 6 }; 7 #[cfg(doc)] 8 use super::{ 9 super::{ 10 super::{ 11 AuthenticatedCredential, DynamicState, StaticState, 12 request::{ 13 UserVerificationRequirement, 14 auth::{ 15 AllowedCredential, AllowedCredentials, AuthenticationVerificationOptions, 16 BackupStateReq, CredentialSpecificExtension, 17 DiscoverableAuthenticationServerState, DiscoverableCredentialRequestOptions, 18 Extension, NonDiscoverableAuthenticationServerState, 19 PublicKeyCredentialRequestOptions, 20 }, 21 }, 22 }, 23 Backup, 24 register::CredentialProtectionPolicy, 25 }, 26 Authentication, AuthenticatorAssertion, AuthenticatorAttachment, AuthenticatorData, 27 AuthenticatorExtensionOutput, CollectedClientData, CompressedPubKeyBorrowed, Flag, HmacSecret, 28 Signature, UserHandle, 29 }; 30 use core::{ 31 convert::Infallible, 32 error::Error, 33 fmt::{self, Display, Formatter}, 34 }; 35 /// Error returned in [`AuthenticatorDataErr::AuthenticatorExtension`]. 36 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 37 pub enum AuthenticatorExtensionOutputErr { 38 /// The `slice` had an invalid length. 39 Len, 40 /// The first byte did not represent a map of one key pair. 41 CborHeader, 42 /// `hmac-secret` was not a byte string with additional info 24. 43 HmacSecretType, 44 /// `hmac-secret` was not a byte string of length 48 or 80. 45 HmacSecretValue, 46 /// An unsupported extension existed. 47 Unsupported, 48 /// Fewer extensions existed than expected. 49 Missing, 50 } 51 impl Display for AuthenticatorExtensionOutputErr { 52 #[inline] 53 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 54 f.write_str(match *self { 55 Self::Len => "CBOR authenticator extensions had an invalid length", 56 Self::CborHeader => { 57 "CBOR authenticator extensions did not represent a map of one key pair" 58 } 59 Self::HmacSecretType => "CBOR authenticator extension 'hmac-secret' was not a byte string with additional info 24", 60 Self::HmacSecretValue => "CBOR authenticator extension 'hmac-secret' was not a byte string of length 48 or 80", 61 Self::Unsupported => "CBOR authenticator extension had an unsupported extension", 62 Self::Missing => "CBOR authenticator extensions had fewer extensions than expected", 63 }) 64 } 65 } 66 impl Error for AuthenticatorExtensionOutputErr {} 67 /// Error returned from [`AuthenticatorData::try_from`]. 68 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 69 pub enum AuthenticatorDataErr { 70 /// The `slice` had an invalid length. 71 Len, 72 /// [`Flag::user_present`] was `false`. 73 UserNotPresent, 74 /// Bit 1 in [`flags`](https://www.w3.org/TR/webauthn-3/#authdata-flags) is not 0. 75 FlagsBit1Not0, 76 /// Bit 5 in [`flags`](https://www.w3.org/TR/webauthn-3/#authdata-flags) is not 0. 77 FlagsBit5Not0, 78 /// [AT](https://www.w3.org/TR/webauthn-3/#authdata-flags-at) was 1. 79 AttestedCredentialDataIncluded, 80 /// [BE](https://www.w3.org/TR/webauthn-3/#authdata-flags-be) and 81 /// [BS](https://www.w3.org/TR/webauthn-3/#authdata-flags-bs) bits were 0 and 1 respectively. 82 BackupWithoutEligibility, 83 /// Error returned when [`AuthenticatorExtensionOutput`] is malformed. 84 AuthenticatorExtension(AuthenticatorExtensionOutputErr), 85 /// [ED](https://www.w3.org/TR/webauthn-3/#authdata-flags-ed) bit was 0, but 86 /// [`extensions`](https://www.w3.org/TR/webauthn-3/#authdata-extensions) existed. 87 NoExtensionBitWithData, 88 /// [ED](https://www.w3.org/TR/webauthn-3/#authdata-flags-ed) bit was 1, but 89 /// [`extensions`](https://www.w3.org/TR/webauthn-3/#authdata-extensions) did not exist. 90 ExtensionBitWithoutData, 91 /// There was data remaining that could not be deserialized. 92 TrailingData, 93 } 94 impl Display for AuthenticatorDataErr { 95 #[inline] 96 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 97 match *self { 98 Self::Len => AuthDataErr::<(), Infallible, AuthenticatorExtensionOutputErr>::Len.fmt(f), 99 Self::UserNotPresent => f.write_str("the user was not present"), 100 Self::FlagsBit1Not0 => { 101 AuthDataErr::<(), Infallible, AuthenticatorExtensionOutputErr>::FlagsBit1Not0.fmt(f) 102 } 103 Self::FlagsBit5Not0 => { 104 AuthDataErr::<(), Infallible, AuthenticatorExtensionOutputErr>::FlagsBit5Not0.fmt(f) 105 } 106 Self::AttestedCredentialDataIncluded => { 107 f.write_str("attested credential data was included") 108 } 109 Self::BackupWithoutEligibility => AuthDataErr::< 110 (), 111 Infallible, 112 AuthenticatorExtensionOutputErr, 113 >::BackupWithoutEligibility 114 .fmt(f), 115 Self::AuthenticatorExtension(err) => err.fmt(f), 116 Self::NoExtensionBitWithData => AuthDataErr::< 117 (), 118 Infallible, 119 AuthenticatorExtensionOutputErr, 120 >::NoExtensionBitWithData 121 .fmt(f), 122 Self::ExtensionBitWithoutData => AuthDataErr::< 123 (), 124 Infallible, 125 AuthenticatorExtensionOutputErr, 126 >::ExtensionBitWithoutData 127 .fmt(f), 128 Self::TrailingData => { 129 AuthDataErr::<(), Infallible, AuthenticatorExtensionOutputErr>::TrailingData.fmt(f) 130 } 131 } 132 } 133 } 134 impl Error for AuthenticatorDataErr {} 135 /// One or two. 136 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 137 pub enum OneOrTwo { 138 /// One. 139 One, 140 /// Two. 141 Two, 142 } 143 impl Display for OneOrTwo { 144 #[inline] 145 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 146 f.write_str(match *self { 147 Self::One => "one", 148 Self::Two => "two", 149 }) 150 } 151 } 152 /// Error in [`AuthCeremonyErr::Extension`]. 153 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 154 pub enum ExtensionErr { 155 /// [`AuthenticatorExtensionOutput::hmac_secret`] was sent from the client, but [`Flag::user_verified`] 156 /// was `false`. 157 /// 158 /// Note this is only possible iff [`PublicKeyCredentialRequestOptions::user_verification`] is not 159 /// [`UserVerificationRequirement::Required`], [`Extension::prf`] is `None`, 160 /// [`CredentialSpecificExtension::prf`] is `None`, and 161 /// [`AuthenticationVerificationOptions::error_on_unsolicited_extensions`] is `false`. 162 UserNotVerifiedHmacSecret, 163 /// [`AuthenticatorExtensionOutput::hmac_secret`] was sent from the client but was not supposed to be. 164 ForbiddenHmacSecret, 165 /// [`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) 166 /// was received for a credential that does not support it. 167 HmacSecretForNonHmacSecretCredential, 168 /// [`Extension::prf`] was requested for a PRF-capable credential that is based on the 169 /// [`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) 170 /// extension, but the required response was not sent back. 171 MissingHmacSecret, 172 /// [`Extension::prf`] was requested with the first number of PRF inputs, but the second number of 173 /// [`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) 174 /// outputs were sent for a PRF-capable credential that is based on the `hmac-secret` extension. 175 InvalidHmacSecretValue(OneOrTwo, OneOrTwo), 176 } 177 impl Display for ExtensionErr { 178 #[inline] 179 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 180 match *self { 181 Self::UserNotVerifiedHmacSecret => { 182 f.write_str("user was not verified but hmac-secret info was sent from the client") 183 } 184 Self::ForbiddenHmacSecret => { 185 f.write_str("hmac-secret info was sent from the client, but it is not allowed") 186 } 187 Self::HmacSecretForNonHmacSecretCredential => f.write_str( 188 "hmac-secret info was sent from the client, but the credential does not support it", 189 ), 190 Self::MissingHmacSecret => f.write_str("hmac-secret was not sent from the client"), 191 Self::InvalidHmacSecretValue(sent, recv) => write!( 192 f, 193 "{sent} PRF input(s) were sent, but {recv} hmac-secret output(s) were received" 194 ), 195 } 196 } 197 } 198 impl Error for ExtensionErr {} 199 /// Error returned by [`DiscoverableAuthenticationServerState::verify`] and 200 /// [`NonDiscoverableAuthenticationServerState::verify`]. 201 #[derive(Debug)] 202 pub enum AuthCeremonyErr { 203 /// [`PublicKeyCredentialRequestOptions::timeout`] was exceeded. 204 Timeout, 205 /// [`AuthenticatorAssertion::client_data_json`] could not be parsed by 206 /// [`CollectedClientData::from_client_data_json`]. 207 CollectedClientData(CollectedClientDataErr), 208 /// [`AuthenticatorAssertion::client_data_json`] could not be parsed by 209 /// [`CollectedClientData::from_client_data_json_relaxed`]. 210 #[cfg(feature = "serde_relaxed")] 211 CollectedClientDataRelaxed(SerdeJsonErr), 212 /// [`AuthenticatorAssertion::authenticator_data`] could not be parsed into an 213 /// [`AuthenticatorData`]. 214 AuthenticatorData(AuthenticatorDataErr), 215 /// [`CompressedPubKeyBorrowed`] was not valid. 216 PubKey(PubKeyErr), 217 /// [`CompressedPubKeyBorrowed`] was not able to verify [`AuthenticatorAssertion::signature`]. 218 AssertionSignature, 219 /// [`CollectedClientData::origin`] does not match one of the values in 220 /// [`AuthenticationVerificationOptions::allowed_origins`]. 221 OriginMismatch, 222 /// [`CollectedClientData::cross_origin`] was `true`, but 223 /// [`AuthenticationVerificationOptions::allowed_top_origins`] was `None`. 224 CrossOrigin, 225 /// [`CollectedClientData::top_origin`] does not match one of the values in 226 /// [`AuthenticationVerificationOptions::allowed_top_origins`]. 227 TopOriginMismatch, 228 /// [`PublicKeyCredentialRequestOptions::challenge`] and [`CollectedClientData::challenge`] don't match. 229 ChallengeMismatch, 230 /// The SHA-256 hash of the [`RpId`] does not match [`AuthenticatorData::rp_id_hash`]. 231 RpIdHashMismatch, 232 /// [`PublicKeyCredentialRequestOptions::user_verification`] was set to 233 /// [`UserVerificationRequirement::Required`], but [`Flag::user_verified`] was `false`. 234 UserNotVerified, 235 /// [`Backup::Eligible`] was sent back despite the credential not being eligible to be backed up. 236 BackupEligible, 237 /// [`Backup::NotEligible`] was sent back despite the credential being eligible to be backed up. 238 BackupNotEligible, 239 /// [`Backup::Exists`] was sent back despite [`BackupStateReq::DoesntExist`]. 240 BackupExists, 241 /// [`Backup::Eligible`] was sent back despite [`BackupStateReq::Exists`]. 242 BackupDoesNotExist, 243 /// [`AuthenticatorAttachment`] was not sent back despite being required. 244 MissingAuthenticatorAttachment, 245 /// [`AuthenticatorAttachment`] modality changed despite it being forbidden to do so. 246 AuthenticatorAttachmentMismatch, 247 /// Variant returned when there is an issue with [`Extension`]s. 248 Extension(ExtensionErr), 249 /// [`AuthenticatorData::sign_count`] was not strictly greater than [`DynamicState::sign_count`]. 250 SignatureCounter, 251 /// [`AuthenticatorAssertion::user_handle`] did not match [`AuthenticatedCredential::user_id`]. 252 UserHandleMismatch, 253 /// [`Authentication::raw_id`] did not match [`AuthenticatedCredential::id`]. 254 CredentialIdMismatch, 255 /// [`AllowedCredentials`] did not have a matching [`CredentialId`] as 256 /// [`Authentication::raw_id`]. 257 NoMatchingAllowedCredential, 258 /// [`AllowedCredentials`] is empty (i.e., a discoverable request was issued), but 259 /// [`AuthenticatorAssertion::user_handle`] was [`None`]. 260 MissingUserHandle, 261 /// [`Flag::user_verified`] was `false`, but the credential has 262 /// [`CredentialProtectionPolicy::UserVerificationRequired`]. 263 UserNotVerifiedCredProtectRequired, 264 /// [`DiscoverableCredentialRequestOptions`] was sent but the credential has 265 /// [`CredentialProtectionPolicy::UserVerificationOptionalWithCredentialIdList`]. 266 DiscoverableCredProtectCredentialIdList, 267 } 268 impl Display for AuthCeremonyErr { 269 #[inline] 270 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 271 match *self { 272 Self::Timeout => CeremonyErr::<AuthenticatorDataErr>::Timeout.fmt(f), 273 Self::CollectedClientData(ref err) => write!(f, "clientDataJSON could not be parsed: {err}"), 274 #[cfg(feature = "serde_relaxed")] 275 Self::CollectedClientDataRelaxed(ref err) => write!(f, "clientDataJSON could not be parsed: {err}"), 276 Self::AuthenticatorData(err) => err.fmt(f), 277 Self::PubKey(err) => err.fmt(f), 278 Self::AssertionSignature => AuthRespErr::<AuthenticatorDataErr>::Signature.fmt(f), 279 Self::OriginMismatch => CeremonyErr::<AuthenticatorDataErr>::OriginMismatch.fmt(f), 280 Self::CrossOrigin => CeremonyErr::<AuthenticatorDataErr>::CrossOrigin.fmt(f), 281 Self::TopOriginMismatch => CeremonyErr::<AuthenticatorDataErr>::TopOriginMismatch.fmt(f), 282 Self::BackupEligible => CeremonyErr::<AuthenticatorDataErr>::BackupEligible.fmt(f), 283 Self::BackupNotEligible => CeremonyErr::<AuthenticatorDataErr>::BackupNotEligible.fmt(f), 284 Self::BackupExists => CeremonyErr::<AuthenticatorDataErr>::BackupExists.fmt(f), 285 Self::BackupDoesNotExist => CeremonyErr::<AuthenticatorDataErr>::BackupDoesNotExist.fmt(f), 286 Self::ChallengeMismatch => CeremonyErr::<AuthenticatorDataErr>::ChallengeMismatch.fmt(f), 287 Self::RpIdHashMismatch => CeremonyErr::<AuthenticatorDataErr>::RpIdHashMismatch.fmt(f), 288 Self::UserNotVerified => CeremonyErr::<AuthenticatorDataErr>::UserNotVerified.fmt(f), 289 Self::MissingAuthenticatorAttachment=> f.write_str( 290 "authenticator attachment was not sent back despite being required", 291 ), 292 Self::AuthenticatorAttachmentMismatch => f.write_str( 293 "authenticator attachment modality changed despite not being allowed to", 294 ), 295 Self::Extension(err) => err.fmt(f), 296 Self::SignatureCounter => f.write_str( 297 "the signature counter sent back is not strictly greater than the previous counter", 298 ), 299 Self::UserHandleMismatch => f.write_str("the user handle does not match"), 300 Self::CredentialIdMismatch => f.write_str("the credential ID does not match"), 301 Self::NoMatchingAllowedCredential => f.write_str("none of the credentials used to start the non-discoverable request have the same Credential ID as the credential used to finish the ceremony"), 302 Self::MissingUserHandle => f.write_str("the credential used to finish the ceremony did not have a user handle despite a discoverable request being issued"), 303 Self::UserNotVerifiedCredProtectRequired => f.write_str("the credential requires user verification, but the user was not verified"), 304 Self::DiscoverableCredProtectCredentialIdList => f.write_str("the credential requires user verification or to be used for non-discoverable requests, but a discoverable request was used and the user was not verified"), 305 } 306 } 307 } 308 impl Error for AuthCeremonyErr {} 309 /// [`UnknownCredentialOptions`](https://www.w3.org/TR/webauthn-3/#dictdef-unknowncredentialoptions). 310 /// 311 /// This can be sent to the client when an authentication ceremony fails due to an unknown [`CredentialId`]. This 312 /// can be due to the user deleting a credential on the RP's side but not deleting it on the authenticator. This 313 /// response can be forwarded to the authenticator which can subsequently delete the credential. 314 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 315 pub struct UnknownCredentialOptions<'rp, 'cred> { 316 /// [`rpId`](https://www.w3.org/TR/webauthn-3/#dictdef-unknowncredentialoptions-rpid). 317 pub rp_id: &'rp RpId, 318 /// [`credentialId`](https://www.w3.org/TR/webauthn-3/#dictdef-unknowncredentialoptions-credentialid). 319 pub credential_id: CredentialId<&'cred [u8]>, 320 } 321 /// Error when a [`UserHandle`] does not exist that is required to. 322 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 323 pub struct MissingUserHandleErr; 324 impl Display for MissingUserHandleErr { 325 #[inline] 326 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 327 f.write_str("user handle does not exist") 328 } 329 } 330 impl Error for MissingUserHandleErr {}