|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
File: PFXHlpr.cpp
Content: PFX helper routines.
History: 09-15-2001 dsie created
------------------------------------------------------------------------------*/
#include "StdAfx.h"
#include "CAPICOM.h"
#include "PFXHlpr.h"
#include "Common.h"
////////////////////////////////////////////////////////////////////////////////
//
// Local functions.
//
////////////////////////////////////////////////////////////////////////////////
//
// Exported functions.
//
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : PFXExportStore
Synopsis : Export cert store to PFX blob.
Parameter: HCERTSTORE hCertStore - Store handle. LPWSTR pwszPassword - Password to encrypt the PFX file.
DWPRD dwFlags - PFX export flags.
DATA_BLOB * pPFXBlob - Pointer to DATA_BLOB to receive PFX blob.
Remark :
------------------------------------------------------------------------------*/
HRESULT PFXExportStore (HCERTSTORE hCertStore, LPWSTR pwszPassword, DWORD dwFlags, DATA_BLOB * pPFXBlob) { HRESULT hr = S_OK; DATA_BLOB DataBlob = {0, NULL};
DebugTrace("Entering PFXExportStore().\n");
//
// Sanity check.
//
ATLASSERT(hCertStore); ATLASSERT(pPFXBlob);
//
// Export to blob.
//
if (!::PFXExportCertStoreEx(hCertStore, &DataBlob, pwszPassword, NULL, dwFlags)) { hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: PFXExportCertStoreEx() failed.\n", hr); goto ErrorExit; }
if (!(DataBlob.pbData = (LPBYTE) ::CoTaskMemAlloc(DataBlob.cbData))) { hr = E_OUTOFMEMORY;
DebugTrace("Error: out of memory.\n"); goto ErrorExit; }
if (!::PFXExportCertStoreEx(hCertStore, &DataBlob, pwszPassword, NULL, dwFlags)) { hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: PFXExportCertStoreEx() failed.\n", hr); goto ErrorExit; }
//
// Return the blob to caller.
//
*pPFXBlob = DataBlob;
CommonExit:
DebugTrace("Leaving PFXExportStore().\n");
return hr;
ErrorExit: //
// Sanity check.
//
ATLASSERT(FAILED(hr));
//
// Remap private key not exportable errors to a common error code.
//
if (HRESULT_FROM_WIN32(NTE_BAD_KEY) == hr || HRESULT_FROM_WIN32(NTE_BAD_KEY_STATE) == hr || HRESULT_FROM_WIN32(NTE_BAD_TYPE) == hr) { DebugTrace("Info: Win32 error %#x is remapped to %#x.\n", hr, CAPICOM_E_PRIVATE_KEY_NOT_EXPORTABLE);
hr = CAPICOM_E_PRIVATE_KEY_NOT_EXPORTABLE;
}
//
// Free resources.
//
if (DataBlob.pbData) { ::CoTaskMemFree((LPVOID) DataBlob.pbData); }
goto CommonExit; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : PFXSaveStore
Synopsis : Save a PFX file and return all the certs in a HCERTSTORE.
Parameter: HCERTSTORE hCertStore - Store handle. LPWSTR pwszFileName - PFX filename. LPWSTR pwszPassword - Password to encrypt the PFX file.
DWPRD dwFlags - PFX export flags.
Remark :
------------------------------------------------------------------------------*/
HRESULT PFXSaveStore (HCERTSTORE hCertStore, LPWSTR pwszFileName, LPWSTR pwszPassword, DWORD dwFlags) { HRESULT hr = S_OK; DATA_BLOB DataBlob = {0, NULL};
DebugTrace("Entering PFXSaveStore().\n");
//
// Sanity check.
//
ATLASSERT(hCertStore); ATLASSERT(pwszFileName);
//
// Export to blob.
//
if (FAILED(hr = ::PFXExportStore(hCertStore, pwszPassword, dwFlags, &DataBlob))) { DebugTrace("Error [%#x]: PFXExportStore() failed.\n", hr); goto ErrorExit; }
//
// Now write to file.
//
if (FAILED(hr = ::WriteFileContent(pwszFileName, DataBlob))) { DebugTrace("Error [%#x]: WriteFileContent() failed.\n", hr); goto ErrorExit; }
CommonExit: //
// Free resources.
//
if (DataBlob.pbData) { ::CoTaskMemFree(DataBlob.pbData); }
DebugTrace("Leaving PFXSaveStore().\n");
return hr;
ErrorExit: //
// Sanity check.
//
ATLASSERT(FAILED(hr));
goto CommonExit; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : PFXLoadStore
Synopsis : Load a PFX file and return all the certs in a HCERTSTORE.
Parameter: LPWSTR pwszFileName - PFX filename. LPWSTR pwszPassword - Password to decrypt the PFX file.
DWPRD dwFlags - PFX import flags.
HCERTSTORE * phCertStore - Pointer to HCERSTORE to receive the handle. Remark :
------------------------------------------------------------------------------*/
HRESULT PFXLoadStore (LPWSTR pwszFileName, LPWSTR pwszPassword, DWORD dwFlags, HCERTSTORE * phCertStore) { HRESULT hr = S_OK; DATA_BLOB DataBlob = {0, NULL}; HCERTSTORE hCertStore = NULL;
DebugTrace("Entering PFXLoadStore().\n");
//
// Sanity check.
//
ATLASSERT(pwszFileName); ATLASSERT(phCertStore);
//
// Read content into memory.
//
if (FAILED(hr = ::ReadFileContent(pwszFileName, &DataBlob))) { DebugTrace("Error [%#x]: ReadFileContent() failed.\n", hr); goto ErrorExit; }
//
// Now import the blob to store.
//
if (!(hCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB *) &DataBlob, pwszPassword, dwFlags))) { hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: PFXImportCertStore() failed.\n", hr); goto ErrorExit; }
//
// Return HCERSTORE to caller.
//
*phCertStore = hCertStore;
CommonExit: //
// Free resources.
//
if (DataBlob.pbData) { ::UnmapViewOfFile(DataBlob.pbData); }
DebugTrace("Leaving PFXLoadStore().\n");
return hr;
ErrorExit: //
// Sanity check.
//
ATLASSERT(FAILED(hr));
//
// Free resources.
//
if (hCertStore) { ::CertCloseStore(hCertStore, 0); }
goto CommonExit; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : PFXFreeStore
Synopsis : Free resources by deleting key containers loaded by PFXLoadStore, and then close the store.
Parameter: HCERTSTORE hCertStore - Store handle returned by PFXLoadStore. Remark : hCertStore is always closed even if error occurred.
------------------------------------------------------------------------------*/
HRESULT PFXFreeStore (HCERTSTORE hCertStore) { HRESULT hr = S_OK; HCRYPTPROV hCryptProv = NULL; PCCERT_CONTEXT pCertContext = NULL; PCRYPT_KEY_PROV_INFO pKeyProvInfo = NULL;
DebugTrace("Entering PFXFreeStore().\n");
//
// Sanity check.
//
ATLASSERT(hCertStore);
//
// Now delete all key containers.
//
while (pCertContext = ::CertEnumCertificatesInStore(hCertStore, pCertContext)) { DWORD cbData = 0;
//
// Retrieve key container info.
//
if (!::CertGetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, NULL, &cbData)) { continue; }
if (!(pKeyProvInfo = (CRYPT_KEY_PROV_INFO *) ::CoTaskMemAlloc(cbData))) { hr = E_OUTOFMEMORY;
DebugTrace("Error: out of memory.\n"); goto ErrorExit; }
if (!::CertGetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, pKeyProvInfo, &cbData)) { hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CertGetCertificateContextProperty() failed.\n", hr); goto ErrorExit; }
//
// First disassociate the key from the cert.
//
if (!::CertSetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, 0, NULL)) { hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CertSetCertificateContextProperty() failed to disassociate key container.\n", hr); goto ErrorExit; }
//
// Then delete the key container.
//
if (FAILED (hr = ::AcquireContext(pKeyProvInfo->pwszProvName, pKeyProvInfo->pwszContainerName, pKeyProvInfo->dwProvType, CRYPT_DELETEKEYSET | (pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET), FALSE, &hCryptProv))) { DebugTrace("Error [%#x]: AcquireContext(CRYPT_DELETEKEYSET) failed .\n", hr); goto ErrorExit; }
::CoTaskMemFree((LPVOID) pKeyProvInfo), pKeyProvInfo = NULL;
//
// Don'f free cert context here, as CertEnumCertificatesInStore()
// will do that automatically!!!
//
}
//
// Above loop can exit either because there is no more certificate in
// the store or an error. Need to check last error to be certain.
//
if (CRYPT_E_NOT_FOUND != ::GetLastError()) { hr = HRESULT_FROM_WIN32(::GetLastError()); DebugTrace("Error [%#x]: CertEnumCertificatesInStore() failed.\n", hr); goto ErrorExit; }
CommonExit: //
// Free resources.
//
if (pKeyProvInfo) { ::CoTaskMemFree((LPVOID) pKeyProvInfo); } if (pCertContext) { ::CertFreeCertificateContext(pCertContext); } if (hCertStore) { ::CertCloseStore(hCertStore, 0); }
DebugTrace("Leaving PFXFreeStore().\n");
return hr;
ErrorExit: //
// Sanity check.
//
ATLASSERT(FAILED(hr));
goto CommonExit; }
|