Documentation ¶
Index ¶
- Variables
- func RandBytes(length int) []byte
- func SetLogger(l Logger)
- type Assertion
- type AssertionOpts
- type Attestation
- type BioTemplate
- type CredProtect
- type Credential
- type CredentialType
- type CredentialsInfo
- type Device
- func (d *Device) Assertion(rpID string, clientDataHash []byte, credentialIDs [][]byte, pin string, ...) (*Assertion, error)
- func (d *Device) BioDelete(pin, templateId string) error
- func (d *Device) BioEnroll(pin string) error
- func (d *Device) BioList(pin string) ([]BioTemplate, error)
- func (d *Device) BioSetTemplateName(pin, templateId, name string) error
- func (d *Device) CTAPHIDInfo() (*HIDInfo, error)
- func (d *Device) Cancel() error
- func (d *Device) Credentials(rpID string, pin string) ([]*Credential, error)
- func (d *Device) CredentialsInfo(pin string) (*CredentialsInfo, error)
- func (d *Device) DeleteCredential(credID []byte, pin string) error
- func (d *Device) Info() (*DeviceInfo, error)
- func (d *Device) IsFIDO2() (bool, error)
- func (d *Device) MakeCredential(clientDataHash []byte, rp RelyingParty, user User, typ CredentialType, ...) (*Attestation, error)
- func (d *Device) RelyingParties(pin string) ([]*RelyingParty, error)
- func (d *Device) Reset() error
- func (d *Device) RetryCount() (int, error)
- func (d *Device) SetPIN(pin string, old string) error
- func (d *Device) Type() (DeviceType, error)
- type DeviceInfo
- type DeviceLocation
- type DeviceType
- type Error
- type Extension
- type HIDInfo
- type LogLevel
- type Logger
- type MakeCredentialOpts
- type Option
- type OptionValue
- type RelyingParty
- type User
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrActionTimeout = errors.New("action timed out")
ErrActionTimeout if action timed out.
var ErrInternal = errors.New("internal error")
ErrInternal internal error.
var ErrInvalidArgument = errors.New("invalid argument")
ErrInvalidArgument if arguments are invalid.
var ErrInvalidCommand = errors.New("invalid command")
ErrInvalidCommand if command is not supported.
var ErrInvalidCredential = errors.New("invalid credential")
ErrInvalidCredential if credential is invalid.
var ErrInvalidLength = errors.New("invalid length")
ErrInvalidLength if invalid length.
var ErrInvalidOption = errors.Errorf("invalid option")
ErrInvalidOption if option is invalid.
var ErrKeepaliveCancel = errors.Errorf("keep alive cancel")
ErrKeepaliveCancel if action was cancelled.
var ErrMissingParameter = errors.New("missing parameter")
ErrMissingParameter if missing parameter.
var ErrNoCredentials = errors.New("no credentials")
ErrNoCredentials if no credentials.
var ErrNotAllowed = errors.New("not allowed")
ErrNotAllowed if not allowed.
var ErrNotFIDO2 = errors.Errorf("not a FIDO2 device")
ErrNotFIDO2 if device is not a FIDO2 device.
var ErrOperationDenied = errors.New("operation denied")
ErrOperationDenied if operation denied.
var ErrOther = errors.Errorf("other error")
ErrOther if other error?
var ErrPinAuthBlocked = errors.New("pin auth blocked")
ErrPinAuthBlocked if too many PIN failures.
var ErrPinInvalid = errors.New("pin invalid")
ErrPinInvalid if pin is wrong.
var ErrPinNotSet = errors.New("pin not set")
ErrPinNotSet if PIN is not set and is required for command.
var ErrPinPolicyViolation = errors.New("pin policy violation")
ErrPinPolicyViolation if PIN policy violation.
var ErrPinRequired = errors.New("pin required")
ErrPinRequired if PIN is required.
var ErrRX = errors.New("rx error")
ErrRX if there was an error receiving.
var ErrRXInvalidCBOR = errors.New("rx invalid cbor")
ErrRXInvalidCBOR if receiving invalid CBOR.
var ErrRXNotCBOR = errors.New("rx not CBOR")
ErrRXNotCBOR rx not CBOR.
var ErrTX = errors.New("tx error")
ErrTX if there was an error transmitting.
var ErrUPRequired = errors.New("up required")
ErrUPRequired if user presence is required.
var ErrUnsupportedOption = errors.New("unsupported option")
ErrUnsupportedOption if option is unsupported.
var ErrUserPresenceRequired = errors.New("user presence required")
ErrUserPresenceRequired is user presence required.
Functions ¶
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 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 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 ¶
CredentialsInfo ...
type Device ¶
Device ...
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 ¶
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) 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 ¶
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) 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 ¶
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) Info ¶
func (d *Device) Info() (*DeviceInfo, error)
Info represents authenticatorGetInfo (0x04). https://fidoalliance.org/specs/fido2/fido-client-to-authenticator-protocol-v2.1-rd-20191217.html#authenticatorGetInfo
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.
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 ¶
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) SetPIN ¶
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:
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 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 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.
type MakeCredentialOpts ¶
type MakeCredentialOpts struct { Extensions []Extension RK OptionValue UV OptionValue CredProtect CredProtect }
MakeCredentialOpts ...
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" )