Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

561 lines
13 KiB

#include <windows.h>
#include <wincrypt.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "basecsp.h"
#include "cardmod.h"
#include <dsysdbg.h>
#define wszTEST_CARD L"Wfsc Demo 3\0"
#define cMAX_READERS 20
//
// Need to define the dsys debug symbols since we're linking directly to the
// card interface lib which requires them.
//
DEFINE_DEBUG2(Basecsp)
//
// Functions defined in the card interface lib that we call.
//
extern DWORD InitializeCardState(PCARD_STATE);
extern void DeleteCardState(PCARD_STATE);
//
// Wrapper for making test calls.
//
#define TEST_CASE(X) { if (ERROR_SUCCESS != (dwSts = X)) { printf("%s", #X); goto Ret; } }
//
// Function: CspAllocH
//
LPVOID WINAPI CspAllocH(
IN SIZE_T cBytes)
{
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cBytes);
}
//
// Function: CspFreeH
//
void WINAPI CspFreeH(
IN LPVOID pMem)
{
HeapFree(GetProcessHeap(), 0, pMem);
}
//
// Function: CspReAllocH
//
LPVOID WINAPI CspReAllocH(
IN LPVOID pMem,
IN SIZE_T cBytes)
{
return HeapReAlloc(
GetProcessHeap(), HEAP_ZERO_MEMORY, pMem, cBytes);
}
//
// Critical Section Management
//
//
// Function: CspInitializeCriticalSection
//
DWORD CspInitializeCriticalSection(
IN CRITICAL_SECTION *pcs)
{
__try {
InitializeCriticalSection(pcs);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
return ERROR_NOT_ENOUGH_MEMORY;
}
return ERROR_SUCCESS;
}
//
// Function: CspEnterCriticalSection
//
DWORD CspEnterCriticalSection(
IN CRITICAL_SECTION *pcs)
{
__try {
EnterCriticalSection(pcs);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
return ERROR_NOT_ENOUGH_MEMORY;
}
return ERROR_SUCCESS;
}
//
// Function: CspLeaveCriticalSection
//
void CspLeaveCriticalSection(
IN CRITICAL_SECTION *pcs)
{
LeaveCriticalSection(pcs);
}
//
// Function: CspDeleteCriticalSection
//
void CspDeleteCriticalSection(
IN CRITICAL_SECTION *pcs)
{
DeleteCriticalSection(pcs);
}
int _cdecl main(int argc, char * argv[])
{
CARD_STATE CardState;
PCARD_DATA pCardData;
DWORD dwSts = ERROR_SUCCESS;
PFN_CARD_ACQUIRE_CONTEXT pfnCardAcquireContext = NULL;
CARD_FREE_SPACE_INFO CardFreeSpaceInfo;
CARD_CAPABILITIES CardCapabilities;
CARD_KEY_SIZES CardKeySizes;
CONTAINER_INFO ContainerInfo;
LPWSTR pwsz = NULL;
DATA_BLOB dbOut;
BYTE rgb [] = { 0x3, 0x2, 0x1, 0x0 };
DATA_BLOB dbIn;
SCARDCONTEXT hContext = 0;
LPWSTR mszReaders = NULL;
DWORD cchReaders = SCARD_AUTOALLOCATE;
LPWSTR mszCards = NULL;
DWORD cchCards = SCARD_AUTOALLOCATE;
SCARD_READERSTATE rgReaderState [cMAX_READERS];
DWORD iReader = 0;
DWORD cchCurrent = 0;
DWORD dwProtocol = 0;
SCARDHANDLE hCard = 0;
BOOL fConnected = FALSE;
CARD_FILE_ACCESS_CONDITION Acl = EveryoneReadUserWriteAc;
BYTE rgbPin [] = { 0x00, 0x00, 0x00, 0x00 };
DATA_BLOB dbPin;
PBYTE pbKey = NULL;
DWORD cbKey = 0;
HCRYPTKEY hKey = 0;
HCRYPTPROV hProv = 0;
WCHAR rgwsz [MAX_PATH];
BYTE bContainerIndex = 0;
memset(&CardState, 0, sizeof(CardState));
memset(&CardFreeSpaceInfo, 0, sizeof(CardFreeSpaceInfo));
memset(&CardCapabilities, 0, sizeof(CardCapabilities));
memset(&ContainerInfo, 0, sizeof(ContainerInfo));
memset(&CardKeySizes, 0, sizeof(CardKeySizes));
memset(&dbOut, 0, sizeof(dbOut));
memset(rgReaderState, 0, sizeof(rgReaderState));
memset(&dbPin, 0, sizeof(dbPin));
dbPin.cbData = sizeof(rgbPin);
dbPin.pbData = rgbPin;
dbIn.cbData = sizeof(rgb);
dbIn.pbData = rgb;
//
// Initialization
//
//
// Get a list of readers
//
dwSts = SCardEstablishContext(
SCARD_SCOPE_USER, NULL, NULL, &hContext);
if (ERROR_SUCCESS != dwSts)
goto Ret;
dwSts = SCardListReaders(
hContext,
NULL,
(LPWSTR) &mszReaders,
&cchReaders);
if (ERROR_SUCCESS != dwSts)
goto Ret;
//
// Get a list of cards
//
/*
dwSts = SCardListCards(
hContext, NULL, NULL, 0, (LPWSTR) &mszCards, &cchCards);
if (ERROR_SUCCESS != dwSts)
goto Ret;
*/
//
// Build the reader state array
//
for ( iReader = 0, cchReaders = 0;
iReader < (sizeof(rgReaderState) / sizeof(rgReaderState[0]))
&&
L'\0' != mszReaders[cchReaders];
iReader++)
{
rgReaderState[iReader].dwCurrentState = SCARD_STATE_UNAWARE;
rgReaderState[iReader].szReader = mszReaders + cchReaders;
cchReaders += 1 + wcslen(mszReaders);
}
//
// Find a card we can talk to
//
dwSts = SCardLocateCards(
hContext,
wszTEST_CARD,
rgReaderState,
iReader);
if (ERROR_SUCCESS != dwSts)
goto Ret;
while (0 != iReader && FALSE == fConnected)
{
iReader--;
if (SCARD_STATE_ATRMATCH & rgReaderState[iReader].dwEventState)
{
dwSts = SCardConnect(
hContext,
rgReaderState[iReader].szReader,
SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
&hCard,
&dwProtocol);
if (ERROR_SUCCESS != dwSts)
goto Ret;
else
fConnected = TRUE;
}
}
if (FALSE == fConnected)
goto Ret;
//
// Initialize the card data structures
//
TEST_CASE(InitializeCardState(&CardState));
CardState.hCardModule = LoadLibrary(L"cardmod.dll");
if (INVALID_HANDLE_VALUE == CardState.hCardModule)
{
printf("LoadLibrary cardmod.dll");
dwSts = GetLastError();
goto Ret;
}
pfnCardAcquireContext =
(PFN_CARD_ACQUIRE_CONTEXT) GetProcAddress(
CardState.hCardModule,
"CardAcquireContext");
if (NULL == pfnCardAcquireContext)
{
printf("GetProcAddress");
dwSts = GetLastError();
goto Ret;
}
pCardData = (PCARD_DATA) CspAllocH(sizeof(CARD_DATA));
if (NULL == pCardData)
{
dwSts = ERROR_NOT_ENOUGH_MEMORY;
goto Ret;
}
pCardData->pwszCardName = wszTEST_CARD;
pCardData->hScard = hCard;
pCardData->hSCardCtx = hContext;
pCardData->dwVersion = CARD_DATA_CURRENT_VERSION;
pCardData->pfnCspAlloc = CspAllocH;
pCardData->pfnCspReAlloc = CspReAllocH;
pCardData->pfnCspFree = CspFreeH;
pCardData->pbAtr = rgReaderState[iReader].rgbAtr;
pCardData->cbAtr = rgReaderState[iReader].cbAtr;
TEST_CASE(pfnCardAcquireContext(pCardData, 0));
CardState.pCardData = pCardData;
TEST_CASE(InitializeCspCaching(&CardState));
//
// Now start tests
//
//
// Test 1: Container data caching
//
/*
TEST_CASE(CspEnumContainers(&CardState, 0, &pwsz));
CspFreeH(pwsz);
pwsz = NULL;
// Check cached call
TEST_CASE(CspEnumContainers(&CardState, 0, &pwsz));
CspFreeH(pwsz);
pwsz = NULL;
*/
//
// Create a private key blob to import to the card
//
if (! CryptAcquireContext(
&hProv, NULL, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
dwSts = GetLastError();
goto Ret;
}
//
// For now, make this key really small so we're sure to not run out of
// space on wimpy test cards.
//
if (! CryptGenKey(
hProv, AT_KEYEXCHANGE, (384 << 16) | CRYPT_EXPORTABLE, &hKey))
{
dwSts = GetLastError();
goto Ret;
}
if (! CryptExportKey(
hKey, 0, PRIVATEKEYBLOB, 0, NULL, &cbKey))
{
dwSts = GetLastError();
goto Ret;
}
pbKey = (PBYTE) CspAllocH(cbKey);
if (NULL == pbKey)
{
dwSts = ERROR_NOT_ENOUGH_MEMORY;
goto Ret;
}
if (! CryptExportKey(
hKey, 0, PRIVATEKEYBLOB, 0, pbKey, &cbKey))
{
dwSts = GetLastError();
goto Ret;
}
//
// Now we'll be modifying card data, so we need to authenticate.
//
TEST_CASE(CspSubmitPin(
&CardState,
wszCARD_USER_USER,
dbPin.pbData,
dbPin.cbData,
NULL));
// CreateContainer call will invalidate current container-space cache items
TEST_CASE(CspCreateContainer(
&CardState,
bContainerIndex,
CARD_CREATE_CONTAINER_KEY_IMPORT,
AT_KEYEXCHANGE,
cbKey,
pbKey));
// Cached container enum should now be invalid
/*
TEST_CASE(CspEnumContainers(&CardState, 0, &pwsz));
CspFreeH(pwsz);
pwsz = NULL;
*/
//
// Test 2: File data caching
//
/*
TODO - re-enabled the EnumFiles tests once CardEnumFiles is correctly
implemented
pwsz = wszCSP_DATA_DIR_FULL_PATH;
TEST_CASE(CspEnumFiles(&CardState, 0, &pwsz));
CspFreeH(pwsz);
pwsz = NULL;
// Use cached data
pwsz = wszCSP_DATA_DIR_FULL_PATH;
TEST_CASE(CspEnumFiles(&CardState, 0, &pwsz));
CspFreeH(pwsz);
pwsz = NULL;
*/
// Create some test files just in case they don't already exist on
// this card.
wsprintf(
rgwsz, L"%s/File2", wszCSP_DATA_DIR_FULL_PATH);
dwSts = CspCreateFile(&CardState, rgwsz, Acl);
wsprintf(
rgwsz, L"%s/File1", wszCSP_DATA_DIR_FULL_PATH);
dwSts = CspCreateFile(&CardState, rgwsz, Acl);
// Write file should invalidate all cached file data
TEST_CASE(CspWriteFile(&CardState, rgwsz, 0, dbIn.pbData, dbIn.cbData));
// Invalidate cached file we just created
TEST_CASE(CspWriteFile(&CardState, rgwsz, 0, dbIn.pbData, dbIn.cbData));
// Cached file enum should now be invalid
/*
pwsz = wszCSP_DATA_DIR_FULL_PATH;
TEST_CASE(CspEnumFiles(&CardState, 0, &pwsz));
CspFreeH(pwsz);
pwsz = NULL;
*/
//
// Test 3: Get container info
//
ContainerInfo.dwVersion = CONTAINER_INFO_CURRENT_VERSION;
TEST_CASE(CspGetContainerInfo(&CardState, bContainerIndex, 0, &ContainerInfo));
// Caller won't free the key data buffers. Leave them for final cleanup.
if (ContainerInfo.pbKeyExPublicKey)
CspFreeH(ContainerInfo.pbKeyExPublicKey);
ContainerInfo.pbKeyExPublicKey = NULL;
if (ContainerInfo.pbSigPublicKey)
CspFreeH(ContainerInfo.pbSigPublicKey);
ContainerInfo.pbSigPublicKey = NULL;
// Use cached data
TEST_CASE(CspGetContainerInfo(&CardState, bContainerIndex, 0, &ContainerInfo));
if (ContainerInfo.pbKeyExPublicKey)
CspFreeH(ContainerInfo.pbKeyExPublicKey);
ContainerInfo.pbKeyExPublicKey = NULL;
if (ContainerInfo.pbSigPublicKey)
CspFreeH(ContainerInfo.pbSigPublicKey);
ContainerInfo.pbSigPublicKey = NULL;
//
// Test 4: Get Card Capabilities
//
CardCapabilities.dwVersion = CARD_CAPABILITIES_CURRENT_VERSION;
TEST_CASE(CspQueryCapabilities(&CardState, &CardCapabilities));
// Read cached
TEST_CASE(CspQueryCapabilities(&CardState, &CardCapabilities));
//
// Test 5: Read file
//
wsprintf(
rgwsz, L"%s/File1", wszCSP_DATA_DIR_FULL_PATH);
TEST_CASE(CspReadFile(&CardState, rgwsz, 0, &dbOut.pbData, &dbOut.cbData));
CspFreeH(dbOut.pbData);
memset(&dbOut, 0, sizeof(dbOut));
// Use cached data
TEST_CASE(CspReadFile(&CardState, rgwsz, 0, &dbOut.pbData, &dbOut.cbData));
CspFreeH(dbOut.pbData);
memset(&dbOut, 0, sizeof(dbOut));
wsprintf(
rgwsz, L"%s/File2", wszCSP_DATA_DIR_FULL_PATH);
// Invalidate all file-related cached data
TEST_CASE(CspDeleteFile(&CardState, 0, rgwsz));
wsprintf(
rgwsz, L"%s/File1", wszCSP_DATA_DIR_FULL_PATH);
// Re-read file from card
TEST_CASE(CspReadFile(&CardState, rgwsz, 0, &dbOut.pbData, &dbOut.cbData));
CspFreeH(dbOut.pbData);
memset(&dbOut, 0, sizeof(dbOut));
//
// Test 6: Query Key Sizes
//
CardKeySizes.dwVersion = CARD_KEY_SIZES_CURRENT_VERSION;
// Signature Keys
TEST_CASE(CspQueryKeySizes(&CardState, AT_SIGNATURE, 0, &CardKeySizes));
// Query cached
TEST_CASE(CspQueryKeySizes(&CardState, AT_SIGNATURE, 0, &CardKeySizes));
// Key Exchange Keys
TEST_CASE(CspQueryKeySizes(&CardState, AT_KEYEXCHANGE, 0, &CardKeySizes));
// Query cached
TEST_CASE(CspQueryKeySizes(&CardState, AT_KEYEXCHANGE, 0, &CardKeySizes));
Ret:
if (pbKey)
CspFreeH(pbKey);
if (hKey)
CryptDestroyKey(hKey);
if (hProv)
CryptReleaseContext(hProv, 0);
if (mszCards)
SCardFreeMemory(hContext, mszCards);
if (mszReaders)
SCardFreeMemory(hContext, mszReaders);
if (dbOut.pbData)
CspFreeH(dbOut.pbData);
if (pwsz)
CspFreeH(pwsz);
if (ERROR_SUCCESS != dwSts)
printf(" failed, 0x%x\n", dwSts);
// Static buffers were used, don't let them be freed
pCardData->pwszCardName = NULL;
pCardData->pbAtr = NULL;
DeleteCardState(&CardState);
return 0;
}