Skip to content

Commit

Permalink
temp
Browse files Browse the repository at this point in the history
  • Loading branch information
james-d-elliott committed Jul 9, 2024
1 parent b2d190d commit 42c91cd
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 7 deletions.
59 changes: 59 additions & 0 deletions metadata/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import (
"errors"
"fmt"
"io"
"math"
"net/http"
"reflect"
"strings"
"time"

Expand Down Expand Up @@ -274,3 +276,60 @@ func mdsParseX509Certificate(value string) (certificate *x509.Certificate, err e

return certificate, nil
}

// StringToMailAddressHookFunc decodes a string into a mail.Address or *mail.Address.
func hookDecodeUnsignedInt32() mapstructure.DecodeHookFuncType {
return func(f reflect.Type, t reflect.Type, data any) (value any, err error) {
switch f.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
break
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
break
case reflect.Float32, reflect.Float64:
break
default:
return data, nil
}

if t.Kind() != reflect.Uint32 {
return data, nil
}

var result uint64

switch i := data.(type) {
case int:
result = uint64(i)
case int8:
result = uint64(i)
case int16:
result = uint64(i)
case int32:
result = uint64(i)
case int64:
result = uint64(i)
case uint:
result = uint64(i)
case uint8:
result = uint64(i)
case uint16:
result = uint64(i)
case uint32:
result = uint64(i)
case uint64:
result = i
case float32:
result = uint64(i)
case float64:
result = uint64(i)
default:
return data, nil
}

if result > math.MaxUint32 {
return 0, nil
}

return uint32(result), nil
}
}
2 changes: 1 addition & 1 deletion metadata/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,7 @@ type PatternAccuracyDescriptor struct {
// See: https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.0-ps-20210518.html#verificationmethoddescriptor-dictionary
type VerificationMethodDescriptor struct {
// a single USER_VERIFY constant (see [FIDORegistry]), not a bit flag combination. This value MUST be non-zero.
UserVerificationMethod string `json:"userVerification"`
UserVerificationMethod string `json:"userVerificationMethod"`

// May optionally be used in the case of method USER_VERIFY_PASSCODE.
CaDesc CodeAccuracyDescriptor `json:"caDesc"`
Expand Down
13 changes: 13 additions & 0 deletions metadata/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"io"
"math"
"net/http"
"testing"
"time"
Expand Down Expand Up @@ -34,6 +35,18 @@ func TestProductionMetadataTOCParsing(t *testing.T) {
metadata, err = decoder.Parse(payload)
require.NoError(t, err)

fmt.Println(payload.Number)

for i, entry := range metadata.Parsed.Entries {
for _, items := range entry.MetadataStatement.UserVerificationDetails {
for _, item := range items {
if item.PaDesc.MinComplexity > math.MaxUint32 {
fmt.Printf("item %d pa complexity for %s is too large with value %d\n", i, item.UserVerificationMethod, item.PaDesc.MinComplexity)
}
}
}
}

for _, perr := range metadata.Unparsed {
fmt.Println(perr.Error)
}
Expand Down
20 changes: 15 additions & 5 deletions metadata/providers/memory/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func WithMetadata(mds map[uuid.UUID]*metadata.Entry) Option {

// WithValidateEntry requires that the provided metadata has an entry for the given authenticator to be considered
// valid. By default an AAGUID which has a zero value should fail validation if WithValidateEntryPermitZeroAAGUID is not
// provided with the value of true.
// provided with the value of true. Default is true.
func WithValidateEntry(require bool) Option {
return func(provider *Provider) (err error) {
provider.entry = require
Expand All @@ -30,7 +30,7 @@ func WithValidateEntry(require bool) Option {
}

// WithValidateEntryPermitZeroAAGUID is an option that permits a zero'd AAGUID from an attestation statement to
// automatically pass metadata validations. Generally helpful to use with WithValidateEntry.
// automatically pass metadata validations. Generally helpful to use with WithValidateEntry. Default is false.
func WithValidateEntryPermitZeroAAGUID(permit bool) Option {
return func(provider *Provider) (err error) {
provider.entryPermitZero = permit
Expand All @@ -40,7 +40,7 @@ func WithValidateEntryPermitZeroAAGUID(permit bool) Option {
}

// WithValidateTrustAnchor when set to true enables the validation of the attestation statement against the trust anchor
// from the metadata.
// from the metadata. Default is true.
func WithValidateTrustAnchor(validate bool) Option {
return func(provider *Provider) (err error) {
provider.anchors = validate
Expand All @@ -49,8 +49,8 @@ func WithValidateTrustAnchor(validate bool) Option {
}
}

// WithValidateStatus when set to true enables the validation of the attestation statments AAGUID against the desired
// and undesired metadata.AuthenticatorStatus lists.
// WithValidateStatus when set to true enables the validation of the attestation statements AAGUID against the desired
// and undesired metadata.AuthenticatorStatus lists. Default is true.
func WithValidateStatus(validate bool) Option {
return func(provider *Provider) (err error) {
provider.status = validate
Expand All @@ -59,6 +59,16 @@ func WithValidateStatus(validate bool) Option {
}
}

// WithValidateAttestationTypes when set to true enables the validation of the attestation statements type against the
// known types the authenticator can produce. Default is true.
func WithValidateAttestationTypes(validate bool) Option {
return func(provider *Provider) (err error) {
provider.status = validate

return nil
}
}

// WithStatusUndesired provides the list of statuses which are considered undesirable for status report validation
// purposes. Should be used with WithValidateStatus set to true.
func WithStatusUndesired(statuses []metadata.AuthenticatorStatus) Option {
Expand Down
11 changes: 10 additions & 1 deletion metadata/providers/memory/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import (
// New returns a new memory Provider given a set of functional Option's.
func New(opts ...Option) (provider metadata.Provider, err error) {
p := &Provider{
undesired: metadata.DefaultUndesiredAuthenticatorStatuses(),
undesired: metadata.DefaultUndesiredAuthenticatorStatuses(),
entry: true,
anchors: true,
status: true,
attestation: true,
}

for _, opt := range opts {
Expand All @@ -39,6 +43,7 @@ type Provider struct {
entryPermitZero bool
anchors bool
status bool
attestation bool
}

func (p *Provider) GetEntry(ctx context.Context, aaguid uuid.UUID) (entry *metadata.Entry, err error) {
Expand Down Expand Up @@ -71,6 +76,10 @@ func (p *Provider) GetValidateStatus(ctx context.Context) (validate bool) {
return p.status
}

func (p *Provider) GetValidateAttestationTypes(ctx context.Context) (validate bool) {
return p.attestation
}

func (p *Provider) ValidateStatusReports(ctx context.Context, reports []metadata.StatusReport) (err error) {
if !p.status {
return nil
Expand Down
4 changes: 4 additions & 0 deletions metadata/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ type Provider interface {
// undesired statuses.
GetValidateStatus(ctx context.Context) (validate bool)

// GetValidateAttestationTypes if true will enforce checking that the provided attestation is possible with the
// given authenticator.
GetValidateAttestationTypes(ctx context.Context) (validate bool)

// ValidateStatusReports returns nil if the provided authenticator status reports are desired.
ValidateStatusReports(ctx context.Context, reports []StatusReport) (err error)
}
Expand Down
16 changes: 16 additions & 0 deletions protocol/attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,22 @@ func (a *AttestationObject) VerifyAttestation(clientDataHash []byte, mds metadat
return nil
}

if mds.GetValidateAttestationTypes(ctx) {
found := false

for _, atype := range entry.MetadataStatement.AttestationTypes {
if atype == metadata.AuthenticatorAttestationType(attestationType) {
found = true

break
}
}

if !found {
return ErrInvalidAttestation.WithDetails(fmt.Sprintf("Authenticator with invalid attestation type encountered during attestation validation. The attestation type '%s' is not known to be used by AAGUID '%s'", attestationType, aaguid.String()))
}
}

if mds.GetValidateStatus(ctx) {
if err = mds.ValidateStatusReports(ctx, entry.StatusReports); err != nil {
return ErrInvalidAttestation.WithDetails(fmt.Sprintf("Authenticator with invalid status encountered during attestation validation. %s", err.Error()))
Expand Down

0 comments on commit 42c91cd

Please sign in to comment.