You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
509 lines
12 KiB
509 lines
12 KiB
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
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;
|
|
}
|