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.

8351 lines
182 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: dump.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include <pch.cpp>
  11. #pragma hdrstop
  12. #include "csprop.h"
  13. #include "cscsp.h"
  14. #include "csber.h"
  15. #define __dwFILE__ __dwFILE_CERTUTIL_DUMP_CPP__
  16. #if DBG
  17. #define wszCERTUTIL L"(certutil)"
  18. #else
  19. #define wszCERTUTIL L""
  20. #endif
  21. WCHAR const g_wszCertUtil[] = wszCERTUTIL;
  22. DWORD s_DbgSsRecoveryTrace = DBG_SS_CERTUTILI;
  23. HRESULT
  24. DumpAttributes(
  25. IN CRYPT_ATTRIBUTE const *rgAttr,
  26. IN DWORD cAttr,
  27. IN BOOL fQuiet,
  28. IN DWORD Type, // FOT_*
  29. OPTIONAL IN HCERTSTORE hStore,
  30. OPTIONAL OUT BYTE *pbHashUserCert,
  31. OPTIONAL IN OUT DWORD *pcbHashUserCert,
  32. OPTIONAL IN OUT CERT_EXTENSIONS **ppExtInfo);
  33. WCHAR const *
  34. wszRDNValueType(
  35. IN DWORD dwValueType)
  36. {
  37. WCHAR const *pwsz;
  38. switch (CERT_RDN_TYPE_MASK & dwValueType)
  39. {
  40. case CERT_RDN_ANY_TYPE:
  41. pwsz = L"CERT_RDN_ANY_TYPE";
  42. break;
  43. case CERT_RDN_ENCODED_BLOB:
  44. pwsz = L"CERT_RDN_ENCODED_BLOB";
  45. break;
  46. case CERT_RDN_OCTET_STRING:
  47. pwsz = L"CERT_RDN_OCTET_STRING";
  48. break;
  49. case CERT_RDN_NUMERIC_STRING:
  50. pwsz = L"CERT_RDN_NUMERIC_STRING";
  51. break;
  52. case CERT_RDN_PRINTABLE_STRING:
  53. pwsz = L"CERT_RDN_PRINTABLE_STRING";
  54. break;
  55. case CERT_RDN_TELETEX_STRING:
  56. pwsz = L"CERT_RDN_TELETEX_STRING";
  57. break;
  58. //case CERT_RDN_T61_STRING:
  59. //pwsz = L"CERT_RDN_T61_STRING";
  60. //break;
  61. case CERT_RDN_VIDEOTEX_STRING:
  62. pwsz = L"CERT_RDN_VIDEOTEX_STRING";
  63. break;
  64. case CERT_RDN_IA5_STRING:
  65. pwsz = L"CERT_RDN_IA5_STRING";
  66. break;
  67. case CERT_RDN_GRAPHIC_STRING:
  68. pwsz = L"CERT_RDN_GRAPHIC_STRING";
  69. break;
  70. //case CERT_RDN_VISIBLE_STRING:
  71. //pwsz = L"CERT_RDN_VISIBLE_STRING";
  72. //break;
  73. case CERT_RDN_ISO646_STRING:
  74. pwsz = L"CERT_RDN_ISO646_STRING";
  75. break;
  76. case CERT_RDN_GENERAL_STRING:
  77. pwsz = L"CERT_RDN_GENERAL_STRING";
  78. break;
  79. case CERT_RDN_UNIVERSAL_STRING:
  80. pwsz = L"CERT_RDN_UNIVERSAL_STRING";
  81. break;
  82. //case CERT_RDN_INT4_STRING:
  83. //pwsz = L"CERT_RDN_INT4_STRING";
  84. //break;
  85. //case CERT_RDN_BMP_STRING:
  86. //pwsz = L"CERT_RDN_BMP_STRING";
  87. //break;
  88. case CERT_RDN_UNICODE_STRING:
  89. pwsz = L"CERT_RDN_UNICODE_STRING";
  90. break;
  91. case CERT_RDN_UTF8_STRING:
  92. pwsz = L"CERT_RDN_UTF8_STRING";
  93. break;
  94. default:
  95. pwsz = myLoadResourceString(IDS_QUESTIONMARKS); // "???"
  96. break;
  97. }
  98. return(pwsz);
  99. }
  100. VOID
  101. cuPrintCRLFString(
  102. IN WCHAR const *pwszPrefix,
  103. IN WCHAR const *pwszIn)
  104. {
  105. if (NULL == pwszPrefix)
  106. {
  107. pwszPrefix = g_wszEmpty;
  108. }
  109. while (L'\0' != *pwszIn)
  110. {
  111. DWORD i;
  112. WCHAR const *pwc;
  113. pwc = pwszIn++;
  114. i = wcscspn(pwszIn, L"\r\n");
  115. wprintf(
  116. L"%.1ws%ws%.*ws",
  117. pwc,
  118. L'\n' == *pwc? pwszPrefix : g_wszEmpty,
  119. i,
  120. pwszIn);
  121. pwszIn += i;
  122. if (L'\r' == *pwszIn)
  123. {
  124. pwszIn++;
  125. }
  126. }
  127. }
  128. VOID
  129. cuPrintPossibleObjectIdName(
  130. IN WCHAR const *pwszObjId)
  131. {
  132. HRESULT hr;
  133. if (iswdigit(*pwszObjId))
  134. {
  135. hr = myVerifyObjId(pwszObjId);
  136. if (S_OK == hr)
  137. {
  138. WCHAR const *pwszName = cuGetOIDName(pwszObjId);
  139. if (NULL != pwszName && L'\0' != *pwszName)
  140. {
  141. wprintf(L" %ws", pwszName);
  142. }
  143. }
  144. }
  145. }
  146. WCHAR const *
  147. cuGetOIDNameA(
  148. IN char const *pszObjId)
  149. {
  150. HRESULT hr;
  151. WCHAR const *pwszName1 = g_wszEmpty;
  152. WCHAR const *pwszName2;
  153. char *pszT = NULL;
  154. static WCHAR s_wszName[512];
  155. pszT = (char *) LocalAlloc(LMEM_FIXED, 1 + strlen(pszObjId) + 1);
  156. if (NULL == pszT)
  157. {
  158. hr = E_OUTOFMEMORY;
  159. _JumpError(hr, error, "LocalAlloc");
  160. }
  161. strcpy(&pszT[1], pszObjId);
  162. *pszT = '+';
  163. pwszName1 = myGetOIDNameA(pszT); // Group OID lookup
  164. *pszT = '-';
  165. pwszName2 = myGetOIDNameA(pszT); // Generic OID lookup
  166. if (0 == mylstrcmpiL(pwszName1, pwszName2))
  167. {
  168. pwszName2 = g_wszEmpty; // display only one if they're the same
  169. }
  170. if (L'\0' == *pwszName1)
  171. {
  172. pwszName1 = pwszName2;
  173. pwszName2 = g_wszEmpty;
  174. }
  175. if (L'\0' != *pwszName2 &&
  176. ARRAYSIZE(s_wszName) > wcslen(pwszName1) + wcslen(pwszName2) + 3)
  177. {
  178. wcscpy(s_wszName, pwszName1);
  179. wcscat(s_wszName, L" " wszLPAREN);
  180. wcscat(s_wszName, pwszName2);
  181. wcscat(s_wszName, wszRPAREN);
  182. pwszName1 = s_wszName;
  183. }
  184. error:
  185. if (NULL != pszT)
  186. {
  187. LocalFree(pszT);
  188. }
  189. return(pwszName1);
  190. }
  191. WCHAR const *
  192. cuGetOIDName(
  193. IN WCHAR const *pwszObjId)
  194. {
  195. HRESULT hr;
  196. char *pszObjId = NULL;
  197. WCHAR const *pwszName = g_wszEmpty;
  198. if (!myConvertWszToSz(&pszObjId, pwszObjId, -1))
  199. {
  200. hr = E_OUTOFMEMORY;
  201. _JumpError(hr, error, "myConvertWszToSz");
  202. }
  203. pwszName = cuGetOIDNameA(pszObjId);
  204. error:
  205. if (NULL != pszObjId)
  206. {
  207. LocalFree(pszObjId);
  208. }
  209. return(pwszName);
  210. }
  211. VOID
  212. cuDumpOIDAndDescriptionA(
  213. IN char const *pszObjId)
  214. {
  215. WCHAR const *pwsz;
  216. wprintf(L"%hs", pszObjId);
  217. pwsz = cuGetOIDNameA(pszObjId);
  218. if (NULL != pwsz && L'\0' != *pwsz)
  219. {
  220. wprintf(L" %ws", pwsz);
  221. }
  222. }
  223. VOID
  224. cuDumpOIDAndDescription(
  225. IN WCHAR const *pwszObjId)
  226. {
  227. WCHAR const *pwsz;
  228. wprintf(L"%ws", pwszObjId);
  229. pwsz = cuGetOIDName(pwszObjId);
  230. if (NULL != pwsz && L'\0' != *pwsz)
  231. {
  232. wprintf(L" %ws", pwsz);
  233. }
  234. }
  235. HRESULT
  236. cuCertNameToStr(
  237. IN BOOL fMultiLine,
  238. IN CERT_NAME_BLOB const *pNameBlob,
  239. OUT WCHAR **ppwszCertName)
  240. {
  241. HRESULT hr;
  242. DWORD Flags = CERT_X500_NAME_STR |
  243. CERT_NAME_STR_REVERSE_FLAG |
  244. CERT_NAME_STR_NO_QUOTING_FLAG;
  245. *ppwszCertName = NULL;
  246. if (fMultiLine)
  247. {
  248. Flags |= CERT_NAME_STR_CRLF_FLAG;
  249. }
  250. hr = myCertNameToStr(
  251. X509_ASN_ENCODING,
  252. pNameBlob,
  253. Flags,
  254. ppwszCertName);
  255. _JumpIfError(hr, error, "myCertNameToStr");
  256. error:
  257. return(hr);
  258. }
  259. typedef struct _RDNTABLE
  260. {
  261. CHAR const *pszObjId;
  262. DWORD cchMax;
  263. } RDNTABLE;
  264. RDNTABLE const g_RdnTable[] =
  265. {
  266. { szOID_COUNTRY_NAME, cchCOUNTRYNAMEMAX },
  267. { szOID_ORGANIZATION_NAME, cchORGANIZATIONNAMEMAX },
  268. { szOID_ORGANIZATIONAL_UNIT_NAME, cchORGANIZATIONALUNITNAMEMAX },
  269. { szOID_COMMON_NAME, cchCOMMONNAMEMAX },
  270. { szOID_LOCALITY_NAME, cchLOCALITYMANAMEMAX },
  271. { szOID_STATE_OR_PROVINCE_NAME, cchSTATEORPROVINCENAMEMAX },
  272. { szOID_TITLE, cchTITLEMAX },
  273. { szOID_GIVEN_NAME, cchGIVENNAMEMAX },
  274. { szOID_INITIALS, cchINITIALSMAX },
  275. { szOID_SUR_NAME, cchSURNAMEMAX },
  276. { szOID_DOMAIN_COMPONENT, cchDOMAINCOMPONENTMAX },
  277. { szOID_RSA_emailAddr, cchEMAILMAX },
  278. { szOID_STREET_ADDRESS, cchSTREETADDRESSMAX },
  279. { szOID_RSA_unstructName, cchUNSTRUCTUREDNAMEMAX },
  280. { szOID_RSA_unstructAddr, cchUNSTRUCTUREDADDRESSMAX },
  281. { szOID_DEVICE_SERIAL_NUMBER, cchDEVICESERIALNUMBERMAX },
  282. { NULL, 0 },
  283. };
  284. DWORD
  285. cwcRDNMax(
  286. IN char const *pszObjId)
  287. {
  288. RDNTABLE const *pRdnTable;
  289. DWORD cwcMax = MAXDWORD;
  290. for (pRdnTable = g_RdnTable; NULL != pRdnTable->pszObjId; pRdnTable++)
  291. {
  292. if (0 == strcmp(pszObjId, pRdnTable->pszObjId))
  293. {
  294. cwcMax = pRdnTable->cchMax;
  295. break;
  296. }
  297. }
  298. return(cwcMax);
  299. }
  300. HRESULT
  301. cuDisplayCertNameValue(
  302. OPTIONAL IN char const *pszObjId,
  303. OPTIONAL IN WCHAR const *pwszChoice,
  304. IN DWORD dwValueType,
  305. IN CRYPT_DATA_BLOB const *pValueW,
  306. IN CRYPT_DATA_BLOB const *pValueA)
  307. {
  308. HRESULT hr;
  309. DWORD cwc;
  310. DWORD cwcMax = MAXDWORD;
  311. CRYPT_DATA_BLOB ValueUTF8;
  312. ValueUTF8.pbData = NULL;
  313. cwc = pValueW->cbData / sizeof(WCHAR);
  314. if (NULL != pszObjId)
  315. {
  316. cwcMax = cwcRDNMax(pszObjId);
  317. }
  318. if (CERT_RDN_UTF8_STRING == dwValueType)
  319. {
  320. if (myConvertWszToUTF8(
  321. (char **) &ValueUTF8.pbData,
  322. (WCHAR const *) pValueW->pbData,
  323. pValueW->cbData / sizeof(WCHAR)))
  324. {
  325. ValueUTF8.cbData = strlen((CHAR const *) ValueUTF8.pbData);
  326. pValueA = &ValueUTF8;
  327. }
  328. }
  329. wprintf(
  330. L"%ws, %ws = %u",
  331. wszRDNValueType(dwValueType),
  332. myLoadResourceString(IDS_LENGTH), // "Length"
  333. pValueA->cbData);
  334. if (MAXDWORD != cwcMax || CERT_RDN_OCTET_STRING != dwValueType)
  335. {
  336. wprintf(
  337. L" " wszLPAREN L"%ws%ws%u",
  338. cwc <= cwcMax? g_wszEmpty : myLoadResourceString(IDS_OVERFLOW), // "OVERFLOW:"
  339. cwc <= cwcMax? g_wszEmpty : L" ",
  340. cwc);
  341. if (NULL != pszObjId && MAXDWORD != cwcMax)
  342. {
  343. wprintf(L"/%u", cwcMax);
  344. }
  345. wprintf(
  346. L" %ws" wszRPAREN,
  347. myLoadResourceString(IDS_CHARS)); // "Characters"
  348. }
  349. wprintf(wszNewLine);
  350. wprintf(g_wszPad8);
  351. if (NULL != pszObjId)
  352. {
  353. cuDumpOIDAndDescriptionA(pszObjId);
  354. wprintf(L"=");
  355. }
  356. else if (NULL != pwszChoice)
  357. {
  358. wprintf(L"%ws=", pwszChoice);
  359. }
  360. if (CERT_RDN_OCTET_STRING != dwValueType)
  361. {
  362. wprintf(L"\"%ws\"\n", pValueW->pbData);
  363. }
  364. wprintf(wszNewLine);
  365. DumpHex(
  366. DH_NOADDRESS | DH_NOTABPREFIX | 8,
  367. pValueA->pbData,
  368. pValueA->cbData);
  369. if (pValueA->cbData != pValueW->cbData ||
  370. 0 != memcmp(pValueA->pbData, pValueW->pbData, pValueW->cbData))
  371. {
  372. wprintf(wszNewLine);
  373. DumpHex(
  374. DH_NOADDRESS | DH_NOTABPREFIX | 8,
  375. pValueW->pbData,
  376. pValueW->cbData);
  377. }
  378. hr = S_OK;
  379. //error:
  380. if (NULL != ValueUTF8.pbData)
  381. {
  382. LocalFree(ValueUTF8.pbData);
  383. }
  384. return(hr);
  385. }
  386. HRESULT
  387. cuDisplayCertName(
  388. IN BOOL fMultiLine,
  389. OPTIONAL IN WCHAR const *pwszNamePrefix,
  390. OPTIONAL IN WCHAR const *pwszName,
  391. IN WCHAR const *pwszPad,
  392. IN CERT_NAME_BLOB const *pNameBlob,
  393. OPTIONAL IN CERT_INFO const *pCertInfo)
  394. {
  395. WCHAR *pwszCertName = NULL;
  396. DWORD i;
  397. HRESULT hr = S_OK;
  398. CERT_NAME_INFO *pNameInfoA = NULL;
  399. CERT_NAME_INFO *pNameInfoW = NULL;
  400. WCHAR *pwszAltName = NULL;
  401. DWORD cb;
  402. hr = cuCertNameToStr(fMultiLine, pNameBlob, &pwszCertName);
  403. _JumpIfError(hr, error, "cuCertNameToStr");
  404. if (NULL != pwszNamePrefix)
  405. {
  406. wprintf(pwszNamePrefix);
  407. }
  408. if (NULL != pwszName)
  409. {
  410. wprintf(L"%ws:", pwszName);
  411. }
  412. wprintf(fMultiLine? L"\n%ws" : L" ", pwszPad);
  413. cuPrintCRLFString(pwszPad, pwszCertName);
  414. if (L'\0' == *pwszCertName)
  415. {
  416. wprintf(L"%ws", myLoadResourceString(IDS_PROP_EMPTY)); // "EMPTY"
  417. if (NULL != pCertInfo)
  418. {
  419. CERT_EXTENSION const *pExt;
  420. pExt = CertFindExtension(
  421. szOID_SUBJECT_ALT_NAME2,
  422. pCertInfo->cExtension,
  423. pCertInfo->rgExtension);
  424. if (NULL != pExt)
  425. {
  426. if (!CryptFormatObject(
  427. X509_ASN_ENCODING,
  428. 0,
  429. CRYPT_FORMAT_STR_NO_HEX,
  430. NULL,
  431. pExt->pszObjId,
  432. pExt->Value.pbData,
  433. pExt->Value.cbData,
  434. NULL,
  435. &cb))
  436. {
  437. hr = myHLastError();
  438. _PrintError(hr, "CryptFormatObject");
  439. if (S_OK == hr)
  440. {
  441. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  442. }
  443. }
  444. else
  445. {
  446. pwszAltName = (WCHAR *) LocalAlloc(LMEM_FIXED, cb);
  447. if (NULL == pwszAltName)
  448. {
  449. hr = E_OUTOFMEMORY;
  450. _JumpError(hr, error, "LocalAlloc");
  451. }
  452. if (!CryptFormatObject(
  453. X509_ASN_ENCODING,
  454. 0,
  455. CRYPT_FORMAT_STR_NO_HEX,
  456. NULL,
  457. pExt->pszObjId,
  458. pExt->Value.pbData,
  459. pExt->Value.cbData,
  460. pwszAltName,
  461. &cb))
  462. {
  463. hr = myHLastError();
  464. _JumpError(hr, error, "CryptFormatObject");
  465. }
  466. wprintf(L" (%ws)", pwszAltName);
  467. }
  468. }
  469. }
  470. }
  471. wprintf(wszNewLine);
  472. if (1 < g_fVerbose)
  473. {
  474. DumpHex(
  475. DH_NOTABPREFIX | 4,
  476. pNameBlob->pbData,
  477. pNameBlob->cbData);
  478. wprintf(wszNewLine);
  479. }
  480. if (!myDecodeName(
  481. X509_ASN_ENCODING,
  482. X509_UNICODE_NAME,
  483. pNameBlob->pbData,
  484. pNameBlob->cbData,
  485. CERTLIB_USE_LOCALALLOC,
  486. &pNameInfoW,
  487. &cb))
  488. {
  489. hr = myHLastError();
  490. _JumpError(hr, error, "myDecodeName");
  491. }
  492. if (!myDecodeName(
  493. X509_ASN_ENCODING,
  494. X509_NAME,
  495. pNameBlob->pbData,
  496. pNameBlob->cbData,
  497. CERTLIB_USE_LOCALALLOC,
  498. &pNameInfoA,
  499. &cb))
  500. {
  501. hr = myHLastError();
  502. _JumpError(hr, error, "myDecodeName");
  503. }
  504. if (g_fVerbose)
  505. {
  506. for (i = 0; i < pNameInfoW->cRDN; i++)
  507. {
  508. CERT_RDN const *prdnA;
  509. CERT_RDN const *prdnW;
  510. DWORD j;
  511. prdnA = &pNameInfoA->rgRDN[i];
  512. prdnW = &pNameInfoW->rgRDN[i];
  513. for (j = 0; j < prdnW->cRDNAttr; j++)
  514. {
  515. CERT_RDN_ATTR const *prdnaA;
  516. CERT_RDN_ATTR const *prdnaW;
  517. prdnaA = &prdnA->rgRDNAttr[j];
  518. prdnaW = &prdnW->rgRDNAttr[j];
  519. wprintf(L" [%u,%u]: ", i, j);
  520. hr = cuDisplayCertNameValue(
  521. prdnaW->pszObjId,
  522. NULL,
  523. prdnaW->dwValueType,
  524. &prdnaW->Value,
  525. &prdnaA->Value);
  526. _PrintIfError(hr, "cuDisplayCertNameValue");
  527. wprintf(wszNewLine);
  528. }
  529. }
  530. }
  531. error:
  532. if (NULL != pwszCertName)
  533. {
  534. LocalFree(pwszCertName);
  535. }
  536. if (NULL != pwszAltName)
  537. {
  538. LocalFree(pwszAltName);
  539. }
  540. if (NULL != pNameInfoW)
  541. {
  542. LocalFree(pNameInfoW);
  543. }
  544. if (NULL != pNameInfoA)
  545. {
  546. LocalFree(pNameInfoA);
  547. }
  548. return(hr);
  549. }
  550. HRESULT
  551. cuDisplayCertNames(
  552. IN BOOL fMultiLine,
  553. OPTIONAL IN WCHAR const *pwszNamePrefix,
  554. IN CERT_INFO const *pCertInfo)
  555. {
  556. HRESULT hr;
  557. hr = cuDisplayCertName(
  558. fMultiLine,
  559. pwszNamePrefix,
  560. myLoadResourceString(IDS_ISSUER), // "Issuer"
  561. g_wszPad4,
  562. &pCertInfo->Issuer,
  563. NULL);
  564. _JumpIfError(hr, error, "cuDisplayCertName(Issuer)");
  565. hr = cuDisplayCertName(
  566. fMultiLine,
  567. pwszNamePrefix,
  568. myLoadResourceString(IDS_SUBJECT), // "Subject"
  569. g_wszPad4,
  570. &pCertInfo->Subject,
  571. pCertInfo);
  572. _JumpIfError(hr, error, "cuDisplayCertName(Subject)");
  573. error:
  574. return(hr);
  575. }
  576. #define POLICY_MASK \
  577. (EXTENSION_POLICY_MASK & ~(EXTENSION_CRITICAL_FLAG | EXTENSION_DISABLE_FLAG))
  578. #define EXTRA_MASK (~(EXTENSION_POLICY_MASK | EXTENSION_ORIGIN_MASK))
  579. WCHAR const *
  580. cuwszFromExtFlags(
  581. DWORD ExtFlags)
  582. {
  583. static WCHAR awc[MAX_PATH];
  584. WCHAR const *pwszComma;
  585. WCHAR const *pwszSep = wszLPAREN;
  586. DWORD msgid;
  587. WCHAR const *pwszT;
  588. awc[0] = L'\0';
  589. pwszComma = myLoadResourceString(IDS_SEPARATOR); // ", "
  590. if (NULL == pwszComma)
  591. {
  592. pwszComma = L", ";
  593. }
  594. if (EXTENSION_CRITICAL_FLAG & ExtFlags)
  595. {
  596. wcscat(awc, pwszSep);
  597. pwszSep = pwszComma;
  598. pwszT = myLoadResourceString(IDS_CRITICAL); // "Critical"
  599. if (NULL != pwszT)
  600. {
  601. wcscat(awc, pwszT);
  602. }
  603. }
  604. if (~EXTENSION_CRITICAL_FLAG & ExtFlags)
  605. {
  606. if (EXTENSION_DISABLE_FLAG & ExtFlags)
  607. {
  608. wcscat(awc, pwszSep);
  609. pwszSep = pwszComma;
  610. pwszT = myLoadResourceString(IDS_DISABLED); // "Disabled"
  611. if (NULL != pwszT)
  612. {
  613. wcscat(awc, pwszT);
  614. }
  615. }
  616. if (POLICY_MASK & ExtFlags)
  617. {
  618. wcscat(awc, pwszSep);
  619. pwszSep = pwszComma;
  620. pwszT = myLoadResourceString(IDS_FORMAT_POLICYFLAGS); // "PolicyFlags=%x"
  621. if (NULL == pwszT)
  622. {
  623. pwszT = L"PolicyFlags=%x";
  624. }
  625. wsprintf(&awc[wcslen(awc)], pwszT, POLICY_MASK & ExtFlags);
  626. }
  627. switch (EXTENSION_ORIGIN_MASK & ExtFlags)
  628. {
  629. case EXTENSION_ORIGIN_REQUEST:
  630. msgid = IDS_REQUEST; // "Request"
  631. break;
  632. case EXTENSION_ORIGIN_POLICY:
  633. msgid = IDS_POLICY; // "Policy"
  634. break;
  635. case EXTENSION_ORIGIN_ADMIN:
  636. msgid = IDS_ADMIN; // "Admin"
  637. break;
  638. case EXTENSION_ORIGIN_SERVER:
  639. msgid = IDS_SERVER; // "Server"
  640. break;
  641. case EXTENSION_ORIGIN_RENEWALCERT:
  642. msgid = IDS_RENEWALCERT; // "Renewal Cert"
  643. break;
  644. case EXTENSION_ORIGIN_IMPORTEDCERT:
  645. msgid = IDS_IMPORTEDCERT; // "Imported Cert"
  646. break;
  647. case EXTENSION_ORIGIN_PKCS7:
  648. msgid = IDS_PKCS7ATTRIBUTE; // "PKCS7 Attribute"
  649. break;
  650. case EXTENSION_ORIGIN_CMC:
  651. msgid = IDS_CMCATTRIBUTE; // "CMC Attribute"
  652. break;
  653. case EXTENSION_ORIGIN_CACERT:
  654. msgid = IDS_CACERTEXT; // "CA Cert"
  655. break;
  656. default:
  657. msgid = IDS_UNKNOWN; // "UNKNOWN"
  658. break;
  659. }
  660. wcscat(awc, pwszSep);
  661. pwszSep = pwszComma;
  662. pwszT = myLoadResourceString(IDS_FORMAT_ORIGIN); // "Origin=%ws"
  663. if (NULL == pwszT)
  664. {
  665. pwszT = L"Origin=%ws";
  666. }
  667. wsprintf(&awc[wcslen(awc)], pwszT, myLoadResourceString(msgid));
  668. if (EXTRA_MASK & ExtFlags)
  669. {
  670. wcscat(awc, pwszSep);
  671. pwszT = myLoadResourceString(IDS_FORMAT_UNKNOWN_HEX); // "???=%x"
  672. if (NULL == pwszT)
  673. {
  674. pwszT = L"???=%x";
  675. }
  676. wsprintf(&awc[wcslen(awc)], pwszT, EXTRA_MASK & ExtFlags);
  677. }
  678. }
  679. if (L'\0' != awc[0])
  680. {
  681. wcscat(awc, wszRPAREN);
  682. }
  683. return(awc);
  684. }
  685. VOID
  686. PrintStringWithPrefix(
  687. IN WCHAR const *pwszPrefix,
  688. IN WCHAR const *pwszIn)
  689. {
  690. while (L'\0' != *pwszIn)
  691. {
  692. DWORD i;
  693. DWORD j;
  694. WCHAR const *pwszNewLine;
  695. pwszNewLine = g_wszEmpty;
  696. j = 0;
  697. i = wcscspn(pwszIn, L"\n");
  698. if (L'\n' == pwszIn[i])
  699. {
  700. pwszNewLine = L"\n";
  701. j++;
  702. if (0 < i && L'\r' == pwszIn[i - 1])
  703. {
  704. i--;
  705. j++;
  706. }
  707. }
  708. wprintf(L"%ws%.*ws%ws", pwszPrefix, i, pwszIn, pwszNewLine);
  709. pwszIn += i + j;
  710. }
  711. }
  712. WCHAR const *
  713. wszAltNameChoice(
  714. IN LONG Choice)
  715. {
  716. WCHAR const *pwsz;
  717. switch (Choice)
  718. {
  719. case CERT_ALT_NAME_OTHER_NAME:
  720. pwsz = L"CERT_ALT_NAME_OTHER_NAME";
  721. break;
  722. case CERT_ALT_NAME_RFC822_NAME:
  723. pwsz = L"CERT_ALT_NAME_RFC822_NAME";
  724. break;
  725. case CERT_ALT_NAME_DNS_NAME:
  726. pwsz = L"CERT_ALT_NAME_DNS_NAME";
  727. break;
  728. case CERT_ALT_NAME_X400_ADDRESS:
  729. pwsz = L"CERT_ALT_NAME_X400_ADDRESS";
  730. break;
  731. case CERT_ALT_NAME_DIRECTORY_NAME:
  732. pwsz = L"CERT_ALT_NAME_DIRECTORY_NAME";
  733. break;
  734. case CERT_ALT_NAME_EDI_PARTY_NAME:
  735. pwsz = L"CERT_ALT_NAME_EDI_PARTY_NAME";
  736. break;
  737. case CERT_ALT_NAME_URL:
  738. pwsz = L"CERT_ALT_NAME_URL";
  739. break;
  740. case CERT_ALT_NAME_IP_ADDRESS:
  741. pwsz = L"CERT_ALT_NAME_IP_ADDRESS";
  742. break;
  743. case CERT_ALT_NAME_REGISTERED_ID:
  744. pwsz = L"CERT_ALT_NAME_REGISTERED_ID";
  745. break;
  746. default:
  747. pwsz = myLoadResourceString(IDS_QUESTIONMARKS); // "???"
  748. break;
  749. }
  750. return(pwsz);
  751. }
  752. HRESULT
  753. DumpIPAddress(
  754. IN WCHAR const *pwszPad,
  755. IN UINT idsMsg,
  756. IN BYTE const *pb,
  757. IN DWORD cb)
  758. {
  759. HRESULT hr;
  760. if (CB_IPV6ADDRESS != cb && CB_IPV4ADDRESS != cb)
  761. {
  762. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  763. _JumpError(hr, error, "IPAddress size");
  764. }
  765. wprintf(L"%ws %ws = ", pwszPad, myLoadResourceString(idsMsg));
  766. if (CB_IPV6ADDRESS == cb)
  767. {
  768. BYTE abZero[CB_IPV6ADDRESS - CB_IPV4ADDRESS];
  769. ZeroMemory(abZero, sizeof(abZero));
  770. if (0 == memcmp(abZero, pb, sizeof(abZero)))
  771. {
  772. wprintf(L"::");
  773. pb += sizeof(abZero);
  774. cb = CB_IPV4ADDRESS;
  775. CSASSERT(CB_IPV6ADDRESS - sizeof(abZero) == cb);
  776. }
  777. else
  778. {
  779. DWORD j;
  780. WCHAR const *pwsz = L"";
  781. BOOL fZeroSeen = FALSE;
  782. BOOL fZero = FALSE;
  783. for (j = 0; j < cb / sizeof(USHORT); j++)
  784. {
  785. USHORT us =
  786. (pb[sizeof(USHORT) * j] << 8) |
  787. pb[sizeof(USHORT) * j + 1];
  788. if (0 == us && (fZero || !fZeroSeen))
  789. {
  790. fZero = TRUE;
  791. fZeroSeen = TRUE;
  792. pwsz = L"::";
  793. }
  794. else
  795. {
  796. wprintf(L"%ws%04x", pwsz, us);
  797. pwsz = L":";
  798. fZero = FALSE;
  799. }
  800. }
  801. if (fZero)
  802. {
  803. wprintf(L"%ws", pwsz);
  804. CSASSERT(0 == lstrcmp(pwsz, L"::"));
  805. }
  806. }
  807. }
  808. if (CB_IPV4ADDRESS == cb)
  809. {
  810. wprintf(
  811. L"%u.%u.%u.%u",
  812. pb[0],
  813. pb[1],
  814. pb[2],
  815. pb[3]);
  816. }
  817. wprintf(wszNewLine);
  818. hr = S_OK;
  819. error:
  820. return(hr);
  821. }
  822. HRESULT
  823. DumpAltName(
  824. IN WCHAR const *pwszPad,
  825. IN DWORD dwSubtreeIndex,
  826. IN BYTE const *pbExtension,
  827. IN DWORD cbExtension)
  828. {
  829. HRESULT hr;
  830. BSTR strExtension = NULL;
  831. BSTR strObjId = NULL;
  832. BSTR strName = NULL;
  833. ICertEncodeAltName *pAltName = NULL;
  834. CRYPT_DATA_BLOB *pBlob = NULL;
  835. LONG Count;
  836. LONG Choice;
  837. LONG i;
  838. DWORD cb;
  839. hr = CoCreateInstance(
  840. CLSID_CCertEncodeAltName,
  841. NULL, // pUnkOuter
  842. CLSCTX_INPROC_SERVER,
  843. IID_ICertEncodeAltName,
  844. (VOID **) &pAltName);
  845. _JumpIfError(hr, error, "CoCreateInstance");
  846. if (!ConvertWszToBstr(
  847. &strExtension,
  848. (WCHAR const *) pbExtension,
  849. cbExtension))
  850. {
  851. hr = E_OUTOFMEMORY;
  852. _JumpError(hr, error, "ConvertWszToBstr");
  853. }
  854. hr = pAltName->Decode(strExtension);
  855. _JumpIfError(hr, error, "Decode");
  856. hr = pAltName->GetNameCount(&Count);
  857. _JumpIfError(hr, error, "GetNameCount");
  858. if (MAXDWORD == dwSubtreeIndex)
  859. {
  860. wprintf(pwszPad);
  861. wprintf(
  862. myLoadResourceString(IDS_FORMAT_ALTNAMECOUNT), // "AltName: %u entries:"
  863. Count);
  864. wprintf(wszNewLine);
  865. }
  866. for (i = 0; i < Count; i++)
  867. {
  868. BOOL fHex = FALSE;
  869. BOOL fNameBlob = FALSE;
  870. hr = pAltName->GetNameChoice(i, &Choice);
  871. _JumpIfError(hr, error, "GetNameChoice");
  872. if (NULL != strName)
  873. {
  874. SysFreeString(strName);
  875. strName = NULL;
  876. }
  877. hr = pAltName->GetName(i, &strName);
  878. _JumpIfError(hr, error, "GetName");
  879. myRegisterMemAlloc(strName, -1, CSM_SYSALLOC);
  880. wprintf(pwszPad);
  881. if (MAXDWORD == dwSubtreeIndex)
  882. {
  883. wprintf(
  884. L"%ws[%u] ",
  885. myLoadResourceString(IDS_ALTNAME), // "AltName"
  886. i);
  887. }
  888. wprintf(L"%ws:", wszAltNameChoice(Choice));
  889. if (CERT_ALT_NAME_DIRECTORY_NAME == Choice)
  890. {
  891. fNameBlob = TRUE; // Name is encoded as a blob
  892. }
  893. else if (CERT_ALT_NAME_IP_ADDRESS == Choice)
  894. {
  895. BYTE const *pb = (BYTE const *) strName;
  896. cb = SysStringByteLen(strName);
  897. wprintf(wszNewLine);
  898. if (2 * CB_IPV6ADDRESS == cb || 2 * CB_IPV4ADDRESS == cb)
  899. {
  900. DumpIPAddress(pwszPad, IDS_IPADDRESS, pb, cb / 2);
  901. DumpIPAddress(pwszPad, IDS_MASK, &pb[cb / 2], cb / 2);
  902. }
  903. else
  904. {
  905. fHex = TRUE;
  906. }
  907. }
  908. else if (CERT_ALT_NAME_OTHER_NAME == Choice)
  909. {
  910. if (NULL != strObjId)
  911. {
  912. SysFreeString(strObjId);
  913. strObjId = NULL;
  914. }
  915. hr = pAltName->GetName(EAN_NAMEOBJECTID | i, &strObjId);
  916. _JumpIfError(hr, error, "GetName");
  917. myRegisterMemAlloc(strObjId, -1, CSM_SYSALLOC);
  918. wprintf(L" ");
  919. cuDumpOIDAndDescription(strObjId);
  920. wprintf(L": ");
  921. if (0 == lstrcmp(TEXT(szOID_NT_PRINCIPAL_NAME), strObjId) ||
  922. BER_UTF8_STRING == *(BYTE const *) strName ||
  923. BER_UNICODE_STRING == *(BYTE const *) strName)
  924. {
  925. CERT_NAME_VALUE *pNameValueA = NULL;
  926. CERT_NAME_VALUE *pNameValueW = NULL;
  927. if (!myDecodeObject(
  928. X509_ASN_ENCODING,
  929. X509_ANY_STRING,
  930. (BYTE *) strName,
  931. SysStringByteLen(strName),
  932. CERTLIB_USE_LOCALALLOC,
  933. (VOID **) &pNameValueA,
  934. &cb))
  935. {
  936. hr = myHLastError();
  937. _PrintError(hr, "myDecodeObject");
  938. CSASSERT(NULL == pNameValueA);
  939. }
  940. if (!myDecodeObject(
  941. X509_ASN_ENCODING,
  942. X509_UNICODE_ANY_STRING,
  943. (BYTE *) strName,
  944. SysStringByteLen(strName),
  945. CERTLIB_USE_LOCALALLOC,
  946. (VOID **) &pNameValueW,
  947. &cb))
  948. {
  949. hr = myHLastError();
  950. _PrintError(hr, "myDecodeObject");
  951. CSASSERT(NULL == pNameValueW);
  952. }
  953. if (NULL != pNameValueA && NULL != pNameValueW)
  954. {
  955. wprintf(wszNewLine);
  956. wprintf(L"%ws ", pwszPad);
  957. hr = cuDisplayCertNameValue(
  958. NULL,
  959. NULL, // wszAltNameChoice(Choice),
  960. pNameValueW->dwValueType,
  961. &pNameValueW->Value,
  962. &pNameValueA->Value);
  963. _PrintIfError(hr, "cuDisplayCertNameValue");
  964. wprintf(wszNewLine);
  965. }
  966. if (NULL != pNameValueA)
  967. {
  968. LocalFree(pNameValueA);
  969. }
  970. if (NULL != pNameValueW)
  971. {
  972. LocalFree(pNameValueW);
  973. }
  974. }
  975. else
  976. if (0 == lstrcmp(TEXT(szOID_NTDS_REPLICATION), strObjId) ||
  977. BER_OCTET_STRING == *(BYTE const *) strName)
  978. {
  979. fHex = TRUE;
  980. if (myDecodeObject(
  981. X509_ASN_ENCODING,
  982. X509_OCTET_STRING,
  983. (BYTE const *) strName,
  984. SysStringByteLen(strName),
  985. CERTLIB_USE_LOCALALLOC,
  986. (VOID **) &pBlob,
  987. &cb))
  988. {
  989. if (0 == lstrcmp(TEXT(szOID_NTDS_REPLICATION), strObjId) &&
  990. pBlob->cbData == sizeof(GUID))
  991. {
  992. WCHAR *pwsz;
  993. hr = myCLSIDToWsz((CLSID const *) pBlob->pbData, &pwsz);
  994. if (S_OK == hr)
  995. {
  996. wprintf(L"\n%ws %ws\n", pwszPad, pwsz);
  997. LocalFree(pwsz);
  998. fHex = FALSE;
  999. }
  1000. }
  1001. if (fHex)
  1002. {
  1003. wprintf(wszNewLine);
  1004. DumpHex(
  1005. DH_NOTABPREFIX | 8,
  1006. pBlob->pbData,
  1007. pBlob->cbData);
  1008. wprintf(wszNewLine);
  1009. fHex = FALSE;
  1010. }
  1011. }
  1012. }
  1013. else
  1014. {
  1015. fHex = TRUE;
  1016. }
  1017. }
  1018. else
  1019. {
  1020. wprintf(L" \"%ws\"\n", strName);
  1021. }
  1022. if (fNameBlob)
  1023. {
  1024. CERT_NAME_BLOB Name;
  1025. Name.pbData = (BYTE *) strName;
  1026. Name.cbData = SysStringByteLen(strName);
  1027. hr = cuDisplayCertName(
  1028. TRUE,
  1029. NULL,
  1030. NULL, // wszAltNameChoice(Choice)
  1031. g_wszPad8,
  1032. &Name,
  1033. NULL);
  1034. _PrintIfError(hr, "cuDisplayCertName(DirectoryName)");
  1035. if (S_OK != hr)
  1036. {
  1037. fHex = TRUE;
  1038. }
  1039. }
  1040. if (fHex)
  1041. {
  1042. wprintf(wszNewLine);
  1043. DumpHex(
  1044. DH_NOTABPREFIX | 8,
  1045. (BYTE *) strName,
  1046. SysStringByteLen(strName));
  1047. wprintf(wszNewLine);
  1048. }
  1049. }
  1050. error:
  1051. if (NULL != pBlob)
  1052. {
  1053. LocalFree(pBlob);
  1054. }
  1055. if (NULL != strObjId)
  1056. {
  1057. SysFreeString(strObjId);
  1058. }
  1059. if (NULL != strName)
  1060. {
  1061. SysFreeString(strName);
  1062. }
  1063. if (NULL != strExtension)
  1064. {
  1065. SysFreeString(strExtension);
  1066. }
  1067. if (NULL != pAltName)
  1068. {
  1069. pAltName->Release();
  1070. }
  1071. return(hr);
  1072. }
  1073. HRESULT
  1074. DumpGeneralSubTree(
  1075. IN UINT idsMsg,
  1076. IN DWORD cSubtree,
  1077. IN CERT_GENERAL_SUBTREE const *rgSubtree)
  1078. {
  1079. HRESULT hr;
  1080. HRESULT hr2;
  1081. DWORD i;
  1082. CERT_ALT_NAME_INFO cani;
  1083. BYTE *pb = NULL;
  1084. DWORD cb;
  1085. wprintf(L" %ws:\n", myLoadResourceString(idsMsg));
  1086. hr = S_OK;
  1087. for (i = 0; i < cSubtree; i++)
  1088. {
  1089. wprintf(
  1090. L" %ws[%u]: " wszLPAREN L"%u...",
  1091. myLoadResourceString(IDS_SUBTREE),
  1092. i,
  1093. rgSubtree[i].dwMinimum);
  1094. wprintf(
  1095. rgSubtree[i].fMaximum? L"%u" : L"Max",
  1096. rgSubtree[i].dwMaximum);
  1097. wprintf(wszRPAREN L"\n");
  1098. cani.cAltEntry = 1;
  1099. cani.rgAltEntry = const_cast<CERT_ALT_NAME_ENTRY *>(&rgSubtree[i].Base);
  1100. if (!myEncodeObject(
  1101. X509_ASN_ENCODING,
  1102. X509_ALTERNATE_NAME,
  1103. &cani,
  1104. 0,
  1105. CERTLIB_USE_LOCALALLOC,
  1106. &pb, // pbEncoded
  1107. &cb))
  1108. {
  1109. hr = myHLastError();
  1110. _JumpError(hr, error, "myEncodeObject");
  1111. }
  1112. hr2 = DumpAltName(g_wszPad6, i, pb, cb);
  1113. _PrintIfError(hr2, "DumpAltName");
  1114. if (S_OK == hr)
  1115. {
  1116. hr = hr2;
  1117. }
  1118. LocalFree(pb);
  1119. pb = NULL;
  1120. }
  1121. _JumpIfError(hr, error, "DumpAltName");
  1122. error:
  1123. if (NULL != pb)
  1124. {
  1125. LocalFree(pb);
  1126. }
  1127. return(hr);
  1128. }
  1129. HRESULT
  1130. DumpNameConstraints(
  1131. IN BYTE const *pbExtension,
  1132. IN DWORD cbExtension)
  1133. {
  1134. HRESULT hr;
  1135. HRESULT hr2;
  1136. CERT_NAME_CONSTRAINTS_INFO *pnci = NULL;
  1137. DWORD cb;
  1138. if (!myDecodeObject(
  1139. X509_ASN_ENCODING,
  1140. X509_NAME_CONSTRAINTS,
  1141. pbExtension,
  1142. cbExtension,
  1143. CERTLIB_USE_LOCALALLOC,
  1144. (VOID **) &pnci,
  1145. &cb))
  1146. {
  1147. hr = myHLastError();
  1148. _JumpError(hr, error, "myDecodeObject");
  1149. }
  1150. hr = DumpGeneralSubTree(
  1151. IDS_PERMITTED,
  1152. pnci->cPermittedSubtree,
  1153. pnci->rgPermittedSubtree);
  1154. _PrintIfError(hr, "DumpGeneralSubTree");
  1155. hr2 = DumpGeneralSubTree(
  1156. IDS_EXCLUDED,
  1157. pnci->cExcludedSubtree,
  1158. pnci->rgExcludedSubtree);
  1159. _PrintIfError(hr2, "DumpGeneralSubTree");
  1160. if (S_OK == hr)
  1161. {
  1162. hr = hr2;
  1163. }
  1164. _JumpIfError(hr, error, "DumpGeneralSubTree");
  1165. error:
  1166. if (NULL != pnci)
  1167. {
  1168. LocalFree(pnci);
  1169. }
  1170. return(hr);
  1171. }
  1172. HRESULT
  1173. DumpOctetHash(
  1174. IN WCHAR const *pwszPad,
  1175. IN UINT idsDescription,
  1176. OPTIONAL IN WCHAR const *pwszCertutil,
  1177. IN BYTE const *pbIn,
  1178. IN DWORD cbIn,
  1179. OPTIONAL OUT BYTE *pbOut,
  1180. OPTIONAL IN OUT DWORD *pcbOut)
  1181. {
  1182. HRESULT hr;
  1183. CRYPT_DATA_BLOB aBlob[1 + BLOB_ROUND(CBMAX_CRYPT_HASH_LEN)];
  1184. DWORD cb;
  1185. BSTR strHash = NULL;
  1186. cb = sizeof(aBlob);
  1187. if (CryptDecodeObject(
  1188. X509_ASN_ENCODING,
  1189. X509_OCTET_STRING,
  1190. pbIn,
  1191. cbIn,
  1192. 0,
  1193. aBlob,
  1194. &cb))
  1195. {
  1196. if (NULL == pbOut)
  1197. {
  1198. wprintf(
  1199. L"%ws%ws%ws:\n",
  1200. pwszPad,
  1201. 0 != idsDescription?
  1202. myLoadResourceString(idsDescription) : g_wszEmpty,
  1203. NULL != pwszCertutil? pwszCertutil : g_wszEmpty);
  1204. hr = MultiByteIntegerToBstr(
  1205. TRUE,
  1206. aBlob[0].cbData,
  1207. aBlob[0].pbData,
  1208. &strHash);
  1209. _JumpIfError(hr, error, "MultiByteIntegerToBstr");
  1210. wprintf(L" %ws\n", strHash);
  1211. }
  1212. else
  1213. {
  1214. if (NULL == pcbOut)
  1215. {
  1216. hr = E_INVALIDARG;
  1217. _JumpError(hr, error, "NULL parm");
  1218. }
  1219. cb = *pcbOut;
  1220. *pcbOut = aBlob[0].cbData;
  1221. CopyMemory(pbOut, aBlob[0].pbData, min(cb, aBlob[0].cbData));
  1222. if (cb < aBlob[0].cbData)
  1223. {
  1224. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  1225. _JumpError(hr, error, "buffer too small");
  1226. }
  1227. }
  1228. }
  1229. hr = S_OK;
  1230. error:
  1231. if (NULL != strHash)
  1232. {
  1233. SysFreeString(strHash);
  1234. }
  1235. return(hr);
  1236. }
  1237. HRESULT
  1238. DumpHash(
  1239. OPTIONAL IN WCHAR const *pwszPrefix,
  1240. OPTIONAL IN DWORD idMessage,
  1241. OPTIONAL IN WCHAR const *pwszHashNamePrefix,
  1242. IN WCHAR const *pwszHashName,
  1243. IN BYTE const *pbHash,
  1244. IN DWORD cbHash)
  1245. {
  1246. HRESULT hr;
  1247. BSTR strHash = NULL;
  1248. WCHAR *pwsz = NULL;
  1249. if (NULL != pbHash)
  1250. {
  1251. hr = MultiByteIntegerToBstr(TRUE, cbHash, pbHash, &strHash);
  1252. _JumpIfError(hr, error, "MultiByteIntegerToBstr");
  1253. if (NULL != pwszPrefix)
  1254. {
  1255. wprintf(pwszPrefix);
  1256. }
  1257. if (0 != idMessage)
  1258. {
  1259. if (NULL != pwszHashNamePrefix)
  1260. {
  1261. DWORD cwc;
  1262. cwc = wcslen(pwszHashNamePrefix) + 1 + wcslen(pwszHashName);
  1263. pwsz = (WCHAR *) LocalAlloc(
  1264. LMEM_FIXED,
  1265. (cwc + 1) * sizeof(WCHAR));
  1266. if (NULL == pwsz)
  1267. {
  1268. hr = E_OUTOFMEMORY;
  1269. _JumpError(hr, error, "LocalAlloc");
  1270. }
  1271. wcscpy(pwsz, pwszHashNamePrefix);
  1272. wcscat(pwsz, L" ");
  1273. wcscat(pwsz, pwszHashName);
  1274. CSASSERT(wcslen(pwsz) == cwc);
  1275. pwszHashName = pwsz;
  1276. }
  1277. wprintf(myLoadResourceString(idMessage), pwszHashName, strHash);
  1278. }
  1279. else
  1280. {
  1281. wprintf(strHash);
  1282. }
  1283. wprintf(wszNewLine);
  1284. if (1 < g_fVerbose)
  1285. {
  1286. DumpHex(DH_NOTABPREFIX | 4, pbHash, cbHash);
  1287. wprintf(wszNewLine);
  1288. }
  1289. }
  1290. hr = S_OK;
  1291. error:
  1292. if (NULL != pwsz)
  1293. {
  1294. LocalFree(pwsz);
  1295. }
  1296. if (NULL != strHash)
  1297. {
  1298. SysFreeString(strHash);
  1299. }
  1300. return(hr);
  1301. }
  1302. #define FOT_EXTENSION 0
  1303. #define FOT_ATTRIBUTE 1
  1304. #define FOT_PROPERTY 2
  1305. BOOL
  1306. DumpFormattedObject(
  1307. IN char const *pszObjId,
  1308. IN DWORD Type, // FOT_*
  1309. IN BYTE const *pbObject,
  1310. IN DWORD cbObject)
  1311. {
  1312. HRESULT hr;
  1313. BOOL fDisplayed = FALSE;
  1314. WCHAR *pwszFormatted = NULL;
  1315. DWORD cbFormatted;
  1316. CRYPT_DATA_BLOB *pBlobProp = NULL;
  1317. DWORD cbBlobProp;
  1318. WCHAR const *pwszPrefix0 = g_wszPad4;
  1319. WCHAR const *pwszPrefix1 = g_wszPad8;
  1320. WCHAR const *pwszDescriptiveName;
  1321. // format the object using the installed formatting function
  1322. hr = S_OK;
  1323. if (!CryptFormatObject(
  1324. X509_ASN_ENCODING,
  1325. 0,
  1326. CRYPT_FORMAT_STR_MULTI_LINE | CRYPT_FORMAT_STR_NO_HEX,
  1327. NULL,
  1328. pszObjId,
  1329. pbObject,
  1330. cbObject,
  1331. NULL,
  1332. &cbFormatted))
  1333. {
  1334. hr = myHLastError();
  1335. _PrintErrorStr2(hr, pszObjId, L"CryptFormatObject", hr);
  1336. if (S_OK == hr)
  1337. {
  1338. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1339. }
  1340. }
  1341. if (S_OK != hr)
  1342. {
  1343. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr &&
  1344. CRYPT_E_ASN1_BADTAG != hr &&
  1345. CRYPT_E_ASN1_CORRUPT != hr)
  1346. {
  1347. _JumpError(hr, error, "CryptFormatObject");
  1348. }
  1349. if (FOT_PROPERTY == Type)
  1350. {
  1351. if (!myDecodeObject(
  1352. X509_ASN_ENCODING,
  1353. X509_OCTET_STRING,
  1354. pbObject,
  1355. cbObject,
  1356. CERTLIB_USE_LOCALALLOC,
  1357. (VOID **) &pBlobProp,
  1358. &cbBlobProp))
  1359. {
  1360. hr = myHLastError();
  1361. _PrintError(hr, "myDecodeObject");
  1362. }
  1363. else
  1364. {
  1365. hr = cuDumpFormattedProperty(
  1366. MAXDWORD,
  1367. pszObjId,
  1368. pBlobProp->pbData,
  1369. pBlobProp->cbData);
  1370. _PrintIfError(hr, "cuDumpFormattedProperty");
  1371. if (S_OK == hr)
  1372. {
  1373. fDisplayed = TRUE;
  1374. }
  1375. }
  1376. }
  1377. if (S_OK != hr && !g_fQuiet)
  1378. {
  1379. PrintStringWithPrefix(
  1380. pwszPrefix0,
  1381. myLoadResourceString(FOT_ATTRIBUTE == Type?
  1382. IDS_UNKNOWN_ATTRIBUTE : // "Unknown Attribute type"
  1383. (FOT_EXTENSION == Type?
  1384. IDS_UNKNOWN_EXTENSION : // "Unknown Extension type"
  1385. IDS_UNKNOWN_PROPERTY))); // "Unknown Property"
  1386. wprintf(wszNewLine);
  1387. }
  1388. }
  1389. else
  1390. {
  1391. pwszFormatted = (WCHAR *) LocalAlloc(LMEM_FIXED, cbFormatted);
  1392. if (NULL == pwszFormatted)
  1393. {
  1394. hr = E_OUTOFMEMORY;
  1395. _JumpError(hr, error, "LocalAlloc");
  1396. }
  1397. if (!CryptFormatObject(
  1398. X509_ASN_ENCODING,
  1399. 0,
  1400. CRYPT_FORMAT_STR_MULTI_LINE | CRYPT_FORMAT_STR_NO_HEX,
  1401. NULL,
  1402. pszObjId,
  1403. pbObject,
  1404. cbObject,
  1405. pwszFormatted,
  1406. &cbFormatted))
  1407. {
  1408. hr = myHLastError();
  1409. _JumpErrorStr(hr, error, pszObjId, L"CryptFormatObject");
  1410. }
  1411. PrintStringWithPrefix(g_fQuiet? g_wszEmpty : pwszPrefix1, pwszFormatted);
  1412. fDisplayed = TRUE;
  1413. }
  1414. if (g_fVerbose)
  1415. {
  1416. if (0 == strcmp(szOID_SUBJECT_ALT_NAME, pszObjId) ||
  1417. 0 == strcmp(szOID_SUBJECT_ALT_NAME2, pszObjId) ||
  1418. 0 == strcmp(szOID_ISSUER_ALT_NAME, pszObjId) ||
  1419. 0 == strcmp(szOID_ISSUER_ALT_NAME2, pszObjId))
  1420. {
  1421. DumpAltName(g_wszPad4, MAXDWORD, pbObject, cbObject);
  1422. }
  1423. else
  1424. if (0 == strcmp(szOID_NAME_CONSTRAINTS, pszObjId))
  1425. {
  1426. DumpNameConstraints(pbObject, cbObject);
  1427. }
  1428. }
  1429. error:
  1430. if (NULL != pBlobProp)
  1431. {
  1432. LocalFree(pBlobProp);
  1433. }
  1434. if (NULL != pwszFormatted)
  1435. {
  1436. LocalFree(pwszFormatted);
  1437. }
  1438. return(fDisplayed);
  1439. }
  1440. HRESULT
  1441. cuDumpUsage(
  1442. OPTIONAL IN WCHAR const *pwszPrefix,
  1443. IN DWORD idMessage,
  1444. IN CTL_USAGE const *pUsage)
  1445. {
  1446. HRESULT hr;
  1447. DWORD i;
  1448. if (NULL == pwszPrefix)
  1449. {
  1450. pwszPrefix = L"";
  1451. }
  1452. wprintf(L"%ws", pwszPrefix);
  1453. wprintf(myLoadResourceString(idMessage));
  1454. wprintf(L" %u\n", pUsage->cUsageIdentifier);
  1455. for (i = 0; i < pUsage->cUsageIdentifier; i++)
  1456. {
  1457. wprintf(
  1458. L"%ws%ws[%d] ",
  1459. pwszPrefix,
  1460. g_wszPad2,
  1461. i);
  1462. cuDumpOIDAndDescriptionA(pUsage->rgpszUsageIdentifier[i]);
  1463. wprintf(wszNewLine);
  1464. }
  1465. hr = S_OK;
  1466. //error:
  1467. return(hr);
  1468. }
  1469. #ifndef XENROLL_PASS_THRU_PROP_ID
  1470. #define XENROLL_PASS_THRU_PROP_ID (CERT_FIRST_USER_PROP_ID + 0x100)
  1471. #endif
  1472. #ifndef XENROLL_RENEWAL_CERTIFICATE_PROP_ID
  1473. #define XENROLL_RENEWAL_CERTIFICATE_PROP_ID (CERT_FIRST_USER_PROP_ID + 0x101)
  1474. #endif
  1475. typedef struct _DUMPPROP
  1476. {
  1477. DWORD dwPropId;
  1478. WCHAR const *pwszDescription;
  1479. } DUMPPROP;
  1480. #define _DFPROP(def) { (def), L#def }
  1481. DUMPPROP s_apwszPropIds[] = {
  1482. _DFPROP(CERT_KEY_PROV_HANDLE_PROP_ID),
  1483. _DFPROP(CERT_KEY_PROV_INFO_PROP_ID),
  1484. _DFPROP(CERT_SHA1_HASH_PROP_ID),
  1485. _DFPROP(CERT_MD5_HASH_PROP_ID),
  1486. _DFPROP(CERT_KEY_CONTEXT_PROP_ID),
  1487. _DFPROP(CERT_KEY_SPEC_PROP_ID),
  1488. _DFPROP(CERT_IE30_RESERVED_PROP_ID),
  1489. _DFPROP(CERT_PUBKEY_HASH_RESERVED_PROP_ID),
  1490. _DFPROP(CERT_ENHKEY_USAGE_PROP_ID),
  1491. _DFPROP(CERT_NEXT_UPDATE_LOCATION_PROP_ID),
  1492. _DFPROP(CERT_FRIENDLY_NAME_PROP_ID),
  1493. _DFPROP(CERT_PVK_FILE_PROP_ID),
  1494. _DFPROP(CERT_DESCRIPTION_PROP_ID),
  1495. _DFPROP(CERT_ACCESS_STATE_PROP_ID),
  1496. _DFPROP(CERT_SIGNATURE_HASH_PROP_ID),
  1497. _DFPROP(CERT_SMART_CARD_DATA_PROP_ID),
  1498. _DFPROP(CERT_EFS_PROP_ID),
  1499. _DFPROP(CERT_FORTEZZA_DATA_PROP_ID),
  1500. _DFPROP(CERT_ARCHIVED_PROP_ID),
  1501. _DFPROP(CERT_KEY_IDENTIFIER_PROP_ID),
  1502. _DFPROP(CERT_AUTO_ENROLL_PROP_ID),
  1503. _DFPROP(CERT_PUBKEY_ALG_PARA_PROP_ID),
  1504. _DFPROP(CERT_CROSS_CERT_DIST_POINTS_PROP_ID),
  1505. _DFPROP(CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID),
  1506. _DFPROP(CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID),
  1507. _DFPROP(CERT_ENROLLMENT_PROP_ID),
  1508. _DFPROP(CERT_DATE_STAMP_PROP_ID),
  1509. _DFPROP(CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID),
  1510. _DFPROP(CERT_SUBJECT_NAME_MD5_HASH_PROP_ID),
  1511. _DFPROP(CERT_EXTENDED_ERROR_INFO_PROP_ID),
  1512. _DFPROP(XENROLL_PASS_THRU_PROP_ID),
  1513. _DFPROP(XENROLL_RENEWAL_CERTIFICATE_PROP_ID),
  1514. };
  1515. HRESULT
  1516. cuDecodeBool(
  1517. IN BYTE const *pbIn,
  1518. IN DWORD cbIn,
  1519. OUT BOOL *pfWriteToDS)
  1520. {
  1521. HRESULT hr;
  1522. hr = E_INVALIDARG;
  1523. if (3 == cbIn && BER_BOOL == pbIn[0] && 1 == pbIn[1])
  1524. {
  1525. *pfWriteToDS = FALSE;
  1526. if (0 != pbIn[2])
  1527. {
  1528. if (0xff != pbIn[2])
  1529. {
  1530. _PrintError(hr, "BER_BOOL");
  1531. }
  1532. *pfWriteToDS = TRUE;
  1533. }
  1534. hr = S_OK;
  1535. }
  1536. return(hr);
  1537. }
  1538. HRESULT
  1539. DecodeRequestFlags(
  1540. IN BYTE const *pbIn,
  1541. IN DWORD cbIn,
  1542. OUT BOOL *pfWriteToCSP,
  1543. OUT BOOL *pfWriteToDS,
  1544. OUT DWORD *popenFlags)
  1545. {
  1546. HRESULT hr;
  1547. CRYPT_SEQUENCE_OF_ANY *pSeq = NULL;
  1548. DWORD cb;
  1549. hr = cuDecodeSequence(pbIn, cbIn, 3, &pSeq);
  1550. _JumpIfError(hr, error, "cuDecodeSequence");
  1551. hr = cuDecodeBool(
  1552. pSeq->rgValue[0].pbData,
  1553. pSeq->rgValue[0].cbData,
  1554. pfWriteToCSP);
  1555. _JumpIfError(hr, error, "cuDecodeBool");
  1556. hr = cuDecodeBool(
  1557. pSeq->rgValue[1].pbData,
  1558. pSeq->rgValue[1].cbData,
  1559. pfWriteToDS);
  1560. _JumpIfError(hr, error, "cuDecodeBool");
  1561. cb = sizeof(*popenFlags);
  1562. *popenFlags = 0;
  1563. if (!CryptDecodeObject(
  1564. X509_ASN_ENCODING,
  1565. X509_INTEGER,
  1566. pSeq->rgValue[2].pbData,
  1567. pSeq->rgValue[2].cbData,
  1568. 0,
  1569. popenFlags,
  1570. &cb))
  1571. {
  1572. hr = myHLastError();
  1573. _JumpError(hr, error, "CryptDecodeObject");
  1574. }
  1575. hr = S_OK;
  1576. error:
  1577. if (NULL != pSeq)
  1578. {
  1579. LocalFree(pSeq);
  1580. }
  1581. return(hr);
  1582. }
  1583. HRESULT
  1584. cuDumpFormattedProperty(
  1585. IN DWORD dwPropId,
  1586. OPTIONAL IN char const *pszObjId,
  1587. IN BYTE const *pb,
  1588. IN DWORD cb)
  1589. {
  1590. HRESULT hr;
  1591. char szObjId[sizeof(szOID_CERT_PROP_ID_PREFIX) + 20];
  1592. WCHAR const *pwszDescriptiveName;
  1593. BOOL fDisplayed;
  1594. DWORD i;
  1595. CSASSERT(NULL == pszObjId || MAXDWORD == dwPropId);
  1596. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1597. if (NULL != pszObjId)
  1598. {
  1599. char const *psz;
  1600. if (0 != strncmp(
  1601. szOID_CERT_PROP_ID_PREFIX,
  1602. pszObjId,
  1603. ARRAYSIZE(szOID_CERT_PROP_ID_PREFIX) - 1))
  1604. {
  1605. _JumpError(hr, error, "Not a property ObjId");
  1606. }
  1607. psz = &pszObjId[ARRAYSIZE(szOID_CERT_PROP_ID_PREFIX) - 1];
  1608. dwPropId = atol(psz);
  1609. while ('\0' != *psz)
  1610. {
  1611. if (!isdigit(*psz))
  1612. {
  1613. _JumpError(hr, error, "Bad property ObjId suffix");
  1614. }
  1615. psz++;
  1616. }
  1617. }
  1618. wprintf(wszNewLine);
  1619. for (i = 0; ; i++)
  1620. {
  1621. if (i >= ARRAYSIZE(s_apwszPropIds))
  1622. {
  1623. pwszDescriptiveName = myLoadResourceString(IDS_UNKNOWN_PROPERTY); // "Unknown Property"
  1624. break;
  1625. }
  1626. if (s_apwszPropIds[i].dwPropId == dwPropId)
  1627. {
  1628. pwszDescriptiveName = s_apwszPropIds[i].pwszDescription;
  1629. break;
  1630. }
  1631. }
  1632. wprintf(L" %ws", pwszDescriptiveName);
  1633. if (NULL != pszObjId)
  1634. {
  1635. wprintf(L"(%hs)", pszObjId);
  1636. }
  1637. else
  1638. {
  1639. wprintf(L"(%u)", dwPropId);
  1640. }
  1641. sprintf(szObjId, "%hs%u", szOID_CERT_PROP_ID_PREFIX, dwPropId);
  1642. pwszDescriptiveName = cuGetOIDNameA(szObjId);
  1643. if (NULL != pwszDescriptiveName && L'\0' != *pwszDescriptiveName)
  1644. {
  1645. wprintf(L" %ws", pwszDescriptiveName);
  1646. }
  1647. wprintf(L":\n");
  1648. #if 0
  1649. fDisplayed = DumpFormattedObject(szObjId, FOT_PROPERTY, pb, cb);
  1650. #else
  1651. fDisplayed = FALSE;
  1652. #endif
  1653. if (!fDisplayed)
  1654. {
  1655. if (IS_CERT_HASH_PROP_ID(dwPropId) ||
  1656. IS_PUBKEY_HASH_PROP_ID(dwPropId) ||
  1657. IS_CHAIN_HASH_PROP_ID(dwPropId) ||
  1658. CERT_KEY_IDENTIFIER_PROP_ID == dwPropId)
  1659. {
  1660. wprintf(g_wszPad4);
  1661. hr = DumpHash(NULL, 0, NULL, g_wszEmpty, pb, cb);
  1662. _JumpIfError(hr, error, "DumpHash");
  1663. fDisplayed = TRUE;
  1664. }
  1665. else
  1666. if (CERT_FRIENDLY_NAME_PROP_ID == dwPropId ||
  1667. CERT_DESCRIPTION_PROP_ID == dwPropId)
  1668. {
  1669. wprintf(L"%ws%ws\n", g_wszPad4, pb);
  1670. fDisplayed = TRUE;
  1671. }
  1672. else
  1673. if (CERT_KEY_PROV_INFO_PROP_ID == dwPropId)
  1674. {
  1675. hr = cuDumpCertKeyProviderInfo(
  1676. g_wszPad4,
  1677. NULL,
  1678. (CRYPT_KEY_PROV_INFO *) pb,
  1679. NULL);
  1680. _JumpIfError(hr, error, "cuDumpCertKeyProviderInfo");
  1681. fDisplayed = TRUE;
  1682. }
  1683. else
  1684. if (CERT_AUTO_ENROLL_PROP_ID == dwPropId)
  1685. {
  1686. wprintf(
  1687. L"%ws%ws = %.*ws\n",
  1688. g_wszPad4,
  1689. myLoadResourceString(IDS_PROP_AUTOENROLL), // "AutoEnroll Property"
  1690. cb / sizeof(WCHAR),
  1691. pb);
  1692. fDisplayed = TRUE;
  1693. }
  1694. else
  1695. if (CERT_ENROLLMENT_PROP_ID == dwPropId)
  1696. {
  1697. BYTE const *pbTmp = pb;
  1698. DWORD cbTmp = cb;
  1699. DWORD cwc;
  1700. if (sizeof(LONG) <= cbTmp)
  1701. {
  1702. // RequestId:
  1703. wprintf(
  1704. L"%ws%ws = %u\n",
  1705. g_wszPad4,
  1706. myLoadResourceString(IDS_REQUESTID), // "RequestId"
  1707. *(LONG *) pbTmp);
  1708. pbTmp += sizeof(LONG);
  1709. cbTmp -= sizeof(LONG);
  1710. if (sizeof(cwc) <= cbTmp)
  1711. {
  1712. // CA DNS name:
  1713. cwc = *(DWORD *) pbTmp;
  1714. pbTmp += sizeof(cwc); // skip count of next field
  1715. cbTmp -= sizeof(cwc);
  1716. wprintf(
  1717. L"%ws%ws = %.*ws\\",
  1718. g_wszPad4,
  1719. myLoadResourceString(IDS_CADNSNAME), // "Authority"
  1720. min(cwc, cbTmp / sizeof(WCHAR)),
  1721. pbTmp);
  1722. pbTmp += cwc * sizeof(WCHAR);
  1723. cbTmp -= cwc * sizeof(WCHAR);
  1724. if (sizeof(cwc) <= cbTmp)
  1725. {
  1726. // CA name:
  1727. cwc = *(DWORD UNALIGNED *) pbTmp;
  1728. pbTmp += sizeof(cwc); // skip count of next field
  1729. cbTmp -= sizeof(cwc);
  1730. wprintf(
  1731. L"%.*ws\n",
  1732. min(cwc, cbTmp / sizeof(WCHAR)),
  1733. pbTmp);
  1734. pbTmp += cwc * sizeof(WCHAR);
  1735. cbTmp -= cwc * sizeof(WCHAR);
  1736. if (sizeof(cwc) <= cbTmp)
  1737. {
  1738. // friendly name:
  1739. cwc = *(DWORD UNALIGNED *) pbTmp;
  1740. pbTmp += sizeof(cwc); // skip count of next field
  1741. cbTmp -= sizeof(cwc);
  1742. wprintf(
  1743. L"%ws%ws = %.*ws\n",
  1744. g_wszPad4,
  1745. myLoadResourceString(IDS_FRIENDLYNAME), // "Friendly Name"
  1746. min(cwc, cbTmp / sizeof(WCHAR)),
  1747. pbTmp);
  1748. pbTmp += cwc * sizeof(WCHAR);
  1749. cbTmp -= cwc * sizeof(WCHAR);
  1750. fDisplayed = TRUE;
  1751. }
  1752. }
  1753. }
  1754. }
  1755. }
  1756. else
  1757. if (CERT_CTL_USAGE_PROP_ID == dwPropId)
  1758. {
  1759. CTL_USAGE *pUsage;
  1760. if (!myDecodeObject(
  1761. X509_ASN_ENCODING,
  1762. X509_ENHANCED_KEY_USAGE,
  1763. pb,
  1764. cb,
  1765. CERTLIB_USE_LOCALALLOC,
  1766. (VOID **) &pUsage,
  1767. &cb))
  1768. {
  1769. hr = myHLastError();
  1770. _PrintError(hr, "myDecodeObject");
  1771. }
  1772. else
  1773. {
  1774. hr = cuDumpUsage(g_wszPad2, IDS_USAGEENTRIES, pUsage);
  1775. _JumpIfError(hr, error, "cuDumpUsage");
  1776. fDisplayed = TRUE;
  1777. }
  1778. }
  1779. else
  1780. if (CERT_PUBKEY_ALG_PARA_PROP_ID == dwPropId)
  1781. {
  1782. CERT_DSS_PARAMETERS *pDssParms;
  1783. if (!myDecodeObject(
  1784. X509_ASN_ENCODING,
  1785. X509_DSS_PARAMETERS,
  1786. pb,
  1787. cb,
  1788. CERTLIB_USE_LOCALALLOC,
  1789. (VOID **) &pDssParms,
  1790. &cb))
  1791. {
  1792. hr = myHLastError();
  1793. _PrintError(hr, "myDecodeObject");
  1794. }
  1795. else
  1796. {
  1797. wprintf(
  1798. myLoadResourceString(IDS_FORMAT_DSSKEY_LENGTH), // "DSS Key Length: %u bits"
  1799. pDssParms->p.cbData * 8);
  1800. wprintf(L" DSS P:\n");
  1801. DumpHex(
  1802. DH_NOADDRESS | DH_NOTABPREFIX | 4,
  1803. pDssParms->p.pbData,
  1804. pDssParms->p.cbData);
  1805. wprintf(L" DSS Q:\n");
  1806. DumpHex(
  1807. DH_NOADDRESS | DH_NOTABPREFIX | 4,
  1808. pDssParms->q.pbData,
  1809. pDssParms->q.cbData);
  1810. wprintf(L" DSS G:\n");
  1811. DumpHex(
  1812. DH_NOADDRESS | DH_NOTABPREFIX | 4,
  1813. pDssParms->g.pbData,
  1814. pDssParms->g.cbData);
  1815. LocalFree(pDssParms);
  1816. fDisplayed = TRUE;
  1817. }
  1818. }
  1819. else
  1820. if (XENROLL_PASS_THRU_PROP_ID == dwPropId)
  1821. {
  1822. BOOL fWriteToCSP;
  1823. BOOL fWriteToDS;
  1824. DWORD openFlags;
  1825. hr = DecodeRequestFlags(
  1826. pb,
  1827. cb,
  1828. &fWriteToCSP,
  1829. &fWriteToDS,
  1830. &openFlags);
  1831. _PrintIfError(hr, "DecodeRequestFlags");
  1832. if (S_OK == hr)
  1833. {
  1834. wprintf(L" fWriteToCSP: %u\n", fWriteToCSP);
  1835. wprintf(L" fWriteToDS: %u\n", fWriteToDS);
  1836. wprintf(L" openFlags: 0x%x\n", openFlags);
  1837. fDisplayed = TRUE;
  1838. }
  1839. }
  1840. else
  1841. if (XENROLL_RENEWAL_CERTIFICATE_PROP_ID == dwPropId)
  1842. {
  1843. wprintf(myLoadResourceString(IDS_RENEWAL_CERT)); // "Renewal Certificate:"
  1844. wprintf(wszNewLine);
  1845. hr = cuDumpAsnBinary(pb, cb, MAXDWORD);
  1846. _JumpIfError(hr, error, "cuDumpAsnBinary");
  1847. }
  1848. }
  1849. if (!fDisplayed || g_fVerbose)
  1850. {
  1851. DumpHex(DH_NOADDRESS | DH_NOTABPREFIX | 4, pb, cb);
  1852. }
  1853. hr = S_OK;
  1854. error:
  1855. return(hr);
  1856. }
  1857. //+-------------------------------------------------------------------------
  1858. // cuDecodeObjId -- decode an ASN.1 encoded ObjectId
  1859. //
  1860. // Construct an ASN.1 encoded PKCS_ATTRIBUTE with an array of empty values,
  1861. // to trick CryptDecodeObject into decoding the passed in encoded Object Id.
  1862. //--------------------------------------------------------------------------
  1863. HRESULT
  1864. cuDecodeObjId(
  1865. IN BYTE const *pbData,
  1866. IN DWORD cbData,
  1867. OUT char **ppszObjId)
  1868. {
  1869. HRESULT hr;
  1870. CRYPT_ATTRIBUTE *pAttr = NULL;
  1871. BYTE *pbAlloc = NULL;
  1872. DWORD cbAlloc;
  1873. BYTE *pb;
  1874. DWORD cb;
  1875. //DumpHex(DH_NOTABPREFIX | 2, pbData, cbData);
  1876. cbAlloc = 2 + cbData + 2;
  1877. pbAlloc = (BYTE *) LocalAlloc(LMEM_FIXED, cbAlloc);
  1878. if (NULL == pbAlloc)
  1879. {
  1880. hr = E_OUTOFMEMORY;
  1881. _JumpError(hr, error, "LocalAlloc");
  1882. }
  1883. pb = pbAlloc;
  1884. *pb++ = BER_SEQUENCE; // PKCS_ATTRIBUTE sequence
  1885. CSASSERT(0x7f >= cbData + 2);
  1886. *pb++ = (BYTE ) (cbData + 2); // overall length
  1887. CopyMemory(pb, pbData, cbData); // copy encoded Object Id
  1888. pb += cbData;
  1889. *pb++ = BER_SET; // empty array of attribute values
  1890. *pb = 0; // zero length array of values
  1891. //DumpHex(DH_NOTABPREFIX | 2, pbAlloc, cbAlloc);
  1892. if (!myDecodeObject(
  1893. X509_ASN_ENCODING,
  1894. PKCS_ATTRIBUTE,
  1895. pbAlloc,
  1896. cbAlloc,
  1897. CERTLIB_USE_LOCALALLOC,
  1898. (VOID **) &pAttr,
  1899. &cb))
  1900. {
  1901. hr = myHLastError();
  1902. _JumpError(hr, error, "myDecodeObject");
  1903. }
  1904. hr = myDupStringA(pAttr->pszObjId, ppszObjId);
  1905. _JumpIfError(hr, error, "myDupStringA");
  1906. error:
  1907. if (NULL != pbAlloc)
  1908. {
  1909. LocalFree(pbAlloc);
  1910. }
  1911. if (NULL != pAttr)
  1912. {
  1913. LocalFree(pAttr);
  1914. }
  1915. return(hr);
  1916. }
  1917. //+-------------------------------------------------------------------------
  1918. // cuEncodeObjId -- decode an ASN.1 encoded ObjectId
  1919. //
  1920. // Construct an ASN.1 encoded PKCS_ATTRIBUTE with an array of empty values,
  1921. // to trick CryptEncodeObject into decoding the passed in encoded Object Id.
  1922. //--------------------------------------------------------------------------
  1923. HRESULT
  1924. cuEncodeObjId(
  1925. IN char const *pszObjId,
  1926. OUT BYTE **ppbData,
  1927. OUT DWORD *pcbData)
  1928. {
  1929. HRESULT hr;
  1930. CRYPT_ATTRIBUTE Attr;
  1931. BYTE *pbAttr = NULL;
  1932. DWORD cbAttr;
  1933. *ppbData = NULL;
  1934. ZeroMemory(&Attr, sizeof(Attr));
  1935. Attr.pszObjId = const_cast<char *>(pszObjId);
  1936. if (!myEncodeObject(
  1937. X509_ASN_ENCODING,
  1938. PKCS_ATTRIBUTE,
  1939. &Attr,
  1940. 0,
  1941. CERTLIB_USE_LOCALALLOC,
  1942. &pbAttr, // pbEncoded
  1943. &cbAttr))
  1944. {
  1945. hr = myHLastError();
  1946. _JumpError(hr, error, "myEncodeObject");
  1947. }
  1948. if (cbAttr <= 2 + 2 + 2 ||
  1949. BER_SEQUENCE != pbAttr[0] ||
  1950. cbAttr != pbAttr[1] + 2 ||
  1951. BER_OBJECT_ID != pbAttr[2] ||
  1952. cbAttr != pbAttr[3] + 2 + 2 + 2 ||
  1953. BER_SET != pbAttr[cbAttr - 2] ||
  1954. 0 != pbAttr[cbAttr - 1])
  1955. {
  1956. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1957. _JumpError(hr, error, "bad Attr");
  1958. }
  1959. *pcbData = cbAttr - 4;
  1960. *ppbData = (BYTE *) LocalAlloc(LMEM_FIXED, *pcbData);
  1961. if (NULL == *ppbData)
  1962. {
  1963. hr = E_OUTOFMEMORY;
  1964. _JumpError(hr, error, "LocalAlloc");
  1965. }
  1966. CopyMemory(*ppbData, &pbAttr[2], *pcbData);
  1967. hr = S_OK;
  1968. error:
  1969. if (NULL != pbAttr)
  1970. {
  1971. LocalFree(pbAttr);
  1972. }
  1973. return(hr);
  1974. }
  1975. // UnicodeDecode()
  1976. //
  1977. // This function is responsible for decoding unicode crypt data blobs from
  1978. // various certificate fields. The returned WCHAR * must be freed by LocalFree
  1979. //
  1980. // Params:
  1981. //
  1982. // pBlob - IN CRYPT_DATA_BLOB to be decoded, expected UNICODE
  1983. //
  1984. // Returns:
  1985. //
  1986. // WCHAR * to decoded string, to be freed using LocalFree
  1987. HRESULT
  1988. UnicodeDecode(
  1989. IN CRYPT_DATA_BLOB const *pBlob,
  1990. OUT WCHAR **ppwszOut)
  1991. {
  1992. HRESULT hr;
  1993. CERT_NAME_VALUE *pName = NULL;
  1994. DWORD cb;
  1995. *ppwszOut = NULL;
  1996. if (!myDecodeObject(
  1997. X509_ASN_ENCODING,
  1998. X509_UNICODE_ANY_STRING,
  1999. pBlob->pbData,
  2000. pBlob->cbData,
  2001. CERTLIB_USE_LOCALALLOC,
  2002. (VOID **) &pName,
  2003. &cb))
  2004. {
  2005. CSASSERT(NULL == pName);
  2006. hr = myHLastError();
  2007. _JumpError(hr, error, "myDecodeObject");
  2008. }
  2009. hr = myDupString((WCHAR const *) pName->Value.pbData, ppwszOut);
  2010. _JumpIfError(hr, error, "myDupString");
  2011. error:
  2012. if (NULL != pName)
  2013. {
  2014. LocalFree(pName);
  2015. }
  2016. return(hr);
  2017. }
  2018. BOOL
  2019. cuDumpFormattedExtension(
  2020. IN WCHAR const *pwszName,
  2021. IN BYTE const *pbObject,
  2022. IN DWORD cbObject)
  2023. {
  2024. HRESULT hr;
  2025. BOOL fDisplayed = FALSE;
  2026. char *pszObjId = NULL;
  2027. BSTR strHash = NULL;
  2028. WCHAR const *pwszDescriptiveName;
  2029. DWORD cb;
  2030. WCHAR const *pwszPad = g_fQuiet? g_wszEmpty : g_wszPad4;
  2031. if (!ConvertWszToSz(&pszObjId, pwszName, -1))
  2032. {
  2033. hr = E_OUTOFMEMORY;
  2034. _JumpError(hr, error, "ConvertWszToSz");
  2035. }
  2036. pwszDescriptiveName = cuGetOIDName(pwszName);
  2037. if (NULL != pwszDescriptiveName && L'\0' != *pwszDescriptiveName)
  2038. {
  2039. PrintStringWithPrefix(pwszPad, pwszDescriptiveName);
  2040. if (g_fQuiet)
  2041. {
  2042. wprintf(L": ");
  2043. }
  2044. else
  2045. {
  2046. wprintf(wszNewLine);
  2047. }
  2048. }
  2049. if (0 == cbObject)
  2050. {
  2051. if (!g_fQuiet)
  2052. {
  2053. wprintf(
  2054. L"%ws%ws\n",
  2055. g_wszPad8,
  2056. myLoadResourceString(IDS_PROP_EMPTY)); // "EMPTY"
  2057. }
  2058. fDisplayed = TRUE;
  2059. }
  2060. else
  2061. {
  2062. fDisplayed = DumpFormattedObject(
  2063. pszObjId,
  2064. FOT_EXTENSION,
  2065. pbObject,
  2066. cbObject);
  2067. if (!fDisplayed)
  2068. {
  2069. if (0 == strcmp(pszObjId, szOID_CERTSRV_CA_VERSION))
  2070. {
  2071. DWORD NameId;
  2072. cb = sizeof(NameId);
  2073. NameId = 0;
  2074. if (CryptDecodeObject(
  2075. X509_ASN_ENCODING,
  2076. X509_INTEGER,
  2077. pbObject,
  2078. cbObject,
  2079. 0,
  2080. &NameId,
  2081. &cb))
  2082. {
  2083. wprintf(
  2084. L"%ws%ws%ws: %u.%u\n",
  2085. pwszPad,
  2086. myLoadResourceString(IDS_CAVERSION),
  2087. g_wszCertUtil,
  2088. CANAMEIDTOICERT(NameId),
  2089. CANAMEIDTOIKEY(NameId));
  2090. fDisplayed = TRUE;
  2091. }
  2092. }
  2093. else
  2094. if (0 == strcmp(pszObjId, szOID_CERTSRV_CROSSCA_VERSION))
  2095. {
  2096. DWORD CrossCAVersion;
  2097. cb = sizeof(CrossCAVersion);
  2098. CrossCAVersion = 0;
  2099. if (CryptDecodeObject(
  2100. X509_ASN_ENCODING,
  2101. X509_INTEGER,
  2102. pbObject,
  2103. cbObject,
  2104. 0,
  2105. &CrossCAVersion,
  2106. &cb))
  2107. {
  2108. wprintf(
  2109. L"%ws%ws%ws: (%u-%u)\n",
  2110. pwszPad,
  2111. myLoadResourceString(IDS_CAVERSION),
  2112. g_wszCertUtil,
  2113. CROSSCAVERSIONTOSOURCE(CrossCAVersion),
  2114. CROSSCAVERSIONTOTARGET(CrossCAVersion));
  2115. fDisplayed = TRUE;
  2116. }
  2117. }
  2118. else
  2119. if (0 == strcmp(pszObjId, szOID_CERTSRV_PREVIOUS_CERT_HASH))
  2120. {
  2121. hr = DumpOctetHash(
  2122. pwszPad,
  2123. IDS_PREVIOUS_CA_CERT_HASH,
  2124. g_wszCertUtil,
  2125. pbObject,
  2126. cbObject,
  2127. NULL,
  2128. NULL);
  2129. if (S_OK == hr)
  2130. {
  2131. fDisplayed = TRUE;
  2132. }
  2133. }
  2134. else
  2135. if (0 == strcmp(pszObjId, szOID_CRL_NUMBER))
  2136. {
  2137. DWORD CRLNumber;
  2138. cb = sizeof(CRLNumber);
  2139. CRLNumber = 0;
  2140. if (CryptDecodeObject(
  2141. X509_ASN_ENCODING,
  2142. X509_INTEGER,
  2143. pbObject,
  2144. cbObject,
  2145. 0,
  2146. &CRLNumber,
  2147. &cb))
  2148. {
  2149. wprintf(
  2150. L"%ws%ws%ws: %u\n",
  2151. pwszPad,
  2152. myLoadResourceString(IDS_CRL_NUMBER),
  2153. g_wszCertUtil,
  2154. CRLNumber);
  2155. fDisplayed = TRUE;
  2156. }
  2157. }
  2158. else
  2159. if (0 == strcmp(pszObjId, szOID_DELTA_CRL_INDICATOR))
  2160. {
  2161. DWORD CRLNumber;
  2162. cb = sizeof(CRLNumber);
  2163. CRLNumber = 0;
  2164. if (CryptDecodeObject(
  2165. X509_ASN_ENCODING,
  2166. X509_INTEGER,
  2167. pbObject,
  2168. cbObject,
  2169. 0,
  2170. &CRLNumber,
  2171. &cb))
  2172. {
  2173. wprintf(
  2174. L"%ws%ws%ws: %u\n",
  2175. pwszPad,
  2176. myLoadResourceString(IDS_MINIMUM_BASE_CRL_NUMBER),
  2177. g_wszCertUtil,
  2178. CRLNumber);
  2179. fDisplayed = TRUE;
  2180. }
  2181. }
  2182. else
  2183. if (0 == strcmp(pszObjId, szOID_CRL_VIRTUAL_BASE))
  2184. {
  2185. DWORD CRLNumber;
  2186. cb = sizeof(CRLNumber);
  2187. CRLNumber = 0;
  2188. if (CryptDecodeObject(
  2189. X509_ASN_ENCODING,
  2190. X509_INTEGER,
  2191. pbObject,
  2192. cbObject,
  2193. 0,
  2194. &CRLNumber,
  2195. &cb))
  2196. {
  2197. wprintf(
  2198. L"%ws%ws%ws: %u\n",
  2199. pwszPad,
  2200. myLoadResourceString(IDS_VIRTUAL_BASE_CRL_NUMBER),
  2201. g_wszCertUtil,
  2202. CRLNumber);
  2203. fDisplayed = TRUE;
  2204. }
  2205. }
  2206. else
  2207. if (0 == strcmp(pszObjId, szOID_CRL_NEXT_PUBLISH) ||
  2208. 0 == strcmp(pszObjId, szOID_RSA_signingTime))
  2209. {
  2210. FILETIME ft;
  2211. cb = sizeof(ft);
  2212. if (CryptDecodeObject(
  2213. X509_ASN_ENCODING,
  2214. X509_CHOICE_OF_TIME,
  2215. pbObject,
  2216. cbObject,
  2217. 0,
  2218. &ft,
  2219. &cb))
  2220. {
  2221. wprintf(
  2222. L"%ws%ws%ws: ",
  2223. pwszPad,
  2224. myLoadResourceString(
  2225. 0 == strcmp(pszObjId, szOID_CRL_NEXT_PUBLISH)?
  2226. IDS_CRL_NEXT_PUBLISH : IDS_SIGNING_TIME),
  2227. g_wszCertUtil);
  2228. hr = cuDumpFileTime(0, NULL, &ft);
  2229. _JumpIfError(hr, error, "cuDumpFileTime");
  2230. fDisplayed = TRUE;
  2231. }
  2232. }
  2233. else
  2234. if (0 == strcmp(pszObjId, szOID_FRESHEST_CRL))
  2235. {
  2236. wprintf(
  2237. L"%ws%ws%ws:\n",
  2238. pwszPad,
  2239. myLoadResourceString(IDS_FRESHEST_CRL_CDP),
  2240. g_wszCertUtil);
  2241. cuDumpFormattedExtension(
  2242. TEXT(szOID_CRL_DIST_POINTS),
  2243. pbObject,
  2244. cbObject);
  2245. fDisplayed = TRUE;
  2246. }
  2247. else
  2248. if (0 == strcmp(pszObjId, szOID_CRL_SELF_CDP))
  2249. {
  2250. wprintf(
  2251. L"%ws%ws%ws:\n",
  2252. pwszPad,
  2253. myLoadResourceString(IDS_CRL_SELF_CDP),
  2254. g_wszCertUtil);
  2255. cuDumpFormattedExtension(
  2256. TEXT(szOID_CRL_DIST_POINTS),
  2257. pbObject,
  2258. cbObject);
  2259. fDisplayed = TRUE;
  2260. }
  2261. else
  2262. if (0 == strcmp(pszObjId, szOID_PKIX ".2"))
  2263. {
  2264. // Exchange policy module intended to use szOID_PKIX_CA_ISSUERS,
  2265. // but the ".48.2" suffix was instead written as ".2".
  2266. //
  2267. // szOID_PKIX_CA_ISSUERS was wrong anyway -- it should have
  2268. // used szOID_AUTHORITY_INFO_ACCESS instead.
  2269. wprintf(
  2270. L"%ws%ws%ws:\n",
  2271. pwszPad,
  2272. myLoadResourceString(IDS_EXCHANGEAIA), // "Exchange Authority Information Access"
  2273. g_wszCertUtil);
  2274. cuDumpFormattedExtension(
  2275. TEXT(szOID_AUTHORITY_INFO_ACCESS),
  2276. pbObject,
  2277. cbObject);
  2278. fDisplayed = TRUE;
  2279. }
  2280. else
  2281. if (0 == strcmp(pszObjId, szOID_ISSUER_ALT_NAME))
  2282. {
  2283. // Exchange policy module overloaded this OID and stored the
  2284. // file version information for expolicy.dll and certsrv.exe.
  2285. typedef struct _CUVER {
  2286. USHORT usMajor;
  2287. USHORT usMinor;
  2288. USHORT usBuild;
  2289. USHORT usBuildMinor;
  2290. } CUVER;
  2291. CUVER const *pVer;
  2292. CRYPT_INTEGER_BLOB aBlob[1 + BLOB_ROUND(2 * sizeof(*pVer))];
  2293. cb = sizeof(aBlob);
  2294. if (CryptDecodeObject(
  2295. X509_ASN_ENCODING,
  2296. X509_MULTI_BYTE_INTEGER,
  2297. pbObject,
  2298. cbObject,
  2299. 0,
  2300. aBlob,
  2301. &cb))
  2302. {
  2303. if (2 * sizeof(*pVer) == aBlob[0].cbData)
  2304. {
  2305. wprintf(
  2306. L"%ws%ws%ws:\n",
  2307. pwszPad,
  2308. myLoadResourceString(IDS_EXCHANGEVERSION), // "Exchange Version"
  2309. g_wszCertUtil);
  2310. pVer = (CUVER const *) aBlob[0].pbData;
  2311. wprintf(
  2312. L" expolicy.dll: %u.%u:%u.%u\n",
  2313. pVer->usMajor,
  2314. pVer->usMinor,
  2315. pVer->usBuild,
  2316. pVer->usBuildMinor);
  2317. pVer++;
  2318. wprintf(
  2319. L" certsrv.exe: %u.%u:%u.%u\n",
  2320. pVer->usMajor,
  2321. pVer->usMinor,
  2322. pVer->usBuild,
  2323. pVer->usBuildMinor);
  2324. fDisplayed = TRUE;
  2325. }
  2326. }
  2327. else
  2328. {
  2329. hr = myHLastError();
  2330. _JumpError(hr, error, "CryptDecodeObject");
  2331. }
  2332. }
  2333. else
  2334. if (0 == strcmp(pszObjId, szOID_APPLICATION_CERT_POLICIES))
  2335. {
  2336. wprintf(
  2337. L"%ws%ws%ws:\n",
  2338. pwszPad,
  2339. myLoadResourceString(IDS_APPLICATION_CERT_POLICIES),
  2340. g_wszCertUtil);
  2341. cuDumpFormattedExtension(
  2342. TEXT(szOID_CERT_POLICIES),
  2343. pbObject,
  2344. cbObject);
  2345. fDisplayed = TRUE;
  2346. }
  2347. else
  2348. if (0 == strcmp(pszObjId, szOID_APPLICATION_POLICY_MAPPINGS))
  2349. {
  2350. wprintf(
  2351. L"%ws%ws%ws:\n",
  2352. pwszPad,
  2353. myLoadResourceString(IDS_APPLICATION_POLICY_MAPPINGS),
  2354. g_wszCertUtil);
  2355. cuDumpFormattedExtension(
  2356. TEXT(szOID_POLICY_MAPPINGS),
  2357. pbObject,
  2358. cbObject);
  2359. fDisplayed = TRUE;
  2360. }
  2361. else
  2362. if (0 == strcmp(pszObjId, szOID_APPLICATION_POLICY_CONSTRAINTS))
  2363. {
  2364. wprintf(
  2365. L"%ws%ws%ws:\n",
  2366. pwszPad,
  2367. myLoadResourceString(IDS_APPLICATION_POLICY_CONSTRAINTS),
  2368. g_wszCertUtil);
  2369. cuDumpFormattedExtension(
  2370. TEXT(szOID_POLICY_CONSTRAINTS),
  2371. pbObject,
  2372. cbObject);
  2373. fDisplayed = TRUE;
  2374. }
  2375. else
  2376. if (0 == strcmp(pszObjId, szOID_POLICY_MAPPINGS))
  2377. {
  2378. CERT_POLICY_MAPPINGS_INFO *pPolicyMappings = NULL;
  2379. DWORD i;
  2380. if (!myDecodeObject(
  2381. X509_ASN_ENCODING,
  2382. X509_POLICY_MAPPINGS,
  2383. pbObject,
  2384. cbObject,
  2385. CERTLIB_USE_LOCALALLOC,
  2386. (VOID **) &pPolicyMappings,
  2387. &cb))
  2388. {
  2389. hr = myHLastError();
  2390. CSASSERT(NULL == pPolicyMappings);
  2391. _JumpIfError(hr, error, "myDecodeObject");
  2392. }
  2393. wprintf(
  2394. L"%ws%ws%ws:\n",
  2395. pwszPad,
  2396. myLoadResourceString(IDS_POLICY_MAPPINGS),
  2397. g_wszCertUtil);
  2398. for (i = 0; i < pPolicyMappings->cPolicyMapping; i++)
  2399. {
  2400. wprintf(g_wszPad4);
  2401. wprintf(myLoadResourceString(IDS_FORMAT_MAP_ARRAY_COLON), i);
  2402. wprintf(wszNewLine);
  2403. wprintf(g_wszPad8);
  2404. wprintf(myLoadResourceString(IDS_ISSUER_DOMAIN_POLICY));
  2405. cuDumpOIDAndDescriptionA(
  2406. pPolicyMappings->rgPolicyMapping[i].pszIssuerDomainPolicy);
  2407. wprintf(wszNewLine);
  2408. wprintf(g_wszPad8);
  2409. wprintf(myLoadResourceString(IDS_SUBJECT_DOMAIN_POLICY));
  2410. cuDumpOIDAndDescriptionA(
  2411. pPolicyMappings->rgPolicyMapping[i].pszSubjectDomainPolicy);
  2412. wprintf(wszNewLine);
  2413. }
  2414. LocalFree(pPolicyMappings);
  2415. fDisplayed = TRUE;
  2416. }
  2417. else
  2418. if (0 == strcmp(pszObjId, szOID_POLICY_CONSTRAINTS))
  2419. {
  2420. CERT_POLICY_CONSTRAINTS_INFO Constraints;
  2421. cb = sizeof(Constraints);
  2422. if (!CryptDecodeObject(
  2423. X509_ASN_ENCODING,
  2424. X509_POLICY_CONSTRAINTS,
  2425. pbObject,
  2426. cbObject,
  2427. 0,
  2428. &Constraints,
  2429. &cb))
  2430. {
  2431. hr = myHLastError();
  2432. _JumpError(hr, error, "CryptDecodeObject");
  2433. }
  2434. wprintf(
  2435. L"%ws%ws%ws:\n",
  2436. pwszPad,
  2437. myLoadResourceString(IDS_POLICY_CONSTRAINTS),
  2438. g_wszCertUtil);
  2439. if (Constraints.fRequireExplicitPolicy)
  2440. {
  2441. wprintf(
  2442. L" dwRequireExplicitPolicySkipCerts: %u\n",
  2443. Constraints.dwRequireExplicitPolicySkipCerts);
  2444. }
  2445. if (Constraints.fInhibitPolicyMapping)
  2446. {
  2447. wprintf(
  2448. L" dwInhibitPolicyMappingSkipCerts: %u\n",
  2449. Constraints.dwInhibitPolicyMappingSkipCerts);
  2450. }
  2451. fDisplayed = TRUE;
  2452. }
  2453. else
  2454. if (0 == strcmp(pszObjId, szOID_REASON_CODE_HOLD))
  2455. {
  2456. char *pszObjIdT;
  2457. hr = cuDecodeObjId(pbObject, cbObject, &pszObjIdT);
  2458. if (S_OK == hr)
  2459. {
  2460. wprintf(pwszPad);
  2461. cuDumpOIDAndDescriptionA(pszObjIdT);
  2462. wprintf(wszNewLine);
  2463. LocalFree(pszObjIdT);
  2464. fDisplayed = TRUE;
  2465. }
  2466. }
  2467. else
  2468. if (0 == strcmp(pszObjId, szOID_VERISIGN_ONSITE_JURISDICTION_HASH))
  2469. {
  2470. CRYPT_DATA_BLOB Value;
  2471. WCHAR *pwsz;
  2472. Value.pbData = const_cast<BYTE *>(pbObject);
  2473. Value.cbData = cbObject;
  2474. hr = UnicodeDecode(&Value, &pwsz);
  2475. if (S_OK == hr)
  2476. {
  2477. wprintf(L"%ws%ws\n", pwszPad, pwsz);
  2478. LocalFree(pwsz);
  2479. fDisplayed = TRUE;
  2480. }
  2481. }
  2482. }
  2483. }
  2484. error:
  2485. if (NULL != strHash)
  2486. {
  2487. SysFreeString(strHash);
  2488. }
  2489. if (NULL != pszObjId)
  2490. {
  2491. LocalFree(pszObjId);
  2492. }
  2493. return(fDisplayed);
  2494. }
  2495. WCHAR const * const g_apwszFieldNames[] = {
  2496. wszCONFIG_COMMONNAME,
  2497. wszCONFIG_ORGUNIT,
  2498. wszCONFIG_ORGANIZATION,
  2499. wszCONFIG_LOCALITY,
  2500. wszCONFIG_STATE,
  2501. wszCONFIG_COUNTRY,
  2502. wszCONFIG_CONFIG,
  2503. wszCONFIG_EXCHANGECERTIFICATE,
  2504. wszCONFIG_SIGNATURECERTIFICATE,
  2505. wszCONFIG_DESCRIPTION,
  2506. wszCONFIG_SERVER,
  2507. wszCONFIG_AUTHORITY,
  2508. wszCONFIG_SANITIZEDNAME,
  2509. wszCONFIG_SHORTNAME,
  2510. wszCONFIG_SANITIZEDSHORTNAME,
  2511. wszCONFIG_FLAGS,
  2512. };
  2513. #define CSTRING (sizeof(g_apwszFieldNames)/sizeof(g_apwszFieldNames[0]))
  2514. WCHAR const *g_apwszDisplayNames[CSTRING];
  2515. LONG g_amsgidDisplayNames[CSTRING] = {
  2516. IDS_CONFIGDISPLAY_COMMONNAME_COLON,
  2517. IDS_CONFIGDISPLAY_ORGUNIT_COLON,
  2518. IDS_CONFIGDISPLAY_ORG_COLON,
  2519. IDS_CONFIGDISPLAY_LOCALITY_COLON,
  2520. IDS_CONFIGDISPLAY_STATE_COLON,
  2521. IDS_CONFIGDISPLAY_COUNTRY_COLON,
  2522. IDS_CONFIGDISPLAY_CONFIG_COLON,
  2523. IDS_CONFIGDISPLAY_EXCHANGECERT_COLON,
  2524. IDS_CONFIGDISPLAY_SIGCERT_COLON,
  2525. IDS_CONFIGDISPLAY_DESCRIPTION_COLON,
  2526. IDS_CONFIGDISPLAY_SERVER_COLON,
  2527. IDS_CONFIGDISPLAY_AUTHORITY_COLON,
  2528. IDS_CONFIGDISPLAY_SANITIZEDNAME_COLON,
  2529. IDS_CONFIGDISPLAY_SHORTNAME_COLON,
  2530. IDS_CONFIGDISPLAY_SANITIZEDSHORTNAME_COLON,
  2531. IDS_CONFIGDISPLAY_FLAGS_COLON,
  2532. };
  2533. HRESULT
  2534. cuConfigDump(VOID)
  2535. {
  2536. HRESULT hr;
  2537. DWORD i;
  2538. for (i = 0; i < CSTRING; i++)
  2539. {
  2540. g_apwszDisplayNames[i] = myLoadResourceString(g_amsgidDisplayNames[i]);
  2541. }
  2542. hr = ConfigDumpSetDisplayNames(
  2543. g_apwszFieldNames,
  2544. g_apwszDisplayNames,
  2545. CSTRING);
  2546. _JumpIfError(hr, error, "ConfigDumpSetDisplayNames");
  2547. hr = ConfigDump(
  2548. g_DispatchFlags,
  2549. myLoadResourceString(IDS_CONFIGDISPLAY_ENTRY), // "Entry"
  2550. myLoadResourceString(IDS_CONFIGDISPLAY_LOCAL), // "(Local)"
  2551. g_pwszDnsName,
  2552. g_pwszOldName);
  2553. _JumpIfError(hr, error, "ConfigDump");
  2554. error:
  2555. return(hr);
  2556. }
  2557. typedef HRESULT (FNDUMP)(
  2558. IN DWORD idMessage,
  2559. IN BYTE const *pbIn,
  2560. IN DWORD cbIn,
  2561. IN BYTE const *pbDecoded,
  2562. IN DWORD cbDecoded,
  2563. IN CERT_SIGNED_CONTENT_INFO const *pcsci);
  2564. FNDUMP dumpCert, dumpCRL, dumpRequest, dumpCMCRequest, dumpCMCResponse,
  2565. dumpKeyGenRequest, dumpCertSequence, dumpCTL;
  2566. typedef struct _ASNFORMATS
  2567. {
  2568. char const *pszFormat;
  2569. FNDUMP *pfnDump;
  2570. DWORD idMessage;
  2571. WCHAR const *pwszExtension;
  2572. } ASNFORMATS;
  2573. ASNFORMATS g_aasn[] = {
  2574. {
  2575. X509_CERT_TO_BE_SIGNED,
  2576. dumpCert,
  2577. IDS_DUMP_CERT,
  2578. L".crt",
  2579. },
  2580. {
  2581. X509_CERT_CRL_TO_BE_SIGNED,
  2582. dumpCRL,
  2583. IDS_DUMP_CRL,
  2584. L".crl",
  2585. },
  2586. {
  2587. X509_CERT_REQUEST_TO_BE_SIGNED,
  2588. dumpRequest,
  2589. IDS_DUMP_REQUEST,
  2590. L".p10",
  2591. },
  2592. {
  2593. CMC_DATA,
  2594. dumpCMCRequest,
  2595. IDS_DUMP_CMC,
  2596. L".cmc",
  2597. },
  2598. {
  2599. CMC_RESPONSE,
  2600. dumpCMCResponse,
  2601. IDS_DUMP_CMCRESPONSE,
  2602. L".res",
  2603. },
  2604. {
  2605. X509_KEYGEN_REQUEST_TO_BE_SIGNED,
  2606. dumpKeyGenRequest,
  2607. IDS_DUMP_KEYGEN,
  2608. L".req",
  2609. },
  2610. {
  2611. PKCS_CONTENT_INFO_SEQUENCE_OF_ANY,
  2612. dumpCertSequence,
  2613. IDS_DUMP_CERTSEQ,
  2614. L".seq",
  2615. },
  2616. {
  2617. PKCS_CTL,
  2618. dumpCTL,
  2619. IDS_DUMP_CTL,
  2620. L".stl",
  2621. },
  2622. };
  2623. #define CASNFORMATS (sizeof(g_aasn)/sizeof(g_aasn[0]))
  2624. HRESULT
  2625. dumpPKCS7(
  2626. OPTIONAL IN HCERTSTORE hStoreWrapper,
  2627. IN BYTE const *pbIn,
  2628. IN DWORD cbIn);
  2629. typedef struct _DUMPALGID
  2630. {
  2631. ALG_ID Algid;
  2632. WCHAR const *pwszDescription;
  2633. } DUMPALGID;
  2634. #define _DFALGID(algid) { (algid), L#algid }
  2635. DUMPALGID g_adfAlgids[] =
  2636. {
  2637. _DFALGID(CALG_MD2),
  2638. _DFALGID(CALG_MD4),
  2639. _DFALGID(CALG_MD5),
  2640. //_DFALGID(CALG_SHA), same as CALG_SHA1
  2641. _DFALGID(CALG_SHA1),
  2642. _DFALGID(CALG_MAC),
  2643. _DFALGID(CALG_RSA_SIGN),
  2644. _DFALGID(CALG_DSS_SIGN),
  2645. _DFALGID(CALG_NO_SIGN),
  2646. _DFALGID(CALG_RSA_KEYX),
  2647. _DFALGID(CALG_DES),
  2648. _DFALGID(CALG_3DES_112),
  2649. _DFALGID(CALG_3DES),
  2650. _DFALGID(CALG_DESX),
  2651. _DFALGID(CALG_RC2),
  2652. _DFALGID(CALG_RC4),
  2653. _DFALGID(CALG_SEAL),
  2654. _DFALGID(CALG_DH_SF),
  2655. _DFALGID(CALG_DH_EPHEM),
  2656. _DFALGID(CALG_AGREEDKEY_ANY),
  2657. _DFALGID(CALG_KEA_KEYX),
  2658. _DFALGID(CALG_HUGHES_MD5),
  2659. _DFALGID(CALG_SKIPJACK),
  2660. _DFALGID(CALG_TEK),
  2661. _DFALGID(CALG_CYLINK_MEK),
  2662. _DFALGID(CALG_SSL3_SHAMD5),
  2663. _DFALGID(CALG_SSL3_MASTER),
  2664. _DFALGID(CALG_SCHANNEL_MASTER_HASH),
  2665. _DFALGID(CALG_SCHANNEL_MAC_KEY),
  2666. _DFALGID(CALG_SCHANNEL_ENC_KEY),
  2667. _DFALGID(CALG_PCT1_MASTER),
  2668. _DFALGID(CALG_SSL2_MASTER),
  2669. _DFALGID(CALG_TLS1_MASTER),
  2670. _DFALGID(CALG_RC5),
  2671. _DFALGID(CALG_HMAC),
  2672. _DFALGID(CALG_TLS1PRF),
  2673. _DFALGID(CALG_HASH_REPLACE_OWF),
  2674. _DFALGID(CALG_AES_128),
  2675. _DFALGID(CALG_AES_192),
  2676. _DFALGID(CALG_AES_256),
  2677. _DFALGID(CALG_AES),
  2678. };
  2679. DUMPALGID g_adfClass[] =
  2680. {
  2681. _DFALGID(ALG_CLASS_ANY),
  2682. _DFALGID(ALG_CLASS_SIGNATURE),
  2683. _DFALGID(ALG_CLASS_MSG_ENCRYPT),
  2684. _DFALGID(ALG_CLASS_DATA_ENCRYPT),
  2685. _DFALGID(ALG_CLASS_HASH),
  2686. _DFALGID(ALG_CLASS_KEY_EXCHANGE),
  2687. };
  2688. DUMPALGID g_adfType[] =
  2689. {
  2690. _DFALGID(ALG_TYPE_ANY),
  2691. _DFALGID(ALG_TYPE_DSS),
  2692. _DFALGID(ALG_TYPE_RSA),
  2693. _DFALGID(ALG_TYPE_BLOCK),
  2694. _DFALGID(ALG_TYPE_STREAM),
  2695. _DFALGID(ALG_TYPE_DH),
  2696. _DFALGID(ALG_TYPE_SECURECHANNEL),
  2697. };
  2698. // Generic sub-ids
  2699. DUMPALGID g_adfSubIdAny[] =
  2700. {
  2701. _DFALGID(ALG_SID_ANY),
  2702. };
  2703. // Some DSS sub-ids
  2704. DUMPALGID g_adfSubIdDSS[] =
  2705. {
  2706. _DFALGID(ALG_SID_DSS_ANY),
  2707. _DFALGID(ALG_SID_DSS_PKCS),
  2708. _DFALGID(ALG_SID_DSS_DMS),
  2709. };
  2710. // Some RSA sub-ids
  2711. DUMPALGID g_adfSubIdRSA[] =
  2712. {
  2713. _DFALGID(ALG_SID_RSA_ANY),
  2714. _DFALGID(ALG_SID_RSA_PKCS),
  2715. _DFALGID(ALG_SID_RSA_MSATWORK),
  2716. _DFALGID(ALG_SID_RSA_ENTRUST),
  2717. _DFALGID(ALG_SID_RSA_PGP),
  2718. };
  2719. // Block cipher sub ids
  2720. DUMPALGID g_adfSubIdBlock[] =
  2721. {
  2722. // RC2 sub-ids
  2723. _DFALGID(ALG_SID_RC2),
  2724. // DES sub_ids
  2725. _DFALGID(ALG_SID_DES),
  2726. _DFALGID(ALG_SID_3DES),
  2727. _DFALGID(ALG_SID_DESX),
  2728. _DFALGID(ALG_SID_IDEA),
  2729. _DFALGID(ALG_SID_CAST),
  2730. _DFALGID(ALG_SID_SAFERSK64),
  2731. _DFALGID(ALG_SID_SAFERSK128),
  2732. _DFALGID(ALG_SID_3DES_112),
  2733. _DFALGID(ALG_SID_CYLINK_MEK),
  2734. _DFALGID(ALG_SID_RC5),
  2735. _DFALGID(ALG_SID_AES_128),
  2736. _DFALGID(ALG_SID_AES_192),
  2737. _DFALGID(ALG_SID_AES_256),
  2738. _DFALGID(ALG_SID_AES),
  2739. // Fortezza sub-ids
  2740. _DFALGID(ALG_SID_SKIPJACK),
  2741. _DFALGID(ALG_SID_TEK),
  2742. };
  2743. // Stream cipher sub-ids
  2744. DUMPALGID g_adfSubIdStream[] =
  2745. {
  2746. _DFALGID(ALG_SID_RC4),
  2747. _DFALGID(ALG_SID_SEAL),
  2748. };
  2749. // Diffie-Hellman sub-ids
  2750. DUMPALGID g_adfSubIdDH[] =
  2751. {
  2752. _DFALGID(ALG_SID_DH_SANDF),
  2753. _DFALGID(ALG_SID_DH_EPHEM),
  2754. _DFALGID(ALG_SID_AGREED_KEY_ANY),
  2755. _DFALGID(ALG_SID_KEA),
  2756. };
  2757. // secure channel sub ids
  2758. DUMPALGID g_adfSubIdSecureChannel[] =
  2759. {
  2760. _DFALGID(ALG_SID_SSL3_MASTER),
  2761. _DFALGID(ALG_SID_SCHANNEL_MASTER_HASH),
  2762. _DFALGID(ALG_SID_SCHANNEL_MAC_KEY),
  2763. _DFALGID(ALG_SID_PCT1_MASTER),
  2764. _DFALGID(ALG_SID_SSL2_MASTER),
  2765. _DFALGID(ALG_SID_TLS1_MASTER),
  2766. _DFALGID(ALG_SID_SCHANNEL_ENC_KEY),
  2767. };
  2768. // Hash sub ids
  2769. DUMPALGID g_adfSubIdHash[] =
  2770. {
  2771. _DFALGID(ALG_SID_MD2),
  2772. _DFALGID(ALG_SID_MD4),
  2773. _DFALGID(ALG_SID_MD5),
  2774. _DFALGID(ALG_SID_SHA1),
  2775. _DFALGID(ALG_SID_MAC),
  2776. _DFALGID(ALG_SID_RIPEMD),
  2777. _DFALGID(ALG_SID_RIPEMD160),
  2778. _DFALGID(ALG_SID_SSL3SHAMD5),
  2779. _DFALGID(ALG_SID_HMAC),
  2780. _DFALGID(ALG_SID_TLS1PRF),
  2781. _DFALGID(ALG_SID_HASH_REPLACE_OWF),
  2782. };
  2783. #if 0
  2784. // KP_MODE
  2785. #define CRYPT_MODE_CBCI 6 // ANSI CBC Interleaved
  2786. #define CRYPT_MODE_CFBP 7 // ANSI CFB Pipelined
  2787. #define CRYPT_MODE_OFBP 8 // ANSI OFB Pipelined
  2788. #define CRYPT_MODE_CBCOFM 9 // ANSI CBC + OF Masking
  2789. #define CRYPT_MODE_CBCOFMI 10 // ANSI CBC + OFM Interleaved
  2790. #endif
  2791. typedef struct _DUMPSUBIDMAP
  2792. {
  2793. DWORD dwAlgType;
  2794. DUMPALGID *adfSubId;
  2795. DWORD cdfSubId;
  2796. } DUMPSUBIDMAP;
  2797. #define _DFARRAYANDSIZE(adf) (adf), ARRAYSIZE(adf)
  2798. DUMPSUBIDMAP g_adfSubIdMap[] =
  2799. {
  2800. { ALG_TYPE_ANY, _DFARRAYANDSIZE(g_adfSubIdAny) },
  2801. { ALG_TYPE_DSS, _DFARRAYANDSIZE(g_adfSubIdDSS) },
  2802. { ALG_TYPE_RSA, _DFARRAYANDSIZE(g_adfSubIdRSA) },
  2803. { ALG_TYPE_BLOCK, _DFARRAYANDSIZE(g_adfSubIdBlock) },
  2804. { ALG_TYPE_STREAM, _DFARRAYANDSIZE(g_adfSubIdStream) },
  2805. { ALG_TYPE_DH, _DFARRAYANDSIZE(g_adfSubIdDH) },
  2806. { ALG_TYPE_SECURECHANNEL, _DFARRAYANDSIZE(g_adfSubIdSecureChannel) },
  2807. };
  2808. VOID
  2809. cuDumpAlgid(
  2810. IN DWORD Algid)
  2811. {
  2812. WCHAR const *pwsz;
  2813. WCHAR const *pwszQuestionMarks;
  2814. DUMPALGID *pda;
  2815. DUMPALGID *pdaSubId;
  2816. DWORD cdaSubId;
  2817. DUMPSUBIDMAP *pdsm;
  2818. DWORD AlgClass;
  2819. DWORD AlgType;
  2820. DWORD AlgSubId;
  2821. pwszQuestionMarks = myLoadResourceString(IDS_QUESTIONMARKS); // "???"
  2822. for (pda = g_adfAlgids; pda < &g_adfAlgids[ARRAYSIZE(g_adfAlgids)]; pda++)
  2823. {
  2824. if (Algid == pda->Algid)
  2825. {
  2826. wprintf(L" %ws\n", pda->pwszDescription);
  2827. break;
  2828. }
  2829. }
  2830. AlgClass = GET_ALG_CLASS(Algid);
  2831. pwsz = pwszQuestionMarks;
  2832. for (pda = g_adfClass; pda < &g_adfClass[ARRAYSIZE(g_adfClass)]; pda++)
  2833. {
  2834. if (AlgClass == pda->Algid)
  2835. {
  2836. pwsz = pda->pwszDescription;
  2837. break;
  2838. }
  2839. }
  2840. wprintf(
  2841. L" %ws: 0x%x(%u) %ws\n",
  2842. myLoadResourceString(IDS_ALGORITHM_CLASS), // "Algorithm Class"
  2843. AlgClass,
  2844. AlgClass >> 13,
  2845. pwsz);
  2846. AlgType = GET_ALG_TYPE(Algid);
  2847. pwsz = pwszQuestionMarks;
  2848. for (pda = g_adfType; pda < &g_adfType[ARRAYSIZE(g_adfType)]; pda++)
  2849. {
  2850. if (AlgType == pda->Algid)
  2851. {
  2852. pwsz = pda->pwszDescription;
  2853. break;
  2854. }
  2855. }
  2856. wprintf(
  2857. L" %ws: 0x%x(%u) %ws\n",
  2858. myLoadResourceString(IDS_ALGORITHM_TYPE), // "Algorithm Type"
  2859. AlgType,
  2860. AlgType >> 9,
  2861. pwsz);
  2862. pdaSubId = g_adfSubIdAny;
  2863. cdaSubId = ARRAYSIZE(g_adfSubIdAny);
  2864. for (pdsm = g_adfSubIdMap; pdsm < &g_adfSubIdMap[ARRAYSIZE(g_adfSubIdMap)]; pdsm++)
  2865. {
  2866. if (AlgType == pdsm->dwAlgType)
  2867. {
  2868. pdaSubId = pdsm->adfSubId;
  2869. cdaSubId = pdsm->cdfSubId;
  2870. break;
  2871. }
  2872. }
  2873. if (ALG_CLASS_HASH == AlgClass && pdaSubId == g_adfSubIdAny)
  2874. {
  2875. pdaSubId = g_adfSubIdHash;
  2876. cdaSubId = ARRAYSIZE(g_adfSubIdHash);
  2877. }
  2878. pwsz = pwszQuestionMarks;
  2879. AlgSubId = GET_ALG_SID(Algid);
  2880. for (pda = pdaSubId; pda < &pdaSubId[cdaSubId]; pda++)
  2881. {
  2882. if (AlgSubId == pda->Algid)
  2883. {
  2884. pwsz = pda->pwszDescription;
  2885. break;
  2886. }
  2887. }
  2888. wprintf(
  2889. L" %ws: 0x%x(%u) %ws\n",
  2890. myLoadResourceString(IDS_ALGORITHM_SUBID), // "Algorithm Sub-id"
  2891. AlgSubId,
  2892. AlgSubId >> 0,
  2893. pwsz);
  2894. }
  2895. HRESULT
  2896. cuDumpPrivateKeyBlob(
  2897. IN BYTE const *pbKey,
  2898. IN DWORD cbKey,
  2899. IN BOOL fQuiet)
  2900. {
  2901. HRESULT hr;
  2902. PUBLICKEYSTRUC const *pkey = (PUBLICKEYSTRUC const *) pbKey;
  2903. WCHAR const *pwszType;
  2904. if (sizeof(*pkey) >= cbKey)
  2905. {
  2906. //DumpHex(DH_NOTABPREFIX | DH_PRIVATEDATA | 2, pbKey, cbKey);
  2907. hr = CRYPT_E_ASN1_BADTAG;
  2908. _JumpError2(hr, error, "key check", hr);
  2909. }
  2910. switch (pkey->bType)
  2911. {
  2912. case SIMPLEBLOB: pwszType = L"SIMPLEBLOB"; break;
  2913. case PUBLICKEYBLOB: pwszType = L"PUBLICKEYBLOB"; break;
  2914. case PRIVATEKEYBLOB: pwszType = L"PRIVATEKEYBLOB"; break;
  2915. case PLAINTEXTKEYBLOB: pwszType = L"PLAINTEXTKEYBLOB"; break;
  2916. case OPAQUEKEYBLOB: pwszType = L"OPAQUEKEYBLOB"; break;
  2917. case PUBLICKEYBLOBEX: pwszType = L"PUBLICKEYBLOBEX"; break;
  2918. case SYMMETRICWRAPKEYBLOB: pwszType = L"SYMMETRICWRAPKEYBLOB"; break;
  2919. default:
  2920. //DumpHex(DH_NOTABPREFIX | DH_PRIVATEDATA | 2, pbKey, cbKey);
  2921. hr = CRYPT_E_ASN1_BADTAG;
  2922. _JumpError2(hr, error, "key check", hr);
  2923. }
  2924. if (fQuiet)
  2925. {
  2926. hr = S_OK;
  2927. goto error;
  2928. }
  2929. wprintf(myLoadResourceString(IDS_PRIVATEKEY));
  2930. wprintf(wszNewLine);
  2931. wprintf(L" %ws\n", pwszType);
  2932. wprintf(g_wszPad2);
  2933. wprintf(
  2934. myLoadResourceString(IDS_FORMAT_VERSION), // "Version: %u"
  2935. pkey->bVersion);
  2936. wprintf(wszNewLine);
  2937. wprintf(L" aiKeyAlg: 0x%x\n", pkey->aiKeyAlg);
  2938. cuDumpAlgid(pkey->aiKeyAlg);
  2939. DumpHex(
  2940. DH_NOTABPREFIX | DH_PRIVATEDATA | 2,
  2941. (BYTE const *) &pkey[1],
  2942. cbKey - sizeof(*pkey));
  2943. hr = S_OK;
  2944. error:
  2945. return(hr);
  2946. }
  2947. HRESULT DisplayUniqueContainer(IN HCRYPTPROV hProv);
  2948. HRESULT
  2949. cuDumpPrivateKey(
  2950. IN CERT_CONTEXT const *pCert,
  2951. OPTIONAL OUT BOOL *pfSigningKey,
  2952. OPTIONAL OUT BOOL *pfMatchingKey)
  2953. {
  2954. HRESULT hr;
  2955. HCRYPTPROV hProv = NULL;
  2956. HCRYPTKEY hKey = NULL;
  2957. DWORD dwKeySpec;
  2958. DWORD cb;
  2959. CRYPT_BIT_BLOB PrivateKey;
  2960. CERT_PUBLIC_KEY_INFO *pPublicKeyInfo = NULL;
  2961. ZeroMemory(&PrivateKey, sizeof(PrivateKey));
  2962. if (NULL != pfSigningKey)
  2963. {
  2964. *pfSigningKey = FALSE;
  2965. }
  2966. if (NULL != pfMatchingKey)
  2967. {
  2968. *pfMatchingKey = FALSE;
  2969. }
  2970. if (!CryptAcquireCertificatePrivateKey(
  2971. pCert,
  2972. 0, // dwFlags
  2973. NULL, // pvReserved
  2974. &hProv,
  2975. &dwKeySpec,
  2976. NULL)) // pfCallerFreeProv
  2977. {
  2978. hr = myHLastError();
  2979. if (CRYPT_E_NO_KEY_PROPERTY == hr)
  2980. {
  2981. wprintf(myLoadResourceString(IDS_NO_KEY_PROPERTY)); // "No stored keyset property"
  2982. wprintf(wszNewLine);
  2983. hr = S_OK;
  2984. _JumpError2(
  2985. CRYPT_E_NO_KEY_PROPERTY,
  2986. error,
  2987. "CryptAcquireCertificatePrivateKey",
  2988. CRYPT_E_NO_KEY_PROPERTY);
  2989. }
  2990. if (NTE_BAD_KEYSET == hr)
  2991. {
  2992. wprintf(myLoadResourceString(IDS_NO_KEY)); // "Missing stored keyset"
  2993. wprintf(wszNewLine);
  2994. hr = S_OK;
  2995. _JumpError2(
  2996. NTE_BAD_KEYSET,
  2997. error,
  2998. "CryptAcquireCertificatePrivateKey",
  2999. NTE_BAD_KEYSET);
  3000. }
  3001. _JumpError(hr, error, "CryptAcquireCertificatePrivateKey");
  3002. }
  3003. if (!g_fQuiet)
  3004. {
  3005. DisplayUniqueContainer(hProv);
  3006. }
  3007. if (NULL != pfSigningKey)
  3008. {
  3009. *pfSigningKey = AT_SIGNATURE == dwKeySpec;
  3010. }
  3011. if (!CryptGetUserKey(hProv, dwKeySpec, &hKey))
  3012. {
  3013. hr = myHLastError();
  3014. _PrintError(hr, "CryptGetUserKey");
  3015. cuPrintError(IDS_ERR_FORMAT_LOADKEY, hr);
  3016. goto error;
  3017. }
  3018. hr = myCryptExportPrivateKey(
  3019. hKey,
  3020. &PrivateKey.pbData,
  3021. &PrivateKey.cbData);
  3022. if (NTE_BAD_TYPE == hr || NTE_BAD_KEY_STATE == hr || NTE_PERM == hr)
  3023. {
  3024. wprintf(myLoadResourceString(IDS_PRIVATE_KEY_NOT_EXPORTABLE)); // "Private key is NOT exportable"
  3025. wprintf(wszNewLine);
  3026. }
  3027. else
  3028. {
  3029. _JumpIfError(hr, error, "myCryptExportPrivateKey");
  3030. }
  3031. if (!myCryptExportPublicKeyInfo(
  3032. hProv,
  3033. dwKeySpec,
  3034. CERTLIB_USE_LOCALALLOC,
  3035. &pPublicKeyInfo,
  3036. &cb))
  3037. {
  3038. hr = myHLastError();
  3039. _JumpError(hr, error, "myCryptExportPublicKeyInfo");
  3040. }
  3041. if (!myCertComparePublicKeyInfo(
  3042. X509_ASN_ENCODING,
  3043. CERT_V1 == pCert->pCertInfo->dwVersion,
  3044. pPublicKeyInfo,
  3045. &pCert->pCertInfo->SubjectPublicKeyInfo))
  3046. {
  3047. // by design, (my)CertComparePublicKeyInfo doesn't set last error!
  3048. wprintf(myLoadResourceString(IDS_ERR_PUBLICKEY_MISMATCH)); // "ERROR: Certificate public key does NOT match stored keyset"
  3049. wprintf(wszNewLine);
  3050. }
  3051. else
  3052. {
  3053. if (AT_SIGNATURE == dwKeySpec)
  3054. {
  3055. hr = myValidateKeyForSigning(
  3056. hProv,
  3057. &pCert->pCertInfo->SubjectPublicKeyInfo,
  3058. CALG_SHA1);
  3059. _PrintIfError(hr, "myValidateKeyForSigning");
  3060. }
  3061. else
  3062. {
  3063. hr = myValidateKeyForEncrypting(
  3064. hProv,
  3065. &pCert->pCertInfo->SubjectPublicKeyInfo,
  3066. CALG_RC4);
  3067. _PrintIfError(hr, "myValidateKeyForEncrypting");
  3068. }
  3069. if (S_OK != hr)
  3070. {
  3071. wprintf(myLoadResourceString(IDS_ERR_PRIVATEKEY_MISMATCH)); // "ERROR: Certificate public key does NOT match private key"
  3072. wprintf(wszNewLine);
  3073. hr = S_OK;
  3074. }
  3075. else if (NULL != pfMatchingKey)
  3076. {
  3077. *pfMatchingKey = TRUE;
  3078. }
  3079. if (!g_fQuiet && NULL != PrivateKey.pbData)
  3080. {
  3081. wprintf(wszNewLine);
  3082. hr = cuDumpPrivateKeyBlob(
  3083. PrivateKey.pbData,
  3084. PrivateKey.cbData,
  3085. FALSE);
  3086. _JumpIfError(hr, error, "cuDumpPrivateKeyBlob");
  3087. }
  3088. }
  3089. error:
  3090. if (NULL != PrivateKey.pbData)
  3091. {
  3092. SecureZeroMemory(PrivateKey.pbData, PrivateKey.cbData); // Key material
  3093. LocalFree(PrivateKey.pbData);
  3094. }
  3095. if (NULL != pPublicKeyInfo)
  3096. {
  3097. LocalFree(pPublicKeyInfo);
  3098. }
  3099. if (NULL != hKey)
  3100. {
  3101. CryptDestroyKey(hKey);
  3102. }
  3103. if (NULL != hProv)
  3104. {
  3105. CryptReleaseContext(hProv, 0);
  3106. }
  3107. return(hr);
  3108. }
  3109. HRESULT
  3110. cuDumpCertKeyProviderInfo(
  3111. IN WCHAR const *pwszPrefix,
  3112. OPTIONAL IN CERT_CONTEXT const *pCert,
  3113. OPTIONAL IN CRYPT_KEY_PROV_INFO *pkpi,
  3114. OPTIONAL OUT CRYPT_KEY_PROV_INFO **ppkpi)
  3115. {
  3116. HRESULT hr;
  3117. CRYPT_KEY_PROV_INFO *pkpiT = NULL;
  3118. DWORD i;
  3119. if (NULL != ppkpi)
  3120. {
  3121. *ppkpi = NULL;
  3122. }
  3123. CSASSERT((NULL == pCert) ^ (NULL == pkpi));
  3124. if (NULL != pCert)
  3125. {
  3126. CSASSERT(NULL == pkpi);
  3127. hr = myCertGetKeyProviderInfo(pCert, &pkpiT);
  3128. if (S_OK != hr)
  3129. {
  3130. _PrintIfError2(hr, "myCertGetKeyProviderInfo", CRYPT_E_NOT_FOUND);
  3131. if (CRYPT_E_NOT_FOUND != hr)
  3132. {
  3133. _JumpError(hr, error, "myCertGetKeyProviderInfo");
  3134. }
  3135. // Ignore missing property if we're just dumping the key provider info
  3136. wprintf(myLoadResourceString(IDS_NO_KEY_PROVIDER_INFO)); // "No key provider information"
  3137. wprintf(wszNewLine);
  3138. CSASSERT(NULL == pkpiT);
  3139. hr = S_OK;
  3140. goto error;
  3141. }
  3142. pkpi = pkpiT;
  3143. }
  3144. else
  3145. {
  3146. CSASSERT(NULL != pkpi);
  3147. }
  3148. wprintf(pwszPrefix);
  3149. wprintf(
  3150. myLoadResourceString(IDS_FORMAT_KEY_CONTAINER),
  3151. pkpi->pwszContainerName);
  3152. wprintf(wszNewLine);
  3153. wprintf(pwszPrefix);
  3154. wprintf(
  3155. myLoadResourceString(IDS_FORMAT_PROVIDER_NAME),
  3156. pkpi->pwszProvName);
  3157. wprintf(wszNewLine);
  3158. if (!g_fQuiet)
  3159. {
  3160. wprintf(pwszPrefix);
  3161. wprintf(
  3162. myLoadResourceString(IDS_FORMAT_PROVIDER_TYPE),
  3163. pkpi->dwProvType);
  3164. wprintf(wszNewLine);
  3165. }
  3166. if (!g_fQuiet)
  3167. {
  3168. wprintf(pwszPrefix);
  3169. wprintf(
  3170. myLoadResourceString(IDS_FORMAT_FLAGS),
  3171. pkpi->dwFlags);
  3172. wprintf(wszNewLine);
  3173. if (NULL != pkpi->rgProvParam)
  3174. {
  3175. for (i = 0; i < pkpi->cProvParam; i++)
  3176. {
  3177. wprintf(pwszPrefix);
  3178. wprintf(
  3179. myLoadResourceString(IDS_FORMAT_PROVPARM),
  3180. pkpi->rgProvParam[i].dwParam);
  3181. wprintf(wszNewLine);
  3182. DumpHex(
  3183. DH_MULTIADDRESS | DH_NOTABPREFIX | 4,
  3184. pkpi->rgProvParam[i].pbData,
  3185. pkpi->rgProvParam[i].cbData);
  3186. wprintf(pwszPrefix);
  3187. wprintf(
  3188. myLoadResourceString(IDS_FORMAT_PROVPARMFLAGS),
  3189. pkpi->rgProvParam[i].dwFlags);
  3190. wprintf(wszNewLine);
  3191. }
  3192. }
  3193. wprintf(pwszPrefix);
  3194. wprintf(
  3195. myLoadResourceString(IDS_FORMAT_KEYSPEC),
  3196. pkpi->dwKeySpec);
  3197. wprintf(wszNewLine);
  3198. }
  3199. if (NULL != pkpiT && NULL != ppkpi)
  3200. {
  3201. *ppkpi = pkpiT;
  3202. pkpiT = NULL;
  3203. }
  3204. hr = S_OK;
  3205. error:
  3206. if (NULL != pkpiT)
  3207. {
  3208. LocalFree(pkpiT);
  3209. }
  3210. return(hr);
  3211. }
  3212. VOID
  3213. cuDumpAlgorithm(
  3214. IN DWORD idMessage,
  3215. IN CRYPT_ALGORITHM_IDENTIFIER const *pAlg)
  3216. {
  3217. wprintf(myLoadResourceString(idMessage));
  3218. wprintf(wszNewLine);
  3219. wprintf(g_wszPad4);
  3220. wprintf(myLoadResourceString(IDS_ALG_OID)); // "Algorithm ObjectId"
  3221. wprintf(L": ");
  3222. cuDumpOIDAndDescriptionA(pAlg->pszObjId);
  3223. wprintf(wszNewLine);
  3224. wprintf(g_wszPad4);
  3225. wprintf(myLoadResourceString(IDS_ALG_PARAMETERS_COLON)); // "Algorithm Parameters:"
  3226. if (NULL != pAlg->Parameters.pbData)
  3227. {
  3228. wprintf(wszNewLine);
  3229. DumpHex(
  3230. DH_MULTIADDRESS | DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
  3231. pAlg->Parameters.pbData,
  3232. pAlg->Parameters.cbData);
  3233. }
  3234. else
  3235. {
  3236. wprintf(L" %ws\n", myLoadResourceString(IDS_NULL)); // "NULL"
  3237. }
  3238. }
  3239. VOID
  3240. cuDumpPublicKey(
  3241. IN CERT_PUBLIC_KEY_INFO const *pKey)
  3242. {
  3243. cuDumpAlgorithm(IDS_PUBLICKEY_ALGORITHM, &pKey->Algorithm);
  3244. wprintf(
  3245. myLoadResourceString(IDS_FORMAT_PUBLICKEY_LENGTH), // "Public Key Length: %u bits"
  3246. CertGetPublicKeyLength(
  3247. X509_ASN_ENCODING,
  3248. const_cast<CERT_PUBLIC_KEY_INFO *>(pKey)));
  3249. wprintf(wszNewLine);
  3250. wprintf(
  3251. myLoadResourceString(IDS_FORMAT_PUBLICKEY_UNUSEDBITS), // "Public Key: UnusedBits=%u"
  3252. pKey->PublicKey.cUnusedBits);
  3253. wprintf(wszNewLine);
  3254. DumpHex(
  3255. DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
  3256. pKey->PublicKey.pbData,
  3257. pKey->PublicKey.cbData);
  3258. }
  3259. VOID
  3260. cuDumpSignature(
  3261. OPTIONAL IN CERT_SIGNED_CONTENT_INFO const *pcsci)
  3262. {
  3263. if (NULL == pcsci)
  3264. {
  3265. wprintf(myLoadResourceString(IDS_NO_SIGNATURE));
  3266. wprintf(wszNewLine);
  3267. goto error;
  3268. }
  3269. if (1 < g_fVerbose)
  3270. {
  3271. DumpHex(
  3272. DH_NOTABPREFIX | 4,
  3273. pcsci->ToBeSigned.pbData,
  3274. pcsci->ToBeSigned.cbData);
  3275. }
  3276. cuDumpAlgorithm(IDS_SIGNATURE_ALGORITHM, &pcsci->SignatureAlgorithm);
  3277. wprintf(
  3278. myLoadResourceString(IDS_FORMAT_SIGNATURE_UNUSEDBITS), // "Signature: UnusedBits=%u"
  3279. pcsci->Signature.cUnusedBits);
  3280. wprintf(wszNewLine);
  3281. DumpHex(
  3282. DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
  3283. pcsci->Signature.pbData,
  3284. pcsci->Signature.cbData);
  3285. error:
  3286. ;
  3287. }
  3288. HRESULT
  3289. cuSaveAsnToFile(
  3290. IN BYTE const *pbIn,
  3291. IN DWORD cbIn,
  3292. IN int imajor,
  3293. IN int ilevel,
  3294. IN DWORD iElement,
  3295. IN WCHAR const *pwszExtension)
  3296. {
  3297. HRESULT hr;
  3298. WCHAR awc[MAX_PATH];
  3299. CSASSERT(0 < imajor);
  3300. CSASSERT(0 < ilevel);
  3301. wsprintf(
  3302. awc,
  3303. MAXDWORD == iElement? L"Blob%d_%d" : L"Blob%d_%d_%d",
  3304. imajor - 1,
  3305. ilevel - 1,
  3306. iElement);
  3307. if (wcslen(awc) + wcslen(pwszExtension) >= ARRAYSIZE(awc))
  3308. {
  3309. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  3310. _JumpErrorStr(hr, error, "awc", pwszExtension);
  3311. }
  3312. wcscat(awc, pwszExtension);
  3313. if (g_fSplitASN)
  3314. {
  3315. //wprintf(L"cuSaveAsnToFile: %d %d %d: %ws\n", imajor - 1, ilevel - 1, iElement, awc);
  3316. hr = EncodeToFileW(awc, pbIn, cbIn, CRYPT_STRING_BINARY | g_EncodeFlags);
  3317. _JumpIfError(hr, error, "EncodeToFileW");
  3318. }
  3319. hr = S_OK;
  3320. error:
  3321. return(hr);
  3322. }
  3323. HRESULT
  3324. DumpAsnBlob(
  3325. OPTIONAL IN HCERTSTORE hStoreWrapper,
  3326. IN BOOL fQuiet,
  3327. IN BYTE const *pbIn,
  3328. IN DWORD cbIn,
  3329. IN DWORD iElement)
  3330. {
  3331. HRESULT hr;
  3332. HRESULT hr2;
  3333. ASNFORMATS *pasn;
  3334. ASNFORMATS *pasnEnd;
  3335. DWORD cbDecoded;
  3336. BYTE *pbDecoded = NULL;
  3337. HCERTSTORE hStorePFX = NULL;
  3338. CERT_CONTEXT const *pCert = NULL;
  3339. CRYPT_KEY_PROV_INFO *pkpi = NULL;
  3340. CERT_SIGNED_CONTENT_INFO *pcsci = NULL;
  3341. DWORD cbcsci;
  3342. static int s_major = 0;
  3343. static int s_level = 0;
  3344. BOOL fSaved = FALSE;
  3345. WCHAR wszPassword[MAX_PATH];
  3346. if (0 == s_level)
  3347. {
  3348. s_major++;
  3349. }
  3350. s_level++;
  3351. if (1 < s_level)
  3352. {
  3353. wprintf(myLoadResourceString(IDS_FORMAT_DUMP_LEVEL_START), s_level - 1);
  3354. wprintf(wszNewLine);
  3355. }
  3356. if (MAXDWORD != iElement)
  3357. {
  3358. wprintf(myLoadResourceString(IDS_FORMAT_ELEMENT), iElement);
  3359. wprintf(wszNewLine);
  3360. }
  3361. if (1 < g_fVerbose)
  3362. {
  3363. wprintf(myLoadResourceString(IDS_FORMAT_ELEMENT_DUMP)); // "Embedded ASN.1 Element:"
  3364. wprintf(wszNewLine);
  3365. DumpHex(0, pbIn, cbIn);
  3366. }
  3367. pasnEnd = &g_aasn[CASNFORMATS];
  3368. for (pasn = g_aasn; pasn < pasnEnd; pasn++)
  3369. {
  3370. CSASSERT(NULL == pbDecoded);
  3371. if (myDecodeObject(
  3372. X509_ASN_ENCODING,
  3373. pasn->pszFormat,
  3374. pbIn,
  3375. cbIn,
  3376. CERTLIB_USE_LOCALALLOC,
  3377. (VOID **) &pbDecoded,
  3378. &cbDecoded))
  3379. {
  3380. if (!myDecodeObject(
  3381. X509_ASN_ENCODING,
  3382. X509_CERT,
  3383. pbIn,
  3384. cbIn,
  3385. CERTLIB_USE_LOCALALLOC,
  3386. (VOID **) &pcsci,
  3387. &cbcsci))
  3388. {
  3389. hr = myHLastError();
  3390. _PrintError3(
  3391. hr,
  3392. "myDecodeObject",
  3393. CRYPT_E_ASN1_BADTAG,
  3394. CRYPT_E_ASN1_EOD);
  3395. }
  3396. hr = (*pasn->pfnDump)(
  3397. pasn->idMessage,
  3398. pbIn,
  3399. cbIn,
  3400. pbDecoded,
  3401. cbDecoded,
  3402. pcsci);
  3403. if (S_OK != hr && dumpCertSequence == pasn->pfnDump)
  3404. {
  3405. LocalFree(pbDecoded);
  3406. pbDecoded = NULL;
  3407. CSASSERT(NULL == pcsci);
  3408. continue;
  3409. }
  3410. hr2 = cuSaveAsnToFile(
  3411. pbIn,
  3412. cbIn,
  3413. s_major,
  3414. s_level,
  3415. iElement,
  3416. pasn->pwszExtension);
  3417. _PrintIfError(hr2, "cuSaveAsnToFile");
  3418. fSaved = TRUE;
  3419. _JumpIfError(hr, error, "(*pfnDump)");
  3420. break;
  3421. }
  3422. hr = myHLastError();
  3423. _PrintError2(hr, "myDecodeObject", hr);
  3424. CSASSERT(S_OK != hr);
  3425. }
  3426. if (pasn >= pasnEnd)
  3427. {
  3428. CRYPT_DATA_BLOB pfx;
  3429. CSASSERT(S_OK != hr);
  3430. pfx.pbData = const_cast<BYTE *>(pbIn);
  3431. pfx.cbData = cbIn;
  3432. if (PFXIsPFXBlob(&pfx))
  3433. {
  3434. DWORD dwKeySpec;
  3435. DWORD dwFlags;
  3436. WCHAR const *pwszPassword;
  3437. DWORD iCert;
  3438. hr = cuGetPassword(
  3439. 0, // idsPrompt
  3440. NULL, // pwszfn
  3441. g_pwszPassword,
  3442. FALSE, // fVerify
  3443. wszPassword,
  3444. ARRAYSIZE(wszPassword),
  3445. &pwszPassword);
  3446. _JumpIfError(hr, error, "cuGetPassword");
  3447. hStorePFX = myPFXImportCertStore(
  3448. &pfx,
  3449. pwszPassword,
  3450. CRYPT_EXPORTABLE);
  3451. if (NULL == hStorePFX)
  3452. {
  3453. hr = myHLastError();
  3454. _JumpError(hr, error, "myPFXImportCertStore");
  3455. }
  3456. hr = cuSaveAsnToFile(pbIn, cbIn, s_major, s_level, iElement, L".p12");
  3457. _PrintIfError(hr, "cuSaveAsnToFile");
  3458. fSaved = TRUE;
  3459. for (iCert = 0; ; iCert++)
  3460. {
  3461. BOOL fSigningKey;
  3462. BOOL fMatchingKey;
  3463. BOOL fRepaired = FALSE;
  3464. pCert = CertEnumCertificatesInStore(hStorePFX, pCert);
  3465. if (NULL == pCert)
  3466. {
  3467. break;
  3468. }
  3469. hr = cuDumpAsnBinary(
  3470. pCert->pbCertEncoded,
  3471. pCert->cbCertEncoded,
  3472. iCert);
  3473. _JumpIfError(hr, error, "cuDumpAsnBinary");
  3474. while (TRUE)
  3475. {
  3476. if (NULL != pkpi)
  3477. {
  3478. LocalFree(pkpi);
  3479. pkpi = NULL;
  3480. }
  3481. hr = cuDumpCertKeyProviderInfo(
  3482. g_wszPad2,
  3483. pCert,
  3484. NULL,
  3485. &pkpi);
  3486. if (S_OK != hr)
  3487. {
  3488. if (CRYPT_E_NOT_FOUND != hr)
  3489. {
  3490. _JumpError(hr, error, "cuDumpCertKeyProviderInfo");
  3491. }
  3492. }
  3493. else
  3494. if (NULL != pkpi)
  3495. {
  3496. // NT4 PFXImportCertStore doesn't set machine keyset
  3497. hr = cuDumpPrivateKey(
  3498. pCert,
  3499. &fSigningKey,
  3500. &fMatchingKey);
  3501. _PrintIfError2(
  3502. hr,
  3503. "cuDumpPrivateKey",
  3504. CRYPT_E_NO_KEY_PROPERTY);
  3505. if (S_OK == hr &&
  3506. !fMatchingKey &&
  3507. !fRepaired &&
  3508. 0 == (CRYPT_MACHINE_KEYSET & pkpi->dwFlags))
  3509. {
  3510. LocalFree(pkpi);
  3511. pkpi = NULL;
  3512. hr = myRepairCertKeyProviderInfo(pCert, TRUE, NULL);
  3513. _JumpIfError(hr, error, "myRepairCertKeyProviderInfo");
  3514. fRepaired = TRUE;
  3515. continue;
  3516. }
  3517. }
  3518. break;
  3519. }
  3520. }
  3521. hr = S_OK;
  3522. }
  3523. else
  3524. {
  3525. hr = dumpPKCS7(hStoreWrapper, pbIn, cbIn);
  3526. if (S_OK == hr)
  3527. {
  3528. hr = cuSaveAsnToFile(
  3529. pbIn,
  3530. cbIn,
  3531. s_major,
  3532. s_level,
  3533. iElement,
  3534. L".p7b");
  3535. _PrintIfError(hr, "cuSaveAsnToFile");
  3536. fSaved = TRUE;
  3537. }
  3538. else
  3539. {
  3540. hr = cuDumpPrivateKeyBlob(pbIn, cbIn, fQuiet);
  3541. if (S_OK == hr)
  3542. {
  3543. hr = cuSaveAsnToFile(
  3544. pbIn,
  3545. cbIn,
  3546. s_major,
  3547. s_level,
  3548. iElement,
  3549. L".key");
  3550. _PrintIfError(hr, "cuSaveAsnToFile");
  3551. fSaved = TRUE;
  3552. }
  3553. else
  3554. {
  3555. _PrintError2(hr, "dumpPKCS7", CRYPT_E_ASN1_BADTAG);
  3556. if (!fQuiet)
  3557. {
  3558. DumpHex(DH_MULTIADDRESS | DH_NOTABPREFIX | 4, pbIn, cbIn);
  3559. }
  3560. }
  3561. hr = S_OK;
  3562. }
  3563. }
  3564. }
  3565. error:
  3566. SecureZeroMemory(wszPassword, sizeof(wszPassword)); // password data
  3567. if (!fSaved)
  3568. {
  3569. hr2 = cuSaveAsnToFile(pbIn, cbIn, s_major, s_level, iElement, L".bin");
  3570. _PrintIfError(hr2, "cuSaveAsnToFile");
  3571. }
  3572. if (NULL != pkpi)
  3573. {
  3574. LocalFree(pkpi);
  3575. }
  3576. if (NULL != pCert)
  3577. {
  3578. CertFreeCertificateContext(pCert);
  3579. }
  3580. if (NULL != hStorePFX)
  3581. {
  3582. myDeleteGuidKeys(hStorePFX, FALSE);
  3583. CertCloseStore(hStorePFX, CERT_CLOSE_STORE_CHECK_FLAG);
  3584. }
  3585. if (NULL != pcsci)
  3586. {
  3587. LocalFree(pcsci);
  3588. }
  3589. if (NULL != pbDecoded)
  3590. {
  3591. LocalFree(pbDecoded);
  3592. }
  3593. if (1 < s_level)
  3594. {
  3595. wprintf(myLoadResourceString(IDS_FORMAT_DUMP_LEVEL_END), s_level - 1);
  3596. wprintf(wszNewLine);
  3597. }
  3598. s_level--;
  3599. return(hr);
  3600. }
  3601. HRESULT
  3602. cuDumpAsnBinary(
  3603. IN BYTE const *pbIn,
  3604. IN DWORD cbIn,
  3605. IN DWORD iElement)
  3606. {
  3607. return(DumpAsnBlob(NULL, FALSE, pbIn, cbIn, iElement));
  3608. }
  3609. HRESULT
  3610. cuDumpExtensionArray(
  3611. IN DWORD idMessage,
  3612. IN DWORD cExtension,
  3613. IN CERT_EXTENSION const *rgExtension)
  3614. {
  3615. HRESULT hr;
  3616. DWORD i;
  3617. WCHAR *pwszName = NULL;
  3618. WCHAR const *pwszExtensionFormat;
  3619. if (!g_fQuiet)
  3620. {
  3621. wprintf(myLoadResourceString(idMessage));
  3622. wprintf(L" %u\n", cExtension);
  3623. }
  3624. pwszExtensionFormat = myLoadResourceString(IDS_FORMAT_EXTENSION); // "%ws: Flags = %x%ws, Length = %x"
  3625. for (i = 0; i < cExtension; i++)
  3626. {
  3627. CERT_EXTENSION const *pce;
  3628. if (NULL != pwszName)
  3629. {
  3630. LocalFree(pwszName);
  3631. pwszName = NULL;
  3632. }
  3633. pce = &rgExtension[i];
  3634. if (g_fQuiet &&
  3635. 0 != strcmp(pce->pszObjId, szOID_CERTSRV_CA_VERSION) &&
  3636. 0 != strcmp(pce->pszObjId, szOID_ENROLL_CERTTYPE_EXTENSION) &&
  3637. 0 != strcmp(pce->pszObjId, szOID_CRL_NUMBER) &&
  3638. 0 != strcmp(pce->pszObjId, szOID_CRL_VIRTUAL_BASE) &&
  3639. 0 != strcmp(pce->pszObjId, szOID_DELTA_CRL_INDICATOR))
  3640. {
  3641. continue;
  3642. }
  3643. if (!ConvertSzToWsz(&pwszName, pce->pszObjId, -1))
  3644. {
  3645. hr = E_OUTOFMEMORY;
  3646. _JumpError(hr, error, "ConvertSzToWsz");
  3647. }
  3648. if (!g_fQuiet)
  3649. {
  3650. wprintf(g_wszPad4);
  3651. wprintf(
  3652. pwszExtensionFormat,
  3653. pwszName,
  3654. pce->fCritical,
  3655. cuwszFromExtFlags(pce->fCritical),
  3656. pce->Value.cbData);
  3657. wprintf(wszNewLine);
  3658. }
  3659. if (!cuDumpFormattedExtension(
  3660. pwszName,
  3661. pce->Value.pbData,
  3662. pce->Value.cbData) ||
  3663. g_fVerbose)
  3664. {
  3665. wprintf(wszNewLine);
  3666. DumpHex(DH_NOTABPREFIX | 4, pce->Value.pbData, pce->Value.cbData);
  3667. }
  3668. if (!g_fQuiet)
  3669. {
  3670. wprintf(wszNewLine);
  3671. }
  3672. }
  3673. hr = S_OK;
  3674. error:
  3675. if (NULL != pwszName)
  3676. {
  3677. LocalFree(pwszName);
  3678. }
  3679. return(hr);
  3680. }
  3681. VOID
  3682. cuDumpVersion(
  3683. IN DWORD dwVersion)
  3684. {
  3685. wprintf(
  3686. myLoadResourceString(IDS_FORMAT_VERSION), // "Version: %u"
  3687. dwVersion);
  3688. wprintf(wszNewLine);
  3689. }
  3690. HRESULT
  3691. cuDumpCMSSignerInfo(
  3692. IN CMSG_CMS_SIGNER_INFO const *pcsi,
  3693. IN DWORD iElement,
  3694. IN BOOL fQuiet,
  3695. DWORD idVerify,
  3696. OPTIONAL IN HCERTSTORE hStore,
  3697. OPTIONAL OUT BYTE *pbHashUserCert,
  3698. OPTIONAL IN OUT DWORD *pcbHashUserCert)
  3699. {
  3700. HRESULT hr;
  3701. WCHAR const *pwszFmt = MAXDWORD == iElement? L"%ws:\n" : L"%ws[%u]:\n";
  3702. if (!fQuiet || g_fVerbose)
  3703. {
  3704. if (!fQuiet)
  3705. {
  3706. wprintf(wszNewLine);
  3707. }
  3708. wprintf(
  3709. pwszFmt,
  3710. myLoadResourceString(IDS_SIGNER_INFO), // "Signer Info"
  3711. iElement);
  3712. if (!fQuiet)
  3713. {
  3714. WCHAR const *pwszVersion = NULL;
  3715. if (0 != idVerify)
  3716. {
  3717. wprintf(myLoadResourceString(idVerify));
  3718. wprintf(wszNewLine);
  3719. }
  3720. switch (pcsi->dwVersion)
  3721. {
  3722. case CMSG_SIGNER_INFO_PKCS_1_5_VERSION:
  3723. pwszVersion = L"CMSG_SIGNER_INFO_PKCS_1_5_VERSION";
  3724. break;
  3725. case CMSG_SIGNER_INFO_CMS_VERSION:
  3726. pwszVersion = L"CMSG_SIGNER_INFO_CMS_VERSION";
  3727. break;
  3728. }
  3729. if (NULL == pwszVersion)
  3730. {
  3731. cuDumpVersion(pcsi->dwVersion);
  3732. }
  3733. else
  3734. {
  3735. wprintf(L"%ws(%u)\n", pwszVersion, pcsi->dwVersion);
  3736. }
  3737. }
  3738. switch (pcsi->SignerId.dwIdChoice)
  3739. {
  3740. case CERT_ID_ISSUER_SERIAL_NUMBER:
  3741. wprintf(
  3742. L"%ws(%u)\n",
  3743. L"CERT_ID_ISSUER_SERIAL_NUMBER",
  3744. pcsi->SignerId.dwIdChoice);
  3745. hr = cuDumpIssuerSerialAndSubject(
  3746. &pcsi->SignerId.IssuerSerialNumber.Issuer,
  3747. &pcsi->SignerId.IssuerSerialNumber.SerialNumber,
  3748. NULL, // pSubject
  3749. hStore);
  3750. _JumpIfError(hr, error, "cuDumpIssuerSerialAndSubject(Signer)");
  3751. break;
  3752. case CERT_ID_KEY_IDENTIFIER:
  3753. wprintf(
  3754. L"%ws(%u)\n",
  3755. L"CERT_ID_KEY_IDENTIFIER",
  3756. pcsi->SignerId.dwIdChoice);
  3757. DumpHex(
  3758. DH_MULTIADDRESS | DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
  3759. pcsi->SignerId.KeyId.pbData,
  3760. pcsi->SignerId.KeyId.cbData);
  3761. break;
  3762. case CERT_ID_SHA1_HASH:
  3763. wprintf(
  3764. L"%ws(%u)\n",
  3765. L"CERT_ID_SHA1_HASH",
  3766. pcsi->SignerId.dwIdChoice);
  3767. DumpHex(
  3768. DH_MULTIADDRESS | DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
  3769. pcsi->SignerId.HashId.pbData,
  3770. pcsi->SignerId.HashId.cbData);
  3771. break;
  3772. default:
  3773. wprintf(
  3774. L"%ws(%u)\n",
  3775. myLoadResourceString(IDS_QUESTIONMARKS), // "???"
  3776. pcsi->SignerId.dwIdChoice);
  3777. break;
  3778. }
  3779. }
  3780. if (!fQuiet)
  3781. {
  3782. cuDumpAlgorithm(IDS_HASH_ALGORITHM, &pcsi->HashAlgorithm);
  3783. cuDumpAlgorithm(IDS_HASH_ENCRYPTION_ALGORITHM, &pcsi->HashEncryptionAlgorithm);
  3784. wprintf(myLoadResourceString(IDS_FORMAT_ENCRYPTEDHASH_COLON)); // "Encrypted Hash:"
  3785. wprintf(wszNewLine);
  3786. DumpHex(
  3787. DH_MULTIADDRESS | DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
  3788. pcsi->EncryptedHash.pbData,
  3789. pcsi->EncryptedHash.cbData);
  3790. wprintf(wszNewLine);
  3791. wprintf(
  3792. pwszFmt,
  3793. myLoadResourceString(IDS_DUMP_PKCS7_ATTRIBUTES),
  3794. iElement);
  3795. }
  3796. if (!fQuiet || NULL != pbHashUserCert)
  3797. {
  3798. hr = DumpAttributes(
  3799. pcsi->AuthAttrs.rgAttr,
  3800. pcsi->AuthAttrs.cAttr,
  3801. fQuiet,
  3802. FOT_ATTRIBUTE,
  3803. hStore,
  3804. pbHashUserCert,
  3805. pcbHashUserCert,
  3806. NULL);
  3807. _JumpIfError(hr, error, "DumpAttributes");
  3808. }
  3809. if (!fQuiet)
  3810. {
  3811. wprintf(wszNewLine);
  3812. wprintf(
  3813. pwszFmt,
  3814. myLoadResourceString(IDS_DUMP_PKCS7_UNAUTHATTRIBUTES),
  3815. iElement);
  3816. hr = DumpAttributes(
  3817. pcsi->UnauthAttrs.rgAttr,
  3818. pcsi->UnauthAttrs.cAttr,
  3819. fQuiet,
  3820. FOT_ATTRIBUTE,
  3821. hStore,
  3822. NULL,
  3823. NULL,
  3824. NULL);
  3825. _JumpIfError(hr, error, "DumpAttributes");
  3826. }
  3827. hr = S_OK;
  3828. error:
  3829. return(hr);
  3830. }
  3831. HRESULT
  3832. cuDumpSignerInfo(
  3833. IN CMSG_SIGNER_INFO const *psi,
  3834. IN DWORD iElement,
  3835. IN BOOL fQuiet,
  3836. DWORD idVerify,
  3837. OPTIONAL IN HCERTSTORE hStore,
  3838. OPTIONAL OUT BYTE *pbHashUserCert,
  3839. OPTIONAL IN OUT DWORD *pcbHashUserCert)
  3840. {
  3841. HRESULT hr;
  3842. CMSG_CMS_SIGNER_INFO csi;
  3843. ZeroMemory(&csi, sizeof(csi));
  3844. csi.dwVersion = psi->dwVersion;
  3845. csi.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
  3846. csi.SignerId.IssuerSerialNumber.Issuer = psi->Issuer;
  3847. csi.SignerId.IssuerSerialNumber.SerialNumber = psi->SerialNumber;
  3848. csi.HashAlgorithm = psi->HashAlgorithm;
  3849. csi.HashEncryptionAlgorithm = psi->HashEncryptionAlgorithm;
  3850. csi.EncryptedHash = psi->EncryptedHash;
  3851. csi.AuthAttrs = psi->AuthAttrs;
  3852. csi.UnauthAttrs = psi->UnauthAttrs;
  3853. hr = cuDumpCMSSignerInfo(
  3854. &csi,
  3855. iElement,
  3856. fQuiet,
  3857. idVerify,
  3858. hStore,
  3859. pbHashUserCert,
  3860. pcbHashUserCert);
  3861. _JumpIfError(hr, error, "cuDumpCMSSignerInfo");
  3862. error:
  3863. return(hr);
  3864. }
  3865. HRESULT
  3866. DumpAttributes(
  3867. IN CRYPT_ATTRIBUTE const *rgAttr,
  3868. IN DWORD cAttr,
  3869. IN BOOL fQuiet,
  3870. IN DWORD Type, // FOT_*
  3871. OPTIONAL IN HCERTSTORE hStore,
  3872. OPTIONAL OUT BYTE *pbHashUserCert,
  3873. OPTIONAL IN OUT DWORD *pcbHashUserCert,
  3874. OPTIONAL IN OUT CERT_EXTENSIONS **ppExtInfo)
  3875. {
  3876. HRESULT hr;
  3877. CRYPT_ATTRIBUTE const *pAttr;
  3878. CRYPT_ATTRIBUTE const *pAttrEnd;
  3879. CRYPT_ENROLLMENT_NAME_VALUE_PAIR *pNamePair = NULL;
  3880. CERT_EXTENSIONS *pExtInfo = NULL;
  3881. CERT_NAME_VALUE *pNameInfo = NULL;
  3882. DWORD cb;
  3883. DWORD iv;
  3884. if (NULL != ppExtInfo)
  3885. {
  3886. *ppExtInfo = NULL;
  3887. }
  3888. if (!fQuiet && FOT_PROPERTY != Type)
  3889. {
  3890. wprintf(
  3891. myLoadResourceString(IDS_FORMAT_PKCS7_ATTRIBUTE_COUNT), // " %d attributes:"
  3892. cAttr);
  3893. wprintf(wszNewLine);
  3894. }
  3895. pAttrEnd = &rgAttr[cAttr];
  3896. for (pAttr = rgAttr; pAttr < pAttrEnd; pAttr++)
  3897. {
  3898. WCHAR const *pwszOID = cuGetOIDNameA(pAttr->pszObjId);
  3899. if (!fQuiet && FOT_PROPERTY != Type)
  3900. {
  3901. wprintf(wszNewLine);
  3902. wprintf(
  3903. L" %ws[%u]: %hs%ws%ws%ws\n",
  3904. myLoadResourceString(IDS_ATTRIBUTE), // "Attribute"
  3905. pAttr - rgAttr,
  3906. pAttr->pszObjId,
  3907. L'\0' != *pwszOID? L" " wszLPAREN : g_wszEmpty,
  3908. pwszOID,
  3909. L'\0' != *pwszOID? wszRPAREN : g_wszEmpty);
  3910. }
  3911. for (iv = 0; iv < pAttr->cValue; iv++)
  3912. {
  3913. CRYPT_ATTR_BLOB const *pval = &pAttr->rgValue[iv];
  3914. if (fQuiet)
  3915. {
  3916. if (0 == strcmp(pAttr->pszObjId, szOID_ARCHIVED_KEY_CERT_HASH))
  3917. {
  3918. hr = DumpOctetHash(
  3919. g_wszEmpty,
  3920. 0,
  3921. g_wszEmpty,
  3922. pval->pbData,
  3923. pval->cbData,
  3924. pbHashUserCert,
  3925. pcbHashUserCert);
  3926. _JumpIfError(hr, error, "DumpOctetHash");
  3927. }
  3928. }
  3929. else
  3930. {
  3931. if (FOT_PROPERTY != Type)
  3932. {
  3933. wprintf(
  3934. myLoadResourceString(IDS_FORMAT_PKCS7_ATTRIBUTE_VALUE), // " Value[%d][%d]:"
  3935. pAttr - rgAttr,
  3936. iv);
  3937. wprintf(wszNewLine);
  3938. }
  3939. if (!DumpFormattedObject(
  3940. pAttr->pszObjId,
  3941. Type, // FOT_*
  3942. pval->pbData,
  3943. pval->cbData))
  3944. {
  3945. BOOL fDumpHex = FALSE;
  3946. if (0 == strcmp(pAttr->pszObjId, szOID_ENROLLMENT_NAME_VALUE_PAIR))
  3947. {
  3948. if (g_fVerbose)
  3949. {
  3950. DumpHex(0, pval->pbData, pval->cbData);
  3951. }
  3952. if (NULL != pNamePair)
  3953. {
  3954. LocalFree(pNamePair);
  3955. pNamePair = NULL;
  3956. }
  3957. if (!myDecodeNameValuePair(
  3958. X509_ASN_ENCODING,
  3959. pval->pbData,
  3960. pval->cbData,
  3961. CERTLIB_USE_LOCALALLOC,
  3962. &pNamePair,
  3963. &cb))
  3964. {
  3965. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  3966. _JumpError(hr, error, "myDecodeNameValuePair");
  3967. // if attribute name & value are both non-empty ...
  3968. }
  3969. wprintf(
  3970. L" %ws%ws = %ws\n",
  3971. pNamePair->pwszName,
  3972. g_wszCertUtil,
  3973. pNamePair->pwszValue);
  3974. }
  3975. else
  3976. if (0 == strcmp(pAttr->pszObjId, szOID_CERT_EXTENSIONS) ||
  3977. 0 == strcmp(pAttr->pszObjId, szOID_RSA_certExtensions))
  3978. {
  3979. if (NULL != pNameInfo)
  3980. {
  3981. LocalFree(pNameInfo);
  3982. pNameInfo = NULL;
  3983. }
  3984. while (TRUE)
  3985. {
  3986. if (NULL != pExtInfo)
  3987. {
  3988. LocalFree(pExtInfo);
  3989. pExtInfo = NULL;
  3990. }
  3991. if (myDecodeObject(
  3992. X509_ASN_ENCODING,
  3993. X509_EXTENSIONS,
  3994. pval->pbData,
  3995. pval->cbData,
  3996. CERTLIB_USE_LOCALALLOC,
  3997. (VOID **) &pExtInfo,
  3998. &cb))
  3999. {
  4000. break; // success
  4001. }
  4002. hr = myHLastError();
  4003. // if we already decoded the attribute as a T61
  4004. // string, or if it's not a PKCS 9.14 attribute,
  4005. // just hex dump the attribute -- we don't know
  4006. // what it contains.
  4007. if (NULL != pNameInfo ||
  4008. 0 != strcmp(
  4009. pAttr->pszObjId,
  4010. szOID_RSA_certExtensions))
  4011. {
  4012. //_JumpError(hr, error, "myDecodeObject");
  4013. _PrintError(hr, "myDecodeObject");
  4014. fDumpHex = TRUE;
  4015. break;
  4016. }
  4017. // decode the attribute as a T61 string. Some
  4018. // implementations wrap the PKCS 9.14 extension
  4019. // array in an extra level of encoding as a Teletex
  4020. // string.
  4021. if (!myDecodeObject(
  4022. X509_ASN_ENCODING,
  4023. X509_ANY_STRING,
  4024. pval->pbData,
  4025. pval->cbData,
  4026. CERTLIB_USE_LOCALALLOC,
  4027. (VOID **) &pNameInfo,
  4028. &cb))
  4029. {
  4030. hr = myHLastError();
  4031. //_JumpError(hr, error, "myDecodeObject");
  4032. _PrintError(hr, "myDecodeObject");
  4033. fDumpHex = TRUE;
  4034. break;
  4035. }
  4036. // Now loop again and try to decode the raw name
  4037. // blob as X509_EXTENSIONS.
  4038. pval = &pNameInfo->Value;
  4039. wprintf(myLoadResourceString(IDS_TELETEX_EXTENSIONS)); // "Decoded extra Extension Array encoding layer (Teletex string)"
  4040. wprintf(wszNewLine);
  4041. }
  4042. if (!fDumpHex)
  4043. {
  4044. hr = cuDumpExtensionArray(
  4045. IDS_CERTIFICATE_EXTENSIONS,
  4046. pExtInfo->cExtension,
  4047. pExtInfo->rgExtension);
  4048. _JumpIfError(hr, error, "cuDumpExtensionArray");
  4049. }
  4050. }
  4051. else
  4052. if (0 == strcmp(pAttr->pszObjId, szOID_RENEWAL_CERTIFICATE) ||
  4053. 0 == strcmp(pAttr->pszObjId, szOID_RSA_SMIMECapabilities))
  4054. {
  4055. wprintf(myLoadResourceString(
  4056. 0 == strcmp(
  4057. pAttr->pszObjId,
  4058. szOID_RENEWAL_CERTIFICATE)?
  4059. IDS_RENEWAL_CERT : // "Renewal Certificate:"
  4060. IDS_SMIME_CAPABILITIES)); // "SMIME Capabilities:"
  4061. wprintf(wszNewLine);
  4062. hr = cuDumpAsnBinary(pval->pbData, pval->cbData, MAXDWORD);
  4063. _JumpIfError(hr, error, "cuDumpAsnBinary");
  4064. }
  4065. else
  4066. if (0 == strcmp(pAttr->pszObjId, szOID_RSA_contentType))
  4067. {
  4068. char *pszObjId;
  4069. hr = cuDecodeObjId(pval->pbData, pval->cbData, &pszObjId);
  4070. if (S_OK != hr)
  4071. {
  4072. fDumpHex = TRUE;
  4073. }
  4074. else
  4075. {
  4076. wprintf(g_wszPad4);
  4077. cuDumpOIDAndDescriptionA(pszObjId);
  4078. wprintf(wszNewLine);
  4079. LocalFree(pszObjId);
  4080. }
  4081. }
  4082. else
  4083. if (0 == strcmp(pAttr->pszObjId, szOID_RSA_messageDigest))
  4084. {
  4085. hr = DumpOctetHash(
  4086. g_wszPad4,
  4087. IDS_MESSAGE_DIGEST,
  4088. g_wszCertUtil,
  4089. pval->pbData,
  4090. pval->cbData,
  4091. NULL,
  4092. NULL);
  4093. if (S_OK != hr)
  4094. {
  4095. fDumpHex = TRUE;
  4096. }
  4097. }
  4098. else
  4099. if (0 == strcmp(pAttr->pszObjId, szOID_ARCHIVED_KEY_ATTR))
  4100. {
  4101. hr = cuDumpAsnBinary(pval->pbData, pval->cbData, MAXDWORD);
  4102. if (S_OK != hr)
  4103. {
  4104. fDumpHex = TRUE;
  4105. }
  4106. }
  4107. else
  4108. if (0 == strcmp(pAttr->pszObjId, szOID_ARCHIVED_KEY_CERT_HASH))
  4109. {
  4110. hr = DumpOctetHash(
  4111. g_wszPad4,
  4112. IDS_ARCHIVED_KEY_CERT_HASH,
  4113. g_wszCertUtil,
  4114. pval->pbData,
  4115. pval->cbData,
  4116. pbHashUserCert,
  4117. pcbHashUserCert);
  4118. if (S_OK != hr)
  4119. {
  4120. fDumpHex = TRUE;
  4121. }
  4122. }
  4123. else
  4124. if (0 == strcmp(pAttr->pszObjId, szOID_ISSUED_CERT_HASH))
  4125. {
  4126. hr = DumpOctetHash(
  4127. g_wszPad4,
  4128. IDS_ISSUED_CERT_HASH,
  4129. g_wszCertUtil,
  4130. pval->pbData,
  4131. pval->cbData,
  4132. pbHashUserCert,
  4133. pcbHashUserCert);
  4134. if (S_OK != hr)
  4135. {
  4136. fDumpHex = TRUE;
  4137. }
  4138. }
  4139. else
  4140. if (0 == strcmp(pAttr->pszObjId, szOID_ENCRYPTED_KEY_HASH))
  4141. {
  4142. hr = DumpOctetHash(
  4143. g_wszPad4,
  4144. IDS_ENCRYPTED_KEY_HASH,
  4145. g_wszCertUtil,
  4146. pval->pbData,
  4147. pval->cbData,
  4148. NULL,
  4149. NULL);
  4150. if (S_OK != hr)
  4151. {
  4152. fDumpHex = TRUE;
  4153. }
  4154. }
  4155. else
  4156. if (0 == strcmp(pAttr->pszObjId, szOID_ENROLLMENT_CSP_PROVIDER))
  4157. {
  4158. CRYPT_CSP_PROVIDER *pccp;
  4159. hr = myDecodeCSPProviderAttribute(
  4160. pval->pbData,
  4161. pval->cbData,
  4162. &pccp);
  4163. if (S_OK == hr)
  4164. {
  4165. wprintf(g_wszPad4);
  4166. wprintf(
  4167. myLoadResourceString(IDS_CSP_PROVIDER_INFO));
  4168. wprintf(wszNewLine);
  4169. wprintf(g_wszPad4);
  4170. wprintf(
  4171. myLoadResourceString(IDS_FORMAT_KEYSPEC),
  4172. pccp->dwKeySpec);
  4173. wprintf(wszNewLine);
  4174. wprintf(g_wszPad4);
  4175. wprintf(
  4176. myLoadResourceString(IDS_FORMAT_PROVIDER_NAME),
  4177. NULL == pccp->pwszProviderName?
  4178. myLoadResourceString(IDS_PROP_EMPTY) :
  4179. pccp->pwszProviderName);
  4180. wprintf(wszNewLine);
  4181. wprintf(g_wszPad4);
  4182. wprintf(
  4183. myLoadResourceString(IDS_FORMAT_SIGNATURE_UNUSEDBITS), // "Signature: UnusedBits=%u"
  4184. pccp->Signature.cUnusedBits);
  4185. wprintf(wszNewLine);
  4186. DumpHex(
  4187. DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
  4188. pccp->Signature.pbData,
  4189. pccp->Signature.cbData);
  4190. LocalFree(pccp);
  4191. }
  4192. else
  4193. {
  4194. fDumpHex = TRUE;
  4195. }
  4196. }
  4197. else
  4198. if (0 == strcmp(pAttr->pszObjId, szOID_RSA_signingTime))
  4199. {
  4200. FILETIME ft;
  4201. cb = sizeof(ft);
  4202. if (CryptDecodeObject(
  4203. X509_ASN_ENCODING,
  4204. X509_CHOICE_OF_TIME,
  4205. pval->pbData,
  4206. pval->cbData,
  4207. 0,
  4208. &ft,
  4209. &cb))
  4210. {
  4211. wprintf(
  4212. L"%ws%ws%ws: ",
  4213. g_wszPad4,
  4214. myLoadResourceString(IDS_SIGNING_TIME),
  4215. g_wszCertUtil);
  4216. hr = cuDumpFileTime(0, NULL, &ft);
  4217. _JumpIfError(hr, error, "cuDumpFileTime");
  4218. }
  4219. else
  4220. {
  4221. fDumpHex = TRUE;
  4222. }
  4223. }
  4224. else
  4225. if (0 == strcmp(pAttr->pszObjId, szOID_REQUEST_CLIENT_INFO))
  4226. {
  4227. CRYPT_REQUEST_CLIENT_INFO *pcrci = NULL;
  4228. hr = myDecodeRequestClientAttribute(
  4229. pval->pbData,
  4230. pval->cbData,
  4231. &pcrci);
  4232. if (S_OK == hr)
  4233. {
  4234. wprintf(g_wszPad2);
  4235. cuRegPrintDwordValue(
  4236. TRUE,
  4237. wszREQUESTCLIENTID,
  4238. myLoadResourceString(IDS_CLIENTID),
  4239. pcrci->dwClientId);
  4240. wprintf(
  4241. L"%ws%ws %ws\n",
  4242. g_wszPad4,
  4243. myLoadResourceString(IDS_USERCOLON),
  4244. pcrci->pwszUser);
  4245. wprintf(
  4246. L"%ws%ws %ws\n",
  4247. g_wszPad4,
  4248. myLoadResourceString(IDS_MACHINECOLON),
  4249. pcrci->pwszMachine);
  4250. wprintf(
  4251. L"%ws%ws %ws\n",
  4252. g_wszPad4,
  4253. myLoadResourceString(IDS_PROCESSCOLON),
  4254. pcrci->pwszProcess);
  4255. LocalFree(pcrci);
  4256. }
  4257. else
  4258. {
  4259. fDumpHex = TRUE;
  4260. }
  4261. }
  4262. else
  4263. if (0 == strcmp(pAttr->pszObjId, szOID_RSA_counterSign))
  4264. {
  4265. CMSG_SIGNER_INFO *psi = NULL;
  4266. if (!myDecodeObject(
  4267. X509_ASN_ENCODING,
  4268. PKCS7_SIGNER_INFO,
  4269. pval->pbData,
  4270. pval->cbData,
  4271. CERTLIB_USE_LOCALALLOC,
  4272. (VOID **) &psi,
  4273. &cb))
  4274. {
  4275. CSASSERT(NULL == psi);
  4276. hr = myHLastError();
  4277. _PrintError(hr, "myDecodeObject");
  4278. fDumpHex = TRUE;
  4279. }
  4280. else
  4281. {
  4282. wprintf(
  4283. L"%ws%ws%ws: ",
  4284. g_wszPad4,
  4285. myLoadResourceString(IDS_COUNTER_SIGNATURE),
  4286. g_wszCertUtil);
  4287. hr = cuDumpSignerInfo(
  4288. psi,
  4289. MAXDWORD, // iElement
  4290. fQuiet,
  4291. 0,
  4292. hStore,
  4293. pbHashUserCert,
  4294. pcbHashUserCert);
  4295. _PrintIfError(hr, "cuDumpSignerInfo");
  4296. if (S_OK != hr)
  4297. {
  4298. fDumpHex = TRUE;
  4299. }
  4300. }
  4301. if (NULL != psi)
  4302. {
  4303. LocalFree(psi);
  4304. }
  4305. }
  4306. else
  4307. if (0 == strcmp(pAttr->pszObjId, szOID_RSA_challengePwd))
  4308. {
  4309. CRYPT_DATA_BLOB Value;
  4310. WCHAR *pwsz;
  4311. Value.pbData = pval->pbData;
  4312. Value.cbData = pval->cbData;
  4313. hr = UnicodeDecode(&Value, &pwsz);
  4314. if (S_OK == hr)
  4315. {
  4316. wprintf(L"%ws%ws\n", g_wszPad4, pwsz);
  4317. LocalFree(pwsz);
  4318. }
  4319. else
  4320. {
  4321. fDumpHex = TRUE;
  4322. }
  4323. }
  4324. else
  4325. if (0 == strcmp(pAttr->pszObjId, szOID_YESNO_TRUST_ATTR))
  4326. {
  4327. DWORD Bool;
  4328. cb = sizeof(Bool);
  4329. Bool = 0;
  4330. if (CryptDecodeObject(
  4331. X509_ASN_ENCODING,
  4332. X509_INTEGER,
  4333. pval->pbData,
  4334. pval->cbData,
  4335. 0,
  4336. &Bool,
  4337. &cb))
  4338. {
  4339. wprintf(
  4340. L"%ws%x\n",
  4341. g_wszPad4,
  4342. Bool);
  4343. }
  4344. else
  4345. {
  4346. fDumpHex = TRUE;
  4347. }
  4348. }
  4349. if (fDumpHex)
  4350. {
  4351. DumpHex(
  4352. DH_NOTABPREFIX | 4,
  4353. pval->pbData,
  4354. pval->cbData);
  4355. }
  4356. }
  4357. }
  4358. }
  4359. }
  4360. if (NULL != ppExtInfo)
  4361. {
  4362. *ppExtInfo = pExtInfo;
  4363. pExtInfo = NULL;
  4364. }
  4365. hr = S_OK;
  4366. error:
  4367. if (NULL != pNamePair)
  4368. {
  4369. LocalFree(pNamePair);
  4370. }
  4371. if (NULL != pExtInfo)
  4372. {
  4373. LocalFree(pExtInfo);
  4374. }
  4375. if (NULL != pNameInfo)
  4376. {
  4377. LocalFree(pNameInfo);
  4378. }
  4379. return(hr);
  4380. }
  4381. HRESULT
  4382. FindCertStoreIndex(
  4383. IN HCERTSTORE hStore,
  4384. IN CERT_CONTEXT const *pCertSigner,
  4385. OUT DWORD *piElement)
  4386. {
  4387. HRESULT hr;
  4388. DWORD iElement;
  4389. CERT_CONTEXT const *pcc = NULL;
  4390. *piElement = -1;
  4391. for (iElement = 0; ; iElement++)
  4392. {
  4393. pcc = CertEnumCertificatesInStore(hStore, pcc);
  4394. if (NULL == pcc)
  4395. {
  4396. hr = CRYPT_E_NOT_FOUND;
  4397. _JumpError(hr, error, "CertEnumCertificatesInStore");
  4398. }
  4399. if (pCertSigner->cbCertEncoded == pcc->cbCertEncoded &&
  4400. 0 == memcmp(
  4401. pCertSigner->pbCertEncoded,
  4402. pcc->pbCertEncoded,
  4403. pcc->cbCertEncoded))
  4404. {
  4405. break;
  4406. }
  4407. }
  4408. *piElement = iElement;
  4409. hr = S_OK;
  4410. error:
  4411. if (NULL != pcc)
  4412. {
  4413. CertFreeCertificateContext(pcc);
  4414. }
  4415. return(hr);
  4416. }
  4417. HRESULT
  4418. cuDumpIssuerSerialAndSubject(
  4419. IN CERT_NAME_BLOB const *pIssuer,
  4420. IN CRYPT_INTEGER_BLOB const *pSerialNumber,
  4421. OPTIONAL IN CERT_NAME_BLOB const *pSubject,
  4422. OPTIONAL IN HCERTSTORE hStore)
  4423. {
  4424. HRESULT hr;
  4425. BOOL fVerbose = g_fVerbose;
  4426. CERT_ID CertId;
  4427. CERT_CONTEXT const *pcc = NULL;
  4428. BOOL fMultiLine = NULL == pSerialNumber || g_fVerbose;
  4429. if (g_fVerbose)
  4430. {
  4431. g_fVerbose--;
  4432. }
  4433. hr = cuDumpSerial(g_wszPad4, IDS_SERIAL, pSerialNumber);
  4434. _JumpIfError(hr, error, "cuDumpSerial");
  4435. hr = cuDisplayCertName(
  4436. fMultiLine,
  4437. g_wszPad4,
  4438. myLoadResourceString(IDS_ISSUER), // "Issuer"
  4439. g_wszPad8,
  4440. pIssuer,
  4441. NULL);
  4442. _JumpIfError(hr, error, "cuDisplayCertName(Issuer)");
  4443. ZeroMemory(&CertId, sizeof(CertId));
  4444. CertId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
  4445. CertId.IssuerSerialNumber.Issuer = *pIssuer;
  4446. if (NULL != pSerialNumber)
  4447. {
  4448. CertId.IssuerSerialNumber.SerialNumber = *pSerialNumber;
  4449. }
  4450. if (NULL == pSubject && NULL != hStore)
  4451. {
  4452. pcc = CertFindCertificateInStore(
  4453. hStore,
  4454. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  4455. 0, // dwFindFlags
  4456. CERT_FIND_CERT_ID,
  4457. &CertId,
  4458. NULL);
  4459. if (NULL == pcc)
  4460. {
  4461. hr = myHLastError();
  4462. _PrintError2(hr, "CertFindCertificateInStore", hr);
  4463. }
  4464. else
  4465. {
  4466. pSubject = &pcc->pCertInfo->Subject;
  4467. }
  4468. }
  4469. if (NULL != pSubject)
  4470. {
  4471. hr = cuDisplayCertName(
  4472. fMultiLine,
  4473. g_wszPad4,
  4474. myLoadResourceString(IDS_SUBJECT), // "Subject"
  4475. g_wszPad8,
  4476. pSubject,
  4477. NULL);
  4478. _JumpIfError(hr, error, "cuDisplayCertName(Issuer)");
  4479. }
  4480. hr = S_OK;
  4481. error:
  4482. g_fVerbose = fVerbose;
  4483. if (NULL != pcc)
  4484. {
  4485. CertFreeCertificateContext(pcc);
  4486. }
  4487. return(hr);
  4488. }
  4489. HRESULT
  4490. cuDumpSigners(
  4491. IN HCRYPTMSG hMsg,
  4492. IN CHAR const *pszInnerContentObjId,
  4493. IN HCERTSTORE hStore,
  4494. IN DWORD cSigner,
  4495. IN BOOL fContentEmpty,
  4496. IN BOOL fQuiet,
  4497. OPTIONAL OUT BYTE *pbHashUserCert,
  4498. OPTIONAL IN OUT DWORD *pcbHashUserCert)
  4499. {
  4500. HRESULT hr;
  4501. DWORD i;
  4502. CMSG_CMS_SIGNER_INFO *pcsi = NULL;
  4503. DWORD cb;
  4504. CERT_CONTEXT const *pcc = NULL;
  4505. BYTE abHash[CBMAX_CRYPT_HASH_LEN];
  4506. DWORD iElement;
  4507. DWORD VerifyState;
  4508. BOOL fVerbose = g_fVerbose;
  4509. CERT_REQUEST_INFO *pRequest = NULL;
  4510. if (!fQuiet)
  4511. {
  4512. if (0 == cSigner)
  4513. {
  4514. wprintf(myLoadResourceString(IDS_DUMP_PKCS7_NO_SIGNER));
  4515. wprintf(wszNewLine);
  4516. }
  4517. else
  4518. {
  4519. wprintf(
  4520. L"%ws: %d\n",
  4521. myLoadResourceString(IDS_DUMP_PKCS7_SIGNER_COUNT),
  4522. cSigner);
  4523. }
  4524. }
  4525. for (i = 0; i < cSigner; i++)
  4526. {
  4527. DWORD idVerify = 0;
  4528. if (NULL != pcsi)
  4529. {
  4530. LocalFree(pcsi);
  4531. pcsi = NULL;
  4532. }
  4533. hr = myCryptMsgGetParam(
  4534. hMsg,
  4535. CMSG_CMS_SIGNER_INFO_PARAM,
  4536. i,
  4537. CERTLIB_USE_LOCALALLOC,
  4538. (VOID **) &pcsi,
  4539. &cb);
  4540. _JumpIfError(hr, error, "myCryptMsgGetParam");
  4541. if (CERT_ID_KEY_IDENTIFIER == pcsi->SignerId.dwIdChoice ||
  4542. (NULL != pcsi->HashEncryptionAlgorithm.pszObjId &&
  4543. 0 == strcmp(
  4544. szOID_PKIX_NO_SIGNATURE,
  4545. pcsi->HashEncryptionAlgorithm.pszObjId)))
  4546. {
  4547. CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA cvse;
  4548. ZeroMemory(&cvse, sizeof(cvse));
  4549. cvse.cbSize = sizeof(cvse);
  4550. cvse.dwSignerIndex = i;
  4551. if (CERT_ID_KEY_IDENTIFIER == pcsi->SignerId.dwIdChoice)
  4552. {
  4553. if (NULL == pRequest)
  4554. {
  4555. hr = myGetInnerPKCS10(
  4556. hMsg,
  4557. pszInnerContentObjId,
  4558. &pRequest);
  4559. _JumpIfError(hr, error, "myGetInnerPKCS10");
  4560. }
  4561. cvse.dwSignerType = CMSG_VERIFY_SIGNER_PUBKEY;
  4562. cvse.pvSigner = &pRequest->SubjectPublicKeyInfo;
  4563. }
  4564. else
  4565. {
  4566. cvse.dwSignerType = CMSG_VERIFY_SIGNER_NULL;
  4567. }
  4568. if (!CryptMsgControl(
  4569. hMsg,
  4570. 0, // dwFlags
  4571. CMSG_CTRL_VERIFY_SIGNATURE_EX,
  4572. &cvse))
  4573. {
  4574. hr = myHLastError();
  4575. _PrintError(hr, "CryptMsgControl");
  4576. cuPrintError(0, hr);
  4577. }
  4578. else
  4579. {
  4580. idVerify = CERT_ID_KEY_IDENTIFIER == pcsi->SignerId.dwIdChoice?
  4581. IDS_REQUEST_SIGNATUREMATCHES : // "Signature matches request Public Key"
  4582. IDS_NULL_SIGNATUREMATCHES; // "NULL signature verifies"
  4583. }
  4584. }
  4585. else
  4586. {
  4587. DWORD dwFlags;
  4588. dwFlags = CMSG_USE_SIGNER_INDEX_FLAG;
  4589. while (TRUE)
  4590. {
  4591. iElement = i;
  4592. if (CryptMsgGetAndVerifySigner(
  4593. hMsg,
  4594. 0, // cSignerStore
  4595. NULL, // rghSignerStore
  4596. dwFlags,
  4597. &pcc,
  4598. &iElement))
  4599. {
  4600. hr = S_OK;
  4601. break;
  4602. }
  4603. hr = myHLastError();
  4604. _PrintError(hr, "CryptMsgGetAndVerifySigner");
  4605. if (CMSG_SIGNER_ONLY_FLAG & dwFlags)
  4606. {
  4607. cuPrintError(0, hr);
  4608. break;
  4609. }
  4610. cuPrintError(
  4611. (fContentEmpty && NTE_BAD_SIGNATURE == hr)?
  4612. IDS_DETACHED_SIGNATURE : // "Cannot verify detached signature"
  4613. 0,
  4614. hr);
  4615. dwFlags |= CMSG_SIGNER_ONLY_FLAG;
  4616. }
  4617. if (S_OK == hr)
  4618. {
  4619. idVerify = IDS_SIGNATUREMATCHES; // "Signature matches Public Key"
  4620. hr = FindCertStoreIndex(hStore, pcc, &iElement);
  4621. _JumpIfError(hr, error, "FindCertStoreIndex");
  4622. if (!fQuiet)
  4623. {
  4624. wprintf(
  4625. L"%ws: %u\n",
  4626. myLoadResourceString(IDS_DUMP_PKCS7_SIGNCERT), // "Signing Certificate Index"
  4627. iElement);
  4628. }
  4629. hr = cuVerifyCertContext(
  4630. pcc,
  4631. hStore,
  4632. 0, // cApplicationPolicies
  4633. NULL, // apszApplicationPolicies
  4634. 0, // cIssuancePolicies
  4635. NULL, // apszIssuancePolicies
  4636. FALSE, // fNTAuth
  4637. &VerifyState);
  4638. _PrintIfError(hr, "cuVerifyCertContext");
  4639. CertFreeCertificateContext(pcc);
  4640. pcc = NULL;
  4641. }
  4642. }
  4643. hr = cuDumpCMSSignerInfo(
  4644. pcsi,
  4645. i,
  4646. fQuiet,
  4647. idVerify,
  4648. hStore,
  4649. pbHashUserCert,
  4650. pcbHashUserCert);
  4651. _PrintIfError(hr, "cuDumpCMSSignerInfo");
  4652. cb = sizeof(abHash);
  4653. if (!CryptMsgGetParam(
  4654. hMsg,
  4655. CMSG_COMPUTED_HASH_PARAM,
  4656. 0,
  4657. abHash,
  4658. &cb))
  4659. {
  4660. hr = myHLastError();
  4661. _PrintError(hr, "CryptMsgGetParam(computed hash)");
  4662. }
  4663. else
  4664. {
  4665. wprintf(wszNewLine);
  4666. hr = DumpHash(
  4667. NULL,
  4668. IDS_FORMAT_COMPUTED_HASH_COLON, // "Computed Hash%ws: %ws"
  4669. NULL,
  4670. g_wszEmpty,
  4671. abHash,
  4672. cb);
  4673. _JumpIfError(hr, error, "DumpHash");
  4674. }
  4675. }
  4676. hr = S_OK;
  4677. error:
  4678. if (NULL != pRequest)
  4679. {
  4680. LocalFree(pRequest);
  4681. }
  4682. if (NULL != pcsi)
  4683. {
  4684. LocalFree(pcsi);
  4685. }
  4686. if (NULL != pcc)
  4687. {
  4688. CertFreeCertificateContext(pcc);
  4689. }
  4690. return(hr);
  4691. }
  4692. HRESULT
  4693. cuDumpRecipientCertHash(
  4694. IN CERT_INFO const *pci,
  4695. IN HCERTSTORE hStore)
  4696. {
  4697. HRESULT hr;
  4698. CERT_CONTEXT const *pcc = NULL;
  4699. CERT_ID CertId;
  4700. CSASSERT(NULL != hStore);
  4701. CertId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
  4702. CertId.IssuerSerialNumber.Issuer = pci->Issuer;
  4703. CertId.IssuerSerialNumber.SerialNumber = pci->SerialNumber;
  4704. pcc = CertFindCertificateInStore(
  4705. hStore,
  4706. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  4707. 0, // dwFindFlags
  4708. CERT_FIND_CERT_ID,
  4709. &CertId,
  4710. NULL);
  4711. if (NULL == pcc)
  4712. {
  4713. hr = myHLastError();
  4714. _JumpError(hr, error, "CertFindCertificateInStore");
  4715. }
  4716. hr = cuDisplayHash(g_wszPad4, pcc, NULL, CERT_SHA1_HASH_PROP_ID, L"sha1");
  4717. _JumpIfError(hr, error, "cuDisplayHash");
  4718. error:
  4719. if (NULL != pcc)
  4720. {
  4721. CertFreeCertificateContext(pcc);
  4722. }
  4723. return(hr);
  4724. }
  4725. HRESULT
  4726. cuDumpRecipients(
  4727. IN HCRYPTMSG hMsg,
  4728. OPTIONAL IN HCERTSTORE hStoreWrapper,
  4729. IN DWORD cRecipient,
  4730. IN BOOL fQuiet)
  4731. {
  4732. HRESULT hr;
  4733. DWORD i;
  4734. CERT_INFO *pci = NULL;
  4735. DWORD cb;
  4736. if (!fQuiet)
  4737. {
  4738. if (0 == cRecipient)
  4739. {
  4740. wprintf(myLoadResourceString(IDS_DUMP_PKCS7_NO_RECIPIENT));
  4741. wprintf(wszNewLine);
  4742. }
  4743. else
  4744. {
  4745. wprintf(
  4746. L"%ws: %d\n",
  4747. myLoadResourceString(IDS_DUMP_PKCS7_RECIPIENT_COUNT),
  4748. cRecipient);
  4749. }
  4750. }
  4751. for (i = 0; i < cRecipient; i++)
  4752. {
  4753. if (NULL != pci)
  4754. {
  4755. LocalFree(pci);
  4756. pci = NULL;
  4757. }
  4758. hr = myCryptMsgGetParam(
  4759. hMsg,
  4760. CMSG_RECIPIENT_INFO_PARAM,
  4761. i,
  4762. CERTLIB_USE_LOCALALLOC,
  4763. (VOID **) &pci,
  4764. &cb);
  4765. _JumpIfError(hr, error, "myCryptMsgGetParam");
  4766. wprintf(wszNewLine);
  4767. wprintf(
  4768. L"%ws[%u]:\n",
  4769. myLoadResourceString(IDS_RECIPIENT_INFO), // "Recipient Info"
  4770. i);
  4771. hr = cuDumpIssuerSerialAndSubject(
  4772. &pci->Issuer,
  4773. &pci->SerialNumber,
  4774. NULL, // pSubject
  4775. hStoreWrapper);
  4776. _JumpIfError(hr, error, "cuDumpIssuerSerialAndSubject(Recipient)");
  4777. if (NULL != hStoreWrapper)
  4778. {
  4779. hr = cuDumpRecipientCertHash(pci, hStoreWrapper);
  4780. _PrintIfError(hr, "cuDumpRecipientCertHash");
  4781. }
  4782. }
  4783. hr = S_OK;
  4784. error:
  4785. if (NULL != pci)
  4786. {
  4787. LocalFree(pci);
  4788. }
  4789. return(hr);
  4790. }
  4791. HRESULT
  4792. OpenCAXchgMemoryStore(
  4793. OUT HCERTSTORE *phStore)
  4794. {
  4795. HRESULT hr;
  4796. WCHAR const *pwszConfig = g_pwszConfig;
  4797. BSTR strConfig = NULL;
  4798. DISPATCHINTERFACE diRequest;
  4799. BSTR strCert = NULL;
  4800. HCERTSTORE hStore = NULL;
  4801. if (NULL == pwszConfig)
  4802. {
  4803. hr = ConfigGetConfig(g_DispatchFlags, CC_LOCALACTIVECONFIG, &strConfig);
  4804. _JumpIfError(hr, error, "ConfigGetConfig");
  4805. pwszConfig = strConfig;
  4806. }
  4807. hr = Request_Init(g_DispatchFlags, &diRequest);
  4808. _JumpIfError(hr, error, "Request_Init");
  4809. hr = Request2_GetCAProperty(
  4810. &diRequest,
  4811. pwszConfig,
  4812. CR_PROP_CAXCHGCERT,
  4813. MAXDWORD, // PropIndex
  4814. PROPTYPE_BINARY,
  4815. CR_OUT_BINARY,
  4816. &strCert);
  4817. _JumpIfError(hr, error, "Request2_GetCAProperty");
  4818. hStore = CertOpenStore(
  4819. CERT_STORE_PROV_MEMORY,
  4820. X509_ASN_ENCODING,
  4821. NULL,
  4822. 0,
  4823. NULL);
  4824. if (NULL == hStore)
  4825. {
  4826. hr = myHLastError();
  4827. _JumpError(hr, error, "CertOpenStore");
  4828. }
  4829. // Add as encoded blob to avoid all properties, key prov info, etc.
  4830. if (!CertAddEncodedCertificateToStore(
  4831. hStore,
  4832. X509_ASN_ENCODING,
  4833. (BYTE *) strCert,
  4834. SysStringByteLen(strCert),
  4835. CERT_STORE_ADD_REPLACE_EXISTING,
  4836. NULL)) // ppCertContext
  4837. {
  4838. hr = myHLastError();
  4839. _JumpError(hr, error, "CertAddEncodedCertificateToStore");
  4840. }
  4841. *phStore = hStore;
  4842. hStore = NULL;
  4843. hr = S_OK;
  4844. error:
  4845. if (NULL != hStore)
  4846. {
  4847. CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
  4848. }
  4849. if (NULL != strCert)
  4850. {
  4851. SysFreeString(strCert);
  4852. }
  4853. Request_Release(&diRequest);
  4854. if (NULL != strConfig)
  4855. {
  4856. SysFreeString(strConfig);
  4857. }
  4858. return(hr);
  4859. }
  4860. HRESULT
  4861. OpenNamedStore(
  4862. IN BOOL fUserStore,
  4863. IN WCHAR const *pwszStoreName,
  4864. OUT HCERTSTORE *phStore)
  4865. {
  4866. HRESULT hr;
  4867. *phStore = CertOpenStore(
  4868. CERT_STORE_PROV_SYSTEM_W,
  4869. X509_ASN_ENCODING,
  4870. NULL, // hProv
  4871. CERT_STORE_OPEN_EXISTING_FLAG |
  4872. CERT_STORE_READONLY_FLAG |
  4873. CERT_STORE_ENUM_ARCHIVED_FLAG |
  4874. (fUserStore?
  4875. CERT_SYSTEM_STORE_CURRENT_USER :
  4876. CERT_SYSTEM_STORE_LOCAL_MACHINE),
  4877. pwszStoreName);
  4878. if (NULL == *phStore)
  4879. {
  4880. hr = myHLastError();
  4881. _JumpErrorStr2(
  4882. hr,
  4883. error,
  4884. "CertOpenStore",
  4885. pwszStoreName,
  4886. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  4887. }
  4888. hr = S_OK;
  4889. error:
  4890. return(hr);
  4891. }
  4892. HRESULT
  4893. cuCryptDecryptMessageFromCert(
  4894. IN CERT_CONTEXT const *pcc,
  4895. IN BYTE const *pbIn,
  4896. IN DWORD cbIn,
  4897. OUT DWORD *pdwKeySpecFound,
  4898. OUT BYTE **ppbDecrypted,
  4899. OUT DWORD *pcbDecrypted)
  4900. {
  4901. HRESULT hr;
  4902. HCERTSTORE hStore = NULL;
  4903. CERT_CONTEXT const *pccStore = NULL;
  4904. CERT_KEY_CONTEXT ckc;
  4905. HCRYPTPROV hProv = NULL;
  4906. DWORD dwKeySpec;
  4907. CRYPT_KEY_PROV_INFO *pkpi = NULL;
  4908. DWORD dwTickCount = GetTickCount();
  4909. *pdwKeySpecFound = 0;
  4910. hStore = CertOpenStore(
  4911. CERT_STORE_PROV_MEMORY,
  4912. X509_ASN_ENCODING,
  4913. NULL,
  4914. 0,
  4915. NULL);
  4916. if (NULL == hStore)
  4917. {
  4918. hr = myHLastError();
  4919. _JumpError(hr, error, "CertOpenStore");
  4920. }
  4921. // Add as encoded blob to avoid all properties, key prov info, etc.
  4922. if (!CertAddEncodedCertificateToStore(
  4923. hStore,
  4924. X509_ASN_ENCODING,
  4925. pcc->pbCertEncoded,
  4926. pcc->cbCertEncoded,
  4927. CERT_STORE_ADD_REPLACE_EXISTING,
  4928. &pccStore)) // ppCertContext
  4929. {
  4930. hr = myHLastError();
  4931. _JumpError(hr, error, "CertAddEncodedCertificateToStore");
  4932. }
  4933. hr = myCertGetKeyProviderInfo(pcc, &pkpi);
  4934. _PrintIfError2(hr, "myCertGetKeyProviderInfo", CRYPT_E_NOT_FOUND);
  4935. if (S_OK == hr)
  4936. {
  4937. DBGPRINT((
  4938. s_DbgSsRecoveryTrace,
  4939. "Original KeyProvInfo: container=%ws, type=%x, prov=%ws, KeySpec=%x, f=%x\n",
  4940. pkpi->pwszContainerName,
  4941. pkpi->dwProvType,
  4942. pkpi->pwszProvName,
  4943. pkpi->dwKeySpec,
  4944. pkpi->dwFlags));
  4945. }
  4946. else if (!g_fForce)
  4947. {
  4948. _JumpError2(hr, error, "myCertGetKeyProviderInfo", CRYPT_E_NOT_FOUND);
  4949. }
  4950. DBGPRINT((
  4951. s_DbgSsRecoveryTrace,
  4952. "Before CryptAcquireCertificatePrivateKey: Ticks=%u\n",
  4953. GetTickCount() - dwTickCount));
  4954. if (!CryptAcquireCertificatePrivateKey(
  4955. pcc,
  4956. 0, // dwFlags
  4957. NULL, // pvReserved
  4958. &hProv,
  4959. &dwKeySpec,
  4960. NULL)) // pfCallerFreeProv
  4961. {
  4962. hr = myHLastError();
  4963. _PrintError2(
  4964. hr,
  4965. "CryptAcquireCertificatePrivateKey",
  4966. CRYPT_E_NO_KEY_PROPERTY);
  4967. DBGPRINT((
  4968. s_DbgSsRecoveryTrace,
  4969. "Before CryptFindCertificateKeyProvInfo: Ticks=%u\n",
  4970. GetTickCount() - dwTickCount));
  4971. if (!CryptFindCertificateKeyProvInfo(pcc, 0, NULL))
  4972. {
  4973. hr = myHLastError();
  4974. _JumpError2(
  4975. hr,
  4976. error,
  4977. "CryptFindCertificateKeyProvInfo",
  4978. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  4979. }
  4980. if (NULL != pkpi)
  4981. {
  4982. LocalFree(pkpi);
  4983. pkpi = NULL;
  4984. }
  4985. hr = myCertGetKeyProviderInfo(pcc, &pkpi);
  4986. _JumpIfError(hr, error, "myCertGetKeyProviderInfo");
  4987. DBGPRINT((
  4988. s_DbgSsRecoveryTrace,
  4989. "Constructed KeyProvInfo: container=%ws, type=%x, prov=%ws, KeySpec=%x, f=%x\n",
  4990. pkpi->pwszContainerName,
  4991. pkpi->dwProvType,
  4992. pkpi->pwszProvName,
  4993. pkpi->dwKeySpec,
  4994. pkpi->dwFlags));
  4995. dwKeySpec = pkpi->dwKeySpec;
  4996. DBGPRINT((
  4997. s_DbgSsRecoveryTrace,
  4998. "Before CryptAcquireContext: Ticks=%u\n",
  4999. GetTickCount() - dwTickCount));
  5000. if (!CryptAcquireContext(
  5001. &hProv,
  5002. pkpi->pwszContainerName,
  5003. pkpi->pwszProvName,
  5004. pkpi->dwProvType,
  5005. pkpi->dwFlags))
  5006. {
  5007. hr = myHLastError();
  5008. _JumpErrorStr(
  5009. hr,
  5010. error,
  5011. "CryptAcquireContext",
  5012. pkpi->pwszContainerName);
  5013. }
  5014. }
  5015. ZeroMemory(&ckc, sizeof(ckc));
  5016. ckc.cbSize = sizeof(ckc);
  5017. ckc.dwKeySpec = dwKeySpec;
  5018. ckc.hCryptProv = hProv;
  5019. *pdwKeySpecFound = dwKeySpec;
  5020. DBGPRINT((
  5021. s_DbgSsRecoveryTrace,
  5022. "Before CertSetCertificateContextProperty: Ticks=%u\n",
  5023. GetTickCount() - dwTickCount));
  5024. if (!CertSetCertificateContextProperty(
  5025. pccStore,
  5026. CERT_KEY_CONTEXT_PROP_ID,
  5027. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  5028. &ckc))
  5029. {
  5030. hr = myHLastError();
  5031. _JumpError(hr, error, "CertSetCertificateContextProperty");
  5032. }
  5033. DBGPRINT((
  5034. s_DbgSsRecoveryTrace,
  5035. "Before myCryptDecryptMessage: Ticks=%u\n",
  5036. GetTickCount() - dwTickCount));
  5037. hr = myCryptDecryptMessage(
  5038. hStore,
  5039. pbIn,
  5040. cbIn,
  5041. CERTLIB_USE_LOCALALLOC,
  5042. ppbDecrypted,
  5043. pcbDecrypted);
  5044. _JumpIfError(hr, error, "myCryptDecryptMessage");
  5045. DBGPRINT((
  5046. s_DbgSsRecoveryTrace,
  5047. "After myCryptDecryptMessage: Ticks=%u\n",
  5048. GetTickCount() - dwTickCount));
  5049. error:
  5050. if (S_OK != hr)
  5051. {
  5052. DBGPRINT((
  5053. s_DbgSsRecoveryTrace,
  5054. "Skipped myCryptDecryptMessage(%x): Ticks=%u\n",
  5055. hr,
  5056. GetTickCount() - dwTickCount));
  5057. }
  5058. if (NULL != pkpi)
  5059. {
  5060. LocalFree(pkpi);
  5061. }
  5062. if (NULL != pccStore)
  5063. {
  5064. CertFreeCertificateContext(pccStore);
  5065. }
  5066. if (NULL != hStore)
  5067. {
  5068. CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
  5069. }
  5070. if (NULL != hProv)
  5071. {
  5072. CryptReleaseContext(hProv, 0);
  5073. }
  5074. return(hr);
  5075. }
  5076. // Attempt to find any one recipient cert with a usable private key in the
  5077. // following locations:
  5078. // - the next outer PKCS7 store (hStoreWrapper parameter)
  5079. // - the PKCS7 store (hStorePKCS7 parameter)
  5080. // - the local machine's current CA Exchange cert
  5081. // - the HKLM KRA store
  5082. // - the HKLM MY store
  5083. // - the HKCU MY store
  5084. HRESULT
  5085. cuDumpEncryptedAsnBinary(
  5086. IN HCRYPTMSG hMsg,
  5087. IN DWORD cRecipient,
  5088. IN DWORD RecipientIndex,
  5089. OPTIONAL IN HCERTSTORE hStoreWrapper,
  5090. IN HCERTSTORE hStorePKCS7,
  5091. IN BYTE const *pbIn,
  5092. IN DWORD cbIn,
  5093. IN BOOL fQuiet,
  5094. OPTIONAL OUT BYTE **ppbDecrypted,
  5095. OPTIONAL OUT DWORD *pcbDecrypted)
  5096. {
  5097. HRESULT hr;
  5098. HCERTSTORE ahStore[6];
  5099. WCHAR *apwszStore[6];
  5100. DWORD cStore = 0;
  5101. DWORD iRecipient;
  5102. DWORD iStore;
  5103. DWORD cb;
  5104. CERT_INFO *pci = NULL;
  5105. CERT_CONTEXT const *pcc = NULL;
  5106. BOOL fDecrypted = FALSE;
  5107. BYTE *pbDecrypted = NULL;
  5108. DWORD cbDecrypted;
  5109. DWORD dwKeySpecFound;
  5110. BOOL fSignatureKey = FALSE;
  5111. BOOL fExchangeKey = FALSE;
  5112. DWORD dwTickCount = GetTickCount();
  5113. if (NULL != ppbDecrypted)
  5114. {
  5115. *ppbDecrypted = NULL;
  5116. }
  5117. if (NULL != pcbDecrypted)
  5118. {
  5119. *pcbDecrypted = 0;
  5120. }
  5121. s_DbgSsRecoveryTrace = g_fVerbose? DBG_SS_CERTUTIL : DBG_SS_CERTUTILI;
  5122. hr = OpenNamedStore(TRUE, wszMY_CERTSTORE, &ahStore[cStore]);
  5123. if (S_OK == hr)
  5124. {
  5125. apwszStore[cStore] = L"HKCU MY";
  5126. cStore++;
  5127. }
  5128. hr = OpenNamedStore(FALSE, wszMY_CERTSTORE, &ahStore[cStore]);
  5129. if (S_OK == hr)
  5130. {
  5131. apwszStore[cStore] = L"HKLM MY";
  5132. cStore++;
  5133. }
  5134. if (NULL != hStoreWrapper)
  5135. {
  5136. apwszStore[cStore] = L"PKCS7 Wrapper";
  5137. ahStore[cStore++] = hStoreWrapper;
  5138. }
  5139. if (NULL != hStorePKCS7)
  5140. {
  5141. apwszStore[cStore] = L"PKCS7";
  5142. ahStore[cStore++] = hStorePKCS7;
  5143. }
  5144. hr = OpenCAXchgMemoryStore(&ahStore[cStore]);
  5145. if (S_OK == hr)
  5146. {
  5147. apwszStore[cStore] = L"CAXchgMemory";
  5148. cStore++;
  5149. }
  5150. hr = OpenNamedStore(FALSE, wszKRA_CERTSTORE, &ahStore[cStore]);
  5151. if (S_OK == hr)
  5152. {
  5153. apwszStore[cStore] = L"HKLM KRA";
  5154. cStore++;
  5155. }
  5156. for (iRecipient = 0; !fDecrypted && iRecipient < cRecipient; iRecipient++)
  5157. {
  5158. CERT_ID CertId;
  5159. if (MAXDWORD != RecipientIndex && iRecipient != RecipientIndex)
  5160. {
  5161. continue;
  5162. }
  5163. if (NULL != pci)
  5164. {
  5165. LocalFree(pci);
  5166. pci = NULL;
  5167. }
  5168. hr = myCryptMsgGetParam(
  5169. hMsg,
  5170. CMSG_RECIPIENT_INFO_PARAM,
  5171. iRecipient,
  5172. CERTLIB_USE_LOCALALLOC,
  5173. (VOID **) &pci,
  5174. &cb);
  5175. _JumpIfError(hr, error, "myCryptMsgGetParam");
  5176. CertId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
  5177. CertId.IssuerSerialNumber.Issuer = pci->Issuer;
  5178. CertId.IssuerSerialNumber.SerialNumber = pci->SerialNumber;
  5179. for (iStore = 0; !fDecrypted && iStore < cStore; iStore++)
  5180. {
  5181. if (NULL != pcc)
  5182. {
  5183. CertFreeCertificateContext(pcc);
  5184. pcc = NULL;
  5185. }
  5186. while (TRUE)
  5187. {
  5188. pcc = CertFindCertificateInStore(
  5189. ahStore[iStore],
  5190. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  5191. 0, // dwFindFlags
  5192. CERT_FIND_CERT_ID,
  5193. &CertId,
  5194. pcc);
  5195. if (NULL == pcc)
  5196. {
  5197. hr = myHLastError();
  5198. _PrintError2(hr, "CertFindCertificateInStore", hr);
  5199. break;
  5200. }
  5201. {
  5202. WCHAR *pwsz;
  5203. pwsz = NULL;
  5204. hr = myCertNameToStr(
  5205. X509_ASN_ENCODING,
  5206. &pcc->pCertInfo->Subject,
  5207. CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
  5208. &pwsz);
  5209. _PrintIfError(hr, "myCertNameToStr");
  5210. DBGPRINT((
  5211. s_DbgSsRecoveryTrace,
  5212. "================================================\n"));
  5213. DBGPRINT((
  5214. s_DbgSsRecoveryTrace,
  5215. "Found Recipient[%u] in %ws -- ahStore[%u of %u]: %ws\n",
  5216. iRecipient,
  5217. apwszStore[iStore],
  5218. iStore,
  5219. cStore,
  5220. pwsz));
  5221. if (NULL != pwsz)
  5222. {
  5223. LocalFree(pwsz);
  5224. }
  5225. }
  5226. if (g_fVerbose)
  5227. {
  5228. wprintf(wszNewLine);
  5229. wprintf(
  5230. L"%ws[%u]:\n",
  5231. myLoadResourceString(IDS_RECIPIENT_INFO), // "Recipient Info"
  5232. iRecipient);
  5233. hr = cuDumpIssuerSerialAndSubject(
  5234. &pci->Issuer,
  5235. &pci->SerialNumber,
  5236. &pcc->pCertInfo->Subject,
  5237. NULL); // hStore
  5238. _JumpIfError(hr, error, "cuDumpIssuerSerialAndSubject(Recipient)");
  5239. }
  5240. hr = cuCryptDecryptMessageFromCert(
  5241. pcc,
  5242. pbIn,
  5243. cbIn,
  5244. &dwKeySpecFound,
  5245. &pbDecrypted,
  5246. &cbDecrypted);
  5247. _PrintIfError2(
  5248. hr,
  5249. "cuCryptDecryptMessageFromCert",
  5250. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  5251. {
  5252. DBGPRINT((
  5253. s_DbgSsRecoveryTrace,
  5254. "cuCryptDecryptMessageFromCert(Recipient[%u]): %x\n",
  5255. iRecipient,
  5256. hr));
  5257. }
  5258. if (AT_SIGNATURE == dwKeySpecFound)
  5259. {
  5260. fSignatureKey = TRUE;
  5261. }
  5262. else if (AT_KEYEXCHANGE == dwKeySpecFound)
  5263. {
  5264. fExchangeKey = TRUE;
  5265. }
  5266. if (S_OK != hr)
  5267. {
  5268. DBGPRINT((
  5269. s_DbgSsRecoveryTrace,
  5270. "cuDumpEncryptedAsnBinary failed(%x): Ticks=%u\n",
  5271. hr,
  5272. GetTickCount() - dwTickCount));
  5273. continue;
  5274. }
  5275. wprintf(myLoadResourceString(IDS_DUMP_DECRYPTED)); // "Decrypted PKCS7 Content"
  5276. wprintf(wszNewLine);
  5277. hr = DumpAsnBlob(
  5278. NULL,
  5279. fQuiet,
  5280. pbDecrypted,
  5281. cbDecrypted,
  5282. MAXDWORD);
  5283. _PrintIfError(hr, "DumpAsnBlob(decrypted content)");
  5284. if (S_OK == hr)
  5285. {
  5286. fDecrypted = TRUE;
  5287. if (NULL != ppbDecrypted)
  5288. {
  5289. *ppbDecrypted = pbDecrypted;
  5290. pbDecrypted = NULL;
  5291. }
  5292. if (NULL != pcbDecrypted)
  5293. {
  5294. *pcbDecrypted = cbDecrypted;
  5295. }
  5296. }
  5297. break;
  5298. }
  5299. }
  5300. }
  5301. DBGPRINT((
  5302. s_DbgSsRecoveryTrace,
  5303. "cuDumpEncryptedAsnBinary end(fDecrypted=%d): Ticks=%u\n",
  5304. fDecrypted,
  5305. GetTickCount() - dwTickCount));
  5306. if (!fDecrypted)
  5307. {
  5308. if (fSignatureKey && !fExchangeKey)
  5309. {
  5310. wprintf(myLoadResourceString(IDS_SIGNATURE_NOTKEYEXCHANGE)); // "Found AT_SIGNATURE key but no AT_KEYEXCHANGE key"
  5311. wprintf(wszNewLine);
  5312. }
  5313. hr = CRYPT_E_NO_DECRYPT_CERT;
  5314. _JumpError(hr, error, "No decryption key");
  5315. }
  5316. hr = S_OK;
  5317. error:
  5318. if (NULL != pbDecrypted)
  5319. {
  5320. LocalFree(pbDecrypted);
  5321. }
  5322. if (NULL != pci)
  5323. {
  5324. LocalFree(pci);
  5325. }
  5326. if (NULL != pcc)
  5327. {
  5328. CertFreeCertificateContext(pcc);
  5329. }
  5330. for (iStore = 0; iStore < cStore; iStore++)
  5331. {
  5332. if (NULL != ahStore[iStore] &&
  5333. hStoreWrapper != ahStore[iStore] &&
  5334. hStorePKCS7 != ahStore[iStore])
  5335. {
  5336. CertCloseStore(ahStore[iStore], CERT_CLOSE_STORE_CHECK_FLAG);
  5337. }
  5338. }
  5339. return(hr);
  5340. }
  5341. HRESULT
  5342. dumpPKCS7(
  5343. OPTIONAL IN HCERTSTORE hStoreWrapper,
  5344. IN BYTE const *pbIn,
  5345. IN DWORD cbIn)
  5346. {
  5347. HRESULT hr;
  5348. BYTE *pbContents = NULL;
  5349. DWORD cbContents;
  5350. HCERTSTORE hStore = NULL;
  5351. CERT_CONTEXT const *pCert = NULL;
  5352. CRL_CONTEXT const *pCRL = NULL;
  5353. HCRYPTMSG hMsg = NULL;
  5354. CRYPT_ATTRIBUTES *pAttrib = NULL;
  5355. BOOL fDisplayed;
  5356. DWORD iElement;
  5357. DWORD cSigner;
  5358. DWORD cRecipient;
  5359. DWORD cb;
  5360. DWORD dwMsgType;
  5361. DWORD dwMsgVersion;
  5362. char *pszInnerContentObjId = NULL;
  5363. WCHAR const *pwsz;
  5364. WCHAR const *pwszVersion;
  5365. UINT idsType = IDS_DUMP_PKCS7;
  5366. hr = myDecodePKCS7(
  5367. pbIn,
  5368. cbIn,
  5369. &pbContents,
  5370. &cbContents,
  5371. &dwMsgType,
  5372. &pszInnerContentObjId,
  5373. &cSigner,
  5374. &cRecipient,
  5375. &hStore,
  5376. &hMsg);
  5377. _JumpIfError2(hr, error, "myDecodePKCS7", CRYPT_E_ASN1_BADTAG);
  5378. cb = sizeof(dwMsgVersion);
  5379. if (!CryptMsgGetParam(
  5380. hMsg,
  5381. CMSG_VERSION_PARAM,
  5382. 0,
  5383. &dwMsgVersion,
  5384. &cb))
  5385. {
  5386. hr = myHLastError();
  5387. _PrintError(hr, "CryptMsgGetParam(version)");
  5388. dwMsgVersion = MAXDWORD;
  5389. }
  5390. pwszVersion = NULL;
  5391. switch (dwMsgType)
  5392. {
  5393. case CMSG_DATA:
  5394. pwsz = L"CMSG_DATA";
  5395. break;
  5396. case CMSG_ENVELOPED:
  5397. pwsz = L"CMSG_ENVELOPED";
  5398. switch (dwMsgVersion)
  5399. {
  5400. case CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION:
  5401. pwszVersion = L"CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION";
  5402. break;
  5403. case CMSG_ENVELOPED_DATA_CMS_VERSION:
  5404. pwszVersion = L"CMSG_ENVELOPED_DATA_CMS_VERSION";
  5405. idsType = IDS_DUMP_PKCS7CMS;
  5406. break;
  5407. }
  5408. break;
  5409. case CMSG_HASHED:
  5410. pwsz = L"CMSG_HASHED";
  5411. switch (dwMsgVersion)
  5412. {
  5413. case CMSG_HASHED_DATA_PKCS_1_5_VERSION:
  5414. pwszVersion = L"CMSG_HASHED_DATA_PKCS_1_5_VERSION";
  5415. break;
  5416. case CMSG_HASHED_DATA_CMS_VERSION:
  5417. pwszVersion = L"CMSG_HASHED_DATA_CMS_VERSION";
  5418. idsType = IDS_DUMP_PKCS7CMS;
  5419. break;
  5420. }
  5421. break;
  5422. case CMSG_SIGNED:
  5423. pwsz = L"CMSG_SIGNED";
  5424. switch (dwMsgVersion)
  5425. {
  5426. case CMSG_SIGNED_DATA_PKCS_1_5_VERSION:
  5427. pwszVersion = L"CMSG_SIGNED_DATA_PKCS_1_5_VERSION";
  5428. break;
  5429. case CMSG_SIGNED_DATA_CMS_VERSION:
  5430. pwszVersion = L"CMSG_SIGNED_DATA_CMS_VERSION";
  5431. idsType = IDS_DUMP_PKCS7CMS;
  5432. break;
  5433. }
  5434. break;
  5435. case CMSG_SIGNED_AND_ENVELOPED:
  5436. pwsz = L"CMSG_SIGNED_AND_ENVELOPED";
  5437. break;
  5438. default:
  5439. pwsz = myLoadResourceString(IDS_QUESTIONMARKS); // "???"
  5440. break;
  5441. }
  5442. wprintf(myLoadResourceString(idsType));
  5443. wprintf(wszNewLine);
  5444. wprintf(L" %ws(%u)\n", pwsz, dwMsgType);
  5445. if (NULL != pwszVersion)
  5446. {
  5447. wprintf(L" %ws(%u)\n", pwszVersion, dwMsgVersion);
  5448. }
  5449. if (NULL != pszInnerContentObjId)
  5450. {
  5451. wprintf(
  5452. L" %ws: ",
  5453. myLoadResourceString(IDS_DUMP_PKCS7_CONTENT_TYPE));
  5454. cuDumpOIDAndDescriptionA(pszInnerContentObjId);
  5455. wprintf(wszNewLine);
  5456. }
  5457. wprintf(wszNewLine);
  5458. if (NULL == pbContents)
  5459. {
  5460. wprintf(myLoadResourceString(IDS_DUMP_PKCS7_NO_CONTENT));
  5461. wprintf(wszNewLine);
  5462. }
  5463. else
  5464. {
  5465. wprintf(myLoadResourceString(IDS_DUMP_PKCS7_CONTENTS)); // "PKCS7 Message Content:"
  5466. wprintf(wszNewLine);
  5467. fDisplayed = FALSE;
  5468. if (CMSG_ENVELOPED != dwMsgType)
  5469. {
  5470. hr = DumpAsnBlob(hStore, FALSE, pbContents, cbContents, MAXDWORD);
  5471. _PrintIfError(hr, "DumpAsnBlob(content)");
  5472. fDisplayed = TRUE;
  5473. }
  5474. else if (NULL != hMsg && 0 != cRecipient)
  5475. {
  5476. hr = cuDumpEncryptedAsnBinary(
  5477. hMsg,
  5478. cRecipient,
  5479. MAXDWORD, // RecipientIndex
  5480. hStoreWrapper,
  5481. hStore,
  5482. pbIn,
  5483. cbIn,
  5484. FALSE,
  5485. NULL,
  5486. NULL);
  5487. _PrintIfError(hr, "cuDumpEncryptedAsnBinary");
  5488. if (S_OK == hr)
  5489. {
  5490. fDisplayed = TRUE;
  5491. }
  5492. }
  5493. if (!fDisplayed)
  5494. {
  5495. DumpHex(0, pbContents, cbContents);
  5496. }
  5497. }
  5498. wprintf(wszNewLine);
  5499. if (NULL != hMsg)
  5500. {
  5501. BYTE abHash[CBMAX_CRYPT_HASH_LEN];
  5502. hr = cuDumpSigners(
  5503. hMsg,
  5504. pszInnerContentObjId,
  5505. hStore,
  5506. cSigner,
  5507. NULL == pbContents, // fContentEmpty
  5508. FALSE, // fVerifyOnly
  5509. NULL, // pbHashUserCert
  5510. NULL); // pcbHashUserCert
  5511. _JumpIfError(hr, error, "cuDumpSigners");
  5512. hr = cuDumpRecipients(hMsg, hStoreWrapper, cRecipient, FALSE);
  5513. _JumpIfError(hr, error, "cuDumpRecipients");
  5514. cb = sizeof(abHash);
  5515. if (!CryptMsgGetParam(
  5516. hMsg,
  5517. CMSG_HASH_DATA_PARAM,
  5518. 0,
  5519. abHash,
  5520. &cb))
  5521. {
  5522. hr = myHLastError();
  5523. _PrintError2(hr, "CryptMsgGetParam(stored hash)", CRYPT_E_INVALID_MSG_TYPE);
  5524. }
  5525. else
  5526. {
  5527. hr = DumpHash(
  5528. NULL,
  5529. IDS_FORMAT_STORED_HASH_COLON, // "Stored Hash%ws: %ws"
  5530. NULL,
  5531. g_wszEmpty,
  5532. abHash,
  5533. cb);
  5534. _JumpIfError(hr, error, "DumpHash");
  5535. }
  5536. wprintf(wszNewLine);
  5537. }
  5538. fDisplayed = FALSE;
  5539. if (NULL != hStore)
  5540. {
  5541. CSASSERT(NULL == pCert);
  5542. for (iElement = 0; ; iElement++)
  5543. {
  5544. pCert = CertEnumCertificatesInStore(hStore, pCert);
  5545. if (NULL == pCert)
  5546. {
  5547. break;
  5548. }
  5549. if (!fDisplayed)
  5550. {
  5551. wprintf(myLoadResourceString(IDS_DUMP_PKCS7_CERTIFICATES));
  5552. wprintf(wszNewLine);
  5553. fDisplayed = TRUE;
  5554. }
  5555. hr = cuDumpAsnBinary(
  5556. pCert->pbCertEncoded,
  5557. pCert->cbCertEncoded,
  5558. iElement);
  5559. _JumpIfError(hr, error, "cuDumpAsnBinary");
  5560. }
  5561. }
  5562. if (!fDisplayed)
  5563. {
  5564. wprintf(myLoadResourceString(IDS_DUMP_PKCS7_NO_CERTIFICATES));
  5565. wprintf(wszNewLine);
  5566. }
  5567. fDisplayed = FALSE;
  5568. if (NULL != hStore)
  5569. {
  5570. CSASSERT(NULL == pCRL);
  5571. for (iElement = 0; ; iElement++)
  5572. {
  5573. pCRL = CertEnumCRLsInStore(hStore, pCRL);
  5574. if (NULL == pCRL)
  5575. {
  5576. break;
  5577. }
  5578. if (!fDisplayed)
  5579. {
  5580. wprintf(myLoadResourceString(IDS_DUMP_PKCS7_CRLS));
  5581. wprintf(wszNewLine);
  5582. fDisplayed = TRUE;
  5583. }
  5584. hr = cuDumpAsnBinary(
  5585. pCRL->pbCrlEncoded,
  5586. pCRL->cbCrlEncoded,
  5587. iElement);
  5588. _JumpIfError(hr, error, "cuDumpAsnBinary");
  5589. }
  5590. }
  5591. if (!fDisplayed)
  5592. {
  5593. wprintf(myLoadResourceString(IDS_DUMP_PKCS7_NO_CRLS));
  5594. wprintf(wszNewLine);
  5595. }
  5596. hr = S_OK;
  5597. error:
  5598. if (NULL != pszInnerContentObjId)
  5599. {
  5600. LocalFree(pszInnerContentObjId);
  5601. }
  5602. if (NULL != pAttrib)
  5603. {
  5604. LocalFree(pAttrib);
  5605. }
  5606. if (NULL != hMsg)
  5607. {
  5608. CryptMsgClose(hMsg);
  5609. }
  5610. if (NULL != pCRL)
  5611. {
  5612. CertFreeCRLContext(pCRL);
  5613. }
  5614. if (NULL != pCert)
  5615. {
  5616. CertFreeCertificateContext(pCert);
  5617. }
  5618. if (NULL != hStore)
  5619. {
  5620. CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
  5621. }
  5622. if (NULL != pbContents)
  5623. {
  5624. LocalFree(pbContents);
  5625. }
  5626. return(hr);
  5627. }
  5628. HRESULT
  5629. GetVersionStuff(
  5630. IN WCHAR const *pwszFileName,
  5631. OUT DWORD *pdwLangRet,
  5632. OUT VS_FIXEDFILEINFO *pvsRet)
  5633. {
  5634. HRESULT hr;
  5635. VOID *pvData = NULL;
  5636. DWORD cbData;
  5637. DWORD dwHandle;
  5638. DWORD *pdwTranslation;
  5639. UINT uLen;
  5640. DWORD dwDefLang = 0x409;
  5641. VS_FIXEDFILEINFO *pvs;
  5642. cbData = GetFileVersionInfoSize(
  5643. const_cast<WCHAR *>(pwszFileName),
  5644. &dwHandle);
  5645. if (0 == cbData)
  5646. {
  5647. hr = GetLastError();
  5648. if (S_OK == hr)
  5649. {
  5650. hr = ERROR_RESOURCE_DATA_NOT_FOUND;
  5651. }
  5652. goto error;
  5653. }
  5654. pvData = LocalAlloc(LMEM_FIXED, cbData);
  5655. if (NULL == pvData)
  5656. {
  5657. hr = GetLastError();
  5658. goto error;
  5659. }
  5660. if (!GetFileVersionInfo(
  5661. const_cast<WCHAR *>(pwszFileName),
  5662. 0,
  5663. cbData,
  5664. pvData))
  5665. {
  5666. hr = GetLastError();
  5667. goto error;
  5668. }
  5669. if (!VerQueryValue(pvData, L"\\VarFileInfo\\Translation", (VOID **) &pdwTranslation, &uLen))
  5670. {
  5671. pdwTranslation = &dwDefLang;
  5672. uLen = sizeof(DWORD);
  5673. }
  5674. *pdwLangRet = *pdwTranslation;
  5675. if (!VerQueryValue(pvData, L"\\", (VOID **) &pvs, &uLen))
  5676. {
  5677. hr = GetLastError();
  5678. goto error;
  5679. }
  5680. *pvsRet = *pvs;
  5681. hr = S_OK;
  5682. error:
  5683. if (NULL != pvData)
  5684. {
  5685. LocalFree(pvData);
  5686. }
  5687. return(hr);
  5688. }
  5689. HRESULT
  5690. FileVersionDump(
  5691. IN WCHAR const *pwszFileName)
  5692. {
  5693. HRESULT hr;
  5694. DWORD dwLang;
  5695. VS_FIXEDFILEINFO vs;
  5696. hr = GetVersionStuff(pwszFileName, &dwLang, &vs);
  5697. if (S_OK == hr)
  5698. {
  5699. wprintf(
  5700. myLoadResourceString(IDS_FORMAT_LANG), // "%ws: Lang %08x (%d.%d)"
  5701. pwszFileName,
  5702. dwLang,
  5703. HIWORD(dwLang),
  5704. LOWORD(dwLang));
  5705. wprintf(
  5706. myLoadResourceString(IDS_FORMAT_FILE), // " File %d.%d:%d.%d"
  5707. HIWORD(vs.dwFileVersionMS),
  5708. LOWORD(vs.dwFileVersionMS),
  5709. HIWORD(vs.dwFileVersionLS),
  5710. LOWORD(vs.dwFileVersionLS));
  5711. wprintf(
  5712. myLoadResourceString(IDS_FORMAT_PRODUCT), // " Product %d.%d:%d.%d\n"
  5713. HIWORD(vs.dwProductVersionMS),
  5714. LOWORD(vs.dwProductVersionMS),
  5715. HIWORD(vs.dwProductVersionLS),
  5716. LOWORD(vs.dwProductVersionLS));
  5717. }
  5718. return(hr);
  5719. }
  5720. HRESULT
  5721. cuFileDump(
  5722. IN WCHAR const *pwszfn)
  5723. {
  5724. HRESULT hr;
  5725. BYTE *pbIn = NULL;
  5726. DWORD cbIn;
  5727. hr = FileVersionDump(pwszfn);
  5728. if (S_OK == hr)
  5729. {
  5730. goto error;
  5731. }
  5732. hr = EPFFileDump(pwszfn, g_pwszPassword, NULL);
  5733. if (S_FALSE != hr)
  5734. {
  5735. _PrintIfError(hr, "EPFFileDump");
  5736. goto error;
  5737. }
  5738. hr = DecodeFileW(pwszfn, &pbIn, &cbIn, CRYPT_STRING_ANY);
  5739. if (S_OK != hr)
  5740. {
  5741. cuPrintError(IDS_ERR_FORMAT_DECODEFILE, hr);
  5742. goto error;
  5743. }
  5744. CSASSERT(NULL != pbIn);
  5745. hr = cuDumpAsnBinary(pbIn, cbIn, MAXDWORD);
  5746. if (S_OK != hr)
  5747. {
  5748. cuPrintError(IDS_ERR_FORMAT_CANNOT_DECODE, hr);
  5749. goto error;
  5750. }
  5751. error:
  5752. if (NULL != pbIn)
  5753. {
  5754. LocalFree(pbIn);
  5755. }
  5756. return(hr);
  5757. }
  5758. HRESULT
  5759. cuDumpSerial(
  5760. OPTIONAL IN WCHAR const *pwszPrefix,
  5761. IN DWORD idMessage,
  5762. IN CRYPT_INTEGER_BLOB const *pSerial)
  5763. {
  5764. HRESULT hr;
  5765. BSTR strSerial = NULL;
  5766. hr = MultiByteIntegerToBstr(
  5767. FALSE,
  5768. pSerial->cbData,
  5769. pSerial->pbData,
  5770. &strSerial);
  5771. _JumpIfError(hr, error, "MultiByteIntegerToBstr");
  5772. if (NULL != pwszPrefix)
  5773. {
  5774. wprintf(pwszPrefix);
  5775. }
  5776. wprintf(myLoadResourceString(idMessage));
  5777. wprintf(L" %ws\n", strSerial);
  5778. if (g_fVerbose)
  5779. {
  5780. DumpHex(
  5781. DH_MULTIADDRESS | DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
  5782. pSerial->pbData,
  5783. pSerial->cbData);
  5784. }
  5785. error:
  5786. if (NULL != strSerial)
  5787. {
  5788. SysFreeString(strSerial);
  5789. }
  5790. return(hr);
  5791. }
  5792. HRESULT
  5793. cuDumpFileTimePeriod(
  5794. IN DWORD idMessage,
  5795. OPTIONAL IN WCHAR const *pwszQuote,
  5796. IN FILETIME const *pftGMT)
  5797. {
  5798. HRESULT hr;
  5799. WCHAR *pwszTimePeriod;
  5800. hr = myFileTimePeriodToWszTimePeriod(pftGMT, g_fSeconds, &pwszTimePeriod);
  5801. _JumpIfError(hr, error, "myFileTimePeriodToWszTimePeriod");
  5802. if (NULL == pwszQuote)
  5803. {
  5804. pwszQuote = g_wszEmpty;
  5805. }
  5806. wprintf(L" %ws%ws%ws\n", pwszQuote, pwszTimePeriod, pwszQuote);
  5807. hr = S_OK;
  5808. error:
  5809. if (NULL != pwszTimePeriod)
  5810. {
  5811. LocalFree(pwszTimePeriod);
  5812. }
  5813. return(hr);
  5814. }
  5815. HRESULT
  5816. cuDumpFileTime(
  5817. IN DWORD idMessage,
  5818. OPTIONAL IN WCHAR const *pwszQuote,
  5819. IN FILETIME const *pftGMT)
  5820. {
  5821. HRESULT hr;
  5822. WCHAR *pwszDate = NULL;
  5823. WCHAR const *pwszResource = NULL;
  5824. if (0 != idMessage)
  5825. {
  5826. pwszResource = myLoadResourceString(idMessage);
  5827. }
  5828. if (NULL == pwszResource)
  5829. {
  5830. pwszResource = g_wszEmpty;
  5831. }
  5832. if (NULL == pwszQuote)
  5833. {
  5834. pwszQuote = g_wszEmpty;
  5835. }
  5836. if (0 == pftGMT->dwLowDateTime &&
  5837. 0 == pftGMT->dwHighDateTime)
  5838. {
  5839. wprintf(
  5840. L"%ws %ws\n",
  5841. pwszResource,
  5842. myLoadResourceString(IDS_PROP_EMPTY)); // "EMPTY"
  5843. }
  5844. else
  5845. {
  5846. if (g_fGMT)
  5847. {
  5848. hr = myFileTimeToWszTime(pftGMT, g_fSeconds, &pwszDate);
  5849. _JumpIfError(hr, error, "myFileTimeToWszTime");
  5850. }
  5851. else
  5852. {
  5853. hr = myGMTFileTimeToWszLocalTime(pftGMT, g_fSeconds, &pwszDate);
  5854. _JumpIfError(hr, error, "myGMTFileTimeToWszLocalTime");
  5855. }
  5856. wprintf(
  5857. L"%ws %ws%ws%ws%ws%ws\n",
  5858. pwszResource,
  5859. pwszQuote,
  5860. pwszDate,
  5861. g_fGMT? L" " : g_wszEmpty,
  5862. g_fGMT? myLoadResourceString(IDS_GMT_SUFFIX) : g_wszEmpty,
  5863. pwszQuote);
  5864. }
  5865. hr = S_OK;
  5866. error:
  5867. if (NULL != pwszDate)
  5868. {
  5869. LocalFree(pwszDate);
  5870. }
  5871. return(hr);
  5872. }
  5873. HRESULT
  5874. cuDumpFileTimeOrPeriod(
  5875. IN DWORD idMessage,
  5876. OPTIONAL IN WCHAR const *pwszQuote,
  5877. IN FILETIME const *pftGMT)
  5878. {
  5879. HRESULT hr;
  5880. if (0 <= (LONG) pftGMT->dwHighDateTime)
  5881. {
  5882. hr = cuDumpFileTime(idMessage, pwszQuote, pftGMT);
  5883. _JumpIfError(hr, error, "cuDumpFileTime");
  5884. }
  5885. else
  5886. {
  5887. hr = cuDumpFileTimePeriod(idMessage, pwszQuote, pftGMT);
  5888. _JumpIfError(hr, error, "cuDumpFileTimePeriod");
  5889. }
  5890. error:
  5891. return(hr);
  5892. }
  5893. HRESULT
  5894. cuDumpDate(
  5895. IN DATE const *pDate)
  5896. {
  5897. HRESULT hr;
  5898. FILETIME ft;
  5899. if (0.0 == *pDate)
  5900. {
  5901. ft.dwLowDateTime = 0;
  5902. ft.dwHighDateTime = 0;
  5903. }
  5904. else
  5905. {
  5906. hr = myDateToFileTime(pDate, &ft);
  5907. _JumpIfError(hr, error, "myDateToFileTime");
  5908. }
  5909. hr = cuDumpFileTime(0, NULL, &ft);
  5910. _JumpIfError(hr, error, "cuDumpFileTime");
  5911. error:
  5912. return(hr);
  5913. }
  5914. VOID
  5915. DumpBlob(
  5916. IN DWORD idMessage,
  5917. IN CRYPT_BIT_BLOB const *pBlob)
  5918. {
  5919. if (NULL != pBlob->pbData)
  5920. {
  5921. wprintf(myLoadResourceString(idMessage));
  5922. wprintf(wszNewLine);
  5923. DumpHex(DH_NOTABPREFIX | 4, pBlob->pbData, pBlob->cbData);
  5924. }
  5925. }
  5926. HRESULT
  5927. cuDisplayKeyIdFromExtension(
  5928. IN DWORD cExtension,
  5929. OPTIONAL IN CERT_EXTENSION const *rgExtension,
  5930. BYTE const *pbHash,
  5931. DWORD cbHash)
  5932. {
  5933. HRESULT hr;
  5934. hr = S_FALSE;
  5935. if (0 != cExtension && NULL != rgExtension)
  5936. {
  5937. CERT_EXTENSION const *pExt;
  5938. DWORD cb;
  5939. CRYPT_DATA_BLOB aBlob[1 + BLOB_ROUND(CBMAX_CRYPT_HASH_LEN)];
  5940. pExt = CertFindExtension(
  5941. szOID_SUBJECT_KEY_IDENTIFIER,
  5942. cExtension,
  5943. const_cast<CERT_EXTENSION *>(rgExtension));
  5944. if (NULL != pExt)
  5945. {
  5946. cb = sizeof(aBlob);
  5947. if (!CryptDecodeObject(
  5948. X509_ASN_ENCODING,
  5949. X509_OCTET_STRING,
  5950. pExt->Value.pbData,
  5951. pExt->Value.cbData,
  5952. 0,
  5953. aBlob,
  5954. &cb))
  5955. {
  5956. hr = myHLastError();
  5957. _JumpError(hr, error, "CryptDecodeObject");
  5958. }
  5959. if (cbHash != aBlob[0].cbData ||
  5960. 0 != memcmp(pbHash, aBlob[0].pbData, aBlob[0].cbData))
  5961. {
  5962. hr = DumpHash(
  5963. NULL,
  5964. IDS_FORMAT_SUBJECTKEYID_COLON, // "Subject Key Id (%ws): %ws"
  5965. NULL,
  5966. myLoadResourceString(IDS_PRECOMPUTED), // "precomputed"
  5967. aBlob[0].pbData,
  5968. aBlob[0].cbData);
  5969. _JumpIfError(hr, error, "DumpHash");
  5970. }
  5971. }
  5972. hr = S_OK;
  5973. }
  5974. error:
  5975. return(hr);
  5976. }
  5977. HRESULT
  5978. cuDisplayKeyIdCanonicalized(
  5979. IN CERT_PUBLIC_KEY_INFO const *pPublicKeyInfo)
  5980. {
  5981. HRESULT hr;
  5982. CERT_PUBLIC_KEY_INFO PublicKeyInfo;
  5983. BYTE *pbKey = NULL;
  5984. DWORD cbKey;
  5985. DWORD cbHash;
  5986. BYTE abHash[CBMAX_CRYPT_HASH_LEN];
  5987. #if 0
  5988. DumpHex(
  5989. DH_NOTABPREFIX | 4,
  5990. pPublicKeyInfo->PublicKey.pbData,
  5991. pPublicKeyInfo->PublicKey.cbData);
  5992. #endif
  5993. hr = myCanonicalizePublicKey(
  5994. pPublicKeyInfo->PublicKey.pbData,
  5995. pPublicKeyInfo->PublicKey.cbData,
  5996. &pbKey,
  5997. &cbKey);
  5998. _JumpIfError2(hr, error, "myCanonicalizePublicKey", hr);
  5999. PublicKeyInfo = *pPublicKeyInfo;
  6000. PublicKeyInfo.PublicKey.pbData = pbKey;
  6001. PublicKeyInfo.PublicKey.cbData = cbKey;
  6002. #if 0
  6003. DumpHex(
  6004. DH_NOTABPREFIX | 4,
  6005. PublicKeyInfo.PublicKey.pbData,
  6006. PublicKeyInfo.PublicKey.cbData);
  6007. #endif
  6008. cbHash = sizeof(abHash);
  6009. if (!CryptHashPublicKeyInfo(
  6010. NULL, // hCryptProv
  6011. CALG_SHA1,
  6012. 0, // dwFlags,
  6013. X509_ASN_ENCODING,
  6014. &PublicKeyInfo,
  6015. abHash,
  6016. &cbHash))
  6017. {
  6018. hr = myHLastError();
  6019. _JumpError(hr, error, "CryptHashPublicKeyInfo");
  6020. }
  6021. hr = DumpHash(
  6022. NULL,
  6023. IDS_FORMAT_KEYIDHASH_COLON, // "Public Key Hash(%ws): %ws"
  6024. myLoadResourceString(IDS_CANONICALIZED), // "canonicalized"
  6025. L"sha1",
  6026. abHash,
  6027. cbHash);
  6028. _JumpIfError(hr, error, "DumpHash");
  6029. error:
  6030. if (NULL != pbKey)
  6031. {
  6032. LocalFree(pbKey);
  6033. }
  6034. return(hr);
  6035. }
  6036. HRESULT
  6037. cuDisplayKeyId(
  6038. IN CERT_PUBLIC_KEY_INFO const *pPublicKeyInfo,
  6039. IN DWORD cExtension,
  6040. OPTIONAL IN CERT_EXTENSION const *rgExtension)
  6041. {
  6042. HRESULT hr;
  6043. DWORD cbHash;
  6044. BYTE abHash[CBMAX_CRYPT_HASH_LEN];
  6045. cbHash = sizeof(abHash);
  6046. if (!CryptHashPublicKeyInfo(
  6047. NULL, // hCryptProv
  6048. CALG_SHA1,
  6049. 0, // dwFlags,
  6050. X509_ASN_ENCODING,
  6051. const_cast<CERT_PUBLIC_KEY_INFO *>(pPublicKeyInfo),
  6052. abHash,
  6053. &cbHash))
  6054. {
  6055. hr = myHLastError();
  6056. _JumpError(hr, error, "CryptHashPublicKeyInfo");
  6057. }
  6058. hr = DumpHash(
  6059. NULL,
  6060. IDS_FORMAT_KEYIDHASH_COLON, // "Public Key Hash(%ws): %ws"
  6061. NULL,
  6062. L"sha1",
  6063. abHash,
  6064. cbHash);
  6065. _JumpIfError(hr, error, "DumpHash");
  6066. hr = cuDisplayKeyIdFromExtension(
  6067. cExtension,
  6068. rgExtension,
  6069. abHash,
  6070. cbHash);
  6071. _PrintIfError2(hr, "cuDisplayKeyIdFromExtension", hr);
  6072. hr = cuDisplayKeyIdCanonicalized(pPublicKeyInfo);
  6073. _PrintIfError2(hr, "cuDisplayKeyIdCanonicalized", hr);
  6074. hr = S_OK;
  6075. error:
  6076. return(hr);
  6077. }
  6078. HRESULT
  6079. cuDisplayHash(
  6080. OPTIONAL IN WCHAR const *pwszPrefix,
  6081. OPTIONAL IN CERT_CONTEXT const *pCertContext,
  6082. OPTIONAL IN CRL_CONTEXT const *pCRLContext,
  6083. IN DWORD dwPropId,
  6084. IN WCHAR const *pwszHashName)
  6085. {
  6086. HRESULT hr;
  6087. BYTE abHash[CBMAX_CRYPT_HASH_LEN];
  6088. DWORD cbHash;
  6089. UINT idMsg;
  6090. cbHash = sizeof(abHash);
  6091. if (NULL != pCertContext)
  6092. {
  6093. if (!CertGetCertificateContextProperty(
  6094. pCertContext,
  6095. dwPropId,
  6096. abHash,
  6097. &cbHash))
  6098. {
  6099. hr = myHLastError();
  6100. _JumpError(hr, error, "CertGetCertificateContextProperty");
  6101. }
  6102. idMsg = IDS_FORMAT_CERTHASH_COLON; // "Cert Hash(%ws): %ws"
  6103. }
  6104. else
  6105. {
  6106. CSASSERT(NULL != pCRLContext);
  6107. if (!CertGetCRLContextProperty(pCRLContext, dwPropId, abHash, &cbHash))
  6108. {
  6109. hr = myHLastError();
  6110. _JumpError(hr, error, "CertGetCRLContextProperty");
  6111. }
  6112. idMsg = IDS_FORMAT_CRLHASH_COLON; // "CRL Hash(%ws): %ws"
  6113. }
  6114. hr = DumpHash(pwszPrefix, idMsg, NULL, pwszHashName, abHash, cbHash);
  6115. _JumpIfError(hr, error, "DumpHash");
  6116. error:
  6117. return(hr);
  6118. }
  6119. HRESULT
  6120. cuGetCertType(
  6121. IN CERT_INFO const *pCertInfo,
  6122. OPTIONAL OUT WCHAR **ppwszCertTypeNameV1,
  6123. OPTIONAL OUT WCHAR **ppwszDisplayNameV1,
  6124. OPTIONAL OUT WCHAR **ppwszCertTypeObjId,
  6125. OPTIONAL OUT WCHAR **ppwszCertTypeName,
  6126. OPTIONAL OUT WCHAR **ppwszDisplayName)
  6127. {
  6128. HRESULT hr;
  6129. CERT_EXTENSION *pExt;
  6130. WCHAR *pwszCertTypeNameV1 = NULL;
  6131. WCHAR *pwszCNV1 = NULL;
  6132. WCHAR *pwszDisplayNameV1 = NULL;
  6133. WCHAR *pwszCertTypeObjId = NULL;
  6134. WCHAR *pwszCN = NULL;
  6135. WCHAR *pwszDisplayName = NULL;
  6136. CERT_TEMPLATE_EXT *pTemplate = NULL;
  6137. if (NULL != ppwszCertTypeNameV1)
  6138. {
  6139. *ppwszCertTypeNameV1 = NULL;
  6140. }
  6141. if (NULL != ppwszDisplayNameV1)
  6142. {
  6143. *ppwszDisplayNameV1 = NULL;
  6144. }
  6145. if (NULL != ppwszCertTypeObjId)
  6146. {
  6147. *ppwszCertTypeObjId = NULL;
  6148. }
  6149. if (NULL != ppwszCertTypeName)
  6150. {
  6151. *ppwszCertTypeName = NULL;
  6152. }
  6153. if (NULL != ppwszDisplayName)
  6154. {
  6155. *ppwszDisplayName = NULL;
  6156. }
  6157. // Look for the V1 cert type extension first
  6158. pExt = CertFindExtension(
  6159. szOID_ENROLL_CERTTYPE_EXTENSION,
  6160. pCertInfo->cExtension,
  6161. pCertInfo->rgExtension);
  6162. if (NULL != pExt)
  6163. {
  6164. hr = UnicodeDecode(&pExt->Value, &pwszCertTypeNameV1);
  6165. _JumpIfError(hr, error, "UnicodeDecode");
  6166. hr = cuGetTemplateNames(
  6167. pwszCertTypeNameV1,
  6168. &pwszCNV1,
  6169. &pwszDisplayNameV1);
  6170. _PrintIfErrorStr2(hr, "cuGetTemplateNames", pwszCertTypeNameV1, hr);
  6171. if (HRESULT_FROM_WIN32(ERROR_NOT_FOUND) != hr)
  6172. {
  6173. _JumpIfErrorStr(hr, error, "cuGetTemplateNames", pwszCertTypeNameV1);
  6174. }
  6175. }
  6176. pExt = CertFindExtension(
  6177. szOID_CERTIFICATE_TEMPLATE,
  6178. pCertInfo->cExtension,
  6179. pCertInfo->rgExtension);
  6180. if (NULL != pExt)
  6181. {
  6182. DWORD cb;
  6183. if (!myDecodeObject(
  6184. X509_ASN_ENCODING,
  6185. X509_CERTIFICATE_TEMPLATE,
  6186. pExt->Value.pbData,
  6187. pExt->Value.cbData,
  6188. CERTLIB_USE_LOCALALLOC,
  6189. (VOID **) &pTemplate,
  6190. &cb))
  6191. {
  6192. CSASSERT(NULL == pTemplate);
  6193. hr = myHLastError();
  6194. _JumpError(hr, error, "myDecodeObject");
  6195. }
  6196. if (!ConvertSzToWsz(&pwszCertTypeObjId, pTemplate->pszObjId, -1))
  6197. {
  6198. hr = E_OUTOFMEMORY;
  6199. _JumpError(hr, error, "ConvertSzToWsz");
  6200. }
  6201. hr = cuGetTemplateNames(pwszCertTypeObjId, &pwszCN, &pwszDisplayName);
  6202. _PrintIfErrorStr2(hr, "cuGetTemplateNames", pwszCertTypeObjId, hr);
  6203. if (HRESULT_FROM_WIN32(ERROR_NOT_FOUND) != hr)
  6204. {
  6205. _JumpIfErrorStr(hr, error, "cuGetTemplateNames", pwszCertTypeObjId);
  6206. }
  6207. }
  6208. if (NULL == pwszCertTypeNameV1 && NULL == pwszCertTypeObjId)
  6209. {
  6210. hr = CRYPT_E_NOT_FOUND;
  6211. _JumpError2(hr, error, "CertFindExtension", CRYPT_E_NOT_FOUND);
  6212. }
  6213. if (NULL != ppwszCertTypeNameV1)
  6214. {
  6215. if (NULL != pwszCNV1)
  6216. {
  6217. *ppwszCertTypeNameV1 = pwszCNV1;
  6218. pwszCNV1 = NULL;
  6219. }
  6220. else
  6221. {
  6222. *ppwszCertTypeNameV1 = pwszCertTypeNameV1;
  6223. pwszCertTypeNameV1 = NULL;
  6224. }
  6225. }
  6226. if (NULL != ppwszDisplayNameV1)
  6227. {
  6228. *ppwszDisplayNameV1 = pwszDisplayNameV1;
  6229. pwszDisplayNameV1 = NULL;
  6230. }
  6231. if (NULL != ppwszCertTypeObjId)
  6232. {
  6233. *ppwszCertTypeObjId = pwszCertTypeObjId;
  6234. pwszCertTypeObjId = NULL;
  6235. }
  6236. if (NULL != ppwszCertTypeName)
  6237. {
  6238. *ppwszCertTypeName = pwszCN;
  6239. pwszCN = NULL;
  6240. }
  6241. if (NULL != ppwszDisplayName)
  6242. {
  6243. *ppwszDisplayName = pwszDisplayName;
  6244. pwszDisplayName = NULL;
  6245. }
  6246. hr = S_OK;
  6247. error:
  6248. if (NULL != pwszCertTypeNameV1)
  6249. {
  6250. LocalFree(pwszCertTypeNameV1);
  6251. }
  6252. if (NULL != pwszCNV1)
  6253. {
  6254. LocalFree(pwszCNV1);
  6255. }
  6256. if (NULL != pwszDisplayNameV1)
  6257. {
  6258. LocalFree(pwszDisplayNameV1);
  6259. }
  6260. if (NULL != pwszCertTypeObjId)
  6261. {
  6262. LocalFree(pwszCertTypeObjId);
  6263. }
  6264. if (NULL != pwszCN)
  6265. {
  6266. LocalFree(pwszCN);
  6267. }
  6268. if (NULL != pwszDisplayName)
  6269. {
  6270. LocalFree(pwszDisplayName);
  6271. }
  6272. if (NULL != pTemplate)
  6273. {
  6274. LocalFree(pTemplate);
  6275. }
  6276. return(hr);
  6277. }
  6278. HRESULT
  6279. cuDumpCertType(
  6280. OPTIONAL IN WCHAR const *pwszPrefix,
  6281. IN CERT_INFO const *pCertInfo)
  6282. {
  6283. HRESULT hr;
  6284. WCHAR *apwsz[6];
  6285. DWORD i;
  6286. DWORD j;
  6287. BOOL fFirst;
  6288. ZeroMemory(apwsz, sizeof(apwsz));
  6289. hr = cuGetCertType(
  6290. pCertInfo,
  6291. &apwsz[0], // ppwszCertTypeNameV1
  6292. &apwsz[1], // ppwszDisplayNameV1
  6293. &apwsz[2], // ppwszCertTypeObjId
  6294. &apwsz[3], // ppwszCertTypeName
  6295. &apwsz[4]); // ppwszDisplayName
  6296. _JumpIfError2(hr, error, "cuGetCertType", CRYPT_E_NOT_FOUND);
  6297. if (NULL != apwsz[2]) // pwszCertTypeObjId
  6298. {
  6299. WCHAR const *pwszFriendlyName;
  6300. pwszFriendlyName = cuGetOIDName(apwsz[2]);
  6301. if (NULL != pwszFriendlyName && L'\0' != *pwszFriendlyName)
  6302. {
  6303. hr = myDupString(pwszFriendlyName, &apwsz[5]);
  6304. _JumpIfError(hr, error, "myDupString");
  6305. }
  6306. }
  6307. wprintf(
  6308. L"%ws%ws: ",
  6309. NULL != pwszPrefix? pwszPrefix : L"",
  6310. myLoadResourceString(IDS_TEMPLATE_NAME)); // "Template"
  6311. // Suppress the long, ugly ObjId, unless they really want to see it:
  6312. if (!g_fVerbose &&
  6313. NULL != apwsz[2] &&
  6314. (NULL != apwsz[0] || NULL != apwsz[3]))
  6315. {
  6316. LocalFree(apwsz[2]);
  6317. apwsz[2] = NULL;
  6318. }
  6319. fFirst = TRUE;
  6320. for (i = 0; i < ARRAYSIZE(apwsz); i++)
  6321. {
  6322. if (NULL != apwsz[i])
  6323. {
  6324. BOOL fDup = FALSE;
  6325. for (j = 0; j < i; j++)
  6326. {
  6327. if (NULL != apwsz[j] && 0 == lstrcmp(apwsz[i], apwsz[j]))
  6328. {
  6329. fDup = TRUE;
  6330. break;
  6331. }
  6332. }
  6333. if (!fDup)
  6334. {
  6335. if (!fFirst)
  6336. {
  6337. wprintf(L", ");
  6338. }
  6339. wprintf(L"%ws", apwsz[i]);
  6340. fFirst = FALSE;
  6341. }
  6342. }
  6343. }
  6344. wprintf(wszNewLine);
  6345. error:
  6346. for (i = 0; i < ARRAYSIZE(apwsz); i++)
  6347. {
  6348. if (NULL != apwsz[i])
  6349. {
  6350. LocalFree(apwsz[i]);
  6351. }
  6352. }
  6353. return(hr);
  6354. }
  6355. HRESULT
  6356. dumpCert(
  6357. IN DWORD idMessage,
  6358. IN BYTE const *pbIn,
  6359. IN DWORD cbIn,
  6360. IN BYTE const *pbDecoded,
  6361. IN DWORD cbDecoded,
  6362. IN CERT_SIGNED_CONTENT_INFO const *pcsci)
  6363. {
  6364. HRESULT hr;
  6365. CERT_CONTEXT const *pCertContext = NULL;
  6366. CERT_INFO *pCertInfo;
  6367. BOOL fIssuerMatches;
  6368. DWORD id;
  6369. pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING, pbIn, cbIn);
  6370. if (NULL == pCertContext)
  6371. {
  6372. hr = myHLastError();
  6373. _JumpError(hr, error, "CertCreateCertificateContext");
  6374. }
  6375. pCertInfo = pCertContext->pCertInfo;
  6376. if (!g_fQuiet)
  6377. {
  6378. wprintf(myLoadResourceString(idMessage));
  6379. wprintf(wszNewLine);
  6380. cuDumpVersion(pCertInfo->dwVersion + 1);
  6381. }
  6382. hr = cuDumpSerial(NULL, IDS_SERIAL, &pCertInfo->SerialNumber);
  6383. _JumpIfError(hr, error, "cuDumpSerial");
  6384. if (!g_fQuiet)
  6385. {
  6386. cuDumpAlgorithm(IDS_SIGNATURE_ALGORITHM, &pCertInfo->SignatureAlgorithm);
  6387. }
  6388. hr = cuDisplayCertName(
  6389. !g_fQuiet,
  6390. NULL,
  6391. myLoadResourceString(IDS_ISSUER), // "Issuer"
  6392. g_wszPad4,
  6393. &pCertInfo->Issuer,
  6394. NULL);
  6395. _JumpIfError(hr, error, "cuDisplayCertName(Issuer)");
  6396. if (!g_fQuiet)
  6397. {
  6398. wprintf(wszNewLine);
  6399. hr = cuDumpFileTime(IDS_NOTBEFORE, NULL, &pCertInfo->NotBefore);
  6400. _JumpIfError(hr, error, "cuDumpFileTime");
  6401. hr = cuDumpFileTime(IDS_NOTAFTER, NULL, &pCertInfo->NotAfter);
  6402. _JumpIfError(hr, error, "cuDumpFileTime");
  6403. wprintf(wszNewLine);
  6404. }
  6405. hr = cuDisplayCertName(
  6406. !g_fQuiet,
  6407. NULL,
  6408. myLoadResourceString(IDS_SUBJECT), // "Subject"
  6409. g_wszPad4,
  6410. &pCertInfo->Subject,
  6411. pCertInfo);
  6412. _JumpIfError(hr, error, "cuDisplayCertName(Subject)");
  6413. if (!g_fQuiet)
  6414. {
  6415. wprintf(wszNewLine);
  6416. cuDumpPublicKey(&pCertInfo->SubjectPublicKeyInfo);
  6417. DumpBlob(IDS_ISSUERUNIQUEID, &pCertInfo->IssuerUniqueId);
  6418. DumpBlob(IDS_SUBJECTUNIQUEID, &pCertInfo->SubjectUniqueId);
  6419. }
  6420. hr = cuDumpExtensionArray(
  6421. IDS_CERTIFICATE_EXTENSIONS,
  6422. pCertInfo->cExtension,
  6423. pCertInfo->rgExtension);
  6424. _JumpIfError(hr, error, "cuDumpExtensionArray");
  6425. if (!g_fQuiet)
  6426. {
  6427. cuDumpSignature(pcsci);
  6428. }
  6429. if (!CertCompareCertificateName(
  6430. X509_ASN_ENCODING,
  6431. &pCertInfo->Issuer,
  6432. &pCertInfo->Subject))
  6433. {
  6434. fIssuerMatches = FALSE;
  6435. }
  6436. else
  6437. {
  6438. fIssuerMatches = TRUE;
  6439. }
  6440. hr = cuVerifySignature(pbIn, cbIn, &pCertInfo->SubjectPublicKeyInfo, FALSE, TRUE);
  6441. if (S_OK != hr)
  6442. {
  6443. if (fIssuerMatches)
  6444. {
  6445. id = IDS_ERR_FORMAT_ROOT_CERT_BAD_SIG; // "Possible Root Certificate: Subject matches Issuer, but Signature check fails: %x"
  6446. }
  6447. else
  6448. {
  6449. id = IDS_NO_ROOT_CERT; // "Non-root Certificate"
  6450. }
  6451. }
  6452. else
  6453. {
  6454. if (fIssuerMatches)
  6455. {
  6456. id = IDS_ROOT_CERT; // "Root Certificate: Subject matches Issuer"
  6457. }
  6458. else
  6459. {
  6460. id = IDS_NO_ROOT_CERT_GOOD_SIG; // "Non-root Certificate uses same Public Key as Issuer"
  6461. }
  6462. }
  6463. wprintf(myLoadResourceString(id), hr);
  6464. wprintf(wszNewLine);
  6465. if (g_fQuiet)
  6466. {
  6467. hr = cuDumpCertType(NULL, pCertContext->pCertInfo);
  6468. _PrintIfError2(hr, "cuDumpCertType", CRYPT_E_NOT_FOUND);
  6469. }
  6470. else
  6471. {
  6472. cuDisplayKeyId(
  6473. &pCertContext->pCertInfo->SubjectPublicKeyInfo,
  6474. pCertContext->pCertInfo->cExtension,
  6475. pCertContext->pCertInfo->rgExtension);
  6476. hr = cuDisplayHash(
  6477. NULL,
  6478. pCertContext,
  6479. NULL,
  6480. CERT_MD5_HASH_PROP_ID,
  6481. L"md5");
  6482. _JumpIfError(hr, error, "cuDisplayHash");
  6483. }
  6484. hr = cuDisplayHash(
  6485. NULL,
  6486. pCertContext,
  6487. NULL,
  6488. CERT_SHA1_HASH_PROP_ID,
  6489. L"sha1");
  6490. _JumpIfError(hr, error, "cuDisplayHash");
  6491. error:
  6492. if (NULL != pCertContext)
  6493. {
  6494. CertFreeCertificateContext(pCertContext);
  6495. }
  6496. return(hr);
  6497. }
  6498. HRESULT
  6499. dumpCertSequence(
  6500. IN DWORD idMessage,
  6501. IN BYTE const *pbIn,
  6502. IN DWORD cbIn,
  6503. IN BYTE const *pbDecoded,
  6504. IN DWORD cbDecoded,
  6505. IN CERT_SIGNED_CONTENT_INFO const *pcsci)
  6506. {
  6507. HRESULT hr;
  6508. HRESULT hr2;
  6509. DWORD iCert;
  6510. CRYPT_CONTENT_INFO_SEQUENCE_OF_ANY const *pSeq;
  6511. pSeq = (CRYPT_CONTENT_INFO_SEQUENCE_OF_ANY const *) pbDecoded;
  6512. if (0 != strcmp(szOID_NETSCAPE_CERT_SEQUENCE, pSeq->pszObjId))
  6513. {
  6514. hr = CRYPT_E_ASN1_ERROR;
  6515. _JumpError2(hr, error, "not a cert sequence", hr);
  6516. }
  6517. wprintf(myLoadResourceString(idMessage));
  6518. wprintf(wszNewLine);
  6519. hr = S_OK;
  6520. for (iCert = 0; iCert < pSeq->cValue; iCert++)
  6521. {
  6522. wprintf(
  6523. myLoadResourceString(IDS_FORMAT_DUMP_CERT_INDEX), // "================ Certificate %d ================"
  6524. iCert);
  6525. wprintf(wszNewLine);
  6526. hr2 = cuDumpAsnBinary(
  6527. pSeq->rgValue[iCert].pbData,
  6528. pSeq->rgValue[iCert].cbData,
  6529. iCert);
  6530. if (S_OK != hr2)
  6531. {
  6532. cuPrintError(IDS_ERR_FORMAT_CANNOT_DECODE, hr2);
  6533. if (S_OK == hr)
  6534. {
  6535. hr = hr2;
  6536. }
  6537. }
  6538. }
  6539. error:
  6540. return(hr);
  6541. }
  6542. HRESULT
  6543. dumpCRL(
  6544. IN DWORD idMessage,
  6545. IN BYTE const *pbIn,
  6546. IN DWORD cbIn,
  6547. IN BYTE const *pbDecoded,
  6548. IN DWORD cbDecoded,
  6549. IN CERT_SIGNED_CONTENT_INFO const *pcsci)
  6550. {
  6551. HRESULT hr;
  6552. CRL_CONTEXT const *pCRLContext = NULL;
  6553. CRL_INFO const *pCRLInfo;
  6554. DWORD i;
  6555. CRL_ENTRY *pCRLEntry;
  6556. CSASSERT(NULL != pbIn && 0 != cbIn);
  6557. CSASSERT(NULL != pbDecoded && 0 != cbDecoded);
  6558. pCRLContext = CertCreateCRLContext(X509_ASN_ENCODING, pbIn, cbIn);
  6559. if (NULL == pCRLContext)
  6560. {
  6561. hr = myHLastError();
  6562. _JumpError(hr, error, "CertCreateCRLContext");
  6563. }
  6564. pCRLInfo = pCRLContext->pCrlInfo;
  6565. if (!g_fQuiet)
  6566. {
  6567. wprintf(myLoadResourceString(idMessage));
  6568. wprintf(wszNewLine);
  6569. cuDumpVersion(pCRLInfo->dwVersion + 1);
  6570. cuDumpAlgorithm(IDS_SIGNATURE_ALGORITHM, &pCRLInfo->SignatureAlgorithm);
  6571. }
  6572. hr = cuDisplayCertName(
  6573. TRUE,
  6574. NULL,
  6575. myLoadResourceString(IDS_ISSUER), // "Issuer"
  6576. g_wszPad4,
  6577. &pCRLInfo->Issuer,
  6578. NULL);
  6579. _JumpIfError(hr, error, "cuDisplayCertName(Issuer)");
  6580. if (!g_fQuiet)
  6581. {
  6582. wprintf(wszNewLine);
  6583. hr = cuDumpFileTime(IDS_THISUPDATE, NULL, &pCRLInfo->ThisUpdate);
  6584. _JumpIfError(hr, error, "cuDumpFileTime");
  6585. hr = cuDumpFileTime(IDS_NEXTUPDATE, NULL, &pCRLInfo->NextUpdate);
  6586. _JumpIfError(hr, error, "cuDumpFileTime");
  6587. wprintf(myLoadResourceString(IDS_CRLENTRIES)); // "CRL Entries:"
  6588. wprintf(L" %u\n", pCRLInfo->cCRLEntry);
  6589. for (i = 0; i < pCRLInfo->cCRLEntry; i++)
  6590. {
  6591. pCRLEntry = &pCRLInfo->rgCRLEntry[i];
  6592. wprintf(g_wszPad2);
  6593. hr = cuDumpSerial(NULL, IDS_SERIAL, &pCRLEntry->SerialNumber);
  6594. _JumpIfError(hr, error, "cuDumpSerial");
  6595. wprintf(g_wszPad2);
  6596. hr = cuDumpFileTime(
  6597. IDS_REVOCATIONDATE,
  6598. NULL,
  6599. &pCRLEntry->RevocationDate);
  6600. _JumpIfError(hr, error, "cuDumpFileTime");
  6601. if (0 != pCRLEntry->cExtension)
  6602. {
  6603. wprintf(g_wszPad2);
  6604. hr = cuDumpExtensionArray(
  6605. IDS_EXTENSIONS,
  6606. pCRLEntry->cExtension,
  6607. pCRLEntry->rgExtension);
  6608. _JumpIfError(hr, error, "cuDumpExtensionArray");
  6609. }
  6610. wprintf(wszNewLine);
  6611. }
  6612. }
  6613. if (0 != pCRLInfo->cExtension)
  6614. {
  6615. hr = cuDumpExtensionArray(
  6616. IDS_CRLEXTENSIONS,
  6617. pCRLInfo->cExtension,
  6618. pCRLInfo->rgExtension);
  6619. _JumpIfError(hr, error, "cuDumpExtensionArray");
  6620. }
  6621. if (!g_fQuiet)
  6622. {
  6623. cuDumpSignature(pcsci);
  6624. hr = cuDisplayHash(
  6625. NULL,
  6626. NULL,
  6627. pCRLContext,
  6628. CERT_MD5_HASH_PROP_ID,
  6629. L"md5");
  6630. _JumpIfError(hr, error, "cuDisplayHash");
  6631. }
  6632. hr = cuDisplayHash(
  6633. NULL,
  6634. NULL,
  6635. pCRLContext,
  6636. CERT_SHA1_HASH_PROP_ID,
  6637. L"sha1");
  6638. _JumpIfError(hr, error, "cuDisplayHash");
  6639. error:
  6640. return(hr);
  6641. }
  6642. HRESULT
  6643. dumpRequest(
  6644. IN DWORD idMessage,
  6645. IN BYTE const *pbIn,
  6646. IN DWORD cbIn,
  6647. IN BYTE const *pbDecoded,
  6648. IN DWORD cbDecoded,
  6649. IN CERT_SIGNED_CONTENT_INFO const *pcsci)
  6650. {
  6651. HRESULT hr;
  6652. CERT_REQUEST_INFO const *pRequest;
  6653. CERT_EXTENSIONS *pExtInfo = NULL;
  6654. CSASSERT(NULL != pbIn && 0 != cbIn);
  6655. CSASSERT(NULL != pbDecoded && 0 != cbDecoded);
  6656. wprintf(myLoadResourceString(idMessage));
  6657. wprintf(wszNewLine);
  6658. pRequest = (CERT_REQUEST_INFO const *) pbDecoded;
  6659. cuDumpVersion(pRequest->dwVersion + 1);
  6660. hr = cuDisplayCertName(
  6661. TRUE,
  6662. NULL,
  6663. myLoadResourceString(IDS_SUBJECT), // "Subject"
  6664. g_wszPad4,
  6665. &pRequest->Subject,
  6666. NULL);
  6667. _JumpIfError(hr, error, "cuDisplayCertName(Subject)");
  6668. wprintf(wszNewLine);
  6669. cuDumpPublicKey(&pRequest->SubjectPublicKeyInfo);
  6670. wprintf(myLoadResourceString(IDS_REQUEST_ATTRIBUTES)); // "Request Attributes:"
  6671. wprintf(L" %u\n", pRequest->cAttribute);
  6672. // Dump attributes and certificate extensions
  6673. hr = DumpAttributes(
  6674. pRequest->rgAttribute,
  6675. pRequest->cAttribute,
  6676. FALSE,
  6677. FOT_ATTRIBUTE,
  6678. NULL, // hStore
  6679. NULL,
  6680. NULL,
  6681. &pExtInfo);
  6682. _JumpIfError(hr, error, "DumpAttributes");
  6683. cuDumpSignature(pcsci);
  6684. if (NULL != pcsci)
  6685. {
  6686. hr = cuVerifySignature(
  6687. pbIn,
  6688. cbIn,
  6689. &pRequest->SubjectPublicKeyInfo,
  6690. FALSE,
  6691. FALSE);
  6692. _JumpIfError(hr, error, "cuVerifySignature");
  6693. }
  6694. hr = cuDisplayKeyId(
  6695. &pRequest->SubjectPublicKeyInfo,
  6696. NULL == pExtInfo? 0 : pExtInfo->cExtension,
  6697. NULL == pExtInfo? NULL : pExtInfo->rgExtension);
  6698. _JumpIfError(hr, error, "cuDisplayKeyId");
  6699. hr = S_OK;
  6700. error:
  6701. if (NULL != pExtInfo)
  6702. {
  6703. LocalFree(pExtInfo);
  6704. }
  6705. return(hr);
  6706. }
  6707. VOID
  6708. DumpCMCDataReference(
  6709. IN DWORD dwCmcDataReference,
  6710. IN DWORD cCertReference,
  6711. IN DWORD const *rgdwCertReference)
  6712. {
  6713. DWORD i;
  6714. wprintf(
  6715. L" %ws: %u\n",
  6716. myLoadResourceString(IDS_DATA_REFERENCE),
  6717. dwCmcDataReference);
  6718. for (i = 0; i < cCertReference; i++)
  6719. {
  6720. wprintf(
  6721. L" %ws[%u]: %u\n",
  6722. myLoadResourceString(IDS_CERT_REFERENCE),
  6723. i,
  6724. rgdwCertReference[i]);
  6725. }
  6726. }
  6727. HRESULT
  6728. DumpCMCStatus(
  6729. IN CMC_STATUS_INFO const *pcmcStatus)
  6730. {
  6731. HRESULT hr;
  6732. WCHAR const *pwsz;
  6733. DWORD i;
  6734. switch (pcmcStatus->dwStatus)
  6735. {
  6736. case CMC_STATUS_SUCCESS:
  6737. pwsz = L"CMC_STATUS_SUCCESS";
  6738. break;
  6739. case CMC_STATUS_FAILED:
  6740. pwsz = L"CMC_STATUS_FAILED";
  6741. break;
  6742. case CMC_STATUS_PENDING:
  6743. pwsz = L"CMC_STATUS_PENDING";
  6744. break;
  6745. case CMC_STATUS_NO_SUPPORT:
  6746. pwsz = L"CMC_STATUS_NO_SUPPORT";
  6747. break;
  6748. case CMC_STATUS_CONFIRM_REQUIRED:
  6749. pwsz = L"CMC_STATUS_CONFIRM_REQUIRED";
  6750. break;
  6751. default:
  6752. pwsz = g_wszEmpty;
  6753. break;
  6754. }
  6755. wprintf(
  6756. L" %ws: %ws(%u)\n",
  6757. myLoadResourceString(IDS_CMC_STATUS),
  6758. pwsz,
  6759. pcmcStatus->dwStatus);
  6760. for (i = 0; i < pcmcStatus->cBodyList; i++)
  6761. {
  6762. wprintf(
  6763. L" %ws[%u]: %u\n",
  6764. myLoadResourceString(IDS_BODY_REFERENCE),
  6765. i,
  6766. pcmcStatus->rgdwBodyList[i]);
  6767. }
  6768. if (NULL != pcmcStatus->pwszStatusString)
  6769. {
  6770. wprintf(
  6771. L" %ws: %ws\n",
  6772. myLoadResourceString(IDS_CMC_STATUSSTRING),
  6773. pcmcStatus->pwszStatusString);
  6774. }
  6775. switch (pcmcStatus->dwOtherInfoChoice)
  6776. {
  6777. case CMC_OTHER_INFO_NO_CHOICE:
  6778. pwsz = L"CMC_OTHER_INFO_NO_CHOICE";
  6779. break;
  6780. case CMC_OTHER_INFO_FAIL_CHOICE:
  6781. pwsz = L"CMC_OTHER_INFO_FAIL_CHOICE";
  6782. break;
  6783. case CMC_OTHER_INFO_PEND_CHOICE:
  6784. pwsz = L"CMC_OTHER_INFO_PEND_CHOICE";
  6785. break;
  6786. default:
  6787. pwsz = g_wszEmpty;
  6788. break;
  6789. }
  6790. wprintf(
  6791. L" %ws: %ws(%u)\n",
  6792. myLoadResourceString(IDS_CMC_OTHERCHOICE),
  6793. pwsz,
  6794. pcmcStatus->dwOtherInfoChoice);
  6795. switch (pcmcStatus->dwOtherInfoChoice)
  6796. {
  6797. case CMC_OTHER_INFO_FAIL_CHOICE:
  6798. switch (pcmcStatus->dwFailInfo)
  6799. {
  6800. case CMC_FAIL_BAD_ALG:
  6801. pwsz = L"CMC_FAIL_BAD_ALG";
  6802. break;
  6803. case CMC_FAIL_BAD_MESSAGE_CHECK:
  6804. pwsz = L"CMC_FAIL_BAD_MESSAGE_CHECK";
  6805. break;
  6806. case CMC_FAIL_BAD_REQUEST:
  6807. pwsz = L"CMC_FAIL_BAD_REQUEST";
  6808. break;
  6809. case CMC_FAIL_BAD_TIME:
  6810. pwsz = L"CMC_FAIL_BAD_TIME";
  6811. break;
  6812. case CMC_FAIL_BAD_CERT_ID:
  6813. pwsz = L"CMC_FAIL_BAD_CERT_ID";
  6814. break;
  6815. case CMC_FAIL_UNSUPORTED_EXT:
  6816. pwsz = L"CMC_FAIL_UNSUPORTED_EXT";
  6817. break;
  6818. case CMC_FAIL_MUST_ARCHIVE_KEYS:
  6819. pwsz = L"CMC_FAIL_MUST_ARCHIVE_KEYS";
  6820. break;
  6821. case CMC_FAIL_BAD_IDENTITY:
  6822. pwsz = L"CMC_FAIL_BAD_IDENTITY";
  6823. break;
  6824. case CMC_FAIL_POP_REQUIRED:
  6825. pwsz = L"CMC_FAIL_POP_REQUIRED";
  6826. break;
  6827. case CMC_FAIL_POP_FAILED:
  6828. pwsz = L"CMC_FAIL_POP_FAILED";
  6829. break;
  6830. case CMC_FAIL_NO_KEY_REUSE:
  6831. pwsz = L"CMC_FAIL_NO_KEY_REUSE";
  6832. break;
  6833. case CMC_FAIL_INTERNAL_CA_ERROR:
  6834. pwsz = L"CMC_FAIL_INTERNAL_CA_ERROR";
  6835. break;
  6836. case CMC_FAIL_TRY_LATER:
  6837. pwsz = L"CMC_FAIL_TRY_LATER";
  6838. break;
  6839. default:
  6840. pwsz = g_wszEmpty;
  6841. break;
  6842. }
  6843. wprintf(
  6844. L" %ws: %ws(%u)\n",
  6845. myLoadResourceString(IDS_CMC_FAILINFO),
  6846. pwsz,
  6847. pcmcStatus->dwFailInfo);
  6848. break;
  6849. case CMC_OTHER_INFO_PEND_CHOICE:
  6850. wprintf(myLoadResourceString(IDS_PENDTOKEN)); //"Pend Token:"
  6851. DumpHex(
  6852. DH_NOTABPREFIX | 4,
  6853. pcmcStatus->pPendInfo->PendToken.pbData,
  6854. pcmcStatus->pPendInfo->PendToken.cbData);
  6855. wprintf(g_wszPad4);
  6856. hr = cuDumpFileTime(
  6857. IDS_PENDTIME,
  6858. NULL,
  6859. &pcmcStatus->pPendInfo->PendTime);
  6860. _JumpIfError(hr, error, "cuDumpFileTime");
  6861. break;
  6862. }
  6863. hr = S_OK;
  6864. error:
  6865. return(hr);
  6866. }
  6867. HRESULT
  6868. DumpCMCRegInfo(
  6869. IN BYTE const *pbData,
  6870. IN DWORD cbData)
  6871. {
  6872. HRESULT hr;
  6873. WCHAR *pwszDup = NULL;
  6874. WCHAR *pwszBuf;
  6875. WCHAR const *pwszName;
  6876. WCHAR const *pwszValue;
  6877. WCHAR *pwszNameAlloc = NULL;
  6878. WCHAR *pwszValueAlloc = NULL;
  6879. if (NULL == pbData || 0 == cbData)
  6880. {
  6881. hr = S_OK;
  6882. goto error; // silently ignore empty string
  6883. }
  6884. hr = myDecodeCMCRegInfo(pbData, cbData, &pwszDup);
  6885. _JumpIfError(hr, error, "myDecodeCMCRegInfo");
  6886. if (NULL != pwszDup)
  6887. {
  6888. pwszBuf = pwszDup;
  6889. while (TRUE)
  6890. {
  6891. hr = myParseNextAttribute(&pwszBuf, TRUE, &pwszName, &pwszValue);
  6892. if (S_FALSE == hr)
  6893. {
  6894. break;
  6895. }
  6896. _JumpIfError(hr, error, "myParseNextAttribute");
  6897. if (NULL != pwszNameAlloc)
  6898. {
  6899. LocalFree(pwszNameAlloc);
  6900. pwszNameAlloc = NULL;
  6901. }
  6902. if (NULL != pwszValueAlloc)
  6903. {
  6904. LocalFree(pwszValueAlloc);
  6905. pwszValueAlloc = NULL;
  6906. }
  6907. hr = myUncanonicalizeURLParm(pwszName, &pwszNameAlloc);
  6908. _JumpIfError(hr, error, "myUncanonicalizeURLParm");
  6909. hr = myUncanonicalizeURLParm(pwszValue, &pwszValueAlloc);
  6910. _JumpIfError(hr, error, "myUncanonicalizeURLParm");
  6911. wprintf(L"%ws%ws: %ws\n", g_wszPad4, pwszNameAlloc, pwszValueAlloc);
  6912. }
  6913. }
  6914. hr = S_OK;
  6915. error:
  6916. if (NULL != pwszNameAlloc)
  6917. {
  6918. LocalFree(pwszNameAlloc);
  6919. }
  6920. if (NULL != pwszValueAlloc)
  6921. {
  6922. LocalFree(pwszValueAlloc);
  6923. }
  6924. if (NULL != pwszDup)
  6925. {
  6926. LocalFree(pwszDup);
  6927. }
  6928. return(hr);
  6929. }
  6930. HRESULT
  6931. DumpTaggedAttributes(
  6932. IN DWORD cTaggedAttribute,
  6933. IN CMC_TAGGED_ATTRIBUTE const *rgTaggedAttribute)
  6934. {
  6935. HRESULT hr;
  6936. DWORD i;
  6937. DWORD cb;
  6938. CMC_ADD_EXTENSIONS_INFO *pcmcExt = NULL;
  6939. CMC_ADD_ATTRIBUTES_INFO *pcmcAttrib = NULL;
  6940. CMC_STATUS_INFO *pcmcStatus = NULL;
  6941. wprintf(myLoadResourceString(IDS_TAGGED_ATTRIBUTES)); //"Tagged Attributes:"
  6942. wprintf(L" %u\n", cTaggedAttribute);
  6943. wprintf(wszNewLine);
  6944. for (i = 0; i < cTaggedAttribute; i++)
  6945. {
  6946. CMC_TAGGED_ATTRIBUTE const *pTaggedAttribute = &rgTaggedAttribute[i];
  6947. CRYPT_ATTRIBUTE const *pAttribute = &pTaggedAttribute->Attribute;
  6948. DWORD j;
  6949. wprintf(g_wszPad2);
  6950. wprintf(myLoadResourceString(IDS_BODY_PART_ID)); // "Body Part Id:"
  6951. wprintf(L" %u\n", pTaggedAttribute->dwBodyPartID);
  6952. wprintf(g_wszPad2);
  6953. cuDumpOIDAndDescriptionA(pAttribute->pszObjId);
  6954. wprintf(wszNewLine);
  6955. for (j = 0; j < pAttribute->cValue; j++)
  6956. {
  6957. BOOL fUnknown = FALSE;
  6958. wprintf(L" %ws[%u]:\n", myLoadResourceString(IDS_VALUE), j);
  6959. if (0 == strcmp(szOID_CMC_ADD_EXTENSIONS, pAttribute->pszObjId))
  6960. {
  6961. // Decode CMC_ADD_EXTENSIONS_INFO from Attribute Blob
  6962. CSASSERT(NULL == pcmcExt);
  6963. if (!myDecodeObject(
  6964. X509_ASN_ENCODING,
  6965. CMC_ADD_EXTENSIONS,
  6966. pAttribute->rgValue[j].pbData,
  6967. pAttribute->rgValue[j].cbData,
  6968. CERTLIB_USE_LOCALALLOC,
  6969. (VOID **) &pcmcExt,
  6970. &cb))
  6971. {
  6972. hr = myHLastError();
  6973. _JumpError(hr, error, "myDecodeObject");
  6974. }
  6975. DumpCMCDataReference(
  6976. pcmcExt->dwCmcDataReference,
  6977. pcmcExt->cCertReference,
  6978. pcmcExt->rgdwCertReference);
  6979. wprintf(g_wszPad2);
  6980. hr = cuDumpExtensionArray(
  6981. IDS_EXTENSIONS,
  6982. pcmcExt->cExtension,
  6983. pcmcExt->rgExtension);
  6984. _JumpIfError(hr, error, "cuDumpExtensionArray");
  6985. LocalFree(pcmcExt);
  6986. pcmcExt = NULL;
  6987. }
  6988. else
  6989. if (0 == strcmp(szOID_CMC_ADD_ATTRIBUTES, pAttribute->pszObjId))
  6990. {
  6991. // Decode CMC_ADD_ATTRIBUTES_INFO from Attribute Blob
  6992. CSASSERT(NULL == pcmcAttrib);
  6993. if (!myDecodeObject(
  6994. X509_ASN_ENCODING,
  6995. CMC_ADD_ATTRIBUTES,
  6996. pAttribute->rgValue[j].pbData,
  6997. pAttribute->rgValue[j].cbData,
  6998. CERTLIB_USE_LOCALALLOC,
  6999. (VOID **) &pcmcAttrib,
  7000. &cb))
  7001. {
  7002. hr = myHLastError();
  7003. _JumpError(hr, error, "myDecodeObject");
  7004. }
  7005. DumpCMCDataReference(
  7006. pcmcAttrib->dwCmcDataReference,
  7007. pcmcAttrib->cCertReference,
  7008. pcmcAttrib->rgdwCertReference);
  7009. hr = DumpAttributes(
  7010. pcmcAttrib->rgAttribute,
  7011. pcmcAttrib->cAttribute,
  7012. FALSE,
  7013. FOT_ATTRIBUTE,
  7014. NULL, // hStore
  7015. NULL,
  7016. NULL,
  7017. NULL);
  7018. _JumpIfError(hr, error, "DumpAttributes");
  7019. wprintf(wszNewLine);
  7020. LocalFree(pcmcAttrib);
  7021. pcmcAttrib = NULL;
  7022. }
  7023. else
  7024. if (0 == strcmp(szOID_CMC_STATUS_INFO, pAttribute->pszObjId))
  7025. {
  7026. // Decode CMC_STATUS_INFO from Attribute Blob
  7027. CSASSERT(NULL == pcmcStatus);
  7028. if (!myDecodeObject(
  7029. X509_ASN_ENCODING,
  7030. CMC_STATUS,
  7031. pAttribute->rgValue[j].pbData,
  7032. pAttribute->rgValue[j].cbData,
  7033. CERTLIB_USE_LOCALALLOC,
  7034. (VOID **) &pcmcStatus,
  7035. &cb))
  7036. {
  7037. hr = myHLastError();
  7038. _JumpError(hr, error, "myDecodeObject");
  7039. }
  7040. hr = DumpCMCStatus(pcmcStatus);
  7041. _JumpIfError(hr, error, "DumpStatus");
  7042. wprintf(wszNewLine);
  7043. LocalFree(pcmcStatus);
  7044. pcmcStatus = NULL;
  7045. }
  7046. else
  7047. if (0 == strcmp(szOID_CMC_TRANSACTION_ID, pAttribute->pszObjId))
  7048. {
  7049. DWORD XactId;
  7050. cb = sizeof(XactId);
  7051. XactId = 0;
  7052. if (CryptDecodeObject(
  7053. X509_ASN_ENCODING,
  7054. X509_INTEGER,
  7055. pAttribute->rgValue[j].pbData,
  7056. pAttribute->rgValue[j].cbData,
  7057. 0,
  7058. &XactId,
  7059. &cb))
  7060. {
  7061. wprintf(
  7062. L"%ws%x(%u)\n\n",
  7063. g_wszPad4,
  7064. XactId,
  7065. XactId);
  7066. }
  7067. else
  7068. {
  7069. fUnknown = TRUE;
  7070. }
  7071. }
  7072. else
  7073. if (0 == strcmp(szOID_CMC_REG_INFO, pAttribute->pszObjId))
  7074. {
  7075. hr = DumpCMCRegInfo(
  7076. pAttribute->rgValue[j].pbData,
  7077. pAttribute->rgValue[j].cbData);
  7078. if (S_OK != hr)
  7079. {
  7080. fUnknown = TRUE;
  7081. }
  7082. }
  7083. else
  7084. if (0 == strcmp(szOID_CMC_QUERY_PENDING, pAttribute->pszObjId) ||
  7085. 0 == strcmp(szOID_CMC_SENDER_NONCE, pAttribute->pszObjId) ||
  7086. 0 == strcmp(szOID_CMC_RECIPIENT_NONCE, pAttribute->pszObjId))
  7087. {
  7088. CRYPT_DATA_BLOB *pBlob;
  7089. DWORD cbBlob;
  7090. if (myDecodeObject(
  7091. X509_ASN_ENCODING,
  7092. X509_OCTET_STRING,
  7093. pAttribute->rgValue[j].pbData,
  7094. pAttribute->rgValue[j].cbData,
  7095. CERTLIB_USE_LOCALALLOC,
  7096. (VOID **) &pBlob,
  7097. &cbBlob))
  7098. {
  7099. DumpHex(
  7100. DH_NOTABPREFIX | 4,
  7101. pBlob->pbData,
  7102. pBlob->cbData);
  7103. wprintf(wszNewLine);
  7104. LocalFree(pBlob);
  7105. }
  7106. else
  7107. {
  7108. fUnknown = TRUE;
  7109. }
  7110. }
  7111. else
  7112. {
  7113. fUnknown = TRUE;
  7114. }
  7115. if (fUnknown)
  7116. {
  7117. wprintf(myLoadResourceString(IDS_UNKNOWN_TAGGED_ATTRIBUTE)); // "UNKNOWN Tagged Attribute"
  7118. wprintf(wszNewLine);
  7119. DumpHex(
  7120. DH_NOTABPREFIX | 4,
  7121. pAttribute->rgValue[j].pbData,
  7122. pAttribute->rgValue[j].cbData);
  7123. wprintf(wszNewLine);
  7124. }
  7125. }
  7126. }
  7127. if (0 < i)
  7128. {
  7129. wprintf(wszNewLine);
  7130. }
  7131. hr = S_OK;
  7132. error:
  7133. if (NULL != pcmcExt)
  7134. {
  7135. LocalFree(pcmcExt);
  7136. }
  7137. if (NULL != pcmcAttrib)
  7138. {
  7139. LocalFree(pcmcAttrib);
  7140. }
  7141. if (NULL != pcmcStatus)
  7142. {
  7143. LocalFree(pcmcStatus);
  7144. }
  7145. return(hr);
  7146. }
  7147. HRESULT
  7148. DumpTaggedRequests(
  7149. IN DWORD cTaggedRequest,
  7150. IN CMC_TAGGED_REQUEST const *rgTaggedRequest)
  7151. {
  7152. HRESULT hr;
  7153. DWORD i;
  7154. wprintf(myLoadResourceString(IDS_TAGGED_REQUESTS)); // "Tagged Requests:"
  7155. wprintf(L" %u\n", cTaggedRequest);
  7156. for (i = 0; i < cTaggedRequest; i++)
  7157. {
  7158. CMC_TAGGED_REQUEST const *pTaggedRequest = &rgTaggedRequest[i];
  7159. CMC_TAGGED_CERT_REQUEST const *pTaggedCertRequest;
  7160. switch (pTaggedRequest->dwTaggedRequestChoice)
  7161. {
  7162. case CMC_TAGGED_CERT_REQUEST_CHOICE:
  7163. pTaggedCertRequest = pTaggedRequest->pTaggedCertRequest;
  7164. wprintf(L" CMC_TAGGED_CERT_REQUEST_CHOICE:\n");
  7165. wprintf(g_wszPad2);
  7166. wprintf(myLoadResourceString(IDS_BODY_PART_ID)); // "Body Part Id:"
  7167. wprintf(L" %u\n", pTaggedCertRequest->dwBodyPartID);
  7168. hr = cuDumpAsnBinary(
  7169. pTaggedCertRequest->SignedCertRequest.pbData,
  7170. pTaggedCertRequest->SignedCertRequest.cbData,
  7171. i);
  7172. _JumpIfError(hr, error, "cuDumpAsnBinary");
  7173. break;
  7174. default:
  7175. wprintf(myLoadResourceString(IDS_UNKNOWN_REQUEST_CHOICE)); // "UNKNOWN Request Choice"
  7176. wprintf(wszNewLine);
  7177. break;
  7178. }
  7179. }
  7180. if (0 < i)
  7181. {
  7182. wprintf(wszNewLine);
  7183. }
  7184. hr = S_OK;
  7185. error:
  7186. return(hr);
  7187. }
  7188. HRESULT
  7189. DumpTaggedContent(
  7190. IN DWORD cTaggedContentInfo,
  7191. IN CMC_TAGGED_CONTENT_INFO const *rgTaggedContentInfo)
  7192. {
  7193. HRESULT hr;
  7194. DWORD i;
  7195. wprintf(myLoadResourceString(IDS_TAGGED_CONTENTINFO)); // "Tagged Content Info:"
  7196. wprintf(L" %u\n", cTaggedContentInfo);
  7197. for (i = 0; i < cTaggedContentInfo; i++)
  7198. {
  7199. CMC_TAGGED_CONTENT_INFO const *pTaggedContentInfo = &rgTaggedContentInfo[i];
  7200. wprintf(g_wszPad2);
  7201. wprintf(myLoadResourceString(IDS_BODY_PART_ID)); // "Body Part Id:"
  7202. wprintf(L" %u\n", pTaggedContentInfo->dwBodyPartID);
  7203. hr = cuDumpAsnBinary(
  7204. pTaggedContentInfo->EncodedContentInfo.pbData,
  7205. pTaggedContentInfo->EncodedContentInfo.cbData,
  7206. i);
  7207. _JumpIfError(hr, error, "cuDumpAsnBinary");
  7208. }
  7209. if (0 < i)
  7210. {
  7211. wprintf(wszNewLine);
  7212. }
  7213. hr = S_OK;
  7214. error:
  7215. return(hr);
  7216. }
  7217. HRESULT
  7218. DumpTaggedOther(
  7219. IN DWORD cTaggedOtherMsg,
  7220. IN CMC_TAGGED_OTHER_MSG const *rgTaggedOtherMsg)
  7221. {
  7222. HRESULT hr;
  7223. DWORD i;
  7224. wprintf(myLoadResourceString(IDS_TAGGED_OTHERMESSAGES)); // "Tagged Other Messages:"
  7225. wprintf(L" %u\n", cTaggedOtherMsg);
  7226. for (i = 0; i < cTaggedOtherMsg; i++)
  7227. {
  7228. CMC_TAGGED_OTHER_MSG const *pTaggedOtherMsg = &rgTaggedOtherMsg[i];
  7229. wprintf(L" TaggedOtherMessage[%u]\n", i);
  7230. wprintf(g_wszPad2);
  7231. cuDumpOIDAndDescriptionA(pTaggedOtherMsg->pszObjId);
  7232. wprintf(L" %ws[%u]:\n", myLoadResourceString(IDS_VALUE), i);
  7233. DumpHex(
  7234. DH_NOADDRESS | DH_NOTABPREFIX | 4,
  7235. pTaggedOtherMsg->Value.pbData,
  7236. pTaggedOtherMsg->Value.cbData);
  7237. }
  7238. if (0 < i)
  7239. {
  7240. wprintf(wszNewLine);
  7241. }
  7242. hr = S_OK;
  7243. //error:
  7244. return(hr);
  7245. }
  7246. HRESULT
  7247. dumpCMCRequest(
  7248. IN DWORD idMessage,
  7249. IN BYTE const *pbIn,
  7250. IN DWORD cbIn,
  7251. IN BYTE const *pbDecoded,
  7252. IN DWORD cbDecoded,
  7253. IN CERT_SIGNED_CONTENT_INFO const *pcsci)
  7254. {
  7255. HRESULT hr;
  7256. CMC_DATA_INFO const *pcmcData;
  7257. CSASSERT(NULL != pbIn && 0 != cbIn);
  7258. CSASSERT(NULL != pbDecoded && 0 != cbDecoded);
  7259. wprintf(myLoadResourceString(idMessage));
  7260. wprintf(wszNewLine);
  7261. pcmcData = (CMC_DATA_INFO const *) pbDecoded;
  7262. hr = DumpTaggedAttributes(
  7263. pcmcData->cTaggedAttribute,
  7264. pcmcData->rgTaggedAttribute);
  7265. _JumpIfError(hr, error, "DumpTaggedAttributes");
  7266. hr = DumpTaggedRequests(
  7267. pcmcData->cTaggedRequest,
  7268. pcmcData->rgTaggedRequest);
  7269. _JumpIfError(hr, error, "DumpTaggedRequests");
  7270. hr = DumpTaggedContent(
  7271. pcmcData->cTaggedContentInfo,
  7272. pcmcData->rgTaggedContentInfo);
  7273. _JumpIfError(hr, error, "DumpTaggedContent");
  7274. hr = DumpTaggedOther(
  7275. pcmcData->cTaggedOtherMsg,
  7276. pcmcData->rgTaggedOtherMsg);
  7277. _JumpIfError(hr, error, "DumpTaggedOther");
  7278. error:
  7279. return(hr);
  7280. }
  7281. HRESULT
  7282. dumpCMCResponse(
  7283. IN DWORD idMessage,
  7284. IN BYTE const *pbIn,
  7285. IN DWORD cbIn,
  7286. IN BYTE const *pbDecoded,
  7287. IN DWORD cbDecoded,
  7288. IN CERT_SIGNED_CONTENT_INFO const *pcsci)
  7289. {
  7290. HRESULT hr;
  7291. CMC_RESPONSE_INFO const *pcmcResponse;
  7292. CSASSERT(NULL != pbIn && 0 != cbIn);
  7293. CSASSERT(NULL != pbDecoded && 0 != cbDecoded);
  7294. wprintf(myLoadResourceString(idMessage));
  7295. wprintf(wszNewLine);
  7296. pcmcResponse = (CMC_RESPONSE_INFO const *) pbDecoded;
  7297. hr = DumpTaggedAttributes(
  7298. pcmcResponse->cTaggedAttribute,
  7299. pcmcResponse->rgTaggedAttribute);
  7300. _JumpIfError(hr, error, "DumpTaggedAttributes");
  7301. hr = DumpTaggedContent(
  7302. pcmcResponse->cTaggedContentInfo,
  7303. pcmcResponse->rgTaggedContentInfo);
  7304. _JumpIfError(hr, error, "DumpTaggedContent");
  7305. hr = DumpTaggedOther(
  7306. pcmcResponse->cTaggedOtherMsg,
  7307. pcmcResponse->rgTaggedOtherMsg);
  7308. _JumpIfError(hr, error, "DumpTaggedOther");
  7309. error:
  7310. return(hr);
  7311. }
  7312. HRESULT
  7313. dumpKeyGenRequest(
  7314. IN DWORD idMessage,
  7315. IN BYTE const *pbIn,
  7316. IN DWORD cbIn,
  7317. IN BYTE const *pbDecoded,
  7318. IN DWORD cbDecoded,
  7319. IN CERT_SIGNED_CONTENT_INFO const *pcsci)
  7320. {
  7321. HRESULT hr;
  7322. CERT_KEYGEN_REQUEST_INFO const *pKeyGenRequest;
  7323. CSASSERT(NULL != pbIn && 0 != cbIn);
  7324. CSASSERT(NULL != pbDecoded && 0 != cbDecoded);
  7325. wprintf(myLoadResourceString(idMessage));
  7326. wprintf(wszNewLine);
  7327. pKeyGenRequest = (CERT_KEYGEN_REQUEST_INFO const *) pbDecoded;
  7328. cuDumpPublicKey(&pKeyGenRequest->SubjectPublicKeyInfo);
  7329. wprintf(
  7330. myLoadResourceString(IDS_FORMAT_CHALLENGE_STRING), // "ChallengeString: ""%ws"""
  7331. pKeyGenRequest->pwszChallengeString);
  7332. wprintf(wszNewLine);
  7333. cuDumpSignature(pcsci);
  7334. hr = cuVerifySignature(
  7335. pbIn,
  7336. cbIn,
  7337. &pKeyGenRequest->SubjectPublicKeyInfo,
  7338. FALSE,
  7339. FALSE);
  7340. _JumpIfError(hr, error, "cuVerifySignature");
  7341. hr = S_OK;
  7342. error:
  7343. return(hr);
  7344. }
  7345. HRESULT
  7346. dumpCTL(
  7347. IN DWORD idMessage,
  7348. IN BYTE const *pbIn,
  7349. IN DWORD cbIn,
  7350. IN BYTE const *pbDecoded,
  7351. IN DWORD cbDecoded,
  7352. IN CERT_SIGNED_CONTENT_INFO const *pcsci)
  7353. {
  7354. HRESULT hr;
  7355. CTL_INFO const *pCTLInfo;
  7356. CTL_CONTEXT const *pCTLContext = NULL;
  7357. BOOL fIssuerMatches;
  7358. DWORD id;
  7359. DWORD i;
  7360. pCTLInfo = (CTL_INFO const *) pbDecoded;
  7361. //if (!g_fQuiet)
  7362. {
  7363. wprintf(myLoadResourceString(idMessage));
  7364. wprintf(wszNewLine);
  7365. cuDumpVersion(pCTLInfo->dwVersion + 1);
  7366. }
  7367. hr = cuDumpUsage(NULL, IDS_USAGEENTRIES, &pCTLInfo->SubjectUsage);
  7368. _JumpIfError(hr, error, "cuDumpUsage");
  7369. if (0 != pCTLInfo->ListIdentifier.cbData)
  7370. {
  7371. hr = cuDumpSerial(NULL, IDS_LISTID, &pCTLInfo->ListIdentifier);
  7372. _JumpIfError(hr, error, "cuDumpSerial");
  7373. }
  7374. if (0 != pCTLInfo->SequenceNumber.cbData)
  7375. {
  7376. hr = cuDumpSerial(NULL, IDS_SEQUENCENO, &pCTLInfo->SequenceNumber);
  7377. _JumpIfError(hr, error, "cuDumpSerial");
  7378. }
  7379. hr = cuDumpFileTime(IDS_THISUPDATE, NULL, &pCTLInfo->ThisUpdate);
  7380. _JumpIfError(hr, error, "cuDumpFileTime");
  7381. hr = cuDumpFileTime(IDS_NEXTUPDATE, NULL, &pCTLInfo->NextUpdate);
  7382. _JumpIfError(hr, error, "cuDumpFileTime");
  7383. cuDumpAlgorithm(IDS_SUBJECT_ALGORITHM, &pCTLInfo->SubjectAlgorithm);
  7384. wprintf(myLoadResourceString(IDS_CTLENTRIES)); // "CTL Entries:"
  7385. wprintf(L" %u\n", pCTLInfo->cCTLEntry);
  7386. for (i = 0; i < pCTLInfo->cCTLEntry; i++)
  7387. {
  7388. CTL_ENTRY const *pCTLEntry = &pCTLInfo->rgCTLEntry[i];
  7389. wprintf(wszNewLine);
  7390. hr = DumpHash(
  7391. g_wszEmpty,
  7392. IDS_FORMAT_SUBJECTID_COLON,
  7393. NULL,
  7394. g_wszEmpty,
  7395. pCTLEntry->SubjectIdentifier.pbData,
  7396. pCTLEntry->SubjectIdentifier.cbData);
  7397. _JumpIfError(hr, error, "DumpHash");
  7398. hr = DumpAttributes(
  7399. pCTLEntry->rgAttribute,
  7400. pCTLEntry->cAttribute,
  7401. g_fQuiet,
  7402. FOT_ATTRIBUTE,
  7403. NULL, // hStore
  7404. NULL, // pbHashUserCert
  7405. NULL, // pcbHashUserCert
  7406. NULL); // ppExtInfo
  7407. _JumpIfError(hr, error, "DumpAttributes");
  7408. }
  7409. hr = cuDumpExtensionArray(
  7410. IDS_EXTENSIONS,
  7411. pCTLInfo->cExtension,
  7412. pCTLInfo->rgExtension);
  7413. _JumpIfError(hr, error, "cuDumpExtensionArray");
  7414. hr = S_OK;
  7415. error:
  7416. if (NULL != pCTLContext)
  7417. {
  7418. CertFreeCTLContext(pCTLContext);
  7419. }
  7420. return(hr);
  7421. }
  7422. HRESULT
  7423. verbDump(
  7424. IN WCHAR const *pwszOption,
  7425. IN WCHAR const *pwszfn,
  7426. IN WCHAR const *pwszArg2,
  7427. IN WCHAR const *pwszArg3,
  7428. IN WCHAR const *pwszArg4)
  7429. {
  7430. HRESULT hr;
  7431. if (NULL == pwszfn)
  7432. {
  7433. hr = cuConfigDump();
  7434. _JumpIfError(hr, error, "cuConfigDump");
  7435. }
  7436. else
  7437. {
  7438. hr = cuFileDump(pwszfn);
  7439. _JumpIfErrorStr(hr, error, "cuFileDump", pwszfn);
  7440. }
  7441. error:
  7442. return(hr);
  7443. }