Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
wip
Browse files Browse the repository at this point in the history
stv0g committed Dec 10, 2024
1 parent f072b7c commit ec55978
Showing 117 changed files with 2,420 additions and 418 deletions.
110 changes: 84 additions & 26 deletions algorithm.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
// SPDX-FileCopyrightText: 2020 Google LLC
// SPDX-FileCopyrightText: 2023-2024 Steffen Vogel <[email protected]>
// SPDX-License-Identifier: Apache-2.0

package piv

type algorithmType byte

const (
AlgTypeRSA algorithmType = iota + 1
AlgTypeECCP
AlgTypeEd25519
)
import "fmt"

// Algorithm represents a specific algorithm and bit size supported by the PIV
// specification.
@@ -18,41 +13,93 @@ type Algorithm byte
// 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
// For algorithm discovery, see: https://github.com/go-piv/piv-go/issues/1
const (
Alg3DES Algorithm = 0x03
AlgRSA1024 Algorithm = 0x06
AlgRSA2048 Algorithm = 0x07
AlgRSA3072 Algorithm = 0x05
// NIST SP 800-78-4
// https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf#page=21
AlgRSA2048 Algorithm = 0x07 // RSA 2048 bit modulus, 65537 ≤ exponent ≤ 2256 - 1
AlgECCP256 Algorithm = 0x11 // ECC: Curve P-256
AlgECCP384 Algorithm = 0x14 // ECC: Curve P-384

// NIST SP 800-78-5 ipd (Initial Public Draft)
// https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-78-5.ipd.pdf#page=12
Alg3DESSalt Algorithm = 0x00 // 3 Key Triple DES – ECB (deprecated)
Alg3DES Algorithm = 0x03 // 3 Key Triple DES – ECB (deprecated)
AlgRSA3072 Algorithm = 0x05 // RSA 3072 bit modulus, 65537 ≤ exponent ≤ 2256 - 1
AlgRSA1024 Algorithm = 0x06 // RSA 1024 bit modulus, 65537 ≤ exponent ≤ 2256 - 1
AlgAES128 Algorithm = 0x08 // AES-128 – ECB
AlgAES192 Algorithm = 0x0A // AES-192 – ECB
AlgAES256 Algorithm = 0x0C // AES-256 – ECB
AlgCS2 Algorithm = 0x27 // Cipher Suite 2
AlgCS7 Algorithm = 0x2E // Cipher Suite 7

// Non-standard extensions
AlgPIN Algorithm = 0xFF

// YubiKey 5.7 Firmware Specifics - PIV Enhancements - Additional Key Types Supported
//
// https://docs.yubico.com/hardware/yubikey/yk-tech-manual/5.7-firmware-specifics.html#additional-key-types-supported
AlgRSA4096 Algorithm = 0x16
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
AlgEd25519 Algorithm = 0xE0 // YubiKey
AlgX25519 Algorithm = 0xE1 // YubiKey

// Trussed PIV authenticator (NitroKey / SoloKeys)
//
// https://github.com/Nitrokey/piv-authenticator/blob/efb4632b3f498af6732fc716354af746f3960038/tests/command_response.rs#L58-L72

// AlgECCP521 Algorithm = 0x15
// AlgRSA3072 Algorithm = 0xE0
// AlgRSA4096 Algorithm = 0xE1
// AlgEd25519 Algorithm = 0xE2
// AlgX25519 Algorithm = 0xE3
// AlgEd448 Algorithm = 0xE4
// AlgX448 Algorithm = 0xE5

// Internal algorithms for testing
algRSA512 Algorithm = 0xF0
algECCP224 Algorithm = 0xF1
algECCP521 Algorithm = 0xF2
)

func (a Algorithm) algType() algorithmType {
func (a Algorithm) String() string {
switch a {
case AlgRSA1024, AlgRSA2048, AlgRSA3072, AlgRSA4096:
return AlgTypeRSA
case AlgRSA1024, AlgRSA2048, AlgRSA3072, AlgRSA4096, algRSA512:
return fmt.Sprintf("RSA-%d", a.bits())

case AlgECCP256, AlgECCP384, algECCP224, algECCP521:
return fmt.Sprintf("P-%d", a.bits())

case Alg3DESSalt:
return "3DESSalt"
case Alg3DES:
return "3DES"

case AlgAES128, AlgAES192, AlgAES256:
return fmt.Sprintf("AES-%d", a.bits())

case AlgECCP256, AlgECCP384:
return AlgTypeECCP
case AlgCS2:
return "CS2"
case AlgCS7:
return "CS7"

case AlgPIN:
return "PIN"

case AlgEd25519:
return AlgTypeEd25519
return "Ed25519"
case AlgX25519:
return "X25519"

default:
return 0
return ""
}
}

func (a Algorithm) bits() int {
switch a {
case algRSA512:
return 512
case AlgRSA1024:
return 1024
case AlgRSA2048:
@@ -62,10 +109,21 @@ func (a Algorithm) bits() int {
case AlgRSA4096:
return 4096

case algECCP224:
return 224
case AlgECCP256:
return 256
case AlgECCP384:
return 384
case algECCP521:
return 521

case AlgAES128:
return 128
case AlgAES192:
return 192
case AlgAES256:
return 256

default:
return 0
52 changes: 35 additions & 17 deletions auth.go
Original file line number Diff line number Diff line change
@@ -5,6 +5,8 @@ package piv

import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/des" //nolint:gosec
"errors"
"fmt"
@@ -25,8 +27,13 @@ var errFailedToGenerateKey = errors.New("failed to generate random key")
// https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf#page=92
// https://tsapps.nist.gov/publication/get_pdf.cfm?pub_id=918402#page=114
func (c *Card) authenticate(key ManagementKey) error {
meta, err := c.Metadata(SlotCardManagement)
if err != nil {
return fmt.Errorf("failed to get management key metadata: %w", err)
}

// Request a witness
resp, err := sendTLV(c.tx, iso.InsGeneralAuthenticate, byte(Alg3DES), keyCardManagement,
resp, err := sendTLV(c.tx, iso.InsGeneralAuthenticate, byte(meta.Algorithm), keyCardManagement,
tlv.New(0x7c,
tlv.New(0x80),
),
@@ -35,30 +42,41 @@ func (c *Card) authenticate(key ManagementKey) error {
return fmt.Errorf("failed to execute command: %w", err)
}

var block cipher.Block

switch meta.Algorithm {
case Alg3DES:
block, err = des.NewTripleDESCipher(key[:]) //nolint:gosec

case AlgAES128, AlgAES192, AlgAES256:
block, err = aes.NewCipher(key[:])

default:
return errUnsupportedKeyType
}
if err != nil {
return fmt.Errorf("failed to create block cipher: %w", err)
}

cardChallenge, _, ok := resp.GetChild(0x7c, 0x80)
if !ok {
return errUnmarshal
} else if len(cardChallenge) != 8 {
return errUnexpectedLength
}

block, err := des.NewTripleDESCipher(key[:]) //nolint:gosec
if err != nil {
return fmt.Errorf("failed to create triple des block cipher: %w", err)
} else if len(cardChallenge) != block.BlockSize() {
return fmt.Errorf("%w: %d", errUnexpectedLength, len(cardChallenge))
}

cardResponse := make([]byte, 8)
cardResponse := make([]byte, block.BlockSize())
block.Decrypt(cardResponse, cardChallenge)

challenge := make([]byte, 8)
challenge := make([]byte, block.BlockSize())
if _, err := io.ReadFull(c.Rand, challenge); err != nil {
return fmt.Errorf("failed to read random data: %w", err)
}

response := make([]byte, 8)
response := make([]byte, block.BlockSize())
block.Encrypt(response, challenge)

if resp, err = sendTLV(c.tx, iso.InsGeneralAuthenticate, byte(Alg3DES), keyCardManagement,
if resp, err = sendTLV(c.tx, iso.InsGeneralAuthenticate, byte(meta.Algorithm), keyCardManagement,
tlv.New(0x7c,
tlv.New(0x80, cardResponse),
tlv.New(0x81, challenge),
@@ -69,7 +87,7 @@ func (c *Card) authenticate(key ManagementKey) error {

if cardResponse, _, ok = resp.GetChild(0x7c, 0x82); !ok {
return errUnmarshal
} else if len(cardResponse) != 8 {
} else if len(cardResponse) != block.BlockSize() {
return errUnexpectedLength
} else if !bytes.Equal(cardResponse, response) {
return errChallengeFailed
@@ -109,7 +127,7 @@ func (c *Card) authenticateWithPIN(pin string) error {
// if err := c.SetManagementKey(piv.DefaultManagementKey, newKey); err != nil {
// // ...
// }
func (c *Card) SetManagementKey(oldKey, newKey ManagementKey, requireTouch bool) error {
func (c *Card) SetManagementKey(oldKey, newKey ManagementKey, requireTouch bool, alg Algorithm) error {
if err := c.authenticate(oldKey); err != nil {
return fmt.Errorf("failed to authenticate with old key: %w", err)
}
@@ -120,7 +138,7 @@ func (c *Card) SetManagementKey(oldKey, newKey ManagementKey, requireTouch bool)
}

if _, err := send(c.tx, insSetManagementKey, 0xff, p2, append([]byte{
byte(Alg3DES), keyCardManagement, 24,
byte(alg), keyCardManagement, 24,
}, newKey[:]...)); err != nil {
return fmt.Errorf("failed to execute command: %w", err)
}
@@ -130,7 +148,7 @@ func (c *Card) SetManagementKey(oldKey, newKey ManagementKey, requireTouch bool)

// https://docs.yubico.com/yesdk/users-manual/application-piv/pin-only.html
// https://docs.yubico.com/yesdk/users-manual/application-piv/piv-objects.html#pinprotecteddata
func (c *Card) SetManagementKeyPinProtected(oldKey ManagementKey, pin string, requireTouch bool) error {
func (c *Card) SetManagementKeyPinProtected(oldKey ManagementKey, pin string, requireTouch bool, alg Algorithm) error {
var newKey ManagementKey

if n, err := c.Rand.Read(newKey[:]); err != nil {
@@ -152,7 +170,7 @@ func (c *Card) SetManagementKeyPinProtected(oldKey ManagementKey, pin string, re
return err
}

return c.SetManagementKey(oldKey, newKey, requireTouch)
return c.SetManagementKey(oldKey, newKey, requireTouch, alg)
}

// SetPIN updates the PIN to a new value. For compatibility, PINs should be 1-8
38 changes: 21 additions & 17 deletions auth_test.go
Original file line number Diff line number Diff line change
@@ -52,20 +52,24 @@ func TestAuthenticate(t *testing.T) {
}

func TestSetManagementKey(t *testing.T) {
withCard(t, false, false, nil, func(t *testing.T, c *Card) {
var mgmtKey ManagementKey
_, err := io.ReadFull(c.Rand, mgmtKey[:])
require.NoError(t, err, "Failed to generate management key")

err = c.SetManagementKey(DefaultManagementKey, mgmtKey, false)
require.NoError(t, err, "Failed to set management key")

err = c.authenticate(mgmtKey)
assert.NoError(t, err, "Failed to authenticate with new management key")

err = c.SetManagementKey(mgmtKey, DefaultManagementKey, false)
require.NoError(t, err, "Failed to reset management key")
})
for _, alg := range []Algorithm{Alg3DES, AlgAES128, AlgAES192, AlgAES256} {
t.Run(alg.String(), func(t *testing.T) {
withCard(t, false, false, nil, func(t *testing.T, c *Card) {
var mgmtKey ManagementKey
_, err := io.ReadFull(c.Rand, mgmtKey[:])
require.NoError(t, err, "Failed to generate management key")

err = c.SetManagementKey(DefaultManagementKey, mgmtKey, false, alg)
require.NoError(t, err, "Failed to set management key")

err = c.authenticate(mgmtKey)
assert.NoError(t, err, "Failed to authenticate with new management key")

err = c.SetManagementKey(mgmtKey, DefaultManagementKey, false, alg)
require.NoError(t, err, "Failed to reset management key")
})
})
}
}

func TestUnblockPIN(t *testing.T) {
@@ -134,13 +138,13 @@ func TestChangeManagementKey(t *testing.T) {
}
}

err = c.SetManagementKey(newKey, newKey, false)
err = c.SetManagementKey(newKey, newKey, false, Alg3DES)
assert.Error(t, err, "Successfully changed management key with invalid key, expected error")

err = c.SetManagementKey(DefaultManagementKey, newKey, false)
err = c.SetManagementKey(DefaultManagementKey, newKey, false, Alg3DES)
require.NoError(t, err, "Failed to change management key")

err = c.SetManagementKey(newKey, DefaultManagementKey, false)
err = c.SetManagementKey(newKey, DefaultManagementKey, false, Alg3DES)
require.NoError(t, err, "Failed to reset management key")
})
}
25 changes: 22 additions & 3 deletions filter.go
Original file line number Diff line number Diff line change
@@ -4,12 +4,31 @@
package piv

import (
iso "cunicu.li/go-iso7816"
"cunicu.li/go-iso7816/devices/yubikey"
"cunicu.li/go-iso7816/filter"
)

//nolint:gochecknoglobals
var (
SupportsAttestation = yubikey.HasVersionStr("4.3.0")
SupportsMetadata = yubikey.HasVersionStr("5.3.0")
SupportsAlgorithmEC384 = yubikey.HasVersionStr("4.3.0")
v430 = iso.Version{Major: 4, Minor: 3, Patch: 0}
v530 = iso.Version{Major: 5, Minor: 3, Patch: 0}
v571 = iso.Version{Major: 5, Minor: 7, Patch: 1}

SupportsAttestation = yubikey.HasVersion(v430)
SupportsMetadata = yubikey.HasVersion(v530)
SupportsKeyMoveDelete = yubikey.HasVersion(v571)
)

func SupportsAlgorithm(alg Algorithm) filter.Filter {
switch alg {
case AlgRSA1024, AlgRSA2048, AlgECCP256, AlgECCP384:
return yubikey.HasVersion(v430)

case AlgRSA3072, AlgRSA4096, AlgX25519, AlgEd25519:
return yubikey.HasVersion(v571)

default:
return filter.None
}
}
28 changes: 2 additions & 26 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,42 +1,18 @@
cunicu.li/go-iso7816 v0.3.0 h1:KSt0D7TBh0ghWnpDSjNJDehFmXwM67Q8I3Qg0fvZlgw=
cunicu.li/go-iso7816 v0.3.0/go.mod h1:jL3bciDEU4prkEtONmCzVAz542Vb7SLJBnLV3o4o8qo=
cunicu.li/go-iso7816 v0.4.0 h1:GwYTCcaGlaNC+Tb+TVVqGTKX83Z/UALM1U388Ymgfec=
cunicu.li/go-iso7816 v0.4.0/go.mod h1:jL3bciDEU4prkEtONmCzVAz542Vb7SLJBnLV3o4o8qo=
cunicu.li/go-iso7816 v0.5.0 h1:HjjEZFw5DqNukwswPBtHrt/iqfuZ2zZsHEhmasT7eXI=
cunicu.li/go-iso7816 v0.5.0/go.mod h1:jL3bciDEU4prkEtONmCzVAz542Vb7SLJBnLV3o4o8qo=
cunicu.li/go-iso7816 v0.5.1 h1:0fsdN5j+AoU9Y32RfF2IR126xpYAU1CC9WNBV6zmZAs=
cunicu.li/go-iso7816 v0.5.1/go.mod h1:OwF8/IxfJAi/GEuMv3cv7jXFmbto+7lDwl2eknMucoA=
cunicu.li/go-iso7816 v0.5.2 h1:hdGm6xLZ5//FjRSFxMRfuqfEFDIu6bIlKreKrXH6Fx8=
cunicu.li/go-iso7816 v0.5.2/go.mod h1:OwF8/IxfJAi/GEuMv3cv7jXFmbto+7lDwl2eknMucoA=
cunicu.li/go-iso7816 v0.6.0 h1:l0CzHZWN7FFLJOGY1NUQGyRxv0IuZODpMvEHWFIvOz4=
cunicu.li/go-iso7816 v0.6.0/go.mod h1:DBXPMv/k9XQplA9qQT2k/Xo2gPCWQ9/rIh+h4hzJ850=
cunicu.li/go-iso7816 v0.8.0 h1:EEQ9hAbdIbTUM0uVrWbfGnQnFjA3P/VoNj1GM71Tf5w=
cunicu.li/go-iso7816 v0.8.0/go.mod h1:gSG/jc0iH2bykUasCbyIfnI1PFotnm76Gmk1bc7UFEg=
cunicu.li/go-iso7816 v0.8.1 h1:3kgjW+iCwkw6DtLDh5aKUQfwpwd0zoHHyPxyDS9t7HU=
cunicu.li/go-iso7816 v0.8.1/go.mod h1:bt5Uo0kVcv8+wbIaMdWw3YrcwdhGEDCu/arp7dsHuTY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ebfe/scard v0.0.0-20230420082256-7db3f9b7c8a7 h1:HYAhfGa9dEemCZgGZWL5AvVsctBCsHxl2CI0HUXzHQE=
github.com/ebfe/scard v0.0.0-20230420082256-7db3f9b7c8a7/go.mod h1:BkYEeWL6FbT4Ek+TcOBnPzEKnL7kOq2g19tTQXkorHY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
24 changes: 21 additions & 3 deletions key.go
Original file line number Diff line number Diff line change
@@ -142,6 +142,11 @@ func decodePublic(b []byte, alg Algorithm) (pub crypto.PublicKey, err error) {
return nil, fmt.Errorf("failed to decode Ed25519 public key: %w", err)
}

case AlgX25519:
if pub, err = decodeX25519Public(tvs); err != nil {
return nil, fmt.Errorf("failed to decode X25519 public key: %w", err)
}

default:
return nil, errUnsupportedAlgorithm
}
@@ -184,6 +189,9 @@ func (c *Card) PrivateKey(slot Slot, public crypto.PublicKey, auth KeyAuth) (cry
case ed25519.PublicKey:
return &keyEd25519{c, slot, pub, auth, pp}, nil

case *ecdh.PublicKey:
return &keyX25519{c, slot, pub, auth, pp}, nil

case *rsa.PublicKey:
return &keyRSA{c, slot, pub, auth, pp}, nil

@@ -283,6 +291,16 @@ func (c *Card) SetPrivateKeyInsecure(key ManagementKey, slot Slot, private crypt

tvs = append(tvs, tlv.New(0x06, pad(elemLen, priv.D.Bytes()))) // S value

case *ed25519.PrivateKey:
tvs = append(tvs, tlv.New(0x07, priv.Seed()))

case *ecdh.PrivateKey:
if priv.Curve() != ecdh.X25519() {
return UnsupportedCurveError{}
}

tvs = append(tvs, tlv.New(0x08, priv.Bytes()))

default:
return errUnsupportedKeyType
}
@@ -301,13 +319,13 @@ func (c *Card) SetPrivateKeyInsecure(key ManagementKey, slot Slot, private crypt
//
// This enables retaining retired encryption keys on the device to decrypt older messages.
//
// Note: This is a YubiKey specific extension to PIV. Its supported by YubiKeys with firmware 5.7 or newer.
// Note: This is a YubiKey specific extension to PIV. Its supported by YubiKeys with firmware 5.7.0 or newer.
func (c *Card) MoveKey(key ManagementKey, from, to Slot) error {
if err := c.authenticate(key); err != nil {
return fmt.Errorf("failed to authenticate with management key: %w", err)
}

_, err := send(c.tx, insMoveDeleteKey, from.Key, to.Key, nil)
_, err := send(c.tx, insMoveDeleteKey, to.Key, from.Key, nil)

return err
}
@@ -316,7 +334,7 @@ func (c *Card) MoveKey(key ManagementKey, from, to Slot) error {
//
// This enables destroying key material without overwriting with bogus data or resetting the PIV application.
//
// Note: This is a YubiKey specific extension to PIV. Its supported by YubiKeys with firmware 5.7 or newer.
// Note: This is a YubiKey specific extension to PIV. Its supported by YubiKeys with firmware 5.7.0 or newer.
func (c *Card) DeleteKey(key ManagementKey, slot Slot) error {
return c.MoveKey(key, slot, SlotGraveyard)
}
22 changes: 13 additions & 9 deletions key_data_test.go
Original file line number Diff line number Diff line change
@@ -52,14 +52,14 @@ var (
// testKey returns a deterministic key for testing
// We require deterministic keys for reproducible tests
// in order for the test transcript to match
func testKey(t *testing.T, typ algorithmType, bits int) (key privateKey) {
func testKey(t *testing.T, alg Algorithm) (key privateKey) {
t.Helper()

var testKey []byte
var err error
switch typ {
case AlgTypeECCP:
switch bits {
switch alg {
case algECCP224, AlgECCP256, AlgECCP384, algECCP521:
switch alg.bits() {
case 224:
testKey = testKeyEC224
case 256:
@@ -68,6 +68,8 @@ func testKey(t *testing.T, typ algorithmType, bits int) (key privateKey) {
testKey = testKeyEC384
case 521:
testKey = testKeyEC521
default:
t.Fatalf("Unsupported EC curve: P-%d", alg.bits())
}

b, _ := pem.Decode(testKey)
@@ -76,23 +78,23 @@ func testKey(t *testing.T, typ algorithmType, bits int) (key privateKey) {
key, err = x509.ParseECPrivateKey(b.Bytes)
require.NoError(t, err)

case AlgTypeEd25519:
case AlgEd25519:
b, _ := pem.Decode(testKeyEd25519)
require.NotNil(t, b)
require.Len(t, b.Bytes, 32)

key = ed25519.PrivateKey(b.Bytes)

case AlgTypeX25519:
case AlgX25519:
b, _ := pem.Decode(testKeyX25519)
require.NotNil(t, b)
require.Len(t, b.Bytes, 32)

key, err = ecdh.X25519().NewPrivateKey(b.Bytes)
require.NoError(t, err)

case AlgTypeRSA:
switch bits {
case algRSA512, AlgRSA1024, AlgRSA2048, AlgRSA3072, AlgRSA4096:
switch alg.bits() {
case 512:
testKey = testKeyRSA512
case 1024:
@@ -103,6 +105,8 @@ func testKey(t *testing.T, typ algorithmType, bits int) (key privateKey) {
testKey = testKeyRSA3072
case 4096:
testKey = testKeyRSA4096
default:
t.Fatalf("Unsupported RSA modulus length: %d", alg.bits())
}

b, _ := pem.Decode(testKey)
@@ -112,7 +116,7 @@ func testKey(t *testing.T, typ algorithmType, bits int) (key privateKey) {
require.NoError(t, err)

default:
t.Fatalf("ephemeral key: unknown algorithm")
t.Fatalf("test key: unknown algorithm: %s", alg)
}

return key
73 changes: 73 additions & 0 deletions key_ecdh.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SPDX-FileCopyrightText: 2020 Google LLC
// SPDX-License-Identifier: Apache-2.0

package piv

import (
"crypto/ecdh"
"fmt"

iso "cunicu.li/go-iso7816"
"cunicu.li/go-iso7816/encoding/tlv"
)

type keyX25519 struct {
c *Card
slot Slot
pub *ecdh.PublicKey
auth KeyAuth
pp PINPolicy
}

func (k *keyX25519) Public() *ecdh.PublicKey {
return k.pub
}

// 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 (k *keyX25519) SharedKey(peer *ecdh.PublicKey) ([]byte, error) {
if peer.Curve() != k.pub.Curve() {
return nil, errMismatchingAlgorithms
}

return k.auth.do(k.c, k.pp, func(tx *iso.Transaction) ([]byte, error) {

Check failure on line 40 in key_ecdh.go

GitHub Actions / Build (ubuntu-latest)

unused-parameter: parameter 'tx' seems to be unused, consider removing or renaming it as _ (revive)

Check failure on line 40 in key_ecdh.go

GitHub Actions / Build (macOS-latest)

unused-parameter: parameter 'tx' seems to be unused, consider removing or renaming it as _ (revive)
// https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf#page=118
// https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf#page=93
resp, err := sendTLV(k.c.tx, iso.InsGeneralAuthenticate, byte(AlgX25519), k.slot.Key,
tlv.New(0x7c,
tlv.New(0x82),
tlv.New(0x85, peer.Bytes()),
),
)
if err != nil {
return nil, fmt.Errorf("failed to execute command: %w", err)
}

rs, _, ok := resp.GetChild(0x7c, 0x82)
if !ok {
return nil, fmt.Errorf("%w: missing tag", errUnmarshal)
}
return rs, nil
})
}

// https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf#page=95
func decodeX25519Public(tvs tlv.TagValues) (*ecdh.PublicKey, error) {
p, _, ok := tvs.Get(0x86)
if !ok {
return nil, fmt.Errorf("%w points", errUnmarshal)
}

if len(p) != 32 {
return nil, fmt.Errorf("%w of points: %d", errUnexpectedLength, len(p))
}

return ecdh.X25519().NewPublicKey(p)
}
4 changes: 4 additions & 0 deletions key_ecdh_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// SPDX-FileCopyrightText: 2023-2024 Steffen Vogel <post@steffenvogel.de>
// SPDX-License-Identifier: Apache-2.0

package piv
163 changes: 88 additions & 75 deletions key_ecdsa_test.go
Original file line number Diff line number Diff line change
@@ -15,89 +15,100 @@
"github.com/stretchr/testify/require"
)

func TestECCPSharedKey(t *testing.T) {
withCard(t, false, false, nil, func(t *testing.T, c *Card) {
slot := SlotAuthentication
var testsECC = []struct {

Check failure on line 18 in key_ecdsa_test.go

GitHub Actions / Build (ubuntu-latest)

testsECC is a global variable (gochecknoglobals)

Check failure on line 18 in key_ecdsa_test.go

GitHub Actions / Build (macOS-latest)

testsECC is a global variable (gochecknoglobals)
alg Algorithm
slot Slot
}{
{
alg: AlgECCP256,
slot: SlotAuthentication,
},
{
alg: AlgECCP384,
slot: SlotAuthentication,
},
}

key := Key{
Algorithm: AlgECCP256,
TouchPolicy: TouchPolicyNever,
PINPolicy: PINPolicyNever,
}
pubKey, err := c.GenerateKey(DefaultManagementKey, slot, key)
require.NoError(t, err, "Failed to generate key")
func TestSharedKeyECC(t *testing.T) {
for _, test := range testsECC {
t.Run(test.alg.String(), func(t *testing.T) {
withCard(t, false, false, SupportsAlgorithm(test.alg), func(t *testing.T, c *Card) {
key := Key{
Algorithm: test.alg,
TouchPolicy: TouchPolicyNever,
PINPolicy: PINPolicyNever,
}
pubKey, err := c.GenerateKey(DefaultManagementKey, test.slot, key)
require.NoError(t, err, "Failed to generate key")

pub, ok := pubKey.(*ecdsa.PublicKey)
require.True(t, ok, "Public key is not an EC key")
pub, ok := pubKey.(*ecdsa.PublicKey)
require.True(t, ok, "Public key is not an EC key")

priv, err := c.PrivateKey(slot, pub, KeyAuth{})
require.NoError(t, err, "Failed to get private key")
priv, err := c.PrivateKey(test.slot, pub, KeyAuth{})
require.NoError(t, err, "Failed to get private key")

privECCP, ok := priv.(*ECPPPrivateKey)
require.True(t, ok, "Expected private key to be EC private key")
privECCP, ok := priv.(*ECPPPrivateKey)
require.True(t, ok, "Expected private key to be EC private key")

t.Run("good", func(t *testing.T) {
key, ok := testKey(t, AlgTypeECCP, 256).(*ecdsa.PrivateKey)
require.True(t, ok)
t.Run("good", func(t *testing.T) {
key, ok := testKey(t, test.alg).(*ecdsa.PrivateKey)
require.True(t, ok)

mult, _ := pub.ScalarMult(pub.X, pub.Y, key.D.Bytes())
secret1 := mult.Bytes()
mult, _ := pub.ScalarMult(pub.X, pub.Y, key.D.Bytes())
secret1 := mult.Bytes()

secret2, err := privECCP.SharedKey(&key.PublicKey)
require.NoError(t, err, "Key agreement failed")
secret2, err := privECCP.SharedKey(&key.PublicKey)
require.NoError(t, err, "Key agreement failed")

assert.Equal(t, secret1, secret2, "Key agreement didn't match")
})
assert.Equal(t, secret1, secret2, "Key agreement didn't match")
})

t.Run("bad", func(t *testing.T) {
t.Run("size", func(t *testing.T) {
key, ok := testKey(t, AlgTypeECCP, 384).(*ecdsa.PrivateKey)
require.True(t, ok)
t.Run("bad", func(t *testing.T) {
t.Run("size", func(t *testing.T) {
key, ok := testKey(t, AlgECCP384).(*ecdsa.PrivateKey)
require.True(t, ok)

_, err = privECCP.SharedKey(&key.PublicKey)
require.ErrorIs(t, err, errMismatchingAlgorithms)
_, err = privECCP.SharedKey(&key.PublicKey)
require.ErrorIs(t, err, errMismatchingAlgorithms)
})
})
})
})
})
}
}

func TestSetECCPPrivateKey(t *testing.T) {
func TestSetPrivateKeyECC(t *testing.T) {
tests := []struct {
name string
bits int
alg Algorithm
slot Slot
wantErr error
}{
{
name: "EC/P256",
bits: 256,
alg: AlgECCP256,
slot: SlotSignature,
wantErr: nil,
},
{
name: "EC/P384",
bits: 384,
alg: AlgECCP384,
slot: SlotCardAuthentication,
wantErr: nil,
},
{
name: "EC/P224",
bits: 224,
alg: algECCP224,
slot: SlotAuthentication,
wantErr: UnsupportedCurveError{curve: 224},
},
{
name: "EC/P521",
bits: 521,
alg: algECCP521,
slot: SlotKeyManagement,
wantErr: UnsupportedCurveError{curve: 521},
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Run(test.alg.String(), func(t *testing.T) {
withCard(t, false, false, nil, func(t *testing.T, c *Card) {
generated, ok := testKey(t, AlgTypeECCP, test.bits).(*ecdsa.PrivateKey)
generated, ok := testKey(t, test.alg).(*ecdsa.PrivateKey)
require.True(t, ok)

err := c.SetPrivateKeyInsecure(DefaultManagementKey, test.slot, generated, Key{
@@ -128,41 +139,43 @@
}
}

func TestSignECCP(t *testing.T) {
withCard(t, false, false, nil, func(t *testing.T, c *Card) {
err := c.Reset()
require.NoError(t, err, "Failed to reset applet")
func TestSignECC(t *testing.T) {
for _, test := range testsECC {
t.Run(test.alg.String(), func(t *testing.T) {
withCard(t, false, false, SupportsAlgorithm(test.alg), func(t *testing.T, c *Card) {
err := c.Reset()
require.NoError(t, err, "Failed to reset applet")

slot := SlotAuthentication

key := Key{
Algorithm: AlgECCP256,
TouchPolicy: TouchPolicyNever,
PINPolicy: PINPolicyNever,
}
pubKey, err := c.GenerateKey(DefaultManagementKey, slot, key)
require.NoError(t, err, "Failed to generate key")
key := Key{
Algorithm: test.alg,
TouchPolicy: TouchPolicyNever,
PINPolicy: PINPolicyNever,
}
pubKey, err := c.GenerateKey(DefaultManagementKey, test.slot, key)
require.NoError(t, err, "Failed to generate key")

pub, ok := pubKey.(*ecdsa.PublicKey)
require.True(t, ok, "public key is not an EC key")
pub, ok := pubKey.(*ecdsa.PublicKey)
require.True(t, ok, "public key is not an EC key")

data := sha256.Sum256([]byte("hello"))
priv, err := c.PrivateKey(slot, pub, KeyAuth{})
require.NoError(t, err, "Failed to get private key")
data := sha256.Sum256([]byte("hello"))
priv, err := c.PrivateKey(test.slot, pub, KeyAuth{})
require.NoError(t, err, "Failed to get private key")

s, ok := priv.(crypto.Signer)
require.True(t, ok, "expected private key to implement crypto.Signer")
s, ok := priv.(crypto.Signer)
require.True(t, ok, "expected private key to implement crypto.Signer")

out, err := s.Sign(c.Rand, data[:], crypto.SHA256)
require.NoError(t, err, "Failed to sign")
out, err := s.Sign(c.Rand, data[:], crypto.SHA256)
require.NoError(t, err, "Failed to sign")

var sig struct {
R, S *big.Int
}
_, err = asn1.Unmarshal(out, &sig)
require.NoError(t, err, "Failed to unmarshal signature")
var sig struct {
R, S *big.Int
}
_, err = asn1.Unmarshal(out, &sig)
require.NoError(t, err, "Failed to unmarshal signature")

verified := ecdsa.Verify(pub, data[:], sig.R, sig.S)
assert.True(t, verified, "Signature didn't match")
})
verified := ecdsa.Verify(pub, data[:], sig.R, sig.S)
assert.True(t, verified, "Signature didn't match")
})
})
}
}
5 changes: 3 additions & 2 deletions key_eddsa.go
Original file line number Diff line number Diff line change
@@ -25,8 +25,9 @@ func (k *keyEd25519) Public() crypto.PublicKey {
return k.pub
}

// This function only works on SoloKeys prototypes and other PIV devices that choose
// to implement Ed25519 signatures under alg 0x22.
// This function only works on YubiKeys with firmware version 5.7.0 and higher as well
// as SoloKeys prototypes and other PIV devices that choose to implement Ed25519
// signatures under algorithm type 0xE0 / 0x22.
func (k *keyEd25519) Sign(_ io.Reader, digest []byte, _ crypto.SignerOpts) ([]byte, error) {
return k.auth.do(k.c, k.pp, func(tx *iso.Transaction) ([]byte, error) {
return signEd25519(tx, k.slot, digest)
46 changes: 19 additions & 27 deletions key_rsa_test.go
Original file line number Diff line number Diff line change
@@ -23,17 +23,16 @@ import (

func TestSignRSA(t *testing.T) {
tests := []struct {
name string
alg Algorithm
long bool
}{
{"RSA/1024", AlgRSA1024, false},
{"RSA/2048", AlgRSA2048, true},
{"RSA/3072", AlgRSA3072, true},
{"RSA/4096", AlgRSA4096, true},
{AlgRSA1024, false},
{AlgRSA2048, true},
{AlgRSA3072, true},
{AlgRSA4096, true},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Run(test.alg.String(), func(t *testing.T) {
withCard(t, false, test.long, nil, func(t *testing.T, c *Card) {
slot := SlotAuthentication
key := Key{
@@ -66,17 +65,16 @@ func TestSignRSA(t *testing.T) {

func TestSignRSAPSS(t *testing.T) {
tests := []struct {
name string
alg Algorithm
long bool
}{
{"RSA/1024", AlgRSA1024, false},
{"RSA/2048", AlgRSA2048, true},
{"RSA/3072", AlgRSA3072, true},
{"RSA/4096", AlgRSA4096, true},
{AlgRSA1024, false},
{AlgRSA2048, true},
{AlgRSA3072, true},
{AlgRSA4096, true},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Run(test.alg.String(), func(t *testing.T) {
withCard(t, false, test.long, nil, func(t *testing.T, c *Card) {
slot := SlotAuthentication
key := Key{
@@ -108,49 +106,43 @@ func TestSignRSAPSS(t *testing.T) {
}
}

func TestSetRSAPrivateKey(t *testing.T) {
func TestSetPrivateKeyRSA(t *testing.T) {
tests := []struct {
name string
bits int
alg Algorithm
slot Slot
wantErr error
}{
{
name: "RSA/1024",
bits: 1024,
alg: AlgRSA1024,
slot: SlotSignature,
wantErr: nil,
},
{
name: "RSA/2048",
bits: 2048,
alg: AlgRSA2048,
slot: SlotCardAuthentication,
wantErr: nil,
},
{
name: "RSA/3072",
bits: 3072,
alg: AlgRSA3072,
slot: SlotAuthentication,
wantErr: nil,
},
{
name: "RSA/4096",
bits: 4096,
alg: AlgRSA4096,
slot: SlotAuthentication,
wantErr: nil,
},
{
name: "RSA/512",
bits: 512,
alg: algRSA512,
slot: SlotKeyManagement,
wantErr: errUnsupportedKeySize,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Run(test.alg.String(), func(t *testing.T) {
withCard(t, false, false, nil, func(t *testing.T, c *Card) {
key := testKey(t, AlgTypeRSA, test.bits)
key := testKey(t, test.alg)
generated, ok := key.(*rsa.PrivateKey)
require.True(t, ok)

108 changes: 82 additions & 26 deletions key_test.go
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ import (
"testing"
"time"

"cunicu.li/go-iso7816/filter"
"cunicu.li/go-iso7816"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

@@ -85,17 +85,16 @@ func TestPINPrompt(t *testing.T) {

func TestDecryptRSA(t *testing.T) {
tests := []struct {
name string
alg Algorithm
long bool
}{
{"RSA/1024", AlgRSA1024, false},
{"RSA/2048", AlgRSA2048, true},
{"RSA/3072", AlgRSA3072, true},
{"RSA/4096", AlgRSA4096, true},
{AlgRSA1024, false},
{AlgRSA2048, true},
{AlgRSA3072, true},
{AlgRSA4096, true},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Run(test.alg.String(), func(t *testing.T) {
withCard(t, false, test.long, nil, func(t *testing.T, c *Card) {
slot := SlotAuthentication
key := Key{
@@ -133,7 +132,7 @@ func TestStoreCertificate(t *testing.T) {
withCard(t, false, false, nil, func(t *testing.T, c *Card) {
slot := SlotAuthentication

caPriv := testKey(t, AlgTypeECCP, 256)
caPriv := testKey(t, AlgECCP256)

// Generate a self-signed certificate
caTmpl := &x509.Certificate{
@@ -199,47 +198,34 @@ func TestStoreCertificate(t *testing.T) {

func TestGenerateKey(t *testing.T) {
tests := []struct {
name string
alg Algorithm
bits int
long bool
}{
{
name: "EC/P256",
alg: AlgECCP256,
alg: AlgECCP256,
},
{
name: "EC/P384",
alg: AlgECCP384,
alg: AlgECCP384,
},
{
name: "RSA/1024",
alg: AlgRSA1024,
alg: AlgRSA1024,
},
{
name: "RSA/2048",
alg: AlgRSA2048,
long: true,
},
{
name: "RSA/3072",
alg: AlgRSA3072,
long: true,
},
{
name: "RSA/4096",
alg: AlgRSA4096,
long: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
var flt filter.Filter
if test.alg == AlgECCP384 {
flt = SupportsAlgorithmEC384
}

withCard(t, false, test.long, flt, func(t *testing.T, c *Card) {
t.Run(test.alg.String(), func(t *testing.T) {
withCard(t, false, test.long, SupportsAlgorithm(test.alg), func(t *testing.T, c *Card) {
key := Key{
Algorithm: test.alg,
TouchPolicy: TouchPolicyNever,
@@ -403,3 +389,73 @@ func TestVerify(t *testing.T) {
})
}
}

func TestMoveKey(t *testing.T) {
withCard(t, true, false, SupportsKeyMoveDelete, func(t *testing.T, c *Card) {
// Moving non-existing key must fail
err := c.MoveKey(DefaultManagementKey, SlotAuthentication, SlotCardAuthentication)
require.ErrorIs(t, err, iso7816.ErrReferenceNotFound, "Expected move of non-existing key to fail")

// Generate key
_, err = c.GenerateKey(DefaultManagementKey, SlotAuthentication, Key{
Algorithm: AlgRSA1024,
PINPolicy: PINPolicyNever,
TouchPolicy: TouchPolicyNever,
})
require.NoErrorf(t, err, "Generation of new key failed: %w", err)

// Check that new key exists
m1, err := c.Metadata(SlotAuthentication)
require.NoErrorf(t, err, "Failed to retrieve metadata of new key: %w", err)
require.Equal(t, m1.Algorithm, AlgRSA1024, "Mismatching algorithm for new key")

pk1, ok := m1.PublicKey.(*rsa.PublicKey)
require.True(t, ok, "Key is not an RSA key")

// Move key
err = c.MoveKey(DefaultManagementKey, SlotAuthentication, SlotCardAuthentication)
require.NoErrorf(t, err, "Failed to move key: %w", err)

// Check key has been removed from source slot
_, err = c.Metadata(SlotAuthentication)
require.ErrorIs(t, err, iso7816.ErrReferenceNotFound, "Key still exists")

// Check key is now in the new slot
m2, err := c.Metadata(SlotCardAuthentication)
require.NoErrorf(t, err, "Failed to retrieve metadata of moved key: %w", err)

pk2, ok := m2.PublicKey.(*rsa.PublicKey)
require.True(t, ok, "Key is not an RSA key")

require.True(t, pk1.Equal(pk2), "Public keys of moved slot are not equal")
})
}

func TestDeleteKey(t *testing.T) {
withCard(t, true, false, SupportsKeyMoveDelete, func(t *testing.T, c *Card) {
// Delete non-existing key must fail
err := c.DeleteKey(DefaultManagementKey, SlotAuthentication)
require.ErrorIs(t, err, iso7816.ErrReferenceNotFound, "Deletion of non-existing key succeeded")

// Generate key
_, err = c.GenerateKey(DefaultManagementKey, SlotAuthentication, Key{
Algorithm: AlgRSA1024,
PINPolicy: PINPolicyNever,
TouchPolicy: TouchPolicyNever,
})
require.NoErrorf(t, err, "Failed to generate key: %w", err)

// Check that new key exists
m, err := c.Metadata(SlotAuthentication)
require.NoErrorf(t, err, "Failed to retrieve metadata of new key: %w", err)
require.Equal(t, m.Algorithm, AlgRSA1024, "Key is not an RSA key")

// Delete key
err = c.DeleteKey(DefaultManagementKey, SlotAuthentication)
require.NoErrorf(t, err, "Failed to delete key: %w", err)

// Check key has been removed
_, err = c.Metadata(SlotAuthentication)
require.ErrorIs(t, err, iso7816.ErrReferenceNotFound, "Key has not been removed")
})
}
26 changes: 13 additions & 13 deletions metadata_test.go
Original file line number Diff line number Diff line change
@@ -18,73 +18,73 @@ func TestMetadata(t *testing.T) {
importKey bool
}{
{
"EC/P256/Generated",
"EC-P256/Generated",
SlotAuthentication,
Key{AlgECCP256, PINPolicyNever, TouchPolicyNever},
false,
},
{
"EC/P384/Generated",
"EC-P384/Generated",
SlotAuthentication,
Key{AlgECCP384, PINPolicyNever, TouchPolicyNever},
false,
},
{
"RSA/1024/Generated",
"RSA-1024/Generated",
SlotAuthentication,
Key{AlgRSA1024, PINPolicyNever, TouchPolicyNever},
false,
},
{
"RSA/2048/Generated",
"RSA-2048/Generated",
SlotAuthentication,
Key{AlgRSA2048, PINPolicyNever, TouchPolicyNever},
false,
},
{
"RSA/3072/Generated",
"RSA-3072/Generated",
SlotAuthentication,
Key{AlgRSA3072, PINPolicyNever, TouchPolicyNever},
false,
},
{
"RSA/4096/Generated",
"RSA-4096/Generated",
SlotAuthentication,
Key{AlgRSA4096, PINPolicyNever, TouchPolicyNever},
false,
},
{
"EC/P256/Imported",
"EC-P256/Imported",
SlotAuthentication,
Key{AlgECCP256, PINPolicyNever, TouchPolicyNever},
true,
},
{
"EC/P384/Imported",
"EC-P384/Imported",
SlotAuthentication,
Key{AlgECCP384, PINPolicyNever, TouchPolicyNever},
true,
},
{
"RSA/1024/Imported",
"RSA-1024/Imported",
SlotAuthentication,
Key{AlgRSA1024, PINPolicyNever, TouchPolicyNever},
true,
},
{
"RSA/2048/Imported",
"RSA-2048/Imported",
SlotAuthentication,
Key{AlgRSA2048, PINPolicyNever, TouchPolicyNever},
true,
},
{
"RSA/3072/Imported",
"RSA-3072/Imported",
SlotAuthentication,
Key{AlgRSA3072, PINPolicyNever, TouchPolicyNever},
true,
},
{
"RSA/4096/Imported",
"RSA-4096/Imported",
SlotAuthentication,
Key{AlgRSA4096, PINPolicyNever, TouchPolicyNever},
true,
@@ -144,7 +144,7 @@ func TestMetadata(t *testing.T) {
}

if test.importKey {
key := testKey(t, test.key.Algorithm.algType(), test.key.Algorithm.bits())
key := testKey(t, test.key.Algorithm)

err := c.SetPrivateKeyInsecure(DefaultManagementKey, test.slot, key, test.key)
require.NoError(t, err, "importing key")
30 changes: 30 additions & 0 deletions mockdata/TestAttestation/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions mockdata/TestAuthenticate/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions mockdata/TestChangeManagementKey/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions mockdata/TestChangePIN/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions mockdata/TestChangePUK/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
23 changes: 23 additions & 0 deletions mockdata/TestDecryptRSA/RSA-1024/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
24 changes: 24 additions & 0 deletions mockdata/TestDecryptRSA/RSA-2048/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions mockdata/TestDecryptRSA/RSA-3072/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions mockdata/TestDecryptRSA/RSA-4096/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 39 additions & 0 deletions mockdata/TestDeleteKey/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
22 changes: 22 additions & 0 deletions mockdata/TestGenerateKey/P-256/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
22 changes: 22 additions & 0 deletions mockdata/TestGenerateKey/P-384/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
22 changes: 22 additions & 0 deletions mockdata/TestGenerateKey/RSA-1024/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
23 changes: 23 additions & 0 deletions mockdata/TestGenerateKey/RSA-2048/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions mockdata/TestGenerateKey/RSA-3072/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions mockdata/TestGenerateKey/RSA-4096/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions mockdata/TestGetVersion/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions mockdata/TestLogin/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions mockdata/TestLoginNeeded/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions mockdata/TestMetadata/ECC/P256/Generated/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions mockdata/TestMetadata/ECC/P256/Imported/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions mockdata/TestMetadata/ECC/P384/Generated/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions mockdata/TestMetadata/ECC/P384/Imported/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions mockdata/TestMetadata/PINPolicy/Always/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions mockdata/TestMetadata/PINPolicy/Once/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions mockdata/TestMetadata/RSA/1024/Generated/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions mockdata/TestMetadata/RSA/1024/Imported/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions mockdata/TestMetadata/RSA/2048/Generated/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions mockdata/TestMetadata/RSA/2048/Imported/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions mockdata/TestMetadata/RSA/3072/Generated/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions mockdata/TestMetadata/RSA/3072/Imported/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 34 additions & 0 deletions mockdata/TestMetadata/RSA/4096/Generated/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions mockdata/TestMetadata/RSA/4096/Imported/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit ec55978

Please sign in to comment.