|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Microsoft Windows, Copyright (C) Microsoft Corporation, 2000 - 2001.
File: CertHlpr.cpp
Content: Helper functions for cert.
History: 09-10-2001 dsie created
------------------------------------------------------------------------------*/
#include "StdAfx.h"
#include "CAPICOM.h"
#include "CertHlpr.h"
#include "Settings.h"
#include "Certificate.h"
#include "Common.h"
typedef PCCERT_CONTEXT (WINAPI * PCRYPTUIDLGSELECTCERTIFICATEW) (IN PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc);
////////////////////////////////////////////////////////////////////////////////
//
// Exported functions.
//
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : GetEnhancedKeyUsage
Synopsis : Retrieve the EKU from the cert.
Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT.
DWORD dwFlags - 0, or CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, or CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG.
PCERT_ENHKEY_USAGE * ppUsage - Pointer to PCERT_ENHKEY_USAGE to receive the usages.
Remark : If EKU extension is found with no EKU, then return HRESULT is CERT_E_WRONG_USAGE. ------------------------------------------------------------------------------*/
HRESULT GetEnhancedKeyUsage (PCCERT_CONTEXT pCertContext, DWORD dwFlags, PCERT_ENHKEY_USAGE * ppUsage) { HRESULT hr = S_OK; DWORD dwWinError = 0; DWORD cbUsage = 0; PCERT_ENHKEY_USAGE pUsage = NULL;
//
// Sanity check.
//
ATLASSERT(pCertContext); ATLASSERT(ppUsage);
//
// Initialize.
//
*ppUsage = NULL;
//
// Determine extended key usage data length.
//
if (!::CertGetEnhancedKeyUsage(pCertContext, dwFlags, NULL, &cbUsage)) { //
// Older version of Crypt32.dll would return FALSE for
// empty EKU. In this case, we want to treat it as success,
//
if (CRYPT_E_NOT_FOUND == (dwWinError = ::GetLastError())) { //
// and also set the cbUsage.
//
cbUsage = sizeof(CERT_ENHKEY_USAGE);
DebugTrace("Info: CertGetEnhancedKeyUsage() found no EKU, so valid for all uses.\n"); } else { hr = HRESULT_FROM_WIN32(dwWinError);
DebugTrace("Error [%#x]: CertGetEnhancedKeyUsage() failed to get size.\n", hr); goto ErrorExit; } }
//
// Allocate memory.
//
if (!(pUsage = (PCERT_ENHKEY_USAGE) ::CoTaskMemAlloc((ULONG) cbUsage))) { hr = E_OUTOFMEMORY;
DebugTrace("Error: out of memory.\n"); goto ErrorExit; }
//
// Get extended key usage data.
//
if (!::CertGetEnhancedKeyUsage(pCertContext, dwFlags, pUsage, &cbUsage)) { //
// Older version of Crypt32.dll would return FALSE for
// empty EKU. In this case, we want to treat it as success.
//
if (CRYPT_E_NOT_FOUND == (dwWinError = ::GetLastError())) { //
// Structure pointed to by pUsage is not initialized by older
// version of Cryp32 for empty EKU.
//
::ZeroMemory(pUsage, sizeof(CERT_ENHKEY_USAGE)); } else { hr = HRESULT_FROM_WIN32(dwWinError);
DebugTrace("Error [%#x]: CertGetEnhancedKeyUsage() failed to get data.\n", hr); goto ErrorExit; } }
//
// See if we have any EKU?
//
if (0 == pUsage->cUsageIdentifier && CRYPT_E_NOT_FOUND != ::GetLastError()) { //
// This is not valid for any usage.
//
hr = CERT_E_WRONG_USAGE; goto ErrorExit; }
//
// Return usages to caller.
//
*ppUsage = pUsage;
CommonExit:
DebugTrace("Leaving GetEnhancedKeyUsage().\n");
return hr;
ErrorExit: //
// Sanity check.
//
ATLASSERT(FAILED(hr));
//
// Free resource.
//
if (pUsage) { ::CoTaskMemFree(pUsage); }
goto CommonExit; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : BuildChain
Synopsis : Build a chain using the specified policy.
Parameter: PCCERT_CONTEXT pCertContext - CERT_CONTEXT of cert to verify.
HCERTSTORE hCertStore - Additional store (can be NULL).
LPCSTR pszPolicy - Policy used to verify the cert (i.e. CERT_CHAIN_POLICY_BASE).
PCCERT_CHAIN_CONTEXT * ppChainContext - Pointer to PCCERT_CHAIN_CONTEXT. Remark :
------------------------------------------------------------------------------*/
HRESULT BuildChain (PCCERT_CONTEXT pCertContext, HCERTSTORE hCertStore, LPCSTR pszPolicy, PCCERT_CHAIN_CONTEXT * ppChainContext) { HRESULT hr = S_OK; CERT_CHAIN_PARA ChainPara = {0};; LPSTR rgpszUsageIdentifier[1] = {NULL};
DebugTrace("Entering BuildChain().\n");
//
// Sanity check.
//
ATLASSERT(pCertContext); ATLASSERT(pszPolicy); ATLASSERT(ppChainContext);
//
// Initialize.
//
ChainPara.cbSize = sizeof(ChainPara);
//
// Check policy.
//
if (CERT_CHAIN_POLICY_BASE == pszPolicy) { //
// No EKU for base policy.
//
} else if (CERT_CHAIN_POLICY_AUTHENTICODE == pszPolicy) { //
// Setup EKU for Authenticode policy.
//
rgpszUsageIdentifier[0] = szOID_PKIX_KP_CODE_SIGNING; ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND; ChainPara.RequestedUsage.Usage.cUsageIdentifier = 1; ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = rgpszUsageIdentifier; } else { //
// We don't support any other policy, yet.
//
hr = CERT_E_INVALID_POLICY;
DebugTrace("Internal error [%#x]: unexpected policy (%#x).\n", hr, pszPolicy); goto ErrorExit; }
//
// Build the chain.
//
if (!::CertGetCertificateChain(NULL, // in optional
pCertContext, // in
NULL, // in optional
hCertStore, // in optional
&ChainPara, // in
0, // in
NULL, // in
ppChainContext)) // out
{ hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CertGetCertificateChain() failed.\n", hr); goto ErrorExit; } CommonExit:
DebugTrace("Leaving BuildChain().\n");
return hr;
ErrorExit: //
// Sanity check.
//
ATLASSERT(FAILED(hr));
goto CommonExit; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : VerifyCertificate
Synopsis : Verify if the certificate is valid.
Parameter: PCCERT_CONTEXT pCertContext - CERT_CONTEXT of cert to verify.
HCERTSTORE hCertStore - Additional store (can be NULL).
LPCSTR pszPolicy - Policy used to verify the cert (i.e. CERT_CHAIN_POLICY_BASE). Remark :
------------------------------------------------------------------------------*/
HRESULT VerifyCertificate (PCCERT_CONTEXT pCertContext, HCERTSTORE hCertStore, LPCSTR pszPolicy) { HRESULT hr = S_OK; PCCERT_CHAIN_CONTEXT pChainContext = NULL; CERT_CHAIN_POLICY_PARA PolicyPara = {0}; CERT_CHAIN_POLICY_STATUS PolicyStatus = {0};
DebugTrace("Entering VerifyCertificate().\n");
//
// Sanity check.
//
ATLASSERT(pCertContext); ATLASSERT(pszPolicy);
//
// Initialize.
//
PolicyPara.cbSize = sizeof(PolicyPara); PolicyStatus.cbSize = sizeof(PolicyStatus);
//
// Build the chain.
//
if (FAILED(hr = ::BuildChain(pCertContext, hCertStore, pszPolicy, &pChainContext))) { DebugTrace("Error [%#x]: BuildChain() failed.\n", hr); goto ErrorExit; }
//
// Verify the chain using the specified policy.
//
if (::CertVerifyCertificateChainPolicy(pszPolicy, pChainContext, &PolicyPara, &PolicyStatus)) { if (PolicyStatus.dwError) { hr = HRESULT_FROM_WIN32(PolicyStatus.dwError);
DebugTrace("Error [%#x]: invalid policy.\n", hr); goto ErrorExit; } } else { hr = HRESULT_FROM_WIN32(CERT_E_INVALID_POLICY);
DebugTrace("Error [%#x]: CertVerifyCertificateChainPolicy() failed.\n", hr); goto ErrorExit; } CommonExit: //
// Free resource.
//
if (pChainContext) { ::CertFreeCertificateChain(pChainContext); }
DebugTrace("Leaving VerifyCertificate().\n");
return hr;
ErrorExit: //
// Sanity check.
//
ATLASSERT(FAILED(hr));
goto CommonExit; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : SelectCertificateContext
Synopsis : Pop UI to prompt user to select a certificate from an opened store.
Parameter: HCERTSTORE hCertStore - Source cert store.
LPWCSTR pwszTitle - Dialog title string.
LPWCSTR - pwszDisplayString - Dialog display string.
BOOL bMultiSelect - TRUE to enable multi-select.
PFNCFILTERPROC pfnFilterCallback - Pointer to filter callback function. HCERTSTORE hSelectedCertStore - HCERTSTORE to receive the selected certs for multi-select mode.
PCCERT_CONTEXT * ppCertContext - Pointer to PCCERT_CONTEXT receive the certificate context for single selection mode.
Remark : typedef struct tagCRYPTUI_SELECTCERTIFICATE_STRUCTW { DWORD dwSize; HWND hwndParent; // OPTIONAL
DWORD dwFlags; // OPTIONAL
LPCWSTR szTitle; // OPTIONAL
DWORD dwDontUseColumn; // OPTIONAL
LPCWSTR szDisplayString; // OPTIONAL
PFNCFILTERPROC pFilterCallback; // OPTIONAL
PFNCCERTDISPLAYPROC pDisplayCallback; // OPTIONAL
void * pvCallbackData; // OPTIONAL
DWORD cDisplayStores; HCERTSTORE * rghDisplayStores; DWORD cStores; // OPTIONAL
HCERTSTORE * rghStores; // OPTIONAL
DWORD cPropSheetPages; // OPTIONAL
LPCPROPSHEETPAGEW rgPropSheetPages; // OPTIONAL
HCERTSTORE hSelectedCertStore; // OPTIONAL
} CRYPTUI_SELECTCERTIFICATE_STRUCTW ------------------------------------------------------------------------------*/
HRESULT SelectCertificateContext (HCERTSTORE hCertStore, LPCWSTR pwszTitle, LPCWSTR pwszDisplayString, BOOL bMultiSelect, PFNCFILTERPROC pfnFilterCallback, HCERTSTORE hSelectedCertStore, PCCERT_CONTEXT * ppCertContext) { HRESULT hr = S_OK; HINSTANCE hDLL = NULL; PCCERT_CONTEXT pCertContext = NULL;
PCRYPTUIDLGSELECTCERTIFICATEW pCryptUIDlgSelectCertificateW = NULL; CRYPTUI_SELECTCERTIFICATE_STRUCTW csc;
DebugTrace("Entering SelectCertificateContext().\n");
//
// Sanity check.
//
ATLASSERT(hCertStore);
//
// Initialize.
//
if (ppCertContext) { *ppCertContext = NULL; }
//
// Make sure we are allowed to pop UI.
//
if (!PromptForCertificateEnabled()) { hr = CAPICOM_E_UI_DISABLED;
DebugTrace("Error [%#x]: Certificate selection UI is disabled.\n", hr); goto ErrorExit; }
//
// Get pointer to CryptUIDlgSelectCertificateW().
//
if (hDLL = ::LoadLibrary("CryptUI.dll")) { pCryptUIDlgSelectCertificateW = (PCRYPTUIDLGSELECTCERTIFICATEW) ::GetProcAddress(hDLL, "CryptUIDlgSelectCertificateW"); }
//
// Is CryptUIDlgSelectCertificateW() available?
//
if (!pCryptUIDlgSelectCertificateW) { hr = CAPICOM_E_NOT_SUPPORTED;
DebugTrace("Error [%#x]: CryptUIDlgSelectCertificateW() API not available.\n", hr); goto ErrorExit; }
//
// Pop UI to prompt user to select cert.
//
::ZeroMemory(&csc, sizeof(csc)); #if (0) //DSIE: Bug in older version of CRYPTUI does not check size correctly,
// so always force it to the oldest version of structure.
csc.dwSize = sizeof(csc); #else
csc.dwSize = offsetof(CRYPTUI_SELECTCERTIFICATE_STRUCTW, hSelectedCertStore); #endif
csc.dwFlags = bMultiSelect ? CRYPTUI_SELECTCERT_MULTISELECT : 0; csc.szTitle = pwszTitle; csc.szDisplayString = pwszDisplayString; csc.cDisplayStores = 1; csc.rghDisplayStores = &hCertStore; csc.pFilterCallback = pfnFilterCallback; csc.hSelectedCertStore = bMultiSelect ? hSelectedCertStore : NULL;
//
// Display the selection dialog.
//
if (pCertContext = (PCERT_CONTEXT) pCryptUIDlgSelectCertificateW(&csc)) { //
// Return CERT_CONTEXT to caller.
//
if (!(*ppCertContext = ::CertDuplicateCertificateContext(pCertContext))) { hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CertDuplicateCertificateContext() failed.\n", hr); goto ErrorExit; } } else { //
// Is this multi-select?
//
if (bMultiSelect) { //
// See if we have any cert in the store?
//
if (!(pCertContext = ::CertEnumCertificatesInStore(hSelectedCertStore, pCertContext))) { hr = CAPICOM_E_CANCELLED; DebugTrace("Error [%#x]: user cancelled cert selection dialog box.\n", hr); goto ErrorExit; } } else { hr = CAPICOM_E_CANCELLED; DebugTrace("Error [%#x]: user cancelled cert selection dialog box.\n", hr); goto ErrorExit; } } CommonExit: //
// Release resources.
//
if (pCertContext) { ::CertFreeCertificateContext(pCertContext); } if (hDLL) { ::FreeLibrary(hDLL); }
DebugTrace("Leaving SelectCertificateContext().\n");
return hr;
ErrorExit: //
// Sanity check.
//
ATLASSERT(FAILED(hr));
goto CommonExit; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : SelectCertificate
Synopsis : Select a certificate from the sepcified store. If only 1 cert is found after the filter, then that cert is returned. If more than 1 cert is found, then UI is popped to prompt user to select a certificate from the specified store.
Parameter: CAPICOM_STORE_INFO StoreInfo - Store to select from.
PFNCFILTERPROC pfnFilterCallback - Pointer to filter callback function. ICertificate2 ** ppICertificate - Pointer to pointer to ICertificate2 to receive interface pointer. Remark :
------------------------------------------------------------------------------*/
HRESULT SelectCertificate (CAPICOM_STORE_INFO StoreInfo, PFNCFILTERPROC pfnFilterCallback, ICertificate2 ** ppICertificate) { HRESULT hr = S_OK; HCERTSTORE hCertStore = NULL; PCCERT_CONTEXT pCertContext = NULL; PCCERT_CONTEXT pEnumContext = NULL; DWORD dwValidCerts = 0;
DebugTrace("Entering SelectCertificate().\n");
//
// Sanity check.
//
ATLASSERT(ppICertificate);
//
// Open the store for cert selection if necessary.
//
switch (StoreInfo.dwChoice) { case CAPICOM_STORE_INFO_STORENAME: { if (!(hCertStore = ::CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, CAPICOM_ASN_ENCODING, NULL, CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, (void *) StoreInfo.pwszStoreName))) { hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CertOpenStore() failed.\n", hr); goto ErrorExit; }
break; }
case CAPICOM_STORE_INFO_HCERTSTORE: { if (!(hCertStore = ::CertDuplicateStore(StoreInfo.hCertStore))) { hr = HRESULT_FROM_WIN32(::GetLastError()); DebugTrace("Error [%#x]: CertDuplicateStore() failed.\n", hr); goto ErrorExit; }
break; }
default: { hr = CAPICOM_E_INTERNAL;
DebugTrace("Internal error [%#x]: unknow store info deChoice (%d).\n", hr, StoreInfo.dwChoice); goto ErrorExit; } }
//
// Count number of certs in store.
//
while (pEnumContext = ::CertEnumCertificatesInStore(hCertStore, pEnumContext)) { //
// Count only if it will not be filtered out.
//
if (pfnFilterCallback && !pfnFilterCallback(pEnumContext, NULL, NULL)) { continue; }
if (pCertContext) { ::CertFreeCertificateContext(pCertContext); }
if (!(pCertContext = ::CertDuplicateCertificateContext(pEnumContext))) { hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CertDuplicateCertificateContext() failed.\n", hr); goto ErrorExit; }
dwValidCerts++; }
//
// 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; }
//
// If only 1 cert available, don't pop UI (just use it).
//
if (0 == dwValidCerts) { hr = CAPICOM_E_STORE_EMPTY;
DebugTrace("Error [%#x]: no certificate found.\n", hr); goto ErrorExit; } else if (1 < dwValidCerts) { //
// First free the CERT_CONTEXT we duplicated above.
//
::CertFreeCertificateContext(pCertContext), pCertContext = NULL;
//
// Pop UI to prompt user to select the signer cert.
//
if (FAILED(hr = ::SelectCertificateContext(hCertStore, NULL, NULL, FALSE, pfnFilterCallback, NULL, &pCertContext))) { DebugTrace("Error [%#x]: SelectCertificateContext() failed.\n", hr); goto ErrorExit; } }
//
// Create an ICertificate object from the CERT_CONTEXT.
//
if (FAILED(hr = ::CreateCertificateObject(pCertContext, 0, ppICertificate))) { DebugTrace("Error [%#x]: CreateCertificateObject() failed.\n", hr); goto ErrorExit; } CommonExit: //
// Release resources.
//
if (pEnumContext) { ::CertFreeCertificateContext(pEnumContext); } if (pCertContext) { ::CertFreeCertificateContext(pCertContext); } if (hCertStore) { ::CertCloseStore(hCertStore, 0); }
DebugTrace("Leaving SelectCertificate().\n");
return hr;
ErrorExit: //
// Sanity check.
//
ATLASSERT(FAILED(hr));
goto CommonExit; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : ExportCertificatesToStore
Synopsis : Copy all certs from the collections to the specified store.
Parameter: ICertificates2 * pICertificate - Pointer to collection.
HCERTSTORE hCertStore - Store to copy to.
Remark : ------------------------------------------------------------------------------*/
HRESULT ExportCertificatesToStore(ICertificates2 * pICertificates, HCERTSTORE hCertStore) { HRESULT hr = S_OK; CComPtr<ICCertificates> pICCertificates = NULL;
DebugTrace("Entering ExportCertificatesToStore().\n");
//
// Sanity check.
//
ATLASSERT(hCertStore);
//
// Make sure we have something to load.
//
if (pICertificates) { //
// Get ICCertificate interface pointer.
//
if (FAILED(hr = pICertificates->QueryInterface(IID_ICCertificates, (void **) &pICCertificates))) { DebugTrace("Error [%#x]: pICertificates->QueryInterface() failed.\n", hr); goto ErrorExit; }
//
// Get the CERT_CONTEXT.
//
if (FAILED(hr = pICCertificates->_ExportToStore(hCertStore))) { DebugTrace("Error [%#x]: pICCertificates->_ExportToStore() failed.\n", hr); goto ErrorExit; } }
CommonExit:
DebugTrace("Leaving ExportCertificatesToStore().\n");
return hr;
ErrorExit: //
// Sanity check.
//
ATLASSERT(FAILED(hr));
goto CommonExit; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CreateMemoryStoreFromCertificates
Synopsis : Create a memory cert store and copy all certs from the collections to the store.
Parameter: ICertificates2 * pICertificates - Pointer to collection.
HCERTSTORE * phCertStore - Pointer to receive store handle.
Remark : If pICertificate is NULL, then the returned store is still valid nut empty. Also, caller must close the returned store.
------------------------------------------------------------------------------*/
HRESULT CreateMemoryStoreFromCertificates(ICertificates2 * pICertificates, HCERTSTORE * phCertStore) { HRESULT hr = S_OK; HCERTSTORE hCertStore = NULL;
DebugTrace("Entering CreateMemoryStoreFromCertificates().\n");
//
// Sanity check.
//
ATLASSERT(phCertStore);
//
// Initialize.
//
*phCertStore = hCertStore;
//
// Create the memory store.
//
if (!(hCertStore = ::CertOpenStore(CERT_STORE_PROV_MEMORY, CAPICOM_ASN_ENCODING, NULL, CERT_STORE_CREATE_NEW_FLAG, NULL))) { DebugTrace("Error [%#x]: CertOpenStore() failed.\n", hr); goto ErrorExit; }
//
// Now load the collection into the store.
//
if (FAILED(hr = ::ExportCertificatesToStore(pICertificates, hCertStore))) { DebugTrace("Error [%#x]: ExportCertificatesToStore() failed.\n", hr); goto ErrorExit; }
//
// Return store handle to caller.
//
*phCertStore = hCertStore;
CommonExit:
DebugTrace("Leaving CreateMemoryStoreFromCertificates().\n");
return hr;
ErrorExit: //
// Sanity check.
//
ATLASSERT(FAILED(hr));
//
// Free resource.
//
if (hCertStore) { ::CertCloseStore(hCertStore, 0); }
goto CommonExit; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CompareCertAndContainerPublicKey
Synopsis : Compare public key in cert matches the container's key.
Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT to be used to initialize the IPrivateKey object.
BSTR ContainerName - Container name. BSTR ProviderName - Provider name.
DWORD dwProvType - Provider type.
DWORD dwKeySpec - Key spec.
DWORD dwFlags - Provider flags. Remark :
------------------------------------------------------------------------------*/
HRESULT CompareCertAndContainerPublicKey (PCCERT_CONTEXT pCertContext, LPWSTR pwszContainerName, LPWSTR pwszProvName, DWORD dwProvType, DWORD dwKeySpec, DWORD dwFlags) { HRESULT hr = S_OK; HCRYPTPROV hCryptProv = NULL; DWORD cbProvPubKeyInfo = 0; PCERT_PUBLIC_KEY_INFO pProvPubKeyInfo = NULL;
DebugTrace("Entering CompareCertAndContainerPublicKey().\n");
//
// Sanity check.
//
ATLASSERT(pCertContext); ATLASSERT(pwszContainerName); ATLASSERT(pwszProvName);
//
// Acquire provider with key access.
//
if (FAILED(hr = ::AcquireContext(pwszProvName, pwszContainerName, dwProvType, dwFlags, TRUE, &hCryptProv))) { DebugTrace("Error [%#x]: AcquireContext() failed.\n", hr); goto ErrorExit; }
//
// Get provider's public key.
//
if (!::CryptExportPublicKeyInfo(hCryptProv, dwKeySpec, pCertContext->dwCertEncodingType, NULL, &cbProvPubKeyInfo)) { hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptExportPublicKeyInfo() failed.\n", hr); goto ErrorExit; } if (!(pProvPubKeyInfo = (PCERT_PUBLIC_KEY_INFO) ::CoTaskMemAlloc(cbProvPubKeyInfo))) { hr = E_OUTOFMEMORY;
DebugTrace("Error: out of memory.\n"); goto ErrorExit; } if (!::CryptExportPublicKeyInfo(hCryptProv, dwKeySpec, pCertContext->dwCertEncodingType, pProvPubKeyInfo, &cbProvPubKeyInfo)) { hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptExportPublicKeyInfo() failed.\n", hr); goto ErrorExit; }
//
// Compare the keys.
//
if (!::CertComparePublicKeyInfo(pCertContext->dwCertEncodingType, &pCertContext->pCertInfo->SubjectPublicKeyInfo, pProvPubKeyInfo)) { hr = HRESULT_FROM_WIN32(NTE_BAD_PUBLIC_KEY);
DebugTrace("Error [%#x]: CertComparePublicKeyInfo() failed.\n", hr); goto ErrorExit; }
CommonExit: //
// Free resources.
//
if (pProvPubKeyInfo) { ::CoTaskMemFree(pProvPubKeyInfo); }
if (hCryptProv) { ::CryptReleaseContext(hCryptProv, 0); }
DebugTrace("Leaving CompareCertAndContainerPublicKey().\n");
return hr;
ErrorExit: //
// Sanity check.
//
ATLASSERT(FAILED(hr)); goto CommonExit; }
|