Skip to content

Commit e582e2c

Browse files
feat: refactor errors
1 parent 961325b commit e582e2c

18 files changed

+85
-71
lines changed

metadata/const.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ const (
2020
)
2121

2222
var (
23-
errIntermediateCertRevoked = &MetadataError{
23+
errIntermediateCertRevoked = &Error{
2424
Type: "intermediate_revoked",
2525
Details: "Intermediate certificate is on issuers revocation list",
2626
}
27-
errLeafCertRevoked = &MetadataError{
27+
errLeafCertRevoked = &Error{
2828
Type: "leaf_revoked",
2929
Details: "Leaf certificate is on issuers revocation list",
3030
}
31-
errCRLUnavailable = &MetadataError{
31+
errCRLUnavailable = &Error{
3232
Type: "crl_unavailable",
3333
Details: "Certificate revocation list is unavailable",
3434
}

metadata/metadata_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func TestConformanceMetadataTOCParsing(t *testing.T) {
8282
var (
8383
res *http.Response
8484
blob *PayloadJSON
85-
me *MetadataError
85+
me *Error
8686
)
8787

8888
for _, endpoint := range endpoints {

metadata/status.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,17 @@ func ValidateStatusReports(reports []StatusReport, desired, undesired []Authenti
4444
case len(present) == 0 && len(absent) == 0:
4545
return nil
4646
case len(present) != 0 && len(absent) == 0:
47-
return &MetadataError{
47+
return &Error{
4848
Type: "invalid_status",
4949
Details: fmt.Sprintf("The following undesired status reports were present: %s", strings.Join(present, ", ")),
5050
}
5151
case len(present) == 0 && len(absent) != 0:
52-
return &MetadataError{
52+
return &Error{
5353
Type: "invalid_status",
5454
Details: fmt.Sprintf("The following desired status reports were absent: %s", strings.Join(absent, ", ")),
5555
}
5656
default:
57-
return &MetadataError{
57+
return &Error{
5858
Type: "invalid_status",
5959
Details: fmt.Sprintf("The following undesired status reports were present: %s; the following desired status reports were absent: %s", strings.Join(present, ", "), strings.Join(absent, ", ")),
6060
}

metadata/types.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ const (
299299
ALG_KEY_COSE PublicKeyAlgAndEncoding = "cose"
300300
)
301301

302-
type MetadataError struct {
302+
type Error struct {
303303
// Short name for the type of error that has occurred.
304304
Type string `json:"type"`
305305

@@ -310,8 +310,8 @@ type MetadataError struct {
310310
DevInfo string `json:"debug"`
311311
}
312312

313-
func (err *MetadataError) Error() string {
314-
return err.Details
313+
func (e *Error) Error() string {
314+
return e.Details
315315
}
316316

317317
// Clock is an interface used to implement clock functionality in various metadata areas.

protocol/assertion.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func ParseCredentialRequestResponseBody(body io.Reader) (par *ParsedCredentialAs
6969
var car CredentialAssertionResponse
7070

7171
if err = decodeBody(body, &car); err != nil {
72-
return nil, ErrBadRequest.WithDetails("Parse error for Assertion").WithInfo(err.Error())
72+
return nil, ErrBadRequest.WithDetails("Parse error for Assertion").WithInfo(err.Error()).WithError(err)
7373
}
7474

7575
return car.Parse()
@@ -81,7 +81,7 @@ func ParseCredentialRequestResponseBytes(data []byte) (par *ParsedCredentialAsse
8181
var car CredentialAssertionResponse
8282

8383
if err = decodeBytes(data, &car); err != nil {
84-
return nil, ErrBadRequest.WithDetails("Parse error for Assertion").WithInfo(err.Error())
84+
return nil, ErrBadRequest.WithDetails("Parse error for Assertion").WithInfo(err.Error()).WithError(err)
8585
}
8686

8787
return car.Parse()
@@ -97,7 +97,7 @@ func (car CredentialAssertionResponse) Parse() (par *ParsedCredentialAssertionDa
9797
}
9898

9999
if _, err = base64.RawURLEncoding.DecodeString(car.ID); err != nil {
100-
return nil, ErrBadRequest.WithDetails("CredentialAssertionResponse with ID not base64url encoded")
100+
return nil, ErrBadRequest.WithDetails("CredentialAssertionResponse with ID not base64url encoded").WithError(err)
101101
}
102102

103103
if car.Type != string(PublicKeyCredentialType) {
@@ -129,7 +129,7 @@ func (car CredentialAssertionResponse) Parse() (par *ParsedCredentialAssertionDa
129129
}
130130

131131
if err = par.Response.AuthenticatorData.Unmarshal(car.AssertionResponse.AuthenticatorData); err != nil {
132-
return nil, ErrParsingData.WithDetails("Error unmarshalling auth data")
132+
return nil, ErrParsingData.WithDetails("Error unmarshalling auth data").WithError(err)
133133
}
134134

135135
return par, nil
@@ -189,12 +189,12 @@ func (p *ParsedCredentialAssertionData) Verify(storedChallenge string, relyingPa
189189
}
190190

191191
if err != nil {
192-
return ErrAssertionSignature.WithDetails(fmt.Sprintf("Error parsing the assertion public key: %+v", err))
192+
return ErrAssertionSignature.WithDetails(fmt.Sprintf("Error parsing the assertion public key: %+v", err)).WithError(err)
193193
}
194194

195195
valid, err := webauthncose.VerifySignature(key, sigData, p.Response.Signature)
196196
if !valid || err != nil {
197-
return ErrAssertionSignature.WithDetails(fmt.Sprintf("Error validating the assertion signature: %+v", err))
197+
return ErrAssertionSignature.WithDetails(fmt.Sprintf("Error validating the assertion signature: %+v", err)).WithError(err)
198198
}
199199

200200
return nil

protocol/attestation.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,18 @@ func (ccr *AuthenticatorAttestationResponse) Parse() (p *ParsedAttestationRespon
9494
p = &ParsedAttestationResponse{}
9595

9696
if err = json.Unmarshal(ccr.ClientDataJSON, &p.CollectedClientData); err != nil {
97-
return nil, ErrParsingData.WithInfo(err.Error())
97+
return nil, ErrParsingData.WithInfo(err.Error()).WithError(err)
9898
}
9999

100100
if err = webauthncbor.Unmarshal(ccr.AttestationObject, &p.AttestationObject); err != nil {
101-
return nil, ErrParsingData.WithInfo(err.Error())
101+
return nil, ErrParsingData.WithInfo(err.Error()).WithError(err)
102102
}
103103

104104
// Step 8. Perform CBOR decoding on the attestationObject field of the AuthenticatorAttestationResponse
105105
// structure to obtain the attestation statement format fmt, the authenticator data authData, and
106106
// the attestation statement attStmt.
107107
if err = p.AttestationObject.AuthData.Unmarshal(p.AttestationObject.RawAuthData); err != nil {
108-
return nil, fmt.Errorf("error decoding auth data: %v", err)
108+
return nil, err
109109
}
110110

111111
if !p.AttestationObject.AuthData.Flags.HasAttestedCredentialData() {
@@ -176,7 +176,7 @@ func (a *AttestationObject) VerifyAttestation(clientDataHash []byte, mds metadat
176176

177177
if len(a.AuthData.AttData.AAGUID) != 0 {
178178
if aaguid, err = uuid.FromBytes(a.AuthData.AttData.AAGUID); err != nil {
179-
return ErrInvalidAttestation.WithInfo("Error occurred parsing AAGUID during attestation validation").WithDetails(err.Error())
179+
return ErrInvalidAttestation.WithInfo("Error occurred parsing AAGUID during attestation validation").WithDetails(err.Error()).WithError(err)
180180
}
181181
}
182182

@@ -187,7 +187,7 @@ func (a *AttestationObject) VerifyAttestation(clientDataHash []byte, mds metadat
187187
var protoErr *Error
188188

189189
if protoErr = ValidateMetadata(context.Background(), mds, aaguid, attestationType, x5cs); protoErr != nil {
190-
return ErrInvalidAttestation.WithInfo(fmt.Sprintf("Error occurred validating metadata during attestation validation: %+v", protoErr)).WithDetails(protoErr.DevInfo)
190+
return ErrInvalidAttestation.WithInfo(fmt.Sprintf("Error occurred validating metadata during attestation validation: %+v", protoErr)).WithDetails(protoErr.DevInfo).WithError(protoErr)
191191
}
192192

193193
return nil

protocol/attestation_androidkey.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,25 +65,25 @@ func verifyAndroidKeyFormat(att AttestationObject, clientDataHash []byte, _ meta
6565

6666
attCert, err := x509.ParseCertificate(attCertBytes)
6767
if err != nil {
68-
return "", nil, ErrAttestationFormat.WithDetails(fmt.Sprintf("Error parsing certificate from ASN.1 data: %+v", err))
68+
return "", nil, ErrAttestationFormat.WithDetails(fmt.Sprintf("Error parsing certificate from ASN.1 data: %+v", err)).WithError(err)
6969
}
7070

7171
coseAlg := webauthncose.COSEAlgorithmIdentifier(alg)
7272
if err = attCert.CheckSignature(webauthncose.SigAlgFromCOSEAlg(coseAlg), signatureData, sig); err != nil {
73-
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Signature validation error: %+v\n", err))
73+
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Signature validation error: %+v\n", err)).WithError(err)
7474
}
7575

7676
// Verify that the public key in the first certificate in x5c matches the credentialPublicKey in the attestedCredentialData in authenticatorData.
7777
pubKey, err := webauthncose.ParsePublicKey(att.AuthData.AttData.CredentialPublicKey)
7878
if err != nil {
79-
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error parsing public key: %+v\n", err))
79+
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error parsing public key: %+v\n", err)).WithError(err)
8080
}
8181

8282
e := pubKey.(webauthncose.EC2PublicKeyData)
8383

8484
valid, err = e.Verify(signatureData, sig)
8585
if err != nil || !valid {
86-
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error parsing public key: %+v\n", err))
86+
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error parsing public key: %+v\n", err)).WithError(err)
8787
}
8888

8989
// §8.4.3. Verify that the attestationChallenge field in the attestation certificate extension data is identical to clientDataHash.
@@ -105,11 +105,11 @@ func verifyAndroidKeyFormat(att AttestationObject, clientDataHash []byte, _ meta
105105
decoded := keyDescription{}
106106

107107
if _, err = asn1.Unmarshal(attExtBytes, &decoded); err != nil {
108-
return "", nil, ErrAttestationFormat.WithDetails("Unable to parse Android key attestation certificate extensions")
108+
return "", nil, ErrAttestationFormat.WithDetails("Unable to parse Android key attestation certificate extensions").WithError(err)
109109
}
110110

111111
// Verify that the attestationChallenge field in the attestation certificate extension data is identical to clientDataHash.
112-
if 0 != bytes.Compare(decoded.AttestationChallenge, clientDataHash) {
112+
if bytes.Compare(decoded.AttestationChallenge, clientDataHash) != 0 {
113113
return "", nil, ErrAttestationFormat.WithDetails("Attestation challenge not equal to clientDataHash")
114114
}
115115

protocol/attestation_apple.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func verifyAppleFormat(att AttestationObject, clientDataHash []byte, _ metadata.
4848

4949
credCert, err := x509.ParseCertificate(credCertBytes)
5050
if err != nil {
51-
return "", nil, ErrAttestationFormat.WithDetails(fmt.Sprintf("Error parsing certificate from ASN.1 data: %+v", err))
51+
return "", nil, ErrAttestationFormat.WithDetails(fmt.Sprintf("Error parsing certificate from ASN.1 data: %+v", err)).WithError(err)
5252
}
5353

5454
// Step 2. Concatenate authenticatorData and clientDataHash to form nonceToHash.
@@ -73,7 +73,7 @@ func verifyAppleFormat(att AttestationObject, clientDataHash []byte, _ metadata.
7373
decoded := AppleAnonymousAttestation{}
7474

7575
if _, err = asn1.Unmarshal(attExtBytes, &decoded); err != nil {
76-
return "", nil, ErrAttestationFormat.WithDetails("Unable to parse apple attestation certificate extensions")
76+
return "", nil, ErrAttestationFormat.WithDetails("Unable to parse apple attestation certificate extensions").WithError(err)
7777
}
7878

7979
if !bytes.Equal(decoded.Nonce, nonce[:]) {
@@ -84,7 +84,7 @@ func verifyAppleFormat(att AttestationObject, clientDataHash []byte, _ metadata.
8484
// TODO: Probably move this part to webauthncose.go
8585
pubKey, err := webauthncose.ParsePublicKey(att.AuthData.AttData.CredentialPublicKey)
8686
if err != nil {
87-
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error parsing public key: %+v\n", err))
87+
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error parsing public key: %+v\n", err)).WithError(err)
8888
}
8989

9090
credPK := pubKey.(webauthncose.EC2PublicKeyData)

protocol/attestation_packed.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func handleBasicAttestation(signature, clientDataHash, authData, aaguid []byte,
8181

8282
ct, err := x509.ParseCertificate(cb)
8383
if err != nil {
84-
return "", x5c, ErrAttestationFormat.WithDetails(fmt.Sprintf("Error parsing certificate from ASN.1 data: %+v", err))
84+
return "", x5c, ErrAttestationFormat.WithDetails(fmt.Sprintf("Error parsing certificate from ASN.1 data: %+v", err)).WithError(err)
8585
}
8686

8787
if ct.NotBefore.After(time.Now()) || ct.NotAfter.Before(time.Now()) {
@@ -98,12 +98,12 @@ func handleBasicAttestation(signature, clientDataHash, authData, aaguid []byte,
9898

9999
attCert, err := x509.ParseCertificate(attCertBytes)
100100
if err != nil {
101-
return "", x5c, ErrAttestationFormat.WithDetails(fmt.Sprintf("Error parsing certificate from ASN.1 data: %+v", err))
101+
return "", x5c, ErrAttestationFormat.WithDetails(fmt.Sprintf("Error parsing certificate from ASN.1 data: %+v", err)).WithError(err)
102102
}
103103

104104
coseAlg := webauthncose.COSEAlgorithmIdentifier(alg)
105105
if err = attCert.CheckSignature(webauthncose.SigAlgFromCOSEAlg(coseAlg), signatureData, signature); err != nil {
106-
return "", x5c, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Signature validation error: %+v\n", err))
106+
return "", x5c, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Signature validation error: %+v\n", err)).WithError(err)
107107
}
108108

109109
// Step 2.2 Verify that attestnCert meets the requirements in §8.2.1 Packed attestation statement certificate requirements.

protocol/attestation_safetynet.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,14 @@ func verifySafetyNetFormat(att AttestationObject, clientDataHash []byte, mds met
9090
})
9191

9292
if err != nil {
93-
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error finding cert issued to correct hostname: %+v", err))
93+
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error finding cert issued to correct hostname: %+v", err)).WithError(err)
9494
}
9595

9696
// marshall the JWT payload into the safetynet response json
9797
var safetyNetResponse SafetyNetResponse
9898

9999
if err = mapstructure.Decode(token.Claims, &safetyNetResponse); err != nil {
100-
return "", nil, ErrAttestationFormat.WithDetails(fmt.Sprintf("Error parsing the SafetyNet response: %+v", err))
100+
return "", nil, ErrAttestationFormat.WithDetails(fmt.Sprintf("Error parsing the SafetyNet response: %+v", err)).WithError(err)
101101
}
102102

103103
// §8.5.3 Verify that the nonce in the response is identical to the Base64 encoding of the SHA-256 hash of the concatenation
@@ -106,7 +106,7 @@ func verifySafetyNetFormat(att AttestationObject, clientDataHash []byte, mds met
106106

107107
nonceBytes, err := base64.StdEncoding.DecodeString(safetyNetResponse.Nonce)
108108
if !bytes.Equal(nonceBuffer[:], nonceBytes) || err != nil {
109-
return "", nil, ErrInvalidAttestation.WithDetails("Invalid nonce for in SafetyNet response")
109+
return "", nil, ErrInvalidAttestation.WithDetails("Invalid nonce for in SafetyNet response").WithError(err)
110110
}
111111

112112
// §8.5.4 Let attestationCert be the attestation certificate (https://www.w3.org/TR/webauthn/#attestation-certificate)
@@ -115,18 +115,18 @@ func verifySafetyNetFormat(att AttestationObject, clientDataHash []byte, mds met
115115

116116
n, err := base64.StdEncoding.Decode(l, []byte(certChain[0].(string)))
117117
if err != nil {
118-
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error finding cert issued to correct hostname: %+v", err))
118+
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error finding cert issued to correct hostname: %+v", err)).WithError(err)
119119
}
120120

121121
attestationCert, err := x509.ParseCertificate(l[:n])
122122
if err != nil {
123-
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error finding cert issued to correct hostname: %+v", err))
123+
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error finding cert issued to correct hostname: %+v", err)).WithError(err)
124124
}
125125

126126
// §8.5.5 Verify that attestationCert is issued to the hostname "attest.android.com"
127127
err = attestationCert.VerifyHostname("attest.android.com")
128128
if err != nil {
129-
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error finding cert issued to correct hostname: %+v", err))
129+
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error finding cert issued to correct hostname: %+v", err)).WithError(err)
130130
}
131131

132132
// §8.5.6 Verify that the ctsProfileMatch attribute in the payload of response is true.

0 commit comments

Comments
 (0)