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

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
File: PrivateKey.cpp
Content: Implementation of CPrivateKey.
History: 06-15-2001 dsie created
------------------------------------------------------------------------------*/
#include "StdAfx.h"
#include "CAPICOM.h"
#include "PrivateKey.h"
#include "Common.h"
#include "CertHlpr.h"
#include "Settings.h"
////////////////////////////////////////////////////////////////////////////////
//
// Exported functions.
//
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CreatePrivateKeyObject
Synopsis : Create and initialize an CPrivateKey object.
Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT to be used
to initialize the IPrivateKey object.
BOOL bReadOnly - TRUE if read-only, else FALSE.
IPrivateKey ** ppIPrivateKey - Pointer to receive IPrivateKey.
Remark :
------------------------------------------------------------------------------*/
HRESULT CreatePrivateKeyObject (PCCERT_CONTEXT pCertContext,
BOOL bReadOnly,
IPrivateKey ** ppIPrivateKey)
{
HRESULT hr = S_OK;
CComObject<CPrivateKey> * pCPrivateKey = NULL;
DebugTrace("Entering CreatePrivateKeyObject().\n");
//
// Sanity check.
//
ATLASSERT(pCertContext);
ATLASSERT(ppIPrivateKey);
try
{
//
// Create the object. Note that the ref count will still be 0
// after the object is created.
//
if (FAILED(hr = CComObject<CPrivateKey>::CreateInstance(&pCPrivateKey)))
{
DebugTrace("Error [%#x]: CComObject<CPrivateKey>::CreateInstance() failed.\n", hr);
goto ErrorExit;
}
//
// Initialize object.
//
if (FAILED(hr = pCPrivateKey->Init(pCertContext, bReadOnly)))
{
DebugTrace("Error [%#x]: pCPrivateKey->Init() failed.\n", hr);
goto ErrorExit;
}
//
// Return interface pointer to caller.
//
if (FAILED(hr = pCPrivateKey->QueryInterface(ppIPrivateKey)))
{
DebugTrace("Error [%#x]: pCPrivateKey->QueryInterface() failed.\n", hr);
goto ErrorExit;
}
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
CommonExit:
DebugTrace("Leaving CreatePrivateKeyObject().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
if (pCPrivateKey)
{
delete pCPrivateKey;
}
goto CommonExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : GetKeyProvInfo
Synopsis : Return pointer to key prov info of a private key object.
Parameter: IPrivateKey * pIPrivateKey - Pointer to private key object.
PCRYPT_KEY_PROV_INFO * ppKeyProvInfo - Pointer to
PCRYPT_KEY_PROV_INFO.
Remark : Caller must NOT free the structure.
------------------------------------------------------------------------------*/
HRESULT GetKeyProvInfo (IPrivateKey * pIPrivateKey,
PCRYPT_KEY_PROV_INFO * ppKeyProvInfo)
{
HRESULT hr = S_OK;
PCRYPT_KEY_PROV_INFO pKeyProvInfo = NULL;
CComPtr<ICPrivateKey> pICPrivateKey = NULL;
DebugTrace("Entering GetKeyProvInfo().\n");
//
// Sanity check.
//
ATLASSERT(pIPrivateKey);
ATLASSERT(ppKeyProvInfo);
//
// Get ICPrivateKey interface pointer.
//
if (FAILED(hr = pIPrivateKey->QueryInterface(IID_ICPrivateKey, (void **) &pICPrivateKey)))
{
DebugTrace("Error [%#x]: pIPrivateKey->QueryInterface() failed.\n", hr);
goto ErrorExit;
}
//
// Get the PCRYPT_KEY_PROV_INFO.
//
if (FAILED(hr = pICPrivateKey->_GetKeyProvInfo(&pKeyProvInfo)))
{
DebugTrace("Error [%#x]: pICPrivateKey->_GetKeyProvInfo() failed.\n", hr);
goto ErrorExit;
}
*ppKeyProvInfo = pKeyProvInfo;
CommonExit:
DebugTrace("Leaving GetKeyProvInfo().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
goto CommonExit;
}
////////////////////////////////////////////////////////////////////////////////
//
// CPrivateKey
//
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CPrivateKey::get_ContainerName
Synopsis : Return the key container name.
Parameter: BSTR * pVal - Pointer to BSTR to receive the value.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CPrivateKey::get_ContainerName (BSTR * pVal)
{
HRESULT hr = S_OK;
DebugTrace("Entering CPrivateKey::get_ContainerName().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Check parameters.
//
if (NULL == pVal)
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
goto ErrorExit;
}
//
// Make sure we do have private key.
//
if (!m_pKeyProvInfo)
{
hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
goto ErrorExit;
}
//
// Return data to caller.
//
if (!(*pVal = ::SysAllocString(m_pKeyProvInfo->pwszContainerName)))
{
hr = E_OUTOFMEMORY;
DebugTrace("Error [%#x]: SysAllocString() failed.\n", hr);
goto ErrorExit;
}
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CPrivateKey::get_ContainerName().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CPrivateKey::get_UniqueContainerName
Synopsis : Return the unique key container name.
Parameter: BSTR * pVal - Pointer to BSTR to receive the value.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CPrivateKey::get_UniqueContainerName (BSTR * pVal)
{
HRESULT hr = S_OK;
DWORD dwFlags = 0;
DWORD cbData = 0;
LPBYTE pbData = NULL;
HCRYPTPROV hCryptProv = NULL;
CComBSTR bstrName;
DebugTrace("Entering CPrivateKey::get_UniqueContainerName().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Check parameters.
//
if (NULL == pVal)
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
goto ErrorExit;
}
//
// Make sure we do have private key.
//
if (!m_pKeyProvInfo)
{
hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
goto ErrorExit;
}
//
// Set dwFlags for machine keyset.
//
dwFlags = m_pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET;
//
// Get the provider context.
//
if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
m_pKeyProvInfo->pwszContainerName,
m_pKeyProvInfo->dwProvType,
dwFlags,
FALSE,
&hCryptProv)))
{
DebugTrace("Error [%#x]: AcquireContext() failed.\n", hr);
goto ErrorExit;
}
//
// Get the unique container name.
//
if (!::CryptGetProvParam(hCryptProv,
PP_UNIQUE_CONTAINER,
NULL,
&cbData,
0))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptGetProvParam() failed.\n", hr);
goto ErrorExit;
}
if (NULL == (pbData = (LPBYTE) ::CoTaskMemAlloc(cbData)))
{
hr = E_OUTOFMEMORY;
DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
goto ErrorExit;
}
if (!::CryptGetProvParam(hCryptProv,
PP_UNIQUE_CONTAINER,
pbData,
&cbData,
0))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptGetProvParam() failed.\n", hr);
goto ErrorExit;
}
//
// Return data to caller.
//
if (!(bstrName = (LPSTR) pbData))
{
hr = E_OUTOFMEMORY;
DebugTrace("Error [%#x]: bstrName = pbData failed.\n", hr);
goto ErrorExit;
}
*pVal = bstrName.Detach();
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
//
// Free resources.
//
if (hCryptProv)
{
::CryptReleaseContext(hCryptProv, 0);
}
DebugTrace("Leaving CPrivateKey::get_UniqueContainerName().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CPrivateKey::get_ProviderName
Synopsis : Return the provider name.
Parameter: BSTR * pVal - Pointer to BSTR to receive the value.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CPrivateKey::get_ProviderName (BSTR * pVal)
{
HRESULT hr = S_OK;
DebugTrace("Entering CPrivateKey::get_ProviderName().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Check parameters.
//
if (NULL == pVal)
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
goto ErrorExit;
}
//
// Make sure we do have private key.
//
if (!m_pKeyProvInfo)
{
hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
goto ErrorExit;
}
//
// Return data to caller.
//
if (!(*pVal = ::SysAllocString(m_pKeyProvInfo->pwszProvName)))
{
hr = E_OUTOFMEMORY;
DebugTrace("Error [%#x]: SysAllocString() failed.\n", hr);
goto ErrorExit;
}
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CPrivateKey::get_ProviderName().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CPrivateKey::get_ProviderType
Synopsis : Return the provider type.
Parameter: CAPICOM_PROV_TYPE * pVal - Pointer to CAPICOM_PROV_TYPE to receive
the value.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CPrivateKey::get_ProviderType (CAPICOM_PROV_TYPE * pVal)
{
HRESULT hr = S_OK;
DebugTrace("Entering CPrivateKey::get_ProviderType().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Check parameters.
//
if (NULL == pVal)
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
goto ErrorExit;
}
//
// Make sure we do have private key.
//
if (!m_pKeyProvInfo)
{
hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
goto ErrorExit;
}
//
// Return data to caller.
//
*pVal = (CAPICOM_PROV_TYPE) m_pKeyProvInfo->dwProvType;
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CPrivateKey::get_ProviderType().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CPrivateKey::get_KeySpec
Synopsis : Return the Key spec.
Parameter: CAPICOM_KEY_SPEC * pVal - Pointer to CAPICOM_KEY_SPEC to receive
the value.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CPrivateKey::get_KeySpec (CAPICOM_KEY_SPEC * pVal)
{
HRESULT hr = S_OK;
DebugTrace("Entering CPrivateKey::get_KeySpec().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Check parameters.
//
if (NULL == pVal)
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
goto ErrorExit;
}
//
// Make sure we do have private key.
//
if (!m_pKeyProvInfo)
{
hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
goto ErrorExit;
}
//
// Return data to caller.
//
*pVal = (CAPICOM_KEY_SPEC) m_pKeyProvInfo->dwKeySpec;
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CPrivateKey::get_KeySpec().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CPrivateKey::IsAccessible
Synopsis : Check to see if the private key is accessible.
Parameter: VARIANT_BOOL * pVal - Pointer to VARIANT_BOOL to receive the result.
Remark : This may cause UI to be displayed.
------------------------------------------------------------------------------*/
STDMETHODIMP CPrivateKey::IsAccessible (VARIANT_BOOL * pVal)
{
HRESULT hr = S_OK;
DWORD dwFlags = 0;
DWORD dwVerifyContextFlag = 0;
DWORD cbData = 0;
DWORD dwImpType = 0;
HCRYPTPROV hCryptProv = NULL;
DebugTrace("Entering CPrivateKey::IsAccessible().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Check parameters.
//
if (NULL == pVal)
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
goto ErrorExit;
}
//
// Initialize.
//
*pVal = VARIANT_FALSE;
//
// Make sure we do have private key.
//
if (!m_pKeyProvInfo)
{
hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
goto ErrorExit;
}
//
// Set dwFlags for machine keyset.
//
dwFlags = m_pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET;
//
// If Win2K and above, use CRYPT_VERIFYCONTEXT flag.
//
if (IsWin2KAndAbove())
{
dwVerifyContextFlag = CRYPT_VERIFYCONTEXT;
}
//
// Get the provider context with no key access.
//
if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
NULL,
m_pKeyProvInfo->dwProvType,
dwVerifyContextFlag | dwFlags,
FALSE,
&hCryptProv)))
{
DebugTrace("Error [%#x]: AcquireContext(CRYPT_VERIFYCONTEXT) failed.\n", hr);
goto ErrorExit;
}
//
// Get provider param.
//
cbData = sizeof(dwImpType);
if (!::CryptGetProvParam(hCryptProv, PP_IMPTYPE, (PBYTE) &dwImpType, &cbData, 0))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptGetProvParam(PP_IMPTYPE) failed.\n", hr);
goto ErrorExit;
}
//
// Release verify context.
//
::ReleaseContext(hCryptProv), hCryptProv = NULL;
//
// Check implementation type.
//
if (dwImpType & CRYPT_IMPL_HARDWARE)
{
//
// We do not support this for hardware key in down level platforms,
// because CRYPT_SILENT flag is not available.
//
if (!IsWin2KAndAbove())
{
hr = CAPICOM_E_NOT_SUPPORTED;
DebugTrace("Error [%#x]: IsAccessible() for hardware key is not supported.\n", hr);
goto ErrorExit;
}
//
// Reacquire context with silent flag.
//
if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
m_pKeyProvInfo->pwszContainerName,
m_pKeyProvInfo->dwProvType,
CRYPT_SILENT | dwFlags,
FALSE,
&hCryptProv)))
{
DebugTrace("Info [%#x]: AcquireContext(CRYPT_SILENT) failed, probably smart card not inserted.\n", hr);
hr = S_OK;
goto UnlockExit;
}
}
else
{
//
// Reacquire context with private key access.
//
if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
m_pKeyProvInfo->pwszContainerName,
m_pKeyProvInfo->dwProvType,
dwFlags,
FALSE,
&hCryptProv)))
{
DebugTrace("Info [%#x]: AcquireContext() failed, probably access denied.\n", hr);
hr = S_OK;
goto UnlockExit;
}
}
//
// Return result to caller.
//
*pVal = VARIANT_TRUE;
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
//
// Free resources.
//
if (hCryptProv)
{
::ReleaseContext(hCryptProv);
}
DebugTrace("Leaving CPrivateKey::IsAccessible().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CPrivateKey::IsProtected
Synopsis : Check to see if the private key is user protected.
Parameter: VARIANT_BOOL * pVal - Pointer to VARIANT_BOOL to receive the result.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CPrivateKey::IsProtected (VARIANT_BOOL * pVal)
{
HRESULT hr = S_OK;
DWORD dwFlags = 0;
DWORD dwVerifyContextFlag = 0;
DWORD cbData = 0;
DWORD dwImpType = 0;
HCRYPTPROV hCryptProv = NULL;
DebugTrace("Entering CPrivateKey::IsProtected().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Check parameters.
//
if (NULL == pVal)
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
goto ErrorExit;
}
//
// Initialize.
//
*pVal = VARIANT_FALSE;
//
// Make sure we do have private key.
//
if (!m_pKeyProvInfo)
{
hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
goto ErrorExit;
}
//
// Set dwFlags for machine keyset.
//
dwFlags = m_pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET;
//
// If Win2K and above, use CRYPT_VERIFYCONTEXT flag.
//
if (IsWin2KAndAbove())
{
dwVerifyContextFlag = CRYPT_VERIFYCONTEXT;
}
//
// Get the provider context with no key access.
//
if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
NULL,
m_pKeyProvInfo->dwProvType,
dwVerifyContextFlag | dwFlags,
FALSE,
&hCryptProv)))
{
DebugTrace("Error [%#x]: AcquireContext(CRYPT_VERIFYCONTEXT) failed.\n", hr);
goto ErrorExit;
}
//
// Get provider param.
//
cbData = sizeof(dwImpType);
if (!::CryptGetProvParam(hCryptProv, PP_IMPTYPE, (PBYTE) &dwImpType, &cbData, 0))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptGetProvParam(PP_IMPTYPE) failed.\n", hr);
goto ErrorExit;
}
//
// Assume hardware key is protected.
//
if (dwImpType & CRYPT_IMPL_HARDWARE)
{
//
// Return result to caller.
//
*pVal = VARIANT_TRUE;
}
else
{
//
// We do not support this for software key in down level platforms,
// because CRYPT_SILENT flag is not available.
//
if (!IsWin2KAndAbove())
{
hr = CAPICOM_E_NOT_SUPPORTED;
DebugTrace("Error [%#x]: IsProtected() for software key is not supported.\n", hr);
goto ErrorExit;
}
//
// Reacquire context with key access (to make sure key exists).
//
::ReleaseContext(hCryptProv), hCryptProv = NULL;
if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
m_pKeyProvInfo->pwszContainerName,
m_pKeyProvInfo->dwProvType,
dwFlags,
FALSE,
&hCryptProv)))
{
DebugTrace("Error [%#x]: AcquireContext() failed.\n", hr);
goto ErrorExit;
}
//
// Reacquire context with silent flag.
//
::ReleaseContext(hCryptProv), hCryptProv = NULL;
if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
m_pKeyProvInfo->pwszContainerName,
m_pKeyProvInfo->dwProvType,
CRYPT_SILENT | dwFlags,
FALSE,
&hCryptProv)))
{
//
// CSP refuses to open the container, so can assume it is user protected.
//
*pVal = VARIANT_TRUE;
DebugTrace("Info [%#x]: AcquireContext(CRYPT_SILENT) failed, assume user protected.\n", hr);
//
// Successful.
//
hr = S_OK;
}
}
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
//
// Free resources.
//
if (hCryptProv)
{
::ReleaseContext(hCryptProv);
}
DebugTrace("Leaving CPrivateKey::IsProtected().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CPrivateKey::IsExportable
Synopsis : Check to see if the private key is exportable.
Parameter: VARIANT_BOOL * pVal - Pointer to VARIANT_BOOL to receive the result.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CPrivateKey::IsExportable (VARIANT_BOOL * pVal)
{
HRESULT hr = S_OK;
DWORD dwFlags = 0;
DWORD dwVerifyContextFlag = 0;
DWORD cbData = 0;
DWORD dwImpType = 0;
DWORD dwPermissions = 0;
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hCryptKey = NULL;
DebugTrace("Entering CPrivateKey::IsExportable().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Check parameters.
//
if (NULL == pVal)
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
goto ErrorExit;
}
//
// Initialize.
//
*pVal = VARIANT_FALSE;
//
// Make sure we do have private key.
//
if (!m_pKeyProvInfo)
{
hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
goto ErrorExit;
}
//
// Set dwFlags for machine keyset.
//
dwFlags = m_pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET;
//
// If Win2K and above, use CRYPT_VERIFYCONTEXT flag.
//
if (IsWin2KAndAbove())
{
dwVerifyContextFlag = CRYPT_VERIFYCONTEXT;
}
//
// Get the provider context with no key access.
//
if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
NULL,
m_pKeyProvInfo->dwProvType,
dwVerifyContextFlag | dwFlags,
FALSE,
&hCryptProv)))
{
DebugTrace("Error [%#x]: AcquireContext(CRYPT_VERIFYCONTEXT) failed.\n", hr);
goto ErrorExit;
}
//
// Get provider param.
//
cbData = sizeof(dwImpType);
if (!::CryptGetProvParam(hCryptProv, PP_IMPTYPE, (PBYTE) &dwImpType, &cbData, 0))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptGetProvParam(PP_IMPTYPE) failed.\n", hr);
goto ErrorExit;
}
//
// Assume hardware key is not exportable.
//
if (!(dwImpType & CRYPT_IMPL_HARDWARE))
{
//
// We do not support this for software key in down level platforms,
// because KP_PERMISSIONS flag is not available.
//
if (!IsWin2KAndAbove())
{
hr = CAPICOM_E_NOT_SUPPORTED;
DebugTrace("Error [%#x]: IsExportabled() for software key is not supported.\n", hr);
goto ErrorExit;
}
//
// Reacquire context with private key access.
//
::ReleaseContext(hCryptProv), hCryptProv = NULL;
if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
m_pKeyProvInfo->pwszContainerName,
m_pKeyProvInfo->dwProvType,
dwFlags,
FALSE,
&hCryptProv)))
{
DebugTrace("Error [%#x]: AcquireContext() failed.\n", hr);
goto ErrorExit;
}
//
// Get key handle.
//
if (!::CryptGetUserKey(hCryptProv, m_pKeyProvInfo->dwKeySpec, &hCryptKey))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptGetUserKey() failed.\n", hr);
goto ErrorExit;
}
//
// Get key param.
//
cbData = sizeof(dwPermissions);
if (!::CryptGetKeyParam(hCryptKey, KP_PERMISSIONS, (PBYTE) &dwPermissions, &cbData, 0))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptGetKeyParam(KP_PERMISSIONS) failed.\n", hr);
goto ErrorExit;
}
//
// Return result to caller.
//
if (dwPermissions & CRYPT_EXPORT)
{
*pVal = VARIANT_TRUE;
}
}
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
//
// Free resources.
//
if (hCryptKey)
{
::CryptDestroyKey(hCryptKey);
}
if (hCryptProv)
{
::ReleaseContext(hCryptProv);
}
DebugTrace("Leaving CPrivateKey::IsExportable().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CPrivateKey::IsRemovable
Synopsis : Check to see if the private key is stored in removable device.
Parameter: VARIANT_BOOL * pVal - Pointer to VARIANT_BOOL to receive the result.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CPrivateKey::IsRemovable (VARIANT_BOOL * pVal)
{
HRESULT hr = S_OK;
DWORD dwFlags = 0;
DWORD dwVerifyContextFlag = 0;
DWORD cbData = 0;
DWORD dwImpType = 0;
HCRYPTPROV hCryptProv = NULL;
DebugTrace("Entering CPrivateKey::IsRemovable().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Check parameters.
//
if (NULL == pVal)
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
goto ErrorExit;
}
//
// Initialize.
//
*pVal = VARIANT_FALSE;
//
// Make sure we do have private key.
//
if (!m_pKeyProvInfo)
{
hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
goto ErrorExit;
}
//
// Set dwFlags for machine keyset.
//
dwFlags = m_pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET;
//
// If Win2K and above, use CRYPT_VERIFYCONTEXT flag.
//
if (IsWin2KAndAbove())
{
dwVerifyContextFlag = CRYPT_VERIFYCONTEXT;
}
//
// Get the provider context with no key access.
//
if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
NULL,
m_pKeyProvInfo->dwProvType,
dwVerifyContextFlag | dwFlags,
FALSE,
&hCryptProv)))
{
DebugTrace("Error [%#x]: AcquireContext(CRYPT_VERIFYCONTEXT) failed.\n", hr);
goto ErrorExit;
}
//
// Get provider param.
//
cbData = sizeof(dwImpType);
if (!::CryptGetProvParam(hCryptProv, PP_IMPTYPE, (PBYTE) &dwImpType, &cbData, 0))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptGetProvParam(PP_IMPTYPE) failed.\n", hr);
goto ErrorExit;
}
//
// Return result to caller.
//
if (dwImpType & CRYPT_IMPL_REMOVABLE)
{
*pVal = VARIANT_TRUE;
}
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
//
// Free resources.
//
if (hCryptProv)
{
::ReleaseContext(hCryptProv);
}
DebugTrace("Leaving CPrivateKey::IsRemovable().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CPrivateKey::IsMachineKeyset
Synopsis : Check to see if the private key is stored in machine key container.
Parameter: VARIANT_BOOL * pVal - Pointer to VARIANT_BOOL to receive the result.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CPrivateKey::IsMachineKeyset (VARIANT_BOOL * pVal)
{
HRESULT hr = S_OK;
DebugTrace("Entering CPrivateKey::IsMachineKeyset().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Check parameters.
//
if (NULL == pVal)
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
goto ErrorExit;
}
//
// Initialize.
//
*pVal = VARIANT_FALSE;
//
// Make sure we do have private key.
//
if (!m_pKeyProvInfo)
{
hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
goto ErrorExit;
}
//
// Return result to caller.
//
if (m_pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET)
{
*pVal = VARIANT_TRUE;
}
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CPrivateKey::IsMachineKeyset().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CPrivateKey::IsHardwareDevice
Synopsis : Check to see if the private key is stored in hardware device.
Parameter: VARIANT_BOOL * pVal - Pointer to VARIANT_BOOL to receive the result.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CPrivateKey::IsHardwareDevice (VARIANT_BOOL * pVal)
{
HRESULT hr = S_OK;
DWORD dwFlags = 0;
DWORD dwVerifyContextFlag = 0;
DWORD cbData = 0;
DWORD dwImpType = 0;
HCRYPTPROV hCryptProv = NULL;
DebugTrace("Entering CPrivateKey::IsHardwareDevice().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Check parameters.
//
if (NULL == pVal)
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
goto ErrorExit;
}
//
// Initialize.
//
*pVal = VARIANT_FALSE;
//
// Make sure we do have private key.
//
if (!m_pKeyProvInfo)
{
hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
goto ErrorExit;
}
//
// Set dwFlags for machine keyset.
//
dwFlags = m_pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET;
//
// If Win2K and above, use CRYPT_VERIFYCONTEXT flag.
//
if (IsWin2KAndAbove())
{
dwVerifyContextFlag = CRYPT_VERIFYCONTEXT;
}
//
// Get the provider context with no key access.
//
if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
NULL,
m_pKeyProvInfo->dwProvType,
dwVerifyContextFlag | dwFlags,
FALSE,
&hCryptProv)))
{
DebugTrace("Error [%#x]: AcquireContext(CRYPT_VERIFYCONTEXT) failed.\n", hr);
goto ErrorExit;
}
//
// Get provider param.
//
cbData = sizeof(dwImpType);
if (!::CryptGetProvParam(hCryptProv, PP_IMPTYPE, (PBYTE) &dwImpType, &cbData, 0))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptGetProvParam(PP_IMPTYPE) failed.\n", hr);
goto ErrorExit;
}
//
// Return result to caller.
//
if (dwImpType & CRYPT_IMPL_HARDWARE)
{
*pVal = VARIANT_TRUE;
}
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
//
// Free resources.
//
if (hCryptProv)
{
::ReleaseContext(hCryptProv);
}
DebugTrace("Leaving CPrivateKey::IsHardwareDevice().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CPrivateKey::Open
Synopsis : Open an existing key container.
Parameter: BSTR ContainerName - Container name.
BSTR ProviderName - Provider name.
CAPICOM_PROV_TYPE ProviderType - Provider type.
CAPICOM_KEY_SPEC KeySpec - Key spec.
CAPICOM_STORE_LOCATION StoreLocation - Machine or user.
VARIANT_BOOL bCheckExistence - True to check if the specified
container and key actually exists.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CPrivateKey::Open (BSTR ContainerName,
BSTR ProviderName,
CAPICOM_PROV_TYPE ProviderType,
CAPICOM_KEY_SPEC KeySpec,
CAPICOM_STORE_LOCATION StoreLocation,
VARIANT_BOOL bCheckExistence)
{
HRESULT hr = S_OK;
DWORD dwFlags = 0;
DWORD dwSerializedLength = 0;
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hCryptKey = NULL;
PCRYPT_KEY_PROV_INFO pKeyProvInfo = NULL;;
DebugTrace("Entering CPrivateKey::Open().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Not allowed if read-only.
//
if (m_bReadOnly)
{
hr = CAPICOM_E_NOT_ALLOWED;
DebugTrace("Error [%#x]: Opening private key from WEB script is not allowed.\n", hr);
goto ErrorExit;
}
//
// Make sure paremeters are valid.
//
switch (StoreLocation)
{
case CAPICOM_LOCAL_MACHINE_STORE:
{
dwFlags = CRYPT_MACHINE_KEYSET;
break;
}
case CAPICOM_CURRENT_USER_STORE:
{
break;
}
default:
{
hr = E_INVALIDARG;
DebugTrace("Error: invalid store location (%#x).\n", StoreLocation);
goto ErrorExit;
}
}
if (KeySpec != CAPICOM_KEY_SPEC_KEYEXCHANGE && KeySpec != CAPICOM_KEY_SPEC_SIGNATURE)
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: invalid key spec (%#x).\n", hr, KeySpec);
goto ErrorExit;
}
//
// Make sure the container and key exists, if requested.
//
if (bCheckExistence)
{
if (FAILED(hr = ::AcquireContext((LPWSTR) ProviderName,
(LPWSTR) ContainerName,
ProviderType,
dwFlags,
FALSE,
&hCryptProv)))
{
DebugTrace("Error [%#x]: AcquireContext() failed.\n", hr);
goto ErrorExit;
}
if (!::CryptGetUserKey(hCryptProv, KeySpec, &hCryptKey))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptGetUserKey() failed.\n", hr);
goto ErrorExit;
}
}
//
// Allocate memory to serialize the structure.
//
dwSerializedLength = sizeof(CRYPT_KEY_PROV_INFO) +
((::SysStringLen(ContainerName) + 1) * sizeof(WCHAR)) +
((::SysStringLen(ProviderName) + 1) * sizeof(WCHAR));
if (!(pKeyProvInfo = (PCRYPT_KEY_PROV_INFO) ::CoTaskMemAlloc(dwSerializedLength)))
{
hr = E_OUTOFMEMORY;
DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
goto ErrorExit;
}
//
// Now serialize it.
//
::ZeroMemory((LPVOID) pKeyProvInfo, dwSerializedLength);
pKeyProvInfo->pwszContainerName = (LPWSTR) ((LPBYTE) pKeyProvInfo + sizeof(CRYPT_KEY_PROV_INFO));
pKeyProvInfo->pwszProvName = (LPWSTR) ((LPBYTE) pKeyProvInfo->pwszContainerName +
((::SysStringLen(ContainerName) + 1) * sizeof(WCHAR)));
pKeyProvInfo->dwProvType = ProviderType;
pKeyProvInfo->dwKeySpec = KeySpec;
pKeyProvInfo->dwFlags = dwFlags;
::wcscpy(pKeyProvInfo->pwszContainerName, ContainerName);
::wcscpy(pKeyProvInfo->pwszProvName, ProviderName);
//
// Update states.
//
if (m_pKeyProvInfo)
{
::CoTaskMemFree((LPVOID) m_pKeyProvInfo);
}
m_cbKeyProvInfo = dwSerializedLength;
m_pKeyProvInfo = pKeyProvInfo;
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Free resources.
//
if (hCryptKey)
{
::CryptDestroyKey(hCryptKey);
}
if (hCryptProv)
{
::ReleaseContext(hCryptProv);
}
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CPrivateKey::Open().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
//
// Free resources.
//
if (pKeyProvInfo)
{
::CoTaskMemFree(pKeyProvInfo);
}
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CPrivateKey::Delete
Synopsis : Delete the existing key container.
Parameter: None.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CPrivateKey::Delete ()
{
HRESULT hr = S_OK;
HCRYPTPROV hCryptProv = NULL;
DebugTrace("Entering CPrivateKey::Delete().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Not allowed if read-only.
//
if (m_bReadOnly)
{
hr = CAPICOM_E_NOT_ALLOWED;
DebugTrace("Error [%#x]: Deleting private key from WEB script is not allowed.\n", hr);
goto ErrorExit;
}
//
// Make sure we do have private key.
//
if (!m_pKeyProvInfo)
{
hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
goto ErrorExit;
}
//
// Delete it!
//
if (FAILED(hr = ::AcquireContext(m_pKeyProvInfo->pwszProvName,
m_pKeyProvInfo->pwszContainerName,
m_pKeyProvInfo->dwProvType,
CRYPT_DELETEKEYSET | (m_pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET),
FALSE,
&hCryptProv)))
{
DebugTrace("Error [%#x]: AcquireContext(CRYPT_DELETEKEYSET) failed.\n", hr);
goto ErrorExit;
}
//
// Update states.
//
::CoTaskMemFree((LPVOID) m_pKeyProvInfo);
m_cbKeyProvInfo = 0;
m_pKeyProvInfo = NULL;
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CPrivateKey::Delete().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
////////////////////////////////////////////////////////////////////////////////
//
// Custom interfaces.
//
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CPrivateKey::_GetKeyProvInfo
Synopsis : Return pointer to key prov info of a private key object.
Parameter: PCRYPT_KEY_PROV_INFO * ppKeyProvInfo - Pointer to
PCRYPT_KEY_PROV_INFO.
Remark : Caller must free the structure with CoTaskMemFree().
------------------------------------------------------------------------------*/
STDMETHODIMP CPrivateKey::_GetKeyProvInfo (PCRYPT_KEY_PROV_INFO * ppKeyProvInfo)
{
HRESULT hr = S_OK;
PCRYPT_KEY_PROV_INFO pKeyProvInfo = NULL;
DebugTrace("Entering CPrivateKey::_GetKeyProvInfo().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Make sure we do have private key.
//
if (!m_pKeyProvInfo)
{
hr = CAPICOM_E_PRIVATE_KEY_NOT_INITIALIZED;
DebugTrace("Error [%#x]: private key object has not been initialized.\n", hr);
goto ErrorExit;
}
//
// Allocate memory.
//
if (!(pKeyProvInfo = (PCRYPT_KEY_PROV_INFO) ::CoTaskMemAlloc(m_cbKeyProvInfo)))
{
hr = E_OUTOFMEMORY;
DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
goto ErrorExit;
}
//
// copy structure over.
//
::CopyMemory((LPVOID) pKeyProvInfo, (LPVOID) m_pKeyProvInfo, (SIZE_T) m_cbKeyProvInfo);
//
// and return the structure to caller.
//
*ppKeyProvInfo = pKeyProvInfo;
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CPrivateKey::_GetKeyProvInfo().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
//
// Free resources.
//
if (pKeyProvInfo)
{
::CoTaskMemFree((LPVOID) pKeyProvInfo);
}
ReportError(hr);
goto UnlockExit;
}
////////////////////////////////////////////////////////////////////////////////
//
// Private methods.
//
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CPrivateKey::Init
Synopsis : Initialize the object.
Parameter: PCCERT_CONTEXT pCertContext - Pointer to PCCERT_CONTEXT to be used
to initialize the object.
BOOL bReadOnly - TRUE if read-only, else FALSE.
Remark : This method is not part of the COM interface (it is a normal C++
member function). We need it to initialize the object created
internally by us.
Since it is only a normal C++ member function, this function can
only be called from a C++ class pointer, not an interface pointer.
------------------------------------------------------------------------------*/
STDMETHODIMP CPrivateKey::Init (PCCERT_CONTEXT pCertContext, BOOL bReadOnly)
{
HRESULT hr = S_OK;
DWORD cbData = 0;
PCRYPT_KEY_PROV_INFO pKeyProvInfo = NULL;
DebugTrace("Entering CPrivateKey::Init().\n");
//
// Sanity check.
//
ATLASSERT(pCertContext);
//
// Get key provider info property.
//
if (!::CertGetCertificateContextProperty(pCertContext,
CERT_KEY_PROV_INFO_PROP_ID,
NULL,
&cbData))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Info [%#x]: CertGetCertificateContextProperty() failed.\n", hr);
goto ErrorExit;
}
if (!(pKeyProvInfo = (PCRYPT_KEY_PROV_INFO) ::CoTaskMemAlloc(cbData)))
{
hr = E_OUTOFMEMORY;
DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
goto ErrorExit;
}
if (!::CertGetCertificateContextProperty(pCertContext,
CERT_KEY_PROV_INFO_PROP_ID,
pKeyProvInfo,
&cbData))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Info [%#x]: CertGetCertificateContextProperty() failed.\n", hr);
goto ErrorExit;
}
//
// Update states.
//
if (m_pKeyProvInfo)
{
::CoTaskMemFree((LPVOID) m_pKeyProvInfo);
}
m_bReadOnly = bReadOnly;
m_cbKeyProvInfo = cbData;
m_pKeyProvInfo = pKeyProvInfo;
CommonExit:
DebugTrace("Leaving CPrivateKey::Init().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
//
// Free resources.
//
if (pKeyProvInfo)
{
::CoTaskMemFree((LPVOID) pKeyProvInfo);
}
goto CommonExit;
}