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.

3053 lines
81 KiB

  1. #include <windows.h>
  2. #include <psapi.h>
  3. #pragma warning(push)
  4. #pragma warning(disable:4201)
  5. // Disable error C4201 in public header
  6. // nonstandard extension used : nameless struct/union
  7. #include <winscard.h>
  8. #pragma warning(pop)
  9. #include "basecsp.h"
  10. #include "cardmod.h"
  11. #include "wpscproxy.h"
  12. #include "marshalpc.h"
  13. #include <limits.h>
  14. #include "pincache.h"
  15. #include <rsa.h>
  16. #include <carddbg.h>
  17. #include <stdio.h>
  18. #include "physfile.h"
  19. DWORD I_CardMapErrorCode(IN SCODE status);
  20. //
  21. // Get the number of characters in a Unicode string,
  22. // NOT including the terminating Null.
  23. //
  24. #define WSZ_CHAR_COUNT(x) ((sizeof(x) / sizeof(WCHAR)) - 1)
  25. //
  26. // Macro for testing DWORD return codes. Any return not equal to
  27. // ERROR_SUCCESS is assumed to mean Failure.
  28. //
  29. #define CARDMOD_FAILED(x) (ERROR_SUCCESS != x)
  30. //
  31. // Debug Logging
  32. //
  33. // This uses the debug routines from dsysdbg.h
  34. // Debug output will only be available in chk
  35. // bits.
  36. //
  37. DEFINE_DEBUG2(Cardmod)
  38. #define LOG_BEGIN_FUNCTION(x) \
  39. { DebugLog((DEB_TRACE_FUNC, "%s: Entering\n", #x)); }
  40. #define LOG_END_FUNCTION(x, y) \
  41. { DebugLog((DEB_TRACE_FUNC, "%s: Leaving, status: 0x%x\n", #x, y)); }
  42. #define LOG_CHECK_ALLOC(x) \
  43. { if (NULL == x) { \
  44. dwError = ERROR_NOT_ENOUGH_MEMORY; \
  45. DebugLog((DEB_TRACE_MEM, "%s: Allocation failed\n", #x)); \
  46. goto Ret; \
  47. } }
  48. #define LOG_CHECK_SCW_CALL(x) \
  49. { if (ERROR_SUCCESS != (dwError = I_CardMapErrorCode(x))) { \
  50. DebugLog((DEB_TRACE_FUNC, "%s: failed, status: 0x%x\n", \
  51. #x, dwError)); \
  52. goto Ret; \
  53. } }
  54. //
  55. // Defines for interoperating with Crypto API public keys
  56. //
  57. #define cbCAPI_PUBLIC_EXPONENT 3
  58. #define CAPI_PUBLIC_EXPONENT 0x10001
  59. //
  60. // Define data size used for Admin principal challenge-response authentication
  61. //
  62. #define cbCHALLENGE_RESPONSE_DATA 8
  63. //
  64. // Card module applet instruction codes
  65. //
  66. #define PIN_CHANGE_CLA 0x00
  67. #define PIN_CHANGE_INS 0x52
  68. #define PIN_CHANGE_P1 0x00
  69. #define PIN_CHANGE_P2 0x00
  70. #define PIN_UNBLOCK_CLA 0x00
  71. #define PIN_UNBLOCK_INS 0x52
  72. #define PIN_UNBLOCK_P1 0x01
  73. // PIN_UNBLOCK_P2 is the new max retry count, which can be set by caller
  74. #define PIN_RETRY_COUNTER_CLA 0x00
  75. #define PIN_RETRY_COUNTER_INS 0x50
  76. #define PIN_RETRY_COUNTER_P1 0x00
  77. #define PIN_RETRY_COUNTER_P2 0x00
  78. //
  79. // Data Structures used by this module
  80. //
  81. //
  82. // Type: SUPPORTED_CARD
  83. //
  84. #define MAX_SUPPORTED_FILE_LEN 50 // WCHARS
  85. #define MAX_SUPPORTED_CARD_ATR_LEN 21
  86. typedef struct _SUPPORTED_CARD_
  87. {
  88. LPWSTR wszCardName;
  89. BYTE rgbAtr[MAX_SUPPORTED_CARD_ATR_LEN];
  90. DWORD cbAtr;
  91. BYTE rgbAtrMask[MAX_SUPPORTED_CARD_ATR_LEN];
  92. CARD_CAPABILITIES CardCapabilities;
  93. CARD_FREE_SPACE_INFO CardFreeSpaceInfo;
  94. CARD_KEY_SIZES CardKeySizes_KeyEx;
  95. CARD_KEY_SIZES CardKeySizes_Sig;
  96. } SUPPORTED_CARD, *PSUPPORTED_CARD;
  97. SUPPORTED_CARD SupportedCards [] =
  98. {
  99. //
  100. // ITG's deployment cards
  101. //
  102. // T=1
  103. { L"ITG_MSCSP_V1",
  104. { 0x3b, 0x8c, 0x81, 0x31, 0x20, 0x55, 0x49, 0x54,
  105. 0x47, 0x5f, 0x4d, 0x53, 0x43, 0x53, 0x50, 0x5f,
  106. 0x56, 0x31, 0x2a },
  107. 19,
  108. { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  109. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  110. 0xFF, 0xFF, 0xFF },
  111. { CARD_CAPABILITIES_CURRENT_VERSION, FALSE, FALSE },
  112. { CARD_FREE_SPACE_INFO_CURRENT_VERSION, CARD_DATA_VALUE_UNKNOWN, (DWORD) -1, 2 },
  113. { CARD_KEY_SIZES_CURRENT_VERSION, 1024, 1024, 1024, 0 },
  114. { CARD_KEY_SIZES_CURRENT_VERSION, 1024, 1024, 1024, 0 }
  115. },
  116. // T=0
  117. { L"ITG_MSCSP_V2",
  118. { 0x3b, 0xdc, 0x13, 0x00, 0x40, 0x3a, 0x49, 0x54,
  119. 0x47, 0x5f, 0x4d, 0x53, 0x43, 0x53, 0x50, 0x5f,
  120. 0x56, 0x32 },
  121. 18,
  122. { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  123. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  124. 0xFF, 0xFF },
  125. { CARD_CAPABILITIES_CURRENT_VERSION, FALSE, FALSE },
  126. { CARD_FREE_SPACE_INFO_CURRENT_VERSION, CARD_DATA_VALUE_UNKNOWN, (DWORD) -1, 2 },
  127. { CARD_KEY_SIZES_CURRENT_VERSION, 1024, 1024, 1024, 0 },
  128. { CARD_KEY_SIZES_CURRENT_VERSION, 1024, 1024, 1024, 0 }
  129. },
  130. //
  131. // These are Windows for Smart Cards test cards. They do not support
  132. // on-card key gen.
  133. //
  134. // T=0 Cards
  135. { L"BaseCSP-T0-1",
  136. { 0x3B, 0xDC, 0x13, 0x00, 0x40, 0x3A, 0x42, 0x61,
  137. 0x73, 0x65, 0x43, 0x53, 0x50, 0x2D, 0x54, 0x30,
  138. 0x2D, 0x31 },
  139. 18,
  140. { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  141. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  142. 0xFF, 0xFF },
  143. { CARD_CAPABILITIES_CURRENT_VERSION, FALSE, FALSE },
  144. { CARD_FREE_SPACE_INFO_CURRENT_VERSION, CARD_DATA_VALUE_UNKNOWN, (DWORD) -1, 2 },
  145. { CARD_KEY_SIZES_CURRENT_VERSION, 1024, 1024, 1024, 0 },
  146. { CARD_KEY_SIZES_CURRENT_VERSION, 1024, 1024, 1024, 0 }
  147. },
  148. // T=1 Card, 9600 bps
  149. { L"BaseCSP-T1-1",
  150. { 0x3B, 0x8C, 0x81, 0x31, 0x20, 0x55, 0x42, 0x61,
  151. 0x73, 0x65, 0x43, 0x53, 0x50, 0x2D, 0x54, 0x31,
  152. 0x2D, 0x31, 0x68 },
  153. 19,
  154. { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  155. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  156. 0xFF, 0xFF, 0xFF },
  157. { CARD_CAPABILITIES_CURRENT_VERSION, FALSE, FALSE },
  158. { CARD_FREE_SPACE_INFO_CURRENT_VERSION, CARD_DATA_VALUE_UNKNOWN, (DWORD) -1, 2 },
  159. { CARD_KEY_SIZES_CURRENT_VERSION, 1024, 1024, 1024, 0 },
  160. { CARD_KEY_SIZES_CURRENT_VERSION, 1024, 1024, 1024, 0 }
  161. },
  162. // T=1 Card, 19 kbps
  163. { L"BaseCSP-T1-2",
  164. { 0x3B, 0xDC, 0x13, 0x0A, 0x81, 0x31, 0x20, 0x55, 0x42, 0x61,
  165. 0x73, 0x65, 0x43, 0x53, 0x50, 0x2D, 0x54, 0x31,
  166. 0x2D, 0x31, 0x21 },
  167. 21,
  168. { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  169. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  170. 0xFF, 0xFF, 0xFF },
  171. { CARD_CAPABILITIES_CURRENT_VERSION, FALSE, FALSE },
  172. { CARD_FREE_SPACE_INFO_CURRENT_VERSION, CARD_DATA_VALUE_UNKNOWN, (DWORD) -1, 2 },
  173. { CARD_KEY_SIZES_CURRENT_VERSION, 1024, 1024, 1024, 0 },
  174. { CARD_KEY_SIZES_CURRENT_VERSION, 1024, 1024, 1024, 0 }
  175. },
  176. // T=1 Card, 38 kbps
  177. { L"BaseCSP-T1-3",
  178. { 0x3B, 0x9C, 0x13, 0x81, 0x31, 0x20, 0x55, 0x42, 0x61,
  179. 0x73, 0x65, 0x43, 0x53, 0x50, 0x2D, 0x54, 0x31,
  180. 0x2D, 0x31, 0x6B },
  181. 20,
  182. { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  183. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  184. 0xFF, 0xFF, 0xFF },
  185. { CARD_CAPABILITIES_CURRENT_VERSION, FALSE, FALSE },
  186. { CARD_FREE_SPACE_INFO_CURRENT_VERSION, CARD_DATA_VALUE_UNKNOWN, (DWORD) -1, 2 },
  187. { CARD_KEY_SIZES_CURRENT_VERSION, 1024, 1024, 1024, 0 },
  188. { CARD_KEY_SIZES_CURRENT_VERSION, 1024, 1024, 1024, 0 }
  189. }
  190. };
  191. static WCHAR l_wszImagePath[MAX_PATH];
  192. //
  193. // Type: CARDMOD_CONTEXT
  194. //
  195. typedef struct _CARDMOD_CONTEXT
  196. {
  197. SCARDHANDLE hWfscCardHandle;
  198. PSUPPORTED_CARD pSupportedCard;
  199. } CARDMOD_CONTEXT, *PCARDMOD_CONTEXT;
  200. typedef struct _VERIFY_PIN_CALLBACK_DATA
  201. {
  202. LPWSTR wszUserId;
  203. PCARD_DATA pCardData;
  204. } VERIFY_PIN_CALLBACK_DATA, *PVERIFY_PIN_CALLBACK_DATA;
  205. //
  206. // Maps status codes returned from the Smart Card for Windows proxy to common
  207. // Windows status codes.
  208. //
  209. DWORD I_CardMapErrorCode(
  210. IN SCODE status)
  211. {
  212. DWORD iMap = 0;
  213. struct {
  214. SCODE scode;
  215. DWORD dwError;
  216. } ErrorMap [] = {
  217. { SCW_S_OK, ERROR_SUCCESS },
  218. { SCW_E_FILENOTFOUND, (DWORD) SCARD_E_FILE_NOT_FOUND },
  219. { SCW_E_DIRNOTFOUND, (DWORD) SCARD_E_DIR_NOT_FOUND },
  220. { SCW_E_PARTITIONFULL, (DWORD) SCARD_E_WRITE_TOO_MANY },
  221. { SCW_E_MEMORYFAILURE, ERROR_NOT_ENOUGH_MEMORY },
  222. { SCW_E_VMNOMEMORY, ERROR_NOT_ENOUGH_MEMORY },
  223. { SCW_E_NOTAUTHENTICATED, (DWORD) SCARD_E_INVALID_CHV },
  224. { SCW_E_ALREADYEXISTS, (DWORD) ERROR_FILE_EXISTS }
  225. };
  226. for (iMap = 0; iMap < (sizeof(ErrorMap) / sizeof(ErrorMap[0])); iMap++)
  227. {
  228. if (ErrorMap[iMap].scode == status)
  229. return ErrorMap[iMap].dwError;
  230. }
  231. // Otherwise, best we can do is pass a general error
  232. DebugLog((
  233. DEB_WARN,
  234. "I_CardMapErrorCode could not map error 0x%X\n",
  235. status));
  236. return (DWORD) SCARD_F_INTERNAL_ERROR;
  237. }
  238. //
  239. // Maps the error code returned by a card applet to a common error code. The
  240. // status word returned by the applet is first converted into a Windows For
  241. // Smart Cards error code.
  242. //
  243. // Reminder: Status words returned by the RTE apps are in the form:
  244. // 9000 -> Success
  245. // 6Fyy -> An API failed with return code yy
  246. // 6Ezz -> An exception was raised (zz is the err number)
  247. //
  248. DWORD I_CardMapExecuteErrorCode(
  249. IN WORD wStatus)
  250. {
  251. SCODE status = 0xC0000000 | (wStatus & 0xFF);
  252. if (0x90 == (wStatus >> 8))
  253. return ERROR_SUCCESS;
  254. else
  255. return I_CardMapErrorCode(status);
  256. }
  257. //
  258. // Creates and writes a new file to the card with the supplied Access Condition
  259. // and file contents. If fCache is true, the file is cached using the caller's
  260. // CacheAddFile function.
  261. //
  262. DWORD I_CardWriteFile(
  263. IN PCARD_DATA pCardData,
  264. IN LPWSTR wszPhysicalFile,
  265. IN LPWSTR wszAcl,
  266. IN PBYTE pbData,
  267. IN DWORD cbData,
  268. IN BOOL fCache)
  269. {
  270. DWORD dwError = ERROR_SUCCESS;
  271. PCARDMOD_CONTEXT pCardmodContext =
  272. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  273. HFILE hFile = 0;
  274. DWORD cbActual = 0;
  275. UNREFERENCED_PARAMETER(fCache);
  276. LOG_CHECK_SCW_CALL(hScwCreateFile(
  277. pCardmodContext->hWfscCardHandle,
  278. wszPhysicalFile,
  279. wszAcl,
  280. &hFile));
  281. LOG_CHECK_SCW_CALL(hScwWriteFile32(
  282. pCardmodContext->hWfscCardHandle,
  283. hFile,
  284. pbData,
  285. cbData,
  286. &cbActual));
  287. if (cbActual != cbData)
  288. {
  289. dwError = (DWORD) SCARD_W_EOF;
  290. goto Ret;
  291. }
  292. DebugLog((
  293. DEB_TRACE,
  294. "I_CardWriteFile: wrote %S, %d bytes\n",
  295. wszPhysicalFile,
  296. cbData));
  297. if (fCache)
  298. {
  299. dwError = pCardData->pfnCspCacheAddFile(
  300. pCardData->pvCacheContext,
  301. wszPhysicalFile,
  302. 0,
  303. pbData,
  304. cbData);
  305. }
  306. Ret:
  307. if (hFile)
  308. hScwCloseFile(
  309. pCardmodContext->hWfscCardHandle, hFile);
  310. return dwError;
  311. }
  312. //
  313. // If fUseCached is true, first attempts to satisfy the read request
  314. // via the caller's CacheLookupFile function. Otherwise,
  315. // reads a file directly from the smart card by first opening the file and
  316. // determining its size. The file is cached using the caller's CacheAddFile
  317. // pointer if fCache is true.
  318. //
  319. DWORD I_CardReadFile(
  320. IN PCARD_DATA pCardData,
  321. IN LPWSTR wszPhysicalFile,
  322. OUT PBYTE *ppbData,
  323. OUT DWORD *pcbData,
  324. IN BOOL fUseCached)
  325. {
  326. DWORD dwError = ERROR_SUCCESS;
  327. PCARDMOD_CONTEXT pCardmodContext =
  328. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  329. HFILE hFile = 0;
  330. DWORD cbActual = 0;
  331. if (fUseCached)
  332. {
  333. dwError = pCardData->pfnCspCacheLookupFile(
  334. pCardData->pvCacheContext,
  335. wszPhysicalFile,
  336. 0,
  337. ppbData,
  338. pcbData);
  339. switch (dwError)
  340. {
  341. case ERROR_NOT_FOUND:
  342. // A cached copy of the requested file is not available;
  343. // read it from the card.
  344. break;
  345. case ERROR_SUCCESS:
  346. // Fall through
  347. default:
  348. // Either we found cached data or an unexpected error occurred.
  349. // We're done.
  350. goto Ret;
  351. }
  352. }
  353. LOG_CHECK_SCW_CALL(hScwCreateFile(
  354. pCardmodContext->hWfscCardHandle,
  355. wszPhysicalFile,
  356. NULL,
  357. &hFile));
  358. LOG_CHECK_SCW_CALL(hScwGetFileLength(
  359. pCardmodContext->hWfscCardHandle,
  360. hFile,
  361. (TOFFSET *) pcbData));
  362. *ppbData = (PBYTE) pCardData->pfnCspAlloc(*pcbData);
  363. LOG_CHECK_ALLOC(*ppbData);
  364. LOG_CHECK_SCW_CALL(hScwReadFile32(
  365. pCardmodContext->hWfscCardHandle,
  366. hFile,
  367. *ppbData,
  368. *pcbData,
  369. &cbActual));
  370. if (cbActual != *pcbData)
  371. dwError = (DWORD) SCARD_W_EOF;
  372. DebugLog((
  373. DEB_TRACE,
  374. "I_CardReadFile: read %S, %d bytes\n",
  375. wszPhysicalFile,
  376. *pcbData));
  377. if (fUseCached)
  378. {
  379. // Cache this file.
  380. dwError = pCardData->pfnCspCacheAddFile(
  381. pCardData->pvCacheContext,
  382. wszPhysicalFile,
  383. 0,
  384. *ppbData,
  385. *pcbData);
  386. }
  387. Ret:
  388. if (hFile)
  389. hScwCloseFile(
  390. pCardmodContext->hWfscCardHandle, hFile);
  391. if (ERROR_SUCCESS != dwError && *ppbData)
  392. {
  393. pCardData->pfnCspFree(*ppbData);
  394. *ppbData = NULL;
  395. }
  396. return dwError;
  397. }
  398. //
  399. // Maps a logical user name to a physical user, or principal, recognized by
  400. // the card.
  401. //
  402. DWORD GetWellKnownUserMapping(
  403. IN PCARD_DATA pCardData,
  404. IN LPWSTR wszLogicalUser,
  405. OUT LPWSTR *ppwszPhysicalUser)
  406. {
  407. DWORD dwError = ERROR_NO_SUCH_USER;
  408. int iUser = 0;
  409. static const WCHAR wszAdmin [] = L"admin";
  410. static const WCHAR wszAnonymous [] = L"anonymous";
  411. static const WCHAR wszUser [] = L"user";
  412. struct {
  413. LPWSTR wszLogicalUser;
  414. const WCHAR (*wszPhysicalUser);
  415. DWORD cchPhysicalUser;
  416. } UserMap [] = {
  417. { wszCARD_USER_ADMIN,
  418. wszAdmin,
  419. WSZ_CHAR_COUNT(wszAdmin) },
  420. { wszCARD_USER_EVERYONE,
  421. wszAnonymous,
  422. WSZ_CHAR_COUNT(wszAnonymous) },
  423. { wszCARD_USER_USER,
  424. wszUser,
  425. WSZ_CHAR_COUNT(wszUser) }
  426. };
  427. for (iUser = 0; iUser < sizeof(UserMap) / sizeof(UserMap[0]); iUser++)
  428. {
  429. if (0 == wcscmp(wszLogicalUser, UserMap[iUser].wszLogicalUser))
  430. {
  431. *ppwszPhysicalUser = (LPWSTR) pCardData->pfnCspAlloc(
  432. sizeof(WCHAR) * (1 + UserMap[iUser].cchPhysicalUser));
  433. LOG_CHECK_ALLOC(*ppwszPhysicalUser);
  434. wcscpy(
  435. *ppwszPhysicalUser,
  436. UserMap[iUser].wszPhysicalUser);
  437. dwError = ERROR_SUCCESS;
  438. break;
  439. }
  440. }
  441. Ret:
  442. return dwError;
  443. }
  444. //
  445. // Maps a logical Access Condition to a physical ACL file recognized by the
  446. // card.
  447. //
  448. DWORD GetWellKnownAcMapping(
  449. IN PCARD_DATA pCardData,
  450. IN CARD_FILE_ACCESS_CONDITION AccessCondition,
  451. OUT LPWSTR *ppwszPhysicalAclFile)
  452. {
  453. DWORD dwError = ERROR_NOT_FOUND;
  454. int iAcl = 0;
  455. struct {
  456. CARD_FILE_ACCESS_CONDITION LogicalAc;
  457. const WCHAR (*wszPhysicalAcl);
  458. DWORD cchPhysicalAcl;
  459. } AclMap [] = {
  460. { EveryoneReadUserWriteAc,
  461. wszUserWritePhysicalAcl,
  462. WSZ_CHAR_COUNT(wszUserWritePhysicalAcl) },
  463. { UserWriteExecuteAc,
  464. wszUserExecutePhysicalAcl,
  465. WSZ_CHAR_COUNT(wszUserExecutePhysicalAcl) },
  466. { EveryoneReadAdminWriteAc,
  467. wszAdminWritePhysicalAcl,
  468. WSZ_CHAR_COUNT(wszAdminWritePhysicalAcl) }
  469. };
  470. for (iAcl = 0; iAcl< sizeof(AclMap) / sizeof(AclMap[0]); iAcl++)
  471. {
  472. if (AccessCondition == AclMap[iAcl].LogicalAc)
  473. {
  474. *ppwszPhysicalAclFile = (LPWSTR) pCardData->pfnCspAlloc(
  475. (1 + AclMap[iAcl].cchPhysicalAcl) * sizeof(WCHAR));
  476. LOG_CHECK_ALLOC(*ppwszPhysicalAclFile);
  477. memcpy(
  478. *ppwszPhysicalAclFile,
  479. AclMap[iAcl].wszPhysicalAcl,
  480. (1 + AclMap[iAcl].cchPhysicalAcl) * sizeof(WCHAR));
  481. dwError = ERROR_SUCCESS;
  482. break;
  483. }
  484. }
  485. Ret:
  486. return dwError;
  487. }
  488. //
  489. // Maps a well known logical file or directory name to a physical file
  490. // or directory.
  491. //
  492. DWORD GetWellKnownFileMapping(
  493. IN PCARD_DATA pCardData,
  494. IN LPWSTR wszLogicalFileName,
  495. OUT LPSTR *ppszPhysicalFileName)
  496. {
  497. DWORD cbPhysicalFileName = 0;
  498. int i = 0;
  499. BOOL fMatched = FALSE;
  500. DWORD dwError = ERROR_SUCCESS;
  501. DWORD cchLogicalName = 0;
  502. LPSTR szAnsiExtra = NULL;
  503. enum NameType { File, Directory };
  504. struct {
  505. LPWSTR wszLogicalName;
  506. LPSTR szPhysicalName;
  507. enum NameType type;
  508. DWORD cbPhysicalName;
  509. } FileMap [] = {
  510. //
  511. // When composing the lookup table, the deepest directory paths
  512. // must be listed first, so that partial matching will find the
  513. // longest partial match first.
  514. //
  515. { wszUSER_SIGNATURE_CERT_PREFIX, szPHYSICAL_USER_SIGNATURE_CERT_PREFIX,
  516. File, cbPHYSICAL_USER_SIGNATURE_CERT_PREFIX },
  517. { wszUSER_KEYEXCHANGE_CERT_PREFIX,szPHYSICAL_USER_KEYEXCHANGE_CERT_PREFIX,
  518. File, cbPHYSICAL_USER_KEYEXCHANGE_CERT_PREFIX },
  519. { wszCSP_DATA_DIR_FULL_PATH, szPHYSICAL_CSP_DIR,
  520. Directory, cbPHYSICAL_CSP_DIR },
  521. { wszCACHE_FILE_FULL_PATH, szPHYSICAL_CACHE_FILE,
  522. File, cbPHYSICAL_CACHE_FILE },
  523. { wszCARD_IDENTIFIER_FILE_FULL_PATH,
  524. szPHYSICAL_CARD_IDENTIFIER,
  525. File, cbPHYSICAL_CARD_IDENTIFIER },
  526. { wszCONTAINER_MAP_FILE_FULL_PATH,
  527. szPHYSICAL_CONTAINER_MAP_FILE,
  528. File, cbPHYSICAL_CONTAINER_MAP_FILE },
  529. { wszPERSONAL_DATA_FILE_FULL_PATH,
  530. szPHYSICAL_PERSONAL_DATA_FILE,
  531. File, cbPHYSICAL_PERSONAL_DATA_FILE }
  532. };
  533. *ppszPhysicalFileName = NULL;
  534. // First, look for an exact match.
  535. for (i = 0; i < sizeof(FileMap) / sizeof(FileMap[0]); i++)
  536. {
  537. if (0 == wcscmp(wszLogicalFileName, FileMap[i].wszLogicalName))
  538. {
  539. fMatched = TRUE;
  540. break;
  541. }
  542. }
  543. if (fMatched)
  544. {
  545. if (NULL == FileMap[i].szPhysicalName)
  546. {
  547. dwError = ERROR_NOT_FOUND;
  548. goto Ret;
  549. }
  550. cbPhysicalFileName = FileMap[i].cbPhysicalName + sizeof(WCHAR);
  551. *ppszPhysicalFileName = (LPSTR) pCardData->pfnCspAlloc(cbPhysicalFileName);
  552. LOG_CHECK_ALLOC(*ppszPhysicalFileName);
  553. memcpy(
  554. *ppszPhysicalFileName,
  555. FileMap[i].szPhysicalName,
  556. FileMap[i].cbPhysicalName);
  557. }
  558. else
  559. {
  560. // Have to try for a partial match. Check if the beginning
  561. // of the logical name matches a known name.
  562. for ( i = 0;
  563. FALSE == fMatched && (i < sizeof(FileMap) / sizeof(FileMap[0]));
  564. i++)
  565. {
  566. if (wszLogicalFileName !=
  567. wcsstr(wszLogicalFileName, FileMap[i].wszLogicalName))
  568. continue;
  569. //
  570. // We found a match and it's at the beginning of the string
  571. //
  572. cchLogicalName = (DWORD) wcslen(FileMap[i].wszLogicalName);
  573. //
  574. // Convert the trailing portion of the matched Unicode string
  575. // to Ansi.
  576. //
  577. dwError = I_CardConvertFileNameToAnsi(
  578. pCardData,
  579. wszLogicalFileName + cchLogicalName,
  580. &szAnsiExtra);
  581. if (ERROR_SUCCESS != dwError)
  582. goto Ret;
  583. //
  584. // Build the fully matched/converted physical file string. The
  585. // resultant string will have three single-byte NULL chars
  586. // appended to ensure that the resultant string is a valid,
  587. // terminated Unicode string.
  588. //
  589. *ppszPhysicalFileName = (LPSTR) pCardData->pfnCspAlloc(
  590. 3 +
  591. FileMap[i].cbPhysicalName +
  592. strlen(szAnsiExtra));
  593. LOG_CHECK_ALLOC(*ppszPhysicalFileName);
  594. memcpy(
  595. *ppszPhysicalFileName,
  596. FileMap[i].szPhysicalName,
  597. FileMap[i].cbPhysicalName);
  598. memcpy(
  599. *ppszPhysicalFileName + FileMap[i].cbPhysicalName,
  600. szAnsiExtra,
  601. strlen(szAnsiExtra));
  602. fMatched = TRUE;
  603. }
  604. }
  605. if (FALSE == fMatched)
  606. dwError = ERROR_NOT_FOUND;
  607. Ret:
  608. if (NULL != szAnsiExtra)
  609. pCardData->pfnCspFree(szAnsiExtra);
  610. return dwError;
  611. }
  612. //
  613. // Converts a Crypto API private key blob to the separate public and private
  614. // key files that will be written to the card.
  615. //
  616. DWORD ConvertPrivateKeyBlobToCardFormat(
  617. IN PCARD_DATA pCardData,
  618. IN DWORD dwKeySpec,
  619. IN PBYTE pbKeyBlob,
  620. IN DWORD cbKeyBlob,
  621. OUT PBYTE *ppbCardPrivateKey,
  622. OUT DWORD *pcbCardPrivateKey,
  623. OUT PBYTE *ppbCardPublicKey,
  624. OUT DWORD *pcbCardPublicKey)
  625. {
  626. DWORD dwError = ERROR_SUCCESS;
  627. RSAPUBKEY *pPub = NULL;
  628. DWORD cBitlenBytes = 0;
  629. DWORD cbKey = 0;
  630. PBYTE pbKey = NULL;
  631. UNREFERENCED_PARAMETER(pCardData);
  632. UNREFERENCED_PARAMETER(dwKeySpec);
  633. UNREFERENCED_PARAMETER(cbKeyBlob);
  634. *ppbCardPrivateKey = NULL;
  635. *pcbCardPrivateKey = 0;
  636. *ppbCardPublicKey = NULL;
  637. *pcbCardPublicKey = 0;
  638. //
  639. // Setup the public key file
  640. //
  641. pPub = (RSAPUBKEY *) (pbKeyBlob + sizeof(BLOBHEADER));
  642. *pcbCardPublicKey = (pPub->bitlen / 8) + sizeof(RSAPUBKEY);
  643. *ppbCardPublicKey = (PBYTE) pCardData->pfnCspAlloc(*pcbCardPublicKey);
  644. LOG_CHECK_ALLOC(*ppbCardPublicKey);
  645. memcpy(
  646. *ppbCardPublicKey,
  647. pPub,
  648. *pcbCardPublicKey);
  649. //
  650. // Need to change the RSA "magic" field in the Public key blob from
  651. // "RSA2" to "RSA1" to make this a correct PUBLICKEYBLOB (although we
  652. // won't add the BLOBHEADER to the front until someone tries to export
  653. // it from the card).
  654. //
  655. memcpy(
  656. *ppbCardPublicKey,
  657. (PBYTE) "RSA1",
  658. 4);
  659. //
  660. // Setup the private key file
  661. //
  662. cBitlenBytes = pPub->bitlen / 8;
  663. *pcbCardPrivateKey = 1 + 1 + 3 + 1 + 9 * cBitlenBytes / 2;
  664. *ppbCardPrivateKey = (PBYTE) pCardData->pfnCspAlloc(*pcbCardPrivateKey);
  665. LOG_CHECK_ALLOC(*ppbCardPrivateKey);
  666. pbKey = *ppbCardPrivateKey;
  667. // Key mode
  668. pbKey[cbKey] = MODE_RSA_SIGN;
  669. cbKey++;
  670. // size of public exponent
  671. pbKey[cbKey] = cbCAPI_PUBLIC_EXPONENT;
  672. cbKey++;
  673. DsysAssert(CAPI_PUBLIC_EXPONENT == pPub->pubexp);
  674. // public exponent
  675. memcpy(
  676. pbKey + cbKey,
  677. (PBYTE) &pPub->pubexp,
  678. cbCAPI_PUBLIC_EXPONENT);
  679. cbKey += cbCAPI_PUBLIC_EXPONENT;
  680. // RSA key length
  681. pbKey[cbKey] = (BYTE) cBitlenBytes;
  682. cbKey++;
  683. // public key
  684. memcpy(
  685. pbKey + cbKey,
  686. pbKeyBlob + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
  687. cBitlenBytes);
  688. cbKey += cBitlenBytes;
  689. // prime 1
  690. memcpy(
  691. pbKey + cbKey,
  692. pbKeyBlob + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
  693. cBitlenBytes,
  694. cBitlenBytes / 2);
  695. cbKey += cBitlenBytes / 2;
  696. // prime 2
  697. memcpy(
  698. pbKey + cbKey,
  699. pbKeyBlob + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
  700. (3 * cBitlenBytes / 2),
  701. cBitlenBytes / 2);
  702. cbKey += cBitlenBytes / 2;
  703. // Exp1 (D mod (P-1)) (m/2 bytes)
  704. memcpy(
  705. pbKey + cbKey,
  706. pbKeyBlob + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
  707. 2 * cBitlenBytes,
  708. cBitlenBytes / 2);
  709. cbKey += cBitlenBytes / 2;
  710. // Exp2 (D mod (Q-1)) (m/2 bytes)
  711. memcpy(
  712. pbKey + cbKey,
  713. pbKeyBlob + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
  714. (5 * cBitlenBytes / 2),
  715. cBitlenBytes / 2);
  716. cbKey += cBitlenBytes / 2;
  717. // Coef ((Q^(-1)) mod p) (m/2 bytes)
  718. memcpy(
  719. pbKey + cbKey,
  720. pbKeyBlob + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
  721. 3 * cBitlenBytes,
  722. cBitlenBytes / 2);
  723. cbKey += cBitlenBytes / 2;
  724. // private exponent
  725. memcpy(
  726. pbKey + cbKey,
  727. pbKeyBlob + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
  728. (7 * cBitlenBytes / 2),
  729. cBitlenBytes);
  730. cbKey += cBitlenBytes;
  731. DsysAssert(cbKey == *pcbCardPrivateKey);
  732. Ret:
  733. if (ERROR_SUCCESS != dwError)
  734. {
  735. if (*ppbCardPublicKey)
  736. {
  737. pCardData->pfnCspFree(*ppbCardPublicKey);
  738. *ppbCardPublicKey = NULL;
  739. }
  740. }
  741. return dwError;
  742. }
  743. //
  744. // Card Module Exported Functions
  745. //
  746. //
  747. // Initializes a CARD_DATA context structure for the card identified by Name,
  748. // ATR, and SCARDHANDLE supplied by the caller.
  749. //
  750. DWORD
  751. WINAPI
  752. CardAcquireContext(
  753. IN OUT PCARD_DATA pCardData,
  754. IN DWORD dwFlags)
  755. {
  756. int iSupportedCard = 0;
  757. BOOL fSupportedCard = FALSE;
  758. PCARDMOD_CONTEXT pCardmodContext = NULL;
  759. DWORD dwError = ERROR_SUCCESS;
  760. LOG_BEGIN_FUNCTION(CardAcquireContext);
  761. if (0 != dwFlags)
  762. {
  763. dwError = (DWORD) NTE_BAD_FLAGS;
  764. goto Ret;
  765. }
  766. for (
  767. iSupportedCard = 0;
  768. iSupportedCard < sizeof(SupportedCards) /
  769. sizeof(SupportedCards[0]);
  770. iSupportedCard++)
  771. {
  772. if (0 == wcscmp(
  773. SupportedCards[iSupportedCard].wszCardName,
  774. pCardData->pwszCardName)
  775. &&
  776. SupportedCards[iSupportedCard].cbAtr == pCardData->cbAtr
  777. &&
  778. 0 == memcmp(
  779. SupportedCards[iSupportedCard].rgbAtr,
  780. pCardData->pbAtr,
  781. SupportedCards[iSupportedCard].cbAtr))
  782. {
  783. fSupportedCard = TRUE;
  784. break;
  785. }
  786. }
  787. if (FALSE == fSupportedCard)
  788. {
  789. dwError = (DWORD) SCARD_E_UNKNOWN_CARD;
  790. goto Ret;
  791. }
  792. pCardData->pfnCardDeleteContext = CardDeleteContext;
  793. pCardData->pfnCardQueryCapabilities = CardQueryCapabilities;
  794. pCardData->pfnCardDeleteContainer = CardDeleteContainer;
  795. pCardData->pfnCardCreateContainer = CardCreateContainer;
  796. pCardData->pfnCardGetContainerInfo = CardGetContainerInfo;
  797. pCardData->pfnCardSubmitPin = CardSubmitPin;
  798. pCardData->pfnCardChangeAuthenticator = CardChangeAuthenticator;
  799. pCardData->pfnCardGetChallenge = CardGetChallenge;
  800. pCardData->pfnCardAuthenticateChallenge = CardAuthenticateChallenge;
  801. pCardData->pfnCardUnblockPin = CardUnblockPin;
  802. pCardData->pfnCardDeauthenticate = CardDeauthenticate;
  803. pCardData->pfnCardCreateFile = CardCreateFile;
  804. pCardData->pfnCardReadFile = CardReadFile;
  805. pCardData->pfnCardWriteFile = CardWriteFile;
  806. pCardData->pfnCardDeleteFile = CardDeleteFile;
  807. pCardData->pfnCardEnumFiles = CardEnumFiles;
  808. pCardData->pfnCardGetFileInfo = CardGetFileInfo;
  809. pCardData->pfnCardQueryFreeSpace = CardQueryFreeSpace;
  810. pCardData->pfnCardPrivateKeyDecrypt = CardPrivateKeyDecrypt;
  811. pCardData->pfnCardQueryKeySizes = CardQueryKeySizes;
  812. pCardmodContext =
  813. (PCARDMOD_CONTEXT) pCardData->pfnCspAlloc(sizeof(CARDMOD_CONTEXT));
  814. LOG_CHECK_ALLOC(pCardmodContext);
  815. LOG_CHECK_SCW_CALL(hScwAttachToCard(
  816. pCardData->hScard,
  817. NULL,
  818. &pCardmodContext->hWfscCardHandle));
  819. pCardmodContext->pSupportedCard = SupportedCards + iSupportedCard;
  820. pCardData->pvVendorSpecific = (PVOID) pCardmodContext;
  821. pCardmodContext = NULL;
  822. Ret:
  823. if ( ERROR_SUCCESS != dwError &&
  824. NULL != pCardmodContext &&
  825. pCardmodContext->hWfscCardHandle)
  826. hScwDetachFromCard(pCardmodContext->hWfscCardHandle);
  827. if (pCardmodContext)
  828. pCardData->pfnCspFree(pCardmodContext);
  829. LOG_END_FUNCTION(CardAcquireContext, dwError);
  830. return dwError;
  831. }
  832. //
  833. // Frees the resources consumed by a CARD_DATA structure.
  834. //
  835. DWORD
  836. WINAPI
  837. CardDeleteContext(
  838. OUT PCARD_DATA pCardData)
  839. {
  840. DWORD dwError = ERROR_SUCCESS;
  841. PCARDMOD_CONTEXT pCardmodContext =
  842. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  843. LOG_BEGIN_FUNCTION(CardDeleteContext);
  844. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  845. if (pCardmodContext->hWfscCardHandle)
  846. {
  847. hScwDetachFromCard(pCardmodContext->hWfscCardHandle);
  848. pCardmodContext->hWfscCardHandle = 0;
  849. }
  850. if (pCardData->pvVendorSpecific)
  851. {
  852. pCardData->pfnCspFree(pCardData->pvVendorSpecific);
  853. pCardData->pvVendorSpecific = NULL;
  854. }
  855. LOG_END_FUNCTION(CardDeleteContext, dwError);
  856. return dwError;
  857. }
  858. //
  859. // Returns the static capabilities of the target card.
  860. //
  861. DWORD
  862. WINAPI
  863. CardQueryCapabilities(
  864. IN PCARD_DATA pCardData,
  865. IN OUT PCARD_CAPABILITIES pCardCapabilities)
  866. {
  867. DWORD dwError = ERROR_SUCCESS;
  868. PCARDMOD_CONTEXT pCardmodContext =
  869. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  870. LOG_BEGIN_FUNCTION(CardQueryCapabilities);
  871. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  872. memcpy(
  873. pCardCapabilities,
  874. &pCardmodContext->pSupportedCard->CardCapabilities,
  875. sizeof(CARD_CAPABILITIES));
  876. LOG_END_FUNCTION(CardQueryCapabilities, dwError);
  877. return dwError;
  878. }
  879. //
  880. // The encoded key filename is one hex byte, such as "FF", which requires
  881. // two characters.
  882. //
  883. #define cchENCODED_KEY_FILENAME 2
  884. //
  885. // Creates the physical filenames used for the key files associated with the
  886. // specified container.
  887. //
  888. DWORD BuildCardKeyFilenames(
  889. IN PCARD_DATA pCardData,
  890. IN DWORD dwKeySpec,
  891. IN BYTE bContainerIndex,
  892. OUT OPTIONAL LPSTR *pszPrivateFilename,
  893. OUT OPTIONAL LPSTR *pszPublicFilename)
  894. {
  895. DWORD dwError = ERROR_SUCCESS;
  896. DWORD cchFileName = 0;
  897. DWORD dwIndex = (DWORD) bContainerIndex;
  898. LPSTR szPrivatePrefix = NULL;
  899. DWORD cbPrivatePrefix = 0;
  900. LPSTR szPublicPrefix = NULL;
  901. DWORD cbPublicPrefix = 0;
  902. if (pszPrivateFilename)
  903. *pszPrivateFilename = NULL;
  904. if (pszPublicFilename)
  905. *pszPublicFilename = NULL;
  906. switch (dwKeySpec)
  907. {
  908. case AT_SIGNATURE:
  909. szPrivatePrefix = szPHYSICAL_SIGNATURE_PRIVATE_KEY_PREFIX;
  910. cbPrivatePrefix = cbPHYSICAL_SIGNATURE_PRIVATE_KEY_PREFIX;
  911. szPublicPrefix = szPHYSICAL_SIGNATURE_PUBLIC_KEY_PREFIX;
  912. cbPublicPrefix = cbPHYSICAL_SIGNATURE_PUBLIC_KEY_PREFIX;
  913. break;
  914. case AT_KEYEXCHANGE:
  915. szPrivatePrefix = szPHYSICAL_KEYEXCHANGE_PRIVATE_KEY_PREFIX;
  916. cbPrivatePrefix = cbPHYSICAL_KEYEXCHANGE_PRIVATE_KEY_PREFIX;
  917. szPublicPrefix = szPHYSICAL_KEYEXCHANGE_PUBLIC_KEY_PREFIX;
  918. cbPublicPrefix = cbPHYSICAL_KEYEXCHANGE_PUBLIC_KEY_PREFIX;
  919. break;
  920. default:
  921. dwError = (DWORD) NTE_BAD_ALGID;
  922. goto Ret;
  923. }
  924. //
  925. // Build the public key filename
  926. //
  927. if (pszPublicFilename)
  928. {
  929. cchFileName = cchENCODED_KEY_FILENAME;
  930. cchFileName += (cbPublicPrefix / sizeof(CHAR)) + 3;
  931. *pszPublicFilename = (LPSTR) pCardData->pfnCspAlloc(
  932. cchFileName * sizeof(CHAR));
  933. LOG_CHECK_ALLOC(*pszPublicFilename);
  934. memcpy(*pszPublicFilename, szPublicPrefix, cbPublicPrefix);
  935. sprintf(
  936. *pszPublicFilename + cbPublicPrefix,
  937. "%d\0\0",
  938. dwIndex);
  939. }
  940. //
  941. // Build the private key filename
  942. //
  943. if (pszPrivateFilename)
  944. {
  945. cchFileName = cchENCODED_KEY_FILENAME;
  946. cchFileName += (cbPrivatePrefix / sizeof(CHAR)) + 3;
  947. *pszPrivateFilename = (LPSTR) pCardData->pfnCspAlloc(
  948. cchFileName * sizeof(CHAR));
  949. LOG_CHECK_ALLOC(*pszPrivateFilename);
  950. memcpy(*pszPrivateFilename, szPrivatePrefix, cbPrivatePrefix);
  951. sprintf(
  952. *pszPrivateFilename + cbPrivatePrefix,
  953. "%d\0\0",
  954. dwIndex);
  955. }
  956. Ret:
  957. if (ERROR_SUCCESS != dwError)
  958. {
  959. if (*pszPublicFilename)
  960. {
  961. pCardData->pfnCspFree(*pszPublicFilename);
  962. *pszPublicFilename = NULL;
  963. }
  964. if (*pszPrivateFilename)
  965. {
  966. pCardData->pfnCspFree(*pszPrivateFilename);
  967. *pszPrivateFilename = NULL;
  968. }
  969. }
  970. return dwError;
  971. }
  972. //
  973. // Deletes the Signature and Key Exchange public and private key files,
  974. // if present, associated with the specified container.
  975. //
  976. DWORD
  977. WINAPI
  978. CardDeleteContainer(
  979. IN PCARD_DATA pCardData,
  980. IN BYTE bContainerIndex,
  981. IN DWORD dwReserved)
  982. {
  983. DWORD dwError = ERROR_SUCCESS;
  984. PCARDMOD_CONTEXT pCardmodContext =
  985. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  986. LPSTR szPrivateKeyFile = NULL;
  987. LPSTR szPublicKeyFile = NULL;
  988. SCODE scode = 0;
  989. UNREFERENCED_PARAMETER(dwReserved);
  990. LOG_BEGIN_FUNCTION(CardDeleteContainer);
  991. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  992. //
  993. // Attempt to delete the Signature key files associated with this
  994. // container, if any.
  995. //
  996. dwError = BuildCardKeyFilenames(
  997. pCardData,
  998. AT_SIGNATURE,
  999. bContainerIndex,
  1000. &szPrivateKeyFile,
  1001. &szPublicKeyFile);
  1002. if (CARDMOD_FAILED(dwError))
  1003. goto Ret;
  1004. scode = hScwDeleteFile(
  1005. pCardmodContext->hWfscCardHandle,
  1006. (LPWSTR) szPrivateKeyFile);
  1007. if (SCW_E_FILENOTFOUND != scode && SCW_S_OK != scode)
  1008. goto Ret;
  1009. scode = hScwDeleteFile(
  1010. pCardmodContext->hWfscCardHandle,
  1011. (LPWSTR) szPublicKeyFile);
  1012. if (SCW_E_FILENOTFOUND != scode && SCW_S_OK != scode)
  1013. goto Ret;
  1014. pCardData->pfnCspFree(szPrivateKeyFile);
  1015. szPrivateKeyFile = NULL;
  1016. pCardData->pfnCspFree(szPublicKeyFile);
  1017. szPublicKeyFile = NULL;
  1018. //
  1019. // Attempt to delete the Key Exchange key files associated with this
  1020. // container, if any.
  1021. //
  1022. dwError = BuildCardKeyFilenames(
  1023. pCardData,
  1024. AT_KEYEXCHANGE,
  1025. bContainerIndex,
  1026. &szPrivateKeyFile,
  1027. &szPublicKeyFile);
  1028. if (CARDMOD_FAILED(dwError))
  1029. goto Ret;
  1030. scode = hScwDeleteFile(
  1031. pCardmodContext->hWfscCardHandle,
  1032. (LPWSTR) szPrivateKeyFile);
  1033. if (SCW_E_FILENOTFOUND != scode && SCW_S_OK != scode)
  1034. goto Ret;
  1035. scode = hScwDeleteFile(
  1036. pCardmodContext->hWfscCardHandle,
  1037. (LPWSTR) szPublicKeyFile);
  1038. Ret:
  1039. if (SCW_E_FILENOTFOUND != scode && SCW_S_OK != scode)
  1040. dwError = I_CardMapErrorCode(scode);
  1041. if (szPrivateKeyFile)
  1042. pCardData->pfnCspFree(szPrivateKeyFile);
  1043. if (szPublicKeyFile)
  1044. pCardData->pfnCspFree(szPublicKeyFile);
  1045. LOG_END_FUNCTION(CardDeleteContainer, dwError);
  1046. return dwError;
  1047. }
  1048. //
  1049. // Writes the private and public key files to the card, supplying the
  1050. // appropriate access conditions.
  1051. //
  1052. DWORD WriteCardKeyFiles(
  1053. IN PCARD_DATA pCardData,
  1054. IN LPWSTR wszPrivateKeyFile,
  1055. IN LPWSTR wszPublicKeyFile,
  1056. IN PBYTE pbPrivateKey,
  1057. IN DWORD cbPrivateKey,
  1058. IN PBYTE pbPublicKey,
  1059. IN DWORD cbPublicKey)
  1060. {
  1061. DWORD dwError = ERROR_SUCCESS;
  1062. PCARDMOD_CONTEXT pCardmodContext =
  1063. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  1064. CARD_FILE_ACCESS_CONDITION Ac;
  1065. LPWSTR wszPrivateAcl = NULL;
  1066. LPWSTR wszPublicAcl = NULL;
  1067. HFILE hFile = 0;
  1068. SCODE scode = 0;
  1069. memset(&Ac, 0, sizeof(Ac));
  1070. Ac = UserWriteExecuteAc;
  1071. dwError = GetWellKnownAcMapping(
  1072. pCardData, Ac, &wszPrivateAcl);
  1073. if (CARDMOD_FAILED(dwError))
  1074. goto Ret;
  1075. Ac = EveryoneReadUserWriteAc;
  1076. dwError = GetWellKnownAcMapping(
  1077. pCardData, Ac, &wszPublicAcl);
  1078. if (CARDMOD_FAILED(dwError))
  1079. goto Ret;
  1080. //
  1081. // See if the private key file already exists
  1082. //
  1083. scode = hScwDeleteFile(
  1084. pCardmodContext->hWfscCardHandle,
  1085. wszPrivateKeyFile);
  1086. if (SCW_S_OK != scode && SCW_E_FILENOTFOUND != scode)
  1087. {
  1088. dwError = I_CardMapErrorCode(scode);
  1089. goto Ret;
  1090. }
  1091. dwError = I_CardWriteFile(
  1092. pCardData,
  1093. wszPrivateKeyFile,
  1094. wszPrivateAcl,
  1095. pbPrivateKey,
  1096. cbPrivateKey,
  1097. FALSE);
  1098. if (CARDMOD_FAILED(dwError))
  1099. goto Ret;
  1100. // Done with private key file
  1101. //
  1102. // See if the public key file already exists
  1103. //
  1104. scode = hScwDeleteFile(
  1105. pCardmodContext->hWfscCardHandle,
  1106. wszPublicKeyFile);
  1107. if (SCW_S_OK != scode && SCW_E_FILENOTFOUND != scode)
  1108. {
  1109. dwError = I_CardMapErrorCode(scode);
  1110. goto Ret;
  1111. }
  1112. dwError = I_CardWriteFile(
  1113. pCardData,
  1114. wszPublicKeyFile,
  1115. wszPublicAcl,
  1116. pbPublicKey,
  1117. cbPublicKey,
  1118. TRUE);
  1119. if (CARDMOD_FAILED(dwError))
  1120. goto Ret;
  1121. // Done with public key file
  1122. Ret:
  1123. if (wszPrivateAcl)
  1124. pCardData->pfnCspFree(wszPrivateAcl);
  1125. if (wszPublicAcl)
  1126. pCardData->pfnCspFree(wszPublicAcl);
  1127. if (hFile)
  1128. hScwCloseFile(
  1129. pCardmodContext->hWfscCardHandle, hFile);
  1130. return dwError;
  1131. }
  1132. //
  1133. // Writes new keys to the card in a location logically defined by the
  1134. // bContainerIndex container name. If keys are already defined for the
  1135. // specified container, the existing keys are over-written.
  1136. //
  1137. // If dwFlags contains CARD_CREATE_CONTAINER_KEY_GEN, then dwKeySize is the
  1138. // number of bits of the key to be created.
  1139. //
  1140. // If dwFlags contains CARD_CREATE_CONTAINER_KEY_IMPORT, then dwKeySize is
  1141. // the byte length of pbKeyData.
  1142. //
  1143. DWORD
  1144. WINAPI
  1145. CardCreateContainer(
  1146. IN PCARD_DATA pCardData,
  1147. IN BYTE bContainerIndex,
  1148. IN DWORD dwFlags,
  1149. IN DWORD dwKeySpec,
  1150. IN DWORD dwKeySize,
  1151. IN PBYTE pbKeyData)
  1152. {
  1153. DWORD dwError = ERROR_SUCCESS;
  1154. PBYTE pbPrivateKeyFile = NULL;
  1155. DWORD cbPrivateKeyFile = 0;
  1156. PBYTE pbPublicKeyFile = NULL;
  1157. DWORD cbPublicKeyFile = 0;
  1158. LPSTR szPrivateKeyFile = NULL;
  1159. LPSTR szPublicKeyFile = NULL;
  1160. PCARDMOD_CONTEXT pCardmodContext =
  1161. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  1162. LOG_BEGIN_FUNCTION(CardCreateContainer);
  1163. if (CARD_CREATE_CONTAINER_KEY_GEN & dwFlags)
  1164. {
  1165. dwError = (DWORD) SCARD_E_UNSUPPORTED_FEATURE;
  1166. goto Ret;
  1167. }
  1168. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  1169. //
  1170. // Setup the key files
  1171. //
  1172. dwError = ConvertPrivateKeyBlobToCardFormat(
  1173. pCardData,
  1174. dwKeySpec,
  1175. pbKeyData,
  1176. dwKeySize,
  1177. &pbPrivateKeyFile,
  1178. &cbPrivateKeyFile,
  1179. &pbPublicKeyFile,
  1180. &cbPublicKeyFile);
  1181. if (CARDMOD_FAILED(dwError))
  1182. goto Ret;
  1183. dwError = BuildCardKeyFilenames(
  1184. pCardData,
  1185. dwKeySpec,
  1186. bContainerIndex,
  1187. &szPrivateKeyFile,
  1188. &szPublicKeyFile);
  1189. if (CARDMOD_FAILED(dwError))
  1190. goto Ret;
  1191. //
  1192. // Write the actual keys to the card
  1193. //
  1194. dwError = WriteCardKeyFiles(
  1195. pCardData,
  1196. (LPWSTR) szPrivateKeyFile,
  1197. (LPWSTR) szPublicKeyFile,
  1198. pbPrivateKeyFile,
  1199. cbPrivateKeyFile,
  1200. pbPublicKeyFile,
  1201. cbPublicKeyFile);
  1202. Ret:
  1203. if (pbPrivateKeyFile)
  1204. {
  1205. RtlSecureZeroMemory(pbPrivateKeyFile, cbPrivateKeyFile);
  1206. pCardData->pfnCspFree(pbPrivateKeyFile);
  1207. }
  1208. if (pbPublicKeyFile)
  1209. pCardData->pfnCspFree(pbPublicKeyFile);
  1210. if (szPrivateKeyFile)
  1211. pCardData->pfnCspFree(szPrivateKeyFile);
  1212. if (szPublicKeyFile)
  1213. pCardData->pfnCspFree(szPublicKeyFile);
  1214. LOG_END_FUNCTION(CardCreateContainer, dwError);
  1215. return dwError;
  1216. }
  1217. //
  1218. // Initializes a CONTAINER_INFO structure for the indicated container,
  1219. // including Signature and Key Exchange Crypto API public key blobs if
  1220. // those keys exist.
  1221. //
  1222. DWORD
  1223. WINAPI
  1224. CardGetContainerInfo(
  1225. IN PCARD_DATA pCardData,
  1226. IN BYTE bContainerIndex,
  1227. IN DWORD dwFlags,
  1228. IN OUT PCONTAINER_INFO pContainerInfo)
  1229. {
  1230. DWORD dwError = ERROR_SUCCESS;
  1231. LPSTR szPublicKeyFile = NULL;
  1232. PBYTE pbPublicKey = NULL;
  1233. DWORD cbPublicKey = 0;
  1234. BLOBHEADER *pBlobHeader = NULL;
  1235. PCARDMOD_CONTEXT pCardmodContext =
  1236. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  1237. UNREFERENCED_PARAMETER(dwFlags);
  1238. LOG_BEGIN_FUNCTION(CardGetContainerInfo);
  1239. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  1240. //
  1241. // Does this container have a Signature key?
  1242. //
  1243. dwError = BuildCardKeyFilenames(
  1244. pCardData,
  1245. AT_SIGNATURE,
  1246. bContainerIndex,
  1247. NULL,
  1248. &szPublicKeyFile);
  1249. if (CARDMOD_FAILED(dwError))
  1250. goto Ret;
  1251. dwError = I_CardReadFile(
  1252. pCardData,
  1253. (LPWSTR) szPublicKeyFile,
  1254. &pbPublicKey,
  1255. &cbPublicKey,
  1256. TRUE);
  1257. switch (dwError)
  1258. {
  1259. case SCARD_E_FILE_NOT_FOUND:
  1260. // There appears to be no Signature key in this container. Continue.
  1261. break;
  1262. case ERROR_SUCCESS:
  1263. pContainerInfo->pbSigPublicKey =
  1264. (PBYTE) pCardData->pfnCspAlloc(sizeof(BLOBHEADER) + cbPublicKey);
  1265. LOG_CHECK_ALLOC(pContainerInfo->pbSigPublicKey);
  1266. pBlobHeader = (BLOBHEADER *) pContainerInfo->pbSigPublicKey;
  1267. pBlobHeader->bType = PUBLICKEYBLOB;
  1268. pBlobHeader->bVersion = CUR_BLOB_VERSION;
  1269. pBlobHeader->reserved = 0x0000;
  1270. pBlobHeader->aiKeyAlg = CALG_RSA_SIGN;
  1271. memcpy(
  1272. pContainerInfo->pbSigPublicKey + sizeof(BLOBHEADER),
  1273. pbPublicKey,
  1274. cbPublicKey);
  1275. pContainerInfo->cbSigPublicKey = sizeof(BLOBHEADER) + cbPublicKey;
  1276. pCardData->pfnCspFree(szPublicKeyFile);
  1277. szPublicKeyFile = NULL;
  1278. pCardData->pfnCspFree(pbPublicKey);
  1279. pbPublicKey = NULL;
  1280. break;
  1281. default:
  1282. // Unexpected error
  1283. goto Ret;
  1284. }
  1285. //
  1286. // Does this container have a Key Exchange key?
  1287. //
  1288. dwError = BuildCardKeyFilenames(
  1289. pCardData,
  1290. AT_KEYEXCHANGE,
  1291. bContainerIndex,
  1292. NULL,
  1293. &szPublicKeyFile);
  1294. if (CARDMOD_FAILED(dwError))
  1295. goto Ret;
  1296. dwError = I_CardReadFile(
  1297. pCardData,
  1298. (LPWSTR) szPublicKeyFile,
  1299. &pbPublicKey,
  1300. &cbPublicKey,
  1301. TRUE);
  1302. switch (dwError)
  1303. {
  1304. case SCARD_E_FILE_NOT_FOUND:
  1305. // There appears to be no Key Exchange key in this container.
  1306. break;
  1307. case ERROR_SUCCESS:
  1308. pContainerInfo->pbKeyExPublicKey =
  1309. (PBYTE) pCardData->pfnCspAlloc(sizeof(BLOBHEADER) + cbPublicKey);
  1310. LOG_CHECK_ALLOC(pContainerInfo->pbKeyExPublicKey);
  1311. pBlobHeader = (BLOBHEADER *) pContainerInfo->pbKeyExPublicKey;
  1312. pBlobHeader->bType = PUBLICKEYBLOB;
  1313. pBlobHeader->bVersion = CUR_BLOB_VERSION;
  1314. pBlobHeader->reserved = 0x0000;
  1315. pBlobHeader->aiKeyAlg = CALG_RSA_KEYX;
  1316. memcpy(
  1317. pContainerInfo->pbKeyExPublicKey + sizeof(BLOBHEADER),
  1318. pbPublicKey,
  1319. cbPublicKey);
  1320. pContainerInfo->cbKeyExPublicKey = sizeof(BLOBHEADER) + cbPublicKey;
  1321. break;
  1322. default:
  1323. // Unexpected error
  1324. goto Ret;
  1325. }
  1326. // If we got here, then the API has succeeded
  1327. dwError = ERROR_SUCCESS;
  1328. Ret:
  1329. if (pbPublicKey)
  1330. pCardData->pfnCspFree(pbPublicKey);
  1331. if (szPublicKeyFile)
  1332. pCardData->pfnCspFree(szPublicKeyFile);
  1333. if (ERROR_SUCCESS != dwError)
  1334. {
  1335. if (NULL != pContainerInfo->pbKeyExPublicKey)
  1336. {
  1337. pCardData->pfnCspFree(pContainerInfo->pbKeyExPublicKey);
  1338. pContainerInfo->pbKeyExPublicKey = NULL;
  1339. }
  1340. if (NULL != pContainerInfo->pbSigPublicKey)
  1341. {
  1342. pCardData->pfnCspFree(pContainerInfo->pbSigPublicKey);
  1343. pContainerInfo->pbSigPublicKey = NULL;
  1344. }
  1345. }
  1346. LOG_END_FUNCTION(CardGetContainerInfo, dwError);
  1347. return dwError;
  1348. }
  1349. //
  1350. // Queries the number of pin retries available for the specified user, using
  1351. // the pin counter applet.
  1352. //
  1353. DWORD I_CardQueryPinRetries(
  1354. IN PCARD_DATA pCardData,
  1355. IN LPWSTR wszPrincipal,
  1356. OUT PDWORD pcAttemptsRemaining)
  1357. {
  1358. DWORD dwError = ERROR_SUCCESS;
  1359. ISO_HEADER IsoHeader;
  1360. UINT16 wStatusWord = 0;
  1361. SCODE status = 0;
  1362. PCARDMOD_CONTEXT pCardmodContext =
  1363. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  1364. // Build the command
  1365. IsoHeader.INS = PIN_RETRY_COUNTER_INS;
  1366. IsoHeader.CLA = PIN_RETRY_COUNTER_CLA;
  1367. IsoHeader.P1 = PIN_RETRY_COUNTER_P1;
  1368. IsoHeader.P2 = PIN_RETRY_COUNTER_P2;
  1369. status = hScwExecute(
  1370. pCardmodContext->hWfscCardHandle,
  1371. &IsoHeader,
  1372. (PBYTE) wszPrincipal,
  1373. (TCOUNT) (wcslen(wszPrincipal) + 1) * sizeof(WCHAR),
  1374. NULL,
  1375. NULL,
  1376. &wStatusWord);
  1377. if (SCW_S_OK == status)
  1378. dwError = I_CardMapExecuteErrorCode(wStatusWord);
  1379. else
  1380. dwError = I_CardMapErrorCode(status);
  1381. if (ERROR_SUCCESS == dwError)
  1382. *pcAttemptsRemaining = (DWORD) (wStatusWord & 0xFF);
  1383. return dwError;
  1384. }
  1385. //
  1386. // Authenticates the specified logical user name via the specified pin.
  1387. //
  1388. // If pcAttemptsRemaining is non-NULL, and if the authentication fails,
  1389. // that parameter will container the number of authentication attempts
  1390. // remaining before the card is locked.
  1391. //
  1392. DWORD
  1393. WINAPI
  1394. CardSubmitPin(
  1395. IN PCARD_DATA pCardData,
  1396. IN LPWSTR pwszUserId,
  1397. IN PBYTE pbPin,
  1398. IN DWORD cbPin,
  1399. OUT OPTIONAL PDWORD pcAttemptsRemaining)
  1400. {
  1401. DWORD dwError = ERROR_SUCCESS;
  1402. PCARDMOD_CONTEXT pCardmodContext =
  1403. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  1404. LPWSTR wszPrincipal = NULL;
  1405. SCODE scode = SCW_S_OK;
  1406. DWORD dwAttempts = 0;
  1407. LOG_BEGIN_FUNCTION(CardSubmitPin);
  1408. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  1409. if (NULL != pcAttemptsRemaining)
  1410. *pcAttemptsRemaining = CARD_DATA_VALUE_UNKNOWN;
  1411. dwError = GetWellKnownUserMapping(
  1412. pCardData, pwszUserId, &wszPrincipal);
  1413. if (ERROR_SUCCESS != dwError)
  1414. goto Ret;
  1415. scode = hScwAuthenticateName(
  1416. pCardmodContext->hWfscCardHandle,
  1417. wszPrincipal,
  1418. pbPin,
  1419. (TCOUNT) cbPin);
  1420. dwError = I_CardMapErrorCode(scode);
  1421. if (SCARD_E_INVALID_CHV == dwError && NULL != pcAttemptsRemaining)
  1422. {
  1423. // Determine how many more invalid pin presentation attempts can be
  1424. // made before the card is locked.
  1425. dwError = I_CardQueryPinRetries(
  1426. pCardData,
  1427. wszPrincipal,
  1428. &dwAttempts);
  1429. if (ERROR_SUCCESS != dwError)
  1430. goto Ret;
  1431. *pcAttemptsRemaining = dwAttempts;
  1432. dwError = (DWORD) SCARD_E_INVALID_CHV;
  1433. }
  1434. Ret:
  1435. if (wszPrincipal)
  1436. pCardData->pfnCspFree(wszPrincipal);
  1437. LOG_END_FUNCTION(CardSubmitPin, dwError);
  1438. return dwError;
  1439. }
  1440. //
  1441. // Changes the pin for the specified logical user.
  1442. //
  1443. // If the authentication using the current pin fails, and if
  1444. // pcAttemptsRemaining is non-NULL, that parameter will be set to the number
  1445. // of authentication attempts remaining before the card is locked.
  1446. //
  1447. DWORD I_CardChangePin(
  1448. IN PCARD_DATA pCardData,
  1449. IN LPWSTR wszPhysicalUser,
  1450. IN PBYTE pbCurrentPin,
  1451. IN DWORD cbCurrentPin,
  1452. IN PBYTE pbNewPin,
  1453. IN DWORD cbNewPin,
  1454. OUT OPTIONAL PDWORD pcAttemptsRemaining)
  1455. {
  1456. ISO_HEADER IsoHeader;
  1457. UINT16 wStatusWord = 0;
  1458. PBYTE pbDataIn = NULL;
  1459. DWORD cbDataIn = 0;
  1460. DWORD cbUser = 0;
  1461. SCODE status = 0;
  1462. DWORD dwError = ERROR_SUCCESS;
  1463. PCARDMOD_CONTEXT pCardmodContext =
  1464. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  1465. DWORD cAttempts = 0;
  1466. memset(&IsoHeader, 0, sizeof(IsoHeader));
  1467. if (NULL != pcAttemptsRemaining)
  1468. *pcAttemptsRemaining = CARD_DATA_VALUE_UNKNOWN;
  1469. //
  1470. // Allocate a command buffer to be transmitted to the card
  1471. //
  1472. cbUser = (DWORD) (wcslen(wszPhysicalUser) + 1) * sizeof(WCHAR);
  1473. cbDataIn = 2 + cbUser + 2 + cbCurrentPin + 2 + cbNewPin;
  1474. pbDataIn = (PBYTE) pCardData->pfnCspAlloc(cbDataIn);
  1475. LOG_CHECK_ALLOC(pbDataIn);
  1476. cbDataIn = 0;
  1477. // Setup User Name TLV
  1478. pbDataIn[cbDataIn] = 0;
  1479. cbDataIn++;
  1480. pbDataIn[cbDataIn] = (BYTE) cbUser;
  1481. cbDataIn++;
  1482. memcpy(pbDataIn + cbDataIn, (PBYTE) wszPhysicalUser, cbUser);
  1483. cbDataIn += cbUser;
  1484. // Setup Current Pin TLV
  1485. pbDataIn[cbDataIn] = 1;
  1486. cbDataIn++;
  1487. pbDataIn[cbDataIn] = (BYTE) cbCurrentPin;
  1488. cbDataIn++;
  1489. memcpy(pbDataIn + cbDataIn, pbCurrentPin, cbCurrentPin);
  1490. cbDataIn += cbCurrentPin;
  1491. // Setup New Pin TLV
  1492. pbDataIn[cbDataIn] = 2;
  1493. cbDataIn++;
  1494. pbDataIn[cbDataIn] = (BYTE) cbNewPin;
  1495. cbDataIn++;
  1496. memcpy(pbDataIn + cbDataIn, pbNewPin, cbNewPin);
  1497. cbDataIn += cbNewPin;
  1498. // Build the command
  1499. IsoHeader.INS = PIN_CHANGE_INS;
  1500. IsoHeader.CLA = PIN_CHANGE_CLA;
  1501. IsoHeader.P1 = PIN_CHANGE_P1;
  1502. IsoHeader.P2 = PIN_CHANGE_P2;
  1503. //
  1504. // Send the pin change command to the card
  1505. //
  1506. status = hScwExecute(
  1507. pCardmodContext->hWfscCardHandle,
  1508. &IsoHeader,
  1509. pbDataIn,
  1510. (TCOUNT) cbDataIn,
  1511. NULL,
  1512. NULL,
  1513. &wStatusWord);
  1514. if (SCW_S_OK == status)
  1515. dwError = I_CardMapExecuteErrorCode(wStatusWord);
  1516. else
  1517. dwError = I_CardMapErrorCode(status);
  1518. if (SCARD_E_INVALID_CHV == dwError && NULL != pcAttemptsRemaining)
  1519. {
  1520. dwError = I_CardQueryPinRetries(
  1521. pCardData,
  1522. wszPhysicalUser,
  1523. &cAttempts);
  1524. if (ERROR_SUCCESS != dwError)
  1525. goto Ret;
  1526. *pcAttemptsRemaining = cAttempts;
  1527. dwError = (DWORD) SCARD_E_INVALID_CHV;
  1528. }
  1529. Ret:
  1530. if (pbDataIn)
  1531. pCardData->pfnCspFree(pbDataIn);
  1532. return dwError;
  1533. }
  1534. //
  1535. // Performs the challenge-response using the provided callback
  1536. //
  1537. /*
  1538. DWORD I_CardChallengeResponse(
  1539. IN PCARD_DATA pCardData,
  1540. IN PFN_PIN_CHALLENGE_CALLBACK pfnCallback,
  1541. IN PVOID pvCallbackContext,
  1542. OUT PBYTE *ppbResponse,
  1543. OUT DWORD *pcbResponse)
  1544. {
  1545. PBYTE pbChallenge = NULL;
  1546. DWORD cbChallenge = 0;
  1547. DWORD dwError = ERROR_SUCCESS;
  1548. PCARDMOD_CONTEXT pCardmodContext =
  1549. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  1550. cbChallenge = cbCHALLENGE_RESPONSE_DATA;
  1551. *pcbResponse = cbCHALLENGE_RESPONSE_DATA;
  1552. pbChallenge = pCardData->pfnCspAlloc(cbChallenge);
  1553. LOG_CHECK_ALLOC(pbChallenge);
  1554. *ppbResponse = pCardData->pfnCspAlloc(*pcbResponse);
  1555. LOG_CHECK_ALLOC(*ppbResponse);
  1556. LOG_CHECK_SCW_CALL(hScwGenerateRandom(
  1557. pCardmodContext->hWfscCardHandle,
  1558. pbChallenge,
  1559. (TCOUNT) cbChallenge));
  1560. dwError = pfnCallback(
  1561. pbChallenge,
  1562. cbChallenge,
  1563. *ppbResponse,
  1564. *pcbResponse,
  1565. pvCallbackContext);
  1566. Ret:
  1567. if (NULL != pbChallenge)
  1568. pCardData->pfnCspFree(pbChallenge);
  1569. if (NULL != *ppbResponse && ERROR_SUCCESS != dwError)
  1570. {
  1571. pCardData->pfnCspFree(*ppbResponse);
  1572. *ppbResponse = NULL;
  1573. }
  1574. return dwError;
  1575. }
  1576. */
  1577. //
  1578. // Calls the pin unblock applet on the card
  1579. //
  1580. DWORD I_CardUnblock(
  1581. IN PCARD_DATA pCardData,
  1582. IN LPWSTR wszPhysicalUser,
  1583. IN PBYTE pbNewPin,
  1584. IN DWORD cbNewPin,
  1585. IN DWORD cNewMaxRetries)
  1586. {
  1587. ISO_HEADER IsoHeader;
  1588. UINT16 wStatusWord = 0;
  1589. PBYTE pbDataIn = NULL;
  1590. DWORD cbDataIn = 0;
  1591. DWORD cbUser = 0;
  1592. SCODE status = 0;
  1593. DWORD dwError = ERROR_SUCCESS;
  1594. PCARDMOD_CONTEXT pCardmodContext =
  1595. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  1596. memset(&IsoHeader, 0, sizeof(IsoHeader));
  1597. //
  1598. // Allocate a command buffer to be transmitted to the card
  1599. //
  1600. cbUser = (DWORD) (wcslen(wszPhysicalUser) + 1) * sizeof(WCHAR);
  1601. cbDataIn = 2 + cbUser + 2 + cbNewPin;
  1602. pbDataIn = (PBYTE) pCardData->pfnCspAlloc(cbDataIn);
  1603. LOG_CHECK_ALLOC(pbDataIn);
  1604. cbDataIn = 0;
  1605. // Setup User Name TLV
  1606. pbDataIn[cbDataIn] = 0;
  1607. cbDataIn++;
  1608. pbDataIn[cbDataIn] = (BYTE) cbUser;
  1609. cbDataIn++;
  1610. memcpy(pbDataIn + cbDataIn, (PBYTE) wszPhysicalUser, cbUser);
  1611. cbDataIn += cbUser;
  1612. // Setup New Pin TLV
  1613. pbDataIn[cbDataIn] = 2;
  1614. cbDataIn++;
  1615. pbDataIn[cbDataIn] = (BYTE) cbNewPin;
  1616. cbDataIn++;
  1617. memcpy(pbDataIn + cbDataIn, pbNewPin, cbNewPin);
  1618. cbDataIn += cbNewPin;
  1619. // Build the command
  1620. IsoHeader.INS = PIN_UNBLOCK_INS;
  1621. IsoHeader.CLA = PIN_UNBLOCK_CLA;
  1622. IsoHeader.P1 = PIN_UNBLOCK_P1;
  1623. IsoHeader.P2 = (BYTE) cNewMaxRetries;
  1624. //
  1625. // Send the pin change command to the card
  1626. //
  1627. status = hScwExecute(
  1628. pCardmodContext->hWfscCardHandle,
  1629. &IsoHeader,
  1630. pbDataIn,
  1631. (TCOUNT) cbDataIn,
  1632. NULL,
  1633. NULL,
  1634. &wStatusWord);
  1635. if (SCW_S_OK == status)
  1636. dwError = I_CardMapExecuteErrorCode(wStatusWord);
  1637. else
  1638. dwError = I_CardMapErrorCode(status);
  1639. Ret:
  1640. if (pbDataIn)
  1641. pCardData->pfnCspFree(pbDataIn);
  1642. return dwError;
  1643. }
  1644. //
  1645. // Retrieves cryptographic authentication challenge bytes from the card.
  1646. //
  1647. DWORD
  1648. WINAPI
  1649. CardGetChallenge(
  1650. IN PCARD_DATA pCardData,
  1651. OUT PBYTE *ppbChallengeData,
  1652. OUT PDWORD pcbChallengeData)
  1653. {
  1654. DWORD dwError = ERROR_SUCCESS;
  1655. PCARDMOD_CONTEXT pCardmodContext =
  1656. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  1657. LOG_BEGIN_FUNCTION(CardGetChallenge);
  1658. *pcbChallengeData = cbCHALLENGE_RESPONSE_DATA;
  1659. *ppbChallengeData = pCardData->pfnCspAlloc(*pcbChallengeData);
  1660. LOG_CHECK_ALLOC(*ppbChallengeData);
  1661. LOG_CHECK_SCW_CALL(hScwGenerateRandom(
  1662. pCardmodContext->hWfscCardHandle,
  1663. *ppbChallengeData,
  1664. (TCOUNT) (*pcbChallengeData)));
  1665. Ret:
  1666. if (NULL != *ppbChallengeData && ERROR_SUCCESS != dwError)
  1667. {
  1668. pCardData->pfnCspFree(*ppbChallengeData);
  1669. *ppbChallengeData = NULL;
  1670. }
  1671. LOG_END_FUNCTION(CardGetChallenge, dwError);
  1672. return dwError;
  1673. }
  1674. //
  1675. // Submits the supplied response bytes to the card, to complete an Admin
  1676. // challenge-response authentication.
  1677. //
  1678. DWORD
  1679. WINAPI
  1680. CardAuthenticateChallenge(
  1681. IN PCARD_DATA pCardData,
  1682. IN PBYTE pbResponseData,
  1683. IN DWORD cbResponseData,
  1684. OUT OPTIONAL PDWORD pcAttemptsRemaining)
  1685. {
  1686. DWORD dwError = ERROR_SUCCESS;
  1687. PCARDMOD_CONTEXT pCardmodContext =
  1688. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  1689. LOG_BEGIN_FUNCTION(CardAuthenticateChallenge);
  1690. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  1691. //
  1692. // Authenticate the admin
  1693. //
  1694. dwError = CardSubmitPin(
  1695. pCardData,
  1696. wszCARD_USER_ADMIN,
  1697. pbResponseData,
  1698. cbResponseData,
  1699. pcAttemptsRemaining);
  1700. LOG_END_FUNCTION(CardAuthenticateChallenge, dwError);
  1701. return dwError;
  1702. }
  1703. //
  1704. // Authenticates as Admin using the provided auth material. Then unblocks the
  1705. // specified account and sets the specified new pin and retry count. The Admin
  1706. // is deauthenticated before returning.
  1707. //
  1708. DWORD
  1709. WINAPI
  1710. CardUnblockPin(
  1711. IN PCARD_DATA pCardData,
  1712. IN LPWSTR pwszUserId,
  1713. IN PBYTE pbAuthenticationData,
  1714. IN DWORD cbAuthenticationData,
  1715. IN PBYTE pbNewPinData,
  1716. IN DWORD cbNewPinData,
  1717. IN DWORD cRetryCount,
  1718. IN DWORD dwFlags)
  1719. {
  1720. DWORD dwError = ERROR_SUCCESS;
  1721. PCARDMOD_CONTEXT pCardmodContext =
  1722. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  1723. LPWSTR wszPhysicalUser = NULL;
  1724. LOG_BEGIN_FUNCTION(CardUnblockPin);
  1725. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  1726. // Verify that admin authentication method flags are valid, although this
  1727. // module will use the auth data the same way in either case.
  1728. if (CARD_UNBLOCK_PIN_PIN != dwFlags &&
  1729. CARD_UNBLOCK_PIN_CHALLENGE_RESPONSE != dwFlags)
  1730. {
  1731. dwError = (DWORD) NTE_BAD_FLAGS;
  1732. goto Ret;
  1733. }
  1734. // Map the provided logical user name to physical user
  1735. dwError = GetWellKnownUserMapping(
  1736. pCardData,
  1737. pwszUserId,
  1738. &wszPhysicalUser);
  1739. if (ERROR_SUCCESS != dwError)
  1740. goto Ret;
  1741. // Authenticate as admin
  1742. dwError = CardSubmitPin(
  1743. pCardData,
  1744. wszCARD_USER_ADMIN,
  1745. pbAuthenticationData,
  1746. cbAuthenticationData,
  1747. NULL);
  1748. if (ERROR_SUCCESS != dwError)
  1749. goto Ret;
  1750. // Perform the unblock
  1751. dwError = I_CardUnblock(
  1752. pCardData,
  1753. wszPhysicalUser,
  1754. pbNewPinData,
  1755. cbNewPinData,
  1756. cRetryCount);
  1757. Ret:
  1758. if (NULL != wszPhysicalUser)
  1759. pCardData->pfnCspFree(wszPhysicalUser);
  1760. LOG_END_FUNCTION(CardUnblockPin, dwError);
  1761. return dwError;
  1762. }
  1763. //
  1764. // Changes the pin or challenge-response key for the specified account.
  1765. //
  1766. // Updating the retry count via this API is not supported in this
  1767. // implementation.
  1768. //
  1769. DWORD
  1770. WINAPI
  1771. CardChangeAuthenticator(
  1772. IN PCARD_DATA pCardData,
  1773. IN LPWSTR pwszUserId,
  1774. IN PBYTE pbCurrentAuthenticator,
  1775. IN DWORD cbCurrentAuthenticator,
  1776. IN PBYTE pbNewAuthenticator,
  1777. IN DWORD cbNewAuthenticator,
  1778. IN DWORD cRetryCount,
  1779. OUT OPTIONAL PDWORD pcAttemptsRemaining)
  1780. {
  1781. DWORD dwError = ERROR_SUCCESS;
  1782. PCARDMOD_CONTEXT pCardmodContext =
  1783. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  1784. LPWSTR wszPhysicalUser = NULL;
  1785. LOG_BEGIN_FUNCTION(CardChangeAuthenticator);
  1786. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  1787. if (0 != cRetryCount)
  1788. {
  1789. dwError = ERROR_INVALID_PARAMETER;
  1790. goto Ret;
  1791. }
  1792. // Map the provided logical user name to physical user
  1793. dwError = GetWellKnownUserMapping(
  1794. pCardData,
  1795. pwszUserId,
  1796. &wszPhysicalUser);
  1797. if (ERROR_SUCCESS != dwError)
  1798. goto Ret;
  1799. // Change the authenticator (pin or challenge-response key) for the target
  1800. // account.
  1801. dwError = I_CardChangePin(
  1802. pCardData,
  1803. wszPhysicalUser,
  1804. pbCurrentAuthenticator,
  1805. cbCurrentAuthenticator,
  1806. pbNewAuthenticator,
  1807. cbNewAuthenticator,
  1808. pcAttemptsRemaining);
  1809. Ret:
  1810. if (NULL != wszPhysicalUser)
  1811. pCardData->pfnCspFree(wszPhysicalUser);
  1812. LOG_END_FUNCTION(CardChangeAuthenticator, dwError);
  1813. return dwError;
  1814. }
  1815. //
  1816. // De-authenticates the specified logical user.
  1817. //
  1818. DWORD
  1819. WINAPI
  1820. CardDeauthenticate(
  1821. IN PCARD_DATA pCardData,
  1822. IN LPWSTR pwszUserId,
  1823. IN DWORD dwFlags)
  1824. {
  1825. DWORD dwError = ERROR_SUCCESS;
  1826. LPWSTR wszPhysicalUser = NULL;
  1827. PCARDMOD_CONTEXT pCardmodContext =
  1828. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  1829. UNREFERENCED_PARAMETER(dwFlags);
  1830. LOG_BEGIN_FUNCTION(CardDeauthenticate);
  1831. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  1832. dwError = GetWellKnownUserMapping(pCardData, pwszUserId, &wszPhysicalUser);
  1833. if (CARDMOD_FAILED(dwError))
  1834. goto Ret;
  1835. LOG_CHECK_SCW_CALL(hScwDeauthenticateName(
  1836. pCardmodContext->hWfscCardHandle,
  1837. wszPhysicalUser));
  1838. Ret:
  1839. if (wszPhysicalUser)
  1840. pCardData->pfnCspFree(wszPhysicalUser);
  1841. LOG_END_FUNCTION(CardDeauthenticate, dwError);
  1842. return dwError;
  1843. }
  1844. //
  1845. // Creates a new file on the card using the specified logical name and Access
  1846. // Condition.
  1847. //
  1848. // If the specified file already exists, ERROR_FILE_EXISTS is returned.
  1849. //
  1850. DWORD
  1851. WINAPI
  1852. CardCreateFile(
  1853. IN PCARD_DATA pCardData,
  1854. IN LPWSTR pwszFileName,
  1855. IN CARD_FILE_ACCESS_CONDITION AccessCondition)
  1856. {
  1857. DWORD dwError = ERROR_SUCCESS;
  1858. LPSTR szPhysicalFileName = NULL;
  1859. LPWSTR wszPhysicalAcl = NULL;
  1860. PCARDMOD_CONTEXT pCardmodContext =
  1861. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  1862. HFILE hFile = 0;
  1863. LOG_BEGIN_FUNCTION(CardCreateFile);
  1864. if (wcslen(pwszFileName) >
  1865. MAX_SUPPORTED_FILE_LEN)
  1866. {
  1867. dwError = ERROR_FILENAME_EXCED_RANGE;
  1868. goto Ret;
  1869. }
  1870. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  1871. dwError = GetWellKnownFileMapping(
  1872. pCardData, pwszFileName, &szPhysicalFileName);
  1873. if (ERROR_SUCCESS != dwError)
  1874. goto Ret;
  1875. dwError = GetWellKnownAcMapping(
  1876. pCardData, AccessCondition, &wszPhysicalAcl);
  1877. if (ERROR_SUCCESS != dwError)
  1878. goto Ret;
  1879. LOG_CHECK_SCW_CALL(hScwCreateFile(
  1880. pCardmodContext->hWfscCardHandle,
  1881. (LPWSTR) szPhysicalFileName,
  1882. wszPhysicalAcl,
  1883. &hFile));
  1884. Ret:
  1885. if (szPhysicalFileName)
  1886. pCardData->pfnCspFree(szPhysicalFileName);
  1887. if (wszPhysicalAcl)
  1888. pCardData->pfnCspFree(wszPhysicalAcl);
  1889. if (hFile)
  1890. hScwCloseFile(
  1891. pCardmodContext->hWfscCardHandle,
  1892. hFile);
  1893. LOG_END_FUNCTION(CardCreateFile, dwError);
  1894. return dwError;
  1895. }
  1896. //
  1897. // Reads the specified logical file directly from the card (without any
  1898. // caching).
  1899. //
  1900. // If the specified file is not found, returns SCARD_E_FILE_NOT_FOUND.
  1901. //
  1902. DWORD
  1903. WINAPI
  1904. CardReadFile(
  1905. IN PCARD_DATA pCardData,
  1906. IN LPWSTR pwszFileName,
  1907. IN DWORD dwFlags,
  1908. OUT PBYTE *ppbData,
  1909. OUT PDWORD pcbData)
  1910. {
  1911. LPSTR szPhysical = NULL;
  1912. DWORD dwError = ERROR_SUCCESS;
  1913. PCARDMOD_CONTEXT pCardmodContext =
  1914. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  1915. UNREFERENCED_PARAMETER(dwFlags);
  1916. LOG_BEGIN_FUNCTION(CardReadFile);
  1917. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  1918. dwError = GetWellKnownFileMapping(
  1919. pCardData,
  1920. pwszFileName,
  1921. &szPhysical);
  1922. if (CARDMOD_FAILED(dwError))
  1923. goto Ret;
  1924. //
  1925. // For any file requested directly by the CSP (or other caller), assume
  1926. // that no cache lookup should be done. That is, assume that the caller
  1927. // is doing its own caching for files that it "owns".
  1928. //
  1929. dwError = I_CardReadFile(
  1930. pCardData,
  1931. (LPWSTR) szPhysical,
  1932. ppbData,
  1933. pcbData,
  1934. FALSE);
  1935. Ret:
  1936. if (szPhysical)
  1937. pCardData->pfnCspFree(szPhysical);
  1938. if (CARDMOD_FAILED(dwError) && *ppbData)
  1939. {
  1940. pCardData->pfnCspFree(*ppbData);
  1941. *ppbData = NULL;
  1942. }
  1943. LOG_END_FUNCTION(CardReadFile, dwError);
  1944. return dwError;
  1945. }
  1946. //
  1947. // Writes the specified logical file to the card.
  1948. //
  1949. // If the specified file does not already exist, SCARD_E_FILE_NOT_FOUND
  1950. // is returned.
  1951. //
  1952. DWORD
  1953. WINAPI
  1954. CardWriteFile(
  1955. IN PCARD_DATA pCardData,
  1956. IN LPWSTR pwszFileName,
  1957. IN DWORD dwFlags,
  1958. IN PBYTE pbData,
  1959. IN DWORD cbData)
  1960. {
  1961. LPSTR szPhysical = NULL;
  1962. DWORD dwError = ERROR_SUCCESS;
  1963. HFILE hFile = 0;
  1964. PCARDMOD_CONTEXT pCardmodContext =
  1965. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  1966. DWORD cbActual = 0;
  1967. UNREFERENCED_PARAMETER(dwFlags);
  1968. LOG_BEGIN_FUNCTION(CardWriteFile);
  1969. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  1970. dwError = GetWellKnownFileMapping(
  1971. pCardData, pwszFileName, &szPhysical);
  1972. if (ERROR_SUCCESS != dwError)
  1973. goto Ret;
  1974. LOG_CHECK_SCW_CALL(hScwCreateFile(
  1975. pCardmodContext->hWfscCardHandle,
  1976. (LPWSTR) szPhysical,
  1977. NULL,
  1978. &hFile));
  1979. LOG_CHECK_SCW_CALL(hScwWriteFile32(
  1980. pCardmodContext->hWfscCardHandle,
  1981. hFile,
  1982. pbData,
  1983. cbData,
  1984. &cbActual));
  1985. if (cbActual != cbData)
  1986. {
  1987. dwError = (DWORD) SCARD_W_EOF;
  1988. goto Ret;
  1989. }
  1990. Ret:
  1991. if (hFile)
  1992. hScwCloseFile(
  1993. pCardmodContext->hWfscCardHandle, hFile);
  1994. if (szPhysical)
  1995. pCardData->pfnCspFree(szPhysical);
  1996. LOG_END_FUNCTION(CardWriteFile, dwError);
  1997. return dwError;
  1998. }
  1999. //
  2000. // Deletes the specified logical file from the card.
  2001. //
  2002. // If the specified files is not found, SCARD_E_FILE_NOT_FOUND is returned.
  2003. //
  2004. DWORD
  2005. WINAPI
  2006. CardDeleteFile(
  2007. IN PCARD_DATA pCardData,
  2008. IN DWORD dwReserved,
  2009. IN LPWSTR pwszFileName)
  2010. {
  2011. LPSTR szPhysical = NULL;
  2012. DWORD dwError = ERROR_SUCCESS;
  2013. PCARDMOD_CONTEXT pCardmodContext =
  2014. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  2015. UNREFERENCED_PARAMETER(dwReserved);
  2016. LOG_BEGIN_FUNCTION(CardDeleteFile);
  2017. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  2018. dwError = GetWellKnownFileMapping(
  2019. pCardData, pwszFileName, &szPhysical);
  2020. if (ERROR_SUCCESS != dwError)
  2021. goto Ret;
  2022. LOG_CHECK_SCW_CALL(hScwDeleteFile(
  2023. pCardmodContext->hWfscCardHandle, (LPWSTR) szPhysical));
  2024. Ret:
  2025. if (szPhysical)
  2026. pCardData->pfnCspFree(szPhysical);
  2027. LOG_END_FUNCTION(CardDeleteFile, dwError);
  2028. return dwError;
  2029. }
  2030. //
  2031. // Enumerates the files present on the card in the logical directory name
  2032. // specified by the caller in the pmwszFileName parameter.
  2033. //
  2034. DWORD
  2035. WINAPI
  2036. CardEnumFiles(
  2037. IN PCARD_DATA pCardData,
  2038. IN DWORD dwFlags,
  2039. IN OUT LPWSTR *pmwszFileName)
  2040. {
  2041. /*
  2042. LPWSTR wszPhysicalDirectory = NULL;
  2043. DWORD dwError = ERROR_SUCCESS;
  2044. PCARDMOD_CONTEXT pCardmodContext =
  2045. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  2046. LPWSTR wszFiles = NULL;
  2047. LPWSTR wsz = NULL;
  2048. DWORD cchFiles = MAX_SUPPORTED_FILE_LEN;
  2049. DWORD cchCurrent = 0;
  2050. UINT16 nEnumCookie = 0;
  2051. SCODE result = 0;
  2052. BOOL fRetrying = FALSE;
  2053. */
  2054. UNREFERENCED_PARAMETER(dwFlags);
  2055. //
  2056. // TODO - need to implement reverse file mapping for this function to work
  2057. // correctly.
  2058. //
  2059. UNREFERENCED_PARAMETER(pCardData);
  2060. UNREFERENCED_PARAMETER(pmwszFileName);
  2061. return ERROR_CALL_NOT_IMPLEMENTED;
  2062. /*
  2063. LOG_BEGIN_FUNCTION(CardEnumFiles);
  2064. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  2065. // Find the physical directory name in which we'll
  2066. // be enumerating.
  2067. dwError = GetWellKnownFileMapping(
  2068. pCardData, *pmwszFileName, &wszPhysicalDirectory);
  2069. if (ERROR_SUCCESS != dwError)
  2070. goto Ret;
  2071. // Now set the CSP's pointer to the logical directory
  2072. // name to NULL to avoid ambiguity, since we'll be re-using the same
  2073. // pointer to return the list of files.
  2074. *pmwszFileName = NULL;
  2075. // Allocate space for a multi-string that may or may not be
  2076. // large enough to hold all of the enumerated file names.
  2077. wszFiles = (LPWSTR) pCardData->pfnCspAlloc(cchFiles * sizeof(WCHAR));
  2078. LOG_CHECK_ALLOC(wszFiles);
  2079. #pragma warning(push)
  2080. // Disable warning/error for conditional expression is constant
  2081. #pragma warning(disable:4127)
  2082. while (TRUE)
  2083. {
  2084. #pragma warning(pop)
  2085. //
  2086. // The WFSC marshalling code seems to puke if a buffer length of
  2087. // greater than SCHAR_MAX (127) is passed.
  2088. //
  2089. result = hScwEnumFile(
  2090. pCardmodContext->hWfscCardHandle,
  2091. wszPhysicalDirectory,
  2092. &nEnumCookie,
  2093. wszFiles + cchCurrent,
  2094. (TCOUNT) min(cchFiles - cchCurrent, MAX_SUPPORTED_FILE_LEN));
  2095. if (SCW_S_OK == result)
  2096. {
  2097. // Add on the length of the new file plus its terminator
  2098. cchCurrent += (DWORD) wcslen(wszFiles + cchCurrent) + 1;
  2099. fRetrying = FALSE;
  2100. // Continue looping
  2101. }
  2102. else if (SCW_E_BUFFERTOOSMALL == result)
  2103. {
  2104. if (fRetrying)
  2105. {
  2106. // We already retried this call once. Give up.
  2107. break;
  2108. }
  2109. wsz = (LPWSTR) pCardData->pfnCspAlloc((cchCurrent * 2) * sizeof(WCHAR));
  2110. LOG_CHECK_ALLOC(wsz);
  2111. memcpy(
  2112. wsz,
  2113. wszFiles,
  2114. cchCurrent);
  2115. pCardData->pfnCspFree(wszFiles);
  2116. wszFiles = wsz;
  2117. wsz = NULL;
  2118. cchFiles = cchCurrent * 2;
  2119. fRetrying = TRUE;
  2120. // Retry the last enum call
  2121. }
  2122. else if (SCW_E_NOMOREFILES == result)
  2123. {
  2124. *pmwszFileName = (LPWSTR) pCardData->pfnCspAlloc(
  2125. (1 + cchCurrent) * sizeof(WCHAR));
  2126. LOG_CHECK_ALLOC(*pmwszFileName);
  2127. memcpy(
  2128. *pmwszFileName,
  2129. wszFiles,
  2130. cchCurrent * sizeof(WCHAR));
  2131. // Make sure the multi-string is terminated by an extra NULL
  2132. (*pmwszFileName)[cchCurrent] = L'\0';
  2133. // We're done
  2134. break;
  2135. }
  2136. else
  2137. {
  2138. // Unexpected error. Bail.
  2139. dwError = (DWORD) result;
  2140. goto Ret;
  2141. }
  2142. }
  2143. Ret:
  2144. if (wszPhysicalDirectory)
  2145. pCardData->pfnCspFree(wszPhysicalDirectory);
  2146. if (wszFiles)
  2147. pCardData->pfnCspFree(wszFiles);
  2148. if (wsz)
  2149. pCardData->pfnCspFree(wsz);
  2150. if (ERROR_SUCCESS != dwError && *pmwszFileName)
  2151. {
  2152. pCardData->pfnCspFree(*pmwszFileName);
  2153. *pmwszFileName = NULL;
  2154. }
  2155. LOG_END_FUNCTION(CardEnumFiles, dwError);
  2156. return dwError;
  2157. */
  2158. }
  2159. //
  2160. // Initializes a CARD_FILE_INFO structure for the specified logical file.
  2161. //
  2162. DWORD
  2163. WINAPI
  2164. CardGetFileInfo(
  2165. IN PCARD_DATA pCardData,
  2166. IN LPWSTR pwszFileName,
  2167. OUT PCARD_FILE_INFO pCardFileInfo)
  2168. {
  2169. DWORD dwError = ERROR_SUCCESS;
  2170. LPSTR szPhysical = NULL;
  2171. HFILE hFile = 0;
  2172. PCARDMOD_CONTEXT pCardmodContext =
  2173. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  2174. TOFFSET nFileLength = 0;
  2175. LOG_BEGIN_FUNCTION(CardGetFileInfo);
  2176. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  2177. dwError = GetWellKnownFileMapping(
  2178. pCardData,
  2179. pwszFileName,
  2180. &szPhysical);
  2181. if (ERROR_SUCCESS != dwError)
  2182. goto Ret;
  2183. //
  2184. // First, get the length of the file.
  2185. //
  2186. LOG_CHECK_SCW_CALL(hScwCreateFile(
  2187. pCardmodContext->hWfscCardHandle,
  2188. (LPWSTR) szPhysical,
  2189. NULL,
  2190. &hFile));
  2191. LOG_CHECK_SCW_CALL(hScwGetFileLength(
  2192. pCardmodContext->hWfscCardHandle,
  2193. hFile,
  2194. &nFileLength));
  2195. pCardFileInfo->cbFileSize = (DWORD) nFileLength;
  2196. //
  2197. // Next, get ACL info.
  2198. //
  2199. // TODO
  2200. pCardFileInfo->AccessCondition = InvalidAc;
  2201. Ret:
  2202. if (szPhysical)
  2203. pCardData->pfnCspFree(szPhysical);
  2204. if (hFile)
  2205. hScwCloseFile(
  2206. pCardmodContext->hWfscCardHandle, hFile);
  2207. LOG_END_FUNCTION(CardGetFileInfo, dwError);
  2208. return dwError;
  2209. }
  2210. //
  2211. // Initializes a CARD_FREE_SPACE_INFO structure using static information about
  2212. // the available space on the target card.
  2213. //
  2214. DWORD
  2215. WINAPI
  2216. CardQueryFreeSpace(
  2217. IN PCARD_DATA pCardData,
  2218. IN DWORD dwFlags,
  2219. OUT PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo)
  2220. {
  2221. PCARDMOD_CONTEXT pCardmodContext =
  2222. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  2223. UNREFERENCED_PARAMETER(dwFlags);
  2224. LOG_BEGIN_FUNCTION(CardQueryFreeSpace);
  2225. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  2226. //
  2227. // Get the base free space information for this card.
  2228. //
  2229. memcpy(
  2230. pCardFreeSpaceInfo,
  2231. &pCardmodContext->pSupportedCard->CardFreeSpaceInfo,
  2232. sizeof(CARD_FREE_SPACE_INFO));
  2233. LOG_END_FUNCTION(CardQueryFreeSpace, 0);
  2234. return ERROR_SUCCESS;
  2235. }
  2236. //
  2237. // Performs an RSA decryption using the specified Signature or Key Exchange
  2238. // key on the specified data. The length of the target data must be equal
  2239. // to the length of the public modulus, and pInfo->cbData must be set to
  2240. // that length.
  2241. //
  2242. DWORD
  2243. WINAPI
  2244. CardPrivateKeyDecrypt(
  2245. IN PCARD_DATA pCardData,
  2246. IN OUT PCARD_PRIVATE_KEY_DECRYPT_INFO pInfo)
  2247. {
  2248. DWORD dwError = ERROR_SUCCESS;
  2249. LPSTR szPrivateKeyFile = NULL;
  2250. PBYTE pbInit = NULL;
  2251. DWORD cbInit = 0;
  2252. DWORD cbPrivateKeyFile = 0;
  2253. PCARDMOD_CONTEXT pCardmodContext =
  2254. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  2255. PBYTE pbCiphertext = NULL;
  2256. TCOUNT cbCiphertext = 0;
  2257. LOG_BEGIN_FUNCTION(CardPrivateKeyDecrypt);
  2258. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  2259. dwError = BuildCardKeyFilenames(
  2260. pCardData,
  2261. pInfo->dwKeySpec,
  2262. pInfo->bContainerIndex,
  2263. &szPrivateKeyFile,
  2264. NULL);
  2265. if (CARDMOD_FAILED(dwError))
  2266. goto Ret;
  2267. //
  2268. // Setup the command to initialize the RSA operation on the card
  2269. //
  2270. cbPrivateKeyFile = ((DWORD) wcslen(
  2271. (LPWSTR) szPrivateKeyFile) + 1) * sizeof(WCHAR);
  2272. cbInit = 1 + 1 + 1 + cbPrivateKeyFile + 2;
  2273. pbInit = (PBYTE) pCardData->pfnCspAlloc(cbInit);
  2274. LOG_CHECK_ALLOC(pbInit);
  2275. cbInit = 0;
  2276. // Tag
  2277. pbInit[cbInit] = 0x00;
  2278. cbInit++;
  2279. // Length
  2280. // Number of following bytes:
  2281. // filename len, filename + NULL, key data offset
  2282. pbInit[cbInit] = (BYTE) (1 + cbPrivateKeyFile + 2);
  2283. cbInit++;
  2284. // Value
  2285. pbInit[cbInit] = (BYTE) cbPrivateKeyFile / sizeof(WCHAR);
  2286. cbInit++;
  2287. memcpy(pbInit + cbInit, (PBYTE) szPrivateKeyFile, cbPrivateKeyFile);
  2288. cbInit += cbPrivateKeyFile;
  2289. *(UNALIGNED WORD *) (pbInit + cbInit) = 0x0000;
  2290. LOG_CHECK_SCW_CALL(hScwCryptoInitialize(
  2291. pCardmodContext->hWfscCardHandle,
  2292. CM_RSA_CRT | CM_KEY_INFILE,
  2293. pbInit));
  2294. //
  2295. // Do the private key decrypt
  2296. //
  2297. pbCiphertext = (PBYTE) pCardData->pfnCspAlloc(pInfo->cbData);
  2298. LOG_CHECK_ALLOC(pbCiphertext);
  2299. cbCiphertext = (TCOUNT) pInfo->cbData;
  2300. LOG_CHECK_SCW_CALL(hScwCryptoAction(
  2301. pCardmodContext->hWfscCardHandle,
  2302. pInfo->pbData,
  2303. (TCOUNT) pInfo->cbData,
  2304. pbCiphertext,
  2305. &cbCiphertext));
  2306. if (cbCiphertext != pInfo->cbData)
  2307. {
  2308. dwError = ERROR_INTERNAL_ERROR;
  2309. goto Ret;
  2310. }
  2311. memcpy(pInfo->pbData, pbCiphertext, cbCiphertext);
  2312. Ret:
  2313. if (pbCiphertext)
  2314. pCardData->pfnCspFree(pbCiphertext);
  2315. if (pbInit)
  2316. pCardData->pfnCspFree(pbInit);
  2317. if (szPrivateKeyFile)
  2318. pCardData->pfnCspFree(szPrivateKeyFile);
  2319. LOG_END_FUNCTION(CardPrivateKeyDecrypt, dwError);
  2320. return dwError;
  2321. }
  2322. //
  2323. // Initializes a CARD_KEY_SIZES structure for the specified key type, indicated
  2324. // the key sizes supported by the target card.
  2325. //
  2326. DWORD
  2327. WINAPI
  2328. CardQueryKeySizes(
  2329. IN PCARD_DATA pCardData,
  2330. IN DWORD dwKeySpec,
  2331. IN DWORD dwReserved,
  2332. OUT PCARD_KEY_SIZES pKeySizes)
  2333. {
  2334. DWORD dwError = ERROR_SUCCESS;
  2335. PCARDMOD_CONTEXT pCardmodContext =
  2336. (PCARDMOD_CONTEXT) pCardData->pvVendorSpecific;
  2337. UNREFERENCED_PARAMETER(dwReserved);
  2338. LOG_BEGIN_FUNCTION(CardQueryKeySizes);
  2339. ProxyUpdateScardHandle(pCardmodContext->hWfscCardHandle, pCardData->hScard);
  2340. switch (dwKeySpec)
  2341. {
  2342. case AT_SIGNATURE:
  2343. memcpy(
  2344. pKeySizes,
  2345. &pCardmodContext->pSupportedCard->CardKeySizes_Sig,
  2346. sizeof(CARD_KEY_SIZES));
  2347. break;
  2348. case AT_KEYEXCHANGE:
  2349. memcpy(
  2350. pKeySizes,
  2351. &pCardmodContext->pSupportedCard->CardKeySizes_KeyEx,
  2352. sizeof(CARD_KEY_SIZES));
  2353. break;
  2354. default:
  2355. dwError = (DWORD) NTE_BAD_ALGID;
  2356. break;
  2357. }
  2358. LOG_END_FUNCTION(CardQueryKeySizes, dwError);
  2359. return dwError;
  2360. }
  2361. //
  2362. // Loader callback.
  2363. //
  2364. BOOL WINAPI
  2365. DllInitialize(
  2366. IN PVOID hmod,
  2367. IN ULONG Reason,
  2368. IN PCONTEXT Context) // Unused parameter
  2369. {
  2370. DWORD dwLen = 0;
  2371. UNREFERENCED_PARAMETER(Context);
  2372. if (Reason == DLL_PROCESS_ATTACH)
  2373. {
  2374. // Get our image name.
  2375. dwLen = GetModuleBaseName(
  2376. GetCurrentProcess(),
  2377. hmod,
  2378. l_wszImagePath,
  2379. sizeof(l_wszImagePath) / sizeof(l_wszImagePath[0]));
  2380. if (0 == dwLen)
  2381. return FALSE;
  2382. DisableThreadLibraryCalls(hmod);
  2383. #if DBG
  2384. CardmodInitDebug(MyDebugKeys);
  2385. #endif
  2386. }
  2387. else if (Reason == DLL_PROCESS_DETACH)
  2388. {
  2389. // Cleanup
  2390. #if DBG
  2391. CardmodUnloadDebug();
  2392. #endif
  2393. }
  2394. return TRUE;
  2395. }
  2396. //
  2397. // Registers the cards supported by this card module.
  2398. //
  2399. STDAPI
  2400. DllRegisterServer(
  2401. void)
  2402. {
  2403. DWORD dwReturn = ERROR_SUCCESS;
  2404. DWORD dwSts;
  2405. int iSupportedCard = 0;
  2406. for (
  2407. iSupportedCard = 0;
  2408. iSupportedCard < sizeof(SupportedCards) /
  2409. sizeof(SupportedCards[0]);
  2410. iSupportedCard++)
  2411. {
  2412. SCardForgetCardType(
  2413. 0,
  2414. SupportedCards[iSupportedCard].wszCardName);
  2415. dwSts = SCardIntroduceCardType(
  2416. 0,
  2417. SupportedCards[iSupportedCard].wszCardName,
  2418. NULL,
  2419. NULL,
  2420. 0,
  2421. SupportedCards[iSupportedCard].rgbAtr,
  2422. SupportedCards[iSupportedCard].rgbAtrMask,
  2423. SupportedCards[iSupportedCard].cbAtr);
  2424. if (SCARD_S_SUCCESS != dwSts)
  2425. {
  2426. dwReturn = dwSts;
  2427. goto ErrorRet;
  2428. }
  2429. dwSts = SCardSetCardTypeProviderName(
  2430. 0,
  2431. SupportedCards[iSupportedCard].wszCardName,
  2432. SCARD_PROVIDER_CSP,
  2433. MS_SCARD_PROV);
  2434. if (SCARD_S_SUCCESS != dwSts)
  2435. {
  2436. dwReturn = dwSts;
  2437. goto ErrorRet;
  2438. }
  2439. dwSts = SCardSetCardTypeProviderName(
  2440. 0,
  2441. SupportedCards[iSupportedCard].wszCardName,
  2442. SCARD_PROVIDER_CARD_MODULE,
  2443. l_wszImagePath);
  2444. if (SCARD_S_SUCCESS != dwSts)
  2445. {
  2446. dwReturn = dwSts;
  2447. goto ErrorRet;
  2448. }
  2449. }
  2450. ErrorRet:
  2451. return dwReturn;
  2452. }
  2453. //
  2454. // Deletes the registration of cards supported by this card module.
  2455. //
  2456. STDAPI
  2457. DllUnregisterServer(
  2458. void)
  2459. {
  2460. DWORD dwSts = ERROR_SUCCESS;
  2461. int iSupportedCard = 0;
  2462. for (
  2463. iSupportedCard = 0;
  2464. iSupportedCard < sizeof(SupportedCards) /
  2465. sizeof(SupportedCards[0]);
  2466. iSupportedCard++)
  2467. {
  2468. dwSts = SCardForgetCardType(
  2469. 0,
  2470. SupportedCards[iSupportedCard].wszCardName);
  2471. }
  2472. return dwSts;
  2473. }