#include "config.h"
#include "wintypes.h"
#include "pcsclite.h"
#include "ifdhandler.h"
#include "debuglog.h"
#include "readerfactory.h"
#include "ifdwrapper.h"
#include "atrhandler.h"
#include "dyn_generic.h"
#include "sys_generic.h"
#include <security_utilities/debugging.h>
#undef PCSCLITE_STATIC_DRIVER
LONG IFDSetPTS(PREADER_CONTEXT rContext, DWORD dwProtocol, UCHAR ucFlags,
UCHAR ucPTS1, UCHAR ucPTS2, UCHAR ucPTS3)
{
RESPONSECODE rv = IFD_SUCCESS;
UCHAR ucValue[1];
#ifndef PCSCLITE_STATIC_DRIVER
RESPONSECODE(*IFD_set_protocol_parameters) (DWORD, UCHAR, UCHAR,
UCHAR, UCHAR) = NULL;
RESPONSECODE(*IFDH_set_protocol_parameters) (DWORD, DWORD, UCHAR,
UCHAR, UCHAR, UCHAR) = NULL;
if (rContext->dwVersion == IFD_HVERSION_1_0)
{
IFD_set_protocol_parameters = (RESPONSECODE(*)(DWORD, UCHAR, UCHAR,
UCHAR, UCHAR)) rContext->psFunctions.psFunctions_v1.pvfSetProtocolParameters;
if (NULL == IFD_set_protocol_parameters)
return SCARD_E_UNSUPPORTED_FEATURE;
}
else
{
IFDH_set_protocol_parameters = (RESPONSECODE(*)(DWORD, DWORD, UCHAR,
UCHAR, UCHAR, UCHAR))
rContext->psFunctions.psFunctions_v2.pvfSetProtocolParameters;
if (NULL == IFDH_set_protocol_parameters)
return SCARD_E_UNSUPPORTED_FEATURE;
}
#endif
ucValue[0] = rContext->dwSlot;
#ifndef PCSCLITE_STATIC_DRIVER
if (rContext->dwVersion == IFD_HVERSION_1_0)
{
ucValue[0] = rContext->dwSlot;
IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
rv = (*IFD_set_protocol_parameters) (dwProtocol,
ucFlags, ucPTS1, ucPTS2, ucPTS3);
}
else
{
rv = (*IFDH_set_protocol_parameters) (rContext->dwSlot,
dwProtocol,
ucFlags, ucPTS1,
ucPTS2, ucPTS3);
}
#else
if (rContext->dwVersion == IFD_HVERSION_1_0)
{
ucValue[0] = rContext->dwSlot;
IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
rv = IFD_Set_Protocol_Parameters(dwProtocol, ucFlags, ucPTS1,
ucPTS2, ucPTS3);
}
else
{
rv = IFDHSetProtocolParameters(rContext->dwSlot, dwProtocol,
ucFlags, ucPTS1, ucPTS2, ucPTS3);
}
#endif
return rv;
}
LONG IFDOpenIFD(PREADER_CONTEXT rContext)
{
RESPONSECODE rv = 0;
#ifndef PCSCLITE_STATIC_DRIVER
RESPONSECODE(*IO_create_channel) (DWORD) = NULL;
RESPONSECODE(*IFDH_create_channel) (DWORD, DWORD) = NULL;
RESPONSECODE(*IFDH_create_channel_by_name) (DWORD, LPSTR) = NULL;
if (rContext->dwVersion == IFD_HVERSION_1_0)
IO_create_channel =
rContext->psFunctions.psFunctions_v1.pvfCreateChannel;
else
if (rContext->dwVersion == IFD_HVERSION_2_0)
IFDH_create_channel =
rContext->psFunctions.psFunctions_v2.pvfCreateChannel;
else
{
IFDH_create_channel =
rContext->psFunctions.psFunctions_v3.pvfCreateChannel;
IFDH_create_channel_by_name =
rContext->psFunctions.psFunctions_v3.pvfCreateChannelByName;
}
#endif
SYS_MutexLock(rContext->mMutex);
#ifndef PCSCLITE_STATIC_DRIVER
if (rContext->dwVersion == IFD_HVERSION_1_0)
{
rv = (*IO_create_channel) (rContext->dwPort);
} else if (rContext->dwVersion == IFD_HVERSION_2_0)
{
rv = (*IFDH_create_channel) (rContext->dwSlot, rContext->dwPort);
} else
{
if (rContext->lpcDevice[0] != '\0')
rv = (*IFDH_create_channel_by_name) (rContext->dwSlot, rContext->lpcDevice);
else
rv = (*IFDH_create_channel) (rContext->dwSlot, rContext->dwPort);
}
#else
if (rContext->dwVersion == IFD_HVERSION_1_0)
{
rv = IO_Create_Channel(rContext->dwPort);
} else if (rContext->dwVersion == IFD_HVERSION_2_0)
{
rv = IFDHCreateChannel(rContext->dwSlot, rContext->dwPort);
} else
{
if (rContext->lpcDevice[0] != '\0')
rv = IFDHCreateChannelByName(rContext->dwSlot, rContext->lpcDevice);
else
rv = IFDHCreateChannel(rContext->dwSlot, rContext->dwPort);
}
#endif
SYS_MutexUnLock(rContext->mMutex);
return rv;
}
LONG IFDCloseIFD(PREADER_CONTEXT rContext)
{
RESPONSECODE rv = IFD_SUCCESS;
#ifndef PCSCLITE_STATIC_DRIVER
RESPONSECODE(*IO_close_channel) () = NULL;
RESPONSECODE(*IFDH_close_channel) (DWORD) = NULL;
if (rContext->dwVersion == IFD_HVERSION_1_0)
IO_close_channel = rContext->psFunctions.psFunctions_v1.pvfCloseChannel;
else
IFDH_close_channel = rContext->psFunctions.psFunctions_v2.pvfCloseChannel;
#endif
SYS_MutexLock(rContext->mMutex);
#ifndef PCSCLITE_STATIC_DRIVER
if (rContext->dwVersion == IFD_HVERSION_1_0)
rv = (*IO_close_channel) ();
else
rv = (*IFDH_close_channel) (rContext->dwSlot);
#else
if (rContext->dwVersion == IFD_HVERSION_1_0)
rv = IO_Close_Channel();
else
rv = IFDHCloseChannel(rContext->dwSlot);
#endif
SYS_MutexUnLock(rContext->mMutex);
return rv;
}
LONG IFDSetCapabilities(PREADER_CONTEXT rContext, DWORD dwTag,
DWORD dwLength, PUCHAR pucValue)
{
RESPONSECODE rv = IFD_SUCCESS;
#ifndef PCSCLITE_STATIC_DRIVER
RESPONSECODE(*IFD_set_capabilities) (DWORD, PUCHAR) = NULL;
RESPONSECODE(*IFDH_set_capabilities) (DWORD, DWORD, DWORD, PUCHAR) = NULL;
if (rContext->dwVersion == IFD_HVERSION_1_0)
IFD_set_capabilities = rContext->psFunctions.psFunctions_v1.pvfSetCapabilities;
else
IFDH_set_capabilities = rContext->psFunctions.psFunctions_v2.pvfSetCapabilities;
#endif
#ifndef PCSCLITE_STATIC_DRIVER
if (rContext->dwVersion == IFD_HVERSION_1_0)
rv = (*IFD_set_capabilities) (dwTag, pucValue);
else
rv = (*IFDH_set_capabilities) (rContext->dwSlot, dwTag,
dwLength, pucValue);
#else
if (rContext->dwVersion == IFD_HVERSION_1_0)
rv = IFD_Set_Capabilities(dwTag, pucValue);
else
rv = IFDHSetCapabilities(rContext->dwSlot, dwTag, dwLength,
pucValue);
#endif
return rv;
}
LONG IFDGetCapabilities(PREADER_CONTEXT rContext, DWORD dwTag,
PDWORD pdwLength, PUCHAR pucValue)
{
RESPONSECODE rv = IFD_SUCCESS;
#ifndef PCSCLITE_STATIC_DRIVER
RESPONSECODE(*IFD_get_capabilities) (DWORD, PUCHAR) = NULL;
RESPONSECODE(*IFDH_get_capabilities) (DWORD, DWORD, PDWORD, PUCHAR) = NULL;
if (rContext->dwVersion == IFD_HVERSION_1_0)
IFD_get_capabilities =
rContext->psFunctions.psFunctions_v1.pvfGetCapabilities;
else
IFDH_get_capabilities =
rContext->psFunctions.psFunctions_v2.pvfGetCapabilities;
#endif
SYS_MutexLock(rContext->mMutex);
#ifndef PCSCLITE_STATIC_DRIVER
if (rContext->dwVersion == IFD_HVERSION_1_0)
rv = (*IFD_get_capabilities) (dwTag, pucValue);
else
rv = (*IFDH_get_capabilities) (rContext->dwSlot, dwTag,
pdwLength, pucValue);
#else
if (rContext->dwVersion == IFD_HVERSION_1_0)
rv = IFD_Get_Capabilities(dwTag, pucValue);
else
rv = IFDHGetCapabilities(rContext->dwSlot, dwTag, pdwLength,
pucValue);
#endif
SYS_MutexUnLock(rContext->mMutex);
return rv;
}
LONG IFDPowerICC(PREADER_CONTEXT rContext, DWORD dwAction,
const unsigned char *pucAtr, PDWORD pdwAtrLen)
{
RESPONSECODE rv;
short ret;
SMARTCARD_EXTENSION sSmartCard;
DWORD dwStatus;
UCHAR ucValue[1];
#ifndef PCSCLITE_STATIC_DRIVER
RESPONSECODE(*IFD_power_icc) (DWORD) = NULL;
RESPONSECODE(*IFDH_power_icc) (DWORD, DWORD, PUCHAR, PDWORD) = NULL;
#endif
rv = IFD_SUCCESS;
dwStatus = 0;
ucValue[0] = 0;
IFDStatusICC(rContext, &dwStatus, pucAtr, pdwAtrLen);
if (dwStatus & SCARD_ABSENT)
return SCARD_W_REMOVED_CARD;
#ifndef PCSCLITE_STATIC_DRIVER
if (rContext->dwVersion == IFD_HVERSION_1_0)
IFD_power_icc = rContext->psFunctions.psFunctions_v1.pvfPowerICC;
else
IFDH_power_icc = rContext->psFunctions.psFunctions_v2.pvfPowerICC;
#endif
SYS_MutexLock(rContext->mMutex);
#ifndef PCSCLITE_STATIC_DRIVER
if (rContext->dwVersion == IFD_HVERSION_1_0)
{
ucValue[0] = rContext->dwSlot;
IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
rv = (*IFD_power_icc) (dwAction);
}
else
{
rv = (*IFDH_power_icc) (rContext->dwSlot, dwAction,
(unsigned char *)pucAtr, pdwAtrLen);
ret = ATRDecodeAtr(&sSmartCard, pucAtr, *pdwAtrLen);
}
#else
if (rContext->dwVersion == IFD_HVERSION_1_0)
{
ucValue[0] = rContext->dwSlot;
IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
rv = IFD_Power_ICC(dwAction);
}
else
rv = IFDHPowerICC(rContext->dwSlot, dwAction, pucAtr, pdwAtrLen);
#endif
SYS_MutexUnLock(rContext->mMutex);
if (rv != IFD_SUCCESS)
{
*pdwAtrLen = 0;
if (rv == IFD_NO_SUCH_DEVICE)
{
return SCARD_E_READER_UNAVAILABLE;
}
return SCARD_E_NOT_TRANSACTED;
}
if (rContext->dwVersion == IFD_HVERSION_1_0)
IFDStatusICC(rContext, &dwStatus, pucAtr, pdwAtrLen);
return rv;
}
LONG IFDStatusICC(PREADER_CONTEXT rContext, PDWORD pdwStatus,
const unsigned char *pucAtr, PDWORD pdwAtrLen)
{
RESPONSECODE rv = IFD_SUCCESS;
DWORD dwTag = 0, dwCardStatus = 0;
SMARTCARD_EXTENSION sSmartCard;
UCHAR ucValue[1] = "\x00";
#ifndef PCSCLITE_STATIC_DRIVER
RESPONSECODE(*IFD_is_icc_present) () = NULL;
RESPONSECODE(*IFDH_icc_presence) (DWORD) = NULL;
RESPONSECODE(*IFD_get_capabilities) (DWORD, PUCHAR) = NULL;
if (rContext->dwVersion == IFD_HVERSION_1_0)
{
IFD_is_icc_present =
rContext->psFunctions.psFunctions_v1.pvfICCPresence;
IFD_get_capabilities =
rContext->psFunctions.psFunctions_v1.pvfGetCapabilities;
}
else
{
IFDH_icc_presence = rContext->psFunctions.psFunctions_v2.pvfICCPresence;
if (!IFDH_icc_presence)
return SCARD_E_SYSTEM_CANCELLED;
}
#endif
SYS_MutexLock(rContext->mMutex);
#ifndef PCSCLITE_STATIC_DRIVER
if (rContext->dwVersion == IFD_HVERSION_1_0)
{
ucValue[0] = rContext->dwSlot;
IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
rv = (*IFD_is_icc_present) ();
}
else
rv = (*IFDH_icc_presence) (rContext->dwSlot);
#else
if (rContext->dwVersion == IFD_HVERSION_1_0)
{
ucValue[0] = rContext->dwSlot;
IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
rv = IFD_Is_ICC_Present();
}
else
rv = IFDHICCPresence(rContext->dwSlot);
#endif
SYS_MutexUnLock(rContext->mMutex);
if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT)
dwCardStatus |= SCARD_PRESENT;
else
if (rv == IFD_ICC_NOT_PRESENT)
dwCardStatus |= SCARD_ABSENT;
else
{
Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
*pdwStatus = SCARD_UNKNOWN;
if (rv == IFD_NO_SUCH_DEVICE)
{
return SCARD_E_READER_UNAVAILABLE;
}
return SCARD_E_NOT_TRANSACTED;
}
if (rContext->dwVersion == IFD_HVERSION_1_0)
{
if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT)
{
short ret;
dwTag = TAG_IFD_ATR;
SYS_MutexLock(rContext->mMutex);
ucValue[0] = rContext->dwSlot;
IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
#ifndef PCSCLITE_STATIC_DRIVER
rv = (*IFD_get_capabilities) (dwTag, (unsigned char *)pucAtr);
#else
rv = IFD_Get_Capabilities(dwTag, pucAtr);
#endif
SYS_MutexUnLock(rContext->mMutex);
ret = ATRDecodeAtr(&sSmartCard, pucAtr, MAX_ATR_SIZE);
if (ret == 0)
*pdwAtrLen = 0;
else
*pdwAtrLen = sSmartCard.ATR.Length;
}
else
{
*pdwAtrLen = 0;
}
}
*pdwStatus = dwCardStatus;
return SCARD_S_SUCCESS;
}
LONG IFDControl_v2(PREADER_CONTEXT rContext, PUCHAR TxBuffer,
DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength)
{
RESPONSECODE rv = IFD_SUCCESS;
#ifndef PCSCLITE_STATIC_DRIVER
RESPONSECODE(*IFDH_control_v2) (DWORD, PUCHAR, DWORD, PUCHAR, PDWORD);
#endif
if (rContext->dwVersion != IFD_HVERSION_2_0)
return SCARD_E_UNSUPPORTED_FEATURE;
#ifndef PCSCLITE_STATIC_DRIVER
IFDH_control_v2 = rContext->psFunctions.psFunctions_v2.pvfControl;
#endif
SYS_MutexLock(rContext->mMutex);
#ifndef PCSCLITE_STATIC_DRIVER
rv = (*IFDH_control_v2) (rContext->dwSlot, TxBuffer, TxLength,
RxBuffer, RxLength);
#else
rv = IFDHControl_v2(rContext->dwSlot, TxBuffer, TxLength,
RxBuffer, RxLength);
#endif
SYS_MutexUnLock(rContext->mMutex);
if (rv == IFD_SUCCESS)
return SCARD_S_SUCCESS;
else
{
Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
return SCARD_E_NOT_TRANSACTED;
}
}
LONG IFDControl(PREADER_CONTEXT rContext, DWORD ControlCode,
LPCVOID TxBuffer, DWORD TxLength, LPVOID RxBuffer, DWORD RxLength,
LPDWORD BytesReturned)
{
RESPONSECODE rv = IFD_SUCCESS;
#ifndef PCSCLITE_STATIC_DRIVER
RESPONSECODE(*IFDH_control) (DWORD, DWORD, LPCVOID, DWORD, LPVOID, DWORD, LPDWORD);
#endif
if (rContext->dwVersion < IFD_HVERSION_3_0)
return SCARD_E_UNSUPPORTED_FEATURE;
#ifndef PCSCLITE_STATIC_DRIVER
IFDH_control = rContext->psFunctions.psFunctions_v3.pvfControl;
#endif
SYS_MutexLock(rContext->mMutex);
#ifndef PCSCLITE_STATIC_DRIVER
rv = (*IFDH_control) (rContext->dwSlot, ControlCode, TxBuffer,
TxLength, RxBuffer, RxLength, BytesReturned);
#else
rv = IFDHControl(rContext->dwSlot, ControlCode, TxBuffer,
TxLength, RxBuffer, RxLength, BytesReturned);
#endif
SYS_MutexUnLock(rContext->mMutex);
if (rv == IFD_SUCCESS)
return SCARD_S_SUCCESS;
else
{
Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
if (rv == IFD_NO_SUCH_DEVICE)
{
return SCARD_E_READER_UNAVAILABLE;
}
return SCARD_E_NOT_TRANSACTED;
}
}
LONG IFDTransmit(PREADER_CONTEXT rContext, SCARD_IO_HEADER pioTxPci,
PUCHAR pucTxBuffer, DWORD dwTxLength, PUCHAR pucRxBuffer,
PDWORD pdwRxLength, PSCARD_IO_HEADER pioRxPci)
{
RESPONSECODE rv = IFD_SUCCESS;
UCHAR ucValue[1] = "\x00";
#ifndef PCSCLITE_STATIC_DRIVER
RESPONSECODE(*IFD_transmit_to_icc) (SCARD_IO_HEADER, PUCHAR, DWORD,
PUCHAR, PDWORD, PSCARD_IO_HEADER) = NULL;
RESPONSECODE(*IFDH_transmit_to_icc) (DWORD, SCARD_IO_HEADER, PUCHAR,
DWORD, PUCHAR, PDWORD, PSCARD_IO_HEADER) = NULL;
#endif
DebugLogCategory(DEBUG_CATEGORY_APDU, pucTxBuffer, dwTxLength);
#ifndef PCSCLITE_STATIC_DRIVER
if (rContext->dwVersion == IFD_HVERSION_1_0)
IFD_transmit_to_icc =
rContext->psFunctions.psFunctions_v1.pvfTransmitToICC;
else
IFDH_transmit_to_icc =
rContext->psFunctions.psFunctions_v2.pvfTransmitToICC;
#endif
SYS_MutexLock(rContext->mMutex);
#ifndef PCSCLITE_STATIC_DRIVER
if (rContext->dwVersion == IFD_HVERSION_1_0)
{
ucValue[0] = rContext->dwSlot;
IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
rv = (*IFD_transmit_to_icc) (pioTxPci, (LPBYTE) pucTxBuffer,
dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci);
}
else
rv = (*IFDH_transmit_to_icc) (rContext->dwSlot, pioTxPci,
(LPBYTE) pucTxBuffer, dwTxLength,
pucRxBuffer, pdwRxLength, pioRxPci);
#else
if (rContext->dwVersion == IFD_HVERSION_1_0)
{
ucValue[0] = rContext->dwSlot;
IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
rv = IFD_Transmit_to_ICC(pioTxPci, (LPBYTE) pucTxBuffer,
dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci);
}
else
rv = IFDHTransmitToICC(rContext->dwSlot, pioTxPci,
(LPBYTE) pucTxBuffer, dwTxLength,
pucRxBuffer, pdwRxLength, pioRxPci);
#endif
SYS_MutexUnLock(rContext->mMutex);
DebugLogCategory(DEBUG_CATEGORY_SW, pucRxBuffer, *pdwRxLength);
if (rv == IFD_SUCCESS)
return SCARD_S_SUCCESS;
else
{
Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
if (rv == IFD_NO_SUCH_DEVICE)
{
return SCARD_E_READER_UNAVAILABLE;
}
return SCARD_E_NOT_TRANSACTED;
}
}