Friday, December 19, 2014
Great OpenPGP smart card article (in French)
gouttegd published a very good article about the configuration and use of an OpenPGP smart card. The article is "“OpenPGP card“, une application cryptographique pour carte à puce" and is written in French (sorry).
OS X Yosemite bug: SCardStatus returns SCARD_E_INSUFFICIENT_BUFFER
This is part of the series: "OS X Yosemite and smart cards: known bugs".
It is a really stupid bug and very easy to fix for Apple.
Apple bug report #19306215 "PC/SC SCardStatus returns SCARD_E_INSUFFICIENT_BUFFER". Closed by Apple, 9th January 2015, as a duplicated of #18890042.
If I uncomment the line: len += 1; I get:
Note that the reader length returned by the first
Note that the length returned by the first
SCardStatus returns SCARD_E_INSUFFICIENT_BUFFER
SCardStatus() does not correctly report the reader name length. The terminating NUL character of the reader name is not counted. So a second call toSCardStatus()
using the size returned by the first SCardStatus()
call will fail with 0x80100008
(that is SCARD_E_INSUFFICIENT_BUFFER
).It is a really stupid bug and very easy to fix for Apple.
See also
"Problem with SCardStatus on MAC OS X 10.10 (Yosemite)" at https://smartcardservices.macosforge.org/trac/ticket/140.Apple bug report #19306215 "PC/SC SCardStatus returns SCARD_E_INSUFFICIENT_BUFFER". Closed by Apple, 9th January 2015, as a duplicated of #18890042.
Sample code
#include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef __APPLE__ #include <PCSC/winscard.h> #include <PCSC/wintypes.h> #else #include <winscard.h> #endif int main(int argc, const char * argv[]) { SCARDCONTEXT hContext; LPSTR mszReaders; DWORD err = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); if (err != SCARD_S_SUCCESS) { printf("ScardEstablishedContext: 0x%08x\n",err); return -1; } DWORD cchReaders = 0; err = SCardListReaders(hContext, "SCard$AllReaders", NULL, &cchReaders); if (err != 0) { printf("ScardListReaders: 0x%08x\n",err); return -1; } mszReaders = calloc(cchReaders, sizeof(char)); if (!mszReaders) { printf("calloc\n"); return -1; } err = SCardListReaders(hContext,"SCard$AllReaders", mszReaders, &cchReaders); if (err != SCARD_S_SUCCESS) { printf("ScardListReaders: 0x%08x\n",err); return -1; } printf("Reader: %s\n", mszReaders); SCARDHANDLE hCard; DWORD dwActiveProtocol; err = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); if (err != SCARD_S_SUCCESS) { printf("ScardConnect: 0x%08x\n",err); return -1; } /* 1st SCardStatus call to get the reader name length */ char name[100]; DWORD len; err = SCardStatus(hCard, NULL, &len, NULL, NULL, NULL, NULL); if (err != SCARD_S_SUCCESS) { printf("SCardStatus: 0x%08x\n",err); return -1; } printf("reader name length: %d\n", len); //len += 1; /* 2nd SCardStatus call to get the reader name value */ err = SCardStatus(hCard, name, &len, NULL, NULL, NULL, NULL); if (err != SCARD_S_SUCCESS) { printf("SCardStatus: 0x%08x\n",err); return -1; } printf("Reader name: %s (%ld)\n", name, strlen(name)); SCardDisconnect(hCard, SCARD_LEAVE_CARD); SCardReleaseContext(hContext); return 0; }
Result (on Yosemite)
$ CFLAGS="-framework PCSC" make main cc -framework PCSC main.c -o main
$ ./main Reader: Gemalto PC Twin Reader reader name length: 22 SCardStatus: 0x80100008
If I uncomment the line: len += 1; I get:
$ ./main Reader: Gemalto PC Twin Reader reader name length: 22 Reader name: Gemalto PC Twin Reader (22)
Note that the reader length returned by the first
SCardStatus()
call is identical to the value returned by strlen(name)
. And strlen()
does NOT includes the terminating NUL character.Expected result (on Debian)
$ CFLAGS=`pkg-config --cflags libpcsclite` LDFLAGS=`pkg-config --libs libpcsclite` make main cc -pthread -I/usr/include/PCSC -lpcsclite main.c -o main
$ ./main Reader: Gemalto PC Twin Reader 00 00 reader length: 29 Reader name: Gemalto PC Twin Reader 00 00 (28)
Note that the length returned by the first
SCardStatus()
call is strlen(name) + 1
.Known workaround
Add 1 to the reader length returned bySCardStatus()
.Update
This bug is now fixed in Mac OS X Yosemite 10.10.2.Tuesday, December 16, 2014
OS X Yosemite bug: SCardStatus() after a card reset
This is part of the series: "OS X Yosemite and smart cards: known bugs".
If a card has been reseted using another PC/SC context then
The problem will be detected later by, for example, the next
The problem is similar to the one described in OS X Yosemite bug: SCardBeginTransaction() after a card reset.
What is strange is that
#19264087 closed as a duplicate of #18689292.
An error 0x80100068 (for SCARD_W_RESET_CARD) is expected here.
Modify your code to check for
SCardStatus() after a card reset
SCardStatus() does not corectly detect card reset any more on OS X 10.10 Yosemite.If a card has been reseted using another PC/SC context then
SCardStatus()
will not fail with 0x80100068
(for SCARD_W_RESET_CARD
) as before but will succeed instead.The problem will be detected later by, for example, the next
SCardTransmit()
returning SCARD_W_RESET_CARD
.The problem is similar to the one described in OS X Yosemite bug: SCardBeginTransaction() after a card reset.
What is strange is that
SCardTransmit()
erroneously returns SCARD_W_RESET_CARD
after a SCardReconnect(..., SCARD_RESET_CARD, ...)
(see OS X Yosemite bug: SCardReconnect) but SCardStatus()
do not return SCARD_W_RESET_CARD
in the same case. The card reset (or not) state is managed in a "funny" way inside PC/SC on Yosemite.See also
Apple bug report #19264087 "PC/SC function SCardStatus() fails to fail after a card reset"#19264087 closed as a duplicate of #18689292.
Sample code
#include <stdio.h> #include <stdlib.h> #ifdef __APPLE__ #include <PCSC/winscard.h> #include <PCSC/wintypes.h> #else #include <winscard.h> #endif int main(int argc, const char * argv[]) { SCARDCONTEXT hContext; LPSTR mszReaders; DWORD err = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); if (err != SCARD_S_SUCCESS) { printf("ScardEstablishedContext: 0x%08x\n",err); return -1; } DWORD cchReaders = 0; err = SCardListReaders(hContext, "SCard$AllReaders", NULL, &cchReaders); if (err != 0) { printf("ScardListReaders: 0x%08x\n",err); return -1; } mszReaders = calloc(cchReaders, sizeof(char)); if (!mszReaders) { printf("calloc\n"); return -1; } err = SCardListReaders(hContext,"SCard$AllReaders", mszReaders, &cchReaders); if (err != SCARD_S_SUCCESS) { printf("ScardListReaders: 0x%08x\n",err); return -1; } printf("Reader: %s\n", mszReaders); SCARDHANDLE hCard; DWORD dwActiveProtocol; err = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); if (err != SCARD_S_SUCCESS) { printf("ScardConnect: 0x%08x\n",err); return -1; } /* create a second PC/SC handle and reset the card */ SCARDHANDLE hCard2; err = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard2, &dwActiveProtocol); if (err != SCARD_S_SUCCESS) { printf("ScardConnect: 0x%08x\n",err); return -1; } err = SCardDisconnect(hCard2, SCARD_RESET_CARD); if (err != SCARD_S_SUCCESS) { printf("SCardDisconnect: 0x%08x\n",err); } /* SCardStatus should fail with SCARD_W_RESET_CARD */ char name[100]; DWORD len = sizeof name; DWORD dwState, dwProtocol; unsigned char atr[MAX_ATR_SIZE]; DWORD atr_len = sizeof atr; err = SCardStatus(hCard, name, &len, &dwState, &dwProtocol, atr, &atr_len); if (err != SCARD_S_SUCCESS) { printf("SCardStatus: 0x%08x\n",err); return -1; } SCardDisconnect(hCard, SCARD_LEAVE_CARD); SCardReleaseContext(hContext); return 0; }
Result (on Yosemite)
$ CFLAGS="-framework PCSC" make main cc -framework PCSC main.c -o main
An error 0x80100068 (for SCARD_W_RESET_CARD) is expected here.
$ ./main Reader: Gemalto PC Twin Reader
Expected result (on Debian)
$ CFLAGS=`pkg-config --cflags libpcsclite` LDFLAGS=`pkg-config --libs libpcsclite` make main cc -pthread -I/usr/include/PCSC -lpcsclite main.c -o main
$ ./main Reader: Gemalto PC Twin Reader 00 00 SCardStatus: 0x80100068
Known workaround
None known.Modify your code to check for
SCARD_W_RESET_CARD
returned by SCardTransmit()
even after a successful SCardStatus()
.Update
This bug is now fixed in Mac OS X Yosemite 10.10.2.OS X Yosemite bug: SCardBeginTransaction() after a card reset
This is part of the series: "OS X Yosemite and smart cards: known bugs".
If a card has been reseted using another PC/SC context then SCardBeginTransaction() will not fail with 0x80100068 (for SCARD_W_RESET_CARD) as before but will succeed instead.
The problem will be detected later by, for example, the next SCardTransmit() returning SCARD_W_RESET_CARD.
The goal of a PC/SC transaction was to guarantee that you have an exclusive and successful access to the card. This mechanism is broken on Yosemite.
#19263926 closed as a duplicate of #18689292.
An error 0x80100068 (for SCARD_W_RESET_CARD) is expected here.
Modify your code to check for SCARD_W_RESET_CARD returned by SCardTransmit() even inside a PC/SC transaction.
SCardBeginTransaction() after a card reset
SCardBeginTransaction() does not corectly detect card reset any more on OS X 10.10 Yosemite.If a card has been reseted using another PC/SC context then SCardBeginTransaction() will not fail with 0x80100068 (for SCARD_W_RESET_CARD) as before but will succeed instead.
The problem will be detected later by, for example, the next SCardTransmit() returning SCARD_W_RESET_CARD.
The goal of a PC/SC transaction was to guarantee that you have an exclusive and successful access to the card. This mechanism is broken on Yosemite.
See also
Apple bug report #19263926 "PC/SC SCardBeginTransaction() fails after a card reset"#19263926 closed as a duplicate of #18689292.
Sample code
#include <stdio.h> #include <stdlib.h> #ifdef __APPLE__ #include <PCSC/winscard.h> #include <PCSC/wintypes.h> #else #include <winscard.h> #endif int main(int argc, const char * argv[]) { SCARDCONTEXT hContext; LPSTR mszReaders; DWORD err = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); if (err != SCARD_S_SUCCESS) { printf("ScardEstablishedContext: 0x%08x\n",err); return -1; } DWORD cchReaders = 0; err = SCardListReaders(hContext, "SCard$AllReaders", NULL, &cchReaders); if (err != 0) { printf("ScardListReaders: 0x%08x\n",err); return -1; } mszReaders = calloc(cchReaders, sizeof(char)); if (!mszReaders) { printf("calloc\n"); return -1; } err = SCardListReaders(hContext,"SCard$AllReaders", mszReaders, &cchReaders); if (err != SCARD_S_SUCCESS) { printf("ScardListReaders: 0x%08x\n",err); return -1; } printf("Reader: %s\n", mszReaders); SCARDHANDLE hCard; DWORD dwActiveProtocol; err = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); if (err != SCARD_S_SUCCESS) { printf("ScardConnect: 0x%08x\n",err); return -1; } /* create a second PC/SC handle and reset the card */ SCARDHANDLE hCard2; err = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard2, &dwActiveProtocol); if (err != SCARD_S_SUCCESS) { printf("ScardConnect: 0x%08x\n",err); return -1; } err = SCardDisconnect(hCard2, SCARD_RESET_CARD); if (err != SCARD_S_SUCCESS) { printf("SCardReconnect: 0x%08x\n",err); } /* SCardBeginTransaction should fail with SCARD_W_RESET_CARD */ err = SCardBeginTransaction(hCard); if (err != SCARD_S_SUCCESS) { printf("SCardBeginTransaction: 0x%08x\n",err); return -1; } SCardDisconnect(hCard, SCARD_LEAVE_CARD); SCardReleaseContext(hContext); return 0; }
Result (on Yosemite)
$ CFLAGS="-framework PCSC" make main cc -framework PCSC main.c -o main
An error 0x80100068 (for SCARD_W_RESET_CARD) is expected here.
$ ./main Reader: Gemalto PC Twin Reader
Expected result (on Debian)
$ CFLAGS=`pkg-config --cflags libpcsclite` LDFLAGS=`pkg-config --libs libpcsclite` make main cc -pthread -I/usr/include/PCSC -lpcsclite main.c -o main
$ ./main Reader: Gemalto PC Twin Reader 00 00 SCardBeginTransaction: 0x80100068
Known workaround
None known.Modify your code to check for SCARD_W_RESET_CARD returned by SCardTransmit() even inside a PC/SC transaction.
Update
This bug is now fixed in Mac OS X Yosemite 10.10.2.OS X Yosemite bug: SCardReconnect
This is part of the series: "OS X Yosemite and smart cards: known bugs".
After a
This should not happen since
Apple bug report #19262854 "PC/SC function SCardReconnect does not work as expected". Closed by Apple, 6th January 2015, as a duplicated of #18689292.
No error expected:
Or you can replace the bogus SCardReconnect() by the sequence:
I could not find an elegant way to write a macro to automate the code change. The problem is that
SCardReconnect
SCardReconnect() has a bad side effect on Yosemite.After a
SCardReconnect(..., SCARD_RESET_CARD, ...)
the next SCardTransmit() will fail with the error code 0x80100068
that is SCARD_W_RESET_CARD
.This should not happen since
SCardReconnect()
should reconnect (sic) to the card after the card has been reseted.See also
"[OSX 10.10] After connect and SCardReconnect, SCardTransmit raises card reset" https://smartcardservices.macosforge.org/trac/ticket/136Apple bug report #19262854 "PC/SC function SCardReconnect does not work as expected". Closed by Apple, 6th January 2015, as a duplicated of #18689292.
Sample code
#include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef __APPLE__ #include <PCSC/winscard.h> #include <PCSC/wintypes.h> #else #include <winscard.h> #endif int main(int argc, const char * argv[]) { SCARDCONTEXT hContext; LPSTR mszReaders; DWORD err = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); if (err != SCARD_S_SUCCESS) { printf("ScardEstablishedContext: 0x%08x\n",err); return -1; } DWORD cchReaders = 0; err = SCardListReaders(hContext, "SCard$AllReaders", NULL, &cchReaders); if (err != 0) { printf("ScardListReaders: 0x%08x\n",err); return -1; } mszReaders = calloc(cchReaders, sizeof(char)); if (!mszReaders) { printf("calloc\n"); return -1; } err = SCardListReaders(hContext,"SCard$AllReaders", mszReaders, &cchReaders); if (err != SCARD_S_SUCCESS) { printf("ScardListReaders: 0x%08x\n",err); return -1; } printf("Reader: %s\n", mszReaders); SCARDHANDLE hCard; DWORD dwActiveProtocol; err = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); if (err != SCARD_S_SUCCESS) { printf("ScardConnect: 0x%08x\n",err); return -1; } unsigned char cmd[] = {0, 0, 0, 0}; unsigned char resp[255]; DWORD resp_len = sizeof resp; SCARD_IO_REQUEST * pci; err = SCardReconnect(hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_RESET_CARD, &dwActiveProtocol); if (err != SCARD_S_SUCCESS) { printf("SCardReconnect: 0x%08x\n",err); } if (SCARD_PROTOCOL_T0 == dwActiveProtocol) pci = SCARD_PCI_T0; else pci = SCARD_PCI_T1; err = SCardTransmit(hCard, pci, cmd, sizeof cmd, pci, resp, &resp_len); if (err != SCARD_S_SUCCESS) { printf("SCardTransmit: 0x%08x\n",err); } SCardDisconnect(hCard, SCARD_LEAVE_CARD); SCardReleaseContext(hContext); return 0; }
Result (on Yosemite)
$ CFLAGS="-framework PCSC" make main cc -framework PCSC main.c -o main
$ ./main Reader: Gemalto PC Twin Reader SCardTransmit: 0x80100068
Expected result (on Debian)
$ CFLAGS=`pkg-config --cflags libpcsclite` LDFLAGS=`pkg-config --libs libpcsclite` make main cc -pthread -I/usr/include/PCSC -lpcsclite main.c -o main main.c: In function ‘main’: main.c:57:7: warning: assignment discards ‘const’ qualifier from pointer target type [enabled by default] main.c:59:7: warning: assignment discards ‘const’ qualifier from pointer target type [enabled by default]
No error expected:
$ ./main Reader: Gemalto PC Twin Reader 00 00
Known workaround
You can add an second call toSCardReconnect(..., SCARD_LEAVE_CARD, ...)
after the first one to force a card reconnection.Or you can replace the bogus SCardReconnect() by the sequence:
SCardDisconnect(..., SCARD_RESET_CARD); SCardConnect(...);
I could not find an elegant way to write a macro to automate the code change. The problem is that
SCardConnect()
needs parameters (PC/SC context and reader name) that are not available from the SCardReconnect()
call.Update
This bug is now fixed in Mac OS X Yosemite 10.10.2.Monday, December 15, 2014
Feitian bR301 driver for iOS now Free Software
Bluetooth reader
Feitian sells the bR301 smart card reader. This reader uses Blutooth to communicate with a host. The idea is to be able to "connect" the reader to a smart phone (iOS and Android).The reader can also be connected using a USB cable. In that case the reader is a normal CCID reader and is already listed by my CCID driver in the "Should work but untested by me" list.
Software Development Kit (SDK)
The SDK (containing the reader drivers) is not directly available from Feitian web site. But you can get it from a reseller web site at http://cartesapuce-discount.com/en/smart-card-reader-usb/74-lecteur-de-cartes-a-puce-usb-cardman-3121.html. The SDK URL is http://download.ftsafe.com/files/reade/bR301_UB_V2.19_20141008.zip.After I had a look inside the SDK I discovered that the iOS driver bR301_UB_V2.19_20141008/SDK/iOS/Library/NON-PCSC API/lib/libiRockey301_ccid_debug_NPCSC_V1.29.0.a is in fact a derivated work from my CCID driver.
It is perfectly fine to modify my CCID driver and provide a derivated work. The only condition is to respect the GNU LGPL v2.1+ license used by my CCID driver. This was not the case with the Feitian driver.
Free Software version
After some email exchanges with Feitian to explain the situation they decided to release their iOS driver under the same license as my CCID driver: the GNU LGPL v2.1+ license. The Feitian iOS driver is hosted at github: https://github.com/entersafe/bR301_iOS.Conclusion
I am happy the issue ended that way.- The license of my CCID driver is respected by this Feitian driver
- One more Free Software smart card reader driver is available for users
Saturday, December 13, 2014
PySCard 1.6.16 released
As explained in "PySCard: unofficial version 1.6.16 available" the PySCard software was no more actively maintained. After discussing with Jean-Daniel Aussel, previous maintainer, I got the admin rights to manage the sourceforge project. I was already an active code contributor since 2007.
Changes:
1.6.16 (December 2014)
The API documentation is still using epydoc. Maybe I will switch it to Sphinx if I find the time and motivation. Help appreciated.
I also provide a binary installer pyscard-1.6.16.macosx-10.9-x86_64.tar.gz for Mac OS X 10.9 and Python 2.7.
I do not use Windows so no installer is provided for this platform. Help appreciated.
Debian packages and Ubuntu packages are already provided in Debian and Ubuntu. The other GNU distribution should also provide packages but I have not checked.
Release 1.6.16
I just released a new official pyscard version 1.6.16.Changes:
1.6.16 (December 2014)
- added support for windows 64bit amd64 (Jean-Daniel Aussel)
- support python "new" classes (derive classes from object) (Ludovic Rousseau from chrysn feature request ID 3110077)
- fixed Reader.__eq__() (Ludovic Rousseau from Bernard Paulus bug ID 3418113)
- fixed extended APDU transmit buffer too short by 2 (Jean-Daniel Aussel from bugs ID 2914636 and 3106761)
- make Card and Reader objects hashable (Jean-Daniel Aussel from Hans-Peter Jansen feature request and patch)
- convert the user guide to python-Sphinx
Documentation in Sphinx
I also changed the project web pages to use Sphinx (Python document generator) and generate a nice and modern user's guide from ReStructured text instead of manually edited HTML pages.The API documentation is still using epydoc. Maybe I will switch it to Sphinx if I find the time and motivation. Help appreciated.
Provided software
The source code archive pyscard-1.6.16.tar.gz is of course provided.I also provide a binary installer pyscard-1.6.16.macosx-10.9-x86_64.tar.gz for Mac OS X 10.9 and Python 2.7.
I do not use Windows so no installer is provided for this platform. Help appreciated.
Debian packages and Ubuntu packages are already provided in Debian and Ubuntu. The other GNU distribution should also provide packages but I have not checked.
Friday, December 12, 2014
OS X Yosemite bug: SCardTransmit (pioSendPci not checked)
This is part of the series: "OS X Yosemite and smart cards: known bugs".
If you use NULL for
SCardTransmit
SCardTransmit() fails to detect wrong value forpioSendPci
parameter.If you use NULL for
pioSendPci
parameter then you get a crash (Segmentation fault: 11) of the application instead of getting the error 0x80100004
that is SCARD_E_INVALID_PARAMETER
.See also
Apple bug report #19231406 "PC/SC function SCardTransmit: pioSendPci not checked".Sample code
#include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef __APPLE__ #include <PCSC/winscard.h> #include <PCSC/wintypes.h> #else #include <winscard.h> #endif int main(int argc, const char * argv[]) { SCARDCONTEXT hContext; LPSTR mszReaders; DWORD err = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); if (err != SCARD_S_SUCCESS) { printf("ScardEstablishedContext : %08x\n",err); return -1; } DWORD cchReaders = 0; err = SCardListReaders(hContext, "SCard$AllReaders", NULL, &cchReaders); if (err != 0) { printf("ScardListReaders : %08x\n",err); return -1; } mszReaders = calloc(cchReaders, sizeof(char)); if (!mszReaders) { printf("calloc\n"); return -1; } err = SCardListReaders(hContext,"SCard$AllReaders", mszReaders, &cchReaders); if (err != SCARD_S_SUCCESS) { printf("ScardListReaders : %08x\n",err); return -1; } printf("Reader : %s\n", mszReaders); SCARDHANDLE hCard; DWORD dwActiveProtocol; err = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); unsigned char cmd[] = {0, 0, 0, 0, 0}; unsigned char resp[255]; DWORD resp_len = sizeof resp; err = SCardTransmit(hCard, NULL, cmd, sizeof cmd, NULL, resp, &resp_len); if (err != SCARD_S_SUCCESS) { printf("ScardTransmit : %08x\n",err); return -1; } SCardDisconnect(hCard, SCARD_LEAVE_CARD); SCardReleaseContext(hContext); return 0; }
Result (on Yosemite)
$ CFLAGS="-framework PCSC" make main cc -framework PCSC main.c -o main
$ ./main Reader : Gemalto PC Twin Reader Segmentation fault: 11
$ lldb ./main (lldb) target create "./main" Current executable set to './main' (x86_64). (lldb) r Process 6169 launched: './main' (x86_64) Reader : Gemalto PC Twin Reader Process 6169 stopped * thread #1: tid = 0x7472a, 0x0000000100004b6d PCSC`__SCardTransmit_block_invoke + 17, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0) frame #0: 0x0000000100004b6d PCSC`__SCardTransmit_block_invoke + 17 PCSC`__SCardTransmit_block_invoke + 17: -> 0x100004b6d: movl (%rax), %edx 0x100004b6f: leaq 0x6901(%rip), %rsi ; "proto" 0x100004b76: movq %r14, %rdi 0x100004b79: callq 0x10000b0c2 ; symbol stub for: xpc_dictionary_set_uint64
Expected result (on Debian)
CFLAGS=`pkg-config --cflags libpcsclite` LDFLAGS=`pkg-config --libs libpcsclite` make main
$ ./main Reader : Gemalto PC Twin Reader (70D7E2EE) 00 00 ScardTransmit : 80100004
Known workaround
Do not use NULL for pioSendPci. It is a wrong value.Update
This bug is now fixed in Mac OS X El Capitan 10.11.0.OS X Yosemite bug: SCardGetAttrib
This is part of the series: "OS X Yosemite and smart cards: known bugs".
The function returns with
Apple bug report #19231112 "PC/SC function SCardGetAttrib is broken on Yosemite".
#19231112 closed as duplicate of #16366962.
SCardGetAttrib
SCardGetAttrib() do not work any more on Yosemite.The function returns with
8010000c
that is SCARD_F_INTERNAL_ERROR
.See also
"Problem With SCardGetAttrib on Mac OS X 10.10 (Yosemite)" at https://smartcardservices.macosforge.org/trac/ticket/139.Apple bug report #19231112 "PC/SC function SCardGetAttrib is broken on Yosemite".
#19231112 closed as duplicate of #16366962.
Sample code
#include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef __APPLE__ #include <PCSC/winscard.h> #include <PCSC/wintypes.h> #else #include <winscard.h> #endif #define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag))) #define SCARD_CLASS_ICC_STATE 9 /**< ICC State specific definitions */ #define SCARD_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303) /**< Answer to reset (ATR) string. */ int main(int argc, const char * argv[]) { SCARDCONTEXT hContext; LPSTR mszReaders; DWORD err = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); if (err != SCARD_S_SUCCESS) { printf("ScardEstablishedContext : %08x\n",err); } else { DWORD cchReaders = 0; err = SCardListReaders(hContext, "SCard$AllReaders", NULL, &cchReaders); if (err != 0) { printf("ScardListReaders : %08x\n",err); return -1; } mszReaders = calloc(cchReaders, sizeof(char)); if (!mszReaders) { printf("calloc\n"); return -1; } err = SCardListReaders(hContext,"SCard$AllReaders", mszReaders, &cchReaders); if (err != SCARD_S_SUCCESS) { printf("ScardListReaders : %08x\n",err); return -1; } printf("Reader : %s\n", mszReaders); SCARDHANDLE hCard; DWORD dwActiveProtocol; err = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_RAW, &hCard, &dwActiveProtocol); if (err != SCARD_S_SUCCESS) { printf("ScardConnect : %08x\n",err); } else { DWORD dwAtrLen = 32; err = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &dwAtrLen); printf("ATR LENGTH : %1d\n", dwAtrLen); if (err != SCARD_S_SUCCESS) { printf("SCardGetAttrib : %08x\n",err); } else { printf("ATR LENGTH %d\n", dwAtrLen); SCardDisconnect(hCard, SCARD_LEAVE_CARD); SCardReleaseContext(hContext); } } } return 0; }
Result (on Yosemite)
$ CFLAGS="-framework PCSC" make main cc -framework PCSC main.c -o main
$ ./main Reader : Gemalto PC Twin Reader ATR LENGTH : 32 SCardGetAttrib : 80100001
Expected result (on Debian)
$ CFLAGS=`pkg-config --cflags libpcsclite` LDFLAGS=`pkg-config --libs libpcsclite` make main cc -pthread -I/usr/include/PCSC -lpcsclite main.c -o main
$ ./main Reader : Gemalto PC Twin Reader (70D7E2EE) 00 00 ATR LENGTH : 20 ATR LENGTH 20
Known workaround
None known.Update
This bug is now fixed in Mac OS X El Capitan 10.11.0.OS X Yosemite and smart cards: known bugs
Yosemite: OS X 10.10
Yosemite contains a rewrite of pcsc-lite. See "OS X Yosemite and smart cards status". The problem is that the rewrite introduced (many) bugs.Bug list
I will list known (by me) bugs and will try to maintain the list in the future if/when the bugs are fixed.- SCardDisconnect
Fixed in OS X 10.10.2
- SCardReconnect(..., SCARD_RESET_CARD, ...)
- SCardBeginTransaction() after a card reset
- SCardStatus() after a card reset
- SCardStatus returns SCARD_E_INSUFFICIENT_BUFFER
- SCARD_E_PROTO_MISMATCH not returned
- T=0 is used instead of T=1 on dual protocol cards
Fixed in OS X 10.10.3
Fixed in El Capitan 10.11.0
- SCardGetAttrib
- SCardTransmit (pioSendPci not checked)
- SCardGetStatusChange blocks forever
- OS X Yosemite bug: SCardConnect blocks in SCARD_SHARE_SHARED mode
Bugs that will not be fixed
Conclusion
I hope the bugs will be fixed during Yosemite lifetime. But I am afraid it will not happen before the next major version of OS X (OS X 10.11) is out.This reminds me when Mac OS X 10.5 Leopard has been released in 2007 with lots of important bugs like ATR corruption. At that time it was also a major deviation from pcsc-lite. See "Evolution of Apple pcsc-lite (from Jaguar to Mavericks)".
Friday, December 5, 2014
PCSC sample in Python using python-pcsclite
Here is a new PCSC sample in Python language for the series PC/SC sample in different languages.
I already presented, pyscard, a Python wrapper in "PCSC sample in Python". This wrapper is a different implementation and API.
Or you can rebuild the software from the source code. The current version is 0.13.
The web site is http://python-pcsclite.sourceforge.net/. The license is GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
python-pcsclite may provide good ideas that I could reuse in pyscard :-)
As for pyscard, Python3 is not yet supported.
According to the python-pcsclite web site:
I already presented, pyscard, a Python wrapper in "PCSC sample in Python". This wrapper is a different implementation and API.
Installation
The installation is easy on a Debian system. A.deb
package is provided (but the project is not part of Debian).Or you can rebuild the software from the source code. The current version is 0.13.
The web site is http://python-pcsclite.sourceforge.net/. The license is GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Source code
#!/usr/bin/env python import pcsclite import binascii SELECT = "\x00\xA4\x04\x00\x0A\xA0\x00\x00\x00\x62\x03\x01\x0C\x06\x01" COMMAND = "\x00\x00\x00\x00" try: context = pcsclite.Context() readers = context.list_readers() print "PCSC readers:", readers reader = readers[0] print "Using reader:", reader card = context.connect(reader) data = card.transmit(SELECT) print binascii.b2a_hex(data) data = card.transmit(COMMAND) print data print binascii.b2a_hex(data) card.disconnect() del card del context except Exception, message: print "Exception:", message
Output
$ ./sample_pcsclite.py PCSC readers: ('Gemalto PC Twin Reader 00 00',) Using reader: Gemalto PC Twin Reader 00 00 9000 Hello world!? 48656c6c6f20776f726c64219000
Comments
The python-pcsclite project started in 2007 according to the ChangeLog.txt file. I discovered the project only very recently and open some bugs to make it build on my Debian system. Russell Stuart, the maintainer, was very fast to fix the issues.Compared to pyscard
python-pcsclite does not build on Mac OS X (see bug #5). I guess it also does not build on Windows but I have not tested it myself. So if you want a Python wrapper for GNU/Linux, Mac OS X and Windows you should use pyscard instead.python-pcsclite may provide good ideas that I could reuse in pyscard :-)
As for pyscard, Python3 is not yet supported.
History
The python-pcsclite project started in 2007. At the same time the pyscard project is made public (according to the dates in the subversion repository but I guess the pyscard project was already developed since some time).According to the python-pcsclite web site:
The obvious question is why use python-pcsclite instead of the official one. Python-pcsclite is a fairly direct implementation of C API provided by pcsclite, so direct the documentation for pcsclite applies to python-pcsclite. Pyscard on the other hand builds on pcsclite to provide it's own abstractions. I suspect the choice is more a matter of taste, and being an old C programmer I prefer the directness of the C API, which python-pcsclite emulates.You have the freedom to select the wrapper you want to use. Compare the sample code above with the 2 examples at my previous article PCSC sample in Python to select the implementation you prefer.