scard_darwin.go 6.2 KB

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