Source code of Windows XP (NT5)
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.

1725 lines
42 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // FILE : nt_hash.c //
  3. // DESCRIPTION : Crypto CP interfaces: //
  4. // CPBeginHash //
  5. // CPUpdateHash //
  6. // CPDestroyHash //
  7. // AUTHOR : //
  8. // HISTORY : //
  9. // Jan 25 1995 larrys Changed from Nametag //
  10. // Feb 23 1995 larrys Changed NTag_SetLastError to SetLastError //
  11. // May 8 1995 larrys Changes for MAC hashing //
  12. // May 10 1995 larrys added private api calls //
  13. // Jul 13 1995 larrys Changed MAC stuff //
  14. // Aug 07 1995 larrys Added Auto-Inflate to CryptBeginHash //
  15. // Aug 30 1995 larrys Removed RETURNASHVALUE from CryptGetHashValue //
  16. // Sep 19 1995 larrys changed USERDATA to CRYPT_USERDATA //
  17. // Oct 03 1995 larrys check for 0 on Createhash for hKey //
  18. // Oct 05 1995 larrys Changed HashSessionKey to hash key material //
  19. // Oct 13 1995 larrys Removed CPGetHashValue //
  20. // Oct 17 1995 larrys Added MD2 //
  21. // Nov 3 1995 larrys Merge for NT checkin //
  22. // Nov 14 1995 larrys Fixed memory leak //
  23. // Mar 01 1996 rajeshk Added check for Hash Values //
  24. // May 15 1996 larrys Changed NTE_NO_MEMORY to ERROR_NOT_ENOUGHT... //
  25. // Jun 6 1996 a-johnb Added support for SSL 3.0 signatures //
  26. // Apr 25 1997 jeffspel Fix for Bug 76393, GPF on pbData = NULL //
  27. // May 23 1997 jeffspel Added provider type checking //
  28. // //
  29. // Copyright (C) 1993 Microsoft Corporation All Rights Reserved //
  30. /////////////////////////////////////////////////////////////////////////////
  31. #include "precomp.h"
  32. #include "nt_rsa.h"
  33. #include "tripldes.h"
  34. #include "mac.h"
  35. #include "ssl3.h"
  36. #include "aes.h"
  37. extern BOOL
  38. FIsLegalKey(
  39. PNTAGUserList pTmpUser,
  40. PNTAGKeyList pKey,
  41. BOOL fRC2BigKeyOK);
  42. extern DWORD
  43. InflateKey(
  44. IN PNTAGKeyList pTmpKey);
  45. extern DWORD
  46. BlockEncrypt(
  47. void EncFun(BYTE *In, BYTE *Out, void *key, int op),
  48. PNTAGKeyList pKey,
  49. int BlockLen,
  50. BOOL Final,
  51. BYTE *pbData,
  52. DWORD *pdwDataLen,
  53. DWORD dwBufLen);
  54. extern DWORD
  55. LocalGetHashVal(
  56. IN ALG_ID Algid,
  57. IN DWORD dwHashFlags,
  58. IN OUT BYTE *pbHashData,
  59. OUT BYTE *pbHashVal,
  60. OUT DWORD *pcbHashVal);
  61. #ifdef CSP_USE_MD5
  62. //
  63. // Function : TestMD5
  64. //
  65. // Description : This function hashes the passed in message with the MD5 hash
  66. // algorithm and returns the resulting hash value.
  67. //
  68. BOOL
  69. TestMD5(
  70. BYTE *pbMsg,
  71. DWORD cbMsg,
  72. BYTE *pbHash)
  73. {
  74. MD5_CTX MD5;
  75. BOOL fRet = FALSE;
  76. // Check length for input data
  77. if (0 == cbMsg)
  78. goto ErrorExit;
  79. // Initialize MD5
  80. MD5Init(&MD5);
  81. // Compute MD5
  82. MD5Update(&MD5, pbMsg, cbMsg);
  83. MD5Final(&MD5);
  84. memcpy(pbHash, MD5.digest, MD5DIGESTLEN);
  85. fRet = TRUE;
  86. ErrorExit:
  87. return fRet;
  88. }
  89. #endif // CSP_USE_MD5
  90. #ifdef CSP_USE_SHA1
  91. //
  92. // Function : TestSHA1
  93. //
  94. // Description : This function hashes the passed in message with the SHA1 hash
  95. // algorithm and returns the resulting hash value.
  96. //
  97. BOOL
  98. TestSHA1(
  99. BYTE *pbMsg,
  100. DWORD cbMsg,
  101. BYTE *pbHash)
  102. {
  103. A_SHA_CTX HashContext;
  104. BOOL fRet = FALSE;
  105. // Check length for input data
  106. if (0 == cbMsg)
  107. goto ErrorExit;
  108. // Initialize SHA
  109. A_SHAInit(&HashContext);
  110. // Compute SHA
  111. A_SHAUpdate(&HashContext, pbMsg, cbMsg);
  112. A_SHAFinal(&HashContext, pbHash);
  113. fRet = TRUE;
  114. ErrorExit:
  115. return fRet;
  116. }
  117. #endif // CSP_USE_SHA1
  118. BOOL
  119. ValidHashAlgid(
  120. PNTAGUserList pTmpUser,
  121. ALG_ID Algid)
  122. {
  123. if ((PROV_RSA_SCHANNEL == pTmpUser->dwProvType) &&
  124. ((CALG_MD2 == Algid) || (CALG_MD4 == Algid)))
  125. return FALSE;
  126. else
  127. return TRUE;
  128. }
  129. // local function for creating hashes
  130. DWORD
  131. LocalCreateHash(
  132. IN ALG_ID Algid,
  133. OUT BYTE **ppbHashData,
  134. OUT DWORD *pcbHashData)
  135. {
  136. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  137. switch (Algid)
  138. {
  139. #ifdef CSP_USE_MD2
  140. case CALG_MD2:
  141. {
  142. MD2_object *pMD2Hash;
  143. pMD2Hash = (MD2_object *)_nt_malloc(sizeof(MD2_object));
  144. if (NULL == pMD2Hash)
  145. {
  146. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  147. goto ErrorExit;
  148. }
  149. // Set up the Initial MD2 Hash State
  150. memset ((BYTE *)pMD2Hash, 0, sizeof(MD2_object));
  151. pMD2Hash->FinishFlag = FALSE;
  152. *pcbHashData = sizeof(MD2_object);
  153. *ppbHashData = (LPBYTE)pMD2Hash;
  154. break;
  155. }
  156. #endif
  157. #ifdef CSP_USE_MD4
  158. case CALG_MD4:
  159. {
  160. MD4_object *pMD4Hash;
  161. pMD4Hash = (MD4_object *)_nt_malloc(sizeof(MD4_object));
  162. if (NULL == pMD4Hash)
  163. {
  164. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  165. goto ErrorExit;
  166. }
  167. // Set up the Initial MD4 Hash State
  168. memset ((BYTE *)pMD4Hash, 0, sizeof(MD4_object));
  169. pMD4Hash->FinishFlag = FALSE;
  170. MDbegin(&pMD4Hash->MD);
  171. *pcbHashData = sizeof(MD4_object);
  172. *ppbHashData = (BYTE*)pMD4Hash;
  173. break;
  174. }
  175. #endif
  176. #ifdef CSP_USE_MD5
  177. case CALG_MD5:
  178. {
  179. MD5_object *pMD5Hash;
  180. pMD5Hash = (MD5_object *)_nt_malloc(sizeof(MD5_object));
  181. if (NULL == pMD5Hash)
  182. {
  183. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  184. goto ErrorExit;
  185. }
  186. // Set up the our state
  187. pMD5Hash->FinishFlag = FALSE;
  188. MD5Init(pMD5Hash);
  189. *ppbHashData = (BYTE*)pMD5Hash;
  190. *pcbHashData = sizeof(MD5_object);
  191. break;
  192. }
  193. #endif
  194. #ifdef CSP_USE_SHA
  195. case CALG_SHA:
  196. {
  197. A_SHA_CTX *pSHAHash;
  198. pSHAHash = (A_SHA_CTX *)_nt_malloc(sizeof(A_SHA_CTX));
  199. if (NULL == pSHAHash)
  200. {
  201. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  202. goto ErrorExit;
  203. }
  204. // Set up our state
  205. A_SHAInit(pSHAHash);
  206. pSHAHash->FinishFlag = FALSE;
  207. *ppbHashData = (BYTE*)pSHAHash;
  208. *pcbHashData = sizeof(A_SHA_CTX);
  209. break;
  210. }
  211. #endif
  212. default:
  213. dwReturn = (DWORD)NTE_BAD_ALGID;
  214. goto ErrorExit;
  215. }
  216. dwReturn = ERROR_SUCCESS;
  217. ErrorExit:
  218. return dwReturn;
  219. }
  220. /*
  221. - CPBeginHash
  222. -
  223. * Purpose:
  224. * initate the hashing of a stream of data
  225. *
  226. *
  227. * Parameters:
  228. * IN hUID - Handle to the user identifcation
  229. * IN Algid - Algorithm identifier of the hash algorithm
  230. * to be used
  231. * IN hKey - Optional key for MAC algorithms
  232. * IN dwFlags - Flags values
  233. * OUT pHash - Handle to hash object
  234. *
  235. * Returns:
  236. */
  237. BOOL WINAPI
  238. CPCreateHash(
  239. IN HCRYPTPROV hUID,
  240. IN ALG_ID Algid,
  241. IN HCRYPTKEY hKey,
  242. IN DWORD dwFlags,
  243. OUT HCRYPTHASH *phHash)
  244. {
  245. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  246. PNTAGUserList pTmpUser;
  247. PNTAGHashList pCurrentHash = NULL;
  248. PNTAGKeyList pTmpKey;
  249. #ifdef CSP_USE_SSL3
  250. PSCH_HASH pSChHash;
  251. #endif // CSP_USE_SSL3
  252. BOOL fRet;
  253. DWORD dwSts;
  254. EntryPoint
  255. if (dwFlags != 0)
  256. {
  257. dwReturn = (DWORD)NTE_BAD_FLAGS;
  258. goto ErrorExit;
  259. }
  260. // check if the user handle is valid
  261. pTmpUser = NTLCheckList(hUID, USER_HANDLE);
  262. if (NULL == pTmpUser)
  263. {
  264. dwReturn = (DWORD)NTE_BAD_UID;
  265. goto ErrorExit;
  266. }
  267. if (!ValidHashAlgid(pTmpUser, Algid))
  268. {
  269. dwReturn = (DWORD)NTE_BAD_ALGID;
  270. goto ErrorExit;
  271. }
  272. // Prepare the structure to be used as the hash handle
  273. pCurrentHash = (PNTAGHashList)_nt_malloc(sizeof(NTAGHashList));
  274. if (NULL == pCurrentHash)
  275. {
  276. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  277. goto ErrorExit;
  278. }
  279. memset(pCurrentHash, 0, sizeof(NTAGHashList));
  280. pCurrentHash->Algid = Algid;
  281. pCurrentHash->hUID = hUID;
  282. // determine which hash algorithm is to be used
  283. switch (Algid)
  284. {
  285. #ifdef CSP_USE_MAC
  286. case CALG_MAC:
  287. {
  288. MACstate *pMACVal;
  289. if (hKey == 0)
  290. {
  291. dwReturn = (DWORD)NTE_BAD_KEY;
  292. goto ErrorExit;
  293. }
  294. dwSts = NTLValidate(hKey, hUID, KEY_HANDLE, &pTmpKey);
  295. if (ERROR_SUCCESS != dwSts)
  296. {
  297. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_KEY : dwSts;
  298. goto ErrorExit;
  299. }
  300. if (pTmpKey->Mode != CRYPT_MODE_CBC)
  301. {
  302. dwReturn = (DWORD)NTE_BAD_KEY;
  303. goto ErrorExit;
  304. }
  305. // Check if we should do an auto-inflate
  306. if (pTmpKey->pData == NULL)
  307. {
  308. dwSts = InflateKey(pTmpKey);
  309. if (ERROR_SUCCESS != dwSts)
  310. {
  311. dwReturn = dwSts;
  312. goto ErrorExit;
  313. }
  314. }
  315. pMACVal = (MACstate *)_nt_malloc(sizeof(MACstate));
  316. if (NULL == pMACVal)
  317. {
  318. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  319. goto ErrorExit;
  320. }
  321. pCurrentHash->pHashData = pMACVal;
  322. pCurrentHash->dwDataLen = sizeof(MACstate);
  323. pCurrentHash->hKey = hKey;
  324. pMACVal->dwBufLen = 0;
  325. pMACVal->FinishFlag = FALSE;
  326. break;
  327. }
  328. #endif
  329. case CALG_HMAC:
  330. {
  331. if (hKey == 0)
  332. {
  333. dwReturn = (DWORD)NTE_BAD_KEY;
  334. goto ErrorExit;
  335. }
  336. dwSts = NTLValidate(hKey, hUID, KEY_HANDLE, &pTmpKey);
  337. if (ERROR_SUCCESS != dwSts)
  338. {
  339. dwReturn = (NTE_FAIL == dwSts) ? (DWORD)NTE_BAD_KEY : dwSts;
  340. goto ErrorExit;
  341. }
  342. pCurrentHash->hKey = hKey;
  343. break;
  344. }
  345. #ifdef CSP_USE_SSL3SHAMD5
  346. case CALG_SSL3_SHAMD5:
  347. {
  348. pCurrentHash->pHashData = _nt_malloc(SSL3_SHAMD5_LEN);
  349. if (NULL == pCurrentHash->pHashData)
  350. {
  351. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  352. goto ErrorExit;
  353. }
  354. pCurrentHash->dwDataLen = SSL3_SHAMD5_LEN;
  355. break;
  356. }
  357. #endif
  358. #ifdef CSP_USE_SSL3
  359. case CALG_SCHANNEL_MASTER_HASH:
  360. {
  361. if (0 == hKey)
  362. {
  363. dwReturn = (DWORD)NTE_BAD_KEY;
  364. goto ErrorExit;
  365. }
  366. dwSts = NTLValidate(hKey, hUID, KEY_HANDLE, &pTmpKey);
  367. if (ERROR_SUCCESS != dwSts)
  368. {
  369. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_KEY : dwSts;
  370. goto ErrorExit;
  371. }
  372. if ((CALG_SSL3_MASTER != pTmpKey->Algid) &&
  373. (CALG_PCT1_MASTER != pTmpKey->Algid) &&
  374. (pTmpKey->cbKeyLen > MAX_PREMASTER_LEN))
  375. {
  376. dwReturn = (DWORD)NTE_BAD_KEY;
  377. goto ErrorExit;
  378. }
  379. pCurrentHash->dwDataLen = sizeof(SCH_HASH);
  380. pCurrentHash->pHashData = (BYTE *)_nt_malloc(pCurrentHash->dwDataLen);
  381. if (NULL == pCurrentHash->pHashData)
  382. {
  383. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  384. goto ErrorExit;
  385. }
  386. memset(pCurrentHash->pHashData, 0, pCurrentHash->dwDataLen);
  387. pSChHash = (PSCH_HASH)pCurrentHash->pHashData;
  388. pSChHash->ProtocolAlgid = pTmpKey->Algid;
  389. dwSts = SChGenMasterKey(pTmpKey, pSChHash);
  390. if (ERROR_SUCCESS != dwSts)
  391. {
  392. dwReturn = dwSts;
  393. goto ErrorExit;
  394. }
  395. break;
  396. }
  397. case CALG_TLS1PRF:
  398. {
  399. PRF_HASH *pPRFHash;
  400. PSCH_KEY pSChKey;
  401. if (0 == hKey)
  402. {
  403. dwReturn = (DWORD)NTE_BAD_KEY;
  404. goto ErrorExit;
  405. }
  406. dwSts = NTLValidate(hKey, hUID, KEY_HANDLE, &pTmpKey);
  407. if (ERROR_SUCCESS != dwSts)
  408. {
  409. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_KEY : dwSts;
  410. goto ErrorExit;
  411. }
  412. if (CALG_TLS1_MASTER != pTmpKey->Algid)
  413. {
  414. dwReturn = (DWORD)NTE_BAD_KEY;
  415. goto ErrorExit;
  416. }
  417. // check if the master key is finished
  418. pSChKey = (PSCH_KEY)pTmpKey->pData;
  419. if ((!pSChKey->fFinished) || (TLS_MASTER_LEN != pTmpKey->cbKeyLen))
  420. {
  421. dwReturn = (DWORD)NTE_BAD_KEY_STATE;
  422. goto ErrorExit;
  423. }
  424. pCurrentHash->dwDataLen = sizeof(PRF_HASH);
  425. pCurrentHash->pHashData = (BYTE *)_nt_malloc(pCurrentHash->dwDataLen);
  426. if (NULL == pCurrentHash->pHashData)
  427. {
  428. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  429. goto ErrorExit;
  430. }
  431. memset(pCurrentHash->pHashData, 0, pCurrentHash->dwDataLen);
  432. pPRFHash = (PRF_HASH*)pCurrentHash->pHashData;
  433. memcpy(pPRFHash->rgbMasterKey, pTmpKey->pKeyValue, TLS_MASTER_LEN);
  434. break;
  435. }
  436. #endif // CSP_USE_SSL3
  437. default:
  438. if (hKey != 0)
  439. {
  440. dwReturn = NTE_BAD_KEY;
  441. goto ErrorExit;
  442. }
  443. dwSts = LocalCreateHash(Algid, (BYTE**)&pCurrentHash->pHashData,
  444. &pCurrentHash->dwDataLen);
  445. if (ERROR_SUCCESS != dwSts)
  446. {
  447. dwReturn = dwSts;
  448. goto ErrorExit;
  449. }
  450. }
  451. dwSts = NTLMakeItem(phHash, HASH_HANDLE, pCurrentHash);
  452. if (ERROR_SUCCESS != dwSts)
  453. {
  454. dwReturn = dwSts;
  455. goto ErrorExit;
  456. }
  457. dwReturn = ERROR_SUCCESS;
  458. ErrorExit:
  459. fRet = (ERROR_SUCCESS == dwReturn);
  460. if (!fRet)
  461. {
  462. if (NULL != pCurrentHash)
  463. {
  464. if (pCurrentHash->pHashData)
  465. _nt_free(pCurrentHash->pHashData, pCurrentHash->dwDataLen);
  466. _nt_free(pCurrentHash, sizeof(NTAGHashList));
  467. }
  468. SetLastError(dwReturn);
  469. }
  470. return fRet;
  471. }
  472. DWORD
  473. LocalHashData(
  474. IN ALG_ID Algid,
  475. IN OUT BYTE *pbHashData,
  476. IN BYTE *pbData,
  477. IN DWORD cbData)
  478. {
  479. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  480. BYTE *ptmp;
  481. DWORD BytePos;
  482. switch (Algid)
  483. {
  484. #ifdef CSP_USE_MD2
  485. case CALG_MD2:
  486. {
  487. MD2_object *pMD2Hash;
  488. // make sure the hash is updatable
  489. pMD2Hash = (MD2_object *)pbHashData;
  490. if (pMD2Hash->FinishFlag)
  491. {
  492. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  493. goto ErrorExit;
  494. }
  495. if (0 != MD2Update(&pMD2Hash->MD, pbData, cbData))
  496. {
  497. // This is a reasonable return code, since currently
  498. // the only value MD2Update returns is zero.
  499. dwReturn = (DWORD)NTE_FAIL;
  500. goto ErrorExit;
  501. }
  502. break;
  503. }
  504. #endif
  505. #ifdef CSP_USE_MD4
  506. case CALG_MD4:
  507. {
  508. MD4_object *pMD4Hash;
  509. int nSts;
  510. pMD4Hash = (MD4_object *)pbHashData;
  511. // make sure the hash is updatable
  512. if (pMD4Hash->FinishFlag)
  513. {
  514. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  515. goto ErrorExit;
  516. }
  517. // MD4 hashes when the size == MD4BLOCKSIZE and finishes the
  518. // hash when the given size is < MD4BLOCKSIZE.
  519. // So, ensure that the user always gives a full block here --
  520. // when NTagFinishHash is called, we'll send the last bit and
  521. // that'll finish off the hash.
  522. ptmp = (BYTE *)pbData;
  523. for (;;)
  524. {
  525. // check if there's plenty of room in the buffer
  526. if (cbData < (MD4BLOCKSIZE - pMD4Hash->BufLen))
  527. {
  528. // just append to whatever's already
  529. memcpy(pMD4Hash->Buf + pMD4Hash->BufLen, ptmp, cbData);
  530. // set of the trailing buffer length field
  531. pMD4Hash->BufLen += (BYTE)cbData;
  532. break;
  533. }
  534. // determine what we need to fill the buffer, then do it.
  535. BytePos = MD4BLOCKSIZE - pMD4Hash->BufLen;
  536. ASSERT(BytePos <= dwTmpLen);
  537. memcpy(pMD4Hash->Buf + pMD4Hash->BufLen, ptmp, BytePos);
  538. // The buffer is now full, process it.
  539. nSts = MDupdate(&pMD4Hash->MD, pMD4Hash->Buf,
  540. MD4BYTESTOBITS(MD4BLOCKSIZE));
  541. if (MD4_SUCCESS != nSts)
  542. {
  543. dwReturn = (DWORD)NTE_FAIL;
  544. goto ErrorExit;
  545. }
  546. // now it's empty.
  547. pMD4Hash->BufLen = 0;
  548. // we processed some bytes, so reflect that and try again
  549. cbData -= BytePos;
  550. ptmp += BytePos;
  551. if (cbData == 0)
  552. break;
  553. }
  554. break;
  555. }
  556. #endif
  557. #ifdef CSP_USE_MD5
  558. case CALG_MD5:
  559. {
  560. MD5_object *pMD5Hash;
  561. // make sure the hash is updatable
  562. pMD5Hash = (MD5_object *)pbHashData;
  563. if (pMD5Hash->FinishFlag)
  564. {
  565. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  566. goto ErrorExit;
  567. }
  568. MD5Update(pMD5Hash, pbData, cbData);
  569. break;
  570. }
  571. #endif
  572. #ifdef CSP_USE_SHA
  573. case CALG_SHA:
  574. {
  575. A_SHA_CTX *pSHAHash;
  576. // make sure the hash is updatable
  577. pSHAHash = (A_SHA_CTX *)pbHashData;
  578. if (pSHAHash->FinishFlag)
  579. {
  580. dwReturn = (DWORD) NTE_BAD_HASH_STATE;
  581. goto ErrorExit;
  582. }
  583. A_SHAUpdate(pSHAHash, pbData, cbData);
  584. break;
  585. }
  586. #endif
  587. default:
  588. dwReturn = (DWORD)NTE_BAD_ALGID;
  589. goto ErrorExit;
  590. }
  591. dwReturn = ERROR_SUCCESS;
  592. ErrorExit:
  593. return dwReturn;
  594. }
  595. /*static*/ DWORD
  596. LocalMACData(
  597. IN HCRYPTPROV hUID,
  598. IN PNTAGHashList pTmpHash,
  599. IN CONST BYTE *pbData,
  600. IN DWORD cbData)
  601. {
  602. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  603. MACstate *pMAC;
  604. PNTAGKeyList pTmpKey;
  605. BYTE *pbTmp;
  606. DWORD dwTmpLen;
  607. BYTE *pb = NULL;
  608. DWORD cb;
  609. DWORD i;
  610. BYTE *pbJunk = NULL;
  611. DWORD dwBufSlop;
  612. DWORD dwEncLen;
  613. DWORD dwSts;
  614. PBYTE pbKeyHash = NULL;
  615. DWORD cbKeyHash = 0;
  616. dwTmpLen = cbData;
  617. pbTmp = (BYTE *) pbData;
  618. switch (pTmpHash->Algid)
  619. {
  620. #ifdef CSP_USE_MAC
  621. case CALG_MAC:
  622. {
  623. pMAC = (MACstate *)pTmpHash->pHashData;
  624. // make sure the hash is updatable
  625. if (pMAC->FinishFlag)
  626. {
  627. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  628. goto ErrorExit;
  629. }
  630. dwSts = NTLValidate(pTmpHash->hKey, hUID, KEY_HANDLE, &pTmpKey);
  631. if (ERROR_SUCCESS != dwSts)
  632. {
  633. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_KEY : dwSts;
  634. goto ErrorExit;
  635. }
  636. if (pMAC->dwBufLen + dwTmpLen <= pTmpKey->dwBlockLen)
  637. {
  638. memcpy(pMAC->Buffer + pMAC->dwBufLen, pbTmp, dwTmpLen);
  639. pMAC->dwBufLen += dwTmpLen;
  640. dwReturn = ERROR_SUCCESS;
  641. goto ErrorExit;
  642. }
  643. memcpy(pMAC->Buffer+pMAC->dwBufLen, pbTmp,
  644. (pTmpKey->dwBlockLen - pMAC->dwBufLen));
  645. dwTmpLen -= (pTmpKey->dwBlockLen - pMAC->dwBufLen);
  646. pbTmp += (pTmpKey->dwBlockLen - pMAC->dwBufLen);
  647. pMAC->dwBufLen = pTmpKey->dwBlockLen;
  648. switch (pTmpKey->Algid)
  649. {
  650. case CALG_RC2:
  651. dwSts = BlockEncrypt(RC2, pTmpKey, RC2_BLOCKLEN, FALSE,
  652. pMAC->Buffer, &pMAC->dwBufLen,
  653. MAX_BLOCKLEN);
  654. if (ERROR_SUCCESS != dwSts)
  655. {
  656. dwReturn = dwSts;
  657. goto ErrorExit;
  658. }
  659. break;
  660. case CALG_DES:
  661. dwSts = BlockEncrypt(des, pTmpKey, DES_BLOCKLEN, FALSE,
  662. pMAC->Buffer, &pMAC->dwBufLen,
  663. MAX_BLOCKLEN);
  664. if (ERROR_SUCCESS != dwSts)
  665. {
  666. dwReturn = dwSts;
  667. goto ErrorExit;
  668. }
  669. break;
  670. #ifdef CSP_USE_3DES
  671. case CALG_3DES_112:
  672. case CALG_3DES:
  673. dwSts = BlockEncrypt(tripledes, pTmpKey, DES_BLOCKLEN,
  674. FALSE, pMAC->Buffer, &pMAC->dwBufLen,
  675. MAX_BLOCKLEN);
  676. if (ERROR_SUCCESS != dwSts)
  677. {
  678. dwReturn = dwSts;
  679. goto ErrorExit;
  680. }
  681. break;
  682. #endif
  683. #ifdef CSP_USE_AES
  684. case CALG_AES_128:
  685. case CALG_AES_192:
  686. case CALG_AES_256:
  687. dwSts = BlockEncrypt(aes, pTmpKey, pTmpKey->dwBlockLen,
  688. FALSE, pMAC->Buffer, &pMAC->dwBufLen,
  689. MAX_BLOCKLEN);
  690. if (ERROR_SUCCESS != dwSts)
  691. {
  692. dwReturn = dwSts;
  693. goto ErrorExit;
  694. }
  695. break;
  696. #endif
  697. }
  698. pMAC->dwBufLen = 0;
  699. dwBufSlop = dwTmpLen % pTmpKey->dwBlockLen;
  700. if (dwBufSlop == 0)
  701. {
  702. dwBufSlop = pTmpKey->dwBlockLen;
  703. }
  704. pbJunk = _nt_malloc(dwTmpLen);
  705. if (NULL == pbJunk)
  706. {
  707. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  708. goto ErrorExit;
  709. }
  710. memcpy(pbJunk, pbTmp, dwTmpLen - dwBufSlop);
  711. dwEncLen = dwTmpLen - dwBufSlop;
  712. switch (pTmpKey->Algid)
  713. {
  714. case CALG_RC2:
  715. dwSts = BlockEncrypt(RC2, pTmpKey, RC2_BLOCKLEN, FALSE,
  716. pbJunk, &dwEncLen, dwTmpLen);
  717. if (ERROR_SUCCESS != dwSts)
  718. {
  719. dwReturn = dwSts;
  720. goto ErrorExit;
  721. }
  722. break;
  723. case CALG_DES:
  724. dwSts = BlockEncrypt(des, pTmpKey, DES_BLOCKLEN, FALSE,
  725. pbJunk, &dwEncLen, dwTmpLen);
  726. if (ERROR_SUCCESS != dwSts)
  727. {
  728. dwReturn = dwSts;
  729. goto ErrorExit;
  730. }
  731. break;
  732. #ifdef CSP_USE_3DES
  733. case CALG_3DES_112:
  734. case CALG_3DES:
  735. dwSts = BlockEncrypt(tripledes, pTmpKey, DES_BLOCKLEN,
  736. FALSE, pbJunk, &dwEncLen, dwTmpLen);
  737. if (ERROR_SUCCESS != dwSts)
  738. {
  739. dwReturn = dwSts;
  740. goto ErrorExit;
  741. }
  742. break;
  743. #endif
  744. #ifdef CSP_USE_AES
  745. case CALG_AES_128:
  746. case CALG_AES_192:
  747. case CALG_AES_256:
  748. dwSts = BlockEncrypt(aes, pTmpKey, pTmpKey->dwBlockLen,
  749. FALSE, pbJunk, &dwEncLen, dwTmpLen);
  750. if (ERROR_SUCCESS != dwSts)
  751. {
  752. dwReturn = dwSts;
  753. goto ErrorExit;
  754. }
  755. break;
  756. #endif
  757. }
  758. memcpy(pMAC->Buffer, pbTmp + dwEncLen, dwBufSlop);
  759. pMAC->dwBufLen = dwBufSlop;
  760. break;
  761. }
  762. #endif
  763. case CALG_HMAC:
  764. {
  765. if (!(pTmpHash->HMACState & HMAC_STARTED))
  766. {
  767. dwSts = NTLValidate(pTmpHash->hKey, hUID,
  768. KEY_HANDLE, &pTmpKey);
  769. if (ERROR_SUCCESS != dwSts)
  770. {
  771. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_KEY : dwSts;
  772. goto ErrorExit;
  773. }
  774. // If key is longer than block length, hash the key
  775. // data first
  776. if (pTmpKey->cbKeyLen > HMAC_DEFAULT_STRING_LEN)
  777. {
  778. dwSts = LocalCreateHash(pTmpHash->HMACAlgid, &pbKeyHash, &cbKeyHash);
  779. if (ERROR_SUCCESS != dwSts)
  780. {
  781. dwReturn = dwSts;
  782. goto ErrorExit;
  783. }
  784. dwSts = LocalHashData(pTmpHash->HMACAlgid, pbKeyHash, pTmpKey->pKeyValue,
  785. pTmpKey->cbKeyLen);
  786. if (ERROR_SUCCESS != dwSts)
  787. {
  788. dwReturn = dwSts;
  789. goto ErrorExit;
  790. }
  791. pb = (BYTE *)_nt_malloc(HMAC_DEFAULT_STRING_LEN);
  792. if (NULL == pb)
  793. {
  794. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  795. goto ErrorExit;
  796. }
  797. cb = HMAC_DEFAULT_STRING_LEN;
  798. dwSts = LocalGetHashVal(pTmpHash->HMACAlgid, 0, pbKeyHash, pb, &cb);
  799. if (ERROR_SUCCESS != dwSts)
  800. {
  801. dwReturn = dwSts;
  802. goto ErrorExit;
  803. }
  804. for (i = 0; i < HMAC_DEFAULT_STRING_LEN; i++)
  805. pb[i] ^= (pTmpHash->pbHMACInner)[i];
  806. cb = HMAC_DEFAULT_STRING_LEN;
  807. }
  808. else
  809. {
  810. if (pTmpKey->cbKeyLen < pTmpHash->cbHMACInner)
  811. cb = pTmpHash->cbHMACInner;
  812. else
  813. cb = pTmpKey->cbKeyLen;
  814. pb = (BYTE *)_nt_malloc(cb);
  815. if (NULL == pb)
  816. {
  817. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  818. goto ErrorExit;
  819. }
  820. memcpy(pb, pTmpHash->pbHMACInner, pTmpHash->cbHMACInner);
  821. // currently no support for byte reversed keys with HMAC
  822. for (i=0;i<pTmpKey->cbKeyLen;i++)
  823. pb[i] ^= (pTmpKey->pKeyValue)[i];
  824. }
  825. dwSts = LocalHashData(pTmpHash->HMACAlgid, pTmpHash->pHashData,
  826. pb, cb);
  827. if (ERROR_SUCCESS != dwSts)
  828. {
  829. dwReturn = dwSts;
  830. goto ErrorExit;
  831. }
  832. pTmpHash->HMACState |= HMAC_STARTED;
  833. memnuke(pb, cb);
  834. memnuke(pbKeyHash, cbKeyHash);
  835. }
  836. dwSts = LocalHashData(pTmpHash->HMACAlgid, pTmpHash->pHashData,
  837. (BYTE*)pbData, cbData);
  838. if (ERROR_SUCCESS != dwSts)
  839. {
  840. dwReturn = dwSts;
  841. goto ErrorExit;
  842. }
  843. break;
  844. }
  845. default:
  846. dwReturn = (DWORD)NTE_BAD_ALGID;
  847. goto ErrorExit;
  848. }
  849. dwReturn = ERROR_SUCCESS;
  850. ErrorExit:
  851. if (pbJunk)
  852. _nt_free(pbJunk, dwTmpLen);
  853. if (pb)
  854. _nt_free(pb, cb);
  855. if (pbKeyHash)
  856. _nt_free(pbKeyHash, cbKeyHash);
  857. return dwReturn;
  858. }
  859. /*
  860. - CPHashData
  861. -
  862. * Purpose:
  863. * Compute the cryptograghic hash on a stream of data
  864. *
  865. *
  866. * Parameters:
  867. * IN hUID - Handle to the user identifcation
  868. * IN hHash - Handle to hash object
  869. * IN pbData - Pointer to data to be hashed
  870. * IN dwDataLen - Length of the data to be hashed
  871. * IN dwFlags - Flags values
  872. *
  873. * Returns:
  874. */
  875. BOOL WINAPI
  876. CPHashData(
  877. IN HCRYPTPROV hUID,
  878. IN HCRYPTHASH hHash,
  879. IN CONST BYTE *pbData,
  880. IN DWORD dwDataLen,
  881. IN DWORD dwFlags)
  882. {
  883. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  884. PNTAGHashList pTmpHash;
  885. PNTAGUserList pUser;
  886. BOOL fRet;
  887. DWORD dwSts;
  888. EntryPoint
  889. if (0 != (dwFlags & ~(CRYPT_USERDATA)))
  890. {
  891. dwReturn = (DWORD)NTE_BAD_FLAGS;
  892. goto ErrorExit;
  893. }
  894. pUser = (PNTAGUserList)NTLCheckList(hUID, USER_HANDLE);
  895. if (NULL == pUser)
  896. {
  897. dwReturn = (DWORD)NTE_BAD_UID;
  898. goto ErrorExit;
  899. }
  900. if (0 == dwDataLen)
  901. {
  902. dwReturn = ERROR_SUCCESS;
  903. goto ErrorExit;
  904. }
  905. if (NULL == pbData)
  906. {
  907. dwReturn = (DWORD)NTE_BAD_DATA;
  908. goto ErrorExit;
  909. }
  910. dwSts = NTLValidate(hHash, hUID, HASH_HANDLE, &pTmpHash);
  911. if (ERROR_SUCCESS != dwSts)
  912. {
  913. // NTLValidate doesn't know what error to set
  914. // so it set NTE_FAIL -- fix it up.
  915. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_HASH : dwSts;
  916. goto ErrorExit;
  917. }
  918. if (pTmpHash->HashFlags & HF_VALUE_SET)
  919. {
  920. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  921. goto ErrorExit;
  922. }
  923. switch (pTmpHash->Algid)
  924. {
  925. #ifdef CSP_USE_MAC
  926. case CALG_MAC:
  927. #endif // CSP_USE_MAC
  928. case CALG_HMAC:
  929. dwSts = LocalMACData(hUID, pTmpHash, pbData, dwDataLen);
  930. if (ERROR_SUCCESS != dwSts)
  931. {
  932. dwReturn = dwSts;
  933. goto ErrorExit;
  934. }
  935. break;
  936. default:
  937. dwSts = LocalHashData(pTmpHash->Algid, pTmpHash->pHashData,
  938. (BYTE*)pbData, dwDataLen);
  939. if (ERROR_SUCCESS != dwSts)
  940. {
  941. dwReturn = dwSts;
  942. goto ErrorExit;
  943. }
  944. }
  945. pTmpHash->dwHashState |= DATA_IN_HASH;
  946. dwReturn = ERROR_SUCCESS;
  947. ErrorExit:
  948. fRet = (ERROR_SUCCESS == dwReturn);
  949. if (!fRet)
  950. SetLastError(dwReturn);
  951. return fRet;
  952. }
  953. /*static*/ DWORD
  954. SetupKeyToBeHashed(
  955. PNTAGKeyList pKey,
  956. BYTE **ppbData,
  957. DWORD *pcbData,
  958. DWORD dwFlags)
  959. {
  960. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  961. DWORD cb;
  962. DWORD i;
  963. *ppbData = NULL;
  964. cb = pKey->cbKeyLen;
  965. *ppbData = (BYTE *)_nt_malloc(cb);
  966. if (NULL == *ppbData)
  967. {
  968. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  969. goto ErrorExit;
  970. }
  971. if (CRYPT_LITTLE_ENDIAN & dwFlags)
  972. {
  973. memcpy(*ppbData, pKey->pKeyValue, cb);
  974. }
  975. else
  976. {
  977. // Reverse the session key bytes
  978. for (i = 0; i < cb; i++)
  979. (*ppbData)[i] = (pKey->pKeyValue)[cb - i - 1];
  980. }
  981. *pcbData = cb;
  982. dwReturn = ERROR_SUCCESS;
  983. ErrorExit:
  984. return dwReturn;
  985. }
  986. /*
  987. - CPHashSessionKey
  988. -
  989. * Purpose:
  990. * Compute the cryptograghic hash on a key object.
  991. *
  992. *
  993. * Parameters:
  994. * IN hUID - Handle to the user identifcation
  995. * IN hHash - Handle to hash object
  996. * IN hKey - Handle to a key object
  997. * IN dwFlags - Flags values
  998. *
  999. * Returns:
  1000. * CRYPT_FAILED
  1001. * CRYPT_SUCCEED
  1002. */
  1003. BOOL WINAPI
  1004. CPHashSessionKey(
  1005. IN HCRYPTPROV hUID,
  1006. IN HCRYPTHASH hHash,
  1007. IN HCRYPTKEY hKey,
  1008. IN DWORD dwFlags)
  1009. {
  1010. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1011. PNTAGHashList pTmpHash;
  1012. PNTAGKeyList pTmpKey;
  1013. PNTAGUserList pTmpUser;
  1014. DWORD dwDataLen;
  1015. BYTE *pbData = NULL;
  1016. DWORD BytePos;
  1017. #ifdef CSP_USE_SSL3
  1018. PSCH_KEY pSChKey;
  1019. #endif // CSP_USE_SSL3
  1020. BOOL fRet;
  1021. DWORD dwSts;
  1022. EntryPoint
  1023. if (dwFlags & ~(CRYPT_LITTLE_ENDIAN))
  1024. {
  1025. dwReturn = (DWORD)NTE_BAD_FLAGS;
  1026. goto ErrorExit;
  1027. }
  1028. // check the user identification
  1029. pTmpUser = (PNTAGUserList)NTLCheckList(hUID, USER_HANDLE);
  1030. if (NULL == pTmpUser)
  1031. {
  1032. dwReturn = (DWORD)NTE_BAD_UID;
  1033. goto ErrorExit;
  1034. }
  1035. dwSts = NTLValidate(hHash, hUID, HASH_HANDLE, &pTmpHash);
  1036. if (ERROR_SUCCESS != dwSts)
  1037. {
  1038. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_HASH : dwSts;
  1039. goto ErrorExit;
  1040. }
  1041. if (pTmpHash->HashFlags & HF_VALUE_SET)
  1042. {
  1043. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  1044. goto ErrorExit;
  1045. }
  1046. dwSts = NTLValidate((HNTAG)hKey, hUID, KEY_HANDLE, &pTmpKey);
  1047. if (ERROR_SUCCESS != dwSts)
  1048. {
  1049. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_KEY : dwSts;
  1050. goto ErrorExit;
  1051. }
  1052. if (!FIsLegalKey(pTmpUser, pTmpKey, FALSE))
  1053. {
  1054. dwReturn = (DWORD)NTE_BAD_KEY;
  1055. goto ErrorExit;
  1056. }
  1057. #ifdef CSP_USE_SSL3
  1058. if ((CALG_SSL3_MASTER == pTmpKey->Algid) ||
  1059. (CALG_TLS1_MASTER == pTmpKey->Algid) ||
  1060. (CALG_PCT1_MASTER == pTmpKey->Algid))
  1061. {
  1062. if (NULL == pTmpKey->pData)
  1063. {
  1064. dwReturn = (DWORD)NTE_BAD_KEY;
  1065. goto ErrorExit;
  1066. }
  1067. pSChKey = (PSCH_KEY)pTmpKey->pData;
  1068. if (!pSChKey->fFinished)
  1069. {
  1070. dwReturn = (DWORD)NTE_BAD_KEY;
  1071. goto ErrorExit;
  1072. }
  1073. }
  1074. #endif // CSP_USE_SSL3
  1075. #if 0
  1076. // Check if we should do an auto-inflate
  1077. if (pTmpKey->pData == NULL)
  1078. {
  1079. if (NTAG_FAILED(CPInflateKey(pTmpKey)))
  1080. {
  1081. dwReturn = GetLastError();
  1082. goto ErrorExit;
  1083. }
  1084. }
  1085. #endif
  1086. if ((CALG_DES == pTmpKey->Algid)
  1087. || (CALG_3DES == pTmpKey->Algid)
  1088. || (CALG_3DES_112 == pTmpKey->Algid))
  1089. {
  1090. if (PROV_RSA_SCHANNEL != pTmpUser->dwProvType)
  1091. {
  1092. if ((POLICY_MS_STRONG == pTmpUser->dwCspTypeId) ||
  1093. (!(pTmpUser->Rights & CRYPT_DES_HASHKEY_BACKWARDS)))
  1094. {
  1095. desparityonkey(pTmpKey->pKeyValue, pTmpKey->cbKeyLen);
  1096. }
  1097. }
  1098. }
  1099. dwSts = SetupKeyToBeHashed(pTmpKey, &pbData,
  1100. &dwDataLen, dwFlags);
  1101. if (ERROR_SUCCESS != dwSts)
  1102. {
  1103. dwReturn = dwSts;
  1104. goto ErrorExit;
  1105. }
  1106. switch (pTmpHash->Algid)
  1107. {
  1108. #ifdef CSP_USE_MD2
  1109. case CALG_MD2:
  1110. {
  1111. MD2_object *pMD2Hash;
  1112. pMD2Hash = (MD2_object *)pTmpHash->pHashData;
  1113. // make sure the hash is updatable
  1114. if (pMD2Hash->FinishFlag)
  1115. {
  1116. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  1117. goto ErrorExit;
  1118. }
  1119. if (0 != MD2Update(&pMD2Hash->MD, pbData, dwDataLen))
  1120. {
  1121. // This is reasonable, since MD2Update only returns zero.
  1122. dwReturn = (DWORD)NTE_FAIL;
  1123. goto ErrorExit;
  1124. }
  1125. break;
  1126. }
  1127. #endif
  1128. #ifdef CSP_USE_MD4
  1129. case CALG_MD4:
  1130. {
  1131. MD4_object *pMD4Hash;
  1132. int nSts;
  1133. pMD4Hash = (MD4_object *)pTmpHash->pHashData;
  1134. // make sure the hash is updatable
  1135. if (pMD4Hash->FinishFlag)
  1136. {
  1137. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  1138. goto ErrorExit;
  1139. }
  1140. for (;;)
  1141. {
  1142. // check if there's plenty of room in the buffer
  1143. if ((pMD4Hash->BufLen + dwDataLen) < MD4BLOCKSIZE)
  1144. {
  1145. // just append to whatever's already
  1146. memcpy(pMD4Hash->Buf + pMD4Hash->BufLen, pbData, dwDataLen);
  1147. // set of the trailing buffer length field
  1148. pMD4Hash->BufLen += (BYTE)dwDataLen;
  1149. break;
  1150. }
  1151. // determine what we need to fill the buffer, then do it.
  1152. BytePos = MD4BLOCKSIZE - pMD4Hash->BufLen;
  1153. memcpy(pMD4Hash->Buf + pMD4Hash->BufLen, pbData, BytePos);
  1154. // The buffer is now full, process it.
  1155. nSts = MDupdate(&pMD4Hash->MD, pMD4Hash->Buf,
  1156. MD4BYTESTOBITS(MD4BLOCKSIZE));
  1157. if (MD4_SUCCESS != nSts)
  1158. {
  1159. dwReturn = (DWORD)NTE_FAIL;
  1160. goto ErrorExit;
  1161. }
  1162. // now it's empty.
  1163. pMD4Hash->BufLen = 0;
  1164. // we processed some bytes, so reflect that and try again
  1165. dwDataLen -= BytePos;
  1166. if (dwDataLen == 0)
  1167. break;
  1168. }
  1169. break;
  1170. }
  1171. #endif
  1172. #ifdef CSP_USE_MD5
  1173. case CALG_MD5:
  1174. {
  1175. MD5_object *pMD5Hash;
  1176. pMD5Hash = (MD5_object *)pTmpHash->pHashData;
  1177. // make sure the hash is updatable
  1178. if (pMD5Hash->FinishFlag)
  1179. {
  1180. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  1181. goto ErrorExit;
  1182. }
  1183. MD5Update(pMD5Hash, pbData, dwDataLen);
  1184. break;
  1185. }
  1186. #endif
  1187. #ifdef CSP_USE_SHA
  1188. case CALG_SHA:
  1189. {
  1190. A_SHA_CTX *pSHAHash;
  1191. pSHAHash = (A_SHA_CTX *)pTmpHash->pHashData;
  1192. // make sure the hash is updatable
  1193. if (pSHAHash->FinishFlag)
  1194. {
  1195. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  1196. goto ErrorExit;
  1197. }
  1198. A_SHAUpdate(pSHAHash, (BYTE *)pbData, dwDataLen);
  1199. break;
  1200. }
  1201. #endif
  1202. #ifdef CSP_USE_MAC
  1203. case CALG_MAC:
  1204. #endif // CSP_USE_MAC
  1205. case CALG_HMAC:
  1206. dwSts = LocalMACData(hUID, pTmpHash, pbData, dwDataLen);
  1207. if (ERROR_SUCCESS != dwSts)
  1208. {
  1209. dwReturn = dwSts;
  1210. goto ErrorExit;
  1211. }
  1212. break;
  1213. default:
  1214. dwReturn = (DWORD)NTE_BAD_ALGID;
  1215. goto ErrorExit;
  1216. }
  1217. pTmpHash->dwHashState |= DATA_IN_HASH;
  1218. dwReturn = ERROR_SUCCESS;
  1219. ErrorExit:
  1220. fRet = (ERROR_SUCCESS == dwReturn);
  1221. if (pbData)
  1222. _nt_free(pbData, dwDataLen);
  1223. if (!fRet)
  1224. SetLastError(dwReturn);
  1225. return fRet;
  1226. }
  1227. /*static*/ void
  1228. FreeHash(
  1229. IN PNTAGHashList pHash)
  1230. {
  1231. if (pHash)
  1232. {
  1233. if (pHash->pHashData)
  1234. _nt_free(pHash->pHashData, pHash->dwDataLen);
  1235. if (pHash->pbHMACInner)
  1236. _nt_free(pHash->pbHMACInner, pHash->cbHMACInner);
  1237. if (pHash->pbHMACOuter)
  1238. _nt_free(pHash->pbHMACOuter, pHash->cbHMACOuter);
  1239. if (pHash->fTempKey)
  1240. CPDestroyKey(pHash->hUID, pHash->hKey);
  1241. _nt_free(pHash, sizeof(NTAGHashList));
  1242. }
  1243. }
  1244. /*
  1245. - CPDestroyHash
  1246. -
  1247. * Purpose:
  1248. * Destory the hash object
  1249. *
  1250. *
  1251. * Parameters:
  1252. * IN hUID - Handle to the user identifcation
  1253. * IN hHash - Handle to hash object
  1254. *
  1255. * Returns:
  1256. */
  1257. BOOL WINAPI
  1258. CPDestroyHash(
  1259. IN HCRYPTPROV hUID,
  1260. IN HCRYPTHASH hHash)
  1261. {
  1262. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1263. PNTAGHashList pTmpHash;
  1264. BOOL fRet;
  1265. DWORD dwSts;
  1266. EntryPoint
  1267. // check the user identification
  1268. if (NULL == NTLCheckList(hUID, USER_HANDLE))
  1269. {
  1270. dwReturn = (DWORD)NTE_BAD_UID;
  1271. goto ErrorExit;
  1272. }
  1273. dwSts = NTLValidate(hHash, hUID, HASH_HANDLE, &pTmpHash);
  1274. if (ERROR_SUCCESS != dwSts)
  1275. {
  1276. // NTLValidate doesn't know what error to set
  1277. // so it set NTE_FAIL -- fix it up.
  1278. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_HASH : dwSts;
  1279. goto ErrorExit;
  1280. }
  1281. switch (pTmpHash->Algid)
  1282. {
  1283. #ifdef CSP_USE_MD2
  1284. case CALG_MD2:
  1285. #endif
  1286. #ifdef CSP_USE_MD4
  1287. case CALG_MD4:
  1288. #endif
  1289. #ifdef CSP_USE_MD5
  1290. case CALG_MD5:
  1291. #endif
  1292. #ifdef CSP_USE_SHA
  1293. case CALG_SHA:
  1294. #endif
  1295. #ifdef CSP_USE_SSL3SHAMD5
  1296. case CALG_SSL3_SHAMD5:
  1297. #endif
  1298. #ifdef CSP_USE_MAC
  1299. case CALG_MAC:
  1300. case CALG_HMAC:
  1301. #endif
  1302. #ifdef CSP_USE_SSL3
  1303. case CALG_SCHANNEL_MASTER_HASH:
  1304. case CALG_TLS1PRF:
  1305. #endif
  1306. if (CALG_SCHANNEL_MASTER_HASH == pTmpHash->Algid)
  1307. {
  1308. FreeSChHash((PSCH_HASH)pTmpHash->pHashData);
  1309. }
  1310. memnuke(pTmpHash->pHashData, pTmpHash->dwDataLen);
  1311. break;
  1312. default:
  1313. dwReturn = (DWORD)NTE_BAD_ALGID;
  1314. goto ErrorExit;
  1315. }
  1316. // Remove from internal list first so others can't get to it, then free.
  1317. NTLDelete(hHash);
  1318. FreeHash(pTmpHash);
  1319. dwReturn = ERROR_SUCCESS;
  1320. ErrorExit:
  1321. fRet = (ERROR_SUCCESS == dwReturn);
  1322. if (!fRet)
  1323. SetLastError(dwReturn);
  1324. return fRet;
  1325. }
  1326. /*static*/ DWORD
  1327. CopyHash(
  1328. IN PNTAGHashList pOldHash,
  1329. OUT PNTAGHashList *ppNewHash)
  1330. {
  1331. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1332. PNTAGHashList pNewHash;
  1333. BOOL fSts;
  1334. pNewHash = (PNTAGHashList)_nt_malloc(sizeof(NTAGHashList));
  1335. if (NULL == pNewHash)
  1336. {
  1337. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  1338. goto ErrorExit;
  1339. }
  1340. memcpy(pNewHash, pOldHash, sizeof(NTAGHashList));
  1341. pNewHash->fTempKey = FALSE;
  1342. pNewHash->hKey = 0;
  1343. pNewHash->dwDataLen = 0;
  1344. pNewHash->pHashData = NULL;
  1345. pNewHash->cbHMACInner = 0;
  1346. pNewHash->pbHMACInner = NULL;
  1347. pNewHash->cbHMACOuter = 0;
  1348. pNewHash->pbHMACOuter = NULL;
  1349. //
  1350. // Duplicate the associated key.
  1351. //
  1352. if (0 != pOldHash->hKey)
  1353. {
  1354. fSts = CPDuplicateKey(pNewHash->hUID, pOldHash->hKey, NULL, 0,
  1355. &pNewHash->hKey);
  1356. if (!fSts)
  1357. {
  1358. dwReturn = GetLastError();
  1359. goto ErrorExit;
  1360. }
  1361. pNewHash->fTempKey = TRUE;
  1362. }
  1363. //
  1364. // Duplicate the hash data.
  1365. //
  1366. if (0 < pOldHash->dwDataLen)
  1367. {
  1368. pNewHash->pHashData = (BYTE*)_nt_malloc(pOldHash->dwDataLen);
  1369. if (NULL == pNewHash->pHashData)
  1370. {
  1371. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  1372. goto ErrorExit;
  1373. }
  1374. pNewHash->dwDataLen = pOldHash->dwDataLen;
  1375. memcpy(pNewHash->pHashData, pOldHash->pHashData, pOldHash->dwDataLen);
  1376. }
  1377. //
  1378. // Duplicate HMAC Inner.
  1379. //
  1380. if (0 < pOldHash->cbHMACInner)
  1381. {
  1382. pNewHash->pbHMACInner = (LPBYTE)_nt_malloc(pOldHash->cbHMACInner);
  1383. if (NULL == pNewHash->pbHMACInner)
  1384. {
  1385. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  1386. goto ErrorExit;
  1387. }
  1388. pNewHash->cbHMACInner = pOldHash->cbHMACInner;
  1389. memcpy(pNewHash->pbHMACInner, pOldHash->pbHMACInner, pOldHash->cbHMACInner);
  1390. }
  1391. //
  1392. // Duplicate HMAC Outer.
  1393. //
  1394. if (0 < pOldHash->cbHMACOuter)
  1395. {
  1396. pNewHash->pbHMACOuter = (LPBYTE)_nt_malloc(pOldHash->cbHMACOuter);
  1397. if (NULL == pNewHash->pbHMACOuter)
  1398. {
  1399. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  1400. goto ErrorExit;
  1401. }
  1402. pNewHash->cbHMACOuter = pOldHash->cbHMACOuter;
  1403. memcpy(pNewHash->pbHMACOuter, pOldHash->pbHMACOuter, pOldHash->cbHMACOuter);
  1404. }
  1405. //
  1406. // Return to the caller.
  1407. //
  1408. *ppNewHash = pNewHash;
  1409. return ERROR_SUCCESS;
  1410. ErrorExit:
  1411. FreeHash(pNewHash);
  1412. return dwReturn;
  1413. }
  1414. /*
  1415. - CPDuplicateHash
  1416. -
  1417. * Purpose:
  1418. * Duplicates the state of a hash and returns a handle to it
  1419. *
  1420. * Parameters:
  1421. * IN hUID - Handle to a CSP
  1422. * IN hHash - Handle to a hash
  1423. * IN pdwReserved - Reserved
  1424. * IN dwFlags - Flags
  1425. * IN phHash - Handle to the new hash
  1426. *
  1427. * Returns:
  1428. */
  1429. BOOL WINAPI
  1430. CPDuplicateHash(
  1431. IN HCRYPTPROV hUID,
  1432. IN HCRYPTHASH hHash,
  1433. IN DWORD *pdwReserved,
  1434. IN DWORD dwFlags,
  1435. IN HCRYPTHASH *phHash)
  1436. {
  1437. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1438. PNTAGHashList pTmpHash;
  1439. PNTAGHashList pNewHash = NULL;
  1440. BOOL fRet;
  1441. DWORD dwSts;
  1442. EntryPoint
  1443. if (NULL != pdwReserved)
  1444. {
  1445. dwReturn = ERROR_INVALID_PARAMETER;
  1446. goto ErrorExit;
  1447. }
  1448. if (0 != dwFlags)
  1449. {
  1450. dwReturn = (DWORD)NTE_BAD_FLAGS;
  1451. goto ErrorExit;
  1452. }
  1453. dwSts = NTLValidate((HNTAG)hHash, hUID, HASH_HANDLE, &pTmpHash);
  1454. if (ERROR_SUCCESS != dwSts)
  1455. {
  1456. dwReturn = (NTE_FAIL == dwSts) ? (DWORD)NTE_BAD_HASH : dwSts;
  1457. goto ErrorExit;
  1458. }
  1459. dwSts = CopyHash(pTmpHash, &pNewHash);
  1460. if (ERROR_SUCCESS != dwSts)
  1461. {
  1462. dwReturn = dwSts;
  1463. goto ErrorExit;
  1464. }
  1465. dwSts = NTLMakeItem(phHash, HASH_HANDLE, (void *)pNewHash);
  1466. if (ERROR_SUCCESS != dwSts)
  1467. {
  1468. dwReturn = dwSts;
  1469. goto ErrorExit;
  1470. }
  1471. dwReturn = ERROR_SUCCESS;
  1472. ErrorExit:
  1473. fRet = (ERROR_SUCCESS == dwReturn);
  1474. if (!fRet)
  1475. {
  1476. FreeHash(pNewHash);
  1477. SetLastError(dwReturn);
  1478. }
  1479. return fRet;
  1480. }