1539 lines
40 KiB
C++
1539 lines
40 KiB
C++
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
|
|
|
|
File: Common.cpp
|
|
|
|
Content: Common routines.
|
|
|
|
History: 11-15-99 dsie created
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
//
|
|
// Turn off:
|
|
//
|
|
// - Unreferenced formal parameter warning.
|
|
// - Assignment within conditional expression warning.
|
|
//
|
|
#pragma warning (disable: 4100)
|
|
#pragma warning (disable: 4706)
|
|
|
|
#include "stdafx.h"
|
|
#include "CAPICOM.h"
|
|
#include "Common.h"
|
|
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : GetOSVersion
|
|
|
|
Synopsis : Get the current OS platform/version.
|
|
|
|
Parameter: POSVERSION pOSVersion - Pointer to OSVERSION to receive result.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT GetOSVersion (POSVERSION pOSVersion)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
OSVERSIONINFO OSVersionInfo;
|
|
|
|
DebugTrace("Entering GetOSVersion().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(pOSVersion);
|
|
|
|
//
|
|
// Initialize OSVERSIONINFO struct.
|
|
//
|
|
OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
|
|
|
|
//
|
|
// GetVersionEx() will fail on Windows 3.x or below NT 3.5 systems.
|
|
//
|
|
if (!::GetVersionEx(&OSVersionInfo))
|
|
{
|
|
hr = ::GetLastError();
|
|
|
|
DebugTrace("Error [%#x]: GetVersionEx() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Check platform ID.
|
|
//
|
|
switch (OSVersionInfo.dwPlatformId)
|
|
{
|
|
case VER_PLATFORM_WIN32_WINDOWS:
|
|
{
|
|
//
|
|
// Win9x.
|
|
//
|
|
*pOSVersion = WIN_9X;
|
|
break;
|
|
}
|
|
|
|
case VER_PLATFORM_WIN32_NT:
|
|
{
|
|
if (4 == OSVersionInfo.dwMajorVersion)
|
|
{
|
|
//
|
|
// NT 4.
|
|
//
|
|
*pOSVersion = WIN_NT4;
|
|
break;
|
|
}
|
|
else if (5 <= OSVersionInfo.dwMajorVersion)
|
|
{
|
|
//
|
|
// Win2K and above.
|
|
//
|
|
*pOSVersion = WIN_NT5;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Must be NT 3.5.
|
|
//
|
|
|
|
//
|
|
// !!! WARNING !!! Dropping thru to default case.
|
|
//
|
|
}
|
|
|
|
default:
|
|
{
|
|
hr = CAPICOM_E_NOT_SUPPORTED;
|
|
|
|
DebugTrace("Error: unsupported OS (Platform = %d, Major = %d, Minor = %d).\n",
|
|
OSVersionInfo.dwPlatformId, OSVersionInfo.dwMajorVersion, OSVersionInfo.dwMinorVersion);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
CommonExit:
|
|
|
|
DebugTrace("Leaving GetOSVersion().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
goto CommonExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : EncodeObject
|
|
|
|
Synopsis : Allocate memory and encode an ASN.1 object using CAPI
|
|
CryptEncodeObject() API.
|
|
|
|
Parameter: LPCSRT pszStructType - see MSDN document for possible
|
|
types.
|
|
LPVOID pbData - Pointer to data to be encoded
|
|
(data type must match
|
|
pszStrucType).
|
|
CRYPT_DATA_BLOB * pEncodedBlob - Pointer to CRYPT_DATA_BLOB to
|
|
receive the encoded length and
|
|
data.
|
|
|
|
Remark : No parameter check is done.
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT EncodeObject (LPCSTR pszStructType,
|
|
LPVOID pbData,
|
|
CRYPT_DATA_BLOB * pEncodedBlob)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD cbEncoded = 0;
|
|
BYTE * pbEncoded = NULL;
|
|
|
|
DebugTrace("Entering EncodeObject().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(NULL != pszStructType);
|
|
ATLASSERT(NULL != pbData);
|
|
ATLASSERT(NULL != pEncodedBlob);
|
|
|
|
//
|
|
// Intialize return value.
|
|
//
|
|
pEncodedBlob->cbData = 0;
|
|
pEncodedBlob->pbData = NULL;
|
|
|
|
//
|
|
// Determine encoded length required.
|
|
//
|
|
if (!::CryptEncodeObject(CAPICOM_ASN_ENCODING,
|
|
pszStructType,
|
|
(const void *) pbData,
|
|
NULL,
|
|
&cbEncoded))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Unable to determine object encoded length [0x%x]: CryptEncodeObject() failed.\n", hr);
|
|
goto CommonExit;
|
|
}
|
|
|
|
//
|
|
// Allocate memory for encoded blob.
|
|
//
|
|
if (!(pbEncoded = (BYTE *) ::CoTaskMemAlloc(cbEncoded)))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
DebugTrace("Out of memory: CoTaskMemAlloc(cbEncoded) failed.\n");
|
|
goto CommonExit;
|
|
}
|
|
|
|
//
|
|
// Encode.
|
|
//
|
|
if (!::CryptEncodeObject(CAPICOM_ASN_ENCODING,
|
|
pszStructType,
|
|
(const void *) pbData,
|
|
pbEncoded,
|
|
&cbEncoded))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Unable to encode object [0x%x]: CryptEncodeObject() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Return value.
|
|
//
|
|
pEncodedBlob->cbData = cbEncoded;
|
|
pEncodedBlob->pbData = pbEncoded;
|
|
|
|
CommonExit:
|
|
|
|
DebugTrace("Leaving EncodeObject().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
//
|
|
// Free resources.
|
|
//
|
|
if (pbEncoded)
|
|
{
|
|
::CoTaskMemFree((LPVOID) pbEncoded);
|
|
}
|
|
|
|
goto CommonExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : DecodeObject
|
|
|
|
Synopsis : Allocate memory and decode an ASN.1 object using CAPI
|
|
CryptDecodeObject() API.
|
|
|
|
Parameter: LPCSRT pszStructType - see MSDN document for possible
|
|
types.
|
|
BYTE * pbEncoded - Pointer to data to be decoded
|
|
(data type must match
|
|
pszStrucType).
|
|
DWORD cbEncoded - Size of encoded data.
|
|
CRYPT_DATA_BLOB * pDecodedBlob - Pointer to CRYPT_DATA_BLOB to
|
|
receive the decoded length and
|
|
data.
|
|
Remark : No parameter check is done.
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT DecodeObject (LPCSTR pszStructType,
|
|
BYTE * pbEncoded,
|
|
DWORD cbEncoded,
|
|
CRYPT_DATA_BLOB * pDecodedBlob)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD cbDecoded = 0;
|
|
BYTE * pbDecoded = NULL;
|
|
|
|
DebugTrace("Entering DecodeObject().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(pszStructType);
|
|
ATLASSERT(pbEncoded);
|
|
ATLASSERT(pDecodedBlob);
|
|
|
|
//
|
|
// Intialize return value.
|
|
//
|
|
pDecodedBlob->cbData = 0;
|
|
pDecodedBlob->pbData = NULL;
|
|
|
|
//
|
|
// Determine encoded length required.
|
|
//
|
|
if (!::CryptDecodeObject(CAPICOM_ASN_ENCODING,
|
|
pszStructType,
|
|
(const BYTE *) pbEncoded,
|
|
cbEncoded,
|
|
0,
|
|
NULL,
|
|
&cbDecoded))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CryptDecodeObject() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Allocate memory for decoded blob.
|
|
//
|
|
if (!(pbDecoded = (BYTE *) ::CoTaskMemAlloc(cbDecoded)))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
DebugTrace("Error: out of memory.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Decode.
|
|
//
|
|
if (!::CryptDecodeObject(CAPICOM_ASN_ENCODING,
|
|
pszStructType,
|
|
(const BYTE *) pbEncoded,
|
|
cbEncoded,
|
|
0,
|
|
pbDecoded,
|
|
&cbDecoded))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CryptDecodeObject() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Return value.
|
|
//
|
|
pDecodedBlob->cbData = cbDecoded;
|
|
pDecodedBlob->pbData = pbDecoded;
|
|
|
|
CommonExit:
|
|
|
|
DebugTrace("Leaving DecodeObject().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
//
|
|
// Free resources.
|
|
//
|
|
if (pbDecoded)
|
|
{
|
|
::CoTaskMemFree((LPVOID) pbDecoded);
|
|
}
|
|
|
|
goto CommonExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : GetMsgParam
|
|
|
|
Synopsis : Allocate memory and retrieve requested message parameter using
|
|
CryptGetMsgParam() API.
|
|
|
|
Parameter: HCRYPTMSG hMsg - Message handler.
|
|
DWORD dwMsgType - Message param type to retrieve.
|
|
DWORD dwIndex - Index (should be 0 most of the time).
|
|
void ** ppvData - Pointer to receive buffer.
|
|
DWORD * pcbData - Size of buffer.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT GetMsgParam (HCRYPTMSG hMsg,
|
|
DWORD dwMsgType,
|
|
DWORD dwIndex,
|
|
void ** ppvData,
|
|
DWORD * pcbData)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD cbData = 0;
|
|
void * pvData = NULL;
|
|
|
|
DebugTrace("Entering GetMsgParam().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(ppvData);
|
|
ATLASSERT(pcbData);
|
|
|
|
//
|
|
// Determine data buffer size.
|
|
//
|
|
if (!::CryptMsgGetParam(hMsg,
|
|
dwMsgType,
|
|
dwIndex,
|
|
NULL,
|
|
&cbData))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CryptMsgGetParam() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Allocate memory for buffer.
|
|
//
|
|
if (!(pvData = (void *) ::CoTaskMemAlloc(cbData)))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
DebugTrace("Error: out of memory.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Now get the data.
|
|
//
|
|
if (!::CryptMsgGetParam(hMsg,
|
|
dwMsgType,
|
|
dwIndex,
|
|
pvData,
|
|
&cbData))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CryptMsgGetParam() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Return msg param to caller.
|
|
//
|
|
*ppvData = pvData;
|
|
*pcbData = cbData;
|
|
|
|
CommonExit:
|
|
|
|
DebugTrace("Leaving GetMsgParam().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
//
|
|
// Free resources.
|
|
//
|
|
if (pvData)
|
|
{
|
|
::CoTaskMemFree(pvData);
|
|
}
|
|
|
|
goto CommonExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : GetKeyParam
|
|
|
|
Synopsis : Allocate memory and retrieve requested key parameter using
|
|
CryptGetKeyParam() API.
|
|
|
|
Parameter: HCRYPTKEY hKey - Key handler.
|
|
DWORD dwParam - Key parameter query.
|
|
BYTE ** ppbData - Pointer to receive buffer.
|
|
DWORD * pcbData - Size of buffer.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT GetKeyParam (HCRYPTKEY hKey,
|
|
DWORD dwParam,
|
|
BYTE ** ppbData,
|
|
DWORD * pcbData)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD cbData = 0;
|
|
BYTE * pbData = NULL;
|
|
|
|
DebugTrace("Entering GetKeyParam().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(ppbData);
|
|
ATLASSERT(pcbData);
|
|
|
|
//
|
|
// Determine data buffer size.
|
|
//
|
|
if (!::CryptGetKeyParam(hKey,
|
|
dwParam,
|
|
NULL,
|
|
&cbData,
|
|
0))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CryptGetKeyParam() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Allocate memory for buffer.
|
|
//
|
|
if (!(pbData = (BYTE *) ::CoTaskMemAlloc(cbData)))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
DebugTrace("Error: out of memory.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Now get the data.
|
|
//
|
|
if (!::CryptGetKeyParam(hKey,
|
|
dwParam,
|
|
pbData,
|
|
&cbData,
|
|
0))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CryptGetKeyParam() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Return key param to caller.
|
|
//
|
|
*ppbData = pbData;
|
|
*pcbData = cbData;
|
|
|
|
CommonExit:
|
|
|
|
DebugTrace("Leaving GetKeyParam().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
//
|
|
// Free resources.
|
|
//
|
|
if (pbData)
|
|
{
|
|
::CoTaskMemFree(pbData);
|
|
}
|
|
|
|
goto CommonExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : FindSignerCertInMessage
|
|
|
|
Synopsis : Find the signer's cert in the bag of certs of the message for the
|
|
specified signer.
|
|
|
|
Parameter: HCRYPTMSG hMsg - Message handle.
|
|
CERT_NAME_BLOB * pIssuerNameBlob - Pointer to issuer' name
|
|
blob of signer's cert.
|
|
CRYPT_INTEGERT_BLOB * pSerialNumberBlob - Pointer to serial number
|
|
blob of signer's cert.
|
|
PCERT_CONTEXT * ppCertContext - Pointer to PCERT_CONTEXT
|
|
to receive the found
|
|
cert, or NULL to only
|
|
know the result.
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT FindSignerCertInMessage (HCRYPTMSG hMsg,
|
|
CERT_NAME_BLOB * pIssuerNameBlob,
|
|
CRYPT_INTEGER_BLOB * pSerialNumberBlob,
|
|
PCERT_CONTEXT * ppCertContext)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwCertCount = 0;
|
|
DWORD cbCertCount = sizeof(dwCertCount);
|
|
|
|
DebugTrace("Entering FindSignerCertInMessage().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(NULL != hMsg);
|
|
ATLASSERT(NULL != pIssuerNameBlob);
|
|
ATLASSERT(NULL != pSerialNumberBlob);
|
|
ATLASSERT(0 < pIssuerNameBlob->cbData);
|
|
ATLASSERT(NULL != pIssuerNameBlob->pbData);
|
|
ATLASSERT(0 < pSerialNumberBlob->cbData);
|
|
ATLASSERT(NULL != pSerialNumberBlob->pbData);
|
|
|
|
//
|
|
// Get count of certs in message.
|
|
//
|
|
if (!::CryptMsgGetParam(hMsg,
|
|
CMSG_CERT_COUNT_PARAM,
|
|
0,
|
|
&dwCertCount,
|
|
&cbCertCount))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CryptMsgGetParam() failed.\n", hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// See if the signer's cert is in the bag of certs.
|
|
//
|
|
while (dwCertCount--)
|
|
{
|
|
PCCERT_CONTEXT pCertContext = NULL;
|
|
CRYPT_DATA_BLOB EncodedCertBlob = {0, NULL};
|
|
|
|
//
|
|
// Get a cert from the bag of certs.
|
|
//
|
|
hr = ::GetMsgParam(hMsg,
|
|
CMSG_CERT_PARAM,
|
|
dwCertCount,
|
|
(void **) &EncodedCertBlob.pbData,
|
|
&EncodedCertBlob.cbData);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugTrace("Error [%#x]: GetMsgParam() failed.\n", hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Create a context for the cert.
|
|
//
|
|
pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
|
(const BYTE *) EncodedCertBlob.pbData,
|
|
EncodedCertBlob.cbData);
|
|
|
|
//
|
|
// Free encoded cert blob memory before checking result.
|
|
//
|
|
::CoTaskMemFree((LPVOID) EncodedCertBlob.pbData);
|
|
|
|
if (NULL == pCertContext)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertCreateCertificateContext() failed.\n", hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Compare.
|
|
//
|
|
if (::CertCompareCertificateName(CAPICOM_ASN_ENCODING,
|
|
pIssuerNameBlob,
|
|
&pCertContext->pCertInfo->Issuer) &&
|
|
::CertCompareIntegerBlob(pSerialNumberBlob,
|
|
&pCertContext->pCertInfo->SerialNumber))
|
|
{
|
|
if (NULL != ppCertContext)
|
|
{
|
|
*ppCertContext = (PCERT_CONTEXT) pCertContext;
|
|
}
|
|
else
|
|
{
|
|
::CertFreeCertificateContext(pCertContext);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// No, keep looking.
|
|
//
|
|
::CertFreeCertificateContext(pCertContext);
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we get here, that means we never found the cert.
|
|
//
|
|
return CAPICOM_E_SIGNER_NOT_FOUND;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : IsAlgSupported
|
|
|
|
Synopsis : Check to see if the algo is supported by the CSP.
|
|
|
|
Parameter: HCRYPTPROV hCryptProv - CSP handle.
|
|
|
|
ALG_ID AlgID - Algorithm ID.
|
|
|
|
PROV_ENUMALGS_EX * pPeex - Pointer to PROV_ENUMALGS_EX to receive
|
|
the found structure.
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT IsAlgSupported (HCRYPTPROV hCryptProv,
|
|
ALG_ID AlgID,
|
|
PROV_ENUMALGS_EX * pPeex)
|
|
{
|
|
HRESULT hr = CAPICOM_E_NOT_SUPPORTED;
|
|
DWORD EnumFlag = CRYPT_FIRST;
|
|
DWORD cbPeex = sizeof(PROV_ENUMALGS_EX);
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(hCryptProv);
|
|
ATLASSERT(pPeex);
|
|
|
|
//
|
|
// Initialize.
|
|
//
|
|
::ZeroMemory(pPeex, sizeof(PROV_ENUMALGS_EX));
|
|
|
|
//
|
|
// Get algorithm capability from CSP.
|
|
//
|
|
while (::CryptGetProvParam(hCryptProv,
|
|
PP_ENUMALGS_EX,
|
|
(BYTE *) pPeex,
|
|
&cbPeex,
|
|
EnumFlag))
|
|
{
|
|
EnumFlag = 0;
|
|
|
|
if (pPeex->aiAlgid == AlgID)
|
|
{
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : AcquireContext
|
|
|
|
Synopsis : Acquire context for the specified CSP and keyset container.
|
|
|
|
Parameter: LPSTR pszProvider - CSP provider name or NULL.
|
|
|
|
LPSTR pszContainer - Keyset container name or NULL.
|
|
|
|
DWORD dwFlags - Same as dwFlags of CryptAcquireConext.
|
|
|
|
HCRYPTPROV * phCryptProv - Pointer to HCRYPTPROV to recevice
|
|
CSP context.
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT AcquireContext(LPSTR pszProvider,
|
|
LPSTR pszContainer,
|
|
DWORD dwFlags,
|
|
HCRYPTPROV * phCryptProv)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HCRYPTPROV hCryptProv = NULL;
|
|
|
|
DebugTrace("Entering AcquireContext().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(phCryptProv);
|
|
|
|
//
|
|
// Get handle to the default provider.
|
|
//
|
|
if(!::CryptAcquireContextA(&hCryptProv,
|
|
pszContainer,
|
|
pszProvider,
|
|
PROV_RSA_FULL,
|
|
dwFlags))
|
|
{
|
|
DWORD dwWinError = ::GetLastError();
|
|
|
|
if (NTE_BAD_KEYSET != dwWinError)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(dwWinError);
|
|
|
|
DebugTrace("Error [%#x]: CryptAcquireContextA() failed.\n", hr);
|
|
goto CommonExit;
|
|
}
|
|
|
|
//
|
|
// Keyset container not found, so create it.
|
|
//
|
|
if(!::CryptAcquireContextA(&hCryptProv,
|
|
pszContainer,
|
|
pszProvider,
|
|
PROV_RSA_FULL,
|
|
CRYPT_NEWKEYSET | dwFlags))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CryptAcquireContextA() failed.\n", hr);
|
|
goto CommonExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Return handle to caller.
|
|
//
|
|
*phCryptProv = hCryptProv;
|
|
|
|
CommonExit:
|
|
|
|
DebugTrace("Leaving AcquireContext().\n");
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : AcquireContext
|
|
|
|
Synopsis : Acquire context of a CSP using the default container for a
|
|
specified algorithm and desired key length.
|
|
|
|
Parameter: ALG_ID AlgOID - Algorithm ID.
|
|
|
|
DWORD dwKeyLength - Key length.
|
|
|
|
HCRYPTPROV * phCryptProv - Pointer to HCRYPTPROV to recevice
|
|
CSP context.
|
|
|
|
Remark : Note that KeyLength will be ignored for DES and 3DES.
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT AcquireContext(ALG_ID AlgID,
|
|
DWORD dwKeyLength,
|
|
HCRYPTPROV * phCryptProv)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering AcquireContext().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(phCryptProv);
|
|
|
|
//
|
|
// First try default provider.
|
|
//
|
|
if (SUCCEEDED(::AcquireContext(NULL, // Default provider
|
|
NULL,
|
|
CRYPT_VERIFYCONTEXT,
|
|
phCryptProv)))
|
|
{
|
|
PROV_ENUMALGS_EX peex;
|
|
|
|
//
|
|
// See if AlgID and key length supported.
|
|
//
|
|
if (SUCCEEDED(::IsAlgSupported(*phCryptProv, AlgID, &peex)) &&
|
|
(peex.dwMinLen <= dwKeyLength && dwKeyLength <= peex.dwMaxLen))
|
|
{
|
|
goto CommonExit;
|
|
}
|
|
else
|
|
{
|
|
::CryptReleaseContext(*phCryptProv, 0);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Next try MS Enhanced provider, and then MS Strong provider.
|
|
//
|
|
if (FAILED(::AcquireContext(MS_ENHANCED_PROV_A,
|
|
NULL,
|
|
CRYPT_VERIFYCONTEXT,
|
|
phCryptProv)) &&
|
|
FAILED(::AcquireContext(MS_STRONG_PROV_A,
|
|
NULL,
|
|
CRYPT_VERIFYCONTEXT,
|
|
phCryptProv)))
|
|
{
|
|
//
|
|
// For 3DES, must have either Enhanced or Strong.
|
|
//
|
|
if (CALG_3DES == AlgID)
|
|
{
|
|
hr = CAPICOM_E_NOT_SUPPORTED;
|
|
|
|
DebugTrace("Error: 3DES is not available.\n");
|
|
goto CommonExit;
|
|
}
|
|
|
|
//
|
|
// Finally, try MS Base provider if user requested for DES, or
|
|
// 56-bits or less for others.
|
|
//
|
|
if ((CALG_DES != AlgID) && (128 <= dwKeyLength))
|
|
{
|
|
hr = CAPICOM_E_NOT_SUPPORTED;
|
|
|
|
DebugTrace("Error: 128-bits (or more) encryption is not available.\n");
|
|
goto CommonExit;
|
|
}
|
|
|
|
if (FAILED(hr = ::AcquireContext(MS_DEF_PROV_A,
|
|
NULL,
|
|
CRYPT_VERIFYCONTEXT,
|
|
phCryptProv)))
|
|
{
|
|
DebugTrace("Error [%#x]: AcquireContext() failed.\n", hr);
|
|
goto CommonExit;
|
|
}
|
|
}
|
|
|
|
CommonExit:
|
|
|
|
DebugTrace("Leaving AcquireContext().\n");
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : AcquireContext
|
|
|
|
Synopsis : Acquire context of a CSP using the default container for a
|
|
specified algorithm and desired key length.
|
|
|
|
Parameter: CAPICOM_ENCRYPTION_ALGORITHM AlgoName - Algorithm name.
|
|
|
|
CAPICOM_ENCRYPTION_KEY_LENGTH KeyLength - Key length.
|
|
|
|
HCRYPTPROV * phCryptProv - Pointer to HCRYPTPROV to recevice
|
|
CSP context.
|
|
|
|
Remark : Note that KeyLength will be ignored for DES and 3DES.
|
|
|
|
Note also the the returned handle cannot be used to access private
|
|
key, and should NOT be used to store assymetric key, as it refers
|
|
to the default container, which can be easily destroy any existing
|
|
assymetric key pair.
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT AcquireContext (CAPICOM_ENCRYPTION_ALGORITHM AlgoName,
|
|
CAPICOM_ENCRYPTION_KEY_LENGTH KeyLength,
|
|
HCRYPTPROV * phCryptProv)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ALG_ID AlgID = 0;
|
|
DWORD dwKeyLength = 0;
|
|
|
|
DebugTrace("Entering AcquireContext().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(phCryptProv);
|
|
|
|
//
|
|
// Convert enum name to ALG_ID.
|
|
//
|
|
if (FAILED(hr = ::EnumNameToAlgID(AlgoName, &AlgID)))
|
|
{
|
|
DebugTrace("Error [%#x]: EnumNameToAlgID() failed.\n");
|
|
goto CommonExit;
|
|
}
|
|
|
|
//
|
|
// Convert enum name to key length.
|
|
//
|
|
if (FAILED(hr = ::EnumNameToKeyLength(KeyLength, &dwKeyLength)))
|
|
{
|
|
DebugTrace("Error [%#x]: EnumNameToKeyLength() failed.\n");
|
|
goto CommonExit;
|
|
}
|
|
|
|
//
|
|
// Pass on to overloaded version.
|
|
//
|
|
hr = ::AcquireContext(AlgID, dwKeyLength, phCryptProv);
|
|
|
|
CommonExit:
|
|
|
|
DebugTrace("Leaving AcquireContext().\n");
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : AcquireContext
|
|
|
|
Synopsis : Acquire the proper CSP and access to the private key for
|
|
the specified cert.
|
|
|
|
Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT of cert.
|
|
|
|
HCRYPTPROV * phCryptProv - Pointer to HCRYPTPROV to recevice
|
|
CSP context.
|
|
|
|
DWORD * pdwKeySpec - Pointer to DWORD to receive key
|
|
spec, AT_KEYEXCHANGE or AT_SIGNATURE.
|
|
|
|
BOOL * pbReleaseContext - Upon successful and if this is set
|
|
to TRUE, then the caller must
|
|
free the CSP context by calling
|
|
CryptReleaseContext(), otherwise
|
|
the caller must not free the CSP
|
|
context.
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT AcquireContext (PCCERT_CONTEXT pCertContext,
|
|
HCRYPTPROV * phCryptProv,
|
|
DWORD * pdwKeySpec,
|
|
BOOL * pbReleaseContext)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering AcquireContext().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(pCertContext);
|
|
ATLASSERT(phCryptProv);
|
|
ATLASSERT(pdwKeySpec);
|
|
ATLASSERT(pbReleaseContext);
|
|
|
|
//
|
|
// Acquire CSP context and access to the private key associated
|
|
// with this cert.
|
|
//
|
|
if (!::CryptAcquireCertificatePrivateKey(pCertContext,
|
|
CRYPT_ACQUIRE_USE_PROV_INFO_FLAG,
|
|
NULL,
|
|
phCryptProv,
|
|
pdwKeySpec,
|
|
pbReleaseContext))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CryptAcquireCertificatePrivateKey() failed.\n", hr);
|
|
}
|
|
|
|
DebugTrace("Leaving AcquireContext().\n");
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : ReleaseContext
|
|
|
|
Synopsis : Release CSP context.
|
|
|
|
Parameter: HCRYPTPROV hProv - CSP handle.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT ReleaseContext (HCRYPTPROV hProv)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering ReleaseContext().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(hProv);
|
|
|
|
//
|
|
// Release the context.
|
|
//
|
|
if (!::CryptReleaseContext(hProv, 0))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CryptReleaseContext() failed.\n", hr);
|
|
}
|
|
|
|
DebugTrace("Leaving ReleaseContext().\n");
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : OIDToAlgID
|
|
|
|
Synopsis : Convert algorithm OID to the corresponding ALG_ID value.
|
|
|
|
Parameter: LPSTR pszAlgoOID - Algorithm OID string.
|
|
|
|
ALG_ID * pAlgID - Pointer to ALG_ID to receive the value.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT OIDToAlgID (LPSTR pszAlgoOID,
|
|
ALG_ID * pAlgID)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering OIDToAlgID().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(pszAlgoOID);
|
|
ATLASSERT(pAlgID);
|
|
|
|
//
|
|
// Determine ALG_ID.
|
|
//
|
|
if (0 == ::lstrcmpA(szOID_RSA_RC2CBC, pszAlgoOID))
|
|
{
|
|
*pAlgID = CALG_RC2;
|
|
}
|
|
else if (0 == ::lstrcmpA(szOID_RSA_RC4, pszAlgoOID))
|
|
{
|
|
*pAlgID = CALG_RC4;
|
|
}
|
|
else if (0 == ::lstrcmpA(szOID_OIWSEC_desCBC, pszAlgoOID))
|
|
{
|
|
*pAlgID = CALG_DES;
|
|
}
|
|
else if (0 == ::lstrcmpA(szOID_RSA_DES_EDE3_CBC, pszAlgoOID))
|
|
{
|
|
*pAlgID = CALG_3DES;
|
|
}
|
|
else
|
|
{
|
|
hr = CAPICOM_E_INVALID_ALGORITHM;
|
|
DebugTrace("Error: invalid parameter, unknown algorithm OID.\n");
|
|
}
|
|
|
|
DebugTrace("Leaving OIDToAlgID().\n");
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : AlgIDToOID
|
|
|
|
Synopsis : Convert ALG_ID value to the corresponding algorithm OID.
|
|
|
|
Parameter: ALG_ID AlgID - ALG_ID to be converted.
|
|
|
|
LPSTR * ppszAlgoOID - Pointer to LPSTR to receive the OID string.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT AlgIDToOID (ALG_ID AlgID,
|
|
LPSTR * ppszAlgoOID)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPSTR pszAlgoOID = NULL;
|
|
|
|
DebugTrace("Entering AlgIDToOID().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(ppszAlgoOID);
|
|
|
|
//
|
|
// Determine ALG_ID.
|
|
//
|
|
switch (AlgID)
|
|
{
|
|
case CALG_RC2:
|
|
{
|
|
pszAlgoOID = szOID_RSA_RC2CBC;
|
|
break;
|
|
}
|
|
|
|
case CALG_RC4:
|
|
{
|
|
pszAlgoOID = szOID_RSA_RC4;
|
|
break;
|
|
}
|
|
|
|
case CALG_DES:
|
|
{
|
|
pszAlgoOID = szOID_OIWSEC_desCBC;
|
|
break;
|
|
}
|
|
|
|
case CALG_3DES:
|
|
{
|
|
pszAlgoOID = szOID_RSA_DES_EDE3_CBC;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
hr = CAPICOM_E_INVALID_ALGORITHM;
|
|
DebugTrace("Error: invalid parameter, unknown algorithm OID.\n");
|
|
goto CommonExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Allocate memory.
|
|
//
|
|
if (!(*ppszAlgoOID = (LPSTR) ::CoTaskMemAlloc(::lstrlen(pszAlgoOID) + 1)))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
DebugTrace("Error: out of memory.\n");
|
|
goto CommonExit;
|
|
}
|
|
|
|
//
|
|
// Copy OID string to caller.
|
|
//
|
|
::lstrcpy(*ppszAlgoOID, pszAlgoOID);
|
|
|
|
CommonExit:
|
|
|
|
DebugTrace("Leaving AlgIDToOID().\n");
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : AlgIDToEnumName
|
|
|
|
Synopsis : Convert ALG_ID value to the corresponding algorithm enum name.
|
|
|
|
Parameter: ALG_ID AlgID - ALG_ID to be converted.
|
|
|
|
CAPICOM_ENCRYPTION_ALGORITHM * pAlgoName - Receive algo enum name.
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT AlgIDToEnumName (ALG_ID AlgID,
|
|
CAPICOM_ENCRYPTION_ALGORITHM * pAlgoName)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering AlgIDToEnumName().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(pAlgoName);
|
|
|
|
switch (AlgID)
|
|
{
|
|
case CALG_RC2:
|
|
{
|
|
*pAlgoName = CAPICOM_ENCRYPTION_ALGORITHM_RC2;
|
|
break;
|
|
}
|
|
|
|
case CALG_RC4:
|
|
{
|
|
*pAlgoName = CAPICOM_ENCRYPTION_ALGORITHM_RC4;
|
|
break;
|
|
}
|
|
|
|
case CALG_DES:
|
|
{
|
|
*pAlgoName = CAPICOM_ENCRYPTION_ALGORITHM_DES;
|
|
break;
|
|
}
|
|
|
|
case CALG_3DES:
|
|
{
|
|
*pAlgoName = CAPICOM_ENCRYPTION_ALGORITHM_3DES;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
hr = CAPICOM_E_INVALID_ALGORITHM;
|
|
DebugTrace("Error: invalid parameter, unknown ALG_ID.\n");
|
|
}
|
|
}
|
|
|
|
DebugTrace("Leaving AlgIDToEnumName().\n");
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : EnumNameToAlgID
|
|
|
|
Synopsis : Convert algorithm enum name to the corresponding ALG_ID value.
|
|
|
|
Parameter: CAPICOM_ENCRYPTION_ALGORITHM AlgoName - Algo enum name
|
|
|
|
ALG_ID * pAlgID - Pointer to ALG_ID to receive the value.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT EnumNameToAlgID (CAPICOM_ENCRYPTION_ALGORITHM AlgoName,
|
|
ALG_ID * pAlgID)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering EnumNameToAlgID().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(pAlgID);
|
|
|
|
switch (AlgoName)
|
|
{
|
|
case CAPICOM_ENCRYPTION_ALGORITHM_RC2:
|
|
{
|
|
*pAlgID = CALG_RC2;
|
|
break;
|
|
}
|
|
|
|
case CAPICOM_ENCRYPTION_ALGORITHM_RC4:
|
|
{
|
|
*pAlgID = CALG_RC4;
|
|
break;
|
|
}
|
|
|
|
case CAPICOM_ENCRYPTION_ALGORITHM_DES:
|
|
{
|
|
*pAlgID = CALG_DES;
|
|
break;
|
|
}
|
|
|
|
case CAPICOM_ENCRYPTION_ALGORITHM_3DES:
|
|
{
|
|
*pAlgID = CALG_3DES;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
hr = CAPICOM_E_INVALID_ALGORITHM;
|
|
DebugTrace("Error: invalid parameter, unknown CAPICOM_ENCRYPTION_ALGORITHM.\n");
|
|
}
|
|
}
|
|
|
|
DebugTrace("Leaving EnumNameToAlgID().\n");
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : KeyLengthToEnumName
|
|
|
|
Synopsis : Convert actual key length value to the corresponding key length
|
|
enum name.
|
|
|
|
Parameter: DWORD dwKeyLength - Key length.
|
|
|
|
CAPICOM_ENCRYPTION_KEY_LENGTH * pKeyLengthName - Receive key length
|
|
enum name.
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT KeyLengthToEnumName (DWORD dwKeyLength,
|
|
CAPICOM_ENCRYPTION_KEY_LENGTH * pKeyLengthName)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering KeyLengthToEnumName().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(pKeyLengthName);
|
|
|
|
switch (dwKeyLength)
|
|
{
|
|
case 40:
|
|
{
|
|
*pKeyLengthName = CAPICOM_ENCRYPTION_KEY_LENGTH_40_BITS;
|
|
break;
|
|
}
|
|
|
|
case 56:
|
|
{
|
|
*pKeyLengthName = CAPICOM_ENCRYPTION_KEY_LENGTH_56_BITS;
|
|
break;
|
|
}
|
|
|
|
case 128:
|
|
{
|
|
*pKeyLengthName = CAPICOM_ENCRYPTION_KEY_LENGTH_128_BITS;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
hr = CAPICOM_E_INVALID_KEY_LENGTH;
|
|
DebugTrace("Error: invalid parameter, unknown key length.\n");
|
|
}
|
|
}
|
|
|
|
DebugTrace("Leaving KeyLengthToEnumName().\n");
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : EnumNameToKeyLength
|
|
|
|
Synopsis : Convert key length enum name to the corresponding actual key length
|
|
value .
|
|
|
|
Parameter: CAPICOM_ENCRYPTION_KEY_LENGTH KeyLengthName - Key length enum name.
|
|
|
|
DWORD * pdwKeyLength - Pointer to DWORD to receive value.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT EnumNameToKeyLength (CAPICOM_ENCRYPTION_KEY_LENGTH KeyLengthName,
|
|
DWORD * pdwKeyLength)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering EnumNameToKeyLength().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(pdwKeyLength);
|
|
|
|
switch (KeyLengthName)
|
|
{
|
|
case CAPICOM_ENCRYPTION_KEY_LENGTH_40_BITS:
|
|
{
|
|
*pdwKeyLength = 40;
|
|
break;
|
|
}
|
|
|
|
case CAPICOM_ENCRYPTION_KEY_LENGTH_56_BITS:
|
|
{
|
|
*pdwKeyLength = 56;
|
|
break;
|
|
}
|
|
|
|
case CAPICOM_ENCRYPTION_KEY_LENGTH_128_BITS:
|
|
{
|
|
*pdwKeyLength = 128;
|
|
break;
|
|
}
|
|
|
|
case CAPICOM_ENCRYPTION_KEY_LENGTH_MAXIMUM:
|
|
{
|
|
HCRYPTPROV hCryptProv = NULL;
|
|
|
|
//
|
|
// For 128-bits, need either Enhanced or Strong provider.
|
|
//
|
|
if (FAILED(::AcquireContext(MS_ENHANCED_PROV_A,
|
|
NULL,
|
|
CRYPT_VERIFYCONTEXT,
|
|
&hCryptProv)) &&
|
|
FAILED(::AcquireContext(MS_STRONG_PROV_A,
|
|
NULL,
|
|
CRYPT_VERIFYCONTEXT,
|
|
&hCryptProv)))
|
|
{
|
|
//
|
|
// Only 56-bits maximum for MS Base provider.
|
|
//
|
|
*pdwKeyLength = 56;
|
|
}
|
|
else
|
|
{
|
|
*pdwKeyLength = 128;
|
|
|
|
::ReleaseContext(hCryptProv);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
hr = CAPICOM_E_INVALID_KEY_LENGTH;
|
|
DebugTrace("Error: invalid parameter, unknown CAPICOM_ENCRYPTION_KEY_LENGTH.\n");
|
|
}
|
|
}
|
|
|
|
DebugTrace("Leaving EnumNameToKeyLength().\n");
|
|
|
|
return hr;
|
|
}
|