GithubHelp home page GithubHelp logo

go-piv / piv-go Goto Github PK

View Code? Open in Web Editor NEW
331.0 331.0 59.0 129 KB

Keys and certificates for YubiKeys, written in Go

License: Apache License 2.0

Go 98.58% Python 1.37% Makefile 0.05%
cryptography golang piv smart-cards yubikey

piv-go's People

Contributors

areese avatar clausecker avatar daknob avatar deuill avatar dnesting avatar duo-lfalsetta avatar ericchiang avatar gonzoua avatar hslatman avatar jmg292 avatar joemiller avatar jstasiak avatar kilimnik avatar laisky avatar merovius avatar nickray avatar oreparaz avatar psanford avatar qbit avatar rawkode avatar stv0g avatar tobiaskohlbau avatar tv42 avatar xoebus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

piv-go's Issues

Reordering the TouchPolicy in #74 makes the strictness order wrong

TouchPolicyAlways is "stricter" than TouchPolicyCached, however it is "less than" TouchPolicyCached in the code due to #74. This makes it hard to verify a minimum strictness. Compare to PINPolicy:


if cond.PINPolicy > attestation.PINPolicy {
    return fmt.Errorf("Key's PINPolicy %v is less strict than the minimum %v", attestation.PINPolicy, cond.PINPolicy)
}

Because TouchPolicy isn't ordered by strictness, checking it is much harder. It seems a bit silly to make the (once written) parsing code simpler at the expense of use of the values. What do you think?

Incompatibility with Go 1.20rc1

OS: macOS 13.1

Consider the following code:

package main

import (
	"log"

	"github.com/go-piv/piv-go/piv"
)

func main() {
	log.SetFlags(0)
	if err := run(); err != nil {
		log.Fatal(err)
	}
}

func run() error {
	cards, err := piv.Cards()
	if err != nil {
		return err
	}
	log.Print(cards)
	return nil
}

When run with go version go1.20rc1 darwin/arm64, it fails with

connecting to pscs: the Smart card resource manager is not running

With go version go1.19.4 darwin/arm64 however, it works as expected, printing [Yubico YubiKey OTP+FIDO+CCID].

piv: PIN caching doesn't seem to work

Hey, thank you so much for landing these changes so fast, without me even asking!

I tried v1.4.0 with yubikey-agent, and it doesn't quite work =(

  1. It requires a touch before asking for the PIN, presumably because it issues a sign request first, then when it fails it prompts for the PIN.
  2. This happens at every sign operation, so PIN caching does not seem to actually work, even if I'm pretty sure I set this up with a "once" PIN policy.

No idea what's going on with (2), but for (1) I think you can learn about the policy from the attestation certificate, and behave accordingly.

Certificates TSL - error:1408F10B:SSL routines:ssl3_get_record:wrong version number

Hello,

I'm trying to use an x.509 certificate to serve TLS traffic;

The certificate has been generated in the same way as key_test.go.

I defined the http serve like this:

mux := http.NewServeMux()

mux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
	writer.WriteHeader(200)
	writer.Write([]byte("hello world"))
})

logger := log.New(os.Stdout, "http: ", log.LstdFlags)

s := &http.Server{
	Addr:     ":1443",
	ErrorLog: logger,
	TLSConfig: &tls.Config{
		Certificates: []tls.Certificate{
			{
				Certificate: [][]byte{cert.Raw},
				PrivateKey:  priv,
			},
		},
	},
	Handler: mux,
}

When I try to access to https://localhost:1443 I have this error with the curl command:

โžœ  ~ curl -vvv https://localhost:1443/
*   Trying ::1:1443...
* Connected to localhost (::1) port 1443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* error:1408F10B:SSL routines:ssl3_get_record:wrong version number
* Closing connection 0
curl: (35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number

I've created a repository:
https://github.com/shenron/try-piv-go


I've some difficulty to understand if the problem come from the combination with the private key. Or if it's something else.

doesn't build on i686

When trying to build this on a 32 bit machine, the 0x8010002E constant overflowsC.long:

Building subPackage ./.
github.com/go-piv/piv-go/piv
# github.com/go-piv/piv-go/piv
vendor/github.com/go-piv/piv-go/piv/pcsc_linux.go:29:12: constant 2148532270 overflows _Ctype_long
github.com/pkg/errors
github.com/gopasspw/gopass/pkg/pinentry
golang.org/x/crypto/internal/subtle
golang.org/x/crypto/chacha20
golang.org/x/crypto/curve25519
golang.org/x/crypto/ed25519
golang.org/x/crypto/poly1305
golang.org/x/crypto/blowfish
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
golang.org/x/crypto/ssh
golang.org/x/crypto/ssh/agent
golang.org/x/sys/unix
golang.org/x/crypto/ssh/terminal
builder for '/nix/store/7v5l6inyjav2hw79hann01xrdabv20x5-yubikey-agent-0.1.3.drv' failed with exit code 1

Negative error codes are not mapped

When the YubiKey is busy I get an error like unknown pcsc return code 0x-7feffff5 on macOS.

0x-7feffff5 is the negative of 0x8010000B, which would be correctly mapped to "the smart card cannot be accessed because of other connections outstanding".

Non-standard instructions

Hi! I am writing a PIV application for SoloKeys, and found some idiosyncrasies in this repository (which is named piv-go and not yubico-piv-go ๐Ÿ‘ผ).

This is the start of the "handshake" when I run @FiloSottile's https://github.com/FiloSottile/yubikey-agent:

10055575 APDU: 00 A4 04 00 05 A0 00 00 03 08                                                                                                                                                                                                                                     
00001734 SW: 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 90 00

00001345 APDU: 00 FD 00 00 00                                                                                                                                                                                                                                                    
00004496 SW: 04 03 04 90 00                                                                                                                                                                                                                                                      

00000965 APDU: 00 A4 04 00 08 A0 00 00 05 27 20 01 01                                                                                                                                                                                                                            
00002205 SW: 04 03 04 01 05 00 05 0F 00 00 90 00

00000661 APDU: 00 01 10 00 00                                                                                                                                                                                                                                                    
00000929 SW: 00 52 F7 43 90 00

For one, you send instruction 0xFD (getVersion) against the PIV app, I guess because Yubico implements it there. Secondly, instruction 0x01 is used, is this also an idiosyncrasy? As ISO 7816-4 does not contain it. I can "fake" responses here, but it would be neat if answering these commands for non-Yubikeys would not be mandatory.

Also, the "AID" in

aidPIV = [...]byte{0xa0, 0x00, 0x00, 0x03, 0x08}
is only the RID for NIST, the AID should be either the right-truncated or full version, including the the PIV app's PIX [0x00, 0x00, 0x10, 0x00] or additionally its version [0x01, 0x00].

Expose keyRSA and keyEd25519 type

Hi!
I think that keyRSA and keyEd25519 type should be exposed otherwise golang is not able to use purpose-specific interfaces such as Signer and Decrypter of that type.

For example:

priv, err := yk.PrivateKey(...)  // using a RSA pub key

// cannot cast to *piv.keyRSA like: "priv.(*piv.keyRSA)" since the type is not exposed

priv.Decrypt(....) // will not work, golang is not able to convert crypto.PrivateKey, to piv.keyRSA since is not exposed

Let me know if I am wrong, thanks!

RSA stored with OpenPGP

Hello,

Thank you very much for this project.
On my Yubikey I imported RSA keys to be able to sign/encrypt/authenticate. I use OpenPGP for this. I'm wondering if I can use this project to do the same.

My PublicKeyAlgorithm is ECDSA, so I guess it's the "internal" certificat of my Yubikey not my imported keys.

Thanks.

Support windows via winscard

Inspired by the last stream of @FiloSottile I've digged into piv-go and windows and created a port for windows. Are the maintainers willing to merge windows patches into this repo? If it's fine I would put together a PR and would be willing to work with everyone involved.

Thanks in advance and thanks for this nice library.

Cross compile linux amd64 -> darwin amd64 issues with CGO (`<angled> include; use "quotes" instead`)

Hey folks, I've been beating my head against a wall trying to cross compile this library using cgo on a amd64 linux system to be used on a amd64 mac using zig which is using gcc under the covers but continually get <angled> include; use "quotes" instead errors. Does anyone know a way/flag around this?

root@115867f33658:/tmp/project# CC="${ZIG_HOME}/zig cc -target x86_64-macos -isystem /usr/include/ -L/usr/lib/ -Wno-macro-redefined -Wno-error-implicit-function-declaration"\
GOOS=darwin GOARCH=amd64  \
go build -o project

# github.com/go-piv/piv-go/piv
In file included from /go/pkg/mod/github.com/go-piv/[email protected]/piv/pcsc_unix.go:32:
/usr/include/PCSC/winscard.h:41:10: error: 'pcsclite.h' file not found with <angled> include; use "quotes" instead
#include <pcsclite.h>
         ^
In file included from /go/pkg/mod/github.com/go-piv/[email protected]/piv/pcsc_unix.go:32:
In file included from /usr/include/PCSC/winscard.h:41:
/usr/include/PCSC/pcsclite.h:45:10: error: 'wintypes.h' file not found with <angled> include; use "quotes" instead
#include <wintypes.h>
         ^
2 errors generated.

Determine a policy for handling imported keys

These were explicitly left out of the API since hardware bound keys are a much stronger security assertion if they never leave the key and you can prove that they're actually bound to hardware. They also make things harder because of they won't have an attestation certificate for us to get hints about PIN policy.

Consider documenting that imported keys aren't supported or explicitly handling them. Either way it's unlikely we'll provide an API to import keys.

For KeyAuth, the API to handle imported keys might look like:

type KeyAuth struct {
    PIN       string
    PINPrompt func() (string, error)

    // ImportedKeyPINPolicy is required for interacting with other tools that import
    // keys that take a PIN.
    //
    // If a key was generated by this package, this value doesn't need to be set.
    ImportedKeyPINPolicy PINPolicy
}

rsassa-pss signatures not supported

I'm using a certificate stored on a Yubikey to authenticate with a server. After enabling TLS 1.3, the flow broke because the TLS handshake attempts to use rsassa-pss and this library prevents that here:

	if _, ok := opts.(*rsa.PSSOptions); ok {
		return nil, fmt.Errorf("rsassa-pss signatures not supported")
	}

Disabling rsassa-pss is not possible, unfortunately.

Interestingly, if I comment out the code above, the Yubikey seems to support this just fine, and the authentication succeeds.

What was the historical reason for introducing the check above? Was it related to the issues that golang had introducing support for rsassa-pss? Or maybe older Yubikeys did not support it?

Could removing this check be an option?

Unable to retrieve public key

Hi! Thank you for the library.
I'm trying to fetch the public key for generated keypair but this always returns in command failed: smart card error 6a82: data object or application not found.

Code:

	key := piv.Key{
		Algorithm:   piv.AlgorithmRSA2048,
		PINPolicy:   piv.PINPolicyOnce,
		TouchPolicy: piv.TouchPolicyNever,
	}

	newPubKey, err := yubi.GenerateKey(piv.DefaultManagementKey, piv.SlotAuthentication, key)
	if err != nil {
		logger.WithError(err).Fatal("could not generate new public key on the security device")
	}

	cert, err := yubi.Certificate(piv.SlotAuthentication)
	if err != nil {
                // ERROR HERE
		return nil, errors.Wrap(err, "could not get certificate from yubikey")
	}

Any ideas?

Support for linux armv7

I want to build this project to linux armv7 device
cmd: env GOOS=linux GOARCH=arm GOARM=7 go build
got errors:
.../github.com/go-piv/[email protected]/piv/piv.go:103:7: undefined: scContext
.../github.com/go-piv/[email protected]/piv/piv.go:104:7: undefined: scHandle
.../github.com/go-piv/[email protected]/piv/piv.go:105:7: undefined: scTx
.../github.com/go-piv/[email protected]/piv/key.go:521:19: undefined: scTx
.../github.com/go-piv/[email protected]/piv/key.go:614:29: undefined: scTx
.../github.com/go-piv/[email protected]/piv/key.go:668:24: undefined: scTx
.../github.com/go-piv/[email protected]/piv/key.go:773:59: undefined: scTx
.../github.com/go-piv/[email protected]/piv/key.go:929:22: undefined: scTx
.../github.com/go-piv/[email protected]/piv/key.go:1085:22: undefined: scTx
.../github.com/go-piv/[email protected]/piv/key.go:1130:24: undefined: scTx
.../github.com/go-piv/[email protected]/piv/key.go:1130:24: too many errors

Figure out what version of YubiKeys support PIN caching

Currently we're assuming > 4.3.0 since I only have a v4.3.7 and v3.4.9 key to test with

piv-go/piv/piv_test.go

Lines 137 to 152 in 2184bb6

func TestYubiKeyLoginNeeded(t *testing.T) {
yk, close := newTestYubiKey(t)
defer close()
testRequiresVersion(t, yk, 4, 3, 0)
if !ykLoginNeeded(yk.tx) {
t.Errorf("expected login needed")
}
if err := ykLogin(yk.tx, DefaultPIN); err != nil {
t.Fatalf("login: %v", err)
}
if ykLoginNeeded(yk.tx) {
t.Errorf("expected no login needed")
}
}

If someone can confirm that that test passes with an older version of a YubiKey (e.g. 4.2.X), we can support PIN caching and PINPolicyOnce for those versions.

To test against a YubiKey, comment out the version and run (this will destroy all data on your PIV applet but leave GPG and U2F/WebAuthN data unaffected):

go test -v -run=^TestYubiKeyReset$ . -wipe-yubikey
go test -v -run=^TestYubiKeyLoginNeeded$ . -wipe-yubikey

Unable to build on macOS

I am trying to build yubikey-agent on macOS (Apple M1 chip) and I see:

# github.com/go-piv/piv-go/piv
../../go/pkg/mod/github.com/go-piv/[email protected]/piv/piv.go:103:7: undefined: scContext
../../go/pkg/mod/github.com/go-piv/[email protected]/piv/piv.go:104:7: undefined: scHandle
../../go/pkg/mod/github.com/go-piv/[email protected]/piv/piv.go:105:7: undefined: scTx
../../go/pkg/mod/github.com/go-piv/[email protected]/piv/key.go:521:19: undefined: scTx
../../go/pkg/mod/github.com/go-piv/[email protected]/piv/key.go:614:29: undefined: scTx
../../go/pkg/mod/github.com/go-piv/[email protected]/piv/key.go:668:24: undefined: scTx
../../go/pkg/mod/github.com/go-piv/[email protected]/piv/key.go:773:59: undefined: scTx
../../go/pkg/mod/github.com/go-piv/[email protected]/piv/key.go:929:22: undefined: scTx
../../go/pkg/mod/github.com/go-piv/[email protected]/piv/key.go:1085:22: undefined: scTx
../../go/pkg/mod/github.com/go-piv/[email protected]/piv/key.go:1130:24: undefined: scTx
../../go/pkg/mod/github.com/go-piv/[email protected]/piv/key.go:1130:24: too many errors

Google search brought me here, and I saw that some work (#114, #94, #71) already went into supporting builds on ARM cpus. I am aware that yubikey-agent is available via homebrew (on Apple M1 chips), however I am not sure how they achieved that. The homebrew formulas did not reveal anything special (I admit my ruby skills are not great, so I might have missed something).

My build environment is miniconda with native compilers, etc. I was able to build pcsc-lite (this is what they do in homebrew, however it does not seem to have any effect - which would confirm what yubikey-agent says "nothing extra is needed to build the package").

Any help with supporting a native build on macOS would be greatly appreciated.

Thanks in advance!

Slot* variables using wrong Object IDs?

https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf#page=30 (in agreement with https://developers.yubico.com/PIV/Introduction/Certificate_slots.html) says:

Purpose Key Reference BER-TLV Tag
PIV Authentication 9A 5FC105
Digital Signature 9C 5FC10A
Key Management 9D 5FC10B
Card Authentication 9E 5FC101

piv-go/piv/key.go

Lines 224 to 226 in 4cd4b28

SlotAuthentication = Slot{0x9a, 0x5fc101}
SlotSignature = Slot{0x9c, 0x5fc10a}
SlotCardAuthentication = Slot{0x9e, 0x5fc10b}

Purpose Slot Tag
SlotAuthentication 0x9a 0x5fc101 seems to be using object for card auth?
SlotSignature 0x9c 0x5fc10a ok
SlotCardAuthentication 0x9e 0x5fc10b seems to be using object for key management?

When inspecting the card through pkcs11-tool it does look like the wrong slots are being manipulated.

Also should there be a variable for the Key Management slot?

NFC and ISO 7816 support

With the current implementation, it doesn't seem practical detect whether we're dealing with a yubikey via NFC, as the only way we can really do so is by looking at the reader name. But that doesn't work if it's over an NFC reader, which will have a different name under PCSC. I think the ideal way to do this would be to look at the card's ATR, which the current PCSC code doesn't support. I've added Windows support for that, (here: https://github.com/1Dragoon/piv-go) though I don't have a means of easily testing any support I add for other platforms.

Once the ATR is obtained, based on this:

http://ludovic.rousseau.free.fr/softwares/pcsc-tools/smartcard_list.txt

It looks like all yubikeys will have some variation of the word "yubikey" in the historical bytes field, sometimes with the first or last y omitted.

Add support to set CHUID and CCC

It seems that OSX (at least on 10.14.6) will not accept smartcards without a CHUID resulting in the following error:
failed to read CHUID record (Error Domain=CryptoTokenKit Code=-6 "(null)")
and the yubikey is not showing in
security list-smartcards

The card works for pkcs11 use cases, but is not recognized.

Values for yubikey CHUID and CCC are available here:
https://github.com/Yubico/yubico-piv-tool/blob/ebee7f63b85fe4373efc4d8d44cbe5fe321c158c/lib/util.c#L44

Windows: the Smart card resource manager is not running

Hi! Trying to get a go-piv client working on Windows.
I've started 'smart card' in services.msc, however a call to GetCards() will always error with connecting to pscs: the Smart card resource manager is not running.

Any idea?

incorrect TouchPolicy mapping in the attestation code

The PIV spec says this about the TouchPolicy stored as byte 2 in the KeyPolicy OID:

1.3.6.1.4.1.41482.3.8: Two bytes, the first encoding pin policy and the second touch policy

Pin policy: 01 - never, 02 - once per session, 03 - always

Touch policy: 01 - never, 02 - always, 03 - cached for 15s

in key.go the const's are out of order:

// Touch policies supported by this package.
const (
	TouchPolicyNever TouchPolicy = iota + 1
	TouchPolicyCached
	TouchPolicyAlways
)

๐Ÿ‘† Cached (2) and Always (3) are reversed. Should be Always=2 and Cached=3

The other spots where touchpolicy parsing/mapping is implemented have the correct values:

var touchPolicyMap = map[TouchPolicy]byte{
	TouchPolicyNever:  0x01,
	TouchPolicyAlways: 0x02,
	TouchPolicyCached: 0x03,
}
		case 0x01:
			a.TouchPolicy = TouchPolicyNever
		case 0x02:
			a.TouchPolicy = TouchPolicyAlways
		case 0x03:
			a.TouchPolicy = TouchPolicyCached

YubiKey 5Ci form factor

I'm using the piv-go library via yubikey-agent with a YubiKey 5Ci. I was getting errors when trying to sign which looked like:

agent 13: failed to prepare private key: parse attestation cert: parsing extension: unrecognized formfactor: 0x5

I patched the library with the following patch and everything seems to work as expected now.

diff --git a/piv/key.go b/piv/key.go
index f8679b1..fc1eff3 100644
--- a/piv/key.go
+++ b/piv/key.go
@@ -66,6 +66,7 @@ const (
 	FormfactorUSBANano
 	FormfactorUSBCKeychain
 	FormfactorUSBCNano
+	FormfactorUSBCLightning
 )
 
 // Attestation returns additional information about a key attested to be on a
@@ -142,6 +143,8 @@ func (a *Attestation) addExt(e pkix.Extension) error {
 			a.Formfactor = FormfactorUSBCKeychain
 		case 0x04:
 			a.Formfactor = FormfactorUSBCNano
+		case 0x05:
+			a.Formfactor = FormfactorUSBCLightning
 		default:
 			return fmt.Errorf("unrecognized formfactor: 0x%x", e.Value[0])
 		}

Would you accept a pull request to add this form factor to the library?

Thanks!

Cross-compiling requirements

Hi!

Curious what packages I'd need (next to libpcsclite-dev) for cross-compiling?

Error: ../../pkg/ui/open_linux.go:4:9: undefined: exec
66
# github.com/go-piv/piv-go/piv
67
Error: /home/runner/go/pkg/mod/github.com/go-piv/[email protected]/piv/key.go:448:19: undefined: scTx
68
Error: /home/runner/go/pkg/mod/github.com/go-piv/[email protected]/piv/key.go:541:29: undefined: scTx
69
Error: /home/runner/go/pkg/mod/github.com/go-piv/[email protected]/piv/key.go:595:24: undefined: scTx
70
Error: /home/runner/go/pkg/mod/github.com/go-piv/[email protected]/piv/key.go:708:59: undefined: scTx
71
Error: /home/runner/go/pkg/mod/github.com/go-piv/[email protected]/piv/key.go:864:22: undefined: scTx
72
Error: /home/runner/go/pkg/mod/github.com/go-piv/[email protected]/piv/key.go:1020:22: undefined: scTx
73
Error: /home/runner/go/pkg/mod/github.com/go-piv/[email protected]/piv/key.go:1065:24: undefined: scTx
74
Error: /home/runner/go/pkg/mod/github.com/go-piv/[email protected]/piv/piv.go:103:7: undefined: scContext
75
Error: /home/runner/go/pkg/mod/github.com/go-piv/[email protected]/piv/piv.go:104:7: undefined: scHandle
76
Error: /home/runner/go/pkg/mod/github.com/go-piv/[email protected]/piv/piv.go:105:7: undefined: scTx
77
Error: /home/runner/go/pkg/mod/github.com/go-piv/[email protected]/piv/key.go:1065:24: too many errors
78

Bump go.mod version

Could I prompt you to bump the go.mod version, it's currently 1.16.

Per the Go release policy, they only support two prior major releases.

Also this is not just a cosmetic issue, per the gomod-ref , this value affects (a) use of new language features (b) behaviour of go command. Bumping the go.mod version has a positive effect on both.

Cross compiling for ARM

I get the below error when trying to build the piv-go project to run on arm. Apologies if I am simply missing a dependency.

ubuntu@tmc:~/go/src/github.com/filosottile/yubikey-agent$ GOOS=linux GOARCH=arm GOARM=5 go build 
# github.com/go-piv/piv-go/piv
../../../../pkg/mod/github.com/go-piv/[email protected]/piv/piv.go:100:7: undefined: scContext
../../../../pkg/mod/github.com/go-piv/[email protected]/piv/piv.go:101:7: undefined: scHandle
../../../../pkg/mod/github.com/go-piv/[email protected]/piv/piv.go:102:7: undefined: scTx

ubuntu@tmc:~/go/pkg/mod/github.com/go-piv/[email protected]/piv$ GOOS=linux GOARCH=arm GOARM=5 go build
# github.com/go-piv/piv-go/piv
./piv.go:100:7: undefined: scContext
./piv.go:101:7: undefined: scHandle
./piv.go:102:7: undefined: scTx

replace c_pcsclite with go-libpcsclite

This a question not an issue, my question is I recently came across the library go-libpcsclite which is implemented completely in go, I tried to test it (not intensive) but it worked for me (signing and verifying).
So I ran a complete test using (go test -v ./... --wipe-yubikey) and it was 80% successful, if took the time to fix the other issues would you merge the change into the main repository.

--- PASS: TestYubiKeySignECDSA (4.44s)
=== RUN   TestYubiKeyECDSASharedKey
=== RUN   TestYubiKeyECDSASharedKey/good
=== RUN   TestYubiKeyECDSASharedKey/bad
=== RUN   TestYubiKeyECDSASharedKey/bad/size
--- PASS: TestYubiKeyECDSASharedKey (0.18s)
    --- PASS: TestYubiKeyECDSASharedKey/good (0.06s)
    --- PASS: TestYubiKeyECDSASharedKey/bad (0.01s)
        --- PASS: TestYubiKeyECDSASharedKey/bad/size (0.01s)
=== RUN   TestPINPrompt
=== RUN   TestPINPrompt/Never
=== RUN   TestPINPrompt/Once
=== RUN   TestPINPrompt/Always
--- PASS: TestPINPrompt (1.15s)
    --- PASS: TestPINPrompt/Never (0.38s)
    --- PASS: TestPINPrompt/Once (0.38s)
    --- PASS: TestPINPrompt/Always (0.39s)
=== RUN   TestSlots
=== RUN   TestSlots/Authentication
=== RUN   TestSlots/CardAuthentication
=== RUN   TestSlots/KeyManagement
=== RUN   TestSlots/Signature
--- PASS: TestSlots (2.74s)
    --- PASS: TestSlots/Authentication (0.47s)
    --- PASS: TestSlots/CardAuthentication (0.46s)
    --- PASS: TestSlots/KeyManagement (0.46s)
    --- PASS: TestSlots/Signature (0.47s)
=== RUN   TestYubiKeySignRSA
=== RUN   TestYubiKeySignRSA/rsa1024
=== RUN   TestYubiKeySignRSA/rsa2048
--- PASS: TestYubiKeySignRSA (2.31s)
    --- PASS: TestYubiKeySignRSA/rsa1024 (0.71s)
    --- PASS: TestYubiKeySignRSA/rsa2048 (1.59s)
=== RUN   TestYubiKeyDecryptRSA
=== RUN   TestYubiKeyDecryptRSA/rsa1024
=== RUN   TestYubiKeyDecryptRSA/rsa2048
--- PASS: TestYubiKeyDecryptRSA (7.79s)
    --- PASS: TestYubiKeyDecryptRSA/rsa1024 (0.71s)
    --- PASS: TestYubiKeyDecryptRSA/rsa2048 (7.08s)
=== RUN   TestYubiKeyAttestation
--- PASS: TestYubiKeyAttestation (0.24s)
=== RUN   TestYubiKeyStoreCertificate
--- PASS: TestYubiKeyStoreCertificate (0.18s)
=== RUN   TestYubiKeyGenerateKey
=== RUN   TestYubiKeyGenerateKey/ec_256
=== RUN   TestYubiKeyGenerateKey/ec_384
=== RUN   TestYubiKeyGenerateKey/rsa_1024
=== RUN   TestYubiKeyGenerateKey/rsa_2048
--- PASS: TestYubiKeyGenerateKey (9.69s)
    --- PASS: TestYubiKeyGenerateKey/ec_256 (0.10s)
    --- PASS: TestYubiKeyGenerateKey/ec_384 (0.14s)
    --- PASS: TestYubiKeyGenerateKey/rsa_1024 (0.65s)
    --- PASS: TestYubiKeyGenerateKey/rsa_2048 (8.79s)
=== RUN   TestYubiKeyPrivateKey
--- PASS: TestYubiKeyPrivateKey (0.31s)
=== RUN   TestYubiKeyPrivateKeyPINError
--- PASS: TestYubiKeyPrivateKeyPINError (0.24s)
=== RUN   TestRetiredKeyManagementSlot
=== RUN   TestRetiredKeyManagementSlot/Non-existent_slot,_before_range
=== RUN   TestRetiredKeyManagementSlot/Non-existent_slot,_after_range
=== RUN   TestRetiredKeyManagementSlot/First_retired_slot_key
=== RUN   TestRetiredKeyManagementSlot/Last_retired_slot_key
--- PASS: TestRetiredKeyManagementSlot (0.00s)
    --- PASS: TestRetiredKeyManagementSlot/Non-existent_slot,_before_range (0.00s)
    --- PASS: TestRetiredKeyManagementSlot/Non-existent_slot,_after_range (0.00s)
    --- PASS: TestRetiredKeyManagementSlot/First_retired_slot_key (0.00s)
    --- PASS: TestRetiredKeyManagementSlot/Last_retired_slot_key (0.00s)
=== RUN   TestContextClose
--- PASS: TestContextClose (0.00s)
=== RUN   TestContextListReaders
--- PASS: TestContextListReaders (0.00s)
=== RUN   TestHandle
--- PASS: TestHandle (0.00s)
=== RUN   TestTransaction
    pcsc_test.go:72: disconnecting from handle: EOF
    pcsc_test.go:30: closing context: write unix @->/run/pcscd/pcscd.comm: write: broken pipe
--- FAIL: TestTransaction (2.00s)
=== RUN   TestErrors
--- PASS: TestErrors (0.00s)
=== RUN   TestGetVersion
    pcsc_test.go:72: disconnecting from handle: EOF
    pcsc_test.go:30: closing context: write unix @->/run/pcscd/pcscd.comm: write: broken pipe
--- FAIL: TestGetVersion (2.00s)
=== RUN   TestCards
--- PASS: TestCards (0.00s)
=== RUN   TestNewYubiKey
--- PASS: TestNewYubiKey (0.00s)
=== RUN   TestMultipleConnections
    piv_test.go:136: expected scErr, got connecting to smart card: invalid return code: 8010000b (sharing violation)
--- FAIL: TestMultipleConnections (0.00s)
=== RUN   TestYubiKeySerial
--- PASS: TestYubiKeySerial (0.00s)
=== RUN   TestYubiKeyLoginNeeded
--- PASS: TestYubiKeyLoginNeeded (0.06s)
=== RUN   TestYubiKeyPINRetries
    piv_test.go:177: getting retries: expected error code from empty pin
--- FAIL: TestYubiKeyPINRetries (0.00s)
=== RUN   TestYubiKeyReset
--- PASS: TestYubiKeyReset (0.97s)
=== RUN   TestYubiKeyLogin
--- PASS: TestYubiKeyLogin (0.01s)
=== RUN   TestYubiKeyAuthenticate
--- PASS: TestYubiKeyAuthenticate (0.00s)
=== RUN   TestYubiKeySetManagementKey
--- PASS: TestYubiKeySetManagementKey (0.02s)
=== RUN   TestYubiKeyUnblockPIN
--- PASS: TestYubiKeyUnblockPIN (0.04s)
=== RUN   TestYubiKeyChangePIN
--- PASS: TestYubiKeyChangePIN (0.03s)
=== RUN   TestYubiKeyChangePUK
--- PASS: TestYubiKeyChangePUK (0.03s)
=== RUN   TestChangeManagementKey
--- PASS: TestChangeManagementKey (0.01s)
=== RUN   TestMetadata
--- PASS: TestMetadata (0.92s)
=== RUN   TestMetadataUnmarshal
--- PASS: TestMetadataUnmarshal (0.00s)
=== RUN   TestMetadataMarshal
--- PASS: TestMetadataMarshal (0.00s)
=== RUN   TestMetadataUpdate
--- PASS: TestMetadataUpdate (0.00s)
=== RUN   TestMetadataAdditoinalFields
--- PASS: TestMetadataAdditoinalFields (0.00s)
FAIL
FAIL	github.com/go-piv/piv-go/piv	35.396s
FAIL

Error: Unable to open the Yubikey card: connecting to smart card: the smart card cannot be accessed because of other connections outstanding

Hello

I'm able to build a program with this library that allows me to successfully interact with my YubiKey. However under some conditions, e.g. after some idle period, I'm getting the aforementioned erorr:

Error: Unable to open the Yubikey card: connecting to smart card: the smart card cannot be accessed because of other connections outstanding

I'm not sure if there is anything wrong with piv-go. But I'm quite puzzled since I make thorough use of the Close() method and additionally I don't get this error with other tools e.g. libykcs11.so.

ECDH for using P-384 keys for more than signing

go-ykpiv's CGo wrapper of libykpiv has this:

https://godoc.org/github.com/go-piv/go-ykpiv#Slot.Decrypt

f the slot holds an EC key, then we will perform ECDH and return the shared secret. In this case, msg must be the peer's public key in octet form, as specified in section 4.3.6 of ANSI X9.62.

I've tested that to work. I would, however, like to use pure-Go libraries.

I couldn't figure out how to get ECDH working with piv-go. For the CGo version, sign and decrypt look very similar:

https://github.com/go-piv/go-ykpiv/blob/32315ce599d8e21e91880e6ecdce55a98420ddc0/decrypt.go#L68
https://github.com/go-piv/go-ykpiv/blob/32315ce599d8e21e91880e6ecdce55a98420ddc0/sign.go#L166

and so do libykpiv's two functions, they both call the same function:

https://github.com/Yubico/yubico-piv-tool/blob/0b27308560ab4f3df4bc29a179e1c91649ce0629/lib/ykpiv.c#L1144
https://github.com/Yubico/yubico-piv-tool/blob/0b27308560ab4f3df4bc29a179e1c91649ce0629/lib/ykpiv.c#L1126

go-ykpiv has a helpful test case here:

https://github.com/go-piv/go-ykpiv/blob/32315ce599d8e21e91880e6ecdce55a98420ddc0/ykpiv_test.go#L522

But I can't see where exactly signing and decrypting are different to make ECDH work with go-piv. Any thoughts?

Tests failing on older YubiKeys

Yubico Yubikey NEO OTP+U2F+CCID
Applet version: piv.version{major:0x1, minor:0x0, patch:0x4}

Logs

=== RUN   TestYubiKeySignECDSA                                                                        
    TestYubiKeySignECDSA: key_test.go:64: signing failed: command failed: smart card error 6982: security status not satisfied
--- FAIL: TestYubiKeySignECDSA (0.94s)                                                                                                                                                                      
=== RUN   TestPINPrompt                                                                                                                                                                                     
=== RUN   TestPINPrompt/Never            
    TestPINPrompt/Never: key_test.go:110: building private key: get attestation cert: command failed: smart card error 6d00
=== RUN   TestPINPrompt/Once                                                                          
    TestPINPrompt/Once: key_test.go:110: building private key: get attestation cert: command failed: smart card error 6d00
=== RUN   TestPINPrompt/Always                                                                        
    TestPINPrompt/Always: key_test.go:110: building private key: get attestation cert: command failed: smart card error 6d00
--- FAIL: TestPINPrompt (2.01s)                                                                       
    --- FAIL: TestPINPrompt/Never (0.67s)     
    --- FAIL: TestPINPrompt/Once (0.67s)                                                                                                                                                                    
    --- FAIL: TestPINPrompt/Always (0.67s)                                                            
=== RUN   TestSlots                    
=== RUN   TestSlots/Authentication                                                                                                                                                                          
    TestSlots/Authentication: key_test.go:153: attest: got err=command failed: smart card error 6d00, want=ErrNotFound                                                                                      
    TestSlots/Authentication: key_test.go:166: attest: command failed: smart card error 6d00
    TestSlots/Authentication: key_test.go:171: private key: get attestation cert: command failed: smart card error 6d00
=== RUN   TestSlots/CardAuthentication                                                                                                                                                            
    TestSlots/CardAuthentication: key_test.go:153: attest: got err=command failed: smart card error 6d00, want=ErrNotFound
    TestSlots/CardAuthentication: key_test.go:166: attest: command failed: smart card error 6d00
    TestSlots/CardAuthentication: key_test.go:171: private key: get attestation cert: command failed: smart card error 6d00
=== RUN   TestSlots/KeyManagement                  
    TestSlots/KeyManagement: key_test.go:153: attest: got err=command failed: smart card error 6d00, want=ErrNotFound
    TestSlots/KeyManagement: key_test.go:166: attest: command failed: smart card error 6d00
    TestSlots/KeyManagement: key_test.go:171: private key: get attestation cert: command failed: smart card error 6d00
=== RUN   TestSlots/Signature         
    TestSlots/Signature: key_test.go:153: attest: got err=command failed: smart card error 6d00, want=ErrNotFound
    TestSlots/Signature: key_test.go:166: attest: command failed: smart card error 6d00
    TestSlots/Signature: key_test.go:171: private key: get attestation cert: command failed: smart card error 6d00
--- FAIL: TestSlots (6.84s)                                                                           
    --- FAIL: TestSlots/Authentication (0.93s)                                                        
    --- FAIL: TestSlots/CardAuthentication (0.91s)
    --- FAIL: TestSlots/KeyManagement (0.91s)
    --- FAIL: TestSlots/Signature (0.91s)                                                             
=== RUN   TestYubiKeySignRSA          
=== RUN   TestYubiKeySignRSA/rsa1024  
    TestYubiKeySignRSA/rsa1024: key_test.go:249: signing failed: command failed: smart card error 6982: security status not satisfied
=== RUN   TestYubiKeySignRSA/rsa2048    
    TestYubiKeySignRSA/rsa2048: key_test.go:249: signing failed: command failed: smart card error 6982: security status not satisfied
--- FAIL: TestYubiKeySignRSA (19.47s)  
    --- FAIL: TestYubiKeySignRSA/rsa1024 (4.92s)
    --- FAIL: TestYubiKeySignRSA/rsa2048 (14.54s)
=== RUN   TestYubiKeyDecryptRSA       
=== RUN   TestYubiKeyDecryptRSA/rsa1024
    TestYubiKeyDecryptRSA/rsa1024: key_test.go:305: decryption failed: command failed: smart card error 6982: security status not satisfied
=== RUN   TestYubiKeyDecryptRSA/rsa2048  
    TestYubiKeyDecryptRSA/rsa2048: key_test.go:305: decryption failed: command failed: smart card error 6982: security status not satisfied
--- FAIL: TestYubiKeyDecryptRSA (36.03s)     
    --- FAIL: TestYubiKeyDecryptRSA/rsa1024 (4.67s) 
    --- FAIL: TestYubiKeyDecryptRSA/rsa2048 (31.36s)
=== RUN   TestYubiKeyAttestation      
    TestYubiKeyAttestation: key_test.go:325: getting attestation certificate: command failed: smart card error 6a82: data object or application not found
--- FAIL: TestYubiKeyAttestation (0.03s)
=== RUN   TestYubiKeyStoreCertificate              
--- PASS: TestYubiKeyStoreCertificate (3.54s)                                                         
=== RUN   TestYubiKeyGenerateKey                                                                      
=== RUN   TestYubiKeyGenerateKey/ec_256
=== RUN   TestYubiKeyGenerateKey/ec_384                                                                                                                                                                     
    TestYubiKeyGenerateKey/ec_384: key_test.go:462: generating key: command failed: smart card error 6a80: incorrect parameter in command data field
=== RUN   TestYubiKeyGenerateKey/rsa_1024
=== RUN   TestYubiKeyGenerateKey/rsa_2048     
--- FAIL: TestYubiKeyGenerateKey (20.94s)                                                             
    --- PASS: TestYubiKeyGenerateKey/ec_256 (0.67s) 
    --- FAIL: TestYubiKeyGenerateKey/ec_384 (0.07s)                                                   
    --- PASS: TestYubiKeyGenerateKey/rsa_1024 (5.02s)
    --- PASS: TestYubiKeyGenerateKey/rsa_2048 (15.18s)
=== RUN   TestYubiKeyPrivateKey               
    TestYubiKeyPrivateKey: key_test.go:492: getting private key: get attestation cert: command failed: smart card error 6d00
--- FAIL: TestYubiKeyPrivateKey (3.36s)                                                               
=== RUN   TestYubiKeyPrivateKeyPINError
    TestYubiKeyPrivateKeyPINError: key_test.go:542: getting private key: get attestation cert: command failed: smart card error 6d00
--- FAIL: TestYubiKeyPrivateKeyPINError (0.67s)                                                                                                                                                             
=== RUN   TestContextClose             
--- PASS: TestContextClose (0.00s)
=== RUN   TestContextListReaders                                                                                                                                                                  
--- PASS: TestContextListReaders (0.00s)
=== RUN   TestHandle                      
--- PASS: TestHandle (0.00s)                                                                          
=== RUN   TestTransaction                          
--- PASS: TestTransaction (0.00s)      
=== RUN   TestErrors                             
--- PASS: TestErrors (0.00s)
=== RUN   TestGetVersion              
--- PASS: TestGetVersion (0.02s)                                                                      
=== RUN   TestCards                   
--- PASS: TestCards (0.00s)                                                                           
=== RUN   TestNewYubiKey                                                                              
--- PASS: TestNewYubiKey (0.02s)                                                                      
=== RUN   TestMultipleConnections     
--- PASS: TestMultipleConnections (0.02s)
=== RUN   TestYubiKeySerial                                                                           
--- PASS: TestYubiKeySerial (0.05s)   
=== RUN   TestYubiKeyLoginNeeded      
    TestYubiKeyLoginNeeded: piv_test.go:140: expected no login needed
--- FAIL: TestYubiKeyLoginNeeded (0.07s)
=== RUN   TestYubiKeyPINRetries                                                                       
--- PASS: TestYubiKeyPINRetries (0.03s)
=== RUN   TestYubiKeyReset            
--- PASS: TestYubiKeyReset (3.26s)    
=== RUN   TestYubiKeyLogin            
--- PASS: TestYubiKeyLogin (0.05s)    
=== RUN   TestYubiKeyAuthenticate     
--- PASS: TestYubiKeyAuthenticate (0.07s)
=== RUN   TestYubiKeySetManagementKey 
--- PASS: TestYubiKeySetManagementKey (0.19s)
=== RUN   TestYubiKeyUnblockPIN       
--- PASS: TestYubiKeyUnblockPIN (0.20s)
=== RUN   TestYubiKeyChangePIN        
--- PASS: TestYubiKeyChangePIN (0.15s)        
=== RUN   TestYubiKeyChangePUK        
--- PASS: TestYubiKeyChangePUK (0.14s)             
=== RUN   TestChangeManagementKey                                                                     
--- PASS: TestChangeManagementKey (0.18s)                                                             
=== RUN   TestMetadata     
--- PASS: TestMetadata (3.43s)                                                                                                                                                                              
=== RUN   TestMetadataUnmarshal    
--- PASS: TestMetadataUnmarshal (0.00s)
=== RUN   TestMetadataMarshal                 
--- PASS: TestMetadataMarshal (0.00s)                                                                 
=== RUN   TestMetadataUpdate
--- PASS: TestMetadataUpdate (0.00s)                                                                  
=== RUN   TestMetadataAdditoinalFields
--- PASS: TestMetadataAdditoinalFields (0.00s)
FAIL                                          
FAIL    github.com/go-piv/piv-go/piv    102.041s   
FAIL          

Build failure on arm FreeBSD

The build fails as follows on arm FreeBSD:

# github.com/go-piv/piv-go/piv
vendor/github.com/go-piv/piv-go/piv/pcsc_freebsd.go:29:15: 0x8010002E (untyped int constant 2148532270) overflows int32
golang.org/x/crypto/ssh/agent
*** Error code 2

Please check and possible add a cast to make the number negative.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.