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.

2719 lines
66 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: verify.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include <pch.cpp>
  11. #pragma hdrstop
  12. #include "cscsp.h"
  13. #define __dwFILE__ __dwFILE_CERTUTIL_VERIFY_CPP__
  14. HRESULT
  15. cuVerifyKeyAuthority(
  16. IN CERT_NAME_BLOB const *pIssuer,
  17. IN CERT_INFO const *pCertInfoCA,
  18. IN BYTE const *pbData,
  19. IN DWORD cbData,
  20. IN BOOL fQuiet,
  21. OUT BOOL *pfKeyAuthorityMatch)
  22. {
  23. CERT_AUTHORITY_KEY_ID2_INFO const *pcaki = NULL;
  24. DWORD cbcaki;
  25. HRESULT hr = S_OK;
  26. BOOL fDisplayIssuer = !fQuiet && g_fVerbose;
  27. CERT_NAME_BLOB const *pAuthorityCertIssuerName = NULL;
  28. BYTE *pbHash = NULL;
  29. DWORD cbHash;
  30. *pfKeyAuthorityMatch = TRUE;
  31. if (!myDecodeKeyAuthority2(
  32. X509_ASN_ENCODING,
  33. pbData,
  34. cbData,
  35. CERTLIB_USE_LOCALALLOC,
  36. &pcaki,
  37. &cbcaki))
  38. {
  39. hr = myHLastError();
  40. _JumpError(hr, error, "myDecodeKeyAuthority(IssuerKey)");
  41. }
  42. if (0 != pcaki->KeyId.cbData)
  43. {
  44. //DumpHex(DH_NOTABPREFIX | 4, pcaki->KeyId.pbData, pcaki->KeyId.cbData);
  45. hr = myGetPublicKeyHash(
  46. pCertInfoCA,
  47. &pCertInfoCA->SubjectPublicKeyInfo,
  48. &pbHash,
  49. &cbHash);
  50. _JumpIfError(hr, error, "myGetPublicKeyHash");
  51. //DumpHex(DH_NOTABPREFIX | 4, pbHash, cbHash);
  52. if (cbHash == pcaki->KeyId.cbData &&
  53. 0 == memcmp(pbHash, pcaki->KeyId.pbData, cbHash))
  54. {
  55. if (!fQuiet)
  56. {
  57. wprintf(myLoadResourceString(IDS_KEYID_IS_KEYAUTHORITY)); // "CA Key Id matches Key Id"
  58. }
  59. }
  60. else
  61. {
  62. if (!fQuiet)
  63. {
  64. wprintf(wszNewLine);
  65. wprintf(myLoadResourceString(IDS_ERR_KEYID_NOT_KEYAUTHORITY)); // "ERROR: CA Key Id does not match Key Id"
  66. wprintf(wszNewLine);
  67. }
  68. *pfKeyAuthorityMatch = FALSE;
  69. }
  70. }
  71. else
  72. {
  73. if (!fQuiet)
  74. {
  75. wprintf(myLoadResourceString(IDS_NO_KEYID)); // "No Key Id"
  76. }
  77. }
  78. if (!fQuiet)
  79. {
  80. wprintf(wszNewLine);
  81. }
  82. if (1 == pcaki->AuthorityCertIssuer.cAltEntry &&
  83. CERT_ALT_NAME_DIRECTORY_NAME ==
  84. pcaki->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice)
  85. {
  86. pAuthorityCertIssuerName = &pcaki->AuthorityCertIssuer.rgAltEntry[0].DirectoryName;
  87. // The Issuer's Issuer name and the Issuer's SerialNumber combined
  88. // should uniquely identify the Issuer cert.
  89. // Verify Issuer's Issuer name:
  90. // -------- ------ ----
  91. if (!CertCompareCertificateName(
  92. X509_ASN_ENCODING,
  93. const_cast<CERT_NAME_BLOB *>(&pCertInfoCA->Issuer),
  94. const_cast<CERT_NAME_BLOB *>(pAuthorityCertIssuerName)))
  95. {
  96. // This API doesn't set LastError
  97. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  98. if (!fQuiet)
  99. {
  100. wprintf(wszNewLine);
  101. wprintf(
  102. myLoadResourceString(IDS_ERR_FORMAT_ISSUER_NOT_KEYAUTHORITY), // "ERROR: CA Issuer name does not match Key Authority name (%x)"
  103. hr);
  104. hr = S_OK;
  105. fDisplayIssuer = TRUE;
  106. }
  107. *pfKeyAuthorityMatch = FALSE;
  108. }
  109. else
  110. {
  111. if (!fQuiet)
  112. {
  113. wprintf(myLoadResourceString(IDS_ISSUER_IS_KEYAUTHORITY)); // "CA Issuer name matches Key Authority name"
  114. }
  115. }
  116. }
  117. else
  118. {
  119. if (!fQuiet)
  120. {
  121. wprintf(myLoadResourceString(IDS_NO_KEYAUTHORITY)); // "No Key Authority name"
  122. }
  123. }
  124. if (!fQuiet)
  125. {
  126. wprintf(wszNewLine);
  127. }
  128. if (0 != pcaki->AuthorityCertSerialNumber.cbData)
  129. {
  130. if (pCertInfoCA->SerialNumber.cbData !=
  131. pcaki->AuthorityCertSerialNumber.cbData ||
  132. 0 != memcmp(
  133. pCertInfoCA->SerialNumber.pbData,
  134. pcaki->AuthorityCertSerialNumber.pbData,
  135. pcaki->AuthorityCertSerialNumber.cbData))
  136. {
  137. if (!fQuiet)
  138. {
  139. wprintf(wszNewLine);
  140. wprintf(myLoadResourceString(IDS_SERIAL_NOT_KEYAUTHORITY)); // "ERROR: Issuer serial number does not match Key Authority"
  141. wprintf(wszNewLine);
  142. fDisplayIssuer = TRUE;
  143. }
  144. *pfKeyAuthorityMatch = FALSE;
  145. }
  146. else
  147. {
  148. if (!fQuiet)
  149. {
  150. wprintf(myLoadResourceString(IDS_SERIAL_IS_KEYAUTHORITY)); // "Issuer serial number matches Key Authority"
  151. }
  152. }
  153. }
  154. else
  155. {
  156. if (!fQuiet)
  157. {
  158. wprintf(myLoadResourceString(IDS_NO_KEYAUTHORITYSERIAL)); // "No Key Authority serial number"
  159. }
  160. }
  161. if (!fQuiet)
  162. {
  163. wprintf(wszNewLine);
  164. }
  165. if (!fQuiet && fDisplayIssuer)
  166. {
  167. hr = cuDisplayCertName(
  168. TRUE,
  169. NULL,
  170. myLoadResourceString(IDS_ISSUERNAME), // "Issuer Name"
  171. g_wszPad4,
  172. pIssuer,
  173. NULL);
  174. _JumpIfError(hr, error, "cuDisplayCertName(Issuer)");
  175. if (NULL != pAuthorityCertIssuerName)
  176. {
  177. hr = cuDisplayCertName(
  178. TRUE,
  179. NULL,
  180. myLoadResourceString(IDS_KEYAUTHORITYNAME), // "KeyAuthority
  181. g_wszPad4,
  182. pAuthorityCertIssuerName,
  183. NULL);
  184. _JumpIfError(hr, error, "cuDisplayCertName(KeyAuthority)");
  185. }
  186. wprintf(wszNewLine);
  187. wprintf(myLoadResourceString(IDS_KEYID)); // "KeyId:"
  188. wprintf(wszNewLine);
  189. DumpHex(DH_NOTABPREFIX | 4, pcaki->KeyId.pbData, pcaki->KeyId.cbData);
  190. wprintf(wszNewLine);
  191. hr = cuDumpSerial(
  192. NULL,
  193. IDS_KEYAUTHORITYSERIAL,
  194. &pcaki->AuthorityCertSerialNumber);
  195. _JumpIfError(hr, error, "cuDumpSerial");
  196. wprintf(wszNewLine);
  197. hr = cuDumpSerial(NULL, IDS_CASERIAL, &pCertInfoCA->SerialNumber);
  198. _JumpIfError(hr, error, "cuDumpSerial");
  199. }
  200. error:
  201. if (NULL != pcaki)
  202. {
  203. LocalFree(const_cast<CERT_AUTHORITY_KEY_ID2_INFO *>(pcaki));
  204. }
  205. if (NULL != pbHash)
  206. {
  207. LocalFree(pbHash);
  208. }
  209. return(hr);
  210. }
  211. static DWORD s_adwProvType[] =
  212. {
  213. PROV_RSA_FULL,
  214. PROV_RSA_SIG,
  215. PROV_DSS,
  216. PROV_FORTEZZA,
  217. PROV_MS_EXCHANGE,
  218. PROV_SSL,
  219. PROV_RSA_SCHANNEL,
  220. PROV_DSS_DH,
  221. PROV_EC_ECDSA_SIG,
  222. PROV_EC_ECNRA_SIG,
  223. PROV_EC_ECDSA_FULL,
  224. PROV_EC_ECNRA_FULL,
  225. PROV_DH_SCHANNEL,
  226. PROV_SPYRUS_LYNKS,
  227. PROV_RNG,
  228. PROV_INTEL_SEC,
  229. };
  230. HRESULT
  231. cuLoadKeys(
  232. OPTIONAL IN WCHAR const *pwszProvName,
  233. IN OUT DWORD *pdwProvType,
  234. IN WCHAR const *pwszKeyContainerName,
  235. IN BOOL fMachineKeyset,
  236. IN BOOL fSoftFail,
  237. OPTIONAL OUT HCRYPTPROV *phProv,
  238. OPTIONAL OUT CERT_PUBLIC_KEY_INFO **ppPubKeyInfo,
  239. OPTIONAL OUT CERT_PUBLIC_KEY_INFO **ppPubKeyInfoXchg)
  240. {
  241. HRESULT hr;
  242. HRESULT hr2;
  243. HCRYPTPROV hProv = NULL;
  244. DWORD cb;
  245. DWORD *pdwProvTypeT = pdwProvType;
  246. DWORD *pdwProvTypeEnd = &pdwProvTypeT[1];
  247. DWORD dwSilent = g_fCryptSilent? CRYPT_SILENT : 0;
  248. CERT_PUBLIC_KEY_INFO *pPubKeyInfo = NULL;
  249. CERT_PUBLIC_KEY_INFO *pPubKeyInfoXchg = NULL;
  250. if (NULL != phProv)
  251. {
  252. *phProv = NULL;
  253. }
  254. if (NULL != ppPubKeyInfo)
  255. {
  256. *ppPubKeyInfo = NULL;
  257. }
  258. if (NULL != ppPubKeyInfoXchg)
  259. {
  260. *ppPubKeyInfoXchg = NULL;
  261. }
  262. // If no provider type was specified, try them all
  263. if (0 == *pdwProvTypeT)
  264. {
  265. pdwProvTypeT = s_adwProvType;
  266. pdwProvTypeEnd = &s_adwProvType[ARRAYSIZE(s_adwProvType)];
  267. }
  268. hr = S_OK;
  269. for ( ; pdwProvTypeT < pdwProvTypeEnd; pdwProvTypeT++)
  270. {
  271. DBGPRINT((
  272. DBG_SS_CERTUTILI,
  273. "myCertSrvCryptAcquireContext(%ws, t=%x, f=%x, m=%x)\n",
  274. pwszKeyContainerName,
  275. *pdwProvTypeT,
  276. dwSilent,
  277. fMachineKeyset));
  278. if (myCertSrvCryptAcquireContext(
  279. &hProv,
  280. pwszKeyContainerName,
  281. pwszProvName,
  282. *pdwProvTypeT,
  283. dwSilent, // dwFlags
  284. fMachineKeyset))
  285. {
  286. hr = S_OK;
  287. break;
  288. }
  289. hr2 = myHLastError();
  290. if (S_OK == hr ||
  291. (NTE_BAD_PROV_TYPE != hr2 &&
  292. NTE_PROV_TYPE_NOT_DEF != hr2 &&
  293. NTE_BAD_KEYSET != hr2))
  294. {
  295. hr = hr2;
  296. }
  297. _PrintErrorStr2(
  298. hr2,
  299. "myCertSrvCryptAcquireContext",
  300. pwszKeyContainerName,
  301. hr2);
  302. if (NTE_BAD_FLAGS == hr2 &&
  303. PROV_MS_EXCHANGE == *pdwProvTypeT &&
  304. ((CRYPT_SILENT & dwSilent) || fMachineKeyset))
  305. {
  306. DBGPRINT((
  307. DBG_SS_CERTUTILI,
  308. "myCertSrvCryptAcquireContext(%ws, t=%x, f=%x, m=%x)\n",
  309. pwszKeyContainerName,
  310. *pdwProvTypeT,
  311. 0,
  312. FALSE));
  313. if (myCertSrvCryptAcquireContext(
  314. &hProv,
  315. pwszKeyContainerName,
  316. pwszProvName,
  317. *pdwProvTypeT,
  318. 0, // dwFlags
  319. FALSE))
  320. {
  321. hr = S_OK;
  322. break;
  323. }
  324. hr2 = myHLastError();
  325. _PrintErrorStr2(
  326. hr2,
  327. "myCertSrvCryptAcquireContext",
  328. pwszKeyContainerName,
  329. hr2);
  330. }
  331. }
  332. if (S_OK != hr)
  333. {
  334. cuPrintErrorAndString(
  335. L"CryptAcquireContext",
  336. 0,
  337. hr,
  338. pwszKeyContainerName);
  339. goto error;
  340. }
  341. // export the public key blob
  342. if (NULL != ppPubKeyInfo &&
  343. !myCryptExportPublicKeyInfo(
  344. hProv,
  345. AT_SIGNATURE,
  346. CERTLIB_USE_LOCALALLOC,
  347. &pPubKeyInfo,
  348. &cb))
  349. {
  350. hr = myHLastError();
  351. if (!fSoftFail)
  352. {
  353. cuPrintErrorAndString(
  354. L"CryptExportPublicKeyInfo",
  355. 0,
  356. hr,
  357. L"AT_SIGNATURE");
  358. goto error;
  359. }
  360. }
  361. if (NULL != ppPubKeyInfoXchg &&
  362. !myCryptExportPublicKeyInfo(
  363. hProv,
  364. AT_KEYEXCHANGE,
  365. CERTLIB_USE_LOCALALLOC,
  366. &pPubKeyInfoXchg,
  367. &cb))
  368. {
  369. hr = myHLastError();
  370. if (!fSoftFail)
  371. {
  372. cuPrintErrorAndString(
  373. L"CryptExportPublicKeyInfo",
  374. 0,
  375. hr,
  376. L"AT_KEYEXCHANGE");
  377. goto error;
  378. }
  379. }
  380. *pdwProvType = *pdwProvTypeT;
  381. if (NULL != phProv)
  382. {
  383. *phProv = hProv;
  384. hProv = NULL;
  385. }
  386. if (NULL != ppPubKeyInfo)
  387. {
  388. *ppPubKeyInfo = pPubKeyInfo;
  389. pPubKeyInfo = NULL;
  390. }
  391. if (NULL != ppPubKeyInfoXchg)
  392. {
  393. *ppPubKeyInfoXchg = pPubKeyInfoXchg;
  394. pPubKeyInfoXchg = NULL;
  395. }
  396. hr = S_OK;
  397. error:
  398. if (NULL != pPubKeyInfo)
  399. {
  400. LocalFree(pPubKeyInfo);
  401. }
  402. if (NULL != pPubKeyInfoXchg)
  403. {
  404. LocalFree(pPubKeyInfoXchg);
  405. }
  406. if (NULL != hProv)
  407. {
  408. CryptReleaseContext(hProv, 0);
  409. }
  410. return(hr);
  411. }
  412. HRESULT
  413. VerifyPrivateKey(
  414. IN CERT_CONTEXT const *pCertContextCA,
  415. IN WCHAR const *pwszSanitizedCA,
  416. IN WCHAR const *pwszKeyContainerName,
  417. OUT BOOL *pfMatchFailed,
  418. OUT BOOL *pfSigningTestAttempted,
  419. OUT BOOL *pfKeyUsageCountSupported,
  420. OUT BOOL *pfKeyUsageCountEnabled,
  421. OUT ULARGE_INTEGER *puliKeyUsageCount)
  422. {
  423. HRESULT hr;
  424. HCRYPTPROV hProv = NULL;
  425. DWORD dwProvType;
  426. WCHAR *pwszProvName = NULL;
  427. ALG_ID idAlg;
  428. BOOL fMachineKeyset;
  429. *pfMatchFailed = TRUE;
  430. *pfSigningTestAttempted = FALSE;
  431. *pfKeyUsageCountSupported = FALSE;
  432. *pfKeyUsageCountEnabled = FALSE;
  433. puliKeyUsageCount->QuadPart = 0;
  434. // get provider name
  435. hr = myGetCertSrvCSP(
  436. FALSE, // fEncryptionCSP
  437. pwszSanitizedCA,
  438. &dwProvType,
  439. &pwszProvName,
  440. &idAlg,
  441. &fMachineKeyset,
  442. NULL); // pdwKeySize
  443. _JumpIfError(hr, error, "myGetCertSrvCSP");
  444. hr = myValidateSigningKey(
  445. pwszKeyContainerName,
  446. pwszProvName,
  447. dwProvType,
  448. g_fCryptSilent,
  449. fMachineKeyset,
  450. g_fForce, // fForceSignatureTest
  451. pCertContextCA,
  452. NULL, // pPublicKeyInfo
  453. idAlg,
  454. pfSigningTestAttempted,
  455. &hProv);
  456. _JumpIfError(hr, error, "myValidateSigningKey");
  457. *pfMatchFailed = FALSE;
  458. hr = myGetSigningKeyUsageCount(
  459. hProv,
  460. pfKeyUsageCountSupported,
  461. pfKeyUsageCountEnabled,
  462. puliKeyUsageCount);
  463. _JumpIfError(hr, error, "myGetSigningKeyUsageCount");
  464. error:
  465. if (NULL != hProv)
  466. {
  467. CryptReleaseContext(hProv, 0);
  468. }
  469. if (NULL != pwszProvName)
  470. {
  471. LocalFree(pwszProvName);
  472. }
  473. return(hr);
  474. }
  475. HRESULT
  476. VerifyCAKeys(
  477. IN CERT_CONTEXT const *pCertContextCA,
  478. IN WCHAR const *pwszSanitizedCA,
  479. IN WCHAR const *pwszCertNameCA,
  480. IN WCHAR const *pwszKeyContainerName)
  481. {
  482. HRESULT hr;
  483. CERT_PUBLIC_KEY_INFO *pPubKeyInfo = NULL;
  484. BOOL fMatchFailed = FALSE;
  485. BOOL fSigningTestFailed = FALSE;
  486. BOOL fSigningTestAttempted = FALSE;
  487. BOOL fKeyUsageCountSupported = FALSE;
  488. BOOL fKeyUsageCountEnabled = FALSE;
  489. ULARGE_INTEGER uliKeyUsageCount;
  490. WCHAR *pwszRevert = NULL;
  491. DWORD dwNameId;
  492. CRYPT_KEY_PROV_INFO kpi;
  493. CRYPT_KEY_PROV_INFO *pkpi = NULL;
  494. DWORD cbkpi;
  495. ZeroMemory(&kpi, sizeof(kpi));
  496. hr = myGetNameId(pCertContextCA, &dwNameId);
  497. if (S_OK != hr)
  498. {
  499. _PrintError(hr, "myGetNameId");
  500. dwNameId = MAXDWORD;
  501. }
  502. hr = myRevertSanitizeName(pwszKeyContainerName, &pwszRevert);
  503. _JumpIfError(hr, error, "myRevertSanitizeName");
  504. if (!myCertGetCertificateContextProperty(
  505. pCertContextCA,
  506. CERT_KEY_PROV_INFO_PROP_ID,
  507. CERTLIB_USE_LOCALALLOC,
  508. (VOID **) &pkpi,
  509. &cbkpi))
  510. {
  511. hr = myHLastError();
  512. _PrintError(hr, "myCertGetCertificateContextProperty");
  513. kpi.pwszContainerName = const_cast<WCHAR *>(pwszKeyContainerName);
  514. }
  515. else
  516. {
  517. kpi = *pkpi;
  518. if (0 != lstrcmp(pwszKeyContainerName, pkpi->pwszContainerName))
  519. {
  520. wprintf(
  521. L"%ws --> %ws\n",
  522. pwszKeyContainerName,
  523. pkpi->pwszContainerName);
  524. kpi.pwszContainerName = pkpi->pwszContainerName;
  525. }
  526. }
  527. // Load public key
  528. hr = cuLoadKeys(
  529. kpi.pwszProvName,
  530. &kpi.dwProvType,
  531. kpi.pwszContainerName,
  532. TRUE, // fMachineKeyset
  533. FALSE, // fSoftFail
  534. NULL, // phProv
  535. &pPubKeyInfo,
  536. NULL);
  537. if (S_OK != hr)
  538. {
  539. cuPrintError(IDS_ERR_FORMAT_LOADKEYS, hr);
  540. _JumpError(hr, error, "cuLoadKeys");
  541. }
  542. // see if the public key matches the certificate's public key
  543. if (!CertComparePublicKeyInfo(
  544. X509_ASN_ENCODING,
  545. pPubKeyInfo,
  546. &pCertContextCA->pCertInfo->SubjectPublicKeyInfo))
  547. {
  548. wprintf(wszNewLine);
  549. wprintf(myLoadResourceString(IDS_ERR_PUBLICKEY_MISMATCH)); // "ERROR: Certificate public key does NOT match stored keyset"
  550. wprintf(wszNewLine);
  551. wprintf(wszNewLine);
  552. fMatchFailed = TRUE;
  553. }
  554. if (g_fVerbose || fMatchFailed)
  555. {
  556. wprintf(wszNewLine);
  557. wprintf(myLoadResourceString(IDS_CONTAINER_PUBLIC_KEY)); // "Container Public Key:"
  558. wprintf(wszNewLine);
  559. DumpHex(
  560. DH_NOTABPREFIX | 4,
  561. pPubKeyInfo->PublicKey.pbData,
  562. pPubKeyInfo->PublicKey.cbData);
  563. wprintf(wszNewLine);
  564. wprintf(myLoadResourceString(IDS_CERT_PUBLIC_KEY)); // "Certificate Public Key:"
  565. wprintf(wszNewLine);
  566. DumpHex(
  567. DH_NOTABPREFIX | 4,
  568. pCertContextCA->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
  569. pCertContextCA->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData);
  570. }
  571. if (!fMatchFailed)
  572. {
  573. hr = VerifyPrivateKey(
  574. pCertContextCA,
  575. pwszSanitizedCA,
  576. kpi.pwszContainerName,
  577. &fSigningTestFailed,
  578. &fSigningTestAttempted,
  579. &fKeyUsageCountSupported,
  580. &fKeyUsageCountEnabled,
  581. &uliKeyUsageCount);
  582. _PrintIfError(hr, "VerifyPrivateKey");
  583. }
  584. wprintf(
  585. myLoadResourceString(
  586. fMatchFailed?
  587. IDS_FORMAT_KEY_NOT_VERIFY : // "%ws does NOT verify as the public key in %ws"
  588. IDS_FORMAT_KEY_IS_VERIFY), // "%ws verifies as the public key in %ws"
  589. pwszRevert,
  590. pwszCertNameCA);
  591. wprintf(wszNewLine);
  592. if (MAXDWORD != dwNameId)
  593. {
  594. wprintf(
  595. L" V%u.%u\n",
  596. CANAMEIDTOICERT(dwNameId),
  597. CANAMEIDTOIKEY(dwNameId));
  598. }
  599. if (fSigningTestAttempted)
  600. {
  601. wprintf(
  602. L" %ws\n",
  603. myLoadResourceString(
  604. fSigningTestFailed?
  605. IDS_SIGNATURE_BAD : // "Signature test FAILED"
  606. IDS_SIGNATURE_OK)); // "Signature test passed"
  607. }
  608. if (fKeyUsageCountEnabled)
  609. {
  610. wprintf(
  611. L" %ws: %I64u (0x%I64x)\n",
  612. myLoadResourceString(IDS_KEY_USAGE_COUNT), // "Key usage count:"
  613. uliKeyUsageCount.QuadPart,
  614. uliKeyUsageCount.QuadPart);
  615. }
  616. else if (g_fVerbose)
  617. {
  618. wprintf(
  619. L" %ws: %ws\n",
  620. myLoadResourceString(IDS_KEY_USAGE_COUNT), // "Key usage count:"
  621. myLoadResourceString(
  622. fKeyUsageCountSupported?
  623. IDS_KEY_USAGE_COUNT_DISABLED : // "Disabled"
  624. IDS_KEY_USAGE_COUNT_NOTSUPPORTED)); // "Not supported"
  625. }
  626. wprintf(wszNewLine);
  627. if (fMatchFailed || fSigningTestFailed)
  628. {
  629. hr = E_INVALIDARG;
  630. _JumpError(hr, error, "fMatchFailed || fSigningTestFailed");
  631. }
  632. hr = S_OK;
  633. error:
  634. if (NULL != pwszRevert)
  635. {
  636. LocalFree(pwszRevert);
  637. }
  638. if (NULL != pPubKeyInfo)
  639. {
  640. LocalFree(pPubKeyInfo);
  641. }
  642. if (NULL != pkpi)
  643. {
  644. LocalFree(pkpi);
  645. }
  646. return(hr);
  647. }
  648. HRESULT
  649. VerifyAllCAKeys(
  650. IN WCHAR const *pwszCA,
  651. IN WCHAR const *pwszSanitizedCA)
  652. {
  653. HRESULT hr;
  654. HRESULT hr2;
  655. WCHAR *pwszCertName = NULL;
  656. DWORD cCACerts;
  657. DWORD iHash;
  658. HCERTSTORE hMyStore = NULL;
  659. CERT_CONTEXT const *pccCA = NULL;
  660. CRYPT_KEY_PROV_INFO *pkpi = NULL;
  661. DWORD cbkpi;
  662. hr = myGetCARegHashCount(pwszSanitizedCA, CSRH_CASIGCERT, &cCACerts);
  663. if (S_OK == hr && 0 == cCACerts)
  664. {
  665. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  666. }
  667. _JumpIfError(hr, error, "myGetCARegHashCount");
  668. // open MY store
  669. hMyStore = CertOpenStore(
  670. CERT_STORE_PROV_SYSTEM_W,
  671. X509_ASN_ENCODING,
  672. NULL, // hProv
  673. CERT_SYSTEM_STORE_LOCAL_MACHINE |
  674. CERT_STORE_READONLY_FLAG,
  675. wszMY_CERTSTORE);
  676. if (NULL == hMyStore)
  677. {
  678. hr = myHLastError();
  679. _JumpError(hr, error, "CertOpenStore");
  680. }
  681. hr2 = S_OK;
  682. for (iHash = 0; iHash < cCACerts; iHash++)
  683. {
  684. DWORD NameId;
  685. hr = myFindCACertByHashIndex(
  686. hMyStore,
  687. pwszSanitizedCA,
  688. CSRH_CASIGCERT,
  689. iHash,
  690. &NameId,
  691. &pccCA);
  692. if (S_FALSE == hr)
  693. {
  694. continue;
  695. }
  696. _JumpIfError(hr, error, "myFindCACertByHashIndex");
  697. // get the private key provider info
  698. if (!myCertGetCertificateContextProperty(
  699. pccCA,
  700. CERT_KEY_PROV_INFO_PROP_ID,
  701. CERTLIB_USE_LOCALALLOC,
  702. (VOID **) &pkpi,
  703. &cbkpi))
  704. {
  705. hr = myHLastError();
  706. _JumpError(hr, error, "myCertGetCertificateContextProperty");
  707. }
  708. if (MAXDWORD == NameId)
  709. {
  710. NameId = MAKECANAMEID(iHash, iHash);
  711. }
  712. hr = myAllocIndexedName(
  713. pwszCA,
  714. CANAMEIDTOICERT(NameId),
  715. MAXDWORD, // IndexTarget
  716. &pwszCertName);
  717. _JumpIfError(hr, error, "myAllocIndexedName");
  718. hr = VerifyCAKeys(
  719. pccCA,
  720. pwszSanitizedCA,
  721. pwszCertName,
  722. pkpi->pwszContainerName);
  723. _PrintIfError(hr, "VerifyCAKeys");
  724. if (S_OK == hr2)
  725. {
  726. hr2 = hr;
  727. }
  728. CertFreeCertificateContext(pccCA);
  729. pccCA = NULL;
  730. LocalFree(pkpi);
  731. pkpi = NULL;
  732. LocalFree(pwszCertName);
  733. pwszCertName = NULL;
  734. }
  735. hr = hr2;
  736. error:
  737. if (NULL != pkpi)
  738. {
  739. LocalFree(pkpi);
  740. }
  741. if (NULL != pccCA)
  742. {
  743. CertFreeCertificateContext(pccCA);
  744. }
  745. if (NULL != hMyStore)
  746. {
  747. CertCloseStore(hMyStore, CERT_CLOSE_STORE_CHECK_FLAG);
  748. }
  749. if (NULL != pwszCertName)
  750. {
  751. LocalFree(pwszCertName);
  752. }
  753. return(hr);
  754. }
  755. HRESULT
  756. verbVerifyKeys(
  757. IN WCHAR const *pwszOption,
  758. OPTIONAL IN WCHAR const *pwszKeyContainerName,
  759. OPTIONAL IN WCHAR const *pwszfnCertCA,
  760. OPTIONAL IN WCHAR const *pwszArg3,
  761. OPTIONAL IN WCHAR const *pwszArg4)
  762. {
  763. HRESULT hr;
  764. CERT_CONTEXT const *pCertContextCA = NULL;
  765. WCHAR *pwszCA = NULL;
  766. WCHAR *pwszSanitizedCA = NULL;
  767. WCHAR *pwszRevertContainer = NULL;
  768. WCHAR *pwszSanitizedContainer = NULL;
  769. hr = cuGetLocalCANameFromConfig(NULL, &pwszCA);
  770. _JumpIfError(hr, error, "GetLocalCANameFromConfig");
  771. hr = mySanitizeName(pwszCA, &pwszSanitizedCA);
  772. _JumpIfError(hr, error, "mySanitizeName");
  773. if (NULL == pwszfnCertCA)
  774. {
  775. if (NULL != pwszKeyContainerName)
  776. {
  777. hr = E_INVALIDARG;
  778. _JumpError(hr, error, "extra arg");
  779. }
  780. hr = VerifyAllCAKeys(pwszCA, pwszSanitizedCA);
  781. _JumpIfError(hr, error, "VerifyAllCAKeys");
  782. }
  783. else
  784. {
  785. hr = myRevertSanitizeName(pwszKeyContainerName, &pwszRevertContainer);
  786. _JumpIfError(hr, error, "myRevertSanitizeName");
  787. hr = cuSanitizeNameWithSuffix(
  788. pwszRevertContainer,
  789. &pwszSanitizedContainer);
  790. _JumpIfError(hr, error, "cuSanitizeNameWithSuffix");
  791. // Load and decode CA certificate
  792. hr = cuLoadCert(pwszfnCertCA, &pCertContextCA);
  793. if (S_OK != hr)
  794. {
  795. cuPrintError(IDS_ERR_FORMAT_LOADCACERT, hr);
  796. goto error;
  797. }
  798. hr = VerifyCAKeys(
  799. pCertContextCA,
  800. pwszSanitizedCA,
  801. pwszfnCertCA,
  802. pwszSanitizedContainer);
  803. _JumpIfError(hr, error, "VerifyCAKeys");
  804. }
  805. error:
  806. cuUnloadCert(&pCertContextCA);
  807. if (NULL != pwszSanitizedCA)
  808. {
  809. LocalFree(pwszSanitizedCA);
  810. }
  811. if (NULL != pwszCA)
  812. {
  813. LocalFree(pwszCA);
  814. }
  815. if (NULL != pwszSanitizedContainer)
  816. {
  817. LocalFree(pwszSanitizedContainer);
  818. }
  819. if (NULL != pwszRevertContainer)
  820. {
  821. LocalFree(pwszRevertContainer);
  822. }
  823. return(hr);
  824. }
  825. VOID
  826. cuDumpPolicies(
  827. IN UINT idMsg,
  828. IN WCHAR const *pwszzPolicies)
  829. {
  830. wprintf(L"%ws:", myLoadResourceString(idMsg));
  831. if (NULL == pwszzPolicies)
  832. {
  833. wprintf(L" %ws\n", myLoadResourceString(IDS_ALL_POLICIES));
  834. }
  835. else if (L'\0' == *pwszzPolicies)
  836. {
  837. wprintf(L" %ws\n", myLoadResourceString(IDS_NO_POLICIES));
  838. }
  839. else
  840. {
  841. wprintf(wszNewLine);
  842. for ( ;
  843. L'\0' != *pwszzPolicies;
  844. pwszzPolicies += wcslen(pwszzPolicies) + 1)
  845. {
  846. wprintf(g_wszPad4);
  847. cuDumpOIDAndDescription(pwszzPolicies);
  848. wprintf(wszNewLine);
  849. }
  850. }
  851. }
  852. FNSIMPLECHAINELEMENTCALLBACK cuSimpleChainElementCallback;
  853. VOID
  854. cuSimpleChainElementCallback(
  855. IN DWORD dwFlags,
  856. IN DWORD iElement,
  857. IN CERT_SIMPLE_CHAIN const *pChain)
  858. {
  859. CERT_CHAIN_ELEMENT const *pElement = pChain->rgpElement[iElement];
  860. CERT_REVOCATION_INFO *pRevocationInfo;
  861. WCHAR const *pwszFmtHeader = L" ----------------%ws%ws%ws----------------\n";
  862. CSASSERT(iElement < pChain->cElement);
  863. pElement = pChain->rgpElement[iElement];
  864. wprintf(
  865. pwszFmtHeader,
  866. g_wszPad2,
  867. myLoadResourceString(IDS_CERT_AIA), // "Certificate AIA"
  868. g_wszPad2);
  869. cuDisplayAIAUrlsFromCert(pElement->pCertContext);
  870. wprintf(
  871. pwszFmtHeader,
  872. g_wszPad2,
  873. myLoadResourceString(IDS_CERT_CDP), // "Certificate CDP"
  874. g_wszPad2);
  875. cuDisplayCDPUrlsFromCertOrCRL(pElement->pCertContext, NULL);
  876. pRevocationInfo = pElement->pRevocationInfo;
  877. if (NULL != pRevocationInfo &&
  878. CCSIZEOF_STRUCT(CERT_REVOCATION_INFO, pCrlInfo) <=
  879. pRevocationInfo->cbSize &&
  880. NULL != pRevocationInfo->pCrlInfo)
  881. {
  882. CERT_REVOCATION_CRL_INFO *pCrlInfo;
  883. pCrlInfo = pRevocationInfo->pCrlInfo;
  884. if (NULL != pCrlInfo)
  885. {
  886. if (NULL != pCrlInfo->pBaseCrlContext)
  887. {
  888. wprintf(
  889. pwszFmtHeader,
  890. g_wszPad2,
  891. myLoadResourceString(IDS_BASECRL_CDP), // "Base CRL CDP"
  892. g_wszPad2);
  893. cuDisplayCDPUrlsFromCertOrCRL(NULL, pCrlInfo->pBaseCrlContext);
  894. }
  895. //if (NULL != pCrlInfo->pDeltaCrlContext)
  896. }
  897. }
  898. wprintf(
  899. pwszFmtHeader,
  900. g_wszEmpty,
  901. g_wszEmpty,
  902. g_wszEmpty);
  903. }
  904. HRESULT
  905. cuVerifyCertContext(
  906. IN CERT_CONTEXT const *pCert,
  907. OPTIONAL IN HCERTSTORE hStoreCA,
  908. IN DWORD cApplicationPolicies,
  909. OPTIONAL IN char const * const *apszApplicationPolicies,
  910. IN DWORD cIssuancePolicies,
  911. OPTIONAL IN char const * const *apszIssuancePolicies,
  912. IN BOOL fNTAuth,
  913. OUT DWORD *pVerifyState)
  914. {
  915. HRESULT hr;
  916. DWORD idMsg;
  917. WCHAR *pwszMissingIssuer = NULL;
  918. WCHAR *pwszzIssuancePolicies = NULL;
  919. WCHAR *pwszzApplicationPolicies = NULL;
  920. WCHAR *pwszExtendedErrorInfo = NULL;
  921. DWORD Flags;
  922. *pVerifyState = 0;
  923. if (CertCompareCertificateName(
  924. X509_ASN_ENCODING,
  925. &pCert->pCertInfo->Issuer,
  926. &pCert->pCertInfo->Subject))
  927. {
  928. *pVerifyState |= VS_ROOT;
  929. #if 0
  930. hr = cuVerifySignature(
  931. pCert->pbCertEncoded,
  932. pCert->cbCertEncoded,
  933. &pCert->pCertInfo->SubjectPublicKeyInfo,
  934. FALSE,
  935. FALSE);
  936. if (S_OK == hr)
  937. {
  938. *pVerifyState |= VS_ROOTSIGOK;
  939. }
  940. _PrintIfError(hr, "cuVerifySignature");
  941. #endif
  942. }
  943. // Verify the cert and chain:
  944. Flags = 0;
  945. if (fNTAuth || g_fEnterpriseRegistry)
  946. {
  947. Flags |= CA_VERIFY_FLAGS_NT_AUTH;
  948. }
  949. if (g_fForce)
  950. {
  951. Flags |= CA_VERIFY_FLAGS_FULL_CHAIN_REVOCATION;
  952. Flags |= CA_VERIFY_FLAGS_IGNORE_OFFLINE |
  953. CA_VERIFY_FLAGS_ALLOW_UNTRUSTED_ROOT;
  954. if (1 < g_fForce)
  955. {
  956. Flags |= CA_VERIFY_FLAGS_NO_REVOCATION;
  957. }
  958. }
  959. if (!g_fQuiet)
  960. {
  961. Flags |= CA_VERIFY_FLAGS_DUMP_CHAIN;
  962. }
  963. if (g_fSplitASN)
  964. {
  965. Flags |= CA_VERIFY_FLAGS_SAVE_CHAIN;
  966. }
  967. hr = myVerifyCertContextEx(
  968. pCert,
  969. Flags,
  970. g_dwmsTimeout,
  971. cApplicationPolicies,
  972. apszApplicationPolicies,
  973. cIssuancePolicies,
  974. apszIssuancePolicies,
  975. g_fUserRegistry? HCCE_CURRENT_USER : HCCE_LOCAL_MACHINE,
  976. NULL, // pft
  977. hStoreCA, // hAdditionalStore
  978. g_fURLFetch? cuSimpleChainElementCallback : NULL,
  979. &pwszMissingIssuer,
  980. &pwszzIssuancePolicies,
  981. &pwszzApplicationPolicies,
  982. &pwszExtendedErrorInfo,
  983. NULL); // pTrustStatus
  984. if (S_OK == hr &&
  985. (NULL != pwszzIssuancePolicies ||
  986. NULL != pwszzApplicationPolicies ||
  987. IsWhistler()))
  988. {
  989. // Suppress misleading "All Policies" display on Windows 2000.
  990. cuDumpPolicies(IDS_ISSUANCE_POLICIES, pwszzIssuancePolicies);
  991. cuDumpPolicies(IDS_APPLICATION_POLICIES, pwszzApplicationPolicies);
  992. }
  993. if (NULL != pwszExtendedErrorInfo)
  994. {
  995. wprintf(L"%ws\n", pwszExtendedErrorInfo);
  996. }
  997. idMsg = 0;
  998. if (CRYPT_E_REVOKED == hr || CERT_E_REVOKED == hr)
  999. {
  1000. idMsg = IDS_REVOKED_CERT; // "Certificate is REVOKED"
  1001. *pVerifyState |= VS_REVOKED;
  1002. }
  1003. else if (CERT_E_UNTRUSTEDROOT == hr)
  1004. {
  1005. idMsg = IDS_UNTRUSTED_ROOT; // "Verifies against UNTRUSTED root"
  1006. *pVerifyState |= VS_UNTRUSTEDROOT;
  1007. }
  1008. else if (CERT_E_CHAINING == hr)
  1009. {
  1010. idMsg = IDS_INCOMPLETE_CHAIN; // "Incomplete certificate chain"
  1011. *pVerifyState |= VS_INCOMPLETECHAIN;
  1012. }
  1013. else if (CERT_E_EXPIRED == hr)
  1014. {
  1015. idMsg = IDS_EXPIRED_CERT; // "Expired certificate"
  1016. *pVerifyState |= VS_EXPIRED;
  1017. }
  1018. else if (CRYPT_E_REVOCATION_OFFLINE == hr)
  1019. {
  1020. idMsg = IDS_REVOCATION_OFFLINE; // "Revocation check skipped -- server offline"
  1021. *pVerifyState |= VS_REVOCATIONOFFLINE;
  1022. }
  1023. else if (CRYPT_E_NO_REVOCATION_CHECK == hr)
  1024. {
  1025. idMsg = IDS_NO_REVOCATION_CHECK; // "Revocation check skipped -- no revocation information available"
  1026. *pVerifyState |= VS_NOREVOCATIONCHECK;
  1027. }
  1028. if (0 != idMsg)
  1029. {
  1030. wprintf(myLoadResourceString(idMsg));
  1031. wprintf(wszNewLine);
  1032. if (NULL != pwszMissingIssuer)
  1033. {
  1034. wprintf(myLoadResourceString(IDS_MISSING_CERT));
  1035. wprintf(L"\n %ws\n", pwszMissingIssuer);
  1036. }
  1037. hr = S_OK;
  1038. }
  1039. if (S_OK != hr)
  1040. {
  1041. *pVerifyState |= VS_OTHERERROR;
  1042. }
  1043. _JumpIfError(hr, error, "cuVerifyCertContext");
  1044. error:
  1045. if (NULL != pwszMissingIssuer)
  1046. {
  1047. LocalFree(pwszMissingIssuer);
  1048. }
  1049. if (NULL != pwszzIssuancePolicies)
  1050. {
  1051. LocalFree(pwszzIssuancePolicies);
  1052. }
  1053. if (NULL != pwszzApplicationPolicies)
  1054. {
  1055. LocalFree(pwszzApplicationPolicies);
  1056. }
  1057. if (NULL != pwszExtendedErrorInfo)
  1058. {
  1059. LocalFree(pwszExtendedErrorInfo);
  1060. }
  1061. return(hr);
  1062. }
  1063. #define RS_INCOMPLETE 0
  1064. #define RS_PASS 1
  1065. #define RS_FAIL 2
  1066. #define RS_REVOKED 3
  1067. DWORD
  1068. VerifyRevocation(
  1069. IN CERT_CONTEXT const *pCertContext,
  1070. OPTIONAL IN CERT_CONTEXT const *pCertContextCA)
  1071. {
  1072. HRESULT hr;
  1073. CERT_REVOCATION_PARA crp;
  1074. CERT_REVOCATION_STATUS crs;
  1075. DWORD RevState = RS_INCOMPLETE;
  1076. ZeroMemory(&crp, sizeof(crp));
  1077. crp.cbSize = sizeof(crp);
  1078. crp.pIssuerCert = pCertContextCA;
  1079. ZeroMemory(&crs, sizeof(crs));
  1080. crs.cbSize = sizeof(crs);
  1081. crp.hCrlStore = CertOpenStore(
  1082. CERT_STORE_PROV_SYSTEM_W,
  1083. X509_ASN_ENCODING,
  1084. NULL, // hProv
  1085. cuGetSystemStoreFlags() | CERT_STORE_READONLY_FLAG,
  1086. wszCA_CERTSTORE);
  1087. if (NULL == crp.hCrlStore)
  1088. {
  1089. hr = myHLastError();
  1090. _JumpError(hr, error, "CertOpenStore");
  1091. }
  1092. if (!CertVerifyRevocation(
  1093. X509_ASN_ENCODING,
  1094. CERT_CONTEXT_REVOCATION_TYPE,
  1095. 1, // cContext
  1096. (VOID **) &pCertContext, // rgpContext
  1097. 0, // dwFlags
  1098. &crp,
  1099. &crs))
  1100. {
  1101. hr = myHLastError();
  1102. if (CRYPT_E_REVOKED == hr || CERT_E_REVOKED == hr)
  1103. {
  1104. wprintf(
  1105. myLoadResourceString(IDS_FORMAT_IS_REVOKED), // "Leaf certificate is REVOKED (Reason=%x)"
  1106. crs.dwReason);
  1107. wprintf(wszNewLine);
  1108. RevState = RS_REVOKED;
  1109. goto error;
  1110. }
  1111. if (CRYPT_E_NO_REVOCATION_CHECK != hr)
  1112. {
  1113. wprintf(wszNewLine);
  1114. cuPrintError(IDS_ERR_FORMAT_VERIFY_REVSTATUS, hr); // "ERROR: Verifying leaf certificate revocation status returned %ws"
  1115. cuPrintErrorMessageText(hr);
  1116. wprintf(wszNewLine);
  1117. RevState = RS_FAIL;
  1118. goto error;
  1119. }
  1120. wprintf(myLoadResourceString(IDS_CANNOT_CHECK_REVSTATUS)); // "Cannot check leaf certificate revocation status"
  1121. wprintf(wszNewLine);
  1122. RevState = RS_INCOMPLETE;
  1123. goto error;
  1124. }
  1125. wprintf(myLoadResourceString(IDS_REVSTATUS_OK)); // "Leaf certificate revocation check passed"
  1126. wprintf(wszNewLine);
  1127. RevState = RS_PASS;
  1128. error:
  1129. if (NULL != crp.hCrlStore)
  1130. {
  1131. CertCloseStore(crp.hCrlStore, CERT_CLOSE_STORE_CHECK_FLAG);
  1132. }
  1133. return(RevState);
  1134. }
  1135. #define CAS_UNKNOWN 0
  1136. #define CAS_CA 1
  1137. #define CAS_ENDENTITY 2
  1138. VOID
  1139. VerifyCACert(
  1140. IN CERT_INFO const *pCertInfo,
  1141. IN BOOL fCA,
  1142. OUT DWORD *pState)
  1143. {
  1144. HRESULT hr;
  1145. CERT_EXTENSION *pExt;
  1146. UINT id = 0;
  1147. *pState = CAS_UNKNOWN;
  1148. pExt = CertFindExtension(
  1149. szOID_BASIC_CONSTRAINTS2,
  1150. pCertInfo->cExtension,
  1151. pCertInfo->rgExtension);
  1152. if (NULL == pExt)
  1153. {
  1154. // This API doesn't set LastError
  1155. //hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  1156. //_PrintError(hr, "CertFindExtension");
  1157. if (fCA)
  1158. {
  1159. id = IDS_NOBASICCONSTRAINTS2_ERROR; // "ERROR: CA Cert has no Basic Constraints2 Extension"
  1160. }
  1161. }
  1162. else
  1163. {
  1164. DWORD cb;
  1165. CERT_BASIC_CONSTRAINTS2_INFO Constraints;
  1166. cb = sizeof(Constraints);
  1167. if (!CryptDecodeObject(
  1168. X509_ASN_ENCODING,
  1169. X509_BASIC_CONSTRAINTS2,
  1170. pExt->Value.pbData,
  1171. pExt->Value.cbData,
  1172. 0,
  1173. &Constraints,
  1174. &cb))
  1175. {
  1176. hr = myHLastError();
  1177. _PrintError(hr, "CryptDecodeObject");
  1178. id = IDS_CANNOTDECODEBASICCONSTRAINTS2_ERROR; // "ERROR: Cannot decode CA Cert Basic Constraints2 Extension"
  1179. }
  1180. else
  1181. {
  1182. *pState = Constraints.fCA? CAS_CA : CAS_ENDENTITY;
  1183. if (!Constraints.fCA)
  1184. {
  1185. id = IDS_ENDENTITYCACERT_ERROR; // "ERROR: CA Cert is an End Entity certificate"
  1186. }
  1187. }
  1188. }
  1189. if (fCA && 0 != id)
  1190. {
  1191. wprintf(wszNewLine);
  1192. wprintf(myLoadResourceString(id));
  1193. wprintf(wszNewLine);
  1194. wprintf(wszNewLine);
  1195. }
  1196. if (!fCA)
  1197. {
  1198. switch (*pState)
  1199. {
  1200. case CAS_CA:
  1201. wprintf(myLoadResourceString(IDS_CACERT)); // "Cert is a CA certificate"
  1202. wprintf(wszNewLine);
  1203. break;
  1204. case CAS_ENDENTITY:
  1205. wprintf(myLoadResourceString(IDS_ENDENTITYCERT)); // "Cert is an End Entity certificate"
  1206. wprintf(wszNewLine);
  1207. break;
  1208. }
  1209. }
  1210. }
  1211. HRESULT
  1212. VerifyCertAgainstChain(
  1213. IN WCHAR const *pwszfnCert,
  1214. IN DWORD cApplicationPolicies,
  1215. OPTIONAL IN char const * const *apszApplicationPolicies,
  1216. IN DWORD cIssuancePolicies,
  1217. OPTIONAL IN char const * const *apszIssuancePolicies)
  1218. {
  1219. HRESULT hr;
  1220. CERT_CONTEXT const *pCertContext = NULL;
  1221. DWORD VerifyState;
  1222. DWORD CertState;
  1223. DWORD RevState;
  1224. // Load and decode certificates
  1225. hr = cuLoadCert(pwszfnCert, &pCertContext);
  1226. if (S_OK != hr)
  1227. {
  1228. cuPrintError(IDS_FORMAT_LOADTESTCERT, hr);
  1229. goto error;
  1230. }
  1231. // Display name info:
  1232. hr = cuDisplayCertNames(TRUE, NULL, pCertContext->pCertInfo);
  1233. _JumpIfError(hr, error, "cuDisplayCertNames(Cert)");
  1234. cuDumpSerial(NULL, IDS_CERT_SERIAL, &pCertContext->pCertInfo->SerialNumber);
  1235. wprintf(wszNewLine);
  1236. hr = cuVerifyCertContext(
  1237. pCertContext, // pCert
  1238. NULL, // hStoreCA
  1239. cApplicationPolicies,
  1240. apszApplicationPolicies,
  1241. cIssuancePolicies,
  1242. apszIssuancePolicies,
  1243. FALSE, // fNTAuth
  1244. &VerifyState);
  1245. _JumpIfError(hr, error, "cuVerifyCertContext");
  1246. VerifyCACert(pCertContext->pCertInfo, FALSE, &CertState);
  1247. if (!g_fCryptSilent)
  1248. {
  1249. RevState = VerifyRevocation(pCertContext, NULL);
  1250. }
  1251. error:
  1252. cuUnloadCert(&pCertContext);
  1253. return(hr);
  1254. }
  1255. HRESULT
  1256. VerifyCertAgainstParent(
  1257. IN WCHAR const *pwszfnCert,
  1258. IN WCHAR const *pwszfnCertCA,
  1259. OPTIONAL IN WCHAR const *pwszfnCertCACrossed,
  1260. OUT BOOL *pfCertLoaded)
  1261. {
  1262. HRESULT hr;
  1263. CERT_INFO const *pCertInfo;
  1264. CERT_INFO const *pCertInfoCA;
  1265. CERT_INFO const *pCertInfoCACrossed;
  1266. CERT_CONTEXT const *pCertContext = NULL;
  1267. CERT_CONTEXT const *pCertContextCA = NULL;
  1268. CERT_CONTEXT const *pCertContextCACrossed = NULL;
  1269. DWORD dwFlags;
  1270. BOOL fDisplayCANames = g_fVerbose;
  1271. DWORD i;
  1272. BOOL fCertInvalid = FALSE;
  1273. DWORD RevState = RS_INCOMPLETE;
  1274. BOOL fCheckRevocation = FALSE;
  1275. SYSTEMTIME st;
  1276. FILETIME ft;
  1277. DWORD CAState;
  1278. DWORD CertState;
  1279. BYTE *pbKeyId = NULL;
  1280. DWORD cbKeyId;
  1281. BYTE *pbKeyIdCACrossed = NULL;
  1282. DWORD cbKeyIdCACrossed;
  1283. // Load and decode certificates
  1284. *pfCertLoaded = FALSE;
  1285. hr = cuLoadCert(pwszfnCert, &pCertContext);
  1286. if (S_OK != hr)
  1287. {
  1288. if (CRYPT_E_ASN1_BADTAG != hr)
  1289. {
  1290. cuPrintError(IDS_FORMAT_LOADTESTCERT, hr);
  1291. }
  1292. goto error;
  1293. }
  1294. *pfCertLoaded = TRUE;
  1295. pCertInfo = pCertContext->pCertInfo;
  1296. hr = cuLoadCert(pwszfnCertCA, &pCertContextCA);
  1297. if (S_OK != hr)
  1298. {
  1299. cuPrintError(IDS_FORMAT_LOADCACERT, hr);
  1300. goto error;
  1301. }
  1302. pCertInfoCA = pCertContextCA->pCertInfo;
  1303. if (NULL != pwszfnCertCACrossed)
  1304. {
  1305. hr = cuLoadCert(pwszfnCertCACrossed, &pCertContextCACrossed);
  1306. if (S_OK != hr)
  1307. {
  1308. cuPrintError(IDS_FORMAT_LOADCACERT, hr);
  1309. goto error;
  1310. }
  1311. pCertInfoCACrossed = pCertContextCACrossed->pCertInfo;
  1312. }
  1313. // Display name info:
  1314. hr = cuDisplayCertNames(
  1315. TRUE,
  1316. myLoadResourceString(IDS_CERT), // "Cert"
  1317. pCertInfo);
  1318. _JumpIfError(hr, error, "cuDisplayCertNames(Cert)");
  1319. hr = cuDisplayCertNames(
  1320. TRUE,
  1321. myLoadResourceString(IDS_ISSUINGCACERT), // "Issuing CA Cert"
  1322. pCertInfoCA);
  1323. _JumpIfError(hr, error, "cuDisplayCertNames(CA)");
  1324. if (NULL != pwszfnCertCACrossed)
  1325. {
  1326. hr = cuDisplayCertNames(
  1327. TRUE,
  1328. myLoadResourceString(IDS_CROSSEDCACERT), // "Crossed CA Cert"
  1329. pCertInfoCACrossed);
  1330. _JumpIfError(hr, error, "cuDisplayCertNames(CrossedCA)");
  1331. }
  1332. if (g_fVerbose)
  1333. {
  1334. wprintf(wszNewLine);
  1335. cuDumpSerial(NULL, IDS_CERT_SERIAL, &pCertInfo->SerialNumber);
  1336. wprintf(wszNewLine);
  1337. cuDumpSerial(NULL, IDS_ISSUINGCACERT_SERIAL, &pCertInfoCA->SerialNumber);
  1338. if (NULL != pwszfnCertCACrossed)
  1339. {
  1340. wprintf(wszNewLine);
  1341. cuDumpSerial(NULL, IDS_CROSSEDCACERT_SERIAL, &pCertInfoCACrossed->SerialNumber);
  1342. }
  1343. wprintf(wszNewLine);
  1344. }
  1345. if (!CertCompareCertificateName(
  1346. X509_ASN_ENCODING,
  1347. const_cast<CERT_NAME_BLOB *>(&pCertInfoCA->Issuer),
  1348. const_cast<CERT_NAME_BLOB *>(&pCertInfoCA->Subject)))
  1349. {
  1350. // This API doesn't set LastError
  1351. wprintf(myLoadResourceString(IDS_ISSUINGCA_NOT_ROOT)); // "Issuing CA is not a root: Subject name does not match Issuer"
  1352. wprintf(wszNewLine);
  1353. wprintf(wszNewLine);
  1354. hr = S_OK;
  1355. }
  1356. if (!CertCompareCertificateName(
  1357. X509_ASN_ENCODING,
  1358. const_cast<CERT_NAME_BLOB *>(&pCertInfo->Issuer),
  1359. const_cast<CERT_NAME_BLOB *>(&pCertInfoCA->Subject)))
  1360. {
  1361. // This API doesn't set LastError
  1362. wprintf(wszNewLine);
  1363. wprintf(
  1364. myLoadResourceString(IDS_ISSUINGCA_SUBJECT_NOT_ISSUER)); // "ERROR: Issuing CA Subject name does not match Cert Issuer"
  1365. wprintf(wszNewLine);
  1366. wprintf(wszNewLine);
  1367. hr = S_OK;
  1368. fCertInvalid = TRUE;
  1369. }
  1370. else
  1371. {
  1372. wprintf(myLoadResourceString(IDS_ISSUINGCA_SUBJECT_IS_ISSUER)); // "Issuing CA Subject name matches Cert Issuer"
  1373. wprintf(wszNewLine);
  1374. }
  1375. if (NULL != pwszfnCertCACrossed)
  1376. {
  1377. if (!CertCompareCertificateName(
  1378. X509_ASN_ENCODING,
  1379. const_cast<CERT_NAME_BLOB *>(&pCertInfo->Subject),
  1380. const_cast<CERT_NAME_BLOB *>(&pCertInfoCACrossed->Subject)))
  1381. {
  1382. // This API doesn't set LastError
  1383. wprintf(wszNewLine);
  1384. wprintf(
  1385. myLoadResourceString(IDS_CROSSEDCA_SUBJECT_NOT_SUBJECT)); // "ERROR: Crossed CA Subject name does not match Cert Subject"
  1386. wprintf(wszNewLine);
  1387. wprintf(wszNewLine);
  1388. hr = S_OK;
  1389. fCertInvalid = TRUE;
  1390. }
  1391. else
  1392. {
  1393. wprintf(myLoadResourceString(IDS_CROSEDGCA_SUBJECT_IS_SUBJECT)); // "Crossed CA Subject name matches Cert Subject"
  1394. wprintf(wszNewLine);
  1395. }
  1396. // see if the public key matches the certificate's public key
  1397. if (!CertComparePublicKeyInfo(
  1398. X509_ASN_ENCODING,
  1399. const_cast<CERT_PUBLIC_KEY_INFO *>(&pCertInfo->SubjectPublicKeyInfo),
  1400. const_cast<CERT_PUBLIC_KEY_INFO *>(&pCertInfoCACrossed->SubjectPublicKeyInfo)))
  1401. {
  1402. wprintf(wszNewLine);
  1403. wprintf(myLoadResourceString(IDS_CROSEDGCA_NOT_PUBLICKEY)); // "ERROR: Certificate public key does NOT match Cert key"
  1404. wprintf(wszNewLine);
  1405. fCertInvalid = TRUE;
  1406. }
  1407. else
  1408. {
  1409. wprintf(myLoadResourceString(IDS_CROSEDGCA_NOT_IS_PUBLICKEY)); // "Crossed CA public key matches Cert key"
  1410. }
  1411. wprintf(wszNewLine);
  1412. hr = myGetPublicKeyHash(
  1413. pCertInfo,
  1414. &pCertInfo->SubjectPublicKeyInfo,
  1415. &pbKeyId,
  1416. &cbKeyId);
  1417. _JumpIfError(hr, error, "myGetPublicKeyHash");
  1418. hr = myGetPublicKeyHash(
  1419. pCertInfoCACrossed,
  1420. &pCertInfoCACrossed->SubjectPublicKeyInfo,
  1421. &pbKeyIdCACrossed,
  1422. &cbKeyIdCACrossed);
  1423. _JumpIfError(hr, error, "myGetPublicKeyHash");
  1424. if (cbKeyId == cbKeyIdCACrossed &&
  1425. 0 == memcmp(pbKeyId, pbKeyIdCACrossed, cbKeyId))
  1426. {
  1427. wprintf(myLoadResourceString(IDS_CROSSEDKEYID_IS_KEYID)); // "Crossed CA Key Id matches Key Id"
  1428. }
  1429. else
  1430. {
  1431. wprintf(wszNewLine);
  1432. wprintf(myLoadResourceString(IDS_CROSSEDKEYID_NOT_KEYID)); // "ERROR: Crossed CA Key Id does not match Key Id"
  1433. wprintf(wszNewLine);
  1434. fCertInvalid = TRUE;
  1435. }
  1436. wprintf(wszNewLine);
  1437. }
  1438. GetSystemTime(&st);
  1439. if (!SystemTimeToFileTime(&st, &ft))
  1440. {
  1441. hr = myHLastError();
  1442. _JumpError(hr, error, "SystemTimeToFileTime");
  1443. }
  1444. if (0 < CompareFileTime(&pCertInfo->NotBefore, &ft))
  1445. {
  1446. wprintf(wszNewLine);
  1447. wprintf(
  1448. myLoadResourceString(IDS_NOWNOTBEFORE_ERROR)); // "ERROR: Cert is not yet valid"
  1449. wprintf(wszNewLine);
  1450. wprintf(wszNewLine);
  1451. fCertInvalid = TRUE;
  1452. }
  1453. if (0 > CompareFileTime(&pCertInfo->NotAfter, &ft))
  1454. {
  1455. wprintf(wszNewLine);
  1456. wprintf(
  1457. myLoadResourceString(IDS_NOWNOTAFTER_ERROR)); // "ERROR: Cert has expired"
  1458. wprintf(wszNewLine);
  1459. wprintf(wszNewLine);
  1460. fCertInvalid = TRUE;
  1461. }
  1462. if (0 < CompareFileTime(&pCertInfoCA->NotBefore, &pCertInfo->NotBefore))
  1463. {
  1464. wprintf(wszNewLine);
  1465. wprintf(
  1466. myLoadResourceString(IDS_CANOTBEFORE_ERROR)); // "ERROR: Cert Valid before issuing CA Cert Valid"
  1467. wprintf(wszNewLine);
  1468. wprintf(wszNewLine);
  1469. //fCertInvalid = TRUE;
  1470. }
  1471. if (0 > CompareFileTime(&pCertInfoCA->NotAfter, &pCertInfo->NotAfter))
  1472. {
  1473. wprintf(wszNewLine);
  1474. wprintf(
  1475. myLoadResourceString(IDS_CANOTAFTER_ERROR)); // "ERROR: Cert Expires after issuing CA Cert Expires"
  1476. wprintf(wszNewLine);
  1477. wprintf(wszNewLine);
  1478. //fCertInvalid = TRUE;
  1479. }
  1480. VerifyCACert(pCertInfoCA, TRUE, &CAState);
  1481. VerifyCACert(pCertInfo, FALSE, &CertState);
  1482. hr = S_OK;
  1483. dwFlags =
  1484. CERT_STORE_SIGNATURE_FLAG |
  1485. CERT_STORE_TIME_VALIDITY_FLAG;
  1486. //CERT_STORE_REVOCATION_FLAG;
  1487. if (g_fVerbose)
  1488. {
  1489. wprintf(
  1490. myLoadResourceString(IDS_FORMAT_CERTVERIFYSUBJECTCERTIFICATECONTEXT_FLAGS), // "CertVerifySubjectCertificateContext Flags = %x --> "
  1491. dwFlags);
  1492. }
  1493. if (!CertVerifySubjectCertificateContext(
  1494. pCertContext,
  1495. pCertContextCA,
  1496. &dwFlags))
  1497. {
  1498. hr = myHLastError();
  1499. if (g_fVerbose)
  1500. {
  1501. wprintf(wszNewLine);
  1502. fflush(stdout);
  1503. }
  1504. _JumpError(hr, error, "CertVerifySubjectCertificateContext");
  1505. }
  1506. if (g_fVerbose)
  1507. {
  1508. wprintf(L"%x\n", dwFlags);
  1509. }
  1510. if (0 != dwFlags)
  1511. {
  1512. wprintf(wszNewLine);
  1513. wprintf(
  1514. myLoadResourceString(IDS_ERR_FORMAT_VALIDATION), // "ERROR: Certificate validation failure: %x"
  1515. dwFlags);
  1516. wprintf(wszNewLine);
  1517. }
  1518. if (CERT_STORE_SIGNATURE_FLAG & dwFlags)
  1519. {
  1520. wprintf(wszNewLine);
  1521. wprintf(myLoadResourceString(IDS_ERR_CA_SIG_NOT_ISSUER)); // "ERROR: CA did not issue Certificate: Signature check failed"
  1522. wprintf(wszNewLine);
  1523. }
  1524. else
  1525. {
  1526. wprintf(myLoadResourceString(IDS_CERT_SIG_OK)); // "Certificate signature is valid"
  1527. }
  1528. wprintf(wszNewLine);
  1529. if (CERT_STORE_TIME_VALIDITY_FLAG & dwFlags)
  1530. {
  1531. wprintf(wszNewLine);
  1532. wprintf(myLoadResourceString(IDS_ERR_EXPIRED)); // "ERROR: Certificate has expired"
  1533. wprintf(wszNewLine);
  1534. }
  1535. else
  1536. {
  1537. wprintf(myLoadResourceString(IDS_CERT_CURRENT)); // "Certificate is current"
  1538. }
  1539. wprintf(wszNewLine);
  1540. if (0 != dwFlags)
  1541. {
  1542. wprintf(wszNewLine);
  1543. fCertInvalid = TRUE;
  1544. }
  1545. for (i = 0; i < pCertInfo->cExtension; i++)
  1546. {
  1547. CERT_EXTENSION *pce;
  1548. pce = &pCertInfo->rgExtension[i];
  1549. //wprintf(L"%d: %hs: %d, %x (%x)\n", i, pce->pszObjId, pce->fCritical, pce->Value.pbData, pce->Value.cbData);
  1550. if (0 == strcmp(pce->pszObjId, szOID_AUTHORITY_KEY_IDENTIFIER2))
  1551. {
  1552. BOOL fKeyAuthorityMatch;
  1553. //wprintf(L"%d: %ws\n", i, L"szOID_AUTHORITY_KEY_IDENTIFIER2");
  1554. hr = cuVerifyKeyAuthority(
  1555. &pCertInfo->Issuer,
  1556. pCertInfoCA,
  1557. pce->Value.pbData,
  1558. pce->Value.cbData,
  1559. FALSE,
  1560. &fKeyAuthorityMatch);
  1561. _JumpIfError(hr, error, "cuVerifyKeyAuthority");
  1562. if (!fKeyAuthorityMatch)
  1563. {
  1564. fCertInvalid = TRUE;
  1565. }
  1566. }
  1567. else
  1568. if (0 == strcmp(pce->pszObjId, szOID_KEY_ATTRIBUTES))
  1569. {
  1570. //wprintf(L"%d: %ws\n", i, L"szOID_KEY_ATTRIBUTES");
  1571. }
  1572. else
  1573. if (0 == strcmp(pce->pszObjId, szOID_CRL_DIST_POINTS))
  1574. {
  1575. //wprintf(L"%d: %ws\n", i, L"szOID_CRL_DIST_POINTS");
  1576. wprintf(myLoadResourceString(IDS_CRL_DIST_POINTS)); // "Contains CRL_DIST_POINTS revocation-check extension"
  1577. wprintf(wszNewLine);
  1578. fCheckRevocation = TRUE;
  1579. }
  1580. else
  1581. if (0 == strcmp(pce->pszObjId, szOID_NETSCAPE_REVOCATION_URL))
  1582. {
  1583. //wprintf(L"%d: %ws\n", i, L"szOID_NETSCAPE_REVOCATION_URL");
  1584. wprintf(myLoadResourceString(IDS_NETSCAPE_REVOCATION_URL)); // "Contains NETSCAPE_REVOCATION_URL revocation-check extension"
  1585. wprintf(wszNewLine);
  1586. fCheckRevocation = TRUE;
  1587. }
  1588. }
  1589. if (fCheckRevocation)
  1590. {
  1591. if (!g_fCryptSilent)
  1592. {
  1593. RevState = VerifyRevocation(pCertContext, pCertContextCA);
  1594. }
  1595. }
  1596. else
  1597. {
  1598. wprintf(myLoadResourceString(IDS_NO_REVCHECKEXTENSION)); // "Certificate has no revocation-check extension"
  1599. wprintf(wszNewLine);
  1600. RevState = RS_INCOMPLETE;
  1601. }
  1602. error:
  1603. cuUnloadCert(&pCertContext);
  1604. cuUnloadCert(&pCertContextCA);
  1605. if (NULL != pbKeyId)
  1606. {
  1607. LocalFree(pbKeyId);
  1608. }
  1609. if (NULL != pbKeyIdCACrossed)
  1610. {
  1611. LocalFree(pbKeyIdCACrossed);
  1612. }
  1613. if (S_OK == hr)
  1614. {
  1615. DWORD msgid;
  1616. wprintf(wszNewLine);
  1617. wprintf(
  1618. myLoadResourceString(
  1619. fCertInvalid?
  1620. IDS_FORMAT_NOT_VERIFY : // "%ws does NOT verify as issued by %ws"
  1621. IDS_FORMAT_IS_VERIFY), // "%ws verifies as issued by %ws"
  1622. pwszfnCert,
  1623. pwszfnCertCA);
  1624. switch (RevState)
  1625. {
  1626. case RS_FAIL:
  1627. msgid = IDS_FORMAT_REVCHECK_FAIL; // " -- Revocation check FAILED."
  1628. break;
  1629. case RS_PASS:
  1630. msgid = IDS_FORMAT_REVCHECK_PASS; // " -- Revocation check passed."
  1631. break;
  1632. case RS_REVOKED:
  1633. msgid = IDS_FORMAT_REVCHECK_REVOKED; // " -- Revocation check: REVOKED."
  1634. break;
  1635. default:
  1636. msgid = IDS_FORMAT_REVCHECK_SKIPPED; // " -- Revocation check skipped."
  1637. break;
  1638. }
  1639. wprintf(myLoadResourceString(msgid));
  1640. wprintf(wszNewLine);
  1641. if (fCertInvalid)
  1642. {
  1643. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1644. }
  1645. }
  1646. return(hr);
  1647. }
  1648. HRESULT
  1649. VerifyCRLAgainstCACert(
  1650. IN WCHAR const *pwszfnCRL,
  1651. IN WCHAR const *pwszfnCertCA,
  1652. OPTIONAL IN WCHAR const *pwszfnCertEE, // or delta CRL
  1653. OUT BOOL *pfCRLLoaded)
  1654. {
  1655. HRESULT hr;
  1656. CRL_CONTEXT const *pCRLContext = NULL;
  1657. CRL_CONTEXT const *pCRLContextDelta = NULL;
  1658. CERT_CONTEXT const *pCertContextCA = NULL;
  1659. CERT_CONTEXT const *pCertContextEE = NULL;
  1660. CRL_INFO const *pCRLInfo;
  1661. CRL_INFO const *pCRLInfoDelta;
  1662. CERT_INFO const *pCertInfoCA;
  1663. CERT_INFO const *pCertInfoEE;
  1664. BOOL fDisplayCANames = g_fVerbose;
  1665. DWORD i;
  1666. BOOL fCRLInvalid = FALSE;
  1667. SYSTEMTIME st;
  1668. FILETIME ft;
  1669. DWORD dwNameIdCRL;
  1670. DWORD dwNameIdCert;
  1671. // Load and decode CRL and certificate
  1672. *pfCRLLoaded = FALSE;
  1673. hr = cuLoadCRL(pwszfnCRL, &pCRLContext);
  1674. if (S_OK != hr)
  1675. {
  1676. cuPrintError(IDS_FORMAT_LOADTESTCRL, hr);
  1677. goto error;
  1678. }
  1679. *pfCRLLoaded = TRUE;
  1680. pCRLInfo = pCRLContext->pCrlInfo;
  1681. hr = cuLoadCert(pwszfnCertCA, &pCertContextCA);
  1682. if (S_OK != hr)
  1683. {
  1684. cuPrintError(IDS_FORMAT_LOADCACERT, hr);
  1685. goto error;
  1686. }
  1687. pCertInfoCA = pCertContextCA->pCertInfo;
  1688. if (NULL != pwszfnCertEE)
  1689. {
  1690. hr = cuLoadCert(pwszfnCertEE, &pCertContextEE);
  1691. if (S_OK != hr)
  1692. {
  1693. hr = cuLoadCRL(pwszfnCertEE, &pCRLContextDelta);
  1694. if (S_OK != hr)
  1695. {
  1696. cuPrintError(IDS_FORMAT_LOADTESTCERT, hr);
  1697. goto error;
  1698. }
  1699. pCRLInfoDelta = pCRLContextDelta->pCrlInfo;
  1700. }
  1701. else
  1702. {
  1703. pCertInfoEE = pCertContextEE->pCertInfo;
  1704. }
  1705. }
  1706. // Display name info:
  1707. hr = cuDisplayCertName(
  1708. TRUE,
  1709. myLoadResourceString(IDS_CRL), // "CRL"
  1710. myLoadResourceString(IDS_ISSUER), // "Issuer"
  1711. g_wszPad4,
  1712. &pCRLInfo->Issuer,
  1713. NULL);
  1714. _JumpIfError(hr, error, "cuDisplayCertName(CRL Issuer)");
  1715. hr = cuDisplayCertNames(
  1716. TRUE,
  1717. myLoadResourceString(IDS_ISSUINGCACERT), // "Issuing CA Cert"
  1718. pCertInfoCA);
  1719. _JumpIfError(hr, error, "cuDisplayCertNames(CA)");
  1720. if (g_fVerbose)
  1721. {
  1722. wprintf(wszNewLine);
  1723. cuDumpSerial(NULL, IDS_ISSUINGCACERT_SERIAL, &pCertInfoCA->SerialNumber);
  1724. wprintf(wszNewLine);
  1725. }
  1726. if (!CertCompareCertificateName(
  1727. X509_ASN_ENCODING,
  1728. const_cast<CERT_NAME_BLOB *>(&pCertInfoCA->Issuer),
  1729. const_cast<CERT_NAME_BLOB *>(&pCertInfoCA->Subject)))
  1730. {
  1731. // This API doesn't set LastError
  1732. wprintf(myLoadResourceString(IDS_ISSUINGCA_NOT_ROOT)); // "Issuing CA is not a root: Subject name does not match Issuer"
  1733. wprintf(wszNewLine);
  1734. wprintf(wszNewLine);
  1735. }
  1736. if (fDisplayCANames)
  1737. {
  1738. hr = cuDisplayCertNames(
  1739. TRUE,
  1740. myLoadResourceString(IDS_ISSUINGCACERT), // "Issuing CA Cert"
  1741. pCertInfoCA);
  1742. _JumpIfError(hr, error, "cuDisplayCertNames(CA)");
  1743. }
  1744. if (!CertCompareCertificateName(
  1745. X509_ASN_ENCODING,
  1746. const_cast<CERT_NAME_BLOB *>(&pCRLInfo->Issuer),
  1747. const_cast<CERT_NAME_BLOB *>(&pCertInfoCA->Subject)))
  1748. {
  1749. // This API doesn't set LastError
  1750. wprintf(wszNewLine);
  1751. wprintf(
  1752. myLoadResourceString(IDS_ISSUINGCA_CRLSUBJECT_NOT_ISSUER)); // "ERROR: Issuing CA Subject name does not match CRL Issuer"
  1753. wprintf(wszNewLine);
  1754. wprintf(wszNewLine);
  1755. fCRLInvalid = TRUE;
  1756. }
  1757. else
  1758. {
  1759. wprintf(myLoadResourceString(IDS_ISSUINGCA_CRLSUBJECT_IS_ISSUER)); // "Issuing CA Subject name matches CRL Issuer"
  1760. wprintf(wszNewLine);
  1761. }
  1762. GetSystemTime(&st);
  1763. if (!SystemTimeToFileTime(&st, &ft))
  1764. {
  1765. hr = myHLastError();
  1766. _JumpError(hr, error, "SystemTimeToFileTime");
  1767. }
  1768. if (0 < CompareFileTime(&pCRLInfo->ThisUpdate, &ft))
  1769. {
  1770. wprintf(wszNewLine);
  1771. wprintf(
  1772. myLoadResourceString(IDS_NOWNOTBEFORECRL_ERROR)); // "ERROR: CRL is not yet valid"
  1773. wprintf(wszNewLine);
  1774. wprintf(wszNewLine);
  1775. fCRLInvalid = TRUE;
  1776. }
  1777. if ((0 != pCRLInfo->NextUpdate.dwLowDateTime ||
  1778. 0 != pCRLInfo->NextUpdate.dwHighDateTime) &&
  1779. 0 > CompareFileTime(&pCRLInfo->NextUpdate, &ft))
  1780. {
  1781. wprintf(wszNewLine);
  1782. wprintf(
  1783. myLoadResourceString(IDS_NOWNOTAFTERCRL_ERROR)); // "ERROR: CRL has expired"
  1784. wprintf(wszNewLine);
  1785. wprintf(wszNewLine);
  1786. fCRLInvalid = TRUE;
  1787. }
  1788. if (0 < CompareFileTime(&pCertInfoCA->NotBefore, &pCRLInfo->ThisUpdate))
  1789. {
  1790. wprintf(wszNewLine);
  1791. wprintf(
  1792. myLoadResourceString(IDS_CANOTBEFORECRL_ERROR)); // "ERROR: CRL Valid before issuing CA Cert Valid"
  1793. wprintf(wszNewLine);
  1794. wprintf(wszNewLine);
  1795. //fCRLInvalid = TRUE;
  1796. }
  1797. if ((0 != pCRLInfo->NextUpdate.dwLowDateTime ||
  1798. 0 != pCRLInfo->NextUpdate.dwHighDateTime) &&
  1799. 0 > CompareFileTime(&pCertInfoCA->NotAfter, &pCRLInfo->NextUpdate))
  1800. {
  1801. wprintf(wszNewLine);
  1802. wprintf(
  1803. myLoadResourceString(IDS_CANOTAFTERCRL_ERROR)); // "ERROR: CRL Expires after issuing CA Cert Expires"
  1804. wprintf(wszNewLine);
  1805. wprintf(wszNewLine);
  1806. //fCRLInvalid = TRUE;
  1807. }
  1808. // verify CRL signature with the CA Cert public key
  1809. if (CryptVerifyCertificateSignature(
  1810. NULL,
  1811. X509_ASN_ENCODING,
  1812. pCRLContext->pbCrlEncoded,
  1813. pCRLContext->cbCrlEncoded,
  1814. &pCertContextCA->pCertInfo->SubjectPublicKeyInfo))
  1815. {
  1816. wprintf(myLoadResourceString(IDS_CRL_SIG_OK)); // "CRL signature is valid"
  1817. wprintf(wszNewLine);
  1818. }
  1819. else
  1820. {
  1821. hr = myHLastError();
  1822. _PrintError(hr, "CryptVerifyCertificateSignature");
  1823. wprintf(wszNewLine);
  1824. wprintf(myLoadResourceString(IDS_ERR_CA_SIG_NOT_CRLISSUER)); // "ERROR: CA did not issue CRL: Signature check failed"
  1825. wprintf(wszNewLine);
  1826. wprintf(wszNewLine);
  1827. fCRLInvalid = TRUE;
  1828. }
  1829. for (i = 0; i < pCRLInfo->cExtension; i++)
  1830. {
  1831. CERT_EXTENSION *pce;
  1832. pce = &pCRLInfo->rgExtension[i];
  1833. //wprintf(L"%d: %hs: %d, %x (%x)\n", i, pce->pszObjId, pce->fCritical, pce->Value.pbData, pce->Value.cbData);
  1834. if (0 == strcmp(pce->pszObjId, szOID_AUTHORITY_KEY_IDENTIFIER2))
  1835. {
  1836. BOOL fKeyAuthorityMatch;
  1837. //wprintf(L"%d: %ws\n", i, L"szOID_AUTHORITY_KEY_IDENTIFIER2");
  1838. hr = cuVerifyKeyAuthority(
  1839. &pCRLInfo->Issuer,
  1840. pCertInfoCA,
  1841. pce->Value.pbData,
  1842. pce->Value.cbData,
  1843. FALSE,
  1844. &fKeyAuthorityMatch);
  1845. _JumpIfError(hr, error, "cuVerifyKeyAuthority");
  1846. if (!fKeyAuthorityMatch)
  1847. {
  1848. fCRLInvalid = TRUE;
  1849. }
  1850. }
  1851. }
  1852. hr = myGetCRLNameId(pCRLContext, &dwNameIdCRL);
  1853. _PrintIfError(hr, "myGetCRLNameId");
  1854. hr = myGetNameId(pCertContextCA, &dwNameIdCert);
  1855. _PrintIfError(hr, "myGetNameId");
  1856. if (MAXDWORD != dwNameIdCRL &&
  1857. MAXDWORD != dwNameIdCert &&
  1858. dwNameIdCRL != dwNameIdCert)
  1859. {
  1860. wprintf(myLoadResourceString(IDS_CRLNAMEID_NOT_CERTNAMEID)); // "WARNING: CRL CA Version does not match Cert CA Version"
  1861. wprintf(wszNewLine);
  1862. wprintf(wszNewLine);
  1863. //fCRLInvalid = TRUE;
  1864. }
  1865. if (NULL != pCertContextEE)
  1866. {
  1867. BOOL fCertLoaded;
  1868. wprintf(wszNewLine);
  1869. wprintf(myLoadResourceString(IDS_VERIFYING_ISSUED_CERT)); // "Verifying Issued Certificate:"
  1870. wprintf(wszNewLine);
  1871. hr = VerifyCertAgainstParent(
  1872. pwszfnCertEE,
  1873. pwszfnCertCA,
  1874. NULL, // pwszfnCertCACrossed
  1875. &fCertLoaded);
  1876. if (S_OK != hr)
  1877. {
  1878. _PrintError(hr, "VerifyCertAgainstParent");
  1879. fCRLInvalid = TRUE;
  1880. }
  1881. wprintf(wszNewLine);
  1882. if (!CertCompareCertificateName(
  1883. X509_ASN_ENCODING,
  1884. const_cast<CERT_NAME_BLOB *>(&pCertInfoEE->Issuer),
  1885. const_cast<CERT_NAME_BLOB *>(&pCRLInfo->Issuer)))
  1886. {
  1887. // This API doesn't set LastError
  1888. wprintf(wszNewLine);
  1889. wprintf(myLoadResourceString(IDS_CRLISSUER_NOT_EEISSUER)); // "ERROR: CRL Issuer does not match Cert Issuer"
  1890. wprintf(wszNewLine);
  1891. wprintf(wszNewLine);
  1892. fCRLInvalid = TRUE;
  1893. }
  1894. else
  1895. {
  1896. wprintf(myLoadResourceString(IDS_CRLISSUER_IS_EEISSUER)); // "CRL Issuer matches Cert Issuer"
  1897. wprintf(wszNewLine);
  1898. }
  1899. if (!cuVerifyIDP(pCertContextEE, pCRLContext))
  1900. {
  1901. wprintf(wszNewLine);
  1902. wprintf(myLoadResourceString(IDS_CRL_IDP_MISMATCH)); // "ERROR: CRL IDP extension does not match Cert CDP"
  1903. wprintf(wszNewLine);
  1904. wprintf(wszNewLine);
  1905. fCRLInvalid = TRUE;
  1906. }
  1907. }
  1908. else if (NULL != pCRLContextDelta)
  1909. {
  1910. BOOL fCRLLoaded;
  1911. BOOL fDelta;
  1912. DWORD dwNameIdDelta;
  1913. wprintf(wszNewLine);
  1914. wprintf(myLoadResourceString(IDS_VERIFYING_DELTA_CRL)); // "Verifying Delta CRL:"
  1915. wprintf(wszNewLine);
  1916. hr = VerifyCRLAgainstCACert(
  1917. pwszfnCertEE, // pwszfnCRL
  1918. pwszfnCertCA,
  1919. NULL, // pwszfnCertEE
  1920. &fCRLLoaded);
  1921. if (S_OK != hr)
  1922. {
  1923. _PrintError(hr, "VerifyCRLAgainstCACert");
  1924. fCRLInvalid = TRUE;
  1925. }
  1926. wprintf(wszNewLine);
  1927. if (!CertCompareCertificateName(
  1928. X509_ASN_ENCODING,
  1929. const_cast<CERT_NAME_BLOB *>(&pCRLInfoDelta->Issuer),
  1930. const_cast<CERT_NAME_BLOB *>(&pCRLInfo->Issuer)))
  1931. {
  1932. // This API doesn't set LastError
  1933. wprintf(wszNewLine);
  1934. wprintf(myLoadResourceString(IDS_CRLISSUER_NOT_DELTAISSUER)); // "ERROR: CRL Issuer does not match Delta CRL Issuer"
  1935. wprintf(wszNewLine);
  1936. wprintf(wszNewLine);
  1937. fCRLInvalid = TRUE;
  1938. }
  1939. else
  1940. {
  1941. wprintf(myLoadResourceString(IDS_CRLISSUER_IS_DELTAISSUER)); // "CRL Issuer matches Delta CRL Issuer"
  1942. wprintf(wszNewLine);
  1943. }
  1944. hr = myIsDeltaCRL(pCRLContext, &fDelta);
  1945. _JumpIfError(hr, error, "myIsDeltaCRL");
  1946. if (fDelta)
  1947. {
  1948. wprintf(wszNewLine);
  1949. wprintf(myLoadResourceString(IDS_CRL_NOT_BASE)); // "ERROR: CRL is not a Base CRL"
  1950. wprintf(wszNewLine);
  1951. wprintf(wszNewLine);
  1952. fCRLInvalid = TRUE;
  1953. }
  1954. hr = myIsDeltaCRL(pCRLContextDelta, &fDelta);
  1955. _JumpIfError(hr, error, "myIsDeltaCRL");
  1956. if (!fDelta)
  1957. {
  1958. wprintf(wszNewLine);
  1959. wprintf(myLoadResourceString(IDS_CRL_NOT_DELTA)); // "ERROR: CRL is not a Delta CRL"
  1960. wprintf(wszNewLine);
  1961. wprintf(wszNewLine);
  1962. fCRLInvalid = TRUE;
  1963. }
  1964. hr = myGetCRLNameId(pCRLContextDelta, &dwNameIdDelta);
  1965. _PrintIfError(hr, "myGetCRLNameId");
  1966. if (MAXDWORD != dwNameIdCRL &&
  1967. MAXDWORD != dwNameIdDelta &&
  1968. dwNameIdCRL != dwNameIdDelta)
  1969. {
  1970. wprintf(myLoadResourceString(IDS_CRLNAMEID_NOT_DELTANAMEID)); // "WARNING: CRL CA Version does not match Delta CRL CA Version"
  1971. wprintf(wszNewLine);
  1972. wprintf(wszNewLine);
  1973. //fCRLInvalid = TRUE;
  1974. }
  1975. if (fDelta && !cuVerifyMinimumBaseCRL(pCRLContext, pCRLContextDelta))
  1976. {
  1977. wprintf(wszNewLine);
  1978. wprintf(myLoadResourceString(IDS_CRL_MINBASE_MISMATCH)); // "ERROR: CRL Number less than Delta CRL Minimum Base"
  1979. wprintf(wszNewLine);
  1980. wprintf(wszNewLine);
  1981. fCRLInvalid = TRUE;
  1982. }
  1983. }
  1984. hr = S_OK;
  1985. error:
  1986. cuUnloadCRL(&pCRLContext);
  1987. cuUnloadCert(&pCertContextCA);
  1988. cuUnloadCert(&pCertContextEE);
  1989. if (S_OK == hr)
  1990. {
  1991. wprintf(wszNewLine);
  1992. wprintf(
  1993. myLoadResourceString(
  1994. fCRLInvalid?
  1995. IDS_FORMAT_NOT_VERIFY : // "%ws does NOT verify as issued by %ws"
  1996. IDS_FORMAT_IS_VERIFY), // "%ws verifies as issued by %ws"
  1997. pwszfnCRL,
  1998. pwszfnCertCA);
  1999. wprintf(wszNewLine);
  2000. if (fCRLInvalid)
  2001. {
  2002. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  2003. }
  2004. }
  2005. return(hr);
  2006. }
  2007. HRESULT
  2008. VerifyBlobAgainstCACert(
  2009. IN WCHAR const *pwszfnBlob,
  2010. IN WCHAR const *pwszfnCertCA)
  2011. {
  2012. HRESULT hr;
  2013. CERT_CONTEXT const *pCertContextCA = NULL;
  2014. CERT_INFO const *pCertInfoCA;
  2015. BYTE *pbBlob = NULL;
  2016. DWORD cbBlob;
  2017. CERT_SIGNED_CONTENT_INFO *pcsci = NULL;
  2018. DWORD cbcsci;
  2019. BOOL fSigInvalid = FALSE;
  2020. // Load blob and load and decode certificate
  2021. hr = DecodeFileW(pwszfnBlob, &pbBlob, &cbBlob, CRYPT_STRING_ANY);
  2022. if (S_OK != hr)
  2023. {
  2024. cuPrintError(IDS_ERR_FORMAT_DECODEFILE, hr);
  2025. goto error;
  2026. }
  2027. if (!myDecodeObject(
  2028. X509_ASN_ENCODING,
  2029. X509_CERT,
  2030. pbBlob,
  2031. cbBlob,
  2032. CERTLIB_USE_LOCALALLOC,
  2033. (VOID **) &pcsci,
  2034. &cbcsci))
  2035. {
  2036. hr = myHLastError();
  2037. _PrintError3(
  2038. hr,
  2039. "myDecodeObject",
  2040. CRYPT_E_ASN1_BADTAG,
  2041. CRYPT_E_ASN1_EOD);
  2042. }
  2043. hr = cuLoadCert(pwszfnCertCA, &pCertContextCA);
  2044. if (S_OK != hr)
  2045. {
  2046. cuPrintError(IDS_FORMAT_LOADCACERT, hr);
  2047. goto error;
  2048. }
  2049. pCertInfoCA = pCertContextCA->pCertInfo;
  2050. hr = cuDumpAsnBinary(pbBlob, cbBlob, MAXDWORD);
  2051. if (S_OK != hr)
  2052. {
  2053. cuPrintError(IDS_ERR_FORMAT_CANNOT_DECODE, hr);
  2054. goto error;
  2055. }
  2056. // Display name info:
  2057. hr = cuDisplayCertNames(
  2058. TRUE,
  2059. myLoadResourceString(IDS_ISSUINGCACERT), // "Issuing CA Cert"
  2060. pCertInfoCA);
  2061. _JumpIfError(hr, error, "cuDisplayCertNames(CA)");
  2062. if (g_fVerbose)
  2063. {
  2064. wprintf(wszNewLine);
  2065. cuDumpSerial(NULL, IDS_ISSUINGCACERT_SERIAL, &pCertInfoCA->SerialNumber);
  2066. wprintf(wszNewLine);
  2067. }
  2068. // verify blob signature with the CA Cert public key
  2069. if (CryptVerifyCertificateSignature(
  2070. NULL,
  2071. X509_ASN_ENCODING,
  2072. pbBlob,
  2073. cbBlob,
  2074. &pCertContextCA->pCertInfo->SubjectPublicKeyInfo))
  2075. {
  2076. wprintf(myLoadResourceString(IDS_CRL_SIG_OK)); // "CRL signature is valid"
  2077. wprintf(wszNewLine);
  2078. }
  2079. else
  2080. {
  2081. hr = myHLastError();
  2082. _PrintError(hr, "CryptVerifyCertificateSignature");
  2083. wprintf(wszNewLine);
  2084. wprintf(myLoadResourceString(IDS_ERR_CA_SIG_NOT_CRLISSUER)); // "ERROR: CA did not issue CRL: Signature check failed"
  2085. wprintf(wszNewLine);
  2086. wprintf(wszNewLine);
  2087. fSigInvalid = TRUE;
  2088. }
  2089. hr = S_OK;
  2090. error:
  2091. if (NULL != pcsci)
  2092. {
  2093. LocalFree(pcsci);
  2094. }
  2095. if (NULL != pbBlob)
  2096. {
  2097. LocalFree(pbBlob);
  2098. }
  2099. cuUnloadCert(&pCertContextCA);
  2100. if (S_OK == hr)
  2101. {
  2102. wprintf(wszNewLine);
  2103. wprintf(
  2104. myLoadResourceString(
  2105. fSigInvalid?
  2106. IDS_FORMAT_NOT_VERIFY : // "%ws does NOT verify as issued by %ws"
  2107. IDS_FORMAT_IS_VERIFY), // "%ws verifies as issued by %ws"
  2108. pwszfnBlob,
  2109. pwszfnCertCA);
  2110. wprintf(wszNewLine);
  2111. }
  2112. return(hr);
  2113. }
  2114. HRESULT
  2115. cuParseOIDList(
  2116. IN WCHAR const *pwszIn,
  2117. OUT DWORD *pcOut,
  2118. OUT char ***pppszOut)
  2119. {
  2120. HRESULT hr;
  2121. WCHAR **ppwszOID = NULL;
  2122. char **ppszOID = NULL;
  2123. DWORD cOID;
  2124. DWORD i;
  2125. hr = cuParseStrings(pwszIn, FALSE, NULL, NULL, &ppwszOID, NULL);
  2126. _JumpIfError2(hr, error, "cuParseStrings", hr);
  2127. for (i = 0; NULL != ppwszOID[i]; i++)
  2128. {
  2129. hr = myVerifyObjId(ppwszOID[i]);
  2130. _JumpIfErrorStr2(hr, error, "myVerifyObjId", ppwszOID[i], hr);
  2131. }
  2132. if (0 == i)
  2133. {
  2134. hr = E_INVALIDARG;
  2135. _JumpError(hr, error, "No OIDs");
  2136. }
  2137. cOID = i;
  2138. ppszOID = (char **) LocalAlloc(
  2139. LMEM_FIXED | LMEM_ZEROINIT,
  2140. (cOID + 1) * sizeof(*ppszOID));
  2141. if (NULL == ppszOID)
  2142. {
  2143. hr = E_OUTOFMEMORY;
  2144. _JumpError(hr, error, "LocalAlloc");
  2145. }
  2146. for (i = 0; NULL != ppwszOID[i]; i++)
  2147. {
  2148. if (!myConvertWszToSz(&ppszOID[i], ppwszOID[i], -1))
  2149. {
  2150. _JumpError(hr, error, "myConvertWszToSz");
  2151. }
  2152. }
  2153. *pcOut = cOID;
  2154. *pppszOut = ppszOID;
  2155. ppszOID = NULL;
  2156. hr = S_OK;
  2157. error:
  2158. cuFreeStringArray(ppwszOID);
  2159. cuFreeStringArrayA(ppszOID);
  2160. return(hr);
  2161. }
  2162. HRESULT
  2163. verbVerifyCert(
  2164. IN WCHAR const *pwszOption,
  2165. IN WCHAR const *pwszfnCert,
  2166. IN WCHAR const *pwszfnCertCA,
  2167. IN WCHAR const *pwszfnCertCACrossed,
  2168. IN WCHAR const *pwszArg4)
  2169. {
  2170. HRESULT hr;
  2171. DWORD cApplicationPolicies;
  2172. char **ppszApplicationPolicies = NULL;
  2173. DWORD cIssuancePolicies;
  2174. char **ppszIssuancePolicies = NULL;
  2175. // First check for Application and Issuance policy OID lists
  2176. cApplicationPolicies = 0;
  2177. cIssuancePolicies = 0;
  2178. if (NULL != pwszfnCertCA)
  2179. {
  2180. hr = S_OK;
  2181. if (!myIsMinusSignString(pwszfnCertCA))
  2182. {
  2183. hr = cuParseOIDList(
  2184. pwszfnCertCA,
  2185. &cApplicationPolicies,
  2186. &ppszApplicationPolicies);
  2187. _PrintIfErrorStr2(hr, "cuParseOIDList", L"Application", hr);
  2188. }
  2189. if (S_OK == hr)
  2190. {
  2191. if (NULL != pwszfnCertCACrossed)
  2192. {
  2193. hr = cuParseOIDList(
  2194. pwszfnCertCACrossed,
  2195. &cIssuancePolicies,
  2196. &ppszIssuancePolicies);
  2197. _JumpIfErrorStr2(hr, error, "cuParseOIDList", L"Issuance", hr);
  2198. pwszfnCertCACrossed = NULL;
  2199. }
  2200. pwszfnCertCA = NULL;
  2201. }
  2202. }
  2203. if (NULL != pwszfnCertCA)
  2204. {
  2205. BOOL fCertLoaded;
  2206. hr = VerifyCertAgainstParent(
  2207. pwszfnCert,
  2208. pwszfnCertCA,
  2209. pwszfnCertCACrossed,
  2210. &fCertLoaded);
  2211. if (S_OK != hr && !fCertLoaded)
  2212. {
  2213. BOOL fCRLLoaded;
  2214. hr = VerifyCRLAgainstCACert(
  2215. pwszfnCert,
  2216. pwszfnCertCA,
  2217. pwszfnCertCACrossed,
  2218. &fCRLLoaded);
  2219. if (S_OK != hr && !fCRLLoaded)
  2220. {
  2221. hr = VerifyBlobAgainstCACert(pwszfnCert, pwszfnCertCA);
  2222. }
  2223. }
  2224. }
  2225. else
  2226. {
  2227. hr = VerifyCertAgainstChain(
  2228. pwszfnCert,
  2229. cApplicationPolicies,
  2230. ppszApplicationPolicies,
  2231. cIssuancePolicies,
  2232. ppszIssuancePolicies);
  2233. }
  2234. error:
  2235. cuFreeStringArrayA(ppszApplicationPolicies);
  2236. cuFreeStringArrayA(ppszIssuancePolicies);
  2237. return(hr);
  2238. }
  2239. DWORD amsgidState[CHECK7F_COUNT] = {
  2240. //IDS_CHECK7F_FIELD_UNKNOWN, // "???"
  2241. IDS_CHECK7F_FIELD_NONE, // "None"
  2242. IDS_CHECK7F_FIELD_OTHER, // "Other"
  2243. IDS_CHECK7F_FIELD_ISSUER, // "Issuer"
  2244. IDS_CHECK7F_FIELD_ISSUERRDN, // "IssuerRDN"
  2245. IDS_CHECK7F_FIELD_ISSUERRDNATTRIBUTE, // "IssuerRDNAttribute"
  2246. IDS_CHECK7F_FIELD_ISSUERRDNSTRING, // "IssuerRDNString"
  2247. IDS_CHECK7F_FIELD_SUBJECT, // "Subject"
  2248. IDS_CHECK7F_FIELD_SUBJECTRDN, // "SubjectRDN"
  2249. IDS_CHECK7F_FIELD_SUBJECTRDNATTRIBUTE, // "SubjectRDNAttribute"
  2250. IDS_CHECK7F_FIELD_SUBJECTRDNSTRING, // "SubjectRDNString"
  2251. IDS_CHECK7F_FIELD_EXTENSIONS, // "Extensions"
  2252. IDS_CHECK7F_FIELD_EXTENSIONARRAY, // "ExtensionArray"
  2253. IDS_CHECK7F_FIELD_EXTENSION, // "Extension"
  2254. IDS_CHECK7F_FIELD_EXTENSIONVALUE, // "ExtensionValue"
  2255. IDS_CHECK7F_FIELD_EXTENSIONVALUERAW, // "ExtensionValueRaw"
  2256. };
  2257. HRESULT
  2258. verbCheck7f(
  2259. IN WCHAR const *pwszOption,
  2260. IN WCHAR const *pwszfnCert,
  2261. IN WCHAR const *pwszArg2,
  2262. IN WCHAR const *pwszArg3,
  2263. IN WCHAR const *pwszArg4)
  2264. {
  2265. HRESULT hr;
  2266. CERT_CONTEXT const *pCertContext = NULL;
  2267. CERT_INFO const *pCertInfo;
  2268. WCHAR const *pwszObjectIdDescription = NULL;
  2269. DWORD i;
  2270. DWORD dwLen;
  2271. DWORD index;
  2272. DWORD index2;
  2273. DWORD state;
  2274. DWORD cwcField;
  2275. DWORD cwcObjectId;
  2276. WCHAR wszField[128];
  2277. WCHAR wszObjectId[40];
  2278. // Load and decode certificates
  2279. hr = cuLoadCert(pwszfnCert, &pCertContext);
  2280. if (S_OK != hr)
  2281. {
  2282. cuPrintError(IDS_FORMAT_LOADTESTCERT, hr);
  2283. goto error;
  2284. }
  2285. pCertInfo = pCertContext->pCertInfo;
  2286. if (g_fVerbose)
  2287. {
  2288. wprintf(wszNewLine);
  2289. wprintf(myLoadResourceString(IDS_CERTCOLON)); // "Cert:"
  2290. wprintf(wszNewLine);
  2291. DumpHex(0, pCertContext->pbCertEncoded, pCertContext->cbCertEncoded);
  2292. // Display name info:
  2293. hr = cuDisplayCertNames(
  2294. TRUE,
  2295. myLoadResourceString(IDS_CERT), // "Cert"
  2296. pCertInfo);
  2297. _JumpIfError(hr, error, "cuDisplayCertNames(Cert)");
  2298. }
  2299. cwcField = sizeof(wszField)/sizeof(wszField[0]);
  2300. cwcObjectId = sizeof(wszObjectId)/sizeof(wszObjectId[0]);
  2301. hr = myCheck7f(
  2302. pCertContext->pbCertEncoded,
  2303. pCertContext->cbCertEncoded,
  2304. g_fVerbose,
  2305. &state,
  2306. &index,
  2307. &index2,
  2308. &cwcField,
  2309. wszField,
  2310. &cwcObjectId,
  2311. wszObjectId,
  2312. &pwszObjectIdDescription);
  2313. _JumpIfError(hr, error, "myCheck7f");
  2314. if (CHECK7F_NONE != state)
  2315. {
  2316. DWORD msgid = IDS_CHECK7F_FIELD_UNKNOWN; // "???"
  2317. CSASSERT(0 != amsgidState[CHECK7F_COUNT - 1]);
  2318. if (CHECK7F_COUNT > state)
  2319. {
  2320. msgid = amsgidState[state];
  2321. }
  2322. CSASSERT(0 != msgid);
  2323. wprintf(myLoadResourceString(IDS_FORMAT_SUSPECT_LENGTH)); // "Suspect length in"
  2324. wprintf(myLoadResourceString(msgid));
  2325. if (0 != index)
  2326. {
  2327. wprintf(
  2328. 0 != index2? L"[%u,%u]" : L"[%u]",
  2329. index - 1,
  2330. index2 - 1);
  2331. }
  2332. wprintf(L": field=%ws", wszField);
  2333. wprintf(
  2334. myLoadResourceString(IDS_FORMAT_FIELD), // ": field=%ws"
  2335. wszField);
  2336. if (0 != index)
  2337. {
  2338. wprintf(
  2339. 0 != index2? L"[%u,%u]" : L"[%u]",
  2340. index - 1,
  2341. index2 - 1);
  2342. }
  2343. if (L'\0' != wszObjectId[0])
  2344. {
  2345. wprintf(
  2346. myLoadResourceString(IDS_FORMAT_OID), // ", oid=%ws"
  2347. wszObjectId);
  2348. }
  2349. if (NULL != pwszObjectIdDescription)
  2350. {
  2351. wprintf(L" (%ws)", pwszObjectIdDescription);
  2352. }
  2353. wprintf(wszNewLine);
  2354. hr = CERTSRV_E_ENCODING_LENGTH;
  2355. }
  2356. for (i = 0; i < pCertInfo->cExtension; i++)
  2357. {
  2358. CERT_EXTENSION *pce;
  2359. WCHAR const *pwszDescriptiveName;
  2360. pce = &pCertInfo->rgExtension[i];
  2361. if (g_fVerbose)
  2362. {
  2363. wprintf(wszNewLine);
  2364. wprintf(
  2365. myLoadResourceString(IDS_FORMAT_EXTENSION_OID), // "Extension %d: oid=""%hs"" fcrit=%u length=%x"
  2366. i,
  2367. pce->pszObjId,
  2368. pce->fCritical,
  2369. pce->Value.cbData);
  2370. pwszDescriptiveName = cuGetOIDNameA(pce->pszObjId);
  2371. if (NULL != pwszDescriptiveName)
  2372. {
  2373. wprintf(L" (%ws)", pwszDescriptiveName);
  2374. }
  2375. wprintf(wszNewLine);
  2376. DumpHex(0, pce->Value.pbData, pce->Value.cbData);
  2377. }
  2378. }
  2379. error:
  2380. cuUnloadCert(&pCertContext);
  2381. return(hr);
  2382. }
  2383. HRESULT
  2384. cuVerifySignature(
  2385. IN BYTE const *pbEncoded,
  2386. IN DWORD cbEncoded,
  2387. IN CERT_PUBLIC_KEY_INFO const *pcpki,
  2388. IN BOOL fSuppressSuccess,
  2389. IN BOOL fSuppressError)
  2390. {
  2391. HRESULT hr;
  2392. DWORD id = 0;
  2393. // verify with the passed public key
  2394. if (!CryptVerifyCertificateSignature(
  2395. NULL,
  2396. X509_ASN_ENCODING,
  2397. const_cast<BYTE *>(pbEncoded),
  2398. cbEncoded,
  2399. const_cast<CERT_PUBLIC_KEY_INFO *>(pcpki)))
  2400. {
  2401. hr = myHLastError();
  2402. if (E_INVALIDARG == hr)
  2403. {
  2404. CRYPT_DATA_BLOB Blob;
  2405. Blob.cbData = cbEncoded;
  2406. Blob.pbData = const_cast<BYTE *>(pbEncoded);
  2407. if (!CryptVerifyCertificateSignatureEx(
  2408. NULL, // hCryptProv
  2409. X509_ASN_ENCODING,
  2410. CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB,
  2411. &Blob,
  2412. CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL,
  2413. NULL, // pvIssuer
  2414. 0, // dwFlags
  2415. NULL)) // pvReserved
  2416. {
  2417. HRESULT hr2 = myHLastError();
  2418. _PrintError(hr2, "CryptVerifyCertificateSignatureEx");
  2419. }
  2420. else
  2421. {
  2422. hr = S_OK;
  2423. if (!fSuppressSuccess)
  2424. {
  2425. id = IDS_NULL_SIGNATUREMATCHES; // "NULL signature verifies"
  2426. }
  2427. }
  2428. }
  2429. if (S_OK != hr && !fSuppressError)
  2430. {
  2431. id = IDS_ERR_FORMAT_NO_SIGNATUREMATCHES; // "Signature does not match Public key: %x"
  2432. }
  2433. }
  2434. else
  2435. {
  2436. hr = S_OK;
  2437. if (!fSuppressSuccess)
  2438. {
  2439. id = IDS_SIGNATUREMATCHES; // "Signature matches Public Key"
  2440. }
  2441. }
  2442. if (0 != id)
  2443. {
  2444. wprintf(myLoadResourceString(id), hr);
  2445. wprintf(wszNewLine);
  2446. }
  2447. return(hr);
  2448. }