OS X El Capitan bug: SCardBeginTransaction() returns different error codes than on GNU/Linux and Windows
This is part of the series: "OS X El Capitan and smart cards: known bugs".
SCardBeginTransaction() returns different error codes than on GNU/Linux and Windows
I found 2 cases in which SCardBeginTransaction() on El Capitan returns error codes that are different than on GNU/Linux and Windows.SCardBeginTransaction() returns SCARD_W_RESET_CARD after a card change
On El CapitanSCardBeginTransaction()
returns SCARD_W_RESET_CARD
if the card has been removed and inserted again in the reader.On GNU/Linux and Windows
SCardBeginTransaction()
returns SCARD_W_REMOVED_CARD
instead.SCardBeginTransaction() returns SCARD_W_UNPOWERED_CARD after a card is unpowered
The same functionSCardBeginTransaction()
returns SCARD_W_UNPOWERED_CARD
on Mac OS X El Capitan if the card has been powered off by another application.On GNU/Linux and Windows
SCardBeginTransaction()
returns SCARD_W_RESET_CARD
instead.See also
Apple bug report #23900844 "PC/SC SCardBeginTransaction() returns different error codes than on GNU/Linux and Windows"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 pcsc_error(fct) printf(fct ": %s 0x%08lX\n", pcsc_stringify_error(err), (long)err) int main(void) { LPSTR mszReaders; DWORD err, cchReaders = 0; SCARDCONTEXT hContext = 0; SCARDHANDLE hCard = 0; err = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); if (err != SCARD_S_SUCCESS) { pcsc_error("ScardEstablishedContext"); return -1; } err = SCardListReaders(hContext, NULL, NULL, &cchReaders); if (err != 0) { pcsc_error("ScardListReaders"); return -1; } mszReaders = calloc(cchReaders, sizeof(char)); if (!mszReaders) { printf("calloc\n"); return -1; } err = SCardListReaders(hContext,NULL, mszReaders, &cchReaders); if (err != SCARD_S_SUCCESS) { pcsc_error("ScardListReaders"); return -1; } printf("Using reader: %s\n", mszReaders); DWORD dwActiveProtocol; err = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); if (err != SCARD_S_SUCCESS) { pcsc_error("SCardConnect"); return 0; } printf("Remove and insert the card. Then press enter\n"); getchar(); err = SCardBeginTransaction(hCard); if (err != SCARD_S_SUCCESS) pcsc_error("SCardBeginTransaction"); err = SCardDisconnect(hCard, SCARD_LEAVE_CARD); if (err != SCARD_S_SUCCESS) pcsc_error("SCardDisconnect"); SCardReleaseContext(hContext); return 0; }
Reset program
Using the Python PC/SC wrapper PySCard to have a shorter code.#! /usr/bin/env python from smartcard.System import readers from smartcard.scard import SCARD_UNPOWER_CARD, SCARD_RESET_CARD reader = readers()[0] print "Using:", reader connection = reader.createConnection() #connection.connect(disposition=SCARD_RESET_CARD) connection.connect(disposition=SCARD_UNPOWER_CARD)
If you modify the reset program to use
disposition=SCARD_RESET_CARD
then SCardBeginTransaction()
will return SCARD_W_RESET_CARD
as is also the case on GNU/Linux and Windows.Result (on El Capitan)
$ CFLAGS="-framework PCSC" make main cc -framework PCSC main.c -o main
$ ./main Using reader: Gemalto PC Twin Reader Remove and insert the card. Then press enter SCardBeginTransaction: Card was reset. 0x80100068
In case of unpower (instead of card removal) by a second application:
$ ./main Using reader: Gemalto PC Twin Reader Remove and insert the card. Then press enter SCardBeginTransaction: Card is unpowered. 0x80100067
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 Using reader: Gemalto PC Twin Reader 00 00 Remove and insert the card. Then press enter SCardBeginTransaction: Card was removed. 0x80100069
In case of unpower:
$ ./main Using reader: Gemalto PC Twin Reader 00 00 Remove and insert the card. Then press enter SCardBeginTransaction: Card was reset. 0x80100068
Known workaround
None known.I have not checked the same code on Mavericks (OS X 10.9) to see if it is a regression or not.
I guess the behaviour changed in Yosemite with the rewrite of PC/SC (see OS X Yosemite and smart cards status)