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.

641 lines
11 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. hash.c
  5. Abstract:
  6. Hash manipulators for the IIS cryptographic package.
  7. The following routines are exported by this module:
  8. IISCryptoCreateHash
  9. IISCryptoDestroyHash
  10. IISCryptoHashData
  11. IISCryptoHashSessionKey
  12. IISCryptoExportHashBlob
  13. IcpGetHashLength
  14. Author:
  15. Keith Moore (keithmo) 02-Dec-1996
  16. Revision History:
  17. --*/
  18. #include "precomp.h"
  19. #pragma hdrstop
  20. //
  21. // Private constants.
  22. //
  23. //
  24. // Private types.
  25. //
  26. //
  27. // Private globals.
  28. //
  29. //
  30. // Private prototypes.
  31. //
  32. //
  33. // Public functions.
  34. //
  35. HRESULT
  36. WINAPI
  37. IISCryptoCreateHash(
  38. OUT HCRYPTHASH * phHash,
  39. IN HCRYPTPROV hProv
  40. )
  41. /*++
  42. Routine Description:
  43. This routine creates a new hash object.
  44. Arguments:
  45. phHash - Receives the hash handle if successful.
  46. hProv - A handle to a crypto service provider.
  47. Return Value:
  48. HRESULT - Completion status, 0 if successful, !0 otherwise.
  49. --*/
  50. {
  51. //
  52. // Sanity check.
  53. //
  54. DBG_ASSERT( IcpGlobals.Initialized );
  55. DBG_ASSERT( phHash != NULL );
  56. DBG_ASSERT( hProv != CRYPT_NULL );
  57. //
  58. // Short-circuit if cryptography is disabled.
  59. //
  60. if( !IcpGlobals.EnableCryptography ) {
  61. if( hProv == DUMMY_HPROV ) {
  62. *phHash = DUMMY_HHASH;
  63. return NO_ERROR;
  64. } else {
  65. return RETURNCODETOHRESULT( ERROR_INVALID_PARAMETER );
  66. }
  67. }
  68. //
  69. // Create the hash object.
  70. //
  71. if( CryptCreateHash(
  72. hProv,
  73. IC_HASH_ALG,
  74. CRYPT_NULL,
  75. 0,
  76. phHash
  77. ) ) {
  78. UpdateHashCreated();
  79. return NO_ERROR;
  80. }
  81. return IcpGetLastError();
  82. } // IISCryptoCreateHash
  83. HRESULT
  84. WINAPI
  85. IISCryptoDestroyHash(
  86. IN HCRYPTHASH hHash
  87. )
  88. /*++
  89. Routine Description:
  90. This routine destroys the specified hash object.
  91. Arguments:
  92. hHash - The hash object to destroy.
  93. Return Value:
  94. HRESULT - Completion status, 0 if successful, !0 otherwise.
  95. --*/
  96. {
  97. //
  98. // Sanity check.
  99. //
  100. DBG_ASSERT( IcpGlobals.Initialized );
  101. DBG_ASSERT( hHash != CRYPT_NULL );
  102. //
  103. // Short-circuit if cryptography is disabled.
  104. //
  105. if( !IcpGlobals.EnableCryptography ) {
  106. if( hHash == DUMMY_HHASH ) {
  107. return NO_ERROR;
  108. } else {
  109. return RETURNCODETOHRESULT( ERROR_INVALID_PARAMETER );
  110. }
  111. }
  112. //
  113. // Destroy it.
  114. //
  115. if( CryptDestroyHash(
  116. hHash
  117. ) ) {
  118. UpdateHashDestroyed();
  119. return NO_ERROR;
  120. }
  121. return IcpGetLastError();
  122. } // IISCryptoDestroyHash
  123. HRESULT
  124. WINAPI
  125. IISCryptoHashData(
  126. IN HCRYPTHASH hHash,
  127. IN PVOID pBuffer,
  128. IN DWORD dwBufferLength
  129. )
  130. /*++
  131. Routine Description:
  132. This routine adds the specified data to the hash.
  133. Arguments:
  134. hHash - A hash object handle.
  135. pBuffer - Pointer to the buffer to add to the hash.
  136. dwBufferLength - The buffer length.
  137. Return Value:
  138. HRESULT - Completion status, 0 if successful, !0 otherwise.
  139. --*/
  140. {
  141. //
  142. // Sanity check.
  143. //
  144. DBG_ASSERT( IcpGlobals.Initialized );
  145. DBG_ASSERT( hHash != CRYPT_NULL );
  146. DBG_ASSERT( pBuffer != NULL );
  147. DBG_ASSERT( dwBufferLength > 0 );
  148. //
  149. // Short-circuit if cryptography is disabled.
  150. //
  151. if( !IcpGlobals.EnableCryptography ) {
  152. if( hHash == DUMMY_HHASH ) {
  153. return NO_ERROR;
  154. } else {
  155. return RETURNCODETOHRESULT( ERROR_INVALID_PARAMETER );
  156. }
  157. }
  158. //
  159. // Hash it.
  160. //
  161. if( CryptHashData(
  162. hHash,
  163. (BYTE *)pBuffer,
  164. dwBufferLength,
  165. 0
  166. ) ) {
  167. return NO_ERROR;
  168. }
  169. return IcpGetLastError();
  170. } // IISCryptoHashData
  171. HRESULT
  172. WINAPI
  173. IISCryptoHashSessionKey(
  174. IN HCRYPTHASH hHash,
  175. IN HCRYPTKEY hSessionKey
  176. )
  177. /*++
  178. Routine Description:
  179. This routine adds the given key object to the hash.
  180. Arguments:
  181. hHash - A hash object handle.
  182. hSessionKey - The session key to add to the hash.
  183. Return Value:
  184. HRESULT - Completion status, 0 if successful, !0 otherwise.
  185. --*/
  186. {
  187. //
  188. // Sanity check.
  189. //
  190. DBG_ASSERT( IcpGlobals.Initialized );
  191. DBG_ASSERT( hHash != CRYPT_NULL );
  192. DBG_ASSERT( hSessionKey != CRYPT_NULL );
  193. //
  194. // Short-circuit if cryptography is disabled.
  195. //
  196. if( !IcpGlobals.EnableCryptography ) {
  197. if( hHash == DUMMY_HHASH &&
  198. hSessionKey == DUMMY_HSESSIONKEY ) {
  199. return NO_ERROR;
  200. } else {
  201. return RETURNCODETOHRESULT( ERROR_INVALID_PARAMETER );
  202. }
  203. }
  204. //
  205. // Hash it.
  206. //
  207. if( CryptHashSessionKey(
  208. hHash,
  209. hSessionKey,
  210. 0
  211. ) ) {
  212. return NO_ERROR;
  213. }
  214. return IcpGetLastError();
  215. } // IISCryptoHashSessionKey
  216. HRESULT
  217. WINAPI
  218. IISCryptoExportHashBlob(
  219. OUT PIIS_CRYPTO_BLOB * ppHashBlob,
  220. IN HCRYPTHASH hHash
  221. )
  222. /*++
  223. Routine Description:
  224. This routine exports a hash object into a hash blob. Note that unlike
  225. the other blobs created by this package, hash blobs are not encrypted,
  226. nor do they have corresponding digital signatures.
  227. Arguments:
  228. ppHashBlob - Will receive a pointer to the newly created hash blob
  229. if successful.
  230. hHash - The hash object to export.
  231. Return Value:
  232. HRESULT - Completion status, 0 if successful, !0 otherwise.
  233. --*/
  234. {
  235. HRESULT result;
  236. DWORD hashLength;
  237. DWORD hashLengthLength;
  238. PIC_BLOB blob;
  239. //
  240. // Sanity check.
  241. //
  242. DBG_ASSERT( IcpGlobals.Initialized );
  243. DBG_ASSERT( ppHashBlob != NULL );
  244. DBG_ASSERT( hHash != CRYPT_NULL );
  245. //
  246. // Short-circuit if cryptography is disabled.
  247. //
  248. if( !IcpGlobals.EnableCryptography ) {
  249. if( hHash == DUMMY_HHASH ) {
  250. return IISCryptoCreateCleartextBlob(
  251. ppHashBlob,
  252. (PVOID)"",
  253. 1
  254. );
  255. } else {
  256. return RETURNCODETOHRESULT( ERROR_INVALID_PARAMETER );
  257. }
  258. }
  259. //
  260. // Setup our locals so we know how to cleanup on exit.
  261. //
  262. blob = NULL;
  263. //
  264. // Determine the length of the hash.
  265. //
  266. hashLengthLength = sizeof(hashLength);
  267. if( !CryptGetHashParam(
  268. hHash,
  269. HP_HASHSIZE,
  270. (BYTE *)&hashLength,
  271. &hashLengthLength,
  272. 0
  273. ) ) {
  274. result = IcpGetLastError();
  275. goto fatal;
  276. }
  277. //
  278. // Create a new blob.
  279. //
  280. blob = IcpCreateBlob(
  281. HASH_BLOB_SIGNATURE,
  282. hashLength,
  283. 0
  284. );
  285. if( blob == NULL ) {
  286. result = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  287. goto fatal;
  288. }
  289. //
  290. // Get the hash data.
  291. //
  292. if( !CryptGetHashParam(
  293. hHash,
  294. HP_HASHVAL,
  295. BLOB_TO_DATA(blob),
  296. &hashLength,
  297. 0
  298. ) ) {
  299. result = IcpGetLastError();
  300. goto fatal;
  301. }
  302. DBG_ASSERT( hashLength == blob->DataLength );
  303. //
  304. // Success!
  305. //
  306. DBG_ASSERT( IISCryptoIsValidBlob( (PIIS_CRYPTO_BLOB)blob ) );
  307. *ppHashBlob = (PIIS_CRYPTO_BLOB)blob;
  308. UpdateBlobsCreated();
  309. return NO_ERROR;
  310. fatal:
  311. if( blob != NULL ) {
  312. IcpFreeMemory( blob );
  313. }
  314. DBG_ASSERT( FAILED(result) );
  315. return result;
  316. } // IISCryptoExportHashBlob
  317. IIS_CRYPTO_API
  318. HRESULT
  319. WINAPI
  320. IISCryptoCacheHashLength(
  321. IN HCRYPTPROV hProv
  322. )
  323. /*++
  324. Routine Description:
  325. This routine calls IcpGetHashLength to cache the hash size.
  326. Arguments:
  327. hProv - A handle to a crypto service provider.
  328. Return Value:
  329. HRESULT
  330. --*/
  331. {
  332. DWORD dwDummy = 0;
  333. return IcpGetHashLength( &dwDummy, hProv );
  334. }
  335. HRESULT
  336. IcpGetHashLength(
  337. OUT LPDWORD pdwHashLength,
  338. IN HCRYPTPROV hProv
  339. )
  340. /*++
  341. Routine Description:
  342. This routine determines the digital signature length used by the
  343. given provider. Since we always use the default provider, and
  344. we always use the same hash algorithm, we can retrieve this once,
  345. store it globally, then use that value.
  346. Arguments:
  347. pdwHashLength - Receives the hash length if successful.
  348. hProv - A handle to a crypto service provider.
  349. Return Value:
  350. HRESULT - Completion status, 0 if successful, !0 otherwise.
  351. --*/
  352. {
  353. HRESULT result;
  354. HCRYPTHASH hash;
  355. //
  356. // Sanity check.
  357. //
  358. DBG_ASSERT( IcpGlobals.Initialized );
  359. DBG_ASSERT( IcpGlobals.EnableCryptography );
  360. DBG_ASSERT( pdwHashLength != NULL );
  361. DBG_ASSERT( hProv != CRYPT_NULL );
  362. //
  363. // If the hash length has already been calculated, just use it.
  364. //
  365. if( IcpGlobals.HashLength > 0 ) {
  366. *pdwHashLength = IcpGlobals.HashLength;
  367. return NO_ERROR;
  368. }
  369. //
  370. // Grab the global lock, then check again, just in case another
  371. // thread has already done it.
  372. //
  373. IcpAcquireGlobalLock();
  374. if( IcpGlobals.HashLength > 0 ) {
  375. *pdwHashLength = IcpGlobals.HashLength;
  376. IcpReleaseGlobalLock();
  377. return NO_ERROR;
  378. }
  379. //
  380. // Setup our locals so we know how to cleanup on exit.
  381. //
  382. hash = CRYPT_NULL;
  383. //
  384. // Create a hash object.
  385. //
  386. result = IISCryptoCreateHash(
  387. &hash,
  388. hProv
  389. );
  390. if( FAILED(result) ) {
  391. goto fatal;
  392. }
  393. //
  394. // Hash some random data.
  395. //
  396. if( !CryptHashData(
  397. hash,
  398. (BYTE *)"IIS",
  399. 4,
  400. 0
  401. ) ) {
  402. result = IcpGetLastError();
  403. goto fatal;
  404. }
  405. //
  406. // Attempt to sign the hash to get its length.
  407. //
  408. if( !CryptSignHash(
  409. hash,
  410. AT_SIGNATURE,
  411. NULL,
  412. 0,
  413. NULL,
  414. &IcpGlobals.HashLength
  415. ) ) {
  416. result = IcpGetLastError();
  417. goto fatal;
  418. }
  419. //
  420. // Success!
  421. //
  422. *pdwHashLength = IcpGlobals.HashLength;
  423. IcpReleaseGlobalLock();
  424. DBG_REQUIRE( SUCCEEDED( IISCryptoDestroyHash( hash ) ) );
  425. return NO_ERROR;
  426. fatal:
  427. if( hash != CRYPT_NULL ) {
  428. DBG_REQUIRE( SUCCEEDED( IISCryptoDestroyHash( hash ) ) );
  429. }
  430. IcpReleaseGlobalLock();
  431. DBG_ASSERT( FAILED(result) );
  432. return result;
  433. } // IcpGetHashLength
  434. //
  435. // Private functions.
  436. //