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.

4530 lines
147 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1996
  6. //
  7. // File: certtest.cpp
  8. //
  9. // Contents: Certificate Test Helper APIs
  10. //
  11. // History: 11-Apr-96 philh created
  12. // 31-May-96 helles Removed check for a particular error code,
  13. // NTE_PROV_TYPE_NOT_DEF, since this can get
  14. // overwritten due to known problem with
  15. // the msvcr40d.dll on Win95.
  16. // 20-Aug-96 jeffspel name changes
  17. //--------------------------------------------------------------------------
  18. #include <windows.h>
  19. #include <winldap.h>
  20. #include <assert.h>
  21. #include "certtest.h"
  22. #include "cryptuiapi.h"
  23. #include "spc.h"
  24. #include "setcert.h"
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <memory.h>
  29. #include <time.h>
  30. #include <stddef.h>
  31. DWORD dwCertEncodingType = X509_ASN_ENCODING;
  32. DWORD dwMsgEncodingType = PKCS_7_ASN_ENCODING;
  33. DWORD dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
  34. #define NULL_ASN_TAG 0x05
  35. //+-------------------------------------------------------------------------
  36. // Error output routines
  37. //--------------------------------------------------------------------------
  38. void PrintError(LPCSTR pszMsg)
  39. {
  40. printf("%s\n", pszMsg);
  41. }
  42. void PrintLastError(LPCSTR pszMsg)
  43. {
  44. DWORD dwErr = GetLastError();
  45. printf("%s failed => 0x%x (%d) \n", pszMsg, dwErr, dwErr);
  46. }
  47. LPCSTR FileTimeText(FILETIME *pft)
  48. {
  49. static char buf[80];
  50. FILETIME ftLocal;
  51. struct tm ctm;
  52. SYSTEMTIME st;
  53. FileTimeToLocalFileTime(pft, &ftLocal);
  54. if (FileTimeToSystemTime(&ftLocal, &st))
  55. {
  56. ctm.tm_sec = st.wSecond;
  57. ctm.tm_min = st.wMinute;
  58. ctm.tm_hour = st.wHour;
  59. ctm.tm_mday = st.wDay;
  60. ctm.tm_mon = st.wMonth-1;
  61. ctm.tm_year = st.wYear-1900;
  62. ctm.tm_wday = st.wDayOfWeek;
  63. ctm.tm_yday = 0;
  64. ctm.tm_isdst = 0;
  65. strcpy(buf, asctime(&ctm));
  66. buf[strlen(buf)-1] = 0;
  67. if (st.wMilliseconds) {
  68. char *pch = buf + strlen(buf);
  69. sprintf(pch, " <milliseconds:: %03d>", st.wMilliseconds);
  70. }
  71. }
  72. else
  73. sprintf(buf, "<FILETIME %08lX:%08lX>", pft->dwHighDateTime,
  74. pft->dwLowDateTime);
  75. return buf;
  76. }
  77. #define CROW 16
  78. void PrintBytes(LPCSTR pszHdr, BYTE *pb, DWORD cbSize)
  79. {
  80. ULONG cb, i;
  81. if (cbSize == 0) {
  82. printf("%s NO Value Bytes\n", pszHdr);
  83. return;
  84. }
  85. while (cbSize > 0)
  86. {
  87. printf("%s", pszHdr);
  88. cb = min(CROW, cbSize);
  89. cbSize -= cb;
  90. for (i = 0; i<cb; i++)
  91. printf(" %02X", pb[i]);
  92. for (i = cb; i<CROW; i++)
  93. printf(" ");
  94. printf(" '");
  95. for (i = 0; i<cb; i++)
  96. if (pb[i] >= 0x20 && pb[i] <= 0x7f)
  97. printf("%c", pb[i]);
  98. else
  99. printf(".");
  100. pb += cb;
  101. printf("'\n");
  102. }
  103. }
  104. //+-------------------------------------------------------------------------
  105. // Test allocation and free routines
  106. //--------------------------------------------------------------------------
  107. LPVOID
  108. WINAPI
  109. TestAlloc(
  110. IN size_t cbBytes
  111. )
  112. {
  113. LPVOID pv;
  114. pv = malloc(cbBytes);
  115. if (pv == NULL) {
  116. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  117. PrintLastError("TestAlloc");
  118. }
  119. return pv;
  120. }
  121. LPVOID
  122. WINAPI
  123. TestRealloc(
  124. IN LPVOID pvOrg,
  125. IN size_t cbBytes
  126. )
  127. {
  128. LPVOID pv;
  129. if (NULL == (pv = pvOrg ? realloc(pvOrg, cbBytes) : malloc(cbBytes))) {
  130. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  131. PrintLastError("TestAlloc");
  132. }
  133. return pv;
  134. }
  135. VOID
  136. WINAPI
  137. TestFree(
  138. IN LPVOID pv
  139. )
  140. {
  141. if (pv)
  142. free(pv);
  143. }
  144. //+-------------------------------------------------------------------------
  145. // Allocate and convert a multi-byte string to a wide string
  146. //--------------------------------------------------------------------------
  147. LPWSTR AllocAndSzToWsz(LPCSTR psz)
  148. {
  149. size_t cb;
  150. LPWSTR pwsz = NULL;
  151. if (-1 == (cb = mbstowcs( NULL, psz, strlen(psz))))
  152. goto bad_param;
  153. cb += 1; // terminating NULL
  154. if (NULL == (pwsz = (LPWSTR)TestAlloc( cb * sizeof(WCHAR)))) {
  155. PrintLastError("AllocAndSzToWsz");
  156. goto failed;
  157. }
  158. if (-1 == mbstowcs( pwsz, psz, cb))
  159. goto bad_param;
  160. goto common_return;
  161. bad_param:
  162. PrintError("Bad AllocAndSzToWsz");
  163. failed:
  164. if (pwsz) {
  165. TestFree(pwsz);
  166. pwsz = NULL;
  167. }
  168. common_return:
  169. return pwsz;
  170. }
  171. static CRYPT_DECODE_PARA TestDecodePara = {
  172. offsetof(CRYPT_DECODE_PARA, pfnFree) + sizeof(TestDecodePara.pfnFree),
  173. TestAlloc,
  174. TestFree
  175. };
  176. static void *TestNoCopyDecodeObject(
  177. IN LPCSTR lpszStructType,
  178. IN const BYTE *pbEncoded,
  179. IN DWORD cbEncoded,
  180. OUT DWORD *pcbStructInfo = NULL
  181. )
  182. {
  183. DWORD cbStructInfo;
  184. void *pvStructInfo;
  185. if (!CryptDecodeObjectEx(
  186. dwCertEncodingType,
  187. lpszStructType,
  188. pbEncoded,
  189. cbEncoded,
  190. CRYPT_DECODE_NOCOPY_FLAG | CRYPT_DECODE_ALLOC_FLAG,
  191. &TestDecodePara,
  192. (void *) &pvStructInfo,
  193. &cbStructInfo
  194. ))
  195. goto ErrorReturn;
  196. CommonReturn:
  197. if (pcbStructInfo)
  198. *pcbStructInfo = cbStructInfo;
  199. return pvStructInfo;
  200. ErrorReturn:
  201. if ((DWORD_PTR) lpszStructType <= 0xFFFF)
  202. printf("CryptDecodeObject(StructType: %d)",
  203. (DWORD)(DWORD_PTR) lpszStructType);
  204. else
  205. printf("CryptDecodeObject(StructType: %s)",
  206. lpszStructType);
  207. PrintLastError("");
  208. pvStructInfo = NULL;
  209. goto CommonReturn;
  210. }
  211. //+-------------------------------------------------------------------------
  212. // Allocate and read an encoded DER blob from a file
  213. //--------------------------------------------------------------------------
  214. BOOL ReadDERFromFile(
  215. LPCSTR pszFileName,
  216. PBYTE *ppbDER,
  217. PDWORD pcbDER
  218. )
  219. {
  220. BOOL fRet;
  221. HANDLE hFile = 0;
  222. PBYTE pbDER = NULL;
  223. DWORD cbDER;
  224. DWORD cbRead;
  225. if( INVALID_HANDLE_VALUE == (hFile = CreateFile( pszFileName, GENERIC_READ,
  226. FILE_SHARE_READ | FILE_SHARE_WRITE,
  227. NULL, OPEN_EXISTING, 0, NULL))) {
  228. printf( "can't open %s\n", pszFileName);
  229. goto ErrorReturn;
  230. }
  231. cbDER = GetFileSize( hFile, NULL);
  232. if (cbDER == 0) {
  233. printf( "empty file %s\n", pszFileName);
  234. goto ErrorReturn;
  235. }
  236. if (NULL == (pbDER = (PBYTE)TestAlloc(cbDER))) {
  237. printf( "can't alloc %d bytes\n", cbDER);
  238. goto ErrorReturn;
  239. }
  240. if (!ReadFile( hFile, pbDER, cbDER, &cbRead, NULL) ||
  241. (cbRead != cbDER)) {
  242. printf( "can't read %s\n", pszFileName);
  243. goto ErrorReturn;
  244. }
  245. *ppbDER = pbDER;
  246. *pcbDER = cbDER;
  247. fRet = TRUE;
  248. CommonReturn:
  249. if (hFile)
  250. CloseHandle(hFile);
  251. return fRet;
  252. ErrorReturn:
  253. if (pbDER)
  254. TestFree(pbDER);
  255. *ppbDER = NULL;
  256. *pcbDER = 0;
  257. fRet = FALSE;
  258. goto CommonReturn;
  259. }
  260. //+-------------------------------------------------------------------------
  261. // Write an encoded DER blob to a file
  262. //--------------------------------------------------------------------------
  263. BOOL WriteDERToFile(
  264. LPCSTR pszFileName,
  265. PBYTE pbDER,
  266. DWORD cbDER
  267. )
  268. {
  269. BOOL fResult;
  270. // Write the Encoded Blob to the file
  271. HANDLE hFile;
  272. hFile = CreateFile(pszFileName,
  273. GENERIC_WRITE,
  274. 0, // fdwShareMode
  275. NULL, // lpsa
  276. CREATE_ALWAYS,
  277. 0, // fdwAttrsAndFlags
  278. 0); // TemplateFile
  279. if (INVALID_HANDLE_VALUE == hFile) {
  280. fResult = FALSE;
  281. PrintLastError("WriteDERToFile::CreateFile");
  282. } else {
  283. DWORD dwBytesWritten;
  284. if (!(fResult = WriteFile(
  285. hFile,
  286. pbDER,
  287. cbDER,
  288. &dwBytesWritten,
  289. NULL // lpOverlapped
  290. )))
  291. PrintLastError("WriteDERToFile::WriteFile");
  292. CloseHandle(hFile);
  293. }
  294. return fResult;
  295. }
  296. HCRYPTPROV GetCryptProvEx(BOOL fVerbose)
  297. {
  298. HCRYPTPROV hProv = 0;
  299. BOOL fResult;
  300. DWORD dwCryptProvType = PROV_RSA_FULL;
  301. fResult = CryptAcquireContext(
  302. &hProv,
  303. NULL, // pszContainer
  304. NULL, // pszProvider
  305. dwCryptProvType,
  306. 0 // dwFlags
  307. );
  308. if (fResult) {
  309. if (fVerbose)
  310. printf("Using default sign and xchg keys for provider: %d\n",
  311. dwCryptProvType);
  312. } else {
  313. DWORD dwErr = GetLastError();
  314. if (dwErr == NTE_BAD_KEYSET) {
  315. // Need to create the keys
  316. printf("Generating SIGNATURE and EXCHANGE private keys\n");
  317. hProv = 0;
  318. fResult = CryptAcquireContext(
  319. &hProv,
  320. NULL, // pszContainer
  321. NULL, // pszProvider
  322. dwCryptProvType,
  323. CRYPT_NEWKEYSET
  324. );
  325. if (!fResult || hProv == 0) {
  326. PrintLastError("CryptAcquireContext");
  327. return 0;
  328. }
  329. HCRYPTKEY hKey = 0;
  330. fResult = CryptGenKey(
  331. hProv,
  332. AT_SIGNATURE,
  333. CRYPT_EXPORTABLE,
  334. &hKey
  335. );
  336. if (!fResult || hKey == 0)
  337. PrintLastError("CryptGenKey(AT_SIGNATURE)");
  338. else
  339. CryptDestroyKey(hKey);
  340. hKey = 0;
  341. fResult = CryptGenKey(
  342. hProv,
  343. AT_KEYEXCHANGE,
  344. CRYPT_EXPORTABLE,
  345. &hKey
  346. );
  347. if (!fResult || hKey == 0)
  348. PrintLastError("CryptGenKey(AT_KEYEXCHANGE)");
  349. else
  350. CryptDestroyKey(hKey);
  351. } else {
  352. PrintLastError("CryptAcquireContext");
  353. return 0;
  354. }
  355. }
  356. return hProv;
  357. }
  358. HCRYPTPROV GetCryptProv() {
  359. return GetCryptProvEx(TRUE);
  360. }
  361. static HKEY OpenRelocateKey(
  362. IN OUT LPCSTR *ppszStoreFilename,
  363. IN DWORD dwFlags
  364. )
  365. {
  366. LPCSTR pszStoreFilename = *ppszStoreFilename;
  367. HKEY hKeyRelocate;
  368. char szRelocate[256];
  369. LPCSTR pszRelocate;
  370. int i = 0;
  371. HKEY hKeyBase;
  372. LONG err;
  373. // Use the following characters until the terminating ":" as the
  374. // relocation path
  375. while ('\0' != *pszStoreFilename && ':' != *pszStoreFilename) {
  376. if (i >= sizeof(szRelocate) - 1)
  377. break;
  378. szRelocate[i++] = *pszStoreFilename++;
  379. }
  380. if (':' == *pszStoreFilename)
  381. pszStoreFilename++;
  382. szRelocate[i] = '\0';
  383. *ppszStoreFilename = pszStoreFilename;
  384. if (0 == _stricmp(szRelocate, "NULL")) {
  385. return NULL;
  386. } else if (0 == _strnicmp(szRelocate, "HKCU", 4)) {
  387. hKeyRelocate = HKEY_CURRENT_USER;
  388. pszRelocate = szRelocate+4;
  389. if ('\\' == *pszRelocate)
  390. pszRelocate++;
  391. } else if (0 == _strnicmp(szRelocate, "HKLM", 4)) {
  392. hKeyRelocate = HKEY_LOCAL_MACHINE;
  393. pszRelocate = szRelocate+4;
  394. if ('\\' == *pszRelocate)
  395. pszRelocate++;
  396. } else {
  397. hKeyRelocate = HKEY_CURRENT_USER;
  398. pszRelocate = szRelocate;
  399. }
  400. if (dwFlags & (CERT_STORE_READONLY_FLAG | CERT_STORE_OPEN_EXISTING_FLAG)) {
  401. REGSAM samDesired;
  402. if (dwFlags & CERT_STORE_READONLY_FLAG)
  403. samDesired = KEY_READ;
  404. else
  405. samDesired = KEY_ALL_ACCESS;
  406. if (ERROR_SUCCESS != (err = RegOpenKeyExA(
  407. hKeyRelocate,
  408. pszRelocate,
  409. 0, // dwReserved
  410. samDesired,
  411. &hKeyBase))) {
  412. printf("RegOpenKeyExA(%s) failed => %d 0x%x\n",
  413. pszRelocate, err, err);
  414. hKeyBase = NULL;
  415. }
  416. } else {
  417. DWORD dwDisposition;
  418. if (ERROR_SUCCESS != (err = RegCreateKeyExA(
  419. hKeyRelocate,
  420. pszRelocate,
  421. 0, // dwReserved
  422. NULL, // lpClass
  423. REG_OPTION_NON_VOLATILE,
  424. KEY_ALL_ACCESS,
  425. NULL, // lpSecurityAttributes
  426. &hKeyBase,
  427. &dwDisposition))) {
  428. printf("RegCreateKeyExA(%s) failed => %d 0x%x\n",
  429. pszRelocate, err, err);
  430. hKeyBase = NULL;
  431. }
  432. }
  433. return hKeyBase;
  434. }
  435. // LastError can get globbered when doing remote registry access
  436. static void CloseRelocateKey(
  437. IN HKEY hKey
  438. )
  439. {
  440. if (hKey) {
  441. DWORD dwErr = GetLastError();
  442. LONG RegCloseKeyStatus;
  443. RegCloseKeyStatus = RegCloseKey(hKey);
  444. assert(ERROR_SUCCESS == RegCloseKeyStatus);
  445. SetLastError(dwErr);
  446. }
  447. }
  448. typedef PLDAP (LDAPAPI *PFN_LDAP_INIT_W)(
  449. const PWCHAR HostName,
  450. ULONG PortNumber
  451. );
  452. typedef ULONG (LDAPAPI *PFN_LDAP_UNBIND)(
  453. LDAP *ld
  454. );
  455. typedef ULONG (LDAPAPI *PFN_LDAP_CONNECT)(
  456. LDAP *ld,
  457. struct l_timeval *timeout
  458. );
  459. typedef ULONG (LDAPAPI *PFN_LDAP_BIND_SW)(
  460. LDAP *ld,
  461. PWCHAR dn,
  462. PWCHAR cred,
  463. ULONG method
  464. );
  465. static
  466. HCERTSTORE
  467. OpenLdapStore(
  468. IN DWORD dwFlags,
  469. IN OUT LPWSTR pwszLdapUrl
  470. )
  471. {
  472. HCERTSTORE hStore = NULL;
  473. LPWSTR pwszHostName = NULL;
  474. LPWSTR pwszTrailingSlash = NULL;
  475. CERT_LDAP_STORE_OPENED_PARA OpenPara = {NULL, pwszLdapUrl};
  476. HMODULE hDll = NULL;
  477. PFN_LDAP_INIT_W pfn_ldap_initW = NULL;
  478. PFN_LDAP_BIND_SW pfn_ldap_bind_sW = NULL;
  479. PFN_LDAP_UNBIND pfn_ldap_unbind = NULL;
  480. LDAP *ld = NULL;
  481. ULONG ulStatus;
  482. if (0 == _wcsnicmp(L"ldap://", pwszLdapUrl, 7)) {
  483. pwszHostName = pwszLdapUrl + 7;
  484. pwszTrailingSlash = pwszHostName;
  485. while (L'\0' != *pwszTrailingSlash && L'/' != *pwszTrailingSlash)
  486. pwszTrailingSlash++;
  487. if (L'/' == *pwszTrailingSlash && pwszTrailingSlash != pwszHostName) {
  488. *pwszTrailingSlash = L'\0';
  489. } else {
  490. pwszHostName = NULL;
  491. pwszTrailingSlash = NULL;
  492. }
  493. }
  494. if (NULL == (hDll = LoadLibraryA("wldap32.dll"))) {
  495. PrintLastError("LoadLibraryA(wldap32.dll)");
  496. goto CommonReturn;
  497. }
  498. if (NULL == (pfn_ldap_initW =
  499. (PFN_LDAP_INIT_W) GetProcAddress(hDll,
  500. "ldap_initW"))) {
  501. PrintLastError("GetProcAddress(ldap_initW)");
  502. goto CommonReturn;
  503. }
  504. if (NULL == (pfn_ldap_bind_sW =
  505. (PFN_LDAP_BIND_SW) GetProcAddress(hDll,
  506. "ldap_bind_sW"))) {
  507. PrintLastError("GetProcAddress(ldap_bind_sW)");
  508. goto CommonReturn;
  509. }
  510. if (NULL == (pfn_ldap_unbind =
  511. (PFN_LDAP_UNBIND) GetProcAddress(hDll,
  512. "ldap_unbind"))) {
  513. PrintLastError("GetProcAddress(ldap_unbind)");
  514. goto CommonReturn;
  515. }
  516. ld = pfn_ldap_initW(pwszHostName, 0);
  517. if (pwszTrailingSlash)
  518. *pwszTrailingSlash = L'/';
  519. if (NULL == ld) {
  520. PrintError("ldap_initW failed");
  521. goto CommonReturn;
  522. }
  523. OpenPara.pvLdapSessionHandle = ld;
  524. ulStatus = pfn_ldap_bind_sW(ld, NULL, NULL, LDAP_AUTH_SSPI);
  525. if (LDAP_SUCCESS != ulStatus) {
  526. printf("ldap_bind_sW failed ==> 0x%x\n", ulStatus);
  527. goto CommonReturn;
  528. }
  529. if (0 == (dwFlags & CERT_STORE_READONLY_FLAG))
  530. dwFlags |= CERT_LDAP_STORE_UNBIND_FLAG;
  531. hStore = CertOpenStore(
  532. CERT_STORE_PROV_LDAP_W,
  533. dwCertEncodingType | dwMsgEncodingType,
  534. 0, // hCryptProv
  535. dwFlags | CERT_LDAP_STORE_OPENED_FLAG,
  536. (const void *) &OpenPara
  537. );
  538. if (NULL == hStore) {
  539. PrintLastError("CertOpenStore(CERT_LDAP_STORE_OPENED_FLAG)");
  540. if (0 != (dwFlags & CERT_STORE_DELETE_FLAG) && 0 == GetLastError() &&
  541. 0 != (dwFlags & CERT_LDAP_STORE_UNBIND_FLAG))
  542. ld = NULL;
  543. } else if (0 != (dwFlags & CERT_LDAP_STORE_UNBIND_FLAG))
  544. ld = NULL;
  545. CommonReturn:
  546. if (ld)
  547. pfn_ldap_unbind(ld);
  548. if (hDll)
  549. FreeLibrary(hDll);
  550. return hStore;
  551. }
  552. typedef struct _SYSTEM_LOCATION_INFO {
  553. LPCSTR pszPrefix;
  554. DWORD dwStoreLocation;
  555. } SYSTEM_LOCATION_INFO;
  556. static SYSTEM_LOCATION_INFO rgSystemLocationInfo[] = {
  557. "LocalMachine:", CERT_SYSTEM_STORE_LOCAL_MACHINE,
  558. "LM:", CERT_SYSTEM_STORE_LOCAL_MACHINE,
  559. "Services:", CERT_SYSTEM_STORE_SERVICES,
  560. "Users:", CERT_SYSTEM_STORE_USERS,
  561. "CurrentService:", CERT_SYSTEM_STORE_CURRENT_SERVICE,
  562. "CS:", CERT_SYSTEM_STORE_CURRENT_SERVICE,
  563. "CurrentUser:", CERT_SYSTEM_STORE_CURRENT_USER,
  564. "CU:", CERT_SYSTEM_STORE_CURRENT_USER,
  565. "CUGP:", CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY,
  566. "LMGP:", CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY,
  567. "Enterprise:", CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE,
  568. "EP:", CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE
  569. };
  570. #define NUM_SYSTEM_LOCATION (sizeof(rgSystemLocationInfo) / \
  571. sizeof(rgSystemLocationInfo[0]))
  572. // returns NULL if unable to open. Doesn't open memory store.
  573. HCERTSTORE OpenStoreEx2(BOOL fSystemStore, LPCSTR pszStoreFilename,
  574. DWORD dwFlags)
  575. {
  576. HCERTSTORE hStore = NULL;
  577. if (fSystemStore) {
  578. DWORD i;
  579. // Check for special System Location Prefix. If found, strip off,
  580. // set store location and try again
  581. for (i = 0; i < NUM_SYSTEM_LOCATION; i++) {
  582. LPCSTR pszPrefix = rgSystemLocationInfo[i].pszPrefix;
  583. DWORD cchPrefix = strlen(pszPrefix);
  584. if (0 == _strnicmp(pszPrefix, pszStoreFilename, cchPrefix)) {
  585. if (0 == (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
  586. dwFlags |= rgSystemLocationInfo[i].dwStoreLocation;
  587. return OpenStoreEx2(TRUE, pszStoreFilename + cchPrefix,
  588. dwFlags);
  589. }
  590. }
  591. // Check for special "archived:" Prefix. If found, strip off and
  592. // set ENUM_ARCHIVE flag and try again
  593. if (0 == _strnicmp("archived:", pszStoreFilename, 9)) {
  594. dwFlags |= CERT_STORE_ENUM_ARCHIVED_FLAG;
  595. return OpenStoreEx2(TRUE, pszStoreFilename + 9,
  596. dwFlags);
  597. }
  598. // Check for special "reg:", "unprotected:", "phy:", "prov:ProvName:",
  599. // "rel:<RegPath>:", "relreg:<RegPath>:" or "relphy:<RegPath>:" prefix
  600. //
  601. // Where <RegPath> is <string>, HKCU\<string>, HKLM\<string> or
  602. // NULL. <string> defaults to HKCU.
  603. if (0 == _strnicmp("reg:", pszStoreFilename, 4)) {
  604. if (0 == (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
  605. dwFlags |= CERT_SYSTEM_STORE_CURRENT_USER;
  606. hStore = CertOpenStore(
  607. CERT_STORE_PROV_SYSTEM_REGISTRY_A,
  608. dwCertEncodingType | dwMsgEncodingType,
  609. 0, // hCryptProv
  610. dwFlags,
  611. (const void *) (pszStoreFilename + 4)
  612. );
  613. } else if (0 == _strnicmp("unprotected:", pszStoreFilename, 12)) {
  614. if (0 == (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
  615. dwFlags |= CERT_SYSTEM_STORE_CURRENT_USER;
  616. hStore = CertOpenStore(
  617. CERT_STORE_PROV_SYSTEM_REGISTRY_A,
  618. dwCertEncodingType | dwMsgEncodingType,
  619. 0, // hCryptProv
  620. dwFlags | CERT_SYSTEM_STORE_UNPROTECTED_FLAG,
  621. (const void *) (pszStoreFilename + 12)
  622. );
  623. } else if (0 == _strnicmp("phy:", pszStoreFilename, 4)) {
  624. LPWSTR pwszStore;
  625. if (0 == (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
  626. dwFlags |= CERT_SYSTEM_STORE_CURRENT_USER;
  627. if (pwszStore = AllocAndSzToWsz(pszStoreFilename + 4)) {
  628. hStore = CertOpenStore(
  629. CERT_STORE_PROV_PHYSICAL,
  630. dwCertEncodingType | dwMsgEncodingType,
  631. 0, // hCryptProv
  632. dwFlags,
  633. (const void *) pwszStore
  634. );
  635. TestFree(pwszStore);
  636. }
  637. } else if (0 == _strnicmp("prov:", pszStoreFilename, 5)) {
  638. LPWSTR pwszStore;
  639. char ch;
  640. char szStoreProvider[256];
  641. int i = 0;
  642. // Advance past "prov:"
  643. pszStoreFilename += 5;
  644. // Use the following characters until the terminating ":" as the
  645. // store provider
  646. while ('\0' != *pszStoreFilename && ':' != *pszStoreFilename) {
  647. if (i >= sizeof(szStoreProvider) - 1)
  648. break;
  649. szStoreProvider[i++] = *pszStoreFilename++;
  650. }
  651. if (':' == *pszStoreFilename)
  652. pszStoreFilename++;
  653. szStoreProvider[i] = '\0';
  654. if (pwszStore = AllocAndSzToWsz(pszStoreFilename)) {
  655. if (0 == _stricmp("ldap", szStoreProvider) &&
  656. 0 != (dwFlags & CERT_LDAP_STORE_OPENED_FLAG))
  657. hStore = OpenLdapStore(dwFlags, pwszStore);
  658. else
  659. hStore = CertOpenStore(
  660. szStoreProvider,
  661. dwCertEncodingType | dwMsgEncodingType,
  662. 0, // hCryptProv
  663. dwFlags,
  664. (const void *) pwszStore
  665. );
  666. TestFree(pwszStore);
  667. }
  668. } else if (0 == _strnicmp("rel:", pszStoreFilename, 4)) {
  669. CERT_SYSTEM_STORE_RELOCATE_PARA RelocatePara;
  670. pszStoreFilename += 4;
  671. RelocatePara.hKeyBase = OpenRelocateKey(&pszStoreFilename, dwFlags);
  672. RelocatePara.pszSystemStore = pszStoreFilename;
  673. if (0 == (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
  674. dwFlags |= CERT_SYSTEM_STORE_CURRENT_USER;
  675. dwFlags |= CERT_SYSTEM_STORE_RELOCATE_FLAG;
  676. hStore = CertOpenStore(
  677. CERT_STORE_PROV_SYSTEM_A,
  678. dwCertEncodingType | dwMsgEncodingType,
  679. 0, // hCryptProv
  680. dwFlags,
  681. (const void *) &RelocatePara
  682. );
  683. CloseRelocateKey(RelocatePara.hKeyBase);
  684. } else if (0 == _strnicmp("relsys:", pszStoreFilename, 7)) {
  685. CERT_SYSTEM_STORE_RELOCATE_PARA RelocatePara;
  686. pszStoreFilename += 7;
  687. RelocatePara.hKeyBase = OpenRelocateKey(&pszStoreFilename, dwFlags);
  688. RelocatePara.pszSystemStore = pszStoreFilename;
  689. if (0 == (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
  690. dwFlags |= CERT_SYSTEM_STORE_CURRENT_USER;
  691. dwFlags |= CERT_SYSTEM_STORE_RELOCATE_FLAG;
  692. hStore = CertOpenStore(
  693. CERT_STORE_PROV_SYSTEM_REGISTRY_A,
  694. dwCertEncodingType | dwMsgEncodingType,
  695. 0, // hCryptProv
  696. dwFlags,
  697. (const void *) &RelocatePara
  698. );
  699. CloseRelocateKey(RelocatePara.hKeyBase);
  700. } else if (0 == _strnicmp("relphy:", pszStoreFilename, 7)) {
  701. LPWSTR pwszStore;
  702. CERT_SYSTEM_STORE_RELOCATE_PARA RelocatePara;
  703. pszStoreFilename += 7;
  704. RelocatePara.hKeyBase = OpenRelocateKey(&pszStoreFilename, dwFlags);
  705. if (pwszStore = AllocAndSzToWsz(pszStoreFilename)) {
  706. RelocatePara.pwszSystemStore = pwszStore;
  707. if (0 == (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
  708. dwFlags |= CERT_SYSTEM_STORE_CURRENT_USER;
  709. dwFlags |= CERT_SYSTEM_STORE_RELOCATE_FLAG;
  710. hStore = CertOpenStore(
  711. CERT_STORE_PROV_PHYSICAL_W,
  712. dwCertEncodingType | dwMsgEncodingType,
  713. 0, // hCryptProv
  714. dwFlags,
  715. (const void *) &RelocatePara
  716. );
  717. TestFree(pwszStore);
  718. }
  719. CloseRelocateKey(RelocatePara.hKeyBase);
  720. } else if (0 != (dwFlags & ~CERT_STORE_SET_LOCALIZED_NAME_FLAG)) {
  721. if (0 == (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
  722. dwFlags |= CERT_SYSTEM_STORE_CURRENT_USER;
  723. hStore = CertOpenStore(
  724. CERT_STORE_PROV_SYSTEM_A,
  725. dwCertEncodingType | dwMsgEncodingType,
  726. 0, // hCryptProv
  727. dwFlags,
  728. (const void *) pszStoreFilename
  729. );
  730. } else
  731. hStore = CertOpenSystemStore(NULL, pszStoreFilename);
  732. } else
  733. hStore = CertOpenStore(
  734. CERT_STORE_PROV_FILENAME_A,
  735. dwCertEncodingType | dwMsgEncodingType,
  736. 0, // hCryptProv
  737. dwFlags,
  738. (const void *) pszStoreFilename
  739. );
  740. if (dwFlags & CERT_STORE_DELETE_FLAG) {
  741. if (NULL != hStore)
  742. printf(
  743. "failed => CERT_STORE_DELETE_FLAG returned non-NULL hStore\n");
  744. else {
  745. if (0 == GetLastError())
  746. printf("Successful delete store\n");
  747. else
  748. PrintLastError("CertOpenStore(CERT_STORE_DELETE_FLAG)");
  749. }
  750. hStore = NULL;
  751. } else if (NULL == hStore) {
  752. DWORD dwErr = GetLastError();
  753. printf("NULL OpenStoreEx %d 0x%x\n", dwErr, dwErr);
  754. } else {
  755. if (dwFlags & CERT_STORE_SET_LOCALIZED_NAME_FLAG) {
  756. LPWSTR pwszLocalizedName;
  757. DWORD cbLocalizedName;
  758. if (!CertGetStoreProperty(
  759. hStore,
  760. CERT_STORE_LOCALIZED_NAME_PROP_ID,
  761. NULL,
  762. &cbLocalizedName
  763. )) {
  764. if (CRYPT_E_NOT_FOUND == GetLastError())
  765. printf("No localized store name property\n");
  766. else
  767. PrintLastError("CertGetStoreProperty");
  768. } else if (pwszLocalizedName = (LPWSTR) TestAlloc(
  769. cbLocalizedName)) {
  770. if (!CertGetStoreProperty(
  771. hStore,
  772. CERT_STORE_LOCALIZED_NAME_PROP_ID,
  773. pwszLocalizedName,
  774. &cbLocalizedName
  775. ))
  776. PrintLastError("CertGetStoreProperty");
  777. else
  778. printf("Localized Store Name:: %S\n", pwszLocalizedName);
  779. TestFree(pwszLocalizedName);
  780. }
  781. }
  782. DWORD dwAccessStateFlags;
  783. DWORD cbData = sizeof(dwAccessStateFlags);
  784. CertGetStoreProperty(
  785. hStore,
  786. CERT_ACCESS_STATE_PROP_ID,
  787. &dwAccessStateFlags,
  788. &cbData
  789. );
  790. if (0 == cbData)
  791. printf("No Store AccessState PropId\n");
  792. else {
  793. printf("Store AccessState PropId dwFlags:: 0x%x",
  794. dwAccessStateFlags);
  795. if (dwAccessStateFlags & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG)
  796. printf(" WRITE_PERSIST");
  797. if (dwAccessStateFlags & CERT_ACCESS_STATE_SYSTEM_STORE_FLAG)
  798. printf(" SYSTEM_STORE");
  799. if (dwAccessStateFlags & CERT_ACCESS_STATE_LM_SYSTEM_STORE_FLAG)
  800. printf(" LM_SYSTEM_STORE");
  801. printf("\n");
  802. }
  803. }
  804. return hStore;
  805. }
  806. HCERTSTORE OpenSystemStoreOrFile(BOOL fSystemStore, LPCSTR pszStoreFilename,
  807. DWORD dwFlags)
  808. {
  809. HCERTSTORE hStore;
  810. hStore = OpenStoreEx2(fSystemStore, pszStoreFilename, dwFlags);
  811. if (hStore == NULL) {
  812. DWORD dwErr = GetLastError();
  813. printf( "can't open %s\n", pszStoreFilename);
  814. SetLastError(dwErr);
  815. PrintLastError("CertOpenStore");
  816. }
  817. return hStore;
  818. }
  819. HCERTSTORE OpenStoreEx(BOOL fSystemStore, LPCSTR pszStoreFilename,
  820. DWORD dwFlags)
  821. {
  822. HCERTSTORE hStore;
  823. hStore = OpenStoreEx2(fSystemStore, pszStoreFilename, dwFlags);
  824. if (hStore == NULL) {
  825. printf( "can't open %s\n", pszStoreFilename);
  826. hStore = CertOpenStore(
  827. CERT_STORE_PROV_MEMORY,
  828. 0, // dwEncodingType
  829. 0, // hCryptProv
  830. 0, // dwFlags
  831. NULL // pvPara
  832. );
  833. }
  834. if (hStore == NULL)
  835. PrintLastError("CertOpenStore");
  836. return hStore;
  837. }
  838. HCERTSTORE OpenStore(BOOL fSystemStore, LPCSTR pszStoreFilename)
  839. {
  840. return OpenStoreEx(fSystemStore, pszStoreFilename, 0);
  841. }
  842. HCERTSTORE OpenStoreOrSpc(BOOL fSystemStore, LPCSTR pszStoreFilename,
  843. BOOL *pfSpc)
  844. {
  845. *pfSpc = FALSE;
  846. return OpenStore(fSystemStore, pszStoreFilename);
  847. }
  848. void SaveStore(HCERTSTORE hStore, LPCSTR pszSaveFilename)
  849. {
  850. HANDLE hFile;
  851. hFile = CreateFile(pszSaveFilename,
  852. GENERIC_WRITE,
  853. 0, // fdwShareMode
  854. NULL, // lpsa
  855. CREATE_ALWAYS,
  856. 0, // fdwAttrsAndFlags
  857. 0); // TemplateFile
  858. if (INVALID_HANDLE_VALUE == hFile) {
  859. printf( "can't open %s\n", pszSaveFilename);
  860. PrintLastError("CloseStore::CreateFile");
  861. } else {
  862. printf("Saving store to %s\n", pszSaveFilename);
  863. if (!CertSaveStore(
  864. hStore,
  865. 0, // dwEncodingType,
  866. CERT_STORE_SAVE_AS_STORE,
  867. CERT_STORE_SAVE_TO_FILE,
  868. (void *) hFile,
  869. 0 // dwFlags
  870. ))
  871. PrintLastError("CertSaveStore");
  872. CloseHandle(hFile);
  873. }
  874. }
  875. void SaveStoreEx(HCERTSTORE hStore, BOOL fPKCS7Save, LPCSTR pszSaveFilename)
  876. {
  877. DWORD dwSaveAs;
  878. if (fPKCS7Save) {
  879. dwSaveAs = CERT_STORE_SAVE_AS_PKCS7;
  880. printf("Saving store as PKCS #7 to %s\n", pszSaveFilename);
  881. } else {
  882. dwSaveAs = CERT_STORE_SAVE_AS_STORE;
  883. printf("Saving store to %s\n", pszSaveFilename);
  884. }
  885. if (!CertSaveStore(
  886. hStore,
  887. dwCertEncodingType | dwMsgEncodingType,
  888. dwSaveAs,
  889. CERT_STORE_SAVE_TO_FILENAME_A,
  890. (void *) pszSaveFilename,
  891. 0 // dwFlags
  892. ))
  893. PrintLastError("CertSaveStore");
  894. }
  895. LPCWSTR GetOIDName(LPCSTR pszOID, DWORD dwGroupId)
  896. {
  897. PCCRYPT_OID_INFO pInfo;
  898. if (pInfo = CryptFindOIDInfo(
  899. CRYPT_OID_INFO_OID_KEY,
  900. (void *) pszOID,
  901. dwGroupId
  902. )) {
  903. if (L'\0' != pInfo->pwszName[0])
  904. return pInfo->pwszName;
  905. }
  906. return L"???";
  907. }
  908. ALG_ID GetAlgid(LPCSTR pszOID, DWORD dwGroupId)
  909. {
  910. PCCRYPT_OID_INFO pInfo;
  911. if (pInfo = CryptFindOIDInfo(
  912. CRYPT_OID_INFO_OID_KEY,
  913. (void *) pszOID,
  914. dwGroupId
  915. ))
  916. return pInfo->Algid;
  917. return 0;
  918. }
  919. static void GetSignAlgids(
  920. IN LPCSTR pszOID,
  921. OUT ALG_ID *paiHash,
  922. OUT ALG_ID *paiPubKey
  923. )
  924. {
  925. PCCRYPT_OID_INFO pInfo;
  926. *paiHash = 0;
  927. *paiPubKey = 0;
  928. if (pInfo = CryptFindOIDInfo(
  929. CRYPT_OID_INFO_OID_KEY,
  930. (void *) pszOID,
  931. CRYPT_SIGN_ALG_OID_GROUP_ID
  932. )) {
  933. DWORD cExtra = pInfo->ExtraInfo.cbData / sizeof(DWORD);
  934. DWORD *pdwExtra = (DWORD *) pInfo->ExtraInfo.pbData;
  935. *paiHash = pInfo->Algid;
  936. if (1 <= cExtra)
  937. *paiPubKey = pdwExtra[0];
  938. }
  939. }
  940. void DisplayVerifyFlags(LPSTR pszHdr, DWORD dwFlags)
  941. {
  942. if (dwFlags == CERT_STORE_TIME_VALIDITY_FLAG)
  943. printf("***** %s: Warning:: Time Invalid\n", pszHdr);
  944. else if (dwFlags != 0) {
  945. printf("***** %s: Failed Verification Checks:: ", pszHdr);
  946. if (dwFlags & CERT_STORE_SIGNATURE_FLAG)
  947. printf("SIGNATURE ");
  948. if (dwFlags & CERT_STORE_TIME_VALIDITY_FLAG)
  949. printf("TIME ");
  950. if (dwFlags & CERT_STORE_REVOCATION_FLAG)
  951. printf("REVOCATION ");
  952. if (dwFlags & CERT_STORE_NO_CRL_FLAG)
  953. printf("NO_CRL ");
  954. if (dwFlags & CERT_STORE_NO_ISSUER_FLAG)
  955. printf("NO_ISSUER ");
  956. if (dwFlags & CERT_STORE_DELTA_CRL_FLAG)
  957. printf("NOT_DELTA_CRL ");
  958. if (dwFlags & CERT_STORE_BASE_CRL_FLAG)
  959. printf("NOT_BASE_CRL ");
  960. printf("\n");
  961. }
  962. }
  963. static void DisplayThumbprint(
  964. LPCSTR pszHash,
  965. BYTE *pbHash,
  966. DWORD cbHash
  967. )
  968. {
  969. printf("%s Thumbprint:: ", pszHash);
  970. if (cbHash == 0)
  971. printf("???");
  972. else {
  973. ULONG cb;
  974. while (cbHash > 0) {
  975. cb = min(4, cbHash);
  976. cbHash -= cb;
  977. for (; cb > 0; cb--, pbHash++)
  978. printf("%02X", *pbHash);
  979. printf(" ");
  980. }
  981. }
  982. printf("\n");
  983. }
  984. static void DisplaySerialNumber(
  985. PCRYPT_INTEGER_BLOB pSerialNumber
  986. )
  987. {
  988. DWORD cb;
  989. BYTE *pb;
  990. for (cb = pSerialNumber->cbData,
  991. pb = pSerialNumber->pbData + (cb - 1); cb > 0; cb--, pb--) {
  992. printf(" %02X", *pb);
  993. }
  994. }
  995. static void DisplayAnyString(
  996. LPCSTR pszPrefix,
  997. BYTE *pbEncoded,
  998. DWORD cbEncoded,
  999. DWORD dwDisplayFlags
  1000. )
  1001. {
  1002. PCERT_NAME_VALUE pInfo = NULL;
  1003. if (NULL == (pInfo = (PCERT_NAME_VALUE) TestNoCopyDecodeObject(
  1004. X509_UNICODE_ANY_STRING,
  1005. pbEncoded,
  1006. cbEncoded
  1007. ))) goto CommonReturn;
  1008. if (pInfo->dwValueType == CERT_RDN_ENCODED_BLOB ||
  1009. pInfo->dwValueType == CERT_RDN_OCTET_STRING) {
  1010. printf("%s ValueType: %d\n", pszPrefix, pInfo->dwValueType);
  1011. PrintBytes(" ", pInfo->Value.pbData, pInfo->Value.cbData);
  1012. } else
  1013. printf("%s ValueType: %d String: %S\n",
  1014. pszPrefix, pInfo->dwValueType, pInfo->Value.pbData);
  1015. CommonReturn:
  1016. if (pInfo)
  1017. TestFree(pInfo);
  1018. }
  1019. static void DisplayBits(
  1020. LPCSTR pszPrefix,
  1021. BYTE *pbEncoded,
  1022. DWORD cbEncoded,
  1023. DWORD dwDisplayFlags)
  1024. {
  1025. PCRYPT_BIT_BLOB pInfo = NULL;
  1026. if (NULL == (pInfo = (PCRYPT_BIT_BLOB) TestNoCopyDecodeObject(
  1027. X509_BITS,
  1028. pbEncoded,
  1029. cbEncoded
  1030. ))) goto CommonReturn;
  1031. printf("%s", pszPrefix);
  1032. if (1 == pInfo->cbData) {
  1033. printf(" %02X", *pInfo->pbData);
  1034. if (pInfo->cUnusedBits)
  1035. printf(" UnusedBits: %d\n", pInfo->cUnusedBits);
  1036. else
  1037. printf("\n");
  1038. } else {
  1039. if (pInfo->cbData) {
  1040. printf("\n");
  1041. PrintBytes(" ", pInfo->pbData, pInfo->cbData);
  1042. printf(" UnusedBits: %d\n", pInfo->cUnusedBits);
  1043. } else
  1044. printf(" NONE\n");
  1045. }
  1046. CommonReturn:
  1047. if (pInfo)
  1048. TestFree(pInfo);
  1049. }
  1050. static void DisplayInteger(
  1051. BYTE *pbEncoded,
  1052. DWORD cbEncoded,
  1053. DWORD dwDisplayFlags)
  1054. {
  1055. int iInfo = 0;
  1056. DWORD cbInfo;
  1057. cbInfo = sizeof(iInfo);
  1058. if (!CryptDecodeObject(
  1059. dwCertEncodingType,
  1060. X509_INTEGER,
  1061. pbEncoded,
  1062. cbEncoded,
  1063. 0, // dwFlags
  1064. &iInfo,
  1065. &cbInfo
  1066. )) {
  1067. PrintLastError("IntegerDecode");
  1068. goto CommonReturn;
  1069. }
  1070. printf(" Integer:: %d (0x%x)\n", iInfo, iInfo);
  1071. CommonReturn:
  1072. return;
  1073. }
  1074. static void DisplayOctetString(
  1075. LPCSTR pszPrefix,
  1076. BYTE *pbEncoded,
  1077. DWORD cbEncoded,
  1078. DWORD dwDisplayFlags)
  1079. {
  1080. PCRYPT_DATA_BLOB pInfo = NULL;
  1081. if (NULL == (pInfo = (PCRYPT_DATA_BLOB) TestNoCopyDecodeObject(
  1082. X509_OCTET_STRING,
  1083. pbEncoded,
  1084. cbEncoded
  1085. ))) goto CommonReturn;
  1086. printf("%s", pszPrefix);
  1087. if (pInfo->cbData) {
  1088. printf("\n");
  1089. PrintBytes(" ", pInfo->pbData, pInfo->cbData);
  1090. } else
  1091. printf(" NONE\n");
  1092. CommonReturn:
  1093. if (pInfo)
  1094. TestFree(pInfo);
  1095. }
  1096. static BOOL DecodeName(BYTE *pbEncoded, DWORD cbEncoded, DWORD dwDisplayFlags)
  1097. {
  1098. BOOL fResult;
  1099. PCERT_NAME_INFO pInfo = NULL;
  1100. DWORD i,j;
  1101. PCERT_RDN pRDN;
  1102. PCERT_RDN_ATTR pAttr;
  1103. #if 0
  1104. {
  1105. CERT_NAME_BLOB Name;
  1106. DWORD cwsz;
  1107. LPWSTR pwsz;
  1108. DWORD csz;
  1109. LPSTR psz;
  1110. Name.pbData = pbEncoded;
  1111. Name.cbData = cbEncoded;
  1112. DWORD rgdwStrType[] = {
  1113. CERT_SIMPLE_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG |
  1114. CERT_NAME_STR_NO_PLUS_FLAG | CERT_NAME_STR_NO_QUOTING_FLAG,
  1115. CERT_OID_NAME_STR,
  1116. CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG |
  1117. CERT_NAME_STR_NO_QUOTING_FLAG,
  1118. 0
  1119. };
  1120. DWORD *pdwStrType;
  1121. cwsz = CertNameToStrW(
  1122. dwCertEncodingType,
  1123. &Name,
  1124. CERT_X500_NAME_STR,
  1125. NULL, // pwsz
  1126. 0); // cwsz
  1127. if (pwsz = (LPWSTR) TestAlloc(cwsz * sizeof(WCHAR))) {
  1128. CertNameToStrW(
  1129. dwCertEncodingType,
  1130. &Name,
  1131. CERT_X500_NAME_STR,
  1132. pwsz,
  1133. cwsz);
  1134. printf(" %S\n", pwsz);
  1135. TestFree(pwsz);
  1136. }
  1137. for (pdwStrType = rgdwStrType; *pdwStrType; pdwStrType++) {
  1138. csz = CertNameToStrA(
  1139. dwCertEncodingType,
  1140. &Name,
  1141. *pdwStrType,
  1142. NULL, // psz
  1143. 0); // csz
  1144. if (psz = (LPSTR) TestAlloc(csz)) {
  1145. CertNameToStrA(
  1146. dwCertEncodingType,
  1147. &Name,
  1148. *pdwStrType,
  1149. psz,
  1150. csz);
  1151. printf(" %s\n", psz);
  1152. TestFree(psz);
  1153. }
  1154. }
  1155. }
  1156. #endif
  1157. if (NULL == (pInfo = (PCERT_NAME_INFO) TestNoCopyDecodeObject(
  1158. X509_NAME,
  1159. pbEncoded,
  1160. cbEncoded
  1161. ))) goto ErrorReturn;
  1162. for (i = 0, pRDN = pInfo->rgRDN; i < pInfo->cRDN; i++, pRDN++) {
  1163. for (j = 0, pAttr = pRDN->rgRDNAttr; j < pRDN->cRDNAttr; j++, pAttr++) {
  1164. LPSTR pszObjId = pAttr->pszObjId;
  1165. if (pszObjId == NULL)
  1166. pszObjId = "<NULL OBJID>";
  1167. if ((dwDisplayFlags & DISPLAY_VERBOSE_FLAG) ||
  1168. (pAttr->dwValueType == CERT_RDN_ENCODED_BLOB) ||
  1169. (pAttr->dwValueType == CERT_RDN_OCTET_STRING)) {
  1170. printf(" [%d,%d] %s (%S) ValueType: %d\n",
  1171. i, j, pszObjId, GetOIDName(pszObjId), pAttr->dwValueType);
  1172. PrintBytes(" ", pAttr->Value.pbData, pAttr->Value.cbData);
  1173. } else if (pAttr->dwValueType == CERT_RDN_UNIVERSAL_STRING) {
  1174. printf(" [%d,%d] %s (%S)",
  1175. i, j, pszObjId, GetOIDName(pszObjId));
  1176. DWORD cdw = pAttr->Value.cbData / 4;
  1177. DWORD *pdw = (DWORD *) pAttr->Value.pbData;
  1178. for ( ; cdw > 0; cdw--, pdw++)
  1179. printf(" 0x%08X", *pdw);
  1180. printf("\n");
  1181. DWORD csz;
  1182. csz = CertRDNValueToStrA(
  1183. pAttr->dwValueType,
  1184. &pAttr->Value,
  1185. NULL, // psz
  1186. 0 // csz
  1187. );
  1188. if (csz > 1) {
  1189. LPSTR psz = (LPSTR) TestAlloc(csz);
  1190. if (psz) {
  1191. CertRDNValueToStrA(
  1192. pAttr->dwValueType,
  1193. &pAttr->Value,
  1194. psz,
  1195. csz
  1196. );
  1197. printf(" Str: %s\n", psz);
  1198. PrintBytes(" ", (BYTE *) psz, csz);
  1199. TestFree(psz);
  1200. }
  1201. }
  1202. DWORD cwsz;
  1203. cwsz = CertRDNValueToStrW(
  1204. pAttr->dwValueType,
  1205. &pAttr->Value,
  1206. NULL, // pwsz
  1207. 0 // cwsz
  1208. );
  1209. if (cwsz > 1) {
  1210. LPWSTR pwsz =
  1211. (LPWSTR) TestAlloc(cwsz * sizeof(WCHAR));
  1212. if (pwsz) {
  1213. CertRDNValueToStrW(
  1214. pAttr->dwValueType,
  1215. &pAttr->Value,
  1216. pwsz,
  1217. cwsz
  1218. );
  1219. printf(" WStr: %S\n", pwsz);
  1220. PrintBytes(" ", (BYTE *) pwsz, cwsz * sizeof(WCHAR));
  1221. TestFree(pwsz);
  1222. }
  1223. }
  1224. } else if (pAttr->dwValueType == CERT_RDN_BMP_STRING ||
  1225. pAttr->dwValueType == CERT_RDN_UTF8_STRING) {
  1226. printf(" [%d,%d] %s (%S) %S\n",
  1227. i, j, pszObjId, GetOIDName(pszObjId), pAttr->Value.pbData);
  1228. } else
  1229. printf(" [%d,%d] %s (%S) %s\n",
  1230. i, j, pszObjId, GetOIDName(pszObjId), pAttr->Value.pbData);
  1231. }
  1232. }
  1233. fResult = TRUE;
  1234. goto CommonReturn;
  1235. ErrorReturn:
  1236. fResult = FALSE;
  1237. CommonReturn:
  1238. if (pInfo)
  1239. TestFree(pInfo);
  1240. return fResult;
  1241. }
  1242. static void DisplayAltNameEntry(
  1243. PCERT_ALT_NAME_ENTRY pEntry,
  1244. DWORD dwDisplayFlags)
  1245. {
  1246. switch (pEntry->dwAltNameChoice) {
  1247. case CERT_ALT_NAME_OTHER_NAME:
  1248. printf("OtherName: %s\n", pEntry->pOtherName->pszObjId);
  1249. PrintBytes(" ", pEntry->pOtherName->Value.pbData,
  1250. pEntry->pOtherName->Value.cbData);
  1251. break;
  1252. case CERT_ALT_NAME_X400_ADDRESS:
  1253. printf("X400Address:\n");
  1254. break;
  1255. case CERT_ALT_NAME_DIRECTORY_NAME:
  1256. printf("DirectoryName:\n");
  1257. DecodeName(pEntry->DirectoryName.pbData,
  1258. pEntry->DirectoryName.cbData, dwDisplayFlags);
  1259. break;
  1260. case CERT_ALT_NAME_EDI_PARTY_NAME:
  1261. printf("EdiPartyName:\n");
  1262. break;
  1263. case CERT_ALT_NAME_RFC822_NAME:
  1264. printf("RFC822: %S\n", pEntry->pwszRfc822Name);
  1265. break;
  1266. case CERT_ALT_NAME_DNS_NAME:
  1267. printf("DNS: %S\n", pEntry->pwszDNSName);
  1268. break;
  1269. case CERT_ALT_NAME_URL:
  1270. printf("URL: %S\n", pEntry->pwszURL);
  1271. break;
  1272. case CERT_ALT_NAME_IP_ADDRESS:
  1273. printf("IPAddress:\n");
  1274. PrintBytes(" ", pEntry->IPAddress.pbData, pEntry->IPAddress.cbData);
  1275. break;
  1276. case CERT_ALT_NAME_REGISTERED_ID:
  1277. printf("RegisteredID: %s\n", pEntry->pszRegisteredID);
  1278. break;
  1279. default:
  1280. printf("Unknown choice: %d\n", pEntry->dwAltNameChoice);
  1281. }
  1282. }
  1283. static void DisplayAltName(
  1284. PCERT_ALT_NAME_INFO pInfo,
  1285. DWORD dwDisplayFlags)
  1286. {
  1287. DWORD i;
  1288. PCERT_ALT_NAME_ENTRY pEntry = pInfo->rgAltEntry;
  1289. DWORD cEntry = pInfo->cAltEntry;
  1290. for (i = 0; i < cEntry; i++, pEntry++) {
  1291. printf(" [%d] ", i);
  1292. DisplayAltNameEntry(pEntry, dwDisplayFlags);
  1293. }
  1294. }
  1295. static void DecodeAndDisplayAltName(
  1296. BYTE *pbEncoded,
  1297. DWORD cbEncoded,
  1298. DWORD dwDisplayFlags)
  1299. {
  1300. PCERT_ALT_NAME_INFO pInfo = NULL;
  1301. if (NULL == (pInfo = (PCERT_ALT_NAME_INFO) TestNoCopyDecodeObject(
  1302. X509_ALTERNATE_NAME,
  1303. pbEncoded,
  1304. cbEncoded
  1305. ))) goto CommonReturn;
  1306. DisplayAltName(pInfo, dwDisplayFlags);
  1307. CommonReturn:
  1308. if (pInfo)
  1309. TestFree(pInfo);
  1310. }
  1311. static void DisplayAuthorityKeyIdExtension(
  1312. BYTE *pbEncoded,
  1313. DWORD cbEncoded,
  1314. DWORD dwDisplayFlags)
  1315. {
  1316. PCERT_AUTHORITY_KEY_ID_INFO pInfo;
  1317. printf(" <AuthorityKeyId>\n");
  1318. if (NULL == (pInfo = (PCERT_AUTHORITY_KEY_ID_INFO) TestNoCopyDecodeObject(
  1319. X509_AUTHORITY_KEY_ID,
  1320. pbEncoded,
  1321. cbEncoded
  1322. ))) goto CommonReturn;
  1323. if (pInfo->KeyId.cbData) {
  1324. printf(" KeyId::\n");
  1325. PrintBytes(" ", pInfo->KeyId.pbData, pInfo->KeyId.cbData);
  1326. }
  1327. if (pInfo->CertIssuer.cbData) {
  1328. printf(" CertIssuer::\n");
  1329. DecodeName(pInfo->CertIssuer.pbData, pInfo->CertIssuer.cbData,
  1330. dwDisplayFlags);
  1331. }
  1332. if (pInfo->CertSerialNumber.cbData) {
  1333. printf(" CertSerialNumber::");
  1334. DisplaySerialNumber(&pInfo->CertSerialNumber);
  1335. printf("\n");
  1336. }
  1337. CommonReturn:
  1338. if (pInfo)
  1339. TestFree(pInfo);
  1340. }
  1341. static void DisplayAuthorityKeyId2Extension(
  1342. BYTE *pbEncoded,
  1343. DWORD cbEncoded,
  1344. DWORD dwDisplayFlags)
  1345. {
  1346. PCERT_AUTHORITY_KEY_ID2_INFO pInfo;
  1347. printf(" <AuthorityKeyId #2>\n");
  1348. if (NULL == (pInfo = (PCERT_AUTHORITY_KEY_ID2_INFO) TestNoCopyDecodeObject(
  1349. X509_AUTHORITY_KEY_ID2,
  1350. pbEncoded,
  1351. cbEncoded
  1352. ))) goto CommonReturn;
  1353. if (pInfo->KeyId.cbData) {
  1354. printf(" KeyId::\n");
  1355. PrintBytes(" ", pInfo->KeyId.pbData, pInfo->KeyId.cbData);
  1356. }
  1357. if (pInfo->AuthorityCertIssuer.cAltEntry) {
  1358. printf(" AuthorityCertIssuer::\n");
  1359. DisplayAltName(&pInfo->AuthorityCertIssuer, dwDisplayFlags);
  1360. }
  1361. if (pInfo->AuthorityCertSerialNumber.cbData) {
  1362. printf(" AuthorityCertSerialNumber::");
  1363. DisplaySerialNumber(&pInfo->AuthorityCertSerialNumber);
  1364. printf("\n");
  1365. }
  1366. CommonReturn:
  1367. if (pInfo)
  1368. TestFree(pInfo);
  1369. }
  1370. static void DisplayKeyAttrExtension(
  1371. BYTE *pbEncoded,
  1372. DWORD cbEncoded,
  1373. DWORD dwDisplayFlags)
  1374. {
  1375. PCERT_KEY_ATTRIBUTES_INFO pInfo;
  1376. if (NULL == (pInfo = (PCERT_KEY_ATTRIBUTES_INFO) TestNoCopyDecodeObject(
  1377. X509_KEY_ATTRIBUTES,
  1378. pbEncoded,
  1379. cbEncoded
  1380. ))) goto CommonReturn;
  1381. if (pInfo->KeyId.cbData) {
  1382. printf(" KeyId::\n");
  1383. PrintBytes(" ", pInfo->KeyId.pbData, pInfo->KeyId.cbData);
  1384. }
  1385. if (pInfo->IntendedKeyUsage.cbData) {
  1386. BYTE bFlags = *pInfo->IntendedKeyUsage.pbData;
  1387. printf(" IntendedKeyUsage:: ");
  1388. if (bFlags == 0)
  1389. printf("<NONE> ");
  1390. if (bFlags & CERT_DIGITAL_SIGNATURE_KEY_USAGE)
  1391. printf("DIGITAL_SIGNATURE ");
  1392. if (bFlags & CERT_NON_REPUDIATION_KEY_USAGE)
  1393. printf("NON_REPUDIATION ");
  1394. if (bFlags & CERT_KEY_ENCIPHERMENT_KEY_USAGE)
  1395. printf("KEY_ENCIPHERMENT ");
  1396. if (bFlags & CERT_DATA_ENCIPHERMENT_KEY_USAGE)
  1397. printf("DATA_ENCIPHERMENT ");
  1398. if (bFlags & CERT_KEY_AGREEMENT_KEY_USAGE)
  1399. printf("KEY_AGREEMENT ");
  1400. if (bFlags & CERT_KEY_CERT_SIGN_KEY_USAGE)
  1401. printf("KEY_CERT ");
  1402. if (bFlags & CERT_OFFLINE_CRL_SIGN_KEY_USAGE)
  1403. printf("OFFLINE_CRL_SIGN ");
  1404. printf("\n");
  1405. }
  1406. if (pInfo->pPrivateKeyUsagePeriod) {
  1407. PCERT_PRIVATE_KEY_VALIDITY p = pInfo->pPrivateKeyUsagePeriod;
  1408. printf(" NotBefore:: %s\n", FileTimeText(&p->NotBefore));
  1409. printf(" NotAfter:: %s\n", FileTimeText(&p->NotAfter));
  1410. }
  1411. CommonReturn:
  1412. if (pInfo)
  1413. TestFree(pInfo);
  1414. }
  1415. static void DisplayKeyUsageRestrictionExtension(
  1416. BYTE *pbEncoded,
  1417. DWORD cbEncoded,
  1418. DWORD dwDisplayFlags)
  1419. {
  1420. PCERT_KEY_USAGE_RESTRICTION_INFO pInfo;
  1421. if (NULL == (pInfo =
  1422. (PCERT_KEY_USAGE_RESTRICTION_INFO) TestNoCopyDecodeObject(
  1423. X509_KEY_USAGE_RESTRICTION,
  1424. pbEncoded,
  1425. cbEncoded
  1426. ))) goto ErrorReturn;
  1427. if (pInfo->cCertPolicyId) {
  1428. DWORD i, j;
  1429. printf(" CertPolicySet::\n");
  1430. PCERT_POLICY_ID pPolicyId = pInfo->rgCertPolicyId;
  1431. for (i = 0; i < pInfo->cCertPolicyId; i++, pPolicyId++) {
  1432. if (pPolicyId->cCertPolicyElementId == 0)
  1433. printf(" [%d,*] <NO ELEMENTS>\n", i);
  1434. LPSTR *ppszObjId = pPolicyId->rgpszCertPolicyElementId;
  1435. for (j = 0; j < pPolicyId->cCertPolicyElementId; j++, ppszObjId++) {
  1436. LPSTR pszObjId = *ppszObjId;
  1437. if (pszObjId == NULL)
  1438. pszObjId = "<NULL OBJID>";
  1439. printf(" [%d,%d] %s\n", i, j, pszObjId);
  1440. }
  1441. }
  1442. }
  1443. if (pInfo->RestrictedKeyUsage.cbData) {
  1444. BYTE bFlags = *pInfo->RestrictedKeyUsage.pbData;
  1445. printf(" RestrictedKeyUsage:: ");
  1446. if (bFlags == 0)
  1447. printf("<NONE> ");
  1448. if (bFlags & CERT_DIGITAL_SIGNATURE_KEY_USAGE)
  1449. printf("DIGITAL_SIGNATURE ");
  1450. if (bFlags & CERT_NON_REPUDIATION_KEY_USAGE)
  1451. printf("NON_REPUDIATION ");
  1452. if (bFlags & CERT_KEY_ENCIPHERMENT_KEY_USAGE)
  1453. printf("KEY_ENCIPHERMENT ");
  1454. if (bFlags & CERT_DATA_ENCIPHERMENT_KEY_USAGE)
  1455. printf("DATA_ENCIPHERMENT ");
  1456. if (bFlags & CERT_KEY_AGREEMENT_KEY_USAGE)
  1457. printf("KEY_AGREEMENT ");
  1458. if (bFlags & CERT_KEY_CERT_SIGN_KEY_USAGE)
  1459. printf("KEY_CERT ");
  1460. if (bFlags & CERT_OFFLINE_CRL_SIGN_KEY_USAGE)
  1461. printf("OFFLINE_CRL_SIGN ");
  1462. printf("\n");
  1463. }
  1464. goto CommonReturn;
  1465. ErrorReturn:
  1466. CommonReturn:
  1467. if (pInfo)
  1468. TestFree(pInfo);
  1469. }
  1470. static void DisplayBasicConstraintsExtension(
  1471. BYTE *pbEncoded,
  1472. DWORD cbEncoded,
  1473. DWORD dwDisplayFlags)
  1474. {
  1475. PCERT_BASIC_CONSTRAINTS_INFO pInfo;
  1476. if (NULL == (pInfo = (PCERT_BASIC_CONSTRAINTS_INFO) TestNoCopyDecodeObject(
  1477. X509_BASIC_CONSTRAINTS,
  1478. pbEncoded,
  1479. cbEncoded
  1480. ))) goto ErrorReturn;
  1481. printf(" SubjectType:: ");
  1482. if (pInfo->SubjectType.cbData == 0)
  1483. printf("<NONE> ");
  1484. else {
  1485. BYTE bSubjectType = *pInfo->SubjectType.pbData;
  1486. if (bSubjectType == 0)
  1487. printf("<NONE> ");
  1488. if (bSubjectType & CERT_CA_SUBJECT_FLAG)
  1489. printf("CA ");
  1490. if (bSubjectType & CERT_END_ENTITY_SUBJECT_FLAG)
  1491. printf("END_ENTITY ");
  1492. }
  1493. printf("\n");
  1494. printf(" PathLenConstraint:: ");
  1495. if (pInfo->fPathLenConstraint)
  1496. printf("%d", pInfo->dwPathLenConstraint);
  1497. else
  1498. printf("<NONE>");
  1499. printf("\n");
  1500. if (pInfo->cSubtreesConstraint) {
  1501. DWORD i;
  1502. PCERT_NAME_BLOB pSubtrees = pInfo->rgSubtreesConstraint;
  1503. for (i = 0; i < pInfo->cSubtreesConstraint; i++, pSubtrees++) {
  1504. printf(" SubtreesConstraint[%d]::\n", i);
  1505. DecodeName(pSubtrees->pbData, pSubtrees->cbData, dwDisplayFlags);
  1506. }
  1507. }
  1508. goto CommonReturn;
  1509. ErrorReturn:
  1510. CommonReturn:
  1511. if (pInfo)
  1512. TestFree(pInfo);
  1513. }
  1514. static void DisplayKeyUsageExtension(
  1515. BYTE *pbEncoded,
  1516. DWORD cbEncoded,
  1517. DWORD dwDisplayFlags)
  1518. {
  1519. PCRYPT_BIT_BLOB pInfo;
  1520. BYTE bFlags;
  1521. if (NULL == (pInfo =
  1522. (PCRYPT_BIT_BLOB) TestNoCopyDecodeObject(
  1523. X509_KEY_USAGE,
  1524. pbEncoded,
  1525. cbEncoded
  1526. ))) goto ErrorReturn;
  1527. printf(" KeyUsage:: ");
  1528. if (pInfo->cbData)
  1529. bFlags = *pInfo->pbData;
  1530. else
  1531. bFlags = 0;
  1532. if (bFlags == 0)
  1533. printf("<NONE> ");
  1534. if (bFlags & CERT_DIGITAL_SIGNATURE_KEY_USAGE)
  1535. printf("DIGITAL_SIGNATURE ");
  1536. if (bFlags & CERT_NON_REPUDIATION_KEY_USAGE)
  1537. printf("NON_REPUDIATION ");
  1538. if (bFlags & CERT_KEY_ENCIPHERMENT_KEY_USAGE)
  1539. printf("KEY_ENCIPHERMENT ");
  1540. if (bFlags & CERT_DATA_ENCIPHERMENT_KEY_USAGE)
  1541. printf("DATA_ENCIPHERMENT ");
  1542. if (bFlags & CERT_KEY_AGREEMENT_KEY_USAGE)
  1543. printf("KEY_AGREEMENT ");
  1544. if (bFlags & CERT_KEY_CERT_SIGN_KEY_USAGE)
  1545. printf("KEY_CERT ");
  1546. if (bFlags & CERT_OFFLINE_CRL_SIGN_KEY_USAGE)
  1547. printf("OFFLINE_CRL_SIGN ");
  1548. printf("\n");
  1549. ErrorReturn:
  1550. if (pInfo)
  1551. TestFree(pInfo);
  1552. }
  1553. static void DisplayBasicConstraints2Extension(
  1554. BYTE *pbEncoded,
  1555. DWORD cbEncoded,
  1556. DWORD dwDisplayFlags)
  1557. {
  1558. PCERT_BASIC_CONSTRAINTS2_INFO pInfo;
  1559. if (NULL == (pInfo = (PCERT_BASIC_CONSTRAINTS2_INFO) TestNoCopyDecodeObject(
  1560. X509_BASIC_CONSTRAINTS2,
  1561. pbEncoded,
  1562. cbEncoded
  1563. ))) goto ErrorReturn;
  1564. printf(" Basic Constraints:: ");
  1565. if (pInfo->fCA)
  1566. printf("CA\n");
  1567. else
  1568. printf("End-user\n");
  1569. printf(" PathLenConstraint:: ");
  1570. if (pInfo->fPathLenConstraint)
  1571. printf("%d", pInfo->dwPathLenConstraint);
  1572. else
  1573. printf("<NONE>");
  1574. printf("\n");
  1575. ErrorReturn:
  1576. if (pInfo)
  1577. TestFree(pInfo);
  1578. }
  1579. static void DisplayPoliciesExtension(
  1580. LPSTR pszType, // "Certificate" | "Revocation" | "Application"
  1581. BYTE *pbEncoded,
  1582. DWORD cbEncoded,
  1583. DWORD dwDisplayFlags)
  1584. {
  1585. PCERT_POLICIES_INFO pInfo;
  1586. DWORD cPolicy;
  1587. PCERT_POLICY_INFO pPolicy;
  1588. DWORD i;
  1589. if (NULL == (pInfo =
  1590. (PCERT_POLICIES_INFO) TestNoCopyDecodeObject(
  1591. X509_CERT_POLICIES,
  1592. pbEncoded,
  1593. cbEncoded
  1594. ))) goto ErrorReturn;
  1595. cPolicy = pInfo->cPolicyInfo;
  1596. pPolicy = pInfo->rgPolicyInfo;
  1597. if (cPolicy == 0)
  1598. printf(" No %s Policies\n", pszType);
  1599. else
  1600. printf(" %s Policies::\n", pszType);
  1601. for (i = 0; i < cPolicy; i++, pPolicy++) {
  1602. DWORD cQualifier = pPolicy->cPolicyQualifier;
  1603. PCERT_POLICY_QUALIFIER_INFO pQualifier;
  1604. DWORD j;
  1605. if (pPolicy->pszPolicyIdentifier)
  1606. printf(" [%d] %s", i, pPolicy->pszPolicyIdentifier);
  1607. if (cQualifier)
  1608. printf(" Qualifiers::");
  1609. printf("\n");
  1610. pQualifier = pPolicy->rgPolicyQualifier;
  1611. for (j = 0; j < cQualifier; j++, pQualifier++) {
  1612. printf(" [%d] %s", j, pQualifier->pszPolicyQualifierId);
  1613. if (pQualifier->Qualifier.cbData) {
  1614. printf(" Encoded Data::\n");
  1615. PrintBytes(" ",
  1616. pQualifier->Qualifier.pbData, pQualifier->Qualifier.cbData);
  1617. } else
  1618. printf("\n");
  1619. }
  1620. }
  1621. ErrorReturn:
  1622. if (pInfo)
  1623. TestFree(pInfo);
  1624. }
  1625. static void DisplaySMIMECapabilitiesExtension(
  1626. BYTE *pbEncoded,
  1627. DWORD cbEncoded,
  1628. DWORD dwDisplayFlags)
  1629. {
  1630. PCRYPT_SMIME_CAPABILITIES pInfo;
  1631. DWORD cCap;
  1632. PCRYPT_SMIME_CAPABILITY pCap;
  1633. DWORD i;
  1634. if (NULL == (pInfo =
  1635. (PCRYPT_SMIME_CAPABILITIES) TestNoCopyDecodeObject(
  1636. PKCS_SMIME_CAPABILITIES,
  1637. pbEncoded,
  1638. cbEncoded
  1639. ))) goto ErrorReturn;
  1640. cCap = pInfo->cCapability;
  1641. pCap = pInfo->rgCapability;
  1642. if (cCap == 0)
  1643. printf(" No SMIME Capabilities\n");
  1644. else
  1645. printf(" SMIME Capabilties::\n");
  1646. for (i = 0; i < cCap; i++, pCap++) {
  1647. LPSTR pszObjId = pCap->pszObjId;
  1648. printf(" [%d] %s (%S)", i, pszObjId, GetOIDName(pszObjId));
  1649. if (pCap->Parameters.cbData) {
  1650. printf(" Parameters::\n");
  1651. PrintBytes(" ",
  1652. pCap->Parameters.pbData,
  1653. pCap->Parameters.cbData);
  1654. } else
  1655. printf("\n");
  1656. }
  1657. ErrorReturn:
  1658. if (pInfo)
  1659. TestFree(pInfo);
  1660. }
  1661. static void DecodeAndDisplayCtlUsage(
  1662. BYTE *pbEncoded,
  1663. DWORD cbEncoded,
  1664. DWORD dwDisplayFlags)
  1665. {
  1666. PCTL_USAGE pInfo;
  1667. DWORD cId;
  1668. LPSTR *ppszId;
  1669. DWORD i;
  1670. if (NULL == (pInfo =
  1671. (PCTL_USAGE) TestNoCopyDecodeObject(
  1672. X509_ENHANCED_KEY_USAGE,
  1673. pbEncoded,
  1674. cbEncoded
  1675. ))) goto ErrorReturn;
  1676. cId = pInfo->cUsageIdentifier;
  1677. ppszId = pInfo->rgpszUsageIdentifier;
  1678. if (cId == 0)
  1679. printf(" No Usage Identifiers\n");
  1680. for (i = 0; i < cId; i++, ppszId++)
  1681. printf(" [%d] %s\n", i, *ppszId);
  1682. ErrorReturn:
  1683. if (pInfo)
  1684. TestFree(pInfo);
  1685. }
  1686. static void DisplayEnhancedKeyUsageExtension(
  1687. BYTE *pbEncoded,
  1688. DWORD cbEncoded,
  1689. DWORD dwDisplayFlags)
  1690. {
  1691. printf(" EnhancedKeyUsage::\n");
  1692. DecodeAndDisplayCtlUsage(pbEncoded, cbEncoded, dwDisplayFlags);
  1693. }
  1694. static void DisplayAltNameExtension(
  1695. LPCSTR pszExt,
  1696. BYTE *pbEncoded,
  1697. DWORD cbEncoded,
  1698. DWORD dwDisplayFlags)
  1699. {
  1700. printf(" <%s>\n", pszExt);
  1701. DecodeAndDisplayAltName(pbEncoded, cbEncoded, dwDisplayFlags);
  1702. }
  1703. static void DisplayNameConstraintsSubtree(
  1704. DWORD cSubtree,
  1705. PCERT_GENERAL_SUBTREE pSubtree,
  1706. DWORD dwDisplayFlags
  1707. )
  1708. {
  1709. DWORD i;
  1710. for (i = 0; i < cSubtree; i++, pSubtree++) {
  1711. printf(" Subtree[%d] ", i);
  1712. if (pSubtree->dwMinimum || pSubtree->fMaximum) {
  1713. printf("(%d ", pSubtree->dwMinimum);
  1714. if (pSubtree->fMaximum)
  1715. printf("- %d) ", pSubtree->dwMaximum);
  1716. else
  1717. printf("...) ");
  1718. }
  1719. DisplayAltNameEntry(&pSubtree->Base, dwDisplayFlags);
  1720. }
  1721. }
  1722. static void DisplayNameConstraintsExtension(
  1723. BYTE *pbEncoded,
  1724. DWORD cbEncoded,
  1725. DWORD dwDisplayFlags)
  1726. {
  1727. PCERT_NAME_CONSTRAINTS_INFO pInfo = NULL;
  1728. if (NULL == (pInfo = (PCERT_NAME_CONSTRAINTS_INFO) TestNoCopyDecodeObject(
  1729. X509_NAME_CONSTRAINTS,
  1730. pbEncoded,
  1731. cbEncoded
  1732. ))) goto CommonReturn;
  1733. if (pInfo->cPermittedSubtree) {
  1734. printf(" <PermittedSubtree>\n");
  1735. DisplayNameConstraintsSubtree(pInfo->cPermittedSubtree,
  1736. pInfo->rgPermittedSubtree, dwDisplayFlags);
  1737. } else
  1738. printf(" No PermittedSubtree\n");
  1739. if (pInfo->cExcludedSubtree) {
  1740. printf(" <ExcludedSubtree>\n");
  1741. DisplayNameConstraintsSubtree(pInfo->cExcludedSubtree,
  1742. pInfo->rgExcludedSubtree, dwDisplayFlags);
  1743. } else
  1744. printf(" No ExcludedSubtree\n");
  1745. CommonReturn:
  1746. if (pInfo)
  1747. TestFree(pInfo);
  1748. }
  1749. static void DisplayPolicyMappingsExtension(
  1750. BYTE *pbEncoded,
  1751. DWORD cbEncoded,
  1752. DWORD dwDisplayFlags)
  1753. {
  1754. PCERT_POLICY_MAPPINGS_INFO pInfo = NULL;
  1755. DWORD i;
  1756. if (NULL == (pInfo = (PCERT_POLICY_MAPPINGS_INFO) TestNoCopyDecodeObject(
  1757. X509_POLICY_MAPPINGS,
  1758. pbEncoded,
  1759. cbEncoded
  1760. ))) goto CommonReturn;
  1761. if (pInfo->cPolicyMapping) {
  1762. for (i = 0; i < pInfo->cPolicyMapping; i++) {
  1763. printf(" [%d] Issuer: %s Subject: %s\n", i,
  1764. pInfo->rgPolicyMapping[i].pszIssuerDomainPolicy,
  1765. pInfo->rgPolicyMapping[i].pszSubjectDomainPolicy);
  1766. }
  1767. } else
  1768. printf(" No PolicyMappings\n");
  1769. CommonReturn:
  1770. if (pInfo)
  1771. TestFree(pInfo);
  1772. }
  1773. static void DisplayPolicyConstraintsExtension(
  1774. BYTE *pbEncoded,
  1775. DWORD cbEncoded,
  1776. DWORD dwDisplayFlags)
  1777. {
  1778. PCERT_POLICY_CONSTRAINTS_INFO pInfo = NULL;
  1779. if (NULL == (pInfo = (PCERT_POLICY_CONSTRAINTS_INFO) TestNoCopyDecodeObject(
  1780. X509_POLICY_CONSTRAINTS,
  1781. pbEncoded,
  1782. cbEncoded
  1783. ))) goto CommonReturn;
  1784. if (pInfo->fRequireExplicitPolicy)
  1785. printf(" RequireExplicitPolicySkipCerts: %d",
  1786. pInfo->dwRequireExplicitPolicySkipCerts);
  1787. if (pInfo->fInhibitPolicyMapping)
  1788. printf(" InhibitPolicyMappingSkipCerts: %d",
  1789. pInfo->dwInhibitPolicyMappingSkipCerts);
  1790. printf("\n");
  1791. CommonReturn:
  1792. if (pInfo)
  1793. TestFree(pInfo);
  1794. }
  1795. static void DisplayCrossCertDistPointsExtension(
  1796. BYTE *pbEncoded,
  1797. DWORD cbEncoded,
  1798. DWORD dwDisplayFlags)
  1799. {
  1800. PCROSS_CERT_DIST_POINTS_INFO pInfo = NULL;
  1801. DWORD i;
  1802. if (NULL == (pInfo = (PCROSS_CERT_DIST_POINTS_INFO) TestNoCopyDecodeObject(
  1803. X509_CROSS_CERT_DIST_POINTS,
  1804. pbEncoded,
  1805. cbEncoded
  1806. ))) goto CommonReturn;
  1807. printf(" SyncDeltaTime (seconds) : %d\n", pInfo->dwSyncDeltaTime);
  1808. for (i = 0; i < pInfo->cDistPoint; i++) {
  1809. printf(" DistPoint[%d]\n", i);
  1810. DisplayAltName(&pInfo->rgDistPoint[i], dwDisplayFlags);
  1811. }
  1812. CommonReturn:
  1813. if (pInfo)
  1814. TestFree(pInfo);
  1815. }
  1816. static void DisplayAccessDescriptions(
  1817. LPCSTR pszAccDescr,
  1818. DWORD cAccDescr,
  1819. PCERT_ACCESS_DESCRIPTION pAccDescr,
  1820. DWORD dwDisplayFlags)
  1821. {
  1822. DWORD i;
  1823. for (i = 0; i < cAccDescr; i++, pAccDescr++) {
  1824. printf(" %s[%d] %s ", pszAccDescr, i, pAccDescr->pszAccessMethod);
  1825. DisplayAltNameEntry(&pAccDescr->AccessLocation, dwDisplayFlags);
  1826. }
  1827. }
  1828. static void DisplayAuthorityInfoAccessExtension(
  1829. BYTE *pbEncoded,
  1830. DWORD cbEncoded,
  1831. DWORD dwDisplayFlags)
  1832. {
  1833. PCERT_AUTHORITY_INFO_ACCESS pInfo = NULL;
  1834. if (NULL == (pInfo = (PCERT_AUTHORITY_INFO_ACCESS) TestNoCopyDecodeObject(
  1835. X509_AUTHORITY_INFO_ACCESS,
  1836. pbEncoded,
  1837. cbEncoded
  1838. ))) goto CommonReturn;
  1839. printf(" <AuthorityInfoAccess>\n");
  1840. if (pInfo->cAccDescr)
  1841. DisplayAccessDescriptions("",
  1842. pInfo->cAccDescr, pInfo->rgAccDescr, dwDisplayFlags);
  1843. CommonReturn:
  1844. if (pInfo)
  1845. TestFree(pInfo);
  1846. }
  1847. static void DisplayCrlDistPointsExtension(
  1848. BYTE *pbEncoded,
  1849. DWORD cbEncoded,
  1850. DWORD dwDisplayFlags)
  1851. {
  1852. PCRL_DIST_POINTS_INFO pInfo = NULL;
  1853. DWORD i;
  1854. if (NULL == (pInfo = (PCRL_DIST_POINTS_INFO) TestNoCopyDecodeObject(
  1855. X509_CRL_DIST_POINTS,
  1856. pbEncoded,
  1857. cbEncoded
  1858. ))) goto CommonReturn;
  1859. if (0 == pInfo->cDistPoint)
  1860. printf(" NO CRL Distribution Points\n");
  1861. else {
  1862. DWORD cPoint = pInfo->cDistPoint;
  1863. PCRL_DIST_POINT pPoint = pInfo->rgDistPoint;
  1864. for (i = 0; i < cPoint; i++, pPoint++) {
  1865. printf(" CRL Distribution Point[%d]\n", i);
  1866. DWORD dwNameChoice = pPoint->DistPointName.dwDistPointNameChoice;
  1867. switch (dwNameChoice) {
  1868. case CRL_DIST_POINT_NO_NAME:
  1869. break;
  1870. case CRL_DIST_POINT_FULL_NAME:
  1871. printf(" FullName:\n");
  1872. DisplayAltName(&pPoint->DistPointName.FullName,
  1873. dwDisplayFlags);
  1874. break;
  1875. case CRL_DIST_POINT_ISSUER_RDN_NAME:
  1876. printf(" IssuerRDN: (Not Implemented)\n");
  1877. break;
  1878. default:
  1879. printf(" Unknown name choice: %d\n", dwNameChoice);
  1880. }
  1881. if (pPoint->ReasonFlags.cbData) {
  1882. BYTE bFlags;
  1883. printf(" ReasonFlags: ");
  1884. bFlags = *pPoint->ReasonFlags.pbData;
  1885. if (bFlags == 0)
  1886. printf("<NONE> ");
  1887. if (bFlags & CRL_REASON_UNUSED_FLAG)
  1888. printf("UNUSED ");
  1889. if (bFlags & CRL_REASON_KEY_COMPROMISE_FLAG)
  1890. printf("KEY_COMPROMISE ");
  1891. if (bFlags & CRL_REASON_CA_COMPROMISE_FLAG)
  1892. printf("CA_COMPROMISE ");
  1893. if (bFlags & CRL_REASON_AFFILIATION_CHANGED_FLAG)
  1894. printf("AFFILIATION_CHANGED ");
  1895. if (bFlags & CRL_REASON_SUPERSEDED_FLAG)
  1896. printf("SUPERSEDED ");
  1897. if (bFlags & CRL_REASON_CESSATION_OF_OPERATION_FLAG)
  1898. printf("CESSATION_OF_OPERATION ");
  1899. if (bFlags & CRL_REASON_CERTIFICATE_HOLD_FLAG)
  1900. printf("CERTIFICATE_HOLD ");
  1901. printf("\n");
  1902. }
  1903. if (pPoint->CRLIssuer.cAltEntry) {
  1904. printf(" CRLIssuer:");
  1905. DisplayAltName(&pPoint->CRLIssuer, dwDisplayFlags);
  1906. }
  1907. }
  1908. }
  1909. CommonReturn:
  1910. if (pInfo)
  1911. TestFree(pInfo);
  1912. }
  1913. static void DisplayIssuingDistPointExtension(
  1914. BYTE *pbEncoded,
  1915. DWORD cbEncoded,
  1916. DWORD dwDisplayFlags)
  1917. {
  1918. PCRL_ISSUING_DIST_POINT pInfo = NULL;
  1919. DWORD i;
  1920. DWORD dwNameChoice;
  1921. if (NULL == (pInfo = (PCRL_ISSUING_DIST_POINT) TestNoCopyDecodeObject(
  1922. X509_ISSUING_DIST_POINT,
  1923. pbEncoded,
  1924. cbEncoded
  1925. ))) goto CommonReturn;
  1926. dwNameChoice = pInfo->DistPointName.dwDistPointNameChoice;
  1927. switch (dwNameChoice) {
  1928. case CRL_DIST_POINT_NO_NAME:
  1929. printf(" No DistPointName\n");
  1930. break;
  1931. case CRL_DIST_POINT_FULL_NAME:
  1932. printf(" DistPointName FullName:\n");
  1933. DisplayAltName(&pInfo->DistPointName.FullName,
  1934. dwDisplayFlags);
  1935. break;
  1936. case CRL_DIST_POINT_ISSUER_RDN_NAME:
  1937. printf(" DistPointName IssuerRDN: (Not Implemented)\n");
  1938. break;
  1939. default:
  1940. printf(" Unknown DistPointName choice: %d\n", dwNameChoice);
  1941. }
  1942. if (pInfo->fOnlyContainsUserCerts ||
  1943. pInfo->fOnlyContainsCACerts ||
  1944. pInfo->fIndirectCRL
  1945. ) {
  1946. printf(" ");
  1947. if (pInfo->fOnlyContainsUserCerts)
  1948. printf(" OnlyContainsUserCerts");
  1949. if (pInfo->fOnlyContainsCACerts)
  1950. printf(" OnlyContainsCACerts");
  1951. if (pInfo->fIndirectCRL)
  1952. printf(" IndirectCRL");
  1953. printf("\n");
  1954. }
  1955. if (pInfo->OnlySomeReasonFlags.cbData) {
  1956. BYTE bFlags;
  1957. printf(" OnlySomeReasonFlags: ");
  1958. bFlags = *pInfo->OnlySomeReasonFlags.pbData;
  1959. if (bFlags == 0)
  1960. printf("<NONE> ");
  1961. if (bFlags & CRL_REASON_UNUSED_FLAG)
  1962. printf("UNUSED ");
  1963. if (bFlags & CRL_REASON_KEY_COMPROMISE_FLAG)
  1964. printf("KEY_COMPROMISE ");
  1965. if (bFlags & CRL_REASON_CA_COMPROMISE_FLAG)
  1966. printf("CA_COMPROMISE ");
  1967. if (bFlags & CRL_REASON_AFFILIATION_CHANGED_FLAG)
  1968. printf("AFFILIATION_CHANGED ");
  1969. if (bFlags & CRL_REASON_SUPERSEDED_FLAG)
  1970. printf("SUPERSEDED ");
  1971. if (bFlags & CRL_REASON_CESSATION_OF_OPERATION_FLAG)
  1972. printf("CESSATION_OF_OPERATION ");
  1973. if (bFlags & CRL_REASON_CERTIFICATE_HOLD_FLAG)
  1974. printf("CERTIFICATE_HOLD ");
  1975. printf("\n");
  1976. }
  1977. CommonReturn:
  1978. if (pInfo)
  1979. TestFree(pInfo);
  1980. }
  1981. static void DisplaySETAccountAliasExtension(
  1982. BYTE *pbEncoded,
  1983. DWORD cbEncoded,
  1984. DWORD dwDisplayFlags)
  1985. {
  1986. BOOL bInfo = FALSE;
  1987. DWORD cbInfo;
  1988. cbInfo = sizeof(bInfo);
  1989. if (!CryptDecodeObject(
  1990. dwCertEncodingType,
  1991. szOID_SET_ACCOUNT_ALIAS,
  1992. pbEncoded,
  1993. cbEncoded,
  1994. 0, // dwFlags
  1995. &bInfo,
  1996. &cbInfo
  1997. )) {
  1998. PrintLastError("SETAccountAliasDecode");
  1999. goto CommonReturn;
  2000. }
  2001. if (bInfo)
  2002. printf(" SETAccountAlias:: TRUE\n");
  2003. else
  2004. printf(" SETAccountAlias:: FALSE\n");
  2005. CommonReturn:
  2006. return;
  2007. }
  2008. static void DisplaySETHashedRootKeyExtension(
  2009. BYTE *pbEncoded,
  2010. DWORD cbEncoded,
  2011. DWORD dwDisplayFlags)
  2012. {
  2013. BYTE rgbInfo[SET_HASHED_ROOT_LEN];
  2014. DWORD cbInfo;
  2015. cbInfo = sizeof(rgbInfo);
  2016. if (!CryptDecodeObject(
  2017. dwCertEncodingType,
  2018. szOID_SET_HASHED_ROOT_KEY,
  2019. pbEncoded,
  2020. cbEncoded,
  2021. 0, // dwFlags
  2022. rgbInfo,
  2023. &cbInfo
  2024. )) {
  2025. PrintLastError("SETHashedRootKeyDecode");
  2026. goto CommonReturn;
  2027. }
  2028. DisplayThumbprint(" SETHashedRootKey", rgbInfo, cbInfo);
  2029. CommonReturn:
  2030. return;
  2031. }
  2032. static void DisplaySETCertTypeExtension(
  2033. BYTE *pbEncoded,
  2034. DWORD cbEncoded,
  2035. DWORD dwDisplayFlags)
  2036. {
  2037. PCRYPT_BIT_BLOB pInfo;
  2038. if (NULL == (pInfo = (PCRYPT_BIT_BLOB) TestNoCopyDecodeObject(
  2039. szOID_SET_CERTIFICATE_TYPE,
  2040. pbEncoded,
  2041. cbEncoded
  2042. ))) goto ErrorReturn;
  2043. printf(" SETCertificateType:: ");
  2044. if (pInfo->cbData == 0)
  2045. printf("<NONE> ");
  2046. else {
  2047. DWORD cb;
  2048. BYTE *pb;
  2049. for (cb = pInfo->cbData, pb = pInfo->pbData; cb > 0; cb--, pb++)
  2050. printf(" %02X", *pb);
  2051. }
  2052. printf("\n");
  2053. goto CommonReturn;
  2054. ErrorReturn:
  2055. CommonReturn:
  2056. if (pInfo)
  2057. TestFree(pInfo);
  2058. }
  2059. static void DisplaySETMerchantDataExtension(
  2060. BYTE *pbEncoded,
  2061. DWORD cbEncoded,
  2062. DWORD dwDisplayFlags)
  2063. {
  2064. PSET_MERCHANT_DATA_INFO pInfo;
  2065. if (NULL == (pInfo = (PSET_MERCHANT_DATA_INFO) TestNoCopyDecodeObject(
  2066. szOID_SET_MERCHANT_DATA,
  2067. pbEncoded,
  2068. cbEncoded
  2069. ))) goto ErrorReturn;
  2070. printf(" SETMerchantData:: \n");
  2071. if(pInfo->pszMerID && *pInfo->pszMerID)
  2072. printf(" MerID: %s\n", pInfo->pszMerID);
  2073. if(pInfo->pszMerAcquirerBIN && *pInfo->pszMerAcquirerBIN)
  2074. printf(" MerAcquirerBIN: %s\n", pInfo->pszMerAcquirerBIN);
  2075. if(pInfo->pszMerTermID && *pInfo->pszMerTermID)
  2076. printf(" MerTermID: %s\n", pInfo->pszMerTermID);
  2077. if(pInfo->pszMerName && *pInfo->pszMerName)
  2078. printf(" MerName: %s\n", pInfo->pszMerName);
  2079. if(pInfo->pszMerCity && *pInfo->pszMerCity)
  2080. printf(" MerCity: %s\n", pInfo->pszMerCity);
  2081. if(pInfo->pszMerStateProvince && *pInfo->pszMerStateProvince)
  2082. printf(" MerStateProvince: %s\n", pInfo->pszMerStateProvince);
  2083. if(pInfo->pszMerPostalCode && *pInfo->pszMerPostalCode)
  2084. printf(" MerPostalCode: %s\n", pInfo->pszMerPostalCode);
  2085. if(pInfo->pszMerCountry && *pInfo->pszMerCountry)
  2086. printf(" MerCountry: %s\n", pInfo->pszMerCountry);
  2087. if(pInfo->pszMerPhone && *pInfo->pszMerPhone)
  2088. printf(" MerPhone: %s\n", pInfo->pszMerPhone);
  2089. if(pInfo->fMerPhoneRelease)
  2090. printf(" MerPhoneRelease: TRUE\n");
  2091. else
  2092. printf(" MerPhoneRelease: FALSE\n");
  2093. if(pInfo->fMerAuthFlag)
  2094. printf(" MerAuthFlag: TRUE\n");
  2095. else
  2096. printf(" MerAuthFlag: FALSE\n");
  2097. goto CommonReturn;
  2098. ErrorReturn:
  2099. CommonReturn:
  2100. if (pInfo)
  2101. TestFree(pInfo);
  2102. }
  2103. #pragma pack(1)
  2104. struct SplitGuid
  2105. {
  2106. DWORD dw1;
  2107. WORD w1;
  2108. WORD w2;
  2109. BYTE b[8];
  2110. };
  2111. #pragma pack()
  2112. static char *GuidText(GUID *pguid)
  2113. {
  2114. static char buf[39];
  2115. SplitGuid *psg = (SplitGuid *)pguid;
  2116. sprintf(buf, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
  2117. psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
  2118. psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
  2119. return buf;
  2120. }
  2121. void DisplaySpcLink(PSPC_LINK pSpcLink)
  2122. {
  2123. switch (pSpcLink->dwLinkChoice) {
  2124. case SPC_URL_LINK_CHOICE:
  2125. printf("URL=> %S\n", pSpcLink->pwszUrl);
  2126. break;
  2127. case SPC_MONIKER_LINK_CHOICE:
  2128. printf("%s\n", GuidText((GUID *) pSpcLink->Moniker.ClassId));
  2129. if (pSpcLink->Moniker.SerializedData.cbData) {
  2130. printf(" SerializedData::\n");
  2131. PrintBytes(" ", pSpcLink->Moniker.SerializedData.pbData,
  2132. pSpcLink->Moniker.SerializedData.cbData);
  2133. }
  2134. break;
  2135. case SPC_FILE_LINK_CHOICE:
  2136. printf("FILE=> %S\n", pSpcLink->pwszFile);
  2137. break;
  2138. default:
  2139. printf("Bad SPC Link Choice:: %d\n", pSpcLink->dwLinkChoice);
  2140. }
  2141. }
  2142. static void DisplaySpcSpAgencyExtension(
  2143. BYTE *pbEncoded,
  2144. DWORD cbEncoded,
  2145. DWORD dwDisplayFlags)
  2146. {
  2147. PSPC_SP_AGENCY_INFO pInfo;
  2148. if (NULL == (pInfo = (PSPC_SP_AGENCY_INFO) TestNoCopyDecodeObject(
  2149. SPC_SP_AGENCY_INFO_OBJID,
  2150. pbEncoded,
  2151. cbEncoded
  2152. ))) goto ErrorReturn;
  2153. printf(" SpAgencyInfo::\n");
  2154. if (pInfo->pPolicyInformation) {
  2155. printf(" PolicyInformation: ");
  2156. DisplaySpcLink(pInfo->pPolicyInformation);
  2157. }
  2158. if (pInfo->pwszPolicyDisplayText) {
  2159. printf(" PolicyDisplayText: %S\n", pInfo->pwszPolicyDisplayText);
  2160. }
  2161. if (pInfo->pLogoImage) {
  2162. PSPC_IMAGE pImage = pInfo->pLogoImage;
  2163. if (pImage->pImageLink) {
  2164. printf(" ImageLink: ");
  2165. DisplaySpcLink(pImage->pImageLink);
  2166. }
  2167. if (pImage->Bitmap.cbData) {
  2168. printf(" Bitmap:\n");
  2169. PrintBytes(" ", pImage->Bitmap.pbData, pImage->Bitmap.cbData);
  2170. }
  2171. if (pImage->Metafile.cbData) {
  2172. printf(" Metafile:\n");
  2173. PrintBytes(" ", pImage->Metafile.pbData,
  2174. pImage->Metafile.cbData);
  2175. }
  2176. if (pImage->EnhancedMetafile.cbData) {
  2177. printf(" EnhancedMetafile:\n");
  2178. PrintBytes(" ", pImage->EnhancedMetafile.pbData,
  2179. pImage->EnhancedMetafile.cbData);
  2180. }
  2181. if (pImage->GifFile.cbData) {
  2182. printf(" GifFile:\n");
  2183. PrintBytes(" ", pImage->GifFile.pbData,
  2184. pImage->GifFile.cbData);
  2185. }
  2186. }
  2187. if (pInfo->pLogoLink) {
  2188. printf(" LogoLink: ");
  2189. DisplaySpcLink(pInfo->pLogoLink);
  2190. }
  2191. goto CommonReturn;
  2192. ErrorReturn:
  2193. CommonReturn:
  2194. if (pInfo)
  2195. TestFree(pInfo);
  2196. }
  2197. static void DisplaySpcFinancialCriteriaExtension(
  2198. BYTE *pbEncoded,
  2199. DWORD cbEncoded,
  2200. DWORD dwDisplayFlags)
  2201. {
  2202. SPC_FINANCIAL_CRITERIA FinancialCriteria;
  2203. DWORD cbInfo = sizeof(FinancialCriteria);
  2204. if (!CryptDecodeObject(
  2205. dwCertEncodingType,
  2206. SPC_FINANCIAL_CRITERIA_OBJID,
  2207. pbEncoded,
  2208. cbEncoded,
  2209. 0, // dwFlags
  2210. &FinancialCriteria,
  2211. &cbInfo
  2212. )) {
  2213. PrintLastError("SpcFinancialCriteriaInfoDecode");
  2214. return;
  2215. }
  2216. printf(" FinancialCriteria:: ");
  2217. if (FinancialCriteria.fFinancialInfoAvailable)
  2218. printf("Financial Info Available.");
  2219. else
  2220. printf("NO Financial Info.");
  2221. if (FinancialCriteria.fMeetsCriteria)
  2222. printf(" Meets Criteria.");
  2223. else
  2224. printf(" Doesn't Meet Criteria.");
  2225. printf("\n");
  2226. }
  2227. static void DisplaySpcMinimalCriteriaExtension(
  2228. BYTE *pbEncoded,
  2229. DWORD cbEncoded,
  2230. DWORD dwDisplayFlags)
  2231. {
  2232. BOOL fMinimalCriteria;
  2233. DWORD cbInfo = sizeof(fMinimalCriteria);
  2234. if (!CryptDecodeObject(
  2235. dwCertEncodingType,
  2236. SPC_MINIMAL_CRITERIA_OBJID,
  2237. pbEncoded,
  2238. cbEncoded,
  2239. 0, // dwFlags
  2240. &fMinimalCriteria,
  2241. &cbInfo)) {
  2242. PrintLastError("SpcMinimalCriteriaInfoDecode");
  2243. return;
  2244. }
  2245. printf(" MinimalCriteria:: ");
  2246. if (fMinimalCriteria)
  2247. printf("Meets Minimal Criteria.");
  2248. else
  2249. printf("Doesn't Meet Minimal Criteria.");
  2250. printf("\n");
  2251. }
  2252. static void DisplayCommonNameExtension(
  2253. BYTE *pbEncoded,
  2254. DWORD cbEncoded,
  2255. DWORD dwDisplayFlags)
  2256. {
  2257. PCERT_NAME_VALUE pInfo = NULL;
  2258. LPWSTR pwsz = NULL;
  2259. DWORD cwsz;
  2260. if (NULL == (pInfo = (PCERT_NAME_VALUE) TestNoCopyDecodeObject(
  2261. X509_NAME_VALUE,
  2262. pbEncoded,
  2263. cbEncoded
  2264. ))) goto ErrorReturn;
  2265. cwsz = CertRDNValueToStrW(
  2266. pInfo->dwValueType,
  2267. &pInfo->Value,
  2268. NULL, // pwsz
  2269. 0 // cwsz
  2270. );
  2271. if (cwsz > 1) {
  2272. pwsz = (LPWSTR) TestAlloc(cwsz * sizeof(WCHAR));
  2273. if (pwsz)
  2274. CertRDNValueToStrW(
  2275. pInfo->dwValueType,
  2276. &pInfo->Value,
  2277. pwsz,
  2278. cwsz
  2279. );
  2280. }
  2281. printf(" CommonName:: ValueType: %d String: ", pInfo->dwValueType);
  2282. if (pwsz)
  2283. printf("%S\n", pwsz);
  2284. else
  2285. printf("NULL");
  2286. goto CommonReturn;
  2287. ErrorReturn:
  2288. CommonReturn:
  2289. if (pInfo)
  2290. TestFree(pInfo);
  2291. if (pwsz)
  2292. TestFree(pwsz);
  2293. }
  2294. static void DisplayCRLReason(
  2295. BYTE *pbEncoded,
  2296. DWORD cbEncoded,
  2297. DWORD dwDisplayFlags)
  2298. {
  2299. DWORD cbInfo;
  2300. int CRLReason;
  2301. cbInfo = sizeof(CRLReason);
  2302. if (!CryptDecodeObject(
  2303. dwCertEncodingType,
  2304. szOID_CRL_REASON_CODE,
  2305. pbEncoded,
  2306. cbEncoded,
  2307. 0, // dwFlags
  2308. &CRLReason,
  2309. &cbInfo
  2310. )) {
  2311. PrintLastError("CRLReason");
  2312. return;
  2313. }
  2314. printf(" CRL Reason:: ");
  2315. switch (CRLReason) {
  2316. case CRL_REASON_UNSPECIFIED:
  2317. printf("Unspecified");
  2318. break;
  2319. case CRL_REASON_KEY_COMPROMISE:
  2320. printf("Key Compromise");
  2321. break;
  2322. case CRL_REASON_CA_COMPROMISE:
  2323. printf("CA Compromise");
  2324. break;
  2325. case CRL_REASON_AFFILIATION_CHANGED:
  2326. printf("Affiliation Changed");
  2327. break;
  2328. case CRL_REASON_SUPERSEDED:
  2329. printf("Superseded");
  2330. break;
  2331. case CRL_REASON_CESSATION_OF_OPERATION:
  2332. printf("Cessation of Operation");
  2333. break;
  2334. case CRL_REASON_CERTIFICATE_HOLD:
  2335. printf("Certificate Hold");
  2336. break;
  2337. case CRL_REASON_REMOVE_FROM_CRL:
  2338. printf("Remove from CRL");
  2339. break;
  2340. default:
  2341. printf("%d", CRLReason);
  2342. break;
  2343. }
  2344. printf("\n");
  2345. }
  2346. static void PrintExtensions(DWORD cExt, PCERT_EXTENSION pExt, DWORD dwDisplayFlags)
  2347. {
  2348. DWORD i;
  2349. for (i = 0; i < cExt; i++, pExt++) {
  2350. LPSTR pszObjId = pExt->pszObjId;
  2351. if (pszObjId == NULL)
  2352. pszObjId = "<NULL OBJID>";
  2353. LPSTR pszCritical = pExt->fCritical ? "TRUE" : "FALSE";
  2354. printf("Extension[%d] %s (%S) Critical: %s::\n",
  2355. i, pszObjId, GetOIDName(pszObjId), pszCritical);
  2356. PrintBytes(" ", pExt->Value.pbData, pExt->Value.cbData);
  2357. if (strcmp(pszObjId, szOID_AUTHORITY_KEY_IDENTIFIER) == 0)
  2358. DisplayAuthorityKeyIdExtension(
  2359. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2360. else if (strcmp(pszObjId, szOID_AUTHORITY_KEY_IDENTIFIER2) == 0)
  2361. DisplayAuthorityKeyId2Extension(
  2362. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2363. else if (strcmp(pszObjId, szOID_AUTHORITY_INFO_ACCESS) == 0)
  2364. DisplayAuthorityInfoAccessExtension(
  2365. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2366. else if (strcmp(pszObjId, szOID_CRL_DIST_POINTS) == 0)
  2367. DisplayCrlDistPointsExtension(
  2368. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2369. else if (strcmp(pszObjId, szOID_SUBJECT_KEY_IDENTIFIER) == 0)
  2370. DisplayOctetString(" SubjectKeyIdentifer::",
  2371. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2372. else if (strcmp(pszObjId, szOID_KEY_ATTRIBUTES) == 0)
  2373. DisplayKeyAttrExtension(
  2374. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2375. else if (strcmp(pszObjId, szOID_SUBJECT_ALT_NAME) == 0)
  2376. DisplayAltNameExtension("Subject AltName",
  2377. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2378. else if (strcmp(pszObjId, szOID_ISSUER_ALT_NAME) == 0)
  2379. DisplayAltNameExtension("Issuer AltName",
  2380. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2381. else if (strcmp(pszObjId, szOID_SUBJECT_ALT_NAME2) == 0)
  2382. DisplayAltNameExtension("Subject AltName #2",
  2383. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2384. else if (strcmp(pszObjId, szOID_ISSUER_ALT_NAME2) == 0)
  2385. DisplayAltNameExtension("Issuer AltName #2",
  2386. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2387. else if (strcmp(pszObjId, szOID_NEXT_UPDATE_LOCATION) == 0)
  2388. DisplayAltNameExtension("NextUpdateLocation",
  2389. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2390. else if (strcmp(pszObjId, szOID_KEY_USAGE_RESTRICTION) == 0)
  2391. DisplayKeyUsageRestrictionExtension(
  2392. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2393. else if (strcmp(pszObjId, szOID_BASIC_CONSTRAINTS) == 0)
  2394. DisplayBasicConstraintsExtension(
  2395. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2396. else if (strcmp(pszObjId, szOID_KEY_USAGE) == 0)
  2397. DisplayKeyUsageExtension(
  2398. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2399. else if (strcmp(pszObjId, szOID_BASIC_CONSTRAINTS2) == 0)
  2400. DisplayBasicConstraints2Extension(
  2401. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2402. else if (strcmp(pszObjId, szOID_CERT_POLICIES) == 0)
  2403. DisplayPoliciesExtension("Certificate",
  2404. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2405. else if (strcmp(pszObjId, szOID_CERT_POLICIES_95) == 0)
  2406. DisplayPoliciesExtension("Certificate",
  2407. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2408. else if (strcmp(pszObjId, szOID_APPLICATION_CERT_POLICIES) == 0)
  2409. DisplayPoliciesExtension("Application",
  2410. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2411. else if (strcmp(pszObjId, szOID_SET_ACCOUNT_ALIAS) == 0)
  2412. DisplaySETAccountAliasExtension(
  2413. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2414. else if (strcmp(pszObjId, szOID_SET_HASHED_ROOT_KEY) == 0)
  2415. DisplaySETHashedRootKeyExtension(
  2416. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2417. else if (strcmp(pszObjId, szOID_SET_CERTIFICATE_TYPE) == 0)
  2418. DisplaySETCertTypeExtension(
  2419. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2420. else if (strcmp(pszObjId, szOID_SET_MERCHANT_DATA) == 0)
  2421. DisplaySETMerchantDataExtension(
  2422. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2423. else if (strcmp(pszObjId, SPC_SP_AGENCY_INFO_OBJID) == 0)
  2424. DisplaySpcSpAgencyExtension(
  2425. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2426. else if (strcmp(pszObjId, SPC_FINANCIAL_CRITERIA_OBJID) == 0)
  2427. DisplaySpcFinancialCriteriaExtension(
  2428. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2429. else if (strcmp(pszObjId, SPC_MINIMAL_CRITERIA_OBJID) == 0)
  2430. DisplaySpcMinimalCriteriaExtension(
  2431. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2432. else if (strcmp(pszObjId, szOID_COMMON_NAME) == 0)
  2433. DisplayCommonNameExtension(
  2434. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2435. else if (strcmp(pszObjId, szOID_ENHANCED_KEY_USAGE) == 0)
  2436. DisplayEnhancedKeyUsageExtension(
  2437. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2438. else if (strcmp(pszObjId, szOID_RSA_SMIMECapabilities) == 0)
  2439. DisplaySMIMECapabilitiesExtension(
  2440. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2441. // CRL extensions
  2442. else if (strcmp(pszObjId, szOID_CRL_REASON_CODE) == 0)
  2443. DisplayCRLReason(
  2444. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2445. else if (strcmp(pszObjId, szOID_CRL_NUMBER) == 0)
  2446. DisplayInteger(
  2447. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2448. else if (strcmp(pszObjId, szOID_DELTA_CRL_INDICATOR) == 0)
  2449. DisplayInteger(
  2450. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2451. else if (strcmp(pszObjId, szOID_ISSUING_DIST_POINT) == 0)
  2452. DisplayIssuingDistPointExtension(
  2453. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2454. else if (strcmp(pszObjId, szOID_FRESHEST_CRL) == 0)
  2455. DisplayCrlDistPointsExtension(
  2456. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2457. else if (strcmp(pszObjId, szOID_NAME_CONSTRAINTS) == 0)
  2458. DisplayNameConstraintsExtension(
  2459. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2460. else if (strcmp(pszObjId, szOID_POLICY_MAPPINGS) == 0)
  2461. DisplayPolicyMappingsExtension(
  2462. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2463. else if (strcmp(pszObjId, szOID_LEGACY_POLICY_MAPPINGS) == 0)
  2464. DisplayPolicyMappingsExtension(
  2465. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2466. else if (strcmp(pszObjId, szOID_APPLICATION_POLICY_MAPPINGS) == 0)
  2467. DisplayPolicyMappingsExtension(
  2468. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2469. else if (strcmp(pszObjId, szOID_POLICY_CONSTRAINTS) == 0)
  2470. DisplayPolicyConstraintsExtension(
  2471. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2472. else if (strcmp(pszObjId, szOID_APPLICATION_POLICY_CONSTRAINTS) == 0)
  2473. DisplayPolicyConstraintsExtension(
  2474. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2475. else if (strcmp(pszObjId, szOID_CROSS_CERT_DIST_POINTS) == 0)
  2476. DisplayCrossCertDistPointsExtension(
  2477. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2478. // Netscape extensions
  2479. else if (strcmp(pszObjId, szOID_NETSCAPE_CERT_TYPE) == 0)
  2480. DisplayBits(" NetscapeCertType::",
  2481. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2482. else if (strcmp(pszObjId, szOID_NETSCAPE_BASE_URL) == 0)
  2483. DisplayAnyString(" NetscapeBaseURL::",
  2484. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2485. else if (strcmp(pszObjId, szOID_NETSCAPE_REVOCATION_URL) == 0)
  2486. DisplayAnyString(" NetscapeRevocationURL::",
  2487. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2488. else if (strcmp(pszObjId, szOID_NETSCAPE_CA_REVOCATION_URL) == 0)
  2489. DisplayAnyString(" NetscapeCARevocationURL::",
  2490. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2491. else if (strcmp(pszObjId, szOID_NETSCAPE_CERT_RENEWAL_URL) == 0)
  2492. DisplayAnyString(" NetscapeCertRenewalURL::",
  2493. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2494. else if (strcmp(pszObjId, szOID_NETSCAPE_CA_POLICY_URL) == 0)
  2495. DisplayAnyString(" NetscapeCAPolicyURL::",
  2496. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2497. else if (strcmp(pszObjId, szOID_NETSCAPE_SSL_SERVER_NAME) == 0)
  2498. DisplayAnyString(" NetscapeSSLServerName::",
  2499. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2500. else if (strcmp(pszObjId, szOID_NETSCAPE_COMMENT) == 0)
  2501. DisplayAnyString(" NetscapeComment::",
  2502. pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
  2503. }
  2504. }
  2505. static void DecodeAndDisplayDSSParameters(
  2506. IN BYTE *pbData,
  2507. IN DWORD cbData
  2508. )
  2509. {
  2510. PCERT_DSS_PARAMETERS pDssParameters;
  2511. DWORD cbDssParameters;
  2512. if (pDssParameters =
  2513. (PCERT_DSS_PARAMETERS) TestNoCopyDecodeObject(
  2514. X509_DSS_PARAMETERS,
  2515. pbData,
  2516. cbData,
  2517. &cbDssParameters
  2518. )) {
  2519. DWORD cbKey = pDssParameters->p.cbData;
  2520. printf("DSS Key Length:: %d bytes, %d bits\n", cbKey,
  2521. cbKey*8);
  2522. printf("DSS P (little endian)::\n");
  2523. PrintBytes(" ", pDssParameters->p.pbData,
  2524. pDssParameters->p.cbData);
  2525. printf("DSS Q (little endian)::\n");
  2526. PrintBytes(" ", pDssParameters->q.pbData,
  2527. pDssParameters->q.cbData);
  2528. printf("DSS G (little endian)::\n");
  2529. PrintBytes(" ", pDssParameters->g.pbData,
  2530. pDssParameters->g.cbData);
  2531. TestFree(pDssParameters);
  2532. }
  2533. }
  2534. static void PrintAuxCertProperties(
  2535. PCCERT_CONTEXT pCert,
  2536. DWORD dwDisplayFlags
  2537. )
  2538. {
  2539. if (0 == (dwDisplayFlags & DISPLAY_VERBOSE_FLAG))
  2540. return;
  2541. DWORD dwPropId = 0;
  2542. while (dwPropId = CertEnumCertificateContextProperties(pCert, dwPropId)) {
  2543. switch (dwPropId) {
  2544. case CERT_KEY_PROV_INFO_PROP_ID:
  2545. case CERT_SHA1_HASH_PROP_ID:
  2546. case CERT_MD5_HASH_PROP_ID:
  2547. case CERT_SIGNATURE_HASH_PROP_ID:
  2548. case CERT_KEY_CONTEXT_PROP_ID:
  2549. case CERT_KEY_IDENTIFIER_PROP_ID:
  2550. // Formatted elsewhere
  2551. break;
  2552. default:
  2553. {
  2554. BYTE *pbData;
  2555. DWORD cbData;
  2556. if (CERT_ARCHIVED_PROP_ID == dwPropId)
  2557. printf("Archived PropId %d (0x%x) ::\n",
  2558. dwPropId, dwPropId);
  2559. else
  2560. printf("Aux PropId %d (0x%x) ::\n", dwPropId, dwPropId);
  2561. CertGetCertificateContextProperty(
  2562. pCert,
  2563. dwPropId,
  2564. NULL, // pvData
  2565. &cbData
  2566. );
  2567. if (cbData) {
  2568. if (pbData = (BYTE *) TestAlloc(cbData)) {
  2569. // Try without a large enough buffer
  2570. DWORD cbSmall = cbData - 1;
  2571. if (CertGetCertificateContextProperty(
  2572. pCert,
  2573. dwPropId,
  2574. pbData,
  2575. &cbSmall
  2576. ))
  2577. printf("failed => returned success for too small buffer\n");
  2578. else {
  2579. DWORD dwErr = GetLastError();
  2580. if (ERROR_MORE_DATA != dwErr)
  2581. printf("failed => returned: %d 0x%x instead of ERROR_MORE_DATA\n", dwErr, dwErr);
  2582. }
  2583. if (cbSmall != cbData)
  2584. printf("failed => wrong size returned for small buffer\n");
  2585. if (CertGetCertificateContextProperty(
  2586. pCert,
  2587. dwPropId,
  2588. pbData,
  2589. &cbData
  2590. )) {
  2591. PrintBytes(" ", pbData, cbData);
  2592. if (CERT_CTL_USAGE_PROP_ID == dwPropId) {
  2593. printf(" EnhancedKeyUsage::\n");
  2594. DecodeAndDisplayCtlUsage(pbData, cbData,
  2595. dwDisplayFlags);
  2596. } else if (CERT_CROSS_CERT_DIST_POINTS_PROP_ID ==
  2597. dwPropId) {
  2598. printf(" CrossCertDistPoints::\n");
  2599. DisplayCrossCertDistPointsExtension(
  2600. pbData, cbData, dwDisplayFlags);
  2601. #ifdef CERT_PUBKEY_ALG_PARA_PROP_ID
  2602. } else if (CERT_PUBKEY_ALG_PARA_PROP_ID ==
  2603. dwPropId) {
  2604. DecodeAndDisplayDSSParameters(pbData, cbData);
  2605. #endif
  2606. }
  2607. } else
  2608. printf(" ERROR getting property bytes\n");
  2609. TestFree(pbData);
  2610. }
  2611. } else
  2612. printf(" NO Property Bytes\n");
  2613. }
  2614. break;
  2615. }
  2616. }
  2617. }
  2618. //+-------------------------------------------------------------------------
  2619. // Reverses a buffer of bytes in place
  2620. //--------------------------------------------------------------------------
  2621. void
  2622. ReverseBytes(
  2623. IN OUT PBYTE pbIn,
  2624. IN DWORD cbIn
  2625. )
  2626. {
  2627. // reverse in place
  2628. PBYTE pbLo;
  2629. PBYTE pbHi;
  2630. BYTE bTmp;
  2631. for (pbLo = pbIn, pbHi = pbIn + cbIn - 1; pbLo < pbHi; pbHi--, pbLo++) {
  2632. bTmp = *pbHi;
  2633. *pbHi = *pbLo;
  2634. *pbLo = bTmp;
  2635. }
  2636. }
  2637. static void DisplaySignature(
  2638. BYTE *pbEncoded,
  2639. DWORD cbEncoded,
  2640. DWORD dwDisplayFlags
  2641. )
  2642. {
  2643. PCERT_SIGNED_CONTENT_INFO pSignedContent;
  2644. if (pSignedContent = (PCERT_SIGNED_CONTENT_INFO) TestNoCopyDecodeObject(
  2645. X509_CERT,
  2646. pbEncoded,
  2647. cbEncoded
  2648. )) {
  2649. LPSTR pszObjId;
  2650. pszObjId = pSignedContent->SignatureAlgorithm.pszObjId;
  2651. if (pszObjId == NULL)
  2652. pszObjId = "<NULL OBJID>";
  2653. printf("Content SignatureAlgorithm:: %s (%S)\n",
  2654. pszObjId, GetOIDName(pszObjId, CRYPT_SIGN_ALG_OID_GROUP_ID));
  2655. if (pSignedContent->SignatureAlgorithm.Parameters.cbData) {
  2656. printf("Content SignatureAlgorithm.Parameters::\n");
  2657. PrintBytes(" ",
  2658. pSignedContent->SignatureAlgorithm.Parameters.pbData,
  2659. pSignedContent->SignatureAlgorithm.Parameters.cbData);
  2660. }
  2661. if (pSignedContent->Signature.cbData) {
  2662. ALG_ID aiHash;
  2663. ALG_ID aiPubKey;
  2664. printf("Content Signature (little endian)::\n");
  2665. PrintBytes(" ", pSignedContent->Signature.pbData,
  2666. pSignedContent->Signature.cbData);
  2667. GetSignAlgids(pszObjId, &aiHash, &aiPubKey);
  2668. if (CALG_SHA == aiHash && CALG_DSS_SIGN == aiPubKey) {
  2669. BYTE *pbDssSignature;
  2670. DWORD cbDssSignature;
  2671. ReverseBytes(pSignedContent->Signature.pbData,
  2672. pSignedContent->Signature.cbData);
  2673. if (pbDssSignature =
  2674. (BYTE *) TestNoCopyDecodeObject(
  2675. X509_DSS_SIGNATURE,
  2676. pSignedContent->Signature.pbData,
  2677. pSignedContent->Signature.cbData,
  2678. &cbDssSignature
  2679. )) {
  2680. if (CERT_DSS_SIGNATURE_LEN == cbDssSignature) {
  2681. printf("DSS R (little endian)::\n");
  2682. PrintBytes(" ", pbDssSignature, CERT_DSS_R_LEN);
  2683. printf("DSS S (little endian)::\n");
  2684. PrintBytes(" ", pbDssSignature + CERT_DSS_R_LEN,
  2685. CERT_DSS_S_LEN);
  2686. } else {
  2687. printf("DSS Signature (unexpected length, little endian)::\n");
  2688. PrintBytes(" ", pbDssSignature, cbDssSignature);
  2689. }
  2690. TestFree(pbDssSignature);
  2691. }
  2692. }
  2693. } else
  2694. printf("Content Signature:: NONE\n");
  2695. printf("Content Length:: %d\n", pSignedContent->ToBeSigned.cbData);
  2696. TestFree(pSignedContent);
  2697. }
  2698. }
  2699. void DisplayStore(
  2700. IN HCERTSTORE hStore,
  2701. IN DWORD dwDisplayFlags
  2702. )
  2703. {
  2704. DWORD i;
  2705. DWORD dwFlags;
  2706. PCCERT_CONTEXT pCert;
  2707. PCCRL_CONTEXT pCrl;
  2708. PCCTL_CONTEXT pCtl;
  2709. printf("#### Certificates ####\n");
  2710. pCert = NULL;
  2711. i = 0;
  2712. while (pCert = CertEnumCertificatesInStore(hStore, pCert)) {
  2713. printf("===== %d =====\n", i);
  2714. DisplayCert(pCert, dwDisplayFlags);
  2715. i++;
  2716. }
  2717. printf("#### CRLs ####\n");
  2718. pCrl = NULL;
  2719. i = 0;
  2720. while (pCrl = CertEnumCRLsInStore(hStore, pCrl)) {
  2721. printf("===== %d =====\n", i);
  2722. DisplayCrl(pCrl, dwDisplayFlags);
  2723. i++;
  2724. }
  2725. printf("#### CTLs ####\n");
  2726. pCtl = NULL;
  2727. i = 0;
  2728. while (pCtl = CertEnumCTLsInStore(hStore, pCtl)) {
  2729. printf("===== %d =====\n", i);
  2730. DisplayCtl(pCtl, dwDisplayFlags);
  2731. i++;
  2732. }
  2733. }
  2734. // Not displayed when DISPLAY_BRIEF_FLAG is set
  2735. void DisplayCertKeyProvInfo(
  2736. PCCERT_CONTEXT pCert,
  2737. DWORD dwDisplayFlags
  2738. )
  2739. {
  2740. PCRYPT_KEY_PROV_INFO pInfo = NULL;
  2741. DWORD cbInfo;
  2742. if (dwDisplayFlags & DISPLAY_BRIEF_FLAG)
  2743. return;
  2744. cbInfo = 0;
  2745. CertGetCertificateContextProperty(
  2746. pCert,
  2747. CERT_KEY_PROV_INFO_PROP_ID,
  2748. NULL, // pvData
  2749. &cbInfo
  2750. );
  2751. if (cbInfo) {
  2752. pInfo = (PCRYPT_KEY_PROV_INFO) TestAlloc(cbInfo);
  2753. if (pInfo) {
  2754. // Try without a large enough buffer
  2755. DWORD cbSmall = cbInfo - 1;
  2756. if (CertGetCertificateContextProperty(
  2757. pCert,
  2758. CERT_KEY_PROV_INFO_PROP_ID,
  2759. pInfo,
  2760. &cbSmall
  2761. ))
  2762. printf("failed => returned success for too small buffer\n");
  2763. else {
  2764. DWORD dwErr = GetLastError();
  2765. if (ERROR_MORE_DATA != dwErr)
  2766. printf("failed => returned: %d 0x%x instead of ERROR_MORE_DATA\n", dwErr, dwErr);
  2767. }
  2768. if (cbSmall != cbInfo)
  2769. printf("failed => wrong size returned for small buffer\n");
  2770. if (CertGetCertificateContextProperty(
  2771. pCert,
  2772. CERT_KEY_PROV_INFO_PROP_ID,
  2773. pInfo,
  2774. &cbInfo
  2775. )) {
  2776. printf("Key Provider:: Type: %d", pInfo->dwProvType);
  2777. if (pInfo->pwszProvName)
  2778. printf(" Name: %S", pInfo->pwszProvName);
  2779. if (pInfo->dwFlags) {
  2780. printf(" Flags: 0x%x", pInfo->dwFlags);
  2781. if (pInfo->dwFlags & CRYPT_MACHINE_KEYSET)
  2782. printf(" (MACHINE_KEYSET)");
  2783. if (pInfo->dwFlags & CERT_SET_KEY_CONTEXT_PROP_ID)
  2784. printf(" (SET_KEY_CONTEXT_PROP)");
  2785. printf(" ");
  2786. }
  2787. if (pInfo->pwszContainerName)
  2788. printf(" Container: %S", pInfo->pwszContainerName);
  2789. if (pInfo->dwKeySpec)
  2790. printf(" KeySpec: %d", pInfo->dwKeySpec);
  2791. printf("\n");
  2792. if (pInfo->cProvParam) {
  2793. DWORD i;
  2794. printf("Key Provider Params::\n");
  2795. for (i = 0; i < pInfo->cProvParam; i++) {
  2796. PCRYPT_KEY_PROV_PARAM pParam =
  2797. &pInfo->rgProvParam[i];
  2798. printf(" [%d] dwParam: 0x%x dwFlags: 0x%x\n",
  2799. i, pParam->dwParam, pParam->dwFlags);
  2800. if (pParam->cbData)
  2801. PrintBytes(" ",
  2802. pParam->pbData, pParam->cbData);
  2803. }
  2804. }
  2805. } else
  2806. PrintLastError("CertGetCertificateContextProperty");
  2807. TestFree(pInfo);
  2808. }
  2809. }
  2810. }
  2811. void DisplayFriendlyName(
  2812. IN PCCERT_CONTEXT pCertContext,
  2813. IN DWORD dwDisplayFlags
  2814. )
  2815. {
  2816. DWORD cch;
  2817. LPWSTR pwsz = NULL;
  2818. if (0 == (dwDisplayFlags & DISPLAY_VERBOSE_FLAG))
  2819. return;
  2820. cch = CertGetNameStringW(
  2821. pCertContext,
  2822. CERT_NAME_FRIENDLY_DISPLAY_TYPE,
  2823. 0, // dwFlags
  2824. NULL, // pvTypePara
  2825. NULL, // pwsz
  2826. 0); // cch
  2827. if (cch <= 1) {
  2828. DWORD dwErr = GetLastError();
  2829. printf("failed => CertGetNameStringW returned empty string\n");
  2830. } else if (pwsz = (LPWSTR) TestAlloc(cch * sizeof(WCHAR))) {
  2831. cch = CertGetNameStringW(
  2832. pCertContext,
  2833. CERT_NAME_FRIENDLY_DISPLAY_TYPE,
  2834. 0, // dwFlags
  2835. NULL, // pvTypePara
  2836. pwsz,
  2837. cch);
  2838. printf("Friendly Name:: <%S>\n", pwsz);
  2839. TestFree(pwsz);
  2840. }
  2841. }
  2842. void DisplayUPN(
  2843. IN PCCERT_CONTEXT pCertContext,
  2844. IN DWORD dwDisplayFlags
  2845. )
  2846. {
  2847. DWORD cch;
  2848. LPWSTR pwsz = NULL;
  2849. if (0 == (dwDisplayFlags & DISPLAY_VERBOSE_FLAG))
  2850. return;
  2851. cch = CertGetNameStringW(
  2852. pCertContext,
  2853. CERT_NAME_UPN_TYPE,
  2854. 0, // dwFlags
  2855. NULL, // pvTypePara
  2856. NULL, // pwsz
  2857. 0); // cch
  2858. if (cch <= 1) {
  2859. ;
  2860. } else if (pwsz = (LPWSTR) TestAlloc(cch * sizeof(WCHAR))) {
  2861. cch = CertGetNameStringW(
  2862. pCertContext,
  2863. CERT_NAME_UPN_TYPE,
  2864. 0, // dwFlags
  2865. NULL, // pvTypePara
  2866. pwsz,
  2867. cch);
  2868. printf("UPN Name:: <%S>\n", pwsz);
  2869. TestFree(pwsz);
  2870. }
  2871. }
  2872. void DisplayCert(
  2873. PCCERT_CONTEXT pCert,
  2874. DWORD dwDisplayFlags,
  2875. DWORD dwIssuer
  2876. )
  2877. {
  2878. DisplayCert2(
  2879. pCert->hCertStore,
  2880. pCert,
  2881. dwDisplayFlags,
  2882. dwIssuer
  2883. );
  2884. }
  2885. typedef BOOL (WINAPI *PFN_CRYPT_UI_DLG_VIEW_CONTEXT)(
  2886. IN DWORD dwContextType,
  2887. IN const void *pvContext,
  2888. IN OPTIONAL HWND hwnd, // Defaults to the desktop window
  2889. IN OPTIONAL LPCWSTR pwszTitle, // Defaults to the context type title
  2890. IN DWORD dwFlags,
  2891. IN void *pvReserved
  2892. );
  2893. void DisplayContextUI(
  2894. IN DWORD dwContextType,
  2895. IN const void *pvContext
  2896. )
  2897. {
  2898. HMODULE hDll = NULL;
  2899. PFN_CRYPT_UI_DLG_VIEW_CONTEXT pfnCryptUIDlgViewContext;
  2900. if (NULL == (hDll = LoadLibraryA("cryptui.dll"))) {
  2901. PrintLastError("LoadLibraryA(cryptui.dll)");
  2902. goto CommonReturn;
  2903. }
  2904. if (NULL == (pfnCryptUIDlgViewContext =
  2905. (PFN_CRYPT_UI_DLG_VIEW_CONTEXT) GetProcAddress(hDll,
  2906. "CryptUIDlgViewContext"))) {
  2907. PrintLastError("GetProcAddress(CryptUIDlgViewContext)");
  2908. goto CommonReturn;
  2909. }
  2910. if (!pfnCryptUIDlgViewContext(
  2911. dwContextType,
  2912. pvContext,
  2913. NULL, // hHwnd
  2914. NULL, // pwszTitle
  2915. 0, // dwFlags
  2916. NULL // pvReserved
  2917. ))
  2918. PrintLastError("CryptUIDlgViewContext");
  2919. CommonReturn:
  2920. if (hDll)
  2921. FreeLibrary(hDll);
  2922. }
  2923. void DisplayCert2(
  2924. HCERTSTORE hStore,
  2925. PCCERT_CONTEXT pCert,
  2926. DWORD dwDisplayFlags,
  2927. DWORD dwIssuer
  2928. )
  2929. {
  2930. if (dwDisplayFlags & DISPLAY_UI_FLAG) {
  2931. DisplayContextUI(CERT_STORE_CERTIFICATE_CONTEXT, pCert);
  2932. dwDisplayFlags = DISPLAY_BRIEF_FLAG;
  2933. }
  2934. DisplayFriendlyName(pCert, dwDisplayFlags);
  2935. DisplayUPN(pCert, dwDisplayFlags);
  2936. printf("Subject::\n");
  2937. DecodeName(pCert->pCertInfo->Subject.pbData,
  2938. pCert->pCertInfo->Subject.cbData, dwDisplayFlags);
  2939. if (!(dwDisplayFlags & DISPLAY_BRIEF_FLAG)) {
  2940. printf("Issuer::\n");
  2941. DecodeName(pCert->pCertInfo->Issuer.pbData,
  2942. pCert->pCertInfo->Issuer.cbData, dwDisplayFlags);
  2943. {
  2944. printf("SerialNumber::");
  2945. DisplaySerialNumber(&pCert->pCertInfo->SerialNumber);
  2946. printf("\n");
  2947. }
  2948. }
  2949. {
  2950. BYTE rgbHash[MAX_HASH_LEN];
  2951. DWORD cbHash = MAX_HASH_LEN;
  2952. #define MAX_KEY_ID_LEN 128
  2953. BYTE rgbKeyId[MAX_KEY_ID_LEN];
  2954. DWORD cbKeyId;
  2955. CertGetCertificateContextProperty(
  2956. pCert,
  2957. CERT_SHA1_HASH_PROP_ID,
  2958. rgbHash,
  2959. &cbHash
  2960. );
  2961. DisplayThumbprint("SHA1", rgbHash, cbHash);
  2962. cbHash = MAX_HASH_LEN;
  2963. CertGetCertificateContextProperty(
  2964. pCert,
  2965. CERT_MD5_HASH_PROP_ID,
  2966. rgbHash,
  2967. &cbHash
  2968. );
  2969. DisplayThumbprint("MD5", rgbHash, cbHash);
  2970. cbHash = MAX_HASH_LEN;
  2971. CertGetCertificateContextProperty(
  2972. pCert,
  2973. CERT_SIGNATURE_HASH_PROP_ID,
  2974. rgbHash,
  2975. &cbHash
  2976. );
  2977. DisplayThumbprint("Signature", rgbHash, cbHash);
  2978. cbKeyId = MAX_KEY_ID_LEN;
  2979. if (CertGetCertificateContextProperty(
  2980. pCert,
  2981. CERT_KEY_IDENTIFIER_PROP_ID,
  2982. rgbKeyId,
  2983. &cbKeyId
  2984. ))
  2985. DisplayThumbprint("KeyIdentifier", rgbKeyId, cbKeyId);
  2986. else
  2987. PrintLastError(
  2988. "CertGetCertificateContextProperty(KEY_IDENTIFIER)");
  2989. cbKeyId = MAX_KEY_ID_LEN;
  2990. if (CryptHashPublicKeyInfo(
  2991. NULL, // hCryptProv
  2992. CALG_SHA1,
  2993. 0, // dwFlags
  2994. X509_ASN_ENCODING,
  2995. &pCert->pCertInfo->SubjectPublicKeyInfo,
  2996. rgbKeyId,
  2997. &cbKeyId
  2998. ))
  2999. DisplayThumbprint("SHA1 KeyIdentifier", rgbKeyId, cbKeyId);
  3000. else
  3001. PrintLastError(
  3002. "CertGetCertificateContextProperty(SHA1 KEY_IDENTIFIER)");
  3003. if (dwDisplayFlags & DISPLAY_KEY_THUMB_FLAG) {
  3004. HCRYPTPROV hProv = 0;
  3005. CryptAcquireContext(
  3006. &hProv,
  3007. NULL,
  3008. NULL, // pszProvider
  3009. PROV_RSA_FULL,
  3010. CRYPT_VERIFYCONTEXT
  3011. );
  3012. if (hProv) {
  3013. cbHash = MAX_HASH_LEN;
  3014. CryptHashPublicKeyInfo(
  3015. hProv,
  3016. CALG_MD5,
  3017. 0, // dwFlags
  3018. dwCertEncodingType,
  3019. &pCert->pCertInfo->SubjectPublicKeyInfo,
  3020. rgbHash,
  3021. &cbHash
  3022. );
  3023. DisplayThumbprint("Key (MD5)", rgbHash, cbHash);
  3024. CryptReleaseContext(hProv, 0);
  3025. }
  3026. }
  3027. }
  3028. DisplayCertKeyProvInfo(pCert);
  3029. if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
  3030. DWORD dwAccessStateFlags;
  3031. DWORD cbData = sizeof(dwAccessStateFlags);
  3032. CertGetCertificateContextProperty(
  3033. pCert,
  3034. CERT_ACCESS_STATE_PROP_ID,
  3035. &dwAccessStateFlags,
  3036. &cbData
  3037. );
  3038. if (0 == cbData)
  3039. printf("No AccessState PropId\n");
  3040. else {
  3041. printf("AccessState PropId dwFlags:: 0x%x", dwAccessStateFlags);
  3042. if (dwAccessStateFlags & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG)
  3043. printf(" WRITE_PERSIST");
  3044. if (dwAccessStateFlags & CERT_ACCESS_STATE_SYSTEM_STORE_FLAG)
  3045. printf(" SYSTEM_STORE");
  3046. if (dwAccessStateFlags & CERT_ACCESS_STATE_LM_SYSTEM_STORE_FLAG)
  3047. printf(" LM_SYSTEM_STORE");
  3048. printf("\n");
  3049. }
  3050. }
  3051. PrintAuxCertProperties(pCert, dwDisplayFlags);
  3052. if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
  3053. LPSTR pszObjId;
  3054. ALG_ID aiPubKey;
  3055. DWORD dwBitLen;
  3056. printf("Version:: %d\n", pCert->pCertInfo->dwVersion);
  3057. pszObjId = pCert->pCertInfo->SignatureAlgorithm.pszObjId;
  3058. if (pszObjId == NULL)
  3059. pszObjId = "<NULL OBJID>";
  3060. printf("SignatureAlgorithm:: %s (%S)\n",
  3061. pszObjId, GetOIDName(pszObjId, CRYPT_SIGN_ALG_OID_GROUP_ID));
  3062. if (pCert->pCertInfo->SignatureAlgorithm.Parameters.cbData) {
  3063. printf("SignatureAlgorithm.Parameters::\n");
  3064. PrintBytes(" ",
  3065. pCert->pCertInfo->SignatureAlgorithm.Parameters.pbData,
  3066. pCert->pCertInfo->SignatureAlgorithm.Parameters.cbData);
  3067. }
  3068. printf("NotBefore:: %s\n", FileTimeText(&pCert->pCertInfo->NotBefore));
  3069. printf("NotAfter:: %s\n", FileTimeText(&pCert->pCertInfo->NotAfter));
  3070. pszObjId = pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId;
  3071. if (pszObjId == NULL)
  3072. pszObjId = "<NULL OBJID>";
  3073. printf("SubjectPublicKeyInfo.Algorithm:: %s (%S)\n",
  3074. pszObjId, GetOIDName(pszObjId, CRYPT_PUBKEY_ALG_OID_GROUP_ID));
  3075. aiPubKey = GetAlgid(pszObjId, CRYPT_PUBKEY_ALG_OID_GROUP_ID);
  3076. if (pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData) {
  3077. printf("SubjectPublicKeyInfo.Algorithm.Parameters::\n");
  3078. PrintBytes(" ",
  3079. pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData,
  3080. pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData);
  3081. if (NULL_ASN_TAG ==
  3082. *pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData)
  3083. {
  3084. // NULL parameters
  3085. } else if (CALG_DSS_SIGN == aiPubKey) {
  3086. DecodeAndDisplayDSSParameters(
  3087. pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData,
  3088. pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData);
  3089. } else if (CALG_DH_SF == aiPubKey || CALG_DH_EPHEM == aiPubKey) {
  3090. PCERT_X942_DH_PARAMETERS pDhParameters;
  3091. DWORD cbDhParameters;
  3092. if (pDhParameters =
  3093. (PCERT_X942_DH_PARAMETERS) TestNoCopyDecodeObject(
  3094. X942_DH_PARAMETERS,
  3095. pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData,
  3096. pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData,
  3097. &cbDhParameters
  3098. )) {
  3099. DWORD cbKey = pDhParameters->p.cbData;
  3100. printf("DH Key Length:: %d bytes, %d bits\n", cbKey,
  3101. cbKey*8);
  3102. printf("DH P (little endian)::\n");
  3103. PrintBytes(" ", pDhParameters->p.pbData,
  3104. pDhParameters->p.cbData);
  3105. printf("DH G (little endian)::\n");
  3106. PrintBytes(" ", pDhParameters->g.pbData,
  3107. pDhParameters->g.cbData);
  3108. if (pDhParameters->q.cbData) {
  3109. printf("DH Q (little endian)::\n");
  3110. PrintBytes(" ", pDhParameters->q.pbData,
  3111. pDhParameters->q.cbData);
  3112. }
  3113. if (pDhParameters->j.cbData) {
  3114. printf("DH J (little endian)::\n");
  3115. PrintBytes(" ", pDhParameters->j.pbData,
  3116. pDhParameters->j.cbData);
  3117. }
  3118. if (pDhParameters->pValidationParams) {
  3119. printf("DH seed ::\n");
  3120. PrintBytes(" ",
  3121. pDhParameters->pValidationParams->seed.pbData,
  3122. pDhParameters->pValidationParams->seed.cbData);
  3123. printf("DH pgenCounter:: %d (0x%x)\n",
  3124. pDhParameters->pValidationParams->pgenCounter,
  3125. pDhParameters->pValidationParams->pgenCounter);
  3126. }
  3127. TestFree(pDhParameters);
  3128. }
  3129. }
  3130. }
  3131. printf("SubjectPublicKeyInfo.PublicKey");
  3132. if (0 != (dwBitLen = CertGetPublicKeyLength(
  3133. dwCertEncodingType,
  3134. &pCert->pCertInfo->SubjectPublicKeyInfo)))
  3135. printf(" (BitLength: %d)", dwBitLen);
  3136. if (pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cUnusedBits)
  3137. printf(" (UnusedBits: %d)",
  3138. pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cUnusedBits);
  3139. printf("::\n");
  3140. if (pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData) {
  3141. PrintBytes(" ",
  3142. pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
  3143. pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData);
  3144. if (CALG_RSA_SIGN == aiPubKey || CALG_RSA_KEYX == aiPubKey) {
  3145. PUBLICKEYSTRUC *pPubKeyStruc;
  3146. DWORD cbPubKeyStruc;
  3147. printf("RSA_CSP_PUBLICKEYBLOB::\n");
  3148. if (pPubKeyStruc = (PUBLICKEYSTRUC *) TestNoCopyDecodeObject(
  3149. RSA_CSP_PUBLICKEYBLOB,
  3150. pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
  3151. pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
  3152. &cbPubKeyStruc
  3153. )) {
  3154. PrintBytes(" ", (BYTE *) pPubKeyStruc, cbPubKeyStruc);
  3155. TestFree(pPubKeyStruc);
  3156. }
  3157. } else if (CALG_DSS_SIGN == aiPubKey) {
  3158. PCRYPT_UINT_BLOB pDssPubKey;
  3159. DWORD cbDssPubKey;
  3160. printf("DSS Y (little endian)::\n");
  3161. if (pDssPubKey = (PCRYPT_UINT_BLOB) TestNoCopyDecodeObject(
  3162. X509_DSS_PUBLICKEY,
  3163. pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
  3164. pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
  3165. &cbDssPubKey
  3166. )) {
  3167. PrintBytes(" ", pDssPubKey->pbData, pDssPubKey->cbData);
  3168. TestFree(pDssPubKey);
  3169. }
  3170. } else if (CALG_DH_SF == aiPubKey || CALG_DH_EPHEM == aiPubKey) {
  3171. PCRYPT_UINT_BLOB pDhPubKey;
  3172. DWORD cbDhPubKey;
  3173. printf("DH Y (little endian)::\n");
  3174. if (pDhPubKey = (PCRYPT_UINT_BLOB) TestNoCopyDecodeObject(
  3175. X509_DH_PUBLICKEY,
  3176. pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
  3177. pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
  3178. &cbDhPubKey
  3179. )) {
  3180. PrintBytes(" ", pDhPubKey->pbData, pDhPubKey->cbData);
  3181. TestFree(pDhPubKey);
  3182. }
  3183. }
  3184. } else
  3185. printf(" No public key\n");
  3186. DisplaySignature(
  3187. pCert->pbCertEncoded,
  3188. pCert->cbCertEncoded,
  3189. dwDisplayFlags);
  3190. if (pCert->pCertInfo->IssuerUniqueId.cbData) {
  3191. printf("IssuerUniqueId");
  3192. if (pCert->pCertInfo->IssuerUniqueId.cUnusedBits)
  3193. printf(" (UnusedBits: %d)",
  3194. pCert->pCertInfo->IssuerUniqueId.cUnusedBits);
  3195. printf("::\n");
  3196. PrintBytes(" ", pCert->pCertInfo->IssuerUniqueId.pbData,
  3197. pCert->pCertInfo->IssuerUniqueId.cbData);
  3198. }
  3199. if (pCert->pCertInfo->SubjectUniqueId.cbData) {
  3200. printf("SubjectUniqueId");
  3201. if (pCert->pCertInfo->SubjectUniqueId.cUnusedBits)
  3202. printf(" (UnusedBits: %d)",
  3203. pCert->pCertInfo->SubjectUniqueId.cUnusedBits);
  3204. printf("::\n");
  3205. PrintBytes(" ", pCert->pCertInfo->SubjectUniqueId.pbData,
  3206. pCert->pCertInfo->SubjectUniqueId.cbData);
  3207. }
  3208. if (pCert->pCertInfo->cExtension != 0) {
  3209. PrintExtensions(pCert->pCertInfo->cExtension,
  3210. pCert->pCertInfo->rgExtension, dwDisplayFlags);
  3211. }
  3212. }
  3213. if (dwDisplayFlags & DISPLAY_CHECK_FLAG) {
  3214. // Display any CRLs associated with the certificate
  3215. PCCRL_CONTEXT pCrl = NULL;
  3216. PCCRL_CONTEXT pFindCrl = NULL;
  3217. DWORD dwFlags;
  3218. int i;
  3219. // i = 0 => BASE
  3220. // i = 1 => DELTA
  3221. for (i = 0; i <= 1; i++) {
  3222. while (TRUE) {
  3223. if (dwDisplayFlags &
  3224. (DISPLAY_CHECK_SIGN_FLAG | DISPLAY_CHECK_TIME_FLAG)) {
  3225. dwFlags = 0;
  3226. if (dwDisplayFlags & DISPLAY_CHECK_SIGN_FLAG)
  3227. dwFlags |= CERT_STORE_SIGNATURE_FLAG;
  3228. if (dwDisplayFlags & DISPLAY_CHECK_TIME_FLAG)
  3229. dwFlags |= CERT_STORE_TIME_VALIDITY_FLAG;
  3230. } else
  3231. dwFlags = CERT_STORE_SIGNATURE_FLAG |
  3232. CERT_STORE_TIME_VALIDITY_FLAG;
  3233. if (i == 0)
  3234. dwFlags |= CERT_STORE_BASE_CRL_FLAG;
  3235. else
  3236. dwFlags |= CERT_STORE_DELTA_CRL_FLAG;
  3237. pCrl = CertGetCRLFromStore(
  3238. hStore,
  3239. pCert,
  3240. pCrl,
  3241. &dwFlags
  3242. );
  3243. // Check that find comes up with the same CRL
  3244. pFindCrl = CertFindCRLInStore(
  3245. hStore,
  3246. pCert->dwCertEncodingType,
  3247. (i == 0) ? CRL_FIND_ISSUED_BY_BASE_FLAG :
  3248. CRL_FIND_ISSUED_BY_DELTA_FLAG,
  3249. CRL_FIND_ISSUED_BY,
  3250. (const void *) pCert,
  3251. pFindCrl
  3252. );
  3253. if (pCrl == NULL) {
  3254. if (pFindCrl != NULL) {
  3255. printf("failed => CertFindCRLInStore didn't return expected NULL\n");
  3256. CertFreeCRLContext(pFindCrl);
  3257. pFindCrl = NULL;
  3258. }
  3259. break;
  3260. } else if (pFindCrl == NULL) {
  3261. printf("failed => CertFindCRLInStore returned unexpected NULL\n");
  3262. CertFreeCRLContext(pCrl);
  3263. pCrl = NULL;
  3264. break;
  3265. }
  3266. if (!(pFindCrl->pbCrlEncoded == pCrl->pbCrlEncoded
  3267. ||
  3268. (pFindCrl->cbCrlEncoded == pCrl->cbCrlEncoded &&
  3269. 0 == memcmp(pFindCrl->pbCrlEncoded, pCrl->pbCrlEncoded,
  3270. pFindCrl->cbCrlEncoded))))
  3271. printf("failed => CertFindCRLInStore didn't match CertGetCRLFromStore\n");
  3272. if (i == 0)
  3273. printf("----- BASE CRL -----\n");
  3274. else
  3275. printf("----- DELTA CRL -----\n");
  3276. DisplayCrl(pCrl, dwDisplayFlags | DISPLAY_NO_ISSUER_FLAG);
  3277. DisplayVerifyFlags("CRL", dwFlags);
  3278. }
  3279. }
  3280. }
  3281. if (dwDisplayFlags & DISPLAY_CHECK_FLAG) {
  3282. BOOL fIssuer = FALSE;
  3283. PCCERT_CONTEXT pIssuer = NULL;
  3284. DWORD dwFlags;
  3285. while (TRUE) {
  3286. if (dwDisplayFlags &
  3287. (DISPLAY_CHECK_SIGN_FLAG | DISPLAY_CHECK_TIME_FLAG)) {
  3288. dwFlags = 0;
  3289. if (dwDisplayFlags & DISPLAY_CHECK_SIGN_FLAG)
  3290. dwFlags |= CERT_STORE_SIGNATURE_FLAG;
  3291. if (dwDisplayFlags & DISPLAY_CHECK_TIME_FLAG)
  3292. dwFlags |= CERT_STORE_TIME_VALIDITY_FLAG;
  3293. } else
  3294. dwFlags = CERT_STORE_SIGNATURE_FLAG |
  3295. CERT_STORE_TIME_VALIDITY_FLAG |
  3296. CERT_STORE_REVOCATION_FLAG;
  3297. pIssuer = CertGetIssuerCertificateFromStore(
  3298. hStore,
  3299. pCert,
  3300. pIssuer,
  3301. &dwFlags
  3302. );
  3303. if (pIssuer) {
  3304. printf("----- Issuer [%d] -----\n", dwIssuer);
  3305. DisplayVerifyFlags("Above Subject", dwFlags);
  3306. DisplayCert2(hStore, pIssuer, dwDisplayFlags, dwIssuer + 1);
  3307. fIssuer = TRUE;
  3308. } else {
  3309. DWORD dwErr = GetLastError();
  3310. if (dwErr == CRYPT_E_SELF_SIGNED) {
  3311. printf("----- Self Signed Issuer -----\n");
  3312. DisplayVerifyFlags("Issuer", dwFlags);
  3313. } else if (dwErr != CRYPT_E_NOT_FOUND)
  3314. PrintLastError("CertGetIssuerCertificateFromStore");
  3315. else if (!fIssuer) {
  3316. printf("----- No Issuer -----\n");
  3317. DisplayVerifyFlags("Above Subject", dwFlags);
  3318. }
  3319. break;
  3320. }
  3321. }
  3322. }
  3323. }
  3324. void PrintCrlEntries(
  3325. DWORD cEntry,
  3326. PCRL_ENTRY pEntry,
  3327. DWORD dwDisplayFlags
  3328. )
  3329. {
  3330. DWORD i;
  3331. for (i = 0; i < cEntry; i++, pEntry++) {
  3332. {
  3333. printf(" [%d] SerialNumber::", i);
  3334. DisplaySerialNumber(&pEntry->SerialNumber);
  3335. printf("\n");
  3336. }
  3337. if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
  3338. printf(" [%d] RevocationDate:: %s\n", i,
  3339. FileTimeText(&pEntry->RevocationDate));
  3340. if (pEntry->cExtension == 0)
  3341. printf(" [%d] Extensions:: NONE\n", i);
  3342. else {
  3343. printf(" [%d] Extensions::\n", i);
  3344. PrintExtensions(pEntry->cExtension, pEntry->rgExtension,
  3345. dwDisplayFlags);
  3346. }
  3347. }
  3348. }
  3349. }
  3350. static void PrintAuxCrlProperties(
  3351. PCCRL_CONTEXT pCrl,
  3352. DWORD dwDisplayFlags
  3353. )
  3354. {
  3355. if (0 == (dwDisplayFlags & DISPLAY_VERBOSE_FLAG))
  3356. return;
  3357. DWORD dwPropId = 0;
  3358. while (dwPropId = CertEnumCRLContextProperties(pCrl, dwPropId)) {
  3359. switch (dwPropId) {
  3360. case CERT_SHA1_HASH_PROP_ID:
  3361. case CERT_MD5_HASH_PROP_ID:
  3362. // Formatted elsewhere
  3363. break;
  3364. default:
  3365. {
  3366. BYTE *pbData;
  3367. DWORD cbData;
  3368. printf("Aux PropId %d (0x%x) ::\n", dwPropId, dwPropId);
  3369. CertGetCRLContextProperty(
  3370. pCrl,
  3371. dwPropId,
  3372. NULL, // pvData
  3373. &cbData
  3374. );
  3375. if (cbData) {
  3376. if (pbData = (BYTE *) TestAlloc(cbData)) {
  3377. if (CertGetCRLContextProperty(
  3378. pCrl,
  3379. dwPropId,
  3380. pbData,
  3381. &cbData
  3382. ))
  3383. PrintBytes(" ", pbData, cbData);
  3384. else
  3385. printf(" ERROR getting property bytes\n");
  3386. TestFree(pbData);
  3387. }
  3388. } else
  3389. printf(" NO Property Bytes\n");
  3390. }
  3391. break;
  3392. }
  3393. }
  3394. }
  3395. void DisplayCrl(PCCRL_CONTEXT pCrl, DWORD dwDisplayFlags)
  3396. {
  3397. if (dwDisplayFlags & DISPLAY_UI_FLAG) {
  3398. DisplayContextUI(CERT_STORE_CRL_CONTEXT, pCrl);
  3399. dwDisplayFlags = DISPLAY_BRIEF_FLAG;
  3400. }
  3401. if (!(dwDisplayFlags & DISPLAY_NO_ISSUER_FLAG)) {
  3402. printf("Issuer::\n");
  3403. DecodeName(pCrl->pCrlInfo->Issuer.pbData,
  3404. pCrl->pCrlInfo->Issuer.cbData, dwDisplayFlags);
  3405. }
  3406. printf("ThisUpdate:: %s\n", FileTimeText(&pCrl->pCrlInfo->ThisUpdate));
  3407. printf("NextUpdate:: %s\n", FileTimeText(&pCrl->pCrlInfo->NextUpdate));
  3408. {
  3409. BYTE rgbHash[MAX_HASH_LEN];
  3410. DWORD cbHash = MAX_HASH_LEN;
  3411. CertGetCRLContextProperty(
  3412. pCrl,
  3413. CERT_SHA1_HASH_PROP_ID,
  3414. rgbHash,
  3415. &cbHash
  3416. );
  3417. DisplayThumbprint("SHA1", rgbHash, cbHash);
  3418. cbHash = MAX_HASH_LEN;
  3419. CertGetCRLContextProperty(
  3420. pCrl,
  3421. CERT_MD5_HASH_PROP_ID,
  3422. rgbHash,
  3423. &cbHash
  3424. );
  3425. DisplayThumbprint("MD5", rgbHash, cbHash);
  3426. cbHash = MAX_HASH_LEN;
  3427. CertGetCRLContextProperty(
  3428. pCrl,
  3429. CERT_SIGNATURE_HASH_PROP_ID,
  3430. rgbHash,
  3431. &cbHash
  3432. );
  3433. DisplayThumbprint("Signature", rgbHash, cbHash);
  3434. }
  3435. PrintAuxCrlProperties(pCrl, dwDisplayFlags);
  3436. if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
  3437. LPSTR pszObjId;
  3438. printf("Version:: %d\n", pCrl->pCrlInfo->dwVersion);
  3439. pszObjId = pCrl->pCrlInfo->SignatureAlgorithm.pszObjId;
  3440. if (pszObjId == NULL)
  3441. pszObjId = "<NULL OBJID>";
  3442. printf("SignatureAlgorithm:: %s (%S)\n",
  3443. pszObjId, GetOIDName(pszObjId, CRYPT_SIGN_ALG_OID_GROUP_ID));
  3444. if (pCrl->pCrlInfo->SignatureAlgorithm.Parameters.cbData) {
  3445. printf("SignatureAlgorithm.Parameters::\n");
  3446. PrintBytes(" ",
  3447. pCrl->pCrlInfo->SignatureAlgorithm.Parameters.pbData,
  3448. pCrl->pCrlInfo->SignatureAlgorithm.Parameters.cbData);
  3449. }
  3450. if (pCrl->pCrlInfo->cExtension != 0) {
  3451. PrintExtensions(pCrl->pCrlInfo->cExtension,
  3452. pCrl->pCrlInfo->rgExtension,
  3453. dwDisplayFlags);
  3454. }
  3455. }
  3456. if (pCrl->pCrlInfo->cCRLEntry == 0)
  3457. printf("Entries:: NONE\n");
  3458. else {
  3459. printf("Entries::\n");
  3460. PrintCrlEntries(pCrl->pCrlInfo->cCRLEntry,
  3461. pCrl->pCrlInfo->rgCRLEntry, dwDisplayFlags);
  3462. }
  3463. }
  3464. static void PrintAttributes(DWORD cAttr, PCRYPT_ATTRIBUTE pAttr,
  3465. DWORD dwDisplayFlags)
  3466. {
  3467. DWORD i;
  3468. DWORD j;
  3469. for (i = 0; i < cAttr; i++, pAttr++) {
  3470. DWORD cValue = pAttr->cValue;
  3471. PCRYPT_ATTR_BLOB pValue = pAttr->rgValue;
  3472. LPSTR pszObjId = pAttr->pszObjId;
  3473. if (pszObjId == NULL)
  3474. pszObjId = "<NULL OBJID>";
  3475. if (cValue) {
  3476. for (j = 0; j < cValue; j++, pValue++) {
  3477. printf(" [%d,%d] %s\n", i, j, pszObjId);
  3478. if (pValue->cbData) {
  3479. PrintBytes(" ", pValue->pbData, pValue->cbData);
  3480. if (strcmp(pszObjId, szOID_NEXT_UPDATE_LOCATION) == 0) {
  3481. printf(" NextUpdateLocation::\n");
  3482. DecodeAndDisplayAltName(pValue->pbData, pValue->cbData,
  3483. dwDisplayFlags);
  3484. }
  3485. } else
  3486. printf(" NO Value Bytes\n");
  3487. }
  3488. } else
  3489. printf(" [%d] %s :: No Values\n", i, pszObjId);
  3490. }
  3491. }
  3492. static void PrintCtlEntries(
  3493. PCCTL_CONTEXT pCtl,
  3494. DWORD dwDisplayFlags,
  3495. HCERTSTORE hStore)
  3496. {
  3497. PCTL_INFO pInfo = pCtl->pCtlInfo;
  3498. DWORD cEntry = pInfo->cCTLEntry;
  3499. PCTL_ENTRY pEntry = pInfo->rgCTLEntry;
  3500. DWORD i;
  3501. DWORD Algid;
  3502. DWORD dwFindType;
  3503. Algid = CertOIDToAlgId(pInfo->SubjectAlgorithm.pszObjId);
  3504. switch (Algid) {
  3505. case CALG_SHA1:
  3506. dwFindType = CERT_FIND_SHA1_HASH;
  3507. break;
  3508. case CALG_MD5:
  3509. dwFindType = CERT_FIND_MD5_HASH;
  3510. break;
  3511. default:
  3512. dwFindType = 0;
  3513. }
  3514. for (i = 0; i < cEntry; i++, pEntry++) {
  3515. printf(" [%d] SubjectIdentifier::\n", i);
  3516. PrintBytes(" ",
  3517. pEntry->SubjectIdentifier.pbData,
  3518. pEntry->SubjectIdentifier.cbData);
  3519. if (hStore && dwFindType) {
  3520. PCCERT_CONTEXT pCert;
  3521. pCert = CertFindCertificateInStore(
  3522. hStore,
  3523. dwCertEncodingType,
  3524. 0, // dwFindFlags
  3525. dwFindType,
  3526. (void *) &pEntry->SubjectIdentifier,
  3527. NULL // pPrevCert
  3528. );
  3529. if (pCert) {
  3530. DWORD cwsz;
  3531. LPWSTR pwsz;
  3532. cwsz = CertNameToStrW(
  3533. dwCertEncodingType,
  3534. &pCert->pCertInfo->Subject,
  3535. CERT_SIMPLE_NAME_STR,
  3536. NULL, // pwsz
  3537. 0); // cwsz
  3538. if (pwsz = (LPWSTR) TestAlloc(cwsz * sizeof(WCHAR))) {
  3539. CertNameToStrW(
  3540. dwCertEncodingType,
  3541. &pCert->pCertInfo->Subject,
  3542. CERT_SIMPLE_NAME_STR,
  3543. pwsz,
  3544. cwsz);
  3545. printf(" Subject: %S\n", pwsz);
  3546. TestFree(pwsz);
  3547. }
  3548. CertFreeCertificateContext(pCert);
  3549. }
  3550. }
  3551. if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
  3552. if (pEntry->cAttribute) {
  3553. printf(" [%d] Attributes::\n", i);
  3554. PrintAttributes(pEntry->cAttribute, pEntry->rgAttribute,
  3555. dwDisplayFlags);
  3556. }
  3557. }
  3558. }
  3559. }
  3560. static void PrintAuxCtlProperties(
  3561. PCCTL_CONTEXT pCtl,
  3562. DWORD dwDisplayFlags
  3563. )
  3564. {
  3565. if (0 == (dwDisplayFlags & DISPLAY_VERBOSE_FLAG))
  3566. return;
  3567. DWORD dwPropId = 0;
  3568. while (dwPropId = CertEnumCTLContextProperties(pCtl, dwPropId)) {
  3569. switch (dwPropId) {
  3570. case CERT_SHA1_HASH_PROP_ID:
  3571. #if 0
  3572. case CERT_MD5_HASH_PROP_ID:
  3573. #endif
  3574. // Formatted elsewhere
  3575. break;
  3576. default:
  3577. {
  3578. BYTE *pbData;
  3579. DWORD cbData;
  3580. printf("Aux PropId %d (0x%x) ::\n", dwPropId, dwPropId);
  3581. CertGetCTLContextProperty(
  3582. pCtl,
  3583. dwPropId,
  3584. NULL, // pvData
  3585. &cbData
  3586. );
  3587. if (cbData) {
  3588. if (pbData = (BYTE *) TestAlloc(cbData)) {
  3589. if (CertGetCTLContextProperty(
  3590. pCtl,
  3591. dwPropId,
  3592. pbData,
  3593. &cbData
  3594. )) {
  3595. PrintBytes(" ", pbData, cbData);
  3596. if (CERT_NEXT_UPDATE_LOCATION_PROP_ID ==
  3597. dwPropId) {
  3598. printf(" NextUpdateLocation::\n");
  3599. DecodeAndDisplayAltName(pbData, cbData,
  3600. dwDisplayFlags);
  3601. }
  3602. } else
  3603. printf(" ERROR getting property bytes\n");
  3604. TestFree(pbData);
  3605. }
  3606. } else
  3607. printf(" NO Property Bytes\n");
  3608. }
  3609. break;
  3610. }
  3611. }
  3612. }
  3613. //+-------------------------------------------------------------------------
  3614. // Returns TRUE if the CTL is still time valid.
  3615. //
  3616. // A CTL without a NextUpdate is considered time valid.
  3617. //--------------------------------------------------------------------------
  3618. BOOL IsTimeValidCtl(
  3619. IN PCCTL_CONTEXT pCtl
  3620. )
  3621. {
  3622. PCTL_INFO pCtlInfo = pCtl->pCtlInfo;
  3623. SYSTEMTIME SystemTime;
  3624. FILETIME CurrentTime;
  3625. // Get current time to be used to determine if CTLs are time valid
  3626. GetSystemTime(&SystemTime);
  3627. SystemTimeToFileTime(&SystemTime, &CurrentTime);
  3628. // Note, NextUpdate is optional. When not present, its set to 0
  3629. if ((0 == pCtlInfo->NextUpdate.dwLowDateTime &&
  3630. 0 == pCtlInfo->NextUpdate.dwHighDateTime) ||
  3631. CompareFileTime(&pCtlInfo->NextUpdate, &CurrentTime) >= 0)
  3632. return TRUE;
  3633. else
  3634. return FALSE;
  3635. }
  3636. //+-------------------------------------------------------------------------
  3637. // Allocates and returns the specified cryptographic message parameter.
  3638. //--------------------------------------------------------------------------
  3639. static void *AllocAndGetMsgParam(
  3640. IN HCRYPTMSG hMsg,
  3641. IN DWORD dwParamType,
  3642. IN DWORD dwIndex,
  3643. OUT DWORD *pcbData
  3644. )
  3645. {
  3646. void *pvData;
  3647. DWORD cbData;
  3648. if (!CryptMsgGetParam(
  3649. hMsg,
  3650. dwParamType,
  3651. dwIndex,
  3652. NULL, // pvData
  3653. &cbData) || 0 == cbData)
  3654. goto ErrorReturn;
  3655. if (NULL == (pvData = TestAlloc(cbData)))
  3656. goto ErrorReturn;
  3657. if (!CryptMsgGetParam(
  3658. hMsg,
  3659. dwParamType,
  3660. dwIndex,
  3661. pvData,
  3662. &cbData)) {
  3663. TestFree(pvData);
  3664. goto ErrorReturn;
  3665. }
  3666. CommonReturn:
  3667. *pcbData = cbData;
  3668. return pvData;
  3669. ErrorReturn:
  3670. pvData = NULL;
  3671. cbData = 0;
  3672. goto CommonReturn;
  3673. }
  3674. void DisplaySignerInfo(
  3675. HCRYPTMSG hMsg,
  3676. DWORD dwSignerIndex,
  3677. DWORD dwDisplayFlags
  3678. )
  3679. {
  3680. DWORD cbData;
  3681. PCRYPT_ATTRIBUTES pAttrs;
  3682. if (pAttrs = (PCRYPT_ATTRIBUTES) AllocAndGetMsgParam(
  3683. hMsg,
  3684. CMSG_SIGNER_AUTH_ATTR_PARAM,
  3685. dwSignerIndex,
  3686. &cbData)) {
  3687. printf("----- Signer [%d] AuthenticatedAttributes -----\n",
  3688. dwSignerIndex);
  3689. PrintAttributes(pAttrs->cAttr, pAttrs->rgAttr, dwDisplayFlags);
  3690. TestFree(pAttrs);
  3691. }
  3692. if (pAttrs = (PCRYPT_ATTRIBUTES) AllocAndGetMsgParam(
  3693. hMsg,
  3694. CMSG_SIGNER_UNAUTH_ATTR_PARAM,
  3695. dwSignerIndex,
  3696. &cbData)) {
  3697. printf("----- Signer [%d] UnauthenticatedAttributes -----\n",
  3698. dwSignerIndex);
  3699. PrintAttributes(pAttrs->cAttr, pAttrs->rgAttr, dwDisplayFlags);
  3700. TestFree(pAttrs);
  3701. }
  3702. }
  3703. static BOOL CompareSortedAttributes(
  3704. IN DWORD dwSubject,
  3705. IN PCTL_ENTRY pEntry,
  3706. IN PCRYPT_DER_BLOB pEncodedAttributes
  3707. )
  3708. {
  3709. BOOL fResult;
  3710. PCRYPT_ATTRIBUTES pAttrs = NULL;
  3711. DWORD i;
  3712. if (0 == pEntry->cAttribute) {
  3713. if (0 != pEncodedAttributes->cbData) {
  3714. printf("failed => Didn't expect sorted attributes for subject %d\n",
  3715. dwSubject);
  3716. return FALSE;
  3717. } else
  3718. return TRUE;
  3719. }
  3720. if (0 == pEncodedAttributes->cbData) {
  3721. printf("failed => Expected sorted attributes for subject %d\n",
  3722. dwSubject);
  3723. return FALSE;
  3724. }
  3725. if (NULL == (pAttrs = (PCRYPT_ATTRIBUTES) TestNoCopyDecodeObject(
  3726. PKCS_ATTRIBUTES,
  3727. pEncodedAttributes->pbData,
  3728. pEncodedAttributes->cbData
  3729. )))
  3730. goto ErrorReturn;
  3731. if (pAttrs->cAttr != pEntry->cAttribute) {
  3732. printf("failed => Wrong number of sorted attributes for subject %d\n",
  3733. dwSubject);
  3734. goto ErrorReturn;
  3735. }
  3736. for (i = 0; i < pAttrs->cAttr; i++) {
  3737. PCRYPT_ATTRIBUTE pAttr = &pEntry->rgAttribute[i];
  3738. PCRYPT_ATTRIBUTE pSortedAttr = &pAttrs->rgAttr[i];
  3739. DWORD j;
  3740. if (0 != strcmp(pAttr->pszObjId, pSortedAttr->pszObjId)) {
  3741. printf("failed => wrong sorted attribute[%d] OID for subject %d\n",
  3742. i, dwSubject);
  3743. goto ErrorReturn;
  3744. }
  3745. if (pAttr->cValue != pSortedAttr->cValue) {
  3746. printf("failed => Wrong number of values for attribute[%d] for subject %d\n",
  3747. i, dwSubject);
  3748. goto ErrorReturn;
  3749. }
  3750. for (j = 0; j < pAttr->cValue; j++) {
  3751. PCRYPT_ATTR_BLOB pValue = &pAttr->rgValue[j];
  3752. PCRYPT_ATTR_BLOB pSortedValue = &pSortedAttr->rgValue[j];
  3753. if (pValue->cbData != pSortedValue->cbData ||
  3754. (0 != pValue->cbData &&
  3755. 0 != memcmp(pValue->pbData, pSortedValue->pbData,
  3756. pValue->cbData))) {
  3757. printf("failed => bad value[%d, %d] for subject %d\n",
  3758. i, j, dwSubject);
  3759. goto ErrorReturn;
  3760. }
  3761. }
  3762. }
  3763. fResult = TRUE;
  3764. CommonReturn:
  3765. TestFree(pAttrs);
  3766. return fResult;
  3767. ErrorReturn:
  3768. fResult = FALSE;
  3769. goto CommonReturn;
  3770. }
  3771. void DisplayCtl(PCCTL_CONTEXT pCtl, DWORD dwDisplayFlags, HCERTSTORE hStore)
  3772. {
  3773. PCTL_INFO pInfo = pCtl->pCtlInfo;
  3774. PCCTL_CONTEXT pSortedCtl;
  3775. if (dwDisplayFlags & DISPLAY_UI_FLAG) {
  3776. DisplayContextUI(CERT_STORE_CTL_CONTEXT, pCtl);
  3777. dwDisplayFlags = DISPLAY_BRIEF_FLAG;
  3778. }
  3779. // Test the creation of a sorted CTL. Its decoded output should match
  3780. // the normal decoded CTL.
  3781. if (NULL == (pSortedCtl = (PCCTL_CONTEXT) CertCreateContext(
  3782. CERT_STORE_CTL_CONTEXT,
  3783. pCtl->dwMsgAndCertEncodingType,
  3784. pCtl->pbCtlEncoded,
  3785. pCtl->cbCtlEncoded,
  3786. CERT_CREATE_CONTEXT_NOCOPY_FLAG |
  3787. CERT_CREATE_CONTEXT_SORTED_FLAG,
  3788. NULL // pCreatePara
  3789. )))
  3790. PrintLastError("CertCreateContext(CTL => NOCOPY, SORTED)");
  3791. else {
  3792. PCTL_INFO pSortedInfo = pSortedCtl->pCtlInfo;
  3793. DWORD cEntry = pInfo->cCTLEntry;
  3794. PCTL_ENTRY pEntry = pInfo->rgCTLEntry;
  3795. DWORD iEntry;
  3796. void *pvNextSubject;
  3797. CRYPT_DER_BLOB SubjectIdentifier;
  3798. CRYPT_DER_BLOB EncodedAttributes;
  3799. // Check that the sorted info matches
  3800. if (pSortedInfo->dwVersion != pInfo->dwVersion ||
  3801. pSortedInfo->SubjectUsage.cUsageIdentifier !=
  3802. pInfo->SubjectUsage.cUsageIdentifier ||
  3803. 0 != CompareFileTime(&pSortedInfo->ThisUpdate,
  3804. &pInfo->ThisUpdate) ||
  3805. 0 != CompareFileTime(&pSortedInfo->NextUpdate,
  3806. &pInfo->NextUpdate) ||
  3807. 0 != strcmp(pSortedInfo->SubjectAlgorithm.pszObjId,
  3808. pInfo->SubjectAlgorithm.pszObjId) ||
  3809. pSortedInfo->SubjectAlgorithm.Parameters.cbData !=
  3810. pInfo->SubjectAlgorithm.Parameters.cbData)
  3811. printf("failed => SortedCtl info doesn't match Ctl info\n");
  3812. else {
  3813. // Check that the sorted extensions match
  3814. DWORD cExt = pInfo->cExtension;
  3815. PCERT_EXTENSION pExt = pInfo->rgExtension;
  3816. DWORD cSortedExt = pSortedInfo->cExtension;
  3817. PCERT_EXTENSION pSortedExt = pSortedInfo->rgExtension;
  3818. if (cExt > 0 && 0 == strcmp(pExt->pszObjId, szOID_SORTED_CTL)) {
  3819. cExt--,
  3820. pExt++;
  3821. }
  3822. if (cSortedExt != cExt)
  3823. printf("failed => SortedCtl extension count doesn't match Ctl\n");
  3824. else {
  3825. for ( ; cExt; cExt--, pSortedExt++, pExt++) {
  3826. if (0 != strcmp(pSortedExt->pszObjId, pExt->pszObjId) ||
  3827. pSortedExt->fCritical != pExt->fCritical ||
  3828. pSortedExt->Value.cbData != pExt->Value.cbData) {
  3829. printf("failed => SortedCtl extension doesn't match Ctl\n");
  3830. break;
  3831. }
  3832. if (pSortedExt->Value.cbData && 0 != memcmp(
  3833. pSortedExt->Value.pbData, pExt->Value.pbData,
  3834. pSortedExt->Value.cbData)) {
  3835. printf("failed => SortedCtl extension doesn't match Ctl\n");
  3836. break;
  3837. }
  3838. }
  3839. }
  3840. }
  3841. pvNextSubject = NULL;
  3842. iEntry = 0;
  3843. while (CertEnumSubjectInSortedCTL(
  3844. pSortedCtl,
  3845. &pvNextSubject,
  3846. &SubjectIdentifier,
  3847. &EncodedAttributes
  3848. )) {
  3849. if (iEntry >= cEntry) {
  3850. printf( "failed => CertEnumSubjectInSortedCTL(too many subjects)\n");
  3851. break;
  3852. }
  3853. if (SubjectIdentifier.cbData !=
  3854. pEntry[iEntry].SubjectIdentifier.cbData ||
  3855. 0 != memcmp(SubjectIdentifier.pbData,
  3856. pEntry[iEntry].SubjectIdentifier.pbData,
  3857. SubjectIdentifier.cbData)) {
  3858. printf("failed => CertEnumSubjectsInSortedCTL(invalid subject %d)\n",
  3859. iEntry);
  3860. iEntry = cEntry;
  3861. break;
  3862. }
  3863. if (!CompareSortedAttributes(
  3864. iEntry,
  3865. &pEntry[iEntry],
  3866. &EncodedAttributes
  3867. )) {
  3868. iEntry = cEntry;
  3869. break;
  3870. }
  3871. iEntry++;
  3872. }
  3873. if (iEntry != cEntry)
  3874. printf( "failed => CertEnumSubjectInSortedCTL(missing subjects)\n");
  3875. if (0 == cEntry) {
  3876. BYTE rgbIdentifier[] = {0x1, 0x2};
  3877. SubjectIdentifier.pbData = rgbIdentifier;
  3878. SubjectIdentifier.cbData = sizeof(rgbIdentifier);
  3879. if (CertFindSubjectInSortedCTL(
  3880. &SubjectIdentifier,
  3881. pSortedCtl,
  3882. 0, // dwFlags
  3883. NULL, // pvReserved,
  3884. &EncodedAttributes
  3885. ))
  3886. printf("failed => CertFindSubjectInSortedCTL returned success for no entries\n");
  3887. else if (GetLastError() != CRYPT_E_NOT_FOUND)
  3888. printf("failed => CertFindSubjectInSortedCTL didn't return CRYPT_E_NOT_FOUND for no entries\n");
  3889. } else {
  3890. DWORD rgiEntry[] = {0, cEntry/3, cEntry/2, cEntry -1};
  3891. DWORD i;
  3892. for (i = 0; i < sizeof(rgiEntry) / sizeof(rgiEntry[0]); i++) {
  3893. iEntry = rgiEntry[i];
  3894. if (!CertFindSubjectInSortedCTL(
  3895. &pEntry[iEntry].SubjectIdentifier,
  3896. pSortedCtl,
  3897. 0, // dwFlags
  3898. NULL, // pvReserved,
  3899. &EncodedAttributes
  3900. )) {
  3901. PrintLastError("CertFindSubjectInSortedCTL");
  3902. break;
  3903. }
  3904. }
  3905. }
  3906. CertFreeCTLContext(pSortedCtl);
  3907. }
  3908. if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG)
  3909. printf("Version:: %d\n", pInfo->dwVersion);
  3910. {
  3911. DWORD cId;
  3912. LPSTR *ppszId;
  3913. DWORD i;
  3914. printf("SubjectUsage::\n");
  3915. cId = pInfo->SubjectUsage.cUsageIdentifier;
  3916. ppszId = pInfo->SubjectUsage.rgpszUsageIdentifier;
  3917. if (cId == 0)
  3918. printf(" No Usage Identifiers\n");
  3919. for (i = 0; i < cId; i++, ppszId++)
  3920. printf(" [%d] %s\n", i, *ppszId);
  3921. }
  3922. if (pInfo->ListIdentifier.cbData) {
  3923. printf("ListIdentifier::\n");
  3924. PrintBytes(" ",
  3925. pInfo->ListIdentifier.pbData,
  3926. pInfo->ListIdentifier.cbData);
  3927. }
  3928. if (pInfo->SequenceNumber.cbData) {
  3929. printf("SequenceNumber::");
  3930. DisplaySerialNumber(&pInfo->SequenceNumber);
  3931. printf("\n");
  3932. }
  3933. printf("ThisUpdate:: %s\n", FileTimeText(&pCtl->pCtlInfo->ThisUpdate));
  3934. printf("NextUpdate:: %s\n", FileTimeText(&pCtl->pCtlInfo->NextUpdate));
  3935. if (!IsTimeValidCtl(pCtl))
  3936. printf("****** Time Invalid CTL\n");
  3937. {
  3938. BYTE rgbHash[MAX_HASH_LEN];
  3939. DWORD cbHash = MAX_HASH_LEN;
  3940. CertGetCTLContextProperty(
  3941. pCtl,
  3942. CERT_SHA1_HASH_PROP_ID,
  3943. rgbHash,
  3944. &cbHash
  3945. );
  3946. DisplayThumbprint("SHA1", rgbHash, cbHash);
  3947. #if 0
  3948. CertGetCTLContextProperty(
  3949. pCtl,
  3950. CERT_MD5_HASH_PROP_ID,
  3951. rgbHash,
  3952. &cbHash
  3953. );
  3954. DisplayThumbprint("MD5", rgbHash, cbHash);
  3955. #endif
  3956. }
  3957. PrintAuxCtlProperties(pCtl, dwDisplayFlags);
  3958. if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
  3959. LPSTR pszObjId;
  3960. pszObjId = pInfo->SubjectAlgorithm.pszObjId;
  3961. if (pszObjId == NULL)
  3962. pszObjId = "<NULL OBJID>";
  3963. printf("SubjectAlgorithm:: %s\n", pszObjId);
  3964. if (pInfo->SubjectAlgorithm.Parameters.cbData) {
  3965. printf("SubjectAlgorithm.Parameters::\n");
  3966. PrintBytes(" ",
  3967. pInfo->SubjectAlgorithm.Parameters.pbData,
  3968. pInfo->SubjectAlgorithm.Parameters.cbData);
  3969. }
  3970. if (pInfo->cExtension != 0) {
  3971. PrintExtensions(pInfo->cExtension, pInfo->rgExtension,
  3972. dwDisplayFlags);
  3973. }
  3974. }
  3975. if (dwDisplayFlags & DISPLAY_NO_ISSUER_FLAG)
  3976. ;
  3977. else if (0 == (dwDisplayFlags & DISPLAY_VERBOSE_FLAG)) {
  3978. DWORD dwFlags;
  3979. PCCERT_CONTEXT pSigner;
  3980. if (dwDisplayFlags & DISPLAY_CHECK_FLAG)
  3981. dwFlags = 0;
  3982. else
  3983. dwFlags = CMSG_SIGNER_ONLY_FLAG;
  3984. if (CryptMsgGetAndVerifySigner(
  3985. pCtl->hCryptMsg,
  3986. 1, // cSignerStore
  3987. &hStore, // rghSignerStore
  3988. dwFlags,
  3989. &pSigner,
  3990. NULL // pdwSignerIndex
  3991. )) {
  3992. printf("----- Signer -----\n");
  3993. DisplayCert(pSigner, dwDisplayFlags & DISPLAY_BRIEF_FLAG);
  3994. CertFreeCertificateContext(pSigner);
  3995. } else {
  3996. DWORD dwErr = GetLastError();
  3997. if (CRYPT_E_NO_TRUSTED_SIGNER == dwErr)
  3998. printf("----- No Trusted Signer -----\n");
  3999. else {
  4000. printf("----- Signer -----\n");
  4001. PrintLastError("CryptMsgGetAndVerifySigner");
  4002. }
  4003. }
  4004. } else {
  4005. DWORD dwSignerCount;
  4006. DWORD cbData;
  4007. cbData = sizeof(dwSignerCount);
  4008. if (!CryptMsgGetParam(
  4009. pCtl->hCryptMsg,
  4010. CMSG_SIGNER_COUNT_PARAM,
  4011. 0, // dwIndex
  4012. &dwSignerCount,
  4013. &cbData)) {
  4014. printf("----- Signer -----\n");
  4015. PrintLastError("CryptMsgGetParam(SIGNER_COUNT)");
  4016. } else if (0 == dwSignerCount)
  4017. printf("----- No Signers -----\n");
  4018. else {
  4019. DWORD dwSignerIndex;
  4020. for (dwSignerIndex = 0; dwSignerIndex < dwSignerCount;
  4021. dwSignerIndex++) {
  4022. DWORD dwFlags;
  4023. PCCERT_CONTEXT pSigner;
  4024. dwFlags = CMSG_USE_SIGNER_INDEX_FLAG;
  4025. if (0 == (dwDisplayFlags & DISPLAY_CHECK_FLAG))
  4026. dwFlags |= CMSG_SIGNER_ONLY_FLAG;
  4027. if (CryptMsgGetAndVerifySigner(
  4028. pCtl->hCryptMsg,
  4029. 1, // cSignerStore
  4030. &hStore, // rghSignerStore
  4031. dwFlags,
  4032. &pSigner,
  4033. &dwSignerIndex
  4034. )) {
  4035. printf("----- Signer [%d] -----\n", dwSignerIndex);
  4036. DisplayCert(pSigner, 0);
  4037. CertFreeCertificateContext(pSigner);
  4038. } else {
  4039. DWORD dwErr = GetLastError();
  4040. if (CRYPT_E_NO_TRUSTED_SIGNER == dwErr)
  4041. printf("----- No Trusted Signer [%d] -----\n",
  4042. dwSignerIndex);
  4043. else {
  4044. printf("----- Signer [%d] -----\n", dwSignerIndex);
  4045. PrintLastError("CryptMsgGetAndVerifySigner");
  4046. }
  4047. }
  4048. DisplaySignerInfo(pCtl->hCryptMsg, dwSignerIndex,
  4049. dwDisplayFlags);
  4050. }
  4051. }
  4052. }
  4053. if (0 == (dwDisplayFlags & DISPLAY_BRIEF_FLAG)) {
  4054. if (pInfo->cCTLEntry == 0)
  4055. printf("----- No Entries -----\n");
  4056. else {
  4057. printf("----- Entries -----\n");
  4058. PrintCtlEntries(pCtl, dwDisplayFlags, hStore);
  4059. }
  4060. }
  4061. }