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.

1112 lines
28 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 2001
  6. //
  7. // File: scinfo.cpp
  8. //
  9. // Abstract:
  10. //
  11. // This application is used to provide a snapshot of the Calais (Smart Card
  12. // Resource Manager) service's status, and to display certificates on smart
  13. // cards via the common WinNT UI.
  14. //
  15. // SCInfo -- describes the RM status and displays each available sc cert(s)
  16. //
  17. // The following options are always enabled:
  18. // Readername -- for just one reader
  19. // -sig -- display signature key certs only
  20. // -ex -- display exchange key certs only
  21. // -nocert -- don't look for certs to display
  22. // -key -- verify keyset public key matches cert public key
  23. //
  24. // Author: Amanda Matlosz (AMatlosz) 07/14/1998
  25. //
  26. // Environment: Win32 Console App
  27. //
  28. // Notes: For use in NT5 public key rollout testing
  29. //
  30. // Need to include the following libs:
  31. // winscard.lib
  32. //
  33. //--------------------------------------------------------------------------
  34. #include <pch.cpp>
  35. #pragma hdrstop
  36. #include <winscard.h>
  37. #include <winsvc.h>
  38. #include <cryptui.h>
  39. #include "cscsp.h"
  40. #define __dwFILE__ __dwFILE_CERTUTIL_SCINFO_CPP__
  41. #define wszSCARDSERVICE L"SCardSvr"
  42. //+-------------------------------------------------------------------------
  43. // IsSCardSvrRunning checks the registry and queries the service for status
  44. //--------------------------------------------------------------------------
  45. HRESULT
  46. IsSCardSvrRunning()
  47. {
  48. HRESULT hr;
  49. WCHAR const *pwszError = NULL;
  50. UINT idmsg = IDS_SMARTCARD_NOTRUNNING; // "The Microsoft Smart Card Resource Manager is not running."
  51. HANDLE hSCardSvrStarted = NULL;
  52. HMODULE hDll = GetModuleHandle(L"winscard.dll");
  53. typedef HANDLE (WINAPI FNSCARDACCESSSTARTEDEVENT)(VOID);
  54. FNSCARDACCESSSTARTEDEVENT *pfnSCardAccessStartedEvent;
  55. pfnSCardAccessStartedEvent = (FNSCARDACCESSSTARTEDEVENT *)
  56. GetProcAddress(hDll, "SCardAccessStartedEvent");
  57. if (NULL == pfnSCardAccessStartedEvent)
  58. {
  59. hr = myHLastError();
  60. pwszError = L"GetProcAddress";
  61. _JumpErrorStr(hr, error, "GetProcAddress", L"SCardAccessStartedEvent");
  62. }
  63. hSCardSvrStarted = (*pfnSCardAccessStartedEvent)();
  64. if (NULL == hSCardSvrStarted)
  65. {
  66. hr = myHLastError();
  67. if (S_OK == hr)
  68. {
  69. hr = E_HANDLE;
  70. }
  71. pwszError = L"SCardAccessStartedEvent";
  72. _JumpError(hr, error, "SCardAccessStartedEvent");
  73. }
  74. hr = WaitForSingleObject(hSCardSvrStarted, 1000);
  75. if (WAIT_OBJECT_0 != hr)
  76. {
  77. hr = myHError(hr);
  78. pwszError = L"WaitForSingleObject";
  79. _JumpError(hr, error, "WaitForSingleObject");
  80. }
  81. idmsg = IDS_SMARTCARD_RUNNING; // "The Microsoft Smart Card Resource Manager is running."
  82. hr = S_OK;
  83. error:
  84. // Display status
  85. wprintf(myLoadResourceString(idmsg));
  86. wprintf(wszNewLine);
  87. if (S_OK != hr)
  88. {
  89. // IDS_SERVICEPAUSED; // "Service is paused."
  90. // IDS_SERVICESTOPPED; // "Service is stopped."
  91. cuPrintErrorAndString(
  92. pwszError,
  93. IDS_SERVICEUNKNOWNSTATE, // "Service is in an unknown state."
  94. hr,
  95. NULL);
  96. }
  97. return(hr);
  98. }
  99. VOID
  100. FreeReaderList(
  101. IN SCARDCONTEXT hSCard,
  102. IN WCHAR *pwszzReaderNameAlloc,
  103. IN SCARD_READERSTATE *prgReaderState)
  104. {
  105. if (NULL != hSCard)
  106. {
  107. if (NULL != pwszzReaderNameAlloc)
  108. {
  109. SCardFreeMemory(hSCard, pwszzReaderNameAlloc);
  110. }
  111. SCardReleaseContext(hSCard);
  112. }
  113. if (NULL != prgReaderState)
  114. {
  115. LocalFree(prgReaderState);
  116. }
  117. }
  118. //+-------------------------------------------------------------------------
  119. // BuildReaderList tries to set *phSCard and get a list of currently available
  120. // smart card readers.
  121. //--------------------------------------------------------------------------
  122. HRESULT
  123. BuildReaderList(
  124. OPTIONAL IN WCHAR const *pwszReaderName,
  125. OUT SCARDCONTEXT *phSCard,
  126. OUT WCHAR **ppwszzReaderNameAlloc,
  127. OUT SCARD_READERSTATE **pprgReaderState,
  128. OUT DWORD *pcReaders)
  129. {
  130. HRESULT hr;
  131. DWORD i;
  132. DWORD dwAutoAllocate;
  133. SCARDCONTEXT hSCard = NULL;
  134. WCHAR *pwszzReaderNameAlloc = NULL;
  135. SCARD_READERSTATE *prgReaderState = NULL;
  136. DWORD cReaders;
  137. *phSCard = NULL;
  138. *ppwszzReaderNameAlloc = NULL;
  139. *pcReaders = 0;
  140. *pprgReaderState = NULL;
  141. wprintf(myLoadResourceString(IDS_SCREADER_STATUS_COLON));
  142. wprintf(wszNewLine);
  143. // Acquire global SCARDCONTEXT from resource manager if possible
  144. hr = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &hSCard);
  145. if (S_OK != hr)
  146. {
  147. cuPrintAPIError(L"SCardEstablishContext", hr);
  148. wprintf(myLoadResourceString(IDS_SC_USER_SCOPE));
  149. wprintf(wszNewLine);
  150. wprintf(myLoadResourceString(IDS_SC_NO_LIST));
  151. wprintf(wszNewLine);
  152. _JumpError(hr, error, "SCardEstablishContext");
  153. }
  154. // Build a readerstatus array from either a list of readers; or use the one
  155. // the user specified
  156. cReaders = 1;
  157. if (NULL == pwszReaderName)
  158. {
  159. dwAutoAllocate = SCARD_AUTOALLOCATE;
  160. hr = SCardListReaders(
  161. hSCard,
  162. SCARD_DEFAULT_READERS,
  163. (WCHAR *) &pwszzReaderNameAlloc,
  164. &dwAutoAllocate);
  165. if (S_OK != hr)
  166. {
  167. cuPrintAPIError(L"SCardListReaders", hr);
  168. wprintf(myLoadResourceString(IDS_SC_LIST_FAILED));
  169. wprintf(wszNewLine);
  170. if (SCARD_E_NO_READERS_AVAILABLE == hr)
  171. {
  172. wprintf(myLoadResourceString(IDS_SC_LIST_FAILED_NO_READERS));
  173. }
  174. else
  175. {
  176. wprintf(myLoadResourceString(IDS_SC_LIST_FAILED_GENERIC));
  177. }
  178. wprintf(wszNewLine);
  179. _JumpError(hr, error, "SCardListReaders");
  180. }
  181. // Build a readerstatus array...
  182. cReaders = 0;
  183. if (NULL != pwszzReaderNameAlloc)
  184. {
  185. for (
  186. pwszReaderName = pwszzReaderNameAlloc;
  187. L'\0' != *pwszReaderName;
  188. pwszReaderName += wcslen(pwszReaderName) + 1)
  189. {
  190. cReaders++;
  191. }
  192. }
  193. pwszReaderName = pwszzReaderNameAlloc;
  194. }
  195. prgReaderState = (SCARD_READERSTATE *) LocalAlloc(
  196. LMEM_FIXED | LMEM_ZEROINIT,
  197. cReaders * sizeof(**pprgReaderState));
  198. if (NULL == prgReaderState)
  199. {
  200. hr = E_OUTOFMEMORY;
  201. _JumpError(hr, error, "LocalAlloc");
  202. }
  203. wprintf(myLoadResourceString(IDS_SC_READERS_COLON));
  204. wprintf(L" %u\n", cReaders);
  205. for (i = 0; i < cReaders; i++)
  206. {
  207. wprintf(L" %u: %ws\n", i, pwszReaderName);
  208. prgReaderState[i].szReader = const_cast<WCHAR *>(pwszReaderName);
  209. prgReaderState[i].dwCurrentState = SCARD_STATE_UNAWARE;
  210. pwszReaderName += wcslen(pwszReaderName) + 1;
  211. }
  212. // ...And get the reader status from the resource manager
  213. hr = SCardGetStatusChange(
  214. hSCard,
  215. INFINITE, // hardly
  216. prgReaderState,
  217. cReaders);
  218. if (S_OK != hr)
  219. {
  220. cuPrintAPIError(L"SCardGetStatusChange", hr);
  221. _JumpError(hr, error, "SCardGetStatusChange");
  222. }
  223. *phSCard = hSCard;
  224. hSCard = NULL;
  225. *ppwszzReaderNameAlloc = pwszzReaderNameAlloc;
  226. pwszzReaderNameAlloc = NULL;
  227. *pprgReaderState = prgReaderState;
  228. prgReaderState = NULL;
  229. *pcReaders = cReaders;
  230. hr = S_OK;
  231. error:
  232. FreeReaderList(hSCard, pwszzReaderNameAlloc, prgReaderState);
  233. return(hr);
  234. }
  235. //+-------------------------------------------------------------------------
  236. // DisplayReaderList displays the status for a list of readers.
  237. //--------------------------------------------------------------------------
  238. HRESULT
  239. DisplayReaderList(
  240. IN SCARDCONTEXT hSCard,
  241. IN SCARD_READERSTATE const *prgReaderState,
  242. IN DWORD cReaders)
  243. {
  244. HRESULT hr;
  245. DWORD i;
  246. DWORD dwAutoAllocate;
  247. UINT idsMsg;
  248. // Display all reader information
  249. for (i = 0; i < cReaders; i++)
  250. {
  251. DWORD dwState;
  252. WCHAR const *pwszSep;
  253. static WCHAR const s_wszSep[] = L" | ";
  254. //--- reader: readerName
  255. wprintf(myLoadResourceString(IDS_SC_MINUS_READER_COLON));
  256. wprintf(L" %ws\n", prgReaderState[i].szReader);
  257. //--- status: /bits/
  258. wprintf(myLoadResourceString(IDS_SC_MINUS_STATUS_COLON));
  259. dwState = prgReaderState[i].dwEventState;
  260. pwszSep = L" ";
  261. if (SCARD_STATE_UNKNOWN & dwState)
  262. {
  263. wprintf(L"%wsSCARD_STATE_UNKNOWN", pwszSep);
  264. pwszSep = s_wszSep;
  265. }
  266. if (SCARD_STATE_UNAVAILABLE & dwState)
  267. {
  268. wprintf(L"%wsSCARD_STATE_UNAVAILABLE", pwszSep);
  269. pwszSep = s_wszSep;
  270. }
  271. if (SCARD_STATE_EMPTY & dwState)
  272. {
  273. wprintf(L"%wsSCARD_STATE_EMPTY", pwszSep);
  274. pwszSep = s_wszSep;
  275. }
  276. if (SCARD_STATE_PRESENT & dwState)
  277. {
  278. wprintf(L"%wsSCARD_STATE_PRESENT", pwszSep);
  279. pwszSep = s_wszSep;
  280. }
  281. if (SCARD_STATE_EXCLUSIVE & dwState)
  282. {
  283. wprintf(L"%wsSCARD_STATE_EXCLUSIVE", pwszSep);
  284. pwszSep = s_wszSep;
  285. }
  286. if (SCARD_STATE_INUSE & dwState)
  287. {
  288. wprintf(L"%wsSCARD_STATE_INUSE", pwszSep);
  289. pwszSep = s_wszSep;
  290. }
  291. if (SCARD_STATE_MUTE & dwState)
  292. {
  293. wprintf(L"%wsSCARD_STATE_MUTE", pwszSep);
  294. pwszSep = s_wszSep;
  295. }
  296. if (SCARD_STATE_UNPOWERED & dwState)
  297. {
  298. wprintf(L"%wsSCARD_STATE_UNPOWERED", pwszSep);
  299. }
  300. wprintf(wszNewLine);
  301. //--- status: what scstatus would say
  302. // NO CARD
  303. if (SCARD_STATE_EMPTY & dwState) // SC_STATUS_NO_CARD
  304. {
  305. idsMsg = IDS_SC_STATUS_NO_CARD;
  306. }
  307. // CARD in reader: SHARED, EXCLUSIVE, FREE, UNKNOWN ?
  308. else
  309. if (SCARD_STATE_PRESENT & dwState)
  310. {
  311. if (SCARD_STATE_MUTE & dwState) // SC_STATUS_UNKNOWN
  312. {
  313. idsMsg = IDS_SC_STATUS_UNKNOWN;
  314. }
  315. else
  316. if (SCARD_STATE_INUSE & dwState)
  317. {
  318. if (dwState & SCARD_STATE_EXCLUSIVE & dwState)
  319. {
  320. // SC_STATUS_EXCLUSIVE
  321. idsMsg = IDS_SC_STATUS_BUSY;
  322. }
  323. else // SC_STATUS_SHARED
  324. {
  325. idsMsg = IDS_SC_STATUS_SHARED;
  326. }
  327. }
  328. else // SC_SATATUS_AVAILABLE
  329. {
  330. idsMsg = IDS_SC_STATUS_AVAILABLE;
  331. }
  332. }
  333. // READER ERROR: at this point, something's gone wrong
  334. else // SCARD_STATE_UNAVAILABLE & dwState -- SC_STATUS_ERROR
  335. {
  336. idsMsg = IDS_SC_STATUS_NO_RESPONSE;
  337. }
  338. wprintf(myLoadResourceString(IDS_SC_MINUS_STATUS_COLON));
  339. wprintf(L" ");
  340. wprintf(myLoadResourceString(idsMsg));
  341. wprintf(wszNewLine);
  342. // card name(s):
  343. wprintf(myLoadResourceString(IDS_SC_MINUS_CARD_COLON));
  344. if (0 < prgReaderState[i].cbAtr)
  345. {
  346. WCHAR *pwszCardName = NULL;
  347. // Get the name of the card
  348. dwAutoAllocate = SCARD_AUTOALLOCATE;
  349. hr = SCardListCards(
  350. hSCard,
  351. prgReaderState[i].rgbAtr,
  352. NULL,
  353. 0,
  354. (WCHAR *) &pwszCardName,
  355. &dwAutoAllocate);
  356. if (S_OK != hr || NULL == pwszCardName)
  357. {
  358. wprintf(L" ");
  359. wprintf(myLoadResourceString(IDS_SC_UNKNOWN_CARD));
  360. }
  361. else
  362. {
  363. WCHAR const *pwszName;
  364. pwszSep = L"";
  365. for (
  366. pwszName = pwszCardName;
  367. L'\0' != *pwszName;
  368. pwszName += wcslen(pwszName) + 1)
  369. {
  370. wprintf(L"%ws %ws", pwszSep, pwszName);
  371. pwszSep = L",";
  372. }
  373. }
  374. if (NULL != pwszCardName)
  375. {
  376. SCardFreeMemory(hSCard, pwszCardName);
  377. }
  378. }
  379. wprintf(wszNewLine);
  380. }
  381. hr = S_OK;
  382. //error:
  383. return(hr);
  384. }
  385. HRESULT
  386. myCryptGetProvParamToUnicode(
  387. IN HCRYPTPROV hProv,
  388. IN DWORD dwParam,
  389. OUT WCHAR **ppwszOut,
  390. IN DWORD dwFlags)
  391. {
  392. HRESULT hr;
  393. char *psz = NULL;
  394. DWORD cb;
  395. *ppwszOut = NULL;
  396. if (!CryptGetProvParam(hProv, dwParam, NULL, &cb, 0))
  397. {
  398. hr = myHLastError();
  399. _JumpError(hr, error, "CryptGetProvParam");
  400. }
  401. psz = (char *) LocalAlloc(LMEM_FIXED, cb);
  402. if (NULL == psz)
  403. {
  404. hr = E_OUTOFMEMORY;
  405. _JumpError(hr, error, "LocalAlloc");
  406. }
  407. if (!CryptGetProvParam(hProv, dwParam, (BYTE *) psz, &cb, 0))
  408. {
  409. hr = myHLastError();
  410. _JumpError(hr, error, "CryptGetProvParam");
  411. }
  412. if (!myConvertSzToWsz(ppwszOut, psz, -1))
  413. {
  414. hr = E_OUTOFMEMORY;
  415. _JumpError(hr, error, "myConvertSzToWsz");
  416. }
  417. hr = S_OK;
  418. error:
  419. if (NULL != psz)
  420. {
  421. LocalFree(psz);
  422. }
  423. return(hr);
  424. }
  425. //+-------------------------------------------------------------------------
  426. // GetCertContext -- called by DisplayCerts
  427. //--------------------------------------------------------------------------
  428. HRESULT
  429. GetCertContext(
  430. IN HCRYPTPROV hProv,
  431. IN HCRYPTKEY hKey,
  432. IN DWORD dwKeySpec,
  433. IN WCHAR const *pwszKeyType,
  434. OUT CERT_CONTEXT const **ppCert)
  435. {
  436. HRESULT hr;
  437. CERT_CONTEXT const *pCert = NULL;
  438. CERT_PUBLIC_KEY_INFO *pKey = NULL;
  439. CRYPT_KEY_PROV_INFO KeyProvInfo;
  440. WCHAR *pwszContainerName = NULL;
  441. WCHAR *pwszProvName = NULL;
  442. BYTE *pbCert = NULL;
  443. DWORD cbCert;
  444. DWORD cbKey;
  445. *ppCert = NULL;
  446. // Get the cert from this key
  447. if (!CryptGetKeyParam(hKey, KP_CERTIFICATE, NULL, &cbCert, 0))
  448. {
  449. hr = myHLastError();
  450. if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr)
  451. {
  452. _JumpError(hr, error, "CryptGetKeyParam");
  453. }
  454. }
  455. pbCert = (BYTE *) LocalAlloc(LMEM_FIXED, cbCert);
  456. if (NULL == pbCert)
  457. {
  458. hr = E_OUTOFMEMORY;
  459. _JumpError(hr, error, "LocalAlloc");
  460. }
  461. if (!CryptGetKeyParam(hKey, KP_CERTIFICATE, pbCert, &cbCert, 0))
  462. {
  463. hr = myHLastError();
  464. _JumpError(hr, error, "CryptGetKeyParam");
  465. }
  466. // Convert the certificate into a Cert Context.
  467. pCert = CertCreateCertificateContext(
  468. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  469. pbCert,
  470. cbCert);
  471. if (NULL == pCert)
  472. {
  473. hr = myHLastError();
  474. _JumpError(hr, error, "CertCreateCertificateContext");
  475. }
  476. // Perform public key check
  477. wprintf(wszNewLine);
  478. wprintf(myLoadResourceString(IDS_FORMAT_SC_TESTING_MATCH), pwszKeyType);
  479. wprintf(wszNewLine);
  480. if (!CryptExportPublicKeyInfo(
  481. hProv,
  482. dwKeySpec,
  483. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  484. NULL,
  485. &cbKey)) // in, out
  486. {
  487. hr = myHLastError();
  488. cuPrintAPIError(L"CryptExportPublicKeyInfo", hr);
  489. _JumpError(hr, error, "CryptExportPublicKeyInfo");
  490. }
  491. if (0 == cbKey)
  492. {
  493. hr = SCARD_E_UNEXPECTED; // huh?
  494. wprintf(
  495. myLoadResourceString(IDS_SC_SIZE_ZERO),
  496. L"CryptExportPublicKeyInfo");
  497. wprintf(wszNewLine);
  498. _JumpError(hr, error, "zero info size");
  499. }
  500. pKey = (CERT_PUBLIC_KEY_INFO *) LocalAlloc(LMEM_FIXED, cbKey);
  501. if (NULL == pKey)
  502. {
  503. hr = E_OUTOFMEMORY;
  504. _JumpError(hr, error, "LocalAlloc");
  505. }
  506. if (!CryptExportPublicKeyInfo(
  507. hProv,
  508. dwKeySpec,
  509. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  510. pKey,
  511. &cbKey))
  512. {
  513. hr = myHLastError();
  514. cuPrintAPIError(L"CryptExportPublicKeyInfo", hr);
  515. _JumpError(hr, error, "CryptExportPublicKeyInfo");
  516. }
  517. if (!CertComparePublicKeyInfo(
  518. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  519. pKey, // from the private keyset
  520. &pCert->pCertInfo->SubjectPublicKeyInfo)) // cert public key
  521. {
  522. wprintf(wszNewLine);
  523. wprintf(myLoadResourceString(IDS_SC_KEYPROVINFO_KEY));
  524. wprintf(wszNewLine);
  525. cuDumpPublicKey(pKey);
  526. wprintf(wszNewLine);
  527. wprintf(myLoadResourceString(IDS_SC_CERT_KEY));
  528. wprintf(wszNewLine);
  529. cuDumpPublicKey(&pCert->pCertInfo->SubjectPublicKeyInfo);
  530. // by design, CertComparePublicKeyInfo doesn't set last error!
  531. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  532. _JumpError(hr, error, "CertComparePublicKeyInfo");
  533. }
  534. wprintf(myLoadResourceString(IDS_SC_KEY_MATCHES));
  535. wprintf(wszNewLine);
  536. // Associate cryptprovider w/ the private key property of this cert
  537. // ... need the container name
  538. hr = myCryptGetProvParamToUnicode(
  539. hProv,
  540. PP_CONTAINER,
  541. &pwszContainerName,
  542. 0);
  543. _JumpIfError(hr, error, "myCryptGetProvParamToUnicode");
  544. // ... need the provider name
  545. hr = myCryptGetProvParamToUnicode(hProv, PP_NAME, &pwszProvName, 0);
  546. _JumpIfError(hr, error, "myCryptGetProvParamToUnicode");
  547. // Set the cert context properties to reflect the prov info
  548. KeyProvInfo.pwszContainerName = pwszContainerName;
  549. KeyProvInfo.pwszProvName = pwszProvName;
  550. KeyProvInfo.dwProvType = PROV_RSA_FULL;
  551. KeyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
  552. KeyProvInfo.cProvParam = 0;
  553. KeyProvInfo.rgProvParam = NULL;
  554. KeyProvInfo.dwKeySpec = dwKeySpec;
  555. if (!CertSetCertificateContextProperty(
  556. pCert,
  557. CERT_KEY_PROV_INFO_PROP_ID,
  558. 0,
  559. (VOID *) &KeyProvInfo))
  560. {
  561. hr = myHLastError();
  562. // the cert's been incorrectly created -- scrap it.
  563. _JumpError(hr, error, "CertSetCertificateContextProperty");
  564. }
  565. hr = cuDumpCertKeyProviderInfo(g_wszPad2, pCert, NULL, NULL);
  566. _PrintIfError(hr, "cuDumpCertKeyProviderInfo");
  567. if (!g_fCryptSilent)
  568. {
  569. if (AT_SIGNATURE == dwKeySpec)
  570. {
  571. hr = myValidateKeyForSigning(
  572. hProv,
  573. &pCert->pCertInfo->SubjectPublicKeyInfo,
  574. CALG_SHA1);
  575. }
  576. else
  577. {
  578. hr = myValidateKeyForEncrypting(
  579. hProv,
  580. &pCert->pCertInfo->SubjectPublicKeyInfo,
  581. CALG_RC4);
  582. }
  583. if (S_OK != hr)
  584. {
  585. if (SCARD_W_CANCELLED_BY_USER != hr)
  586. {
  587. wprintf(myLoadResourceString(IDS_ERR_PRIVATEKEY_MISMATCH)); // "ERROR: Certificate public key does NOT match private key"
  588. wprintf(wszNewLine);
  589. //_JumpError(hr, error, "myValidateKeyForEncrypting");
  590. _PrintError(hr, "myValidateKeyForEncrypting");
  591. }
  592. }
  593. else
  594. {
  595. wprintf(myLoadResourceString(IDS_PRIVATEKEY_VERIFIES));
  596. wprintf(wszNewLine);
  597. }
  598. }
  599. *ppCert = pCert;
  600. pCert = NULL;
  601. hr = S_OK;
  602. error:
  603. if (NULL != pbCert)
  604. {
  605. LocalFree(pbCert);
  606. }
  607. if (NULL != pKey)
  608. {
  609. LocalFree(pKey);
  610. }
  611. if (NULL != pwszContainerName)
  612. {
  613. LocalFree(pwszContainerName);
  614. }
  615. if (NULL != pwszProvName)
  616. {
  617. LocalFree(pwszProvName);
  618. }
  619. if (NULL != pCert)
  620. {
  621. CertFreeCertificateContext(pCert);
  622. }
  623. return(hr);
  624. }
  625. //+-------------------------------------------------------------------------
  626. // DisplayChainInfo -- This code verifies that the SC cert is valid.
  627. // Uses identical code to KDC cert chaining engine.
  628. //
  629. // Author: Todds
  630. //--------------------------------------------------------------------------
  631. DWORD
  632. DisplayChainInfo(
  633. IN CERT_CONTEXT const *pCert)
  634. {
  635. HRESULT hr;
  636. CERT_CHAIN_PARA ChainParameters;
  637. char *pszSCUsage = szOID_KP_SMARTCARD_LOGON;
  638. CERT_CHAIN_CONTEXT const *pChainContext = NULL;
  639. DWORD VerifyState;
  640. ZeroMemory(&ChainParameters, sizeof(ChainParameters));
  641. ChainParameters.cbSize = sizeof(ChainParameters);
  642. ChainParameters.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
  643. ChainParameters.RequestedUsage.Usage.cUsageIdentifier = 1;
  644. ChainParameters.RequestedUsage.Usage.rgpszUsageIdentifier = &pszSCUsage;
  645. if (!CertGetCertificateChain(
  646. HCCE_LOCAL_MACHINE,
  647. pCert,
  648. NULL, // evaluate at current time
  649. NULL, // no additional stores
  650. &ChainParameters,
  651. CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
  652. NULL, // reserved
  653. &pChainContext))
  654. {
  655. hr = myHLastError();
  656. cuPrintAPIError(L"CertGetCertificateChain", hr);
  657. _JumpError(hr, error, "CertGetCertificateChain");
  658. }
  659. if (CERT_TRUST_NO_ERROR != pChainContext->TrustStatus.dwErrorStatus)
  660. {
  661. wprintf(
  662. L"CertGetCertificateChain(dwErrorStatus) = 0x%x\n",
  663. pChainContext->TrustStatus.dwErrorStatus);
  664. wprintf(myLoadResourceString(IDS_SC_BAD_CHAIN));
  665. wprintf(wszNewLine);
  666. }
  667. else
  668. {
  669. wprintf(myLoadResourceString(IDS_SC_GOOD_CHAIN));
  670. wprintf(wszNewLine);
  671. }
  672. hr = cuVerifyCertContext(
  673. pCert, // pCert
  674. NULL, // hStoreCA
  675. 1, // cApplicationPolicies
  676. &pszSCUsage, // apszApplicationPolicies
  677. 0, // cIssuancePolicies
  678. NULL, // apszIssuancePolicies
  679. TRUE, // fNTAuth
  680. &VerifyState);
  681. _JumpIfError(hr, error, "cuVerifyCertContext");
  682. error:
  683. if (NULL != pChainContext)
  684. {
  685. CertFreeCertificateChain(pChainContext);
  686. }
  687. return(hr);
  688. }
  689. HRESULT
  690. DisplayReaderCertAndKey(
  691. IN SCARD_READERSTATE const *pReaderState,
  692. IN HCRYPTPROV hProv,
  693. IN DWORD dwKeySpec,
  694. IN WCHAR const *pwszKeyType,
  695. IN WCHAR const *pwszCardName,
  696. IN WCHAR const *pwszCSPName)
  697. {
  698. HRESULT hr;
  699. HCRYPTKEY hKey = NULL;
  700. CERT_CONTEXT const *pCert = NULL;
  701. DWORD cwc;
  702. WCHAR *pwszTitle = NULL;
  703. CRYPTUI_VIEWCERTIFICATE_STRUCT CertViewInfo;
  704. // Get the key
  705. if (!CryptGetUserKey(hProv, dwKeySpec, &hKey))
  706. {
  707. hr = myHLastError();
  708. cuPrintAPIError(L"CryptGetUserKey", hr);
  709. if (NTE_NO_KEY == hr)
  710. {
  711. wprintf(
  712. myLoadResourceString(IDS_FORMAT_SC_NO_KEY_COLON),
  713. pwszKeyType);
  714. }
  715. else
  716. {
  717. wprintf(
  718. myLoadResourceString(IDS_FORMAT_SC_CANNOT_OPEN_KEY_COLON),
  719. pwszKeyType);
  720. }
  721. wprintf(L" %ws\n", pReaderState->szReader);
  722. _JumpError2(hr, error, "CryptGetUserKey", NTE_NO_KEY);
  723. }
  724. // Get the cert for this key
  725. hr = GetCertContext(hProv, hKey, dwKeySpec, pwszKeyType, &pCert);
  726. if (S_OK != hr)
  727. {
  728. wprintf(
  729. myLoadResourceString(IDS_FORMAT_SC_NO_CERT_COLON),
  730. pwszKeyType);
  731. wprintf(L" %ws\n", pReaderState->szReader);
  732. _JumpError(hr, error, "GetCertContext");
  733. }
  734. // Attempt to build a certificate chain
  735. wprintf(wszNewLine);
  736. wprintf(myLoadResourceString(IDS_SC_VALIDATING_CHAIN));
  737. wprintf(wszNewLine);
  738. DisplayChainInfo(pCert);
  739. // call common UI to display Cert Context
  740. // (from cryptui.h (cryptui.dll))
  741. if (!g_fCryptSilent)
  742. {
  743. cwc = wcslen(pReaderState->szReader) +
  744. 2 +
  745. wcslen(pwszKeyType);
  746. pwszTitle = (WCHAR *) LocalAlloc(
  747. LMEM_FIXED,
  748. (cwc + 1) * sizeof(WCHAR));
  749. if (NULL == pwszTitle)
  750. {
  751. hr = E_OUTOFMEMORY;
  752. _JumpError(hr, error, "LocalAlloc");
  753. }
  754. swprintf(
  755. pwszTitle,
  756. L"%ws: %ws",
  757. pReaderState->szReader,
  758. pwszKeyType);
  759. ZeroMemory(&CertViewInfo, sizeof(CertViewInfo));
  760. CertViewInfo.dwSize = sizeof(CertViewInfo);
  761. //CertViewInfo.hwndParent = NULL;
  762. CertViewInfo.szTitle = pwszTitle;
  763. CertViewInfo.dwFlags = CRYPTUI_DISABLE_EDITPROPERTIES |
  764. CRYPTUI_DISABLE_ADDTOSTORE |
  765. CRYPTUI_ENABLE_REVOCATION_CHECKING;
  766. CertViewInfo.pCertContext = pCert;
  767. CryptUIDlgViewCertificate(&CertViewInfo, NULL);
  768. CertFreeCertificateContext(pCert);
  769. }
  770. wprintf(
  771. myLoadResourceString(IDS_FORMAT_SC_CERT_DISPLAYED_COLON),
  772. pwszKeyType);
  773. wprintf(L" %ws\n", pReaderState->szReader);
  774. hr = S_OK;
  775. error:
  776. if (NULL != pwszTitle)
  777. {
  778. LocalFree(pwszTitle);
  779. }
  780. if (NULL != hKey)
  781. {
  782. CryptDestroyKey(hKey);
  783. }
  784. return(hr);
  785. }
  786. HRESULT
  787. DisplayReaderCert(
  788. IN SCARDCONTEXT hSCard,
  789. IN SCARD_READERSTATE const *pReaderState)
  790. {
  791. HRESULT hr;
  792. HRESULT hr2;
  793. DWORD dwAutoAllocate;
  794. WCHAR wszFQCN[256];
  795. HCRYPTPROV hProv = NULL;
  796. WCHAR *pwszCardName = NULL;
  797. WCHAR *pwszCSPName = NULL;
  798. if (0 >= pReaderState->cbAtr)
  799. {
  800. hr = S_OK;
  801. goto error; // no point to do any more work on this reader
  802. }
  803. // Inform user of current test
  804. wprintf(L"\n=======================================================\n");
  805. wprintf(myLoadResourceString(IDS_SC_ANALYZING_CARD_COLON));
  806. wprintf(L" %ws\n", pReaderState->szReader);
  807. // Get the name of the card
  808. dwAutoAllocate = SCARD_AUTOALLOCATE;
  809. hr = SCardListCards(
  810. hSCard,
  811. pReaderState->rgbAtr,
  812. NULL, // rgguidInterfaces
  813. 0, // cguidInterfaceCount
  814. (WCHAR *) &pwszCardName, // mszCards
  815. &dwAutoAllocate); // pcchCards
  816. _JumpIfError(hr, error, "SCardListCards");
  817. dwAutoAllocate = SCARD_AUTOALLOCATE;
  818. hr = SCardGetCardTypeProviderName(
  819. hSCard,
  820. pwszCardName,
  821. SCARD_PROVIDER_CSP,
  822. (WCHAR *) &pwszCSPName,
  823. &dwAutoAllocate);
  824. if (S_OK != hr)
  825. {
  826. cuPrintAPIError(L"SCardGetCardTypeProviderName", hr);
  827. wprintf(
  828. myLoadResourceString(IDS_FORMAT_SC_CANNOT_GET_CSP),
  829. pwszCardName);
  830. _JumpError(hr, error, "SCardGetCardTypeProviderName");
  831. }
  832. // Prepare FullyQualifiedContainerName for CryptAcquireContext call
  833. swprintf(wszFQCN, L"\\\\.\\%ws\\", pReaderState->szReader);
  834. if (!CryptAcquireContext(
  835. &hProv,
  836. wszFQCN, // default container via reader
  837. pwszCSPName,
  838. PROV_RSA_FULL,
  839. g_fCryptSilent? CRYPT_SILENT : 0))
  840. {
  841. hr = myHLastError();
  842. wprintf(L"%ws:\n", pReaderState->szReader);
  843. wprintf(L"%ws:\n", pwszCSPName);
  844. cuPrintAPIError(L"CryptAcquireContext", hr);
  845. _JumpError(hr, error, "SCardGetCardTypeProviderName");
  846. }
  847. // Enumerate the keys user specified and display the certs...
  848. hr = DisplayReaderCertAndKey(
  849. pReaderState,
  850. hProv,
  851. AT_SIGNATURE,
  852. L"AT_SIGNATURE",
  853. pwszCardName,
  854. pwszCSPName);
  855. _PrintIfError2(hr, "DisplayReaderCertAndKey", NTE_NO_KEY);
  856. hr2 = DisplayReaderCertAndKey(
  857. pReaderState,
  858. hProv,
  859. AT_KEYEXCHANGE,
  860. L"AT_KEYEXCHANGE",
  861. pwszCardName,
  862. pwszCSPName);
  863. _PrintIfError2(hr2, "DisplayReaderCertAndKey", NTE_NO_KEY);
  864. if (S_OK == hr)
  865. {
  866. hr = hr2;
  867. hr2 = S_OK;
  868. }
  869. // ignore NTE_NO_KEY if the other key type exists or has a different error:
  870. if (NTE_NO_KEY == hr)
  871. {
  872. hr = hr2;
  873. _PrintIfError2(hr, "DisplayReaderCertAndKey", NTE_NO_KEY);
  874. }
  875. error:
  876. if (NULL != pwszCSPName)
  877. {
  878. SCardFreeMemory(hSCard, pwszCSPName);
  879. }
  880. if (NULL != pwszCardName)
  881. {
  882. SCardFreeMemory(hSCard, pwszCardName);
  883. }
  884. if (NULL != hProv)
  885. {
  886. CryptReleaseContext(hProv, 0);
  887. }
  888. return(hr);
  889. }
  890. //+-------------------------------------------------------------------------
  891. // DisplayCerts
  892. //--------------------------------------------------------------------------
  893. HRESULT
  894. DisplayCerts(
  895. IN SCARDCONTEXT hSCard,
  896. IN SCARD_READERSTATE const *prgReaderState,
  897. IN DWORD cReaders)
  898. {
  899. HRESULT hr;
  900. HRESULT hr2;
  901. DWORD i;
  902. // For each reader that has a card, load the CSP and display the cert
  903. hr = S_OK;
  904. for (i = 0; i < cReaders; i++)
  905. {
  906. hr2 = DisplayReaderCert(hSCard, &prgReaderState[i]);
  907. _PrintIfError(hr2, "DisplayReaderCert");
  908. if (S_OK == hr)
  909. {
  910. hr = hr2;
  911. }
  912. }
  913. return(hr);
  914. }
  915. //+-------------------------------------------------------------------------
  916. // verbSCInfo -- This is the main entry point for the smart card test program.
  917. // Nice and simple, borrowed from DBarlow
  918. //
  919. // Author: Doug Barlow (dbarlow) 11/10/1997
  920. //
  921. // Revisions:
  922. // AMatlosz 2/26/98
  923. //--------------------------------------------------------------------------
  924. HRESULT
  925. verbSCInfo(
  926. IN WCHAR const *pwszOption,
  927. OPTIONAL IN WCHAR const *pwszReaderName,
  928. IN WCHAR const *pwszArg2,
  929. IN WCHAR const *pwszArg3,
  930. IN WCHAR const *pwszArg4)
  931. {
  932. HRESULT hr;
  933. HRESULT hr2;
  934. SCARDCONTEXT hSCard = NULL;
  935. WCHAR *pwszzReaderNameAlloc = NULL;
  936. SCARD_READERSTATE *prgReaderState = NULL;
  937. DWORD cReaders;
  938. hr = IsSCardSvrRunning();
  939. _JumpIfError(hr, error, "IsSCardSvrRunning");
  940. hr = BuildReaderList(
  941. pwszReaderName,
  942. &hSCard,
  943. &pwszzReaderNameAlloc,
  944. &prgReaderState,
  945. &cReaders);
  946. _PrintIfError(hr, "BuildReaderList");
  947. hr2 = DisplayReaderList(hSCard, prgReaderState, cReaders);
  948. _PrintIfError(hr2, "DisplayReaderList");
  949. if (S_OK == hr)
  950. {
  951. hr = hr2;
  952. }
  953. hr2 = DisplayCerts(hSCard, prgReaderState, cReaders);
  954. _PrintIfError(hr2, "DisplayCerts");
  955. if (S_OK == hr)
  956. {
  957. hr = hr2;
  958. }
  959. wprintf(wszNewLine);
  960. wprintf(myLoadResourceString(IDS_DONE));
  961. wprintf(wszNewLine);
  962. error:
  963. FreeReaderList(hSCard, pwszzReaderNameAlloc, prgReaderState);
  964. return(hr);
  965. }