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.

449 lines
12 KiB

  1. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
  3. File: PFXHlpr.cpp
  4. Content: PFX helper routines.
  5. History: 09-15-2001 dsie created
  6. ------------------------------------------------------------------------------*/
  7. #include "StdAfx.h"
  8. #include "CAPICOM.h"
  9. #include "PFXHlpr.h"
  10. #include "Common.h"
  11. ////////////////////////////////////////////////////////////////////////////////
  12. //
  13. // Local functions.
  14. //
  15. ////////////////////////////////////////////////////////////////////////////////
  16. //
  17. // Exported functions.
  18. //
  19. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  20. Function : PFXExportStore
  21. Synopsis : Export cert store to PFX blob.
  22. Parameter: HCERTSTORE hCertStore - Store handle.
  23. LPWSTR pwszPassword - Password to encrypt the PFX file.
  24. DWPRD dwFlags - PFX export flags.
  25. DATA_BLOB * pPFXBlob - Pointer to DATA_BLOB to receive PFX blob.
  26. Remark :
  27. ------------------------------------------------------------------------------*/
  28. HRESULT PFXExportStore (HCERTSTORE hCertStore,
  29. LPWSTR pwszPassword,
  30. DWORD dwFlags,
  31. DATA_BLOB * pPFXBlob)
  32. {
  33. HRESULT hr = S_OK;
  34. DATA_BLOB DataBlob = {0, NULL};
  35. DebugTrace("Entering PFXExportStore().\n");
  36. //
  37. // Sanity check.
  38. //
  39. ATLASSERT(hCertStore);
  40. ATLASSERT(pPFXBlob);
  41. //
  42. // Export to blob.
  43. //
  44. if (!::PFXExportCertStoreEx(hCertStore,
  45. &DataBlob,
  46. pwszPassword,
  47. NULL,
  48. dwFlags))
  49. {
  50. hr = HRESULT_FROM_WIN32(::GetLastError());
  51. DebugTrace("Error [%#x]: PFXExportCertStoreEx() failed.\n", hr);
  52. goto ErrorExit;
  53. }
  54. if (!(DataBlob.pbData = (LPBYTE) ::CoTaskMemAlloc(DataBlob.cbData)))
  55. {
  56. hr = E_OUTOFMEMORY;
  57. DebugTrace("Error: out of memory.\n");
  58. goto ErrorExit;
  59. }
  60. if (!::PFXExportCertStoreEx(hCertStore,
  61. &DataBlob,
  62. pwszPassword,
  63. NULL,
  64. dwFlags))
  65. {
  66. hr = HRESULT_FROM_WIN32(::GetLastError());
  67. DebugTrace("Error [%#x]: PFXExportCertStoreEx() failed.\n", hr);
  68. goto ErrorExit;
  69. }
  70. //
  71. // Return the blob to caller.
  72. //
  73. *pPFXBlob = DataBlob;
  74. CommonExit:
  75. DebugTrace("Leaving PFXExportStore().\n");
  76. return hr;
  77. ErrorExit:
  78. //
  79. // Sanity check.
  80. //
  81. ATLASSERT(FAILED(hr));
  82. //
  83. // Remap private key not exportable errors to a common error code.
  84. //
  85. if (HRESULT_FROM_WIN32(NTE_BAD_KEY) == hr ||
  86. HRESULT_FROM_WIN32(NTE_BAD_KEY_STATE) == hr ||
  87. HRESULT_FROM_WIN32(NTE_BAD_TYPE) == hr)
  88. {
  89. DebugTrace("Info: Win32 error %#x is remapped to %#x.\n",
  90. hr, CAPICOM_E_PRIVATE_KEY_NOT_EXPORTABLE);
  91. hr = CAPICOM_E_PRIVATE_KEY_NOT_EXPORTABLE;
  92. }
  93. //
  94. // Free resources.
  95. //
  96. if (DataBlob.pbData)
  97. {
  98. ::CoTaskMemFree((LPVOID) DataBlob.pbData);
  99. }
  100. goto CommonExit;
  101. }
  102. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  103. Function : PFXSaveStore
  104. Synopsis : Save a PFX file and return all the certs in a HCERTSTORE.
  105. Parameter: HCERTSTORE hCertStore - Store handle.
  106. LPWSTR pwszFileName - PFX filename.
  107. LPWSTR pwszPassword - Password to encrypt the PFX file.
  108. DWPRD dwFlags - PFX export flags.
  109. Remark :
  110. ------------------------------------------------------------------------------*/
  111. HRESULT PFXSaveStore (HCERTSTORE hCertStore,
  112. LPWSTR pwszFileName,
  113. LPWSTR pwszPassword,
  114. DWORD dwFlags)
  115. {
  116. HRESULT hr = S_OK;
  117. DATA_BLOB DataBlob = {0, NULL};
  118. DebugTrace("Entering PFXSaveStore().\n");
  119. //
  120. // Sanity check.
  121. //
  122. ATLASSERT(hCertStore);
  123. ATLASSERT(pwszFileName);
  124. //
  125. // Export to blob.
  126. //
  127. if (FAILED(hr = ::PFXExportStore(hCertStore,
  128. pwszPassword,
  129. dwFlags,
  130. &DataBlob)))
  131. {
  132. DebugTrace("Error [%#x]: PFXExportStore() failed.\n", hr);
  133. goto ErrorExit;
  134. }
  135. //
  136. // Now write to file.
  137. //
  138. if (FAILED(hr = ::WriteFileContent(pwszFileName, DataBlob)))
  139. {
  140. DebugTrace("Error [%#x]: WriteFileContent() failed.\n", hr);
  141. goto ErrorExit;
  142. }
  143. CommonExit:
  144. //
  145. // Free resources.
  146. //
  147. if (DataBlob.pbData)
  148. {
  149. ::CoTaskMemFree(DataBlob.pbData);
  150. }
  151. DebugTrace("Leaving PFXSaveStore().\n");
  152. return hr;
  153. ErrorExit:
  154. //
  155. // Sanity check.
  156. //
  157. ATLASSERT(FAILED(hr));
  158. goto CommonExit;
  159. }
  160. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  161. Function : PFXLoadStore
  162. Synopsis : Load a PFX file and return all the certs in a HCERTSTORE.
  163. Parameter: LPWSTR pwszFileName - PFX filename.
  164. LPWSTR pwszPassword - Password to decrypt the PFX file.
  165. DWPRD dwFlags - PFX import flags.
  166. HCERTSTORE * phCertStore - Pointer to HCERSTORE to receive the
  167. handle.
  168. Remark :
  169. ------------------------------------------------------------------------------*/
  170. HRESULT PFXLoadStore (LPWSTR pwszFileName,
  171. LPWSTR pwszPassword,
  172. DWORD dwFlags,
  173. HCERTSTORE * phCertStore)
  174. {
  175. HRESULT hr = S_OK;
  176. DATA_BLOB DataBlob = {0, NULL};
  177. HCERTSTORE hCertStore = NULL;
  178. DebugTrace("Entering PFXLoadStore().\n");
  179. //
  180. // Sanity check.
  181. //
  182. ATLASSERT(pwszFileName);
  183. ATLASSERT(phCertStore);
  184. //
  185. // Read content into memory.
  186. //
  187. if (FAILED(hr = ::ReadFileContent(pwszFileName, &DataBlob)))
  188. {
  189. DebugTrace("Error [%#x]: ReadFileContent() failed.\n", hr);
  190. goto ErrorExit;
  191. }
  192. //
  193. // Now import the blob to store.
  194. //
  195. if (!(hCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB *) &DataBlob,
  196. pwszPassword,
  197. dwFlags)))
  198. {
  199. hr = HRESULT_FROM_WIN32(::GetLastError());
  200. DebugTrace("Error [%#x]: PFXImportCertStore() failed.\n", hr);
  201. goto ErrorExit;
  202. }
  203. //
  204. // Return HCERSTORE to caller.
  205. //
  206. *phCertStore = hCertStore;
  207. CommonExit:
  208. //
  209. // Free resources.
  210. //
  211. if (DataBlob.pbData)
  212. {
  213. ::UnmapViewOfFile(DataBlob.pbData);
  214. }
  215. DebugTrace("Leaving PFXLoadStore().\n");
  216. return hr;
  217. ErrorExit:
  218. //
  219. // Sanity check.
  220. //
  221. ATLASSERT(FAILED(hr));
  222. //
  223. // Free resources.
  224. //
  225. if (hCertStore)
  226. {
  227. ::CertCloseStore(hCertStore, 0);
  228. }
  229. goto CommonExit;
  230. }
  231. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  232. Function : PFXFreeStore
  233. Synopsis : Free resources by deleting key containers loaded by PFXLoadStore,
  234. and then close the store.
  235. Parameter: HCERTSTORE hCertStore - Store handle returned by PFXLoadStore.
  236. Remark : hCertStore is always closed even if error occurred.
  237. ------------------------------------------------------------------------------*/
  238. HRESULT PFXFreeStore (HCERTSTORE hCertStore)
  239. {
  240. HRESULT hr = S_OK;
  241. HCRYPTPROV hCryptProv = NULL;
  242. PCCERT_CONTEXT pCertContext = NULL;
  243. PCRYPT_KEY_PROV_INFO pKeyProvInfo = NULL;
  244. DebugTrace("Entering PFXFreeStore().\n");
  245. //
  246. // Sanity check.
  247. //
  248. ATLASSERT(hCertStore);
  249. //
  250. // Now delete all key containers.
  251. //
  252. while (pCertContext = ::CertEnumCertificatesInStore(hCertStore, pCertContext))
  253. {
  254. DWORD cbData = 0;
  255. //
  256. // Retrieve key container info.
  257. //
  258. if (!::CertGetCertificateContextProperty(pCertContext,
  259. CERT_KEY_PROV_INFO_PROP_ID,
  260. NULL,
  261. &cbData))
  262. {
  263. continue;
  264. }
  265. if (!(pKeyProvInfo = (CRYPT_KEY_PROV_INFO *) ::CoTaskMemAlloc(cbData)))
  266. {
  267. hr = E_OUTOFMEMORY;
  268. DebugTrace("Error: out of memory.\n");
  269. goto ErrorExit;
  270. }
  271. if (!::CertGetCertificateContextProperty(pCertContext,
  272. CERT_KEY_PROV_INFO_PROP_ID,
  273. pKeyProvInfo,
  274. &cbData))
  275. {
  276. hr = HRESULT_FROM_WIN32(::GetLastError());
  277. DebugTrace("Error [%#x]: CertGetCertificateContextProperty() failed.\n", hr);
  278. goto ErrorExit;
  279. }
  280. //
  281. // First disassociate the key from the cert.
  282. //
  283. if (!::CertSetCertificateContextProperty(pCertContext,
  284. CERT_KEY_PROV_INFO_PROP_ID,
  285. 0,
  286. NULL))
  287. {
  288. hr = HRESULT_FROM_WIN32(::GetLastError());
  289. DebugTrace("Error [%#x]: CertSetCertificateContextProperty() failed to disassociate key container.\n", hr);
  290. goto ErrorExit;
  291. }
  292. //
  293. // Then delete the key container.
  294. //
  295. if (FAILED (hr = ::AcquireContext(pKeyProvInfo->pwszProvName,
  296. pKeyProvInfo->pwszContainerName,
  297. pKeyProvInfo->dwProvType,
  298. CRYPT_DELETEKEYSET | (pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET),
  299. FALSE,
  300. &hCryptProv)))
  301. {
  302. DebugTrace("Error [%#x]: AcquireContext(CRYPT_DELETEKEYSET) failed .\n", hr);
  303. goto ErrorExit;
  304. }
  305. ::CoTaskMemFree((LPVOID) pKeyProvInfo), pKeyProvInfo = NULL;
  306. //
  307. // Don'f free cert context here, as CertEnumCertificatesInStore()
  308. // will do that automatically!!!
  309. //
  310. }
  311. //
  312. // Above loop can exit either because there is no more certificate in
  313. // the store or an error. Need to check last error to be certain.
  314. //
  315. if (CRYPT_E_NOT_FOUND != ::GetLastError())
  316. {
  317. hr = HRESULT_FROM_WIN32(::GetLastError());
  318. DebugTrace("Error [%#x]: CertEnumCertificatesInStore() failed.\n", hr);
  319. goto ErrorExit;
  320. }
  321. CommonExit:
  322. //
  323. // Free resources.
  324. //
  325. if (pKeyProvInfo)
  326. {
  327. ::CoTaskMemFree((LPVOID) pKeyProvInfo);
  328. }
  329. if (pCertContext)
  330. {
  331. ::CertFreeCertificateContext(pCertContext);
  332. }
  333. if (hCertStore)
  334. {
  335. ::CertCloseStore(hCertStore, 0);
  336. }
  337. DebugTrace("Leaving PFXFreeStore().\n");
  338. return hr;
  339. ErrorExit:
  340. //
  341. // Sanity check.
  342. //
  343. ATLASSERT(FAILED(hr));
  344. goto CommonExit;
  345. }