1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
//! Possible errors that may occur during Webauthn Operation processing

use base64::DecodeError as b64DecodeError;
use openssl::error::ErrorStack as OpenSSLErrorStack;
use serde_cbor::error::Error as CBORError;
use serde_json::error::Error as JSONError;
// use serde::{Deserialize, Serialize};
// use nom::Err as NOMError;

/// A wrapper for `Result<T, WebauthnError>`
pub type WebauthnResult<T> = core::result::Result<T, WebauthnError>;

/// Possible errors that may occur during Webauthn Operation processing.
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum WebauthnError {
    #[error("The configuration was invalid")]
    Configuration,

    #[error("The JSON from the client did not indicate webauthn.<method> correctly")]
    InvalidClientDataType,

    #[error(
        "The client response challenge differs from the latest challenge issued to the userId"
    )]
    MismatchedChallenge,

    #[error("There are no challenges associated to the UserId")]
    ChallengeNotFound,

    #[error("The clients relying party origin does not match our servers information")]
    InvalidRPOrigin,

    #[error("The clients relying party id hash does not match the hash of our relying party id")]
    InvalidRPIDHash,

    #[error("The user present bit is not set, and required")]
    UserNotPresent,

    #[error("The user verified bit is not set, and required by policy")]
    UserNotVerified,

    #[error("The extensions are unknown to this server")]
    InvalidExtensions,

    #[error("An extension for this identifier was not in the authenticator data")]
    AuthenticatorDataMissingExtension,

    #[error("The required attestation data is not present in the response")]
    MissingAttestationCredentialData,

    #[error("The attestation format requested is not able to be processed by this server - please report an issue to add the attestation format")]
    AttestationNotSupported,

    #[error("A failure occurred in persisting the Challenge data")]
    ChallengePersistenceError,

    #[error("The attestation statement map is not valid")]
    AttestationStatementMapInvalid,

    #[error("The attestation statement response is not present")]
    AttestationStatementResponseMissing,

    #[error("The attestation statement response is not valid")]
    AttestationStatementResponseInvalid,

    #[error("The attestation statement signature is not present")]
    AttestationStatementSigMissing,

    #[error("The attestation statement signature is not valid")]
    AttestationStatementSigInvalid,

    #[error("The attestation statement version is not present")]
    AttestationStatementVerMissing,

    #[error("The attestation statement version is not valid")]
    AttestationStatementVerInvalid,

    #[error("The attestation statement version not supported")]
    AttestationStatementVerUnsupported,

    #[error("The attestation statement x5c (trust root) is not present")]
    AttestationStatementX5CMissing,

    #[error("The attestation statement x5c (trust root) is not valid")]
    AttestationStatementX5CInvalid,

    #[error("The attestation statement algorithm is not present")]
    AttestationStatementAlgMissing,

    #[error("The attestation statement certInfo is not present")]
    AttestationStatementCertInfoMissing,

    #[error("A required extension was not in the attestation statement")]
    AttestationStatementMissingExtension,

    #[error("The attestation statement pubArea is not present")]
    AttestationStatementPubAreaMissing,

    #[error("The attestation statement alg does not match algorithm of the credentialPublicKey in authenticatorData")]
    AttestationStatementAlgMismatch,

    #[error("The attestation statement alg does not match algorithm of the credentialPublicKey in authenticatorData")]
    AttestationStatementAlgInvalid,

    #[error("The attestation trust could not be established")]
    AttestationTrustFailure,

    #[error("The attestation Certificate's OID 1.3.6.1.4.1.45724.1.1.4 aaguid does not match the aaguid of the token")]
    AttestationCertificateAAGUIDMismatch,

    #[error("The attestation Certificate's OID 1.2.840.113635.100.8.2 value does not match the computed nonce")]
    AttestationCertificateNonceMismatch,

    #[error("The attestation created by the TPM is not correct")]
    AttestationTpmStInvalid,

    #[error("The TPM attestation and key algorithms do not match")]
    AttestationTpmPubAreaMismatch,

    #[error("The TPM attestation extraData is missing or invalid")]
    AttestationTpmExtraDataInvalid,

    #[error("The TPM attestation extraData does not match the hash of the verification data")]
    AttestationTpmExtraDataMismatch,

    #[error("The TPM requested hash over pubArea is unknown")]
    AttestationTpmPubAreaHashUnknown,

    #[error("The TPM requested hash over pubArea is invalid")]
    AttestationTpmPubAreaHashInvalid,

    #[error("The TPM attest certify structure is invalid")]
    AttestationTpmAttestCertifyInvalid,

    #[error("The requirements of https://w3c.github.io/webauthn/#sctn-packed-attestation-cert-requirements are not met by this attestation certificate")]
    AttestationCertificateRequirementsNotMet,

    #[error("The provided list of CA's for attestation is empty, allowing no trust path to be established")]
    AttestationCertificateTrustStoreEmpty,

    #[error("The leaf certificate we intented to verify is missing.")]
    AttestationLeafCertMissing,

    #[error("The attestation was parsed, but is not a format valid for CA chain validation")]
    AttestationNotVerifiable,

    #[error(
        "The attestation was parsed, but is not trusted by one of the selected CA certificates"
    )]
    AttestationChainNotTrusted(String),

    #[error("The X5C trust root is not a valid algorithm for signing")]
    CertificatePublicKeyInvalid,

    #[error("A base64 parser failure has occurred")]
    ParseBase64Failure(#[from] b64DecodeError),

    #[error("A CBOR parser failure has occurred")]
    ParseCBORFailure(#[from] CBORError),

    #[error("A JSON parser failure has occurred")]
    ParseJSONFailure(#[from] JSONError),

    #[error("A NOM parser failure has occurred")]
    ParseNOMFailure,

    #[error("In parsing the attestation object, there was insufficient data")]
    ParseInsufficientBytesAvailable,

    #[error("An OpenSSL Error has occurred")]
    OpenSSLError(#[from] OpenSSLErrorStack),

    #[error("The requested OpenSSL curve is not supported by OpenSSL")]
    OpenSSLErrorNoCurveName,

    #[error("The COSEKey contains invalid CBOR which can not be processed")]
    COSEKeyInvalidCBORValue,

    #[error("The COSEKey type is not supported by this implementation")]
    COSEKeyInvalidType,

    #[error("ED25519 and ED448 keys are not supported by this implementation")]
    COSEKeyEDUnsupported,

    #[error("The COSEKey contains invalid ECDSA X/Y coordinate data")]
    COSEKeyECDSAXYInvalid,

    #[error("The COSEKey contains invalid RSA modulus/exponent data")]
    COSEKeyRSANEInvalid,

    #[error("The COSEKey uses a curve that is not supported by this implementation")]
    COSEKeyECDSAInvalidCurve,

    #[error("The COSEKey contains invalid EDDSA X coordinate data")]
    COSEKeyEDDSAXInvalid,

    #[error("The COSEKey uses a curve that is not supported by this implementation")]
    COSEKeyEDDSAInvalidCurve,

    #[error("The COSEKey contains invalid cryptographic algorithm request")]
    COSEKeyInvalidAlgorithm,

    #[error("The credential may be a passkey and not truly bound to hardware.")]
    CredentialMayNotBeHardwareBound,

    #[error("The credential uses insecure cryptographic routines and is not trusted")]
    CredentialInsecureCryptography,

    #[error("The credential exist check failed")]
    CredentialExistCheckError,

    #[error("The credential already exists")]
    CredentialAlreadyExists,

    #[error("The credential was not able to be persisted")]
    CredentialPersistenceError,

    #[error("The credential was not able to be retrieved")]
    CredentialRetrievalError,

    #[error("The credential requested could not be found")]
    CredentialNotFound,

    #[error("A credential alg that was not allowed in the request was attempted.")]
    CredentialAlteredAlgFromRequest,

    #[error("A credential that was excluded in the request attempted to register.")]
    CredentialExcludedFromRequest,

    #[error("The credential may have be compromised and should be inspected")]
    CredentialPossibleCompromise,

    #[error("The credential counter could not be updated")]
    CredentialCounterUpdateFailure,

    #[error("The provided call back failed to allow reporting the credential failure")]
    CredentialCompromiseReportFailure,

    #[error("The backup (passkey) elligibility of this device has changed, meaning it must be re-enrolled for security validation")]
    CredentialBackupElligibilityInconsistent,

    #[error("The trust path could not be established")]
    TrustFailure,

    #[error("Authentication has failed")]
    AuthenticationFailure,

    #[error("Inconsistent Credential Verification and User Verification Policy")]
    InconsistentUserVerificationPolicy,

    #[error("Invalid User Name supplied for registration")]
    InvalidUsername,

    #[error("Invalid UserID supplied during authentication")]
    InvalidUserUniqueId,

    #[error("Supplied Nid does not correspond to a supported ECDSA curve")]
    ECDSACurveInvalidNid,

    #[error("The attested credential public key and subject public key do not match")]
    AttestationCredentialSubjectKeyMismatch,

    #[error(
        "The credential was created in a cross-origin context (while cross-origin was disallowed)"
    )]
    CredentialCrossOrigin,

    #[error("The attestation ca list can not be empty")]
    MissingAttestationCaList,
}

impl PartialEq for WebauthnError {
    fn eq(&self, other: &Self) -> bool {
        std::mem::discriminant(self) == std::mem::discriminant(other)
    }
}