piv

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Nov 28, 2023 License: Apache-2.0 Imports: 25 Imported by: 0

README

go-piv: A Go implementation of the PIV standards for smart card certificate management

GitHub build goreportcard Codecov License GitHub go.mod Go version Go Reference

YubiKeys provide an applet implementing the PIV standards for managing certificates on a smart card. This applet is a simpler alternative to GPG for managing asymmetric keys on a YubiKey.

This package is an alternative to Paul Tagliamonte's go-ykpiv, a wrapper for YubiKey's ykpiv.h C library. This package aims to provide:

  • Better error messages
  • Idiomatic Go APIs
  • Modern features such as PIN protected management keys

This package is a fork from github.com/go-piv/piv-go with the following changes:

  • Replacement of in-repo PCSC bindings with github.com/ebfe/scard.
  • Improved CI tests, linting and repository structure.
  • Made repository REUSE compliant.
  • Removal of Google's CLA.

Examples

Signing

The piv-go package can be used to generate keys and store certificates on a YubiKey. This uses a management key to generate new keys on the applet, and a PIN for signing operations. The package provides default PIN values. If the PIV credentials on the YubiKey haven't been modified, the follow code generates a new EC key on the smart card, and provides a signing interface:

// List all smart cards connected to the system.
cards, err := piv.Cards()
if err != nil {
    // ...
}

// Find a YubiKey and open the reader.
var c *piv.Card
for _, card := range cards {
    if strings.Contains(strings.ToLower(card), "yubikey") {
        if c, err = piv.Open(card); err != nil {
            // ...
        }
        break
    }
}

if c == nil {
    // ...
}

// Generate a private key on the YubiKey.
key := piv.Key{
    Algorithm:   piv.AlgorithmEC256,
    PINPolicy:   piv.PINPolicyAlways,
    TouchPolicy: piv.TouchPolicyAlways,
}

pub, err := c.GenerateKey(piv.DefaultManagementKey, piv.SlotAuthentication, key)
if err != nil {
    // ...
}

auth := piv.KeyAuth{PIN: piv.DefaultPIN}
priv, err := c.PrivateKey(piv.SlotAuthentication, pub, auth)
if err != nil {
    // ...
}
// Use private key to sign or decrypt.
PINs

The PIV applet has three unique credentials:

  • Management key (3DES key) used to generate new keys on the YubiKey.
  • PIN (up to 8 digits, usually 6) used to access signing operations.
  • PUK (up to 8 digits) used to unblock the PIN. Usually set once and thrown away or managed by an administrator.

piv-go implements PIN protected management keys to store the management key on the YubiKey. This allows users to only provide a PIN and still access management capabilities.

The following code generates new, random credentials for a YubiKey:

newPINInt, err := rand.Int(rand.Reader, big.NewInt(1_000_000))
if err != nil {
    // ...
}

newPUKInt, err := rand.Int(rand.Reader, big.NewInt(100_000_000))
if err != nil {
    // ...
}

var newKey ManagementKey
if _, err := io.ReadFull(rand.Reader, newKey[:]); err != nil {
    // ...
}

// Format with leading zeros.
newPIN := fmt.Sprintf("%06d", newPINInt)
newPUK := fmt.Sprintf("%08d", newPUKInt)

// Set all values to a new value.
if err := c.SetManagementKey(piv.DefaultManagementKey, newKey); err != nil {
    // ...
}

if err := c.SetPUK(piv.DefaultPUK, newPUK); err != nil {
    // ...
}

if err := c.SetPIN(piv.DefaultPIN, newPIN); err != nil {
    // ...
}

// Store management key on the YubiKey.
m := piv.Metadata{ManagementKey: &newKey}
if err := c.SetMetadata(newKey, m); err != nil {
    // ...
}

fmt.Println("Credentials set. Your PIN is: %s", newPIN)

The user can use the PIN later to fetch the management key:

m, err := c.Metadata(pin)
if err != nil {
    // ...
}

if m.ManagementKey == nil {
    // ...
}

key := *m.ManagementKey
Certificates

The PIV applet can also store X.509 certificates on the YubiKey:

cert, err := x509.ParseCertificate(certDER)
if err != nil {
    // ...
}

if err := c.SetCertificate(managementKey, piv.SlotAuthentication, cert); err != nil {
    // ...
}

The certificate can later be used in combination with the private key. For example, to serve TLS traffic:

cert, err := c.Certificate(piv.SlotAuthentication)
if err != nil {
    // ...
}

priv, err := c.PrivateKey(piv.SlotAuthentication, cert.PublicKey, auth)
if err != nil {
    // ...
}

s := &http.Server{
    TLSConfig: &tls.Config{
        Certificates: []tls.Certificate{
            {
                Certificate: [][]byte{cert.Raw},
                PrivateKey:  priv,
            },
        },
    },
    Handler: myHandler,
}
Attestation

YubiKeys can attest that a particular key was generated on the smart card, and that it was set with specific PIN and touch policies. The client generates a key, then asks the YubiKey to sign an attestation certificate:

// Get the YubiKey's attestation certificate, which is signed by Yubico.
yubiKeyAttestationCert, err := c.AttestationCertificate()
if err != nil {
    // ...
}

// Generate a key on the YubiKey and generate an attestation certificate for
// that key. This will be signed by the YubiKey's attestation certificate.
key := piv.Key{
    Algorithm:   piv.AlgorithmEC256,
    PINPolicy:   piv.PINPolicyAlways,
    TouchPolicy: piv.TouchPolicyAlways,
}
if _, err := c.GenerateKey(managementKey, piv.SlotAuthentication, key); err != nil {
    // ...
}
slotAttestationCertificate, err := c.Attest(piv.SlotAuthentication)
if err != nil {
    // ...
}

// Send certificates to server.

A CA can then verify the attestation, proving a key was generated on the card and enforce policy:

// Server receives both certificates, then proves a key was generated on the
// YubiKey.
a, err := piv.Verify(yubiKeyAttestationCert, slotAttestationCertificate)
if err != nil {
    // ...
}
if a.TouchPolicy != piv.TouchPolicyAlways {
    // ...
}

// Record YubiKey's serial number and public key.
pub := slotAttestationCertificate.PublicKey
serial := a.Serial

Installation

On MacOS, piv-go doesn't require any additional packages.

To build on Linux, piv-go requires PCSC lite. To install on Debian-based distributions, run:

Debian, Ubuntu
sudo apt-get install libpcsclite-dev
RHEL, Fedora, Rocky Linux
sudo yum install pcsc-lite-devel
FreeBSD
sudo pkg install pcsc-lite
Windows

No prerequisites are needed. The default driver by Microsoft supports all functionalities which get tested by unit tests. However if you run into problems try the official YubiKey Smart Card Minidriver. Yubico states on their website the driver adds additional smart functionality.

Please notice the following:

Windows support is best effort due to lack of test hardware. This means the maintainers will take patches for Windows, but if you encounter a bug or the build is broken, you may be asked to fix it.

Non-YubiKey smart cards

Non-YubiKey smart cards that implement the PIV standard are not officially supported due to a lack of test hardware. However, PRs that fix integrations with other smart cards are welcome, and piv-go will attempt to not break that support.

Testing

Tests automatically find connected available YubiKeys, but won't modify the smart card without the TEST_DANGEROUS_WIPE_REAL_CARD=1 environment variable is set. To let the tests modify your YubiKey's PIV applet, run:

TEST_DANGEROUS_WIPE_REAL_CARD=1 go test -v ./piv

Longer tests can be skipped with the --test.short flag.

TEST_DANGEROUS_WIPE_REAL_CARD=1  go test -v --short ./piv

Why?

YubiKey's C PIV library, ykpiv, is brittle. The error messages aren't terrific, and while it has debug options, plumbing them through isn't idiomatic or convenient.

ykpiv wraps PC/SC APIs available on Windows, Mac, and Linux. There's no requirement for it to be written in any particular langauge. As an alternative to pault.ag/go/ykpiv this package re-implements ykpiv in Go instead of calling it.

Authors

go-piv has been forked from go-piv/piv-go at commit 8c3a0ff

License

go-piv is licensed under the Apache 2.0 license.

  • SPDX-FileCopyrightText: 2020 Google LLC
  • SPDX-FileCopyrightText: 2023 Steffen Vogel post@steffenvogel.de
  • SPDX-License-Identifier: Apache-2.0

Documentation

Overview

Package piv implements management functionality for the YubiKey PIV applet.

Index

Constants

View Source
const (
	AlgTypeRSA algorithmType = iota + 1
	AlgTypeECCP
	AlgTypeEd25519
)
View Source
const (
	FormFactorUSBAKeychain          = 0x1
	FormFactorUSBANano              = 0x2
	FormFactorUSBCKeychain          = 0x3
	FormFactorUSBCNano              = 0x4
	FormFactorUSBCLightningKeychain = 0x5

	FormFactorUSBAKeychainFIPS          = 0x80 + FormFactorUSBAKeychain
	FormFactorUSBANanoFIPS              = 0x80 + FormFactorUSBANano
	FormFactorUSBCKeychainFIPS          = 0x80 + FormFactorUSBCKeychain
	FormFactorUSBCNanoFIPS              = 0x80 + FormFactorUSBCNano
	FormFactorUSBCLightningKeychainFIPS = 0x80 + FormFactorUSBCLightningKeychain
)

Formfactors recognized by this package. See the reference for more information: https://developers.yubico.com/yubikey-manager/Config_Reference.html#_form_factor

View Source
const (
	// DefaultPIN for the PIV applet. The PIN is used to change the Management Key,
	// and slots can optionally require it to perform signing operations.
	DefaultPIN = "123456"

	// DefaultPUK for the PIV applet. The PUK is only used to reset the PIN when
	// the card's PIN retries have been exhausted.
	DefaultPUK = "12345678"
)

Variables

View Source
var (
	SupportsAttestation    = yubikey.HasVersionStr("4.3.0")
	SupportsMetadata       = yubikey.HasVersionStr("5.3.0")
	SupportsAlgorithmEC384 = yubikey.HasVersionStr("4.3.0")
)
View Source
var (
	SlotAuthentication     = Slot{keyAuthentication, doCertAuthentication}
	SlotSignature          = Slot{keySignature, doCertSignature}
	SlotCardAuthentication = Slot{keyCardAuthentication, doCertCardAuthentication}
	SlotKeyManagement      = Slot{keyKeyManagement, doCertKeyManagement}

	// YubiKey specific
	SlotAttestation = Slot{keyAttestation, doCertAttestation}
)

Slot combinations pre-defined by this package.

Object IDs are specified in NIST 800-73-4 section 4.3: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf#page=30

Key IDs are specified in NIST 800-73-4 section 5.1: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf#page=32

View Source
var DefaultManagementKey = ManagementKey{
	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
}

DefaultManagementKey for the PIV applet. The Management Key is a Triple-DES key required for slot actions such as generating keys, setting certificates, and signing.

View Source
var ErrNotFound = errors.New("data object or application not found")

ErrNotFound is returned when the requested object on the smart card is not found.

Functions

This section is empty.

Types

type Algorithm

type Algorithm byte

Algorithm represents a specific algorithm and bit size supported by the PIV specification.

const (
	Alg3DES    Algorithm = 0x03
	AlgRSA1024 Algorithm = 0x06
	AlgRSA2048 Algorithm = 0x07
	AlgECCP256 Algorithm = 0x11
	AlgECCP384 Algorithm = 0x14

	// Non-standard; as implemented by SoloKeys. Chosen for low probability of eventual
	// clashes, if and when PIV standard adds Ed25519 support
	AlgEd25519 Algorithm = 0x22
)

Algorithms supported by this package. Note that not all cards will support every algorithm.

AlgorithmEd25519 is currently only implemented by SoloKeys.

For algorithm discovery, see: https://github.com/ericchiang/piv-go/issues/1

type Attestation

type Attestation struct {
	// Version of the YubiKey's firmware.
	Version iso.Version

	// Serial is the YubiKey's serial number.
	Serial uint32

	// FormFactor indicates the physical type of the YubiKey.
	//
	// FormFactor may be empty FormFactor(0) for some YubiKeys.
	FormFactor FormFactor

	// PINPolicy set on the slot.
	PINPolicy PINPolicy
	// TouchPolicy set on the slot.
	TouchPolicy TouchPolicy

	// Slot is the inferred slot the attested key resides in based on the
	// common name in the attestation. If the slot cannot be determined,
	// this field will be an empty struct.
	Slot Slot
}

Attestation returns additional information about a key attested to be generated on a card. See https://developers.yubico.com/PIV/Introduction/PIV_attestation.html for more information.

func Verify

func Verify(attestationCert, slotCert *x509.Certificate) (*Attestation, error)

Verify proves that a key was generated on a YubiKey. It ensures the slot and YubiKey certificate chains up to the Yubico CA, parsing additional information out of the slot certificate, such as the touch and PIN policies of a key.

type AuthError

type AuthError struct {
	// Retries is the number of retries remaining if this error resulted from a retry-able
	// authentication attempt.  If the authentication method is blocked or does not support
	// retries, this will be 0.
	Retries int
}

AuthError is an error indicating an authentication error occurred (wrong PIN or blocked).

func (AuthError) Error

func (v AuthError) Error() string

type Card

type Card struct {
	*iso.Card

	Rand io.Reader
	// contains filtered or unexported fields
}

Card is an exclusive open connection to a Card smart card. While open, no other process can query the given card.

To release the connection, call the Close method.

func NewCard added in v0.3.0

func NewCard(card *iso.Card) (pivCard *Card, err error)

func (*Card) Attest

func (c *Card) Attest(slot Slot) (cert *x509.Certificate, err error)

Attest generates a certificate for a key, signed by the YubiKey's attestation certificate. This can be used to prove a key was generate on a specific YubiKey.

This method is only supported for YubiKey versions >= 4.3.0. https://developers.yubico.com/PIV/Introduction/PIV_attestation.html

Certificates returned by this method MUST NOT be used for anything other than attestation or determining the slots public key. For example, the certificate is NOT suitable for TLS.

If the slot doesn't have a key, the returned error wraps ErrNotFound.

func (*Card) AttestationCertificate

func (c *Card) AttestationCertificate() (*x509.Certificate, error)

AttestationCertificate returns the YubiKey's attestation certificate, which is unique to the key and signed by Yubico.

func (*Card) Certificate

func (c *Card) Certificate(slot Slot) (*x509.Certificate, error)

Certificate returns the certificate object stored in a given slot.

If a certificate hasn't been set in the provided slot, the returned error wraps ErrNotFound.

func (*Card) Close

func (c *Card) Close() error

Close releases the connection to the smart card.

func (*Card) GenerateKey

func (c *Card) GenerateKey(key ManagementKey, slot Slot, opts Key) (crypto.PublicKey, error)

GenerateKey generates an asymmetric key on the card, returning the key's public key.

func (*Card) Metadata

func (c *Card) Metadata(slot Slot) (*Metadata, error)

Metadata returns public information about the given key slot. It is only supported by YubiKeys with a version >= 5.3.0.

func (*Card) PinProtectedData added in v0.3.0

func (c *Card) PinProtectedData(pin string) (*PinProtectedData, error)

PinProtectedData returns protected data stored on the card. This can be used to retrieve PIN protected management keys.

func (*Card) PrivateKey

func (c *Card) PrivateKey(slot Slot, public crypto.PublicKey, auth KeyAuth) (crypto.PrivateKey, error)

PrivateKey is used to access signing and decryption options for the key stored in the slot. The returned key implements crypto.Signer and/or crypto.Decrypter depending on the key type.

If the public key hasn't been stored externally, it can be provided by fetching the slot's attestation certificate:

cert, err := c.Attest(slot)
if err != nil {
	// ...
}
priv, err := c.PrivateKey(slot, cert.PublicKey, auth)

func (*Card) Reset

func (c *Card) Reset() error

Reset resets the PIV applet to its factory settings, wiping all slots and resetting the PIN, PUK, and Management Key to their default values. This does NOT affect data on other applets, such as GPG or U2F.

func (*Card) Retries

func (c *Card) Retries() (int, error)

Retries returns the number of attempts remaining to enter the correct PIN.

func (*Card) Serial

func (c *Card) Serial() (uint32, error)

Serial returns the YubiKey's serial number.

func (*Card) SetCertificate

func (c *Card) SetCertificate(key ManagementKey, slot Slot, cert *x509.Certificate) error

SetCertificate stores a certificate object in the provided slot. Setting a certificate isn't required to use the associated key for signing or decryption.

func (*Card) SetManagementKey

func (c *Card) SetManagementKey(oldKey, newKey ManagementKey) error

SetManagementKey updates the management key to a new key. Management keys are triple-des keys, however padding isn't verified. To generate a new key, generate 24 random bytes.

var newKey ManagementKey
if _, err := io.ReadFull(rand.Reader, newKey[:]); err != nil {
	// ...
}
if err := c.SetManagementKey(piv.DefaultManagementKey, newKey); err != nil {
	// ...
}

func (*Card) SetPIN

func (c *Card) SetPIN(oldPIN, newPIN string) error

SetPIN updates the PIN to a new value. For compatibility, PINs should be 1-8 numeric characters.

To generate a new PIN, use the crypto/rand package.

// Generate a 6 character PIN.
newPINInt, err := rand.Int(rand.Reader, bit.NewInt(1_000_000))
if err != nil {
	// ...
}
// Format with leading zeros.
newPIN := fmt.Sprintf("%06d", newPINInt)
if err := c.SetPIN(piv.DefaultPIN, newPIN); err != nil {
	// ...
}

func (*Card) SetPUK

func (c *Card) SetPUK(oldPUK, newPUK string) error

SetPUK updates the PUK to a new value. For compatibility, PUKs should be 1-8 numeric characters.

To generate a new PUK, use the crypto/rand package.

// Generate a 8 character PUK.
newPUKInt, err := rand.Int(rand.Reader, big.NewInt(100_000_000))
if err != nil {
	// ...
}
// Format with leading zeros.
newPUK := fmt.Sprintf("%08d", newPUKInt)
if err := c.SetPUK(piv.DefaultPUK, newPUK); err != nil {
	// ...
}

func (*Card) SetPinProtectedData added in v0.3.0

func (c *Card) SetPinProtectedData(key ManagementKey, ppd *PinProtectedData) error

SetMetadata sets PIN protected metadata on the key. This is primarily to store the management key on the smart card instead of managing the PIN and management key separately.

func (*Card) SetPrivateKeyInsecure

func (c *Card) SetPrivateKeyInsecure(key ManagementKey, slot Slot, private crypto.PrivateKey, policy Key) error

SetPrivateKeyInsecure is an insecure method which imports a private key into the slot. Users should almost always use GeneratePrivateKey() instead.

Importing a private key breaks functionality provided by this package, including AttestationCertificate() and Attest(). There are no stability guarantees for other methods for imported private keys.

Keys generated outside of the YubiKey should not be considered hardware-backed, as there's no way to prove the key wasn't copied, exfiltrated, or replaced with malicious material before being imported.

func (*Card) SupportsAttestation added in v0.3.0

func (c *Card) SupportsAttestation() bool

func (*Card) Unblock

func (c *Card) Unblock(puk, newPIN string) error

Unblock unblocks the PIN, setting it to a new value.

func (*Card) VerifyPIN

func (c *Card) VerifyPIN(pin string) error

VerifyPIN attempts to authenticate against the card with the provided PIN.

PIN authentication for other operations are handled separately, and VerifyPIN does not need to be called before those methods.

After a specific number of authentication attempts with an invalid PIN, usually 3, the PIN will become block and refuse further attempts. At that point the PUK must be used to unblock the PIN.

Use DefaultPIN if the PIN hasn't been set.

func (*Card) Version

func (c *Card) Version() iso.Version

Version returns the version as reported by the PIV applet. For newer YubiKeys (>=4.0.0) this corresponds to the version of the YubiKey itself.

Older YubiKeys return values that aren't directly related to the YubiKey version. For example, 3rd generation YubiKeys report 1.0.X.

type ECPPPrivateKey added in v0.3.0

type ECPPPrivateKey struct {
	// contains filtered or unexported fields
}

ECPPPrivateKey is a crypto.PrivateKey implementation for EC keys. It implements crypto.Signer and the method SharedKey performs Diffie-Hellman key agreements.

Keys returned by Card.PrivateKey() may be type asserted to *ECPPPrivateKey, if the slot contains an EC key.

func (*ECPPPrivateKey) Public added in v0.3.0

func (k *ECPPPrivateKey) Public() crypto.PublicKey

Public returns the public key associated with this private key.

func (*ECPPPrivateKey) SharedKey added in v0.3.0

func (k *ECPPPrivateKey) SharedKey(peer *ecdsa.PublicKey) ([]byte, error)

SharedKey performs a Diffie-Hellman key agreement with the peer to produce a shared secret key.

Peer's public key must use the same algorithm as the key in this slot, or an error will be returned.

Length of the result depends on the types and sizes of the keys used for the operation. Callers should use a cryptographic key derivation function to extract the amount of bytes they need.

func (*ECPPPrivateKey) Sign added in v0.3.0

func (k *ECPPPrivateKey) Sign(_ io.Reader, digest []byte, _ crypto.SignerOpts) ([]byte, error)

Sign implements crypto.Signer.

type FormFactor

type FormFactor int

FormFactor enumerates the physical set of forms a key can take. USB-A vs. USB-C and Keychain vs. Nano (and FIPS variants for these).

func (FormFactor) String

func (f FormFactor) String() string

String returns the human-readable description for the given form-factor value, or a fallback value for any other, unknown form-factor.

type Key

type Key struct {
	// Algorithm to use when generating the key.
	Algorithm Algorithm
	// PINPolicy for the key.
	//
	// BUG(ericchiang): some older YubiKeys (third generation) will silently
	// drop this value. If PINPolicyNever or PINPolicyOnce is supplied but the
	// key still requires a PIN every time, you may be using a buggy key and
	// should supply PINPolicyAlways. See https://cunicu.li/go-piv/issues/60
	PINPolicy PINPolicy
	// TouchPolicy for the key.
	TouchPolicy TouchPolicy
}

Key is used for key generation and holds different options for the key.

While keys can have default PIN and touch policies, this package currently doesn't support this option, and all fields must be provided.

type KeyAuth

type KeyAuth struct {
	// PIN, if provided, is a static PIN used to authenticate against the key.
	// If provided, PINPrompt is ignored.
	PIN string

	// PINPrompt can be used to interactively request the PIN from the user. The
	// method is only called when needed. For example, if a key specifies
	// PINPolicyOnce, PINPrompt will only be called once per card struct.
	PINPrompt func() (pin string, err error)

	// PINPolicy can be used to specify the PIN caching strategy for the slot. If
	// not provided, this will be inferred from the attestation certificate.
	//
	// This field is required on older (<4.3.0) YubiKeys when using PINPrompt,
	// as well as for keys imported to the card.
	PINPolicy PINPolicy
}

KeyAuth is used to authenticate against the card on each signing and decryption request.

type ManagementKey added in v0.3.0

type ManagementKey [24]byte

type Metadata

type Metadata struct {
	Algorithm   Algorithm
	PINPolicy   PINPolicy
	TouchPolicy TouchPolicy
	Origin      Origin
	PublicKey   crypto.PublicKey
}

Metadata holds unprotected metadata about a key slot.

type Object added in v0.3.0

type Object []byte

func (Object) TagValue added in v0.3.0

func (o Object) TagValue() tlv.TagValue

type Origin

type Origin int

Origin represents whether a key was generated on the hardware, or has been imported into it.

const (
	OriginGenerated Origin = iota + 1
	OriginImported
)

Origins supported by this package.

type PINPolicy

type PINPolicy int

PINPolicy represents PIN requirements when signing or decrypting with an asymmetric key in a given slot.

const (
	PINPolicyNever PINPolicy = iota + 1
	PINPolicyOnce
	PINPolicyAlways
)

PIN policies supported by this package.

BUG(ericchiang): Caching for PINPolicyOnce isn't supported on YubiKey versions older than 4.3.0 due to issues with verifying if a PIN is needed. If specified, a PIN will be required for every operation.

type PinProtectedData added in v0.3.0

type PinProtectedData struct {
	tlv.TagValues
}

PinProtectedData holds PIN protected data. This is primarily used by YubiKey manager to implement PIN protect management keys, storing management keys on the card guarded by the PIN.

func (PinProtectedData) ManagementKey added in v0.3.0

func (d PinProtectedData) ManagementKey() (k ManagementKey, err error)

func (*PinProtectedData) SetManagementKey added in v0.3.0

func (d *PinProtectedData) SetManagementKey(key ManagementKey) error

type Slot

type Slot struct {
	// Key is a reference for a key type.
	//
	// See: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf#page=32
	Key byte

	// Object is a reference for data object.
	//
	// See: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf#page=30
	Object Object
}

Slot is a private key and certificate combination managed by the security key.

func SlotRetiredKeyManagement added in v0.3.0

func SlotRetiredKeyManagement(key byte) (Slot, bool)

SlotRetiredKeyManagement provides access to "retired" slots. Slots meant for old Key Management keys that have been rotated. YubiKeys 4 and later support values between 0x82 and 0x95 (inclusive).

slot, ok := SlotRetiredKeyManagement(0x82)
if !ok {
    // unrecognized slot
}
pub, err := c.GenerateKey(managementKey, slot, key)

https://developers.yubico.com/PIV/Introduction/Certificate_slots.html#_slot_82_95_retired_key_management

func (Slot) String

func (s Slot) String() string

String returns the two-character hex representation of the slot

type TouchPolicy

type TouchPolicy int

TouchPolicy represents proof-of-presence requirements when signing or decrypting with asymmetric key in a given slot.

const (
	TouchPolicyNever TouchPolicy = iota + 1
	TouchPolicyAlways
	TouchPolicyCached
)

Touch policies supported by this package.

type UnsupportedCurveError added in v0.3.0

type UnsupportedCurveError struct {
	// contains filtered or unexported fields
}

UnsupportedCurveError is used when a key has an unsupported curve

func (UnsupportedCurveError) Error added in v0.3.0

func (e UnsupportedCurveError) Error() string

type Verifier

type Verifier struct {
	// Root certificates to use to validate challenges. If nil, this defaults to Yubico's
	// CA bundle.
	//
	// https://developers.yubico.com/PIV/Introduction/PIV_attestation.html
	// https://developers.yubico.com/PIV/Introduction/piv-attestation-ca.pem
	// https://developers.yubico.com/U2F/yubico-u2f-ca-certs.txt
	Roots *x509.CertPool
}

Verifier allows specifying options when verifying attestations produced by YubiKeys.

func (*Verifier) Verify

func (v *Verifier) Verify(attestationCert, slotCert *x509.Certificate) (*Attestation, error)

Verify proves that a key was generated on a YubiKey.

As opposed to the package level Verify, it uses any options enabled on the Verifier.

Notes

Bugs

  • some older YubiKeys (third generation) will silently drop this value. If PINPolicyNever or PINPolicyOnce is supplied but the key still requires a PIN every time, you may be using a buggy key and should supply PINPolicyAlways. See https://cunicu.li/go-piv/issues/60

  • Caching for PINPolicyOnce isn't supported on YubiKey versions older than 4.3.0 due to issues with verifying if a PIN is needed. If specified, a PIN will be required for every operation.

Directories

Path Synopsis
internal
rsa

Jump to

Keyboard shortcuts

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