#include "config.h"
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>
#include "wintypes.h"
#include "pcsclite.h"
#include "winscard.h"
#include "ifdhandler.h"
#include "debuglog.h"
#include "readerfactory.h"
#include "prothandler.h"
#include "ifdwrapper.h"
#include "atrhandler.h"
#include "configfile.h"
#include "sys_generic.h"
#include "eventhandler.h"
#include "readerstate.h"
#include <security_utilities/debugging.h>
#define SCARD_PROTOCOL_ANY_OLD 0x1000
#define SCARD_LAST_CONTEXT 1
#define SCARD_NO_CONTEXT 0
#define SCARD_EXCLUSIVE_CONTEXT -1
#define SCARD_NO_LOCK 0
SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 };
SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 };
SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 };
#define PCSCLITE_LOCK_POLL_RATE 100000
static LONG NotifyOfCardReset(DWORD state, PREADER_CONTEXT rContext, SCARDHANDLE hCard);
static LONG EjectCard(PREADER_CONTEXT rContext);
LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
{
if (phContext == 0)
return SCARD_E_INVALID_PARAMETER;
if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL &&
dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL)
{
*phContext = 0;
return SCARD_E_INVALID_VALUE;
}
*phContext = (PCSCLITE_SVC_IDENTITY + SYS_Random(SYS_GetSeed(),
1.0, 65535.0));
Log3(PCSC_LOG_DEBUG, "Establishing Context: %d [0x%08X]", *phContext, *phContext);
return SCARD_S_SUCCESS;
}
LONG SCardReleaseContext(SCARDCONTEXT hContext)
{
Log2(PCSC_LOG_DEBUG, "Releasing Context: %d", hContext);
return SCARD_S_SUCCESS;
}
LONG SCardSetTimeout(SCARDCONTEXT hContext, DWORD dwTimeout)
{
return SCARD_E_UNSUPPORTED_FEATURE;
}
LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader,
DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
LPDWORD pdwActiveProtocol)
{
LONG rv;
PREADER_CONTEXT rContext = NULL;
DWORD dwStatus;
if (szReader == NULL || phCard == NULL || pdwActiveProtocol == NULL)
return SCARD_E_INVALID_PARAMETER;
else
*phCard = 0;
if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
!(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
!(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
!(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
return SCARD_E_PROTO_MISMATCH;
if (dwShareMode != SCARD_SHARE_EXCLUSIVE &&
dwShareMode != SCARD_SHARE_SHARED &&
dwShareMode != SCARD_SHARE_DIRECT)
return SCARD_E_INVALID_VALUE;
Log3(PCSC_LOG_DEBUG, "Attempting Connect to %s using protocol: %d",
szReader, dwPreferredProtocols);
rv = RFReaderInfo((LPSTR) szReader, &rContext);
if (rv != SCARD_S_SUCCESS)
{
Log2(PCSC_LOG_ERROR, "Reader %s Not Found", szReader);
return rv;
}
rv = RFCheckReaderStatus(rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
{
Log1(PCSC_LOG_ERROR, "Error Reader Exclusive");
return SCARD_E_SHARING_VIOLATION;
}
if (rContext->dwLockId != 0)
{
Log1(PCSC_LOG_INFO, "Waiting for release of lock");
while (rContext->dwLockId != 0)
SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
Log1(PCSC_LOG_INFO, "Lock released");
SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
}
dwStatus = SharedReaderState_State(rContext->readerState);
if (dwShareMode != SCARD_SHARE_DIRECT)
{
if (!(dwStatus & SCARD_PRESENT))
{
Log1(PCSC_LOG_ERROR, "Card Not Inserted");
return SCARD_E_NO_SMARTCARD;
}
if (dwStatus & SCARD_SWALLOWED)
{
Log1(PCSC_LOG_ERROR, "Card Not Powered");
return SCARD_W_UNPOWERED_CARD;
}
}
if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
SharedReaderState_SetProtocol(rContext->readerState, SCARD_PROTOCOL_RAW);
else
{
if (dwShareMode != SCARD_SHARE_DIRECT)
{
SYS_MutexLock(rContext->mMutex);
if (SCARD_PROTOCOL_UNSET == SharedReaderState_Protocol(rContext->readerState))
{
UCHAR ucAvailable, ucDefault;
int ret;
ucDefault = PHGetDefaultProtocol(SharedReaderState_CardAtr(rContext->readerState),
SharedReaderState_CardAtrLength(rContext->readerState));
ucAvailable =
PHGetAvailableProtocols(SharedReaderState_CardAtr(rContext->readerState),
SharedReaderState_CardAtrLength(rContext->readerState));
if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
ret = PHSetProtocol(rContext, dwPreferredProtocols,
ucAvailable, ucDefault);
if (SET_PROTOCOL_PPS_FAILED == ret)
{
SYS_MutexUnLock(rContext->mMutex);
return SCARD_W_UNRESPONSIVE_CARD;
}
if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
{
SYS_MutexUnLock(rContext->mMutex);
return SCARD_E_PROTO_MISMATCH;
}
SharedReaderState_SetProtocol(rContext->readerState, ret);
SYS_MutexUnLock(rContext->mMutex);
}
else
{
SYS_MutexUnLock(rContext->mMutex);
if (! (dwPreferredProtocols & SharedReaderState_Protocol(rContext->readerState)))
return SCARD_E_PROTO_MISMATCH;
}
}
}
*pdwActiveProtocol = SharedReaderState_Protocol(rContext->readerState);
if (dwShareMode != SCARD_SHARE_DIRECT)
{
if ((*pdwActiveProtocol != SCARD_PROTOCOL_T0)
&& (*pdwActiveProtocol != SCARD_PROTOCOL_T1))
Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %d",
*pdwActiveProtocol);
else
Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d",
(*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
}
else
Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected");
*phCard = RFCreateReaderHandle(rContext);
Log2(PCSC_LOG_DEBUG, "hCard Identity: %x", *phCard);
if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
{
if (rContext->dwContexts == SCARD_NO_CONTEXT)
{
rContext->dwContexts = SCARD_EXCLUSIVE_CONTEXT;
RFLockSharing(*phCard);
}
else
{
RFDestroyReaderHandle(*phCard);
*phCard = 0;
Log1(PCSC_LOG_ERROR, "SCardConnect: share mode is exclusive, but already in use");
return SCARD_E_SHARING_VIOLATION;
}
}
else
{
rContext->dwContexts += 1;
}
rv = RFAddReaderHandle(rContext, *phCard);
if (rv != SCARD_S_SUCCESS)
{
RFDestroyReaderHandle(*phCard);
if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
rContext->dwContexts = SCARD_NO_CONTEXT;
else
if (rContext->dwContexts > SCARD_NO_CONTEXT)
rContext->dwContexts -= 1;
*phCard = 0;
return SCARD_F_INTERNAL_ERROR;
}
SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
return SCARD_S_SUCCESS;
}
LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
DWORD dwPreferredProtocols, DWORD dwInitialization,
LPDWORD pdwActiveProtocol)
{
LONG rv;
PREADER_CONTEXT rContext = NULL;
int do_sleep = 1;
Log1(PCSC_LOG_DEBUG, "Attempting reconnect to token.");
if (hCard == 0)
return SCARD_E_INVALID_HANDLE;
if (dwInitialization != SCARD_LEAVE_CARD &&
dwInitialization != SCARD_RESET_CARD &&
dwInitialization != SCARD_UNPOWER_CARD)
return SCARD_E_INVALID_VALUE;
if (dwShareMode != SCARD_SHARE_SHARED &&
dwShareMode != SCARD_SHARE_EXCLUSIVE &&
dwShareMode != SCARD_SHARE_DIRECT)
return SCARD_E_INVALID_VALUE;
if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
!(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
!(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
!(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
return SCARD_E_PROTO_MISMATCH;
if (pdwActiveProtocol == NULL)
return SCARD_E_INVALID_PARAMETER;
rv = RFReaderInfoById(hCard, &rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
rv = RFCheckReaderStatus(rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
rv = RFFindReaderHandle(hCard);
if (rv != SCARD_S_SUCCESS)
return rv;
rv = RFCheckSharing(hCard);
if (rv != SCARD_S_SUCCESS)
return rv;
if (dwInitialization == SCARD_RESET_CARD ||
dwInitialization == SCARD_UNPOWER_CARD)
{
LONG ret = NotifyOfCardReset(dwInitialization, rContext, hCard);
if (ret != SCARD_S_SUCCESS)
return ret;
do_sleep = 1;
}
else if (dwInitialization == SCARD_LEAVE_CARD)
{
do_sleep = 0;
}
if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
SharedReaderState_SetProtocol(rContext->readerState, SCARD_PROTOCOL_RAW);
else
{
if (dwShareMode != SCARD_SHARE_DIRECT)
{
SYS_MutexLock(rContext->mMutex);
if (SCARD_PROTOCOL_UNSET == SharedReaderState_Protocol(rContext->readerState))
{
UCHAR ucAvailable, ucDefault;
int ret;
ucDefault = PHGetDefaultProtocol(SharedReaderState_CardAtr(rContext->readerState),
SharedReaderState_CardAtrLength(rContext->readerState));
ucAvailable =
PHGetAvailableProtocols(SharedReaderState_CardAtr(rContext->readerState),
SharedReaderState_CardAtrLength(rContext->readerState));
if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
ret = PHSetProtocol(rContext, dwPreferredProtocols,
ucAvailable, ucDefault);
if (SET_PROTOCOL_PPS_FAILED == ret)
{
SYS_MutexUnLock(rContext->mMutex);
return SCARD_W_UNRESPONSIVE_CARD;
}
if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
{
SYS_MutexUnLock(rContext->mMutex);
return SCARD_E_PROTO_MISMATCH;
}
SharedReaderState_SetProtocol(rContext->readerState, ret);
SYS_MutexUnLock(rContext->mMutex);
}
else
{
SYS_MutexUnLock(rContext->mMutex);
if (! (dwPreferredProtocols & SharedReaderState_Protocol(rContext->readerState)))
return SCARD_E_PROTO_MISMATCH;
}
}
}
*pdwActiveProtocol = SharedReaderState_Protocol(rContext->readerState);
if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
{
if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
{
} else
{
if (rContext->dwContexts == SCARD_LAST_CONTEXT)
{
rContext->dwContexts = SCARD_EXCLUSIVE_CONTEXT;
RFLockSharing(hCard);
} else
{
Log1(PCSC_LOG_ERROR, "SCardReConnect: share mode is exclusive, but already in use");
return SCARD_E_SHARING_VIOLATION;
}
}
} else if (dwShareMode == SCARD_SHARE_SHARED)
{
if (rContext->dwContexts != SCARD_EXCLUSIVE_CONTEXT)
{
} else
{
RFUnlockSharing(hCard);
rContext->dwContexts = SCARD_LAST_CONTEXT;
}
} else if (dwShareMode == SCARD_SHARE_DIRECT)
{
if (rContext->dwContexts != SCARD_EXCLUSIVE_CONTEXT)
{
} else
{
RFUnlockSharing(hCard);
rContext->dwContexts = SCARD_LAST_CONTEXT;
}
} else
return SCARD_E_INVALID_VALUE;
RFClearReaderEventState(rContext, hCard);
if (do_sleep)
SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
return SCARD_S_SUCCESS;
}
LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
{
LONG rv;
PREADER_CONTEXT rContext = NULL;
if (hCard == 0)
return SCARD_E_INVALID_HANDLE;
rv = RFReaderInfoById(hCard, &rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
rv = RFFindReaderHandle(hCard);
if (rv != SCARD_S_SUCCESS)
return rv;
if ((dwDisposition != SCARD_LEAVE_CARD)
&& (dwDisposition != SCARD_UNPOWER_CARD)
&& (dwDisposition != SCARD_RESET_CARD)
&& (dwDisposition != SCARD_EJECT_CARD))
return SCARD_E_INVALID_VALUE;
if ((rContext->dwLockId != 0) && (rContext->dwLockId != (uint32_t)hCard))
{
Log1(PCSC_LOG_INFO, "Waiting for release of lock");
while (rContext->dwLockId != 0)
SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
Log1(PCSC_LOG_INFO, "Lock released");
}
rv = RFUnlockSharing(hCard);
if (rv != SCARD_S_SUCCESS)
return rv;
Log2(PCSC_LOG_DEBUG, "Active Contexts: %d", rContext->dwContexts);
if (dwDisposition == SCARD_RESET_CARD ||
dwDisposition == SCARD_UNPOWER_CARD)
{
NotifyOfCardReset(dwDisposition, rContext, hCard);
SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
}
else
if (dwDisposition == SCARD_EJECT_CARD)
EjectCard(rContext);
else if (dwDisposition == SCARD_LEAVE_CARD)
{
}
RFRemoveReaderHandle(rContext, hCard);
RFDestroyReaderHandle(hCard);
if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
{
rContext->dwContexts = SCARD_NO_CONTEXT;
return SCARD_S_SUCCESS;
}
rContext->dwContexts -= 1;
if (rContext->dwContexts < 0)
rContext->dwContexts = 0;
return SCARD_S_SUCCESS;
}
LONG SCardBeginTransaction(SCARDHANDLE hCard)
{
LONG rv;
PREADER_CONTEXT rContext;
if (hCard == 0)
return SCARD_E_INVALID_HANDLE;
rv = RFReaderInfoById(hCard, &rContext);
if (rv != SCARD_S_SUCCESS)
{
Log3(PCSC_LOG_DEBUG, "SCardBeginTransaction: cannot find hCard: 0x%08X [0x%08X]", hCard, rv);
return rv;
}
rv = RFCheckReaderStatus(rContext);
if (rv != SCARD_S_SUCCESS)
{
Log3(PCSC_LOG_DEBUG, "SCardBeginTransaction: reader status fail: 0x%08X [0x%08X]", hCard, rv);
return rv;
}
rv = RFFindReaderHandle(hCard);
if (rv != SCARD_S_SUCCESS)
{
Log3(PCSC_LOG_DEBUG, "SCardBeginTransaction: reader handle fail: 0x%08X [0x%08X]", hCard, rv);
return rv;
}
if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
{
Log3(PCSC_LOG_DEBUG, "SCardBeginTransaction: reader event fail: 0x%08X [0x%08X]", hCard, rv);
return rv;
}
rv = RFLockSharing(hCard);
if (SCARD_E_SHARING_VIOLATION == (uint32_t)rv)
SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
Log2(PCSC_LOG_DEBUG, "SCardBeginTransaction ending status: 0x%08X", rv);
return rv;
}
LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
{
LONG rv;
PREADER_CONTEXT rContext = NULL;
if (hCard == 0)
return SCARD_E_INVALID_HANDLE;
if ((dwDisposition != SCARD_LEAVE_CARD)
&& (dwDisposition != SCARD_UNPOWER_CARD)
&& (dwDisposition != SCARD_RESET_CARD)
&& (dwDisposition != SCARD_EJECT_CARD))
return SCARD_E_INVALID_VALUE;
rv = RFReaderInfoById(hCard, &rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
rv = RFFindReaderHandle(hCard);
if (rv != SCARD_S_SUCCESS)
return rv;
if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
return rv;
if (dwDisposition == SCARD_RESET_CARD ||
dwDisposition == SCARD_UNPOWER_CARD)
{
NotifyOfCardReset(dwDisposition, rContext, hCard);
}
else if (dwDisposition == SCARD_EJECT_CARD)
EjectCard(rContext);
else if (dwDisposition == SCARD_LEAVE_CARD)
{
}
RFUnlockSharing(hCard);
Log2(PCSC_LOG_DEBUG, "Status: 0x%08X", rv);
return rv;
}
LONG SCardCancelTransaction(SCARDHANDLE hCard)
{
LONG rv;
PREADER_CONTEXT rContext = NULL;
if (hCard == 0)
return SCARD_E_INVALID_HANDLE;
rv = RFReaderInfoById(hCard, &rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
rv = RFFindReaderHandle(hCard);
if (rv != SCARD_S_SUCCESS)
return rv;
if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
return rv;
rv = RFUnlockSharing(hCard);
Log2(PCSC_LOG_DEBUG, "Status: 0x%08X", rv);
return rv;
}
LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderNames,
LPDWORD pcchReaderLen, LPDWORD pdwState,
LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
{
LONG rv;
PREADER_CONTEXT rContext = NULL;
rv = RFReaderInfoById(hCard, &rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
if (strlen(rContext->lpcReader) > MAX_BUFFER_SIZE
|| SharedReaderState_CardAtrLength(rContext->readerState) > MAX_ATR_SIZE)
return SCARD_F_INTERNAL_ERROR;
if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
return rv;
rv = RFCheckReaderStatus(rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
if (mszReaderNames)
{
int cchReaderLen;
if (!pcchReaderLen)
return SCARD_E_INVALID_PARAMETER;
cchReaderLen = strlen(rContext->lpcReader);
if(*pcchReaderLen < cchReaderLen)
rv = SCARD_E_INSUFFICIENT_BUFFER;
else
strncpy(mszReaderNames, rContext->lpcReader, cchReaderLen);
*pcchReaderLen = cchReaderLen;
}
else if (pcchReaderLen)
*pcchReaderLen = strlen(rContext->lpcReader);
if (pdwState)
*pdwState = SharedReaderState_State(rContext->readerState);
if (pdwProtocol)
*pdwProtocol = SharedReaderState_Protocol(rContext->readerState);
if (pbAtr)
{
int cbAtrLen;
if (!pcbAtrLen)
return SCARD_E_INVALID_PARAMETER;
cbAtrLen = SharedReaderState_CardAtrLength(rContext->readerState);
if(cbAtrLen >= *pcbAtrLen)
rv = SCARD_E_INSUFFICIENT_BUFFER;
else
{
*pcbAtrLen = cbAtrLen;
memcpy(pbAtr, SharedReaderState_CardAtr(rContext->readerState), cbAtrLen);
}
}
else if (pcbAtrLen)
*pcbAtrLen = SharedReaderState_CardAtrLength(rContext->readerState);
return rv;
}
LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
{
return SCARD_S_SUCCESS;
}
#undef SCardControl
LONG SCardControl(SCARDHANDLE hCard, const void *pbSendBuffer,
DWORD cbSendLength, void *pbRecvBuffer, LPDWORD pcbRecvLength)
{
uint32_t dwControlCode = 0;
uint32_t cbRecvLength = *pcbRecvLength;
uint32_t bytesReturned = 0;
int32_t rv = SCardControl132(hCard, dwControlCode, pbSendBuffer, cbSendLength,
pbRecvBuffer, cbRecvLength, &bytesReturned);
*pcbRecvLength = bytesReturned;
return rv;
}
int32_t SCardControl132(SCARDHANDLE hCard, uint32_t dwControlCode,
const void *pbSendBuffer, uint32_t cbSendLength,
void *pbRecvBuffer, uint32_t cbRecvLength, uint32_t *lpBytesReturned)
{
LONG rv;
PREADER_CONTEXT rContext = NULL;
*lpBytesReturned = 0;
if (0 == hCard)
return SCARD_E_INVALID_HANDLE;
if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
return rv;
rv = RFReaderInfoById(hCard, &rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
if (IFD_HVERSION_2_0 == rContext->dwVersion)
if (NULL == pbSendBuffer || 0 == cbSendLength)
return SCARD_E_INVALID_PARAMETER;
rv = RFCheckReaderStatus(rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
rv = RFFindReaderHandle(hCard);
if (rv != SCARD_S_SUCCESS)
return rv;
if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
return rv;
if (IFD_HVERSION_2_0 == rContext->dwVersion)
{
*lpBytesReturned = cbRecvLength;
return IFDControl_v2(rContext, (PUCHAR)pbSendBuffer,
cbSendLength, (uint8_t *)pbRecvBuffer, lpBytesReturned);
}
else
if (IFD_HVERSION_3_0 == rContext->dwVersion)
return IFDControl(rContext, dwControlCode, pbSendBuffer,
cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned);
else
return SCARD_E_UNSUPPORTED_FEATURE;
}
LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
LPBYTE pbAttr, LPDWORD pcbAttrLen)
{
LONG rv;
PREADER_CONTEXT rContext = NULL;
if (0 == hCard)
return SCARD_E_INVALID_HANDLE;
if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
return rv;
rv = RFReaderInfoById(hCard, &rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
rv = RFCheckReaderStatus(rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
rv = RFFindReaderHandle(hCard);
if (rv != SCARD_S_SUCCESS)
return rv;
if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
return rv;
rv = IFDGetCapabilities(rContext, dwAttrId, pcbAttrLen, pbAttr);
if (rv == IFD_SUCCESS)
return SCARD_S_SUCCESS;
else
if (rv == IFD_ERROR_TAG)
return SCARD_E_UNSUPPORTED_FEATURE;
else
return SCARD_E_NOT_TRANSACTED;
}
LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
LPCBYTE pbAttr, DWORD cbAttrLen)
{
LONG rv;
PREADER_CONTEXT rContext = NULL;
if (0 == hCard)
return SCARD_E_INVALID_HANDLE;
if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
return rv;
rv = RFReaderInfoById(hCard, &rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
rv = RFCheckReaderStatus(rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
rv = RFFindReaderHandle(hCard);
if (rv != SCARD_S_SUCCESS)
return rv;
if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
return rv;
rv = IFDSetCapabilities(rContext, dwAttrId, cbAttrLen, (PUCHAR)pbAttr);
if (rv == IFD_SUCCESS)
return SCARD_S_SUCCESS;
else
if (rv == IFD_ERROR_TAG)
return SCARD_E_UNSUPPORTED_FEATURE;
else
return SCARD_E_NOT_TRANSACTED;
}
#define kSCARD_LE_IN_SW2 0x6C
#define kReadBinaryAPDU 0xB0
#define kReadBinaryLe 4
LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
LPCBYTE pbSendBuffer, DWORD cbSendLength,
LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
LPDWORD pcbRecvLength)
{
LONG rv;
PREADER_CONTEXT rContext = NULL;
SCARD_IO_HEADER sSendPci, sRecvPci;
DWORD dwRxLength, tempRxLength;
if (pcbRecvLength == 0)
return SCARD_E_INVALID_PARAMETER;
dwRxLength = *pcbRecvLength;
*pcbRecvLength = 0;
if (hCard == 0)
return SCARD_E_INVALID_HANDLE;
if (pbSendBuffer == NULL || pbRecvBuffer == NULL || pioSendPci == NULL)
return SCARD_E_INVALID_PARAMETER;
if (cbSendLength < 4)
return SCARD_E_INVALID_PARAMETER;
if (dwRxLength < 2)
return SCARD_E_INSUFFICIENT_BUFFER;
if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
return rv;
rv = RFReaderInfoById(hCard, &rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
rv = RFCheckReaderStatus(rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
rv = RFFindReaderHandle(hCard);
if (rv != SCARD_S_SUCCESS)
return rv;
if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
return rv;
if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
{
if (SharedReaderState_State(rContext->readerState) & SCARD_ABSENT)
{
return SCARD_E_NO_SMARTCARD;
}
}
if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
{
if (pioSendPci->dwProtocol != SCARD_PROTOCOL_ANY_OLD)
{
if (pioSendPci->dwProtocol != SharedReaderState_Protocol(rContext->readerState))
{
return SCARD_E_PROTO_MISMATCH;
}
}
}
sSendPci.Protocol = 0;
if (pioSendPci->dwProtocol == SCARD_PROTOCOL_T1)
{
sSendPci.Protocol = 1;
} else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
{
sSendPci.Protocol = SCARD_PROTOCOL_RAW;
} else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_ANY_OLD)
{
unsigned long i;
unsigned long prot = SharedReaderState_Protocol(rContext->readerState);
for (i = 0 ; prot != 1 ; i++)
prot >>= 1;
sSendPci.Protocol = i;
}
sSendPci.Length = pioSendPci->cbPciLength;
Log2(PCSC_LOG_DEBUG, "Send Protocol: T=%d", sSendPci.Protocol);
tempRxLength = dwRxLength;
if (pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
{
rv = IFDControl_v2(rContext, (PUCHAR)pbSendBuffer , cbSendLength,
pbRecvBuffer, &dwRxLength);
} else
{
rv = IFDTransmit(rContext, sSendPci, (PUCHAR)pbSendBuffer,
cbSendLength, pbRecvBuffer, &dwRxLength, &sRecvPci);
}
if (pioRecvPci)
{
pioRecvPci->dwProtocol = sRecvPci.Protocol;
pioRecvPci->cbPciLength = sRecvPci.Length;
}
Log3(PCSC_LOG_DEBUG, "IFDControl_v2/IFDTransmit result: 0x%08X, received: %d", rv, dwRxLength);
Log3(PCSC_LOG_DEBUG, " pbRecvBuffer: [0]: 0x%02X, [1]: 0x%02X", pbRecvBuffer[0], pbRecvBuffer[1]);
if (rv != SCARD_S_SUCCESS)
{
*pcbRecvLength = 0;
Log2(PCSC_LOG_ERROR, "Card not transacted: 0x%08lX", rv);
return SCARD_E_NOT_TRANSACTED;
}
if (tempRxLength < dwRxLength)
{
Log3(PCSC_LOG_DEBUG, "Available is less than received: avail: %d, received: %d", tempRxLength, dwRxLength);
*pcbRecvLength = 0;
return SCARD_E_INSUFFICIENT_BUFFER;
}
*pcbRecvLength = dwRxLength;
return SCARD_S_SUCCESS;
}
LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups,
LPSTR mszReaders, LPDWORD pcchReaders)
{
return SCARD_S_SUCCESS;
}
LONG SCardCancel(SCARDCONTEXT hContext)
{
return SCARD_S_SUCCESS;
}
static LONG NotifyOfCardReset(DWORD state, PREADER_CONTEXT rContext, SCARDHANDLE hCard)
{
LONG rv = SCARD_S_SUCCESS, ret = SCARD_S_SUCCESS;
DWORD tmpCardAtrLength = SharedReaderState_CardAtrLength(rContext->readerState);
if (SCARD_RESET_CARD == state)
rv = IFDPowerICC(rContext, IFD_RESET, SharedReaderState_CardAtr(rContext->readerState), &tmpCardAtrLength);
else
{
rv = IFDPowerICC(rContext, IFD_POWER_DOWN, SharedReaderState_CardAtr(rContext->readerState), &tmpCardAtrLength);
rv = IFDPowerICC(rContext, IFD_POWER_UP, SharedReaderState_CardAtr(rContext->readerState), &tmpCardAtrLength);
}
SharedReaderState_SetCardAtrLength(rContext->readerState, tmpCardAtrLength);
SharedReaderState_SetProtocol(rContext->readerState, SCARD_PROTOCOL_UNSET);
ret = RFCheckReaderEventState(rContext, hCard);
switch (rv)
{
case SCARD_W_RESET_CARD:
break;
case SCARD_W_REMOVED_CARD:
Log1(PCSC_LOG_ERROR, "card removed");
return SCARD_W_REMOVED_CARD;
case SCARD_E_INVALID_VALUE:
Log1(PCSC_LOG_ERROR, "invalid EventStatus");
return SCARD_F_INTERNAL_ERROR;
case SCARD_E_INVALID_HANDLE:
Log1(PCSC_LOG_ERROR, "invalid handle");
return SCARD_F_INTERNAL_ERROR;
case SCARD_S_SUCCESS:
RFSetReaderEventState(rContext, SCARD_RESET);
DWORD readerStateTmp = SharedReaderState_State(rContext->readerState);
if (rv == SCARD_S_SUCCESS)
{
readerStateTmp |= SCARD_PRESENT;
readerStateTmp &= ~SCARD_ABSENT;
readerStateTmp |= SCARD_POWERED;
readerStateTmp |= SCARD_NEGOTIABLE;
readerStateTmp &= ~SCARD_SPECIFIC;
readerStateTmp &= ~SCARD_SWALLOWED;
readerStateTmp &= ~SCARD_UNKNOWN;
}
else
{
readerStateTmp |= SCARD_PRESENT;
readerStateTmp &= ~SCARD_ABSENT;
readerStateTmp |= SCARD_SWALLOWED;
readerStateTmp &= ~SCARD_POWERED;
readerStateTmp &= ~SCARD_NEGOTIABLE;
readerStateTmp &= ~SCARD_SPECIFIC;
readerStateTmp &= ~SCARD_UNKNOWN;
SharedReaderState_SetCardAtrLength(rContext->readerState, 0);
}
SharedReaderState_SetState(rContext->readerState, readerStateTmp);
if (SharedReaderState_CardAtrLength(rContext->readerState) > 0)
{
Log1(PCSC_LOG_ERROR, "Reset complete.");
LogXxd(PCSC_LOG_DEBUG, "Card ATR: ", SharedReaderState_CardAtr(rContext->readerState),
SharedReaderState_CardAtrLength(rContext->readerState));
}
else
{
DWORD dwStatus, dwAtrLen;
UCHAR ucAtr[MAX_ATR_SIZE];
Log1(PCSC_LOG_ERROR, "Error resetting card.");
IFDStatusICC(rContext, &dwStatus, ucAtr, &dwAtrLen);
if (dwStatus & SCARD_PRESENT)
return SCARD_W_UNRESPONSIVE_CARD;
else
return SCARD_E_NO_SMARTCARD;
}
break;
default:
Log2(PCSC_LOG_ERROR, "invalid retcode from RFCheckReaderEventState (%X)", rv);
return SCARD_F_INTERNAL_ERROR;
}
return SCARD_S_SUCCESS;
}
static LONG EjectCard(PREADER_CONTEXT rContext)
{
LONG rv = SCARD_S_SUCCESS;
UCHAR controlBuffer[5];
UCHAR receiveBuffer[MAX_BUFFER_SIZE];
DWORD receiveLength;
controlBuffer[0] = 0x20;
controlBuffer[1] = 0x15;
controlBuffer[2] = (rContext->dwSlot & 0x0000FFFF) + 1;
controlBuffer[3] = 0x00;
controlBuffer[4] = 0x00;
receiveLength = 2;
rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer, &receiveLength);
if (rv == SCARD_S_SUCCESS)
{
if (receiveLength == 2 && receiveBuffer[0] == 0x90) Log1(PCSC_LOG_ERROR, "Card ejected successfully.");
else
{
Log3(PCSC_LOG_ERROR, "Error ejecting card: %02X%02X", receiveBuffer[0], receiveBuffer[1]);
rv = SCARD_F_UNKNOWN_ERROR;
}
}
else
Log1(PCSC_LOG_ERROR, "Error ejecting card.");
return rv;
}