OS X Yosemite bug: SCardTransmit (pioSendPci not checked)

This is part of the series: "OS X Yosemite and smart cards: known bugs".

SCardTransmit

SCardTransmit() fails to detect wrong value for pioSendPci 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.
Previous
Next Post »