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.

2175 lines
55 KiB

  1. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
  3. File: PrivateKey.cpp
  4. Content: Implementation of CPrivateKey.
  5. History: 06-15-2001 dsie created
  6. ------------------------------------------------------------------------------*/
  7. #include "StdAfx.h"
  8. #include "CAPICOM.h"
  9. #include "PrivateKey.h"
  10. #include "Common.h"
  11. #include "CertHlpr.h"
  12. #include "Settings.h"
  13. ////////////////////////////////////////////////////////////////////////////////
  14. //
  15. // Exported functions.
  16. //
  17. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  18. Function : CreatePrivateKeyObject
  19. Synopsis : Create and initialize an CPrivateKey object.
  20. Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT to be used
  21. to initialize the IPrivateKey object.
  22. BOOL bReadOnly - TRUE if read-only, else FALSE.
  23. IPrivateKey ** ppIPrivateKey - Pointer to receive IPrivateKey.
  24. Remark :
  25. ------------------------------------------------------------------------------*/
  26. HRESULT CreatePrivateKeyObject (PCCERT_CONTEXT pCertContext,
  27. BOOL bReadOnly,
  28. IPrivateKey ** ppIPrivateKey)
  29. {
  30. HRESULT hr = S_OK;
  31. CComObject<CPrivateKey> * pCPrivateKey = NULL;
  32. DebugTrace("Entering CreatePrivateKeyObject().\n");
  33. //
  34. // Sanity check.
  35. //
  36. ATLASSERT(pCertContext);
  37. ATLASSERT(ppIPrivateKey);
  38. try
  39. {
  40. //
  41. // Create the object. Note that the ref count will still be 0
  42. // after the object is created.
  43. //
  44. if (FAILED(hr = CComObject<CPrivateKey>::CreateInstance(&pCPrivateKey)))
  45. {
  46. DebugTrace("Error [%#x]: CComObject<CPrivateKey>::CreateInstance() failed.\n", hr);
  47. goto ErrorExit;
  48. }
  49. //
  50. // Initialize object.
  51. //
  52. if (FAILED(hr = pCPrivateKey->Init(pCertContext, bReadOnly)))
  53. {
  54. DebugTrace("Error [%#x]: pCPrivateKey->Init() failed.\n", hr);
  55. goto ErrorExit;
  56. }
  57. //
  58. // Return interface pointer to caller.
  59. //
  60. if (FAILED(hr = pCPrivateKey->QueryInterface(ppIPrivateKey)))
  61. {
  62. DebugTrace("Error [%#x]: pCPrivateKey->QueryInterface() failed.\n", hr);
  63. goto ErrorExit;
  64. }
  65. }
  66. catch(...)
  67. {
  68. hr = E_POINTER;
  69. DebugTrace("Exception: invalid parameter.\n");
  70. goto ErrorExit;
  71. }
  72. CommonExit:
  73. DebugTrace("Leaving CreatePrivateKeyObject().\n");
  74. return hr;
  75. ErrorExit:
  76. //
  77. // Sanity check.
  78. //
  79. ATLASSERT(FAILED(hr));
  80. if (pCPrivateKey)
  81. {
  82. delete pCPrivateKey;
  83. }
  84. goto CommonExit;
  85. }
  86. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  87. Function : GetKeyProvInfo
  88. Synopsis : Return pointer to key prov info of a private key object.
  89. Parameter: IPrivateKey * pIPrivateKey - Pointer to private key object.
  90. PCRYPT_KEY_PROV_INFO * ppKeyProvInfo - Pointer to
  91. PCRYPT_KEY_PROV_INFO.
  92. Remark : Caller must NOT free the structure.
  93. ------------------------------------------------------------------------------*/
  94. HRESULT GetKeyProvInfo (IPrivateKey * pIPrivateKey,
  95. PCRYPT_KEY_PROV_INFO * ppKeyProvInfo)
  96. {
  97. HRESULT hr = S_OK;
  98. PCRYPT_KEY_PROV_INFO pKeyProvInfo = NULL;
  99. CComPtr<ICPrivateKey> pICPrivateKey = NULL;
  100. DebugTrace("Entering GetKeyProvInfo().\n");
  101. //
  102. // Sanity check.
  103. //
  104. ATLASSERT(pIPrivateKey);
  105. ATLASSERT(ppKeyProvInfo);
  106. //
  107. // Get ICPrivateKey interface pointer.
  108. //
  109. if (FAILED(hr = pIPrivateKey->QueryInterface(IID_ICPrivateKey, (void **) &pICPrivateKey)))
  110. {
  111. DebugTrace("Error [%#x]: pIPrivateKey->QueryInterface() failed.\n", hr);
  112. goto ErrorExit;
  113. }
  114. //
  115. // Get the PCRYPT_KEY_PROV_INFO.
  116. //
  117. if (FAILED(hr = pICPrivateKey->_GetKeyProvInfo(&pKeyProvInfo)))
  118. {
  119. DebugTrace("Error [%#x]: pICPrivateKey->_GetKeyProvInfo() failed.\n", hr);
  120. goto ErrorExit;
  121. }
  122. *ppKeyProvInfo = pKeyProvInfo;
  123. CommonExit:
  124. DebugTrace("Leaving GetKeyProvInfo().\n");
  125. return hr;
  126. ErrorExit:
  127. //
  128. // Sanity check.
  129. //
  130. ATLASSERT(FAILED(hr));
  131. goto CommonExit;
  132. }
  133. ////////////////////////////////////////////////////////////////////////////////
  134. //
  135. // CPrivateKey
  136. //
  137. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  138. Function : CPrivateKey::get_ContainerName
  139. Synopsis : Return the key container name.
  140. Parameter: BSTR * pVal - Pointer to BSTR to receive the value.
  141. Remark :
  142. ------------------------------------------------------------------------------*/
  143. STDMETHODIMP CPrivateKey::get_ContainerName (BSTR * pVal)
  144. {
  145. HRESULT hr = S_OK;
  146. DebugTrace("Entering CPrivateKey::get_ContainerName().\n");
  147. try
  148. {
  149. //
  150. // Lock access to this object.
  151. //
  152. m_Lock.Lock();
  153. //
  154. // Check parameters.
  155. //
  156. if (NULL == pVal)
  157. {
  158. hr = E_INVALIDARG;
  159. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  160. goto ErrorExit;
  161. }
  162. //
  163. // Make sure we do have private key.
  164. //
  165. if (!m_pKeyProvInfo)
  166. {
  167. hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
  168. DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
  169. goto ErrorExit;
  170. }
  171. //
  172. // Return data to caller.
  173. //
  174. if (!(*pVal = ::SysAllocString(m_pKeyProvInfo->pwszContainerName)))
  175. {
  176. hr = E_OUTOFMEMORY;
  177. DebugTrace("Error [%#x]: SysAllocString() failed.\n", hr);
  178. goto ErrorExit;
  179. }
  180. }
  181. catch(...)
  182. {
  183. hr = E_POINTER;
  184. DebugTrace("Exception: invalid parameter.\n");
  185. goto ErrorExit;
  186. }
  187. UnlockExit:
  188. //
  189. // Unlock access to this object.
  190. //
  191. m_Lock.Unlock();
  192. DebugTrace("Leaving CPrivateKey::get_ContainerName().\n");
  193. return hr;
  194. ErrorExit:
  195. //
  196. // Sanity check.
  197. //
  198. ATLASSERT(FAILED(hr));
  199. ReportError(hr);
  200. goto UnlockExit;
  201. }
  202. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  203. Function : CPrivateKey::get_UniqueContainerName
  204. Synopsis : Return the unique key container name.
  205. Parameter: BSTR * pVal - Pointer to BSTR to receive the value.
  206. Remark :
  207. ------------------------------------------------------------------------------*/
  208. STDMETHODIMP CPrivateKey::get_UniqueContainerName (BSTR * pVal)
  209. {
  210. HRESULT hr = S_OK;
  211. DWORD dwFlags = 0;
  212. DWORD cbData = 0;
  213. LPBYTE pbData = NULL;
  214. HCRYPTPROV hCryptProv = NULL;
  215. CComBSTR bstrName;
  216. DebugTrace("Entering CPrivateKey::get_UniqueContainerName().\n");
  217. try
  218. {
  219. //
  220. // Lock access to this object.
  221. //
  222. m_Lock.Lock();
  223. //
  224. // Check parameters.
  225. //
  226. if (NULL == pVal)
  227. {
  228. hr = E_INVALIDARG;
  229. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  230. goto ErrorExit;
  231. }
  232. //
  233. // Make sure we do have private key.
  234. //
  235. if (!m_pKeyProvInfo)
  236. {
  237. hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
  238. DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
  239. goto ErrorExit;
  240. }
  241. //
  242. // Set dwFlags for machine keyset.
  243. //
  244. dwFlags = m_pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET;
  245. //
  246. // Get the provider context.
  247. //
  248. if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
  249. m_pKeyProvInfo->pwszContainerName,
  250. m_pKeyProvInfo->dwProvType,
  251. dwFlags,
  252. FALSE,
  253. &hCryptProv)))
  254. {
  255. DebugTrace("Error [%#x]: AcquireContext() failed.\n", hr);
  256. goto ErrorExit;
  257. }
  258. //
  259. // Get the unique container name.
  260. //
  261. if (!::CryptGetProvParam(hCryptProv,
  262. PP_UNIQUE_CONTAINER,
  263. NULL,
  264. &cbData,
  265. 0))
  266. {
  267. hr = HRESULT_FROM_WIN32(::GetLastError());
  268. DebugTrace("Error [%#x]: CryptGetProvParam() failed.\n", hr);
  269. goto ErrorExit;
  270. }
  271. if (NULL == (pbData = (LPBYTE) ::CoTaskMemAlloc(cbData)))
  272. {
  273. hr = E_OUTOFMEMORY;
  274. DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
  275. goto ErrorExit;
  276. }
  277. if (!::CryptGetProvParam(hCryptProv,
  278. PP_UNIQUE_CONTAINER,
  279. pbData,
  280. &cbData,
  281. 0))
  282. {
  283. hr = HRESULT_FROM_WIN32(::GetLastError());
  284. DebugTrace("Error [%#x]: CryptGetProvParam() failed.\n", hr);
  285. goto ErrorExit;
  286. }
  287. //
  288. // Return data to caller.
  289. //
  290. if (!(bstrName = (LPSTR) pbData))
  291. {
  292. hr = E_OUTOFMEMORY;
  293. DebugTrace("Error [%#x]: bstrName = pbData failed.\n", hr);
  294. goto ErrorExit;
  295. }
  296. *pVal = bstrName.Detach();
  297. }
  298. catch(...)
  299. {
  300. hr = E_POINTER;
  301. DebugTrace("Exception: invalid parameter.\n");
  302. goto ErrorExit;
  303. }
  304. UnlockExit:
  305. //
  306. // Unlock access to this object.
  307. //
  308. m_Lock.Unlock();
  309. //
  310. // Free resources.
  311. //
  312. if (hCryptProv)
  313. {
  314. ::CryptReleaseContext(hCryptProv, 0);
  315. }
  316. DebugTrace("Leaving CPrivateKey::get_UniqueContainerName().\n");
  317. return hr;
  318. ErrorExit:
  319. //
  320. // Sanity check.
  321. //
  322. ATLASSERT(FAILED(hr));
  323. ReportError(hr);
  324. goto UnlockExit;
  325. }
  326. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  327. Function : CPrivateKey::get_ProviderName
  328. Synopsis : Return the provider name.
  329. Parameter: BSTR * pVal - Pointer to BSTR to receive the value.
  330. Remark :
  331. ------------------------------------------------------------------------------*/
  332. STDMETHODIMP CPrivateKey::get_ProviderName (BSTR * pVal)
  333. {
  334. HRESULT hr = S_OK;
  335. DebugTrace("Entering CPrivateKey::get_ProviderName().\n");
  336. try
  337. {
  338. //
  339. // Lock access to this object.
  340. //
  341. m_Lock.Lock();
  342. //
  343. // Check parameters.
  344. //
  345. if (NULL == pVal)
  346. {
  347. hr = E_INVALIDARG;
  348. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  349. goto ErrorExit;
  350. }
  351. //
  352. // Make sure we do have private key.
  353. //
  354. if (!m_pKeyProvInfo)
  355. {
  356. hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
  357. DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
  358. goto ErrorExit;
  359. }
  360. //
  361. // Return data to caller.
  362. //
  363. if (!(*pVal = ::SysAllocString(m_pKeyProvInfo->pwszProvName)))
  364. {
  365. hr = E_OUTOFMEMORY;
  366. DebugTrace("Error [%#x]: SysAllocString() failed.\n", hr);
  367. goto ErrorExit;
  368. }
  369. }
  370. catch(...)
  371. {
  372. hr = E_POINTER;
  373. DebugTrace("Exception: invalid parameter.\n");
  374. goto ErrorExit;
  375. }
  376. UnlockExit:
  377. //
  378. // Unlock access to this object.
  379. //
  380. m_Lock.Unlock();
  381. DebugTrace("Leaving CPrivateKey::get_ProviderName().\n");
  382. return hr;
  383. ErrorExit:
  384. //
  385. // Sanity check.
  386. //
  387. ATLASSERT(FAILED(hr));
  388. ReportError(hr);
  389. goto UnlockExit;
  390. }
  391. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  392. Function : CPrivateKey::get_ProviderType
  393. Synopsis : Return the provider type.
  394. Parameter: CAPICOM_PROV_TYPE * pVal - Pointer to CAPICOM_PROV_TYPE to receive
  395. the value.
  396. Remark :
  397. ------------------------------------------------------------------------------*/
  398. STDMETHODIMP CPrivateKey::get_ProviderType (CAPICOM_PROV_TYPE * pVal)
  399. {
  400. HRESULT hr = S_OK;
  401. DebugTrace("Entering CPrivateKey::get_ProviderType().\n");
  402. try
  403. {
  404. //
  405. // Lock access to this object.
  406. //
  407. m_Lock.Lock();
  408. //
  409. // Check parameters.
  410. //
  411. if (NULL == pVal)
  412. {
  413. hr = E_INVALIDARG;
  414. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  415. goto ErrorExit;
  416. }
  417. //
  418. // Make sure we do have private key.
  419. //
  420. if (!m_pKeyProvInfo)
  421. {
  422. hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
  423. DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
  424. goto ErrorExit;
  425. }
  426. //
  427. // Return data to caller.
  428. //
  429. *pVal = (CAPICOM_PROV_TYPE) m_pKeyProvInfo->dwProvType;
  430. }
  431. catch(...)
  432. {
  433. hr = E_POINTER;
  434. DebugTrace("Exception: invalid parameter.\n");
  435. goto ErrorExit;
  436. }
  437. UnlockExit:
  438. //
  439. // Unlock access to this object.
  440. //
  441. m_Lock.Unlock();
  442. DebugTrace("Leaving CPrivateKey::get_ProviderType().\n");
  443. return hr;
  444. ErrorExit:
  445. //
  446. // Sanity check.
  447. //
  448. ATLASSERT(FAILED(hr));
  449. ReportError(hr);
  450. goto UnlockExit;
  451. }
  452. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  453. Function : CPrivateKey::get_KeySpec
  454. Synopsis : Return the Key spec.
  455. Parameter: CAPICOM_KEY_SPEC * pVal - Pointer to CAPICOM_KEY_SPEC to receive
  456. the value.
  457. Remark :
  458. ------------------------------------------------------------------------------*/
  459. STDMETHODIMP CPrivateKey::get_KeySpec (CAPICOM_KEY_SPEC * pVal)
  460. {
  461. HRESULT hr = S_OK;
  462. DebugTrace("Entering CPrivateKey::get_KeySpec().\n");
  463. try
  464. {
  465. //
  466. // Lock access to this object.
  467. //
  468. m_Lock.Lock();
  469. //
  470. // Check parameters.
  471. //
  472. if (NULL == pVal)
  473. {
  474. hr = E_INVALIDARG;
  475. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  476. goto ErrorExit;
  477. }
  478. //
  479. // Make sure we do have private key.
  480. //
  481. if (!m_pKeyProvInfo)
  482. {
  483. hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
  484. DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
  485. goto ErrorExit;
  486. }
  487. //
  488. // Return data to caller.
  489. //
  490. *pVal = (CAPICOM_KEY_SPEC) m_pKeyProvInfo->dwKeySpec;
  491. }
  492. catch(...)
  493. {
  494. hr = E_POINTER;
  495. DebugTrace("Exception: invalid parameter.\n");
  496. goto ErrorExit;
  497. }
  498. UnlockExit:
  499. //
  500. // Unlock access to this object.
  501. //
  502. m_Lock.Unlock();
  503. DebugTrace("Leaving CPrivateKey::get_KeySpec().\n");
  504. return hr;
  505. ErrorExit:
  506. //
  507. // Sanity check.
  508. //
  509. ATLASSERT(FAILED(hr));
  510. ReportError(hr);
  511. goto UnlockExit;
  512. }
  513. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  514. Function : CPrivateKey::IsAccessible
  515. Synopsis : Check to see if the private key is accessible.
  516. Parameter: VARIANT_BOOL * pVal - Pointer to VARIANT_BOOL to receive the result.
  517. Remark : This may cause UI to be displayed.
  518. ------------------------------------------------------------------------------*/
  519. STDMETHODIMP CPrivateKey::IsAccessible (VARIANT_BOOL * pVal)
  520. {
  521. HRESULT hr = S_OK;
  522. DWORD dwFlags = 0;
  523. DWORD dwVerifyContextFlag = 0;
  524. DWORD cbData = 0;
  525. DWORD dwImpType = 0;
  526. HCRYPTPROV hCryptProv = NULL;
  527. DebugTrace("Entering CPrivateKey::IsAccessible().\n");
  528. try
  529. {
  530. //
  531. // Lock access to this object.
  532. //
  533. m_Lock.Lock();
  534. //
  535. // Check parameters.
  536. //
  537. if (NULL == pVal)
  538. {
  539. hr = E_INVALIDARG;
  540. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  541. goto ErrorExit;
  542. }
  543. //
  544. // Initialize.
  545. //
  546. *pVal = VARIANT_FALSE;
  547. //
  548. // Make sure we do have private key.
  549. //
  550. if (!m_pKeyProvInfo)
  551. {
  552. hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
  553. DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
  554. goto ErrorExit;
  555. }
  556. //
  557. // Set dwFlags for machine keyset.
  558. //
  559. dwFlags = m_pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET;
  560. //
  561. // If Win2K and above, use CRYPT_VERIFYCONTEXT flag.
  562. //
  563. if (IsWin2KAndAbove())
  564. {
  565. dwVerifyContextFlag = CRYPT_VERIFYCONTEXT;
  566. }
  567. //
  568. // Get the provider context with no key access.
  569. //
  570. if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
  571. NULL,
  572. m_pKeyProvInfo->dwProvType,
  573. dwVerifyContextFlag | dwFlags,
  574. FALSE,
  575. &hCryptProv)))
  576. {
  577. DebugTrace("Error [%#x]: AcquireContext(CRYPT_VERIFYCONTEXT) failed.\n", hr);
  578. goto ErrorExit;
  579. }
  580. //
  581. // Get provider param.
  582. //
  583. cbData = sizeof(dwImpType);
  584. if (!::CryptGetProvParam(hCryptProv, PP_IMPTYPE, (PBYTE) &dwImpType, &cbData, 0))
  585. {
  586. hr = HRESULT_FROM_WIN32(::GetLastError());
  587. DebugTrace("Error [%#x]: CryptGetProvParam(PP_IMPTYPE) failed.\n", hr);
  588. goto ErrorExit;
  589. }
  590. //
  591. // Release verify context.
  592. //
  593. ::ReleaseContext(hCryptProv), hCryptProv = NULL;
  594. //
  595. // Check implementation type.
  596. //
  597. if (dwImpType & CRYPT_IMPL_HARDWARE)
  598. {
  599. //
  600. // We do not support this for hardware key in down level platforms,
  601. // because CRYPT_SILENT flag is not available.
  602. //
  603. if (!IsWin2KAndAbove())
  604. {
  605. hr = CAPICOM_E_NOT_SUPPORTED;
  606. DebugTrace("Error [%#x]: IsAccessible() for hardware key is not supported.\n", hr);
  607. goto ErrorExit;
  608. }
  609. //
  610. // Reacquire context with silent flag.
  611. //
  612. if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
  613. m_pKeyProvInfo->pwszContainerName,
  614. m_pKeyProvInfo->dwProvType,
  615. CRYPT_SILENT | dwFlags,
  616. FALSE,
  617. &hCryptProv)))
  618. {
  619. DebugTrace("Info [%#x]: AcquireContext(CRYPT_SILENT) failed, probably smart card not inserted.\n", hr);
  620. hr = S_OK;
  621. goto UnlockExit;
  622. }
  623. }
  624. else
  625. {
  626. //
  627. // Reacquire context with private key access.
  628. //
  629. if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
  630. m_pKeyProvInfo->pwszContainerName,
  631. m_pKeyProvInfo->dwProvType,
  632. dwFlags,
  633. FALSE,
  634. &hCryptProv)))
  635. {
  636. DebugTrace("Info [%#x]: AcquireContext() failed, probably access denied.\n", hr);
  637. hr = S_OK;
  638. goto UnlockExit;
  639. }
  640. }
  641. //
  642. // Return result to caller.
  643. //
  644. *pVal = VARIANT_TRUE;
  645. }
  646. catch(...)
  647. {
  648. hr = E_POINTER;
  649. DebugTrace("Exception: invalid parameter.\n");
  650. goto ErrorExit;
  651. }
  652. UnlockExit:
  653. //
  654. // Unlock access to this object.
  655. //
  656. m_Lock.Unlock();
  657. //
  658. // Free resources.
  659. //
  660. if (hCryptProv)
  661. {
  662. ::ReleaseContext(hCryptProv);
  663. }
  664. DebugTrace("Leaving CPrivateKey::IsAccessible().\n");
  665. return hr;
  666. ErrorExit:
  667. //
  668. // Sanity check.
  669. //
  670. ATLASSERT(FAILED(hr));
  671. ReportError(hr);
  672. goto UnlockExit;
  673. }
  674. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  675. Function : CPrivateKey::IsProtected
  676. Synopsis : Check to see if the private key is user protected.
  677. Parameter: VARIANT_BOOL * pVal - Pointer to VARIANT_BOOL to receive the result.
  678. Remark :
  679. ------------------------------------------------------------------------------*/
  680. STDMETHODIMP CPrivateKey::IsProtected (VARIANT_BOOL * pVal)
  681. {
  682. HRESULT hr = S_OK;
  683. DWORD dwFlags = 0;
  684. DWORD dwVerifyContextFlag = 0;
  685. DWORD cbData = 0;
  686. DWORD dwImpType = 0;
  687. HCRYPTPROV hCryptProv = NULL;
  688. DebugTrace("Entering CPrivateKey::IsProtected().\n");
  689. try
  690. {
  691. //
  692. // Lock access to this object.
  693. //
  694. m_Lock.Lock();
  695. //
  696. // Check parameters.
  697. //
  698. if (NULL == pVal)
  699. {
  700. hr = E_INVALIDARG;
  701. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  702. goto ErrorExit;
  703. }
  704. //
  705. // Initialize.
  706. //
  707. *pVal = VARIANT_FALSE;
  708. //
  709. // Make sure we do have private key.
  710. //
  711. if (!m_pKeyProvInfo)
  712. {
  713. hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
  714. DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
  715. goto ErrorExit;
  716. }
  717. //
  718. // Set dwFlags for machine keyset.
  719. //
  720. dwFlags = m_pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET;
  721. //
  722. // If Win2K and above, use CRYPT_VERIFYCONTEXT flag.
  723. //
  724. if (IsWin2KAndAbove())
  725. {
  726. dwVerifyContextFlag = CRYPT_VERIFYCONTEXT;
  727. }
  728. //
  729. // Get the provider context with no key access.
  730. //
  731. if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
  732. NULL,
  733. m_pKeyProvInfo->dwProvType,
  734. dwVerifyContextFlag | dwFlags,
  735. FALSE,
  736. &hCryptProv)))
  737. {
  738. DebugTrace("Error [%#x]: AcquireContext(CRYPT_VERIFYCONTEXT) failed.\n", hr);
  739. goto ErrorExit;
  740. }
  741. //
  742. // Get provider param.
  743. //
  744. cbData = sizeof(dwImpType);
  745. if (!::CryptGetProvParam(hCryptProv, PP_IMPTYPE, (PBYTE) &dwImpType, &cbData, 0))
  746. {
  747. hr = HRESULT_FROM_WIN32(::GetLastError());
  748. DebugTrace("Error [%#x]: CryptGetProvParam(PP_IMPTYPE) failed.\n", hr);
  749. goto ErrorExit;
  750. }
  751. //
  752. // Assume hardware key is protected.
  753. //
  754. if (dwImpType & CRYPT_IMPL_HARDWARE)
  755. {
  756. //
  757. // Return result to caller.
  758. //
  759. *pVal = VARIANT_TRUE;
  760. }
  761. else
  762. {
  763. //
  764. // We do not support this for software key in down level platforms,
  765. // because CRYPT_SILENT flag is not available.
  766. //
  767. if (!IsWin2KAndAbove())
  768. {
  769. hr = CAPICOM_E_NOT_SUPPORTED;
  770. DebugTrace("Error [%#x]: IsProtected() for software key is not supported.\n", hr);
  771. goto ErrorExit;
  772. }
  773. //
  774. // Reacquire context with key access (to make sure key exists).
  775. //
  776. ::ReleaseContext(hCryptProv), hCryptProv = NULL;
  777. if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
  778. m_pKeyProvInfo->pwszContainerName,
  779. m_pKeyProvInfo->dwProvType,
  780. dwFlags,
  781. FALSE,
  782. &hCryptProv)))
  783. {
  784. DebugTrace("Error [%#x]: AcquireContext() failed.\n", hr);
  785. goto ErrorExit;
  786. }
  787. //
  788. // Reacquire context with silent flag.
  789. //
  790. ::ReleaseContext(hCryptProv), hCryptProv = NULL;
  791. if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
  792. m_pKeyProvInfo->pwszContainerName,
  793. m_pKeyProvInfo->dwProvType,
  794. CRYPT_SILENT | dwFlags,
  795. FALSE,
  796. &hCryptProv)))
  797. {
  798. //
  799. // CSP refuses to open the container, so can assume it is user protected.
  800. //
  801. *pVal = VARIANT_TRUE;
  802. DebugTrace("Info [%#x]: AcquireContext(CRYPT_SILENT) failed, assume user protected.\n", hr);
  803. //
  804. // Successful.
  805. //
  806. hr = S_OK;
  807. }
  808. }
  809. }
  810. catch(...)
  811. {
  812. hr = E_POINTER;
  813. DebugTrace("Exception: invalid parameter.\n");
  814. goto ErrorExit;
  815. }
  816. UnlockExit:
  817. //
  818. // Unlock access to this object.
  819. //
  820. m_Lock.Unlock();
  821. //
  822. // Free resources.
  823. //
  824. if (hCryptProv)
  825. {
  826. ::ReleaseContext(hCryptProv);
  827. }
  828. DebugTrace("Leaving CPrivateKey::IsProtected().\n");
  829. return hr;
  830. ErrorExit:
  831. //
  832. // Sanity check.
  833. //
  834. ATLASSERT(FAILED(hr));
  835. ReportError(hr);
  836. goto UnlockExit;
  837. }
  838. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  839. Function : CPrivateKey::IsExportable
  840. Synopsis : Check to see if the private key is exportable.
  841. Parameter: VARIANT_BOOL * pVal - Pointer to VARIANT_BOOL to receive the result.
  842. Remark :
  843. ------------------------------------------------------------------------------*/
  844. STDMETHODIMP CPrivateKey::IsExportable (VARIANT_BOOL * pVal)
  845. {
  846. HRESULT hr = S_OK;
  847. DWORD dwFlags = 0;
  848. DWORD dwVerifyContextFlag = 0;
  849. DWORD cbData = 0;
  850. DWORD dwImpType = 0;
  851. DWORD dwPermissions = 0;
  852. HCRYPTPROV hCryptProv = NULL;
  853. HCRYPTKEY hCryptKey = NULL;
  854. DebugTrace("Entering CPrivateKey::IsExportable().\n");
  855. try
  856. {
  857. //
  858. // Lock access to this object.
  859. //
  860. m_Lock.Lock();
  861. //
  862. // Check parameters.
  863. //
  864. if (NULL == pVal)
  865. {
  866. hr = E_INVALIDARG;
  867. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  868. goto ErrorExit;
  869. }
  870. //
  871. // Initialize.
  872. //
  873. *pVal = VARIANT_FALSE;
  874. //
  875. // Make sure we do have private key.
  876. //
  877. if (!m_pKeyProvInfo)
  878. {
  879. hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
  880. DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
  881. goto ErrorExit;
  882. }
  883. //
  884. // Set dwFlags for machine keyset.
  885. //
  886. dwFlags = m_pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET;
  887. //
  888. // If Win2K and above, use CRYPT_VERIFYCONTEXT flag.
  889. //
  890. if (IsWin2KAndAbove())
  891. {
  892. dwVerifyContextFlag = CRYPT_VERIFYCONTEXT;
  893. }
  894. //
  895. // Get the provider context with no key access.
  896. //
  897. if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
  898. NULL,
  899. m_pKeyProvInfo->dwProvType,
  900. dwVerifyContextFlag | dwFlags,
  901. FALSE,
  902. &hCryptProv)))
  903. {
  904. DebugTrace("Error [%#x]: AcquireContext(CRYPT_VERIFYCONTEXT) failed.\n", hr);
  905. goto ErrorExit;
  906. }
  907. //
  908. // Get provider param.
  909. //
  910. cbData = sizeof(dwImpType);
  911. if (!::CryptGetProvParam(hCryptProv, PP_IMPTYPE, (PBYTE) &dwImpType, &cbData, 0))
  912. {
  913. hr = HRESULT_FROM_WIN32(::GetLastError());
  914. DebugTrace("Error [%#x]: CryptGetProvParam(PP_IMPTYPE) failed.\n", hr);
  915. goto ErrorExit;
  916. }
  917. //
  918. // Assume hardware key is not exportable.
  919. //
  920. if (!(dwImpType & CRYPT_IMPL_HARDWARE))
  921. {
  922. //
  923. // We do not support this for software key in down level platforms,
  924. // because KP_PERMISSIONS flag is not available.
  925. //
  926. if (!IsWin2KAndAbove())
  927. {
  928. hr = CAPICOM_E_NOT_SUPPORTED;
  929. DebugTrace("Error [%#x]: IsExportabled() for software key is not supported.\n", hr);
  930. goto ErrorExit;
  931. }
  932. //
  933. // Reacquire context with private key access.
  934. //
  935. ::ReleaseContext(hCryptProv), hCryptProv = NULL;
  936. if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
  937. m_pKeyProvInfo->pwszContainerName,
  938. m_pKeyProvInfo->dwProvType,
  939. dwFlags,
  940. FALSE,
  941. &hCryptProv)))
  942. {
  943. DebugTrace("Error [%#x]: AcquireContext() failed.\n", hr);
  944. goto ErrorExit;
  945. }
  946. //
  947. // Get key handle.
  948. //
  949. if (!::CryptGetUserKey(hCryptProv, m_pKeyProvInfo->dwKeySpec, &hCryptKey))
  950. {
  951. hr = HRESULT_FROM_WIN32(::GetLastError());
  952. DebugTrace("Error [%#x]: CryptGetUserKey() failed.\n", hr);
  953. goto ErrorExit;
  954. }
  955. //
  956. // Get key param.
  957. //
  958. cbData = sizeof(dwPermissions);
  959. if (!::CryptGetKeyParam(hCryptKey, KP_PERMISSIONS, (PBYTE) &dwPermissions, &cbData, 0))
  960. {
  961. hr = HRESULT_FROM_WIN32(::GetLastError());
  962. DebugTrace("Error [%#x]: CryptGetKeyParam(KP_PERMISSIONS) failed.\n", hr);
  963. goto ErrorExit;
  964. }
  965. //
  966. // Return result to caller.
  967. //
  968. if (dwPermissions & CRYPT_EXPORT)
  969. {
  970. *pVal = VARIANT_TRUE;
  971. }
  972. }
  973. }
  974. catch(...)
  975. {
  976. hr = E_POINTER;
  977. DebugTrace("Exception: invalid parameter.\n");
  978. goto ErrorExit;
  979. }
  980. UnlockExit:
  981. //
  982. // Unlock access to this object.
  983. //
  984. m_Lock.Unlock();
  985. //
  986. // Free resources.
  987. //
  988. if (hCryptKey)
  989. {
  990. ::CryptDestroyKey(hCryptKey);
  991. }
  992. if (hCryptProv)
  993. {
  994. ::ReleaseContext(hCryptProv);
  995. }
  996. DebugTrace("Leaving CPrivateKey::IsExportable().\n");
  997. return hr;
  998. ErrorExit:
  999. //
  1000. // Sanity check.
  1001. //
  1002. ATLASSERT(FAILED(hr));
  1003. ReportError(hr);
  1004. goto UnlockExit;
  1005. }
  1006. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1007. Function : CPrivateKey::IsRemovable
  1008. Synopsis : Check to see if the private key is stored in removable device.
  1009. Parameter: VARIANT_BOOL * pVal - Pointer to VARIANT_BOOL to receive the result.
  1010. Remark :
  1011. ------------------------------------------------------------------------------*/
  1012. STDMETHODIMP CPrivateKey::IsRemovable (VARIANT_BOOL * pVal)
  1013. {
  1014. HRESULT hr = S_OK;
  1015. DWORD dwFlags = 0;
  1016. DWORD dwVerifyContextFlag = 0;
  1017. DWORD cbData = 0;
  1018. DWORD dwImpType = 0;
  1019. HCRYPTPROV hCryptProv = NULL;
  1020. DebugTrace("Entering CPrivateKey::IsRemovable().\n");
  1021. try
  1022. {
  1023. //
  1024. // Lock access to this object.
  1025. //
  1026. m_Lock.Lock();
  1027. //
  1028. // Check parameters.
  1029. //
  1030. if (NULL == pVal)
  1031. {
  1032. hr = E_INVALIDARG;
  1033. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  1034. goto ErrorExit;
  1035. }
  1036. //
  1037. // Initialize.
  1038. //
  1039. *pVal = VARIANT_FALSE;
  1040. //
  1041. // Make sure we do have private key.
  1042. //
  1043. if (!m_pKeyProvInfo)
  1044. {
  1045. hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
  1046. DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
  1047. goto ErrorExit;
  1048. }
  1049. //
  1050. // Set dwFlags for machine keyset.
  1051. //
  1052. dwFlags = m_pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET;
  1053. //
  1054. // If Win2K and above, use CRYPT_VERIFYCONTEXT flag.
  1055. //
  1056. if (IsWin2KAndAbove())
  1057. {
  1058. dwVerifyContextFlag = CRYPT_VERIFYCONTEXT;
  1059. }
  1060. //
  1061. // Get the provider context with no key access.
  1062. //
  1063. if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
  1064. NULL,
  1065. m_pKeyProvInfo->dwProvType,
  1066. dwVerifyContextFlag | dwFlags,
  1067. FALSE,
  1068. &hCryptProv)))
  1069. {
  1070. DebugTrace("Error [%#x]: AcquireContext(CRYPT_VERIFYCONTEXT) failed.\n", hr);
  1071. goto ErrorExit;
  1072. }
  1073. //
  1074. // Get provider param.
  1075. //
  1076. cbData = sizeof(dwImpType);
  1077. if (!::CryptGetProvParam(hCryptProv, PP_IMPTYPE, (PBYTE) &dwImpType, &cbData, 0))
  1078. {
  1079. hr = HRESULT_FROM_WIN32(::GetLastError());
  1080. DebugTrace("Error [%#x]: CryptGetProvParam(PP_IMPTYPE) failed.\n", hr);
  1081. goto ErrorExit;
  1082. }
  1083. //
  1084. // Return result to caller.
  1085. //
  1086. if (dwImpType & CRYPT_IMPL_REMOVABLE)
  1087. {
  1088. *pVal = VARIANT_TRUE;
  1089. }
  1090. }
  1091. catch(...)
  1092. {
  1093. hr = E_POINTER;
  1094. DebugTrace("Exception: invalid parameter.\n");
  1095. goto ErrorExit;
  1096. }
  1097. UnlockExit:
  1098. //
  1099. // Unlock access to this object.
  1100. //
  1101. m_Lock.Unlock();
  1102. //
  1103. // Free resources.
  1104. //
  1105. if (hCryptProv)
  1106. {
  1107. ::ReleaseContext(hCryptProv);
  1108. }
  1109. DebugTrace("Leaving CPrivateKey::IsRemovable().\n");
  1110. return hr;
  1111. ErrorExit:
  1112. //
  1113. // Sanity check.
  1114. //
  1115. ATLASSERT(FAILED(hr));
  1116. ReportError(hr);
  1117. goto UnlockExit;
  1118. }
  1119. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1120. Function : CPrivateKey::IsMachineKeyset
  1121. Synopsis : Check to see if the private key is stored in machine key container.
  1122. Parameter: VARIANT_BOOL * pVal - Pointer to VARIANT_BOOL to receive the result.
  1123. Remark :
  1124. ------------------------------------------------------------------------------*/
  1125. STDMETHODIMP CPrivateKey::IsMachineKeyset (VARIANT_BOOL * pVal)
  1126. {
  1127. HRESULT hr = S_OK;
  1128. DebugTrace("Entering CPrivateKey::IsMachineKeyset().\n");
  1129. try
  1130. {
  1131. //
  1132. // Lock access to this object.
  1133. //
  1134. m_Lock.Lock();
  1135. //
  1136. // Check parameters.
  1137. //
  1138. if (NULL == pVal)
  1139. {
  1140. hr = E_INVALIDARG;
  1141. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  1142. goto ErrorExit;
  1143. }
  1144. //
  1145. // Initialize.
  1146. //
  1147. *pVal = VARIANT_FALSE;
  1148. //
  1149. // Make sure we do have private key.
  1150. //
  1151. if (!m_pKeyProvInfo)
  1152. {
  1153. hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
  1154. DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
  1155. goto ErrorExit;
  1156. }
  1157. //
  1158. // Return result to caller.
  1159. //
  1160. if (m_pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET)
  1161. {
  1162. *pVal = VARIANT_TRUE;
  1163. }
  1164. }
  1165. catch(...)
  1166. {
  1167. hr = E_POINTER;
  1168. DebugTrace("Exception: invalid parameter.\n");
  1169. goto ErrorExit;
  1170. }
  1171. UnlockExit:
  1172. //
  1173. // Unlock access to this object.
  1174. //
  1175. m_Lock.Unlock();
  1176. DebugTrace("Leaving CPrivateKey::IsMachineKeyset().\n");
  1177. return hr;
  1178. ErrorExit:
  1179. //
  1180. // Sanity check.
  1181. //
  1182. ATLASSERT(FAILED(hr));
  1183. ReportError(hr);
  1184. goto UnlockExit;
  1185. }
  1186. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1187. Function : CPrivateKey::IsHardwareDevice
  1188. Synopsis : Check to see if the private key is stored in hardware device.
  1189. Parameter: VARIANT_BOOL * pVal - Pointer to VARIANT_BOOL to receive the result.
  1190. Remark :
  1191. ------------------------------------------------------------------------------*/
  1192. STDMETHODIMP CPrivateKey::IsHardwareDevice (VARIANT_BOOL * pVal)
  1193. {
  1194. HRESULT hr = S_OK;
  1195. DWORD dwFlags = 0;
  1196. DWORD dwVerifyContextFlag = 0;
  1197. DWORD cbData = 0;
  1198. DWORD dwImpType = 0;
  1199. HCRYPTPROV hCryptProv = NULL;
  1200. DebugTrace("Entering CPrivateKey::IsHardwareDevice().\n");
  1201. try
  1202. {
  1203. //
  1204. // Lock access to this object.
  1205. //
  1206. m_Lock.Lock();
  1207. //
  1208. // Check parameters.
  1209. //
  1210. if (NULL == pVal)
  1211. {
  1212. hr = E_INVALIDARG;
  1213. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  1214. goto ErrorExit;
  1215. }
  1216. //
  1217. // Initialize.
  1218. //
  1219. *pVal = VARIANT_FALSE;
  1220. //
  1221. // Make sure we do have private key.
  1222. //
  1223. if (!m_pKeyProvInfo)
  1224. {
  1225. hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
  1226. DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
  1227. goto ErrorExit;
  1228. }
  1229. //
  1230. // Set dwFlags for machine keyset.
  1231. //
  1232. dwFlags = m_pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET;
  1233. //
  1234. // If Win2K and above, use CRYPT_VERIFYCONTEXT flag.
  1235. //
  1236. if (IsWin2KAndAbove())
  1237. {
  1238. dwVerifyContextFlag = CRYPT_VERIFYCONTEXT;
  1239. }
  1240. //
  1241. // Get the provider context with no key access.
  1242. //
  1243. if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
  1244. NULL,
  1245. m_pKeyProvInfo->dwProvType,
  1246. dwVerifyContextFlag | dwFlags,
  1247. FALSE,
  1248. &hCryptProv)))
  1249. {
  1250. DebugTrace("Error [%#x]: AcquireContext(CRYPT_VERIFYCONTEXT) failed.\n", hr);
  1251. goto ErrorExit;
  1252. }
  1253. //
  1254. // Get provider param.
  1255. //
  1256. cbData = sizeof(dwImpType);
  1257. if (!::CryptGetProvParam(hCryptProv, PP_IMPTYPE, (PBYTE) &dwImpType, &cbData, 0))
  1258. {
  1259. hr = HRESULT_FROM_WIN32(::GetLastError());
  1260. DebugTrace("Error [%#x]: CryptGetProvParam(PP_IMPTYPE) failed.\n", hr);
  1261. goto ErrorExit;
  1262. }
  1263. //
  1264. // Return result to caller.
  1265. //
  1266. if (dwImpType & CRYPT_IMPL_HARDWARE)
  1267. {
  1268. *pVal = VARIANT_TRUE;
  1269. }
  1270. }
  1271. catch(...)
  1272. {
  1273. hr = E_POINTER;
  1274. DebugTrace("Exception: invalid parameter.\n");
  1275. goto ErrorExit;
  1276. }
  1277. UnlockExit:
  1278. //
  1279. // Unlock access to this object.
  1280. //
  1281. m_Lock.Unlock();
  1282. //
  1283. // Free resources.
  1284. //
  1285. if (hCryptProv)
  1286. {
  1287. ::ReleaseContext(hCryptProv);
  1288. }
  1289. DebugTrace("Leaving CPrivateKey::IsHardwareDevice().\n");
  1290. return hr;
  1291. ErrorExit:
  1292. //
  1293. // Sanity check.
  1294. //
  1295. ATLASSERT(FAILED(hr));
  1296. ReportError(hr);
  1297. goto UnlockExit;
  1298. }
  1299. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1300. Function : CPrivateKey::Open
  1301. Synopsis : Open an existing key container.
  1302. Parameter: BSTR ContainerName - Container name.
  1303. BSTR ProviderName - Provider name.
  1304. CAPICOM_PROV_TYPE ProviderType - Provider type.
  1305. CAPICOM_KEY_SPEC KeySpec - Key spec.
  1306. CAPICOM_STORE_LOCATION StoreLocation - Machine or user.
  1307. VARIANT_BOOL bCheckExistence - True to check if the specified
  1308. container and key actually exists.
  1309. Remark :
  1310. ------------------------------------------------------------------------------*/
  1311. STDMETHODIMP CPrivateKey::Open (BSTR ContainerName,
  1312. BSTR ProviderName,
  1313. CAPICOM_PROV_TYPE ProviderType,
  1314. CAPICOM_KEY_SPEC KeySpec,
  1315. CAPICOM_STORE_LOCATION StoreLocation,
  1316. VARIANT_BOOL bCheckExistence)
  1317. {
  1318. HRESULT hr = S_OK;
  1319. DWORD dwFlags = 0;
  1320. DWORD dwSerializedLength = 0;
  1321. HCRYPTPROV hCryptProv = NULL;
  1322. HCRYPTKEY hCryptKey = NULL;
  1323. PCRYPT_KEY_PROV_INFO pKeyProvInfo = NULL;;
  1324. DebugTrace("Entering CPrivateKey::Open().\n");
  1325. try
  1326. {
  1327. //
  1328. // Lock access to this object.
  1329. //
  1330. m_Lock.Lock();
  1331. //
  1332. // Not allowed if read-only.
  1333. //
  1334. if (m_bReadOnly)
  1335. {
  1336. hr = CAPICOM_E_NOT_ALLOWED;
  1337. DebugTrace("Error [%#x]: Opening private key from WEB script is not allowed.\n", hr);
  1338. goto ErrorExit;
  1339. }
  1340. //
  1341. // Make sure paremeters are valid.
  1342. //
  1343. switch (StoreLocation)
  1344. {
  1345. case CAPICOM_LOCAL_MACHINE_STORE:
  1346. {
  1347. dwFlags = CRYPT_MACHINE_KEYSET;
  1348. break;
  1349. }
  1350. case CAPICOM_CURRENT_USER_STORE:
  1351. {
  1352. break;
  1353. }
  1354. default:
  1355. {
  1356. hr = E_INVALIDARG;
  1357. DebugTrace("Error: invalid store location (%#x).\n", StoreLocation);
  1358. goto ErrorExit;
  1359. }
  1360. }
  1361. if (KeySpec != CAPICOM_KEY_SPEC_KEYEXCHANGE && KeySpec != CAPICOM_KEY_SPEC_SIGNATURE)
  1362. {
  1363. hr = E_INVALIDARG;
  1364. DebugTrace("Error [%#x]: invalid key spec (%#x).\n", hr, KeySpec);
  1365. goto ErrorExit;
  1366. }
  1367. //
  1368. // Make sure the container and key exists, if requested.
  1369. //
  1370. if (bCheckExistence)
  1371. {
  1372. if (FAILED(hr = ::AcquireContext((LPWSTR) ProviderName,
  1373. (LPWSTR) ContainerName,
  1374. ProviderType,
  1375. dwFlags,
  1376. FALSE,
  1377. &hCryptProv)))
  1378. {
  1379. DebugTrace("Error [%#x]: AcquireContext() failed.\n", hr);
  1380. goto ErrorExit;
  1381. }
  1382. if (!::CryptGetUserKey(hCryptProv, KeySpec, &hCryptKey))
  1383. {
  1384. hr = HRESULT_FROM_WIN32(::GetLastError());
  1385. DebugTrace("Error [%#x]: CryptGetUserKey() failed.\n", hr);
  1386. goto ErrorExit;
  1387. }
  1388. }
  1389. //
  1390. // Allocate memory to serialize the structure.
  1391. //
  1392. dwSerializedLength = sizeof(CRYPT_KEY_PROV_INFO) +
  1393. ((::SysStringLen(ContainerName) + 1) * sizeof(WCHAR)) +
  1394. ((::SysStringLen(ProviderName) + 1) * sizeof(WCHAR));
  1395. if (!(pKeyProvInfo = (PCRYPT_KEY_PROV_INFO) ::CoTaskMemAlloc(dwSerializedLength)))
  1396. {
  1397. hr = E_OUTOFMEMORY;
  1398. DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
  1399. goto ErrorExit;
  1400. }
  1401. //
  1402. // Now serialize it.
  1403. //
  1404. ::ZeroMemory((LPVOID) pKeyProvInfo, dwSerializedLength);
  1405. pKeyProvInfo->pwszContainerName = (LPWSTR) ((LPBYTE) pKeyProvInfo + sizeof(CRYPT_KEY_PROV_INFO));
  1406. pKeyProvInfo->pwszProvName = (LPWSTR) ((LPBYTE) pKeyProvInfo->pwszContainerName +
  1407. ((::SysStringLen(ContainerName) + 1) * sizeof(WCHAR)));
  1408. pKeyProvInfo->dwProvType = ProviderType;
  1409. pKeyProvInfo->dwKeySpec = KeySpec;
  1410. pKeyProvInfo->dwFlags = dwFlags;
  1411. ::wcscpy(pKeyProvInfo->pwszContainerName, ContainerName);
  1412. ::wcscpy(pKeyProvInfo->pwszProvName, ProviderName);
  1413. //
  1414. // Update states.
  1415. //
  1416. if (m_pKeyProvInfo)
  1417. {
  1418. ::CoTaskMemFree((LPVOID) m_pKeyProvInfo);
  1419. }
  1420. m_cbKeyProvInfo = dwSerializedLength;
  1421. m_pKeyProvInfo = pKeyProvInfo;
  1422. }
  1423. catch(...)
  1424. {
  1425. hr = E_POINTER;
  1426. DebugTrace("Exception: invalid parameter.\n");
  1427. goto ErrorExit;
  1428. }
  1429. UnlockExit:
  1430. //
  1431. // Free resources.
  1432. //
  1433. if (hCryptKey)
  1434. {
  1435. ::CryptDestroyKey(hCryptKey);
  1436. }
  1437. if (hCryptProv)
  1438. {
  1439. ::ReleaseContext(hCryptProv);
  1440. }
  1441. //
  1442. // Unlock access to this object.
  1443. //
  1444. m_Lock.Unlock();
  1445. DebugTrace("Leaving CPrivateKey::Open().\n");
  1446. return hr;
  1447. ErrorExit:
  1448. //
  1449. // Sanity check.
  1450. //
  1451. ATLASSERT(FAILED(hr));
  1452. //
  1453. // Free resources.
  1454. //
  1455. if (pKeyProvInfo)
  1456. {
  1457. ::CoTaskMemFree(pKeyProvInfo);
  1458. }
  1459. ReportError(hr);
  1460. goto UnlockExit;
  1461. }
  1462. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1463. Function : CPrivateKey::Delete
  1464. Synopsis : Delete the existing key container.
  1465. Parameter: None.
  1466. Remark :
  1467. ------------------------------------------------------------------------------*/
  1468. STDMETHODIMP CPrivateKey::Delete ()
  1469. {
  1470. HRESULT hr = S_OK;
  1471. HCRYPTPROV hCryptProv = NULL;
  1472. DebugTrace("Entering CPrivateKey::Delete().\n");
  1473. try
  1474. {
  1475. //
  1476. // Lock access to this object.
  1477. //
  1478. m_Lock.Lock();
  1479. //
  1480. // Not allowed if read-only.
  1481. //
  1482. if (m_bReadOnly)
  1483. {
  1484. hr = CAPICOM_E_NOT_ALLOWED;
  1485. DebugTrace("Error [%#x]: Deleting private key from WEB script is not allowed.\n", hr);
  1486. goto ErrorExit;
  1487. }
  1488. //
  1489. // Make sure we do have private key.
  1490. //
  1491. if (!m_pKeyProvInfo)
  1492. {
  1493. hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
  1494. DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
  1495. goto ErrorExit;
  1496. }
  1497. //
  1498. // Delete it!
  1499. //
  1500. if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
  1501. m_pKeyProvInfo->pwszContainerName,
  1502. m_pKeyProvInfo->dwProvType,
  1503. CRYPT_DELETEKEYSET | (m_pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET),
  1504. FALSE,
  1505. &hCryptProv)))
  1506. {
  1507. DebugTrace("Error [%#x]: AcquireContext(CRYPT_DELETEKEYSET) failed.\n", hr);
  1508. goto ErrorExit;
  1509. }
  1510. //
  1511. // Update states.
  1512. //
  1513. ::CoTaskMemFree((LPVOID) m_pKeyProvInfo);
  1514. m_cbKeyProvInfo = 0;
  1515. m_pKeyProvInfo = NULL;
  1516. }
  1517. catch(...)
  1518. {
  1519. hr = E_POINTER;
  1520. DebugTrace("Exception: invalid parameter.\n");
  1521. goto ErrorExit;
  1522. }
  1523. UnlockExit:
  1524. //
  1525. // Unlock access to this object.
  1526. //
  1527. m_Lock.Unlock();
  1528. DebugTrace("Leaving CPrivateKey::Delete().\n");
  1529. return hr;
  1530. ErrorExit:
  1531. //
  1532. // Sanity check.
  1533. //
  1534. ATLASSERT(FAILED(hr));
  1535. ReportError(hr);
  1536. goto UnlockExit;
  1537. }
  1538. ////////////////////////////////////////////////////////////////////////////////
  1539. //
  1540. // Custom interfaces.
  1541. //
  1542. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1543. Function : CPrivateKey::_GetKeyProvInfo
  1544. Synopsis : Return pointer to key prov info of a private key object.
  1545. Parameter: PCRYPT_KEY_PROV_INFO * ppKeyProvInfo - Pointer to
  1546. PCRYPT_KEY_PROV_INFO.
  1547. Remark : Caller must free the structure with CoTaskMemFree().
  1548. ------------------------------------------------------------------------------*/
  1549. STDMETHODIMP CPrivateKey::_GetKeyProvInfo (PCRYPT_KEY_PROV_INFO * ppKeyProvInfo)
  1550. {
  1551. HRESULT hr = S_OK;
  1552. PCRYPT_KEY_PROV_INFO pKeyProvInfo = NULL;
  1553. DebugTrace("Entering CPrivateKey::_GetKeyProvInfo().\n");
  1554. try
  1555. {
  1556. //
  1557. // Lock access to this object.
  1558. //
  1559. m_Lock.Lock();
  1560. //
  1561. // Make sure we do have private key.
  1562. //
  1563. if (!m_pKeyProvInfo)
  1564. {
  1565. hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
  1566. DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
  1567. goto ErrorExit;
  1568. }
  1569. //
  1570. // Allocate memory.
  1571. //
  1572. if (!(pKeyProvInfo = (PCRYPT_KEY_PROV_INFO) ::CoTaskMemAlloc(m_cbKeyProvInfo)))
  1573. {
  1574. hr = E_OUTOFMEMORY;
  1575. DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
  1576. goto ErrorExit;
  1577. }
  1578. //
  1579. // copy structure over.
  1580. //
  1581. ::CopyMemory((LPVOID) pKeyProvInfo, (LPVOID) m_pKeyProvInfo, (SIZE_T) m_cbKeyProvInfo);
  1582. //
  1583. // and return the structure to caller.
  1584. //
  1585. *ppKeyProvInfo = pKeyProvInfo;
  1586. }
  1587. catch(...)
  1588. {
  1589. hr = E_POINTER;
  1590. DebugTrace("Exception: invalid parameter.\n");
  1591. goto ErrorExit;
  1592. }
  1593. UnlockExit:
  1594. //
  1595. // Unlock access to this object.
  1596. //
  1597. m_Lock.Unlock();
  1598. DebugTrace("Leaving CPrivateKey::_GetKeyProvInfo().\n");
  1599. return hr;
  1600. ErrorExit:
  1601. //
  1602. // Sanity check.
  1603. //
  1604. ATLASSERT(FAILED(hr));
  1605. //
  1606. // Free resources.
  1607. //
  1608. if (pKeyProvInfo)
  1609. {
  1610. ::CoTaskMemFree((LPVOID) pKeyProvInfo);
  1611. }
  1612. ReportError(hr);
  1613. goto UnlockExit;
  1614. }
  1615. ////////////////////////////////////////////////////////////////////////////////
  1616. //
  1617. // Private methods.
  1618. //
  1619. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1620. Function : CPrivateKey::Init
  1621. Synopsis : Initialize the object.
  1622. Parameter: PCCERT_CONTEXT pCertContext - Pointer to PCCERT_CONTEXT to be used
  1623. to initialize the object.
  1624. BOOL bReadOnly - TRUE if read-only, else FALSE.
  1625. Remark : This method is not part of the COM interface (it is a normal C++
  1626. member function). We need it to initialize the object created
  1627. internally by us.
  1628. Since it is only a normal C++ member function, this function can
  1629. only be called from a C++ class pointer, not an interface pointer.
  1630. ------------------------------------------------------------------------------*/
  1631. STDMETHODIMP CPrivateKey::Init (PCCERT_CONTEXT pCertContext, BOOL bReadOnly)
  1632. {
  1633. HRESULT hr = S_OK;
  1634. DWORD cbData = 0;
  1635. PCRYPT_KEY_PROV_INFO pKeyProvInfo = NULL;
  1636. DebugTrace("Entering CPrivateKey::Init().\n");
  1637. //
  1638. // Sanity check.
  1639. //
  1640. ATLASSERT(pCertContext);
  1641. //
  1642. // Get key provider info property.
  1643. //
  1644. if (!::CertGetCertificateContextProperty(pCertContext,
  1645. CERT_KEY_PROV_INFO_PROP_ID,
  1646. NULL,
  1647. &cbData))
  1648. {
  1649. hr = HRESULT_FROM_WIN32(::GetLastError());
  1650. DebugTrace("Info [%#x]: CertGetCertificateContextProperty() failed.\n", hr);
  1651. goto ErrorExit;
  1652. }
  1653. if (!(pKeyProvInfo = (PCRYPT_KEY_PROV_INFO) ::CoTaskMemAlloc(cbData)))
  1654. {
  1655. hr = E_OUTOFMEMORY;
  1656. DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
  1657. goto ErrorExit;
  1658. }
  1659. if (!::CertGetCertificateContextProperty(pCertContext,
  1660. CERT_KEY_PROV_INFO_PROP_ID,
  1661. pKeyProvInfo,
  1662. &cbData))
  1663. {
  1664. hr = HRESULT_FROM_WIN32(::GetLastError());
  1665. DebugTrace("Info [%#x]: CertGetCertificateContextProperty() failed.\n", hr);
  1666. goto ErrorExit;
  1667. }
  1668. //
  1669. // Update states.
  1670. //
  1671. if (m_pKeyProvInfo)
  1672. {
  1673. ::CoTaskMemFree((LPVOID) m_pKeyProvInfo);
  1674. }
  1675. m_bReadOnly = bReadOnly;
  1676. m_cbKeyProvInfo = cbData;
  1677. m_pKeyProvInfo = pKeyProvInfo;
  1678. CommonExit:
  1679. DebugTrace("Leaving CPrivateKey::Init().\n");
  1680. return hr;
  1681. ErrorExit:
  1682. //
  1683. // Sanity check.
  1684. //
  1685. ATLASSERT(FAILED(hr));
  1686. //
  1687. // Free resources.
  1688. //
  1689. if (pKeyProvInfo)
  1690. {
  1691. ::CoTaskMemFree((LPVOID) pKeyProvInfo);
  1692. }
  1693. goto CommonExit;
  1694. }