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.
 
 
 
 
 
 

1048 lines
30 KiB

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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;
}