vpcd: allow *extended* length APDUs
- don't predefine any limits on the transceive size - fixes out of bounds access
This commit is contained in:
@@ -71,7 +71,7 @@ bool PipeReader::CheckATR() {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool PipeReader::QueryTransmit(BYTE *APDU,int APDUlen,BYTE *Resp,int *Resplen) {
|
bool PipeReader::QueryTransmit(BYTE *APDU,int APDUlen,BYTE **Resp,int *Resplen) {
|
||||||
//SectionLocker lock(dataSection);
|
//SectionLocker lock(dataSection);
|
||||||
|
|
||||||
if (pipe==NULL)
|
if (pipe==NULL)
|
||||||
@@ -97,7 +97,13 @@ bool PipeReader::QueryTransmit(BYTE *APDU,int APDUlen,BYTE *Resp,int *Resplen) {
|
|||||||
pipe=NULL;
|
pipe=NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!ReadFile(pipe,Resp,dwRespLen,&read,NULL)) {
|
BYTE *p=(BYTE *)realloc(*Resp, dwRespLen);
|
||||||
|
if (p==NULL) {
|
||||||
|
pipe=NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*Resp=p;
|
||||||
|
if (!ReadFile(pipe,*Resp,dwRespLen,&read,NULL)) {
|
||||||
pipe=NULL;
|
pipe=NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,25 +199,39 @@ void Reader::IoSmartCardTransmit(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T
|
|||||||
UNREFERENCED_PARAMETER(inBufSize);
|
UNREFERENCED_PARAMETER(inBufSize);
|
||||||
UNREFERENCED_PARAMETER(outBufSize);
|
UNREFERENCED_PARAMETER(outBufSize);
|
||||||
OutputDebugString(L"[BixVReader][TRSM]IOCTL_SMARTCARD_TRANSMIT");
|
OutputDebugString(L"[BixVReader][TRSM]IOCTL_SMARTCARD_TRANSMIT");
|
||||||
BYTE APDU[1000];
|
SCARD_IO_REQUEST *scardRequest=NULL;
|
||||||
int APDUSize;
|
int scardRequestSize=0;
|
||||||
getBuffer(pRequest,APDU,&APDUSize);
|
BYTE *RAPDU=NULL;
|
||||||
if (((SCARD_IO_REQUEST*)APDU)->dwProtocol!=protocol) {
|
int RAPDUSize=0;
|
||||||
|
if (!getBuffer(pRequest,(void **)&scardRequest,&scardRequestSize)
|
||||||
|
|| scardRequestSize<sizeof *scardRequest
|
||||||
|
|| scardRequest->dwProtocol!=protocol) {
|
||||||
SectionLocker lock(device->m_RequestLock);
|
SectionLocker lock(device->m_RequestLock);
|
||||||
pRequest->CompleteWithInformation(STATUS_INVALID_DEVICE_STATE, 0);
|
pRequest->CompleteWithInformation(STATUS_INVALID_DEVICE_STATE, 0);
|
||||||
return;
|
goto end;
|
||||||
}
|
}
|
||||||
BYTE Resp[1000];
|
if (!QueryTransmit((BYTE *)(scardRequest+1),
|
||||||
int RespSize;
|
scardRequestSize-sizeof(SCARD_IO_REQUEST),
|
||||||
if (!QueryTransmit(APDU+sizeof(SCARD_IO_REQUEST),APDUSize-sizeof(SCARD_IO_REQUEST),Resp+sizeof(SCARD_IO_REQUEST),&RespSize))
|
&RAPDU,&RAPDUSize))
|
||||||
{
|
{
|
||||||
SectionLocker lock(device->m_RequestLock);
|
SectionLocker lock(device->m_RequestLock);
|
||||||
pRequest->CompleteWithInformation(STATUS_NO_MEDIA, 0);
|
pRequest->CompleteWithInformation(STATUS_NO_MEDIA, 0);
|
||||||
return;
|
goto end;
|
||||||
}
|
}
|
||||||
((SCARD_IO_REQUEST*)Resp)->cbPciLength=sizeof(SCARD_IO_REQUEST);
|
SCARD_IO_REQUEST *p=(SCARD_IO_REQUEST *)realloc(scardRequest,RAPDUSize+sizeof(SCARD_IO_REQUEST));
|
||||||
((SCARD_IO_REQUEST*)Resp)->dwProtocol=protocol;
|
if (p==NULL) {
|
||||||
setBuffer(device,pRequest,Resp,RespSize+sizeof(SCARD_IO_REQUEST));
|
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) {
|
void Reader::IoSmartCardGetAttribute(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
|
||||||
@@ -345,7 +359,7 @@ bool Reader::CheckATR() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Reader::QueryTransmit(BYTE *APDU,int APDUlen,BYTE *Resp,int *Resplen) {
|
bool Reader::QueryTransmit(BYTE *APDU,int APDUlen,BYTE **Resp,int *Resplen) {
|
||||||
APDU;
|
APDU;
|
||||||
APDUlen;
|
APDUlen;
|
||||||
Resp;
|
Resp;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public:
|
|||||||
void IoSmartCardTransmit(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize);
|
void IoSmartCardTransmit(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize);
|
||||||
|
|
||||||
bool initProtocols();
|
bool initProtocols();
|
||||||
virtual bool QueryTransmit(BYTE *APDU,int APDUlen,BYTE *Resp,int *Resplen);
|
virtual bool QueryTransmit(BYTE *APDU,int APDUlen,BYTE **Resp,int *Resplen);
|
||||||
virtual bool QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset=false);
|
virtual bool QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset=false);
|
||||||
virtual bool CheckATR();
|
virtual bool CheckATR();
|
||||||
virtual DWORD startServer();
|
virtual DWORD startServer();
|
||||||
@@ -52,7 +52,7 @@ public:
|
|||||||
HANDLE eventpipe;
|
HANDLE eventpipe;
|
||||||
|
|
||||||
PipeReader();
|
PipeReader();
|
||||||
bool QueryTransmit(BYTE *APDU,int APDUlen,BYTE *Resp,int *Resplen);
|
bool QueryTransmit(BYTE *APDU,int APDUlen,BYTE **Resp,int *Resplen);
|
||||||
bool QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset=false);
|
bool QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset=false);
|
||||||
bool CheckATR();
|
bool CheckATR();
|
||||||
DWORD startServer();
|
DWORD startServer();
|
||||||
@@ -74,7 +74,7 @@ public:
|
|||||||
bool breakSocket;
|
bool breakSocket;
|
||||||
|
|
||||||
TcpIpReader();
|
TcpIpReader();
|
||||||
bool QueryTransmit(BYTE *APDU,int APDUlen,BYTE *Resp,int *Resplen);
|
bool QueryTransmit(BYTE *APDU,int APDUlen,BYTE **Resp,int *Resplen);
|
||||||
bool QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset=false);
|
bool QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset=false);
|
||||||
bool CheckATR();
|
bool CheckATR();
|
||||||
DWORD startServer();
|
DWORD startServer();
|
||||||
@@ -95,7 +95,7 @@ public:
|
|||||||
|
|
||||||
VpcdReader();
|
VpcdReader();
|
||||||
~VpcdReader();
|
~VpcdReader();
|
||||||
bool QueryTransmit(BYTE *APDU,int APDUlen,BYTE *Resp,int *Resplen);
|
bool QueryTransmit(BYTE *APDU,int APDUlen,BYTE **Resp,int *Resplen);
|
||||||
bool QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset=false);
|
bool QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset=false);
|
||||||
bool CheckATR();
|
bool CheckATR();
|
||||||
DWORD startServer();
|
DWORD startServer();
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ bool TcpIpReader::CheckATR() {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool TcpIpReader::QueryTransmit(BYTE *APDU,int APDUlen,BYTE *Resp,int *Resplen) {
|
bool TcpIpReader::QueryTransmit(BYTE *APDU,int APDUlen,BYTE **Resp,int *Resplen) {
|
||||||
//SectionLocker lock(dataSection);
|
//SectionLocker lock(dataSection);
|
||||||
if (AcceptSocket==NULL)
|
if (AcceptSocket==NULL)
|
||||||
return false;
|
return false;
|
||||||
@@ -73,7 +73,14 @@ bool TcpIpReader::QueryTransmit(BYTE *APDU,int APDUlen,BYTE *Resp,int *Resplen)
|
|||||||
AcceptSocket=NULL;
|
AcceptSocket=NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((read=recv(AcceptSocket,(char*)Resp,dwRespLen,MSG_WAITALL))<=0) {
|
BYTE *p=(BYTE *)realloc(*Resp, dwRespLen);
|
||||||
|
if (p==NULL) {
|
||||||
|
::shutdown(AcceptSocket,SD_BOTH);
|
||||||
|
AcceptSocket=NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*Resp=p;
|
||||||
|
if ((read=recv(AcceptSocket,(char*)*Resp,dwRespLen,MSG_WAITALL))<=0) {
|
||||||
::shutdown(AcceptSocket,SD_BOTH);
|
::shutdown(AcceptSocket,SD_BOTH);
|
||||||
AcceptSocket=NULL;
|
AcceptSocket=NULL;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -44,17 +44,13 @@ bool VpcdReader::CheckATR() {
|
|||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
bool VpcdReader::QueryTransmit(BYTE *APDU,int APDUlen,BYTE *Resp,int *Resplen) {
|
bool VpcdReader::QueryTransmit(BYTE *APDU,int APDUlen,BYTE **Resp,int *Resplen) {
|
||||||
unsigned char *rapdu = NULL;
|
|
||||||
ssize_t rapdu_len;
|
|
||||||
bool r = false;
|
bool r = false;
|
||||||
|
|
||||||
if (APDU && APDUlen && Resp && Resplen) {
|
if (APDU && APDUlen && Resplen) {
|
||||||
rapdu_len = vicc_transmit((struct vicc_ctx *) ctx, APDUlen, APDU, &rapdu);
|
ssize_t rapdu_len = vicc_transmit((struct vicc_ctx *) ctx, APDUlen, APDU, Resp);
|
||||||
if (rapdu_len > 0) {
|
if (rapdu_len > 0) {
|
||||||
memcpy(Resp, rapdu, rapdu_len);
|
|
||||||
*Resplen = rapdu_len;
|
*Resplen = rapdu_len;
|
||||||
free(rapdu);
|
|
||||||
r = true;
|
r = true;
|
||||||
} else {
|
} else {
|
||||||
signalRemoval();
|
signalRemoval();
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "SectionLocker.h"
|
#include "SectionLocker.h"
|
||||||
|
|
||||||
bool getBuffer(IWDFIoRequest* pRequest,BYTE *buffer,int *bufferLen) {
|
bool getBuffer(IWDFIoRequest* pRequest,void **buffer,int *bufferLen) {
|
||||||
|
|
||||||
IWDFMemory *inmem=NULL;
|
IWDFMemory *inmem=NULL;
|
||||||
pRequest->GetInputMemory(&inmem);
|
pRequest->GetInputMemory(&inmem);
|
||||||
if (inmem==NULL) {
|
if (inmem==NULL) {
|
||||||
@@ -12,13 +11,20 @@ bool getBuffer(IWDFIoRequest* pRequest,BYTE *buffer,int *bufferLen) {
|
|||||||
else {
|
else {
|
||||||
SIZE_T size;
|
SIZE_T size;
|
||||||
void *data=inmem->GetDataBuffer(&size);
|
void *data=inmem->GetDataBuffer(&size);
|
||||||
memcpy(buffer,data,size);
|
void *out = realloc(*buffer, size);
|
||||||
|
if (out==NULL) {
|
||||||
|
OutputDebugString(L"realloc failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(out,data,size);
|
||||||
(*bufferLen)=(int)size;
|
(*bufferLen)=(int)size;
|
||||||
|
(*buffer)=out;
|
||||||
inmem->Release();
|
inmem->Release();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void setBuffer(CMyDevice *device,IWDFIoRequest* pRequest,BYTE *result,int inSize) {
|
|
||||||
|
void setBuffer(CMyDevice *device,IWDFIoRequest* pRequest,void *result,int inSize) {
|
||||||
IWDFMemory *outmem=NULL;
|
IWDFMemory *outmem=NULL;
|
||||||
pRequest->GetOutputMemory (&outmem);
|
pRequest->GetOutputMemory (&outmem);
|
||||||
if (outmem==NULL) {
|
if (outmem==NULL) {
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
|
||||||
|
|
||||||
bool getBuffer(IWDFIoRequest* pRequest,BYTE *buffer,int *bufferLen);
|
bool getBuffer(IWDFIoRequest* pRequest,void **buffer,int *bufferLen);
|
||||||
void setString(CMyDevice *device,IWDFIoRequest* pRequest,char *result,int outSize);
|
void setString(CMyDevice *device,IWDFIoRequest* pRequest,char *result,int outSize);
|
||||||
void setBuffer(CMyDevice *device,IWDFIoRequest* pRequest,BYTE *result,int inSize);
|
void setBuffer(CMyDevice *device,IWDFIoRequest* pRequest,void *result,int inSize);
|
||||||
void setInt(CMyDevice *device,IWDFIoRequest* pRequest,DWORD result);
|
void setInt(CMyDevice *device,IWDFIoRequest* pRequest,DWORD result);
|
||||||
DWORD getInt(IWDFIoRequest* pRequest);
|
DWORD getInt(IWDFIoRequest* pRequest);
|
||||||
|
|||||||
Reference in New Issue
Block a user