Rename BixV Reader to VivoKey Smart Reader
This commit is contained in:
440
virtualsmartcard/win32/VivoKeySmartReader/Reader.cpp
Normal file
440
virtualsmartcard/win32/VivoKeySmartReader/Reader.cpp
Normal file
@@ -0,0 +1,440 @@
|
||||
#include "internal.h"
|
||||
#include "VirtualSCReader.h"
|
||||
#include "reader.h"
|
||||
#include "device.h"
|
||||
#include <winscard.h>
|
||||
#include "memory.h"
|
||||
#include <Sddl.h>
|
||||
#include "SectionLocker.h"
|
||||
|
||||
void Reader::init(wchar_t *section) {
|
||||
section;
|
||||
state=SCARD_ABSENT;
|
||||
}
|
||||
|
||||
void Reader::IoSmartCardIsPresent(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
|
||||
UNREFERENCED_PARAMETER(inBufSize);
|
||||
UNREFERENCED_PARAMETER(outBufSize);
|
||||
|
||||
OutputDebugString(L"[VivoKeySmartReader][IPRE]IOCTL_SMARTCARD_IS_PRESENT");
|
||||
if (CheckATR()) {
|
||||
// there's a smart card present, so complete the request
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(STATUS_SUCCESS, 0);
|
||||
}
|
||||
else {
|
||||
// there's no smart card present, so leave the request pending; it will be completed later
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
waitInsertIpr.push_back(pRequest);
|
||||
IRequestCallbackCancel *callback;
|
||||
device->QueryInterface(__uuidof(IRequestCallbackCancel),(void**)&callback);
|
||||
pRequest->MarkCancelable(callback);
|
||||
callback->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void Reader::IoSmartCardGetState(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
|
||||
UNREFERENCED_PARAMETER(inBufSize);
|
||||
UNREFERENCED_PARAMETER(outBufSize);
|
||||
OutputDebugString(L"[VivoKeySmartReader][GSTA]IOCTL_SMARTCARD_GET_STATE");
|
||||
wchar_t log[300];
|
||||
swprintf(log,L"[VivoKeySmartReader]STATE:%08X",state);
|
||||
OutputDebugString(log);
|
||||
setInt(device,pRequest,state);
|
||||
}
|
||||
void Reader::IoSmartCardIsAbsent(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
|
||||
UNREFERENCED_PARAMETER(inBufSize);
|
||||
UNREFERENCED_PARAMETER(outBufSize);
|
||||
OutputDebugString(L"[VivoKeySmartReader][IABS]IOCTL_SMARTCARD_IS_ABSENT");
|
||||
if (!CheckATR()) {
|
||||
// there's no smart card present, so complete the request
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(STATUS_SUCCESS, 0);
|
||||
}
|
||||
else {
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
// there's a smart card present, so leave the request pending; it will be completed later
|
||||
waitRemoveIpr.push_back(pRequest);
|
||||
IRequestCallbackCancel *callback;
|
||||
|
||||
device->QueryInterface(__uuidof(IRequestCallbackCancel),(void**)&callback);
|
||||
pRequest->MarkCancelable(callback);
|
||||
callback->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void Reader::IoSmartCardPower(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
|
||||
UNREFERENCED_PARAMETER(inBufSize);
|
||||
UNREFERENCED_PARAMETER(outBufSize);
|
||||
OutputDebugString(L"[VivoKeySmartReader][POWR]IOCTL_SMARTCARD_POWER");
|
||||
DWORD code=getInt(pRequest);
|
||||
if (code==SCARD_COLD_RESET) {
|
||||
OutputDebugString(L"[VivoKeySmartReader][POWR]SCARD_COLD_RESET");
|
||||
protocol=0;
|
||||
powered=1;
|
||||
state=SCARD_NEGOTIABLE;
|
||||
}
|
||||
else if (code==SCARD_WARM_RESET) {
|
||||
OutputDebugString(L"[VivoKeySmartReader][POWR]SCARD_WARM_RESET");
|
||||
protocol=0;
|
||||
powered=1;
|
||||
state=SCARD_NEGOTIABLE;
|
||||
}
|
||||
else if (code==SCARD_POWER_DOWN) {
|
||||
OutputDebugString(L"[VivoKeySmartReader][POWR]SCARD_POWER_DOWN");
|
||||
protocol=0;
|
||||
powered=0;
|
||||
state=SCARD_SWALLOWED;
|
||||
}
|
||||
if (code==SCARD_COLD_RESET || code==SCARD_WARM_RESET) {
|
||||
BYTE ATR[100];
|
||||
DWORD ATRsize;
|
||||
if (!QueryATR(ATR,&ATRsize,true))
|
||||
{
|
||||
pRequest->CompleteWithInformation(STATUS_NO_MEDIA, 0);
|
||||
return;
|
||||
}
|
||||
setBuffer(device,pRequest,ATR,ATRsize);
|
||||
}
|
||||
else {
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(STATUS_SUCCESS, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Reader::IoSmartCardSetProtocol(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
|
||||
UNREFERENCED_PARAMETER(inBufSize);
|
||||
UNREFERENCED_PARAMETER(outBufSize);
|
||||
UNREFERENCED_PARAMETER(instance);
|
||||
|
||||
DWORD requestedProtocol=getInt(pRequest);
|
||||
wchar_t log[300];
|
||||
swprintf(log,L"[VivoKeySmartReader][SPRT]IOCTL_SMARTCARD_SET_PROTOCOL:%08X",requestedProtocol);
|
||||
OutputDebugString(log);
|
||||
|
||||
BYTE ATR[100];
|
||||
DWORD ATRsize;
|
||||
state=SCARD_SPECIFIC;
|
||||
if (!QueryATR(ATR,&ATRsize,true))
|
||||
{
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(STATUS_NO_MEDIA, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (((requestedProtocol & SCARD_PROTOCOL_T1) != 0) &&
|
||||
((availableProtocol & SCARD_PROTOCOL_T1) != 0)) {
|
||||
protocol = SCARD_PROTOCOL_T1;
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(STATUS_SUCCESS, 0);
|
||||
OutputDebugString(L"[VivoKeySmartReader]PROTOCOL SET: T1");
|
||||
return;
|
||||
}
|
||||
|
||||
if (((requestedProtocol & SCARD_PROTOCOL_T0) != 0) &&
|
||||
((availableProtocol & SCARD_PROTOCOL_T0) != 0)) {
|
||||
protocol = SCARD_PROTOCOL_T0;
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(STATUS_SUCCESS, 0);
|
||||
OutputDebugString(L"[VivoKeySmartReader]PROTOCOL SET: T0");
|
||||
return;
|
||||
}
|
||||
|
||||
if (((requestedProtocol & (SCARD_PROTOCOL_DEFAULT)) != 0) &&
|
||||
((availableProtocol & SCARD_PROTOCOL_T1) != 0)) {
|
||||
protocol = SCARD_PROTOCOL_T1;
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(STATUS_SUCCESS, 0);
|
||||
OutputDebugString(L"[VivoKeySmartReader]PROTOCOL SET: T1");
|
||||
return;
|
||||
}
|
||||
|
||||
if (((requestedProtocol & (SCARD_PROTOCOL_DEFAULT)) != 0) &&
|
||||
((availableProtocol & SCARD_PROTOCOL_T0) != 0)) {
|
||||
protocol = SCARD_PROTOCOL_T0;
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(STATUS_SUCCESS, 0);
|
||||
OutputDebugString(L"[VivoKeySmartReader]PROTOCOL SET: T0");
|
||||
return;
|
||||
}
|
||||
{
|
||||
state=SCARD_NEGOTIABLE;
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Reader::IoSmartCardSetAttribute(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
|
||||
UNREFERENCED_PARAMETER(inBufSize);
|
||||
UNREFERENCED_PARAMETER(outBufSize);
|
||||
UNREFERENCED_PARAMETER(instance);
|
||||
OutputDebugString(L"[VivoKeySmartReader][SATT]IOCTL_SMARTCARD_SET_ATTRIBUTE");
|
||||
|
||||
IWDFMemory *inmem=NULL;
|
||||
pRequest->GetInputMemory(&inmem);
|
||||
|
||||
SIZE_T size;
|
||||
BYTE *data=(BYTE *)inmem->GetDataBuffer(&size);
|
||||
|
||||
DWORD minCode=*(DWORD*)(data);
|
||||
bool handled=false;
|
||||
if (minCode==SCARD_ATTR_DEVICE_IN_USE) {
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
OutputDebugString(L"[VivoKeySmartReader][SATT]SCARD_ATTR_DEVICE_IN_USE");
|
||||
pRequest->CompleteWithInformation(STATUS_SUCCESS, 0);
|
||||
handled=true;
|
||||
}
|
||||
inmem->Release();
|
||||
if (!handled) {
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
wchar_t log[300];
|
||||
swprintf(log,L"[VivoKeySmartReader][SATT]ERROR_NOT_SUPPORTED:%08X",minCode);
|
||||
OutputDebugString(log);
|
||||
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Reader::IoSmartCardTransmit(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
|
||||
UNREFERENCED_PARAMETER(inBufSize);
|
||||
UNREFERENCED_PARAMETER(outBufSize);
|
||||
OutputDebugString(L"[VivoKeySmartReader][TRSM]IOCTL_SMARTCARD_TRANSMIT");
|
||||
SCARD_IO_REQUEST *scardRequest=NULL;
|
||||
int scardRequestSize=0;
|
||||
BYTE *RAPDU=NULL;
|
||||
int RAPDUSize=0;
|
||||
if (!getBuffer(pRequest,(void **)&scardRequest,&scardRequestSize)
|
||||
|| scardRequestSize<sizeof *scardRequest
|
||||
|| scardRequest->dwProtocol!=protocol) {
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(STATUS_INVALID_DEVICE_STATE, 0);
|
||||
goto end;
|
||||
}
|
||||
if (!QueryTransmit((BYTE *)(scardRequest+1),
|
||||
scardRequestSize-sizeof(SCARD_IO_REQUEST),
|
||||
&RAPDU,&RAPDUSize))
|
||||
{
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(STATUS_NO_MEDIA, 0);
|
||||
goto end;
|
||||
}
|
||||
SCARD_IO_REQUEST *p=(SCARD_IO_REQUEST *)realloc(scardRequest,RAPDUSize+sizeof(SCARD_IO_REQUEST));
|
||||
if (p==NULL) {
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(STATUS_INVALID_DEVICE_STATE, 0);
|
||||
goto end;
|
||||
}
|
||||
scardRequest = p;
|
||||
scardRequest->cbPciLength=sizeof(SCARD_IO_REQUEST);
|
||||
scardRequest->dwProtocol=protocol;
|
||||
memcpy(scardRequest+1,RAPDU,RAPDUSize);
|
||||
setBuffer(device,pRequest,scardRequest,RAPDUSize+sizeof(SCARD_IO_REQUEST));
|
||||
end:
|
||||
free(scardRequest);
|
||||
free(RAPDU);
|
||||
}
|
||||
|
||||
void Reader::IoSmartCardGetAttribute(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
|
||||
UNREFERENCED_PARAMETER(inBufSize);
|
||||
|
||||
wchar_t log[300]=L"";
|
||||
char temp[300];
|
||||
|
||||
DWORD code=getInt(pRequest);
|
||||
swprintf(log,L"[VivoKeySmartReader][GATT] - code %0X",code);
|
||||
OutputDebugString(log);
|
||||
|
||||
switch(code) {
|
||||
case SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA009):
|
||||
// custom attribute; RPC_TYPE
|
||||
OutputDebugString(L"[VivoKeySmartReader][GATT]RPC_TYPE");
|
||||
setInt(device,pRequest,rpcType);
|
||||
return;
|
||||
case SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA00a):
|
||||
// custom attribute; PipeName
|
||||
if (rpcType==0) {
|
||||
PipeReader *pipe=(PipeReader *)this;
|
||||
OutputDebugString(L"[VivoKeySmartReader][GATT]PIPE_NAME");
|
||||
sprintf(temp,"%S",pipe->pipeName);
|
||||
setString(device,pRequest,(char*)temp,(int)outBufSize);
|
||||
}
|
||||
else {
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
|
||||
}
|
||||
return;
|
||||
case SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA00b):
|
||||
// custom attribute; EventPipeName
|
||||
if (rpcType==0) {
|
||||
PipeReader *pipe=(PipeReader *)this;
|
||||
OutputDebugString(L"[VivoKeySmartReader][GATT]EVENT_PIPE_NAME");
|
||||
sprintf(temp,"%S",pipe->pipeEventName);
|
||||
setString(device,pRequest,(char*)temp,(int)outBufSize);
|
||||
}
|
||||
else {
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
|
||||
}
|
||||
return;
|
||||
case SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA00c):
|
||||
// custom attribute; TCP port
|
||||
if (rpcType==1) {
|
||||
TcpIpReader *tcpIp=(TcpIpReader *)this;
|
||||
OutputDebugString(L"[VivoKeySmartReader][GATT]PORT");
|
||||
setInt(device,pRequest,tcpIp->port);
|
||||
}
|
||||
else {
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
|
||||
}
|
||||
return;
|
||||
case SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA00d):
|
||||
// custom attribute; TCP event port
|
||||
if (rpcType==1) {
|
||||
TcpIpReader *tcpIp=(TcpIpReader *)this;
|
||||
OutputDebugString(L"[VivoKeySmartReader][GATT]EVENT_PORT");
|
||||
setInt(device,pRequest,tcpIp->eventPort);
|
||||
}
|
||||
else {
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
|
||||
}
|
||||
return;
|
||||
case SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA00e):
|
||||
// custom attribute; TCP base port
|
||||
if (rpcType==1) {
|
||||
TcpIpReader *tcpIp=(TcpIpReader *)this;
|
||||
OutputDebugString(L"[VivoKeySmartReader][GATT]BASE_PORT");
|
||||
setInt(device,pRequest,tcpIp->portBase);
|
||||
tcpIp;
|
||||
}
|
||||
else {
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
|
||||
}
|
||||
return;
|
||||
case SCARD_ATTR_CHARACTERISTICS:
|
||||
// 0x00000000 No special characteristics
|
||||
OutputDebugString(L"[VivoKeySmartReader][GATT]SCARD_ATTR_CHARACTERISTICS");
|
||||
setInt(device,pRequest,0);
|
||||
return;
|
||||
case SCARD_ATTR_VENDOR_NAME:
|
||||
OutputDebugString(L"[VivoKeySmartReader][GATT]SCARD_ATTR_VENDOR_NAME");
|
||||
setString(device,pRequest,vendorName,(int)outBufSize);
|
||||
return;
|
||||
case SCARD_ATTR_VENDOR_IFD_TYPE:
|
||||
OutputDebugString(L"[VivoKeySmartReader][GATT]SCARD_ATTR_VENDOR_IFD_TYPE");
|
||||
setString(device,pRequest,vendorIfdType,(int)outBufSize);
|
||||
return;
|
||||
case SCARD_ATTR_DEVICE_UNIT:
|
||||
OutputDebugString(L"[VivoKeySmartReader][GATT]SCARD_ATTR_DEVICE_UNIT");
|
||||
setInt(device,pRequest,deviceUnit);
|
||||
return;
|
||||
case SCARD_ATTR_ATR_STRING:
|
||||
OutputDebugString(L"[VivoKeySmartReader][GATT]SCARD_ATTR_ATR_STRING");
|
||||
BYTE ATR[100];
|
||||
DWORD ATRsize;
|
||||
if (!QueryATR(ATR,&ATRsize))
|
||||
{
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(STATUS_NO_MEDIA, 0);
|
||||
return;
|
||||
}
|
||||
setBuffer(device,pRequest,ATR,ATRsize);
|
||||
return;
|
||||
case SCARD_ATTR_CURRENT_PROTOCOL_TYPE:
|
||||
OutputDebugString(L"[VivoKeySmartReader][GATT]SCARD_ATTR_CURRENT_PROTOCOL_TYPE");
|
||||
setInt(device,pRequest,protocol); // T=0 or T=1
|
||||
return;
|
||||
default: {
|
||||
swprintf(log,L"[VivoKeySmartReader][GATT]ERROR_NOT_SUPPORTED:%08X",code);
|
||||
OutputDebugString(log);
|
||||
SectionLocker lock(device->m_RequestLock);
|
||||
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Reader::CheckATR() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Reader::QueryTransmit(BYTE *APDU,int APDUlen,BYTE **Resp,int *Resplen) {
|
||||
APDU;
|
||||
APDUlen;
|
||||
Resp;
|
||||
Resplen;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Reader::QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset) {
|
||||
ATR;
|
||||
ATRsize;
|
||||
reset;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Reader::initProtocols() {
|
||||
// ask ATR to determine available protocols
|
||||
BYTE ATR[100];
|
||||
DWORD ATRsize=100;
|
||||
availableProtocol=0;
|
||||
if (QueryATR(ATR,&ATRsize,true))
|
||||
{
|
||||
availableProtocol=0;
|
||||
int iNumHistBytes=0;
|
||||
int iTotHistBytes=0;
|
||||
int y=0;
|
||||
int block=1;
|
||||
bool isHist=false;
|
||||
char let='A';
|
||||
for (unsigned int i=0;i<ATRsize && ! isHist;i++) {
|
||||
if (i==0) {
|
||||
// we are in TS
|
||||
}
|
||||
else if (i==1) {
|
||||
// we are in T0; read number of historical bytes
|
||||
let='A';
|
||||
y=ATR[i] >> 4;
|
||||
iTotHistBytes=ATR[i] & 0xF;
|
||||
}
|
||||
else {
|
||||
while ((y & 1)==0) {
|
||||
let++;
|
||||
y>>=1;
|
||||
if (y==0) {
|
||||
isHist=true;
|
||||
iNumHistBytes=1;
|
||||
i--;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
// we are in T(let)(block)
|
||||
y=y & 0xE;
|
||||
if (let=='D') {
|
||||
// check available protocol(s)
|
||||
protocol=(ATR[i] & 0x0f);
|
||||
availableProtocol|=1 << protocol;
|
||||
// prepare for next block
|
||||
let='A';
|
||||
y=ATR[i] >> 4;
|
||||
block++;
|
||||
}
|
||||
}
|
||||
end:
|
||||
;
|
||||
}
|
||||
//support at least T=0
|
||||
if (availableProtocol==0)
|
||||
availableProtocol=1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD Reader::startServer() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Reader::shutdown() {
|
||||
}
|
||||
Reference in New Issue
Block a user