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.

2242 lines
86 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1995 - 1999
  3. Module Name:
  4. tclCrypt
  5. Abstract:
  6. Tcl commands to support CryptoAPI CSP debugging.
  7. Author:
  8. Doug Barlow (dbarlow) 03/13/1998
  9. Environment:
  10. Tcl for Windows NT.
  11. Notes:
  12. --*/
  13. // #ifndef WIN32_LEAN_AND_MEAN
  14. // #define WIN32_LEAN_AND_MEAN
  15. // #endif
  16. // #include <windows.h> // All the Windows definitions.
  17. #include <afx.h>
  18. #ifndef WINVER
  19. #define WINVER 0x0400
  20. #endif
  21. #include <wincrypt.h>
  22. #include <string.h>
  23. #include <stdio.h>
  24. #include <stddef.h>
  25. #include <math.h>
  26. #ifndef __STDC__
  27. #define __STDC__ 1
  28. #endif
  29. extern "C" {
  30. #include "scext.h"
  31. #include "tclhelp.h"
  32. }
  33. #include "tclRdCmd.h"
  34. #include "cspDirct.h"
  35. typedef enum
  36. {
  37. Undefined = 0,
  38. Provider,
  39. Key,
  40. Hash
  41. } HandleType;
  42. static const ValueMap vmProviderTypes[]
  43. = {
  44. { TEXT("PROV_RSA_FULL"), PROV_RSA_FULL},
  45. { TEXT("PROV_RSA_SIG"), PROV_RSA_SIG},
  46. { TEXT("PROV_DSS"), PROV_DSS},
  47. { TEXT("PROV_FORTEZZA"), PROV_FORTEZZA},
  48. { TEXT("PROV_MS_EXCHANGE"), PROV_MS_EXCHANGE},
  49. { TEXT("PROV_SSL"), PROV_SSL},
  50. { TEXT("PROV_RSA_SCHANNEL"), PROV_RSA_SCHANNEL},
  51. { TEXT("PROV_DSS_DH"), PROV_DSS_DH},
  52. { TEXT("PROV_EC_ECDSA_SIG"), PROV_EC_ECDSA_SIG},
  53. { TEXT("PROV_EC_ECNRA_SIG"), PROV_EC_ECNRA_SIG},
  54. { TEXT("PROV_EC_ECDSA_FULL"), PROV_EC_ECDSA_FULL},
  55. { TEXT("PROV_EC_ECNRA_FULL"), PROV_EC_ECNRA_FULL},
  56. { TEXT("PROV_DH_SCHANNEL"), PROV_DH_SCHANNEL},
  57. { TEXT("PROV_SPYRUS_LYNKS"), PROV_SPYRUS_LYNKS},
  58. { TEXT("PROV_RNG"), PROV_RNG},
  59. { TEXT("PROV_INTEL_SEC"), PROV_INTEL_SEC},
  60. { TEXT("RSA"), PROV_RSA_FULL},
  61. { TEXT("SIGNATURE"), PROV_RSA_SIG},
  62. { TEXT("DSS"), PROV_DSS},
  63. { TEXT("FORTEZZA"), PROV_FORTEZZA},
  64. { NULL, 0} };
  65. static const ValueMap vmAcquireFlags[]
  66. = {
  67. { TEXT("CRYPT_VERIFYCONTEXT"), CRYPT_VERIFYCONTEXT},
  68. { TEXT("CRYPT_NEWKEYSET"), CRYPT_NEWKEYSET},
  69. { TEXT("CRYPT_DELETEKEYSET"), CRYPT_DELETEKEYSET},
  70. { TEXT("CRYPT_MACHINE_KEYSET"), CRYPT_MACHINE_KEYSET},
  71. { TEXT("CRYPT_SILENT"), CRYPT_SILENT},
  72. { TEXT("VERIFYONLY"), CRYPT_VERIFYCONTEXT},
  73. { TEXT("NEW"), CRYPT_NEWKEYSET},
  74. { TEXT("DELETE"), CRYPT_DELETEKEYSET},
  75. { TEXT("MACHINE"), CRYPT_MACHINE_KEYSET},
  76. { TEXT("SILENT"), CRYPT_SILENT},
  77. { NULL, 0} };
  78. static const ValueMap vmGetFlags[]
  79. = {
  80. { TEXT("CRYPT_FIRST"), CRYPT_FIRST},
  81. { TEXT("CRYPT_NEXT"), CRYPT_NEXT},
  82. { TEXT("CRYPT_SGC_ENUM"), CRYPT_SGC_ENUM},
  83. { NULL, 0} };
  84. static const ValueMap vmGetProvParams[]
  85. = {
  86. { TEXT("PP_ENUMALGS"), PP_ENUMALGS},
  87. { TEXT("PP_ENUMCONTAINERS"), PP_ENUMCONTAINERS},
  88. { TEXT("PP_IMPTYPE"), PP_IMPTYPE},
  89. { TEXT("PP_NAME"), PP_NAME},
  90. { TEXT("PP_VERSION"), PP_VERSION},
  91. { TEXT("PP_CONTAINER"), PP_CONTAINER},
  92. { TEXT("PP_CHANGE_PASSWORD"), PP_CHANGE_PASSWORD},
  93. { TEXT("PP_KEYSET_SEC_DESCR"), PP_KEYSET_SEC_DESCR},
  94. { TEXT("PP_CERTCHAIN"), PP_CERTCHAIN},
  95. { TEXT("PP_KEY_TYPE_SUBTYPE"), PP_KEY_TYPE_SUBTYPE},
  96. { TEXT("PP_PROVTYPE"), PP_PROVTYPE},
  97. { TEXT("PP_KEYSTORAGE"), PP_KEYSTORAGE},
  98. { TEXT("PP_APPLI_CERT"), PP_APPLI_CERT},
  99. { TEXT("PP_SYM_KEYSIZE"), PP_SYM_KEYSIZE},
  100. { TEXT("PP_SESSION_KEYSIZE"), PP_SESSION_KEYSIZE},
  101. { TEXT("PP_UI_PROMPT"), PP_UI_PROMPT},
  102. { TEXT("PP_ENUMALGS_EX"), PP_ENUMALGS_EX},
  103. { TEXT("PP_ENUMMANDROOTS"), PP_ENUMMANDROOTS},
  104. { TEXT("PP_ENUMELECTROOTS"), PP_ENUMELECTROOTS},
  105. { TEXT("PP_KEYSET_TYPE"), PP_KEYSET_TYPE},
  106. { TEXT("PP_ADMIN_PIN"), PP_ADMIN_PIN},
  107. { TEXT("PP_KEYEXCHANGE_PIN"), PP_KEYEXCHANGE_PIN},
  108. { TEXT("PP_SIGNATURE_PIN"), PP_SIGNATURE_PIN},
  109. { TEXT("PP_SIG_KEYSIZE_INC"), PP_SIG_KEYSIZE_INC},
  110. { TEXT("PP_KEYX_KEYSIZE_INC"), PP_KEYX_KEYSIZE_INC},
  111. { TEXT("PP_UNIQUE_CONTAINER"), PP_UNIQUE_CONTAINER},
  112. { TEXT("PP_SGC_INFO"), PP_SGC_INFO},
  113. { TEXT("PP_USE_HARDWARE_RNG"), PP_USE_HARDWARE_RNG},
  114. { TEXT("PP_KEYSPEC"), PP_KEYSPEC},
  115. { TEXT("PP_ENUMEX_SIGNING_PROT"), PP_ENUMEX_SIGNING_PROT},
  116. { TEXT("NAME"), PP_NAME},
  117. { TEXT("CONTAINER"), PP_CONTAINER},
  118. { TEXT("KEYSET"), PP_CONTAINER},
  119. { NULL, 0} };
  120. static const ValueMap vmSetProvParams[]
  121. = {
  122. { TEXT("PP_CLIENT_HWND"), PP_CLIENT_HWND},
  123. { TEXT("PP_CONTEXT_INFO"), PP_CONTEXT_INFO},
  124. { TEXT("PP_KEYEXCHANGE_KEYSIZE"), PP_KEYEXCHANGE_KEYSIZE},
  125. { TEXT("PP_SIGNATURE_KEYSIZE"), PP_SIGNATURE_KEYSIZE},
  126. { TEXT("PP_KEYEXCHANGE_ALG"), PP_KEYEXCHANGE_ALG},
  127. { TEXT("PP_SIGNATURE_ALG"), PP_SIGNATURE_ALG},
  128. { TEXT("PP_DELETEKEY"), PP_DELETEKEY},
  129. { NULL, 0} };
  130. static const ValueMap vmKeyParams[]
  131. = {
  132. { TEXT("KP_IV"), KP_IV},
  133. { TEXT("KP_SALT"), KP_SALT},
  134. { TEXT("KP_PADDING"), KP_PADDING},
  135. { TEXT("KP_MODE"), KP_MODE},
  136. { TEXT("KP_MODE_BITS"), KP_MODE_BITS},
  137. { TEXT("KP_PERMISSIONS"), KP_PERMISSIONS},
  138. { TEXT("KP_ALGID"), KP_ALGID},
  139. { TEXT("KP_BLOCKLEN"), KP_BLOCKLEN},
  140. { TEXT("KP_KEYLEN"), KP_KEYLEN},
  141. { TEXT("KP_SALT_EX"), KP_SALT_EX},
  142. { TEXT("KP_P"), KP_P},
  143. { TEXT("KP_G"), KP_G},
  144. { TEXT("KP_Q"), KP_Q},
  145. { TEXT("KP_X"), KP_X},
  146. { TEXT("KP_Y"), KP_Y},
  147. { TEXT("KP_RA"), KP_RA},
  148. { TEXT("KP_RB"), KP_RB},
  149. { TEXT("KP_INFO"), KP_INFO},
  150. { TEXT("KP_EFFECTIVE_KEYLEN"), KP_EFFECTIVE_KEYLEN},
  151. { TEXT("KP_SCHANNEL_ALG"), KP_SCHANNEL_ALG},
  152. { TEXT("KP_CLIENT_RANDOM"), KP_CLIENT_RANDOM},
  153. { TEXT("KP_SERVER_RANDOM"), KP_SERVER_RANDOM},
  154. { TEXT("KP_RP"), KP_RP},
  155. { TEXT("KP_PRECOMP_MD5"), KP_PRECOMP_MD5},
  156. { TEXT("KP_PRECOMP_SHA"), KP_PRECOMP_SHA},
  157. { TEXT("KP_CERTIFICATE"), KP_CERTIFICATE},
  158. { TEXT("KP_CLEAR_KEY"), KP_CLEAR_KEY},
  159. { TEXT("KP_PUB_EX_LEN"), KP_PUB_EX_LEN},
  160. { TEXT("KP_PUB_EX_VAL"), KP_PUB_EX_VAL},
  161. { TEXT("KP_KEYVAL"), KP_KEYVAL},
  162. { TEXT("KP_ADMIN_PIN"), KP_ADMIN_PIN},
  163. { TEXT("KP_KEYEXCHANGE_PIN"), KP_KEYEXCHANGE_PIN},
  164. { TEXT("KP_SIGNATURE_PIN"), KP_SIGNATURE_PIN},
  165. { TEXT("KP_PREHASH"), KP_PREHASH},
  166. { TEXT("KP_OAEP_PARAMS"), KP_OAEP_PARAMS},
  167. { TEXT("KP_CMS_KEY_INFO"), KP_CMS_KEY_INFO},
  168. { TEXT("KP_CMS_DH_KEY_INFO"), KP_CMS_DH_KEY_INFO},
  169. { TEXT("KP_PUB_PARAMS"), KP_PUB_PARAMS},
  170. { TEXT("KP_VERIFY_PARAMS"), KP_VERIFY_PARAMS},
  171. { TEXT("KP_HIGHEST_VERSION"), KP_HIGHEST_VERSION},
  172. { NULL, 0} };
  173. static const ValueMap vmKeyTypes[]
  174. = {
  175. { TEXT("AT_KEYEXCHANGE"), AT_KEYEXCHANGE},
  176. { TEXT("AT_SIGNATURE"), AT_SIGNATURE},
  177. { TEXT("KEYEXCHANGE"), AT_KEYEXCHANGE},
  178. { TEXT("SIGNATURE"), AT_SIGNATURE},
  179. { TEXT("EXCHANGE"), AT_KEYEXCHANGE},
  180. { NULL, 0} };
  181. static const ValueMap vmHashParams[]
  182. = {
  183. { TEXT("HP_ALGID"), HP_ALGID},
  184. { TEXT("HP_HASHVAL"), HP_HASHVAL},
  185. { TEXT("HP_HASHSIZE"), HP_HASHSIZE},
  186. { TEXT("HP_HMAC_INFO"), HP_HMAC_INFO},
  187. { TEXT("HP_TLS1PRF_LABEL"), HP_TLS1PRF_LABEL},
  188. { TEXT("HP_TLS1PRF_SEED"), HP_TLS1PRF_SEED},
  189. { NULL, 0} };
  190. static const ValueMap vmKeyFlags[]
  191. = {
  192. { TEXT("CRYPT_EXPORTABLE"), CRYPT_EXPORTABLE},
  193. { TEXT("CRYPT_USER_PROTECTED"), CRYPT_USER_PROTECTED},
  194. { TEXT("CRYPT_CREATE_SALT"), CRYPT_CREATE_SALT},
  195. { TEXT("CRYPT_UPDATE_KEY"), CRYPT_UPDATE_KEY},
  196. { TEXT("CRYPT_NO_SALT"), CRYPT_NO_SALT},
  197. { TEXT("CRYPT_PREGEN"), CRYPT_PREGEN},
  198. { TEXT("CRYPT_RECIPIENT"), CRYPT_RECIPIENT},
  199. { TEXT("CRYPT_INITIATOR"), CRYPT_INITIATOR},
  200. { TEXT("CRYPT_ONLINE"), CRYPT_ONLINE},
  201. { TEXT("CRYPT_SF"), CRYPT_SF},
  202. { TEXT("CRYPT_CREATE_IV"), CRYPT_CREATE_IV},
  203. { TEXT("CRYPT_KEK"), CRYPT_KEK},
  204. { TEXT("CRYPT_DATA_KEY"), CRYPT_DATA_KEY},
  205. { TEXT("CRYPT_VOLATILE"), CRYPT_VOLATILE},
  206. { TEXT("CRYPT_SGCKEY"), CRYPT_SGCKEY},
  207. { NULL, 0} };
  208. static const ValueMap vmAlgIds[]
  209. = {
  210. { TEXT("AT_KEYEXCHANGE"), AT_KEYEXCHANGE},
  211. { TEXT("AT_SIGNATURE"), AT_SIGNATURE},
  212. { TEXT("CALG_MD2"), CALG_MD2},
  213. { TEXT("CALG_MD4"), CALG_MD4},
  214. { TEXT("CALG_MD5"), CALG_MD5},
  215. { TEXT("CALG_SHA"), CALG_SHA},
  216. { TEXT("CALG_SHA1"), CALG_SHA1},
  217. { TEXT("CALG_MAC"), CALG_MAC},
  218. { TEXT("CALG_RSA_SIGN"), CALG_RSA_SIGN},
  219. { TEXT("CALG_DSS_SIGN"), CALG_DSS_SIGN},
  220. { TEXT("CALG_RSA_KEYX"), CALG_RSA_KEYX},
  221. { TEXT("CALG_DES"), CALG_DES},
  222. { TEXT("CALG_3DES_112"), CALG_3DES_112},
  223. { TEXT("CALG_3DES"), CALG_3DES},
  224. { TEXT("CALG_DESX"), CALG_DESX},
  225. { TEXT("CALG_RC2"), CALG_RC2},
  226. { TEXT("CALG_RC4"), CALG_RC4},
  227. { TEXT("CALG_SEAL"), CALG_SEAL},
  228. { TEXT("CALG_DH_SF"), CALG_DH_SF},
  229. { TEXT("CALG_DH_EPHEM"), CALG_DH_EPHEM},
  230. { TEXT("CALG_AGREEDKEY_ANY"), CALG_AGREEDKEY_ANY},
  231. { TEXT("CALG_KEA_KEYX"), CALG_KEA_KEYX},
  232. { TEXT("CALG_HUGHES_MD5"), CALG_HUGHES_MD5},
  233. { TEXT("CALG_SKIPJACK"), CALG_SKIPJACK},
  234. { TEXT("CALG_TEK"), CALG_TEK},
  235. { TEXT("CALG_CYLINK_MEK"), CALG_CYLINK_MEK},
  236. { TEXT("CALG_SSL3_SHAMD5"), CALG_SSL3_SHAMD5},
  237. { TEXT("CALG_SSL3_MASTER"), CALG_SSL3_MASTER},
  238. { TEXT("CALG_SCHANNEL_MASTER_HASH"), CALG_SCHANNEL_MASTER_HASH},
  239. { TEXT("CALG_SCHANNEL_MAC_KEY"), CALG_SCHANNEL_MAC_KEY},
  240. { TEXT("CALG_SCHANNEL_ENC_KEY"), CALG_SCHANNEL_ENC_KEY},
  241. { TEXT("CALG_PCT1_MASTER"), CALG_PCT1_MASTER},
  242. { TEXT("CALG_SSL2_MASTER"), CALG_SSL2_MASTER},
  243. { TEXT("CALG_TLS1_MASTER"), CALG_TLS1_MASTER},
  244. { TEXT("CALG_RC5"), CALG_RC5},
  245. { TEXT("CALG_HMAC"), CALG_HMAC},
  246. { TEXT("CALG_TLS1PRF"), CALG_TLS1PRF},
  247. { TEXT("MD5"), CALG_MD5},
  248. { TEXT("SHA"), CALG_SHA1},
  249. { NULL, 0} };
  250. static const ValueMap vmClassTypes[]
  251. = {
  252. { TEXT("ALG_CLASS_ANY"), ALG_CLASS_ANY},
  253. { TEXT("ALG_CLASS_SIGNATURE"), ALG_CLASS_SIGNATURE},
  254. { TEXT("ALG_CLASS_MSG_ENCRYPT"), ALG_CLASS_MSG_ENCRYPT},
  255. { TEXT("ALG_CLASS_DATA_ENCRYPT"), ALG_CLASS_DATA_ENCRYPT},
  256. { TEXT("ALG_CLASS_HASH"), ALG_CLASS_HASH},
  257. { TEXT("ALG_CLASS_KEY_EXCHANGE"), ALG_CLASS_KEY_EXCHANGE},
  258. { TEXT("ALG_CLASS_ALL"), ALG_CLASS_ALL},
  259. { NULL, 0} };
  260. static const ValueMap vmHashDataFlags[]
  261. = {
  262. { TEXT("CRYPT_USERDATA"), CRYPT_USERDATA},
  263. { NULL, 0} };
  264. static const ValueMap vmSignVerifyFlags[]
  265. = {
  266. { TEXT("CRYPT_NOHASHOID"), CRYPT_NOHASHOID},
  267. { NULL, 0} };
  268. static const ValueMap vmBlobTypes[]
  269. = {
  270. { TEXT("SIMPLEBLOB"), SIMPLEBLOB},
  271. { TEXT("PUBLICKEYBLOB"), PUBLICKEYBLOB},
  272. { TEXT("PRIVATEKEYBLOB"), PRIVATEKEYBLOB},
  273. { TEXT("PLAINTEXTKEYBLOB"), PLAINTEXTKEYBLOB},
  274. { TEXT("OPAQUEKEYBLOB"), OPAQUEKEYBLOB},
  275. { NULL, 0} };
  276. static const ValueMap vmEmptyFlags[]
  277. = { { NULL, 0} };
  278. static void
  279. ExtractHandle(
  280. CTclCommand &tclCmd,
  281. LONG *phHandle,
  282. HandleType *pnHandleType,
  283. BOOL fMandatory = FALSE);
  284. static void
  285. ReturnHandle(
  286. CTclCommand &tclCmd,
  287. LONG_PTR hHandle,
  288. HandleType nHandleType);
  289. static BOOL WINAPI
  290. MyEnumProviders(
  291. DWORD dwIndex, // in
  292. DWORD *pdwReserved, // in
  293. DWORD dwFlags, // in
  294. DWORD *pdwProvType, // out
  295. LPTSTR pszProvName, // out
  296. DWORD *pcbProvName); // in/out
  297. /*++
  298. Tclsc_cryptCmd:
  299. This routine provides an access point to the various CryptoAPI
  300. object methods.
  301. Arguments:
  302. Per Tcl standard commands.
  303. Return Value:
  304. Per Tcl standard commands.
  305. Author:
  306. Doug Barlow (dbarlow) 03/13/1998
  307. --*/
  308. int
  309. Tclsc_cryptCmd(
  310. ClientData clientData,
  311. Tcl_Interp *interp,
  312. int argc,
  313. char *argv[])
  314. {
  315. CTclCommand tclCmd(interp, argc, argv);
  316. int nTclStatus = TCL_OK;
  317. try
  318. {
  319. LONG hHandle;
  320. HandleType nHandleType;
  321. ExtractHandle(tclCmd, &hHandle, &nHandleType);
  322. switch (tclCmd.Keyword(
  323. TEXT("LIST"), TEXT("ACQUIRE"), TEXT("RELEASE"),
  324. TEXT("PARAMETER"), TEXT("GET"), TEXT("CREATE"),
  325. TEXT("HASH"), TEXT("SIGNHASH"), TEXT("VERIFYSIGNATURE"),
  326. TEXT("ENCRYPT"), TEXT("DECRYPT"), TEXT("IMPORT"),
  327. TEXT("EXPORT"), TEXT("RSA"),
  328. NULL))
  329. {
  330. //
  331. // ==================================================================
  332. //
  333. // crypt [<handle>] list
  334. // providers \
  335. // [type <provType>]
  336. // containers
  337. // algorithms \
  338. // [class <classId>] \
  339. // [extended]
  340. //
  341. case 1:
  342. {
  343. BOOL fSts;
  344. DWORD dwIndex;
  345. switch (tclCmd.Keyword(
  346. TEXT("PROVIDERS"), TEXT("CONTAINERS"), TEXT("KEYSETS"),
  347. TEXT("ALGORITHMS"),
  348. NULL))
  349. {
  350. //
  351. // List all the providers known to the system
  352. //
  353. case 1: // providers [type <n>];
  354. {
  355. CString szProvider;
  356. DWORD dwProvType, dwTargetType = 0;
  357. DWORD dwLength;
  358. DWORD dwSts;
  359. while (tclCmd.IsMoreArguments())
  360. {
  361. switch (tclCmd.Keyword(
  362. TEXT("TYPE"),
  363. NULL))
  364. {
  365. case 1: // Type
  366. dwTargetType = (DWORD)tclCmd.MapValue(vmProviderTypes);
  367. break;
  368. default:
  369. throw tclCmd.BadSyntax();
  370. }
  371. }
  372. tclCmd.NoMoreArguments();
  373. dwIndex = 0;
  374. do
  375. {
  376. dwLength = 0;
  377. fSts = MyEnumProviders(
  378. dwIndex,
  379. NULL,
  380. 0,
  381. &dwProvType,
  382. NULL,
  383. &dwLength);
  384. if (fSts)
  385. {
  386. fSts = MyEnumProviders(
  387. dwIndex,
  388. NULL,
  389. 0,
  390. &dwProvType,
  391. szProvider.GetBuffer(dwLength / sizeof(TCHAR)),
  392. &dwLength);
  393. dwSts = GetLastError();
  394. szProvider.ReleaseBuffer();
  395. if (!fSts)
  396. {
  397. tclCmd.SetError(
  398. TEXT("Can't obtain provider name: "),
  399. dwSts);
  400. throw dwSts;
  401. }
  402. if ((0 == dwTargetType) || (dwTargetType == dwProvType))
  403. Tcl_AppendElement(tclCmd, SZ(szProvider));
  404. }
  405. else
  406. {
  407. dwSts = GetLastError();
  408. if (ERROR_NO_MORE_ITEMS != dwSts)
  409. {
  410. tclCmd.SetError(
  411. TEXT("Can't obtain provider name length: "),
  412. dwSts);
  413. throw dwSts;
  414. }
  415. }
  416. dwIndex += 1;
  417. } while (fSts);
  418. break;
  419. }
  420. //
  421. // List Containers in this provider.
  422. //
  423. case 2: // CONTAINERS
  424. case 3: // KEYSETS
  425. {
  426. CBuffer bfKeyset;
  427. DWORD dwLength = 0;
  428. BOOL fDone = FALSE;
  429. DWORD dwFlags = CRYPT_FIRST;
  430. fSts = CryptGetProvParam(
  431. hHandle,
  432. PP_ENUMCONTAINERS,
  433. NULL,
  434. &dwLength,
  435. CRYPT_FIRST);
  436. if (!fSts)
  437. {
  438. DWORD dwSts = GetLastError();
  439. switch (dwSts)
  440. {
  441. case NTE_BAD_LEN:
  442. ASSERT(ERROR_MORE_DATA == dwSts);
  443. // fall through intentionally
  444. case ERROR_MORE_DATA:
  445. break;
  446. case ERROR_NO_MORE_ITEMS:
  447. fDone = TRUE;
  448. dwLength = 0;
  449. break;
  450. default:
  451. tclCmd.SetError(
  452. TEXT("Can't determine container buffer space requirements: "),
  453. dwSts);
  454. throw (DWORD)TCL_ERROR;
  455. }
  456. }
  457. bfKeyset.Presize(dwLength);
  458. while (!fDone)
  459. {
  460. dwLength = bfKeyset.Space();
  461. fSts = CryptGetProvParam(
  462. hHandle,
  463. PP_ENUMCONTAINERS,
  464. bfKeyset.Access(),
  465. &dwLength,
  466. dwFlags);
  467. if (!fSts)
  468. {
  469. DWORD dwSts = GetLastError();
  470. switch (dwSts)
  471. {
  472. case NTE_BAD_LEN:
  473. ASSERT(ERROR_MORE_DATA == dwSts);
  474. // fall through intentionally
  475. case ERROR_MORE_DATA:
  476. bfKeyset.Resize(dwLength);
  477. break;
  478. case ERROR_NO_MORE_ITEMS:
  479. fDone = TRUE;
  480. break;
  481. default:
  482. tclCmd.SetError(
  483. TEXT("Can't obtain container name: "),
  484. dwSts);
  485. throw (DWORD)TCL_ERROR;
  486. }
  487. }
  488. else
  489. {
  490. bfKeyset.Resize(dwLength, TRUE);
  491. Tcl_AppendElement(tclCmd, (LPSTR)bfKeyset.Access());
  492. dwFlags = 0;
  493. }
  494. }
  495. break;
  496. }
  497. //
  498. // List algorithms supported by this provider.
  499. //
  500. case 4: // ALGORITHMS
  501. {
  502. CBuffer bfAlgId;
  503. DWORD dwLength = 0;
  504. BOOL fDone = FALSE;
  505. DWORD dwFlags = CRYPT_FIRST;
  506. DWORD dwClassType = ALG_CLASS_ANY;
  507. DWORD dwParam = PP_ENUMALGS;
  508. while (tclCmd.IsMoreArguments())
  509. {
  510. switch (tclCmd.Keyword(
  511. TEXT("CLASS"), TEXT("EXTENDED"),
  512. NULL))
  513. {
  514. case 1: // Type
  515. dwClassType = (DWORD)tclCmd.MapValue(vmClassTypes);
  516. break;
  517. case 2: // extended
  518. dwParam = PP_ENUMALGS_EX;
  519. break;
  520. default:
  521. throw tclCmd.BadSyntax();
  522. }
  523. }
  524. fSts = CryptGetProvParam(
  525. hHandle,
  526. dwParam,
  527. NULL,
  528. &dwLength,
  529. CRYPT_FIRST);
  530. if (!fSts)
  531. {
  532. DWORD dwSts = GetLastError();
  533. switch (dwSts)
  534. {
  535. case NTE_BAD_LEN:
  536. ASSERT(ERROR_MORE_DATA == dwSts);
  537. dwSts = ERROR_MORE_DATA;
  538. // fall through intentionally
  539. case ERROR_MORE_DATA:
  540. break;
  541. default:
  542. tclCmd.SetError(
  543. TEXT("Can't determine algorithm buffer space requirements: "),
  544. dwSts);
  545. throw (DWORD)TCL_ERROR;
  546. }
  547. }
  548. bfAlgId.Presize(dwLength);
  549. while (!fDone)
  550. {
  551. dwLength = bfAlgId.Space();
  552. fSts = CryptGetProvParam(
  553. hHandle,
  554. dwParam,
  555. bfAlgId.Access(),
  556. &dwLength,
  557. dwFlags);
  558. if (!fSts)
  559. {
  560. DWORD dwSts = GetLastError();
  561. switch (dwSts)
  562. {
  563. case NTE_BAD_LEN:
  564. ASSERT(ERROR_MORE_DATA == dwSts);
  565. // fall through intentionally
  566. case ERROR_MORE_DATA:
  567. bfAlgId.Resize(dwLength);
  568. break;
  569. case ERROR_NO_MORE_ITEMS:
  570. fDone = TRUE;
  571. break;
  572. default:
  573. tclCmd.SetError(
  574. TEXT("Can't obtain algorithm: "),
  575. dwSts);
  576. throw (DWORD)TCL_ERROR;
  577. }
  578. }
  579. else
  580. {
  581. if (PP_ENUMALGS == dwParam)
  582. {
  583. PROV_ENUMALGS *palgEnum
  584. = (PROV_ENUMALGS *)bfAlgId.Access();
  585. ASSERT(sizeof(PROV_ENUMALGS) == dwLength);
  586. if ((ALG_CLASS_ANY == dwClassType)
  587. || (GET_ALG_CLASS(palgEnum->aiAlgid) == dwClassType))
  588. {
  589. Tcl_AppendElement(
  590. tclCmd,
  591. palgEnum->szName);
  592. }
  593. }
  594. else
  595. {
  596. PROV_ENUMALGS_EX *palgEnum
  597. = (PROV_ENUMALGS_EX *)bfAlgId.Access();
  598. ASSERT(sizeof(PROV_ENUMALGS_EX) == dwLength);
  599. if ((ALG_CLASS_ANY == dwClassType)
  600. || (GET_ALG_CLASS(palgEnum->aiAlgid) == dwClassType))
  601. {
  602. Tcl_AppendElement(
  603. tclCmd,
  604. palgEnum->szLongName);
  605. }
  606. }
  607. dwFlags = 0;
  608. }
  609. }
  610. break;
  611. }
  612. default:
  613. throw tclCmd.BadSyntax();
  614. }
  615. break;
  616. }
  617. //
  618. // ==================================================================
  619. //
  620. // crypt acquire \
  621. // [provider <providerName>] \
  622. // [type <provType>] \
  623. // [container <containerName>] \
  624. // [verifycontext] [newkeyset] [deletekeyset] [machine] [silent] \
  625. // [flags {<acquireFlag> [<acquireFlag> [...]]]}
  626. //
  627. case 2:
  628. {
  629. DWORD dwFlags = 0;
  630. BOOL fProvValid = FALSE;
  631. BOOL fContValid = FALSE;
  632. BOOL fSts;
  633. CString szProvider;
  634. CString szContainer;
  635. DWORD dwProvType = 0;
  636. HCRYPTPROV hProv;
  637. while (tclCmd.IsMoreArguments())
  638. {
  639. switch (tclCmd.Keyword(
  640. TEXT("PROVIDER"), TEXT("TYPE"),
  641. TEXT("CONTAINER"), TEXT("KEYSET"),
  642. TEXT("VERIFYCONTEXT"), TEXT("NEWKEYSET"),
  643. TEXT("DELETEKEYSET"), TEXT("MACHINE"),
  644. TEXT("SILENT"), TEXT("FLAGS"),
  645. NULL))
  646. {
  647. case 1: // PROVIDER
  648. if (fProvValid)
  649. throw tclCmd.BadSyntax();
  650. tclCmd.NextArgument(szProvider);
  651. fProvValid = TRUE;
  652. break;
  653. case 2: // TYPE
  654. if (0 != dwProvType)
  655. throw tclCmd.BadSyntax();
  656. dwProvType = tclCmd.MapValue(vmProviderTypes);
  657. break;
  658. case 3: // CONTAINER
  659. case 4: // KEYSET
  660. if (fContValid)
  661. throw tclCmd.BadSyntax();
  662. tclCmd.NextArgument(szContainer);
  663. fContValid = TRUE;
  664. break;
  665. case 5: // VERIFYCONTEXT
  666. dwFlags |= CRYPT_VERIFYCONTEXT;
  667. break;
  668. case 6: // NEWKEYSET
  669. dwFlags |= CRYPT_NEWKEYSET;
  670. break;
  671. case 7: // DELETEKEYSET
  672. dwFlags |= CRYPT_DELETEKEYSET;
  673. break;
  674. case 8: // MACHINE
  675. dwFlags |= CRYPT_MACHINE_KEYSET;
  676. break;
  677. case 9: // SILENT
  678. dwFlags |= CRYPT_SILENT;
  679. break;
  680. case 10: // FLAGS
  681. dwFlags |= tclCmd.MapFlags(vmAcquireFlags);
  682. break;
  683. default:
  684. throw tclCmd.BadSyntax();
  685. }
  686. }
  687. fSts = CryptAcquireContext(
  688. &hProv,
  689. fContValid ? (LPCTSTR)szContainer : (LPCTSTR)NULL,
  690. fProvValid ? (LPCTSTR)szProvider : (LPCTSTR)MS_DEF_PROV,
  691. 0 != dwProvType ? dwProvType : PROV_RSA_FULL,
  692. dwFlags);
  693. if (!fSts)
  694. {
  695. tclCmd.SetError(
  696. TEXT("Can't acquire context: "),
  697. GetLastError());
  698. throw (DWORD)TCL_ERROR;
  699. }
  700. ReturnHandle(tclCmd, hProv, Provider);
  701. break;
  702. }
  703. //
  704. // ==================================================================
  705. //
  706. // crypt <handle> release
  707. // [flags {<emptyFlags> [<emptyFlags> [...]]}]
  708. //
  709. case 3:
  710. {
  711. DWORD dwFlags = 0;
  712. BOOL fSts;
  713. switch (nHandleType)
  714. {
  715. case Provider:
  716. while (tclCmd.IsMoreArguments())
  717. {
  718. switch (tclCmd.Keyword(
  719. TEXT("FLAGS"),
  720. NULL))
  721. {
  722. case 1: // FLAGS
  723. dwFlags |= tclCmd.MapFlags(vmEmptyFlags);
  724. break;
  725. default:
  726. throw tclCmd.BadSyntax();
  727. }
  728. }
  729. fSts = CryptReleaseContext(
  730. hHandle,
  731. dwFlags);
  732. if (!fSts)
  733. {
  734. tclCmd.SetError(
  735. TEXT("Can't release context: "),
  736. GetLastError());
  737. throw (DWORD)TCL_ERROR;
  738. }
  739. break;
  740. case Key:
  741. tclCmd.NoMoreArguments();
  742. fSts = CryptDestroyKey(hHandle);
  743. if (!fSts)
  744. {
  745. tclCmd.SetError(
  746. TEXT("Can't release key: "),
  747. ErrorString(GetLastError()),
  748. NULL);
  749. throw (DWORD)TCL_ERROR;
  750. }
  751. break;
  752. case Hash:
  753. tclCmd.NoMoreArguments();
  754. fSts = CryptDestroyHash(hHandle);
  755. if (!fSts)
  756. {
  757. tclCmd.SetError(
  758. TEXT("Can't release hash: "),
  759. GetLastError());
  760. throw (DWORD)TCL_ERROR;
  761. }
  762. break;
  763. default:
  764. throw tclCmd.BadSyntax();
  765. }
  766. break;
  767. }
  768. //
  769. // ==================================================================
  770. //
  771. // crypt <handle> parameter <paramId> \
  772. // [output { text | hex | file <fileName> }] \
  773. // [flags {<acquireFlag> [<acquireFlag> [...]]}] \
  774. // [input { text | hex | file }] [value]
  775. //
  776. case 4:
  777. {
  778. DWORD dwFlags = 0;
  779. BOOL fSts;
  780. BOOL fForceRetry;
  781. BOOL fSetValue = FALSE;
  782. CBuffer bfValue;
  783. DWORD dwLength, dwSts;
  784. CBuffer bfData;
  785. DWORD dwParamId = 0;
  786. CRenderableData inData, outData;
  787. switch (nHandleType)
  788. {
  789. case Provider:
  790. dwParamId = tclCmd.MapValue(vmGetProvParams);
  791. break;
  792. case Key:
  793. dwParamId = tclCmd.MapValue(vmKeyParams);
  794. break;
  795. case Hash:
  796. dwParamId = tclCmd.MapValue(vmHashParams);
  797. break;
  798. default:
  799. throw tclCmd.BadSyntax();
  800. }
  801. tclCmd.OutputStyle(outData);
  802. while (tclCmd.IsMoreArguments())
  803. {
  804. switch (tclCmd.Keyword(
  805. TEXT("FLAGS"),
  806. NULL))
  807. {
  808. case 1: // FLAGS
  809. dwFlags |= tclCmd.MapFlags(vmGetFlags);
  810. break;
  811. default: // Value to set
  812. if (fSetValue)
  813. throw tclCmd.BadSyntax();
  814. tclCmd.InputStyle(inData);
  815. tclCmd.ReadData(inData);
  816. fSetValue = TRUE;
  817. }
  818. }
  819. //
  820. // If a value is supplied, set the parmeter to that value.
  821. // Otherwise, just return the current value of the parameter.
  822. //
  823. if (fSetValue)
  824. {
  825. switch (nHandleType)
  826. {
  827. case Provider:
  828. fSts = CryptSetProvParam(
  829. hHandle,
  830. dwParamId,
  831. (LPBYTE)inData.Value(),
  832. dwFlags);
  833. break;
  834. case Key:
  835. fSts = CryptSetKeyParam(
  836. hHandle,
  837. dwParamId,
  838. (LPBYTE)inData.Value(),
  839. dwFlags);
  840. break;
  841. case Hash:
  842. fSts = CryptSetHashParam(
  843. hHandle,
  844. dwParamId,
  845. (LPBYTE)inData.Value(),
  846. dwFlags);
  847. break;
  848. default:
  849. throw (DWORD)SCARD_F_INTERNAL_ERROR;
  850. }
  851. if (!fSts)
  852. {
  853. dwSts = GetLastError();
  854. tclCmd.SetError(
  855. TEXT("Can't set parameter: "),
  856. dwSts);
  857. throw dwSts;
  858. }
  859. }
  860. else
  861. {
  862. do
  863. {
  864. dwLength = bfData.Space();
  865. fForceRetry = (0 == dwLength);
  866. switch (nHandleType)
  867. {
  868. case Provider:
  869. fSts = CryptGetProvParam(
  870. hHandle,
  871. dwParamId,
  872. bfData.Access(),
  873. &dwLength,
  874. dwFlags);
  875. break;
  876. case Key:
  877. fSts = CryptGetKeyParam(
  878. hHandle,
  879. dwParamId,
  880. bfData.Access(),
  881. &dwLength,
  882. dwFlags);
  883. break;
  884. case Hash:
  885. fSts = CryptGetHashParam(
  886. hHandle,
  887. dwParamId,
  888. bfData.Access(),
  889. &dwLength,
  890. dwFlags);
  891. break;
  892. default:
  893. throw (DWORD)SCARD_F_INTERNAL_ERROR;
  894. }
  895. if (!fSts)
  896. {
  897. dwSts = GetLastError();
  898. if (NTE_BAD_LEN == dwSts)
  899. {
  900. ASSERT(ERROR_MORE_DATA == dwSts);
  901. dwSts = ERROR_MORE_DATA;
  902. }
  903. }
  904. else
  905. {
  906. if (fForceRetry)
  907. dwSts = ERROR_MORE_DATA;
  908. else
  909. {
  910. ASSERT(bfData.Space() >= dwLength);
  911. dwSts = ERROR_SUCCESS;
  912. }
  913. }
  914. bfData.Resize(dwLength, fSts);
  915. } while (ERROR_MORE_DATA == dwSts);
  916. if (ERROR_SUCCESS != dwSts)
  917. {
  918. tclCmd.SetError(TEXT("Can't get parameter: "), dwSts);
  919. throw (DWORD)TCL_ERROR;
  920. }
  921. outData.LoadData(bfData.Access(), bfData.Length());
  922. tclCmd.Render(outData);
  923. }
  924. break;
  925. }
  926. //
  927. // ==================================================================
  928. //
  929. // crypt <handle> get \
  930. // key <keyId>
  931. // random <length> \
  932. // [output { text | hex | file <fileName> }]
  933. //
  934. case 5:
  935. {
  936. switch (tclCmd.Keyword(
  937. TEXT("KEY"), TEXT("RANDOM"),
  938. NULL))
  939. {
  940. case 1: // key <keyId>
  941. {
  942. BOOL fSts;
  943. HCRYPTKEY hKey = NULL;
  944. DWORD dwKeyId;
  945. dwKeyId = (DWORD)tclCmd.MapValue(vmKeyTypes);
  946. fSts = CryptGetUserKey(hHandle, dwKeyId, &hKey);
  947. if (!fSts)
  948. {
  949. DWORD dwSts = GetLastError();
  950. tclCmd.SetError(
  951. TEXT("Can't get user key: "),
  952. dwSts);
  953. throw dwSts;
  954. }
  955. ReturnHandle(tclCmd, hKey, Key);
  956. break;
  957. }
  958. case 2: // random length <length>
  959. {
  960. DWORD dwLength = 0;
  961. CBuffer bfData;
  962. BOOL fSts;
  963. BOOL fGotFormat = FALSE;
  964. CRenderableData outData;
  965. tclCmd.OutputStyle(outData);
  966. while (tclCmd.IsMoreArguments())
  967. {
  968. switch (tclCmd.Keyword(
  969. TEXT("LENGTH"),
  970. NULL))
  971. {
  972. case 1: // length
  973. dwLength = tclCmd.Value();
  974. break;
  975. default: // Value to set
  976. if (fGotFormat)
  977. throw tclCmd.BadSyntax();
  978. tclCmd.OutputStyle(outData);
  979. fGotFormat = TRUE;
  980. }
  981. }
  982. bfData.Resize(dwLength);
  983. fSts = CryptGenRandom(
  984. hHandle,
  985. dwLength,
  986. bfData.Access());
  987. if (!fSts)
  988. {
  989. DWORD dwSts = GetLastError();
  990. tclCmd.SetError(
  991. TEXT("Can't generate random data: "),
  992. dwSts);
  993. throw dwSts;
  994. }
  995. outData.LoadData(bfData.Access(), bfData.Length());
  996. tclCmd.Render(outData);
  997. break;
  998. }
  999. default:
  1000. throw tclCmd.BadSyntax();
  1001. }
  1002. break;
  1003. }
  1004. //
  1005. // ==================================================================
  1006. //
  1007. // crypt <handle> create
  1008. // hash \
  1009. // algorithm <algId> \
  1010. // [flags {<emptyFlag> [<emptyFlag> [...]]}]
  1011. // key \
  1012. // algorithm <algId>
  1013. // type <keytype>
  1014. // [hash <hHash>] \
  1015. // [flags {<emptyFlag> [<emptyFlag> [...]]}]
  1016. //
  1017. case 6:
  1018. {
  1019. switch (tclCmd.Keyword(
  1020. TEXT("HASH"), TEXT("KEY"),
  1021. NULL))
  1022. {
  1023. case 1: // hash
  1024. {
  1025. HCRYPTHASH hHash = NULL;
  1026. HCRYPTKEY hKey = NULL;
  1027. ALG_ID algId = 0;
  1028. DWORD dwFlags = 0;
  1029. BOOL fSts;
  1030. HandleType nHandleType;
  1031. while (tclCmd.IsMoreArguments())
  1032. {
  1033. switch (tclCmd.Keyword(
  1034. TEXT("ALGORITHM"), TEXT("FLAGS"), TEXT("KEY"),
  1035. NULL))
  1036. {
  1037. case 1: // algorithm
  1038. algId = tclCmd.MapValue(vmAlgIds);
  1039. break;
  1040. case 2: // key
  1041. ExtractHandle(
  1042. tclCmd,
  1043. (LPLONG)&hKey,
  1044. &nHandleType,
  1045. TRUE);
  1046. if (Key != nHandleType)
  1047. {
  1048. tclCmd.SetError(TEXT("Invalid key handle"), NULL);
  1049. throw (DWORD)TCL_ERROR;
  1050. }
  1051. break;
  1052. case 3: // flags
  1053. dwFlags |= tclCmd.MapFlags(vmEmptyFlags);
  1054. break;
  1055. default:
  1056. throw tclCmd.BadSyntax();
  1057. }
  1058. }
  1059. fSts = CryptCreateHash(
  1060. hHandle,
  1061. algId,
  1062. hKey,
  1063. dwFlags,
  1064. &hHash);
  1065. if (!fSts)
  1066. {
  1067. DWORD dwSts = GetLastError();
  1068. tclCmd.SetError(
  1069. TEXT("Can't create hash: "),
  1070. dwSts);
  1071. throw dwSts;
  1072. }
  1073. ReturnHandle(tclCmd, hHash, Hash);
  1074. break;
  1075. }
  1076. case 2: // key
  1077. {
  1078. ALG_ID algId = 0;
  1079. DWORD dwFlags = 0;
  1080. BOOL fSts;
  1081. HCRYPTKEY hKey = NULL;
  1082. HCRYPTHASH hHash = NULL;
  1083. HandleType nHandleType;
  1084. while (tclCmd.IsMoreArguments())
  1085. {
  1086. switch (tclCmd.Keyword(
  1087. TEXT("ALGORITHM"), TEXT("TYPE"),
  1088. TEXT("HASH"), TEXT("FLAGS"),
  1089. TEXT("KEY"),
  1090. NULL))
  1091. {
  1092. case 1: // algorithm
  1093. algId = tclCmd.MapValue(vmAlgIds);
  1094. break;
  1095. case 2: // type
  1096. algId = tclCmd.MapValue(vmKeyTypes);
  1097. break;
  1098. case 3: // hash
  1099. ExtractHandle(
  1100. tclCmd,
  1101. (LPLONG)&hHash,
  1102. &nHandleType,
  1103. TRUE);
  1104. if (Hash != nHandleType)
  1105. {
  1106. tclCmd.SetError(TEXT("Invalid hash handle"), NULL);
  1107. throw (DWORD)TCL_ERROR;
  1108. }
  1109. break;
  1110. case 4: // flags
  1111. dwFlags |= tclCmd.MapFlags(vmKeyFlags);
  1112. break;
  1113. case 5: // key
  1114. ExtractHandle(
  1115. tclCmd,
  1116. (LPLONG)&hKey,
  1117. &nHandleType,
  1118. TRUE);
  1119. if (Key != nHandleType)
  1120. {
  1121. tclCmd.SetError(TEXT("Invalid key handle"), NULL);
  1122. throw (DWORD)TCL_ERROR;
  1123. }
  1124. break;
  1125. default:
  1126. throw tclCmd.BadSyntax();
  1127. }
  1128. }
  1129. if (NULL != hHash)
  1130. {
  1131. fSts = CryptDeriveKey(
  1132. hHandle,
  1133. algId,
  1134. hHash,
  1135. dwFlags,
  1136. &hKey);
  1137. }
  1138. else
  1139. {
  1140. fSts = CryptGenKey(
  1141. hHandle,
  1142. algId,
  1143. dwFlags,
  1144. &hKey);
  1145. }
  1146. if (!fSts)
  1147. {
  1148. DWORD dwSts = GetLastError();
  1149. tclCmd.SetError(
  1150. TEXT("Can't create key: "),
  1151. dwSts);
  1152. throw dwSts;
  1153. }
  1154. ReturnHandle(tclCmd, hKey, Key);
  1155. break;
  1156. }
  1157. default:
  1158. throw tclCmd.BadSyntax();
  1159. }
  1160. break;
  1161. }
  1162. //
  1163. // ==================================================================
  1164. //
  1165. // crypt <handle> hash \
  1166. // [flags {<hashFlag> [<hashFlag> [...]]}] \
  1167. // [key <keyId>]
  1168. // [data [-input { text | hex | file }] value]
  1169. //
  1170. case 7:
  1171. {
  1172. CRenderableData inData;
  1173. BOOL fSts, fGotData = FALSE;
  1174. DWORD dwFlags = 0;
  1175. HCRYPTKEY hKey = NULL;
  1176. HandleType nHandleType;
  1177. while (tclCmd.IsMoreArguments())
  1178. {
  1179. switch (tclCmd.Keyword(
  1180. TEXT("FLAGS"), TEXT("KEY"), TEXT("DATA"),
  1181. NULL))
  1182. {
  1183. case 1: // FLAGS
  1184. dwFlags |= tclCmd.MapFlags(vmHashDataFlags);
  1185. break;
  1186. case 2: // Key
  1187. if (fGotData || NULL != hKey)
  1188. throw tclCmd.BadSyntax();
  1189. ExtractHandle(
  1190. tclCmd,
  1191. (LPLONG)&hKey,
  1192. &nHandleType,
  1193. TRUE);
  1194. if (Key != nHandleType)
  1195. {
  1196. tclCmd.SetError(TEXT("Invalid key handle"), NULL);
  1197. throw (DWORD)TCL_ERROR;
  1198. }
  1199. break;
  1200. case 3: // data
  1201. {
  1202. if (fGotData || NULL != hKey)
  1203. throw tclCmd.BadSyntax();
  1204. tclCmd.InputStyle(inData);
  1205. tclCmd.ReadData(inData);
  1206. fGotData = TRUE;
  1207. break;
  1208. }
  1209. default:
  1210. throw tclCmd.BadSyntax();
  1211. }
  1212. }
  1213. if (fGotData)
  1214. {
  1215. fSts = CryptHashData(
  1216. hHandle,
  1217. inData.Value(),
  1218. inData.Length(),
  1219. dwFlags);
  1220. if (!fSts)
  1221. {
  1222. DWORD dwSts = GetLastError();
  1223. tclCmd.SetError(
  1224. TEXT("Can't hash data: "),
  1225. dwSts);
  1226. throw dwSts;
  1227. }
  1228. }
  1229. else if (NULL != hKey)
  1230. {
  1231. fSts = CryptHashSessionKey(
  1232. hHandle,
  1233. hKey,
  1234. dwFlags);
  1235. if (!fSts)
  1236. {
  1237. DWORD dwSts = GetLastError();
  1238. tclCmd.SetError(
  1239. TEXT("Can't hash session key: "),
  1240. dwSts);
  1241. throw dwSts;
  1242. }
  1243. }
  1244. else
  1245. throw tclCmd.BadSyntax();
  1246. break;
  1247. }
  1248. //
  1249. // ==================================================================
  1250. //
  1251. // crypt <handle> signhash \
  1252. // [output { text | hex | file <fileName> }] \
  1253. // key <keyId> \
  1254. // [description <desc>] \
  1255. // [flags {<signFlag> [<signFlag> [...]]}] \
  1256. //
  1257. case 8:
  1258. {
  1259. CBuffer bfSignature;
  1260. DWORD dwLength;
  1261. DWORD dwSts;
  1262. BOOL fSts;
  1263. BOOL fForceRetry;
  1264. BOOL fGotDesc = FALSE;
  1265. CString szDescription;
  1266. DWORD dwKeyId = 0;
  1267. DWORD dwFlags = 0;
  1268. CRenderableData outData;
  1269. tclCmd.OutputStyle(outData);
  1270. while (tclCmd.IsMoreArguments())
  1271. {
  1272. switch (tclCmd.Keyword(
  1273. TEXT("FLAGS"), TEXT("DESCRIPTION"), TEXT("KEY"),
  1274. NULL))
  1275. {
  1276. case 1: // FLAGS
  1277. dwFlags |= tclCmd.MapFlags(vmSignVerifyFlags);
  1278. break;
  1279. case 2: // Description
  1280. tclCmd.NextArgument(szDescription);
  1281. fGotDesc = TRUE;
  1282. break;
  1283. case 3: // Key
  1284. dwKeyId = (DWORD)tclCmd.MapValue(vmKeyTypes);
  1285. break;
  1286. default:
  1287. throw tclCmd.BadSyntax();
  1288. }
  1289. }
  1290. do
  1291. {
  1292. dwLength = bfSignature.Space();
  1293. fForceRetry = (0 == dwLength);
  1294. fSts = CryptSignHash(
  1295. hHandle,
  1296. dwKeyId,
  1297. fGotDesc ? (LPCTSTR)szDescription : NULL,
  1298. dwFlags,
  1299. bfSignature.Access(),
  1300. &dwLength);
  1301. if (!fSts)
  1302. {
  1303. dwSts = GetLastError();
  1304. if (NTE_BAD_LEN == dwSts)
  1305. {
  1306. ASSERT(ERROR_MORE_DATA == dwSts);
  1307. dwSts = ERROR_MORE_DATA;
  1308. }
  1309. }
  1310. else
  1311. {
  1312. if (fForceRetry)
  1313. dwSts = ERROR_MORE_DATA;
  1314. else
  1315. {
  1316. ASSERT(bfSignature.Space() >= dwLength);
  1317. dwSts = ERROR_SUCCESS;
  1318. }
  1319. }
  1320. bfSignature.Resize(dwLength, fSts);
  1321. } while (ERROR_MORE_DATA == dwSts);
  1322. if (ERROR_SUCCESS != dwSts)
  1323. {
  1324. tclCmd.SetError(TEXT("Can't sign hash: "), dwSts);
  1325. throw (DWORD)TCL_ERROR;
  1326. }
  1327. outData.LoadData(bfSignature.Access(), bfSignature.Length());
  1328. tclCmd.Render(outData);
  1329. break;
  1330. }
  1331. //
  1332. // ==================================================================
  1333. //
  1334. // crypt <handle> verifysignature \
  1335. // key <hPubKey> \
  1336. // [description <desc>] \
  1337. // [flags {<signFlag> [<signFlag> [...]]}] \
  1338. // [input { text | hex | file }] value
  1339. //
  1340. case 9:
  1341. {
  1342. BOOL fGotDesc = FALSE;
  1343. BOOL fGotValue = FALSE;
  1344. CString szDescription;
  1345. DWORD dwFlags = 0;
  1346. CRenderableData inData;
  1347. HCRYPTKEY hPubKey = 0;
  1348. HandleType nPubKeyType = Undefined;
  1349. BOOL fSts;
  1350. while (tclCmd.IsMoreArguments())
  1351. {
  1352. switch (tclCmd.Keyword(
  1353. TEXT("FLAGS"), TEXT("DESCRIPTION"), TEXT("KEY"),
  1354. NULL))
  1355. {
  1356. case 1: // FLAGS
  1357. dwFlags |= tclCmd.MapFlags(vmSignVerifyFlags);
  1358. break;
  1359. case 2: // Description
  1360. tclCmd.NextArgument(szDescription);
  1361. fGotDesc = TRUE;
  1362. break;
  1363. case 3: // Key
  1364. ExtractHandle(
  1365. tclCmd,
  1366. (LPLONG)&hPubKey,
  1367. &nPubKeyType,
  1368. TRUE);
  1369. if (Key != nPubKeyType)
  1370. {
  1371. tclCmd.SetError(TEXT("Invalid key handle"), NULL);
  1372. throw (DWORD)TCL_ERROR;
  1373. }
  1374. break;
  1375. default:
  1376. if (fGotValue)
  1377. throw tclCmd.BadSyntax();
  1378. tclCmd.InputStyle(inData);
  1379. tclCmd.ReadData(inData);
  1380. fGotValue = TRUE;
  1381. }
  1382. }
  1383. fSts = CryptVerifySignature(
  1384. hHandle,
  1385. inData.Value(),
  1386. inData.Length(),
  1387. hPubKey,
  1388. fGotDesc ? (LPCTSTR)szDescription : NULL,
  1389. dwFlags);
  1390. if (!fSts)
  1391. {
  1392. DWORD dwSts = GetLastError();
  1393. tclCmd.SetError(
  1394. TEXT("Can't verify signature: "),
  1395. dwSts);
  1396. throw dwSts;
  1397. }
  1398. break;
  1399. }
  1400. //
  1401. // ==================================================================
  1402. //
  1403. // crypt <handle> encrypt \
  1404. // [output { text | hex | file <fileName> }] \
  1405. // [hash <hHash>] \
  1406. // [flags {<cryptFlag> [<cryptFlag> [...]]}] \
  1407. // [{more | final}] \
  1408. // [input { text | hex | file }] value
  1409. //
  1410. case 10:
  1411. {
  1412. BOOL fSts;
  1413. BOOL fGotValue = FALSE;
  1414. HCRYPTHASH hHash = NULL;
  1415. HandleType nHashHandle;
  1416. CRenderableData inData, outData;
  1417. CBuffer bfCrypt;
  1418. BOOL fFinal = TRUE;
  1419. DWORD dwFlags = 0;
  1420. DWORD dwLength, dwSts;
  1421. tclCmd.OutputStyle(outData);
  1422. while (tclCmd.IsMoreArguments())
  1423. {
  1424. switch (tclCmd.Keyword(
  1425. TEXT("HASH"), TEXT("MORE"), TEXT("FINAL"),
  1426. NULL))
  1427. {
  1428. case 1: // Hash
  1429. ExtractHandle(
  1430. tclCmd,
  1431. (LPLONG)&hHash,
  1432. &nHashHandle,
  1433. TRUE);
  1434. if (Hash != nHashHandle)
  1435. {
  1436. tclCmd.SetError(TEXT("Invalid hash handle"), NULL);
  1437. throw (DWORD)TCL_ERROR;
  1438. }
  1439. break;
  1440. case 2: // More
  1441. fFinal = FALSE;
  1442. break;
  1443. case 3: // Final
  1444. fFinal = TRUE;
  1445. break;
  1446. case 4: // Flags
  1447. dwFlags |= tclCmd.MapFlags(vmEmptyFlags);
  1448. break;
  1449. default:
  1450. if (fGotValue)
  1451. throw tclCmd.BadSyntax();
  1452. tclCmd.InputStyle(inData);
  1453. tclCmd.ReadData(inData);
  1454. fGotValue = TRUE;
  1455. }
  1456. }
  1457. for (;;)
  1458. {
  1459. dwLength = inData.Length();
  1460. bfCrypt.Set(inData.Value(), dwLength);
  1461. fSts = CryptEncrypt(
  1462. hHandle,
  1463. hHash,
  1464. fFinal,
  1465. dwFlags,
  1466. bfCrypt.Access(),
  1467. &dwLength,
  1468. bfCrypt.Space());
  1469. if (!fSts)
  1470. {
  1471. dwSts = GetLastError();
  1472. switch (dwSts)
  1473. {
  1474. case NTE_BAD_LEN:
  1475. ASSERT(ERROR_MORE_DATA == dwSts);
  1476. // fall through intentionally
  1477. case ERROR_MORE_DATA:
  1478. bfCrypt.Presize(dwLength);
  1479. break;
  1480. default:
  1481. tclCmd.SetError(
  1482. TEXT("Can't encrypt data: "),
  1483. dwSts);
  1484. throw dwSts;
  1485. }
  1486. }
  1487. else
  1488. {
  1489. bfCrypt.Resize(dwLength, TRUE);
  1490. break;
  1491. }
  1492. }
  1493. outData.LoadData(bfCrypt.Access(), bfCrypt.Length());
  1494. tclCmd.Render(outData);
  1495. break;
  1496. }
  1497. //
  1498. // ==================================================================
  1499. //
  1500. // crypt <handle> decrypt \
  1501. // [output { text | hex | file <fileName> }] \
  1502. // [hash <hHash>] \
  1503. // [flags {<cryptFlag> [<cryptFlag> [...]]}] \
  1504. // [{more | final}] \
  1505. // [input { text | hex | file }] value
  1506. //
  1507. case 11:
  1508. {
  1509. BOOL fSts;
  1510. BOOL fGotValue = FALSE;
  1511. HCRYPTHASH hHash = NULL;
  1512. HandleType nHashHandle;
  1513. CRenderableData inData, outData;
  1514. CBuffer bfCrypt;
  1515. BOOL fFinal = TRUE;
  1516. DWORD dwFlags = 0;
  1517. DWORD dwLength, dwSts;
  1518. tclCmd.OutputStyle(outData);
  1519. while (tclCmd.IsMoreArguments())
  1520. {
  1521. switch (tclCmd.Keyword(
  1522. TEXT("HASH"), TEXT("MORE"), TEXT("FINAL"),
  1523. NULL))
  1524. {
  1525. case 1: // Hash
  1526. ExtractHandle(
  1527. tclCmd,
  1528. (LPLONG)&hHash,
  1529. &nHashHandle,
  1530. TRUE);
  1531. if (Hash != nHashHandle)
  1532. {
  1533. tclCmd.SetError(TEXT("Invalid hash handle"), NULL);
  1534. throw (DWORD)TCL_ERROR;
  1535. }
  1536. break;
  1537. case 2: // More
  1538. fFinal = FALSE;
  1539. break;
  1540. case 3: // Final
  1541. fFinal = TRUE;
  1542. break;
  1543. case 4: // Flags
  1544. dwFlags |= tclCmd.MapFlags(vmEmptyFlags);
  1545. break;
  1546. default:
  1547. if (fGotValue)
  1548. throw tclCmd.BadSyntax();
  1549. tclCmd.InputStyle(inData);
  1550. tclCmd.ReadData(inData);
  1551. fGotValue = TRUE;
  1552. }
  1553. }
  1554. dwLength = inData.Length();
  1555. bfCrypt.Set(inData.Value(), dwLength);
  1556. fSts = CryptDecrypt(
  1557. hHandle,
  1558. hHash,
  1559. fFinal,
  1560. dwFlags,
  1561. bfCrypt.Access(),
  1562. &dwLength);
  1563. if (!fSts)
  1564. {
  1565. dwSts = GetLastError();
  1566. switch (dwSts)
  1567. {
  1568. case NTE_BAD_LEN:
  1569. ASSERT(ERROR_MORE_DATA == dwSts);
  1570. // fall through intentionally
  1571. case ERROR_MORE_DATA:
  1572. bfCrypt.Presize(dwLength);
  1573. break;
  1574. default:
  1575. tclCmd.SetError(
  1576. TEXT("Can't encrypt data: "),
  1577. dwSts);
  1578. throw dwSts;
  1579. }
  1580. }
  1581. else
  1582. bfCrypt.Resize(dwLength, TRUE);
  1583. outData.LoadData(bfCrypt.Access(), bfCrypt.Length());
  1584. tclCmd.Render(outData);
  1585. break;
  1586. }
  1587. //
  1588. // ==================================================================
  1589. //
  1590. // crypt <handle> import \
  1591. // [key <hImpKey>] \
  1592. // [flags {<importFlag> [<importFlag> [...]]}] \
  1593. // [input { text | hex | file }] value
  1594. //
  1595. case 12:
  1596. {
  1597. BOOL fSts;
  1598. BOOL fGotValue = FALSE;
  1599. HCRYPTKEY hImpKey = NULL;
  1600. HandleType nHandleType;
  1601. HCRYPTKEY hKey;
  1602. CRenderableData inData;
  1603. DWORD dwFlags = 0;
  1604. while (tclCmd.IsMoreArguments())
  1605. {
  1606. switch (tclCmd.Keyword(
  1607. TEXT("KEY"), TEXT("FLAGS"),
  1608. NULL))
  1609. {
  1610. case 1: // Key
  1611. ExtractHandle(
  1612. tclCmd,
  1613. (LPLONG)&hImpKey,
  1614. &nHandleType,
  1615. TRUE);
  1616. if (Key != nHandleType)
  1617. {
  1618. tclCmd.SetError(TEXT("Invalid key handle"), NULL);
  1619. throw (DWORD)TCL_ERROR;
  1620. }
  1621. break;
  1622. case 2: // Flags
  1623. dwFlags |= tclCmd.MapFlags(vmKeyFlags);
  1624. break;
  1625. default:
  1626. if (fGotValue)
  1627. throw tclCmd.BadSyntax();
  1628. tclCmd.InputStyle(inData);
  1629. tclCmd.ReadData(inData);
  1630. fGotValue = TRUE;
  1631. }
  1632. }
  1633. fSts = CryptImportKey(
  1634. hHandle,
  1635. inData.Value(),
  1636. inData.Length(),
  1637. hImpKey,
  1638. dwFlags,
  1639. &hKey);
  1640. if (!fSts)
  1641. {
  1642. DWORD dwSts = GetLastError();
  1643. tclCmd.SetError(
  1644. TEXT("Can't import key: "),
  1645. dwSts);
  1646. throw dwSts;
  1647. }
  1648. ReturnHandle(tclCmd, hKey, Key);
  1649. break;
  1650. }
  1651. //
  1652. // ==================================================================
  1653. //
  1654. // crypt <handle> export \
  1655. // [output { text | hex | file <fileName> }] \
  1656. // [key <keyId>] \
  1657. // [type <blobType>] \
  1658. // [flags {<exprtFlag> [<exportFlag> [...]]}] \
  1659. //
  1660. case 13:
  1661. {
  1662. BOOL fSts;
  1663. HCRYPTKEY hExpKey = NULL;
  1664. HandleType nHandleType;
  1665. DWORD dwBlobType = 0;
  1666. DWORD dwFlags = 0;
  1667. CBuffer bfBlob;
  1668. DWORD dwLength, dwSts;
  1669. CRenderableData outData;
  1670. tclCmd.OutputStyle(outData);
  1671. while (tclCmd.IsMoreArguments())
  1672. {
  1673. switch (tclCmd.Keyword(
  1674. TEXT("KEY"), TEXT("FLAGS"), TEXT("TYPE"),
  1675. NULL))
  1676. {
  1677. case 1: // Key
  1678. ExtractHandle(
  1679. tclCmd,
  1680. (LPLONG)&hExpKey,
  1681. &nHandleType,
  1682. TRUE);
  1683. if (Key != nHandleType)
  1684. {
  1685. tclCmd.SetError(TEXT("Invalid key handle"), NULL);
  1686. throw (DWORD)TCL_ERROR;
  1687. }
  1688. break;
  1689. case 2: // Flags
  1690. dwFlags |= tclCmd.MapFlags(vmEmptyFlags);
  1691. break;
  1692. case 3: // Type
  1693. dwBlobType = tclCmd.MapValue(vmBlobTypes);
  1694. break;
  1695. default:
  1696. throw tclCmd.BadSyntax();
  1697. }
  1698. }
  1699. for (;;)
  1700. {
  1701. dwLength = bfBlob.Space();
  1702. fSts = CryptExportKey(
  1703. hHandle,
  1704. hExpKey,
  1705. dwBlobType,
  1706. dwFlags,
  1707. bfBlob.Access(),
  1708. &dwLength);
  1709. if (!fSts)
  1710. {
  1711. dwSts = GetLastError();
  1712. switch (dwSts)
  1713. {
  1714. case NTE_BAD_LEN:
  1715. ASSERT(ERROR_MORE_DATA == dwSts);
  1716. // fall through intentionally
  1717. case ERROR_MORE_DATA:
  1718. bfBlob.Presize(dwLength);
  1719. break;
  1720. default:
  1721. tclCmd.SetError(
  1722. TEXT("Can't export key: "),
  1723. dwSts);
  1724. throw dwSts;
  1725. }
  1726. }
  1727. else
  1728. {
  1729. bfBlob.Resize(dwLength, TRUE);
  1730. break;
  1731. }
  1732. }
  1733. outData.LoadData(bfBlob.Access(), bfBlob.Length());
  1734. tclCmd.Render(outData);
  1735. break;
  1736. }
  1737. #if 0
  1738. //
  1739. // ==================================================================
  1740. //
  1741. // crypt <handle> rsa
  1742. // view \
  1743. // [input { text | hex | file }] \
  1744. // [output { text | hex | file <fileName> }] \
  1745. // <value>
  1746. //
  1747. case 14:
  1748. {
  1749. CRenderableData outData;
  1750. tclCmd.OutputStyle(outData);
  1751. while (tclCmd.IsMoreArguments())
  1752. {
  1753. switch (tclCmd.Keyword(
  1754. TEXT("VIEW"),
  1755. NULL))
  1756. {
  1757. case 1: // view
  1758. {
  1759. CBuffer bfBlob;
  1760. CBuffer bfData;
  1761. CBuffer bfModulus;
  1762. CBuffer bfValue;
  1763. CRenderableData inData;
  1764. BOOL fSts;
  1765. DWORD dwLength, dwSts;
  1766. tclCmd.InputStyle(inData);
  1767. tclCmd.ReadData(inData);
  1768. tclCmd.NoMoreArguments();
  1769. //
  1770. // Get the public key
  1771. //
  1772. for (;;)
  1773. {
  1774. dwLength = bfBlob.Space();
  1775. fSts = CryptExportKey(
  1776. hHandle,
  1777. NULL,
  1778. PUBLICKEYBLOB,
  1779. 0,
  1780. bfBlob.Access(),
  1781. &dwLength);
  1782. if (!fSts)
  1783. {
  1784. dwSts = GetLastError();
  1785. switch (dwSts)
  1786. {
  1787. case NTE_BAD_LEN:
  1788. ASSERT(ERROR_MORE_DATA == dwSts);
  1789. // fall through intentionally
  1790. case ERROR_MORE_DATA:
  1791. bfBlob.Presize(dwLength);
  1792. break;
  1793. default:
  1794. tclCmd.SetError(
  1795. TEXT("Can't export RSA public key: "),
  1796. dwSts);
  1797. throw dwSts;
  1798. }
  1799. }
  1800. else
  1801. {
  1802. bfBlob.Resize(dwLength, TRUE);
  1803. break;
  1804. }
  1805. }
  1806. //
  1807. // Calculate the blob fields.
  1808. //
  1809. BLOBHEADER *pBlobHeader = (BLOBHEADER *)bfBlob.Access();
  1810. RSAPUBKEY *pRsaPubKey = (RSAPUBKEY *)bfBlob.Access(sizeof(BLOBHEADER));
  1811. LPDWORD pModulus = (LPDWORD)bfBlob.Access(sizeof(BLOBHEADER) + sizeof(RSAPUBKEY));
  1812. dwLength = pRsaPubKey->bitlen / 8 + sizeof(DWORD) * 3;
  1813. bfModulus.Resize(dwLength);
  1814. bfData.Resize(dwLength);
  1815. bfValue.Resize(dwLength);
  1816. ZeroMemory(bfModulus.Access(), dwLength);
  1817. ZeroMemory(bfData.Access(), dwLength);
  1818. ZeroMemory(bfValue.Access(), dwLength);
  1819. dwLength = pRsaPubKey->bitlen / 8;
  1820. bfModulus.Set((LPCBYTE)pModulus, dwLength);
  1821. bfValue.Set(inData.Value(), inData.Length());
  1822. BenalohModExp(
  1823. (LPDWORD)bfData.Access(),
  1824. (LPDWORD)bfValue.Access(),
  1825. &pRsaPubKey->pubexp,
  1826. (LPDWORD)bfModulus.Access(),
  1827. (dwLength + sizeof(DWORD) - 1 ) / sizeof(DWORD));
  1828. bfData.Resize(dwLength, TRUE);
  1829. outData.LoadData(bfData.Access(), bfData.Length());
  1830. tclCmd.Render(outData);
  1831. break;
  1832. }
  1833. default:
  1834. throw tclCmd.BadSyntax();
  1835. }
  1836. }
  1837. break;
  1838. }
  1839. #endif
  1840. //
  1841. // ==================================================================
  1842. //
  1843. // Not a recognized command. Report an error.
  1844. //
  1845. default:
  1846. throw tclCmd.BadSyntax();
  1847. }
  1848. }
  1849. catch (DWORD)
  1850. {
  1851. nTclStatus = TCL_ERROR;
  1852. }
  1853. return nTclStatus;
  1854. }
  1855. /*++
  1856. ExtractHandle:
  1857. This routine extracts a handle and type from the input stream, if there is
  1858. one to extract.
  1859. Arguments:
  1860. tclCmd supplies the tcl Command processor object.
  1861. phHandle receives the extracted handle value, or zero if none is in the
  1862. stream.
  1863. pnHandleType receives the handle type, or Undefined if none is in the
  1864. stream.
  1865. fMandatory supplies a flag indicating whether or not the key value must
  1866. exist in the input stream. If this value is false, and no handle
  1867. value can be found, then no error is declared, and zeroes are returned.
  1868. Return Value:
  1869. None
  1870. Throws:
  1871. Errors are thrown as DWORD status codes
  1872. Author:
  1873. Doug Barlow (dbarlow) 5/24/1998
  1874. --*/
  1875. static void
  1876. ExtractHandle(
  1877. CTclCommand &tclCmd,
  1878. LONG *phHandle,
  1879. HandleType *pnHandleType,
  1880. BOOL fMandatory)
  1881. {
  1882. CString szHandle;
  1883. DWORD dwHandle = 0;
  1884. HandleType nHandleType = Undefined;
  1885. LPTSTR szTermChar;
  1886. tclCmd.PeekArgument(szHandle);
  1887. dwHandle = _tcstoul(szHandle, &szTermChar, 0);
  1888. if (0 != dwHandle)
  1889. {
  1890. switch (poption(szTermChar,
  1891. TEXT("HASH"), TEXT("KEY"), TEXT("PROVIDER"),
  1892. NULL))
  1893. {
  1894. case 1:
  1895. nHandleType = Hash;
  1896. break;
  1897. case 2:
  1898. nHandleType = Key;
  1899. break;
  1900. case 3:
  1901. nHandleType = Provider;
  1902. break;
  1903. default:
  1904. dwHandle = 0;
  1905. }
  1906. }
  1907. if (Undefined != nHandleType)
  1908. {
  1909. *pnHandleType = nHandleType;
  1910. *phHandle = (LONG)dwHandle;
  1911. tclCmd.NextArgument();
  1912. }
  1913. else if (!fMandatory)
  1914. {
  1915. *pnHandleType = Undefined;
  1916. *phHandle = 0;
  1917. }
  1918. else
  1919. throw tclCmd.BadSyntax();
  1920. return;
  1921. }
  1922. /*++
  1923. ReturnHandle:
  1924. This routine formats a handle and type into a string.
  1925. Arguments:
  1926. tclCmd supplies the tcl Command processor object.
  1927. hHandle supplies the handle value.
  1928. nHandleType supplies the handle type.
  1929. Return Value:
  1930. A String representation of the handle.
  1931. Throws:
  1932. Errors are thrown as DWORD status codes
  1933. Author:
  1934. Doug Barlow (dbarlow) 5/24/1998
  1935. --*/
  1936. static void
  1937. ReturnHandle(
  1938. CTclCommand &tclCmd,
  1939. LONG_PTR hHandle,
  1940. HandleType nHandleType)
  1941. {
  1942. static const LPCTSTR rgszTags[]
  1943. = { NULL, TEXT("Prov"), TEXT("Key"), TEXT("Hash")};
  1944. TCHAR szHandle[24]; // Seems enough for 0x0000000000000000Prov
  1945. sprintf(szHandle, "0x%p%s", hHandle, rgszTags[nHandleType]);
  1946. Tcl_AppendResult(tclCmd, szHandle, NULL);
  1947. }
  1948. /*++
  1949. MyEnumProviders:
  1950. This routine provides a list of providers, akin to CryptEnumProviders.
  1951. Arguments:
  1952. dwIndex - Index of the next provider to be enumerated.
  1953. pdwReserved - Reserved for future use and must be NULL.
  1954. dwFlags - Reserved for future use and must always be zero.
  1955. pdwProvType - Address of the DWORD value designating the type of the
  1956. enumerated provider.
  1957. pszProvName - Pointer to a buffer that receives the data from the
  1958. enumerated provider. This is a string including the terminating NULL
  1959. character. This parameter can be NULL to set the size of the name for
  1960. memory allocation purposes.
  1961. pcbProvName - Pointer to a DWORD specifying the size, in bytes, of the
  1962. buffer pointed to by the pszProvName parameter. When the function
  1963. returns, the DWORD contains the number of bytes stored in the buffer.
  1964. Return Value:
  1965. TRUE - Success
  1966. FALSE - An error occurred. See GetLastError.
  1967. Remarks:
  1968. This is here only for use on pre-Win2k systems.
  1969. Author:
  1970. Doug Barlow (dbarlow) 4/16/1999
  1971. --*/
  1972. static BOOL WINAPI
  1973. MyEnumProviders(
  1974. DWORD dwIndex, // in
  1975. DWORD *pdwReserved, // in
  1976. DWORD dwFlags, // in
  1977. DWORD *pdwProvType, // out
  1978. LPTSTR pszProvName, // out
  1979. DWORD *pcbProvName) // in/out
  1980. {
  1981. static TCHAR szKey[MAX_PATH];
  1982. LONG nSts;
  1983. HKEY hCrypt = NULL;
  1984. FILETIME ft;
  1985. DWORD dwLen;
  1986. if (0 != dwFlags)
  1987. {
  1988. SetLastError(NTE_BAD_FLAGS);
  1989. goto ErrorExit;
  1990. }
  1991. nSts = RegOpenKeyEx(
  1992. HKEY_LOCAL_MACHINE,
  1993. TEXT("SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider"),
  1994. 0,
  1995. KEY_ENUMERATE_SUB_KEYS,
  1996. &hCrypt);
  1997. if (ERROR_SUCCESS != nSts)
  1998. {
  1999. SetLastError(NTE_FAIL);
  2000. goto ErrorExit;
  2001. }
  2002. dwLen = sizeof(szKey) / sizeof(TCHAR);
  2003. nSts = RegEnumKeyEx(
  2004. hCrypt,
  2005. dwIndex,
  2006. szKey,
  2007. &dwLen,
  2008. NULL,
  2009. NULL,
  2010. NULL,
  2011. &ft);
  2012. if (ERROR_SUCCESS != nSts)
  2013. {
  2014. SetLastError(nSts);
  2015. goto ErrorExit;
  2016. }
  2017. nSts = RegCloseKey(hCrypt);
  2018. hCrypt = NULL;
  2019. if (ERROR_SUCCESS != nSts)
  2020. {
  2021. SetLastError(NTE_FAIL);
  2022. goto ErrorExit;
  2023. }
  2024. dwLen += sizeof(TCHAR);
  2025. if (NULL == pszProvName)
  2026. *pcbProvName = dwLen;
  2027. else if (*pcbProvName < dwLen)
  2028. {
  2029. *pcbProvName = dwLen;
  2030. SetLastError(ERROR_MORE_DATA);
  2031. goto ErrorExit;
  2032. }
  2033. else
  2034. {
  2035. *pcbProvName = dwLen;
  2036. lstrcpy(pszProvName, szKey);
  2037. }
  2038. return TRUE;
  2039. ErrorExit:
  2040. if (NULL != hCrypt)
  2041. RegCloseKey(hCrypt);
  2042. return FALSE;
  2043. }