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

561 lines
13 KiB

  1. #include <windows.h>
  2. #include <wincrypt.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include "basecsp.h"
  7. #include "cardmod.h"
  8. #include <dsysdbg.h>
  9. #define wszTEST_CARD L"Wfsc Demo 3\0"
  10. #define cMAX_READERS 20
  11. //
  12. // Need to define the dsys debug symbols since we're linking directly to the
  13. // card interface lib which requires them.
  14. //
  15. DEFINE_DEBUG2(Basecsp)
  16. //
  17. // Functions defined in the card interface lib that we call.
  18. //
  19. extern DWORD InitializeCardState(PCARD_STATE);
  20. extern void DeleteCardState(PCARD_STATE);
  21. //
  22. // Wrapper for making test calls.
  23. //
  24. #define TEST_CASE(X) { if (ERROR_SUCCESS != (dwSts = X)) { printf("%s", #X); goto Ret; } }
  25. //
  26. // Function: CspAllocH
  27. //
  28. LPVOID WINAPI CspAllocH(
  29. IN SIZE_T cBytes)
  30. {
  31. return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cBytes);
  32. }
  33. //
  34. // Function: CspFreeH
  35. //
  36. void WINAPI CspFreeH(
  37. IN LPVOID pMem)
  38. {
  39. HeapFree(GetProcessHeap(), 0, pMem);
  40. }
  41. //
  42. // Function: CspReAllocH
  43. //
  44. LPVOID WINAPI CspReAllocH(
  45. IN LPVOID pMem,
  46. IN SIZE_T cBytes)
  47. {
  48. return HeapReAlloc(
  49. GetProcessHeap(), HEAP_ZERO_MEMORY, pMem, cBytes);
  50. }
  51. //
  52. // Critical Section Management
  53. //
  54. //
  55. // Function: CspInitializeCriticalSection
  56. //
  57. DWORD CspInitializeCriticalSection(
  58. IN CRITICAL_SECTION *pcs)
  59. {
  60. __try {
  61. InitializeCriticalSection(pcs);
  62. }
  63. __except (EXCEPTION_EXECUTE_HANDLER) {
  64. return ERROR_NOT_ENOUGH_MEMORY;
  65. }
  66. return ERROR_SUCCESS;
  67. }
  68. //
  69. // Function: CspEnterCriticalSection
  70. //
  71. DWORD CspEnterCriticalSection(
  72. IN CRITICAL_SECTION *pcs)
  73. {
  74. __try {
  75. EnterCriticalSection(pcs);
  76. }
  77. __except (EXCEPTION_EXECUTE_HANDLER) {
  78. return ERROR_NOT_ENOUGH_MEMORY;
  79. }
  80. return ERROR_SUCCESS;
  81. }
  82. //
  83. // Function: CspLeaveCriticalSection
  84. //
  85. void CspLeaveCriticalSection(
  86. IN CRITICAL_SECTION *pcs)
  87. {
  88. LeaveCriticalSection(pcs);
  89. }
  90. //
  91. // Function: CspDeleteCriticalSection
  92. //
  93. void CspDeleteCriticalSection(
  94. IN CRITICAL_SECTION *pcs)
  95. {
  96. DeleteCriticalSection(pcs);
  97. }
  98. int _cdecl main(int argc, char * argv[])
  99. {
  100. CARD_STATE CardState;
  101. PCARD_DATA pCardData;
  102. DWORD dwSts = ERROR_SUCCESS;
  103. PFN_CARD_ACQUIRE_CONTEXT pfnCardAcquireContext = NULL;
  104. CARD_FREE_SPACE_INFO CardFreeSpaceInfo;
  105. CARD_CAPABILITIES CardCapabilities;
  106. CARD_KEY_SIZES CardKeySizes;
  107. CONTAINER_INFO ContainerInfo;
  108. LPWSTR pwsz = NULL;
  109. DATA_BLOB dbOut;
  110. BYTE rgb [] = { 0x3, 0x2, 0x1, 0x0 };
  111. DATA_BLOB dbIn;
  112. SCARDCONTEXT hContext = 0;
  113. LPWSTR mszReaders = NULL;
  114. DWORD cchReaders = SCARD_AUTOALLOCATE;
  115. LPWSTR mszCards = NULL;
  116. DWORD cchCards = SCARD_AUTOALLOCATE;
  117. SCARD_READERSTATE rgReaderState [cMAX_READERS];
  118. DWORD iReader = 0;
  119. DWORD cchCurrent = 0;
  120. DWORD dwProtocol = 0;
  121. SCARDHANDLE hCard = 0;
  122. BOOL fConnected = FALSE;
  123. CARD_FILE_ACCESS_CONDITION Acl = EveryoneReadUserWriteAc;
  124. BYTE rgbPin [] = { 0x00, 0x00, 0x00, 0x00 };
  125. DATA_BLOB dbPin;
  126. PBYTE pbKey = NULL;
  127. DWORD cbKey = 0;
  128. HCRYPTKEY hKey = 0;
  129. HCRYPTPROV hProv = 0;
  130. WCHAR rgwsz [MAX_PATH];
  131. BYTE bContainerIndex = 0;
  132. memset(&CardState, 0, sizeof(CardState));
  133. memset(&CardFreeSpaceInfo, 0, sizeof(CardFreeSpaceInfo));
  134. memset(&CardCapabilities, 0, sizeof(CardCapabilities));
  135. memset(&ContainerInfo, 0, sizeof(ContainerInfo));
  136. memset(&CardKeySizes, 0, sizeof(CardKeySizes));
  137. memset(&dbOut, 0, sizeof(dbOut));
  138. memset(rgReaderState, 0, sizeof(rgReaderState));
  139. memset(&dbPin, 0, sizeof(dbPin));
  140. dbPin.cbData = sizeof(rgbPin);
  141. dbPin.pbData = rgbPin;
  142. dbIn.cbData = sizeof(rgb);
  143. dbIn.pbData = rgb;
  144. //
  145. // Initialization
  146. //
  147. //
  148. // Get a list of readers
  149. //
  150. dwSts = SCardEstablishContext(
  151. SCARD_SCOPE_USER, NULL, NULL, &hContext);
  152. if (ERROR_SUCCESS != dwSts)
  153. goto Ret;
  154. dwSts = SCardListReaders(
  155. hContext,
  156. NULL,
  157. (LPWSTR) &mszReaders,
  158. &cchReaders);
  159. if (ERROR_SUCCESS != dwSts)
  160. goto Ret;
  161. //
  162. // Get a list of cards
  163. //
  164. /*
  165. dwSts = SCardListCards(
  166. hContext, NULL, NULL, 0, (LPWSTR) &mszCards, &cchCards);
  167. if (ERROR_SUCCESS != dwSts)
  168. goto Ret;
  169. */
  170. //
  171. // Build the reader state array
  172. //
  173. for ( iReader = 0, cchReaders = 0;
  174. iReader < (sizeof(rgReaderState) / sizeof(rgReaderState[0]))
  175. &&
  176. L'\0' != mszReaders[cchReaders];
  177. iReader++)
  178. {
  179. rgReaderState[iReader].dwCurrentState = SCARD_STATE_UNAWARE;
  180. rgReaderState[iReader].szReader = mszReaders + cchReaders;
  181. cchReaders += 1 + wcslen(mszReaders);
  182. }
  183. //
  184. // Find a card we can talk to
  185. //
  186. dwSts = SCardLocateCards(
  187. hContext,
  188. wszTEST_CARD,
  189. rgReaderState,
  190. iReader);
  191. if (ERROR_SUCCESS != dwSts)
  192. goto Ret;
  193. while (0 != iReader && FALSE == fConnected)
  194. {
  195. iReader--;
  196. if (SCARD_STATE_ATRMATCH & rgReaderState[iReader].dwEventState)
  197. {
  198. dwSts = SCardConnect(
  199. hContext,
  200. rgReaderState[iReader].szReader,
  201. SCARD_SHARE_SHARED,
  202. SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
  203. &hCard,
  204. &dwProtocol);
  205. if (ERROR_SUCCESS != dwSts)
  206. goto Ret;
  207. else
  208. fConnected = TRUE;
  209. }
  210. }
  211. if (FALSE == fConnected)
  212. goto Ret;
  213. //
  214. // Initialize the card data structures
  215. //
  216. TEST_CASE(InitializeCardState(&CardState));
  217. CardState.hCardModule = LoadLibrary(L"cardmod.dll");
  218. if (INVALID_HANDLE_VALUE == CardState.hCardModule)
  219. {
  220. printf("LoadLibrary cardmod.dll");
  221. dwSts = GetLastError();
  222. goto Ret;
  223. }
  224. pfnCardAcquireContext =
  225. (PFN_CARD_ACQUIRE_CONTEXT) GetProcAddress(
  226. CardState.hCardModule,
  227. "CardAcquireContext");
  228. if (NULL == pfnCardAcquireContext)
  229. {
  230. printf("GetProcAddress");
  231. dwSts = GetLastError();
  232. goto Ret;
  233. }
  234. pCardData = (PCARD_DATA) CspAllocH(sizeof(CARD_DATA));
  235. if (NULL == pCardData)
  236. {
  237. dwSts = ERROR_NOT_ENOUGH_MEMORY;
  238. goto Ret;
  239. }
  240. pCardData->pwszCardName = wszTEST_CARD;
  241. pCardData->hScard = hCard;
  242. pCardData->hSCardCtx = hContext;
  243. pCardData->dwVersion = CARD_DATA_CURRENT_VERSION;
  244. pCardData->pfnCspAlloc = CspAllocH;
  245. pCardData->pfnCspReAlloc = CspReAllocH;
  246. pCardData->pfnCspFree = CspFreeH;
  247. pCardData->pbAtr = rgReaderState[iReader].rgbAtr;
  248. pCardData->cbAtr = rgReaderState[iReader].cbAtr;
  249. TEST_CASE(pfnCardAcquireContext(pCardData, 0));
  250. CardState.pCardData = pCardData;
  251. TEST_CASE(InitializeCspCaching(&CardState));
  252. //
  253. // Now start tests
  254. //
  255. //
  256. // Test 1: Container data caching
  257. //
  258. /*
  259. TEST_CASE(CspEnumContainers(&CardState, 0, &pwsz));
  260. CspFreeH(pwsz);
  261. pwsz = NULL;
  262. // Check cached call
  263. TEST_CASE(CspEnumContainers(&CardState, 0, &pwsz));
  264. CspFreeH(pwsz);
  265. pwsz = NULL;
  266. */
  267. //
  268. // Create a private key blob to import to the card
  269. //
  270. if (! CryptAcquireContext(
  271. &hProv, NULL, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
  272. {
  273. dwSts = GetLastError();
  274. goto Ret;
  275. }
  276. //
  277. // For now, make this key really small so we're sure to not run out of
  278. // space on wimpy test cards.
  279. //
  280. if (! CryptGenKey(
  281. hProv, AT_KEYEXCHANGE, (384 << 16) | CRYPT_EXPORTABLE, &hKey))
  282. {
  283. dwSts = GetLastError();
  284. goto Ret;
  285. }
  286. if (! CryptExportKey(
  287. hKey, 0, PRIVATEKEYBLOB, 0, NULL, &cbKey))
  288. {
  289. dwSts = GetLastError();
  290. goto Ret;
  291. }
  292. pbKey = (PBYTE) CspAllocH(cbKey);
  293. if (NULL == pbKey)
  294. {
  295. dwSts = ERROR_NOT_ENOUGH_MEMORY;
  296. goto Ret;
  297. }
  298. if (! CryptExportKey(
  299. hKey, 0, PRIVATEKEYBLOB, 0, pbKey, &cbKey))
  300. {
  301. dwSts = GetLastError();
  302. goto Ret;
  303. }
  304. //
  305. // Now we'll be modifying card data, so we need to authenticate.
  306. //
  307. TEST_CASE(CspSubmitPin(
  308. &CardState,
  309. wszCARD_USER_USER,
  310. dbPin.pbData,
  311. dbPin.cbData,
  312. NULL));
  313. // CreateContainer call will invalidate current container-space cache items
  314. TEST_CASE(CspCreateContainer(
  315. &CardState,
  316. bContainerIndex,
  317. CARD_CREATE_CONTAINER_KEY_IMPORT,
  318. AT_KEYEXCHANGE,
  319. cbKey,
  320. pbKey));
  321. // Cached container enum should now be invalid
  322. /*
  323. TEST_CASE(CspEnumContainers(&CardState, 0, &pwsz));
  324. CspFreeH(pwsz);
  325. pwsz = NULL;
  326. */
  327. //
  328. // Test 2: File data caching
  329. //
  330. /*
  331. TODO - re-enabled the EnumFiles tests once CardEnumFiles is correctly
  332. implemented
  333. pwsz = wszCSP_DATA_DIR_FULL_PATH;
  334. TEST_CASE(CspEnumFiles(&CardState, 0, &pwsz));
  335. CspFreeH(pwsz);
  336. pwsz = NULL;
  337. // Use cached data
  338. pwsz = wszCSP_DATA_DIR_FULL_PATH;
  339. TEST_CASE(CspEnumFiles(&CardState, 0, &pwsz));
  340. CspFreeH(pwsz);
  341. pwsz = NULL;
  342. */
  343. // Create some test files just in case they don't already exist on
  344. // this card.
  345. wsprintf(
  346. rgwsz, L"%s/File2", wszCSP_DATA_DIR_FULL_PATH);
  347. dwSts = CspCreateFile(&CardState, rgwsz, Acl);
  348. wsprintf(
  349. rgwsz, L"%s/File1", wszCSP_DATA_DIR_FULL_PATH);
  350. dwSts = CspCreateFile(&CardState, rgwsz, Acl);
  351. // Write file should invalidate all cached file data
  352. TEST_CASE(CspWriteFile(&CardState, rgwsz, 0, dbIn.pbData, dbIn.cbData));
  353. // Invalidate cached file we just created
  354. TEST_CASE(CspWriteFile(&CardState, rgwsz, 0, dbIn.pbData, dbIn.cbData));
  355. // Cached file enum should now be invalid
  356. /*
  357. pwsz = wszCSP_DATA_DIR_FULL_PATH;
  358. TEST_CASE(CspEnumFiles(&CardState, 0, &pwsz));
  359. CspFreeH(pwsz);
  360. pwsz = NULL;
  361. */
  362. //
  363. // Test 3: Get container info
  364. //
  365. ContainerInfo.dwVersion = CONTAINER_INFO_CURRENT_VERSION;
  366. TEST_CASE(CspGetContainerInfo(&CardState, bContainerIndex, 0, &ContainerInfo));
  367. // Caller won't free the key data buffers. Leave them for final cleanup.
  368. if (ContainerInfo.pbKeyExPublicKey)
  369. CspFreeH(ContainerInfo.pbKeyExPublicKey);
  370. ContainerInfo.pbKeyExPublicKey = NULL;
  371. if (ContainerInfo.pbSigPublicKey)
  372. CspFreeH(ContainerInfo.pbSigPublicKey);
  373. ContainerInfo.pbSigPublicKey = NULL;
  374. // Use cached data
  375. TEST_CASE(CspGetContainerInfo(&CardState, bContainerIndex, 0, &ContainerInfo));
  376. if (ContainerInfo.pbKeyExPublicKey)
  377. CspFreeH(ContainerInfo.pbKeyExPublicKey);
  378. ContainerInfo.pbKeyExPublicKey = NULL;
  379. if (ContainerInfo.pbSigPublicKey)
  380. CspFreeH(ContainerInfo.pbSigPublicKey);
  381. ContainerInfo.pbSigPublicKey = NULL;
  382. //
  383. // Test 4: Get Card Capabilities
  384. //
  385. CardCapabilities.dwVersion = CARD_CAPABILITIES_CURRENT_VERSION;
  386. TEST_CASE(CspQueryCapabilities(&CardState, &CardCapabilities));
  387. // Read cached
  388. TEST_CASE(CspQueryCapabilities(&CardState, &CardCapabilities));
  389. //
  390. // Test 5: Read file
  391. //
  392. wsprintf(
  393. rgwsz, L"%s/File1", wszCSP_DATA_DIR_FULL_PATH);
  394. TEST_CASE(CspReadFile(&CardState, rgwsz, 0, &dbOut.pbData, &dbOut.cbData));
  395. CspFreeH(dbOut.pbData);
  396. memset(&dbOut, 0, sizeof(dbOut));
  397. // Use cached data
  398. TEST_CASE(CspReadFile(&CardState, rgwsz, 0, &dbOut.pbData, &dbOut.cbData));
  399. CspFreeH(dbOut.pbData);
  400. memset(&dbOut, 0, sizeof(dbOut));
  401. wsprintf(
  402. rgwsz, L"%s/File2", wszCSP_DATA_DIR_FULL_PATH);
  403. // Invalidate all file-related cached data
  404. TEST_CASE(CspDeleteFile(&CardState, 0, rgwsz));
  405. wsprintf(
  406. rgwsz, L"%s/File1", wszCSP_DATA_DIR_FULL_PATH);
  407. // Re-read file from card
  408. TEST_CASE(CspReadFile(&CardState, rgwsz, 0, &dbOut.pbData, &dbOut.cbData));
  409. CspFreeH(dbOut.pbData);
  410. memset(&dbOut, 0, sizeof(dbOut));
  411. //
  412. // Test 6: Query Key Sizes
  413. //
  414. CardKeySizes.dwVersion = CARD_KEY_SIZES_CURRENT_VERSION;
  415. // Signature Keys
  416. TEST_CASE(CspQueryKeySizes(&CardState, AT_SIGNATURE, 0, &CardKeySizes));
  417. // Query cached
  418. TEST_CASE(CspQueryKeySizes(&CardState, AT_SIGNATURE, 0, &CardKeySizes));
  419. // Key Exchange Keys
  420. TEST_CASE(CspQueryKeySizes(&CardState, AT_KEYEXCHANGE, 0, &CardKeySizes));
  421. // Query cached
  422. TEST_CASE(CspQueryKeySizes(&CardState, AT_KEYEXCHANGE, 0, &CardKeySizes));
  423. Ret:
  424. if (pbKey)
  425. CspFreeH(pbKey);
  426. if (hKey)
  427. CryptDestroyKey(hKey);
  428. if (hProv)
  429. CryptReleaseContext(hProv, 0);
  430. if (mszCards)
  431. SCardFreeMemory(hContext, mszCards);
  432. if (mszReaders)
  433. SCardFreeMemory(hContext, mszReaders);
  434. if (dbOut.pbData)
  435. CspFreeH(dbOut.pbData);
  436. if (pwsz)
  437. CspFreeH(pwsz);
  438. if (ERROR_SUCCESS != dwSts)
  439. printf(" failed, 0x%x\n", dwSts);
  440. // Static buffers were used, don't let them be freed
  441. pCardData->pwszCardName = NULL;
  442. pCardData->pbAtr = NULL;
  443. DeleteCardState(&CardState);
  444. return 0;
  445. }