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.

1344 lines
40 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: pct1msg.c
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 09-23-97 jbanes LSA integration stuff.
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <spbase.h>
  18. #include <pct1msg.h>
  19. #include <pct1prot.h>
  20. static SP_STATUS
  21. Pct1ComputeMac(
  22. PSPContext pContext,
  23. BOOL fWriteMAC,
  24. PSPBuffer pData,
  25. DWORD dwSequence,
  26. PBYTE pbMac,
  27. PDWORD pcbMac);
  28. Pct1CipherMap Pct1CipherRank[] = {
  29. {CALG_RC4, 128, PCT1_CIPHER_RC4 | PCT1_ENC_BITS_128 | PCT1_MAC_BITS_128},
  30. {CALG_RC4, 64, PCT1_CIPHER_RC4 | PCT1_ENC_BITS_64 | PCT1_MAC_BITS_128},
  31. {CALG_RC4, 40, PCT1_CIPHER_RC4 | PCT1_ENC_BITS_40 | PCT1_MAC_BITS_128},
  32. };
  33. DWORD Pct1NumCipher = sizeof(Pct1CipherRank)/sizeof(Pct1CipherMap);
  34. /* available hashes, in order of preference */
  35. Pct1HashMap Pct1HashRank[] = {
  36. {CALG_MD5, PCT1_HASH_MD5},
  37. {CALG_SHA, PCT1_HASH_SHA}
  38. };
  39. DWORD Pct1NumHash = sizeof(Pct1HashRank)/sizeof(Pct1HashMap);
  40. CertTypeMap aPct1CertEncodingPref[] =
  41. {
  42. { X509_ASN_ENCODING , PCT1_CERT_X509_CHAIN },
  43. { X509_ASN_ENCODING , PCT1_CERT_X509 }
  44. };
  45. DWORD cPct1CertEncodingPref = sizeof(aPct1CertEncodingPref)/sizeof(CertTypeMap);
  46. KeyTypeMap aPct1LocalExchKeyPref[] = // CAPI Key type, SCHANNEL ALGID
  47. {
  48. { CALG_RSA_KEYX, SP_EXCH_RSA_PKCS1 }
  49. };
  50. DWORD cPct1LocalExchKeyPref = sizeof(aPct1LocalExchKeyPref)/sizeof(KeyTypeMap);
  51. KeyTypeMap aPct1LocalSigKeyPref[] = // CAPI Key type, SCHANNEL ALGID
  52. {
  53. { CALG_RSA_KEYX, SP_SIG_RSA_MD5 },
  54. { CALG_RSA_KEYX, SP_SIG_RSA_SHA }
  55. };
  56. DWORD cPct1LocalSigKeyPref = sizeof(aPct1LocalSigKeyPref)/sizeof(KeyTypeMap);
  57. SP_STATUS WINAPI
  58. Pct1EncryptRaw( PSPContext pContext,
  59. PSPBuffer pAppInput,
  60. PSPBuffer pCommOutput,
  61. DWORD dwFlags)
  62. {
  63. SP_STATUS pctRet;
  64. DWORD cPadding;
  65. SPBuffer Clean;
  66. SPBuffer Encrypted;
  67. BOOL fEscape;
  68. DWORD cbHeader;
  69. DWORD cbBlockSize;
  70. BYTE rgbMac[SP_MAX_DIGEST_LEN];
  71. DWORD cbMac;
  72. fEscape = (0 != (dwFlags & PCT1_ENCRYPT_ESCAPE));
  73. cbBlockSize = pContext->pCipherInfo->dwBlockSize;
  74. cPadding = pAppInput->cbData & (cbBlockSize - 1);
  75. if(cPadding)
  76. {
  77. cPadding = cbBlockSize - cPadding;
  78. }
  79. if(fEscape || (cbBlockSize > 1))
  80. {
  81. cbHeader = sizeof(PCT1_MESSAGE_HEADER_EX);
  82. }
  83. else
  84. {
  85. cbHeader = sizeof(PCT1_MESSAGE_HEADER);
  86. }
  87. if(pCommOutput->cbBuffer < (cbHeader + cPadding + pAppInput->cbData))
  88. {
  89. return PCT_INT_BUFF_TOO_SMALL;
  90. }
  91. Encrypted.pvBuffer = (PUCHAR)pCommOutput->pvBuffer + cbHeader;
  92. Encrypted.cbBuffer = pCommOutput->cbBuffer - cbHeader;
  93. Encrypted.cbData = pAppInput->cbData;
  94. // Copy input data to output buffer (we're encrypting in place).
  95. if(pAppInput->pvBuffer != Encrypted.pvBuffer)
  96. {
  97. DebugLog((DEB_WARN, "Pct1EncryptRaw: Unnecessary Move, performance hog\n"));
  98. MoveMemory(Encrypted.pvBuffer,
  99. pAppInput->pvBuffer,
  100. pAppInput->cbData);
  101. }
  102. /* Generate Padding */
  103. GenerateRandomBits((PUCHAR)Encrypted.pvBuffer + Encrypted.cbData, cPadding);
  104. Encrypted.cbData += cPadding;
  105. DebugLog((DEB_TRACE, "Sealing message %x\n", pContext->WriteCounter));
  106. // Transfer the write key over from the application process.
  107. if(pContext->hWriteKey == 0)
  108. {
  109. DebugLog((DEB_TRACE, "Transfer write key from user process.\n"));
  110. pctRet = SPGetUserKeys(pContext, SCH_FLAG_WRITE_KEY);
  111. if(pctRet != PCT_ERR_OK)
  112. {
  113. return SP_LOG_RESULT(pctRet);
  114. }
  115. }
  116. // Compute the MAC.
  117. cbMac = sizeof(rgbMac);
  118. pctRet = Pct1ComputeMac(pContext,
  119. TRUE,
  120. &Encrypted,
  121. pContext->WriteCounter,
  122. rgbMac,
  123. &cbMac);
  124. if(pctRet != PCT_ERR_OK)
  125. {
  126. return SP_LOG_RESULT(pctRet);
  127. }
  128. pContext->WriteCounter ++ ;
  129. // Encrypt data.
  130. if(!SchCryptEncrypt(pContext->hWriteKey,
  131. 0, FALSE, 0,
  132. Encrypted.pvBuffer,
  133. &Encrypted.cbData,
  134. Encrypted.cbBuffer,
  135. pContext->RipeZombie->dwCapiFlags))
  136. {
  137. SP_LOG_RESULT(GetLastError());
  138. return PCT_INT_INTERNAL_ERROR;
  139. }
  140. // Add MAC to encrypted buffer.
  141. if(Encrypted.cbData + cbMac > Encrypted.cbBuffer)
  142. {
  143. return PCT_INT_BUFF_TOO_SMALL;
  144. }
  145. CopyMemory((PUCHAR)Encrypted.pvBuffer + Encrypted.cbData,
  146. rgbMac,
  147. cbMac);
  148. Encrypted.cbData += cbMac;
  149. /* set sizes */
  150. if(fEscape || (cbBlockSize > 1))
  151. {
  152. if(Encrypted.cbData > 0x3fff)
  153. {
  154. return PCT_INT_DATA_OVERFLOW;
  155. }
  156. ((PUCHAR)pCommOutput->pvBuffer)[0]= (UCHAR)(0x3f & (Encrypted.cbData>>8));
  157. if(fEscape)
  158. {
  159. ((PUCHAR)pCommOutput->pvBuffer)[0] |= 0x40;
  160. }
  161. ((PUCHAR)pCommOutput->pvBuffer)[1]= (UCHAR)(0xff & Encrypted.cbData);
  162. ((PUCHAR)pCommOutput->pvBuffer)[2]= (UCHAR)cPadding;
  163. }
  164. else
  165. {
  166. if(Encrypted.cbData > 0x7fff)
  167. {
  168. return PCT_INT_DATA_OVERFLOW;
  169. }
  170. ((PUCHAR)pCommOutput->pvBuffer)[0]= (UCHAR)(0x7f & (Encrypted.cbData>>8)) | 0x80;
  171. ((PUCHAR)pCommOutput->pvBuffer)[1]= (UCHAR)(0xff & Encrypted.cbData);
  172. }
  173. pCommOutput->cbData = Encrypted.cbData + cbHeader;
  174. #if DBG
  175. {
  176. DWORD di;
  177. CHAR KeyDispBuf[SP_MAX_DIGEST_LEN*2+1];
  178. for(di=0;di<cbMac;di++)
  179. wsprintf(KeyDispBuf+(di*2), "%2.2x", rgbMac[di]);
  180. DebugLog((DEB_TRACE, " Computed MAC\t%s\n", KeyDispBuf));
  181. }
  182. #endif
  183. return PCT_ERR_OK;
  184. }
  185. SP_STATUS WINAPI
  186. Pct1EncryptMessage( PSPContext pContext,
  187. PSPBuffer pAppInput,
  188. PSPBuffer pCommOutput)
  189. {
  190. return Pct1EncryptRaw(pContext, pAppInput, pCommOutput,0);
  191. }
  192. SP_STATUS WINAPI
  193. Pct1GetHeaderSize(
  194. PSPContext pContext,
  195. PSPBuffer pCommInput,
  196. DWORD * pcbHeaderSize)
  197. {
  198. if(pcbHeaderSize == NULL)
  199. {
  200. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  201. }
  202. if(pCommInput->cbData < 1)
  203. {
  204. return (PCT_INT_INCOMPLETE_MSG);
  205. }
  206. if( ((PUCHAR)pCommInput->pvBuffer)[0]&0x80 )
  207. {
  208. *pcbHeaderSize = 2;
  209. }
  210. else
  211. {
  212. *pcbHeaderSize = 3;
  213. }
  214. return PCT_ERR_OK;
  215. }
  216. SP_STATUS WINAPI
  217. Pct1DecryptMessage(PSPContext pContext,
  218. PSPBuffer pMessage,
  219. PSPBuffer pAppOutput)
  220. {
  221. SP_STATUS pctRet;
  222. DWORD cbHeader;
  223. DWORD cbPadding;
  224. DWORD cbPayload;
  225. DWORD cbActualData;
  226. SPBuffer Encrypted;
  227. PUCHAR pbMAC;
  228. BYTE rgbMac[SP_MAX_DIGEST_LEN];
  229. DWORD cbMac;
  230. cbActualData = pMessage->cbData;
  231. // Do we have a complete header?
  232. pMessage->cbData = 2;
  233. if(cbActualData < 2)
  234. {
  235. return PCT_INT_INCOMPLETE_MSG;
  236. }
  237. if(((PUCHAR)pMessage->pvBuffer)[0] & 0x80)
  238. {
  239. cbHeader = 2;
  240. cbPadding = 0;
  241. cbPayload = MAKEWORD(((PUCHAR)pMessage->pvBuffer)[1],
  242. ((PUCHAR)pMessage->pvBuffer)[0] & 0x7f);
  243. }
  244. else
  245. {
  246. // Do we still have a complete header?
  247. cbHeader = 3;
  248. pMessage->cbData++;
  249. if(cbActualData < cbHeader)
  250. {
  251. return PCT_INT_INCOMPLETE_MSG;
  252. }
  253. cbPadding = ((PUCHAR)pMessage->pvBuffer)[2];
  254. cbPayload = MAKEWORD(((PUCHAR)pMessage->pvBuffer)[1],
  255. ((PUCHAR)pMessage->pvBuffer)[0] & 0x3f);
  256. }
  257. // Do we have the complete message?
  258. pMessage->cbData += cbPayload;
  259. if(cbActualData < cbHeader + cbPayload)
  260. {
  261. return PCT_INT_INCOMPLETE_MSG;
  262. }
  263. /* do we have enough data for our checksum */
  264. if(cbPayload < pContext->pHashInfo->cbCheckSum)
  265. {
  266. return SP_LOG_RESULT(PCT_INT_MSG_ALTERED);
  267. }
  268. Encrypted.pvBuffer = (PUCHAR)pMessage->pvBuffer + cbHeader;
  269. Encrypted.cbBuffer = cbPayload - pContext->pHashInfo->cbCheckSum;
  270. Encrypted.cbData = Encrypted.cbBuffer;
  271. pbMAC = (PUCHAR)Encrypted.pvBuffer + Encrypted.cbData;
  272. /* check to see if we have a block size violation */
  273. if(Encrypted.cbData % pContext->pCipherInfo->dwBlockSize)
  274. {
  275. return SP_LOG_RESULT(PCT_INT_MSG_ALTERED);
  276. }
  277. Encrypted.cbBuffer = Encrypted.cbData;
  278. // Decrypt message.
  279. if(Encrypted.cbData > pAppOutput->cbBuffer)
  280. {
  281. return SP_LOG_RESULT(PCT_INT_BUFF_TOO_SMALL);
  282. }
  283. if(Encrypted.pvBuffer != pAppOutput->pvBuffer)
  284. {
  285. DebugLog((DEB_WARN, "Pct1DecryptMessage: Unnecessary MoveMemory, performance hog\n"));
  286. MoveMemory(pAppOutput->pvBuffer,
  287. Encrypted.pvBuffer,
  288. Encrypted.cbData);
  289. }
  290. pAppOutput->cbData = Encrypted.cbData;
  291. // Transfer the read key over from the application process.
  292. if(pContext->hReadKey == 0)
  293. {
  294. DebugLog((DEB_TRACE, "Transfer read key from user process.\n"));
  295. pctRet = SPGetUserKeys(pContext, SCH_FLAG_READ_KEY);
  296. if(pctRet != PCT_ERR_OK)
  297. {
  298. return SP_LOG_RESULT(pctRet);
  299. }
  300. }
  301. if(!SchCryptDecrypt(pContext->hReadKey,
  302. 0, FALSE, 0,
  303. pAppOutput->pvBuffer,
  304. &pAppOutput->cbData,
  305. pContext->RipeZombie->dwCapiFlags))
  306. {
  307. SP_LOG_RESULT(GetLastError());
  308. return PCT_INT_INTERNAL_ERROR;
  309. }
  310. // Compute MAC
  311. cbMac = sizeof(rgbMac);
  312. pctRet = Pct1ComputeMac(pContext,
  313. FALSE,
  314. pAppOutput,
  315. pContext->ReadCounter,
  316. rgbMac,
  317. &cbMac);
  318. if(pctRet != PCT_ERR_OK)
  319. {
  320. return SP_LOG_RESULT(pctRet);
  321. }
  322. pContext->ReadCounter++;
  323. #if DBG
  324. {
  325. DWORD di;
  326. CHAR KeyDispBuf[SP_MAX_DIGEST_LEN*2+1];
  327. for(di=0;di<pContext->pHashInfo->cbCheckSum;di++)
  328. wsprintf(KeyDispBuf+(di*2), "%2.2x", pbMAC[di]);
  329. DebugLog((DEB_TRACE, " Incoming MAC\t%s\n", KeyDispBuf));
  330. for(di=0;di<cbMac;di++)
  331. wsprintf(KeyDispBuf+(di*2), "%2.2x", rgbMac[di]);
  332. DebugLog((DEB_TRACE, " Computed MAC\t%s\n", KeyDispBuf));
  333. }
  334. #endif
  335. // Validate MAC
  336. if (memcmp( rgbMac, pbMAC, cbMac ) )
  337. {
  338. return SP_LOG_RESULT(PCT_INT_MSG_ALTERED);
  339. }
  340. // Strip off the block cipher padding.
  341. if(cbPadding > pAppOutput->cbData)
  342. {
  343. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  344. }
  345. pAppOutput->cbData -= cbPadding;
  346. return( PCT_ERR_OK );
  347. }
  348. #if 0
  349. SP_STATUS
  350. PctComputeKey(PSPContext pContext,
  351. PBYTE pKey,
  352. DWORD cbKey,
  353. PUCHAR pConst,
  354. DWORD dwCLen,
  355. DWORD fFlags)
  356. {
  357. DWORD pctRet;
  358. HashBuf HBHash;
  359. PCheckSumBuffer pHash;
  360. PSessCacheItem pZombie=NULL;
  361. PSPCredentialGroup pCred=NULL;
  362. BYTE i,j;
  363. DWORD iMax;
  364. BYTE Buffer[MAX_CHECKSUM];
  365. pZombie = pContext->RipeZombie;
  366. pCred = pZombie ->pCred;
  367. SP_BEGIN("PctComputeKey");
  368. pHash = (PCheckSumBuffer)HBHash;
  369. iMax = (cbKey + pContext->pHashInfo->cbCheckSum - 1)/pContext->pHashInfo->cbCheckSum;
  370. if(iMax > 4)
  371. {
  372. SP_RETURN(PCT_INT_INTERNAL_ERROR);
  373. }
  374. for(i=1; i <= iMax; i++)
  375. {
  376. InitHashBuf(HBHash, pContext);
  377. pContext->pHashInfo->System->Sum( pHash, 1, &i );
  378. if (!(fFlags & PCT_MAKE_MAC))
  379. {
  380. // constant^i
  381. pContext->pHashInfo->System->Sum( pHash, dwCLen*i, pConst);
  382. }
  383. // MASTER KEY
  384. pContext->pHashInfo->System->Sum( pHash, pContext->RipeZombie->cbMasterKey, pContext->RipeZombie->pMasterKey);
  385. // constant^i
  386. pContext->pHashInfo->System->Sum( pHash, dwCLen*i, pConst);
  387. // ConnectionID
  388. pContext->pHashInfo->System->Sum( pHash, pContext->cbConnectionID, pContext->pConnectionID);
  389. // constant^i
  390. pContext->pHashInfo->System->Sum( pHash, dwCLen*i, pConst);
  391. if (fFlags & PCT_USE_CERT)
  392. {
  393. /* add in the certificate */
  394. pContext->pHashInfo->System->Sum( pHash, pZombie->cbServerCertificate, pZombie->pbServerCertificate );
  395. // constant^i
  396. pContext->pHashInfo->System->Sum( pHash, dwCLen*i, pConst);
  397. }
  398. // ConnectionID
  399. pContext->pHashInfo->System->Sum( pHash, pContext->cbChallenge, pContext->pChallenge);
  400. // constant^i
  401. pContext->pHashInfo->System->Sum( pHash, dwCLen*i, pConst);
  402. if(pContext->pHashInfo->cbCheckSum*i <= cbKey)
  403. {
  404. pContext->pHashInfo->System->Finalize( pHash, pKey + pContext->pHashInfo->cbCheckSum*(i-1) );
  405. }
  406. else
  407. {
  408. pContext->pHashInfo->System->Finalize( pHash, Buffer );
  409. CopyMemory(pKey + pContext->pHashInfo->cbCheckSum*(i-1),
  410. Buffer,
  411. cbKey - pContext->pHashInfo->cbCheckSum*(i-1));
  412. }
  413. }
  414. SP_RETURN(PCT_ERR_OK);
  415. }
  416. #endif
  417. #if 0
  418. SP_STATUS
  419. PctComputeExportKey(PSPContext pContext,
  420. PBYTE pKey,
  421. DWORD cbWriteKey,
  422. DWORD cbCipherKey)
  423. {
  424. DWORD pctRet;
  425. HashBuf HBHash;
  426. PCheckSumBuffer pHash;
  427. PSessCacheItem pZombie=NULL;
  428. PSPCredentialGroup pCred=NULL;
  429. BYTE i,j;
  430. DWORD d;
  431. DWORD cbClearChunk;
  432. BYTE pWriteKey[SP_MAX_MASTER_KEY];
  433. BYTE Buffer[MAX_CHECKSUM];
  434. pZombie = pContext->RipeZombie;
  435. pCred = pZombie ->pCred;
  436. SP_BEGIN("PctComputeKey");
  437. pHash = (PCheckSumBuffer)HBHash;
  438. CopyMemory(pWriteKey, pKey, cbWriteKey);
  439. d = (cbCipherKey + pContext->pHashInfo->cbCheckSum - 1)/pContext->pHashInfo->cbCheckSum;
  440. if(d > 4)
  441. {
  442. SP_RETURN(PCT_INT_INTERNAL_ERROR);
  443. }
  444. cbClearChunk = pContext->RipeZombie->cbClearKey/d;
  445. for(i=1; i <= d; i++)
  446. {
  447. InitHashBuf(HBHash, pContext);
  448. pContext->pHashInfo->System->Sum( pHash, 1, &i );
  449. // constant^i
  450. pContext->pHashInfo->System->Sum( pHash, PCT_CONST_SLK_LEN*i, PCT_CONST_SLK);
  451. // WRITE_KEY
  452. pContext->pHashInfo->System->Sum( pHash, cbWriteKey, pWriteKey);
  453. // constant^i
  454. pContext->pHashInfo->System->Sum( pHash, PCT_CONST_SLK_LEN*i, PCT_CONST_SLK);
  455. // Clear Key
  456. pContext->pHashInfo->System->Sum( pHash,
  457. cbClearChunk,
  458. (PBYTE)pContext->RipeZombie->pClearKey + (i-1)*cbClearChunk);
  459. if(pContext->pHashInfo->cbCheckSum*i <= cbCipherKey)
  460. {
  461. pContext->pHashInfo->System->Finalize( pHash, pKey + pContext->pHashInfo->cbCheckSum*(i-1) );
  462. }
  463. else
  464. {
  465. pContext->pHashInfo->System->Finalize( pHash, Buffer );
  466. CopyMemory(pKey + pContext->pHashInfo->cbCheckSum*(i-1),
  467. Buffer,
  468. cbCipherKey - pContext->pHashInfo->cbCheckSum*(i-1));
  469. }
  470. }
  471. SP_RETURN(PCT_ERR_OK);
  472. }
  473. #endif
  474. #if 0
  475. SP_STATUS
  476. Pct1MakeSessionKeys(
  477. PSPContext pContext)
  478. {
  479. SP_STATUS pctRet;
  480. BOOL fClient;
  481. UCHAR pWriteKey[SP_MAX_MASTER_KEY], pReadKey[SP_MAX_MASTER_KEY];
  482. #if DBG
  483. DWORD i;
  484. CHAR KeyDispBuf[SP_MAX_MASTER_KEY*2+1];
  485. #endif
  486. PSessCacheItem pZombie=NULL;
  487. PSPCredentialGroup pCred=NULL;
  488. SP_BEGIN("PctMakeSessionKeys");
  489. pZombie = pContext->RipeZombie;
  490. pCred = pZombie ->pCred;
  491. if (!pContext->InitMACState)
  492. {
  493. SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
  494. }
  495. #if DBG
  496. DebugLog((DEB_TRACE, "Making session keys\n", KeyDispBuf));
  497. for(i=0;i<PCT_SESSION_ID_SIZE;i++)
  498. wsprintf(KeyDispBuf+(i*2), "%2.2x",
  499. pContext->pConnectionID[i]);
  500. DebugLog((DEB_TRACE, " ConnId\t%s\n", KeyDispBuf));
  501. for(i=0;i<PCT_CHALLENGE_SIZE;i++)
  502. wsprintf(KeyDispBuf+(i*2), "%2.2x", (UCHAR)pContext->pChallenge[i]);
  503. DebugLog((DEB_TRACE, " Challenge \t%s\n", KeyDispBuf));
  504. for(i=0;i<pContext->RipeZombie->cbClearKey;i++)
  505. wsprintf(KeyDispBuf+(i*2), "%2.2x", (UCHAR)pContext->RipeZombie->pClearKey[i]);
  506. DebugLog((DEB_TRACE, " ClearKey \t%s\n", KeyDispBuf));
  507. #endif
  508. fClient = ((pContext->Flags & CONTEXT_FLAG_CLIENT) != 0);
  509. pctRet = PctComputeKey( pContext, fClient?pWriteKey:pReadKey, pContext->pCipherInfo->cbSecret, PCT_CONST_CWK,
  510. PCT_CONST_CWK_LEN, PCT_USE_CERT);
  511. if(PCT_ERR_OK != pctRet)
  512. {
  513. goto quit;
  514. }
  515. pctRet = PctComputeKey( pContext, fClient?pReadKey:pWriteKey, pContext->pCipherInfo->cbSecret, PCT_CONST_SWK,
  516. PCT_CONST_SWK_LEN, 0);
  517. if(PCT_ERR_OK != pctRet)
  518. {
  519. goto quit;
  520. }
  521. /* compute the ClientMacKey */
  522. pctRet = PctComputeKey(pContext,
  523. (fClient?pContext->WriteMACKey:pContext->ReadMACKey),
  524. pContext->pHashInfo->cbCheckSum,
  525. PCT_CONST_CMK,
  526. PCT_CONST_CMK_LEN,
  527. PCT_USE_CERT | PCT_MAKE_MAC);
  528. if(PCT_ERR_OK != pctRet)
  529. {
  530. goto quit;
  531. }
  532. /* compute the ServerMacKey */
  533. pctRet = PctComputeKey(pContext,
  534. (fClient?pContext->ReadMACKey:pContext->WriteMACKey),
  535. pContext->pHashInfo->cbCheckSum,
  536. PCT_CONST_SMK,
  537. PCT_CONST_SMK_LEN,
  538. PCT_MAKE_MAC);
  539. if(PCT_ERR_OK != pctRet)
  540. {
  541. goto quit;
  542. }
  543. // Initialize the hash states
  544. InitHashBuf(pContext->RdMACBuf, pContext);
  545. InitHashBuf(pContext->WrMACBuf, pContext);
  546. // Note, we truncuate the MACing keys down to the negotiated key size
  547. pContext->ReadMACState = (PCheckSumBuffer)pContext->RdMACBuf;
  548. pContext->pHashInfo->System->Sum( pContext->ReadMACState,
  549. pContext->pHashInfo->cbCheckSum,
  550. pContext->ReadMACKey);
  551. pContext->WriteMACState = (PCheckSumBuffer)pContext->WrMACBuf;
  552. pContext->pHashInfo->System->Sum( pContext->WriteMACState,
  553. pContext->pHashInfo->cbCheckSum,
  554. pContext->WriteMACKey);
  555. if (pContext->pCipherInfo->cbSecret < pContext->pCipherInfo->cbKey)
  556. {
  557. pctRet = PctComputeExportKey(pContext,
  558. pWriteKey,
  559. pContext->pCipherInfo->cbSecret,
  560. pContext->pCipherInfo->cbKey);
  561. if(PCT_ERR_OK != pctRet)
  562. {
  563. goto quit;
  564. }
  565. pctRet = PctComputeExportKey(pContext,
  566. pReadKey,
  567. pContext->pCipherInfo->cbSecret,
  568. pContext->pCipherInfo->cbKey);
  569. if(PCT_ERR_OK != pctRet)
  570. {
  571. goto quit;
  572. }
  573. /* chop the encryption keys down to selected length */
  574. }
  575. #if DBG
  576. for(i=0;i<pContext->RipeZombie->cbMasterKey;i++)
  577. wsprintf(KeyDispBuf+(i*2), "%2.2x", pContext->RipeZombie->pMasterKey[i]);
  578. DebugLog((DEB_TRACE, " MasterKey \t%s\n", KeyDispBuf));
  579. for(i=0;i<pContext->pCipherInfo->cbKey;i++)
  580. wsprintf(KeyDispBuf+(i*2), "%2.2x", pReadKey[i]);
  581. DebugLog((DEB_TRACE, " ReadKey\t%s\n", KeyDispBuf));
  582. for(i=0;i<pContext->pHashInfo->cbCheckSum;i++)
  583. wsprintf(KeyDispBuf+(i*2), "%2.2x", pContext->ReadMACKey[i]);
  584. DebugLog((DEB_TRACE, " MACKey\t%s\n", KeyDispBuf));
  585. for(i=0;i<pContext->pCipherInfo->cbKey;i++)
  586. wsprintf(KeyDispBuf+(i*2), "%2.2x", pWriteKey[i]);
  587. DebugLog((DEB_TRACE, " WriteKey\t%s\n", KeyDispBuf));
  588. for(i=0;i<pContext->pHashInfo->cbCheckSum;i++)
  589. wsprintf(KeyDispBuf+(i*2), "%2.2x", pContext->WriteMACKey[i]);
  590. DebugLog((DEB_TRACE, " MACKey\t%s\n", KeyDispBuf));
  591. #endif
  592. if (pContext->pCipherInfo->System->Initialize( pReadKey,
  593. pContext->pCipherInfo->cbKey,
  594. pZombie->pKeyArgs, // IV
  595. pZombie->cbKeyArgs, // IV length
  596. &pContext->pReadState ) )
  597. {
  598. if (pContext->pCipherInfo->System->Initialize( pWriteKey,
  599. pContext->pCipherInfo->cbKey,
  600. pZombie->pKeyArgs, // IV
  601. pZombie->cbKeyArgs, // IV length
  602. &pContext->pWriteState) )
  603. {
  604. pctRet = PCT_ERR_OK;
  605. goto quit;
  606. }
  607. pctRet = SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  608. pContext->pCipherInfo->System->Discard( &pContext->pReadState );
  609. }
  610. pctRet = SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  611. quit:
  612. SP_RETURN(pctRet);
  613. }
  614. #endif
  615. SP_STATUS WINAPI Pct1DecryptHandler(PSPContext pContext,
  616. PSPBuffer pCommInput,
  617. PSPBuffer pAppOutput)
  618. {
  619. SP_STATUS pctRet= 0;
  620. BOOL fEscape;
  621. PPCT1_CLIENT_HELLO pHello;
  622. if(pCommInput->cbData > 0) {
  623. /* first, we'll handle incoming data packets */
  624. if((pContext->State == SP_STATE_CONNECTED) && (pContext->Decrypt))
  625. {
  626. fEscape = (((*(PUCHAR)pCommInput->pvBuffer) & 0xc0) == 0x40);
  627. /* BUGFIX: IE 3.0 and 3.0a incorrectly respond to a REDO request
  628. * by just sending a PCT1 client hello, instead of another REDO.
  629. * We therefore look at the incomming message and see if it
  630. * looks like a PCT1 client hello.
  631. */
  632. pHello = (PPCT1_CLIENT_HELLO)pCommInput->pvBuffer;
  633. if((pCommInput->cbData >= 5) &&
  634. (pHello->MessageId == PCT1_MSG_CLIENT_HELLO) &&
  635. (pHello->VersionMsb == MSBOF(PCT_VERSION_1)) &&
  636. (pHello->VersionLsb == LSBOF(PCT_VERSION_1)) &&
  637. (pHello->OffsetMsb == MSBOF(PCT_CH_OFFSET_V1)) &&
  638. (pHello->OffsetLsb == LSBOF(PCT_CH_OFFSET_V1)))
  639. {
  640. // This looks a lot like a client hello
  641. /* InitiateRedo */
  642. pAppOutput->cbData = 0;
  643. pCommInput->cbData = 0;
  644. pContext->State = PCT1_STATE_RENEGOTIATE;
  645. ;
  646. return SP_LOG_RESULT(PCT_INT_RENEGOTIATE);
  647. }
  648. if(PCT_ERR_OK ==
  649. (pctRet = pContext->Decrypt(pContext,
  650. pCommInput, /* message */
  651. pAppOutput /* Unpacked Message */
  652. )))
  653. {
  654. /* look for escapes */
  655. if(fEscape)
  656. {
  657. if(pAppOutput->cbData < 1)
  658. {
  659. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  660. }
  661. /* The first byte of the decrypt buffer is the escape code */
  662. switch(*(PUCHAR)pAppOutput->pvBuffer)
  663. {
  664. case PCT1_ET_REDO_CONN:
  665. {
  666. /* InitiateRedo */
  667. if(pAppOutput->cbData != 1)
  668. {
  669. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  670. }
  671. pContext->State = PCT1_STATE_RENEGOTIATE;
  672. pAppOutput->cbData = 0;
  673. return SP_LOG_RESULT(PCT_INT_RENEGOTIATE);
  674. }
  675. case PCT1_ET_OOB_DATA:
  676. /* HandleOOB */
  677. default:
  678. /* Unknown escape, generate error */
  679. pctRet = SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  680. /* Disconnect */
  681. break;
  682. }
  683. }
  684. }
  685. return (pctRet);
  686. }
  687. else
  688. {
  689. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  690. }
  691. }
  692. return PCT_INT_INCOMPLETE_MSG;
  693. }
  694. SP_STATUS Pct1GenerateError(PSPContext pContext,
  695. PSPBuffer pCommOutput,
  696. SP_STATUS pError,
  697. PSPBuffer pErrData)
  698. {
  699. Pct1Error XmitError;
  700. /* Only pack up an error if we are allowed to return errors */
  701. if(!(pContext->Flags & CONTEXT_FLAG_EXT_ERR)) return pError;
  702. XmitError.Error = pError;
  703. XmitError.ErrInfoLen = 0;
  704. XmitError.ErrInfo = NULL;
  705. if(pErrData) {
  706. XmitError.ErrInfoLen = pErrData->cbData;
  707. XmitError.ErrInfo = pErrData->pvBuffer;
  708. }
  709. Pct1PackError(&XmitError,
  710. pCommOutput);
  711. return pError;
  712. }
  713. /* session key computation */
  714. SP_STATUS Pct1HandleError(PSPContext pContext,
  715. PSPBuffer pCommInput,
  716. PSPBuffer pCommOutput)
  717. {
  718. pCommOutput->cbData = 0;
  719. return(((PPCT1_ERROR)pCommInput->pvBuffer)->ErrorMsb << 8 )| ((PPCT1_ERROR)pCommInput->pvBuffer)->ErrorLsb;
  720. }
  721. //+---------------------------------------------------------------------------
  722. //
  723. // Function: Pct1BeginVerifyPrelude
  724. //
  725. // Synopsis: Initiate the "verify prelude" computation.
  726. //
  727. // Arguments: [pContext] -- Schannel context.
  728. // [pClientHello] --
  729. // [cbClientHello] --
  730. // [pServerHello] --
  731. // [cServerHello] --
  732. //
  733. // History: 10-10-97 jbanes Added CAPI integration.
  734. //
  735. // Notes: Hash(CLIENT_MAC_KEY, Hash("cvp", CLIENT_HELLO, SERVER_HELLO));
  736. //
  737. //----------------------------------------------------------------------------
  738. SP_STATUS Pct1BeginVerifyPrelude(PSPContext pContext,
  739. PUCHAR pClientHello,
  740. DWORD cbClientHello,
  741. PUCHAR pServerHello,
  742. DWORD cbServerHello)
  743. {
  744. HCRYPTHASH hHash;
  745. if(!SchCryptCreateHash(pContext->RipeZombie->hMasterProv,
  746. pContext->pHashInfo->aiHash,
  747. 0,
  748. 0,
  749. &hHash,
  750. pContext->RipeZombie->dwCapiFlags))
  751. {
  752. SP_LOG_RESULT(GetLastError());
  753. return PCT_INT_INTERNAL_ERROR;
  754. }
  755. if(!SchCryptHashData(hHash,
  756. PCT_CONST_VP,
  757. PCT_CONST_VP_LEN,
  758. 0,
  759. pContext->RipeZombie->dwCapiFlags))
  760. {
  761. SP_LOG_RESULT(GetLastError());
  762. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  763. return PCT_INT_INTERNAL_ERROR;
  764. }
  765. if(!SchCryptHashData(hHash,
  766. pClientHello,
  767. cbClientHello,
  768. 0,
  769. pContext->RipeZombie->dwCapiFlags))
  770. {
  771. SP_LOG_RESULT(GetLastError());
  772. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  773. return PCT_INT_INTERNAL_ERROR;
  774. }
  775. if(!SchCryptHashData(hHash,
  776. pServerHello,
  777. cbServerHello,
  778. 0,
  779. pContext->RipeZombie->dwCapiFlags))
  780. {
  781. SP_LOG_RESULT(GetLastError());
  782. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  783. return PCT_INT_INTERNAL_ERROR;
  784. }
  785. pContext->hMd5Handshake = hHash;
  786. return PCT_ERR_OK;
  787. }
  788. //+---------------------------------------------------------------------------
  789. //
  790. // Function: Pct1EndVerifyPrelude
  791. //
  792. // Synopsis: Finish the "verify prelude" computation.
  793. //
  794. // Arguments: [pContext] -- Schannel context.
  795. // [VerifyPrelude] --
  796. // [pcbVerifyPrelude] --
  797. //
  798. // History: 10-10-97 jbanes Added CAPI integration.
  799. //
  800. // Notes:
  801. //
  802. //----------------------------------------------------------------------------
  803. SP_STATUS Pct1EndVerifyPrelude(PSPContext pContext,
  804. PUCHAR VerifyPrelude,
  805. DWORD * pcbVerifyPrelude)
  806. {
  807. BOOL fClient;
  808. HCRYPTHASH hHash;
  809. fClient = !(pContext->RipeZombie->fProtocol & SP_PROT_SERVERS);
  810. if(!SchCryptGetHashParam(pContext->hMd5Handshake,
  811. HP_HASHVAL,
  812. VerifyPrelude,
  813. pcbVerifyPrelude,
  814. 0,
  815. pContext->RipeZombie->dwCapiFlags))
  816. {
  817. SP_LOG_RESULT(GetLastError());
  818. SchCryptDestroyHash(pContext->hMd5Handshake, pContext->RipeZombie->dwCapiFlags);
  819. pContext->hMd5Handshake = 0;
  820. return PCT_INT_INTERNAL_ERROR;
  821. }
  822. SchCryptDestroyHash(pContext->hMd5Handshake, pContext->RipeZombie->dwCapiFlags);
  823. pContext->hMd5Handshake = 0;
  824. if(!SchCryptCreateHash(pContext->RipeZombie->hMasterProv,
  825. pContext->pHashInfo->aiHash,
  826. 0,
  827. 0,
  828. &hHash,
  829. pContext->RipeZombie->dwCapiFlags))
  830. {
  831. SP_LOG_RESULT(GetLastError());
  832. return PCT_INT_INTERNAL_ERROR;
  833. }
  834. if(!SchCryptHashSessionKey(hHash,
  835. fClient ? pContext->hWriteMAC : pContext->hReadMAC,
  836. CRYPT_LITTLE_ENDIAN,
  837. pContext->RipeZombie->dwCapiFlags))
  838. {
  839. SP_LOG_RESULT(GetLastError());
  840. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  841. return PCT_INT_INTERNAL_ERROR;
  842. }
  843. if(!SchCryptHashData(hHash,
  844. VerifyPrelude,
  845. *pcbVerifyPrelude,
  846. 0,
  847. pContext->RipeZombie->dwCapiFlags))
  848. {
  849. SP_LOG_RESULT(GetLastError());
  850. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  851. return PCT_INT_INTERNAL_ERROR;
  852. }
  853. if(!SchCryptGetHashParam(hHash,
  854. HP_HASHVAL,
  855. VerifyPrelude,
  856. pcbVerifyPrelude,
  857. 0,
  858. pContext->RipeZombie->dwCapiFlags))
  859. {
  860. SP_LOG_RESULT(GetLastError());
  861. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  862. return PCT_INT_INTERNAL_ERROR;
  863. }
  864. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  865. return PCT_ERR_OK;
  866. }
  867. //+---------------------------------------------------------------------------
  868. //
  869. // Function: Pct1ComputeMac
  870. //
  871. // Synopsis: Compute the
  872. //
  873. // Arguments: [pContext] -- Schannel context.
  874. //
  875. // History: 10-10-97 jbanes Created.
  876. //
  877. // Notes: MAC_DATA := Hash(MAC_KEY, Hash(RECORD_HEADER_DATA,
  878. // ACTUAL_DATA, PADDING_DATA, SEQUENCE_NUMBER))
  879. //
  880. //----------------------------------------------------------------------------
  881. static SP_STATUS
  882. Pct1ComputeMac(
  883. PSPContext pContext, // in
  884. BOOL fWriteMAC, // in
  885. PSPBuffer pData, // in
  886. DWORD dwSequence, // in
  887. PBYTE pbMac, // out
  888. PDWORD pcbMac) // in, out
  889. {
  890. HCRYPTHASH hHash;
  891. DWORD dwReverseSequence;
  892. dwReverseSequence = htonl(dwSequence);
  893. // Compute inner hash
  894. if(!SchCryptCreateHash(pContext->RipeZombie->hMasterProv,
  895. pContext->pHashInfo->aiHash,
  896. 0,
  897. 0,
  898. &hHash,
  899. pContext->RipeZombie->dwCapiFlags))
  900. {
  901. SP_LOG_RESULT(GetLastError());
  902. return PCT_INT_INTERNAL_ERROR;
  903. }
  904. if(!SchCryptHashData(hHash,
  905. pData->pvBuffer,
  906. pData->cbData,
  907. 0,
  908. pContext->RipeZombie->dwCapiFlags))
  909. {
  910. SP_LOG_RESULT(GetLastError());
  911. CryptDestroyHash(hHash);
  912. return PCT_INT_INTERNAL_ERROR;
  913. }
  914. if(!SchCryptHashData(hHash,
  915. (PUCHAR)&dwReverseSequence,
  916. sizeof(DWORD),
  917. 0,
  918. pContext->RipeZombie->dwCapiFlags))
  919. {
  920. SP_LOG_RESULT(GetLastError());
  921. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  922. return PCT_INT_INTERNAL_ERROR;
  923. }
  924. if(!SchCryptGetHashParam(hHash,
  925. HP_HASHVAL,
  926. pbMac,
  927. pcbMac,
  928. 0,
  929. pContext->RipeZombie->dwCapiFlags))
  930. {
  931. SP_LOG_RESULT(GetLastError());
  932. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  933. return PCT_INT_INTERNAL_ERROR;
  934. }
  935. SP_ASSERT(*pcbMac == pContext->pHashInfo->cbCheckSum);
  936. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  937. // Compute outer hash.
  938. if(!SchCryptCreateHash(pContext->RipeZombie->hMasterProv,
  939. pContext->pHashInfo->aiHash,
  940. 0,
  941. 0,
  942. &hHash,
  943. pContext->RipeZombie->dwCapiFlags))
  944. {
  945. SP_LOG_RESULT(GetLastError());
  946. return PCT_INT_INTERNAL_ERROR;
  947. }
  948. if(!SchCryptHashSessionKey(hHash,
  949. fWriteMAC ? pContext->hWriteMAC : pContext->hReadMAC,
  950. CRYPT_LITTLE_ENDIAN,
  951. pContext->RipeZombie->dwCapiFlags))
  952. {
  953. SP_LOG_RESULT(GetLastError());
  954. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  955. return PCT_INT_INTERNAL_ERROR;
  956. }
  957. if(!SchCryptHashData(hHash, pbMac, *pcbMac, 0, pContext->RipeZombie->dwCapiFlags))
  958. {
  959. SP_LOG_RESULT(GetLastError());
  960. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  961. return PCT_INT_INTERNAL_ERROR;
  962. }
  963. if(!SchCryptGetHashParam(hHash,
  964. HP_HASHVAL,
  965. pbMac,
  966. pcbMac,
  967. 0,
  968. pContext->RipeZombie->dwCapiFlags))
  969. {
  970. SP_LOG_RESULT(GetLastError());
  971. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  972. return PCT_INT_INTERNAL_ERROR;
  973. }
  974. SP_ASSERT(*pcbMac == pContext->pHashInfo->cbCheckSum);
  975. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  976. return PCT_ERR_OK;
  977. }
  978. //+---------------------------------------------------------------------------
  979. //
  980. // Function: Pct1ComputeResponse
  981. //
  982. // Synopsis: Compute the "response" field of the ServerVerify message.
  983. //
  984. // Arguments: [pContext] -- Schannel context.
  985. // [pbChallenge] --
  986. // [cbChallenge] --
  987. // [pbConnectionID] --
  988. // [cbConnectionID] --
  989. // [pbSessionID] --
  990. // [cbSessionID] --
  991. // [pbResponse] --
  992. // [pcbResponse] --
  993. //
  994. // History: 10-10-97 jbanes Created.
  995. //
  996. // Notes: Hash(SERVER_MAC_KEY, Hash ("sr", CH_CHALLENGE_DATA,
  997. // SH_CONNECTION_ID_DATA, SV_SESSION_ID_DATA))
  998. //
  999. //----------------------------------------------------------------------------
  1000. SP_STATUS
  1001. Pct1ComputeResponse(
  1002. PSPContext pContext, // in
  1003. PBYTE pbChallenge, // in
  1004. DWORD cbChallenge, // in
  1005. PBYTE pbConnectionID, // in
  1006. DWORD cbConnectionID, // in
  1007. PBYTE pbSessionID, // in
  1008. DWORD cbSessionID, // in
  1009. PBYTE pbResponse, // out
  1010. PDWORD pcbResponse) // in, out
  1011. {
  1012. BOOL fClient;
  1013. HCRYPTHASH hHash = 0;
  1014. SP_STATUS pctRet;
  1015. fClient = !(pContext->RipeZombie->fProtocol & SP_PROT_SERVERS);
  1016. //
  1017. // Hash ("sr", CH_CHALLENGE_DATA, SH_CONNECTION_ID_DATA,
  1018. // SV_SESSION_ID_DATA). Place the result in pbResponse.
  1019. //
  1020. if(!SchCryptCreateHash(pContext->RipeZombie->hMasterProv,
  1021. pContext->pHashInfo->aiHash,
  1022. 0,
  1023. 0,
  1024. &hHash,
  1025. pContext->RipeZombie->dwCapiFlags))
  1026. {
  1027. SP_LOG_RESULT(GetLastError());
  1028. pctRet = PCT_INT_INTERNAL_ERROR;
  1029. goto cleanup;
  1030. }
  1031. if(!SchCryptHashData(hHash,
  1032. PCT_CONST_RESP,
  1033. PCT_CONST_RESP_LEN,
  1034. 0,
  1035. pContext->RipeZombie->dwCapiFlags))
  1036. {
  1037. SP_LOG_RESULT(GetLastError());
  1038. pctRet = PCT_INT_INTERNAL_ERROR;
  1039. goto cleanup;
  1040. }
  1041. if(!SchCryptHashData(hHash,
  1042. pbChallenge,
  1043. cbChallenge,
  1044. 0,
  1045. pContext->RipeZombie->dwCapiFlags))
  1046. {
  1047. SP_LOG_RESULT(GetLastError());
  1048. pctRet = PCT_INT_INTERNAL_ERROR;
  1049. goto cleanup;
  1050. }
  1051. if(!SchCryptHashData(hHash,
  1052. pbConnectionID,
  1053. cbConnectionID,
  1054. 0,
  1055. pContext->RipeZombie->dwCapiFlags))
  1056. {
  1057. SP_LOG_RESULT(GetLastError());
  1058. pctRet = PCT_INT_INTERNAL_ERROR;
  1059. goto cleanup;
  1060. }
  1061. if(!SchCryptHashData(hHash,
  1062. pbSessionID,
  1063. cbSessionID,
  1064. 0,
  1065. pContext->RipeZombie->dwCapiFlags))
  1066. {
  1067. SP_LOG_RESULT(GetLastError());
  1068. pctRet = PCT_INT_INTERNAL_ERROR;
  1069. goto cleanup;
  1070. }
  1071. if(!SchCryptGetHashParam(hHash,
  1072. HP_HASHVAL,
  1073. pbResponse,
  1074. pcbResponse,
  1075. 0,
  1076. pContext->RipeZombie->dwCapiFlags))
  1077. {
  1078. SP_LOG_RESULT(GetLastError());
  1079. pctRet = PCT_INT_INTERNAL_ERROR;
  1080. goto cleanup;
  1081. }
  1082. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  1083. hHash = 0;
  1084. //
  1085. // Hash (SERVER_MAC_KEY, pbResponse). Place the result back in pbResponse.
  1086. //
  1087. if(!SchCryptCreateHash(pContext->RipeZombie->hMasterProv,
  1088. pContext->pHashInfo->aiHash,
  1089. 0,
  1090. 0,
  1091. &hHash,
  1092. pContext->RipeZombie->dwCapiFlags))
  1093. {
  1094. SP_LOG_RESULT(GetLastError());
  1095. pctRet = PCT_INT_INTERNAL_ERROR;
  1096. goto cleanup;
  1097. }
  1098. if(!SchCryptHashSessionKey(hHash,
  1099. fClient ? pContext->hReadMAC : pContext->hWriteMAC,
  1100. CRYPT_LITTLE_ENDIAN,
  1101. pContext->RipeZombie->dwCapiFlags))
  1102. {
  1103. SP_LOG_RESULT(GetLastError());
  1104. pctRet = PCT_INT_INTERNAL_ERROR;
  1105. goto cleanup;
  1106. }
  1107. if(!SchCryptHashData(hHash,
  1108. pbResponse,
  1109. *pcbResponse,
  1110. 0,
  1111. pContext->RipeZombie->dwCapiFlags))
  1112. {
  1113. SP_LOG_RESULT(GetLastError());
  1114. pctRet = PCT_INT_INTERNAL_ERROR;
  1115. goto cleanup;
  1116. }
  1117. if(!SchCryptGetHashParam(hHash,
  1118. HP_HASHVAL,
  1119. pbResponse,
  1120. pcbResponse,
  1121. 0,
  1122. pContext->RipeZombie->dwCapiFlags))
  1123. {
  1124. SP_LOG_RESULT(GetLastError());
  1125. pctRet = PCT_INT_INTERNAL_ERROR;
  1126. goto cleanup;
  1127. }
  1128. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  1129. hHash = 0;
  1130. pctRet = PCT_ERR_OK;
  1131. cleanup:
  1132. if(hHash)
  1133. {
  1134. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  1135. }
  1136. return pctRet;
  1137. }