130 lines
3.8 KiB
C
130 lines
3.8 KiB
C
|
/* Benjamin DELPY `gentilkiwi`
|
||
|
http://blog.gentilkiwi.com
|
||
|
benjamin@gentilkiwi.com
|
||
|
Licence : https://creativecommons.org/licenses/by/4.0/
|
||
|
*/
|
||
|
#include "kull_m_acr.h"
|
||
|
|
||
|
BOOL kull_m_acr_init(SCARDCONTEXT hContext, LPCWSTR szReaderName, BOOL withoutCard, LPVOID suppdata, BOOL descr, PKULL_M_ACR_COMM comm)
|
||
|
{
|
||
|
BOOL status = FALSE;
|
||
|
DWORD dwActiveProtocol;
|
||
|
LONG scStatus;
|
||
|
comm->hCard = 0;
|
||
|
comm->withoutCard = withoutCard;
|
||
|
comm->suppdata = suppdata;
|
||
|
comm->descr = descr;
|
||
|
scStatus = SCardConnect(hContext, szReaderName, withoutCard ? SCARD_SHARE_DIRECT : SCARD_SHARE_SHARED, withoutCard ? SCARD_PROTOCOL_UNDEFINED : SCARD_PROTOCOL_Tx, &comm->hCard, &dwActiveProtocol);
|
||
|
if(!(status = (scStatus == SCARD_S_SUCCESS)))
|
||
|
PRINT_ERROR(L"SCardConnect: 0x%08x\n", scStatus);
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
void kull_m_acr_finish(PKULL_M_ACR_COMM comm)
|
||
|
{
|
||
|
LONG scStatus;
|
||
|
if(comm->hCard)
|
||
|
{
|
||
|
scStatus = SCardDisconnect(comm->hCard, SCARD_LEAVE_CARD);
|
||
|
if(scStatus == SCARD_S_SUCCESS)
|
||
|
comm->hCard = 0;
|
||
|
else PRINT_ERROR(L"SCardDisconnect: 0x%08x\n", scStatus);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL kull_m_arc_sendrecv(PKULL_M_ACR_COMM comm, const BYTE *pbData, const UINT16 cbData, BYTE *pbResult, UINT16 *cbResult)
|
||
|
{
|
||
|
BOOL status = FALSE;
|
||
|
LONG scStatus;
|
||
|
DWORD ret = *cbResult;
|
||
|
|
||
|
if(comm->hCard)
|
||
|
{
|
||
|
if(cbData <= ACR_MAX_LEN)
|
||
|
{
|
||
|
if(comm->descr)
|
||
|
{
|
||
|
kprintf(L"ACR > ");
|
||
|
kull_m_string_wprintf_hex(pbData, cbData, 1);
|
||
|
kprintf(L"\n");
|
||
|
}
|
||
|
scStatus = comm->withoutCard ?
|
||
|
SCardControl(comm->hCard, IOCTL_CCID_ESCAPE, pbData, cbData, pbResult, *cbResult, &ret) :
|
||
|
SCardTransmit(comm->hCard, NULL, pbData, cbData, NULL, pbResult, &ret);
|
||
|
|
||
|
if(scStatus == SCARD_S_SUCCESS)
|
||
|
{
|
||
|
if(comm->descr)
|
||
|
{
|
||
|
kprintf(L"ACR < ");
|
||
|
kull_m_string_wprintf_hex(pbResult, ret, 1);
|
||
|
kprintf(L"\n");
|
||
|
}
|
||
|
if(status = (ret <= *cbResult))
|
||
|
*cbResult = (UINT16) ret;
|
||
|
}
|
||
|
else PRINT_ERROR(L"%s: 0x%08x\n", comm->withoutCard ? L"SCardControl" : L"SCardTransmit", scStatus);
|
||
|
}
|
||
|
else PRINT_ERROR(L"cbData = %hu / cbResult = %hu (max is %hu)\n", cbData, cbResult, ACR_MAX_LEN);
|
||
|
}
|
||
|
else PRINT_ERROR(L"No handle to Card\n");
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
BOOL kull_m_acr_sendrecv_ins(PKULL_M_ACR_COMM comm, BYTE cla, BYTE ins, BYTE p1, BYTE p2, const BYTE *pbData, const UINT16 cbData, BYTE *pbResult, UINT16 *cbResult, BOOL noLe)
|
||
|
{
|
||
|
BOOL status = FALSE;
|
||
|
BYTE buffer[ACR_MAX_LEN], idx = 4;
|
||
|
//BYTE max = sizeof(buffer) - idx -
|
||
|
// CHECK SIZES !
|
||
|
buffer[0] = cla;
|
||
|
buffer[1] = ins;
|
||
|
buffer[2] = p1;
|
||
|
buffer[3] = p2;
|
||
|
|
||
|
if(cbData)
|
||
|
{
|
||
|
buffer[idx++] = (BYTE) cbData;
|
||
|
RtlCopyMemory(buffer + idx, pbData, cbData);
|
||
|
idx += cbData;
|
||
|
}
|
||
|
if(!noLe && *cbResult)
|
||
|
buffer[idx++] = (BYTE) *cbResult;
|
||
|
return kull_m_arc_sendrecv(comm, buffer, idx, pbResult, cbResult);
|
||
|
}
|
||
|
|
||
|
BOOL CALLBACK kull_m_arcr_SendRecvDirect(const BYTE *pbData, const UINT16 cbData, BYTE *pbResult, UINT16 *cbResult, LPVOID suppdata)
|
||
|
{
|
||
|
BOOL status = FALSE;
|
||
|
BYTE buffer[ACR_MAX_LEN];
|
||
|
UINT16 cbOut = *cbResult + 2;
|
||
|
|
||
|
if(suppdata)
|
||
|
{
|
||
|
if(cbOut <= sizeof(buffer))
|
||
|
{
|
||
|
if(kull_m_acr_sendrecv_ins((PKULL_M_ACR_COMM) suppdata, 0xff, 0x00, 0x00, 0x00, pbData, cbData, buffer, &cbOut, TRUE))
|
||
|
{
|
||
|
if(cbOut >= 2)
|
||
|
{
|
||
|
if(*(PUINT16) (buffer + cbOut - 2) == 0x0090)
|
||
|
{
|
||
|
cbOut -= 2;
|
||
|
if(status = (cbOut <= *cbResult))
|
||
|
{
|
||
|
RtlCopyMemory(pbResult, buffer, cbOut);
|
||
|
*cbResult = cbOut;
|
||
|
}
|
||
|
else PRINT_ERROR(L"cbResult = %hu (data is %u)\n", *cbResult, cbOut);
|
||
|
}
|
||
|
else PRINT_ERROR(L"RET: %02x %02x\n", buffer[cbOut - 2], buffer[cbOut - 1]);
|
||
|
}
|
||
|
else PRINT_ERROR(L"cbRetBuffer = %hu (not long enough)\n", cbOut);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else PRINT_ERROR(L"cbOut = %hu (max is %hu)\n", cbOut, sizeof(buffer));
|
||
|
}
|
||
|
else PRINT_ERROR(L"No suppdata (ACR_COMM)\n");
|
||
|
return status;
|
||
|
}
|