VeraCrypt/src/Common/SCardLoader.cpp

402 lines
12 KiB
C++

#include "SCardLoader.h"
#include "PCSCException.h"
#ifndef TC_WINDOWS
#include <dlfcn.h>
#define LoadLibrary(x) dlopen(x, RTLD_NOW | RTLD_LOCAL)
#define FreeLibrary(x) dlclose(x)
#define GetProcAddress(x, y) dlsym(x, y)
typedef void* HMODULE;
#ifdef TC_MACOSX
#if !defined(USE_SCARD_CONTROL_112)
#define SCardControlName "SCardControl132"
#else
#define SCardControlName "SCardControl"
#endif
#else
#define SCardControlName "SCardControl"
#endif
#define SCardConnectName "SCardConnect"
#define SCardStatusName "SCardStatus"
#define SCardGetStatusChangeName "SCardGetStatusChange"
#define SCardListReaderGroupsName "SCardListReaderGroups"
#define SCardListReadersName "SCardListReaders"
#else
#define SCardControlName "SCardControl"
#define SCardConnectName "SCardConnectW"
#define SCardStatusName "SCardStatusW"
#define SCardGetStatusChangeName "SCardGetStatusChangeW"
#define SCardListReaderGroupsName "SCardListReaderGroupsW"
#define SCardListReadersName "SCardListReadersW"
#endif
using namespace std;
namespace VeraCrypt
{
HMODULE SCardLoader::hScardModule = NULL;
SCARDCONTEXT SCardLoader::hScardContext = 0;
SCardEstablishContextPtr SCardLoader::scardEstablishContext = NULL;
SCardReleaseContextPtr SCardLoader::scardReleaseContext = NULL;
SCardIsValidContextPtr SCardLoader::scardIsValidContext = NULL;
#ifndef TC_MACOSX
SCardFreeMemoryPtr SCardLoader::scardFreeMemory = NULL;
#endif
SCardConnectPtr SCardLoader::scardConnect = NULL;
SCardReconnectPtr SCardLoader::scardReconnect = NULL;
SCardDisconnectPtr SCardLoader::scardDisconnect = NULL;
SCardBeginTransactionPtr SCardLoader::scardBeginTransaction = NULL;
SCardEndTransactionPtr SCardLoader::scardEndTransaction = NULL;
SCardStatusPtr SCardLoader::scardStatus = NULL;
SCardGetStatusChangePtr SCardLoader::scardGetStatusChange = NULL;
SCardControlPtr SCardLoader::scardControl = NULL;
SCardTransmitPtr SCardLoader::scardTransmit = NULL;
SCardListReaderGroupsPtr SCardLoader::scardListReaderGroups = NULL;
SCardListReadersPtr SCardLoader::scardListReaders = NULL;
SCardCancelPtr SCardLoader::scardCancel = NULL;
SCardGetAttribPtr SCardLoader::scardGetAttrib = NULL;
SCardSetAttribPtr SCardLoader::scardSetAttrib = NULL;
SCARD_IO_REQUEST* SCardLoader::scardT0Pci = NULL;
SCARD_IO_REQUEST* SCardLoader::scardT1Pci = NULL;
SCARD_IO_REQUEST* SCardLoader::scardRawPci = NULL;
bool SCardLoader::bInitialized = false;
#ifdef TC_WINDOWS
wstring SCardLoader::GetSCardPath()
#else
string SCardLoader::GetSCardPath()
#endif
{
#ifdef TC_WINDOWS
wchar_t winscardPath[TC_MAX_PATH];
if (GetSystemDirectory(winscardPath, TC_MAX_PATH))
{
StringCbCat(winscardPath, sizeof(winscardPath), L"\\Winscard.dll");
}
else
StringCbCopy(winscardPath, sizeof(winscardPath), L"C:\\Windows\\System32\\Winscard.dll");
return winscardPath;
#elif TC_MACOSX
return "/System/Library/Frameworks/PCSC.framework/PCSC";
#else
string pcscPath = "";
FILE* pipe =
#ifdef TC_LINUX
popen("ldconfig -p", "r");
#else
popen("ldconfig -r", "r"); // FreeBSD
#endif
if (pipe)
{
char buffer[128];
while (!feof(pipe))
{
if (fgets(buffer, 128, pipe) != NULL)
{
string line(buffer);
if (line.find("libpcsclite.so") != string::npos)
{
size_t pos = line.find("=>");
if (pos != string::npos)
{
pcscPath = line.substr(pos + 3);
pos = pcscPath.find_first_of(" \t\r\n");
if (pos != string::npos)
pcscPath = pcscPath.substr(0, pos);
break;
}
}
}
}
pclose(pipe);
}
if (pcscPath == "")
{
pcscPath = "libpcsclite.so";
}
return pcscPath;
#endif
}
void SCardLoader::Initialize()
{
if (bInitialized)
return;
hScardModule = LoadLibrary(GetSCardPath().c_str());
if (hScardModule)
{
scardEstablishContext = (SCardEstablishContextPtr)GetProcAddress(hScardModule, "SCardEstablishContext");
scardReleaseContext = (SCardReleaseContextPtr)GetProcAddress(hScardModule, "SCardReleaseContext");
scardIsValidContext = (SCardIsValidContextPtr)GetProcAddress(hScardModule, "SCardIsValidContext");
#ifndef TC_MACOSX
scardFreeMemory = (SCardFreeMemoryPtr)GetProcAddress(hScardModule, "SCardFreeMemory");
#endif
scardConnect = (SCardConnectPtr)GetProcAddress(hScardModule, SCardConnectName);
scardReconnect = (SCardReconnectPtr)GetProcAddress(hScardModule, "SCardReconnect");
scardDisconnect = (SCardDisconnectPtr)GetProcAddress(hScardModule, "SCardDisconnect");
scardBeginTransaction = (SCardBeginTransactionPtr)GetProcAddress(hScardModule, "SCardBeginTransaction");
scardEndTransaction = (SCardEndTransactionPtr)GetProcAddress(hScardModule, "SCardEndTransaction");
scardStatus = (SCardStatusPtr)GetProcAddress(hScardModule, SCardStatusName);
scardGetStatusChange = (SCardGetStatusChangePtr)GetProcAddress(hScardModule, SCardGetStatusChangeName);
scardControl = (SCardControlPtr)GetProcAddress(hScardModule, SCardControlName);
scardTransmit = (SCardTransmitPtr)GetProcAddress(hScardModule, "SCardTransmit");
scardListReaderGroups = (SCardListReaderGroupsPtr)GetProcAddress(hScardModule, SCardListReaderGroupsName);
scardListReaders = (SCardListReadersPtr)GetProcAddress(hScardModule, SCardListReadersName);
scardCancel = (SCardCancelPtr)GetProcAddress(hScardModule, "SCardCancel");
scardGetAttrib = (SCardGetAttribPtr)GetProcAddress(hScardModule, "SCardGetAttrib");
scardSetAttrib = (SCardSetAttribPtr)GetProcAddress(hScardModule, "SCardSetAttrib");
scardT0Pci = (SCARD_IO_REQUEST*)GetProcAddress(hScardModule, "g_rgSCardT0Pci");
scardT1Pci = (SCARD_IO_REQUEST*)GetProcAddress(hScardModule, "g_rgSCardT1Pci");
scardRawPci = (SCARD_IO_REQUEST*)GetProcAddress(hScardModule, "g_rgSCardRawPci");
if (
#ifndef TC_MACOSX
scardFreeMemory &&
#endif
scardEstablishContext && scardReleaseContext && scardIsValidContext && scardConnect && scardReconnect && scardDisconnect &&
scardBeginTransaction && scardEndTransaction && scardStatus && scardGetStatusChange && scardControl && scardTransmit &&
scardListReaderGroups && scardListReaders && scardCancel && scardGetAttrib && scardSetAttrib && scardT0Pci && scardT1Pci && scardRawPci)
{
if (SCARD_S_SUCCESS == scardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hScardContext))
{
bInitialized = true;
}
}
}
if (!bInitialized)
{
Finalize();
}
}
void SCardLoader::Finalize()
{
if (hScardContext)
{
scardReleaseContext(hScardContext);
hScardContext = 0;
}
if (hScardModule)
{
FreeLibrary(hScardModule);
hScardModule = NULL;
}
scardEstablishContext = NULL;
scardReleaseContext = NULL;
scardIsValidContext = NULL;
#ifndef TC_MACOSX
scardFreeMemory = NULL;
#endif
scardConnect = NULL;
scardReconnect = NULL;
scardDisconnect = NULL;
scardBeginTransaction = NULL;
scardEndTransaction = NULL;
scardStatus = NULL;
scardGetStatusChange = NULL;
scardControl = NULL;
scardTransmit = NULL;
scardListReaderGroups = NULL;
scardListReaders = NULL;
scardCancel = NULL;
scardGetAttrib = NULL;
scardSetAttrib = NULL;
scardT0Pci = NULL;
scardT1Pci = NULL;
scardRawPci = NULL;
bInitialized = false;
}
SCARDCONTEXT SCardLoader::GetSCardContext()
{
return hScardContext;
}
LONG SCardLoader::SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardEstablishContext(dwScope, pvReserved1, pvReserved2, phContext);
}
LONG SCardLoader::SCardReleaseContext(SCARDCONTEXT hContext)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardReleaseContext(hContext);
}
LONG SCardLoader::SCardIsValidContext(SCARDCONTEXT hContext)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardIsValidContext(hContext);
}
#ifndef TC_MACOSX
LONG SCardLoader::SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardFreeMemory(hContext, pvMem);
}
#endif
LONG SCardLoader::SCardConnect(SCARDCONTEXT hContext, LPCTSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardConnect(hContext, szReader, dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol);
}
LONG SCardLoader::SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardReconnect(hCard, dwShareMode, dwPreferredProtocols, dwInitialization, pdwActiveProtocol);
}
LONG SCardLoader::SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardDisconnect(hCard, dwDisposition);
}
LONG SCardLoader::SCardBeginTransaction(SCARDHANDLE hCard)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardBeginTransaction(hCard);
}
LONG SCardLoader::SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardEndTransaction(hCard, dwDisposition);
}
LONG SCardLoader::SCardStatus(SCARDHANDLE hCard, LPTSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, BYTE* pbAtr, LPDWORD pcbAtrLen)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardStatus(hCard, mszReaderNames, pcchReaderLen, pdwState, pdwProtocol, pbAtr, pcbAtrLen);
}
LONG SCardLoader::SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, LPSCARD_READERSTATE rgReaderStates, DWORD cReaders)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardGetStatusChange(hContext, dwTimeout, rgReaderStates, cReaders);
}
LONG SCardLoader::SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardControl(hCard, dwControlCode, pbSendBuffer, cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned);
}
LONG SCardLoader::SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci, const BYTE* pbSendBuffer, DWORD cbSendLength, LPSCARD_IO_REQUEST pioRecvPci, BYTE* pbRecvBuffer, LPDWORD pcbRecvLength)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardTransmit(hCard, pioSendPci, pbSendBuffer, cbSendLength, pioRecvPci, pbRecvBuffer, pcbRecvLength);
}
LONG SCardLoader::SCardListReaderGroups(SCARDCONTEXT hContext, LPTSTR mszGroups, LPDWORD pcchGroups)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardListReaderGroups(hContext, mszGroups, pcchGroups);
}
LONG SCardLoader::SCardListReaders(SCARDCONTEXT hContext, LPCTSTR mszGroups, LPTSTR mszReaders, LPDWORD pcchReaders)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardListReaders(hContext, mszGroups, mszReaders, pcchReaders);
}
LONG SCardLoader::SCardCancel(SCARDCONTEXT hContext)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardCancel(hContext);
}
LONG SCardLoader::SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, BYTE* pbAttr, LPDWORD pcbAttrLen)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen);
}
LONG SCardLoader::SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, const BYTE* pbAttr, DWORD cbAttrLen)
{
Initialize();
if (!bInitialized)
throw ScardLibraryInitializationFailed();
return scardSetAttrib(hCard, dwAttrId, pbAttr, cbAttrLen);
}
}