scard.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. // Package scard provides bindings to the PC/SC API.
  2. package scard
  3. import (
  4. "time"
  5. "unsafe"
  6. )
  7. type CardStatus struct {
  8. Reader string
  9. State State
  10. ActiveProtocol Protocol
  11. Atr []byte
  12. }
  13. type ReaderState struct {
  14. Reader string
  15. UserData interface{}
  16. CurrentState StateFlag
  17. EventState StateFlag
  18. Atr []byte
  19. }
  20. type Context struct {
  21. ctx uintptr
  22. }
  23. type Card struct {
  24. handle uintptr
  25. activeProtocol Protocol
  26. }
  27. // wraps SCardEstablishContext
  28. func EstablishContext() (*Context, error) {
  29. ctx, r := scardEstablishContext(ScopeSystem, 0, 0)
  30. if r != ErrSuccess {
  31. return nil, r
  32. }
  33. return &Context{ctx: ctx}, nil
  34. }
  35. // wraps SCardIsValidContext
  36. func (ctx *Context) IsValid() (bool, error) {
  37. r := scardIsValidContext(ctx.ctx)
  38. switch r {
  39. case ErrSuccess:
  40. return true, nil
  41. case ErrInvalidHandle:
  42. return false, nil
  43. default:
  44. return false, r
  45. }
  46. }
  47. // wraps SCardCancel
  48. func (ctx *Context) Cancel() error {
  49. r := scardCancel(ctx.ctx)
  50. if r != ErrSuccess {
  51. return r
  52. }
  53. return nil
  54. }
  55. // wraps SCardReleaseContext
  56. func (ctx *Context) Release() error {
  57. r := scardReleaseContext(ctx.ctx)
  58. if r != ErrSuccess {
  59. return r
  60. }
  61. return nil
  62. }
  63. // wraps SCardListReaders
  64. func (ctx *Context) ListReaders() ([]string, error) {
  65. needed, r := scardListReaders(ctx.ctx, nil, nil, 0)
  66. if r != ErrSuccess {
  67. return nil, r
  68. }
  69. buf := make(strbuf, needed)
  70. n, r := scardListReaders(ctx.ctx, nil, buf.ptr(), uint32(len(buf)))
  71. if r != ErrSuccess {
  72. return nil, r
  73. }
  74. return decodemstr(buf[:n]), nil
  75. }
  76. // wraps SCardListReaderGroups
  77. func (ctx *Context) ListReaderGroups() ([]string, error) {
  78. needed, r := scardListReaderGroups(ctx.ctx, nil, 0)
  79. if r != ErrSuccess {
  80. return nil, r
  81. }
  82. buf := make(strbuf, needed)
  83. n, r := scardListReaderGroups(ctx.ctx, buf.ptr(), uint32(len(buf)))
  84. if r != ErrSuccess {
  85. return nil, r
  86. }
  87. return decodemstr(buf[:n]), nil
  88. }
  89. // wraps SCardGetStatusChange
  90. func (ctx *Context) GetStatusChange(readerStates []ReaderState, timeout time.Duration) error {
  91. dwTimeout := durationToTimeout(timeout)
  92. states := make([]scardReaderState, len(readerStates))
  93. for i := range readerStates {
  94. var err error
  95. states[i], err = readerStates[i].toSys()
  96. if err != nil {
  97. return err
  98. }
  99. }
  100. r := scardGetStatusChange(ctx.ctx, dwTimeout, states)
  101. if r != ErrSuccess {
  102. return r
  103. }
  104. for i := range readerStates {
  105. (&readerStates[i]).update(&states[i])
  106. }
  107. return nil
  108. }
  109. // wraps SCardConnect
  110. func (ctx *Context) Connect(reader string, mode ShareMode, proto Protocol) (*Card, error) {
  111. creader, err := encodestr(reader)
  112. if err != nil {
  113. return nil, err
  114. }
  115. handle, activeProtocol, r := scardConnect(ctx.ctx, creader.ptr(), mode, proto)
  116. if r != ErrSuccess {
  117. return nil, r
  118. }
  119. return &Card{handle: handle, activeProtocol: activeProtocol}, nil
  120. }
  121. // wraps SCardDisconnect
  122. func (card *Card) Disconnect(d Disposition) error {
  123. r := scardDisconnect(card.handle, d)
  124. if r != ErrSuccess {
  125. return r
  126. }
  127. return nil
  128. }
  129. // wraps SCardReconnect
  130. func (card *Card) Reconnect(mode ShareMode, proto Protocol, disp Disposition) error {
  131. activeProtocol, r := scardReconnect(card.handle, mode, proto, disp)
  132. if r != ErrSuccess {
  133. return r
  134. }
  135. card.activeProtocol = activeProtocol
  136. return nil
  137. }
  138. // wraps SCardBeginTransaction
  139. func (card *Card) BeginTransaction() error {
  140. r := scardBeginTransaction(card.handle)
  141. if r != ErrSuccess {
  142. return r
  143. }
  144. return nil
  145. }
  146. // wraps SCardEndTransaction
  147. func (card *Card) EndTransaction(disp Disposition) error {
  148. r := scardEndTransaction(card.handle, disp)
  149. if r != ErrSuccess {
  150. return r
  151. }
  152. return nil
  153. }
  154. // wraps SCardStatus
  155. func (card *Card) Status() (*CardStatus, error) {
  156. reader, state, proto, atr, err := scardCardStatus(card.handle)
  157. if err != ErrSuccess {
  158. return nil, err
  159. }
  160. return &CardStatus{Reader: reader, State: state, ActiveProtocol: proto, Atr: atr}, nil
  161. }
  162. // wraps SCardTransmit
  163. func (card *Card) Transmit(cmd []byte) ([]byte, error) {
  164. rsp := make([]byte, maxBufferSizeExtended)
  165. rspLen, err := scardTransmit(card.handle, card.activeProtocol, cmd, rsp)
  166. if err != ErrSuccess {
  167. return nil, err
  168. }
  169. return rsp[:rspLen], nil
  170. }
  171. // wraps SCardControl
  172. func (card *Card) Control(ioctl uint32, in []byte) ([]byte, error) {
  173. var out [0xffff]byte
  174. outLen, err := scardControl(card.handle, ioctl, in, out[:])
  175. if err != ErrSuccess {
  176. return nil, err
  177. }
  178. return out[:outLen], nil
  179. }
  180. // wraps SCardGetAttrib
  181. func (card *Card) GetAttrib(id Attrib) ([]byte, error) {
  182. needed, err := scardGetAttrib(card.handle, id, nil)
  183. if err != ErrSuccess {
  184. return nil, err
  185. }
  186. var attrib = make([]byte, needed)
  187. n, err := scardGetAttrib(card.handle, id, attrib)
  188. if err != ErrSuccess {
  189. return nil, err
  190. }
  191. return attrib[:n], nil
  192. }
  193. // wraps SCardSetAttrib
  194. func (card *Card) SetAttrib(id Attrib, data []byte) error {
  195. err := scardSetAttrib(card.handle, id, data)
  196. if err != ErrSuccess {
  197. return err
  198. }
  199. return nil
  200. }
  201. func durationToTimeout(timeout time.Duration) uint32 {
  202. switch {
  203. case timeout < 0:
  204. return infiniteTimeout
  205. case timeout > time.Duration(infiniteTimeout)*time.Millisecond:
  206. return infiniteTimeout - 1
  207. default:
  208. return uint32(timeout / time.Millisecond)
  209. }
  210. }
  211. func (buf strbuf) ptr() unsafe.Pointer {
  212. return unsafe.Pointer(&buf[0])
  213. }
  214. func (buf strbuf) split() []strbuf {
  215. var chunks []strbuf
  216. for len(buf) > 0 && buf[0] != 0 {
  217. i := 0
  218. for i = range buf {
  219. if buf[i] == 0 {
  220. break
  221. }
  222. }
  223. chunks = append(chunks, buf[:i+1])
  224. buf = buf[i+1:]
  225. }
  226. return chunks
  227. }
  228. func encodemstr(strings ...string) (strbuf, error) {
  229. var buf strbuf
  230. for _, s := range strings {
  231. utf16, err := encodestr(s)
  232. if err != nil {
  233. return nil, err
  234. }
  235. buf = append(buf, utf16...)
  236. }
  237. buf = append(buf, 0)
  238. return buf, nil
  239. }
  240. func decodemstr(buf strbuf) []string {
  241. var strings []string
  242. for _, chunk := range buf.split() {
  243. strings = append(strings, decodestr(chunk))
  244. }
  245. return strings
  246. }