LudovicRousseau / pyscard

pyscard smartcard library for python
http://pyscard.sourceforge.net/
GNU Lesser General Public License v2.1
383 stars 110 forks source link

SCardConnect() for Direct Control returns error. #57

Closed yika1999 closed 6 years ago

yika1999 commented 6 years ago

I checked the below code in Windows 7 x64, but it failed in Mac. I've got the error

hret, hcard, dwActiveProtocol = SCardConnect( hcontext, readers[0], SCARD_SHARE_DIRECT, 0)

If I changed '0' to T0 or T1, it works but it was not what I want.

Here's the full code.

#! /usr/bin/env python

from smartcard.scard import *
from smartcard.util import *

CMD = [0xFF, 0x00, 0x48, 0x00, 0x00]
IOCTL_CCID_ESCAPE = SCARD_CTL_CODE(3500)
finalFlag = 0

print("\n===== To set PC/SC Reader (ACR122U) to Direct Mode =====\n")

hret, hcontext = SCardEstablishContext(SCARD_SCOPE_SYSTEM)
if hret != SCARD_S_SUCCESS:
    raise error 

hret, readers = SCardListReaders(hcontext, [])
if hret != SCARD_S_SUCCESS:
    raise error( 'Failed to list readers: ' + SCardGetErrorMessage(hret))
if len(readers) < 1:
    raise Exception('No smart card readers')
print('PCSC Readers:', readers, "\n")

hret, hcard, dwActiveProtocol = SCardConnect( hcontext, readers[0], SCARD_SHARE_DIRECT, 0)

if hret != SCARD_S_SUCCESS:
    raise error

hret, response = SCardControl(hcard, IOCTL_CCID_ESCAPE, CMD)
print("----- Trying to set to direct mode -----")
print("> " , toHexString(CMD, HEX))
print("< " , toHexString(response, HEX))
if hret != SCARD_S_SUCCESS:
    raise error
if hret == SCARD_S_SUCCESS:
    finalFlag = 1

hret = SCardDisconnect(hcard, SCARD_UNPOWER_CARD)
if hret != SCARD_S_SUCCESS:
    raise error

hret = SCardReleaseContext (hcontext)
if hret != SCARD_S_SUCCESS:
    raise error
LudovicRousseau commented 6 years ago

You can't use 0 for dwPreferredProtocols. See the SCardConnect() documentation https://pyscard.sourceforge.io/epydoc/smartcard.scard.scard-module.html#SCardConnect

Value of dwPreferredProtocols   Meaning
SCARD_PROTOCOL_T0               Use the T=0 protocol
SCARD_PROTOCOL_T1               Use the T=1 protocol
SCARD_PROTOCOL_RAW              Use with memory type cards
LudovicRousseau commented 6 years ago

Maybe SCARD_PROTOCOL_RAW is your best option.

LudovicRousseau commented 6 years ago

Another option is to open a bugreport at Apple. https://bugreport.apple.com/

0 is a valid value for pcsc-lite on GNU/Linux. See http://pcsclite.alioth.debian.org/api/group__API.html#ga4e515829752e0a8dbc4d630696a8d6a5

yika1999 commented 6 years ago

Surely I've seen that '0' is a valid value on Windows as well. But there is no SCARD_PROTOCOL_RAW which is 255. Can I know why there is the difference?

https://msdn.microsoft.com/en-us/library/windows/desktop/aa379473(v=vs.85).aspx 0 : This parameter may be zero only if dwShareMode is set to SCARD_SHARE_DIRECT. In this case, no protocol negotiation will be performed by the drivers until an IOCTL_SMARTCARD_SET_PROTOCOL control directive is sent with SCardControl.

LudovicRousseau commented 6 years ago

SCARD_PROTOCOL_RAW is not really used in pcsc-lite in fact. Your problem is a bug/missing feature in the PC/SC provided by Apple.