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.
2341 lines
60 KiB
2341 lines
60 KiB
#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;
|
|
}
|