Important!

Blog moved to https://blog.apdu.fr/

I moved my blog from https://ludovicrousseau.blogspot.com/ to https://blog.apdu.fr/ . Why? I wanted to move away from Blogger (owne...

Friday, September 21, 2018

macOS HighSierra bug: SCardStatus() returns SCARD_W_RESET_CARD instead of SCARD_W_REMOVED_CARD

This is part of the series: "macOS High Sierra and smart cards: known bugs"

SCardStatus() returns different error codes than on GNU/Linux and Windows

SCardStatus() on High Sierra returns error codes that are different than on GNU/Linux and Windows.

SCardStatus() returns SCARD_W_RESET_CARD after a card change

On High Sierra SCardStatus() returns SCARD_W_RESET_CARD if the card has been removed and inserted again in the reader.

On GNU/Linux and Windows SCardStatus() returns SCARD_W_REMOVED_CARD instead.

See also

Apple bug report #44672224 "PC/SC SCardStatus() returns SCARD_W_RESET_CARD instead of SCARD_W_REMOVED_CARD". Marked as duplicate of #23900844.

This bug is very similar to previous bugs about SCardTransmit() ("macOS HighSierra bug: SCardTransmit() returns different error codes than on GNU/Linux and Windows") and SCardBeginTransaction() ("OS X El Capitan bug: SCardBeginTransaction() returns different error codes than on GNU/Linux and Windows").

Sample code

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#ifdef __APPLE__
#include <PCSC/winscard.h>
#include <PCSC/wintypes.h>
#else
#include <winscard.h>
#endif

#define CHECK_RV(fct) if (SCARD_S_SUCCESS != rv) { printf(fct"() failed: %s (0x%08X)\n", pcsc_stringify_error(rv), rv); ret = 0; goto error; } else { printf(fct"(): OK\n"); }

int main(void)
{
    int ret = 1;
    SCARDCONTEXT hContext;
    SCARDHANDLE hCard;
    DWORD dwActiveProtocol;
    LONG rv;
    char mszReaders[1024];
    DWORD dwReaders = sizeof(mszReaders);

    rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
    CHECK_RV("SCardEstablishContext");

    rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders);
    CHECK_RV("SCardListReaders");

    rv = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED,
        SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard,
        &dwActiveProtocol);
    CHECK_RV("SCardConnect");

    printf("Remove and insert the card. Then press Enter");
    getchar();

    DWORD chReaderLen = 100;
    DWORD dwState;
    DWORD dwProtocol;
    BYTE bAtr[33];
    DWORD cbAtrLen = sizeof bAtr;
    rv = SCardStatus(hCard, mszReaders, &chReaderLen, &dwState, &dwProtocol,
        bAtr, &cbAtrLen);
    CHECK_RV("SCardStatus");

    rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
    CHECK_RV("SCardDisconnect")

    rv = SCardReleaseContext(hContext);
    CHECK_RV("SCardReleaseContext")

error:
    return ret;
}

Result (on High Sierra)

$ ./main_Mac 
SCardEstablishContext(): OK
SCardListReaders(): OK
SCardConnect(): OK
Remove and insert the card. Then press Enter
SCardStatus() failed: Card was reset. (0x80100068)

Expected result (on Debian)

$ ./main_Linux 
SCardEstablishContext(): OK
SCardListReaders(): OK
SCardConnect(): OK
Remove and insert the card. Then press Enter
SCardStatus() failed: Card was removed. (0x80100069)

Known workaround

None known.