Remove the direct dependency on libpcsclite
Instead, use a go library that communicates with pcscd over a socket. Also update the changes introduced by @gravityblast since this PR's inception
This commit is contained in:
		
							parent
							
								
									ae82c58631
								
							
						
					
					
						commit
						5617dca1c9
					
				| @ -40,11 +40,11 @@ import ( | ||||
| 	"sync" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/ebfe/scard" | ||||
| 	"github.com/ethereum/go-ethereum/accounts" | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| 	"github.com/ethereum/go-ethereum/event" | ||||
| 	"github.com/ethereum/go-ethereum/log" | ||||
| 	pcsc "github.com/gballet/go-libpcsclite" | ||||
| ) | ||||
| 
 | ||||
| // Scheme is the URI prefix for smartcard wallets.
 | ||||
| @ -70,7 +70,7 @@ type smartcardPairing struct { | ||||
| type Hub struct { | ||||
| 	scheme string // Protocol scheme prefixing account and wallet URLs.
 | ||||
| 
 | ||||
| 	context  *scard.Context | ||||
| 	context  *pcsc.Client | ||||
| 	datadir  string | ||||
| 	pairings map[string]smartcardPairing | ||||
| 
 | ||||
| @ -152,7 +152,7 @@ func (hub *Hub) setPairing(wallet *Wallet, pairing *smartcardPairing) error { | ||||
| 
 | ||||
| // NewHub creates a new hardware wallet manager for smartcards.
 | ||||
| func NewHub(scheme string, datadir string) (*Hub, error) { | ||||
| 	context, err := scard.EstablishContext() | ||||
| 	context, err := pcsc.EstablishContext(pcsc.ScopeSystem) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -228,7 +228,7 @@ func (hub *Hub) refreshWallets() { | ||||
| 			delete(hub.wallets, reader) | ||||
| 		} | ||||
| 		// New card detected, try to connect to it
 | ||||
| 		card, err := hub.context.Connect(reader, scard.ShareShared, scard.ProtocolAny) | ||||
| 		card, err := hub.context.Connect(reader, pcsc.ShareShared, pcsc.ProtocolAny) | ||||
| 		if err != nil { | ||||
| 			log.Debug("Failed to open smart card", "reader", reader, "err", err) | ||||
| 			continue | ||||
| @ -236,7 +236,7 @@ func (hub *Hub) refreshWallets() { | ||||
| 		wallet := NewWallet(hub, card) | ||||
| 		if err = wallet.connect(); err != nil { | ||||
| 			log.Debug("Failed to connect to smart card", "reader", reader, "err", err) | ||||
| 			card.Disconnect(scard.LeaveCard) | ||||
| 			card.Disconnect(pcsc.LeaveCard) | ||||
| 			continue | ||||
| 		} | ||||
| 		// Card connected, start tracking in amongs the wallets
 | ||||
|  | ||||
| @ -25,9 +25,11 @@ import ( | ||||
| 	"crypto/sha512" | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"github.com/ebfe/scard" | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| 	pcsc "github.com/gballet/go-libpcsclite" | ||||
| 	"github.com/wsddn/go-ecdh" | ||||
| 	"golang.org/x/crypto/pbkdf2" | ||||
| 	"golang.org/x/text/unicode/norm" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| @ -42,22 +44,24 @@ const ( | ||||
| 	insMutuallyAuthenticate = 0x11 | ||||
| 	insPair                 = 0x12 | ||||
| 	insUnpair               = 0x13 | ||||
| 
 | ||||
| 	pairingSalt = "Keycard Pairing Password Salt" | ||||
| ) | ||||
| 
 | ||||
| // SecureChannelSession enables secure communication with a hardware wallet.
 | ||||
| type SecureChannelSession struct { | ||||
| 	card          *scard.Card // A handle to the smartcard for communication
 | ||||
| 	secret        []byte      // A shared secret generated from our ECDSA keys
 | ||||
| 	publicKey     []byte      // Our own ephemeral public key
 | ||||
| 	PairingKey    []byte      // A permanent shared secret for a pairing, if present
 | ||||
| 	sessionEncKey []byte      // The current session encryption key
 | ||||
| 	sessionMacKey []byte      // The current session MAC key
 | ||||
| 	iv            []byte      // The current IV
 | ||||
| 	PairingIndex  uint8       // The pairing index
 | ||||
| 	card          *pcsc.Card // A handle to the smartcard for communication
 | ||||
| 	secret        []byte     // A shared secret generated from our ECDSA keys
 | ||||
| 	publicKey     []byte     // Our own ephemeral public key
 | ||||
| 	PairingKey    []byte     // A permanent shared secret for a pairing, if present
 | ||||
| 	sessionEncKey []byte     // The current session encryption key
 | ||||
| 	sessionMacKey []byte     // The current session MAC key
 | ||||
| 	iv            []byte     // The current IV
 | ||||
| 	PairingIndex  uint8      // The pairing index
 | ||||
| } | ||||
| 
 | ||||
| // NewSecureChannelSession creates a new secure channel for the given card and public key.
 | ||||
| func NewSecureChannelSession(card *scard.Card, keyData []byte) (*SecureChannelSession, error) { | ||||
| func NewSecureChannelSession(card *pcsc.Card, keyData []byte) (*SecureChannelSession, error) { | ||||
| 	// Generate an ECDSA keypair for ourselves
 | ||||
| 	gen := ecdh.NewEllipticECDH(crypto.S256()) | ||||
| 	private, public, err := gen.GenerateKey(rand.Reader) | ||||
| @ -83,8 +87,8 @@ func NewSecureChannelSession(card *scard.Card, keyData []byte) (*SecureChannelSe | ||||
| } | ||||
| 
 | ||||
| // Pair establishes a new pairing with the smartcard.
 | ||||
| func (s *SecureChannelSession) Pair(sharedSecret []byte) error { | ||||
| 	secretHash := sha256.Sum256(sharedSecret) | ||||
| func (s *SecureChannelSession) Pair(pairingPassword []byte) error { | ||||
| 	secretHash := pbkdf2.Key(norm.NFKD.Bytes([]byte(pairingPassword)), norm.NFKD.Bytes([]byte(pairingSalt)), 50000, 32, sha256.New) | ||||
| 
 | ||||
| 	challenge := make([]byte, 32) | ||||
| 	if _, err := rand.Read(challenge); err != nil { | ||||
| @ -102,10 +106,10 @@ func (s *SecureChannelSession) Pair(sharedSecret []byte) error { | ||||
| 
 | ||||
| 	expectedCryptogram := md.Sum(nil) | ||||
| 	cardCryptogram := response.Data[:32] | ||||
| 	cardChallenge := response.Data[32:] | ||||
| 	cardChallenge := response.Data[32:64] | ||||
| 
 | ||||
| 	if !bytes.Equal(expectedCryptogram, cardCryptogram) { | ||||
| 		return fmt.Errorf("Invalid card cryptogram") | ||||
| 		return fmt.Errorf("Invalid card cryptogram %v != %v", expectedCryptogram, cardCryptogram) | ||||
| 	} | ||||
| 
 | ||||
| 	md.Reset() | ||||
|  | ||||
| @ -32,7 +32,6 @@ import ( | ||||
| 	"sync" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/ebfe/scard" | ||||
| 	ethereum "github.com/ethereum/go-ethereum" | ||||
| 	"github.com/ethereum/go-ethereum/accounts" | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| @ -40,12 +39,13 @@ import ( | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| 	"github.com/ethereum/go-ethereum/crypto/secp256k1" | ||||
| 	"github.com/ethereum/go-ethereum/log" | ||||
| 	pcsc "github.com/gballet/go-libpcsclite" | ||||
| ) | ||||
| 
 | ||||
| // ErrPUKNeeded is returned if opening the smart card requires pairing with a PUK
 | ||||
| // code. In this case, the calling application should request user input to enter
 | ||||
| // the PUK and send it back.
 | ||||
| var ErrPUKNeeded = errors.New("smartcard: puk needed") | ||||
| // ErrPairingPasswordNeeded is returned if opening the smart card requires pairing with a pairing
 | ||||
| // password. In this case, the calling application should request user input to enter
 | ||||
| // the pairing password and send it back.
 | ||||
| var ErrPairingPasswordNeeded = errors.New("smartcard: pairing password needed") | ||||
| 
 | ||||
| // ErrPINNeeded is returned if opening the smart card requires a PIN code. In
 | ||||
| // this case, the calling application should request user input to enter the PIN
 | ||||
| @ -67,7 +67,8 @@ var ErrAlreadyOpen = errors.New("smartcard: already open") | ||||
| var ErrPubkeyMismatch = errors.New("smartcard: recovered public key mismatch") | ||||
| 
 | ||||
| var ( | ||||
| 	appletAID               = []byte{0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x41, 0x70, 0x70} | ||||
| 	// appletAID               = []byte{0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x41, 0x70, 0x70}
 | ||||
| 	appletAID               = []byte{0xA0, 0x00, 0x00, 0x08, 0x04, 0x00, 0x01, 0x01, 0x01} | ||||
| 	DerivationSignatureHash = sha256.Sum256([]byte("STATUS KEY DERIVATION")) | ||||
| ) | ||||
| 
 | ||||
| @ -108,10 +109,10 @@ type Wallet struct { | ||||
| 	Hub       *Hub   // A handle to the Hub that instantiated this wallet.
 | ||||
| 	PublicKey []byte // The wallet's public key (used for communication and identification, not signing!)
 | ||||
| 
 | ||||
| 	lock    sync.Mutex  // Lock that gates access to struct fields and communication with the card
 | ||||
| 	card    *scard.Card // A handle to the smartcard interface for the wallet.
 | ||||
| 	session *Session    // The secure communication session with the card
 | ||||
| 	log     log.Logger  // Contextual logger to tag the base with its id
 | ||||
| 	lock    sync.Mutex // Lock that gates access to struct fields and communication with the card
 | ||||
| 	card    *pcsc.Card // A handle to the smartcard interface for the wallet.
 | ||||
| 	session *Session   // The secure communication session with the card
 | ||||
| 	log     log.Logger // Contextual logger to tag the base with its id
 | ||||
| 
 | ||||
| 	deriveNextPath accounts.DerivationPath   // Next derivation path for account auto-discovery
 | ||||
| 	deriveNextAddr common.Address            // Next derived account address for auto-discovery
 | ||||
| @ -121,7 +122,7 @@ type Wallet struct { | ||||
| } | ||||
| 
 | ||||
| // NewWallet constructs and returns a new Wallet instance.
 | ||||
| func NewWallet(hub *Hub, card *scard.Card) *Wallet { | ||||
| func NewWallet(hub *Hub, card *pcsc.Card) *Wallet { | ||||
| 	wallet := &Wallet{ | ||||
| 		Hub:  hub, | ||||
| 		card: card, | ||||
| @ -132,13 +133,13 @@ func NewWallet(hub *Hub, card *scard.Card) *Wallet { | ||||
| // transmit sends an APDU to the smartcard and receives and decodes the response.
 | ||||
| // It automatically handles requests by the card to fetch the return data separately,
 | ||||
| // and returns an error if the response status code is not success.
 | ||||
| func transmit(card *scard.Card, command *commandAPDU) (*responseAPDU, error) { | ||||
| func transmit(card *pcsc.Card, command *commandAPDU) (*responseAPDU, error) { | ||||
| 	data, err := command.serialize() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	responseData, err := card.Transmit(data) | ||||
| 	responseData, _, err := card.Transmit(data) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -349,7 +350,7 @@ func (w *Wallet) Open(passphrase string) error { | ||||
| 		} else { | ||||
| 			// If no passphrase was supplied, request the PUK from the user
 | ||||
| 			if passphrase == "" { | ||||
| 				return ErrPUKNeeded | ||||
| 				return ErrPairingPasswordNeeded | ||||
| 			} | ||||
| 			// Attempt to pair the smart card with the user supplied PUK
 | ||||
| 			if err := w.pair([]byte(passphrase)); err != nil { | ||||
| @ -814,7 +815,7 @@ func (s *Session) unblockPin(pukpin []byte) error { | ||||
| 
 | ||||
| // release releases resources associated with the channel.
 | ||||
| func (s *Session) release() error { | ||||
| 	return s.Wallet.card.Disconnect(scard.LeaveCard) | ||||
| 	return s.Wallet.card.Disconnect(pcsc.LeaveCard) | ||||
| } | ||||
| 
 | ||||
| // paired returns true if a valid pairing exists.
 | ||||
|  | ||||
| @ -118,9 +118,9 @@ func (b *bridge) OpenWallet(call otto.FunctionCall) (response otto.Value) { | ||||
| 			throwJSException(err.Error()) | ||||
| 		} | ||||
| 
 | ||||
| 	case strings.HasSuffix(err.Error(), scwallet.ErrPUKNeeded.Error()): | ||||
| 	case strings.HasSuffix(err.Error(), scwallet.ErrPairingPasswordNeeded.Error()): | ||||
| 		// PUK input requested, fetch from the user and call open again
 | ||||
| 		if input, err := b.prompter.PromptPassword("Please enter current PUK: "); err != nil { | ||||
| 		if input, err := b.prompter.PromptPassword("Please enter the pairing password: "); err != nil { | ||||
| 			throwJSException(err.Error()) | ||||
| 		} else { | ||||
| 			passwd, _ = otto.ToValue(input) | ||||
|  | ||||
							
								
								
									
										23
									
								
								vendor/github.com/ebfe/scard/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/ebfe/scard/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,23 +0,0 @@ | ||||
| Copyright (c) 2016, Michael Gehring <mg@ebfe.org> | ||||
| All rights reserved. | ||||
| 
 | ||||
| Redistribution and use in source and binary forms, with or without modification, | ||||
| are permitted provided that the following conditions are met: | ||||
| 
 | ||||
| * Redistributions of source code must retain the above copyright notice, this | ||||
|   list of conditions and the following disclaimer. | ||||
| 
 | ||||
| * Redistributions in binary form must reproduce the above copyright notice, this | ||||
|   list of conditions and the following disclaimer in the documentation and/or | ||||
|   other materials provided with the distribution. | ||||
| 
 | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||||
| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | ||||
| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||||
| ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
							
								
								
									
										14
									
								
								vendor/github.com/ebfe/scard/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/ebfe/scard/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,14 +0,0 @@ | ||||
| scard | ||||
| ===== | ||||
| 
 | ||||
| [](https://godoc.org/github.com/ebfe/scard) | ||||
| 
 | ||||
| Go bindings to the PC/SC API. | ||||
| 
 | ||||
| ## Installation | ||||
| 
 | ||||
| 	go get github.com/ebfe/scard | ||||
| 
 | ||||
| ## Bugs | ||||
| 
 | ||||
| 	- Memory layouts/GC needs a thorough review. | ||||
							
								
								
									
										283
									
								
								vendor/github.com/ebfe/scard/scard.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										283
									
								
								vendor/github.com/ebfe/scard/scard.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,283 +0,0 @@ | ||||
| // Package scard provides bindings to the PC/SC API.
 | ||||
| package scard | ||||
| 
 | ||||
| import ( | ||||
| 	"time" | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| type CardStatus struct { | ||||
| 	Reader         string | ||||
| 	State          State | ||||
| 	ActiveProtocol Protocol | ||||
| 	Atr            []byte | ||||
| } | ||||
| 
 | ||||
| type ReaderState struct { | ||||
| 	Reader       string | ||||
| 	UserData     interface{} | ||||
| 	CurrentState StateFlag | ||||
| 	EventState   StateFlag | ||||
| 	Atr          []byte | ||||
| } | ||||
| 
 | ||||
| type Context struct { | ||||
| 	ctx uintptr | ||||
| } | ||||
| 
 | ||||
| type Card struct { | ||||
| 	handle         uintptr | ||||
| 	activeProtocol Protocol | ||||
| } | ||||
| 
 | ||||
| // wraps SCardEstablishContext
 | ||||
| func EstablishContext() (*Context, error) { | ||||
| 	ctx, r := scardEstablishContext(ScopeSystem, 0, 0) | ||||
| 	if r != ErrSuccess { | ||||
| 		return nil, r | ||||
| 	} | ||||
| 
 | ||||
| 	return &Context{ctx: ctx}, nil | ||||
| } | ||||
| 
 | ||||
| // wraps SCardIsValidContext
 | ||||
| func (ctx *Context) IsValid() (bool, error) { | ||||
| 	r := scardIsValidContext(ctx.ctx) | ||||
| 	switch r { | ||||
| 	case ErrSuccess: | ||||
| 		return true, nil | ||||
| 	case ErrInvalidHandle: | ||||
| 		return false, nil | ||||
| 	default: | ||||
| 		return false, r | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // wraps SCardCancel
 | ||||
| func (ctx *Context) Cancel() error { | ||||
| 	r := scardCancel(ctx.ctx) | ||||
| 	if r != ErrSuccess { | ||||
| 		return r | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // wraps SCardReleaseContext
 | ||||
| func (ctx *Context) Release() error { | ||||
| 	r := scardReleaseContext(ctx.ctx) | ||||
| 	if r != ErrSuccess { | ||||
| 		return r | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // wraps SCardListReaders
 | ||||
| func (ctx *Context) ListReaders() ([]string, error) { | ||||
| 	needed, r := scardListReaders(ctx.ctx, nil, nil, 0) | ||||
| 	if r != ErrSuccess { | ||||
| 		return nil, r | ||||
| 	} | ||||
| 
 | ||||
| 	buf := make(strbuf, needed) | ||||
| 	n, r := scardListReaders(ctx.ctx, nil, buf.ptr(), uint32(len(buf))) | ||||
| 	if r != ErrSuccess { | ||||
| 		return nil, r | ||||
| 	} | ||||
| 	return decodemstr(buf[:n]), nil | ||||
| } | ||||
| 
 | ||||
| // wraps SCardListReaderGroups
 | ||||
| func (ctx *Context) ListReaderGroups() ([]string, error) { | ||||
| 	needed, r := scardListReaderGroups(ctx.ctx, nil, 0) | ||||
| 	if r != ErrSuccess { | ||||
| 		return nil, r | ||||
| 	} | ||||
| 
 | ||||
| 	buf := make(strbuf, needed) | ||||
| 	n, r := scardListReaderGroups(ctx.ctx, buf.ptr(), uint32(len(buf))) | ||||
| 	if r != ErrSuccess { | ||||
| 		return nil, r | ||||
| 	} | ||||
| 	return decodemstr(buf[:n]), nil | ||||
| } | ||||
| 
 | ||||
| // wraps SCardGetStatusChange
 | ||||
| func (ctx *Context) GetStatusChange(readerStates []ReaderState, timeout time.Duration) error { | ||||
| 
 | ||||
| 	dwTimeout := durationToTimeout(timeout) | ||||
| 	states := make([]scardReaderState, len(readerStates)) | ||||
| 
 | ||||
| 	for i := range readerStates { | ||||
| 		var err error | ||||
| 		states[i], err = readerStates[i].toSys() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	r := scardGetStatusChange(ctx.ctx, dwTimeout, states) | ||||
| 	if r != ErrSuccess { | ||||
| 		return r | ||||
| 	} | ||||
| 
 | ||||
| 	for i := range readerStates { | ||||
| 		(&readerStates[i]).update(&states[i]) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // wraps SCardConnect
 | ||||
| func (ctx *Context) Connect(reader string, mode ShareMode, proto Protocol) (*Card, error) { | ||||
| 	creader, err := encodestr(reader) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	handle, activeProtocol, r := scardConnect(ctx.ctx, creader.ptr(), mode, proto) | ||||
| 	if r != ErrSuccess { | ||||
| 		return nil, r | ||||
| 	} | ||||
| 	return &Card{handle: handle, activeProtocol: activeProtocol}, nil | ||||
| } | ||||
| 
 | ||||
| // wraps SCardDisconnect
 | ||||
| func (card *Card) Disconnect(d Disposition) error { | ||||
| 	r := scardDisconnect(card.handle, d) | ||||
| 	if r != ErrSuccess { | ||||
| 		return r | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // wraps SCardReconnect
 | ||||
| func (card *Card) Reconnect(mode ShareMode, proto Protocol, disp Disposition) error { | ||||
| 	activeProtocol, r := scardReconnect(card.handle, mode, proto, disp) | ||||
| 	if r != ErrSuccess { | ||||
| 		return r | ||||
| 	} | ||||
| 	card.activeProtocol = activeProtocol | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // wraps SCardBeginTransaction
 | ||||
| func (card *Card) BeginTransaction() error { | ||||
| 	r := scardBeginTransaction(card.handle) | ||||
| 	if r != ErrSuccess { | ||||
| 		return r | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // wraps SCardEndTransaction
 | ||||
| func (card *Card) EndTransaction(disp Disposition) error { | ||||
| 	r := scardEndTransaction(card.handle, disp) | ||||
| 	if r != ErrSuccess { | ||||
| 		return r | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // wraps SCardStatus
 | ||||
| func (card *Card) Status() (*CardStatus, error) { | ||||
| 	reader, state, proto, atr, err := scardCardStatus(card.handle) | ||||
| 	if err != ErrSuccess { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &CardStatus{Reader: reader, State: state, ActiveProtocol: proto, Atr: atr}, nil | ||||
| } | ||||
| 
 | ||||
| // wraps SCardTransmit
 | ||||
| func (card *Card) Transmit(cmd []byte) ([]byte, error) { | ||||
| 	rsp := make([]byte, maxBufferSizeExtended) | ||||
| 	rspLen, err := scardTransmit(card.handle, card.activeProtocol, cmd, rsp) | ||||
| 	if err != ErrSuccess { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return rsp[:rspLen], nil | ||||
| } | ||||
| 
 | ||||
| // wraps SCardControl
 | ||||
| func (card *Card) Control(ioctl uint32, in []byte) ([]byte, error) { | ||||
| 	var out [0xffff]byte | ||||
| 	outLen, err := scardControl(card.handle, ioctl, in, out[:]) | ||||
| 	if err != ErrSuccess { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return out[:outLen], nil | ||||
| } | ||||
| 
 | ||||
| // wraps SCardGetAttrib
 | ||||
| func (card *Card) GetAttrib(id Attrib) ([]byte, error) { | ||||
| 	needed, err := scardGetAttrib(card.handle, id, nil) | ||||
| 	if err != ErrSuccess { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	var attrib = make([]byte, needed) | ||||
| 	n, err := scardGetAttrib(card.handle, id, attrib) | ||||
| 	if err != ErrSuccess { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return attrib[:n], nil | ||||
| } | ||||
| 
 | ||||
| // wraps SCardSetAttrib
 | ||||
| func (card *Card) SetAttrib(id Attrib, data []byte) error { | ||||
| 	err := scardSetAttrib(card.handle, id, data) | ||||
| 	if err != ErrSuccess { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func durationToTimeout(timeout time.Duration) uint32 { | ||||
| 	switch { | ||||
| 	case timeout < 0: | ||||
| 		return infiniteTimeout | ||||
| 	case timeout > time.Duration(infiniteTimeout)*time.Millisecond: | ||||
| 		return infiniteTimeout - 1 | ||||
| 	default: | ||||
| 		return uint32(timeout / time.Millisecond) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (buf strbuf) ptr() unsafe.Pointer { | ||||
| 	return unsafe.Pointer(&buf[0]) | ||||
| } | ||||
| 
 | ||||
| func (buf strbuf) split() []strbuf { | ||||
| 	var chunks []strbuf | ||||
| 	for len(buf) > 0 && buf[0] != 0 { | ||||
| 		i := 0 | ||||
| 		for i = range buf { | ||||
| 			if buf[i] == 0 { | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 		chunks = append(chunks, buf[:i+1]) | ||||
| 		buf = buf[i+1:] | ||||
| 	} | ||||
| 
 | ||||
| 	return chunks | ||||
| } | ||||
| 
 | ||||
| func encodemstr(strings ...string) (strbuf, error) { | ||||
| 	var buf strbuf | ||||
| 	for _, s := range strings { | ||||
| 		utf16, err := encodestr(s) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		buf = append(buf, utf16...) | ||||
| 	} | ||||
| 	buf = append(buf, 0) | ||||
| 	return buf, nil | ||||
| } | ||||
| 
 | ||||
| func decodemstr(buf strbuf) []string { | ||||
| 	var strings []string | ||||
| 	for _, chunk := range buf.split() { | ||||
| 		strings = append(strings, decodestr(chunk)) | ||||
| 	} | ||||
| 	return strings | ||||
| } | ||||
							
								
								
									
										219
									
								
								vendor/github.com/ebfe/scard/scard_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										219
									
								
								vendor/github.com/ebfe/scard/scard_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,219 +0,0 @@ | ||||
| // +build darwin
 | ||||
| 
 | ||||
| package scard | ||||
| 
 | ||||
| // #cgo LDFLAGS: -framework PCSC
 | ||||
| // #cgo CFLAGS: -I /usr/include
 | ||||
| // #include <stdlib.h>
 | ||||
| // #include <PCSC/winscard.h>
 | ||||
| // #include <PCSC/wintypes.h>
 | ||||
| import "C" | ||||
| 
 | ||||
| import ( | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| func (e Error) Error() string { | ||||
| 	return "scard: " + C.GoString(C.pcsc_stringify_error(C.int32_t(e))) | ||||
| } | ||||
| 
 | ||||
| // Version returns the libpcsclite version string
 | ||||
| func Version() string { | ||||
| 	return C.PCSCLITE_VERSION_NUMBER | ||||
| } | ||||
| 
 | ||||
| func scardEstablishContext(scope Scope, reserved1, reserved2 uintptr) (uintptr, Error) { | ||||
| 	var ctx C.SCARDCONTEXT | ||||
| 	r := C.SCardEstablishContext(C.uint32_t(scope), unsafe.Pointer(reserved1), unsafe.Pointer(reserved2), &ctx) | ||||
| 	return uintptr(ctx), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardIsValidContext(ctx uintptr) Error { | ||||
| 	r := C.SCardIsValidContext(C.SCARDCONTEXT(ctx)) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardCancel(ctx uintptr) Error { | ||||
| 	r := C.SCardCancel(C.SCARDCONTEXT(ctx)) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardReleaseContext(ctx uintptr) Error { | ||||
| 	r := C.SCardReleaseContext(C.SCARDCONTEXT(ctx)) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardListReaders(ctx uintptr, groups, buf unsafe.Pointer, bufLen uint32) (uint32, Error) { | ||||
| 	dwBufLen := C.uint32_t(bufLen) | ||||
| 	r := C.SCardListReaders(C.SCARDCONTEXT(ctx), (C.LPCSTR)(groups), (C.LPSTR)(buf), &dwBufLen) | ||||
| 	return uint32(dwBufLen), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardListReaderGroups(ctx uintptr, buf unsafe.Pointer, bufLen uint32) (uint32, Error) { | ||||
| 	dwBufLen := C.uint32_t(bufLen) | ||||
| 	r := C.SCardListReaderGroups(C.SCARDCONTEXT(ctx), (C.LPSTR)(buf), &dwBufLen) | ||||
| 	return uint32(dwBufLen), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardGetStatusChange(ctx uintptr, timeout uint32, states []scardReaderState) Error { | ||||
| 	// In darwin, the LPSCARD_READERSTATE_A has 1 byte alignment and hence
 | ||||
| 	// has no trailing padding. Go does add 3 bytes of padding (on both 32
 | ||||
| 	// and 64 bits), so we pack an array manually instead.
 | ||||
| 	const size = int(unsafe.Sizeof(states[0])) - 3 | ||||
| 	buf := make([]byte, size*len(states)) | ||||
| 	for i, _ := range states { | ||||
| 		copy(buf[i*size:(i+1)*size], (*(*[size]byte)(unsafe.Pointer(&states[i])))[:]) | ||||
| 	} | ||||
| 	r := C.SCardGetStatusChange(C.SCARDCONTEXT(ctx), C.uint32_t(timeout), (C.LPSCARD_READERSTATE_A)(unsafe.Pointer(&buf[0])), C.uint32_t(len(states))) | ||||
| 	for i, _ := range states { | ||||
| 		copy((*(*[size]byte)(unsafe.Pointer(&states[i])))[:], buf[i*size:(i+1)*size]) | ||||
| 	} | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardConnect(ctx uintptr, reader unsafe.Pointer, shareMode ShareMode, proto Protocol) (uintptr, Protocol, Error) { | ||||
| 	var handle C.SCARDHANDLE | ||||
| 	var activeProto C.uint32_t | ||||
| 
 | ||||
| 	r := C.SCardConnect(C.SCARDCONTEXT(ctx), C.LPCSTR(reader), C.uint32_t(shareMode), C.uint32_t(proto), &handle, &activeProto) | ||||
| 
 | ||||
| 	return uintptr(handle), Protocol(activeProto), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardDisconnect(card uintptr, d Disposition) Error { | ||||
| 	r := C.SCardDisconnect(C.SCARDHANDLE(card), C.uint32_t(d)) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardReconnect(card uintptr, mode ShareMode, proto Protocol, disp Disposition) (Protocol, Error) { | ||||
| 	var activeProtocol C.uint32_t | ||||
| 	r := C.SCardReconnect(C.SCARDHANDLE(card), C.uint32_t(mode), C.uint32_t(proto), C.uint32_t(disp), &activeProtocol) | ||||
| 	return Protocol(activeProtocol), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardBeginTransaction(card uintptr) Error { | ||||
| 	r := C.SCardBeginTransaction(C.SCARDHANDLE(card)) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardEndTransaction(card uintptr, disp Disposition) Error { | ||||
| 	r := C.SCardEndTransaction(C.SCARDHANDLE(card), C.uint32_t(disp)) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardCardStatus(card uintptr) (string, State, Protocol, []byte, Error) { | ||||
| 	var readerBuf [C.MAX_READERNAME + 1]byte | ||||
| 	var readerLen = C.uint32_t(len(readerBuf)) | ||||
| 	var state, proto C.uint32_t | ||||
| 	var atr [maxAtrSize]byte | ||||
| 	var atrLen = C.uint32_t(len(atr)) | ||||
| 
 | ||||
| 	r := C.SCardStatus(C.SCARDHANDLE(card), (C.LPSTR)(unsafe.Pointer(&readerBuf[0])), &readerLen, &state, &proto, (*C.uchar)(&atr[0]), &atrLen) | ||||
| 
 | ||||
| 	return decodestr(readerBuf[:readerLen]), State(state), Protocol(proto), atr[:atrLen], Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardTransmit(card uintptr, proto Protocol, cmd []byte, rsp []byte) (uint32, Error) { | ||||
| 	var sendpci C.SCARD_IO_REQUEST | ||||
| 	var recvpci C.SCARD_IO_REQUEST | ||||
| 	var rspLen = C.uint32_t(len(rsp)) | ||||
| 
 | ||||
| 	switch proto { | ||||
| 	case ProtocolT0, ProtocolT1: | ||||
| 		sendpci.dwProtocol = C.uint32_t(proto) | ||||
| 	default: | ||||
| 		panic("unknown protocol") | ||||
| 	} | ||||
| 	sendpci.cbPciLength = C.sizeof_SCARD_IO_REQUEST | ||||
| 
 | ||||
| 	r := C.SCardTransmit(C.SCARDHANDLE(card), &sendpci, (*C.uchar)(&cmd[0]), C.uint32_t(len(cmd)), &recvpci, (*C.uchar)(&rsp[0]), &rspLen) | ||||
| 
 | ||||
| 	return uint32(rspLen), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardControl(card uintptr, ioctl uint32, in, out []byte) (uint32, Error) { | ||||
| 	var ptrIn unsafe.Pointer | ||||
| 	var outLen = C.uint32_t(len(out)) | ||||
| 
 | ||||
| 	if len(in) != 0 { | ||||
| 		ptrIn = unsafe.Pointer(&in[0]) | ||||
| 	} | ||||
| 
 | ||||
| 	r := C.SCardControl(C.SCARDHANDLE(card), C.uint32_t(ioctl), ptrIn, C.uint32_t(len(in)), unsafe.Pointer(&out[0]), C.uint32_t(len(out)), &outLen) | ||||
| 	return uint32(outLen), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardGetAttrib(card uintptr, id Attrib, buf []byte) (uint32, Error) { | ||||
| 	var ptr *C.uint8_t | ||||
| 
 | ||||
| 	if len(buf) != 0 { | ||||
| 		ptr = (*C.uint8_t)(&buf[0]) | ||||
| 	} | ||||
| 
 | ||||
| 	bufLen := C.uint32_t(len(buf)) | ||||
| 	r := C.SCardGetAttrib(C.SCARDHANDLE(card), C.uint32_t(id), ptr, &bufLen) | ||||
| 
 | ||||
| 	return uint32(bufLen), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardSetAttrib(card uintptr, id Attrib, buf []byte) Error { | ||||
| 	r := C.SCardSetAttrib(C.SCARDHANDLE(card), C.uint32_t(id), ((*C.uint8_t)(&buf[0])), C.uint32_t(len(buf))) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| type strbuf []byte | ||||
| 
 | ||||
| func encodestr(s string) (strbuf, error) { | ||||
| 	buf := strbuf(s + "\x00") | ||||
| 	return buf, nil | ||||
| } | ||||
| 
 | ||||
| func decodestr(buf strbuf) string { | ||||
| 	if len(buf) == 0 { | ||||
| 		return "" | ||||
| 	} | ||||
| 
 | ||||
| 	if buf[len(buf)-1] == 0 { | ||||
| 		buf = buf[:len(buf)-1] | ||||
| 	} | ||||
| 
 | ||||
| 	return string(buf) | ||||
| } | ||||
| 
 | ||||
| type scardReaderState struct { | ||||
| 	szReader       uintptr | ||||
| 	pvUserData     uintptr | ||||
| 	dwCurrentState uint32 | ||||
| 	dwEventState   uint32 | ||||
| 	cbAtr          uint32 | ||||
| 	rgbAtr         [33]byte | ||||
| } | ||||
| 
 | ||||
| var pinned = map[string]*strbuf{} | ||||
| 
 | ||||
| func (rs *ReaderState) toSys() (scardReaderState, error) { | ||||
| 	var sys scardReaderState | ||||
| 
 | ||||
| 	creader, err := encodestr(rs.Reader) | ||||
| 	if err != nil { | ||||
| 		return scardReaderState{}, err | ||||
| 	} | ||||
| 	pinned[rs.Reader] = &creader | ||||
| 	sys.szReader = uintptr(creader.ptr()) | ||||
| 	sys.dwCurrentState = uint32(rs.CurrentState) | ||||
| 	sys.cbAtr = uint32(len(rs.Atr)) | ||||
| 	for i, v := range rs.Atr { | ||||
| 		sys.rgbAtr[i] = byte(v) | ||||
| 	} | ||||
| 	return sys, nil | ||||
| } | ||||
| 
 | ||||
| func (rs *ReaderState) update(sys *scardReaderState) { | ||||
| 	rs.EventState = StateFlag(sys.dwEventState) | ||||
| 	if sys.cbAtr > 0 { | ||||
| 		rs.Atr = make([]byte, int(sys.cbAtr)) | ||||
| 		for i := 0; i < int(sys.cbAtr); i++ { | ||||
| 			rs.Atr[i] = byte(sys.rgbAtr[i]) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										206
									
								
								vendor/github.com/ebfe/scard/scard_unix.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										206
									
								
								vendor/github.com/ebfe/scard/scard_unix.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,206 +0,0 @@ | ||||
| // +build !windows,!darwin
 | ||||
| 
 | ||||
| package scard | ||||
| 
 | ||||
| // #cgo pkg-config: libpcsclite
 | ||||
| // #include <stdlib.h>
 | ||||
| // #include <winscard.h>
 | ||||
| import "C" | ||||
| 
 | ||||
| import ( | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| func (e Error) Error() string { | ||||
| 	return "scard: " + C.GoString(C.pcsc_stringify_error(C.LONG(e))) | ||||
| } | ||||
| 
 | ||||
| // Version returns the libpcsclite version string
 | ||||
| func Version() string { | ||||
| 	return C.PCSCLITE_VERSION_NUMBER | ||||
| } | ||||
| 
 | ||||
| func scardEstablishContext(scope Scope, reserved1, reserved2 uintptr) (uintptr, Error) { | ||||
| 	var ctx C.SCARDCONTEXT | ||||
| 	r := C.SCardEstablishContext(C.DWORD(scope), C.LPCVOID(reserved1), C.LPCVOID(reserved2), &ctx) | ||||
| 	return uintptr(ctx), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardIsValidContext(ctx uintptr) Error { | ||||
| 	r := C.SCardIsValidContext(C.SCARDCONTEXT(ctx)) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardCancel(ctx uintptr) Error { | ||||
| 	r := C.SCardCancel(C.SCARDCONTEXT(ctx)) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardReleaseContext(ctx uintptr) Error { | ||||
| 	r := C.SCardReleaseContext(C.SCARDCONTEXT(ctx)) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardListReaders(ctx uintptr, groups, buf unsafe.Pointer, bufLen uint32) (uint32, Error) { | ||||
| 	dwBufLen := C.DWORD(bufLen) | ||||
| 	r := C.SCardListReaders(C.SCARDCONTEXT(ctx), (C.LPCSTR)(groups), (C.LPSTR)(buf), &dwBufLen) | ||||
| 	return uint32(dwBufLen), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardListReaderGroups(ctx uintptr, buf unsafe.Pointer, bufLen uint32) (uint32, Error) { | ||||
| 	dwBufLen := C.DWORD(bufLen) | ||||
| 	r := C.SCardListReaderGroups(C.SCARDCONTEXT(ctx), (C.LPSTR)(buf), &dwBufLen) | ||||
| 	return uint32(dwBufLen), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardGetStatusChange(ctx uintptr, timeout uint32, states []scardReaderState) Error { | ||||
| 	r := C.SCardGetStatusChange(C.SCARDCONTEXT(ctx), C.DWORD(timeout), (C.LPSCARD_READERSTATE)(unsafe.Pointer(&states[0])), C.DWORD(len(states))) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardConnect(ctx uintptr, reader unsafe.Pointer, shareMode ShareMode, proto Protocol) (uintptr, Protocol, Error) { | ||||
| 	var handle C.SCARDHANDLE | ||||
| 	var activeProto C.DWORD | ||||
| 
 | ||||
| 	r := C.SCardConnect(C.SCARDCONTEXT(ctx), C.LPCSTR(reader), C.DWORD(shareMode), C.DWORD(proto), &handle, &activeProto) | ||||
| 
 | ||||
| 	return uintptr(handle), Protocol(activeProto), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardDisconnect(card uintptr, d Disposition) Error { | ||||
| 	r := C.SCardDisconnect(C.SCARDHANDLE(card), C.DWORD(d)) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardReconnect(card uintptr, mode ShareMode, proto Protocol, disp Disposition) (Protocol, Error) { | ||||
| 	var activeProtocol C.DWORD | ||||
| 	r := C.SCardReconnect(C.SCARDHANDLE(card), C.DWORD(mode), C.DWORD(proto), C.DWORD(disp), &activeProtocol) | ||||
| 	return Protocol(activeProtocol), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardBeginTransaction(card uintptr) Error { | ||||
| 	r := C.SCardBeginTransaction(C.SCARDHANDLE(card)) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardEndTransaction(card uintptr, disp Disposition) Error { | ||||
| 	r := C.SCardEndTransaction(C.SCARDHANDLE(card), C.DWORD(disp)) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardCardStatus(card uintptr) (string, State, Protocol, []byte, Error) { | ||||
| 	var readerBuf [C.MAX_READERNAME + 1]byte | ||||
| 	var readerLen = C.DWORD(len(readerBuf)) | ||||
| 	var state, proto C.DWORD | ||||
| 	var atr [maxAtrSize]byte | ||||
| 	var atrLen = C.DWORD(len(atr)) | ||||
| 
 | ||||
| 	r := C.SCardStatus(C.SCARDHANDLE(card), (C.LPSTR)(unsafe.Pointer(&readerBuf[0])), &readerLen, &state, &proto, (*C.BYTE)(&atr[0]), &atrLen) | ||||
| 
 | ||||
| 	return decodestr(readerBuf[:readerLen]), State(state), Protocol(proto), atr[:atrLen], Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardTransmit(card uintptr, proto Protocol, cmd []byte, rsp []byte) (uint32, Error) { | ||||
| 	var sendpci C.SCARD_IO_REQUEST | ||||
| 	var recvpci C.SCARD_IO_REQUEST | ||||
| 	var rspLen = C.DWORD(len(rsp)) | ||||
| 
 | ||||
| 	switch proto { | ||||
| 	case ProtocolT0, ProtocolT1: | ||||
| 		sendpci.dwProtocol = C.ulong(proto) | ||||
| 	default: | ||||
| 		panic("unknown protocol") | ||||
| 	} | ||||
| 	sendpci.cbPciLength = C.sizeof_SCARD_IO_REQUEST | ||||
| 
 | ||||
| 	r := C.SCardTransmit(C.SCARDHANDLE(card), &sendpci, (*C.BYTE)(&cmd[0]), C.DWORD(len(cmd)), &recvpci, (*C.BYTE)(&rsp[0]), &rspLen) | ||||
| 
 | ||||
| 	return uint32(rspLen), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardControl(card uintptr, ioctl uint32, in, out []byte) (uint32, Error) { | ||||
| 	var ptrIn C.LPCVOID | ||||
| 	var outLen = C.DWORD(len(out)) | ||||
| 
 | ||||
| 	if len(in) != 0 { | ||||
| 		ptrIn = C.LPCVOID(unsafe.Pointer(&in[0])) | ||||
| 	} | ||||
| 
 | ||||
| 	r := C.SCardControl(C.SCARDHANDLE(card), C.DWORD(ioctl), ptrIn, C.DWORD(len(in)), (C.LPVOID)(unsafe.Pointer(&out[0])), C.DWORD(len(out)), &outLen) | ||||
| 	return uint32(outLen), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardGetAttrib(card uintptr, id Attrib, buf []byte) (uint32, Error) { | ||||
| 	var ptr C.LPBYTE | ||||
| 
 | ||||
| 	if len(buf) != 0 { | ||||
| 		ptr = C.LPBYTE(unsafe.Pointer(&buf[0])) | ||||
| 	} | ||||
| 
 | ||||
| 	bufLen := C.DWORD(len(buf)) | ||||
| 	r := C.SCardGetAttrib(C.SCARDHANDLE(card), C.DWORD(id), ptr, &bufLen) | ||||
| 
 | ||||
| 	return uint32(bufLen), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardSetAttrib(card uintptr, id Attrib, buf []byte) Error { | ||||
| 	r := C.SCardSetAttrib(C.SCARDHANDLE(card), C.DWORD(id), (*C.BYTE)(unsafe.Pointer(&buf[0])), C.DWORD(len(buf))) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| type strbuf []byte | ||||
| 
 | ||||
| func encodestr(s string) (strbuf, error) { | ||||
| 	buf := strbuf(s + "\x00") | ||||
| 	return buf, nil | ||||
| } | ||||
| 
 | ||||
| func decodestr(buf strbuf) string { | ||||
| 	if len(buf) == 0 { | ||||
| 		return "" | ||||
| 	} | ||||
| 
 | ||||
| 	if buf[len(buf)-1] == 0 { | ||||
| 		buf = buf[:len(buf)-1] | ||||
| 	} | ||||
| 
 | ||||
| 	return string(buf) | ||||
| } | ||||
| 
 | ||||
| type scardReaderState struct { | ||||
| 	szReader       uintptr | ||||
| 	pvUserData     uintptr | ||||
| 	dwCurrentState uintptr | ||||
| 	dwEventState   uintptr | ||||
| 	cbAtr          uintptr | ||||
| 	rgbAtr         [33]byte | ||||
| } | ||||
| 
 | ||||
| var pinned = map[string]*strbuf{} | ||||
| 
 | ||||
| func (rs *ReaderState) toSys() (scardReaderState, error) { | ||||
| 	var sys scardReaderState | ||||
| 
 | ||||
| 	creader, err := encodestr(rs.Reader) | ||||
| 	if err != nil { | ||||
| 		return scardReaderState{}, err | ||||
| 	} | ||||
| 	pinned[rs.Reader] = &creader | ||||
| 	sys.szReader = uintptr(creader.ptr()) | ||||
| 	sys.dwCurrentState = uintptr(rs.CurrentState) | ||||
| 	sys.cbAtr = uintptr(len(rs.Atr)) | ||||
| 	for i, v := range rs.Atr { | ||||
| 		sys.rgbAtr[i] = byte(v) | ||||
| 	} | ||||
| 	return sys, nil | ||||
| } | ||||
| 
 | ||||
| func (rs *ReaderState) update(sys *scardReaderState) { | ||||
| 	rs.EventState = StateFlag(sys.dwEventState) | ||||
| 	if sys.cbAtr > 0 { | ||||
| 		rs.Atr = make([]byte, int(sys.cbAtr)) | ||||
| 		for i := 0; i < int(sys.cbAtr); i++ { | ||||
| 			rs.Atr[i] = byte(sys.rgbAtr[i]) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										221
									
								
								vendor/github.com/ebfe/scard/scard_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										221
									
								
								vendor/github.com/ebfe/scard/scard_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,221 +0,0 @@ | ||||
| package scard | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	modwinscard = syscall.NewLazyDLL("winscard.dll") | ||||
| 
 | ||||
| 	procEstablishContext = modwinscard.NewProc("SCardEstablishContext") | ||||
| 	procReleaseContext   = modwinscard.NewProc("SCardReleaseContext") | ||||
| 	procIsValidContext   = modwinscard.NewProc("SCardIsValidContext") | ||||
| 	procCancel           = modwinscard.NewProc("SCardCancel") | ||||
| 	procListReaders      = modwinscard.NewProc("SCardListReadersW") | ||||
| 	procListReaderGroups = modwinscard.NewProc("SCardListReaderGroupsW") | ||||
| 	procGetStatusChange  = modwinscard.NewProc("SCardGetStatusChangeW") | ||||
| 	procConnect          = modwinscard.NewProc("SCardConnectW") | ||||
| 	procDisconnect       = modwinscard.NewProc("SCardDisconnect") | ||||
| 	procReconnect        = modwinscard.NewProc("SCardReconnect") | ||||
| 	procBeginTransaction = modwinscard.NewProc("SCardBeginTransaction") | ||||
| 	procEndTransaction   = modwinscard.NewProc("SCardEndTransaction") | ||||
| 	procStatus           = modwinscard.NewProc("SCardStatusW") | ||||
| 	procTransmit         = modwinscard.NewProc("SCardTransmit") | ||||
| 	procControl          = modwinscard.NewProc("SCardControl") | ||||
| 	procGetAttrib        = modwinscard.NewProc("SCardGetAttrib") | ||||
| 	procSetAttrib        = modwinscard.NewProc("SCardSetAttrib") | ||||
| 
 | ||||
| 	dataT0Pci = modwinscard.NewProc("g_rgSCardT0Pci") | ||||
| 	dataT1Pci = modwinscard.NewProc("g_rgSCardT1Pci") | ||||
| ) | ||||
| 
 | ||||
| var scardIoReqT0 uintptr | ||||
| var scardIoReqT1 uintptr | ||||
| 
 | ||||
| func init() { | ||||
| 	if err := dataT0Pci.Find(); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	scardIoReqT0 = dataT0Pci.Addr() | ||||
| 	if err := dataT1Pci.Find(); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	scardIoReqT1 = dataT1Pci.Addr() | ||||
| } | ||||
| 
 | ||||
| func (e Error) Error() string { | ||||
| 	err := syscall.Errno(e) | ||||
| 	return fmt.Sprintf("scard: error(%x): %s", uintptr(e), err.Error()) | ||||
| } | ||||
| 
 | ||||
| func scardEstablishContext(scope Scope, reserved1, reserved2 uintptr) (uintptr, Error) { | ||||
| 	var ctx uintptr | ||||
| 	r, _, _ := procEstablishContext.Call(uintptr(scope), reserved1, reserved2, uintptr(unsafe.Pointer(&ctx))) | ||||
| 	return ctx, Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardIsValidContext(ctx uintptr) Error { | ||||
| 	r, _, _ := procIsValidContext.Call(ctx) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardCancel(ctx uintptr) Error { | ||||
| 	r, _, _ := procCancel.Call(ctx) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardReleaseContext(ctx uintptr) Error { | ||||
| 	r, _, _ := procReleaseContext.Call(ctx) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardListReaders(ctx uintptr, groups, buf unsafe.Pointer, bufLen uint32) (uint32, Error) { | ||||
| 	dwBufLen := uint32(bufLen) | ||||
| 	r, _, _ := procListReaders.Call(ctx, uintptr(groups), uintptr(buf), uintptr(unsafe.Pointer(&dwBufLen))) | ||||
| 	return dwBufLen, Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardListReaderGroups(ctx uintptr, buf unsafe.Pointer, bufLen uint32) (uint32, Error) { | ||||
| 	dwBufLen := uint32(bufLen) | ||||
| 	r, _, _ := procListReaderGroups.Call(ctx, uintptr(buf), uintptr(unsafe.Pointer(&dwBufLen))) | ||||
| 	return dwBufLen, Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardGetStatusChange(ctx uintptr, timeout uint32, states []scardReaderState) Error { | ||||
| 	r, _, _ := procGetStatusChange.Call(ctx, uintptr(timeout), uintptr(unsafe.Pointer(&states[0])), uintptr(len(states))) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardConnect(ctx uintptr, reader unsafe.Pointer, shareMode ShareMode, proto Protocol) (uintptr, Protocol, Error) { | ||||
| 	var handle uintptr | ||||
| 	var activeProto uint32 | ||||
| 
 | ||||
| 	r, _, _ := procConnect.Call(ctx, uintptr(reader), uintptr(shareMode), uintptr(proto), uintptr(unsafe.Pointer(&handle)), uintptr(unsafe.Pointer(&activeProto))) | ||||
| 
 | ||||
| 	return handle, Protocol(activeProto), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardDisconnect(card uintptr, d Disposition) Error { | ||||
| 	r, _, _ := procDisconnect.Call(card, uintptr(d)) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardReconnect(card uintptr, mode ShareMode, proto Protocol, disp Disposition) (Protocol, Error) { | ||||
| 	var activeProtocol uint32 | ||||
| 	r, _, _ := procReconnect.Call(card, uintptr(mode), uintptr(proto), uintptr(disp), uintptr(unsafe.Pointer(&activeProtocol))) | ||||
| 	return Protocol(activeProtocol), Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardBeginTransaction(card uintptr) Error { | ||||
| 	r, _, _ := procBeginTransaction.Call(card) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardEndTransaction(card uintptr, disp Disposition) Error { | ||||
| 	r, _, _ := procEndTransaction.Call(card, uintptr(disp)) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardCardStatus(card uintptr) (string, State, Protocol, []byte, Error) { | ||||
| 	var state, proto uint32 | ||||
| 	var atr [maxAtrSize]byte | ||||
| 	var atrLen = uint32(len(atr)) | ||||
| 
 | ||||
| 	reader := make(strbuf, maxReadername+1) | ||||
| 	readerLen := uint32(len(reader)) | ||||
| 
 | ||||
| 	r, _, _ := procStatus.Call(card, uintptr(reader.ptr()), uintptr(unsafe.Pointer(&readerLen)), uintptr(unsafe.Pointer(&state)), uintptr(unsafe.Pointer(&proto)), uintptr(unsafe.Pointer(&atr[0])), uintptr(unsafe.Pointer(&atrLen))) | ||||
| 
 | ||||
| 	return decodestr(reader[:readerLen]), State(state), Protocol(proto), atr[:atrLen], Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardTransmit(card uintptr, proto Protocol, cmd []byte, rsp []byte) (uint32, Error) { | ||||
| 	var sendpci uintptr | ||||
| 	var rspLen = uint32(len(rsp)) | ||||
| 
 | ||||
| 	switch proto { | ||||
| 	case ProtocolT0: | ||||
| 		sendpci = scardIoReqT0 | ||||
| 	case ProtocolT1: | ||||
| 		sendpci = scardIoReqT1 | ||||
| 	default: | ||||
| 		panic("unknown protocol") | ||||
| 	} | ||||
| 
 | ||||
| 	r, _, _ := procTransmit.Call(card, sendpci, uintptr(unsafe.Pointer(&cmd[0])), uintptr(len(cmd)), uintptr(0), uintptr(unsafe.Pointer(&rsp[0])), uintptr(unsafe.Pointer(&rspLen))) | ||||
| 
 | ||||
| 	return rspLen, Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardControl(card uintptr, ioctl uint32, in, out []byte) (uint32, Error) { | ||||
| 	var ptrIn uintptr | ||||
| 	var outLen = uint32(len(out)) | ||||
| 
 | ||||
| 	if len(in) != 0 { | ||||
| 		ptrIn = uintptr(unsafe.Pointer(&in[0])) | ||||
| 	} | ||||
| 
 | ||||
| 	r, _, _ := procControl.Call(card, uintptr(ioctl), ptrIn, uintptr(len(in)), uintptr(unsafe.Pointer(&out[0])), uintptr(len(out)), uintptr(unsafe.Pointer(&outLen))) | ||||
| 	return outLen, Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardGetAttrib(card uintptr, id Attrib, buf []byte) (uint32, Error) { | ||||
| 	var ptr uintptr | ||||
| 
 | ||||
| 	if len(buf) != 0 { | ||||
| 		ptr = uintptr(unsafe.Pointer(&buf[0])) | ||||
| 	} | ||||
| 
 | ||||
| 	bufLen := uint32(len(buf)) | ||||
| 	r, _, _ := procGetAttrib.Call(card, uintptr(id), ptr, uintptr(unsafe.Pointer(&bufLen))) | ||||
| 
 | ||||
| 	return bufLen, Error(r) | ||||
| } | ||||
| 
 | ||||
| func scardSetAttrib(card uintptr, id Attrib, buf []byte) Error { | ||||
| 	r, _, _ := procSetAttrib.Call(card, uintptr(id), uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf))) | ||||
| 	return Error(r) | ||||
| } | ||||
| 
 | ||||
| type scardReaderState struct { | ||||
| 	szReader       uintptr | ||||
| 	pvUserData     uintptr | ||||
| 	dwCurrentState uint32 | ||||
| 	dwEventState   uint32 | ||||
| 	cbAtr          uint32 | ||||
| 	rgbAtr         [36]byte | ||||
| } | ||||
| 
 | ||||
| func (rs *ReaderState) toSys() (scardReaderState, error) { | ||||
| 	var sys scardReaderState | ||||
| 	creader, err := encodestr(rs.Reader) | ||||
| 	if err != nil { | ||||
| 		return scardReaderState{}, err | ||||
| 	} | ||||
| 	sys.szReader = uintptr(creader.ptr()) | ||||
| 	sys.dwCurrentState = uint32(rs.CurrentState) | ||||
| 	sys.cbAtr = uint32(len(rs.Atr)) | ||||
| 	copy(sys.rgbAtr[:], rs.Atr) | ||||
| 	return sys, nil | ||||
| } | ||||
| 
 | ||||
| func (rs *ReaderState) update(sys *scardReaderState) { | ||||
| 	rs.EventState = StateFlag(sys.dwEventState) | ||||
| 	if sys.cbAtr > 0 { | ||||
| 		rs.Atr = make([]byte, int(sys.cbAtr)) | ||||
| 		copy(rs.Atr, sys.rgbAtr[:]) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type strbuf []uint16 | ||||
| 
 | ||||
| func encodestr(s string) (strbuf, error) { | ||||
| 	utf16, err := syscall.UTF16FromString(s) | ||||
| 	return strbuf(utf16), err | ||||
| } | ||||
| 
 | ||||
| func decodestr(buf strbuf) string { | ||||
| 	return syscall.UTF16ToString(buf) | ||||
| } | ||||
							
								
								
									
										190
									
								
								vendor/github.com/ebfe/scard/zconst.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										190
									
								
								vendor/github.com/ebfe/scard/zconst.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,190 +0,0 @@ | ||||
| // Created by cgo -godefs - DO NOT EDIT
 | ||||
| // cgo -godefs -- -I /usr/include/PCSC/ const.go
 | ||||
| 
 | ||||
| package scard | ||||
| 
 | ||||
| type Attrib uint32 | ||||
| 
 | ||||
| const ( | ||||
| 	AttrVendorName           Attrib = 0x10100 | ||||
| 	AttrVendorIfdType        Attrib = 0x10101 | ||||
| 	AttrVendorIfdVersion     Attrib = 0x10102 | ||||
| 	AttrVendorIfdSerialNo    Attrib = 0x10103 | ||||
| 	AttrChannelId            Attrib = 0x20110 | ||||
| 	AttrAsyncProtocolTypes   Attrib = 0x30120 | ||||
| 	AttrDefaultClk           Attrib = 0x30121 | ||||
| 	AttrMaxClk               Attrib = 0x30122 | ||||
| 	AttrDefaultDataRate      Attrib = 0x30123 | ||||
| 	AttrMaxDataRate          Attrib = 0x30124 | ||||
| 	AttrMaxIfsd              Attrib = 0x30125 | ||||
| 	AttrSyncProtocolTypes    Attrib = 0x30126 | ||||
| 	AttrPowerMgmtSupport     Attrib = 0x40131 | ||||
| 	AttrUserToCardAuthDevice Attrib = 0x50140 | ||||
| 	AttrUserAuthInputDevice  Attrib = 0x50142 | ||||
| 	AttrCharacteristics      Attrib = 0x60150 | ||||
| 	AttrCurrentProtocolType  Attrib = 0x80201 | ||||
| 	AttrCurrentClk           Attrib = 0x80202 | ||||
| 	AttrCurrentF             Attrib = 0x80203 | ||||
| 	AttrCurrentD             Attrib = 0x80204 | ||||
| 	AttrCurrentN             Attrib = 0x80205 | ||||
| 	AttrCurrentW             Attrib = 0x80206 | ||||
| 	AttrCurrentIfsc          Attrib = 0x80207 | ||||
| 	AttrCurrentIfsd          Attrib = 0x80208 | ||||
| 	AttrCurrentBwt           Attrib = 0x80209 | ||||
| 	AttrCurrentCwt           Attrib = 0x8020a | ||||
| 	AttrCurrentEbcEncoding   Attrib = 0x8020b | ||||
| 	AttrExtendedBwt          Attrib = 0x8020c | ||||
| 	AttrIccPresence          Attrib = 0x90300 | ||||
| 	AttrIccInterfaceStatus   Attrib = 0x90301 | ||||
| 	AttrCurrentIoState       Attrib = 0x90302 | ||||
| 	AttrAtrString            Attrib = 0x90303 | ||||
| 	AttrIccTypePerAtr        Attrib = 0x90304 | ||||
| 	AttrEscReset             Attrib = 0x7a000 | ||||
| 	AttrEscCancel            Attrib = 0x7a003 | ||||
| 	AttrEscAuthrequest       Attrib = 0x7a005 | ||||
| 	AttrMaxinput             Attrib = 0x7a007 | ||||
| 	AttrDeviceUnit           Attrib = 0x7fff0001 | ||||
| 	AttrDeviceInUse          Attrib = 0x7fff0002 | ||||
| 	AttrDeviceFriendlyName   Attrib = 0x7fff0003 | ||||
| 	AttrDeviceSystemName     Attrib = 0x7fff0004 | ||||
| 	AttrSupressT1IfsRequest  Attrib = 0x7fff0007 | ||||
| ) | ||||
| 
 | ||||
| type Error uint32 | ||||
| 
 | ||||
| const ( | ||||
| 	ErrSuccess                Error = 0x0 | ||||
| 	ErrInternalError          Error = 0x80100001 | ||||
| 	ErrCancelled              Error = 0x80100002 | ||||
| 	ErrInvalidHandle          Error = 0x80100003 | ||||
| 	ErrInvalidParameter       Error = 0x80100004 | ||||
| 	ErrInvalidTarget          Error = 0x80100005 | ||||
| 	ErrNoMemory               Error = 0x80100006 | ||||
| 	ErrWaitedTooLong          Error = 0x80100007 | ||||
| 	ErrInsufficientBuffer     Error = 0x80100008 | ||||
| 	ErrUnknownReader          Error = 0x80100009 | ||||
| 	ErrTimeout                Error = 0x8010000a | ||||
| 	ErrSharingViolation       Error = 0x8010000b | ||||
| 	ErrNoSmartcard            Error = 0x8010000c | ||||
| 	ErrUnknownCard            Error = 0x8010000d | ||||
| 	ErrCantDispose            Error = 0x8010000e | ||||
| 	ErrProtoMismatch          Error = 0x8010000f | ||||
| 	ErrNotReady               Error = 0x80100010 | ||||
| 	ErrInvalidValue           Error = 0x80100011 | ||||
| 	ErrSystemCancelled        Error = 0x80100012 | ||||
| 	ErrCommError              Error = 0x80100013 | ||||
| 	ErrUnknownError           Error = 0x80100014 | ||||
| 	ErrInvalidAtr             Error = 0x80100015 | ||||
| 	ErrNotTransacted          Error = 0x80100016 | ||||
| 	ErrReaderUnavailable      Error = 0x80100017 | ||||
| 	ErrShutdown               Error = 0x80100018 | ||||
| 	ErrPciTooSmall            Error = 0x80100019 | ||||
| 	ErrReaderUnsupported      Error = 0x8010001a | ||||
| 	ErrDuplicateReader        Error = 0x8010001b | ||||
| 	ErrCardUnsupported        Error = 0x8010001c | ||||
| 	ErrNoService              Error = 0x8010001d | ||||
| 	ErrServiceStopped         Error = 0x8010001e | ||||
| 	ErrUnexpected             Error = 0x8010001f | ||||
| 	ErrUnsupportedFeature     Error = 0x8010001f | ||||
| 	ErrIccInstallation        Error = 0x80100020 | ||||
| 	ErrIccCreateorder         Error = 0x80100021 | ||||
| 	ErrFileNotFound           Error = 0x80100024 | ||||
| 	ErrNoDir                  Error = 0x80100025 | ||||
| 	ErrNoFile                 Error = 0x80100026 | ||||
| 	ErrNoAccess               Error = 0x80100027 | ||||
| 	ErrWriteTooMany           Error = 0x80100028 | ||||
| 	ErrBadSeek                Error = 0x80100029 | ||||
| 	ErrInvalidChv             Error = 0x8010002a | ||||
| 	ErrUnknownResMng          Error = 0x8010002b | ||||
| 	ErrNoSuchCertificate      Error = 0x8010002c | ||||
| 	ErrCertificateUnavailable Error = 0x8010002d | ||||
| 	ErrNoReadersAvailable     Error = 0x8010002e | ||||
| 	ErrCommDataLost           Error = 0x8010002f | ||||
| 	ErrNoKeyContainer         Error = 0x80100030 | ||||
| 	ErrServerTooBusy          Error = 0x80100031 | ||||
| 	ErrUnsupportedCard        Error = 0x80100065 | ||||
| 	ErrUnresponsiveCard       Error = 0x80100066 | ||||
| 	ErrUnpoweredCard          Error = 0x80100067 | ||||
| 	ErrResetCard              Error = 0x80100068 | ||||
| 	ErrRemovedCard            Error = 0x80100069 | ||||
| 	ErrSecurityViolation      Error = 0x8010006a | ||||
| 	ErrWrongChv               Error = 0x8010006b | ||||
| 	ErrChvBlocked             Error = 0x8010006c | ||||
| 	ErrEof                    Error = 0x8010006d | ||||
| 	ErrCancelledByUser        Error = 0x8010006e | ||||
| 	ErrCardNotAuthenticated   Error = 0x8010006f | ||||
| ) | ||||
| 
 | ||||
| type Protocol uint32 | ||||
| 
 | ||||
| const ( | ||||
| 	ProtocolUndefined Protocol = 0x0 | ||||
| 	ProtocolT0        Protocol = 0x1 | ||||
| 	ProtocolT1        Protocol = 0x2 | ||||
| 	ProtocolAny       Protocol = ProtocolT0 | ProtocolT1 | ||||
| ) | ||||
| 
 | ||||
| type ShareMode uint32 | ||||
| 
 | ||||
| const ( | ||||
| 	ShareExclusive ShareMode = 0x1 | ||||
| 	ShareShared    ShareMode = 0x2 | ||||
| 	ShareDirect    ShareMode = 0x3 | ||||
| ) | ||||
| 
 | ||||
| type Disposition uint32 | ||||
| 
 | ||||
| const ( | ||||
| 	LeaveCard   Disposition = 0x0 | ||||
| 	ResetCard   Disposition = 0x1 | ||||
| 	UnpowerCard Disposition = 0x2 | ||||
| 	EjectCard   Disposition = 0x3 | ||||
| ) | ||||
| 
 | ||||
| type Scope uint32 | ||||
| 
 | ||||
| const ( | ||||
| 	ScopeUser     Scope = 0x0 | ||||
| 	ScopeTerminal Scope = 0x1 | ||||
| 	ScopeSystem   Scope = 0x2 | ||||
| ) | ||||
| 
 | ||||
| type State uint32 | ||||
| 
 | ||||
| const ( | ||||
| 	Unknown    State = 0x1 | ||||
| 	Absent     State = 0x2 | ||||
| 	Present    State = 0x4 | ||||
| 	Swallowed  State = 0x8 | ||||
| 	Powered    State = 0x10 | ||||
| 	Negotiable State = 0x20 | ||||
| 	Specific   State = 0x40 | ||||
| ) | ||||
| 
 | ||||
| type StateFlag uint32 | ||||
| 
 | ||||
| const ( | ||||
| 	StateUnaware     StateFlag = 0x0 | ||||
| 	StateIgnore      StateFlag = 0x1 | ||||
| 	StateChanged     StateFlag = 0x2 | ||||
| 	StateUnknown     StateFlag = 0x4 | ||||
| 	StateUnavailable StateFlag = 0x8 | ||||
| 	StateEmpty       StateFlag = 0x10 | ||||
| 	StatePresent     StateFlag = 0x20 | ||||
| 	StateAtrmatch    StateFlag = 0x40 | ||||
| 	StateExclusive   StateFlag = 0x80 | ||||
| 	StateInuse       StateFlag = 0x100 | ||||
| 	StateMute        StateFlag = 0x200 | ||||
| 	StateUnpowered   StateFlag = 0x400 | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	maxBufferSize         = 0x108 | ||||
| 	maxBufferSizeExtended = 0x1000c | ||||
| 	maxReadername         = 0x80 | ||||
| 	maxAtrSize            = 0x21 | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	infiniteTimeout = 0xffffffff | ||||
| ) | ||||
							
								
								
									
										29
									
								
								vendor/github.com/gballet/go-libpcsclite/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/gballet/go-libpcsclite/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| BSD 3-Clause License | ||||
| 
 | ||||
| Copyright (c) 2019, Guillaume Ballet | ||||
| All rights reserved. | ||||
| 
 | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions are met: | ||||
| 
 | ||||
| * Redistributions of source code must retain the above copyright notice, this | ||||
|   list of conditions and the following disclaimer. | ||||
| 
 | ||||
| * Redistributions in binary form must reproduce the above copyright notice, | ||||
|   this list of conditions and the following disclaimer in the documentation | ||||
|   and/or other materials provided with the distribution. | ||||
| 
 | ||||
| * Neither the name of the copyright holder nor the names of its | ||||
|   contributors may be used to endorse or promote products derived from | ||||
|   this software without specific prior written permission. | ||||
| 
 | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||
| FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||
| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||
| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||
| OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
							
								
								
									
										53
									
								
								vendor/github.com/gballet/go-libpcsclite/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								vendor/github.com/gballet/go-libpcsclite/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | ||||
| # go-libpcsclite | ||||
| 
 | ||||
| A golang implementation of the [libpcpsclite](http://github.com/LudovicRousseau/PCSC) client. It connects to the `pcscd` daemon over sockets. | ||||
| 
 | ||||
| ## Purpose | ||||
| 
 | ||||
| The goal is for major open source projects to distribute a single binary that doesn't depend on `libpcsclite`. It provides an extra function `CheckPCSCDaemon` that will tell the user if `pcscd` is running. | ||||
| 
 | ||||
| ## Building | ||||
| 
 | ||||
| TODO | ||||
| 
 | ||||
| ## Example | ||||
| 
 | ||||
| TODO | ||||
| 
 | ||||
| ## TODO | ||||
| 
 | ||||
|   - [ ] Finish this README | ||||
|   - [ ] Lock context | ||||
|   - [ ] implement missing functions | ||||
| 
 | ||||
| ## License | ||||
| 
 | ||||
| BSD 3-Clause License | ||||
| 
 | ||||
| Copyright (c) 2019, Guillaume Ballet | ||||
| All rights reserved. | ||||
| 
 | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions are met: | ||||
| 
 | ||||
| * Redistributions of source code must retain the above copyright notice, this | ||||
|   list of conditions and the following disclaimer. | ||||
| 
 | ||||
| * Redistributions in binary form must reproduce the above copyright notice, | ||||
|   this list of conditions and the following disclaimer in the documentation | ||||
|   and/or other materials provided with the distribution. | ||||
| 
 | ||||
| * Neither the name of the copyright holder nor the names of its | ||||
|   contributors may be used to endorse or promote products derived from | ||||
|   this software without specific prior written permission. | ||||
| 
 | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||
| FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||
| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||
| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||
| OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
							
								
								
									
										99
									
								
								vendor/github.com/gballet/go-libpcsclite/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								vendor/github.com/gballet/go-libpcsclite/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,99 @@ | ||||
| // BSD 3-Clause License
 | ||||
| //
 | ||||
| // Copyright (c) 2019, Guillaume Ballet
 | ||||
| // All rights reserved.
 | ||||
| //
 | ||||
| // Redistribution and use in source and binary forms, with or without
 | ||||
| // modification, are permitted provided that the following conditions are met:
 | ||||
| //
 | ||||
| // * Redistributions of source code must retain the above copyright notice, this
 | ||||
| //   list of conditions and the following disclaimer.
 | ||||
| //
 | ||||
| // * Redistributions in binary form must reproduce the above copyright notice,
 | ||||
| //   this list of conditions and the following disclaimer in the documentation
 | ||||
| //   and/or other materials provided with the distribution.
 | ||||
| //
 | ||||
| // * Neither the name of the copyright holder nor the names of its
 | ||||
| //   contributors may be used to endorse or promote products derived from
 | ||||
| //   this software without specific prior written permission.
 | ||||
| //
 | ||||
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | ||||
| // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | ||||
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | ||||
| // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 | ||||
| // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | ||||
| // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 | ||||
| // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 | ||||
| // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | ||||
| // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | ||||
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | ||||
| 
 | ||||
| package pcsc | ||||
| 
 | ||||
| const ( | ||||
| 	SCardSuccess                   = 0x00000000 /* No error was encountered. */ | ||||
| 
 | ||||
| 	AutoAllocate  = -1     /* see SCardFreeMemory() */ | ||||
| 	ScopeUser     = 0x0000 /* Scope in user space */ | ||||
| 	ScopeTerminal = 0x0001 /* Scope in terminal */ | ||||
| 	ScopeSystem   = 0x0002 /* Scope in system */ | ||||
| 	ScopeGlobal   = 0x0003 /* Scope is global */ | ||||
| 
 | ||||
| 	ProtocolUndefined = 0x0000                    /* protocol not set */ | ||||
| 	ProtocolUnSet     = ProtocolUndefined         /* backward compat */ | ||||
| 	ProtocolT0        = 0x0001                    /* T=0 active protocol. */ | ||||
| 	ProtocolT1        = 0x0002                    /* T=1 active protocol. */ | ||||
| 	ProtocolRaw       = 0x0004                    /* Raw active protocol. */ | ||||
| 	ProtocolT15       = 0x0008                    /* T=15 protocol. */ | ||||
| 	ProtocolAny       = (ProtocolT0 | ProtocolT1) /* IFD determines prot. */ | ||||
| 
 | ||||
| 	ShareExclusive = 0x0001 /* Exclusive mode only */ | ||||
| 	ShareShared    = 0x0002 /* Shared mode only */ | ||||
| 	ShareDirect    = 0x0003 /* Raw mode only */ | ||||
| 
 | ||||
| 	LeaveCard   = 0x0000 /* Do nothing on close */ | ||||
| 	ResetCard   = 0x0001 /* Reset on close */ | ||||
| 	UnpowerCard = 0x0002 /* Power down on close */ | ||||
| 	EjectCard   = 0x0003 /* Eject on close */ | ||||
| 
 | ||||
| 	SCardUnknown    = 0x0001 /* Unknown state */ | ||||
| 	SCardAbsent     = 0x0002 /* Card is absent */ | ||||
| 	SCardPresent    = 0x0004 /* Card is present */ | ||||
| 	SCardSwallowed  = 0x0008 /* Card not powered */ | ||||
| 	SCardPowever    = 0x0010 /* Card is powered */ | ||||
| 	SCardNegotiable = 0x0020 /* Ready for PTS */ | ||||
| 	SCardSpecific   = 0x0040 /* PTS has been set */ | ||||
| 
 | ||||
| 	PCSCDSockName = "/run/pcscd/pcscd.comm" | ||||
| ) | ||||
| 
 | ||||
| // List of commands to send to the daemon
 | ||||
| const ( | ||||
| 	_                                   = iota | ||||
| 	SCardEstablishContext               /* used by SCardEstablishContext() */ | ||||
| 	SCardReleaseContext                 /* used by SCardReleaseContext() */ | ||||
| 	SCardListReaders                    /* used by SCardListReaders() */ | ||||
| 	SCardConnect                        /* used by SCardConnect() */ | ||||
| 	SCardReConnect                      /* used by SCardReconnect() */ | ||||
| 	SCardDisConnect                     /* used by SCardDisconnect() */ | ||||
| 	SCardBeginTransaction               /* used by SCardBeginTransaction() */ | ||||
| 	SCardEndTransaction                 /* used by SCardEndTransaction() */ | ||||
| 	SCardTransmit                       /* used by SCardTransmit() */ | ||||
| 	SCardControl                        /* used by SCardControl() */ | ||||
| 	SCardStatus                         /* used by SCardStatus() */ | ||||
| 	SCardGetStatusChange                /* not used */ | ||||
| 	SCardCancel                         /* used by SCardCancel() */ | ||||
| 	SCardCancelTransaction              /* not used */ | ||||
| 	SCardGetAttrib                      /* used by SCardGetAttrib() */ | ||||
| 	SCardSetAttrib                      /* used by SCardSetAttrib() */ | ||||
| 	CommandVersion                      /* get the client/server protocol version */ | ||||
| 	CommandGetReaderState               /* get the readers state */ | ||||
| 	CommandWaitReaderStateChange        /* wait for a reader state change */ | ||||
| 	CommandStopWaitingReaderStateChange /* stop waiting for a reader state change */ | ||||
| ) | ||||
| 
 | ||||
| // Protocol information
 | ||||
| const ( | ||||
| 	ProtocolVersionMajor = 4 /* IPC major */ | ||||
| 	ProtocolVersionMinor = 3 /* IPC minor */ | ||||
| ) | ||||
							
								
								
									
										1
									
								
								vendor/github.com/gballet/go-libpcsclite/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/gballet/go-libpcsclite/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| module github.com/gballet/go-libpcsclite | ||||
							
								
								
									
										78
									
								
								vendor/github.com/gballet/go-libpcsclite/msg.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								vendor/github.com/gballet/go-libpcsclite/msg.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | ||||
| // BSD 3-Clause License
 | ||||
| //
 | ||||
| // Copyright (c) 2019, Guillaume Ballet
 | ||||
| // All rights reserved.
 | ||||
| //
 | ||||
| // Redistribution and use in source and binary forms, with or without
 | ||||
| // modification, are permitted provided that the following conditions are met:
 | ||||
| //
 | ||||
| // * Redistributions of source code must retain the above copyright notice, this
 | ||||
| //   list of conditions and the following disclaimer.
 | ||||
| //
 | ||||
| // * Redistributions in binary form must reproduce the above copyright notice,
 | ||||
| //   this list of conditions and the following disclaimer in the documentation
 | ||||
| //   and/or other materials provided with the distribution.
 | ||||
| //
 | ||||
| // * Neither the name of the copyright holder nor the names of its
 | ||||
| //   contributors may be used to endorse or promote products derived from
 | ||||
| //   this software without specific prior written permission.
 | ||||
| //
 | ||||
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | ||||
| // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | ||||
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | ||||
| // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 | ||||
| // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | ||||
| // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 | ||||
| // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 | ||||
| // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | ||||
| // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | ||||
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | ||||
| 
 | ||||
| package pcsc | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/binary" | ||||
| 	"net" | ||||
| ) | ||||
| 
 | ||||
| /** | ||||
|  * @brief Wrapper for the MessageSend() function. | ||||
|  * | ||||
|  * Called by clients to send messages to the server. | ||||
|  * The parameters \p command and \p data are set in the \c sharedSegmentMsg | ||||
|  * struct in order to be sent. | ||||
|  * | ||||
|  * @param[in] command Command to be sent. | ||||
|  * @param[in] dwClientID Client socket handle. | ||||
|  * @param[in] size Size of the message (\p data). | ||||
|  * @param[in] data_void Data to be sent. | ||||
|  * | ||||
|  * @return Same error codes as MessageSend(). | ||||
|  */ | ||||
| func messageSendWithHeader(command uint32, conn net.Conn, data []byte) error { | ||||
| 	/* Translate header into bytes */ | ||||
| 	msgData := make([]byte, 8+len(data)) | ||||
| 	binary.LittleEndian.PutUint32(msgData[4:], command) | ||||
| 	binary.LittleEndian.PutUint32(msgData, uint32(len(data))) | ||||
| 
 | ||||
| 	/* Copy payload */ | ||||
| 	copy(msgData[8:], data) | ||||
| 
 | ||||
| 	_, err := conn.Write(msgData) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // ClientSetupSession prepares a communication channel for the client to talk to the server.
 | ||||
| // This is called by the application to create a socket for local IPC with the
 | ||||
| // server. The socket is associated to the file \c PCSCLITE_CSOCK_NAME.
 | ||||
| /* | ||||
|  * @param[out] pdwClientID Client Connection ID. | ||||
|  * | ||||
|  * @retval 0 Success. | ||||
|  * @retval -1 Can not create the socket. | ||||
|  * @retval -1 The socket can not open a connection. | ||||
|  * @retval -1 Can not set the socket to non-blocking. | ||||
|  */ | ||||
| func clientSetupSession() (net.Conn, error) { | ||||
| 	return net.Dial("unix", PCSCDSockName) | ||||
| } | ||||
							
								
								
									
										371
									
								
								vendor/github.com/gballet/go-libpcsclite/winscard.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										371
									
								
								vendor/github.com/gballet/go-libpcsclite/winscard.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,371 @@ | ||||
| // BSD 3-Clause License
 | ||||
| //
 | ||||
| // Copyright (c) 2019, Guillaume Ballet
 | ||||
| // All rights reserved.
 | ||||
| //
 | ||||
| // Redistribution and use in source and binary forms, with or without
 | ||||
| // modification, are permitted provided that the following conditions are met:
 | ||||
| //
 | ||||
| // * Redistributions of source code must retain the above copyright notice, this
 | ||||
| //   list of conditions and the following disclaimer.
 | ||||
| //
 | ||||
| // * Redistributions in binary form must reproduce the above copyright notice,
 | ||||
| //   this list of conditions and the following disclaimer in the documentation
 | ||||
| //   and/or other materials provided with the distribution.
 | ||||
| //
 | ||||
| // * Neither the name of the copyright holder nor the names of its
 | ||||
| //   contributors may be used to endorse or promote products derived from
 | ||||
| //   this software without specific prior written permission.
 | ||||
| //
 | ||||
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | ||||
| // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | ||||
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | ||||
| // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 | ||||
| // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | ||||
| // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 | ||||
| // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 | ||||
| // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | ||||
| // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | ||||
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | ||||
| 
 | ||||
| package pcsc | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/binary" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| // Client contains all the information needed to establish
 | ||||
| // and maintain a connection to the deamon/card.
 | ||||
| type Client struct { | ||||
| 	conn net.Conn | ||||
| 
 | ||||
| 	minor uint32 | ||||
| 	major uint32 | ||||
| 
 | ||||
| 	ctx uint32 | ||||
| 
 | ||||
| 	readerStateDescriptors [MaxReaderStateDescriptors]ReaderState | ||||
| } | ||||
| 
 | ||||
| // EstablishContext asks the PCSC daemon to create a context
 | ||||
| // handle for further communication with connected cards and
 | ||||
| // readers.
 | ||||
| func EstablishContext(scope uint32) (*Client, error) { | ||||
| 	client := &Client{} | ||||
| 
 | ||||
| 	conn, err := clientSetupSession() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	client.conn = conn | ||||
| 
 | ||||
| 	/* Exchange version information */ | ||||
| 	payload := make([]byte, 12) | ||||
| 	binary.LittleEndian.PutUint32(payload, ProtocolVersionMajor) | ||||
| 	binary.LittleEndian.PutUint32(payload[4:], ProtocolVersionMinor) | ||||
| 	binary.LittleEndian.PutUint32(payload[8:], SCardSuccess) | ||||
| 	err = messageSendWithHeader(CommandVersion, conn, payload) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response := make([]byte, 12) | ||||
| 	n, err := conn.Read(response) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if n != len(response) { | ||||
| 		return nil, fmt.Errorf("invalid response length: expected %d, got %d", len(response), n) | ||||
| 	} | ||||
| 	code := binary.LittleEndian.Uint32(response[8:]) | ||||
| 	if code != SCardSuccess { | ||||
| 		return nil, fmt.Errorf("invalid response code: expected %d, got %d", SCardSuccess, code) | ||||
| 	} | ||||
| 	client.major = binary.LittleEndian.Uint32(response) | ||||
| 	client.minor = binary.LittleEndian.Uint32(response[4:]) | ||||
| 	if client.major != ProtocolVersionMajor || client.minor != ProtocolVersionMinor { | ||||
| 		return nil, fmt.Errorf("invalid version found: expected %d.%d, got %d.%d", ProtocolVersionMajor, ProtocolVersionMinor, client.major, client.minor) | ||||
| 	} | ||||
| 
 | ||||
| 	/* Establish the context proper */ | ||||
| 	binary.LittleEndian.PutUint32(payload, scope) | ||||
| 	binary.LittleEndian.PutUint32(payload[4:], 0) | ||||
| 	binary.LittleEndian.PutUint32(payload[8:], SCardSuccess) | ||||
| 	err = messageSendWithHeader(SCardEstablishContext, conn, payload) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response = make([]byte, 12) | ||||
| 	n, err = conn.Read(response) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if n != len(response) { | ||||
| 		return nil, fmt.Errorf("invalid response length: expected %d, got %d", len(response), n) | ||||
| 	} | ||||
| 	code = binary.LittleEndian.Uint32(response[8:]) | ||||
| 	if code != SCardSuccess { | ||||
| 		return nil, fmt.Errorf("invalid response code: expected %d, got %d", SCardSuccess, code) | ||||
| 	} | ||||
| 	client.ctx = binary.LittleEndian.Uint32(response[4:]) | ||||
| 
 | ||||
| 	return client, nil | ||||
| } | ||||
| 
 | ||||
| // ReleaseContext tells the daemon that the client will no longer
 | ||||
| // need the context.
 | ||||
| func (client *Client) ReleaseContext() error { | ||||
| 	data := [8]byte{} | ||||
| 	binary.LittleEndian.PutUint32(data[:], client.ctx) | ||||
| 	binary.LittleEndian.PutUint32(data[4:], SCardSuccess) | ||||
| 	err := messageSendWithHeader(SCardReleaseContext, client.conn, data[:]) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	total := 0 | ||||
| 	for total < len(data) { | ||||
| 		n, err := client.conn.Read(data[total:]) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		total += n | ||||
| 	} | ||||
| 	code := binary.LittleEndian.Uint32(data[4:]) | ||||
| 	if code != SCardSuccess { | ||||
| 		return fmt.Errorf("invalid return code: %x", code) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Constants related to the reader state structure
 | ||||
| const ( | ||||
| 	ReaderStateNameLength       = 128 | ||||
| 	ReaderStateMaxAtrSizeLength = 33 | ||||
| 	// NOTE: ATR is 32-byte aligned in the C version, which means it's
 | ||||
| 	// actually 36 byte long and not 33.
 | ||||
| 	ReaderStateDescriptorLength = ReaderStateNameLength + ReaderStateMaxAtrSizeLength + 5*4 + 3 | ||||
| 
 | ||||
| 	MaxReaderStateDescriptors = 16 | ||||
| ) | ||||
| 
 | ||||
| // ReaderState represent the state of a single reader, as reported
 | ||||
| // by the PCSC daemon.
 | ||||
| type ReaderState struct { | ||||
| 	Name          string /* reader name */ | ||||
| 	eventCounter  uint32 /* number of card events */ | ||||
| 	readerState   uint32 /* SCARD_* bit field */ | ||||
| 	readerSharing uint32 /* PCSCLITE_SHARING_* sharing status */ | ||||
| 
 | ||||
| 	cardAtr       [ReaderStateMaxAtrSizeLength]byte /* ATR */ | ||||
| 	cardAtrLength uint32                            /* ATR length */ | ||||
| 	cardProtocol  uint32                            /* SCARD_PROTOCOL_* value */ | ||||
| } | ||||
| 
 | ||||
| func getReaderState(data []byte) (ReaderState, error) { | ||||
| 	ret := ReaderState{} | ||||
| 	if len(data) < ReaderStateDescriptorLength { | ||||
| 		return ret, fmt.Errorf("could not unmarshall data of length %d < %d", len(data), ReaderStateDescriptorLength) | ||||
| 	} | ||||
| 
 | ||||
| 	ret.Name = string(data[:ReaderStateNameLength]) | ||||
| 	ret.eventCounter = binary.LittleEndian.Uint32(data[unsafe.Offsetof(ret.eventCounter):]) | ||||
| 	ret.readerState = binary.LittleEndian.Uint32(data[unsafe.Offsetof(ret.readerState):]) | ||||
| 	ret.readerSharing = binary.LittleEndian.Uint32(data[unsafe.Offsetof(ret.readerSharing):]) | ||||
| 	copy(ret.cardAtr[:], data[unsafe.Offsetof(ret.cardAtr):unsafe.Offsetof(ret.cardAtr)+ReaderStateMaxAtrSizeLength]) | ||||
| 	ret.cardAtrLength = binary.LittleEndian.Uint32(data[unsafe.Offsetof(ret.cardAtrLength):]) | ||||
| 	ret.cardProtocol = binary.LittleEndian.Uint32(data[unsafe.Offsetof(ret.cardProtocol):]) | ||||
| 
 | ||||
| 	return ret, nil | ||||
| } | ||||
| 
 | ||||
| // ListReaders gets the list of readers from the daemon
 | ||||
| func (client *Client) ListReaders() ([]string, error) { | ||||
| 	err := messageSendWithHeader(CommandGetReaderState, client.conn, []byte{}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response := make([]byte, ReaderStateDescriptorLength*MaxReaderStateDescriptors) | ||||
| 	total := 0 | ||||
| 	for total < len(response) { | ||||
| 		n, err := client.conn.Read(response[total:]) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		total += n | ||||
| 	} | ||||
| 
 | ||||
| 	var names []string | ||||
| 	for i := range client.readerStateDescriptors { | ||||
| 		desc, err := getReaderState(response[i*ReaderStateDescriptorLength:]) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		client.readerStateDescriptors[i] = desc | ||||
| 		if desc.Name[0] == 0 { | ||||
| 			break | ||||
| 		} | ||||
| 		names = append(names, desc.Name) | ||||
| 	} | ||||
| 
 | ||||
| 	return names, nil | ||||
| } | ||||
| 
 | ||||
| // Offsets into the Connect request/response packet
 | ||||
| const ( | ||||
| 	SCardConnectReaderNameOffset        = 4 | ||||
| 	SCardConnectShareModeOffset         = SCardConnectReaderNameOffset + ReaderStateNameLength | ||||
| 	SCardConnectPreferredProtocolOffset = SCardConnectShareModeOffset + 4 | ||||
| 	SCardConnectReturnValueOffset       = SCardConnectPreferredProtocolOffset + 12 | ||||
| ) | ||||
| 
 | ||||
| // Card represents the connection to a card
 | ||||
| type Card struct { | ||||
| 	handle      uint32 | ||||
| 	activeProto uint32 | ||||
| 	client      *Client | ||||
| } | ||||
| 
 | ||||
| // Connect asks the daemon to connect to the card
 | ||||
| func (client *Client) Connect(name string, shareMode uint32, preferredProtocol uint32) (*Card, error) { | ||||
| 	request := make([]byte, ReaderStateNameLength+4*6) | ||||
| 	binary.LittleEndian.PutUint32(request, client.ctx) | ||||
| 	copy(request[SCardConnectReaderNameOffset:], []byte(name)) | ||||
| 	binary.LittleEndian.PutUint32(request[SCardConnectShareModeOffset:], shareMode) | ||||
| 	binary.LittleEndian.PutUint32(request[SCardConnectPreferredProtocolOffset:], preferredProtocol) | ||||
| 	binary.LittleEndian.PutUint32(request[SCardConnectReturnValueOffset:], SCardSuccess) | ||||
| 
 | ||||
| 	err := messageSendWithHeader(SCardConnect, client.conn, request) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response := make([]byte, ReaderStateNameLength+4*6) | ||||
| 	total := 0 | ||||
| 	for total < len(response) { | ||||
| 		n, err := client.conn.Read(response[total:]) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		fmt.Println("total, n", total, n, response) | ||||
| 		total += n | ||||
| 	} | ||||
| 	code := binary.LittleEndian.Uint32(response[148:]) | ||||
| 	if code != SCardSuccess { | ||||
| 		return nil, fmt.Errorf("invalid return code: %x", code) | ||||
| 	} | ||||
| 	handle := binary.LittleEndian.Uint32(response[140:]) | ||||
| 	active := binary.LittleEndian.Uint32(response[SCardConnectPreferredProtocolOffset:]) | ||||
| 
 | ||||
| 	return &Card{handle: handle, activeProto: active, client: client}, nil | ||||
| } | ||||
| 
 | ||||
| /** | ||||
| * @brief contained in \ref SCARD_TRANSMIT Messages. | ||||
| * | ||||
| * These data are passed throw the field \c sharedSegmentMsg.data. | ||||
|  */ | ||||
| type transmit struct { | ||||
| 	hCard             uint32 | ||||
| 	ioSendPciProtocol uint32 | ||||
| 	ioSendPciLength   uint32 | ||||
| 	cbSendLength      uint32 | ||||
| 	ioRecvPciProtocol uint32 | ||||
| 	ioRecvPciLength   uint32 | ||||
| 	pcbRecvLength     uint32 | ||||
| 	rv                uint32 | ||||
| } | ||||
| 
 | ||||
| // SCardIoRequest contains the info needed for performing an IO request
 | ||||
| type SCardIoRequest struct { | ||||
| 	proto  uint32 | ||||
| 	length uint32 | ||||
| } | ||||
| 
 | ||||
| const ( | ||||
| 	TransmitRequestLength = 32 | ||||
| ) | ||||
| 
 | ||||
| // Transmit sends request data to a card and returns the response
 | ||||
| func (card *Card) Transmit(adpu []byte) ([]byte, *SCardIoRequest, error) { | ||||
| 	request := [TransmitRequestLength]byte{} | ||||
| 	binary.LittleEndian.PutUint32(request[:], card.handle) | ||||
| 	binary.LittleEndian.PutUint32(request[4:] /*card.activeProto*/, 2) | ||||
| 	binary.LittleEndian.PutUint32(request[8:], 8) | ||||
| 	binary.LittleEndian.PutUint32(request[12:], uint32(len(adpu))) | ||||
| 	binary.LittleEndian.PutUint32(request[16:], 0) | ||||
| 	binary.LittleEndian.PutUint32(request[20:], 0) | ||||
| 	binary.LittleEndian.PutUint32(request[24:], 0x10000) | ||||
| 	binary.LittleEndian.PutUint32(request[28:], SCardSuccess) | ||||
| 	err := messageSendWithHeader(SCardTransmit, card.client.conn, request[:]) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	// Add the ADPU payload after the transmit descriptor
 | ||||
| 	n, err := card.client.conn.Write(adpu) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	if n != len(adpu) { | ||||
| 		return nil, nil, fmt.Errorf("Invalid number of bytes written: expected %d, got %d", len(adpu), n) | ||||
| 	} | ||||
| 	response := [TransmitRequestLength]byte{} | ||||
| 	total := 0 | ||||
| 	for total < len(response) { | ||||
| 		n, err = card.client.conn.Read(response[total:]) | ||||
| 		if err != nil { | ||||
| 			return nil, nil, err | ||||
| 		} | ||||
| 		total += n | ||||
| 	} | ||||
| 
 | ||||
| 	code := binary.LittleEndian.Uint32(response[28:]) | ||||
| 	if code != SCardSuccess { | ||||
| 		return nil, nil, fmt.Errorf("invalid return code: %x", code) | ||||
| 	} | ||||
| 
 | ||||
| 	// Recover the response data
 | ||||
| 	recvProto := binary.LittleEndian.Uint32(response[16:]) | ||||
| 	recvLength := binary.LittleEndian.Uint32(response[20:]) | ||||
| 	recv := &SCardIoRequest{proto: recvProto, length: recvLength} | ||||
| 	recvLength = binary.LittleEndian.Uint32(response[24:]) | ||||
| 	recvData := make([]byte, recvLength) | ||||
| 	total = 0 | ||||
| 	for uint32(total) < recvLength { | ||||
| 		n, err := card.client.conn.Read(recvData[total:]) | ||||
| 		if err != nil { | ||||
| 			return nil, nil, err | ||||
| 		} | ||||
| 		total += n | ||||
| 	} | ||||
| 
 | ||||
| 	return recvData, recv, nil | ||||
| } | ||||
| 
 | ||||
| // Disconnect tells the PCSC daemon that the client is no longer
 | ||||
| // interested in communicating with the card.
 | ||||
| func (card *Card) Disconnect(disposition uint32) error { | ||||
| 	data := [12]byte{} | ||||
| 	binary.LittleEndian.PutUint32(data[:], card.handle) | ||||
| 	binary.LittleEndian.PutUint32(data[4:], disposition) | ||||
| 	binary.LittleEndian.PutUint32(data[8:], SCardSuccess) | ||||
| 	err := messageSendWithHeader(SCardDisConnect, card.client.conn, data[:]) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	total := 0 | ||||
| 	for total < len(data) { | ||||
| 		n, err := card.client.conn.Read(data[total:]) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		total += n | ||||
| 	} | ||||
| 	code := binary.LittleEndian.Uint32(data[8:]) | ||||
| 	if code != SCardSuccess { | ||||
| 		return fmt.Errorf("invalid return code: %x", code) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										6
									
								
								vendor/vendor.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/vendor.json
									
									
									
									
										vendored
									
									
								
							| @ -145,6 +145,12 @@ | ||||
| 			"revision": "ca190fb6ffbc076ff49197b7168a760f30182d2e", | ||||
| 			"revisionTime": "2018-04-18T12:24:29Z" | ||||
| 		}, | ||||
| 		{ | ||||
| 			"checksumSHA1": "GnNfMrYs/4m+HCtDBF7HpPUFFVw=", | ||||
| 			"path": "github.com/gballet/go-libpcsclite", | ||||
| 			"revision": "95b81846253cd854b8bb8f2fd9cc6056d0681ac4", | ||||
| 			"revisionTime": "2019-03-13T11:40:44Z" | ||||
| 		}, | ||||
| 		{ | ||||
| 			"checksumSHA1": "gxV/cPPLkByTdY8y172t7v4qcZA=", | ||||
| 			"path": "github.com/go-ole/go-ole", | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user