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

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