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.

2345 lines
62 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // FILE : ssl3.c //
  3. // DESCRIPTION : Code for performing the SSL3 protocol: //
  4. // AUTHOR : //
  5. // HISTORY : //
  6. // Dec 2 1996 jeffspel Created //
  7. // Apr 8 1997 jeffspel Added PCT1 support
  8. // //
  9. // Copyright (C) 1993 Microsoft Corporation All Rights Reserved //
  10. /////////////////////////////////////////////////////////////////////////////
  11. #include "precomp.h"
  12. #include "nt_rsa.h"
  13. #include "nt_blobs.h"
  14. #include "manage.h"
  15. #include "ssl3.h"
  16. #ifdef CSP_USE_3DES
  17. #include "tripldes.h"
  18. #endif
  19. #define HMAC_K_PADSIZE 64
  20. #ifdef USE_SGC
  21. extern BOOL
  22. FIsLegalSGCKeySize(
  23. IN ALG_ID Algid,
  24. IN DWORD cbKey,
  25. IN BOOL fRC2BigKeyOK,
  26. IN BOOL fGenKey,
  27. OUT BOOL *pfPubKey);
  28. #endif
  29. extern BOOL
  30. FIsLegalKeySize(
  31. IN DWORD dwCspTypeId,
  32. IN ALG_ID Algid,
  33. IN DWORD cbKey,
  34. IN BOOL fRC2BigKeyOK,
  35. OUT BOOL *pfPubKey);
  36. extern BOOL
  37. FIsLegalKey(
  38. PNTAGUserList pTmpUser,
  39. PNTAGKeyList pKey,
  40. BOOL fRC2BigKeyOK);
  41. extern void
  42. FreeNewKey(
  43. PNTAGKeyList pOldKey);
  44. extern DWORD
  45. MakeNewKey(
  46. ALG_ID aiKeyAlg,
  47. DWORD dwRights,
  48. DWORD dwKeyLen,
  49. HCRYPTPROV hUID,
  50. BYTE *pbKeyData,
  51. BOOL fUsePassedKeyBuffer,
  52. BOOL fPreserveExactKey,
  53. PNTAGKeyList *ppKeyList);
  54. /*static*/ BOOL
  55. MyPrimitiveSHA(
  56. PBYTE pbData,
  57. DWORD cbData,
  58. BYTE rgbHash[A_SHA_DIGEST_LEN])
  59. {
  60. BOOL fRet = FALSE;
  61. A_SHA_CTX sSHAHash;
  62. A_SHAInit(&sSHAHash);
  63. A_SHAUpdate(&sSHAHash, (BYTE *) pbData, cbData);
  64. A_SHAFinal(&sSHAHash, rgbHash);
  65. fRet = TRUE;
  66. return fRet;
  67. }
  68. /*static*/ BOOL
  69. MyPrimitiveMD5(
  70. PBYTE pbData,
  71. DWORD cbData,
  72. BYTE rgbHash[MD5DIGESTLEN])
  73. {
  74. BOOL fRet = FALSE;
  75. MD5_CTX sMD5Hash;
  76. MD5Init(&sMD5Hash);
  77. MD5Update(&sMD5Hash, (BYTE *) pbData, cbData);
  78. MD5Final(&sMD5Hash);
  79. memcpy(rgbHash, sMD5Hash.digest, MD5DIGESTLEN);
  80. fRet = TRUE;
  81. return fRet;
  82. }
  83. /*static*/ BOOL
  84. MyPrimitiveHMACParam(
  85. PBYTE pbKeyMaterial,
  86. DWORD cbKeyMaterial,
  87. PBYTE pbData,
  88. DWORD cbData,
  89. ALG_ID Algid,
  90. BYTE rgbHMAC[A_SHA_DIGEST_LEN])
  91. {
  92. BYTE rgbHMACTmp[HMAC_K_PADSIZE+A_SHA_DIGEST_LEN];
  93. BOOL fRet = FALSE;
  94. BYTE rgbKipad[HMAC_K_PADSIZE];
  95. BYTE rgbKopad[HMAC_K_PADSIZE];
  96. DWORD dwBlock;
  97. // truncate
  98. if (cbKeyMaterial > HMAC_K_PADSIZE)
  99. cbKeyMaterial = HMAC_K_PADSIZE;
  100. ZeroMemory(rgbKipad, HMAC_K_PADSIZE);
  101. CopyMemory(rgbKipad, pbKeyMaterial, cbKeyMaterial);
  102. ZeroMemory(rgbKopad, HMAC_K_PADSIZE);
  103. CopyMemory(rgbKopad, pbKeyMaterial, cbKeyMaterial);
  104. // Kipad, Kopad are padded sMacKey. Now XOR across...
  105. for (dwBlock=0; dwBlock<HMAC_K_PADSIZE/sizeof(DWORD); dwBlock++)
  106. {
  107. ((DWORD*)rgbKipad)[dwBlock] ^= 0x36363636;
  108. ((DWORD*)rgbKopad)[dwBlock] ^= 0x5C5C5C5C;
  109. }
  110. // prepend Kipad to data, Hash to get H1
  111. if (CALG_SHA1 == Algid)
  112. {
  113. // do this inline since it would require data copy
  114. A_SHA_CTX sSHAHash;
  115. A_SHAInit(&sSHAHash);
  116. A_SHAUpdate(&sSHAHash, rgbKipad, HMAC_K_PADSIZE);
  117. A_SHAUpdate(&sSHAHash, pbData, cbData);
  118. // Finish off the hash
  119. A_SHAFinal(&sSHAHash, sSHAHash.HashVal);
  120. // prepend Kopad to H1, hash to get HMAC
  121. CopyMemory(rgbHMACTmp, rgbKopad, HMAC_K_PADSIZE);
  122. CopyMemory(rgbHMACTmp+HMAC_K_PADSIZE, sSHAHash.HashVal, A_SHA_DIGEST_LEN);
  123. if (!MyPrimitiveSHA(
  124. rgbHMACTmp,
  125. HMAC_K_PADSIZE + A_SHA_DIGEST_LEN,
  126. rgbHMAC))
  127. goto ErrorExit;
  128. }
  129. else
  130. {
  131. // do this inline since it would require data copy
  132. MD5_CTX sMD5Hash;
  133. MD5Init(&sMD5Hash);
  134. MD5Update(&sMD5Hash, rgbKipad, HMAC_K_PADSIZE);
  135. MD5Update(&sMD5Hash, pbData, cbData);
  136. MD5Final(&sMD5Hash);
  137. // prepend Kopad to H1, hash to get HMAC
  138. CopyMemory(rgbHMACTmp, rgbKopad, HMAC_K_PADSIZE);
  139. CopyMemory(rgbHMACTmp+HMAC_K_PADSIZE, sMD5Hash.digest, MD5DIGESTLEN);
  140. if (!MyPrimitiveMD5(
  141. rgbHMACTmp,
  142. HMAC_K_PADSIZE + MD5DIGESTLEN,
  143. rgbHMAC))
  144. goto ErrorExit;
  145. }
  146. fRet = TRUE;
  147. ErrorExit:
  148. return fRet;
  149. }
  150. //+ ---------------------------------------------------------------------
  151. // the P_Hash algorithm from TLS
  152. /*static*/ DWORD
  153. P_Hash(
  154. PBYTE pbSecret,
  155. DWORD cbSecret,
  156. PBYTE pbSeed,
  157. DWORD cbSeed,
  158. ALG_ID Algid,
  159. PBYTE pbKeyOut, //Buffer to copy the result...
  160. DWORD cbKeyOut) //# of bytes of key length they want as output.
  161. {
  162. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  163. BYTE rgbDigest[A_SHA_DIGEST_LEN];
  164. DWORD iKey;
  165. DWORD cbHash;
  166. PBYTE pbAofiDigest = NULL;
  167. pbAofiDigest = (BYTE*)_nt_malloc(cbSeed + A_SHA_DIGEST_LEN);
  168. if (NULL == pbAofiDigest)
  169. {
  170. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  171. goto ErrorExit;
  172. }
  173. if (CALG_SHA1 == Algid)
  174. cbHash = A_SHA_DIGEST_LEN;
  175. else
  176. cbHash = MD5DIGESTLEN;
  177. // First, we define a data expansion function, P_hash(secret, data)
  178. // which uses a single hash function to expand a secret and seed into
  179. // an arbitrary quantity of output:
  180. // P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
  181. // HMAC_hash(secret, A(2) + seed) +
  182. // HMAC_hash(secret, A(3) + seed) + ...
  183. // Where + indicates concatenation.
  184. // A() is defined as:
  185. // A(0) = seed
  186. // A(i) = HMAC_hash(secret, A(i-1))
  187. // build A(1)
  188. if (!MyPrimitiveHMACParam(pbSecret, cbSecret, pbSeed, cbSeed,
  189. Algid, pbAofiDigest))
  190. {
  191. dwReturn = (DWORD)NTE_FAIL;
  192. goto ErrorExit;
  193. }
  194. // create Aofi: ( A(i) | seed )
  195. CopyMemory(&pbAofiDigest[cbHash], pbSeed, cbSeed);
  196. for (iKey=0; cbKeyOut; iKey++)
  197. {
  198. // build Digest = HMAC(key | A(i) | seed);
  199. if (!MyPrimitiveHMACParam(pbSecret, cbSecret, pbAofiDigest,
  200. cbSeed + cbHash, Algid, rgbDigest))
  201. {
  202. dwReturn = (DWORD)NTE_FAIL;
  203. goto ErrorExit;
  204. }
  205. // append to pbKeyOut
  206. if (cbKeyOut < cbHash)
  207. {
  208. CopyMemory(pbKeyOut, rgbDigest, cbKeyOut);
  209. break;
  210. }
  211. else
  212. {
  213. CopyMemory(pbKeyOut, rgbDigest, cbHash);
  214. pbKeyOut += cbHash;
  215. }
  216. cbKeyOut -= cbHash;
  217. // build A(i) = HMAC(key, A(i-1))
  218. if (!MyPrimitiveHMACParam(pbSecret, cbSecret, pbAofiDigest, cbHash,
  219. Algid, pbAofiDigest))
  220. {
  221. dwReturn = (DWORD)NTE_FAIL;
  222. goto ErrorExit;
  223. }
  224. }
  225. dwReturn = ERROR_SUCCESS;
  226. ErrorExit:
  227. if (pbAofiDigest)
  228. _nt_free(pbAofiDigest, cbSeed + A_SHA_DIGEST_LEN);
  229. return dwReturn;
  230. }
  231. /*static*/ DWORD
  232. PRF(
  233. PBYTE pbSecret,
  234. DWORD cbSecret,
  235. PBYTE pbLabel,
  236. DWORD cbLabel,
  237. PBYTE pbSeed,
  238. DWORD cbSeed,
  239. PBYTE pbKeyOut, //Buffer to copy the result...
  240. DWORD cbKeyOut) //# of bytes of key length they want as output.
  241. {
  242. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  243. BYTE *pbBuff = NULL;
  244. BYTE *pbLabelAndSeed = NULL;
  245. DWORD cbLabelAndSeed;
  246. DWORD cbOdd;
  247. DWORD cbHalfSecret;
  248. DWORD i;
  249. DWORD dwSts;
  250. cbOdd = cbSecret % 2;
  251. cbHalfSecret = cbSecret / 2;
  252. cbLabelAndSeed = cbLabel + cbSeed;
  253. pbLabelAndSeed = (BYTE*)_nt_malloc(cbLabelAndSeed);
  254. if (NULL == pbLabelAndSeed)
  255. {
  256. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  257. goto ErrorExit;
  258. }
  259. pbBuff = (BYTE*)_nt_malloc(cbKeyOut);
  260. if (NULL == pbBuff)
  261. {
  262. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  263. goto ErrorExit;
  264. }
  265. // copy label and seed into one buffer
  266. memcpy(pbLabelAndSeed, pbLabel, cbLabel);
  267. memcpy(pbLabelAndSeed + cbLabel, pbSeed, cbSeed);
  268. // Use P_hash to calculate MD5 half
  269. dwSts = P_Hash(pbSecret, cbHalfSecret + cbOdd, pbLabelAndSeed,
  270. cbLabelAndSeed, CALG_MD5, pbKeyOut, cbKeyOut);
  271. if (ERROR_SUCCESS != dwSts)
  272. {
  273. dwReturn = dwSts;
  274. goto ErrorExit;
  275. }
  276. // Use P_hash to calculate SHA half
  277. dwSts = P_Hash(pbSecret + cbHalfSecret, cbHalfSecret + cbOdd,
  278. pbLabelAndSeed, cbLabelAndSeed, CALG_SHA1,
  279. pbBuff, cbKeyOut);
  280. if (ERROR_SUCCESS != dwSts)
  281. {
  282. dwReturn = dwSts;
  283. goto ErrorExit;
  284. }
  285. // XOR the two halves
  286. for (i=0;i<cbKeyOut;i++)
  287. pbKeyOut[i] = (BYTE)(pbKeyOut[i] ^ pbBuff[i]);
  288. dwReturn = ERROR_SUCCESS;
  289. ErrorExit:
  290. if (pbBuff)
  291. _nt_free(pbBuff, cbKeyOut);
  292. if (pbLabelAndSeed)
  293. _nt_free(pbLabelAndSeed, cbLabelAndSeed);
  294. return dwReturn;
  295. }
  296. void
  297. FreeSChHash(
  298. PSCH_HASH pSChHash)
  299. {
  300. if (NULL != pSChHash->pbCertData)
  301. _nt_free(pSChHash->pbCertData, pSChHash->cbCertData);
  302. }
  303. void FreeSChKey(
  304. PSCH_KEY pSChKey)
  305. {
  306. if (NULL != pSChKey->pbCertData)
  307. _nt_free(pSChKey->pbCertData, pSChKey->cbCertData);
  308. }
  309. DWORD
  310. SCHSetKeyParam(
  311. IN PNTAGUserList pTmpUser,
  312. IN OUT PNTAGKeyList pKey,
  313. IN DWORD dwParam,
  314. IN CONST BYTE *pbData)
  315. {
  316. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  317. PCRYPT_DATA_BLOB pDataBlob = (PCRYPT_DATA_BLOB)pbData;
  318. PSCH_KEY pSChKey;
  319. PSCHANNEL_ALG pSChAlg;
  320. BOOL fPubKey = FALSE;
  321. if ((CALG_SSL3_MASTER != pKey->Algid) &&
  322. (CALG_PCT1_MASTER != pKey->Algid) &&
  323. (CALG_TLS1_MASTER != pKey->Algid) &&
  324. (CALG_SSL2_MASTER != pKey->Algid))
  325. {
  326. dwReturn = (DWORD)NTE_BAD_TYPE;
  327. goto ErrorExit;
  328. }
  329. if (NULL == pKey->pData)
  330. {
  331. pKey->pData = (BYTE*)_nt_malloc(sizeof(SCH_KEY));
  332. if (NULL == pKey->pData)
  333. {
  334. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  335. goto ErrorExit;
  336. }
  337. memset(pKey->pData, 0, sizeof(SCH_KEY));
  338. pKey->cbDataLen = sizeof(SCH_KEY);
  339. }
  340. pSChKey = (PSCH_KEY)pKey->pData;
  341. if (KP_SCHANNEL_ALG == dwParam)
  342. {
  343. pSChAlg = (PSCHANNEL_ALG)pbData;
  344. pSChKey->dwFlags = pSChAlg->dwFlags; // set the international version indicator
  345. switch (pSChAlg->dwUse)
  346. {
  347. case SCHANNEL_MAC_KEY:
  348. switch (pSChAlg->Algid)
  349. {
  350. case CALG_MD5:
  351. if (CALG_PCT1_MASTER == pKey->Algid)
  352. {
  353. pSChKey->cbHash = MD5DIGESTLEN;
  354. pSChKey->cbEncMac = pSChAlg->cBits / 8;
  355. }
  356. else
  357. {
  358. if (pSChAlg->cBits != (MD5DIGESTLEN * 8))
  359. {
  360. dwReturn = (DWORD)NTE_BAD_DATA;
  361. goto ErrorExit;
  362. }
  363. pSChKey->cbEncMac = MD5DIGESTLEN;
  364. }
  365. break;
  366. case CALG_SHA1:
  367. if (CALG_PCT1_MASTER == pKey->Algid)
  368. {
  369. pSChKey->cbHash = A_SHA_DIGEST_LEN;
  370. pSChKey->cbEncMac = pSChAlg->cBits / 8;
  371. }
  372. else
  373. {
  374. if (pSChAlg->cBits != (A_SHA_DIGEST_LEN * 8))
  375. {
  376. dwReturn = (DWORD)NTE_BAD_DATA;
  377. goto ErrorExit;
  378. }
  379. pSChKey->cbEncMac = A_SHA_DIGEST_LEN;
  380. }
  381. break;
  382. default:
  383. dwReturn = (DWORD)NTE_BAD_DATA;
  384. goto ErrorExit;
  385. }
  386. pSChKey->HashAlgid = pSChAlg->Algid;
  387. break;
  388. case SCHANNEL_ENC_KEY:
  389. if (pSChAlg->cBits % 8)
  390. {
  391. dwReturn = (DWORD)NTE_BAD_DATA;
  392. goto ErrorExit;
  393. }
  394. #ifdef USE_SGC
  395. if ((PROV_RSA_SCHANNEL == pTmpUser->dwProvType) &&
  396. (0 != pTmpUser->dwSGCFlags))
  397. {
  398. if (!FIsLegalSGCKeySize(pSChAlg->Algid, pSChAlg->cBits / 8,
  399. FALSE, FALSE, &fPubKey))
  400. {
  401. dwReturn = (DWORD)NTE_BAD_FLAGS;
  402. goto ErrorExit;
  403. }
  404. }
  405. else
  406. #endif
  407. {
  408. if (!FIsLegalKeySize(pTmpUser->dwCspTypeId,
  409. pSChAlg->Algid, pSChAlg->cBits / 8,
  410. FALSE, &fPubKey))
  411. {
  412. dwReturn = (DWORD)NTE_BAD_FLAGS;
  413. goto ErrorExit;
  414. }
  415. }
  416. switch (pSChAlg->Algid)
  417. {
  418. #ifdef CSP_USE_RC4
  419. case CALG_RC4:
  420. pSChKey->cbIV = 0;
  421. break;
  422. #endif
  423. #ifdef CSP_USE_RC2
  424. case CALG_RC2:
  425. pSChKey->cbIV = RC2_BLOCKLEN;
  426. break;
  427. #endif
  428. #ifdef CSP_USE_DES
  429. case CALG_DES:
  430. pSChKey->cbIV = DES_BLOCKLEN;
  431. break;
  432. #endif
  433. #ifdef CSP_USE_3DES
  434. case CALG_3DES_112:
  435. pSChKey->cbIV = DES_BLOCKLEN;
  436. break;
  437. case CALG_3DES:
  438. pSChKey->cbIV = DES_BLOCKLEN;
  439. break;
  440. #endif
  441. default:
  442. dwReturn = (DWORD)NTE_BAD_DATA;
  443. goto ErrorExit;
  444. }
  445. // For SSL2 check that the length of the master key matches the
  446. // the requested encryption length
  447. if ((CALG_SSL2_MASTER == pKey->Algid) &&
  448. ((pSChAlg->cBits / 8) != pKey->cbKeyLen))
  449. {
  450. dwReturn = (DWORD)NTE_BAD_KEY;
  451. goto ErrorExit;
  452. }
  453. pSChKey->cbEnc = (pSChAlg->cBits / 8);
  454. pSChKey->EncAlgid = pSChAlg->Algid;
  455. break;
  456. default:
  457. dwReturn = (DWORD)NTE_BAD_DATA;
  458. goto ErrorExit;
  459. }
  460. }
  461. else
  462. {
  463. switch (dwParam)
  464. {
  465. case KP_CLIENT_RANDOM:
  466. if (pDataBlob->cbData > MAX_RANDOM_LEN)
  467. {
  468. dwReturn = (DWORD)NTE_BAD_DATA;
  469. goto ErrorExit;
  470. }
  471. pSChKey->cbClientRandom = pDataBlob->cbData;
  472. memcpy(pSChKey->rgbClientRandom,
  473. pDataBlob->pbData,
  474. pDataBlob->cbData);
  475. break;
  476. case KP_SERVER_RANDOM:
  477. if (pDataBlob->cbData > MAX_RANDOM_LEN)
  478. {
  479. dwReturn = (DWORD)NTE_BAD_DATA;
  480. goto ErrorExit;
  481. }
  482. pSChKey->cbServerRandom = pDataBlob->cbData;
  483. memcpy(pSChKey->rgbServerRandom,
  484. pDataBlob->pbData,
  485. pDataBlob->cbData);
  486. break;
  487. case KP_CERTIFICATE:
  488. if (CALG_PCT1_MASTER != pKey->Algid)
  489. {
  490. dwReturn = (DWORD)NTE_BAD_TYPE;
  491. goto ErrorExit;
  492. }
  493. if (pSChKey->pbCertData)
  494. _nt_free(pSChKey->pbCertData, pSChKey->cbCertData);
  495. pSChKey->cbCertData = pDataBlob->cbData;
  496. pSChKey->pbCertData = (BYTE*)_nt_malloc(pSChKey->cbCertData);
  497. if (NULL == pSChKey->pbCertData)
  498. {
  499. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  500. goto ErrorExit;
  501. }
  502. memcpy(pSChKey->pbCertData, pDataBlob->pbData, pDataBlob->cbData);
  503. break;
  504. case KP_CLEAR_KEY:
  505. if (pDataBlob->cbData > MAX_RANDOM_LEN)
  506. {
  507. dwReturn = (DWORD)NTE_BAD_DATA;
  508. goto ErrorExit;
  509. }
  510. if ((CALG_PCT1_MASTER != pKey->Algid) &&
  511. (CALG_SSL2_MASTER != pKey->Algid))
  512. {
  513. dwReturn = (DWORD)NTE_BAD_TYPE;
  514. goto ErrorExit;
  515. }
  516. pSChKey->cbClearData = pDataBlob->cbData;
  517. memcpy(pSChKey->rgbClearData,
  518. pDataBlob->pbData,
  519. pDataBlob->cbData);
  520. break;
  521. default:
  522. dwReturn = (DWORD)NTE_BAD_TYPE;
  523. goto ErrorExit;
  524. }
  525. }
  526. dwReturn = ERROR_SUCCESS;
  527. ErrorExit:
  528. return dwReturn;
  529. }
  530. /*static*/ DWORD
  531. SSL3SingleHash(
  532. HCRYPTPROV hUID,
  533. PBYTE pbString,
  534. DWORD cbString,
  535. PBYTE pbSecret,
  536. DWORD cbSecret,
  537. PBYTE pbRand1,
  538. DWORD cbRand1,
  539. PBYTE pbRand2,
  540. DWORD cbRand2,
  541. PBYTE pbResult)
  542. {
  543. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  544. HCRYPTHASH hHashSHA = 0;
  545. HCRYPTHASH hHashMD5 = 0;
  546. BYTE rgb[A_SHA_DIGEST_LEN];
  547. DWORD cb;
  548. // perform the SHA hashing
  549. if (!CPCreateHash(hUID, CALG_SHA1, 0, 0, &hHashSHA))
  550. {
  551. dwReturn = GetLastError();
  552. goto ErrorExit;
  553. }
  554. if (!CPHashData(hUID, hHashSHA, pbString, cbString, 0))
  555. {
  556. dwReturn = GetLastError();
  557. goto ErrorExit;
  558. }
  559. if (!CPHashData(hUID, hHashSHA, pbSecret, cbSecret, 0))
  560. {
  561. dwReturn = GetLastError();
  562. goto ErrorExit;
  563. }
  564. if (!CPHashData(hUID, hHashSHA, pbRand1, cbRand1, 0))
  565. {
  566. dwReturn = GetLastError();
  567. goto ErrorExit;
  568. }
  569. if (!CPHashData(hUID, hHashSHA, pbRand2, cbRand2, 0))
  570. {
  571. dwReturn = GetLastError();
  572. goto ErrorExit;
  573. }
  574. cb = A_SHA_DIGEST_LEN;
  575. if (!CPGetHashParam(hUID, hHashSHA, HP_HASHVAL, rgb, &cb, 0))
  576. {
  577. dwReturn = GetLastError();
  578. goto ErrorExit;
  579. }
  580. // perform the MD5 hashing
  581. if (!CPCreateHash(hUID, CALG_MD5, 0, 0, &hHashMD5))
  582. {
  583. dwReturn = GetLastError();
  584. goto ErrorExit;
  585. }
  586. if (!CPHashData(hUID, hHashMD5, pbSecret, cbSecret, 0))
  587. {
  588. dwReturn = GetLastError();
  589. goto ErrorExit;
  590. }
  591. if (!CPHashData(hUID, hHashMD5, rgb, A_SHA_DIGEST_LEN, 0))
  592. {
  593. dwReturn = GetLastError();
  594. goto ErrorExit;
  595. }
  596. cb = MD5DIGESTLEN;
  597. if (!CPGetHashParam(hUID, hHashMD5, HP_HASHVAL, pbResult, &cb, 0))
  598. {
  599. dwReturn = GetLastError();
  600. goto ErrorExit;
  601. }
  602. dwReturn = ERROR_SUCCESS;
  603. ErrorExit:
  604. if (hHashSHA)
  605. CPDestroyHash(hUID, hHashSHA);
  606. if (hHashMD5)
  607. CPDestroyHash(hUID, hHashMD5);
  608. return dwReturn;
  609. }
  610. /*static*/ DWORD
  611. SSL3HashPreMaster(
  612. HCRYPTPROV hUID,
  613. PBYTE pbSecret,
  614. DWORD cbSecret,
  615. PBYTE pbRand1,
  616. DWORD cbRand1,
  617. PBYTE pbRand2,
  618. DWORD cbRand2,
  619. PBYTE pbFinal,
  620. DWORD cbFinal)
  621. {
  622. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  623. BYTE rgbString[17]; // know max length from MAX_RANDOM_LEN
  624. DWORD cLimit;
  625. DWORD cbIndex = 0;
  626. long i;
  627. DWORD dwSts;
  628. if ((cbFinal > MAX_RANDOM_LEN) || ((cbFinal % MD5DIGESTLEN) != 0))
  629. {
  630. dwReturn = (DWORD)NTE_FAIL;
  631. goto ErrorExit;
  632. }
  633. cLimit = cbFinal / MD5DIGESTLEN;
  634. for (i=0;i<(long)cLimit;i++)
  635. {
  636. memset(rgbString, 0x41 + i, i + 1);
  637. dwSts = SSL3SingleHash(hUID, rgbString, i + 1, pbSecret,
  638. cbSecret, pbRand1, cbRand1,
  639. pbRand2, cbRand2, pbFinal + cbIndex);
  640. if (ERROR_SUCCESS != dwSts)
  641. {
  642. dwReturn = dwSts;
  643. goto ErrorExit;
  644. }
  645. cbIndex += MD5DIGESTLEN;
  646. }
  647. dwReturn = ERROR_SUCCESS;
  648. ErrorExit:
  649. return dwReturn;
  650. }
  651. DWORD
  652. SChGenMasterKey(
  653. PNTAGKeyList pKey,
  654. PSCH_HASH pSChHash)
  655. {
  656. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  657. PSCH_KEY pSChKey;
  658. DWORD cb;
  659. BYTE *pbClientAndServer = NULL;
  660. DWORD cbClientAndServer;
  661. DWORD dwSts;
  662. pSChKey = (PSCH_KEY)pKey->pData;
  663. pSChHash->dwFlags = pSChKey->dwFlags; // set the international flag
  664. // from the key
  665. switch (pKey->Algid)
  666. {
  667. case CALG_SSL3_MASTER:
  668. if (!pSChKey->fFinished)
  669. {
  670. // copy the premaster secret
  671. pSChKey->cbPremaster = pKey->cbKeyLen;
  672. memcpy(pSChKey->rgbPremaster,
  673. pKey->pKeyValue,
  674. pSChKey->cbPremaster);
  675. // hash the pre-master secret
  676. dwSts = SSL3HashPreMaster(pKey->hUID,
  677. pSChKey->rgbPremaster,
  678. pSChKey->cbPremaster,
  679. pSChKey->rgbClientRandom,
  680. pSChKey->cbClientRandom,
  681. pSChKey->rgbServerRandom,
  682. pSChKey->cbServerRandom,
  683. pKey->pKeyValue,
  684. pKey->cbKeyLen);
  685. if (ERROR_SUCCESS != dwSts)
  686. {
  687. dwReturn = dwSts;
  688. goto ErrorExit;
  689. }
  690. }
  691. // copy the necessary information to the hash
  692. pSChHash->EncAlgid = pSChKey->EncAlgid;
  693. pSChHash->cbEnc = pSChKey->cbEnc;
  694. pSChHash->cbEncMac = pSChKey->cbEncMac;
  695. pSChHash->cbIV = pSChKey->cbIV;
  696. pSChHash->cbClientRandom = pSChKey->cbClientRandom;
  697. memcpy(pSChHash->rgbClientRandom,
  698. pSChKey->rgbClientRandom,
  699. pSChHash->cbClientRandom);
  700. pSChHash->cbServerRandom = pSChKey->cbServerRandom;
  701. memcpy(pSChHash->rgbServerRandom,
  702. pSChKey->rgbServerRandom,
  703. pSChHash->cbServerRandom);
  704. cb = pSChHash->cbEnc * 2
  705. + pSChHash->cbEncMac * 2
  706. + pSChHash->cbIV * 2;
  707. pSChHash->cbFinal = (cb / MD5DIGESTLEN) * MD5DIGESTLEN;
  708. if (cb % MD5DIGESTLEN)
  709. pSChHash->cbFinal += MD5DIGESTLEN;
  710. // hash the master secret
  711. dwSts = SSL3HashPreMaster(pKey->hUID,
  712. pKey->pKeyValue,
  713. pKey->cbKeyLen,
  714. pSChKey->rgbServerRandom,
  715. pSChKey->cbServerRandom,
  716. pSChKey->rgbClientRandom,
  717. pSChKey->cbClientRandom,
  718. pSChHash->rgbFinal,
  719. pSChHash->cbFinal);
  720. if (ERROR_SUCCESS != dwSts)
  721. {
  722. dwReturn = dwSts;
  723. goto ErrorExit;
  724. }
  725. pSChKey->fFinished = TRUE;
  726. break;
  727. case CALG_TLS1_MASTER:
  728. cbClientAndServer = pSChKey->cbClientRandom
  729. + pSChKey->cbServerRandom;
  730. pbClientAndServer = (BYTE*)_nt_malloc(cbClientAndServer);
  731. if (NULL == pbClientAndServer)
  732. {
  733. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  734. goto ErrorExit;
  735. }
  736. if (!pSChKey->fFinished)
  737. {
  738. // copy the premaster secret
  739. pSChKey->cbPremaster = pKey->cbKeyLen;
  740. memcpy(pSChKey->rgbPremaster,
  741. pKey->pKeyValue,
  742. pSChKey->cbPremaster);
  743. // concatenate the client random and server random
  744. memcpy(pbClientAndServer,
  745. pSChKey->rgbClientRandom,
  746. pSChKey->cbClientRandom);
  747. memcpy(pbClientAndServer + pSChKey->cbClientRandom,
  748. pSChKey->rgbServerRandom,
  749. pSChKey->cbServerRandom);
  750. // hash the pre-master secret
  751. dwSts = PRF(pSChKey->rgbPremaster, pSChKey->cbPremaster,
  752. (LPBYTE)"master secret", 13,
  753. pbClientAndServer, cbClientAndServer,
  754. pKey->pKeyValue, TLS_MASTER_LEN);
  755. if (ERROR_SUCCESS != dwSts)
  756. {
  757. dwReturn = dwSts;
  758. goto ErrorExit;
  759. }
  760. }
  761. // copy the necessary information to the hash
  762. pSChHash->EncAlgid = pSChKey->EncAlgid;
  763. pSChHash->cbEnc = pSChKey->cbEnc;
  764. pSChHash->cbEncMac = pSChKey->cbEncMac;
  765. pSChHash->cbIV = pSChKey->cbIV;
  766. pSChHash->cbClientRandom = pSChKey->cbClientRandom;
  767. memcpy(pSChHash->rgbClientRandom,
  768. pSChKey->rgbClientRandom,
  769. pSChHash->cbClientRandom);
  770. pSChHash->cbServerRandom = pSChKey->cbServerRandom;
  771. memcpy(pSChHash->rgbServerRandom,
  772. pSChKey->rgbServerRandom,
  773. pSChHash->cbServerRandom);
  774. pSChHash->cbFinal = pSChHash->cbEnc * 2
  775. + pSChHash->cbEncMac * 2
  776. + pSChHash->cbIV * 2;
  777. // concatenate the server random and client random
  778. memcpy(pbClientAndServer,
  779. pSChKey->rgbServerRandom,
  780. pSChKey->cbServerRandom);
  781. memcpy(pbClientAndServer + pSChKey->cbServerRandom,
  782. pSChKey->rgbClientRandom,
  783. pSChKey->cbClientRandom);
  784. // hash the master secret
  785. dwSts = PRF(pKey->pKeyValue, pKey->cbKeyLen,
  786. (LPBYTE)"key expansion", 13,
  787. pbClientAndServer, cbClientAndServer,
  788. pSChHash->rgbFinal, pSChHash->cbFinal);
  789. if (ERROR_SUCCESS != dwSts)
  790. {
  791. dwReturn = dwSts;
  792. goto ErrorExit;
  793. }
  794. pSChKey->fFinished = TRUE;
  795. break;
  796. case CALG_PCT1_MASTER:
  797. pSChHash->cbFinal = pKey->cbKeyLen;
  798. memcpy(pSChHash->rgbFinal, pKey->pKeyValue, pSChHash->cbFinal);
  799. // copy the necessary information to the hash
  800. pSChHash->EncAlgid = pSChKey->EncAlgid;
  801. pSChHash->HashAlgid = pSChKey->HashAlgid;
  802. pSChHash->cbEnc = pSChKey->cbEnc;
  803. pSChHash->cbEncMac = pSChKey->cbEncMac;
  804. pSChHash->cbHash = pSChKey->cbHash;
  805. pSChHash->cbIV = pSChKey->cbIV;
  806. pSChHash->cbClientRandom = pSChKey->cbClientRandom;
  807. memcpy(pSChHash->rgbClientRandom,
  808. pSChKey->rgbClientRandom,
  809. pSChHash->cbClientRandom);
  810. pSChHash->cbServerRandom = pSChKey->cbServerRandom;
  811. memcpy(pSChHash->rgbServerRandom,
  812. pSChKey->rgbServerRandom,
  813. pSChHash->cbServerRandom);
  814. pSChHash->cbCertData = pSChKey->cbCertData;
  815. pSChHash->pbCertData = (BYTE*)_nt_malloc(pSChHash->cbCertData);
  816. if (NULL == pSChHash->pbCertData)
  817. {
  818. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  819. goto ErrorExit;
  820. }
  821. memcpy(pSChHash->pbCertData,
  822. pSChKey->pbCertData,
  823. pSChHash->cbCertData);
  824. pSChHash->cbClearData = pSChKey->cbClearData;
  825. memcpy(pSChHash->rgbClearData,
  826. pSChKey->rgbClearData,
  827. pSChHash->cbClearData);
  828. break;
  829. case CALG_SSL2_MASTER:
  830. pSChHash->cbFinal = pKey->cbKeyLen;
  831. memcpy(pSChHash->rgbFinal, pKey->pKeyValue, pSChHash->cbFinal);
  832. // copy the necessary information to the hash
  833. pSChHash->EncAlgid = pSChKey->EncAlgid;
  834. pSChHash->HashAlgid = pSChKey->HashAlgid;
  835. pSChHash->cbEnc = pSChKey->cbEnc;
  836. pSChHash->cbEncMac = pSChKey->cbEncMac;
  837. pSChHash->cbHash = pSChKey->cbHash;
  838. pSChHash->cbIV = pSChKey->cbIV;
  839. pSChHash->cbClientRandom = pSChKey->cbClientRandom;
  840. memcpy(pSChHash->rgbClientRandom,
  841. pSChKey->rgbClientRandom,
  842. pSChHash->cbClientRandom);
  843. pSChHash->cbServerRandom = pSChKey->cbServerRandom;
  844. memcpy(pSChHash->rgbServerRandom,
  845. pSChKey->rgbServerRandom,
  846. pSChHash->cbServerRandom);
  847. pSChHash->cbClearData = pSChKey->cbClearData;
  848. memcpy(pSChHash->rgbClearData,
  849. pSChKey->rgbClearData,
  850. pSChHash->cbClearData);
  851. break;
  852. }
  853. dwReturn = ERROR_SUCCESS;
  854. ErrorExit:
  855. if (pbClientAndServer)
  856. _nt_free(pbClientAndServer, cbClientAndServer);
  857. return dwReturn;
  858. }
  859. /*static*/ DWORD
  860. HelperHash(
  861. HCRYPTPROV hProv,
  862. BYTE *pb,
  863. DWORD cb,
  864. ALG_ID Algid,
  865. BYTE **ppbHash,
  866. DWORD *pcbHash,
  867. BOOL fAlloc)
  868. {
  869. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  870. HCRYPTHASH hHash = 0;
  871. if (fAlloc)
  872. *ppbHash = NULL;
  873. // hash the key and stuff into a usable key
  874. if (!CPCreateHash(hProv, Algid, 0, 0, &hHash))
  875. {
  876. dwReturn = GetLastError();
  877. goto ErrorExit;
  878. }
  879. if (!CPHashData(hProv, hHash, pb, cb, 0))
  880. {
  881. dwReturn = GetLastError();
  882. goto ErrorExit;
  883. }
  884. if (fAlloc)
  885. {
  886. if (!CPGetHashParam(hProv, hHash, HP_HASHVAL, NULL, pcbHash, 0))
  887. {
  888. dwReturn = GetLastError();
  889. goto ErrorExit;
  890. }
  891. *ppbHash = (BYTE*)_nt_malloc(*pcbHash);
  892. if (NULL == *ppbHash)
  893. {
  894. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  895. goto ErrorExit;
  896. }
  897. }
  898. if (!CPGetHashParam(hProv, hHash, HP_HASHVAL, *ppbHash, pcbHash, 0))
  899. {
  900. dwReturn = GetLastError();
  901. goto ErrorExit;
  902. }
  903. dwReturn = ERROR_SUCCESS;
  904. ErrorExit:
  905. if (hHash)
  906. CPDestroyHash(hProv, hHash);
  907. if ((ERROR_SUCCESS != dwReturn) && fAlloc && *ppbHash)
  908. {
  909. _nt_free(*ppbHash, *pcbHash);
  910. *ppbHash = NULL;
  911. }
  912. return dwReturn;
  913. }
  914. /*static*/ DWORD
  915. SSL3DeriveWriteKey(
  916. PNTAGUserList pTmpUser,
  917. PNTAGHashList pHash,
  918. DWORD dwFlags,
  919. HCRYPTKEY *phKey)
  920. {
  921. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  922. PSCH_HASH pSChHash;
  923. DWORD cbOffset;
  924. BYTE *pbIV = NULL;
  925. DWORD cbIV;
  926. BOOL fUseIV = FALSE;
  927. BYTE *pbKey = NULL;
  928. DWORD cbKey;
  929. PNTAGKeyList pTmpKey = NULL;
  930. BYTE rgbBuff[MAX_RANDOM_LEN * 2 + MAX_PREMASTER_LEN];
  931. DWORD cbBuff;
  932. DWORD dwRights = 0;
  933. DWORD dwSts;
  934. pSChHash = (PSCH_HASH)pHash->pHashData;
  935. cbOffset = 2 * pSChHash->cbEncMac;
  936. // get the IV
  937. if (CALG_RC4 != pSChHash->EncAlgid)
  938. fUseIV = TRUE;
  939. // if not flagged as a server key then default is client
  940. if (pSChHash->dwFlags & INTERNATIONAL_USAGE)
  941. {
  942. if (CRYPT_SERVER & dwFlags)
  943. {
  944. cbBuff = pSChHash->cbEnc
  945. + pSChHash->cbServerRandom
  946. + pSChHash->cbClientRandom;
  947. if (cbBuff > sizeof(rgbBuff))
  948. {
  949. dwReturn = (DWORD)NTE_FAIL;
  950. goto ErrorExit;
  951. }
  952. memcpy(rgbBuff, pSChHash->rgbFinal + cbOffset + pSChHash->cbEnc, pSChHash->cbEnc);
  953. memcpy(rgbBuff + pSChHash->cbEnc, pSChHash->rgbServerRandom, pSChHash->cbServerRandom);
  954. memcpy(rgbBuff + pSChHash->cbEnc + pSChHash->cbServerRandom,
  955. pSChHash->rgbClientRandom, pSChHash->cbClientRandom);
  956. dwSts = HelperHash(pHash->hUID, rgbBuff, cbBuff, CALG_MD5,
  957. &pbKey, &cbKey, TRUE);
  958. if (ERROR_SUCCESS != dwSts)
  959. {
  960. dwReturn = dwSts;
  961. goto ErrorExit;
  962. }
  963. if (fUseIV)
  964. {
  965. cbBuff = pSChHash->cbServerRandom + pSChHash->cbClientRandom;
  966. memcpy(rgbBuff,
  967. pSChHash->rgbServerRandom,
  968. pSChHash->cbServerRandom);
  969. memcpy(rgbBuff + pSChHash->cbServerRandom,
  970. pSChHash->rgbClientRandom,
  971. pSChHash->cbClientRandom);
  972. dwSts = HelperHash(pHash->hUID, rgbBuff, cbBuff, CALG_MD5,
  973. &pbIV, &cbIV, TRUE);
  974. if (ERROR_SUCCESS != dwSts)
  975. {
  976. dwReturn = dwSts;
  977. goto ErrorExit;
  978. }
  979. }
  980. }
  981. else
  982. {
  983. cbBuff = pSChHash->cbEnc
  984. + pSChHash->cbServerRandom
  985. + pSChHash->cbClientRandom;
  986. if (cbBuff > sizeof(rgbBuff))
  987. {
  988. dwReturn = (DWORD)NTE_FAIL;
  989. goto ErrorExit;
  990. }
  991. memcpy(rgbBuff,
  992. pSChHash->rgbFinal + cbOffset,
  993. pSChHash->cbEnc);
  994. memcpy(rgbBuff + pSChHash->cbEnc,
  995. pSChHash->rgbClientRandom,
  996. pSChHash->cbClientRandom);
  997. memcpy(rgbBuff + pSChHash->cbEnc + pSChHash->cbClientRandom,
  998. pSChHash->rgbServerRandom,
  999. pSChHash->cbServerRandom);
  1000. dwSts = HelperHash(pHash->hUID, rgbBuff, cbBuff, CALG_MD5,
  1001. &pbKey, &cbKey, TRUE);
  1002. if (ERROR_SUCCESS != dwSts)
  1003. {
  1004. dwReturn = dwSts;
  1005. goto ErrorExit;
  1006. }
  1007. if (fUseIV)
  1008. {
  1009. cbBuff = pSChHash->cbServerRandom
  1010. + pSChHash->cbClientRandom;
  1011. memcpy(rgbBuff,
  1012. pSChHash->rgbClientRandom,
  1013. pSChHash->cbClientRandom);
  1014. memcpy(rgbBuff + pSChHash->cbClientRandom,
  1015. pSChHash->rgbServerRandom,
  1016. pSChHash->cbServerRandom);
  1017. dwSts = HelperHash(pHash->hUID, rgbBuff, cbBuff, CALG_MD5,
  1018. &pbIV, &cbIV, TRUE);
  1019. if (ERROR_SUCCESS != dwSts)
  1020. {
  1021. dwReturn = dwSts;
  1022. goto ErrorExit;
  1023. }
  1024. }
  1025. }
  1026. }
  1027. else
  1028. {
  1029. cbKey = pSChHash->cbEnc;
  1030. pbKey = (BYTE*)_nt_malloc(cbKey);
  1031. if (NULL == pbKey)
  1032. {
  1033. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  1034. goto ErrorExit;
  1035. }
  1036. cbIV = pSChHash->cbIV;
  1037. pbIV = (BYTE*)_nt_malloc(cbIV);
  1038. if (NULL == pbIV)
  1039. {
  1040. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  1041. goto ErrorExit;
  1042. }
  1043. if (CRYPT_SERVER & dwFlags)
  1044. {
  1045. memcpy(pbKey,
  1046. pSChHash->rgbFinal + cbOffset + pSChHash->cbEnc,
  1047. pSChHash->cbEnc);
  1048. memcpy(pbIV,
  1049. pSChHash->rgbFinal
  1050. + cbOffset
  1051. + pSChHash->cbEnc * 2
  1052. + pSChHash->cbIV,
  1053. pSChHash->cbIV);
  1054. }
  1055. else
  1056. {
  1057. memcpy(pbKey,
  1058. pSChHash->rgbFinal + cbOffset,
  1059. pSChHash->cbEnc);
  1060. memcpy(pbIV,
  1061. pSChHash->rgbFinal + cbOffset + pSChHash->cbEnc * 2,
  1062. pSChHash->cbIV);
  1063. }
  1064. }
  1065. // check if the key is CRYPT_EXPORTABLE
  1066. if (dwFlags & CRYPT_EXPORTABLE)
  1067. dwRights = CRYPT_EXPORTABLE;
  1068. // make the new key
  1069. dwSts = MakeNewKey(pSChHash->EncAlgid,
  1070. dwRights,
  1071. pSChHash->cbEnc,
  1072. pHash->hUID,
  1073. pbKey,
  1074. FALSE,
  1075. TRUE,
  1076. &pTmpKey);
  1077. if (ERROR_SUCCESS != dwSts)
  1078. {
  1079. dwReturn = dwSts;
  1080. goto ErrorExit;
  1081. }
  1082. if (CALG_RC2 == pSChHash->EncAlgid)
  1083. pTmpKey->EffectiveKeyLen = RC2_SCHANNEL_DEFAULT_EFFECTIVE_KEYLEN;
  1084. if ((pSChHash->dwFlags & INTERNATIONAL_USAGE)
  1085. && ((CALG_RC2 == pSChHash->EncAlgid)
  1086. || (CALG_RC4 == pSChHash->EncAlgid)))
  1087. {
  1088. pTmpKey->cbSaltLen = RC_KEYLEN - pSChHash->cbEnc;
  1089. memcpy(pTmpKey->rgbSalt,
  1090. pbKey + pSChHash->cbEnc,
  1091. pTmpKey->cbSaltLen);
  1092. }
  1093. // check keylength...
  1094. if (!FIsLegalKey(pTmpUser, pTmpKey, FALSE))
  1095. {
  1096. dwReturn = (DWORD)NTE_BAD_FLAGS;
  1097. goto ErrorExit;
  1098. }
  1099. // set the IV if necessary
  1100. if (fUseIV)
  1101. {
  1102. // set the mode to CBC
  1103. pTmpKey->Mode = CRYPT_MODE_CBC;
  1104. // set the IV
  1105. memcpy(pTmpKey->IV, pbIV, CRYPT_BLKLEN); // Initialization vector
  1106. }
  1107. dwSts = NTLMakeItem(phKey, KEY_HANDLE, (void *)pTmpKey);
  1108. if (ERROR_SUCCESS != dwSts)
  1109. {
  1110. dwReturn = dwSts;
  1111. goto ErrorExit;
  1112. }
  1113. pTmpKey = NULL;
  1114. dwReturn = ERROR_SUCCESS;
  1115. ErrorExit:
  1116. if (pbKey)
  1117. _nt_free(pbKey, cbKey);
  1118. if (pbIV)
  1119. _nt_free(pbIV, cbIV);
  1120. return dwReturn;
  1121. }
  1122. /*static*/ DWORD
  1123. PCT1MakeKeyHash(
  1124. PNTAGHashList pHash,
  1125. DWORD c,
  1126. DWORD dwFlags,
  1127. BOOL fWriteKey,
  1128. BYTE *pbBuff,
  1129. DWORD *pcbBuff)
  1130. {
  1131. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1132. BYTE *pb = NULL;
  1133. DWORD cb = 0;
  1134. DWORD cbIndex;
  1135. PSCH_HASH pSChHash;
  1136. BYTE *pbStr;
  1137. DWORD cbStr;
  1138. DWORD i;
  1139. BYTE *pbHash = NULL;
  1140. DWORD cbHash;
  1141. DWORD dwSts;
  1142. pSChHash = (PSCH_HASH)pHash->pHashData;
  1143. // For reasons of backward compatibility, use the formula:
  1144. // hash( i, "foo"^i, MASTER_KEY, ...
  1145. // rather than:
  1146. // hash( i, "foo", MASTER_KEY, ...
  1147. // when deriving encryption keys.
  1148. if (fWriteKey)
  1149. {
  1150. if (CRYPT_SERVER & dwFlags)
  1151. {
  1152. pbStr = (LPBYTE)PCT1_S_WRT;
  1153. cbStr = PCT1_S_WRT_LEN;
  1154. cb = cbStr * c;
  1155. }
  1156. else
  1157. {
  1158. pbStr = (LPBYTE)PCT1_C_WRT;
  1159. cbStr = PCT1_C_WRT_LEN;
  1160. cb = pSChHash->cbCertData + cbStr * c * 2;
  1161. }
  1162. }
  1163. else
  1164. {
  1165. if (CRYPT_SERVER & dwFlags)
  1166. {
  1167. pbStr = (LPBYTE)PCT1_S_MAC;
  1168. cbStr = PCT1_S_MAC_LEN;
  1169. }
  1170. else
  1171. {
  1172. pbStr = (LPBYTE)PCT1_C_MAC;
  1173. cbStr = PCT1_C_MAC_LEN;
  1174. cb = pSChHash->cbCertData + cbStr * c;
  1175. }
  1176. }
  1177. cb += 1 + (3 * cbStr * c) + pSChHash->cbFinal +
  1178. + pSChHash->cbClientRandom + pSChHash->cbServerRandom;
  1179. pb = (BYTE*)_nt_malloc(cb);
  1180. if (NULL == pb)
  1181. {
  1182. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  1183. goto ErrorExit;
  1184. }
  1185. // form the buffer to be hashed
  1186. pb[0] = (BYTE)c;
  1187. cbIndex = 1;
  1188. if (fWriteKey)
  1189. {
  1190. for (i=0;i<c;i++)
  1191. {
  1192. memcpy(pb + cbIndex, pbStr, cbStr);
  1193. cbIndex += cbStr;
  1194. }
  1195. }
  1196. memcpy(pb + cbIndex, pSChHash->rgbFinal, pSChHash->cbFinal);
  1197. cbIndex += pSChHash->cbFinal;
  1198. for (i=0;i<c;i++)
  1199. {
  1200. memcpy(pb + cbIndex, pbStr, cbStr);
  1201. cbIndex += cbStr;
  1202. }
  1203. memcpy(pb + cbIndex, pSChHash->rgbServerRandom, pSChHash->cbServerRandom);
  1204. cbIndex += pSChHash->cbServerRandom;
  1205. for (i=0;i<c;i++)
  1206. {
  1207. memcpy(pb + cbIndex, pbStr, cbStr);
  1208. cbIndex += cbStr;
  1209. }
  1210. if (!(CRYPT_SERVER & dwFlags))
  1211. {
  1212. memcpy(pb + cbIndex, pSChHash->pbCertData, pSChHash->cbCertData);
  1213. cbIndex += pSChHash->cbCertData;
  1214. for (i=0;i<c;i++)
  1215. {
  1216. memcpy(pb + cbIndex, pbStr, cbStr);
  1217. cbIndex += cbStr;
  1218. }
  1219. }
  1220. memcpy(pb + cbIndex, pSChHash->rgbClientRandom, pSChHash->cbClientRandom);
  1221. cbIndex += pSChHash->cbClientRandom;
  1222. for (i=0;i<c;i++)
  1223. {
  1224. memcpy(pb + cbIndex, pbStr, cbStr);
  1225. cbIndex += cbStr;
  1226. }
  1227. dwSts = HelperHash(pHash->hUID, pb, cb, pSChHash->HashAlgid,
  1228. &pbHash, &cbHash, TRUE);
  1229. if (ERROR_SUCCESS != dwSts)
  1230. {
  1231. dwReturn = dwSts;
  1232. goto ErrorExit;
  1233. }
  1234. *pcbBuff = cbHash;
  1235. memcpy(pbBuff, pbHash, *pcbBuff);
  1236. dwReturn = ERROR_SUCCESS;
  1237. ErrorExit:
  1238. if (pb)
  1239. _nt_free(pb, cb);
  1240. if (pbHash)
  1241. _nt_free(pbHash, cbHash);
  1242. return dwReturn;
  1243. }
  1244. /*static*/ DWORD
  1245. PCT1MakeExportableWriteKey(
  1246. PNTAGHashList pHash,
  1247. BYTE *pbBuff,
  1248. DWORD *pcbBuff)
  1249. {
  1250. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1251. BYTE *pb = NULL;
  1252. DWORD cb;
  1253. BYTE *pbHash = NULL;
  1254. DWORD cbHash;
  1255. PSCH_HASH pSChHash;
  1256. DWORD dwSts;
  1257. pSChHash = (PSCH_HASH)pHash->pHashData;
  1258. // assumption is made that exportable keys are 16 bytes in length (RC4 & RC2)
  1259. cb = 5 + *pcbBuff + pSChHash->cbClearData;
  1260. pb = (BYTE*)_nt_malloc(cb);
  1261. if (NULL == pb)
  1262. {
  1263. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  1264. goto ErrorExit;
  1265. }
  1266. // form the buffer to be hashed
  1267. pb[0] = 1;
  1268. memcpy(pb + 1, "sl", 2);
  1269. memcpy(pb + 3, pbBuff, *pcbBuff);
  1270. memcpy(pb + 3 + *pcbBuff, "sl", 2);
  1271. memcpy(pb + 5 + *pcbBuff, pSChHash->rgbClearData, pSChHash->cbClearData);
  1272. dwSts = HelperHash(pHash->hUID, pb, cb, pSChHash->HashAlgid,
  1273. &pbHash, &cbHash, TRUE);
  1274. if (ERROR_SUCCESS != dwSts)
  1275. {
  1276. dwReturn = dwSts;
  1277. goto ErrorExit;
  1278. }
  1279. *pcbBuff = cbHash;
  1280. memcpy(pbBuff, pbHash, *pcbBuff);
  1281. dwReturn = ERROR_SUCCESS;
  1282. ErrorExit:
  1283. if (pb)
  1284. _nt_free(pb, cb);
  1285. if (pbHash)
  1286. _nt_free(pbHash, cbHash);
  1287. return dwReturn;
  1288. }
  1289. /*static*/ DWORD
  1290. PCT1DeriveKey(
  1291. PNTAGUserList pTmpUser,
  1292. ALG_ID Algid,
  1293. PNTAGHashList pHash,
  1294. DWORD dwFlags,
  1295. HCRYPTKEY *phKey)
  1296. {
  1297. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1298. BYTE rgbHashBuff[A_SHA_DIGEST_LEN * 2]; // SHA is largest hash and max is two concatenated
  1299. DWORD cbHashBuff = 0;
  1300. DWORD cb;
  1301. DWORD cbKey;
  1302. PNTAGKeyList pTmpKey = NULL;
  1303. DWORD i;
  1304. DWORD cHashes;
  1305. ALG_ID KeyAlgid;
  1306. BOOL fWriteKey = FALSE;
  1307. PSCH_HASH pSChHash;
  1308. BYTE rgbSalt[MAX_SALT_LEN];
  1309. DWORD cbSalt = 0;
  1310. DWORD dwRights = 0;
  1311. DWORD dwSts;
  1312. memset(rgbSalt, 0, sizeof(rgbSalt));
  1313. pSChHash = (PSCH_HASH)pHash->pHashData;
  1314. switch (Algid)
  1315. {
  1316. case CALG_SCHANNEL_MAC_KEY:
  1317. cbKey = pSChHash->cbEncMac;
  1318. KeyAlgid = Algid;
  1319. break;
  1320. case CALG_SCHANNEL_ENC_KEY:
  1321. fWriteKey = TRUE;
  1322. cbKey = pSChHash->cbEnc;
  1323. KeyAlgid = pSChHash->EncAlgid;
  1324. break;
  1325. default:
  1326. dwReturn = (DWORD)NTE_BAD_ALGID;
  1327. goto ErrorExit;
  1328. }
  1329. cHashes = (cbKey + (pSChHash->cbHash - 1)) / pSChHash->cbHash;
  1330. if (cHashes > 2)
  1331. {
  1332. dwReturn = (DWORD)NTE_FAIL;
  1333. goto ErrorExit;
  1334. }
  1335. for (i=0;i<cHashes;i++)
  1336. {
  1337. dwSts = PCT1MakeKeyHash(pHash, i + 1, dwFlags, fWriteKey,
  1338. rgbHashBuff + cbHashBuff, &cb);
  1339. if (ERROR_SUCCESS != dwSts)
  1340. {
  1341. dwReturn = dwSts;
  1342. goto ErrorExit;
  1343. }
  1344. cbHashBuff += cb;
  1345. }
  1346. if ((CALG_SCHANNEL_ENC_KEY == Algid) &&
  1347. (EXPORTABLE_KEYLEN == pSChHash->cbEnc))
  1348. {
  1349. cbHashBuff = cbKey;
  1350. dwSts = PCT1MakeExportableWriteKey(pHash, rgbHashBuff, &cbHashBuff);
  1351. if (ERROR_SUCCESS != dwSts)
  1352. {
  1353. dwReturn = dwSts;
  1354. goto ErrorExit;
  1355. }
  1356. cbSalt = EXPORTABLE_SALTLEN;
  1357. memcpy(rgbSalt, rgbHashBuff + pSChHash->cbEnc, cbSalt);
  1358. }
  1359. // check if the key is CRYPT_EXPORTABLE
  1360. if (dwFlags & CRYPT_EXPORTABLE)
  1361. dwRights = CRYPT_EXPORTABLE;
  1362. // make the new key
  1363. dwSts = MakeNewKey(KeyAlgid, dwRights, cbKey,
  1364. pHash->hUID, rgbHashBuff,
  1365. FALSE, TRUE, &pTmpKey);
  1366. if (ERROR_SUCCESS != dwSts)
  1367. {
  1368. dwReturn = dwSts;
  1369. goto ErrorExit;
  1370. }
  1371. if (CALG_RC2 == KeyAlgid)
  1372. pTmpKey->EffectiveKeyLen = RC2_SCHANNEL_DEFAULT_EFFECTIVE_KEYLEN;
  1373. if ((CALG_SCHANNEL_ENC_KEY == Algid) &&
  1374. (EXPORTABLE_KEYLEN == pSChHash->cbEnc))
  1375. {
  1376. pTmpKey->cbSaltLen = cbSalt;
  1377. memcpy(pTmpKey->rgbSalt, rgbSalt, cbSalt);
  1378. }
  1379. // check keylength...
  1380. if (!FIsLegalKey(pTmpUser, pTmpKey, FALSE))
  1381. {
  1382. dwReturn = (DWORD)NTE_BAD_FLAGS;
  1383. goto ErrorExit;
  1384. }
  1385. dwSts = NTLMakeItem(phKey, KEY_HANDLE, (void *)pTmpKey);
  1386. if (ERROR_SUCCESS != dwSts)
  1387. {
  1388. dwReturn = dwSts;
  1389. goto ErrorExit;
  1390. }
  1391. pTmpKey = NULL;
  1392. dwReturn = ERROR_SUCCESS;
  1393. ErrorExit:
  1394. if (pTmpKey)
  1395. FreeNewKey(pTmpKey);
  1396. return dwReturn;
  1397. }
  1398. /*static*/ DWORD
  1399. TLSDeriveExportableRCKey(
  1400. PSCH_HASH pSChHash,
  1401. BYTE *pbClientAndServer,
  1402. DWORD cbClientAndServer,
  1403. BYTE **ppbKey,
  1404. DWORD *pcbKey,
  1405. BYTE *pbSalt,
  1406. DWORD *pcbSalt,
  1407. DWORD dwFlags)
  1408. {
  1409. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1410. DWORD dwSts;
  1411. // use key length 16 because this should only occur with RC2 and RC4
  1412. // and those key lengths should be 16
  1413. if ((CALG_RC2 == pSChHash->EncAlgid)
  1414. || (CALG_RC4 == pSChHash->EncAlgid))
  1415. {
  1416. *pcbKey = RC_KEYLEN;
  1417. *pcbSalt = RC_KEYLEN - pSChHash->cbEnc;
  1418. }
  1419. else
  1420. {
  1421. *pcbKey = pSChHash->cbEnc;
  1422. }
  1423. *ppbKey = (BYTE*)_nt_malloc(*pcbKey);
  1424. if (NULL == *ppbKey)
  1425. {
  1426. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  1427. goto ErrorExit;
  1428. }
  1429. // check if it is a server key or client key
  1430. if (dwFlags & CRYPT_SERVER)
  1431. {
  1432. dwSts = PRF(pSChHash->rgbFinal
  1433. + pSChHash->cbEncMac * 2
  1434. + pSChHash->cbEnc,
  1435. pSChHash->cbEnc,
  1436. (LPBYTE)"server write key",
  1437. 16,
  1438. pbClientAndServer,
  1439. cbClientAndServer,
  1440. *ppbKey,
  1441. *pcbKey);
  1442. if (ERROR_SUCCESS != dwSts)
  1443. {
  1444. dwReturn = dwSts;
  1445. goto ErrorExit;
  1446. }
  1447. }
  1448. else
  1449. {
  1450. dwSts = PRF(pSChHash->rgbFinal + pSChHash->cbEncMac * 2,
  1451. pSChHash->cbEnc, (LPBYTE)"client write key", 16,
  1452. pbClientAndServer, cbClientAndServer,
  1453. *ppbKey, *pcbKey);
  1454. if (ERROR_SUCCESS != dwSts)
  1455. {
  1456. dwReturn = dwSts;
  1457. goto ErrorExit;
  1458. }
  1459. }
  1460. if (0 != *pcbSalt)
  1461. memcpy(pbSalt, (*ppbKey) + pSChHash->cbEnc, *pcbSalt);
  1462. dwReturn = ERROR_SUCCESS;
  1463. ErrorExit:
  1464. return dwReturn;
  1465. }
  1466. /*static*/ DWORD
  1467. TLSDeriveExportableEncKey(
  1468. PSCH_HASH pSChHash,
  1469. BYTE **ppbKey,
  1470. DWORD *pcbKey,
  1471. BYTE **ppbRealKey,
  1472. BYTE *pbSalt,
  1473. DWORD *pcbSalt,
  1474. BYTE *pbIV,
  1475. DWORD dwFlags)
  1476. {
  1477. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1478. BYTE *pbClientAndServer = NULL;
  1479. DWORD cbClientAndServer;
  1480. BYTE *pbIVBlock = NULL;
  1481. DWORD dwSts;
  1482. cbClientAndServer = pSChHash->cbClientRandom + pSChHash->cbServerRandom;
  1483. pbClientAndServer = (BYTE*)_nt_malloc(cbClientAndServer);
  1484. if (NULL == pbClientAndServer)
  1485. {
  1486. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  1487. goto ErrorExit;
  1488. }
  1489. pbIVBlock = (BYTE*)_nt_malloc(pSChHash->cbIV * 2);
  1490. if (NULL == pbIVBlock)
  1491. {
  1492. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  1493. goto ErrorExit;
  1494. }
  1495. // concatenate the server random and client random
  1496. memcpy(pbClientAndServer, pSChHash->rgbClientRandom,
  1497. pSChHash->cbClientRandom);
  1498. memcpy(pbClientAndServer + pSChHash->cbClientRandom,
  1499. pSChHash->rgbServerRandom, pSChHash->cbServerRandom);
  1500. // calculate the IV block
  1501. if (pSChHash->cbIV)
  1502. {
  1503. dwSts = PRF(NULL, 0, (LPBYTE)"IV block", 8, pbClientAndServer,
  1504. cbClientAndServer, pbIVBlock, pSChHash->cbIV * 2);
  1505. if (ERROR_SUCCESS != dwSts)
  1506. {
  1507. dwReturn = dwSts;
  1508. goto ErrorExit;
  1509. }
  1510. if (dwFlags & CRYPT_SERVER)
  1511. memcpy(pbIV, pbIVBlock + pSChHash->cbIV, pSChHash->cbIV);
  1512. else
  1513. memcpy(pbIV, pbIVBlock, pSChHash->cbIV);
  1514. }
  1515. // check if it is a server key or client key
  1516. dwSts = TLSDeriveExportableRCKey(pSChHash,
  1517. pbClientAndServer,
  1518. cbClientAndServer,
  1519. ppbKey,
  1520. pcbKey,
  1521. pbSalt,
  1522. pcbSalt,
  1523. dwFlags);
  1524. if (ERROR_SUCCESS != dwSts)
  1525. {
  1526. dwReturn = dwSts;
  1527. goto ErrorExit;
  1528. }
  1529. *ppbRealKey = *ppbKey;
  1530. dwReturn = ERROR_SUCCESS;
  1531. ErrorExit:
  1532. if (pbIVBlock)
  1533. _nt_free(pbIVBlock, pSChHash->cbIV * 2);
  1534. if (pbClientAndServer)
  1535. _nt_free(pbClientAndServer, cbClientAndServer);
  1536. return dwReturn;
  1537. }
  1538. /*static*/ DWORD
  1539. TLSDeriveKey(
  1540. PNTAGUserList pTmpUser,
  1541. ALG_ID Algid,
  1542. PNTAGHashList pHash,
  1543. DWORD dwFlags,
  1544. HCRYPTKEY *phKey)
  1545. {
  1546. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1547. PSCH_HASH pSChHash;
  1548. PNTAGKeyList pTmpKey = NULL;
  1549. BYTE *pbKey;
  1550. DWORD cbKey;
  1551. BYTE rgbSalt[MAX_SALT_LEN];
  1552. DWORD cbSalt = 0;
  1553. BYTE rgbIV[CRYPT_BLKLEN];
  1554. DWORD cbIVIndex = 0;
  1555. ALG_ID KeyAlgid;
  1556. BYTE *pbAllocKey = NULL;
  1557. DWORD cbAllocKey;
  1558. DWORD dwRights = 0;
  1559. DWORD dwSts;
  1560. memset(rgbIV, 0, sizeof(rgbIV));
  1561. memset(rgbSalt, 0, sizeof(rgbSalt));
  1562. pSChHash = (PSCH_HASH)pHash->pHashData;
  1563. switch (Algid)
  1564. {
  1565. case CALG_SCHANNEL_MAC_KEY:
  1566. cbKey = pSChHash->cbEncMac;
  1567. KeyAlgid = Algid;
  1568. // check if it is a server key or client key
  1569. if (dwFlags & CRYPT_SERVER)
  1570. pbKey = pSChHash->rgbFinal + pSChHash->cbEncMac;
  1571. else
  1572. pbKey = pSChHash->rgbFinal;
  1573. break;
  1574. case CALG_SCHANNEL_ENC_KEY:
  1575. cbKey = pSChHash->cbEnc;
  1576. KeyAlgid = pSChHash->EncAlgid;
  1577. // if in exportable situation then call the exportable routine
  1578. if (pSChHash->dwFlags & INTERNATIONAL_USAGE)
  1579. {
  1580. dwSts = TLSDeriveExportableEncKey(pSChHash, &pbAllocKey,
  1581. &cbAllocKey, &pbKey, rgbSalt,
  1582. &cbSalt, rgbIV, dwFlags);
  1583. if (ERROR_SUCCESS != dwSts)
  1584. {
  1585. dwReturn = dwSts;
  1586. goto ErrorExit;
  1587. }
  1588. }
  1589. else
  1590. {
  1591. if (dwFlags & CRYPT_SERVER)
  1592. {
  1593. pbKey = pSChHash->rgbFinal + pSChHash->cbEncMac * 2 +
  1594. pSChHash->cbEnc;
  1595. if (pSChHash->cbIV)
  1596. {
  1597. cbIVIndex = pSChHash->cbEncMac * 2 +
  1598. pSChHash->cbEnc * 2 + pSChHash->cbIV;
  1599. }
  1600. }
  1601. else
  1602. {
  1603. pbKey = pSChHash->rgbFinal + pSChHash->cbEncMac * 2;
  1604. if (pSChHash->cbIV)
  1605. {
  1606. cbIVIndex = pSChHash->cbEncMac * 2 +
  1607. pSChHash->cbEnc * 2;
  1608. }
  1609. }
  1610. memcpy(rgbIV, pSChHash->rgbFinal + cbIVIndex,
  1611. pSChHash->cbIV);
  1612. }
  1613. break;
  1614. default:
  1615. dwReturn = (DWORD)NTE_BAD_ALGID;
  1616. goto ErrorExit;
  1617. }
  1618. // check if the key is CRYPT_EXPORTABLE
  1619. if (dwFlags & CRYPT_EXPORTABLE)
  1620. dwRights = CRYPT_EXPORTABLE;
  1621. // make the new key
  1622. dwSts = MakeNewKey(KeyAlgid, dwRights, cbKey,
  1623. pHash->hUID, pbKey,
  1624. FALSE, TRUE, &pTmpKey);
  1625. if (ERROR_SUCCESS != dwSts)
  1626. {
  1627. dwReturn = dwSts;
  1628. goto ErrorExit;
  1629. }
  1630. if (CALG_RC2 == KeyAlgid)
  1631. pTmpKey->EffectiveKeyLen = RC2_SCHANNEL_DEFAULT_EFFECTIVE_KEYLEN;
  1632. // set up the salt
  1633. memcpy(pTmpKey->rgbSalt, rgbSalt, cbSalt);
  1634. pTmpKey->cbSaltLen = cbSalt;
  1635. // copy IV if necessary
  1636. if (pSChHash->cbIV)
  1637. memcpy(pTmpKey->IV, rgbIV, pSChHash->cbIV);
  1638. // check keylength...
  1639. if (!FIsLegalKey(pTmpUser, pTmpKey, FALSE))
  1640. {
  1641. dwReturn = (DWORD)NTE_BAD_FLAGS;
  1642. goto ErrorExit;
  1643. }
  1644. dwSts = NTLMakeItem(phKey, KEY_HANDLE, (void *)pTmpKey);
  1645. if (ERROR_SUCCESS != dwSts)
  1646. {
  1647. dwReturn = dwSts;
  1648. goto ErrorExit;
  1649. }
  1650. pTmpKey = NULL;
  1651. dwReturn = ERROR_SUCCESS;
  1652. ErrorExit:
  1653. if (NULL != pbAllocKey)
  1654. _nt_free(pbAllocKey, cbAllocKey);
  1655. if (NULL != pTmpKey)
  1656. FreeNewKey(pTmpKey);
  1657. return dwReturn;
  1658. }
  1659. /*static*/ DWORD
  1660. SSL2DeriveKey(
  1661. PNTAGUserList pTmpUser,
  1662. ALG_ID Algid,
  1663. PNTAGHashList pHash,
  1664. DWORD dwFlags,
  1665. HCRYPTKEY *phKey)
  1666. {
  1667. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1668. PSCH_HASH pSChHash;
  1669. BYTE rgbHash[2 * MD5DIGESTLEN];
  1670. BYTE *pbHash;
  1671. DWORD cbHash = 2 * MD5DIGESTLEN;
  1672. BYTE *pbTmp = NULL;
  1673. DWORD cbTmp;
  1674. BYTE *pbKey = NULL;
  1675. DWORD cbKey = 0;
  1676. BYTE rgbSalt[MAX_SALT_LEN];
  1677. DWORD cbSalt = 0;
  1678. DWORD cbIndex;
  1679. DWORD cbChangeByte;
  1680. PNTAGKeyList pTmpKey = NULL;
  1681. DWORD dwRights = 0;
  1682. DWORD dwSts;
  1683. memset(rgbSalt, 0, sizeof(rgbSalt));
  1684. if (CALG_SCHANNEL_ENC_KEY != Algid)
  1685. {
  1686. dwReturn = (DWORD)NTE_BAD_ALGID;
  1687. goto ErrorExit;
  1688. }
  1689. pbHash = rgbHash;
  1690. pSChHash = (PSCH_HASH)pHash->pHashData;
  1691. // set up the buffer to be hashed
  1692. cbTmp = pSChHash->cbFinal + pSChHash->cbClearData +
  1693. pSChHash->cbClientRandom + pSChHash->cbServerRandom + 1;
  1694. pbTmp = (BYTE*)_nt_malloc(cbTmp);
  1695. if (NULL == pbTmp)
  1696. {
  1697. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  1698. goto ErrorExit;
  1699. }
  1700. memcpy(pbTmp, pSChHash->rgbClearData,
  1701. pSChHash->cbClearData);
  1702. cbIndex = pSChHash->cbClearData;
  1703. // exportability check
  1704. memcpy(pbTmp + cbIndex, pSChHash->rgbFinal, pSChHash->cbFinal);
  1705. cbIndex += pSChHash->cbFinal;
  1706. cbChangeByte = cbIndex;
  1707. cbIndex++;
  1708. memcpy(pbTmp + cbIndex, pSChHash->rgbClientRandom,
  1709. pSChHash->cbClientRandom);
  1710. cbIndex += pSChHash->cbClientRandom;
  1711. memcpy(pbTmp + cbIndex, pSChHash->rgbServerRandom,
  1712. pSChHash->cbServerRandom);
  1713. cbIndex += pSChHash->cbServerRandom;
  1714. switch (pSChHash->EncAlgid)
  1715. {
  1716. #ifdef CSP_USE_RC2
  1717. case CALG_RC2:
  1718. #endif
  1719. #ifdef CSP_USE_RC4
  1720. case CALG_RC4:
  1721. #endif
  1722. if (CRYPT_SERVER & dwFlags)
  1723. pbTmp[cbChangeByte] = 0x30;
  1724. else
  1725. pbTmp[cbChangeByte] = 0x31;
  1726. // hash the data to get the key
  1727. dwSts = HelperHash(pHash->hUID, pbTmp, cbTmp, CALG_MD5,
  1728. &pbHash, &cbHash, FALSE);
  1729. if (ERROR_SUCCESS != dwSts)
  1730. {
  1731. dwReturn = dwSts;
  1732. goto ErrorExit;
  1733. }
  1734. pbKey = pbHash;
  1735. // check for export
  1736. if (pSChHash->cbClearData)
  1737. {
  1738. cbKey = 5;
  1739. cbSalt = 11;
  1740. memcpy(rgbSalt, pbKey + cbKey, cbSalt);
  1741. }
  1742. else
  1743. cbKey = 16;
  1744. break;
  1745. #ifdef CSP_USE_DES
  1746. case CALG_DES:
  1747. pbTmp[cbChangeByte] = 0x30;
  1748. // hash the data to get the key
  1749. dwSts = HelperHash(pHash->hUID, pbTmp, cbTmp,
  1750. CALG_MD5, &pbHash, &cbHash, FALSE);
  1751. if (ERROR_SUCCESS != dwSts)
  1752. {
  1753. dwReturn = dwSts;
  1754. goto ErrorExit;
  1755. }
  1756. if (CRYPT_SERVER & dwFlags)
  1757. pbKey = pbHash;
  1758. else
  1759. pbKey = pbHash + DES_KEYSIZE;
  1760. cbKey = DES_KEYSIZE;
  1761. break;
  1762. #endif
  1763. #ifdef CSP_USE_3DES
  1764. case CALG_3DES:
  1765. if (CRYPT_SERVER & dwFlags)
  1766. {
  1767. pbTmp[cbChangeByte] = 0x30;
  1768. // hash the data to get the key
  1769. dwSts = HelperHash(pHash->hUID, pbTmp, cbTmp,
  1770. CALG_MD5, &pbHash, &cbHash, FALSE);
  1771. if (ERROR_SUCCESS != dwSts)
  1772. {
  1773. dwReturn = dwSts;
  1774. goto ErrorExit;
  1775. }
  1776. pbTmp[cbChangeByte] = 0x31;
  1777. pbHash = rgbHash + MD5DIGESTLEN;
  1778. // hash the data to get the key
  1779. dwSts = HelperHash(pHash->hUID, pbTmp, cbTmp, CALG_MD5,
  1780. &pbHash, &cbHash, FALSE);
  1781. if (ERROR_SUCCESS != dwSts)
  1782. {
  1783. dwReturn = dwSts;
  1784. goto ErrorExit;
  1785. }
  1786. pbKey = rgbHash;
  1787. }
  1788. else
  1789. {
  1790. pbTmp[cbChangeByte] = 0x31;
  1791. // hash the data to get the key
  1792. dwSts = HelperHash(pHash->hUID, pbTmp, cbTmp,
  1793. CALG_MD5, &pbHash, &cbHash, FALSE);
  1794. if (ERROR_SUCCESS != dwSts)
  1795. {
  1796. dwReturn = dwSts;
  1797. goto ErrorExit;
  1798. }
  1799. pbTmp[cbChangeByte] = 0x32;
  1800. pbHash = rgbHash + MD5DIGESTLEN;
  1801. // hash the data to get the key
  1802. dwSts = HelperHash(pHash->hUID, pbTmp, cbTmp, CALG_MD5,
  1803. &pbHash, &cbHash, FALSE);
  1804. if (ERROR_SUCCESS != dwSts)
  1805. {
  1806. dwReturn = dwSts;
  1807. goto ErrorExit;
  1808. }
  1809. pbKey = rgbHash + DES_KEYSIZE;
  1810. }
  1811. cbKey = DES3_KEYSIZE;
  1812. break;
  1813. #endif
  1814. }
  1815. // check if the key is CRYPT_EXPORTABLE
  1816. if (dwFlags & CRYPT_EXPORTABLE)
  1817. dwRights = CRYPT_EXPORTABLE;
  1818. // make the new key
  1819. dwSts = MakeNewKey(pSChHash->EncAlgid,
  1820. dwRights,
  1821. cbKey,
  1822. pHash->hUID,
  1823. pbKey,
  1824. FALSE,
  1825. TRUE,
  1826. &pTmpKey);
  1827. if (ERROR_SUCCESS != dwSts)
  1828. {
  1829. dwReturn = dwSts;
  1830. goto ErrorExit;
  1831. }
  1832. if (CALG_RC2 == pSChHash->EncAlgid)
  1833. pTmpKey->EffectiveKeyLen = RC2_SCHANNEL_DEFAULT_EFFECTIVE_KEYLEN;
  1834. pTmpKey->cbSaltLen = cbSalt;
  1835. memcpy(pTmpKey->rgbSalt, rgbSalt, cbSalt);
  1836. // check keylength...
  1837. if (!FIsLegalKey(pTmpUser, pTmpKey, FALSE))
  1838. {
  1839. dwReturn = (DWORD)NTE_BAD_FLAGS;
  1840. goto ErrorExit;
  1841. }
  1842. dwSts = NTLMakeItem(phKey, KEY_HANDLE, (void *)pTmpKey);
  1843. if (ERROR_SUCCESS != dwSts)
  1844. {
  1845. dwReturn = dwSts;
  1846. goto ErrorExit;
  1847. }
  1848. pTmpKey = NULL;
  1849. dwReturn = ERROR_SUCCESS;
  1850. ErrorExit:
  1851. if (pbTmp)
  1852. _nt_free(pbTmp, cbTmp);
  1853. if (pTmpKey)
  1854. FreeNewKey(pTmpKey);
  1855. return dwReturn;
  1856. }
  1857. DWORD
  1858. SecureChannelDeriveKey(
  1859. PNTAGUserList pTmpUser,
  1860. PNTAGHashList pHash,
  1861. ALG_ID Algid,
  1862. DWORD dwFlags,
  1863. HCRYPTKEY *phKey)
  1864. {
  1865. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1866. PSCH_HASH pSChHash;
  1867. BYTE *pbKey = NULL;
  1868. DWORD cbKey;
  1869. PNTAGKeyList pTmpKey = NULL;
  1870. DWORD dwRights = 0;
  1871. DWORD dwSts;
  1872. pSChHash = (PSCH_HASH)pHash->pHashData;
  1873. switch (pSChHash->ProtocolAlgid)
  1874. {
  1875. case CALG_SSL3_MASTER:
  1876. switch (Algid)
  1877. {
  1878. case CALG_SCHANNEL_MAC_KEY:
  1879. cbKey = pSChHash->cbEncMac;
  1880. pbKey = (BYTE*)_nt_malloc(cbKey);
  1881. if (NULL == pbKey)
  1882. {
  1883. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  1884. goto ErrorExit;
  1885. }
  1886. // if not flagged as a server key then default is client
  1887. if (CRYPT_SERVER & dwFlags)
  1888. memcpy(pbKey, pSChHash->rgbFinal + cbKey, cbKey);
  1889. else
  1890. memcpy(pbKey, pSChHash->rgbFinal, cbKey);
  1891. // check if the key is CRYPT_EXPORTABLE
  1892. if (dwFlags & CRYPT_EXPORTABLE)
  1893. dwRights = CRYPT_EXPORTABLE;
  1894. // make the new key
  1895. dwSts = MakeNewKey(Algid, dwRights, cbKey, pHash->hUID,
  1896. pbKey, TRUE, TRUE, &pTmpKey);
  1897. if (ERROR_SUCCESS != dwSts)
  1898. {
  1899. dwReturn = dwSts;
  1900. goto ErrorExit;
  1901. }
  1902. pbKey = NULL;
  1903. // check keylength...
  1904. if (!FIsLegalKey(pTmpUser, pTmpKey, FALSE))
  1905. {
  1906. dwReturn = (DWORD)NTE_BAD_FLAGS;
  1907. goto ErrorExit;
  1908. }
  1909. dwSts = NTLMakeItem(phKey, KEY_HANDLE, (void *)pTmpKey);
  1910. if (ERROR_SUCCESS != dwSts)
  1911. {
  1912. dwReturn = dwSts;
  1913. goto ErrorExit;
  1914. }
  1915. break;
  1916. case CALG_SCHANNEL_ENC_KEY:
  1917. // derive the write keys
  1918. dwSts = SSL3DeriveWriteKey(pTmpUser, pHash, dwFlags, phKey);
  1919. if (ERROR_SUCCESS != dwSts)
  1920. {
  1921. dwReturn = dwSts;
  1922. goto ErrorExit;
  1923. }
  1924. break;
  1925. default:
  1926. dwReturn = (DWORD)NTE_BAD_ALGID;
  1927. goto ErrorExit;
  1928. }
  1929. break;
  1930. case CALG_PCT1_MASTER:
  1931. // derive the PCT1 key
  1932. dwSts = PCT1DeriveKey(pTmpUser, Algid, pHash, dwFlags, phKey);
  1933. if (ERROR_SUCCESS != dwSts)
  1934. {
  1935. dwReturn = dwSts;
  1936. goto ErrorExit;
  1937. }
  1938. break;
  1939. case CALG_TLS1_MASTER:
  1940. // derive the PCT1 key
  1941. dwSts = TLSDeriveKey(pTmpUser, Algid, pHash, dwFlags, phKey);
  1942. if (ERROR_SUCCESS != dwSts)
  1943. {
  1944. dwReturn = dwSts;
  1945. goto ErrorExit;
  1946. }
  1947. break;
  1948. case CALG_SSL2_MASTER:
  1949. // derive the PCT1 key
  1950. dwSts = SSL2DeriveKey(pTmpUser, Algid, pHash, dwFlags, phKey);
  1951. if (ERROR_SUCCESS != dwSts)
  1952. {
  1953. dwReturn = dwSts;
  1954. goto ErrorExit;
  1955. }
  1956. break;
  1957. }
  1958. pTmpKey = NULL;
  1959. dwReturn = ERROR_SUCCESS;
  1960. ErrorExit:
  1961. if (pbKey)
  1962. _nt_free(pbKey, cbKey);
  1963. if (NULL != pTmpKey)
  1964. FreeNewKey(pTmpKey);
  1965. return dwReturn;
  1966. }
  1967. DWORD
  1968. SetPRFHashParam(
  1969. PRF_HASH *pPRFHash,
  1970. DWORD dwParam,
  1971. CONST BYTE *pbData)
  1972. {
  1973. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1974. CRYPT_DATA_BLOB *pBlob;
  1975. pBlob = (CRYPT_DATA_BLOB*)pbData;
  1976. if (HP_TLS1PRF_LABEL == dwParam)
  1977. {
  1978. if (pBlob->cbData > sizeof(pPRFHash->rgbLabel))
  1979. {
  1980. dwReturn = (DWORD)NTE_BAD_DATA;
  1981. goto ErrorExit;
  1982. }
  1983. pPRFHash->cbLabel = pBlob->cbData;
  1984. memcpy(pPRFHash->rgbLabel, pBlob->pbData, pBlob->cbData);
  1985. }
  1986. else
  1987. {
  1988. if (pBlob->cbData > sizeof(pPRFHash->rgbSeed))
  1989. {
  1990. dwReturn = (DWORD)NTE_BAD_DATA;
  1991. goto ErrorExit;
  1992. }
  1993. pPRFHash->cbSeed = pBlob->cbData;
  1994. memcpy(pPRFHash->rgbSeed, pBlob->pbData, pBlob->cbData);
  1995. }
  1996. dwReturn = ERROR_SUCCESS;
  1997. ErrorExit:
  1998. return dwReturn;
  1999. }
  2000. DWORD
  2001. CalculatePRF(
  2002. PRF_HASH *pPRFHash,
  2003. BYTE *pbData,
  2004. DWORD *pcbData)
  2005. {
  2006. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  2007. DWORD dwSts;
  2008. if (NULL == pbData)
  2009. {
  2010. *pcbData = 0;
  2011. }
  2012. else
  2013. {
  2014. if ((0 == pPRFHash->cbSeed) || (0 == pPRFHash->cbLabel))
  2015. {
  2016. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  2017. goto ErrorExit;
  2018. }
  2019. dwSts = PRF(pPRFHash->rgbMasterKey, sizeof(pPRFHash->rgbMasterKey),
  2020. pPRFHash->rgbLabel, pPRFHash->cbLabel,
  2021. pPRFHash->rgbSeed, pPRFHash->cbSeed, pbData, *pcbData);
  2022. if (ERROR_SUCCESS != dwSts)
  2023. {
  2024. dwReturn = dwSts;
  2025. goto ErrorExit;
  2026. }
  2027. }
  2028. dwReturn = ERROR_SUCCESS;
  2029. ErrorExit:
  2030. return dwReturn;
  2031. }