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