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

2341 lines
60 KiB

  1. #include <windows.h>
  2. #include "basecsp.h"
  3. #include "cardmod.h"
  4. #include "debug.h"
  5. //
  6. // Debugging Macros
  7. //
  8. #define LOG_BEGIN_FUNCTION(x) \
  9. { DebugLog((DEB_TRACE_CACHE, "%s: Entering\n", #x)); }
  10. #define LOG_END_FUNCTION(x, y) \
  11. { DebugLog((DEB_TRACE_CACHE, "%s: Leaving, status: 0x%x\n", #x, y)); }
  12. //
  13. // Type: CARD_CACHED_DATA_TYPE
  14. //
  15. // These values are used as keys for the card data cache,
  16. // to distinguish the various types of cached data.
  17. //
  18. typedef enum
  19. {
  20. Cached_CardCapabilities = 1,
  21. Cached_ContainerInfo,
  22. Cached_GeneralFile,
  23. Cached_FileEnumeration,
  24. Cached_ContainerEnumeration,
  25. Cached_KeySizes,
  26. Cached_FreeSpace,
  27. Cached_CardmodFile,
  28. Cached_Pin
  29. } CARD_CACHED_DATA_TYPE;
  30. //
  31. // Type: CARD_CACHE_FRESHNESS_LOCATION
  32. //
  33. // These values distinguish the broad classes of card data.
  34. //
  35. typedef DWORD CARD_CACHE_FRESHNESS_LOCATION;
  36. #define CacheLocation_Pins 1
  37. #define CacheLocation_Containers 2
  38. #define CacheLocation_Files 4
  39. //
  40. // Type: CARD_CACHE_ITEM_INFO
  41. //
  42. // This struct is used as the actual item to be added to the
  43. // cache for each data item cached. The data itself is expected to follow
  44. // this header in memory, so that the blob can be managed by a single pointer.
  45. //
  46. typedef struct _CARD_CACHE_ITEM_INFO
  47. {
  48. CARD_CACHE_FILE_FORMAT CacheFreshness;
  49. DWORD cbCachedItem;
  50. } CARD_CACHE_ITEM_INFO, *PCARD_CACHE_ITEM_INFO;
  51. //
  52. // Used for the CARD_CACHE_QUERY_INFO dwQuerySource member
  53. //
  54. #define CARD_CACHE_QUERY_SOURCE_CSP 0
  55. #define CARD_CACHE_QUERY_SOURCE_CARDMOD 1
  56. //
  57. // Type: CARD_CACHE_QUERY_INFO
  58. //
  59. // This is the parameter list for the
  60. // I_CspQueryCardCacheForItem function, below.
  61. //
  62. typedef struct _CARD_CACHE_QUERY_INFO
  63. {
  64. // Input parameters
  65. PCARD_STATE pCardState;
  66. CARD_CACHE_FRESHNESS_LOCATION CacheLocation;
  67. BOOL fIsPerishable;
  68. DWORD cCacheKeys;
  69. DATA_BLOB *mpdbCacheKeys;
  70. DWORD dwQuerySource;
  71. // Output parameters
  72. CARD_CACHE_FILE_FORMAT CacheFreshness;
  73. BOOL fCheckedFreshness;
  74. PCARD_CACHE_ITEM_INFO pItem;
  75. BOOL fFoundStaleItem;
  76. } CARD_CACHE_QUERY_INFO, *PCARD_CACHE_QUERY_INFO;
  77. //
  78. // Function: CountCharsInMultiSz
  79. //
  80. DWORD CountCharsInMultiSz(
  81. IN LPWSTR mwszStrings)
  82. {
  83. DWORD cch = 0;
  84. while (L'\0' != mwszStrings[cch])
  85. cch += wcslen(mwszStrings + cch) + 1;
  86. return cch + 1;
  87. }
  88. //
  89. // Function: MyCacheAddItem
  90. //
  91. // Purpose: Provide the caching functionality of SCardCacheAddItem, until that
  92. // function is available via winscard.dll
  93. //
  94. DWORD WINAPI MyCacheAddItem(
  95. IN PCARD_CACHE_QUERY_INFO pInfo,
  96. IN DATA_BLOB *pdbItem)
  97. {
  98. DWORD dwSts = ERROR_SUCCESS;
  99. DATA_BLOB dbLocalItem;
  100. CACHEHANDLE hCache = 0;
  101. memset(&dbLocalItem, 0, sizeof(dbLocalItem));
  102. if (CARD_CACHE_QUERY_SOURCE_CSP == pInfo->dwQuerySource &&
  103. NULL != pInfo->pCardState->pfnCacheAdd)
  104. {
  105. dwSts = pInfo->pCardState->pfnCacheAdd(
  106. pInfo->mpdbCacheKeys,
  107. pInfo->cCacheKeys,
  108. pdbItem);
  109. }
  110. else
  111. {
  112. switch (pInfo->dwQuerySource)
  113. {
  114. case CARD_CACHE_QUERY_SOURCE_CSP:
  115. hCache = pInfo->pCardState->hCache;
  116. break;
  117. case CARD_CACHE_QUERY_SOURCE_CARDMOD:
  118. hCache = pInfo->pCardState->hCacheCardModuleData;
  119. break;
  120. default:
  121. dwSts = ERROR_INTERNAL_ERROR;
  122. goto Ret;
  123. }
  124. //
  125. // Since we expect that the winscard cache will make a copy of our
  126. // data buffer, we need to do that here to expose the same
  127. // behavior.
  128. //
  129. dbLocalItem.cbData = pdbItem->cbData;
  130. dbLocalItem.pbData = CspAllocH(pdbItem->cbData);
  131. LOG_CHECK_ALLOC(dbLocalItem.pbData);
  132. memcpy(
  133. dbLocalItem.pbData,
  134. pdbItem->pbData,
  135. dbLocalItem.cbData);
  136. dwSts = CacheAddItem(
  137. hCache,
  138. pInfo->mpdbCacheKeys,
  139. pInfo->cCacheKeys,
  140. &dbLocalItem);
  141. }
  142. Ret:
  143. return dwSts;
  144. }
  145. //
  146. // Function: MyCacheLookupItem
  147. //
  148. // Provide: Provide the caching functionality of SCardCacheLookupItem, until
  149. // that function is available via winscard.dll.
  150. //
  151. // Assumes that the caller will free the buffer pInfo->dbItem.pbData
  152. //
  153. DWORD WINAPI MyCacheLookupItem(
  154. IN PCARD_CACHE_QUERY_INFO pInfo,
  155. IN OUT PDATA_BLOB pdbItem)
  156. {
  157. DWORD dwSts = ERROR_SUCCESS;
  158. DATA_BLOB dbLocalItem;
  159. CACHEHANDLE hCache = 0;
  160. SCARD_CACHE_LOOKUP_ITEM_INFO ScardCacheLookup;
  161. memset(&dbLocalItem, 0, sizeof(dbLocalItem));
  162. memset(&ScardCacheLookup, 0, sizeof(ScardCacheLookup));
  163. if (pInfo->pCardState->pfnCacheLookup)
  164. {
  165. ScardCacheLookup.cCacheKey = pInfo->cCacheKeys;
  166. ScardCacheLookup.dwVersion =
  167. SCARD_CACHE_LOOKUP_ITEM_INFO_CURRENT_VERSION;
  168. ScardCacheLookup.pfnAlloc = CspAllocH;
  169. ScardCacheLookup.mpdbCacheKey = pInfo->mpdbCacheKeys;
  170. dwSts = pInfo->pCardState->pfnCacheLookup(&ScardCacheLookup);
  171. if (ERROR_SUCCESS != dwSts)
  172. goto Ret;
  173. pdbItem->cbData = ScardCacheLookup.dbItem.cbData;
  174. pdbItem->pbData = ScardCacheLookup.dbItem.pbData;
  175. }
  176. else
  177. {
  178. switch (pInfo->dwQuerySource)
  179. {
  180. case CARD_CACHE_QUERY_SOURCE_CSP:
  181. hCache = pInfo->pCardState->hCache;
  182. break;
  183. case CARD_CACHE_QUERY_SOURCE_CARDMOD:
  184. hCache = pInfo->pCardState->hCacheCardModuleData;
  185. break;
  186. default:
  187. dwSts = ERROR_INTERNAL_ERROR;
  188. goto Ret;
  189. }
  190. dwSts = CacheGetItem(
  191. hCache,
  192. pInfo->mpdbCacheKeys,
  193. pInfo->cCacheKeys,
  194. &dbLocalItem);
  195. if (ERROR_SUCCESS != dwSts)
  196. goto Ret;
  197. //
  198. // Expect that the winscard cache will make a copy of the cached data
  199. // buffer before returning it to us. So, we need to make our own copy
  200. // of the buffer in this code path.
  201. //
  202. pdbItem->cbData = dbLocalItem.cbData;
  203. pdbItem->pbData = CspAllocH(dbLocalItem.cbData);
  204. LOG_CHECK_ALLOC(pdbItem->pbData);
  205. memcpy(
  206. pdbItem->pbData,
  207. dbLocalItem.pbData,
  208. pdbItem->cbData);
  209. }
  210. Ret:
  211. return dwSts;
  212. }
  213. //
  214. // Function: MyCacheDeleteItem
  215. //
  216. DWORD WINAPI MyCacheDeleteItem(
  217. IN PCARD_CACHE_QUERY_INFO pInfo)
  218. {
  219. DWORD dwSts = ERROR_SUCCESS;
  220. CACHEHANDLE hCache = 0;
  221. //
  222. // We're only concerned about deleting cached items if we're doing local
  223. // caching. Otherwise, we assume that the global cache is doing its own
  224. // management of stale items.
  225. //
  226. if (NULL == pInfo->pCardState->pfnCacheAdd ||
  227. CARD_CACHE_QUERY_SOURCE_CARDMOD == pInfo->dwQuerySource)
  228. {
  229. switch (pInfo->dwQuerySource)
  230. {
  231. case CARD_CACHE_QUERY_SOURCE_CSP:
  232. hCache = pInfo->pCardState->hCache;
  233. break;
  234. case CARD_CACHE_QUERY_SOURCE_CARDMOD:
  235. hCache = pInfo->pCardState->hCacheCardModuleData;
  236. break;
  237. default:
  238. dwSts = ERROR_INTERNAL_ERROR;
  239. goto Ret;
  240. }
  241. dwSts = CacheDeleteItem(
  242. hCache,
  243. pInfo->mpdbCacheKeys,
  244. pInfo->cCacheKeys);
  245. }
  246. Ret:
  247. return dwSts;
  248. }
  249. //
  250. // Function: I_CspReadCardCacheFile
  251. //
  252. DWORD I_CspReadCardCacheFile(
  253. IN PCARD_STATE pCardState,
  254. OUT PCARD_CACHE_FILE_FORMAT pCacheFile)
  255. {
  256. DWORD dwSts = ERROR_SUCCESS;
  257. DATA_BLOB dbCacheFile;
  258. if (FALSE == pCardState->fCacheFileValid)
  259. {
  260. memset(&dbCacheFile, 0, sizeof(dbCacheFile));
  261. dwSts = pCardState->pCardData->pfnCardReadFile(
  262. pCardState->pCardData,
  263. wszCACHE_FILE_FULL_PATH,
  264. 0,
  265. &dbCacheFile.pbData,
  266. &dbCacheFile.cbData);
  267. if (ERROR_SUCCESS != dwSts)
  268. goto Ret;
  269. if (sizeof(CARD_CACHE_FILE_FORMAT) != dbCacheFile.cbData)
  270. {
  271. dwSts = ERROR_BAD_LENGTH;
  272. goto Ret;
  273. }
  274. memcpy(
  275. &pCardState->CacheFile,
  276. dbCacheFile.pbData,
  277. sizeof(CARD_CACHE_FILE_FORMAT));
  278. pCardState->fCacheFileValid = TRUE;
  279. CspFreeH(dbCacheFile.pbData);
  280. }
  281. memcpy(
  282. pCacheFile,
  283. &pCardState->CacheFile,
  284. sizeof(CARD_CACHE_FILE_FORMAT));
  285. Ret:
  286. return dwSts;
  287. }
  288. //
  289. // Function: I_CspWriteCardCacheFile
  290. //
  291. DWORD I_CspWriteCardCacheFile(
  292. IN PCARD_STATE pCardState,
  293. IN PCARD_CACHE_FILE_FORMAT pCacheFile)
  294. {
  295. DWORD dwSts = ERROR_SUCCESS;
  296. DATA_BLOB dbCacheFile;
  297. memset(&dbCacheFile, 0, sizeof(dbCacheFile));
  298. dbCacheFile.pbData = (PBYTE) pCacheFile;
  299. dbCacheFile.cbData = sizeof(CARD_CACHE_FILE_FORMAT);
  300. dwSts = pCardState->pCardData->pfnCardWriteFile(
  301. pCardState->pCardData,
  302. wszCACHE_FILE_FULL_PATH,
  303. 0,
  304. dbCacheFile.pbData,
  305. dbCacheFile.cbData);
  306. if (ERROR_SUCCESS != dwSts)
  307. goto Ret;
  308. // Also update the cached copy of the cache file in the CARD_STATE.
  309. memcpy(
  310. &pCardState->CacheFile,
  311. pCacheFile,
  312. sizeof(CARD_CACHE_FILE_FORMAT));
  313. pCardState->fCacheFileValid = TRUE;
  314. Ret:
  315. return dwSts;
  316. }
  317. //
  318. // Function: I_CspIncrementCacheFreshness
  319. //
  320. // Purpose: Indicates that an item in the specified cache location is
  321. // being updated. As a result, the corresponding counter in
  322. // the cache file will be incremented.
  323. //
  324. DWORD I_CspIncrementCacheFreshness(
  325. IN PCARD_STATE pCardState,
  326. IN CARD_CACHE_FRESHNESS_LOCATION CacheLocation,
  327. OUT PCARD_CACHE_FILE_FORMAT pNewFreshness)
  328. {
  329. DWORD dwSts = ERROR_SUCCESS;
  330. memset(pNewFreshness, 0, sizeof(CARD_CACHE_FILE_FORMAT));
  331. dwSts = I_CspReadCardCacheFile(
  332. pCardState, pNewFreshness);
  333. if (ERROR_SUCCESS != dwSts)
  334. goto Ret;
  335. if (CacheLocation_Pins & CacheLocation)
  336. ++pNewFreshness->bPinsFreshness;
  337. if (CacheLocation_Containers & CacheLocation)
  338. ++pNewFreshness->wContainersFreshness;
  339. if (CacheLocation_Files & CacheLocation)
  340. ++pNewFreshness->wFilesFreshness;
  341. dwSts = I_CspWriteCardCacheFile(
  342. pCardState, pNewFreshness);
  343. Ret:
  344. return dwSts;
  345. }
  346. //
  347. // Function: I_CspAddCardCacheItem
  348. //
  349. // Purpose: Abstract the process of caching some card data that has been
  350. // confirmed to not exist cached (or was removed for being
  351. // stale.
  352. // Copy the provided card data, wrap it in a CARD_CACHE_ITEM_INFO
  353. // structure and then cache it.
  354. //
  355. // Assume: The card state critical section must be held by caller.
  356. // I_CspQueryCardCacheForItem should be called before this function,
  357. // without releasing the crit sec between the two calls.
  358. //
  359. DWORD I_CspAddCardCacheItem(
  360. IN PCARD_CACHE_QUERY_INFO pInfo,
  361. IN PCARD_CACHE_ITEM_INFO pItem)
  362. {
  363. DWORD dwSts = ERROR_SUCCESS;
  364. DATA_BLOB dbItem;
  365. DsysAssert(NULL == pInfo->pItem);
  366. memset(&dbItem, 0, sizeof(dbItem));
  367. if (pInfo->fIsPerishable)
  368. {
  369. if (pInfo->fCheckedFreshness)
  370. {
  371. memcpy(
  372. &pItem->CacheFreshness,
  373. &pInfo->CacheFreshness,
  374. sizeof(pInfo->CacheFreshness));
  375. }
  376. else
  377. {
  378. // This item can stale, and we haven't already queried for the
  379. // current cache counter for this location, so do it now.
  380. dwSts = I_CspReadCardCacheFile(
  381. pInfo->pCardState,
  382. &pItem->CacheFreshness);
  383. if (ERROR_SUCCESS != dwSts)
  384. goto Ret;
  385. }
  386. }
  387. dbItem.pbData = (PBYTE) pItem;
  388. dbItem.cbData = sizeof(CARD_CACHE_ITEM_INFO) + pItem->cbCachedItem;
  389. dwSts = MyCacheAddItem(pInfo, &dbItem);
  390. Ret:
  391. return dwSts;
  392. }
  393. //
  394. // Function: I_CspQueryCardCacheForItem
  395. //
  396. // Purpose: Abstract some of the processing that needs to be done for cache
  397. // lookups of card data. If the item is found
  398. // cached, check if it's perishable, and if so, if it's still valid.
  399. // If it's valid, done.
  400. // If the data is not valid, free it's resources and delete its
  401. // entry from the cache.
  402. //
  403. // Assume: The CARD_STATE critical section is assumed to be held by the caller.
  404. // Also, that the item returned by cache lookups is of type
  405. // CARD_CACHE_ITEM_INFO.
  406. //
  407. DWORD I_CspQueryCardCacheForItem(
  408. PCARD_CACHE_QUERY_INFO pInfo)
  409. {
  410. DWORD dwSts = ERROR_SUCCESS;
  411. PCARD_CACHE_ITEM_INFO pCacheItem = NULL;
  412. BOOL fItemIsFresh = TRUE;
  413. DATA_BLOB dbLocalItem;
  414. LOG_BEGIN_FUNCTION(I_CspQueryCardCacheForItem);
  415. memset(&dbLocalItem, 0, sizeof(dbLocalItem));
  416. pInfo->pItem = NULL;
  417. dwSts = MyCacheLookupItem(pInfo, &dbLocalItem);
  418. switch (dwSts)
  419. {
  420. case ERROR_SUCCESS:
  421. // Item was found cached
  422. pCacheItem = (PCARD_CACHE_ITEM_INFO) dbLocalItem.pbData;
  423. if (TRUE == pInfo->fIsPerishable)
  424. {
  425. // Is the cached data stale?
  426. if (FALSE == pInfo->fCheckedFreshness)
  427. {
  428. // We haven't already read the card cache file for this
  429. // query, so do it now.
  430. dwSts = I_CspReadCardCacheFile(
  431. pInfo->pCardState,
  432. &pInfo->CacheFreshness);
  433. if (ERROR_SUCCESS != dwSts)
  434. goto Ret;
  435. pInfo->fCheckedFreshness = TRUE;
  436. }
  437. //
  438. // Mask out and check each cache counter location, since some
  439. // cached data types may be dependent on multiple cache
  440. // locations to stay fresh.
  441. //
  442. if (CacheLocation_Pins & pInfo->CacheLocation)
  443. {
  444. if ( pCacheItem->CacheFreshness.bPinsFreshness <
  445. pInfo->CacheFreshness.bPinsFreshness)
  446. fItemIsFresh = FALSE;
  447. }
  448. if (CacheLocation_Containers & pInfo->CacheLocation)
  449. {
  450. if ( pCacheItem->CacheFreshness.wContainersFreshness <
  451. pInfo->CacheFreshness.wContainersFreshness)
  452. fItemIsFresh = FALSE;
  453. }
  454. if (CacheLocation_Files & pInfo->CacheLocation)
  455. {
  456. if ( pCacheItem->CacheFreshness.wFilesFreshness <
  457. pInfo->CacheFreshness.wFilesFreshness)
  458. fItemIsFresh = FALSE;
  459. }
  460. if (FALSE == fItemIsFresh)
  461. {
  462. // Cached data is not fresh. Delete it from the cache.
  463. pInfo->fFoundStaleItem = TRUE;
  464. dwSts = MyCacheDeleteItem(pInfo);
  465. if (ERROR_SUCCESS != dwSts)
  466. goto Ret;
  467. // Set error to indicate no cached item is being
  468. // returned.
  469. dwSts = ERROR_NOT_FOUND;
  470. goto Ret;
  471. }
  472. }
  473. // Item is either not perishable, or still fresh.
  474. pInfo->pItem = pCacheItem;
  475. pCacheItem = NULL;
  476. break;
  477. case ERROR_NOT_FOUND:
  478. // No cached data was found
  479. // Don't do anything else at this point, just report the
  480. // status to the caller.
  481. break;
  482. default:
  483. // some sort of unexpected error occurred
  484. goto Ret;
  485. }
  486. Ret:
  487. if (pCacheItem)
  488. CspFreeH(pCacheItem);
  489. LOG_END_FUNCTION(I_CspQueryCardCacheForItem, dwSts);
  490. return dwSts;
  491. }
  492. //
  493. // Initializes the CARD_CACHE_QUERY_INFO structure for a cache lookup
  494. // being performed on behalf of the card module.
  495. //
  496. void I_CspCacheInitializeQueryForCardmod(
  497. IN PVOID pvCacheContext,
  498. IN LPWSTR wszFileName,
  499. IN OUT PCARD_CACHE_QUERY_INFO pInfo,
  500. IN OUT PDATA_BLOB mpdbCacheKeys,
  501. IN DWORD cCacheKeys)
  502. {
  503. CARD_CACHED_DATA_TYPE cachedType = Cached_CardmodFile;
  504. DsysAssert(3 == cCacheKeys);
  505. // Setup the cache keys for this item
  506. mpdbCacheKeys[0].cbData = sizeof(cachedType);
  507. mpdbCacheKeys[0].pbData = (PBYTE) &cachedType;
  508. mpdbCacheKeys[1].cbData =
  509. wcslen(
  510. ((PCARD_STATE) pvCacheContext)->wszSerialNumber) * sizeof(WCHAR);
  511. mpdbCacheKeys[1].pbData =
  512. (PBYTE) ((PCARD_STATE) pvCacheContext)->wszSerialNumber;
  513. mpdbCacheKeys[2].cbData = wcslen(wszFileName) * sizeof(wszFileName[0]);
  514. mpdbCacheKeys[2].pbData = (PBYTE) wszFileName;
  515. //
  516. // Since the card module will use this function to cache files that
  517. // aren't "owned" by the Base CSP, and since cardmod files probably
  518. // don't map to our CacheLocation's very well, assume that any change
  519. // to any part of the card should cause this cached data to be staled.
  520. //
  521. pInfo->CacheLocation =
  522. CacheLocation_Pins | CacheLocation_Files | CacheLocation_Containers;
  523. pInfo->cCacheKeys = cCacheKeys;
  524. pInfo->dwQuerySource = CARD_CACHE_QUERY_SOURCE_CARDMOD;
  525. pInfo->fIsPerishable = TRUE;
  526. pInfo->mpdbCacheKeys = mpdbCacheKeys;
  527. pInfo->pCardState = (PCARD_STATE) pvCacheContext;
  528. }
  529. //
  530. // Cache "Add item" function exposed to the card module.
  531. //
  532. DWORD WINAPI CspCacheAddFileProc(
  533. IN PVOID pvCacheContext,
  534. IN LPWSTR wszTag,
  535. IN DWORD dwFlags,
  536. IN PBYTE pbData,
  537. IN DWORD cbData)
  538. {
  539. DWORD dwSts = ERROR_SUCCESS;
  540. DATA_BLOB rgdbKeys[3];
  541. PCARD_CACHE_ITEM_INFO pItem = NULL;
  542. CARD_CACHE_QUERY_INFO CacheQueryInfo;
  543. memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
  544. if (0 == cbData || NULL == pbData)
  545. goto Ret;
  546. // Copy the data to be cached into a buffer w/ space for a cache
  547. // header.
  548. pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
  549. sizeof(CARD_CACHE_ITEM_INFO) + cbData);
  550. LOG_CHECK_ALLOC(pItem);
  551. memcpy(
  552. ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO),
  553. pbData,
  554. cbData);
  555. pItem->cbCachedItem = cbData;
  556. I_CspCacheInitializeQueryForCardmod(
  557. pvCacheContext,
  558. wszTag,
  559. &CacheQueryInfo,
  560. rgdbKeys,
  561. sizeof(rgdbKeys) / sizeof(rgdbKeys[0]));
  562. dwSts = I_CspAddCardCacheItem(&CacheQueryInfo, pItem);
  563. Ret:
  564. if (pItem)
  565. CspFreeH(pItem);
  566. return dwSts;
  567. }
  568. //
  569. // Cache "Lookup item" function exposed to the card module.
  570. //
  571. DWORD WINAPI CspCacheLookupFileProc(
  572. IN PVOID pvCacheContext,
  573. IN LPWSTR wszTag,
  574. IN DWORD dwFlags,
  575. IN PBYTE *ppbData,
  576. IN PDWORD pcbData)
  577. {
  578. DWORD dwSts = ERROR_SUCCESS;
  579. DATA_BLOB rgdbKeys[3];
  580. CARD_CACHE_QUERY_INFO CacheQueryInfo;
  581. memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
  582. *ppbData = NULL;
  583. *pcbData = 0;
  584. I_CspCacheInitializeQueryForCardmod(
  585. pvCacheContext,
  586. wszTag,
  587. &CacheQueryInfo,
  588. rgdbKeys,
  589. sizeof(rgdbKeys) / sizeof(rgdbKeys[0]));
  590. dwSts = I_CspQueryCardCacheForItem(&CacheQueryInfo);
  591. // Will return ERROR_NOT_FOUND if no matching cached item was found.
  592. if (ERROR_SUCCESS != dwSts)
  593. goto Ret;
  594. *pcbData = CacheQueryInfo.pItem->cbCachedItem;
  595. *ppbData = (PBYTE) CspAllocH(*pcbData);
  596. LOG_CHECK_ALLOC(*ppbData);
  597. memcpy(
  598. *ppbData,
  599. ((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO),
  600. *pcbData);
  601. Ret:
  602. return dwSts;
  603. }
  604. //
  605. // Cache "Delete item" function exposed to the card module.
  606. //
  607. DWORD WINAPI CspCacheDeleteFileProc(
  608. IN PVOID pvCacheContext,
  609. IN LPWSTR wszTag,
  610. IN DWORD dwFlags)
  611. {
  612. DWORD dwSts = ERROR_SUCCESS;
  613. DATA_BLOB rgdbKeys[3];
  614. CARD_CACHE_QUERY_INFO CacheQueryInfo;
  615. memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
  616. I_CspCacheInitializeQueryForCardmod(
  617. pvCacheContext,
  618. wszTag,
  619. &CacheQueryInfo,
  620. rgdbKeys,
  621. sizeof(rgdbKeys) / sizeof(rgdbKeys[0]));
  622. dwSts = MyCacheDeleteItem(&CacheQueryInfo);
  623. return dwSts;
  624. }
  625. //
  626. // Initializes caching for the CSP and for the caching helper routines
  627. // provided to the card module.
  628. //
  629. DWORD InitializeCspCaching(
  630. IN OUT PCARD_STATE pCardState)
  631. {
  632. DWORD dwSts = ERROR_SUCCESS;
  633. CACHE_INITIALIZE_INFO CacheInitializeInfo;
  634. memset(&CacheInitializeInfo, 0, sizeof(CacheInitializeInfo));
  635. //
  636. // Initialize caching for the CSP
  637. //
  638. // Data cached by the CSP should be cached system-wide if possible.
  639. CacheInitializeInfo.dwType = CACHE_TYPE_SERVICE;
  640. //
  641. // Initialize our data caching routines. First, see if winscard.dll
  642. // provides caching routines. If it does, use them. Otherwise,
  643. // use our own local cache.
  644. //
  645. pCardState->hWinscard = LoadLibrary(L"winscard.dll");
  646. if (NULL == pCardState->hWinscard)
  647. {
  648. dwSts = GetLastError();
  649. goto Ret;
  650. }
  651. pCardState->pfnCacheLookup = (PFN_SCARD_CACHE_LOOKUP_ITEM) GetProcAddress(
  652. pCardState->hWinscard,
  653. "SCardCacheLookupItem");
  654. if (NULL == pCardState->pfnCacheLookup)
  655. {
  656. // Since this export is missing from winscard, use local caching.
  657. dwSts = CacheInitializeCache(
  658. &pCardState->hCache,
  659. &CacheInitializeInfo);
  660. if (ERROR_SUCCESS != dwSts)
  661. goto Ret;
  662. }
  663. else
  664. {
  665. pCardState->pfnCacheAdd = (PFN_SCARD_CACHE_ADD_ITEM) GetProcAddress(
  666. pCardState->hWinscard,
  667. "SCardCacheAddItem");
  668. if (NULL == pCardState->pfnCacheAdd)
  669. {
  670. dwSts = GetLastError();
  671. goto Ret;
  672. }
  673. }
  674. //
  675. // Initialize caching for the card module
  676. //
  677. // Assume that file data cached by the card module should only be
  678. // maintained per-process, not system-wide.
  679. CacheInitializeInfo.dwType = CACHE_TYPE_IN_PROC;
  680. dwSts = CacheInitializeCache(
  681. &pCardState->hCacheCardModuleData,
  682. &CacheInitializeInfo);
  683. if (ERROR_SUCCESS != dwSts)
  684. goto Ret;
  685. // When the card module calls back to use our caching routines,
  686. // we need a pointer to the CARD_STATE.
  687. pCardState->pCardData->pvCacheContext = pCardState;
  688. pCardState->pCardData->pfnCspCacheAddFile = CspCacheAddFileProc;
  689. pCardState->pCardData->pfnCspCacheDeleteFile = CspCacheDeleteFileProc;
  690. pCardState->pCardData->pfnCspCacheLookupFile = CspCacheLookupFileProc;
  691. Ret:
  692. return dwSts;
  693. }
  694. //
  695. // Function: InitializeCardState
  696. //
  697. DWORD InitializeCardState(
  698. IN OUT PCARD_STATE pCardState)
  699. {
  700. DWORD dwSts = ERROR_SUCCESS;
  701. dwSts = CspInitializeCriticalSection(
  702. &pCardState->cs);
  703. if (ERROR_SUCCESS != dwSts)
  704. goto Ret;
  705. else
  706. pCardState->fInitializedCS = TRUE;
  707. Ret:
  708. if (ERROR_SUCCESS != dwSts)
  709. DeleteCardState(pCardState);
  710. return dwSts;
  711. }
  712. //
  713. // Takes an array of DATA_BLOB structures, enumerated from a cache.
  714. // Frees all "pbData" pointers in the array.
  715. //
  716. void FreeCacheItems(
  717. PDATA_BLOB pdbItems,
  718. DWORD cItems)
  719. {
  720. PCARD_CACHE_ITEM_INFO pItemInfo = NULL;
  721. PCONTAINER_INFO pContainerInfo = NULL;
  722. while (0 != cItems--)
  723. CspFreeH(pdbItems[cItems].pbData);
  724. }
  725. //
  726. // Function: InitializeCardData
  727. //
  728. DWORD InitializeCardData(PCARD_DATA pCardData)
  729. {
  730. DWORD dwSts = ERROR_SUCCESS;
  731. CACHE_INITIALIZE_INFO CacheInitializeInfo;
  732. memset(&CacheInitializeInfo, 0, sizeof(CacheInitializeInfo));
  733. pCardData->dwVersion = CARD_DATA_CURRENT_VERSION;
  734. pCardData->pfnCspAlloc = CspAllocH;
  735. pCardData->pfnCspReAlloc = CspReAllocH;
  736. pCardData->pfnCspFree = CspFreeH;
  737. return dwSts;
  738. }
  739. //
  740. // Function: CleanupCardData
  741. //
  742. void CleanupCardData(PCARD_DATA pCardData)
  743. {
  744. if (pCardData->pfnCardDeleteContext)
  745. pCardData->pfnCardDeleteContext(pCardData);
  746. if (pCardData->pbAtr)
  747. {
  748. CspFreeH(pCardData->pbAtr);
  749. pCardData->pbAtr = NULL;
  750. }
  751. if (pCardData->pwszCardName)
  752. {
  753. CspFreeH(pCardData->pwszCardName);
  754. pCardData->pwszCardName = NULL;
  755. }
  756. if (pCardData->hScard)
  757. {
  758. SCardDisconnect(pCardData->hScard, SCARD_LEAVE_CARD);
  759. pCardData->hScard = 0;
  760. }
  761. if (pCardData->hSCardCtx)
  762. {
  763. SCardReleaseContext(pCardData->hSCardCtx);
  764. pCardData->hSCardCtx = 0;
  765. }
  766. }
  767. //
  768. // Enumerates and frees all items in the cache, then deletes the cache.
  769. //
  770. void DeleteCacheAndAllItems(CACHEHANDLE hCache)
  771. {
  772. PDATA_BLOB pdbCacheItems = NULL;
  773. DWORD cCacheItems = 0;
  774. if (ERROR_SUCCESS == CacheEnumItems(
  775. hCache, &pdbCacheItems, &cCacheItems))
  776. {
  777. FreeCacheItems(pdbCacheItems, cCacheItems);
  778. CacheFreeEnumItems(pdbCacheItems);
  779. }
  780. CacheDeleteCache(hCache);
  781. }
  782. //
  783. // Function: DeleteCardState
  784. //
  785. void DeleteCardState(PCARD_STATE pCardState)
  786. {
  787. DWORD dwSts = ERROR_SUCCESS;
  788. if (pCardState->fInitializedCS)
  789. CspDeleteCriticalSection(
  790. &pCardState->cs);
  791. if (pCardState->hCache)
  792. {
  793. // Need to free all of our cached data before
  794. // deleting the cache handle.
  795. DeleteCacheAndAllItems(pCardState->hCache);
  796. pCardState->hCache = 0;
  797. }
  798. if (pCardState->hCacheCardModuleData)
  799. {
  800. // Need to free the card module cached data.
  801. DeleteCacheAndAllItems(pCardState->hCacheCardModuleData);
  802. pCardState->hCacheCardModuleData = 0;
  803. }
  804. if (pCardState->hWinscard)
  805. {
  806. FreeLibrary(pCardState->hWinscard);
  807. pCardState->hWinscard = NULL;
  808. pCardState->pfnCacheAdd = NULL;
  809. pCardState->pfnCacheLookup = NULL;
  810. }
  811. if (pCardState->pCardData)
  812. {
  813. CleanupCardData(pCardState->pCardData);
  814. CspFreeH(pCardState->pCardData);
  815. }
  816. if (pCardState->hCardModule)
  817. FreeLibrary(pCardState->hCardModule);
  818. }
  819. //
  820. // Function: CspQueryCapabilities
  821. //
  822. DWORD
  823. WINAPI
  824. CspQueryCapabilities(
  825. IN PCARD_STATE pCardState,
  826. IN OUT PCARD_CAPABILITIES pCardCapabilities)
  827. {
  828. DWORD dwSts = ERROR_SUCCESS;
  829. CARD_CACHE_QUERY_INFO CacheQueryInfo;
  830. DATA_BLOB rgdbKeys[2];
  831. PCARD_CACHE_ITEM_INFO pItem = NULL;
  832. CARD_CACHED_DATA_TYPE cachedType = Cached_CardCapabilities;
  833. memset(rgdbKeys, 0, sizeof(rgdbKeys));
  834. memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
  835. rgdbKeys[0].pbData = (PBYTE) &cachedType;
  836. rgdbKeys[0].cbData = sizeof(cachedType);
  837. rgdbKeys[1].pbData = (PBYTE) pCardState->wszSerialNumber;
  838. rgdbKeys[1].cbData =
  839. sizeof(WCHAR) * wcslen(pCardState->wszSerialNumber);
  840. // Card Capabilities data item is Non-Perishable
  841. CacheQueryInfo.cCacheKeys = sizeof(rgdbKeys) / sizeof(rgdbKeys[0]);
  842. CacheQueryInfo.mpdbCacheKeys = rgdbKeys;
  843. CacheQueryInfo.pCardState = pCardState;
  844. dwSts = I_CspQueryCardCacheForItem(
  845. &CacheQueryInfo);
  846. switch (dwSts)
  847. {
  848. case ERROR_NOT_FOUND:
  849. // This data has not yet been cached. We'll have to
  850. // query the data from the card module.
  851. dwSts = pCardState->pCardData->pfnCardQueryCapabilities(
  852. pCardState->pCardData,
  853. pCardCapabilities);
  854. if (ERROR_SUCCESS != dwSts)
  855. goto Ret;
  856. // Now add this data to the cache before returning.
  857. pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
  858. sizeof(CARD_CACHE_ITEM_INFO) + sizeof(CARD_CAPABILITIES));
  859. LOG_CHECK_ALLOC(pItem);
  860. pItem->cbCachedItem = sizeof(CARD_CAPABILITIES);
  861. memcpy(
  862. ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO),
  863. pCardCapabilities,
  864. sizeof(CARD_CAPABILITIES));
  865. dwSts = I_CspAddCardCacheItem(
  866. &CacheQueryInfo,
  867. pItem);
  868. break;
  869. case ERROR_SUCCESS:
  870. //
  871. // The data was found in the cache.
  872. //
  873. DsysAssert(
  874. sizeof(CARD_CAPABILITIES) == CacheQueryInfo.pItem->cbCachedItem);
  875. memcpy(
  876. pCardCapabilities,
  877. ((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO),
  878. sizeof(CARD_CAPABILITIES));
  879. break;
  880. default:
  881. // Unexpected error
  882. break;
  883. }
  884. Ret:
  885. if (CacheQueryInfo.pItem)
  886. CspFreeH(CacheQueryInfo.pItem);
  887. if (pItem)
  888. CspFreeH(pItem);
  889. return dwSts;
  890. }
  891. //
  892. // Function: CspDeleteContainer
  893. //
  894. DWORD
  895. WINAPI
  896. CspDeleteContainer(
  897. IN PCARD_STATE pCardState,
  898. IN BYTE bContainerIndex,
  899. IN DWORD dwReserved)
  900. {
  901. DWORD dwSts = ERROR_SUCCESS;
  902. DATA_BLOB rgdbKeys[3];
  903. CARD_CACHED_DATA_TYPE cachedType = Cached_ContainerInfo;
  904. CARD_CACHE_FILE_FORMAT CacheFile;
  905. CARD_CACHE_QUERY_INFO QueryInfo;
  906. memset(&QueryInfo, 0, sizeof(QueryInfo));
  907. memset(rgdbKeys, 0, sizeof(rgdbKeys));
  908. //
  909. // First, update the cache file.
  910. //
  911. dwSts = I_CspIncrementCacheFreshness(
  912. pCardState,
  913. CacheLocation_Containers,
  914. &CacheFile);
  915. if (ERROR_SUCCESS != dwSts)
  916. goto Ret;
  917. //
  918. // Do the container deletion in the card module
  919. //
  920. dwSts = pCardState->pCardData->pfnCardDeleteContainer(
  921. pCardState->pCardData,
  922. bContainerIndex,
  923. dwReserved);
  924. if (ERROR_SUCCESS != dwSts)
  925. goto Ret;
  926. //
  927. // Finally, delete any cached Container Information for the
  928. // specified container.
  929. //
  930. // First part of key is data type
  931. rgdbKeys[0].cbData = sizeof(cachedType);
  932. rgdbKeys[0].pbData = (PBYTE) &cachedType;
  933. // Second part of key is container name
  934. rgdbKeys[1].cbData = sizeof(bContainerIndex);
  935. rgdbKeys[1].pbData = &bContainerIndex;
  936. rgdbKeys[2].cbData =
  937. wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
  938. rgdbKeys[2].pbData = (PBYTE) pCardState->wszSerialNumber;
  939. QueryInfo.cCacheKeys = sizeof(rgdbKeys) / sizeof(rgdbKeys[0]);
  940. QueryInfo.mpdbCacheKeys = rgdbKeys;
  941. QueryInfo.pCardState = pCardState;
  942. MyCacheDeleteItem(&QueryInfo);
  943. Ret:
  944. return dwSts;
  945. }
  946. //
  947. // Function: CspCreateContainer
  948. //
  949. DWORD
  950. WINAPI
  951. CspCreateContainer(
  952. IN PCARD_STATE pCardState,
  953. IN BYTE bContainerIndex,
  954. IN DWORD dwFlags,
  955. IN DWORD dwKeySpec,
  956. IN DWORD dwKeySize,
  957. IN PBYTE pbKeyData)
  958. {
  959. DWORD dwSts = ERROR_SUCCESS;
  960. CARD_CACHE_FILE_FORMAT CacheFreshness;
  961. memset(&CacheFreshness, 0, sizeof(CacheFreshness));
  962. //
  963. // Update the cache file
  964. //
  965. dwSts = I_CspIncrementCacheFreshness(
  966. pCardState,
  967. CacheLocation_Containers,
  968. &CacheFreshness);
  969. if (ERROR_SUCCESS != dwSts)
  970. goto Ret;
  971. //
  972. // Create the container on (and/or add the keyset to) the card
  973. //
  974. dwSts = pCardState->pCardData->pfnCardCreateContainer(
  975. pCardState->pCardData,
  976. bContainerIndex,
  977. dwFlags,
  978. dwKeySpec,
  979. dwKeySize,
  980. pbKeyData);
  981. Ret:
  982. return dwSts;
  983. }
  984. //
  985. // Function: CspGetContainerInfo
  986. //
  987. // Purpose: Query for key information for the specified container.
  988. //
  989. // Note, the public key buffers returned in the PCONTAINER_INFO
  990. // struct must be freed by the caller.
  991. //
  992. DWORD
  993. WINAPI
  994. CspGetContainerInfo(
  995. IN PCARD_STATE pCardState,
  996. IN BYTE bContainerIndex,
  997. IN DWORD dwFlags,
  998. IN OUT PCONTAINER_INFO pContainerInfo)
  999. {
  1000. DWORD dwSts = ERROR_SUCCESS;
  1001. DATA_BLOB rgdbKey[3];
  1002. CARD_CACHED_DATA_TYPE cachedType = Cached_ContainerInfo;
  1003. CARD_CACHE_QUERY_INFO CacheQueryInfo;
  1004. PCARD_CACHE_ITEM_INFO pItem = NULL;
  1005. memset(rgdbKey, 0, sizeof(rgdbKey));
  1006. memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
  1007. // first part of cache key is item type
  1008. rgdbKey[0].cbData = sizeof(cachedType);
  1009. rgdbKey[0].pbData = (PBYTE) &cachedType;
  1010. // second part of cache key is container name
  1011. rgdbKey[1].cbData = sizeof(bContainerIndex);
  1012. rgdbKey[1].pbData = &bContainerIndex;
  1013. rgdbKey[2].cbData =
  1014. wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
  1015. rgdbKey[2].pbData = (PBYTE) pCardState->wszSerialNumber;
  1016. CacheQueryInfo.CacheLocation = CacheLocation_Containers;
  1017. CacheQueryInfo.fIsPerishable = TRUE;
  1018. CacheQueryInfo.cCacheKeys = sizeof(rgdbKey) / sizeof(rgdbKey[0]);
  1019. CacheQueryInfo.mpdbCacheKeys = rgdbKey;
  1020. CacheQueryInfo.pCardState = pCardState;
  1021. dwSts = I_CspQueryCardCacheForItem(
  1022. &CacheQueryInfo);
  1023. switch (dwSts)
  1024. {
  1025. case ERROR_SUCCESS:
  1026. // Item was successfully found cached.
  1027. //
  1028. // This data length includes the size of the public keys, so we can
  1029. // only check a minimum size for the cached data.
  1030. //
  1031. DsysAssert(sizeof(CONTAINER_INFO) <= CacheQueryInfo.pItem->cbCachedItem);
  1032. memcpy(
  1033. pContainerInfo,
  1034. ((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO),
  1035. sizeof(CONTAINER_INFO));
  1036. //
  1037. // Now we can check the exact length of the cached blob for sanity.
  1038. //
  1039. DsysAssert(
  1040. sizeof(CONTAINER_INFO) +
  1041. pContainerInfo->cbKeyExPublicKey +
  1042. pContainerInfo->cbSigPublicKey ==
  1043. CacheQueryInfo.pItem->cbCachedItem);
  1044. //
  1045. // If the Signature and Key Exchange public keys exist, copy them out
  1046. // of the "flat" cache structure.
  1047. //
  1048. if (pContainerInfo->cbKeyExPublicKey)
  1049. {
  1050. pContainerInfo->pbKeyExPublicKey = CspAllocH(
  1051. pContainerInfo->cbKeyExPublicKey);
  1052. LOG_CHECK_ALLOC(pContainerInfo->pbKeyExPublicKey);
  1053. memcpy(
  1054. pContainerInfo->pbKeyExPublicKey,
  1055. ((PBYTE) CacheQueryInfo.pItem) +
  1056. sizeof(CARD_CACHE_ITEM_INFO) +
  1057. sizeof(CONTAINER_INFO),
  1058. pContainerInfo->cbKeyExPublicKey);
  1059. }
  1060. if (pContainerInfo->cbSigPublicKey)
  1061. {
  1062. pContainerInfo->pbSigPublicKey = CspAllocH(
  1063. pContainerInfo->cbSigPublicKey);
  1064. LOG_CHECK_ALLOC(pContainerInfo->pbSigPublicKey);
  1065. memcpy(
  1066. pContainerInfo->pbSigPublicKey,
  1067. ((PBYTE) CacheQueryInfo.pItem) +
  1068. sizeof(CARD_CACHE_ITEM_INFO) +
  1069. sizeof(CONTAINER_INFO),
  1070. pContainerInfo->cbSigPublicKey);
  1071. }
  1072. break;
  1073. case ERROR_NOT_FOUND:
  1074. // No matching item was found cached, or the found item
  1075. // was stale. Have to read it from the card.
  1076. //
  1077. // Send the request to the card module
  1078. //
  1079. dwSts = pCardState->pCardData->pfnCardGetContainerInfo(
  1080. pCardState->pCardData,
  1081. bContainerIndex,
  1082. dwFlags,
  1083. pContainerInfo);
  1084. if (ERROR_SUCCESS != dwSts)
  1085. goto Ret;
  1086. //
  1087. // Cache the returned container information
  1088. //
  1089. pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
  1090. sizeof(CARD_CACHE_ITEM_INFO) +
  1091. sizeof(CONTAINER_INFO) +
  1092. pContainerInfo->cbKeyExPublicKey +
  1093. pContainerInfo->cbSigPublicKey);
  1094. LOG_CHECK_ALLOC(pItem);
  1095. pItem->cbCachedItem =
  1096. sizeof(CONTAINER_INFO) +
  1097. pContainerInfo->cbKeyExPublicKey +
  1098. pContainerInfo->cbSigPublicKey;
  1099. memcpy(
  1100. ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO),
  1101. pContainerInfo,
  1102. sizeof(CONTAINER_INFO));
  1103. if (pContainerInfo->pbKeyExPublicKey)
  1104. {
  1105. memcpy(
  1106. ((PBYTE) pItem) +
  1107. sizeof(CARD_CACHE_ITEM_INFO) +
  1108. sizeof(CONTAINER_INFO),
  1109. pContainerInfo->pbKeyExPublicKey,
  1110. pContainerInfo->cbKeyExPublicKey);
  1111. }
  1112. if (pContainerInfo->pbSigPublicKey)
  1113. {
  1114. memcpy(
  1115. ((PBYTE) pItem) +
  1116. sizeof(CARD_CACHE_ITEM_INFO) +
  1117. sizeof(CONTAINER_INFO) +
  1118. pContainerInfo->cbKeyExPublicKey,
  1119. pContainerInfo->pbSigPublicKey,
  1120. pContainerInfo->cbSigPublicKey);
  1121. }
  1122. dwSts = I_CspAddCardCacheItem(
  1123. &CacheQueryInfo,
  1124. pItem);
  1125. break;
  1126. default:
  1127. // An unexpected error occurred.
  1128. goto Ret;
  1129. }
  1130. Ret:
  1131. if (pItem)
  1132. CspFreeH(pItem);
  1133. if (CacheQueryInfo.pItem)
  1134. CspFreeH(CacheQueryInfo.pItem);
  1135. if (ERROR_SUCCESS != dwSts)
  1136. {
  1137. if (pContainerInfo->pbKeyExPublicKey)
  1138. {
  1139. CspFreeH(pContainerInfo->pbKeyExPublicKey);
  1140. pContainerInfo->pbKeyExPublicKey = NULL;
  1141. }
  1142. if (pContainerInfo->pbSigPublicKey)
  1143. {
  1144. CspFreeH(pContainerInfo->pbSigPublicKey);
  1145. pContainerInfo->pbSigPublicKey = NULL;
  1146. }
  1147. }
  1148. return dwSts;
  1149. }
  1150. //
  1151. // Initializes the cache lookup keys and CARD_CACHE_QUERY_INFO structure
  1152. // pin-related cache operations.
  1153. //
  1154. void I_BuildPinCacheQueryInfo(
  1155. IN PCARD_STATE pCardState,
  1156. IN LPWSTR pwszUserId,
  1157. IN PDATA_BLOB pdbKey,
  1158. IN CARD_CACHED_DATA_TYPE *pType,
  1159. IN OUT PCARD_CACHE_QUERY_INFO pInfo)
  1160. {
  1161. // first part of cache key is item type
  1162. pdbKey[0].cbData = sizeof(CARD_CACHED_DATA_TYPE);
  1163. pdbKey[0].pbData = (PBYTE) pType;
  1164. // second part of cache key is user name
  1165. pdbKey[1].cbData =
  1166. wcslen(pwszUserId) * sizeof(WCHAR);
  1167. pdbKey[1].pbData = (PBYTE) pwszUserId;
  1168. pdbKey[2].cbData =
  1169. wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
  1170. pdbKey[2].pbData = (PBYTE) pCardState->wszSerialNumber;
  1171. pInfo->CacheLocation = CacheLocation_Pins;
  1172. pInfo->fIsPerishable = TRUE;
  1173. pInfo->mpdbCacheKeys = pdbKey;
  1174. pInfo->cCacheKeys = 3;
  1175. pInfo->pCardState = pCardState;
  1176. }
  1177. //
  1178. // Removes cached pin information for the specified user from the general data
  1179. // cache and the PinCache.
  1180. //
  1181. void
  1182. WINAPI
  1183. CspRemoveCachedPin(
  1184. IN PCARD_STATE pCardState,
  1185. IN LPWSTR pwszUserId)
  1186. {
  1187. DATA_BLOB rgdbKey[3];
  1188. CARD_CACHE_QUERY_INFO CacheQueryInfo;
  1189. PCARD_CACHE_ITEM_INFO pItem = NULL;
  1190. CARD_CACHED_DATA_TYPE cachedType = Cached_Pin;
  1191. memset(rgdbKey, 0, sizeof(rgdbKey));
  1192. memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
  1193. I_BuildPinCacheQueryInfo(
  1194. pCardState, pwszUserId, rgdbKey, &cachedType, &CacheQueryInfo);
  1195. MyCacheDeleteItem(&CacheQueryInfo);
  1196. PinCacheFlush(&pCardState->hPinCache);
  1197. }
  1198. //
  1199. // Record the change of the pin (or challenge) for the specified user in
  1200. // the data cache, and increment the pin cache counter on the card.
  1201. //
  1202. DWORD
  1203. WINAPI
  1204. CspChangeAuthenticator(
  1205. IN PCARD_STATE pCardState,
  1206. IN LPWSTR pwszUserId,
  1207. IN PBYTE pbCurrentAuthenticator,
  1208. IN DWORD cbCurrentAuthenticator,
  1209. IN PBYTE pbNewAuthenticator,
  1210. IN DWORD cbNewAuthenticator,
  1211. IN DWORD cRetryCount,
  1212. OUT OPTIONAL PDWORD pcAttemptsRemaining)
  1213. {
  1214. DWORD dwSts = ERROR_SUCCESS;
  1215. DATA_BLOB rgdbKey[3];
  1216. CARD_CACHE_QUERY_INFO CacheQueryInfo;
  1217. PCARD_CACHE_ITEM_INFO pItem = NULL;
  1218. CARD_CACHED_DATA_TYPE cachedType = Cached_Pin;
  1219. memset(rgdbKey, 0, sizeof(rgdbKey));
  1220. memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
  1221. //
  1222. // Do the requestion operation
  1223. //
  1224. dwSts = pCardState->pCardData->pfnCardChangeAuthenticator(
  1225. pCardState->pCardData,
  1226. pwszUserId,
  1227. pbCurrentAuthenticator,
  1228. cbCurrentAuthenticator,
  1229. pbNewAuthenticator,
  1230. cbNewAuthenticator,
  1231. cRetryCount,
  1232. pcAttemptsRemaining);
  1233. if (ERROR_SUCCESS != dwSts)
  1234. goto Ret;
  1235. //
  1236. // Update the Pins freshness counter of the card cache file. We do
  1237. // this after the pin change because we need to wait for the card to be
  1238. // authenticated.
  1239. //
  1240. dwSts = I_CspIncrementCacheFreshness(
  1241. pCardState,
  1242. CacheLocation_Pins,
  1243. &CacheQueryInfo.CacheFreshness);
  1244. if (ERROR_SUCCESS != dwSts)
  1245. goto Ret;
  1246. //
  1247. // Delete any existing entry for this user-pin in the cache
  1248. //
  1249. I_BuildPinCacheQueryInfo(
  1250. pCardState, pwszUserId, rgdbKey, &cachedType, &CacheQueryInfo);
  1251. MyCacheDeleteItem(&CacheQueryInfo);
  1252. //
  1253. // Cache the updated pin info
  1254. //
  1255. pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
  1256. sizeof(CARD_CACHE_ITEM_INFO));
  1257. LOG_CHECK_ALLOC(pItem);
  1258. dwSts = I_CspAddCardCacheItem(
  1259. &CacheQueryInfo,
  1260. pItem);
  1261. Ret:
  1262. if (pItem)
  1263. CspFreeH(pItem);
  1264. return dwSts;
  1265. }
  1266. //
  1267. // -- Expect that CspSubmitPin is only called from within a PinCache verify-pin
  1268. // callback. This is because the pbPin is expected to have come directly
  1269. // from the pin cache, and therefore may be stale.
  1270. //
  1271. // -- Expect that the user pin in the pin cache is tightly coupled to the
  1272. // cache stamp information cached in the general data cache for the user.
  1273. // That is, the cached pin must have been the correct pin when the pin-location
  1274. // cache stamp on the card had the stamp value that is stored in the general
  1275. // cache.
  1276. //
  1277. // This allows us to avoid presenting a pin to the card that we already know is
  1278. // wrong. This could happen, for example, if the pin has been changed via a
  1279. // separate process.
  1280. //
  1281. DWORD
  1282. WINAPI
  1283. CspSubmitPin(
  1284. IN PCARD_STATE pCardState,
  1285. IN LPWSTR pwszUserId,
  1286. IN PBYTE pbPin,
  1287. IN DWORD cbPin,
  1288. OUT OPTIONAL PDWORD pcAttemptsRemaining)
  1289. {
  1290. DWORD dwSts = ERROR_SUCCESS;
  1291. DATA_BLOB rgdbKey[3];
  1292. CARD_CACHE_QUERY_INFO CacheQueryInfo;
  1293. PCARD_CACHE_ITEM_INFO pItem = NULL;
  1294. CARD_CACHED_DATA_TYPE cachedType = Cached_Pin;
  1295. memset(rgdbKey, 0, sizeof(rgdbKey));
  1296. memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
  1297. I_BuildPinCacheQueryInfo(
  1298. pCardState, pwszUserId, rgdbKey, &cachedType, &CacheQueryInfo);
  1299. dwSts = I_CspQueryCardCacheForItem(
  1300. &CacheQueryInfo);
  1301. switch (dwSts)
  1302. {
  1303. case ERROR_SUCCESS:
  1304. // The user's cached pin appears to be synchronized with the pin
  1305. // cache counter on the card. Do the submit.
  1306. break;
  1307. case ERROR_NOT_FOUND:
  1308. if (TRUE == CacheQueryInfo.fFoundStaleItem)
  1309. {
  1310. //
  1311. // The user's cached pin is out of synch with the pin cache counter.
  1312. // Don't do the submit, but return a sensible error code.
  1313. //
  1314. dwSts = SCARD_W_WRONG_CHV;
  1315. goto Ret;
  1316. }
  1317. // There is no cached pin information for this user yet. Add it now.
  1318. pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
  1319. sizeof(CARD_CACHE_ITEM_INFO));
  1320. LOG_CHECK_ALLOC(pItem);
  1321. dwSts = I_CspAddCardCacheItem(
  1322. &CacheQueryInfo,
  1323. pItem);
  1324. if (ERROR_SUCCESS != dwSts)
  1325. goto Ret;
  1326. // Now continue and submit the pin
  1327. break;
  1328. default:
  1329. // Unexpected error occurred
  1330. goto Ret;
  1331. }
  1332. dwSts = pCardState->pCardData->pfnCardSubmitPin(
  1333. pCardState->pCardData,
  1334. pwszUserId,
  1335. pbPin,
  1336. cbPin,
  1337. pcAttemptsRemaining);
  1338. Ret:
  1339. if (pItem)
  1340. CspFreeH(pItem);
  1341. if (CacheQueryInfo.pItem)
  1342. CspFreeH(CacheQueryInfo.pItem);
  1343. return dwSts;
  1344. }
  1345. //
  1346. // Function: CspCreateFile
  1347. //
  1348. DWORD
  1349. WINAPI
  1350. CspCreateFile(
  1351. IN PCARD_STATE pCardState,
  1352. IN LPWSTR pwszFileName,
  1353. IN CARD_FILE_ACCESS_CONDITION AccessCondition)
  1354. {
  1355. DWORD dwSts = ERROR_SUCCESS;
  1356. CARD_CACHE_FILE_FORMAT CacheFreshness;
  1357. memset(&CacheFreshness, 0, sizeof(CacheFreshness));
  1358. //
  1359. // Update the Files freshness counter of the card cache file
  1360. //
  1361. dwSts = I_CspIncrementCacheFreshness(
  1362. pCardState,
  1363. CacheLocation_Files,
  1364. &CacheFreshness);
  1365. if (ERROR_SUCCESS != dwSts)
  1366. goto Ret;
  1367. dwSts = pCardState->pCardData->pfnCardCreateFile(
  1368. pCardState->pCardData,
  1369. pwszFileName,
  1370. AccessCondition);
  1371. Ret:
  1372. return dwSts;
  1373. }
  1374. //
  1375. // Function: CspReadFile
  1376. //
  1377. DWORD
  1378. WINAPI
  1379. CspReadFile(
  1380. IN PCARD_STATE pCardState,
  1381. IN LPWSTR pwszFileName,
  1382. IN DWORD dwFlags,
  1383. OUT PBYTE *ppbData,
  1384. OUT PDWORD pcbData)
  1385. {
  1386. DWORD dwSts = ERROR_SUCCESS;
  1387. DATA_BLOB rgdbKey[3];
  1388. CARD_CACHED_DATA_TYPE cachedType = Cached_GeneralFile;
  1389. CARD_CACHE_QUERY_INFO CacheQueryInfo;
  1390. PCARD_CACHE_ITEM_INFO pItem = NULL;
  1391. memset(rgdbKey, 0, sizeof(rgdbKey));
  1392. memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
  1393. // first part of cache key is item type
  1394. rgdbKey[0].cbData = sizeof(cachedType);
  1395. rgdbKey[0].pbData = (PBYTE) &cachedType;
  1396. // second part of cache key is file name
  1397. rgdbKey[1].cbData =
  1398. wcslen(pwszFileName) * sizeof(WCHAR);
  1399. rgdbKey[1].pbData = (PBYTE) pwszFileName;
  1400. rgdbKey[2].cbData =
  1401. wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
  1402. rgdbKey[2].pbData = (PBYTE) pCardState->wszSerialNumber;
  1403. CacheQueryInfo.CacheLocation = CacheLocation_Files;
  1404. CacheQueryInfo.fIsPerishable = TRUE;
  1405. CacheQueryInfo.mpdbCacheKeys = rgdbKey;
  1406. CacheQueryInfo.cCacheKeys = sizeof(rgdbKey) / sizeof(rgdbKey[0]);
  1407. CacheQueryInfo.pCardState = pCardState;
  1408. dwSts = I_CspQueryCardCacheForItem(
  1409. &CacheQueryInfo);
  1410. switch (dwSts)
  1411. {
  1412. case ERROR_SUCCESS:
  1413. // This file was found cached and up to date.
  1414. *pcbData = CacheQueryInfo.pItem->cbCachedItem;
  1415. *ppbData = CspAllocH(*pcbData);
  1416. LOG_CHECK_ALLOC(*ppbData);
  1417. memcpy(
  1418. *ppbData,
  1419. ((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO),
  1420. *pcbData);
  1421. break;
  1422. case ERROR_NOT_FOUND:
  1423. // An up-to-date cached version of the file was not found
  1424. dwSts = pCardState->pCardData->pfnCardReadFile(
  1425. pCardState->pCardData,
  1426. pwszFileName,
  1427. dwFlags,
  1428. ppbData,
  1429. pcbData);
  1430. if (ERROR_SUCCESS != dwSts)
  1431. goto Ret;
  1432. pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
  1433. sizeof(CARD_CACHE_ITEM_INFO) + *pcbData);
  1434. LOG_CHECK_ALLOC(pItem);
  1435. pItem->cbCachedItem = *pcbData;
  1436. memcpy(
  1437. ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO),
  1438. *ppbData,
  1439. *pcbData);
  1440. dwSts = I_CspAddCardCacheItem(
  1441. &CacheQueryInfo,
  1442. pItem);
  1443. break;
  1444. default:
  1445. // Unexpected error occurred
  1446. break;
  1447. }
  1448. Ret:
  1449. if (pItem)
  1450. CspFreeH(pItem);
  1451. if (CacheQueryInfo.pItem)
  1452. CspFreeH(CacheQueryInfo.pItem);
  1453. if (ERROR_SUCCESS != dwSts)
  1454. {
  1455. if (*ppbData)
  1456. {
  1457. CspFreeH(*ppbData);
  1458. *ppbData = NULL;
  1459. }
  1460. }
  1461. return dwSts;
  1462. }
  1463. //
  1464. // Function: CspWriteFile
  1465. //
  1466. DWORD
  1467. WINAPI
  1468. CspWriteFile(
  1469. IN PCARD_STATE pCardState,
  1470. IN LPWSTR pwszFileName,
  1471. IN DWORD dwFlags,
  1472. IN PBYTE pbData,
  1473. IN DWORD cbData)
  1474. {
  1475. DWORD dwSts = ERROR_SUCCESS;
  1476. DATA_BLOB rgdbKeys[3];
  1477. CARD_CACHED_DATA_TYPE cachedType = Cached_GeneralFile;
  1478. CARD_CACHE_QUERY_INFO CacheQueryInfo;
  1479. PCARD_CACHE_ITEM_INFO pItem = NULL;
  1480. memset(rgdbKeys, 0, sizeof(rgdbKeys));
  1481. memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
  1482. //
  1483. // Update the Files freshness counter of the card cache file
  1484. //
  1485. dwSts = I_CspIncrementCacheFreshness(
  1486. pCardState,
  1487. CacheLocation_Files,
  1488. &CacheQueryInfo.CacheFreshness);
  1489. if (ERROR_SUCCESS != dwSts)
  1490. goto Ret;
  1491. //
  1492. // Delete any existing entry for this file in the cache
  1493. //
  1494. // First cache lookup key is data type
  1495. rgdbKeys[0].cbData = sizeof(cachedType);
  1496. rgdbKeys[0].pbData = (PBYTE) &cachedType;
  1497. // Second cache lookup key is filename
  1498. rgdbKeys[1].cbData = wcslen(pwszFileName) * sizeof(WCHAR);
  1499. rgdbKeys[1].pbData = (PBYTE) pwszFileName;
  1500. rgdbKeys[2].cbData =
  1501. wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
  1502. rgdbKeys[2].pbData = (PBYTE) pCardState->wszSerialNumber;
  1503. CacheQueryInfo.fCheckedFreshness = TRUE;
  1504. CacheQueryInfo.fIsPerishable = TRUE;
  1505. CacheQueryInfo.mpdbCacheKeys = rgdbKeys;
  1506. CacheQueryInfo.cCacheKeys = sizeof(rgdbKeys) / sizeof(rgdbKeys[0]);
  1507. CacheQueryInfo.CacheLocation = CacheLocation_Files;
  1508. CacheQueryInfo.pCardState = pCardState;
  1509. //
  1510. // Since we know that any currently cached data for this file is
  1511. // obsolete, make an attempt to delete it from the cache.
  1512. //
  1513. MyCacheDeleteItem(&CacheQueryInfo);
  1514. //
  1515. // Perform the Write File operation
  1516. //
  1517. dwSts = pCardState->pCardData->pfnCardWriteFile(
  1518. pCardState->pCardData,
  1519. pwszFileName,
  1520. dwFlags,
  1521. pbData,
  1522. cbData);
  1523. if (ERROR_SUCCESS != dwSts)
  1524. goto Ret;
  1525. //
  1526. // Cache the updated file contents
  1527. //
  1528. pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
  1529. sizeof(CARD_CACHE_ITEM_INFO) + cbData);
  1530. LOG_CHECK_ALLOC(pItem);
  1531. pItem->cbCachedItem = cbData;
  1532. memcpy(
  1533. ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO),
  1534. pbData,
  1535. cbData);
  1536. dwSts = I_CspAddCardCacheItem(
  1537. &CacheQueryInfo,
  1538. pItem);
  1539. Ret:
  1540. if (pItem)
  1541. CspFreeH(pItem);
  1542. return dwSts;
  1543. }
  1544. //
  1545. // Function: CspDeleteFile
  1546. //
  1547. DWORD
  1548. WINAPI
  1549. CspDeleteFile(
  1550. IN PCARD_STATE pCardState,
  1551. IN DWORD dwReserved,
  1552. IN LPWSTR pwszFileName)
  1553. {
  1554. DWORD dwSts = ERROR_SUCCESS;
  1555. DATA_BLOB rgdbKeys[3];
  1556. CARD_CACHED_DATA_TYPE cachedType = Cached_GeneralFile;
  1557. CARD_CACHE_FILE_FORMAT CacheFile;
  1558. CARD_CACHE_QUERY_INFO QueryInfo;
  1559. memset(rgdbKeys, 0, sizeof(rgdbKeys));
  1560. memset(&QueryInfo, 0, sizeof(QueryInfo));
  1561. //
  1562. // Update the Files freshness counter of the card cache file
  1563. //
  1564. dwSts = I_CspIncrementCacheFreshness(
  1565. pCardState,
  1566. CacheLocation_Files,
  1567. &CacheFile);
  1568. if (ERROR_SUCCESS != dwSts)
  1569. goto Ret;
  1570. //
  1571. // Delete any existing entry for this file in the cache
  1572. //
  1573. // First cache lookup key is data type
  1574. rgdbKeys[0].cbData = sizeof(cachedType);
  1575. rgdbKeys[0].pbData = (PBYTE) &cachedType;
  1576. // Second cache lookup key is filename
  1577. rgdbKeys[1].cbData = wcslen(pwszFileName) * sizeof(WCHAR);
  1578. rgdbKeys[1].pbData = (PBYTE) pwszFileName;
  1579. rgdbKeys[2].cbData =
  1580. wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
  1581. rgdbKeys[2].pbData = (PBYTE) pCardState->wszSerialNumber;
  1582. QueryInfo.cCacheKeys = sizeof(rgdbKeys) / sizeof(rgdbKeys[0]);
  1583. QueryInfo.mpdbCacheKeys = rgdbKeys;
  1584. QueryInfo.pCardState = pCardState;
  1585. MyCacheDeleteItem(&QueryInfo);
  1586. //
  1587. // Do the CardDeleteFile operation
  1588. //
  1589. dwSts = pCardState->pCardData->pfnCardDeleteFile(
  1590. pCardState->pCardData,
  1591. dwReserved,
  1592. pwszFileName);
  1593. Ret:
  1594. return dwSts;
  1595. }
  1596. //
  1597. // Function: CspEnumFiles
  1598. //
  1599. DWORD
  1600. WINAPI
  1601. CspEnumFiles(
  1602. IN PCARD_STATE pCardState,
  1603. IN DWORD dwFlags,
  1604. IN OUT LPWSTR *pmwszFileNames)
  1605. {
  1606. DWORD dwSts = ERROR_SUCCESS;
  1607. DATA_BLOB rgdbKey[2];
  1608. CARD_CACHED_DATA_TYPE cachedType = Cached_FileEnumeration;
  1609. CARD_CACHE_QUERY_INFO CacheQueryInfo;
  1610. DWORD cbFileNames = 0;
  1611. PCARD_CACHE_ITEM_INFO pItem = NULL;
  1612. memset(rgdbKey, 0, sizeof(rgdbKey));
  1613. memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
  1614. // cache key is item type
  1615. rgdbKey[0].cbData = sizeof(cachedType);
  1616. rgdbKey[0].pbData = (PBYTE) &cachedType;
  1617. rgdbKey[1].cbData =
  1618. wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
  1619. rgdbKey[1].pbData = (PBYTE) pCardState->wszSerialNumber;
  1620. CacheQueryInfo.CacheLocation = CacheLocation_Files;
  1621. CacheQueryInfo.fIsPerishable = TRUE;
  1622. CacheQueryInfo.mpdbCacheKeys = rgdbKey;
  1623. CacheQueryInfo.cCacheKeys = sizeof(rgdbKey) / sizeof(rgdbKey[0]);
  1624. CacheQueryInfo.pCardState = pCardState;
  1625. dwSts = I_CspQueryCardCacheForItem(
  1626. &CacheQueryInfo);
  1627. switch (dwSts)
  1628. {
  1629. case ERROR_SUCCESS:
  1630. // The list of files was found cached and up to date.
  1631. *pmwszFileNames = (LPWSTR) CspAllocH(
  1632. CacheQueryInfo.pItem->cbCachedItem);
  1633. memcpy(
  1634. (PBYTE) *pmwszFileNames,
  1635. ((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO),
  1636. CacheQueryInfo.pItem->cbCachedItem);
  1637. break;
  1638. case ERROR_NOT_FOUND:
  1639. // An up-to-date cached version of the file was not found
  1640. dwSts = pCardState->pCardData->pfnCardEnumFiles(
  1641. pCardState->pCardData,
  1642. dwFlags,
  1643. pmwszFileNames);
  1644. if (ERROR_SUCCESS != dwSts)
  1645. goto Ret;
  1646. cbFileNames =
  1647. sizeof(WCHAR) * CountCharsInMultiSz(*pmwszFileNames);
  1648. pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
  1649. sizeof(CARD_CACHE_ITEM_INFO) + cbFileNames);
  1650. LOG_CHECK_ALLOC(pItem);
  1651. pItem->cbCachedItem = cbFileNames;
  1652. memcpy(
  1653. ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO),
  1654. (PBYTE) *pmwszFileNames,
  1655. cbFileNames);
  1656. // Cache the new data
  1657. dwSts = I_CspAddCardCacheItem(
  1658. &CacheQueryInfo,
  1659. pItem);
  1660. break;
  1661. default:
  1662. // Unexpected error occurred
  1663. break;
  1664. }
  1665. Ret:
  1666. if (pItem)
  1667. CspFreeH(pItem);
  1668. if (CacheQueryInfo.pItem)
  1669. CspFreeH(CacheQueryInfo.pItem);
  1670. if (ERROR_SUCCESS != dwSts)
  1671. {
  1672. if (*pmwszFileNames)
  1673. {
  1674. CspFreeH(*pmwszFileNames);
  1675. *pmwszFileNames = NULL;
  1676. }
  1677. }
  1678. return dwSts;
  1679. }
  1680. //
  1681. // Function: CspQueryFreeSpace
  1682. //
  1683. DWORD
  1684. WINAPI
  1685. CspQueryFreeSpace(
  1686. IN PCARD_STATE pCardState,
  1687. IN DWORD dwFlags,
  1688. OUT PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo)
  1689. {
  1690. DWORD dwSts = ERROR_SUCCESS;
  1691. DATA_BLOB rgdbKey[2];
  1692. CARD_CACHED_DATA_TYPE cachedType = Cached_FreeSpace;
  1693. CARD_CACHE_QUERY_INFO CacheQueryInfo;
  1694. PCARD_CACHE_ITEM_INFO pItem = NULL;
  1695. memset(rgdbKey, 0, sizeof(rgdbKey));
  1696. memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
  1697. // cache key is item type
  1698. rgdbKey[0].cbData = sizeof(cachedType);
  1699. rgdbKey[0].pbData = (PBYTE) &cachedType;
  1700. rgdbKey[1].cbData =
  1701. wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
  1702. rgdbKey[1].pbData = (PBYTE) pCardState->wszSerialNumber;
  1703. // Card Free Space information is dependent on both the Files
  1704. // and the Containers cache counters.
  1705. CacheQueryInfo.CacheLocation =
  1706. CacheLocation_Files | CacheLocation_Containers;
  1707. CacheQueryInfo.fIsPerishable = TRUE;
  1708. CacheQueryInfo.mpdbCacheKeys = rgdbKey;
  1709. CacheQueryInfo.cCacheKeys = sizeof(rgdbKey) / sizeof(rgdbKey[0]);
  1710. CacheQueryInfo.pCardState = pCardState;
  1711. dwSts = I_CspQueryCardCacheForItem(
  1712. &CacheQueryInfo);
  1713. switch (dwSts)
  1714. {
  1715. case ERROR_SUCCESS:
  1716. // Free Space info was found cached and up to date
  1717. DsysAssert(
  1718. sizeof(CARD_FREE_SPACE_INFO) ==
  1719. CacheQueryInfo.pItem->cbCachedItem);
  1720. memcpy(
  1721. pCardFreeSpaceInfo,
  1722. ((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO),
  1723. sizeof(CARD_FREE_SPACE_INFO));
  1724. break;
  1725. case ERROR_NOT_FOUND:
  1726. // Up to date Free Space info was not found
  1727. dwSts = pCardState->pCardData->pfnCardQueryFreeSpace(
  1728. pCardState->pCardData,
  1729. dwFlags,
  1730. pCardFreeSpaceInfo);
  1731. if (ERROR_SUCCESS != dwSts)
  1732. goto Ret;
  1733. pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
  1734. sizeof(CARD_CACHE_ITEM_INFO) + sizeof(CARD_FREE_SPACE_INFO));
  1735. LOG_CHECK_ALLOC(pItem);
  1736. pItem->cbCachedItem = sizeof(CARD_FREE_SPACE_INFO);
  1737. memcpy(
  1738. ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO),
  1739. (PBYTE) pCardFreeSpaceInfo,
  1740. sizeof(CARD_FREE_SPACE_INFO));
  1741. // Cache the new data
  1742. dwSts = I_CspAddCardCacheItem(
  1743. &CacheQueryInfo,
  1744. pItem);
  1745. break;
  1746. default:
  1747. // Unexpected error occurred
  1748. goto Ret;
  1749. }
  1750. Ret:
  1751. if (pItem)
  1752. CspFreeH(pItem);
  1753. if (CacheQueryInfo.pItem)
  1754. CspFreeH(CacheQueryInfo.pItem);
  1755. return dwSts;
  1756. }
  1757. //
  1758. // Function: CspPrivateKeyDecrypt
  1759. //
  1760. DWORD
  1761. WINAPI
  1762. CspPrivateKeyDecrypt(
  1763. IN PCARD_STATE pCardState,
  1764. IN PCARD_PRIVATE_KEY_DECRYPT_INFO pInfo)
  1765. {
  1766. return pCardState->pCardData->pfnCardPrivateKeyDecrypt(
  1767. pCardState->pCardData,
  1768. pInfo);
  1769. }
  1770. //
  1771. // Function: CspQueryKeySizes
  1772. //
  1773. DWORD
  1774. WINAPI
  1775. CspQueryKeySizes(
  1776. IN PCARD_STATE pCardState,
  1777. IN DWORD dwKeySpec,
  1778. IN DWORD dwReserved,
  1779. OUT PCARD_KEY_SIZES pKeySizes)
  1780. {
  1781. DWORD dwSts = ERROR_SUCCESS;
  1782. CARD_CACHE_QUERY_INFO CacheQueryInfo;
  1783. DATA_BLOB rgdbKeys[3];
  1784. CARD_CACHED_DATA_TYPE cachedType = Cached_KeySizes;
  1785. PCARD_CACHE_ITEM_INFO pItem = NULL;
  1786. memset(rgdbKeys, 0, sizeof(rgdbKeys));
  1787. memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
  1788. // First part of cache key is item type
  1789. rgdbKeys[0].pbData = (PBYTE) &cachedType;
  1790. rgdbKeys[0].cbData = sizeof(cachedType);
  1791. // Second part of cache key is public-key type
  1792. rgdbKeys[1].pbData = (PBYTE) &dwKeySpec;
  1793. rgdbKeys[1].cbData = sizeof(dwKeySpec);
  1794. rgdbKeys[2].pbData = (PBYTE) pCardState->wszSerialNumber;
  1795. rgdbKeys[2].cbData =
  1796. wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
  1797. // Key Sizes data item is Non-Perishable
  1798. CacheQueryInfo.cCacheKeys = sizeof(rgdbKeys) / sizeof(rgdbKeys[0]);
  1799. CacheQueryInfo.mpdbCacheKeys = rgdbKeys;
  1800. CacheQueryInfo.pCardState = pCardState;
  1801. dwSts = I_CspQueryCardCacheForItem(
  1802. &CacheQueryInfo);
  1803. switch (dwSts)
  1804. {
  1805. case ERROR_NOT_FOUND:
  1806. // This data has not yet been cached. We'll have to
  1807. // query the data from the card module.
  1808. dwSts = pCardState->pCardData->pfnCardQueryKeySizes(
  1809. pCardState->pCardData,
  1810. dwKeySpec,
  1811. dwReserved,
  1812. pKeySizes);
  1813. if (ERROR_SUCCESS != dwSts)
  1814. goto Ret;
  1815. // Now add this data to the cache
  1816. pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
  1817. sizeof(CARD_CACHE_ITEM_INFO) + sizeof(CARD_KEY_SIZES));
  1818. LOG_CHECK_ALLOC(pItem);
  1819. pItem->cbCachedItem = sizeof(CARD_KEY_SIZES);
  1820. memcpy(
  1821. ((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO),
  1822. (PBYTE) pKeySizes,
  1823. sizeof(CARD_KEY_SIZES));
  1824. dwSts = I_CspAddCardCacheItem(
  1825. &CacheQueryInfo,
  1826. pItem);
  1827. break;
  1828. case ERROR_SUCCESS:
  1829. //
  1830. // The data was found in the cache.
  1831. //
  1832. DsysAssert(
  1833. sizeof(CARD_KEY_SIZES) == CacheQueryInfo.pItem->cbCachedItem);
  1834. memcpy(
  1835. pKeySizes,
  1836. ((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO),
  1837. sizeof(CARD_KEY_SIZES));
  1838. break;
  1839. default:
  1840. // Unexpected error
  1841. break;
  1842. }
  1843. Ret:
  1844. if (pItem)
  1845. CspFreeH(pItem);
  1846. if (CacheQueryInfo.pItem)
  1847. CspFreeH(CacheQueryInfo.pItem);
  1848. return dwSts;
  1849. }