|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
File: HashedData.cpp
Content: Implementation of CHashedData.
History: 11-12-2001 dsie created
------------------------------------------------------------------------------*/
#include "stdafx.h"
#include "CAPICOM.h"
#include "HashedData.h"
#include "Common.h"
#include "Convert.h"
typedef struct _tagHashAlgoTable { CAPICOM_HASH_ALGORITHM CapicomHashAlg; ALG_ID AlgId; } HASH_ALGO_TABLE;
static HASH_ALGO_TABLE HashAlgoTable[] = { {CAPICOM_HASH_ALGORITHM_SHA1, CALG_SHA1}, {CAPICOM_HASH_ALGORITHM_MD2, CALG_MD2}, {CAPICOM_HASH_ALGORITHM_MD4, CALG_MD4}, {CAPICOM_HASH_ALGORITHM_MD5, CALG_MD5}, // {CAPICOM_HASH_ALGORITHM_SHA_256, CALG_SHA_256},
// {CAPICOM_HASH_ALGORITHM_SHA_384, CALG_SHA_384},
// {CAPICOM_HASH_ALGORITHM_SHA_512, CALG_SHA_512}
};
////////////////////////////////////////////////////////////////////////////////
//
// CHashedData
//
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CHashedData::get_Value
Synopsis : Return the hash value.
Parameter: BSTR * pVal - Pointer to BSTR to receive the hashed value blob.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CHashedData::get_Value (BSTR * pVal) { HRESULT hr = S_OK; DWORD dwDataLen = sizeof(DWORD); CRYPT_DATA_BLOB HashData = {0, NULL};
DebugTrace("Entering CHashedData::get_Value().\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 have hash data.
//
if (!m_hCryptHash) { hr = CAPICOM_E_HASH_NO_DATA;
DebugTrace("Error [%#x]: no value for HashedData.\n", hr); goto ErrorExit; }
//
// Get size of hashed value.
//
if (!::CryptGetHashParam(m_hCryptHash, HP_HASHSIZE, (LPBYTE) &HashData.cbData, &dwDataLen, 0)) { hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptGetHashParam() failed to get size.\n", hr); goto ErrorExit; }
//
// Allocate memory.
//
if (!(HashData.pbData = (LPBYTE) ::CoTaskMemAlloc(HashData.cbData))) { hr = E_OUTOFMEMORY;
DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr); goto ErrorExit; }
//
// Now get the hashed value.
//
if (!::CryptGetHashParam(m_hCryptHash, HP_HASHVAL, HashData.pbData, &HashData.cbData, 0)) { hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptGetHashParam() failed to get data.\n", hr); goto ErrorExit; }
//
// Export HashedData.
//
if (FAILED(hr = ::BinaryToHexString(HashData.pbData, HashData.cbData, pVal))) { DebugTrace("Error [%#x]: BinaryToHexString() failed.\n", hr); goto ErrorExit; }
//
// Reset state.
//
m_HashState = CAPICOM_HASH_INIT_STATE; }
catch(...) { hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n"); goto ErrorExit; }
UnlockExit: //
// Free resources.
//
if (HashData.pbData) { ::CoTaskMemFree((LPVOID) HashData.pbData); }
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CHashedData::get_Value().\n");
return hr;
ErrorExit: //
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CHashedData::get_Algorithm
Synopsis : Return the agorithm.
Parameter: CAPICOM_HASH_ALGORITHM * pVal - Pointer to CAPICOM_HASH_ALGORITHM to receive result.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CHashedData::get_Algorithm (CAPICOM_HASH_ALGORITHM * pVal) { HRESULT hr = S_OK;
DebugTrace("Entering CHashedData::get_Algorithm().\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; }
//
// Return result.
//
*pVal = m_Algorithm; }
catch(...) { hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n"); goto ErrorExit; }
UnlockExit: //
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CHashedData::get_Algorithm().\n");
return hr;
ErrorExit: //
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CHashedData::put_Algorithm
Synopsis : Set algorithm.
Parameter: CAPICOM_HASH_ALGORITHM newVal - Algorithm enum name. Remark : The object state is reset..
------------------------------------------------------------------------------*/
STDMETHODIMP CHashedData::put_Algorithm (CAPICOM_HASH_ALGORITHM newVal) { HRESULT hr = S_OK;
DebugTrace("Entering CHashedData::put_Algorithm().\n");
try { //
// Lock access to this object.
//
m_Lock.Lock();
//
// Make sure algo is supported.
//
switch (newVal) { case CAPICOM_HASH_ALGORITHM_SHA1: case CAPICOM_HASH_ALGORITHM_MD2: case CAPICOM_HASH_ALGORITHM_MD4: case CAPICOM_HASH_ALGORITHM_MD5: // case CAPICOM_HASH_ALGORITHM_SHA_256:
// case CAPICOM_HASH_ALGORITHM_SHA_384:
// case CAPICOM_HASH_ALGORITHM_SHA_512:
{ break; }
default: { hr = CAPICOM_E_INVALID_ALGORITHM;
DebugTrace("Error [%#x]: Unknown hash algorithm (%u).\n", hr, newVal); goto ErrorExit; } }
m_Algorithm = newVal; }
catch(...) { hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n"); goto ErrorExit; }
UnlockExit: //
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CHashedData::put_Algorithm().\n");
return hr;
ErrorExit: //
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CHashedData::Hash
Synopsis : Hash data.
Parameter: BSTR newVal - BSTR of value to hash.
Remark : ------------------------------------------------------------------------------*/
STDMETHODIMP CHashedData::Hash (BSTR newVal) { HRESULT hr = S_OK;
DebugTrace("Entering CHashedData::Hash().\n");
try { //
// Lock access to this object.
//
m_Lock.Lock();
//
// Check parameters.
//
if (NULL == newVal) { hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Parameter newVal is NULL.\n", hr); goto ErrorExit; }
//
// Check our state.
//
switch (m_HashState) { case CAPICOM_HASH_INIT_STATE: { DWORD Index = 0; ALG_ID AlgId = 0;
//
// Map algorithm to ALG_ID.
//
for (Index = 0; Index < ARRAYSIZE(HashAlgoTable); Index++) { if (HashAlgoTable[Index].CapicomHashAlg == m_Algorithm) { AlgId = HashAlgoTable[Index].AlgId; break; } }
//
// Get the provider, if needed.
//
if (!m_hCryptProv) { if (FAILED(hr = ::AcquireContext(AlgId, &m_hCryptProv))) { DebugTrace("Error [%#x]: AcquireContext() failed.\n", hr); goto ErrorExit; } }
//
// Sanity check.
//
ATLASSERT(Index < ARRAYSIZE(HashAlgoTable));
//
// Free handles if still available.
//
if (m_hCryptHash) { if (!::CryptDestroyHash(m_hCryptHash)) { hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptDestroyHash() failed.\n", hr); goto ErrorExit; }
m_hCryptHash = NULL; }
//
// Create a new hash handle.
//
if (!::CryptCreateHash(m_hCryptProv, AlgId, NULL, 0, &m_hCryptHash)) { hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptCreateHash() failed.\n", hr); goto ErrorExit; }
//
// Update hash handle and state.
//
m_HashState = CAPICOM_HASH_DATA_STATE;
//
// Fall thru to hash data.
//
}
case CAPICOM_HASH_DATA_STATE: { //
// Sanity check.
//
ATLASSERT(m_hCryptProv); ATLASSERT(m_hCryptHash);
//
// Hash the data.
//
if (!::CryptHashData(m_hCryptHash, (PBYTE) newVal, ::SysStringByteLen(newVal), 0)) { hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CryptHashData() failed.\n", hr); goto ErrorExit; } break; }
default: { hr = CAPICOM_E_INTERNAL;
DebugTrace("Error [%#x]: Unknown hash state (%d).\n", hr, m_HashState); goto ErrorExit; } } }
catch(...) { hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n"); goto ErrorExit; }
UnlockExit: //
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CHashedData::Hash().\n");
return hr;
ErrorExit: //
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit; }
|