|
|
#include <windows.h>
#include "basecsp.h"
#include "cardmod.h"
#include "debug.h"
//
// Debugging Macros
//
#define LOG_BEGIN_FUNCTION(x) \
{ DebugLog((DEB_TRACE_CACHE, "%s: Entering\n", #x)); } #define LOG_END_FUNCTION(x, y) \
{ DebugLog((DEB_TRACE_CACHE, "%s: Leaving, status: 0x%x\n", #x, y)); }
//
// Type: CARD_CACHED_DATA_TYPE
//
// These values are used as keys for the card data cache,
// to distinguish the various types of cached data.
//
typedef enum { Cached_CardCapabilities = 1, Cached_ContainerInfo, Cached_GeneralFile, Cached_FileEnumeration, Cached_ContainerEnumeration, Cached_KeySizes, Cached_FreeSpace, Cached_CardmodFile, Cached_Pin
} CARD_CACHED_DATA_TYPE;
//
// Type: CARD_CACHE_FRESHNESS_LOCATION
//
// These values distinguish the broad classes of card data.
//
typedef DWORD CARD_CACHE_FRESHNESS_LOCATION;
#define CacheLocation_Pins 1
#define CacheLocation_Containers 2
#define CacheLocation_Files 4
//
// Type: CARD_CACHE_ITEM_INFO
//
// This struct is used as the actual item to be added to the
// cache for each data item cached. The data itself is expected to follow
// this header in memory, so that the blob can be managed by a single pointer.
//
typedef struct _CARD_CACHE_ITEM_INFO { CARD_CACHE_FILE_FORMAT CacheFreshness; DWORD cbCachedItem;
} CARD_CACHE_ITEM_INFO, *PCARD_CACHE_ITEM_INFO;
//
// Used for the CARD_CACHE_QUERY_INFO dwQuerySource member
//
#define CARD_CACHE_QUERY_SOURCE_CSP 0
#define CARD_CACHE_QUERY_SOURCE_CARDMOD 1
//
// Type: CARD_CACHE_QUERY_INFO
//
// This is the parameter list for the
// I_CspQueryCardCacheForItem function, below.
//
typedef struct _CARD_CACHE_QUERY_INFO { // Input parameters
PCARD_STATE pCardState; CARD_CACHE_FRESHNESS_LOCATION CacheLocation; BOOL fIsPerishable; DWORD cCacheKeys; DATA_BLOB *mpdbCacheKeys; DWORD dwQuerySource;
// Output parameters
CARD_CACHE_FILE_FORMAT CacheFreshness; BOOL fCheckedFreshness; PCARD_CACHE_ITEM_INFO pItem; BOOL fFoundStaleItem;
} CARD_CACHE_QUERY_INFO, *PCARD_CACHE_QUERY_INFO;
//
// Function: CountCharsInMultiSz
//
DWORD CountCharsInMultiSz( IN LPWSTR mwszStrings) { DWORD cch = 0;
while (L'\0' != mwszStrings[cch]) cch += wcslen(mwszStrings + cch) + 1;
return cch + 1; }
//
// Function: MyCacheAddItem
//
// Purpose: Provide the caching functionality of SCardCacheAddItem, until that
// function is available via winscard.dll
//
DWORD WINAPI MyCacheAddItem( IN PCARD_CACHE_QUERY_INFO pInfo, IN DATA_BLOB *pdbItem) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB dbLocalItem; CACHEHANDLE hCache = 0;
memset(&dbLocalItem, 0, sizeof(dbLocalItem));
if (CARD_CACHE_QUERY_SOURCE_CSP == pInfo->dwQuerySource && NULL != pInfo->pCardState->pfnCacheAdd) { dwSts = pInfo->pCardState->pfnCacheAdd( pInfo->mpdbCacheKeys, pInfo->cCacheKeys, pdbItem); } else { switch (pInfo->dwQuerySource) { case CARD_CACHE_QUERY_SOURCE_CSP: hCache = pInfo->pCardState->hCache; break; case CARD_CACHE_QUERY_SOURCE_CARDMOD: hCache = pInfo->pCardState->hCacheCardModuleData; break; default: dwSts = ERROR_INTERNAL_ERROR; goto Ret; }
//
// Since we expect that the winscard cache will make a copy of our
// data buffer, we need to do that here to expose the same
// behavior.
//
dbLocalItem.cbData = pdbItem->cbData;
dbLocalItem.pbData = CspAllocH(pdbItem->cbData);
LOG_CHECK_ALLOC(dbLocalItem.pbData);
memcpy( dbLocalItem.pbData, pdbItem->pbData, dbLocalItem.cbData);
dwSts = CacheAddItem( hCache, pInfo->mpdbCacheKeys, pInfo->cCacheKeys, &dbLocalItem); }
Ret:
return dwSts; }
//
// Function: MyCacheLookupItem
//
// Provide: Provide the caching functionality of SCardCacheLookupItem, until
// that function is available via winscard.dll.
//
// Assumes that the caller will free the buffer pInfo->dbItem.pbData
//
DWORD WINAPI MyCacheLookupItem( IN PCARD_CACHE_QUERY_INFO pInfo, IN OUT PDATA_BLOB pdbItem) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB dbLocalItem; CACHEHANDLE hCache = 0; SCARD_CACHE_LOOKUP_ITEM_INFO ScardCacheLookup;
memset(&dbLocalItem, 0, sizeof(dbLocalItem)); memset(&ScardCacheLookup, 0, sizeof(ScardCacheLookup));
if (pInfo->pCardState->pfnCacheLookup) { ScardCacheLookup.cCacheKey = pInfo->cCacheKeys; ScardCacheLookup.dwVersion = SCARD_CACHE_LOOKUP_ITEM_INFO_CURRENT_VERSION; ScardCacheLookup.pfnAlloc = CspAllocH; ScardCacheLookup.mpdbCacheKey = pInfo->mpdbCacheKeys;
dwSts = pInfo->pCardState->pfnCacheLookup(&ScardCacheLookup);
if (ERROR_SUCCESS != dwSts) goto Ret;
pdbItem->cbData = ScardCacheLookup.dbItem.cbData; pdbItem->pbData = ScardCacheLookup.dbItem.pbData; } else { switch (pInfo->dwQuerySource) { case CARD_CACHE_QUERY_SOURCE_CSP: hCache = pInfo->pCardState->hCache; break; case CARD_CACHE_QUERY_SOURCE_CARDMOD: hCache = pInfo->pCardState->hCacheCardModuleData; break; default: dwSts = ERROR_INTERNAL_ERROR; goto Ret; }
dwSts = CacheGetItem( hCache, pInfo->mpdbCacheKeys, pInfo->cCacheKeys, &dbLocalItem);
if (ERROR_SUCCESS != dwSts) goto Ret;
//
// Expect that the winscard cache will make a copy of the cached data
// buffer before returning it to us. So, we need to make our own copy
// of the buffer in this code path.
//
pdbItem->cbData = dbLocalItem.cbData; pdbItem->pbData = CspAllocH(dbLocalItem.cbData); LOG_CHECK_ALLOC(pdbItem->pbData);
memcpy( pdbItem->pbData, dbLocalItem.pbData, pdbItem->cbData); }
Ret:
return dwSts; }
//
// Function: MyCacheDeleteItem
//
DWORD WINAPI MyCacheDeleteItem( IN PCARD_CACHE_QUERY_INFO pInfo) { DWORD dwSts = ERROR_SUCCESS; CACHEHANDLE hCache = 0;
//
// We're only concerned about deleting cached items if we're doing local
// caching. Otherwise, we assume that the global cache is doing its own
// management of stale items.
//
if (NULL == pInfo->pCardState->pfnCacheAdd || CARD_CACHE_QUERY_SOURCE_CARDMOD == pInfo->dwQuerySource) { switch (pInfo->dwQuerySource) { case CARD_CACHE_QUERY_SOURCE_CSP: hCache = pInfo->pCardState->hCache; break; case CARD_CACHE_QUERY_SOURCE_CARDMOD: hCache = pInfo->pCardState->hCacheCardModuleData; break; default: dwSts = ERROR_INTERNAL_ERROR; goto Ret; }
dwSts = CacheDeleteItem( hCache, pInfo->mpdbCacheKeys, pInfo->cCacheKeys); }
Ret: return dwSts; }
//
// Function: I_CspReadCardCacheFile
//
DWORD I_CspReadCardCacheFile( IN PCARD_STATE pCardState, OUT PCARD_CACHE_FILE_FORMAT pCacheFile) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB dbCacheFile;
if (FALSE == pCardState->fCacheFileValid) { memset(&dbCacheFile, 0, sizeof(dbCacheFile)); dwSts = pCardState->pCardData->pfnCardReadFile( pCardState->pCardData, wszCACHE_FILE_FULL_PATH, 0, &dbCacheFile.pbData, &dbCacheFile.cbData); if (ERROR_SUCCESS != dwSts) goto Ret; if (sizeof(CARD_CACHE_FILE_FORMAT) != dbCacheFile.cbData) { dwSts = ERROR_BAD_LENGTH; goto Ret; } memcpy( &pCardState->CacheFile, dbCacheFile.pbData, sizeof(CARD_CACHE_FILE_FORMAT));
pCardState->fCacheFileValid = TRUE;
CspFreeH(dbCacheFile.pbData); }
memcpy( pCacheFile, &pCardState->CacheFile, sizeof(CARD_CACHE_FILE_FORMAT));
Ret: return dwSts; }
//
// Function: I_CspWriteCardCacheFile
//
DWORD I_CspWriteCardCacheFile( IN PCARD_STATE pCardState, IN PCARD_CACHE_FILE_FORMAT pCacheFile) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB dbCacheFile;
memset(&dbCacheFile, 0, sizeof(dbCacheFile));
dbCacheFile.pbData = (PBYTE) pCacheFile; dbCacheFile.cbData = sizeof(CARD_CACHE_FILE_FORMAT);
dwSts = pCardState->pCardData->pfnCardWriteFile( pCardState->pCardData, wszCACHE_FILE_FULL_PATH, 0, dbCacheFile.pbData, dbCacheFile.cbData);
if (ERROR_SUCCESS != dwSts) goto Ret;
// Also update the cached copy of the cache file in the CARD_STATE.
memcpy( &pCardState->CacheFile, pCacheFile, sizeof(CARD_CACHE_FILE_FORMAT));
pCardState->fCacheFileValid = TRUE;
Ret: return dwSts; }
//
// Function: I_CspIncrementCacheFreshness
//
// Purpose: Indicates that an item in the specified cache location is
// being updated. As a result, the corresponding counter in
// the cache file will be incremented.
//
DWORD I_CspIncrementCacheFreshness( IN PCARD_STATE pCardState, IN CARD_CACHE_FRESHNESS_LOCATION CacheLocation, OUT PCARD_CACHE_FILE_FORMAT pNewFreshness) { DWORD dwSts = ERROR_SUCCESS;
memset(pNewFreshness, 0, sizeof(CARD_CACHE_FILE_FORMAT));
dwSts = I_CspReadCardCacheFile( pCardState, pNewFreshness);
if (ERROR_SUCCESS != dwSts) goto Ret;
if (CacheLocation_Pins & CacheLocation) ++pNewFreshness->bPinsFreshness;
if (CacheLocation_Containers & CacheLocation) ++pNewFreshness->wContainersFreshness;
if (CacheLocation_Files & CacheLocation) ++pNewFreshness->wFilesFreshness;
dwSts = I_CspWriteCardCacheFile( pCardState, pNewFreshness);
Ret: return dwSts; }
//
// Function: I_CspAddCardCacheItem
//
// Purpose: Abstract the process of caching some card data that has been
// confirmed to not exist cached (or was removed for being
// stale.
// Copy the provided card data, wrap it in a CARD_CACHE_ITEM_INFO
// structure and then cache it.
//
// Assume: The card state critical section must be held by caller.
// I_CspQueryCardCacheForItem should be called before this function,
// without releasing the crit sec between the two calls.
//
DWORD I_CspAddCardCacheItem( IN PCARD_CACHE_QUERY_INFO pInfo, IN PCARD_CACHE_ITEM_INFO pItem) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB dbItem;
DsysAssert(NULL == pInfo->pItem);
memset(&dbItem, 0, sizeof(dbItem));
if (pInfo->fIsPerishable) { if (pInfo->fCheckedFreshness) { memcpy( &pItem->CacheFreshness, &pInfo->CacheFreshness, sizeof(pInfo->CacheFreshness)); } else { // This item can stale, and we haven't already queried for the
// current cache counter for this location, so do it now.
dwSts = I_CspReadCardCacheFile( pInfo->pCardState, &pItem->CacheFreshness);
if (ERROR_SUCCESS != dwSts) goto Ret; } }
dbItem.pbData = (PBYTE) pItem; dbItem.cbData = sizeof(CARD_CACHE_ITEM_INFO) + pItem->cbCachedItem;
dwSts = MyCacheAddItem(pInfo, &dbItem);
Ret:
return dwSts; }
//
// Function: I_CspQueryCardCacheForItem
//
// Purpose: Abstract some of the processing that needs to be done for cache
// lookups of card data. If the item is found
// cached, check if it's perishable, and if so, if it's still valid.
// If it's valid, done.
// If the data is not valid, free it's resources and delete its
// entry from the cache.
//
// Assume: The CARD_STATE critical section is assumed to be held by the caller.
// Also, that the item returned by cache lookups is of type
// CARD_CACHE_ITEM_INFO.
//
DWORD I_CspQueryCardCacheForItem( PCARD_CACHE_QUERY_INFO pInfo) { DWORD dwSts = ERROR_SUCCESS; PCARD_CACHE_ITEM_INFO pCacheItem = NULL; BOOL fItemIsFresh = TRUE; DATA_BLOB dbLocalItem;
LOG_BEGIN_FUNCTION(I_CspQueryCardCacheForItem);
memset(&dbLocalItem, 0, sizeof(dbLocalItem));
pInfo->pItem = NULL;
dwSts = MyCacheLookupItem(pInfo, &dbLocalItem);
switch (dwSts) { case ERROR_SUCCESS: // Item was found cached
pCacheItem = (PCARD_CACHE_ITEM_INFO) dbLocalItem.pbData;
if (TRUE == pInfo->fIsPerishable) { // Is the cached data stale?
if (FALSE == pInfo->fCheckedFreshness) { // We haven't already read the card cache file for this
// query, so do it now.
dwSts = I_CspReadCardCacheFile( pInfo->pCardState, &pInfo->CacheFreshness); if (ERROR_SUCCESS != dwSts) goto Ret; pInfo->fCheckedFreshness = TRUE; } //
// Mask out and check each cache counter location, since some
// cached data types may be dependent on multiple cache
// locations to stay fresh.
//
if (CacheLocation_Pins & pInfo->CacheLocation) { if ( pCacheItem->CacheFreshness.bPinsFreshness < pInfo->CacheFreshness.bPinsFreshness) fItemIsFresh = FALSE; }
if (CacheLocation_Containers & pInfo->CacheLocation) { if ( pCacheItem->CacheFreshness.wContainersFreshness < pInfo->CacheFreshness.wContainersFreshness) fItemIsFresh = FALSE; }
if (CacheLocation_Files & pInfo->CacheLocation) { if ( pCacheItem->CacheFreshness.wFilesFreshness < pInfo->CacheFreshness.wFilesFreshness) fItemIsFresh = FALSE; }
if (FALSE == fItemIsFresh) { // Cached data is not fresh. Delete it from the cache.
pInfo->fFoundStaleItem = TRUE; dwSts = MyCacheDeleteItem(pInfo); if (ERROR_SUCCESS != dwSts) goto Ret;
// Set error to indicate no cached item is being
// returned.
dwSts = ERROR_NOT_FOUND; goto Ret; } }
// Item is either not perishable, or still fresh.
pInfo->pItem = pCacheItem; pCacheItem = NULL; break;
case ERROR_NOT_FOUND: // No cached data was found
// Don't do anything else at this point, just report the
// status to the caller.
break;
default: // some sort of unexpected error occurred
goto Ret; }
Ret:
if (pCacheItem) CspFreeH(pCacheItem);
LOG_END_FUNCTION(I_CspQueryCardCacheForItem, dwSts);
return dwSts; }
//
// Initializes the CARD_CACHE_QUERY_INFO structure for a cache lookup
// being performed on behalf of the card module.
//
void I_CspCacheInitializeQueryForCardmod( IN PVOID pvCacheContext, IN LPWSTR wszFileName, IN OUT PCARD_CACHE_QUERY_INFO pInfo, IN OUT PDATA_BLOB mpdbCacheKeys, IN DWORD cCacheKeys) { CARD_CACHED_DATA_TYPE cachedType = Cached_CardmodFile;
DsysAssert(3 == cCacheKeys);
// Setup the cache keys for this item
mpdbCacheKeys[0].cbData = sizeof(cachedType); mpdbCacheKeys[0].pbData = (PBYTE) &cachedType;
mpdbCacheKeys[1].cbData = wcslen( ((PCARD_STATE) pvCacheContext)->wszSerialNumber) * sizeof(WCHAR); mpdbCacheKeys[1].pbData = (PBYTE) ((PCARD_STATE) pvCacheContext)->wszSerialNumber;
mpdbCacheKeys[2].cbData = wcslen(wszFileName) * sizeof(wszFileName[0]); mpdbCacheKeys[2].pbData = (PBYTE) wszFileName;
//
// Since the card module will use this function to cache files that
// aren't "owned" by the Base CSP, and since cardmod files probably
// don't map to our CacheLocation's very well, assume that any change
// to any part of the card should cause this cached data to be staled.
//
pInfo->CacheLocation = CacheLocation_Pins | CacheLocation_Files | CacheLocation_Containers;
pInfo->cCacheKeys = cCacheKeys; pInfo->dwQuerySource = CARD_CACHE_QUERY_SOURCE_CARDMOD; pInfo->fIsPerishable = TRUE; pInfo->mpdbCacheKeys = mpdbCacheKeys; pInfo->pCardState = (PCARD_STATE) pvCacheContext; }
//
// Cache "Add item" function exposed to the card module.
//
DWORD WINAPI CspCacheAddFileProc( IN PVOID pvCacheContext, IN LPWSTR wszTag, IN DWORD dwFlags, IN PBYTE pbData, IN DWORD cbData) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB rgdbKeys[3]; PCARD_CACHE_ITEM_INFO pItem = NULL; CARD_CACHE_QUERY_INFO CacheQueryInfo;
memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
if (0 == cbData || NULL == pbData) goto Ret;
// Copy the data to be cached into a buffer w/ space for a cache
// header.
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH( sizeof(CARD_CACHE_ITEM_INFO) + cbData);
LOG_CHECK_ALLOC(pItem);
memcpy( ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO), pbData, cbData);
pItem->cbCachedItem = cbData;
I_CspCacheInitializeQueryForCardmod( pvCacheContext, wszTag, &CacheQueryInfo, rgdbKeys, sizeof(rgdbKeys) / sizeof(rgdbKeys[0]));
dwSts = I_CspAddCardCacheItem(&CacheQueryInfo, pItem);
Ret:
if (pItem) CspFreeH(pItem);
return dwSts; }
//
// Cache "Lookup item" function exposed to the card module.
//
DWORD WINAPI CspCacheLookupFileProc( IN PVOID pvCacheContext, IN LPWSTR wszTag, IN DWORD dwFlags, IN PBYTE *ppbData, IN PDWORD pcbData) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB rgdbKeys[3]; CARD_CACHE_QUERY_INFO CacheQueryInfo;
memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
*ppbData = NULL; *pcbData = 0;
I_CspCacheInitializeQueryForCardmod( pvCacheContext, wszTag, &CacheQueryInfo, rgdbKeys, sizeof(rgdbKeys) / sizeof(rgdbKeys[0]));
dwSts = I_CspQueryCardCacheForItem(&CacheQueryInfo);
// Will return ERROR_NOT_FOUND if no matching cached item was found.
if (ERROR_SUCCESS != dwSts) goto Ret;
*pcbData = CacheQueryInfo.pItem->cbCachedItem;
*ppbData = (PBYTE) CspAllocH(*pcbData);
LOG_CHECK_ALLOC(*ppbData);
memcpy( *ppbData, ((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO), *pcbData);
Ret:
return dwSts; }
//
// Cache "Delete item" function exposed to the card module.
//
DWORD WINAPI CspCacheDeleteFileProc( IN PVOID pvCacheContext, IN LPWSTR wszTag, IN DWORD dwFlags) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB rgdbKeys[3]; CARD_CACHE_QUERY_INFO CacheQueryInfo;
memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
I_CspCacheInitializeQueryForCardmod( pvCacheContext, wszTag, &CacheQueryInfo, rgdbKeys, sizeof(rgdbKeys) / sizeof(rgdbKeys[0]));
dwSts = MyCacheDeleteItem(&CacheQueryInfo);
return dwSts; }
//
// Initializes caching for the CSP and for the caching helper routines
// provided to the card module.
//
DWORD InitializeCspCaching( IN OUT PCARD_STATE pCardState) { DWORD dwSts = ERROR_SUCCESS; CACHE_INITIALIZE_INFO CacheInitializeInfo;
memset(&CacheInitializeInfo, 0, sizeof(CacheInitializeInfo)); //
// Initialize caching for the CSP
//
// Data cached by the CSP should be cached system-wide if possible.
CacheInitializeInfo.dwType = CACHE_TYPE_SERVICE;
//
// Initialize our data caching routines. First, see if winscard.dll
// provides caching routines. If it does, use them. Otherwise,
// use our own local cache.
//
pCardState->hWinscard = LoadLibrary(L"winscard.dll");
if (NULL == pCardState->hWinscard) { dwSts = GetLastError(); goto Ret; } pCardState->pfnCacheLookup = (PFN_SCARD_CACHE_LOOKUP_ITEM) GetProcAddress( pCardState->hWinscard, "SCardCacheLookupItem");
if (NULL == pCardState->pfnCacheLookup) { // Since this export is missing from winscard, use local caching.
dwSts = CacheInitializeCache( &pCardState->hCache, &CacheInitializeInfo); if (ERROR_SUCCESS != dwSts) goto Ret; } else { pCardState->pfnCacheAdd = (PFN_SCARD_CACHE_ADD_ITEM) GetProcAddress( pCardState->hWinscard, "SCardCacheAddItem");
if (NULL == pCardState->pfnCacheAdd) { dwSts = GetLastError(); goto Ret; } }
//
// Initialize caching for the card module
//
// Assume that file data cached by the card module should only be
// maintained per-process, not system-wide.
CacheInitializeInfo.dwType = CACHE_TYPE_IN_PROC;
dwSts = CacheInitializeCache( &pCardState->hCacheCardModuleData, &CacheInitializeInfo);
if (ERROR_SUCCESS != dwSts) goto Ret;
// When the card module calls back to use our caching routines,
// we need a pointer to the CARD_STATE.
pCardState->pCardData->pvCacheContext = pCardState;
pCardState->pCardData->pfnCspCacheAddFile = CspCacheAddFileProc; pCardState->pCardData->pfnCspCacheDeleteFile = CspCacheDeleteFileProc; pCardState->pCardData->pfnCspCacheLookupFile = CspCacheLookupFileProc;
Ret:
return dwSts; }
//
// Function: InitializeCardState
//
DWORD InitializeCardState( IN OUT PCARD_STATE pCardState) { DWORD dwSts = ERROR_SUCCESS;
dwSts = CspInitializeCriticalSection( &pCardState->cs);
if (ERROR_SUCCESS != dwSts) goto Ret; else pCardState->fInitializedCS = TRUE;
Ret: if (ERROR_SUCCESS != dwSts) DeleteCardState(pCardState);
return dwSts; }
//
// Takes an array of DATA_BLOB structures, enumerated from a cache.
// Frees all "pbData" pointers in the array.
//
void FreeCacheItems( PDATA_BLOB pdbItems, DWORD cItems) { PCARD_CACHE_ITEM_INFO pItemInfo = NULL; PCONTAINER_INFO pContainerInfo = NULL;
while (0 != cItems--) CspFreeH(pdbItems[cItems].pbData); }
//
// Function: InitializeCardData
//
DWORD InitializeCardData(PCARD_DATA pCardData) { DWORD dwSts = ERROR_SUCCESS; CACHE_INITIALIZE_INFO CacheInitializeInfo;
memset(&CacheInitializeInfo, 0, sizeof(CacheInitializeInfo));
pCardData->dwVersion = CARD_DATA_CURRENT_VERSION; pCardData->pfnCspAlloc = CspAllocH; pCardData->pfnCspReAlloc = CspReAllocH; pCardData->pfnCspFree = CspFreeH;
return dwSts; }
//
// Function: CleanupCardData
//
void CleanupCardData(PCARD_DATA pCardData) { if (pCardData->pfnCardDeleteContext) pCardData->pfnCardDeleteContext(pCardData);
if (pCardData->pbAtr) { CspFreeH(pCardData->pbAtr); pCardData->pbAtr = NULL; }
if (pCardData->pwszCardName) { CspFreeH(pCardData->pwszCardName); pCardData->pwszCardName = NULL; }
if (pCardData->hScard) { SCardDisconnect(pCardData->hScard, SCARD_LEAVE_CARD); pCardData->hScard = 0; }
if (pCardData->hSCardCtx) { SCardReleaseContext(pCardData->hSCardCtx); pCardData->hSCardCtx = 0; } }
//
// Enumerates and frees all items in the cache, then deletes the cache.
//
void DeleteCacheAndAllItems(CACHEHANDLE hCache) { PDATA_BLOB pdbCacheItems = NULL; DWORD cCacheItems = 0;
if (ERROR_SUCCESS == CacheEnumItems( hCache, &pdbCacheItems, &cCacheItems)) { FreeCacheItems(pdbCacheItems, cCacheItems); CacheFreeEnumItems(pdbCacheItems); }
CacheDeleteCache(hCache); }
//
// Function: DeleteCardState
//
void DeleteCardState(PCARD_STATE pCardState) { DWORD dwSts = ERROR_SUCCESS;
if (pCardState->fInitializedCS) CspDeleteCriticalSection( &pCardState->cs);
if (pCardState->hCache) { // Need to free all of our cached data before
// deleting the cache handle.
DeleteCacheAndAllItems(pCardState->hCache); pCardState->hCache = 0; } if (pCardState->hCacheCardModuleData) { // Need to free the card module cached data.
DeleteCacheAndAllItems(pCardState->hCacheCardModuleData); pCardState->hCacheCardModuleData = 0; }
if (pCardState->hWinscard) { FreeLibrary(pCardState->hWinscard); pCardState->hWinscard = NULL; pCardState->pfnCacheAdd = NULL; pCardState->pfnCacheLookup = NULL; }
if (pCardState->pCardData) { CleanupCardData(pCardState->pCardData); CspFreeH(pCardState->pCardData); }
if (pCardState->hCardModule) FreeLibrary(pCardState->hCardModule); }
//
// Function: CspQueryCapabilities
//
DWORD WINAPI CspQueryCapabilities( IN PCARD_STATE pCardState, IN OUT PCARD_CAPABILITIES pCardCapabilities) { DWORD dwSts = ERROR_SUCCESS; CARD_CACHE_QUERY_INFO CacheQueryInfo; DATA_BLOB rgdbKeys[2]; PCARD_CACHE_ITEM_INFO pItem = NULL; CARD_CACHED_DATA_TYPE cachedType = Cached_CardCapabilities;
memset(rgdbKeys, 0, sizeof(rgdbKeys)); memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
rgdbKeys[0].pbData = (PBYTE) &cachedType; rgdbKeys[0].cbData = sizeof(cachedType);
rgdbKeys[1].pbData = (PBYTE) pCardState->wszSerialNumber; rgdbKeys[1].cbData = sizeof(WCHAR) * wcslen(pCardState->wszSerialNumber);
// Card Capabilities data item is Non-Perishable
CacheQueryInfo.cCacheKeys = sizeof(rgdbKeys) / sizeof(rgdbKeys[0]); CacheQueryInfo.mpdbCacheKeys = rgdbKeys; CacheQueryInfo.pCardState = pCardState;
dwSts = I_CspQueryCardCacheForItem( &CacheQueryInfo);
switch (dwSts) { case ERROR_NOT_FOUND:
// This data has not yet been cached. We'll have to
// query the data from the card module.
dwSts = pCardState->pCardData->pfnCardQueryCapabilities( pCardState->pCardData, pCardCapabilities);
if (ERROR_SUCCESS != dwSts) goto Ret;
// Now add this data to the cache before returning.
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH( sizeof(CARD_CACHE_ITEM_INFO) + sizeof(CARD_CAPABILITIES));
LOG_CHECK_ALLOC(pItem);
pItem->cbCachedItem = sizeof(CARD_CAPABILITIES);
memcpy( ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO), pCardCapabilities, sizeof(CARD_CAPABILITIES));
dwSts = I_CspAddCardCacheItem( &CacheQueryInfo, pItem);
break;
case ERROR_SUCCESS:
//
// The data was found in the cache.
//
DsysAssert( sizeof(CARD_CAPABILITIES) == CacheQueryInfo.pItem->cbCachedItem);
memcpy( pCardCapabilities, ((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO), sizeof(CARD_CAPABILITIES));
break;
default:
// Unexpected error
break; }
Ret:
if (CacheQueryInfo.pItem) CspFreeH(CacheQueryInfo.pItem); if (pItem) CspFreeH(pItem);
return dwSts; }
//
// Function: CspDeleteContainer
//
DWORD WINAPI CspDeleteContainer( IN PCARD_STATE pCardState, IN BYTE bContainerIndex, IN DWORD dwReserved) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB rgdbKeys[3]; CARD_CACHED_DATA_TYPE cachedType = Cached_ContainerInfo; CARD_CACHE_FILE_FORMAT CacheFile; CARD_CACHE_QUERY_INFO QueryInfo;
memset(&QueryInfo, 0, sizeof(QueryInfo)); memset(rgdbKeys, 0, sizeof(rgdbKeys));
//
// First, update the cache file.
//
dwSts = I_CspIncrementCacheFreshness( pCardState, CacheLocation_Containers, &CacheFile);
if (ERROR_SUCCESS != dwSts) goto Ret;
//
// Do the container deletion in the card module
//
dwSts = pCardState->pCardData->pfnCardDeleteContainer( pCardState->pCardData, bContainerIndex, dwReserved);
if (ERROR_SUCCESS != dwSts) goto Ret;
//
// Finally, delete any cached Container Information for the
// specified container.
//
// First part of key is data type
rgdbKeys[0].cbData = sizeof(cachedType); rgdbKeys[0].pbData = (PBYTE) &cachedType; // Second part of key is container name
rgdbKeys[1].cbData = sizeof(bContainerIndex); rgdbKeys[1].pbData = &bContainerIndex;
rgdbKeys[2].cbData = wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR); rgdbKeys[2].pbData = (PBYTE) pCardState->wszSerialNumber;
QueryInfo.cCacheKeys = sizeof(rgdbKeys) / sizeof(rgdbKeys[0]); QueryInfo.mpdbCacheKeys = rgdbKeys; QueryInfo.pCardState = pCardState;
MyCacheDeleteItem(&QueryInfo);
Ret:
return dwSts; }
//
// Function: CspCreateContainer
//
DWORD WINAPI CspCreateContainer( IN PCARD_STATE pCardState, IN BYTE bContainerIndex, IN DWORD dwFlags, IN DWORD dwKeySpec, IN DWORD dwKeySize, IN PBYTE pbKeyData) { DWORD dwSts = ERROR_SUCCESS; CARD_CACHE_FILE_FORMAT CacheFreshness;
memset(&CacheFreshness, 0, sizeof(CacheFreshness));
//
// Update the cache file
//
dwSts = I_CspIncrementCacheFreshness( pCardState, CacheLocation_Containers, &CacheFreshness); if (ERROR_SUCCESS != dwSts) goto Ret;
//
// Create the container on (and/or add the keyset to) the card
//
dwSts = pCardState->pCardData->pfnCardCreateContainer( pCardState->pCardData, bContainerIndex, dwFlags, dwKeySpec, dwKeySize, pbKeyData);
Ret:
return dwSts; }
//
// Function: CspGetContainerInfo
//
// Purpose: Query for key information for the specified container.
//
// Note, the public key buffers returned in the PCONTAINER_INFO
// struct must be freed by the caller.
//
DWORD WINAPI CspGetContainerInfo( IN PCARD_STATE pCardState, IN BYTE bContainerIndex, IN DWORD dwFlags, IN OUT PCONTAINER_INFO pContainerInfo) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB rgdbKey[3]; CARD_CACHED_DATA_TYPE cachedType = Cached_ContainerInfo; CARD_CACHE_QUERY_INFO CacheQueryInfo; PCARD_CACHE_ITEM_INFO pItem = NULL;
memset(rgdbKey, 0, sizeof(rgdbKey)); memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
// first part of cache key is item type
rgdbKey[0].cbData = sizeof(cachedType); rgdbKey[0].pbData = (PBYTE) &cachedType;
// second part of cache key is container name
rgdbKey[1].cbData = sizeof(bContainerIndex); rgdbKey[1].pbData = &bContainerIndex;
rgdbKey[2].cbData = wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR); rgdbKey[2].pbData = (PBYTE) pCardState->wszSerialNumber;
CacheQueryInfo.CacheLocation = CacheLocation_Containers; CacheQueryInfo.fIsPerishable = TRUE; CacheQueryInfo.cCacheKeys = sizeof(rgdbKey) / sizeof(rgdbKey[0]); CacheQueryInfo.mpdbCacheKeys = rgdbKey; CacheQueryInfo.pCardState = pCardState;
dwSts = I_CspQueryCardCacheForItem( &CacheQueryInfo);
switch (dwSts) { case ERROR_SUCCESS: // Item was successfully found cached.
//
// This data length includes the size of the public keys, so we can
// only check a minimum size for the cached data.
//
DsysAssert(sizeof(CONTAINER_INFO) <= CacheQueryInfo.pItem->cbCachedItem);
memcpy( pContainerInfo, ((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO), sizeof(CONTAINER_INFO));
//
// Now we can check the exact length of the cached blob for sanity.
//
DsysAssert( sizeof(CONTAINER_INFO) + pContainerInfo->cbKeyExPublicKey + pContainerInfo->cbSigPublicKey == CacheQueryInfo.pItem->cbCachedItem);
//
// If the Signature and Key Exchange public keys exist, copy them out
// of the "flat" cache structure.
//
if (pContainerInfo->cbKeyExPublicKey) { pContainerInfo->pbKeyExPublicKey = CspAllocH( pContainerInfo->cbKeyExPublicKey);
LOG_CHECK_ALLOC(pContainerInfo->pbKeyExPublicKey);
memcpy( pContainerInfo->pbKeyExPublicKey, ((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO) + sizeof(CONTAINER_INFO), pContainerInfo->cbKeyExPublicKey); }
if (pContainerInfo->cbSigPublicKey) { pContainerInfo->pbSigPublicKey = CspAllocH( pContainerInfo->cbSigPublicKey);
LOG_CHECK_ALLOC(pContainerInfo->pbSigPublicKey);
memcpy( pContainerInfo->pbSigPublicKey, ((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO) + sizeof(CONTAINER_INFO), pContainerInfo->cbSigPublicKey); }
break;
case ERROR_NOT_FOUND: // No matching item was found cached, or the found item
// was stale. Have to read it from the card.
//
// Send the request to the card module
//
dwSts = pCardState->pCardData->pfnCardGetContainerInfo( pCardState->pCardData, bContainerIndex, dwFlags, pContainerInfo);
if (ERROR_SUCCESS != dwSts) goto Ret;
//
// Cache the returned container information
//
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH( sizeof(CARD_CACHE_ITEM_INFO) + sizeof(CONTAINER_INFO) + pContainerInfo->cbKeyExPublicKey + pContainerInfo->cbSigPublicKey);
LOG_CHECK_ALLOC(pItem);
pItem->cbCachedItem = sizeof(CONTAINER_INFO) + pContainerInfo->cbKeyExPublicKey + pContainerInfo->cbSigPublicKey;
memcpy( ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO), pContainerInfo, sizeof(CONTAINER_INFO));
if (pContainerInfo->pbKeyExPublicKey) { memcpy( ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO) + sizeof(CONTAINER_INFO), pContainerInfo->pbKeyExPublicKey, pContainerInfo->cbKeyExPublicKey); }
if (pContainerInfo->pbSigPublicKey) { memcpy( ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO) + sizeof(CONTAINER_INFO) + pContainerInfo->cbKeyExPublicKey, pContainerInfo->pbSigPublicKey, pContainerInfo->cbSigPublicKey); }
dwSts = I_CspAddCardCacheItem( &CacheQueryInfo, pItem);
break;
default: // An unexpected error occurred.
goto Ret; }
Ret:
if (pItem) CspFreeH(pItem); if (CacheQueryInfo.pItem) CspFreeH(CacheQueryInfo.pItem);
if (ERROR_SUCCESS != dwSts) { if (pContainerInfo->pbKeyExPublicKey) { CspFreeH(pContainerInfo->pbKeyExPublicKey); pContainerInfo->pbKeyExPublicKey = NULL; }
if (pContainerInfo->pbSigPublicKey) { CspFreeH(pContainerInfo->pbSigPublicKey); pContainerInfo->pbSigPublicKey = NULL; } } return dwSts; }
//
// Initializes the cache lookup keys and CARD_CACHE_QUERY_INFO structure
// pin-related cache operations.
//
void I_BuildPinCacheQueryInfo( IN PCARD_STATE pCardState, IN LPWSTR pwszUserId, IN PDATA_BLOB pdbKey, IN CARD_CACHED_DATA_TYPE *pType, IN OUT PCARD_CACHE_QUERY_INFO pInfo) { // first part of cache key is item type
pdbKey[0].cbData = sizeof(CARD_CACHED_DATA_TYPE); pdbKey[0].pbData = (PBYTE) pType;
// second part of cache key is user name
pdbKey[1].cbData = wcslen(pwszUserId) * sizeof(WCHAR); pdbKey[1].pbData = (PBYTE) pwszUserId;
pdbKey[2].cbData = wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR); pdbKey[2].pbData = (PBYTE) pCardState->wszSerialNumber;
pInfo->CacheLocation = CacheLocation_Pins; pInfo->fIsPerishable = TRUE; pInfo->mpdbCacheKeys = pdbKey; pInfo->cCacheKeys = 3; pInfo->pCardState = pCardState; }
//
// Removes cached pin information for the specified user from the general data
// cache and the PinCache.
//
void WINAPI CspRemoveCachedPin( IN PCARD_STATE pCardState, IN LPWSTR pwszUserId) { DATA_BLOB rgdbKey[3]; CARD_CACHE_QUERY_INFO CacheQueryInfo; PCARD_CACHE_ITEM_INFO pItem = NULL; CARD_CACHED_DATA_TYPE cachedType = Cached_Pin;
memset(rgdbKey, 0, sizeof(rgdbKey)); memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
I_BuildPinCacheQueryInfo( pCardState, pwszUserId, rgdbKey, &cachedType, &CacheQueryInfo);
MyCacheDeleteItem(&CacheQueryInfo);
PinCacheFlush(&pCardState->hPinCache); }
//
// Record the change of the pin (or challenge) for the specified user in
// the data cache, and increment the pin cache counter on the card.
//
DWORD WINAPI CspChangeAuthenticator( IN PCARD_STATE pCardState, IN LPWSTR pwszUserId, IN PBYTE pbCurrentAuthenticator, IN DWORD cbCurrentAuthenticator, IN PBYTE pbNewAuthenticator, IN DWORD cbNewAuthenticator, IN DWORD cRetryCount, OUT OPTIONAL PDWORD pcAttemptsRemaining) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB rgdbKey[3]; CARD_CACHE_QUERY_INFO CacheQueryInfo; PCARD_CACHE_ITEM_INFO pItem = NULL; CARD_CACHED_DATA_TYPE cachedType = Cached_Pin;
memset(rgdbKey, 0, sizeof(rgdbKey)); memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
//
// Do the requestion operation
//
dwSts = pCardState->pCardData->pfnCardChangeAuthenticator( pCardState->pCardData, pwszUserId, pbCurrentAuthenticator, cbCurrentAuthenticator, pbNewAuthenticator, cbNewAuthenticator, cRetryCount, pcAttemptsRemaining);
if (ERROR_SUCCESS != dwSts) goto Ret;
//
// Update the Pins freshness counter of the card cache file. We do
// this after the pin change because we need to wait for the card to be
// authenticated.
//
dwSts = I_CspIncrementCacheFreshness( pCardState, CacheLocation_Pins, &CacheQueryInfo.CacheFreshness); if (ERROR_SUCCESS != dwSts) goto Ret;
//
// Delete any existing entry for this user-pin in the cache
//
I_BuildPinCacheQueryInfo( pCardState, pwszUserId, rgdbKey, &cachedType, &CacheQueryInfo);
MyCacheDeleteItem(&CacheQueryInfo);
//
// Cache the updated pin info
//
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH( sizeof(CARD_CACHE_ITEM_INFO));
LOG_CHECK_ALLOC(pItem);
dwSts = I_CspAddCardCacheItem( &CacheQueryInfo, pItem);
Ret:
if (pItem) CspFreeH(pItem);
return dwSts; }
//
// -- Expect that CspSubmitPin is only called from within a PinCache verify-pin
// callback. This is because the pbPin is expected to have come directly
// from the pin cache, and therefore may be stale.
//
// -- Expect that the user pin in the pin cache is tightly coupled to the
// cache stamp information cached in the general data cache for the user.
// That is, the cached pin must have been the correct pin when the pin-location
// cache stamp on the card had the stamp value that is stored in the general
// cache.
//
// This allows us to avoid presenting a pin to the card that we already know is
// wrong. This could happen, for example, if the pin has been changed via a
// separate process.
//
DWORD WINAPI CspSubmitPin( IN PCARD_STATE pCardState, IN LPWSTR pwszUserId, IN PBYTE pbPin, IN DWORD cbPin, OUT OPTIONAL PDWORD pcAttemptsRemaining) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB rgdbKey[3]; CARD_CACHE_QUERY_INFO CacheQueryInfo; PCARD_CACHE_ITEM_INFO pItem = NULL; CARD_CACHED_DATA_TYPE cachedType = Cached_Pin;
memset(rgdbKey, 0, sizeof(rgdbKey)); memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
I_BuildPinCacheQueryInfo( pCardState, pwszUserId, rgdbKey, &cachedType, &CacheQueryInfo);
dwSts = I_CspQueryCardCacheForItem( &CacheQueryInfo);
switch (dwSts) { case ERROR_SUCCESS: // The user's cached pin appears to be synchronized with the pin
// cache counter on the card. Do the submit.
break;
case ERROR_NOT_FOUND:
if (TRUE == CacheQueryInfo.fFoundStaleItem) { //
// The user's cached pin is out of synch with the pin cache counter.
// Don't do the submit, but return a sensible error code.
//
dwSts = SCARD_W_WRONG_CHV; goto Ret; }
// There is no cached pin information for this user yet. Add it now.
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH( sizeof(CARD_CACHE_ITEM_INFO));
LOG_CHECK_ALLOC(pItem);
dwSts = I_CspAddCardCacheItem( &CacheQueryInfo, pItem);
if (ERROR_SUCCESS != dwSts) goto Ret;
// Now continue and submit the pin
break;
default: // Unexpected error occurred
goto Ret; }
dwSts = pCardState->pCardData->pfnCardSubmitPin( pCardState->pCardData, pwszUserId, pbPin, cbPin, pcAttemptsRemaining);
Ret:
if (pItem) CspFreeH(pItem); if (CacheQueryInfo.pItem) CspFreeH(CacheQueryInfo.pItem);
return dwSts; }
//
// Function: CspCreateFile
//
DWORD WINAPI CspCreateFile( IN PCARD_STATE pCardState, IN LPWSTR pwszFileName, IN CARD_FILE_ACCESS_CONDITION AccessCondition) { DWORD dwSts = ERROR_SUCCESS; CARD_CACHE_FILE_FORMAT CacheFreshness;
memset(&CacheFreshness, 0, sizeof(CacheFreshness));
//
// Update the Files freshness counter of the card cache file
//
dwSts = I_CspIncrementCacheFreshness( pCardState, CacheLocation_Files, &CacheFreshness); if (ERROR_SUCCESS != dwSts) goto Ret;
dwSts = pCardState->pCardData->pfnCardCreateFile( pCardState->pCardData, pwszFileName, AccessCondition);
Ret:
return dwSts; }
//
// Function: CspReadFile
//
DWORD WINAPI CspReadFile( IN PCARD_STATE pCardState, IN LPWSTR pwszFileName, IN DWORD dwFlags, OUT PBYTE *ppbData, OUT PDWORD pcbData) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB rgdbKey[3]; CARD_CACHED_DATA_TYPE cachedType = Cached_GeneralFile; CARD_CACHE_QUERY_INFO CacheQueryInfo; PCARD_CACHE_ITEM_INFO pItem = NULL;
memset(rgdbKey, 0, sizeof(rgdbKey)); memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
// first part of cache key is item type
rgdbKey[0].cbData = sizeof(cachedType); rgdbKey[0].pbData = (PBYTE) &cachedType;
// second part of cache key is file name
rgdbKey[1].cbData = wcslen(pwszFileName) * sizeof(WCHAR); rgdbKey[1].pbData = (PBYTE) pwszFileName;
rgdbKey[2].cbData = wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR); rgdbKey[2].pbData = (PBYTE) pCardState->wszSerialNumber;
CacheQueryInfo.CacheLocation = CacheLocation_Files; CacheQueryInfo.fIsPerishable = TRUE; CacheQueryInfo.mpdbCacheKeys = rgdbKey; CacheQueryInfo.cCacheKeys = sizeof(rgdbKey) / sizeof(rgdbKey[0]); CacheQueryInfo.pCardState = pCardState;
dwSts = I_CspQueryCardCacheForItem( &CacheQueryInfo);
switch (dwSts) { case ERROR_SUCCESS: // This file was found cached and up to date.
*pcbData = CacheQueryInfo.pItem->cbCachedItem;
*ppbData = CspAllocH(*pcbData);
LOG_CHECK_ALLOC(*ppbData);
memcpy( *ppbData, ((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO), *pcbData);
break;
case ERROR_NOT_FOUND: // An up-to-date cached version of the file was not found
dwSts = pCardState->pCardData->pfnCardReadFile( pCardState->pCardData, pwszFileName, dwFlags, ppbData, pcbData);
if (ERROR_SUCCESS != dwSts) goto Ret;
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH( sizeof(CARD_CACHE_ITEM_INFO) + *pcbData);
LOG_CHECK_ALLOC(pItem);
pItem->cbCachedItem = *pcbData;
memcpy( ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO), *ppbData, *pcbData);
dwSts = I_CspAddCardCacheItem( &CacheQueryInfo, pItem);
break;
default: // Unexpected error occurred
break; }
Ret:
if (pItem) CspFreeH(pItem); if (CacheQueryInfo.pItem) CspFreeH(CacheQueryInfo.pItem);
if (ERROR_SUCCESS != dwSts) { if (*ppbData) { CspFreeH(*ppbData); *ppbData = NULL; } }
return dwSts; }
//
// Function: CspWriteFile
//
DWORD WINAPI CspWriteFile( IN PCARD_STATE pCardState, IN LPWSTR pwszFileName, IN DWORD dwFlags, IN PBYTE pbData, IN DWORD cbData) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB rgdbKeys[3]; CARD_CACHED_DATA_TYPE cachedType = Cached_GeneralFile; CARD_CACHE_QUERY_INFO CacheQueryInfo; PCARD_CACHE_ITEM_INFO pItem = NULL;
memset(rgdbKeys, 0, sizeof(rgdbKeys)); memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
//
// Update the Files freshness counter of the card cache file
//
dwSts = I_CspIncrementCacheFreshness( pCardState, CacheLocation_Files, &CacheQueryInfo.CacheFreshness); if (ERROR_SUCCESS != dwSts) goto Ret;
//
// Delete any existing entry for this file in the cache
//
// First cache lookup key is data type
rgdbKeys[0].cbData = sizeof(cachedType); rgdbKeys[0].pbData = (PBYTE) &cachedType;
// Second cache lookup key is filename
rgdbKeys[1].cbData = wcslen(pwszFileName) * sizeof(WCHAR); rgdbKeys[1].pbData = (PBYTE) pwszFileName;
rgdbKeys[2].cbData = wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR); rgdbKeys[2].pbData = (PBYTE) pCardState->wszSerialNumber;
CacheQueryInfo.fCheckedFreshness = TRUE; CacheQueryInfo.fIsPerishable = TRUE; CacheQueryInfo.mpdbCacheKeys = rgdbKeys; CacheQueryInfo.cCacheKeys = sizeof(rgdbKeys) / sizeof(rgdbKeys[0]); CacheQueryInfo.CacheLocation = CacheLocation_Files; CacheQueryInfo.pCardState = pCardState;
//
// Since we know that any currently cached data for this file is
// obsolete, make an attempt to delete it from the cache.
//
MyCacheDeleteItem(&CacheQueryInfo);
//
// Perform the Write File operation
//
dwSts = pCardState->pCardData->pfnCardWriteFile( pCardState->pCardData, pwszFileName, dwFlags, pbData, cbData);
if (ERROR_SUCCESS != dwSts) goto Ret;
//
// Cache the updated file contents
//
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH( sizeof(CARD_CACHE_ITEM_INFO) + cbData);
LOG_CHECK_ALLOC(pItem);
pItem->cbCachedItem = cbData;
memcpy( ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO), pbData, cbData);
dwSts = I_CspAddCardCacheItem( &CacheQueryInfo, pItem);
Ret:
if (pItem) CspFreeH(pItem);
return dwSts; }
//
// Function: CspDeleteFile
//
DWORD WINAPI CspDeleteFile( IN PCARD_STATE pCardState, IN DWORD dwReserved, IN LPWSTR pwszFileName) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB rgdbKeys[3]; CARD_CACHED_DATA_TYPE cachedType = Cached_GeneralFile; CARD_CACHE_FILE_FORMAT CacheFile; CARD_CACHE_QUERY_INFO QueryInfo;
memset(rgdbKeys, 0, sizeof(rgdbKeys)); memset(&QueryInfo, 0, sizeof(QueryInfo));
//
// Update the Files freshness counter of the card cache file
//
dwSts = I_CspIncrementCacheFreshness( pCardState, CacheLocation_Files, &CacheFile); if (ERROR_SUCCESS != dwSts) goto Ret;
//
// Delete any existing entry for this file in the cache
//
// First cache lookup key is data type
rgdbKeys[0].cbData = sizeof(cachedType); rgdbKeys[0].pbData = (PBYTE) &cachedType;
// Second cache lookup key is filename
rgdbKeys[1].cbData = wcslen(pwszFileName) * sizeof(WCHAR); rgdbKeys[1].pbData = (PBYTE) pwszFileName;
rgdbKeys[2].cbData = wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR); rgdbKeys[2].pbData = (PBYTE) pCardState->wszSerialNumber;
QueryInfo.cCacheKeys = sizeof(rgdbKeys) / sizeof(rgdbKeys[0]); QueryInfo.mpdbCacheKeys = rgdbKeys; QueryInfo.pCardState = pCardState;
MyCacheDeleteItem(&QueryInfo);
//
// Do the CardDeleteFile operation
//
dwSts = pCardState->pCardData->pfnCardDeleteFile( pCardState->pCardData, dwReserved, pwszFileName);
Ret:
return dwSts; }
//
// Function: CspEnumFiles
//
DWORD WINAPI CspEnumFiles( IN PCARD_STATE pCardState, IN DWORD dwFlags, IN OUT LPWSTR *pmwszFileNames) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB rgdbKey[2]; CARD_CACHED_DATA_TYPE cachedType = Cached_FileEnumeration; CARD_CACHE_QUERY_INFO CacheQueryInfo; DWORD cbFileNames = 0; PCARD_CACHE_ITEM_INFO pItem = NULL;
memset(rgdbKey, 0, sizeof(rgdbKey)); memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
// cache key is item type
rgdbKey[0].cbData = sizeof(cachedType); rgdbKey[0].pbData = (PBYTE) &cachedType;
rgdbKey[1].cbData = wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR); rgdbKey[1].pbData = (PBYTE) pCardState->wszSerialNumber;
CacheQueryInfo.CacheLocation = CacheLocation_Files; CacheQueryInfo.fIsPerishable = TRUE; CacheQueryInfo.mpdbCacheKeys = rgdbKey; CacheQueryInfo.cCacheKeys = sizeof(rgdbKey) / sizeof(rgdbKey[0]); CacheQueryInfo.pCardState = pCardState;
dwSts = I_CspQueryCardCacheForItem( &CacheQueryInfo);
switch (dwSts) { case ERROR_SUCCESS: // The list of files was found cached and up to date.
*pmwszFileNames = (LPWSTR) CspAllocH( CacheQueryInfo.pItem->cbCachedItem);
memcpy( (PBYTE) *pmwszFileNames, ((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO), CacheQueryInfo.pItem->cbCachedItem);
break;
case ERROR_NOT_FOUND: // An up-to-date cached version of the file was not found
dwSts = pCardState->pCardData->pfnCardEnumFiles( pCardState->pCardData, dwFlags, pmwszFileNames);
if (ERROR_SUCCESS != dwSts) goto Ret;
cbFileNames = sizeof(WCHAR) * CountCharsInMultiSz(*pmwszFileNames);
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH( sizeof(CARD_CACHE_ITEM_INFO) + cbFileNames);
LOG_CHECK_ALLOC(pItem);
pItem->cbCachedItem = cbFileNames;
memcpy( ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO), (PBYTE) *pmwszFileNames, cbFileNames);
// Cache the new data
dwSts = I_CspAddCardCacheItem( &CacheQueryInfo, pItem);
break;
default: // Unexpected error occurred
break; }
Ret:
if (pItem) CspFreeH(pItem); if (CacheQueryInfo.pItem) CspFreeH(CacheQueryInfo.pItem);
if (ERROR_SUCCESS != dwSts) { if (*pmwszFileNames) { CspFreeH(*pmwszFileNames); *pmwszFileNames = NULL; } }
return dwSts; }
//
// Function: CspQueryFreeSpace
//
DWORD WINAPI CspQueryFreeSpace( IN PCARD_STATE pCardState, IN DWORD dwFlags, OUT PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo) { DWORD dwSts = ERROR_SUCCESS; DATA_BLOB rgdbKey[2]; CARD_CACHED_DATA_TYPE cachedType = Cached_FreeSpace; CARD_CACHE_QUERY_INFO CacheQueryInfo; PCARD_CACHE_ITEM_INFO pItem = NULL;
memset(rgdbKey, 0, sizeof(rgdbKey)); memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
// cache key is item type
rgdbKey[0].cbData = sizeof(cachedType); rgdbKey[0].pbData = (PBYTE) &cachedType;
rgdbKey[1].cbData = wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR); rgdbKey[1].pbData = (PBYTE) pCardState->wszSerialNumber;
// Card Free Space information is dependent on both the Files
// and the Containers cache counters.
CacheQueryInfo.CacheLocation = CacheLocation_Files | CacheLocation_Containers; CacheQueryInfo.fIsPerishable = TRUE; CacheQueryInfo.mpdbCacheKeys = rgdbKey; CacheQueryInfo.cCacheKeys = sizeof(rgdbKey) / sizeof(rgdbKey[0]); CacheQueryInfo.pCardState = pCardState;
dwSts = I_CspQueryCardCacheForItem( &CacheQueryInfo);
switch (dwSts) { case ERROR_SUCCESS:
// Free Space info was found cached and up to date
DsysAssert( sizeof(CARD_FREE_SPACE_INFO) == CacheQueryInfo.pItem->cbCachedItem);
memcpy( pCardFreeSpaceInfo, ((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO), sizeof(CARD_FREE_SPACE_INFO));
break;
case ERROR_NOT_FOUND: // Up to date Free Space info was not found
dwSts = pCardState->pCardData->pfnCardQueryFreeSpace( pCardState->pCardData, dwFlags, pCardFreeSpaceInfo);
if (ERROR_SUCCESS != dwSts) goto Ret;
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH( sizeof(CARD_CACHE_ITEM_INFO) + sizeof(CARD_FREE_SPACE_INFO));
LOG_CHECK_ALLOC(pItem);
pItem->cbCachedItem = sizeof(CARD_FREE_SPACE_INFO);
memcpy( ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO), (PBYTE) pCardFreeSpaceInfo, sizeof(CARD_FREE_SPACE_INFO));
// Cache the new data
dwSts = I_CspAddCardCacheItem( &CacheQueryInfo, pItem);
break;
default: // Unexpected error occurred
goto Ret; }
Ret:
if (pItem) CspFreeH(pItem); if (CacheQueryInfo.pItem) CspFreeH(CacheQueryInfo.pItem);
return dwSts; }
//
// Function: CspPrivateKeyDecrypt
//
DWORD WINAPI CspPrivateKeyDecrypt( IN PCARD_STATE pCardState, IN PCARD_PRIVATE_KEY_DECRYPT_INFO pInfo) { return pCardState->pCardData->pfnCardPrivateKeyDecrypt( pCardState->pCardData, pInfo); }
//
// Function: CspQueryKeySizes
//
DWORD WINAPI CspQueryKeySizes( IN PCARD_STATE pCardState, IN DWORD dwKeySpec, IN DWORD dwReserved, OUT PCARD_KEY_SIZES pKeySizes) { DWORD dwSts = ERROR_SUCCESS; CARD_CACHE_QUERY_INFO CacheQueryInfo; DATA_BLOB rgdbKeys[3]; CARD_CACHED_DATA_TYPE cachedType = Cached_KeySizes; PCARD_CACHE_ITEM_INFO pItem = NULL;
memset(rgdbKeys, 0, sizeof(rgdbKeys)); memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
// First part of cache key is item type
rgdbKeys[0].pbData = (PBYTE) &cachedType; rgdbKeys[0].cbData = sizeof(cachedType);
// Second part of cache key is public-key type
rgdbKeys[1].pbData = (PBYTE) &dwKeySpec; rgdbKeys[1].cbData = sizeof(dwKeySpec);
rgdbKeys[2].pbData = (PBYTE) pCardState->wszSerialNumber; rgdbKeys[2].cbData = wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
// Key Sizes data item is Non-Perishable
CacheQueryInfo.cCacheKeys = sizeof(rgdbKeys) / sizeof(rgdbKeys[0]); CacheQueryInfo.mpdbCacheKeys = rgdbKeys; CacheQueryInfo.pCardState = pCardState;
dwSts = I_CspQueryCardCacheForItem( &CacheQueryInfo);
switch (dwSts) { case ERROR_NOT_FOUND:
// This data has not yet been cached. We'll have to
// query the data from the card module.
dwSts = pCardState->pCardData->pfnCardQueryKeySizes( pCardState->pCardData, dwKeySpec, dwReserved, pKeySizes);
if (ERROR_SUCCESS != dwSts) goto Ret;
// Now add this data to the cache
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH( sizeof(CARD_CACHE_ITEM_INFO) + sizeof(CARD_KEY_SIZES));
LOG_CHECK_ALLOC(pItem);
pItem->cbCachedItem = sizeof(CARD_KEY_SIZES);
memcpy( ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO), (PBYTE) pKeySizes, sizeof(CARD_KEY_SIZES));
dwSts = I_CspAddCardCacheItem( &CacheQueryInfo, pItem);
break;
case ERROR_SUCCESS:
//
// The data was found in the cache.
//
DsysAssert( sizeof(CARD_KEY_SIZES) == CacheQueryInfo.pItem->cbCachedItem);
memcpy( pKeySizes, ((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO), sizeof(CARD_KEY_SIZES));
break;
default:
// Unexpected error
break; }
Ret:
if (pItem) CspFreeH(pItem); if (CacheQueryInfo.pItem) CspFreeH(CacheQueryInfo.pItem);
return dwSts; }
|