scard_unix.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // +build !windows,!darwin
  2. package scard
  3. // #cgo pkg-config: libpcsclite
  4. // #include <stdlib.h>
  5. // #include <winscard.h>
  6. import "C"
  7. import (
  8. "unsafe"
  9. )
  10. func (e Error) Error() string {
  11. return "scard: " + C.GoString(C.pcsc_stringify_error(C.LONG(e)))
  12. }
  13. // Version returns the libpcsclite version string
  14. func Version() string {
  15. return C.PCSCLITE_VERSION_NUMBER
  16. }
  17. func scardEstablishContext(scope Scope, reserved1, reserved2 uintptr) (uintptr, Error) {
  18. var ctx C.SCARDCONTEXT
  19. r := C.SCardEstablishContext(C.DWORD(scope), C.LPCVOID(reserved1), C.LPCVOID(reserved2), &ctx)
  20. return uintptr(ctx), Error(r)
  21. }
  22. func scardIsValidContext(ctx uintptr) Error {
  23. r := C.SCardIsValidContext(C.SCARDCONTEXT(ctx))
  24. return Error(r)
  25. }
  26. func scardCancel(ctx uintptr) Error {
  27. r := C.SCardCancel(C.SCARDCONTEXT(ctx))
  28. return Error(r)
  29. }
  30. func scardReleaseContext(ctx uintptr) Error {
  31. r := C.SCardReleaseContext(C.SCARDCONTEXT(ctx))
  32. return Error(r)
  33. }
  34. func scardListReaders(ctx uintptr, groups, buf unsafe.Pointer, bufLen uint32) (uint32, Error) {
  35. dwBufLen := C.DWORD(bufLen)
  36. r := C.SCardListReaders(C.SCARDCONTEXT(ctx), (C.LPCSTR)(groups), (C.LPSTR)(buf), &dwBufLen)
  37. return uint32(dwBufLen), Error(r)
  38. }
  39. func scardListReaderGroups(ctx uintptr, buf unsafe.Pointer, bufLen uint32) (uint32, Error) {
  40. dwBufLen := C.DWORD(bufLen)
  41. r := C.SCardListReaderGroups(C.SCARDCONTEXT(ctx), (C.LPSTR)(buf), &dwBufLen)
  42. return uint32(dwBufLen), Error(r)
  43. }
  44. func scardGetStatusChange(ctx uintptr, timeout uint32, states []scardReaderState) Error {
  45. r := C.SCardGetStatusChange(C.SCARDCONTEXT(ctx), C.DWORD(timeout), (C.LPSCARD_READERSTATE)(unsafe.Pointer(&states[0])), C.DWORD(len(states)))
  46. return Error(r)
  47. }
  48. func scardConnect(ctx uintptr, reader unsafe.Pointer, shareMode ShareMode, proto Protocol) (uintptr, Protocol, Error) {
  49. var handle C.SCARDHANDLE
  50. var activeProto C.DWORD
  51. r := C.SCardConnect(C.SCARDCONTEXT(ctx), C.LPCSTR(reader), C.DWORD(shareMode), C.DWORD(proto), &handle, &activeProto)
  52. return uintptr(handle), Protocol(activeProto), Error(r)
  53. }
  54. func scardDisconnect(card uintptr, d Disposition) Error {
  55. r := C.SCardDisconnect(C.SCARDHANDLE(card), C.DWORD(d))
  56. return Error(r)
  57. }
  58. func scardReconnect(card uintptr, mode ShareMode, proto Protocol, disp Disposition) (Protocol, Error) {
  59. var activeProtocol C.DWORD
  60. r := C.SCardReconnect(C.SCARDHANDLE(card), C.DWORD(mode), C.DWORD(proto), C.DWORD(disp), &activeProtocol)
  61. return Protocol(activeProtocol), Error(r)
  62. }
  63. func scardBeginTransaction(card uintptr) Error {
  64. r := C.SCardBeginTransaction(C.SCARDHANDLE(card))
  65. return Error(r)
  66. }
  67. func scardEndTransaction(card uintptr, disp Disposition) Error {
  68. r := C.SCardEndTransaction(C.SCARDHANDLE(card), C.DWORD(disp))
  69. return Error(r)
  70. }
  71. func scardCardStatus(card uintptr) (string, State, Protocol, []byte, Error) {
  72. var readerBuf [C.MAX_READERNAME + 1]byte
  73. var readerLen = C.DWORD(len(readerBuf))
  74. var state, proto C.DWORD
  75. var atr [maxAtrSize]byte
  76. var atrLen = C.DWORD(len(atr))
  77. r := C.SCardStatus(C.SCARDHANDLE(card), (C.LPSTR)(unsafe.Pointer(&readerBuf[0])), &readerLen, &state, &proto, (*C.BYTE)(&atr[0]), &atrLen)
  78. return decodestr(readerBuf[:readerLen]), State(state), Protocol(proto), atr[:atrLen], Error(r)
  79. }
  80. func scardTransmit(card uintptr, proto Protocol, cmd []byte, rsp []byte) (uint32, Error) {
  81. var sendpci C.SCARD_IO_REQUEST
  82. var recvpci C.SCARD_IO_REQUEST
  83. var rspLen = C.DWORD(len(rsp))
  84. switch proto {
  85. case ProtocolT0, ProtocolT1:
  86. sendpci.dwProtocol = C.ulong(proto)
  87. default:
  88. panic("unknown protocol")
  89. }
  90. sendpci.cbPciLength = C.sizeof_SCARD_IO_REQUEST
  91. r := C.SCardTransmit(C.SCARDHANDLE(card), &sendpci, (*C.BYTE)(&cmd[0]), C.DWORD(len(cmd)), &recvpci, (*C.BYTE)(&rsp[0]), &rspLen)
  92. return uint32(rspLen), Error(r)
  93. }
  94. func scardControl(card uintptr, ioctl uint32, in, out []byte) (uint32, Error) {
  95. var ptrIn C.LPCVOID
  96. var outLen = C.DWORD(len(out))
  97. if len(in) != 0 {
  98. ptrIn = C.LPCVOID(unsafe.Pointer(&in[0]))
  99. }
  100. 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)
  101. return uint32(outLen), Error(r)
  102. }
  103. func scardGetAttrib(card uintptr, id Attrib, buf []byte) (uint32, Error) {
  104. var ptr C.LPBYTE
  105. if len(buf) != 0 {
  106. ptr = C.LPBYTE(unsafe.Pointer(&buf[0]))
  107. }
  108. bufLen := C.DWORD(len(buf))
  109. r := C.SCardGetAttrib(C.SCARDHANDLE(card), C.DWORD(id), ptr, &bufLen)
  110. return uint32(bufLen), Error(r)
  111. }
  112. func scardSetAttrib(card uintptr, id Attrib, buf []byte) Error {
  113. r := C.SCardSetAttrib(C.SCARDHANDLE(card), C.DWORD(id), (*C.BYTE)(unsafe.Pointer(&buf[0])), C.DWORD(len(buf)))
  114. return Error(r)
  115. }
  116. type strbuf []byte
  117. func encodestr(s string) (strbuf, error) {
  118. buf := strbuf(s + "\x00")
  119. return buf, nil
  120. }
  121. func decodestr(buf strbuf) string {
  122. if len(buf) == 0 {
  123. return ""
  124. }
  125. if buf[len(buf)-1] == 0 {
  126. buf = buf[:len(buf)-1]
  127. }
  128. return string(buf)
  129. }
  130. type scardReaderState struct {
  131. szReader uintptr
  132. pvUserData uintptr
  133. dwCurrentState uintptr
  134. dwEventState uintptr
  135. cbAtr uintptr
  136. rgbAtr [33]byte
  137. }
  138. var pinned = map[string]*strbuf{}
  139. func (rs *ReaderState) toSys() (scardReaderState, error) {
  140. var sys scardReaderState
  141. creader, err := encodestr(rs.Reader)
  142. if err != nil {
  143. return scardReaderState{}, err
  144. }
  145. pinned[rs.Reader] = &creader
  146. sys.szReader = uintptr(creader.ptr())
  147. sys.dwCurrentState = uintptr(rs.CurrentState)
  148. sys.cbAtr = uintptr(len(rs.Atr))
  149. for i, v := range rs.Atr {
  150. sys.rgbAtr[i] = byte(v)
  151. }
  152. return sys, nil
  153. }
  154. func (rs *ReaderState) update(sys *scardReaderState) {
  155. rs.EventState = StateFlag(sys.dwEventState)
  156. if sys.cbAtr > 0 {
  157. rs.Atr = make([]byte, int(sys.cbAtr))
  158. for i := 0; i < int(sys.cbAtr); i++ {
  159. rs.Atr[i] = byte(sys.rgbAtr[i])
  160. }
  161. }
  162. }