Source code of Windows XP (NT5)
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.

732 lines
18 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: CCert.cpp
  8. //
  9. // Contents: Microsoft Internet Security Certificate Class
  10. //
  11. // History: 14-Aug-1997 pberkman created
  12. //
  13. //--------------------------------------------------------------------------
  14. #include "global.hxx"
  15. #include "signer.h"
  16. extern "C"
  17. {
  18. extern BOOL WINAPI GetCryptProvFromCert(HWND hwnd, PCCERT_CONTEXT pCert, HCRYPTPROV *phCryptProv,
  19. DWORD *pdwKeySpec, BOOL *pfDidCryptAcquire,
  20. LPWSTR *ppwszTmpContainer, LPWSTR *ppwszProviderName,
  21. DWORD *pdwProviderType);
  22. extern void WINAPI FreeCryptProvFromCert(BOOL fAcquired, HCRYPTPROV hProv, LPWSTR pwszCapiProvider,
  23. DWORD dwProviderType, LPWSTR pwszTmpContainer);
  24. };
  25. #include "ccert.hxx"
  26. CCert_::CCert_(PCCERT_CONTEXT pCertContext)
  27. {
  28. m_pCertContext = CertDuplicateCertificateContext(pCertContext);
  29. m_pCCert_Issuer = NULL;
  30. m_pwszPublisherName = NULL;
  31. m_pwszAgencyName = NULL;
  32. m_pwszProvider = NULL;
  33. m_pwszKeyContainer = NULL;
  34. m_dwProviderType = 0;
  35. m_chStores = 0;
  36. m_fTriedPrivateKey = FALSE;
  37. memset(m_pahStores, 0x00, sizeof(HCERTSTORE) * CCERT_MAXSTORES);
  38. }
  39. CCert_::~CCert_(void)
  40. {
  41. CertFreeCertificateContext(m_pCertContext);
  42. DELETE_OBJECT(m_pCCert_Issuer);
  43. DELETE_OBJECT(m_pwszPublisherName);
  44. DELETE_OBJECT(m_pwszAgencyName);
  45. DELETE_OBJECT(m_pwszProvider);
  46. DELETE_OBJECT(m_pwszKeyContainer);
  47. for (int i = 0; i < (int)m_chStores; i++)
  48. {
  49. if (m_pahStores[i])
  50. {
  51. CertCloseStore(m_pahStores[i], 0);
  52. }
  53. }
  54. }
  55. WCHAR *CCert_::PublisherName(void)
  56. {
  57. if (m_pwszPublisherName)
  58. {
  59. return(m_pwszPublisherName);
  60. }
  61. if (!(this->ExtractCommonNameExt(&m_pwszPublisherName)))
  62. {
  63. if (!(this->ExtractCommonNameAttr(&m_pwszPublisherName)))
  64. {
  65. m_pwszPublisherName = this->GetRDNAttr(szOID_COMMON_NAME,
  66. &m_pCertContext->pCertInfo->Subject);
  67. }
  68. }
  69. return(m_pwszPublisherName);
  70. }
  71. WCHAR *CCert_::AgencyName(void)
  72. {
  73. if (m_pwszAgencyName)
  74. {
  75. return(m_pwszAgencyName);
  76. }
  77. if (!(m_pCertContext))
  78. {
  79. return(NULL);
  80. }
  81. m_pwszAgencyName = this->GetRDNAttr(szOID_ORGANIZATIONAL_UNIT_NAME,
  82. &m_pCertContext->pCertInfo->Subject);
  83. if (!(m_pwszAgencyName))
  84. {
  85. m_pwszAgencyName = this->GetRDNAttr(szOID_ORGANIZATION_NAME,
  86. &m_pCertContext->pCertInfo->Subject);
  87. if (!(m_pwszAgencyName))
  88. {
  89. m_pwszAgencyName = this->GetRDNAttr(szOID_COMMON_NAME,
  90. &m_pCertContext->pCertInfo->Subject);
  91. }
  92. }
  93. return(m_pwszAgencyName);
  94. }
  95. WCHAR *CCert_::ProviderName(void)
  96. {
  97. if (m_pwszProvider)
  98. {
  99. return(m_pwszProvider);
  100. }
  101. if (!(m_pCertContext))
  102. {
  103. return(NULL);
  104. }
  105. this->FindPrivateKey();
  106. return(m_pwszProvider);
  107. }
  108. DWORD CCert_::ProviderType(void)
  109. {
  110. if (m_pwszProvider)
  111. {
  112. return(m_dwProviderType);
  113. }
  114. this->FindPrivateKey();
  115. return(m_dwProviderType);
  116. }
  117. WCHAR *CCert_::PrivateKeyContainer(void)
  118. {
  119. if (m_pwszKeyContainer)
  120. {
  121. return(m_pwszKeyContainer);
  122. }
  123. this->FindPrivateKey();
  124. return(m_pwszKeyContainer);
  125. }
  126. BOOL CCert_::BuildChain(FILETIME *psftVerifyAsOf)
  127. {
  128. FILETIME sft;
  129. if (!(m_pCertContext))
  130. {
  131. return(FALSE);
  132. }
  133. if (m_pCCert_Issuer)
  134. {
  135. return(TRUE);
  136. }
  137. if (!(psftVerifyAsOf))
  138. {
  139. GetSystemTimeAsFileTime(&sft);
  140. psftVerifyAsOf = &sft;
  141. }
  142. this->OpenStores();
  143. return(this->BuildChainPrivate(m_chStores, m_pahStores, psftVerifyAsOf));
  144. }
  145. //////////////////////////////////////////////////////////////////////////
  146. ////
  147. //// protected
  148. ////
  149. BOOL CCert_::ExtractCommonNameExt(WCHAR **ppwszRet)
  150. {
  151. *ppwszRet = NULL;
  152. if (!(m_pCertContext))
  153. {
  154. return(FALSE);
  155. }
  156. PCERT_NAME_VALUE pNameValue;
  157. PCERT_EXTENSION pExt;
  158. pNameValue = NULL;
  159. pExt = CertFindExtension(SPC_COMMON_NAME_OBJID,
  160. m_pCertContext->pCertInfo->cExtension,
  161. m_pCertContext->pCertInfo->rgExtension);
  162. if (pExt)
  163. {
  164. DWORD cbInfo;
  165. PCERT_RDN_VALUE_BLOB pValue;
  166. DWORD dwValueType;
  167. DWORD cwsz;
  168. cbInfo = 0;
  169. CryptDecodeObject( X509_ASN_ENCODING,
  170. X509_NAME_VALUE,
  171. pExt->Value.pbData,
  172. pExt->Value.cbData,
  173. 0,
  174. NULL,
  175. &cbInfo);
  176. if (cbInfo == 0)
  177. {
  178. return(FALSE);
  179. }
  180. if (!(pNameValue = (PCERT_NAME_VALUE)new BYTE[cbInfo]))
  181. {
  182. return(FALSE);
  183. }
  184. if (!(CryptDecodeObject(X509_ASN_ENCODING,
  185. X509_NAME_VALUE,
  186. pExt->Value.pbData,
  187. pExt->Value.cbData,
  188. 0,
  189. pNameValue,
  190. &cbInfo)))
  191. {
  192. delete pNameValue;
  193. return(FALSE);
  194. }
  195. dwValueType = pNameValue->dwValueType;
  196. pValue = &pNameValue->Value;
  197. cwsz = CertRDNValueToStrW(dwValueType, pValue, NULL, 0);
  198. if (cwsz > 1)
  199. {
  200. if (!(*ppwszRet = new WCHAR[cwsz]))
  201. {
  202. delete pNameValue;
  203. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  204. return(FALSE);
  205. }
  206. CertRDNValueToStrW(dwValueType, pValue, *ppwszRet, cwsz);
  207. delete pNameValue;
  208. return(TRUE);
  209. }
  210. }
  211. DELETE_OBJECT(pNameValue);
  212. return(FALSE);
  213. }
  214. BOOL CCert_::ExtractCommonNameAttr(WCHAR **ppwszRet)
  215. {
  216. *ppwszRet = GetRDNAttr(szOID_COMMON_NAME, &m_pCertContext->pCertInfo->Subject);
  217. if (*ppwszRet)
  218. {
  219. return(TRUE);
  220. }
  221. return(FALSE);
  222. }
  223. WCHAR *CCert_::GetRDNAttr(char *pszObjId, PCERT_NAME_BLOB pNameBlob)
  224. {
  225. LPWSTR pwsz;
  226. PCERT_NAME_INFO pNameInfo;
  227. PCERT_RDN_ATTR pRDNAttr;
  228. DWORD cbInfo;
  229. pwsz = NULL;
  230. pNameInfo = NULL;
  231. cbInfo = 0;
  232. CryptDecodeObject( X509_ASN_ENCODING,
  233. X509_NAME,
  234. pNameBlob->pbData,
  235. pNameBlob->cbData,
  236. 0,
  237. NULL,
  238. &cbInfo);
  239. if (cbInfo == 0)
  240. {
  241. return(NULL);
  242. }
  243. if (!(pNameInfo = (PCERT_NAME_INFO)new BYTE[cbInfo]))
  244. {
  245. return(NULL);
  246. }
  247. if (!(CryptDecodeObject(X509_ASN_ENCODING,
  248. X509_NAME,
  249. pNameBlob->pbData,
  250. pNameBlob->cbData,
  251. 0,
  252. pNameInfo,
  253. &cbInfo)))
  254. {
  255. delete pNameInfo;
  256. return(NULL);
  257. }
  258. pRDNAttr = CertFindRDNAttr(pszObjId, pNameInfo);
  259. if (pRDNAttr)
  260. {
  261. PCERT_RDN_VALUE_BLOB pValue = &pRDNAttr->Value;
  262. DWORD dwValueType = pRDNAttr->dwValueType;
  263. DWORD cwsz;
  264. pValue = &pRDNAttr->Value;
  265. dwValueType = pRDNAttr->dwValueType;
  266. cwsz = CertRDNValueToStrW(dwValueType,
  267. pValue,
  268. NULL,
  269. 0);
  270. if (cwsz > 1)
  271. {
  272. if (!(pwsz = new WCHAR[cwsz]))
  273. {
  274. delete pNameInfo;
  275. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  276. return(NULL);
  277. }
  278. CertRDNValueToStrW(dwValueType, pValue, pwsz, cwsz);
  279. }
  280. }
  281. DELETE_OBJECT(pNameInfo);
  282. return(pwsz);
  283. }
  284. //////////////////////////////////////////////////////////////////////////
  285. ////
  286. //// private
  287. ////
  288. BOOL CCert_::BuildChainPrivate(DWORD chStores, HCERTSTORE *pahStores, FILETIME *psftVerifyAsOf)
  289. {
  290. DWORD dwError;
  291. PCCERT_CONTEXT pIssuerCertContext;
  292. DELETE_OBJECT(m_pCCert_Issuer);
  293. if (TrustIsCertificateSelfSigned(m_pCertContext,
  294. m_pCertContext->dwCertEncodingType,
  295. 0))
  296. {
  297. return(TRUE);
  298. }
  299. pIssuerCertContext = TrustFindIssuerCertificate(m_pCertContext,
  300. m_pCertContext->dwCertEncodingType,
  301. chStores,
  302. pahStores,
  303. psftVerifyAsOf,
  304. &m_dwConfidence,
  305. &dwError,
  306. 0);
  307. if (!(pIssuerCertContext))
  308. {
  309. SetLastError(dwError);
  310. return(FALSE);
  311. }
  312. m_pCCert_Issuer = new CCert_(pIssuerCertContext);
  313. CertFreeCertificateContext(pIssuerCertContext);
  314. if (!(m_pCCert_Issuer))
  315. {
  316. return(FALSE);
  317. }
  318. return(m_pCCert_Issuer->BuildChainPrivate(chStores, pahStores, psftVerifyAsOf));
  319. }
  320. //
  321. // warning: if you add a store, make sure to add one to the CCERT_MAXSTORES in ccert.hxx!!!
  322. //
  323. void CCert_::OpenStores(void)
  324. {
  325. HCERTSTORE hStore;
  326. m_chStores = 0;
  327. if (hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_A,
  328. 0,
  329. NULL,
  330. CERT_SYSTEM_STORE_CURRENT_USER |
  331. CERT_STORE_READONLY_FLAG |
  332. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  333. "ROOT"))
  334. {
  335. m_pahStores[m_chStores] = hStore;
  336. m_chStores++;
  337. }
  338. else
  339. {
  340. return; // if we can't find the root, FAIL!
  341. }
  342. //
  343. // open the Trust List store
  344. //
  345. if (hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_A,
  346. 0,
  347. NULL,
  348. CERT_SYSTEM_STORE_CURRENT_USER |
  349. CERT_STORE_READONLY_FLAG |
  350. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  351. "TRUST"))
  352. {
  353. m_pahStores[m_chStores] = hStore;
  354. m_chStores++;
  355. }
  356. //
  357. // CA Store
  358. //
  359. if (hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_A,
  360. 0,
  361. NULL,
  362. CERT_SYSTEM_STORE_CURRENT_USER |
  363. CERT_STORE_READONLY_FLAG |
  364. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  365. "CA"))
  366. {
  367. m_pahStores[m_chStores] = hStore;
  368. m_chStores++;
  369. }
  370. //
  371. // MY Store
  372. //
  373. if (hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_A,
  374. 0,
  375. NULL,
  376. CERT_SYSTEM_STORE_CURRENT_USER |
  377. CERT_STORE_READONLY_FLAG |
  378. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  379. "MY"))
  380. {
  381. m_pahStores[m_chStores] = hStore;
  382. m_chStores++;
  383. }
  384. //
  385. // SPC Store (historic reasons!)
  386. //
  387. if (hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_A,
  388. 0,
  389. NULL,
  390. CERT_SYSTEM_STORE_LOCAL_MACHINE |
  391. CERT_STORE_READONLY_FLAG |
  392. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  393. "SPC"))
  394. {
  395. m_pahStores[m_chStores] = hStore;
  396. m_chStores++;
  397. }
  398. }
  399. BOOL CCert_::FindPrivateKey(void)
  400. {
  401. if ((m_pwszProvider) || (m_pwszKeyContainer))
  402. {
  403. return(TRUE);
  404. }
  405. if (m_fTriedPrivateKey)
  406. {
  407. return(FALSE);
  408. }
  409. m_fTriedPrivateKey = TRUE;
  410. DELETE_OBJECT(m_pwszProvider);
  411. DELETE_OBJECT(m_pwszKeyContainer);
  412. //
  413. // try mssign32.dll first
  414. //
  415. HCRYPTPROV signer_hProv;
  416. WCHAR *signer_pwszTmpContainer;
  417. WCHAR *signer_pwszProviderName;
  418. DWORD signer_dwKeySpec;
  419. DWORD signer_dwProviderType;
  420. BOOL signer_fDidCryptAcquire;
  421. signer_hProv = NULL;
  422. signer_pwszTmpContainer = NULL;
  423. signer_pwszProviderName = NULL;
  424. if (GetCryptProvFromCert(NULL,
  425. m_pCertContext,
  426. &signer_hProv,
  427. &signer_dwKeySpec,
  428. &signer_fDidCryptAcquire,
  429. &signer_pwszTmpContainer,
  430. &signer_pwszProviderName,
  431. &signer_dwProviderType))
  432. {
  433. if (signer_pwszProviderName)
  434. {
  435. if (!(m_pwszProvider = new WCHAR[wcslen(signer_pwszProviderName) + 1]))
  436. {
  437. return(FALSE);
  438. }
  439. wcscpy(m_pwszProvider, signer_pwszProviderName);
  440. if (signer_pwszTmpContainer)
  441. {
  442. if (!(m_pwszKeyContainer = new WCHAR[wcslen(signer_pwszTmpContainer) + 1]))
  443. {
  444. return(FALSE);
  445. }
  446. wcscpy(m_pwszKeyContainer, signer_pwszTmpContainer);
  447. }
  448. m_dwProviderType = signer_dwProviderType;
  449. FreeCryptProvFromCert(signer_fDidCryptAcquire,
  450. signer_hProv,
  451. signer_pwszProviderName,
  452. signer_dwProviderType,
  453. signer_pwszTmpContainer);
  454. return(TRUE);
  455. }
  456. FreeCryptProvFromCert(signer_fDidCryptAcquire,
  457. signer_hProv,
  458. signer_pwszProviderName,
  459. signer_dwProviderType,
  460. signer_pwszTmpContainer);
  461. }
  462. DWORD dwIndexProv;
  463. DWORD dwIndexContainer;
  464. DWORD dwProvType;
  465. DWORD cbSize;
  466. WCHAR wszProv[MAX_PATH + 1];
  467. WCHAR *pwszContainer;
  468. HCRYPTPROV hProvEnum;
  469. pwszContainer = NULL;
  470. dwIndexProv = 0;
  471. for EVER
  472. {
  473. cbSize = MAX_PATH;
  474. if (!(CryptEnumProvidersU(dwIndexProv, NULL, 0, &dwProvType, &wszProv[0], &cbSize)))
  475. {
  476. break;
  477. }
  478. wszProv[cbSize] = NULL;
  479. dwIndexContainer = 0;
  480. hProvEnum = NULL;
  481. for EVER
  482. {
  483. if (!(this->EnumContainer(&hProvEnum, dwIndexContainer, dwProvType, &wszProv[0], &pwszContainer)))
  484. {
  485. break;
  486. }
  487. if (this->CheckContainerForKey(&wszProv[0], dwProvType, pwszContainer))
  488. {
  489. m_dwProviderType = dwProvType;
  490. m_pwszKeyContainer = pwszContainer;
  491. if (m_pwszProvider = new WCHAR[wcslen(&wszProv[0]) + 1])
  492. {
  493. wcscpy(m_pwszProvider, &wszProv[0]);
  494. }
  495. CryptReleaseContext(hProvEnum, 0);
  496. return(TRUE);
  497. }
  498. DELETE_OBJECT(pwszContainer);
  499. dwIndexContainer++;
  500. }
  501. if (hProvEnum)
  502. {
  503. CryptReleaseContext(hProvEnum, 0);
  504. }
  505. dwIndexProv++; // for our enum at the top!
  506. }
  507. return(FALSE);
  508. }
  509. BOOL CCert_::EnumContainer(HCRYPTPROV *phProv, DWORD dwIndex, DWORD dwProvType, WCHAR *pwszProv, WCHAR **ppwszContainer)
  510. {
  511. DWORD i;
  512. DWORD cbSize;
  513. char *psz;
  514. *ppwszContainer = NULL;
  515. if (!(*phProv))
  516. {
  517. if (!(CryptAcquireContextU(phProv, NULL, pwszProv, dwProvType, CRYPT_VERIFYCONTEXT)))
  518. {
  519. return(FALSE);
  520. }
  521. }
  522. cbSize = 0;
  523. CryptGetProvParam(*phProv, PP_ENUMCONTAINERS, NULL, &cbSize, CRYPT_FIRST);
  524. if (cbSize > 0)
  525. {
  526. if (!(psz = new char[cbSize]))
  527. {
  528. return(FALSE);
  529. }
  530. memset(psz, 0x00, cbSize);
  531. CryptGetProvParam(*phProv, PP_ENUMCONTAINERS, (BYTE *)psz, &cbSize, CRYPT_FIRST);
  532. for (i = 1; i <= dwIndex; i++)
  533. {
  534. if (!(CryptGetProvParam(*phProv, PP_ENUMCONTAINERS, (BYTE *)psz, &cbSize, 0)))
  535. {
  536. delete psz;
  537. return(FALSE);
  538. }
  539. }
  540. if (!(*ppwszContainer = new WCHAR[strlen(psz) + 1]))
  541. {
  542. delete psz;
  543. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  544. return(FALSE);
  545. }
  546. MultiByteToWideChar(0, 0, psz, -1, *ppwszContainer, (strlen(psz) + 1) * sizeof(WCHAR));
  547. delete psz;
  548. return(TRUE);
  549. }
  550. return(FALSE);
  551. }
  552. BOOL CCert_::CheckContainerForKey(WCHAR *pwszProv, DWORD dwProvType, WCHAR *pwszContainer)
  553. {
  554. HCRYPTPROV hProv;
  555. DWORD cbSize;
  556. PCERT_PUBLIC_KEY_INFO pContInfo;
  557. if (CryptAcquireContextU(&hProv, pwszContainer, pwszProv, dwProvType, 0))
  558. {
  559. if (!(CryptExportPublicKeyInfo(hProv, AT_SIGNATURE, X509_ASN_ENCODING, NULL, &cbSize)))
  560. {
  561. CryptReleaseContext(hProv, 0);
  562. return(FALSE);
  563. }
  564. if (!(pContInfo = (PCERT_PUBLIC_KEY_INFO)new BYTE[cbSize]))
  565. {
  566. CryptReleaseContext(hProv, 0);
  567. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  568. return(FALSE);
  569. }
  570. if (!(CryptExportPublicKeyInfo(hProv, AT_SIGNATURE, X509_ASN_ENCODING, pContInfo, &cbSize)))
  571. {
  572. delete pContInfo;
  573. CryptReleaseContext(hProv, 0);
  574. return(FALSE);
  575. }
  576. CryptReleaseContext(hProv, 0);
  577. if (CertComparePublicKeyInfo(X509_ASN_ENCODING,
  578. &m_pCertContext->pCertInfo->SubjectPublicKeyInfo,
  579. pContInfo))
  580. {
  581. delete pContInfo;
  582. return(TRUE);
  583. }
  584. delete pContInfo;
  585. }
  586. return(FALSE);
  587. }