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.
ConversionConversion EmoticonEmoticon