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;
 | |
| }
 |