Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ coverage:

ignore:
- "**/coverage.txt"
- "testing"

parsers:
gcov:
Expand Down
10 changes: 6 additions & 4 deletions .github/workflows/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ name: 'Dependabot'
on:
pull_request: {}
permissions:
contents: 'write'
pull-requests: 'write'
contents: 'read'
jobs:
automerge:
name: 'Auto-Merge'
runs-on: 'ubuntu-latest'
permissions:
contents: 'read'
pull-requests: 'write'
if: github.event.pull_request.user.login == 'dependabot[bot]' && github.repository == 'go-webauthn/webauthn'
steps:
- name: 'Harden Runner'
Expand All @@ -23,5 +25,5 @@ jobs:
run: |
gh pr merge --auto --squash "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (
github.com/google/uuid v1.6.0
github.com/mitchellh/mapstructure v1.5.0
github.com/stretchr/testify v1.11.0
go.uber.org/mock v0.6.0
)

require (
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQ
github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
Expand Down
64 changes: 35 additions & 29 deletions protocol/attestation_androidkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import (
"crypto/x509"
"encoding/asn1"
"fmt"
"time"

"github.com/go-webauthn/webauthn/metadata"
"github.com/go-webauthn/webauthn/protocol/webauthncose"
)

func init() {
RegisterAttestationFormat(AttestationFormatAndroidKey, verifyAndroidKeyFormat)
RegisterAttestationFormat(AttestationFormatAndroidKey, attestationFormatValidationHandlerAndroidKey)
}

// The android-key attestation statement looks like:
Expand All @@ -29,7 +30,7 @@ func init() {
// }
//
// Specification: §8.4. Android Key Attestation Statement Format (https://www.w3.org/TR/webauthn/#sctn-android-key-attestation)
func verifyAndroidKeyFormat(att AttestationObject, clientDataHash []byte, _ metadata.Provider) (attestationType string, x5cs []any, err error) {
func attestationFormatValidationHandlerAndroidKey(att AttestationObject, clientDataHash []byte, _ metadata.Provider) (attestationType string, x5cs []any, err error) {
// Given the verification procedure inputs attStmt, authenticatorData and clientDataHash, the verification procedure is as follows:
// §8.4.1. Verify that attStmt is valid CBOR conforming to the syntax defined above and perform CBOR decoding on it to extract
// the contained fields.
Expand All @@ -47,51 +48,52 @@ func verifyAndroidKeyFormat(att AttestationObject, clientDataHash []byte, _ meta
return "", nil, ErrAttestationFormat.WithDetails("Error retrieving sig value")
}

// If x5c is not present, return an error.
x5c, x509present := att.AttStatement[stmtX5C].([]any)
if !x509present {
// Handle Basic Attestation steps for the x509 Certificate.
return "", nil, ErrAttestationFormat.WithDetails("Error retrieving x5c value")
}

// §8.4.2. Verify that sig is a valid signature over the concatenation of authenticatorData and clientDataHash
// using the public key in the first certificate in x5c with the algorithm specified in alg.
attCertBytes, valid := x5c[0].([]byte)
if !valid {
return "", nil, ErrAttestation.WithDetails("Error getting certificate from x5c cert chain")
var (
x5c []any
certs []*x509.Certificate
)

if x5c, certs, err = attStatementParseX5CS(att.AttStatement, stmtX5C); err != nil {
return "", nil, err
}

attCert, err := x509.ParseCertificate(attCertBytes)
if err != nil {
return "", nil, ErrAttestationFormat.WithDetails(fmt.Sprintf("Error parsing certificate from ASN.1 data: %+v", err)).WithError(err)
if len(certs) == 0 {
return "", nil, ErrInvalidAttestation.WithDetails("No certificates in x5c")
}

credCert := certs[0]

if _, err = attStatementCertChainVerify(certs, attAndroidKeyHardwareRootsCertPool, true, time.Now().Add(time.Hour*8760).UTC()); err != nil {
return "", nil, ErrInvalidAttestation.WithDetails("Error validating x5c cert chain").WithError(err)
}

signatureData := append(att.RawAuthData, clientDataHash...) //nolint:gocritic // This is intentional.

coseAlg := webauthncose.COSEAlgorithmIdentifier(alg)
if err = attCert.CheckSignature(webauthncose.SigAlgFromCOSEAlg(coseAlg), signatureData, sig); err != nil {
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Signature validation error: %+v\n", err)).WithError(err)
if sigAlg := webauthncose.SigAlgFromCOSEAlg(webauthncose.COSEAlgorithmIdentifier(alg)); sigAlg == x509.UnknownSignatureAlgorithm {
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Unsupported COSE alg: %d", alg))
} else if err = credCert.CheckSignature(sigAlg, signatureData, sig); err != nil {
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Signature validation error: %+v", err)).WithError(err)
}

// Verify that the public key in the first certificate in x5c matches the credentialPublicKey in the attestedCredentialData in authenticatorData.
pubKey, err := webauthncose.ParsePublicKey(att.AuthData.AttData.CredentialPublicKey)
if err != nil {
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error parsing public key: %+v\n", err)).WithError(err)
var attPublicKeyData webauthncose.EC2PublicKeyData
if attPublicKeyData, err = verifyAttestationECDSAPublicKeyMatch(att, credCert); err != nil {
return "", nil, err
}

e := pubKey.(webauthncose.EC2PublicKeyData)

valid, err = e.Verify(signatureData, sig)
if err != nil || !valid {
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error parsing public key: %+v\n", err)).WithError(err)
var valid bool
if valid, err = attPublicKeyData.Verify(signatureData, sig); err != nil || !valid {
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error parsing public key: %+v", err)).WithError(err)
}

// §8.4.3. Verify that the attestationChallenge field in the attestation certificate extension data is identical to clientDataHash.
// attCert.Extensions.
var attExtBytes []byte

for _, ext := range attCert.Extensions {
if ext.Id.Equal([]int{1, 3, 6, 1, 4, 1, 11129, 2, 1, 17}) {
for _, ext := range credCert.Extensions {
if ext.Id.Equal(oidExtensionAndroidKeystore) {
attExtBytes = ext.Value
}
}
Expand All @@ -114,7 +116,7 @@ func verifyAndroidKeyFormat(att AttestationObject, clientDataHash []byte, _ meta
}

// The AuthorizationList.allApplications field is not present on either authorization list (softwareEnforced nor teeEnforced), since PublicKeyCredential MUST be scoped to the RP ID.
if nil != decoded.SoftwareEnforced.AllApplications || nil != decoded.TeeEnforced.AllApplications {
if decoded.SoftwareEnforced.AllApplications != nil || decoded.TeeEnforced.AllApplications != nil {
return "", nil, ErrAttestationFormat.WithDetails("Attestation certificate extensions contains all applications field")
}

Expand Down Expand Up @@ -239,3 +241,7 @@ const (
KM_PURPOSE_DERIVE_KEY /* Usable with EC keys. */
KM_PURPOSE_WRAP /* Usable with wrapped keys. */
)

var (
attAndroidKeyHardwareRootsCertPool *x509.CertPool
)
104 changes: 84 additions & 20 deletions protocol/attestation_androidkey_test.go

Large diffs are not rendered by default.

55 changes: 20 additions & 35 deletions protocol/attestation_apple.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,16 @@ package protocol

import (
"bytes"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/sha256"
"crypto/x509"
"encoding/asn1"
"fmt"
"math/big"
"time"

"github.com/go-webauthn/webauthn/metadata"
"github.com/go-webauthn/webauthn/protocol/webauthncose"
)

func init() {
RegisterAttestationFormat(AttestationFormatApple, verifyAppleFormat)
RegisterAttestationFormat(AttestationFormatApple, attestationFormatValidationHandlerAppleAnonymous)
}

// The apple attestation statement looks like:
Expand All @@ -31,24 +27,23 @@ func init() {
// }
//
// Specification: §8.8. Apple Anonymous Attestation Statement Format (https://www.w3.org/TR/webauthn/#sctn-apple-anonymous-attestation)
func verifyAppleFormat(att AttestationObject, clientDataHash []byte, _ metadata.Provider) (attestationType string, x5cs []any, err error) {
func attestationFormatValidationHandlerAppleAnonymous(att AttestationObject, clientDataHash []byte, _ metadata.Provider) (attestationType string, x5cs []any, err error) {
// Step 1. Verify that attStmt is valid CBOR conforming to the syntax defined
// above and perform CBOR decoding on it to extract the contained fields.
// If x5c is not present, return an error.
x5c, x509present := att.AttStatement[stmtX5C].([]any)
if !x509present {
// Handle Basic Attestation steps for the x509 Certificate.
return "", nil, ErrAttestationFormat.WithDetails("Error retrieving x5c value")
}
var (
x5c []any
certs []*x509.Certificate
)

credCertBytes, valid := x5c[0].([]byte)
if !valid {
return "", nil, ErrAttestation.WithDetails("Error getting certificate from x5c cert chain")
if x5c, certs, err = attStatementParseX5CS(att.AttStatement, stmtX5C); err != nil {
return "", nil, err
}

credCert, err := x509.ParseCertificate(credCertBytes)
if err != nil {
return "", nil, ErrAttestationFormat.WithDetails(fmt.Sprintf("Error parsing certificate from ASN.1 data: %+v", err)).WithError(err)
credCert := certs[0]

if _, err = attStatementCertChainVerify(certs, attAppleHardwareRootsCertPool, true, time.Now().Add(time.Hour*8760).UTC()); err != nil {
return "", nil, ErrInvalidAttestation.WithDetails("Error validating x5c cert chain").WithError(err)
}

// Step 2. Concatenate authenticatorData and clientDataHash to form nonceToHash.
Expand All @@ -61,7 +56,7 @@ func verifyAppleFormat(att AttestationObject, clientDataHash []byte, _ metadata.
var attExtBytes []byte

for _, ext := range credCert.Extensions {
if ext.Id.Equal([]int{1, 2, 840, 113635, 100, 8, 2}) {
if ext.Id.Equal(oidExtensionAppleAnonymousAttestation) {
attExtBytes = ext.Value
}
}
Expand All @@ -81,22 +76,8 @@ func verifyAppleFormat(att AttestationObject, clientDataHash []byte, _ metadata.
}

// Step 5. Verify that the credential public key equals the Subject Public Key of credCert.
// TODO: Probably move this part to webauthncose.go.
pubKey, err := webauthncose.ParsePublicKey(att.AuthData.AttData.CredentialPublicKey)
if err != nil {
return "", nil, ErrInvalidAttestation.WithDetails(fmt.Sprintf("Error parsing public key: %+v\n", err)).WithError(err)
}

credPK := pubKey.(webauthncose.EC2PublicKeyData)
subjectPK := credCert.PublicKey.(*ecdsa.PublicKey)
credPKInfo := &ecdsa.PublicKey{
Curve: elliptic.P256(),
X: big.NewInt(0).SetBytes(credPK.XCoord),
Y: big.NewInt(0).SetBytes(credPK.YCoord),
}

if !credPKInfo.Equal(subjectPK) {
return "", nil, ErrInvalidAttestation.WithDetails("Certificate public key does not match public key in authData")
if _, err = verifyAttestationECDSAPublicKeyMatch(att, credCert); err != nil {
return "", nil, err
}

// Step 6. If successful, return implementation-specific values representing attestation type Anonymization CA and attestation trust path x5c.
Expand All @@ -108,3 +89,7 @@ func verifyAppleFormat(att AttestationObject, clientDataHash []byte, _ metadata.
type AppleAnonymousAttestation struct {
Nonce []byte `asn1:"tag:1,explicit"`
}

var (
attAppleHardwareRootsCertPool *x509.CertPool
)
42 changes: 23 additions & 19 deletions protocol/attestation_apple_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import (
"testing"

"github.com/go-webauthn/webauthn/metadata"
"github.com/stretchr/testify/assert"
)

func Test_verifyAppleFormat(t *testing.T) {
func Test_VerifyAppleFormat(t *testing.T) {
type args struct {
att AttestationObject
clientDataHash []byte
Expand All @@ -16,35 +17,38 @@ func Test_verifyAppleFormat(t *testing.T) {
successAttResponse := attestationTestUnpackResponse(t, appleTestResponse["success"]).Response.AttestationObject
successClientDataHash := sha256.Sum256(attestationTestUnpackResponse(t, appleTestResponse["success"]).Raw.AttestationResponse.ClientDataJSON)

tests := []struct {
name string
args args
want string
want1 []any
wantErr bool
testCases := []struct {
name string
args args
attestationType string
x5cs []any
err string
}{
{
"success",
"ShouldSuccessfullyParseAppleFormat",
args{
successAttResponse,
successClientDataHash[:],
},
string(metadata.AnonCA),
nil,
false,
[]any{
[]byte{0x30, 0x82, 0x2, 0x44, 0x30, 0x82, 0x1, 0xc9, 0xa0, 0x3, 0x2, 0x1, 0x2, 0x2, 0x6, 0x1, 0x75, 0x2, 0x7d, 0x61, 0x83, 0x30, 0xa, 0x6, 0x8, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x4, 0x3, 0x2, 0x30, 0x48, 0x31, 0x1c, 0x30, 0x1a, 0x6, 0x3, 0x55, 0x4, 0x3, 0xc, 0x13, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x65, 0x62, 0x41, 0x75, 0x74, 0x68, 0x6e, 0x20, 0x43, 0x41, 0x20, 0x31, 0x31, 0x13, 0x30, 0x11, 0x6, 0x3, 0x55, 0x4, 0xa, 0xc, 0xa, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x13, 0x30, 0x11, 0x6, 0x3, 0x55, 0x4, 0x8, 0xc, 0xa, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x30, 0x1e, 0x17, 0xd, 0x32, 0x30, 0x31, 0x30, 0x30, 0x37, 0x30, 0x39, 0x34, 0x36, 0x31, 0x32, 0x5a, 0x17, 0xd, 0x32, 0x30, 0x31, 0x30, 0x30, 0x38, 0x30, 0x39, 0x35, 0x36, 0x31, 0x32, 0x5a, 0x30, 0x81, 0x91, 0x31, 0x49, 0x30, 0x47, 0x6, 0x3, 0x55, 0x4, 0x3, 0xc, 0x40, 0x36, 0x31, 0x32, 0x37, 0x36, 0x66, 0x63, 0x30, 0x32, 0x64, 0x33, 0x66, 0x65, 0x38, 0x64, 0x31, 0x36, 0x62, 0x33, 0x33, 0x62, 0x35, 0x35, 0x34, 0x39, 0x64, 0x38, 0x31, 0x39, 0x32, 0x33, 0x36, 0x63, 0x38, 0x31, 0x37, 0x34, 0x36, 0x61, 0x38, 0x33, 0x66, 0x32, 0x65, 0x39, 0x34, 0x61, 0x36, 0x65, 0x34, 0x62, 0x65, 0x65, 0x31, 0x63, 0x37, 0x30, 0x66, 0x38, 0x31, 0x62, 0x35, 0x62, 0x63, 0x31, 0x1a, 0x30, 0x18, 0x6, 0x3, 0x55, 0x4, 0xb, 0xc, 0x11, 0x41, 0x41, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x13, 0x30, 0x11, 0x6, 0x3, 0x55, 0x4, 0xa, 0xc, 0xa, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x13, 0x30, 0x11, 0x6, 0x3, 0x55, 0x4, 0x8, 0xc, 0xa, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x30, 0x59, 0x30, 0x13, 0x6, 0x7, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x2, 0x1, 0x6, 0x8, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x3, 0x1, 0x7, 0x3, 0x42, 0x0, 0x4, 0x79, 0xfe, 0x59, 0x8, 0xbb, 0x51, 0x29, 0xc8, 0x9, 0x38, 0xb7, 0x54, 0xc0, 0x4d, 0x2b, 0x34, 0xe, 0xfa, 0x66, 0x15, 0xb9, 0x87, 0x69, 0x8b, 0xf5, 0x9d, 0xa4, 0xe5, 0x3e, 0xa3, 0xe6, 0xfe, 0xfb, 0x3, 0xda, 0xa1, 0x27, 0xd, 0x58, 0x4, 0xe8, 0xab, 0x61, 0xc1, 0x5a, 0xac, 0xa2, 0x43, 0x5c, 0x7d, 0xbf, 0x36, 0x9d, 0x71, 0xca, 0x15, 0xc5, 0x23, 0xb0, 0x0, 0x4a, 0x1b, 0x75, 0xb7, 0xa3, 0x55, 0x30, 0x53, 0x30, 0xc, 0x6, 0x3, 0x55, 0x1d, 0x13, 0x1, 0x1, 0xff, 0x4, 0x2, 0x30, 0x0, 0x30, 0xe, 0x6, 0x3, 0x55, 0x1d, 0xf, 0x1, 0x1, 0xff, 0x4, 0x4, 0x3, 0x2, 0x4, 0xf0, 0x30, 0x33, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x8, 0x2, 0x4, 0x26, 0x30, 0x24, 0xa1, 0x22, 0x4, 0x20, 0x9c, 0x60, 0x2, 0x15, 0x40, 0xb3, 0xe1, 0x98, 0x34, 0xdf, 0xe3, 0x7e, 0xc6, 0x24, 0x45, 0xc8, 0x9e, 0x1b, 0x29, 0x4f, 0x79, 0x2c, 0xe4, 0x6b, 0x94, 0x13, 0xc3, 0x23, 0xe, 0xf3, 0x86, 0x81, 0x30, 0xa, 0x6, 0x8, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x4, 0x3, 0x2, 0x3, 0x69, 0x0, 0x30, 0x66, 0x2, 0x31, 0x0, 0xda, 0x1c, 0x18, 0xeb, 0x23, 0xbe, 0x71, 0x0, 0x5e, 0xd2, 0x5f, 0x3c, 0x85, 0xe7, 0x34, 0x90, 0x7, 0xf2, 0xe0, 0xf4, 0xf8, 0xd3, 0x77, 0x2c, 0x9e, 0xfb, 0xe, 0xec, 0xb6, 0x2a, 0xb2, 0xf3, 0x82, 0xba, 0x96, 0x6a, 0x3c, 0x77, 0x77, 0xc8, 0xa6, 0xd6, 0x23, 0x2d, 0xc, 0x7c, 0xd5, 0xbb, 0x2, 0x31, 0x0, 0xaf, 0xb, 0xc3, 0x12, 0x37, 0xe6, 0x9e, 0xc2, 0x26, 0x94, 0xd1, 0xb3, 0x2c, 0x77, 0x14, 0x5b, 0x74, 0x37, 0xab, 0x8, 0x92, 0x63, 0xdf, 0x12, 0x5b, 0xdc, 0xa6, 0x70, 0x96, 0x87, 0xaf, 0x27, 0x77, 0x5a, 0xa, 0x60, 0x9c, 0xad, 0x9a, 0xc0, 0x3d, 0x87, 0xcb, 0xa7, 0x69, 0x3, 0x3a, 0xc8},
[]byte{0x30, 0x82, 0x2, 0x34, 0x30, 0x82, 0x1, 0xba, 0xa0, 0x3, 0x2, 0x1, 0x2, 0x2, 0x10, 0x56, 0x25, 0x53, 0x95, 0xc7, 0xa7, 0xfb, 0x40, 0xeb, 0xe2, 0x28, 0xd8, 0x26, 0x8, 0x53, 0xb6, 0x30, 0xa, 0x6, 0x8, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x4, 0x3, 0x3, 0x30, 0x4b, 0x31, 0x1f, 0x30, 0x1d, 0x6, 0x3, 0x55, 0x4, 0x3, 0xc, 0x16, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x65, 0x62, 0x41, 0x75, 0x74, 0x68, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, 0x13, 0x30, 0x11, 0x6, 0x3, 0x55, 0x4, 0xa, 0xc, 0xa, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x13, 0x30, 0x11, 0x6, 0x3, 0x55, 0x4, 0x8, 0xc, 0xa, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x30, 0x1e, 0x17, 0xd, 0x32, 0x30, 0x30, 0x33, 0x31, 0x38, 0x31, 0x38, 0x33, 0x38, 0x30, 0x31, 0x5a, 0x17, 0xd, 0x33, 0x30, 0x30, 0x33, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x48, 0x31, 0x1c, 0x30, 0x1a, 0x6, 0x3, 0x55, 0x4, 0x3, 0xc, 0x13, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x65, 0x62, 0x41, 0x75, 0x74, 0x68, 0x6e, 0x20, 0x43, 0x41, 0x20, 0x31, 0x31, 0x13, 0x30, 0x11, 0x6, 0x3, 0x55, 0x4, 0xa, 0xc, 0xa, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x13, 0x30, 0x11, 0x6, 0x3, 0x55, 0x4, 0x8, 0xc, 0xa, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x30, 0x76, 0x30, 0x10, 0x6, 0x7, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x2, 0x1, 0x6, 0x5, 0x2b, 0x81, 0x4, 0x0, 0x22, 0x3, 0x62, 0x0, 0x4, 0x83, 0x2e, 0x87, 0x2f, 0x26, 0x14, 0x91, 0x81, 0x2, 0x25, 0xb9, 0xf5, 0xfc, 0xd6, 0xbb, 0x63, 0x78, 0xb5, 0xf5, 0x5f, 0x3f, 0xcb, 0x4, 0x5b, 0xc7, 0x35, 0x99, 0x34, 0x75, 0xfd, 0x54, 0x90, 0x44, 0xdf, 0x9b, 0xfe, 0x19, 0x21, 0x17, 0x65, 0xc6, 0x9a, 0x1d, 0xda, 0x5, 0xb, 0x38, 0xd4, 0x50, 0x83, 0x40, 0x1a, 0x43, 0x4f, 0xb2, 0x4d, 0x11, 0x2d, 0x56, 0xc3, 0xe1, 0xcf, 0xbf, 0xcb, 0x98, 0x91, 0xfe, 0xc0, 0x69, 0x60, 0x81, 0xbe, 0xf9, 0x6c, 0xbc, 0x77, 0xc8, 0x8d, 0xdd, 0xaf, 0x46, 0xa5, 0xae, 0xe1, 0xdd, 0x51, 0x5b, 0x5a, 0xfa, 0xab, 0x93, 0xbe, 0x9c, 0xb, 0x26, 0x91, 0xa3, 0x66, 0x30, 0x64, 0x30, 0x12, 0x6, 0x3, 0x55, 0x1d, 0x13, 0x1, 0x1, 0xff, 0x4, 0x8, 0x30, 0x6, 0x1, 0x1, 0xff, 0x2, 0x1, 0x0, 0x30, 0x1f, 0x6, 0x3, 0x55, 0x1d, 0x23, 0x4, 0x18, 0x30, 0x16, 0x80, 0x14, 0x26, 0xd7, 0x64, 0xd9, 0xc5, 0x78, 0xc2, 0x5a, 0x67, 0xd1, 0xa7, 0xde, 0x6b, 0x12, 0xd0, 0x1b, 0x63, 0xf1, 0xc6, 0xd7, 0x30, 0x1d, 0x6, 0x3, 0x55, 0x1d, 0xe, 0x4, 0x16, 0x4, 0x14, 0xeb, 0xae, 0x82, 0xc4, 0xff, 0xa1, 0xac, 0x5b, 0x51, 0xd4, 0xcf, 0x24, 0x61, 0x5, 0x0, 0xbe, 0x63, 0xbd, 0x77, 0x88, 0x30, 0xe, 0x6, 0x3, 0x55, 0x1d, 0xf, 0x1, 0x1, 0xff, 0x4, 0x4, 0x3, 0x2, 0x1, 0x6, 0x30, 0xa, 0x6, 0x8, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x4, 0x3, 0x3, 0x3, 0x68, 0x0, 0x30, 0x65, 0x2, 0x31, 0x0, 0xdd, 0x8b, 0x1a, 0x34, 0x81, 0xa5, 0xfa, 0xd9, 0xdb, 0xb4, 0xe7, 0x65, 0x7b, 0x84, 0x1e, 0x14, 0x4c, 0x27, 0xb7, 0x5b, 0x87, 0x6a, 0x41, 0x86, 0xc2, 0xb1, 0x47, 0x57, 0x50, 0x33, 0x72, 0x27, 0xef, 0xe5, 0x54, 0x45, 0x7e, 0xf6, 0x48, 0x95, 0xc, 0x63, 0x2e, 0x5c, 0x48, 0x3e, 0x70, 0xc1, 0x2, 0x30, 0x2c, 0x8a, 0x60, 0x44, 0xdc, 0x20, 0x1f, 0xcf, 0xe5, 0x9b, 0xc3, 0x4d, 0x29, 0x30, 0xc1, 0x48, 0x78, 0x51, 0xd9, 0x60, 0xed, 0x6a, 0x75, 0xf1, 0xeb, 0x4a, 0xca, 0xbe, 0x38, 0xcd, 0x25, 0xb8, 0x97, 0xd0, 0xc8, 0x5, 0xbe, 0xf0, 0xc7, 0xf7, 0x8b, 0x7, 0xa5, 0x71, 0xc6, 0xe8, 0xe, 0x7}},
"",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, _, err := verifyAppleFormat(tt.args.att, tt.args.clientDataHash, nil)
if (err != nil) != tt.wantErr {
t.Errorf("verifyAppleFormat() error = %v, wantErr %v", err, tt.wantErr)
return
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
attestationType, x5cs, err := attestationFormatValidationHandlerAppleAnonymous(tc.args.att, tc.args.clientDataHash, nil)

assert.Equal(t, tc.attestationType, attestationType)
assert.Equal(t, tc.x5cs, x5cs)

if got != tt.want {
t.Errorf("verifyAppleFormat() got = %v, want %v", got, tt.want)
if tc.err != "" {
assert.EqualError(t, err, tc.err)
} else {
assert.NoError(t, err)
}
})
}
Expand Down
Loading
Loading