libfido2

package module
v1.5.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2022 License: MIT Imports: 8 Imported by: 9

README

go-libfido2

Go wrapper for libfido2.

import (
    "github.com/keys-pub/go-libfido2"
)

func ExampleDevice_Assertion() {
    locs, err := libfido2.DeviceLocations()
    if err != nil {
        log.Fatal(err)
    }
    if len(locs) == 0 {
        log.Println("No devices")
        return
    }

    log.Printf("Using device: %+v\n", locs[0])
    path := locs[0].Path
    device, err := libfido2.NewDevice(path)
    if err != nil {
        log.Fatal(err)
    }

    cdh := libfido2.RandBytes(32)
    userID := libfido2.RandBytes(32)
    salt := libfido2.RandBytes(32)
    pin := "12345"

    attest, err := device.MakeCredential(
        cdh,
        libfido2.RelyingParty{
            ID: "keys.pub",
        },
        libfido2.User{
            ID:   userID,
            Name: "gabriel",
        },
        libfido2.ES256, // Algorithm
        pin,
        &libfido2.MakeCredentialOpts{
            Extensions: []libfido2.Extension{libfido2.HMACSecretExtension},
        },
    )
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("Attestation:\n")
    log.Printf("AuthData: %s\n", hex.EncodeToString(attest.AuthData))
    log.Printf("ClientDataHash: %s\n", hex.EncodeToString(attest.ClientDataHash))
    log.Printf("ID: %s\n", hex.EncodeToString(attest.CredentialID))
    log.Printf("Type: %s\n", attest.CredentialType)
    log.Printf("Sig: %s\n", hex.EncodeToString(attest.Sig))

    assertion, err := device.Assertion(
        "keys.pub",
        cdh,
        [][]byte{attest.CredentialID},
        pin,
        &libfido2.AssertionOpts{
            Extensions: []libfido2.Extension{libfido2.HMACSecretExtension},
            HMACSalt:   salt,
        },
    )
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("Assertion:\n")
    log.Printf("%s\n", hex.EncodeToString(assertion.AuthData))
    log.Printf("%s\n", hex.EncodeToString(assertion.HMACSecret))
    log.Printf("%s\n", hex.EncodeToString(assertion.Sig))

    // Output:
    //
}

Examples

The examples require a device.

To run an example, set FIDO2_EXAMPLES=1.

FIDO2_EXAMPLES=1 go test -v -run ExampleDeviceLocations
FIDO2_EXAMPLES=1 go test -v -run ExampleDevice_Assertion
FIDO2_EXAMPLES=1 go test -v -run ExampleDevice_Credentials

Dependencies

Linux
sudo apt install software-properties-common
sudo apt-add-repository ppa:yubico/stable
sudo apt update
sudo apt install libfido2-dev
macOS
brew install keys-pub/tap/libfido2
Windows
scoop bucket add keys.pub https://github.com/keys-pub/scoop-bucket
scoop install libfido2
Building libfido2
macOS
export CFLAGS="-I/usr/local/include -I/usr/local/opt/openssl@1.1/include"
export LDFLAGS="-L/usr/local/lib -L/usr/local/opt/openssl@1.1/lib/"
(rm -rf build && mkdir build && cd build && cmake ..) && make -C build

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrActionTimeout = errors.New("action timed out")

ErrActionTimeout if action timed out.

View Source
var ErrInternal = errors.New("internal error")

ErrInternal internal error.

View Source
var ErrInvalidArgument = errors.New("invalid argument")

ErrInvalidArgument if arguments are invalid.

View Source
var ErrInvalidCommand = errors.New("invalid command")

ErrInvalidCommand if command is not supported.

View Source
var ErrInvalidCredential = errors.New("invalid credential")

ErrInvalidCredential if credential is invalid.

View Source
var ErrInvalidLength = errors.New("invalid length")

ErrInvalidLength if invalid length.

View Source
var ErrInvalidOption = errors.Errorf("invalid option")

ErrInvalidOption if option is invalid.

View Source
var ErrKeepaliveCancel = errors.Errorf("keep alive cancel")

ErrKeepaliveCancel if action was cancelled.

View Source
var ErrMissingParameter = errors.New("missing parameter")

ErrMissingParameter if missing parameter.

View Source
var ErrNoCredentials = errors.New("no credentials")

ErrNoCredentials if no credentials.

View Source
var ErrNotAllowed = errors.New("not allowed")

ErrNotAllowed if not allowed.

View Source
var ErrNotFIDO2 = errors.Errorf("not a FIDO2 device")

ErrNotFIDO2 if device is not a FIDO2 device.

View Source
var ErrOperationDenied = errors.New("operation denied")

ErrOperationDenied if operation denied.

View Source
var ErrOther = errors.Errorf("other error")

ErrOther if other error?

View Source
var ErrPinAuthBlocked = errors.New("pin auth blocked")

ErrPinAuthBlocked if too many PIN failures.

View Source
var ErrPinInvalid = errors.New("pin invalid")

ErrPinInvalid if pin is wrong.

View Source
var ErrPinNotSet = errors.New("pin not set")

ErrPinNotSet if PIN is not set and is required for command.

View Source
var ErrPinPolicyViolation = errors.New("pin policy violation")

ErrPinPolicyViolation if PIN policy violation.

View Source
var ErrPinRequired = errors.New("pin required")

ErrPinRequired if PIN is required.

View Source
var ErrRX = errors.New("rx error")

ErrRX if there was an error receiving.

View Source
var ErrRXInvalidCBOR = errors.New("rx invalid cbor")

ErrRXInvalidCBOR if receiving invalid CBOR.

View Source
var ErrRXNotCBOR = errors.New("rx not CBOR")

ErrRXNotCBOR rx not CBOR.

View Source
var ErrTX = errors.New("tx error")

ErrTX if there was an error transmitting.

View Source
var ErrUPRequired = errors.New("up required")

ErrUPRequired if user presence is required.

View Source
var ErrUnsupportedOption = errors.New("unsupported option")

ErrUnsupportedOption if option is unsupported.

View Source
var ErrUserPresenceRequired = errors.New("user presence required")

ErrUserPresenceRequired is user presence required.

Functions

func RandBytes

func RandBytes(length int) []byte

RandBytes returns random bytes of length.

func SetLogger

func SetLogger(l Logger)

SetLogger sets logger for the package.

Types

type Assertion

type Assertion struct {
	// AuthDataCBOR is CBOR encoded authdata.
	// TODO: Include "raw" authdata if that is added to libfido2.
	AuthDataCBOR []byte
	Sig          []byte
	HMACSecret   []byte
	CredentialID []byte
	User         User
}

Assertion ...

type AssertionOpts

type AssertionOpts struct {
	Extensions []Extension
	UV         OptionValue
	UP         OptionValue
	HMACSalt   []byte
}

AssertionOpts ...

type Attestation

type Attestation struct {
	ClientDataHash []byte
	AuthData       []byte
	CredentialID   []byte
	CredentialType CredentialType
	PubKey         []byte
	Cert           []byte
	Sig            []byte
	Format         string
}

Attestation from MakeCredential ...

type BioTemplate

type BioTemplate struct {
	ID   string
	Name string
}

type CredProtect

type CredProtect string

CredProtect option if extension is supported.

const (
	// CredProtectNone if unset.
	CredProtectNone CredProtect = ""
	// CredProtectUVOptional UV optional
	CredProtectUVOptional CredProtect = "uv-optional"
	// CredProtectUVOptionalWithID UV optional with ID
	CredProtectUVOptionalWithID CredProtect = "uv-optional-with-id"
	// CredProtectUVRequired UV required
	CredProtectUVRequired CredProtect = "uv-required"
)

type Credential

type Credential struct {
	ID   []byte
	Type CredentialType
	User User
}

Credential ...

type CredentialType

type CredentialType int

CredentialType ...

const (
	// ES256 ...
	ES256 CredentialType = -7
	// EDDSA ...
	EDDSA CredentialType = -8

	// RS256 ...
	RS256 CredentialType = -257
)

func (CredentialType) String

func (c CredentialType) String() string

type CredentialsInfo

type CredentialsInfo struct {
	RKExisting  int64
	RKRemaining int64
}

CredentialsInfo ...

type Device

type Device struct {
	sync.Mutex
	// contains filtered or unexported fields
}

Device ...

func NewDevice

func NewDevice(path string) (*Device, error)

NewDevice opens device at path.

func (*Device) Assertion

func (d *Device) Assertion(
	rpID string,
	clientDataHash []byte,
	credentialIDs [][]byte,
	pin string,
	opts *AssertionOpts) (*Assertion, error)

Assertion ...

Example
if os.Getenv("FIDO2_EXAMPLES") != "1" {
	return
}
locs, err := libfido2.DeviceLocations()
if err != nil {
	log.Fatal(err)
}
if len(locs) == 0 {
	log.Println("No devices")
	return
}

log.Printf("Using device: %+v\n", locs[0])
path := locs[0].Path
device, err := libfido2.NewDevice(path)
if err != nil {
	log.Fatal(err)
}

cdh := libfido2.RandBytes(32)
userID := libfido2.RandBytes(32)
salt := libfido2.RandBytes(32)
pin := "12345"

attest, err := device.MakeCredential(
	cdh,
	libfido2.RelyingParty{
		ID: "keys.pub",
	},
	libfido2.User{
		ID:   userID,
		Name: "gabriel",
	},
	libfido2.ES256, // Algorithm
	pin,
	&libfido2.MakeCredentialOpts{
		Extensions: []libfido2.Extension{libfido2.HMACSecretExtension},
		RK:         libfido2.True,
	},
)
if err != nil {
	log.Fatal(err)
}

log.Printf("Attestation:\n")
log.Printf("AuthData: %s\n", hex.EncodeToString(attest.AuthData))
log.Printf("ClientDataHash: %s\n", hex.EncodeToString(attest.ClientDataHash))
log.Printf("ID: %s\n", hex.EncodeToString(attest.CredentialID))
log.Printf("Type: %s\n", attest.CredentialType)
log.Printf("Sig: %s\n", hex.EncodeToString(attest.Sig))

assertion, err := device.Assertion(
	"keys.pub",
	cdh,
	[][]byte{attest.CredentialID},
	pin,
	&libfido2.AssertionOpts{
		Extensions: []libfido2.Extension{libfido2.HMACSecretExtension},
		UP:         libfido2.True,
		HMACSalt:   salt,
	},
)
if err != nil {
	log.Fatal(err)
}

log.Printf("Assertion:\n")
log.Printf("AuthDataCBOR: %s\n", hex.EncodeToString(assertion.AuthDataCBOR))
log.Printf("HMACSecret: %s\n", hex.EncodeToString(assertion.HMACSecret))
log.Printf("Sig: %s\n", hex.EncodeToString(assertion.Sig))
log.Printf("CredentialID: %s\n", hex.EncodeToString(assertion.CredentialID))
log.Printf("User.ID: %s\n", hex.EncodeToString(assertion.User.ID))
Output:

Example (HmacSecret)
if os.Getenv("FIDO2_EXAMPLES") != "1" {
	return
}
locs, err := libfido2.DeviceLocations()
if err != nil {
	log.Fatal(err)
}
if len(locs) == 0 {
	log.Fatalf("No devices")
	return
}
log.Printf("Using device: %+v\n", locs[0])
path := locs[0].Path
device, err := libfido2.NewDevice(path)
if err != nil {
	log.Fatal(err)
}

name := locs[0].Product + "/" + locs[0].Manufacturer

cdh := bytes.Repeat([]byte{0x01}, 32)
rpID := "keys.pub"
pin := "12345"

testVectors := map[string]testVector{
	"SoloKey 4.0/SoloKeys": testVector{
		CredentialID: "91874f4c3d580370bf5b5301130ecc034f5927d955f5399ebad267f5666c78598942d489f10d4f4780fad392eb2962d065bdd3574375e80c42218dadd199ed3ffe7deb010000",
		Secret:       "dd67d3aa73b13b7bb71ad0fe13cf8a247632a3508d7c9906ef6dc823906c3103",
	},
	"Security Key by Yubico/Yubico": testVector{
		CredentialID: "c4fe75012ed137a0afcaa59ab36f0722b9b05849b2203fc4ba4f304033015eaafdbee823ee42dce88b4ae4d943926de3cc93e797004d108ed2465c675ae568e6",
		Secret:       "f3d37d52ca7a12cf05c34bd3c13ddc3288b723018697347e6ac5ea79b7d3cc83",
	},
}

testVector, ok := testVectors[name]
if !ok {
	log.Fatalf("No test vector found for %s", name)
}

credentialID, err := hex.DecodeString(testVector.CredentialID)
if err != nil {
	log.Fatal(err)
}
salt := bytes.Repeat([]byte{0x02}, 32)

assertion, err := device.Assertion(
	rpID,
	cdh,
	[][]byte{credentialID},
	pin,
	&libfido2.AssertionOpts{
		Extensions: []libfido2.Extension{libfido2.HMACSecretExtension},
		// UP:         libfido2.True, // Required for some devices
		// UV:         libfido2.True, // Required for some devices
		HMACSalt: salt,
	},
)
if err != nil {
	log.Fatal(err)
}

if testVector.Secret != hex.EncodeToString(assertion.HMACSecret) {
	log.Fatalf("Expected %s", testVector.Secret)
}
Output:

func (*Device) BioDelete

func (d *Device) BioDelete(pin, templateId string) error

BioDelete deletes a bio template.

Example
if os.Getenv("FIDO2_EXAMPLES") != "1" {
	return
}
locs, err := libfido2.DeviceLocations()
if err != nil {
	log.Fatal(err)
}
if len(locs) == 0 {
	log.Fatal("No devices")
	return
}

log.Printf("Using device: %+v\n", locs[0])
path := locs[0].Path
device, err := libfido2.NewDevice(path)
if err != nil {
	log.Fatal(err)
}

pin := "12345"

templates, err := device.BioList(pin)
if err != nil {
	log.Fatal(err)
}

for _, template := range templates {
	err := device.BioDelete(pin, template.ID)
	if err != nil {
		log.Fatal(err)
	}
}
Output:

func (*Device) BioEnroll

func (d *Device) BioEnroll(pin string) error

BioEnrollment starts a bio-enabled device enrollment

func (*Device) BioList

func (d *Device) BioList(pin string) ([]BioTemplate, error)

BioList lists all bio templates.

Example
if os.Getenv("FIDO2_EXAMPLES") != "1" {
	return
}
locs, err := libfido2.DeviceLocations()
if err != nil {
	log.Fatal(err)
}
if len(locs) == 0 {
	log.Fatal("No devices")
	return
}

log.Printf("Using device: %+v\n", locs[0])
path := locs[0].Path
device, err := libfido2.NewDevice(path)
if err != nil {
	log.Fatal(err)
}

pin := "12345"

templates, err := device.BioList(pin)
if err != nil {
	log.Fatal(err)
}

log.Println(templates)
Output:

func (*Device) BioSetTemplateName

func (d *Device) BioSetTemplateName(pin, templateId, name string) error

BioSetTemplateName sets the name of template with templateId.

Example
if os.Getenv("FIDO2_EXAMPLES") != "1" {
	return
}
locs, err := libfido2.DeviceLocations()
if err != nil {
	log.Fatal(err)
}
if len(locs) == 0 {
	log.Fatal("No devices")
	return
}

log.Printf("Using device: %+v\n", locs[0])
path := locs[0].Path
device, err := libfido2.NewDevice(path)
if err != nil {
	log.Fatal(err)
}

pin := "12345"

templates, err := device.BioList(pin)
if err != nil {
	log.Fatal(err)
}

if len(templates) == 0 {
	log.Fatal("no bio template")
	return
}

template := templates[0]
newName := "newName"

device.BioSetTemplateName(pin, template.ID, newName)
Output:

func (*Device) CTAPHIDInfo

func (d *Device) CTAPHIDInfo() (*HIDInfo, error)

CTAPHIDInfo ...

func (*Device) Cancel

func (d *Device) Cancel() error

Cancel an action.

func (*Device) Credentials

func (d *Device) Credentials(rpID string, pin string) ([]*Credential, error)

Credentials lists credentials (if credMgmt is supported).

Example
if os.Getenv("FIDO2_EXAMPLES") != "1" {
	return
}
libfido2.SetLogger(libfido2.NewLogger(libfido2.DebugLevel))

locs, err := libfido2.DeviceLocations()
if err != nil {
	log.Fatal(err)
}
if len(locs) == 0 {
	log.Println("No devices")
	return
}

log.Printf("Using device: %+v\n", locs[0])
path := locs[0].Path
device, err := libfido2.NewDevice(path)
if err != nil {
	log.Fatal(err)
}

pin := "12345"

info, err := device.CredentialsInfo(pin)
if err != nil {
	log.Fatal(err)
}
log.Printf("Info: %+v\n", info)

rps, err := device.RelyingParties(pin)
if err != nil {
	log.Fatal(err)
}
for _, rp := range rps {
	log.Printf("RP{ID: %s, Name: %s}\n", rp.ID, rp.Name)
	creds, err := device.Credentials(rp.ID, pin)
	if err != nil {
		log.Fatal(err)
	}
	for _, cred := range creds {
		log.Printf("User{ID: %s, Name: %s}\n", hex.EncodeToString(cred.User.ID), cred.User.Name)
		log.Printf("ID: %s\n", hex.EncodeToString(cred.ID))
		log.Printf("Type: %s\n", cred.Type)
		log.Printf("\n")
	}
}
Output:

func (*Device) CredentialsInfo

func (d *Device) CredentialsInfo(pin string) (*CredentialsInfo, error)

CredentialsInfo ...

func (*Device) DeleteCredential

func (d *Device) DeleteCredential(credID []byte, pin string) error

DeleteCredential deletes a resident credential (if credMgmt is supported).

Example
if os.Getenv("FIDO2_EXAMPLES") != "1" {
	return
}
locs, err := libfido2.DeviceLocations()
if err != nil {
	log.Fatal(err)
}
if len(locs) == 0 {
	log.Fatal("No devices")
	return
}

log.Printf("Using device: %+v\n", locs[0])
path := locs[0].Path
device, err := libfido2.NewDevice(path)
if err != nil {
	log.Fatal(err)
}

pin := "12345"

info, err := device.CredentialsInfo(pin)
if err != nil {
	log.Fatal(err)
}
log.Printf("Info: %+v\n", info)

rps, err := device.RelyingParties(pin)
if err != nil {
	log.Fatal(err)
}
for _, rp := range rps {
	creds, err := device.Credentials(rp.ID, pin)
	if err != nil {
		log.Fatal(err)
	}
	for _, cred := range creds {
		log.Printf("Deleting: %s\n", hex.EncodeToString(cred.ID))
		if err := device.DeleteCredential(cred.ID, pin); err != nil {
			log.Fatal(err)
		}
	}
}
Output:

func (*Device) IsFIDO2

func (d *Device) IsFIDO2() (bool, error)

IsFIDO2 returns true if device supports FIDO2.

func (*Device) MakeCredential

func (d *Device) MakeCredential(
	clientDataHash []byte,
	rp RelyingParty,
	user User,
	typ CredentialType,
	pin string,
	opts *MakeCredentialOpts) (*Attestation, error)

MakeCredential represents authenticatorMakeCredential (0x01). RP, User ID and name are required by some devices, so we return an error if missing.

See https://fidoalliance.org/specs/fido2/fido-client-to-authenticator-protocol-v2.1-rd-20191217.html#authenticatorMakeCredential

Example
if os.Getenv("FIDO2_EXAMPLES") != "1" {
	return
}
libfido2.SetLogger(libfido2.NewLogger(libfido2.DebugLevel))

locs, err := libfido2.DeviceLocations()
if err != nil {
	log.Fatal(err)
}
if len(locs) == 0 {
	log.Println("No devices")
	return
}

log.Printf("Using device: %+v\n", locs[0])
path := locs[0].Path
device, err := libfido2.NewDevice(path)
if err != nil {
	log.Fatal(err)
}

cdh := libfido2.RandBytes(32)
userID := libfido2.RandBytes(32)
pin := "12345"

attest, err := device.MakeCredential(
	cdh,
	libfido2.RelyingParty{
		ID:   "keys.pub",
		Name: "keys.pub",
	},
	libfido2.User{
		ID:          userID,
		Name:        "gabriel",
		DisplayName: "Gabriel",
	},
	libfido2.ES256, // Algorithm
	pin,
	nil,
)
if err != nil {
	log.Fatal(err)
}

log.Printf("Attestation:\n")
log.Printf("AuthData: %s\n", hex.EncodeToString(attest.AuthData))
log.Printf("ClientDataHash: %s\n", hex.EncodeToString(attest.ClientDataHash))
log.Printf("ID: %s\n", hex.EncodeToString(attest.CredentialID))
log.Printf("Type: %d\n", attest.CredentialType)
log.Printf("Sig: %s\n", hex.EncodeToString(attest.Sig))
Output:

Example (HmacSecret)
if os.Getenv("FIDO2_EXAMPLES") != "1" {
	return
}
locs, err := libfido2.DeviceLocations()
if err != nil {
	log.Fatal(err)
}
if len(locs) == 0 {
	log.Fatal("No devices")
	return
}

log.Printf("Using device: %+v\n", locs[0])
path := locs[0].Path
device, err := libfido2.NewDevice(path)
if err != nil {
	log.Fatal(err)
}

cdh := bytes.Repeat([]byte{0x01}, 32)
rpID := "keys.pub"
pin := "12345"

attest, err := device.MakeCredential(
	cdh,
	libfido2.RelyingParty{
		ID:   rpID,
		Name: "hmac-secret",
	},
	libfido2.User{
		ID:   libfido2.RandBytes(16),
		Name: "hmac-secret",
	},
	libfido2.ES256, // Algorithm
	pin,
	&libfido2.MakeCredentialOpts{
		Extensions: []libfido2.Extension{libfido2.HMACSecretExtension},
		RK:         libfido2.True,
		// UV:          libfido2.True,
		// CredProtect: libfido2.CredProtectUVRequired,
	},
)
if err != nil {
	log.Fatal(err)
}

log.Printf("Credential ID: %s\n", hex.EncodeToString(attest.CredentialID))
Output:

func (*Device) RelyingParties

func (d *Device) RelyingParties(pin string) ([]*RelyingParty, error)

RelyingParties ...

func (*Device) Reset

func (d *Device) Reset() error

Reset represents authenticatorReset. https://fidoalliance.org/specs/fido2/fido-client-to-authenticator-protocol-v2.1-rd-20191217.html#authenticatorReset The actual user-flow to perform a reset is outside the scope of the FIDO2 specification, and may therefore vary depending on the authenticator. Yubico authenticators will return ErrNotAllowed if a reset is issued later than 5 seconds after power-up, and ErrActionTimeout if the user fails to confirm the reset by touching the key within 30 seconds.

Example
if os.Getenv("FIDO2_EXAMPLES") != "1" {
	return
}
libfido2.SetLogger(libfido2.NewLogger(libfido2.DebugLevel))

if os.Getenv("FIDO2_EXAMPLES_RESET") != "1" {
	log.Println("only runs if FIDO2_EXAMPLES_RESET=1")
	return
}

locs, err := libfido2.DeviceLocations()
if err != nil {
	log.Fatal(err)
}
if len(locs) == 0 {
	log.Println("No devices")
	return
}

log.Printf("Using device: %+v\n", locs[0])
path := locs[0].Path
device, err := libfido2.NewDevice(path)
if err != nil {
	log.Fatal(err)
}

log.Printf("Resetting: %+v\n", locs[0])
if err := device.Reset(); err != nil {
	log.Fatal(err)
}
Output:

func (*Device) RetryCount

func (d *Device) RetryCount() (int, error)

RetryCount ...

func (*Device) SetPIN

func (d *Device) SetPIN(pin string, old string) error

SetPIN ...

Example
if os.Getenv("FIDO2_EXAMPLES_SET_PIN") != "1" {
	return
}
libfido2.SetLogger(libfido2.NewLogger(libfido2.DebugLevel))

locs, err := libfido2.DeviceLocations()
if err != nil {
	log.Fatal(err)
}
if len(locs) == 0 {
	log.Println("No devices")
	return
}

log.Printf("Using device: %+v\n", locs[0])
path := locs[0].Path
device, err := libfido2.NewDevice(path)
if err != nil {
	log.Fatal(err)
}

pin := "12345"
if err := device.SetPIN(pin, ""); err != nil {
	log.Fatal(err)
}
Output:

func (*Device) Type

func (d *Device) Type() (DeviceType, error)

Type returns device type.

type DeviceInfo

type DeviceInfo struct {
	Versions   []string
	Extensions []string
	AAGUID     []byte
	Options    []Option
	Protocols  []byte
}

DeviceInfo ...

type DeviceLocation

type DeviceLocation struct {
	Path         string
	ProductID    int16
	VendorID     int16
	Manufacturer string
	Product      string
}

DeviceLocation ...

func DeviceLocations

func DeviceLocations() ([]*DeviceLocation, error)

DeviceLocations lists found devices.

Example
if os.Getenv("FIDO2_EXAMPLES") != "1" {
	return
}
libfido2.SetLogger(libfido2.NewLogger(libfido2.DebugLevel))

locs, err := libfido2.DeviceLocations()
if err != nil {
	log.Fatal(err)
}

for _, loc := range locs {
	log.Printf("%+v\n", loc)
	device, err := libfido2.NewDevice(loc.Path)
	if err != nil {
		log.Fatal(err)
	}

	hidInfo, err := device.CTAPHIDInfo()
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("CTAPHIDInfo: %+v\n", hidInfo)

	info, err := device.Info()
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Info: %+v\n", info)
}
Output:

type DeviceType

type DeviceType string

DeviceType is latest type the device supports.

const (
	// UnknownDevice ...
	UnknownDevice DeviceType = ""
	// FIDO2 ...
	FIDO2 DeviceType = "fido2"
	// U2F ...
	U2F DeviceType = "u2f"
)

type Error

type Error struct {
	Code int
}

Error is a generic error with code.

func (Error) Error

func (e Error) Error() string

type Extension

type Extension string

Extension ...

const (
	// HMACSecretExtension for HMAC secret extension.
	// https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-client-to-authenticator-protocol-v2.0-rd-20180702.html#sctn-hmac-secret-extension
	HMACSecretExtension Extension = "hmac-secret"
	// CredProtectExtension for credProtect extension.
	CredProtectExtension Extension = "credProtect"
)

type HIDInfo

type HIDInfo struct {
	Protocol uint8
	Major    uint8
	Minor    uint8
	Build    uint8
	Flags    uint8
}

HIDInfo ...

type LogLevel

type LogLevel int

LogLevel ...

const (
	// DebugLevel ...
	DebugLevel LogLevel = 3
	// InfoLevel ...
	InfoLevel LogLevel = 2
	// WarnLevel ...
	WarnLevel LogLevel = 1
	// ErrLevel ...
	ErrLevel LogLevel = 0
)

func (LogLevel) String

func (l LogLevel) String() string

type Logger

type Logger interface {
	Debugf(format string, args ...interface{})
	Infof(format string, args ...interface{})
	Warningf(format string, args ...interface{})
	Errorf(format string, args ...interface{})
	Fatalf(format string, args ...interface{})
}

Logger interface used in this package.

func NewLogger

func NewLogger(lev LogLevel) Logger

NewLogger ...

type MakeCredentialOpts

type MakeCredentialOpts struct {
	Extensions  []Extension
	RK          OptionValue
	UV          OptionValue
	CredProtect CredProtect
}

MakeCredentialOpts ...

type Option

type Option struct {
	Name  string
	Value OptionValue
}

Option ...

type OptionValue

type OptionValue string

OptionValue is value for option.

const (
	// Default is device default (omitted).
	Default OptionValue = ""
	// True is enabled/yes/true option.
	True OptionValue = "true"
	// False is disabled/no/false option.
	False OptionValue = "false"
)

type RelyingParty

type RelyingParty struct {
	ID   string
	Name string
}

RelyingParty ...

type User

type User struct {
	ID          []byte
	Name        string
	DisplayName string
	Icon        string
}

User ...

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL