Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

509 lines
12 KiB

  1. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
  3. File: HashedData.cpp
  4. Content: Implementation of CHashedData.
  5. History: 11-12-2001 dsie created
  6. ------------------------------------------------------------------------------*/
  7. #include "stdafx.h"
  8. #include "CAPICOM.h"
  9. #include "HashedData.h"
  10. #include "Common.h"
  11. #include "Convert.h"
  12. typedef struct _tagHashAlgoTable
  13. {
  14. CAPICOM_HASH_ALGORITHM CapicomHashAlg;
  15. ALG_ID AlgId;
  16. } HASH_ALGO_TABLE;
  17. static HASH_ALGO_TABLE HashAlgoTable[] = {
  18. {CAPICOM_HASH_ALGORITHM_SHA1, CALG_SHA1},
  19. {CAPICOM_HASH_ALGORITHM_MD2, CALG_MD2},
  20. {CAPICOM_HASH_ALGORITHM_MD4, CALG_MD4},
  21. {CAPICOM_HASH_ALGORITHM_MD5, CALG_MD5},
  22. // {CAPICOM_HASH_ALGORITHM_SHA_256, CALG_SHA_256},
  23. // {CAPICOM_HASH_ALGORITHM_SHA_384, CALG_SHA_384},
  24. // {CAPICOM_HASH_ALGORITHM_SHA_512, CALG_SHA_512}
  25. };
  26. ////////////////////////////////////////////////////////////////////////////////
  27. //
  28. // CHashedData
  29. //
  30. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  31. Function : CHashedData::get_Value
  32. Synopsis : Return the hash value.
  33. Parameter: BSTR * pVal - Pointer to BSTR to receive the hashed value blob.
  34. Remark :
  35. ------------------------------------------------------------------------------*/
  36. STDMETHODIMP CHashedData::get_Value (BSTR * pVal)
  37. {
  38. HRESULT hr = S_OK;
  39. DWORD dwDataLen = sizeof(DWORD);
  40. CRYPT_DATA_BLOB HashData = {0, NULL};
  41. DebugTrace("Entering CHashedData::get_Value().\n");
  42. try
  43. {
  44. //
  45. // Lock access to this object.
  46. //
  47. m_Lock.Lock();
  48. //
  49. // Check parameters.
  50. //
  51. if (NULL == pVal)
  52. {
  53. hr = E_INVALIDARG;
  54. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  55. goto ErrorExit;
  56. }
  57. //
  58. // Make sure we have hash data.
  59. //
  60. if (!m_hCryptHash)
  61. {
  62. hr = CAPICOM_E_HASH_NO_DATA;
  63. DebugTrace("Error [%#x]: no value for HashedData.\n", hr);
  64. goto ErrorExit;
  65. }
  66. //
  67. // Get size of hashed value.
  68. //
  69. if (!::CryptGetHashParam(m_hCryptHash,
  70. HP_HASHSIZE,
  71. (LPBYTE) &HashData.cbData,
  72. &dwDataLen,
  73. 0))
  74. {
  75. hr = HRESULT_FROM_WIN32(::GetLastError());
  76. DebugTrace("Error [%#x]: CryptGetHashParam() failed to get size.\n", hr);
  77. goto ErrorExit;
  78. }
  79. //
  80. // Allocate memory.
  81. //
  82. if (!(HashData.pbData = (LPBYTE) ::CoTaskMemAlloc(HashData.cbData)))
  83. {
  84. hr = E_OUTOFMEMORY;
  85. DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
  86. goto ErrorExit;
  87. }
  88. //
  89. // Now get the hashed value.
  90. //
  91. if (!::CryptGetHashParam(m_hCryptHash, HP_HASHVAL, HashData.pbData, &HashData.cbData, 0))
  92. {
  93. hr = HRESULT_FROM_WIN32(::GetLastError());
  94. DebugTrace("Error [%#x]: CryptGetHashParam() failed to get data.\n", hr);
  95. goto ErrorExit;
  96. }
  97. //
  98. // Export HashedData.
  99. //
  100. if (FAILED(hr = ::BinaryToHexString(HashData.pbData, HashData.cbData, pVal)))
  101. {
  102. DebugTrace("Error [%#x]: BinaryToHexString() failed.\n", hr);
  103. goto ErrorExit;
  104. }
  105. //
  106. // Reset state.
  107. //
  108. m_HashState = CAPICOM_HASH_INIT_STATE;
  109. }
  110. catch(...)
  111. {
  112. hr = E_POINTER;
  113. DebugTrace("Exception: invalid parameter.\n");
  114. goto ErrorExit;
  115. }
  116. UnlockExit:
  117. //
  118. // Free resources.
  119. //
  120. if (HashData.pbData)
  121. {
  122. ::CoTaskMemFree((LPVOID) HashData.pbData);
  123. }
  124. //
  125. // Unlock access to this object.
  126. //
  127. m_Lock.Unlock();
  128. DebugTrace("Leaving CHashedData::get_Value().\n");
  129. return hr;
  130. ErrorExit:
  131. //
  132. // Sanity check.
  133. //
  134. ATLASSERT(FAILED(hr));
  135. ReportError(hr);
  136. goto UnlockExit;
  137. }
  138. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  139. Function : CHashedData::get_Algorithm
  140. Synopsis : Return the agorithm.
  141. Parameter: CAPICOM_HASH_ALGORITHM * pVal - Pointer to CAPICOM_HASH_ALGORITHM
  142. to receive result.
  143. Remark :
  144. ------------------------------------------------------------------------------*/
  145. STDMETHODIMP CHashedData::get_Algorithm (CAPICOM_HASH_ALGORITHM * pVal)
  146. {
  147. HRESULT hr = S_OK;
  148. DebugTrace("Entering CHashedData::get_Algorithm().\n");
  149. try
  150. {
  151. //
  152. // Lock access to this object.
  153. //
  154. m_Lock.Lock();
  155. //
  156. // Check parameters.
  157. //
  158. if (NULL == pVal)
  159. {
  160. hr = E_INVALIDARG;
  161. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  162. goto ErrorExit;
  163. }
  164. //
  165. // Return result.
  166. //
  167. *pVal = m_Algorithm;
  168. }
  169. catch(...)
  170. {
  171. hr = E_POINTER;
  172. DebugTrace("Exception: invalid parameter.\n");
  173. goto ErrorExit;
  174. }
  175. UnlockExit:
  176. //
  177. // Unlock access to this object.
  178. //
  179. m_Lock.Unlock();
  180. DebugTrace("Leaving CHashedData::get_Algorithm().\n");
  181. return hr;
  182. ErrorExit:
  183. //
  184. // Sanity check.
  185. //
  186. ATLASSERT(FAILED(hr));
  187. ReportError(hr);
  188. goto UnlockExit;
  189. }
  190. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  191. Function : CHashedData::put_Algorithm
  192. Synopsis : Set algorithm.
  193. Parameter: CAPICOM_HASH_ALGORITHM newVal - Algorithm enum name.
  194. Remark : The object state is reset..
  195. ------------------------------------------------------------------------------*/
  196. STDMETHODIMP CHashedData::put_Algorithm (CAPICOM_HASH_ALGORITHM newVal)
  197. {
  198. HRESULT hr = S_OK;
  199. DebugTrace("Entering CHashedData::put_Algorithm().\n");
  200. try
  201. {
  202. //
  203. // Lock access to this object.
  204. //
  205. m_Lock.Lock();
  206. //
  207. // Make sure algo is supported.
  208. //
  209. switch (newVal)
  210. {
  211. case CAPICOM_HASH_ALGORITHM_SHA1:
  212. case CAPICOM_HASH_ALGORITHM_MD2:
  213. case CAPICOM_HASH_ALGORITHM_MD4:
  214. case CAPICOM_HASH_ALGORITHM_MD5:
  215. // case CAPICOM_HASH_ALGORITHM_SHA_256:
  216. // case CAPICOM_HASH_ALGORITHM_SHA_384:
  217. // case CAPICOM_HASH_ALGORITHM_SHA_512:
  218. {
  219. break;
  220. }
  221. default:
  222. {
  223. hr = CAPICOM_E_INVALID_ALGORITHM;
  224. DebugTrace("Error [%#x]: Unknown hash algorithm (%u).\n", hr, newVal);
  225. goto ErrorExit;
  226. }
  227. }
  228. m_Algorithm = newVal;
  229. }
  230. catch(...)
  231. {
  232. hr = E_POINTER;
  233. DebugTrace("Exception: invalid parameter.\n");
  234. goto ErrorExit;
  235. }
  236. UnlockExit:
  237. //
  238. // Unlock access to this object.
  239. //
  240. m_Lock.Unlock();
  241. DebugTrace("Leaving CHashedData::put_Algorithm().\n");
  242. return hr;
  243. ErrorExit:
  244. //
  245. // Sanity check.
  246. //
  247. ATLASSERT(FAILED(hr));
  248. ReportError(hr);
  249. goto UnlockExit;
  250. }
  251. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  252. Function : CHashedData::Hash
  253. Synopsis : Hash data.
  254. Parameter: BSTR newVal - BSTR of value to hash.
  255. Remark :
  256. ------------------------------------------------------------------------------*/
  257. STDMETHODIMP CHashedData::Hash (BSTR newVal)
  258. {
  259. HRESULT hr = S_OK;
  260. DebugTrace("Entering CHashedData::Hash().\n");
  261. try
  262. {
  263. //
  264. // Lock access to this object.
  265. //
  266. m_Lock.Lock();
  267. //
  268. // Check parameters.
  269. //
  270. if (NULL == newVal)
  271. {
  272. hr = E_INVALIDARG;
  273. DebugTrace("Error [%#x]: Parameter newVal is NULL.\n", hr);
  274. goto ErrorExit;
  275. }
  276. //
  277. // Check our state.
  278. //
  279. switch (m_HashState)
  280. {
  281. case CAPICOM_HASH_INIT_STATE:
  282. {
  283. DWORD Index = 0;
  284. ALG_ID AlgId = 0;
  285. //
  286. // Map algorithm to ALG_ID.
  287. //
  288. for (Index = 0; Index < ARRAYSIZE(HashAlgoTable); Index++)
  289. {
  290. if (HashAlgoTable[Index].CapicomHashAlg == m_Algorithm)
  291. {
  292. AlgId = HashAlgoTable[Index].AlgId;
  293. break;
  294. }
  295. }
  296. //
  297. // Get the provider, if needed.
  298. //
  299. if (!m_hCryptProv)
  300. {
  301. if (FAILED(hr = ::AcquireContext(AlgId, &m_hCryptProv)))
  302. {
  303. DebugTrace("Error [%#x]: AcquireContext() failed.\n", hr);
  304. goto ErrorExit;
  305. }
  306. }
  307. //
  308. // Sanity check.
  309. //
  310. ATLASSERT(Index < ARRAYSIZE(HashAlgoTable));
  311. //
  312. // Free handles if still available.
  313. //
  314. if (m_hCryptHash)
  315. {
  316. if (!::CryptDestroyHash(m_hCryptHash))
  317. {
  318. hr = HRESULT_FROM_WIN32(::GetLastError());
  319. DebugTrace("Error [%#x]: CryptDestroyHash() failed.\n", hr);
  320. goto ErrorExit;
  321. }
  322. m_hCryptHash = NULL;
  323. }
  324. //
  325. // Create a new hash handle.
  326. //
  327. if (!::CryptCreateHash(m_hCryptProv, AlgId, NULL, 0, &m_hCryptHash))
  328. {
  329. hr = HRESULT_FROM_WIN32(::GetLastError());
  330. DebugTrace("Error [%#x]: CryptCreateHash() failed.\n", hr);
  331. goto ErrorExit;
  332. }
  333. //
  334. // Update hash handle and state.
  335. //
  336. m_HashState = CAPICOM_HASH_DATA_STATE;
  337. //
  338. // Fall thru to hash data.
  339. //
  340. }
  341. case CAPICOM_HASH_DATA_STATE:
  342. {
  343. //
  344. // Sanity check.
  345. //
  346. ATLASSERT(m_hCryptProv);
  347. ATLASSERT(m_hCryptHash);
  348. //
  349. // Hash the data.
  350. //
  351. if (!::CryptHashData(m_hCryptHash,
  352. (PBYTE) newVal,
  353. ::SysStringByteLen(newVal),
  354. 0))
  355. {
  356. hr = HRESULT_FROM_WIN32(::GetLastError());
  357. DebugTrace("Error [%#x]: CryptHashData() failed.\n", hr);
  358. goto ErrorExit;
  359. }
  360. break;
  361. }
  362. default:
  363. {
  364. hr = CAPICOM_E_INTERNAL;
  365. DebugTrace("Error [%#x]: Unknown hash state (%d).\n", hr, m_HashState);
  366. goto ErrorExit;
  367. }
  368. }
  369. }
  370. catch(...)
  371. {
  372. hr = E_POINTER;
  373. DebugTrace("Exception: invalid parameter.\n");
  374. goto ErrorExit;
  375. }
  376. UnlockExit:
  377. //
  378. // Unlock access to this object.
  379. //
  380. m_Lock.Unlock();
  381. DebugTrace("Leaving CHashedData::Hash().\n");
  382. return hr;
  383. ErrorExit:
  384. //
  385. // Sanity check.
  386. //
  387. ATLASSERT(FAILED(hr));
  388. ReportError(hr);
  389. goto UnlockExit;
  390. }